Ejemplo n.º 1
0
/**
 * 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);
}
Ejemplo n.º 2
0
/**
 * 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);
	}
}