示例#1
0
/**
 * Make a compare for every new value we want to store in the
 * directory with the current values. Great tool for debugging
 * against invalid syntax in attributes
 *
 * \param ld AddressBook resource
 * \param dn dn for the entry
 * \param cnt Number of attributes to compare
 * \param  mods LDAPMod structure
 */
void ldapsvr_compare_attr(LDAP *ld, gchar *dn, gint cnt, LDAPMod *mods[]) {
	int i, rc;

#ifdef OPEN_LDAP_API_AT_LEAST_3000

	struct berval val;

#endif

	cm_return_if_fail(ld != NULL || dn != NULL || cnt >= 0 || mods != NULL);
	for (i = 0; i < cnt; i++) {
		gchar *value = g_strdup(mods[i]->mod_vals.modv_strvals[0]);
		if (!value || strcmp(value, "") == 0)
			value = g_strdup("thisisonlyadummy");

#ifdef OPEN_LDAP_API_AT_LEAST_3000

		val.bv_val = value;
		val.bv_len = strlen(value);

		rc = ldap_compare_ext_s(ld, dn, mods[i]->mod_type, &val, NULL, NULL);

#else

		/* This is deprecated as of OpenLDAP-2.3.0 */
		rc = ldap_compare_s(ld, dn, mods[i]->mod_type, value);

#endif

		g_printerr("ldap_compare for (%s:%s)\" failed[0x%x]: %s\n",
        	mods[i]->mod_type, value, rc, ldaputil_get_error(ld));
		g_free(value);
	}
}
示例#2
0
/**
 * Delete contact from LDAP
 *
 * \param server AddressBook resource
 * \param contact GHashTable with object to delete
 */
void ldapsvr_delete_contact(LdapServer *server, GHashTable *contact) {
	LDAP *ld = NULL;
	gchar *dn;
	int rc;

	cm_return_if_fail(server != NULL || contact != NULL);
	ld = ldapsvr_connect(server->control);
	if (ld == NULL) {
		clean_up(ld, server, contact);
		return;
	}
	dn = g_hash_table_lookup(contact, "dn");
	if (dn == NULL) {
		clean_up(ld, server, contact);
		return;
	}
	server->retVal = LDAPRC_SUCCESS;
	rc = ldap_delete_ext_s(ld, dn, NULL, NULL);
	if (rc) {
		g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
				dn, rc, ldaputil_get_error(ld));
		server->retVal = LDAPRC_NODN;
	}
	clean_up(ld, server, contact);
}
示例#3
0
/**
 * Deside which kind of operation is required to handle
 * updating the specified attribute
 *
 * \param ld AddressBook resource
 * \param server Reference to server
 * \param dn dn for the entry
 * \param attr Attribute
 * \param value New value
 * \return int, return will be LDAP_MOD_ADD, LDAP_MOD_REPLACE, or LDAP_MOD_DELETE
 */
int ldapsvr_deside_operation(LDAP *ld, LdapServer *server, char *dn, char *attr, char *value) {
	int rc;
	gboolean dummy = FALSE;

#ifdef OPEN_LDAP_API_AT_LEAST_3000

	struct berval val;

#endif

	cm_return_val_if_fail(ld != NULL || server != NULL || dn != NULL || attr != NULL, -1);
	if (value == NULL)
		return -1;
	/* value containing empty string cause invalid syntax. A bug in
	 * the LDAP library? Therefore we add a dummy value
	 */
	if (strcmp(value,"") == 0) {
		value = g_strdup("thisisonlyadummy");
		dummy = TRUE;
	}

#ifdef OPEN_LDAP_API_AT_LEAST_3000

	val.bv_val = value;
	val.bv_len = strlen(value);

	rc = ldap_compare_ext_s(ld, dn, attr, &val, NULL, NULL);

#else

	/* This is deprecated as of OpenLDAP-2.3.0 */
	rc = ldap_compare_s(ld, dn, attr, value);

#endif

	debug_print("ldap_compare for (%s:%s)\" error_code[0x%x]: %s\n",
       	attr, value, rc, ldaputil_get_error(ld));
	switch (rc) {
		case LDAP_COMPARE_FALSE: 
			if (dummy)
				return LDAP_MOD_DELETE;
			else
				return LDAP_MOD_REPLACE;
		case LDAP_COMPARE_TRUE: return -1;
		case LDAP_NO_SUCH_ATTRIBUTE: return LDAP_MOD_ADD;
		/* LDAP_INAPPROPRIATE_MATCHING needs extensive testing because I
		 * am not aware off the condition causing this return value!
		 */
		case LDAP_INAPPROPRIATE_MATCHING:
			if (dummy)
				value = NULL;
			return ldapsvr_compare_manual_attr(ld, server, dn, attr, value);
		case LDAP_UNDEFINED_TYPE: return -2;
		case LDAP_INVALID_SYNTAX: return -2;
		default: return -2;
	}
}
示例#4
0
/**
 * Connect to LDAP server.
 * \param  qry Query object to process.
 * \return Error/status code.
 */
