]>
Commit | Line | Data |
---|---|---|
50895889 | 1 | /* x3ldap.c - LDAP functionality for x3, by Rubin |
2 | * Copyright 2002-2007 x3 Development Team | |
3 | * | |
4 | * This file is part of x3. | |
5 | * | |
6 | * x3 is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
348683aa | 8 | * the Free Software Foundation; either version 3 of the License, or |
50895889 | 9 | * (at your option) any later version. |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with srvx; if not, write to the Free Software Foundation, | |
18 | * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | |
e166c31b | 19 | * |
e166c31b | 20 | * |
21 | * TODO: | |
22 | * * get queries working in static existance, so i understand how it works | |
23 | * * get ldap enabled in ./configure | |
24 | * * x3.conf settings to enable/configure its use | |
25 | * * generic functions to enable ldap | |
26 | * * nickserv.c work to use said functions. | |
27 | */ | |
28 | ||
39edf54a | 29 | #include "config.h" |
db9a9a8a | 30 | #ifdef WITH_LDAP |
31 | ||
e166c31b | 32 | #include <stdio.h> |
33 | #include <stdlib.h> | |
34 | #include <ldap.h> | |
73d4cc91 | 35 | |
c8b4b87b | 36 | #include "base64.h" |
e166c31b | 37 | #include "conf.h" |
e166c31b | 38 | #include "global.h" |
50895889 | 39 | #include "log.h" |
e166c31b | 40 | #include "x3ldap.h" |
41 | ||
e166c31b | 42 | extern struct nickserv_config nickserv_conf; |
43 | ||
44 | ||
e166c31b | 45 | LDAP *ld = NULL; |
b96027ad | 46 | int admin_bind = false; |
e166c31b | 47 | |
48 | int ldap_do_init() | |
49 | { | |
39edf54a | 50 | if(!nickserv_conf.ldap_enable) |
51 | return false; | |
e166c31b | 52 | /* TODO: check here for all required config options and exit() out if not present */ |
bec5dd26 | 53 | //ld = ldap_init(nickserv_conf.ldap_host, nickserv_conf.ldap_port); |
54 | ||
55 | //if(ld == NULL) { | |
56 | if(ldap_initialize(&ld, nickserv_conf.ldap_uri)) { | |
50895889 | 57 | log_module(MAIN_LOG, LOG_ERROR, "LDAP initilization failed!\n"); |
e166c31b | 58 | exit(1); |
59 | } | |
60 | ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &nickserv_conf.ldap_version); | |
bec5dd26 | 61 | log_module(MAIN_LOG, LOG_INFO, "Success! ldap_init() was successfull in connecting to %s\n", nickserv_conf.ldap_uri); |
e166c31b | 62 | return true; |
63 | } | |
64 | ||
ea02341b | 65 | |
e166c31b | 66 | /* Try to auth someone. If theres problems, try reconnecting |
67 | * once every 10 seconds for 1 minute. | |
68 | * TODO: move this stuff to config file | |
69 | */ | |
ea02341b | 70 | unsigned int ldap_do_bind( const char *dn, const char *pass) |
e166c31b | 71 | { |
e166c31b | 72 | int q; |
73 | ||
e166c31b | 74 | int n = 0; |
75 | while(1) { | |
ea02341b | 76 | q = ldap_simple_bind_s(ld, dn, pass); |
e166c31b | 77 | if(q == LDAP_SUCCESS) { |
4b8ccfeb | 78 | log_module(MAIN_LOG, LOG_DEBUG, "bind() successfull! You are bound as %s", dn); |
ea02341b | 79 | /* unbind now */ |
a5a8a781 | 80 | return q; |
e166c31b | 81 | } |
82 | else if(q == LDAP_INVALID_CREDENTIALS) { | |
a5a8a781 | 83 | return q; |
e166c31b | 84 | } |
85 | else { | |
5aef35cf | 86 | log_module(MAIN_LOG, LOG_ERROR, "Bind failed: %s/****** (%s)", dn, ldap_err2string(q)); |
87 | /* ldap_perror(ld, "ldap"); */ | |
ea02341b | 88 | ldap_do_init(); |
e166c31b | 89 | } |
39edf54a | 90 | if(n++ > 1) { |
91 | /* TODO: return to the user that this is a connection error and not a problem | |
92 | * with their password | |
93 | */ | |
94 | log_module(MAIN_LOG, LOG_ERROR, "Failing to reconnect to ldap server. Auth failing."); | |
a5a8a781 | 95 | return q; |
e166c31b | 96 | } |
97 | } | |
ea02341b | 98 | log_module(MAIN_LOG, LOG_ERROR, "ldap_do_bind falling off the end. this shouldnt happen"); |
a5a8a781 | 99 | return q; |
ea02341b | 100 | } |
24e9e6c3 | 101 | int ldap_do_admin_bind() |
102 | { | |
b96027ad | 103 | int rc; |
24e9e6c3 | 104 | if(!(nickserv_conf.ldap_admin_dn && *nickserv_conf.ldap_admin_dn && |
105 | nickserv_conf.ldap_admin_pass && *nickserv_conf.ldap_admin_pass)) { | |
106 | log_module(MAIN_LOG, LOG_ERROR, "Tried to admin bind, but no admin credentials configured in config file. ldap_admin_dn/ldap_admin_pass"); | |
107 | return LDAP_OTHER; /* not configured to do this */ | |
108 | } | |
b96027ad | 109 | rc = ldap_do_bind(nickserv_conf.ldap_admin_dn, nickserv_conf.ldap_admin_pass); |
110 | if(rc == LDAP_SUCCESS) | |
111 | admin_bind = true; | |
112 | return rc; | |
24e9e6c3 | 113 | } |
114 | ||
ea02341b | 115 | |
63ba9d6f | 116 | unsigned int ldap_check_auth( const char *account, const char *pass) |
ea02341b | 117 | { |
118 | char buff[MAXLEN]; | |
119 | ||
120 | if(!nickserv_conf.ldap_enable) | |
a5a8a781 | 121 | return LDAP_OTHER; |
ea02341b | 122 | |
123 | memset(buff, 0, MAXLEN); | |
124 | snprintf(buff, sizeof(buff)-1, nickserv_conf.ldap_dn_fmt /*"uid=%s,ou=Users,dc=afternet,dc=org"*/, account); | |
b96027ad | 125 | admin_bind = false; |
ea02341b | 126 | return ldap_do_bind(buff, pass); |
e166c31b | 127 | |
128 | } | |
129 | ||
da207c62 | 130 | int ldap_search_user(const char *account, LDAPMessage **entry) |
e166c31b | 131 | { |
132 | ||
24e9e6c3 | 133 | char filter[MAXLEN+1]; |
134 | int rc; | |
135 | LDAPMessage *res; | |
e166c31b | 136 | |
137 | struct timeval timeout; | |
24e9e6c3 | 138 | |
139 | memset(filter, 0, MAXLEN+1); | |
140 | snprintf(filter, MAXLEN, "%s=%s", nickserv_conf.ldap_field_account, account); | |
e166c31b | 141 | /* |
142 | Now we do a search; | |
143 | */ | |
144 | timeout.tv_usec = 0; | |
ddcb3eb3 | 145 | timeout.tv_sec = nickserv_conf.ldap_timeout; |
b96027ad | 146 | if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { |
24e9e6c3 | 147 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); |
148 | return rc; | |
149 | } | |
150 | if( (rc = ldap_search_st(ld, nickserv_conf.ldap_base, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &timeout, &res)) != LDAP_SUCCESS) { | |
151 | log_module(MAIN_LOG, LOG_ERROR, "search failed: %s %s: %s", nickserv_conf.ldap_base, filter, ldap_err2string(rc)); | |
152 | return(rc); | |
e166c31b | 153 | } |
24e9e6c3 | 154 | log_module(MAIN_LOG, LOG_DEBUG, "Search successfull! %s %s\n", nickserv_conf.ldap_base, filter); |
155 | if(ldap_count_entries(ld, res) != 1) { | |
b96027ad | 156 | log_module(MAIN_LOG, LOG_DEBUG, "LDAP search got %d entries when looking for %s", ldap_count_entries(ld, res), account); |
24e9e6c3 | 157 | return(LDAP_OTHER); /* Search was a success, but user not found.. */ |
e166c31b | 158 | } |
24e9e6c3 | 159 | log_module(MAIN_LOG, LOG_DEBUG, "LDAP search got %d entries", ldap_count_entries(ld, res)); |
160 | *entry = ldap_first_entry(ld, res); | |
161 | return(rc); | |
162 | } | |
163 | ||
164 | /* queries the ldap server for account.. | |
165 | * if a single account match is found, | |
166 | * email is allocated and set to the email address | |
167 | * and returns LDAP_SUCCESS. returns LDAP_OTHER if | |
168 | * 0 or 2+ entries are matched, or the proper ldap error | |
169 | * code for other errors. | |
170 | */ | |
63ba9d6f | 171 | int ldap_get_user_info(const char *account, char **email) |
24e9e6c3 | 172 | { |
173 | int rc; | |
4179bc63 | 174 | struct berval **value; |
24e9e6c3 | 175 | LDAPMessage *entry, *res; |
b96027ad | 176 | if(email) |
177 | *email = NULL; | |
24e9e6c3 | 178 | if( (rc = ldap_search_user(account, &res)) == LDAP_SUCCESS) { |
179 | entry = ldap_first_entry(ld, res); | |
4179bc63 | 180 | value = ldap_get_values_len(ld, entry, nickserv_conf.ldap_field_email); |
24e9e6c3 | 181 | if(!value) { |
182 | return(LDAP_OTHER); | |
183 | } | |
b96027ad | 184 | if(email) |
4179bc63 MB |
185 | *email = strdup(value[0]->bv_val); |
186 | log_module(MAIN_LOG, LOG_DEBUG, "%s: %s\n", nickserv_conf.ldap_field_email, value[0]->bv_val); | |
187 | ldap_value_free_len(value); | |
24e9e6c3 | 188 | /* |
189 | value = ldap_get_values(ld, entry, "description"); | |
190 | log_module(MAIN_LOG, LOG_DEBUG, "Description: %s\n", value[0]); | |
191 | value = ldap_get_values(ld, entry, "userPassword"); | |
192 | log_module(MAIN_LOG, LOG_DEBUG, "pass: %s\n", value ? value[0] : "error"); | |
193 | */ | |
194 | } | |
195 | return(rc); | |
196 | } | |
197 | ||
e166c31b | 198 | /* |
199 | ldap_result(); | |
200 | ldap_first_entry(); | |
201 | ldap_first_attribute(); | |
202 | for(;;) { | |
203 | ldap_get_values(); | |
204 | ldap_next_attribute(); | |
205 | } | |
206 | ||
207 | ldap_parse_result(); | |
208 | ||
209 | ldap_unbind_ext(); | |
e166c31b | 210 | */ |
211 | /* get errors with ldap_err2string(); */ | |
e166c31b | 212 | |
e166c31b | 213 | |
4b8ccfeb | 214 | /********* base64 stuff ***********/ |
215 | ||
8dc17ddf | 216 | unsigned char *pack(const char *str, unsigned int *len) |
4b8ccfeb | 217 | { |
218 | int nibbleshift = 4; | |
219 | int first = 1; | |
220 | char *v; | |
221 | static unsigned char buf[MAXLEN+1]; | |
222 | int outputpos = -1; | |
223 | ||
224 | memset(buf, 0, MAXLEN+1); | |
8dc17ddf | 225 | v = (char *)str; |
4b8ccfeb | 226 | while(*v) { |
227 | char n = *(v++); | |
228 | ||
229 | if((n >= '0') && (n <= '9')) { | |
230 | n -= '0'; | |
231 | } else if ((n >= 'A') && (n <= 'F')) { | |
232 | n -= ('A' - 10); | |
233 | } else if ((n >= 'a') && (n <= 'f')) { | |
234 | n -= ('a' - 10); | |
235 | } else { | |
236 | printf("pack type H: illegal hex digit %c", n); | |
237 | n = 0; | |
238 | } | |
239 | ||
240 | if (first--) { | |
241 | buf[++outputpos] = 0; | |
242 | } else { | |
243 | first = 1; | |
244 | } | |
245 | ||
246 | buf[outputpos] |= (n << nibbleshift); | |
247 | nibbleshift = (nibbleshift + 4) & 7; | |
248 | } | |
249 | *len = outputpos+1; | |
250 | return(buf); | |
251 | } | |
252 | ||
73d4cc91 | 253 | char **make_object_vals() |
254 | { | |
255 | unsigned int y; | |
256 | static char **object_vals = NULL; | |
257 | ||
258 | if(object_vals) | |
259 | free(object_vals); | |
260 | ||
1f6bcd18 | 261 | object_vals = malloc(sizeof( *object_vals ) * (nickserv_conf.ldap_object_classes->used+1)); |
73d4cc91 | 262 | |
263 | for(y = 0; y < nickserv_conf.ldap_object_classes->used; y++) { | |
264 | object_vals[y] = nickserv_conf.ldap_object_classes->list[y]; | |
265 | } | |
266 | object_vals[y] = NULL; | |
267 | return object_vals; | |
e688d9c7 | 268 | /* NOTE: The return value of this is only good until the next call to it. */ |
73d4cc91 | 269 | } |
270 | ||
8dc17ddf | 271 | char *make_password(const char *crypted) |
4b8ccfeb | 272 | { |
273 | char *base64pass; | |
4b8ccfeb | 274 | unsigned char *packed; |
275 | unsigned int len; | |
276 | char *passbuf; | |
4b8ccfeb | 277 | |
278 | packed = pack(crypted, &len); | |
c8b4b87b | 279 | base64_encode_alloc(packed, len, &base64pass); |
4b8ccfeb | 280 | passbuf = malloc(strlen(base64pass) + 1 + 5); |
281 | strcpy(passbuf, "{MD5}"); | |
282 | strcat(passbuf, base64pass); | |
283 | //log_module(MAIN_LOG, LOG_DEBUG, "Encoded password is: '%s'", passbuf); | |
284 | free(base64pass); | |
285 | return passbuf; | |
286 | ||
287 | } | |
288 | ||
73d4cc91 | 289 | LDAPMod **make_mods_add(const char *account, const char *password, const char *email, int *num_mods_ret) |
ea02341b | 290 | { |
291 | static char *account_vals[] = { NULL, NULL }; | |
292 | static char *password_vals[] = { NULL, NULL }; | |
293 | static char *email_vals[] = { NULL, NULL }; | |
75fcdcad | 294 | int num_mods = 2; |
ea02341b | 295 | int i; |
75fcdcad | 296 | int mod = 0; |
ea02341b | 297 | /* TODO: take this from nickserv_conf.ldap_add_objects */ |
ea02341b | 298 | LDAPMod **mods; |
73d4cc91 | 299 | static char **object_vals; |
e688d9c7 | 300 | |
301 | account_vals[0] = NULL; | |
302 | account_vals[1] = NULL; | |
303 | password_vals[0] = NULL; | |
304 | password_vals[1] = NULL; | |
305 | email_vals[0] = NULL; | |
306 | email_vals[1] = NULL; | |
73d4cc91 | 307 | object_vals = make_object_vals(); |
ea02341b | 308 | |
309 | account_vals[0] = (char *) account; | |
75fcdcad | 310 | if (password != NULL) { |
311 | password_vals[0] = (char *) password; | |
312 | num_mods++; | |
313 | } | |
ea02341b | 314 | email_vals[0] = (char *) email; |
315 | ||
316 | if(!(nickserv_conf.ldap_field_account && *nickserv_conf.ldap_field_account)) | |
317 | return 0; /* account required */ | |
318 | if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password)) | |
319 | return 0; /* password required */ | |
320 | if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email) | |
321 | num_mods++; | |
322 | ||
323 | mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * )); | |
324 | for( i = 0; i < num_mods; i++) { | |
325 | mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); | |
326 | memset(mods[i], 0, sizeof(LDAPMod)); | |
327 | } | |
328 | ||
75fcdcad | 329 | mods[mod]->mod_op = LDAP_MOD_ADD; |
330 | mods[mod]->mod_type = strdup("objectclass"); | |
331 | mods[mod]->mod_values = object_vals; | |
332 | mod++; | |
333 | ||
334 | mods[mod]->mod_op = LDAP_MOD_ADD; | |
335 | mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_account); | |
336 | mods[mod]->mod_values = account_vals; | |
337 | mod++; | |
338 | ||
339 | if (password != NULL) { | |
340 | mods[mod]->mod_op = LDAP_MOD_ADD; | |
341 | mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_password); | |
342 | mods[mod]->mod_values = password_vals; | |
343 | mod++; | |
344 | } | |
ea02341b | 345 | |
346 | if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email && *email) { | |
75fcdcad | 347 | mods[mod]->mod_op = LDAP_MOD_ADD; |
348 | mods[mod]->mod_type = strdup(nickserv_conf.ldap_field_email); | |
349 | mods[mod]->mod_values = email_vals; | |
350 | mod++; | |
ea02341b | 351 | } |
75fcdcad | 352 | mods[mod] = NULL; |
ea02341b | 353 | *num_mods_ret = num_mods; |
354 | return mods; | |
355 | } | |
356 | ||
8dc17ddf | 357 | int ldap_do_add(const char *account, const char *crypted, const char *email) |
ea02341b | 358 | { |
359 | char newdn[MAXLEN]; | |
360 | LDAPMod **mods; | |
361 | int rc, i; | |
362 | int num_mods; | |
4b8ccfeb | 363 | char *passbuf; |
ea02341b | 364 | |
b96027ad | 365 | if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { |
ea02341b | 366 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); |
a5a8a781 | 367 | return rc; |
ea02341b | 368 | } |
75fcdcad | 369 | |
370 | if (crypted != NULL) | |
371 | passbuf = make_password(crypted); | |
ea02341b | 372 | snprintf(newdn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account); |
75fcdcad | 373 | mods = make_mods_add(account, (crypted != NULL ? passbuf : crypted), email, &num_mods); |
ea02341b | 374 | if(!mods) { |
375 | log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_add"); | |
a5a8a781 | 376 | return LDAP_OTHER; |
ea02341b | 377 | } |
378 | rc = ldap_add_ext_s(ld, newdn, mods, NULL, NULL); | |
eb9bf540 | 379 | if(rc != LDAP_SUCCESS && rc!= LDAP_ALREADY_EXISTS) { |
ea02341b | 380 | log_module(MAIN_LOG, LOG_ERROR, "Error adding ldap account: %s -- %s", account, ldap_err2string(rc)); |
b96027ad | 381 | // return rc; |
ea02341b | 382 | } |
383 | //ldap_unbind_s(ld); | |
384 | for(i = 0; i < num_mods; i++) { | |
385 | free(mods[i]->mod_type); | |
386 | free(mods[i]); | |
387 | } | |
388 | free(mods); | |
75fcdcad | 389 | if (crypted != NULL) |
390 | free(passbuf); | |
a5a8a781 | 391 | return rc; |
ea02341b | 392 | } |
393 | ||
73d4cc91 | 394 | int ldap_delete_account(char *account) |
395 | { | |
396 | char dn[MAXLEN]; | |
a40080a2 | 397 | int rc; |
398 | ||
b96027ad | 399 | if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { |
a40080a2 | 400 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); |
401 | return rc; | |
402 | } | |
403 | ||
73d4cc91 | 404 | memset(dn, 0, MAXLEN); |
405 | snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account); | |
406 | return(ldap_delete_s(ld, dn)); | |
407 | } | |
408 | ||
409 | int ldap_rename_account(char *oldaccount, char *newaccount) | |
410 | { | |
411 | char dn[MAXLEN], newdn[MAXLEN]; | |
412 | int rc; | |
413 | ||
b96027ad | 414 | if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { |
73d4cc91 | 415 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); |
416 | return rc; | |
417 | } | |
418 | ||
419 | memset(dn, 0, MAXLEN); | |
420 | memset(newdn, 0, MAXLEN); | |
421 | snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, oldaccount); | |
422 | strcat(newdn, nickserv_conf.ldap_field_account); | |
423 | strcat(newdn, "="); | |
424 | strcat(newdn, newaccount); | |
425 | rc = ldap_modrdn2_s(ld, dn, newdn, true); | |
426 | if(rc != LDAP_SUCCESS) { | |
427 | log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", oldaccount, ldap_err2string(rc)); | |
b96027ad | 428 | //return rc; |
73d4cc91 | 429 | } |
430 | return rc; | |
431 | ||
432 | } | |
433 | ||
434 | LDAPMod **make_mods_modify(const char *password, const char *email, int *num_mods_ret) | |
435 | { | |
436 | static char *password_vals[] = { NULL, NULL }; | |
437 | static char *email_vals[] = { NULL, NULL }; | |
8a729617 | 438 | int num_mods = 0; |
73d4cc91 | 439 | int i; |
440 | /* TODO: take this from nickserv_conf.ldap_add_objects */ | |
441 | LDAPMod **mods; | |
442 | ||
443 | password_vals[0] = (char *) password; | |
444 | email_vals[0] = (char *) email; | |
445 | ||
446 | if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password)) | |
447 | return 0; /* password required */ | |
8a729617 | 448 | /* |
73d4cc91 | 449 | if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email) |
450 | num_mods++; | |
8a729617 | 451 | */ |
452 | if(password) | |
453 | num_mods++; | |
454 | if(email) | |
455 | num_mods++; | |
73d4cc91 | 456 | |
457 | mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * )); | |
458 | for( i = 0; i < num_mods; i++) { | |
459 | mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); | |
460 | memset(mods[i], 0, sizeof(LDAPMod)); | |
461 | } | |
462 | ||
463 | i = 0; | |
464 | if(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password && | |
465 | password) { | |
466 | mods[i]->mod_op = LDAP_MOD_REPLACE; | |
467 | mods[i]->mod_type = strdup(nickserv_conf.ldap_field_password); | |
468 | mods[i]->mod_values = password_vals; | |
469 | i++; | |
470 | } | |
471 | ||
472 | if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email) { | |
473 | mods[i]->mod_op = LDAP_MOD_REPLACE; | |
474 | mods[i]->mod_type = strdup(nickserv_conf.ldap_field_email); | |
475 | mods[i]->mod_values = email_vals; | |
476 | i++; | |
477 | } | |
478 | mods[i] = NULL; | |
479 | *num_mods_ret = num_mods; | |
480 | return mods; | |
481 | } | |
482 | ||
35ea100f | 483 | /* Save OpServ level to LDAP |
484 | * | |
485 | * level - OpServ level | |
486 | * | |
487 | * A level of <0 will be treated as 0 | |
488 | */ | |
f3aff201 | 489 | int ldap_do_oslevel(const char *account, int level, int oldlevel) |
35ea100f | 490 | { |
491 | LDAPMod **mods; | |
492 | static char *oslevel_vals[] = { NULL, NULL }; | |
493 | char dn[MAXLEN], temp[MAXLEN]; | |
494 | int rc; | |
495 | ||
496 | if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { | |
497 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); | |
498 | return rc; | |
499 | } | |
500 | ||
501 | if (level < 0) { | |
502 | level = 0; | |
503 | } | |
504 | ||
f3aff201 | 505 | snprintf(temp, MAXLEN-1, "%d", (level ? level : oldlevel)); |
35ea100f | 506 | oslevel_vals[0] = (char *) temp; |
507 | ||
508 | if(!(nickserv_conf.ldap_field_oslevel && *nickserv_conf.ldap_field_oslevel)) | |
509 | return 0; | |
510 | ||
511 | snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account); | |
512 | ||
513 | mods = ( LDAPMod ** ) malloc(( 1 ) * sizeof( LDAPMod * )); | |
514 | mods[0] = (LDAPMod *) malloc(sizeof(LDAPMod)); | |
515 | memset(mods[0], 0, sizeof(LDAPMod)); | |
516 | ||
f3aff201 | 517 | mods[0]->mod_op = (level ? LDAP_MOD_REPLACE : LDAP_MOD_DELETE); |
35ea100f | 518 | mods[0]->mod_type = strdup(nickserv_conf.ldap_field_oslevel); |
519 | mods[0]->mod_values = oslevel_vals; | |
520 | mods[1] = NULL; | |
521 | ||
522 | rc = ldap_modify_s(ld, dn, mods); | |
523 | if(rc != LDAP_SUCCESS) { | |
524 | log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap OpServ level: %s -- %s", account, ldap_err2string(rc)); | |
525 | //return rc; | |
526 | } | |
527 | free(mods[0]->mod_type); | |
528 | free(mods[0]); | |
529 | free(mods); | |
530 | ||
531 | return rc; | |
532 | } | |
73d4cc91 | 533 | |
534 | /* Save email or password to server | |
535 | * | |
536 | * password - UNENCRYPTED password. This function encrypts if libs are available | |
537 | * email - email address | |
538 | * | |
539 | * NULL to make no change | |
540 | */ | |
541 | int ldap_do_modify(const char *account, const char *password, const char *email) | |
542 | { | |
543 | char dn[MAXLEN]; | |
544 | LDAPMod **mods; | |
545 | int rc, i; | |
546 | int num_mods; | |
547 | char *passbuf = NULL; | |
548 | ||
b96027ad | 549 | if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { |
73d4cc91 | 550 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); |
551 | return rc; | |
552 | } | |
553 | ||
554 | if(password) { | |
4b8ccfeb | 555 | passbuf = make_password(password); |
73d4cc91 | 556 | } |
557 | ||
558 | snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account); | |
559 | mods = make_mods_modify(passbuf, email, &num_mods); | |
560 | if(!mods) { | |
b96027ad | 561 | log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_do_modify"); |
73d4cc91 | 562 | return LDAP_OTHER; |
563 | } | |
564 | rc = ldap_modify_s(ld, dn, mods); | |
565 | if(rc != LDAP_SUCCESS) { | |
b96027ad | 566 | log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", account, ldap_err2string(rc)); |
567 | // return rc; | |
73d4cc91 | 568 | } |
569 | for(i = 0; i < num_mods; i++) { | |
570 | free(mods[i]->mod_type); | |
571 | free(mods[i]); | |
572 | } | |
573 | free(mods); | |
574 | if(passbuf) | |
575 | free(passbuf); | |
576 | return rc; | |
577 | } | |
578 | ||
8a729617 | 579 | LDAPMod **make_mods_group(const char *account, int operation, int *num_mods_ret) |
580 | { | |
581 | static char *uid_vals[] = { NULL, NULL }; | |
582 | int num_mods = 1; | |
583 | int i; | |
584 | /* TODO: take this from nickserv_conf.ldap_add_objects */ | |
585 | LDAPMod **mods; | |
586 | ||
587 | uid_vals[0] = (char *) account; | |
588 | ||
589 | if(!(nickserv_conf.ldap_field_group_member && *nickserv_conf.ldap_field_group_member)) | |
590 | return 0; /* password required */ | |
591 | ||
592 | mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * )); | |
593 | for( i = 0; i < num_mods; i++) { | |
594 | mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); | |
595 | memset(mods[i], 0, sizeof(LDAPMod)); | |
596 | } | |
597 | ||
598 | i = 0; | |
599 | mods[i]->mod_op = operation; | |
600 | mods[i]->mod_type = strdup(nickserv_conf.ldap_field_group_member); | |
601 | mods[i]->mod_values = uid_vals; | |
602 | i++; | |
603 | mods[i] = NULL; | |
604 | *num_mods_ret = num_mods; | |
605 | return mods; | |
606 | } | |
607 | ||
608 | ||
609 | int ldap_add2group(char *account, const char *group) | |
610 | { | |
611 | LDAPMod **mods; | |
612 | int num_mods; | |
613 | int rc, i; | |
614 | ||
b96027ad | 615 | if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { |
8a729617 | 616 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); |
617 | return rc; | |
618 | } | |
619 | mods = make_mods_group(account, LDAP_MOD_ADD, &num_mods); | |
620 | if(!mods) { | |
621 | log_module(MAIN_LOG, LOG_ERROR, "Error building mods for add2group"); | |
622 | return LDAP_OTHER; | |
623 | } | |
624 | rc = ldap_modify_s(ld, group, mods); | |
87677bd8 | 625 | if(rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) { |
8a729617 | 626 | log_module(MAIN_LOG, LOG_ERROR, "Error adding %s to group %s: %s", account, group, ldap_err2string(rc)); |
627 | return rc; | |
628 | } | |
629 | for(i = 0; i < num_mods; i++) { | |
630 | free(mods[i]->mod_type); | |
631 | free(mods[i]); | |
632 | } | |
633 | free(mods); | |
634 | return rc; | |
635 | } | |
636 | ||
637 | int ldap_delfromgroup(char *account, const char *group) | |
638 | { | |
639 | LDAPMod **mods; | |
640 | int num_mods; | |
641 | int rc, i; | |
642 | ||
b96027ad | 643 | if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { |
8a729617 | 644 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); |
645 | return rc; | |
646 | } | |
647 | mods = make_mods_group(account, LDAP_MOD_DELETE, &num_mods); | |
648 | if(!mods) { | |
649 | log_module(MAIN_LOG, LOG_ERROR, "Error building mods for delfromgroup"); | |
650 | return LDAP_OTHER; | |
651 | } | |
652 | rc = ldap_modify_s(ld, group, mods); | |
eb9bf540 | 653 | if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE) { |
8a729617 | 654 | log_module(MAIN_LOG, LOG_ERROR, "Error removing %s from group %s: %s", account, group, ldap_err2string(rc)); |
655 | return rc; | |
656 | } | |
657 | for(i = 0; i < num_mods; i++) { | |
658 | free(mods[i]->mod_type); | |
659 | free(mods[i]); | |
660 | } | |
661 | free(mods); | |
662 | return rc; | |
663 | } | |
664 | ||
665 | ||
e166c31b | 666 | void ldap_close() |
667 | { | |
b96027ad | 668 | admin_bind = false; |
52ac7828 | 669 | ldap_unbind_ext(ld, NULL, NULL); |
e166c31b | 670 | } |
671 | ||
da207c62 MB |
672 | /* queries the ldap server for account.. |
673 | * returns LDAP_SUCCESS if a match is found | |
674 | * returns LDAP_OTHER if no match is found | |
675 | * on error returns the proper ldap error | |
676 | */ | |
677 | int ldap_user_exists(const char *account) | |
678 | { | |
679 | int rc; | |
680 | LDAPMessage *res; | |
681 | ||
682 | rc = ldap_search_user(account, &res); | |
683 | ||
684 | return rc; | |
685 | } | |
686 | ||
e166c31b | 687 | #endif |