Skip to content

Instantly share code, notes, and snippets.

@haad
Created October 4, 2012 08:05
Show Gist options
  • Save haad/3832101 to your computer and use it in GitHub Desktop.
Save haad/3832101 to your computer and use it in GitHub Desktop.
ldap
static int update_ldap(const char *basedn, const char *table_name, const char *attribute,
1177 const char *lookup, va_list ap)
1178{
1179 int error = 0;
1180 LDAPMessage *ldap_entry = NULL;
1181 LDAPMod **ldap_mods;
1182 const char *newparam = NULL;
1183 const char *newval = NULL;
1184 char *dn;
1185 int num_entries = 0;
1186 int i = 0;
1187 int mods_size = 0;
1188 int mod_exists = 0;
1189 struct ldap_table_config *table_config = NULL;
1190 char *clean_basedn = NULL;
1191 struct ast_str *filter = NULL;
1192 int tries = 0;
1193 int result = 0;
1194 LDAPMessage *ldap_result_msg = NULL;
1195
1196 if (!table_name) {
1197 ast_log(LOG_ERROR, "No table_name specified.\n");
1198 return -1;
1199 }
1200
1201 if (!(filter = ast_str_create(80))) {
1202 return -1;
1203 }
1204
1205 if (!attribute || !lookup) {
1206 ast_log(LOG_WARNING, "LINE(%d): search parameters are empty.\n", __LINE__);
1207 return -1;
1208 }
1209 ast_mutex_lock(&ldap_lock);
1210
1211 /* We now have our complete statement; Lets connect to the server and execute it. */
1212 if (!ldap_reconnect()) {
1213 ast_mutex_unlock(&ldap_lock);
1214 return -1;
1215 }
1216
1217 table_config = table_config_for_table_name(table_name);
1218 if (!table_config) {
1219 ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
1220 ast_mutex_unlock(&ldap_lock);
1221 return -1;
1222 }
1223
1224 clean_basedn = cleaned_basedn(NULL, basedn);
1225
1226 /* Create the filter with the table additional filter and the parameter/value pairs we were given */
1227 ast_str_append(&filter, 0, "(&");
1228 if (table_config && table_config->additional_filter) {
1229 ast_str_append(&filter, 0, "%s", table_config->additional_filter);
1230 }
1231 if (table_config != base_table_config && base_table_config && base_table_config->additional_filter) {
1232 ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
1233 }
1234 append_var_and_value_to_filter(&filter, table_config, attribute, lookup);
1235 ast_str_append(&filter, 0, ")");
1236
1237 /* Create the modification array with the parameter/value pairs we were given,
1238 * if there are several parameters with the same name, we collect them into
1239 * one parameter/value pair and delimit them with a semicolon */
1240 newparam = va_arg(ap, const char *);
1241 newparam = convert_attribute_name_to_ldap(table_config, newparam);
1242 newval = va_arg(ap, const char *);
1243 if (!newparam || !newval) {
1244 ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
1245 return -1;
1246 }
1247
1248 mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
1249 ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
1250 ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));
1251
1252 ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
1253 ldap_mods[0]->mod_type = ast_strdup(newparam);
1254
1255 ldap_mods[0]->mod_values = ast_calloc(sizeof(char *), 2);
1256 ldap_mods[0]->mod_values[0] = ast_strdup(newval);
1257
1258 while ((newparam = va_arg(ap, const char *))) {
1259 newparam = convert_attribute_name_to_ldap(table_config, newparam);
1260 newval = va_arg(ap, const char *);
1261 mod_exists = 0;
1262
1263 for (i = 0; i < mods_size - 1; i++) {
1264 if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
1265 /* We have the parameter allready, adding the value as a semicolon delimited value */
1266 ldap_mods[i]->mod_values[0] = ast_realloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2));
1267 strcat(ldap_mods[i]->mod_values[0], ";");
1268 strcat(ldap_mods[i]->mod_values[0], newval);
1269 mod_exists = 1;
1270 break;
1271 }
1272 }
1273
1274 /* create new mod */
1275 if (!mod_exists) {
1276 mods_size++;
1277 ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
1278 ldap_mods[mods_size - 1] = NULL;
1279
1280 ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));
1281
1282 ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
1283 strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
1284
1285 if (strlen(newval) == 0) {
1286 ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_DELETE;
1287 } else {
1288 ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
1289
1290 ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
1291 ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
1292 strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval);
1293 }
1294 }
1295 }
1296 /* freeing ldap_mods further down */
1297
1298 do {
1299 /* freeing ldap_result further down */
1300 result = ldap_search_ext_s(ldapConn, clean_basedn,
1301 LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
1302 &ldap_result_msg);
1303 if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
1304 ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
1305 tries++;
1306 if (tries < 3) {
1307 usleep(500000L * tries);
1308 if (ldapConn) {
1309 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1310 ldapConn = NULL;
1311 }
1312 if (!ldap_reconnect())
1313 break;
1314 }
1315 }
1316 } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
1317
1318 if (result != LDAP_SUCCESS) {
1319 ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
1320 ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
1321
1322 ast_mutex_unlock(&ldap_lock);
1323 free(filter);
1324 free(clean_basedn);
1325 ldap_msgfree(ldap_result_msg);
1326 ldap_mods_free(ldap_mods, 0);
1327 return -1;
1328 }
1329 /* Ready to update */
1330 if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
1331 ast_debug(3, "LINE(%d) Modifying %s=%s hits: %d\n", __LINE__, attribute, lookup, num_entries);
1332 for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
1333 if (ldap_mods[i]->mod_op != LDAP_MOD_DELETE) {
1334 ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
1335 } else {
1336 ast_debug(3, "LINE(%d) deleting %s \n", __LINE__, ldap_mods[i]->mod_type);
1337 }
1338 }
1339 ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
1340
1341 for (i = 0; ldap_entry; i++) {
1342 dn = ldap_get_dn(ldapConn, ldap_entry);
1343 if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) {
1344 ast_log(LOG_ERROR, "Couldn't modify '%s'='%s', dn:%s because %s\n",
1345 attribute, lookup, dn, ldap_err2string(error));
1346 }
1347 ldap_memfree(dn);
1348 ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
1349 }
1350 }
1351
1352 ast_mutex_unlock(&ldap_lock);
1353 ast_free(filter);
1354 ast_free(clean_basedn);
1355 ldap_msgfree(ldap_result_msg);
1356 ldap_mods_free(ldap_mods, 0);
1357 return num_entries;
1358}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment