Example #1
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);
}
Example #2
0
/**
 * Connect to LDAP server.
 * \param  qry Query object to process.
 * \return Error/status code.
 */
static gint ldapqry_connect( LdapQuery *qry ) {
	LdapControl *ctl;
	LDAP *ld = NULL;

	/* Initialize connection */
	if (debug_get_mode()) {
		debug_print("===ldapqry_connect===\n");
		/*ldapqry_print(qry, stdout);*/
	}
	ctl = qry->control;
	/*if (debug_get_mode()) {
		ldapctl_print(ctl, stdout);
		debug_print("======\n");
	}*/
	ldapqry_touch( qry );
	qry->startTime = qry->touchTime;
	qry->elapsedTime = -1;
	ADDRQUERY_RETVAL(qry) = LDAPRC_INIT;

	ld = ldapsvr_connect(ctl);

	if (ld == NULL)
		return ADDRQUERY_RETVAL(qry);

	qry->ldap = ld;
	ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
	if( ldapqry_get_stop_flag( qry ) ) {
		return ADDRQUERY_RETVAL(qry);
	}
	ldapqry_touch( qry );

	debug_print("connected to LDAP host %s on port %d\n",
			ctl->hostName?ctl->hostName:"null", ctl->port);

	ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
	if( ldapqry_get_stop_flag( qry ) ) {
		return ADDRQUERY_RETVAL(qry);
	}
	ldapqry_touch( qry );

	ADDRQUERY_RETVAL(qry) = LDAP_SUCCESS;

	return ADDRQUERY_RETVAL(qry);
}
Example #3
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);
}
Example #4
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);
}