static gint ldapqry_disconnect( LdapQuery *qry ) {
	gint rc;
	/* Disconnect */
	if( qry->ldap ) {
		rc = ldap_unbind_ext( qry->ldap, NULL, NULL );
		if (rc != LDAP_SUCCESS) {
			log_error(LOG_PROTOCOL, _("LDAP error (unbind): %d (%s)\n"),
					rc, ldaputil_get_error(qry->ldap));
		} else {
			log_print(LOG_PROTOCOL, _("LDAP (unbind): successful\n"));
		}
	}
	qry->ldap = NULL;

	ldapqry_touch( qry );
	qry->elapsedTime = qry->touchTime - qry->startTime;

	return ADDRQUERY_RETVAL(qry);
}
示例#5
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);
}
示例#6
0
/**
 * Perform the data retrieval for a specific LDAP record.
 * 
 * \param  qry Query object to process.
 * \return Error/status code.
 */
static gint ldapqry_locate_retrieve( LdapQuery *qry ) {
	LdapControl *ctl;
	LDAP *ld;
	LDAPMessage *result, *e = NULL;
	gboolean entriesFound;
	gboolean first;
	struct timeval timeout;
	gint rc;
	gchar *dn;
	GList *listValues;

	/* Initialize some variables */
	ld = qry->ldap;
	ctl = qry->control;
	dn = ADDRQUERY_SEARCHVALUE(qry);
	timeout.tv_sec = ctl->timeOut;
	timeout.tv_usec = 0L;
	entriesFound = FALSE;

	/*
	 * 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, dn, LDAP_SCOPE_BASE, CRITERIA_SINGLE,
		NULL, 0, NULL, NULL, &timeout, 0, &result );
	if( rc == LDAP_TIMEOUT ) {
		return ADDRQUERY_RETVAL(qry);
	}
	ADDRQUERY_RETVAL(qry) = LDAPRC_SEARCH;
	if( rc != LDAP_SUCCESS ) {
		log_error(LOG_PROTOCOL, _("LDAP error (search): %d (%s)\n"),
				rc, ldaputil_get_error(ld));
		debug_print("LDAP Error: ldap_search_ext_s: %d (%s)\n",
				rc, ldaputil_get_error(ld));
		return ADDRQUERY_RETVAL(qry);
	} else {
		log_print(LOG_PROTOCOL, _("LDAP (search): successful\n"));
	}

#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 */
	ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
	first = TRUE;
	while( TRUE ) {
		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 */
		listValues = ldapqry_fetch_attribs( ld, e );

		/* Process callback */
		if( qry->callBackEntry ) {
			qry->callBackEntry( qry, ADDRQUERY_ID(qry), listValues, qry->data );
		}
		ldapqry_free_list_name_value( listValues );
		listValues = NULL;

		pthread_mutex_unlock( qry->mutexEntry );
	}

	/* Free up and disconnect */
	ldap_msgfree( result );

	if( entriesFound ) {
		ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
	}
	else {
		ADDRQUERY_RETVAL(qry) = LDAPRC_NOENTRIES;
	}

	return ADDRQUERY_RETVAL(qry);
}
示例#7
0
/**
 * Add new contact to LDAP
 *
 * \param server AddressBook resource
 * \param contact GHashTable with object to add
 */
