/** * Perform the LDAP search, reading LDAP entries into cache. * Note that one LDAP entry can have multiple values for many of its * attributes. If these attributes are E-Mail addresses; these are * broken out into separate address items. For any other attribute, * only the first occurrence is read. * * \param qry Query object to process. * \return Error/status code. */ static gint ldapqry_search_retrieve( LdapQuery *qry ) { LdapControl *ctl; LDAP *ld; LDAPMessage *result = NULL, *e = NULL; char **attribs; gchar *criteria; gboolean searchFlag; gboolean entriesFound; gboolean first; struct timeval timeout; gint rc; AddressCache *cache; GList *listEMail; /* Initialize some variables */ ld = qry->ldap; ctl = qry->control; cache = qry->server->addressCache; timeout.tv_sec = ctl->timeOut; timeout.tv_usec = 0L; entriesFound = FALSE; ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS; /* Define all attributes we are interested in. */ attribs = ldapctl_full_attribute_array( ctl ); /* Create LDAP search string */ criteria = ldapctl_format_criteria( ctl, ADDRQUERY_SEARCHVALUE(qry) ); debug_print("Search criteria ::%s::\n", criteria?criteria:"null"); /* * Execute the search - this step may take some time to complete * depending on network traffic and server response time. */ ADDRQUERY_RETVAL(qry) = LDAPRC_TIMEOUT; rc = ldap_search_ext_s( ld, ctl->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL, &timeout, 0, &result ); debug_print("LDAP ldap_search_ext_s: %d (%s)\n", rc, ldaputil_get_error(ld)); ldapctl_free_attribute_array( attribs ); g_free( criteria ); criteria = NULL; if( rc == LDAP_TIMEOUT ) { log_warning(LOG_PROTOCOL, _("LDAP (search): timeout\n")); return ADDRQUERY_RETVAL(qry); } ADDRQUERY_RETVAL(qry) = LDAPRC_SEARCH; /* Test valid returns */ searchFlag = FALSE; if( rc == LDAP_ADMINLIMIT_EXCEEDED ) { log_warning(LOG_PROTOCOL, _("LDAP (search): server limits exceeded\n")); searchFlag = TRUE; } else if( rc == LDAP_SUCCESS ) { log_print(LOG_PROTOCOL, _("LDAP (search): successful\n")); searchFlag = TRUE; } else if( rc == LDAP_PARTIAL_RESULTS || (result && ldap_count_entries(ld, result) > 0) ) { log_print(LOG_PROTOCOL, _("LDAP (search): successful (partial results)\n")); searchFlag = TRUE; } else { log_error(LOG_PROTOCOL, _("LDAP error (search): %d (%s)\n"), rc, ldaputil_get_error(ld)); return ADDRQUERY_RETVAL(qry); } ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG; #ifdef G_OS_WIN32 debug_print("Total results are: %lu\n", ldap_count_entries(ld, result)); #else debug_print("Total results are: %d\n", ldap_count_entries(ld, result)); #endif /* Process results */ first = TRUE; while( searchFlag ) { ldapqry_touch( qry ); if( qry->entriesRead >= ctl->maxEntries ) break; /* Test for stop */ if( ldapqry_get_stop_flag( qry ) ) { break; } /* Retrieve entry */ if( first ) { first = FALSE; e = ldap_first_entry( ld, result ); } else { e = ldap_next_entry( ld, e ); } if( e == NULL ) break; entriesFound = TRUE; /* Setup a critical section here */ pthread_mutex_lock( qry->mutexEntry ); /* Process entry */ listEMail = ldapqry_process_single_entry( cache, qry, ld, e ); /* Process callback */ if( qry->callBackEntry ) qry->callBackEntry( qry, ADDRQUERY_ID(qry), listEMail, qry->data ); else g_list_free( listEMail ); pthread_mutex_unlock( qry->mutexEntry ); } /* Free up and disconnect */ ldap_msgfree( result ); if( searchFlag ) { if( entriesFound ) { ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS; } else { ADDRQUERY_RETVAL(qry) = LDAPRC_NOENTRIES; } } return ADDRQUERY_RETVAL(qry); }
/** * Deside which other attributes needs updating * * \param ld LDAP resource * \param server AddressBook resource * \param dn dn for the entry * \param contact GHashTable with information for the current contact */ void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHashTable *contact) { GList *node; gboolean CHECKED_ATTRIBUTE[ATTRIBUTE_SIZE + 1]; LDAPMod *mods[ATTRIBUTE_SIZE + 1]; LDAPMod modarr[ATTRIBUTE_SIZE]; gint cnt = 0; char *attr[ATTRIBUTE_SIZE + 1][2]; int mod_op, rc, i; cm_return_if_fail(server != NULL || dn != NULL || contact != NULL); for (i = 0; i <= ATTRIBUTE_SIZE; i++) { CHECKED_ATTRIBUTE[i] = FALSE; attr[i][0] = attr[i][1] = NULL; } node = g_hash_table_lookup(contact , "attribute"); while (node) { AttrKeyValue *item = node->data; if (item) { int index = get_attribute_index(item->key); if (index >= 0) { debug_print("Found other attribute: %s = %s\n", item->key?item->key:"null", item->value?item->value:"null"); mod_op = ldapsvr_deside_operation(ld, server, dn, item->key, item->value); /* Only consider attributes which we no how to handle. * Set to TRUE in CHECKED_ATTRIBUTE array to indicate no further action */ if (mod_op < 0) { CHECKED_ATTRIBUTE[index] = TRUE; node = g_list_next(node); continue; } if (mod_op == LDAP_MOD_DELETE) { /* Setting param to NULL instructs OpenLDAP to remove any * value stored for this attribute and remove the attribute * completely. Should multiple instances of an attribute be * allowed in the future param is required to have the value * store for the attribute which is going to be deleted */ item->value = NULL; } if (mod_op == LDAP_MOD_REPLACE && strcmp(item->value, "") == 0) { /* Having an empty string is considered a syntax error in * ldap. E.g attributes with empty strings are not allowed * in which case we treate this as a request for deleting * the attribute. */ mod_op = LDAP_MOD_DELETE; item->value = NULL; } if (mod_op == LDAP_MOD_ADD && strcmp(item->value, "") == 0) { /* Adding an empty string is considered a syntax error in * ldap. E.g attributes with empty strings are not allowed * in which case we silently refuse to add this entry */ } else { SETMOD(mods[cnt], modarr[cnt], mod_op, g_strdup(item->key), attr[cnt], g_strdup(item->value)); cnt++; CHECKED_ATTRIBUTE[index] = TRUE; } } } node = g_list_next(node); } char **attribs = ldapctl_full_attribute_array(server->control); for (i = 0; i < ATTRIBUTE_SIZE; i++) { /* Attributes which holds no information are to be removed */ if (CHECKED_ATTRIBUTE[i] == FALSE) { /* Only consider those attributes which is currently part of the search criteria. * If attributes are not part of the search criteria they would seem to hold * no information since their values will not be populated in the GUI */ if (!strcmp(ATTRIBUTE[i], "jpegPhoto")) { debug_print("not updating jpegPhoto\n"); continue; } if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) { mod_op = ldapsvr_deside_operation(ld, server, dn, (char *) ATTRIBUTE[i], ""); if (mod_op == LDAP_MOD_DELETE) { SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_DELETE, g_strdup((char *) ATTRIBUTE[i]), attr[cnt], NULL); cnt++; } } } } ldapctl_free_attribute_array(attribs); mods[cnt] = NULL; if (debug_get_mode()) ldapsvr_print_ldapmod(mods); server->retVal = LDAPRC_SUCCESS; rc = ldap_modify_ext_s(ld, dn, mods, NULL, NULL); if (rc) { switch (rc) { case LDAP_ALREADY_EXISTS: server->retVal = LDAPRC_ALREADY_EXIST; break; default: g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n", dn, rc, ldaputil_get_error(ld)); if (rc == 0x8) server->retVal = LDAPRC_STRONG_AUTH; else server->retVal = LDAPRC_NAMING_VIOLATION; } } else { char **attribs = ldapctl_full_attribute_array(server->control); for (i = 0; i < ATTRIBUTE_SIZE; i++) { if (!strcmp(ATTRIBUTE[i], "jpegPhoto")) { debug_print("not updating jpegPhoto\n"); continue; } if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) { if (CHECKED_ATTRIBUTE[i] == FALSE) { AddrItemObject *aio = addrcache_get_object(server->addressCache, g_hash_table_lookup(contact , "uid")); ItemPerson *person = (ItemPerson *) aio; addritem_person_remove_attribute(person, (const gchar *) ATTRIBUTE[i]); } } } ldapctl_free_attribute_array(attribs); } }