]> jfr.im git - irc/evilnet/x3.git/blame - src/x3ldap.c
quick fix for "Unable to find user SOME-SERVER whose mark is changing." errors, bette...
[irc/evilnet/x3.git] / src / x3ldap.c
CommitLineData
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
8 * the Free Software Foundation; either version 2 of the License, or
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
AS
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
AS
30#ifdef WITH_LDAP
31
e166c31b
AS
32#include <stdio.h>
33#include <stdlib.h>
34#include <ldap.h>
73d4cc91 35
e166c31b 36#include "conf.h"
e166c31b 37#include "global.h"
50895889 38#include "log.h"
e166c31b
AS
39#include "x3ldap.h"
40
e166c31b
AS
41extern struct nickserv_config nickserv_conf;
42
43
e166c31b 44LDAP *ld = NULL;
b96027ad 45int admin_bind = false;
e166c31b
AS
46
47int ldap_do_init()
48{
39edf54a
AS
49 if(!nickserv_conf.ldap_enable)
50 return false;
e166c31b 51 /* TODO: check here for all required config options and exit() out if not present */
bec5dd26
AS
52 //ld = ldap_init(nickserv_conf.ldap_host, nickserv_conf.ldap_port);
53
54 //if(ld == NULL) {
55 if(ldap_initialize(&ld, nickserv_conf.ldap_uri)) {
50895889 56 log_module(MAIN_LOG, LOG_ERROR, "LDAP initilization failed!\n");
e166c31b
AS
57 exit(1);
58 }
59 ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &nickserv_conf.ldap_version);
bec5dd26 60 log_module(MAIN_LOG, LOG_INFO, "Success! ldap_init() was successfull in connecting to %s\n", nickserv_conf.ldap_uri);
e166c31b
AS
61 return true;
62}
63
ea02341b 64
e166c31b
AS
65/* Try to auth someone. If theres problems, try reconnecting
66 * once every 10 seconds for 1 minute.
67 * TODO: move this stuff to config file
68 */
ea02341b 69unsigned int ldap_do_bind( const char *dn, const char *pass)
e166c31b 70{
e166c31b
AS
71 int q;
72
e166c31b
AS
73 int n = 0;
74 while(1) {
ea02341b 75 q = ldap_simple_bind_s(ld, dn, pass);
e166c31b 76 if(q == LDAP_SUCCESS) {
4b8ccfeb 77 log_module(MAIN_LOG, LOG_DEBUG, "bind() successfull! You are bound as %s", dn);
ea02341b 78 /* unbind now */
a5a8a781 79 return q;
e166c31b
AS
80 }
81 else if(q == LDAP_INVALID_CREDENTIALS) {
a5a8a781 82 return q;
e166c31b
AS
83 }
84 else {
5aef35cf
AS
85 log_module(MAIN_LOG, LOG_ERROR, "Bind failed: %s/****** (%s)", dn, ldap_err2string(q));
86 /* ldap_perror(ld, "ldap"); */
ea02341b 87 ldap_do_init();
e166c31b 88 }
39edf54a
AS
89 if(n++ > 1) {
90 /* TODO: return to the user that this is a connection error and not a problem
91 * with their password
92 */
93 log_module(MAIN_LOG, LOG_ERROR, "Failing to reconnect to ldap server. Auth failing.");
a5a8a781 94 return q;
e166c31b
AS
95 }
96 }
ea02341b 97 log_module(MAIN_LOG, LOG_ERROR, "ldap_do_bind falling off the end. this shouldnt happen");
a5a8a781 98 return q;
ea02341b 99}
24e9e6c3
AS
100int ldap_do_admin_bind()
101{
b96027ad 102 int rc;
24e9e6c3
AS
103 if(!(nickserv_conf.ldap_admin_dn && *nickserv_conf.ldap_admin_dn &&
104 nickserv_conf.ldap_admin_pass && *nickserv_conf.ldap_admin_pass)) {
105 log_module(MAIN_LOG, LOG_ERROR, "Tried to admin bind, but no admin credentials configured in config file. ldap_admin_dn/ldap_admin_pass");
106 return LDAP_OTHER; /* not configured to do this */
107 }
b96027ad
AS
108 rc = ldap_do_bind(nickserv_conf.ldap_admin_dn, nickserv_conf.ldap_admin_pass);
109 if(rc == LDAP_SUCCESS)
110 admin_bind = true;
111 return rc;
24e9e6c3
AS
112}
113
ea02341b
AS
114
115unsigned int ldap_check_auth( char *account, char *pass)
116{
117 char buff[MAXLEN];
118
119 if(!nickserv_conf.ldap_enable)
a5a8a781 120 return LDAP_OTHER;
ea02341b
AS
121
122 memset(buff, 0, MAXLEN);
123 snprintf(buff, sizeof(buff)-1, nickserv_conf.ldap_dn_fmt /*"uid=%s,ou=Users,dc=afternet,dc=org"*/, account);
b96027ad 124 admin_bind = false;
ea02341b 125 return ldap_do_bind(buff, pass);
e166c31b
AS
126
127}
128
24e9e6c3 129int ldap_search_user(char *account, LDAPMessage **entry)
e166c31b
AS
130{
131
24e9e6c3
AS
132 char filter[MAXLEN+1];
133 int rc;
134 LDAPMessage *res;
e166c31b
AS
135
136 struct timeval timeout;
24e9e6c3
AS
137
138 memset(filter, 0, MAXLEN+1);
139 snprintf(filter, MAXLEN, "%s=%s", nickserv_conf.ldap_field_account, account);
e166c31b
AS
140 /*
141 Now we do a search;
142 */
143 timeout.tv_usec = 0;
ddcb3eb3 144 timeout.tv_sec = nickserv_conf.ldap_timeout;
b96027ad 145 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
24e9e6c3
AS
146 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
147 return rc;
148 }
149 if( (rc = ldap_search_st(ld, nickserv_conf.ldap_base, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &timeout, &res)) != LDAP_SUCCESS) {
150 log_module(MAIN_LOG, LOG_ERROR, "search failed: %s %s: %s", nickserv_conf.ldap_base, filter, ldap_err2string(rc));
151 return(rc);
e166c31b 152 }
24e9e6c3
AS
153 log_module(MAIN_LOG, LOG_DEBUG, "Search successfull! %s %s\n", nickserv_conf.ldap_base, filter);
154 if(ldap_count_entries(ld, res) != 1) {
b96027ad 155 log_module(MAIN_LOG, LOG_DEBUG, "LDAP search got %d entries when looking for %s", ldap_count_entries(ld, res), account);
24e9e6c3 156 return(LDAP_OTHER); /* Search was a success, but user not found.. */
e166c31b 157 }
24e9e6c3
AS
158 log_module(MAIN_LOG, LOG_DEBUG, "LDAP search got %d entries", ldap_count_entries(ld, res));
159 *entry = ldap_first_entry(ld, res);
160 return(rc);
161}
162
163/* queries the ldap server for account..
164 * if a single account match is found,
165 * email is allocated and set to the email address
166 * and returns LDAP_SUCCESS. returns LDAP_OTHER if
167 * 0 or 2+ entries are matched, or the proper ldap error
168 * code for other errors.
169 */
170int ldap_get_user_info(char *account, char **email)
171{
172 int rc;
173 char **value;
174 LDAPMessage *entry, *res;
b96027ad
AS
175 if(email)
176 *email = NULL;
24e9e6c3
AS
177 if( (rc = ldap_search_user(account, &res)) == LDAP_SUCCESS) {
178 entry = ldap_first_entry(ld, res);
179 value = ldap_get_values(ld, entry, nickserv_conf.ldap_field_email);
180 if(!value) {
181 return(LDAP_OTHER);
182 }
b96027ad
AS
183 if(email)
184 *email = strdup(value[0]);
24e9e6c3
AS
185 log_module(MAIN_LOG, LOG_DEBUG, "%s: %s\n", nickserv_conf.ldap_field_email, value[0]);
186 /*
187 value = ldap_get_values(ld, entry, "description");
188 log_module(MAIN_LOG, LOG_DEBUG, "Description: %s\n", value[0]);
189 value = ldap_get_values(ld, entry, "userPassword");
190 log_module(MAIN_LOG, LOG_DEBUG, "pass: %s\n", value ? value[0] : "error");
191 */
192 }
193 return(rc);
194}
195
e166c31b
AS
196 /*
197 ldap_result();
198 ldap_first_entry();
199 ldap_first_attribute();
200 for(;;) {
201 ldap_get_values();
202 ldap_next_attribute();
203 }
204
205 ldap_parse_result();
206
207 ldap_unbind_ext();
e166c31b
AS
208 */
209 /* get errors with ldap_err2string(); */
e166c31b 210
e166c31b 211
4b8ccfeb
AS
212/********* base64 stuff ***********/
213
8dc17ddf 214unsigned char *pack(const char *str, unsigned int *len)
4b8ccfeb
AS
215{
216 int nibbleshift = 4;
217 int first = 1;
218 char *v;
219 static unsigned char buf[MAXLEN+1];
220 int outputpos = -1;
221
222 memset(buf, 0, MAXLEN+1);
8dc17ddf 223 v = (char *)str;
4b8ccfeb
AS
224 while(*v) {
225 char n = *(v++);
226
227 if((n >= '0') && (n <= '9')) {
228 n -= '0';
229 } else if ((n >= 'A') && (n <= 'F')) {
230 n -= ('A' - 10);
231 } else if ((n >= 'a') && (n <= 'f')) {
232 n -= ('a' - 10);
233 } else {
234 printf("pack type H: illegal hex digit %c", n);
235 n = 0;
236 }
237
238 if (first--) {
239 buf[++outputpos] = 0;
240 } else {
241 first = 1;
242 }
243
244 buf[outputpos] |= (n << nibbleshift);
245 nibbleshift = (nibbleshift + 4) & 7;
246 }
247 *len = outputpos+1;
248 return(buf);
249}
250
251
252/* from php5 sources */
253static char base64_table[] =
254 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
255 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
256 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
257 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
258 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
259 };
260static char base64_pad = '=';
261
262char *base64_encode(const unsigned char *str, int length, int *ret_length)
263{
264 const unsigned char *current = str;
265 char *p;
266 char *result;
267
268 if ((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) {
269 if (ret_length != NULL) {
270 *ret_length = 0;
271 }
272 return NULL;
273 }
274
41a3556d 275 result = (char *)calloc((((length + 2) / 3) * 4)+1, sizeof(char));
4b8ccfeb
AS
276 p = result;
277
278 while (length > 2) { /* keep going until we have less than 24 bits */
279 *p++ = base64_table[current[0] >> 2];
280 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
281 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
282 *p++ = base64_table[current[2] & 0x3f];
283
284 current += 3;
285 length -= 3; /* we just handle 3 octets of data */
286 }
287
288 /* now deal with the tail end of things */
289 if (length != 0) {
290 *p++ = base64_table[current[0] >> 2];
291 if (length > 1) {
292 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
293 *p++ = base64_table[(current[1] & 0x0f) << 2];
294 *p++ = base64_pad;
295 } else {
296 *p++ = base64_table[(current[0] & 0x03) << 4];
297 *p++ = base64_pad;
298 *p++ = base64_pad;
299 }
300 }
301 if (ret_length != NULL) {
302 *ret_length = (int)(p - result);
303 }
304 *p = '\0';
305 return result;
306}
307
308
73d4cc91
AS
309char **make_object_vals()
310{
311 unsigned int y;
312 static char **object_vals = NULL;
313
314 if(object_vals)
315 free(object_vals);
316
317 object_vals = malloc(sizeof( *object_vals ) * nickserv_conf.ldap_object_classes->used);
318
319 for(y = 0; y < nickserv_conf.ldap_object_classes->used; y++) {
320 object_vals[y] = nickserv_conf.ldap_object_classes->list[y];
321 }
322 object_vals[y] = NULL;
323 return object_vals;
324}
325
8dc17ddf 326char *make_password(const char *crypted)
4b8ccfeb
AS
327{
328 char *base64pass;
4b8ccfeb
AS
329 unsigned char *packed;
330 unsigned int len;
331 char *passbuf;
4b8ccfeb
AS
332
333 packed = pack(crypted, &len);
334 base64pass = base64_encode(packed, len, NULL);
335 passbuf = malloc(strlen(base64pass) + 1 + 5);
336 strcpy(passbuf, "{MD5}");
337 strcat(passbuf, base64pass);
338 //log_module(MAIN_LOG, LOG_DEBUG, "Encoded password is: '%s'", passbuf);
339 free(base64pass);
340 return passbuf;
341
342}
343
73d4cc91 344LDAPMod **make_mods_add(const char *account, const char *password, const char *email, int *num_mods_ret)
ea02341b
AS
345{
346 static char *account_vals[] = { NULL, NULL };
347 static char *password_vals[] = { NULL, NULL };
348 static char *email_vals[] = { NULL, NULL };
ea02341b
AS
349 int num_mods = 3;
350 int i;
351 /* TODO: take this from nickserv_conf.ldap_add_objects */
ea02341b 352 LDAPMod **mods;
73d4cc91
AS
353 static char **object_vals;
354 object_vals = make_object_vals();
ea02341b
AS
355
356 account_vals[0] = (char *) account;
357 password_vals[0] = (char *) password;
358 email_vals[0] = (char *) email;
359
360 if(!(nickserv_conf.ldap_field_account && *nickserv_conf.ldap_field_account))
361 return 0; /* account required */
362 if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password))
363 return 0; /* password required */
364 if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email)
365 num_mods++;
366
367 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
368 for( i = 0; i < num_mods; i++) {
369 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
370 memset(mods[i], 0, sizeof(LDAPMod));
371 }
372
ea02341b
AS
373 mods[0]->mod_op = LDAP_MOD_ADD;
374 mods[0]->mod_type = strdup("objectclass");
375 mods[0]->mod_values = object_vals;
376
377 mods[1]->mod_op = LDAP_MOD_ADD;
378 mods[1]->mod_type = strdup(nickserv_conf.ldap_field_account);
379 mods[1]->mod_values = account_vals;
380
381 mods[2]->mod_op = LDAP_MOD_ADD;
382 mods[2]->mod_type = strdup(nickserv_conf.ldap_field_password);
383 mods[2]->mod_values = password_vals;
384
385 if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email && *email) {
386 mods[3]->mod_op = LDAP_MOD_ADD;
387 mods[3]->mod_type = strdup(nickserv_conf.ldap_field_email);
388 mods[3]->mod_values = email_vals;
389 mods[4] = NULL;
390 }
391 else
392 mods[3] = NULL;
393 *num_mods_ret = num_mods;
394 return mods;
395}
396
8dc17ddf 397int ldap_do_add(const char *account, const char *crypted, const char *email)
ea02341b
AS
398{
399 char newdn[MAXLEN];
400 LDAPMod **mods;
401 int rc, i;
402 int num_mods;
4b8ccfeb 403 char *passbuf;
ea02341b 404
b96027ad 405 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
ea02341b 406 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
a5a8a781 407 return rc;
ea02341b
AS
408 }
409
8dc17ddf 410 passbuf = make_password(crypted);
ea02341b 411 snprintf(newdn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
8dc17ddf 412 mods = make_mods_add(account, passbuf, email, &num_mods);
ea02341b
AS
413 if(!mods) {
414 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_add");
a5a8a781 415 return LDAP_OTHER;
ea02341b
AS
416 }
417 rc = ldap_add_ext_s(ld, newdn, mods, NULL, NULL);
eb9bf540 418 if(rc != LDAP_SUCCESS && rc!= LDAP_ALREADY_EXISTS) {
ea02341b 419 log_module(MAIN_LOG, LOG_ERROR, "Error adding ldap account: %s -- %s", account, ldap_err2string(rc));
b96027ad 420 // return rc;
ea02341b
AS
421 }
422 //ldap_unbind_s(ld);
423 for(i = 0; i < num_mods; i++) {
424 free(mods[i]->mod_type);
425 free(mods[i]);
426 }
427 free(mods);
4b8ccfeb 428 free(passbuf);
a5a8a781 429 return rc;
ea02341b
AS
430}
431
73d4cc91
AS
432int ldap_delete_account(char *account)
433{
434 char dn[MAXLEN];
a40080a2
AS
435 int rc;
436
b96027ad 437 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
a40080a2
AS
438 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
439 return rc;
440 }
441
73d4cc91
AS
442 memset(dn, 0, MAXLEN);
443 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
444 return(ldap_delete_s(ld, dn));
445}
446
447int ldap_rename_account(char *oldaccount, char *newaccount)
448{
449 char dn[MAXLEN], newdn[MAXLEN];
450 int rc;
451
b96027ad 452 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
73d4cc91
AS
453 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
454 return rc;
455 }
456
457 memset(dn, 0, MAXLEN);
458 memset(newdn, 0, MAXLEN);
459 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, oldaccount);
460 strcat(newdn, nickserv_conf.ldap_field_account);
461 strcat(newdn, "=");
462 strcat(newdn, newaccount);
463 rc = ldap_modrdn2_s(ld, dn, newdn, true);
464 if(rc != LDAP_SUCCESS) {
465 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", oldaccount, ldap_err2string(rc));
b96027ad 466 //return rc;
73d4cc91
AS
467 }
468 return rc;
469
470}
471
472LDAPMod **make_mods_modify(const char *password, const char *email, int *num_mods_ret)
473{
474 static char *password_vals[] = { NULL, NULL };
475 static char *email_vals[] = { NULL, NULL };
8a729617 476 int num_mods = 0;
73d4cc91
AS
477 int i;
478 /* TODO: take this from nickserv_conf.ldap_add_objects */
479 LDAPMod **mods;
480
481 password_vals[0] = (char *) password;
482 email_vals[0] = (char *) email;
483
484 if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password))
485 return 0; /* password required */
8a729617 486 /*
73d4cc91
AS
487 if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email)
488 num_mods++;
8a729617
AS
489 */
490 if(password)
491 num_mods++;
492 if(email)
493 num_mods++;
73d4cc91
AS
494
495 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
496 for( i = 0; i < num_mods; i++) {
497 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
498 memset(mods[i], 0, sizeof(LDAPMod));
499 }
500
501 i = 0;
502 if(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password &&
503 password) {
504 mods[i]->mod_op = LDAP_MOD_REPLACE;
505 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_password);
506 mods[i]->mod_values = password_vals;
507 i++;
508 }
509
510 if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email) {
511 mods[i]->mod_op = LDAP_MOD_REPLACE;
512 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_email);
513 mods[i]->mod_values = email_vals;
514 i++;
515 }
516 mods[i] = NULL;
517 *num_mods_ret = num_mods;
518 return mods;
519}
520
73d4cc91
AS
521
522/* Save email or password to server
523 *
524 * password - UNENCRYPTED password. This function encrypts if libs are available
525 * email - email address
526 *
527 * NULL to make no change
528 */
529int ldap_do_modify(const char *account, const char *password, const char *email)
530{
531 char dn[MAXLEN];
532 LDAPMod **mods;
533 int rc, i;
534 int num_mods;
535 char *passbuf = NULL;
536
b96027ad 537 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
73d4cc91
AS
538 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
539 return rc;
540 }
541
542 if(password) {
4b8ccfeb 543 passbuf = make_password(password);
73d4cc91
AS
544 }
545
546 snprintf(dn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account);
547 mods = make_mods_modify(passbuf, email, &num_mods);
548 if(!mods) {
b96027ad 549 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_do_modify");
73d4cc91
AS
550 return LDAP_OTHER;
551 }
552 rc = ldap_modify_s(ld, dn, mods);
553 if(rc != LDAP_SUCCESS) {
b96027ad
AS
554 log_module(MAIN_LOG, LOG_ERROR, "Error modifying ldap account: %s -- %s", account, ldap_err2string(rc));
555 // return rc;
73d4cc91
AS
556 }
557 for(i = 0; i < num_mods; i++) {
558 free(mods[i]->mod_type);
559 free(mods[i]);
560 }
561 free(mods);
562 if(passbuf)
563 free(passbuf);
564 return rc;
565}
566
8a729617
AS
567LDAPMod **make_mods_group(const char *account, int operation, int *num_mods_ret)
568{
569 static char *uid_vals[] = { NULL, NULL };
570 int num_mods = 1;
571 int i;
572 /* TODO: take this from nickserv_conf.ldap_add_objects */
573 LDAPMod **mods;
574
575 uid_vals[0] = (char *) account;
576
577 if(!(nickserv_conf.ldap_field_group_member && *nickserv_conf.ldap_field_group_member))
578 return 0; /* password required */
579
580 mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * ));
581 for( i = 0; i < num_mods; i++) {
582 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
583 memset(mods[i], 0, sizeof(LDAPMod));
584 }
585
586 i = 0;
587 mods[i]->mod_op = operation;
588 mods[i]->mod_type = strdup(nickserv_conf.ldap_field_group_member);
589 mods[i]->mod_values = uid_vals;
590 i++;
591 mods[i] = NULL;
592 *num_mods_ret = num_mods;
593 return mods;
594}
595
596
597int ldap_add2group(char *account, const char *group)
598{
599 LDAPMod **mods;
600 int num_mods;
601 int rc, i;
602
b96027ad 603 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
8a729617
AS
604 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
605 return rc;
606 }
607 mods = make_mods_group(account, LDAP_MOD_ADD, &num_mods);
608 if(!mods) {
609 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for add2group");
610 return LDAP_OTHER;
611 }
612 rc = ldap_modify_s(ld, group, mods);
87677bd8 613 if(rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) {
8a729617
AS
614 log_module(MAIN_LOG, LOG_ERROR, "Error adding %s to group %s: %s", account, group, ldap_err2string(rc));
615 return rc;
616 }
617 for(i = 0; i < num_mods; i++) {
618 free(mods[i]->mod_type);
619 free(mods[i]);
620 }
621 free(mods);
622 return rc;
623}
624
625int ldap_delfromgroup(char *account, const char *group)
626{
627 LDAPMod **mods;
628 int num_mods;
629 int rc, i;
630
b96027ad 631 if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) {
8a729617
AS
632 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
633 return rc;
634 }
635 mods = make_mods_group(account, LDAP_MOD_DELETE, &num_mods);
636 if(!mods) {
637 log_module(MAIN_LOG, LOG_ERROR, "Error building mods for delfromgroup");
638 return LDAP_OTHER;
639 }
640 rc = ldap_modify_s(ld, group, mods);
eb9bf540 641 if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE) {
8a729617
AS
642 log_module(MAIN_LOG, LOG_ERROR, "Error removing %s from group %s: %s", account, group, ldap_err2string(rc));
643 return rc;
644 }
645 for(i = 0; i < num_mods; i++) {
646 free(mods[i]->mod_type);
647 free(mods[i]);
648 }
649 free(mods);
650 return rc;
651}
652
653
e166c31b
AS
654void ldap_close()
655{
b96027ad 656 admin_bind = false;
e166c31b
AS
657 ldap_unbind(ld);
658}
659
660#endif