void ldapsvr_add_contact(LdapServer *server, GHashTable *contact) {
	gchar *email = NULL, *param = NULL;
	LDAP *ld = NULL;
	LDAPMod *mods[MODSIZE];
	LDAPMod modarr[7];
	gint cnt = 0;
	char *cn[] = {NULL, NULL};
	char *displayName[] = {NULL, NULL};
	char *givenName[] = {NULL, NULL};
	char **mail = NULL;
	char *sn[] = {NULL, NULL};
	char *org[] = {NULL, NULL};
	char *obj[] = {/*"top",*/ "person", "organizationalPerson", "inetOrgPerson", NULL}; 
	int rc=0;
	GList *node;
	AttrKeyValue *ou, *commonName;
	ItemPerson *person;
	gchar *base_dn;
	GList *mailList;

	cm_return_if_fail(server != NULL || contact != NULL);
	node = g_hash_table_lookup(contact , "mail");
	if (node) {
		EmailKeyValue *newEmail = node->data;
		email = g_strdup(newEmail->mail);
	}
	if (email == NULL) {
		server->retVal = LDAPRC_NODN;
		clean_up(ld, server, contact);
		return;
	}
	base_dn = g_strdup_printf("mail=%s,%s",
			email, server->control->baseDN?server->control->baseDN:"null");
	g_free(email);
	person = 
		ldapsvr_get_contact(server, g_hash_table_lookup(contact , "uid"));
	person->externalID = g_strdup(base_dn);
	debug_print("dn: %s\n", base_dn);
	ld = ldapsvr_connect(server->control);
	if (ld == NULL) {
		clean_up(ld, server, contact);
		debug_print("no ldap found\n");
		return;
	}
	SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "objectClass", obj);
	cnt++;
	ou = get_ou(base_dn);
	if (ou != NULL) {
		SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(ou->key), org, g_strdup(ou->value));
		cnt++;
		attrkeyvalue_free(ou);
	}
	
	commonName = get_cn(base_dn);
	if (commonName == NULL) {
		param = g_hash_table_lookup(contact , "cn");
		if (param) {
			SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "cn", cn, param);
		}
		else {
			clean_up(ld, server, contact);
			debug_print("no CN found\n");
			return;
		}
	}
	else {
		SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(commonName->key), cn, g_strdup(commonName->value));
		cnt++;
		param = g_hash_table_lookup(contact , "cn");
		SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "displayName", displayName, param);
		g_hash_table_insert(contact, "displayName", param);
		attrkeyvalue_free(commonName);
	}
	cnt++;
	param = g_hash_table_lookup(contact , "givenName");
	if (param) {
		SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "givenName", givenName, param);
		cnt++;
	}
	mailList = g_hash_table_lookup(contact , "mail");
	if (mailList) {
		char **tmp;
		tmp = g_malloc(sizeof(*tmp) * (g_list_length(mailList)+1));
		mail = tmp;
		while (mailList) {
			EmailKeyValue *item = mailList->data;
			*tmp++ = g_strdup((gchar *) item->mail);
			mailList = g_list_next(mailList);
		}
		*tmp = NULL;
		SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "mail", mail);
		cnt++;
	}
	param = g_hash_table_lookup(contact, "sn");
	if (param == NULL)
		param = g_strdup(N_("Some SN"));
	SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "sn", sn, param);
	cnt++;
	mods[cnt] = NULL;
	if (debug_get_mode()) {
		ldapsvr_print_ldapmod(mods);
	}
	server->retVal = LDAPRC_SUCCESS;
	rc = ldap_add_ext_s(ld, base_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",
						base_dn, rc, ldaputil_get_error(ld));
				if (rc == 0x8)
					server->retVal = LDAPRC_STRONG_AUTH;
				else
					server->retVal = LDAPRC_NAMING_VIOLATION;
		}
	}
	ldapsvr_handle_other_attributes(ld, server, base_dn, contact);
	g_free(base_dn);
	clean_up(ld, server, contact);
}
示例#8
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);
	}
}
示例#9
0
/**
 * compare attribute to LDAP in case of LDAP_INAPPROPRIATE_MATCHING
 *
 * \param ld AddressBook resource
 * \param server Reference to server
 * \param dn dn for the entry
 * \param attr Attribute
 * \param value New value
 * \return int, return will be LDAP_MOD_ADD, LDAP_MOD_REPLACE, or LDAP_MOD_DELETE
 */
