1 #define BITLBEE_CORE
2 #define LDAP_DEPRECATED 1
3 #include "bitlbee.h"
4 #include <ldap.h>
5 
ldap_check_pass(const char * nick,const char * password)6 static storage_status_t ldap_check_pass(const char *nick, const char *password)
7 {
8 	LDAP *ldap;
9 	LDAPMessage *msg, *entry;
10 	char *dn = NULL;
11 	char *filter;
12 	char *attrs[1] = { NULL };
13 	int ret, count;
14 
15 	if((ret = ldap_initialize(&ldap, NULL)) != LDAP_SUCCESS) {
16 		log_message(LOGLVL_WARNING, "ldap_initialize failed: %s", ldap_err2string(ret));
17 		return STORAGE_OTHER_ERROR;
18 	}
19 
20 	/* First we do an anonymous bind to map uid=$nick to a DN*/
21 	if((ret = ldap_simple_bind_s(ldap, NULL, NULL)) != LDAP_SUCCESS) {
22 		ldap_unbind_s(ldap);
23 		log_message(LOGLVL_WARNING, "Anonymous bind failed: %s", ldap_err2string(ret));
24 		return STORAGE_OTHER_ERROR;
25 	}
26 
27 
28 	/* We search and process the result */
29 	filter = g_strdup_printf("(uid=%s)", nick);
30 	ret = ldap_search_ext_s(ldap, NULL, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, NULL, 1, &msg);
31 	g_free(filter);
32 
33 	if(ret != LDAP_SUCCESS) {
34 		ldap_unbind_s(ldap);
35 		log_message(LOGLVL_WARNING, "uid search failed: %s", ldap_err2string(ret));
36 		return STORAGE_OTHER_ERROR;
37 	}
38 
39 	count = ldap_count_entries(ldap, msg);
40 	if (count == -1) {
41 		ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &ret);
42 		ldap_msgfree(msg);
43 		ldap_unbind_s(ldap);
44 		log_message(LOGLVL_WARNING, "uid search failed: %s", ldap_err2string(ret));
45 		return STORAGE_OTHER_ERROR;
46 	}
47 
48 	if (!count) {
49 		ldap_msgfree(msg);
50 		ldap_unbind_s(ldap);
51 		return STORAGE_NO_SUCH_USER;
52 	}
53 
54 	entry = ldap_first_entry(ldap, msg);
55 	dn = ldap_get_dn(ldap, entry);
56 	ldap_msgfree(msg);
57 
58 	/* And now we bind as the user to authenticate */
59 	ret = ldap_simple_bind_s(ldap, dn, password);
60 	g_free(dn);
61 	ldap_unbind_s(ldap);
62 
63 	switch (ret) {
64 		case LDAP_SUCCESS:
65 			return STORAGE_OK;
66 		case LDAP_INVALID_CREDENTIALS:
67 			return STORAGE_INVALID_PASSWORD;
68 		default:
69 			log_message(LOGLVL_WARNING, "Authenticated bind failed: %s", ldap_err2string(ret));
70 			return STORAGE_OTHER_ERROR;
71 	}
72 }
73 
74 auth_backend_t auth_ldap = {
75 	.name = "ldap",
76 	.check_pass = ldap_check_pass,
77 };
78