int ldapsvr_compare_manual_attr(LDAP *ld, LdapServer *server, gchar *dn, char *attr, char *value) {
	LDAPMessage *res, *e = NULL;
	BerElement *ber;
	struct berval **vals;
	int rc;
	LdapControl *ctl;
	gchar *filter;
	gchar *attribute;
	int retVal = -2, i;
	AttrKeyValue *mail;

	cm_return_val_if_fail(ld != NULL || server != NULL || attr != NULL, -1);
	ctl = server->control;
	mail = get_mail(dn);
	if (! mail)
		return -2;
	filter = g_strdup_printf("(&(mail=%s)(%s=*))", mail->value, attr);
	attrkeyvalue_free(mail);
	if (ctl) {

		rc = ldap_search_ext_s(ld, ctl->baseDN, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, NULL, NULL, NULL, 0, &res);

		if (rc) {
			g_printerr("ldap_search for attr=%s\" failed[0x%x]: %s\n",attr, rc, ldaputil_get_error(ld));
			retVal = -2;
		}
		else {
			e = ldap_first_entry(ld, res);
			/* entry has this attribute */
			if (e) {
				attribute = ldap_first_attribute( ld, e, &ber );
				if (attribute) {
					if (value) {
						if( ( vals = ldap_get_values_len( ld, e, attr ) ) != NULL ) {
							for( i = 0; vals[i] != NULL; i++ ) {
								debug_print("Compare: %s=%s\n", attr, vals[i]->bv_val);
								/* attribute has same value */
								if (strcmp(vals[i]->bv_val, value) == 0)
									retVal = -1;
								/* attribute has new value */
								else
									retVal = LDAP_MOD_REPLACE;
							}
						}
						ldap_value_free_len(vals);
					}
					else
						retVal = LDAP_MOD_DELETE;
				}
				if( ber != NULL ) {
					ber_free( ber, 0 );
				}
				ldap_memfree(attribute);
			}
			/* entry does not have this attribute */
			else {
				/* Only add if this is a real attribute */
				if (value)
					retVal = LDAP_MOD_ADD;
				/* This is dummy value used to avoid ldap_compare error */
				else
					retVal = -1;
			}
		}
	}
	else
		retVal = -2;
	g_free(filter);
	return retVal;
}
示例#10
0
/**
 * Update contact to LDAP
 *
 * \param server AddressBook resource
 * \param contact GHashTable with object to update
 */
void ldapsvr_update_contact(LdapServer *server, GHashTable *contact) {
	LDAP *ld = NULL;
	LDAPMod *mods[MODSIZE];
	LDAPMod modarr[4];
	gint cnt = 0;
	gchar *param, *dn;
	Rdn *NoRemove = NULL;
	char *cn[] = {NULL, NULL};
	char *givenName[] = {NULL, NULL};
	char **mail = NULL;
	char *sn[] = {NULL, NULL};
	GList *mailList;
	int mod_op;

	cm_return_if_fail(server != NULL || contact != NULL);
	ld = ldapsvr_connect(server->control);
	if (ld == NULL) {
		clean_up(ld, server, contact);
		return;
	}
	dn = g_hash_table_lookup(contact, "dn");

	if (dn == NULL) {
		clean_up(ld, server, contact);
		return;
	}
	NoRemove = ldapsvr_modify_dn(contact, dn);
	if (NoRemove) {
		/* We are trying to change RDN */
		gchar *newRdn = g_strdup_printf("%s=%s", NoRemove->attribute, NoRemove->value);

#ifdef OPEN_LDAP_API_AT_LEAST_3000

		int rc = ldap_rename_s(ld, dn, newRdn, NULL, 1, NULL, NULL);

#else

		/* This is deprecated as of OpenLDAP-2.3.0 */
		int rc = ldap_modrdn2_s(ld, dn, newRdn, 1);

#endif

		if(rc != LDAP_SUCCESS) {
			if (rc ==  LDAP_ALREADY_EXISTS) {
				/* We are messing with a contact with more than one listed email
				 * address and the email we are changing is not the one used for dn
				 */
				/* It needs to be able to handle renaming errors to an already defined
				 * dn. For now we just refuse the update. It will be caught later on as
				 * a LDAPRC_NAMING_VIOLATION error.
				 */
			}
			else {
				g_printerr("Current dn: %s\n", dn);
				g_printerr("new dn: %s\n", newRdn);
				g_printerr("LDAP Error(ldap_modrdn2_s) failed[0x%x]: %s\n", rc, ldaputil_get_error(ld));
				g_free(newRdn);
				clean_up(ld, server, contact);
				return;
			}
		}
		else {
			ItemPerson *person = g_hash_table_lookup(contact, "person");
			g_free(newRdn);
			dn = g_strdup(NoRemove->new_dn);
			g_hash_table_replace(contact, "dn", dn);
			if (person) {
				g_free(person->externalID);
				person->externalID = dn;
			}
		}
	}
	else {
		server->retVal = LDAPRC_NODN;
		clean_up(ld, server, contact);
		return;
	}
	param = g_hash_table_lookup(contact , "cn");
	mod_op = ldapsvr_deside_operation(ld, server, dn, "displayName", param);
	if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("cn", NoRemove->attribute) != 0)) {
		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
			 */
			param = NULL;
		}
		if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 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;
			param = NULL;
		}
		if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 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, "displayName", cn, param);
			cnt++;
			g_hash_table_insert(contact, "displayName", param);
		}
	}
	param = g_hash_table_lookup(contact , "givenName");
	mod_op = ldapsvr_deside_operation(ld, server, dn, "givenName", param);
	if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("givenName", NoRemove->attribute) != 0)) {
		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
			 */
			param = NULL;
		}
		if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 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;
			param = NULL;
		}
		if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 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, "givenName", givenName, param);
			cnt++;
		}
	}
	mailList = g_hash_table_lookup(contact , "mail");
	if (mailList) {
		debug_print("# of mail: %d\n", g_list_length(mailList));
		if (!(strcmp("mail", NoRemove->attribute) == 0 && g_list_length(mailList) == 1)) {
			char **tmp;
			tmp = g_malloc(sizeof(*tmp) * (g_list_length(mailList)+1));
			mail = tmp;
			while (mailList) {
				EmailKeyValue *item = mailList->data;
				*tmp++ = g_strdup((gchar *) item->mail);
				mailList = g_list_next(mailList);
			}
			*tmp = NULL;
			/*
			 * At least one email address is required
			 * in which case it will always be a replace
			 */
			SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_REPLACE, "mail", mail);
			cnt++;
		}
	}
	else {
		/*
		 * an error condition since at least one email adress
		 * is required. Should never occur though.
		 */
	}
	param = g_hash_table_lookup(contact , "sn");
	mod_op = ldapsvr_deside_operation(ld, server, dn, "sn", param);
	if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("sn", NoRemove->attribute) != 0)) {
		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
			 */
			param = NULL;
		}
		if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 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;
			param = NULL;
		}
		if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 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, "sn", sn, param);
			cnt++;
		}
	}
	debug_print("newDN: %s\n", dn);
	if (NoRemove)
		rdn_free(NoRemove);
	server->retVal = LDAPRC_SUCCESS;
	if (cnt > 0) {
		int rc;
		mods[cnt] = NULL;
		rc = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
		if (rc) {
			g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
                    dn, rc, ldaputil_get_error(ld));
			server->retVal = LDAPRC_NAMING_VIOLATION;
		}
		if (mail)
			g_free(mail);
	}
	ldapsvr_handle_other_attributes(ld, server, dn, contact);
	/* If we do not make changes persistent at this point then changes
	 * will be lost if the user makes new search on the same server since
	 * changes are only present in Claws' internal cache. This issue has to
	 * be solved in addressbook.c since this involves access to structures
	 * which are only accessible in addressbook.c */
	clean_up(ld, server, contact);
}