1 /*
2 * jabberd - Jabber Open Source Server
3 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4 * Ryan Eatmon, Robert Norris
5 *
6 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19 */
20
21 /*
22 * Written by Nikita Smirnov in 2004
23 * on basis of authreg_ldap.c and storage_fs.c
24 */
25
26 #include "storage.h"
27
28 #ifdef STORAGE_LDAP
29
30 #define LDAP_DEPRECATED 1
31 #include <ldap.h>
32 #include <time.h>
33 #include <regex.h>
34
35 #define LDAPVCARD_SRVTYPE_LDAP 1
36 #define LDAPVCARD_SRVTYPE_AD 2
37
38 #define LDAPVCARD_SEARCH_MAX_RETRIES 1
39
40 extern int _ldap_get_lderrno(LDAP *ld);
41
42 /** internal structure, holds our data */
43 typedef struct drvdata_st {
44 LDAP *ld;
45 const char *uri;
46
47 const char *realm; // server id to be appended to uid
48
49 const char *binddn;
50 const char *bindpw;
51 const char *basedn;
52
53 const char *objectclass; // objectclass of jabber users
54 const char *uidattr; // search attribute for users
55 const char *validattr; // search attribute for valid
56 const char *pwattr; // attribute which holds password
57 const char *groupattr; // attribute with group name for published-roster in jabberuser entry
58 const char *groupattr_regex; // regex to create a new group attribute based on groupattr
59 const char *publishedattr; // can we publish it?
60
61 const char *groupsdn; // base dn for group names search
62 const char *groupsoc; // objectclass for group names search
63 const char *groupsidattr; // search attribute for group names
64 const char *groupnameattr; // attribute with text group name
65
66 int srvtype;
67 int mappedgroups;
68
69 #ifndef NO_SM_CACHE
70 os_t cache;
71 time_t cache_time;
72 time_t cache_ttl;
73 #endif
74 } *drvdata_t;
75
76 typedef struct {
77 char *ldapentry, *vcardentry;
78 os_type_t ot;
79 } ldapvcard_entry_st;
80
81 ldapvcard_entry_st ldapvcard_entry[] =
82 {
83 {"displayName","fn",os_type_STRING},
84 {"cn","nickname",os_type_STRING},
85 {"labeledURI","url",os_type_STRING},
86 {"telephoneNumber","tel",os_type_STRING},
87 {"mail","email",os_type_STRING},
88 {"title","title",os_type_STRING},
89 {"role","role",os_type_STRING},
90 {"dateOfBirth","bday",os_type_UNKNOWN}, /* fake type. TODO: os_type_DATE? */
91 // {"birthDate","bday",os_type_UNKNOWN}, /* http://tools.ietf.org/html/draft-gryphon-ldap-schema-vcard4-00 */
92 {"description","desc",os_type_STRING},
93 {"givenName","n-given",os_type_STRING},
94 {"jpegPhoto","photo-binval",os_type_STRING},
95 {"sn","n-family",os_type_STRING},
96 {"initials","n-middle",os_type_STRING},
97 {"st","adr-street",os_type_STRING},
98 {"zip","adr-extadd",os_type_STRING},
99 {"l","adr-locality",os_type_STRING},
100 // {"","adr-region",os_type_STRING},
101 {"postalCode","adr-pcode",os_type_STRING},
102 {"c","adr-country",os_type_STRING},
103 {"o","org-orgname",os_type_STRING},
104 {"ou","org-orgunit",os_type_STRING},
105 {NULL,NULL,0}
106 };
107
processregex(char * src,const char * regex,int patterngroups,int wantedgroup,char * dest,size_t dest_size,st_driver_t drv)108 static int processregex(char *src, const char *regex, int patterngroups, int wantedgroup, char *dest, size_t dest_size, st_driver_t drv) {
109 regex_t preg;
110 regmatch_t pmatch[patterngroups];
111 //log_debug(ZONE,"processregex: src='%s' regex='%s'", src, regex);
112 if (regcomp(&preg, regex, REG_ICASE|REG_EXTENDED) !=0) {
113 log_write(drv->st->log, LOG_ERR, "ldapvcard: regex compile failed on '%s'", regex);
114 return -1;
115 }
116 if (regexec(&preg, src, patterngroups, pmatch, 0) !=0) {
117 log_write(drv->st->log, LOG_ERR, "ldapvcard: regexec failed");
118 return -2;
119 }
120 regfree(&preg);
121 int len = pmatch[wantedgroup].rm_eo-pmatch[wantedgroup].rm_so>dest_size?dest_size:pmatch[wantedgroup].rm_eo-pmatch[wantedgroup].rm_so;
122 memcpy(dest, src+pmatch[wantedgroup].rm_so, len);
123 dest[len<dest_size?len:dest_size]='\0';
124 //log_debug(ZONE,"processregex: dest='%s'", dest);
125 return 0;
126 }
127
128 #ifndef NO_SM_CACHE
os_copy(os_t src,os_t dst)129 void os_copy(os_t src, os_t dst) {
130 os_object_t o,dsto;
131 char *key;
132 void *val, *cval;
133 os_type_t ot;
134
135 if(os_iter_first(src)) {
136 do {
137 //log_write(log, LOG_ERR, "reading object");
138 o = os_iter_object(src);
139 dsto = os_object_new(dst);
140 if( os_object_iter_first(o)) {
141 do {
142 os_object_iter_get(o,&key,&val,&ot);
143 switch(ot) {
144 case os_type_BOOLEAN:
145 case os_type_INTEGER:
146 cval = &val;
147 break;
148 default:
149 cval = val;
150 }
151 os_object_put(dsto,key,cval,ot);
152 //log_write(log, LOG_ERR, "wrote.");
153 } while(os_object_iter_next(o));
154 }
155 } while(os_iter_next(src));
156 } else { // ! os_iter_first(src)
157 log_debug(ZONE,"os_copy: cannot read source object");
158 }
159 }
160 #endif
161
162 /** utility function to get ld_errno */
_st_ldapvcard_get_lderrno(LDAP * ld)163 static int _st_ldapvcard_get_lderrno(LDAP *ld)
164 {
165 int ld_errno;
166 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
167 return ld_errno;
168 }
169
170 /** entry-point function for following referrals, required in some cases by Active Directory */
rebindProc(LDAP * ld,LDAP_CONST char * url,ber_tag_t request,ber_int_t msgid,void * mdata)171 static int rebindProc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *mdata)
172 {
173 drvdata_t data = mdata;
174 data->ld = ld;
175 if(ldap_simple_bind_s(data->ld, data->binddn, data->bindpw)) {
176 log_debug(ZONE, "ldapvcard: bind failed (to %s): %s", url, ldap_err2string(_ldap_get_lderrno(data->ld)));
177 ldap_unbind_s(data->ld);
178 data->ld = NULL;
179 return LDAP_INAPPROPRIATE_AUTH;
180 }
181
182 return LDAP_SUCCESS;
183 }
184
185 /** connect to the ldap host */
_st_ldapvcard_connect(st_driver_t drv)186 static int _st_ldapvcard_connect(st_driver_t drv)
187 {
188 drvdata_t data = (drvdata_t) drv->private;
189 int ldapversion = LDAP_VERSION3;
190 int rc;
191
192 if(data->ld != NULL)
193 ldap_unbind_s(data->ld);
194
195 rc = ldap_initialize( &(data->ld), data->uri);
196 if( rc != LDAP_SUCCESS )
197 {
198 log_write(drv->st->log, LOG_ERR, "ldapvcard: ldap_initialize failed (uri=%s): %s", data->uri, ldap_err2string(rc));
199 return 1;
200 }
201
202 if (ldap_set_option(data->ld, LDAP_OPT_PROTOCOL_VERSION, &ldapversion) != LDAP_SUCCESS)
203 {
204 log_write(drv->st->log, LOG_ERR, "ldapvcard: couldn't set v3 protocol");
205 return 1;
206 }
207 if (ldap_set_option(data->ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON) != LDAP_SUCCESS)
208 {
209 log_write(drv->st->log, LOG_ERR, "ldapvcard: couldn't set LDAP_OPT_REFERRALS");
210 }
211
212 return 0;
213 }
214
215 /** unbind and clear variables */
_st_ldapvcard_unbind(st_driver_t drv)216 static int _st_ldapvcard_unbind(st_driver_t drv) {
217 drvdata_t data = (drvdata_t) drv->private;
218 ldap_unbind_s(data->ld);
219 data->ld = NULL;
220 return 0;
221 }
222
223 /** connect to ldap and bind as data->binddn */
_st_ldapvcard_connect_bind(st_driver_t drv)224 static int _st_ldapvcard_connect_bind(st_driver_t drv) {
225 drvdata_t data = (drvdata_t) drv->private;
226
227 if(data->ld != NULL ) {
228 return 0;
229 }
230
231 if( _st_ldapvcard_connect(drv) ) {
232 return 1;
233 }
234 if(ldap_simple_bind_s(data->ld, data->binddn, data->bindpw))
235 {
236 log_write(drv->st->log, LOG_ERR, "ldapvcard: bind as %s failed: %s", data->binddn, ldap_err2string(_st_ldapvcard_get_lderrno(data->ld)));
237 _st_ldapvcard_unbind(drv);
238 return 1;
239 }
240 return 0;
241 }
242
_st_ldapvcard_add_type(st_driver_t drv,const char * type)243 static st_ret_t _st_ldapvcard_add_type(st_driver_t drv, const char *type) {
244 drvdata_t data = (drvdata_t) drv->private;
245
246 if( strncmp(type,"vcard",6) &&
247 strncmp(type,"published-roster",17) &&
248 strncmp(type,"published-roster-groups",24)
249 ) {
250 log_write(drv->st->log, LOG_ERR, "ldapvcard: only vcard,published-roster,published-roster-groups types supperted for now");
251 return st_FAILED;
252 } else {
253 if( !strncmp(type,"published-roster-groups",24) ) {
254 if( !data->mappedgroups ) {
255 log_write(drv->st->log, LOG_ERR, "ldapvcard: published-roster-groups is not enabled by map-groups config option in ldapvcard section");
256 return st_FAILED;
257 }
258 }
259 return st_SUCCESS;
260 }
261
262 return st_SUCCESS;
263 }
264
_st_ldapvcard_get(st_driver_t drv,const char * type,const char * owner,const char * filter,os_t * os)265 static st_ret_t _st_ldapvcard_get(st_driver_t drv, const char *type, const char *owner, const char *filter, os_t *os) {
266 drvdata_t data = (drvdata_t) drv->private;
267 os_object_t o;
268 char validfilter[256], ldapfilter[1024], **vals;
269 char *attrs_vcard[sizeof(ldapvcard_entry)/sizeof(ldapvcard_entry_st)];
270 const char *attrs_pr[] = { data->uidattr, data->groupattr, "sn", "displayName", "initials", NULL };
271 const char *attrs_prg[] = { data->groupnameattr, NULL };
272 LDAPMessage *result, *entry;
273 ldapvcard_entry_st le;
274 int i,ival;
275 int tried = 0;
276 char jid[2048], group[1024], name[2048]; // name is sn[1024] + ' ' + initials[1024]
277
278 if( _st_ldapvcard_connect_bind(drv) ) {
279 return st_FAILED;
280 }
281
282 if( strncmp(type,"vcard",6) == 0 ) {
283 // prepare need attributes
284 i = 0;
285 do {
286 le = ldapvcard_entry[i];
287 attrs_vcard[i++] = le.ldapentry;
288 } while ( le.ldapentry != NULL );
289
290 snprintf(ldapfilter, 1024, "(&(objectClass=%s)(%s=%s))", data->objectclass, data->uidattr, owner);
291 log_debug(ZONE, "search filter: %s", ldapfilter);
292
293 if(ldap_set_rebind_proc(data->ld, &rebindProc, data))
294 {
295 log_write(drv->st->log, LOG_ERR, "ldap: set_rebind_proc failed: %s", ldap_err2string(_st_ldapvcard_get_lderrno(data->ld)));
296 ldap_unbind_s(data->ld);
297 data->ld = NULL;
298 return st_FAILED;
299 }
300
301 if(ldap_search_s(data->ld, data->basedn, LDAP_SCOPE_SUBTREE, ldapfilter, attrs_vcard, 0, &result))
302 {
303 log_write(drv->st->log, LOG_ERR, "ldapvcard: search %s failed: %s", ldapfilter, ldap_err2string(_st_ldapvcard_get_lderrno(data->ld)));
304 _st_ldapvcard_unbind(drv);
305 return st_FAILED;
306 }
307
308 entry = ldap_first_entry(data->ld, result);
309 if(entry == NULL)
310 {
311 ldap_msgfree(result);
312 return st_FAILED;
313 }
314
315 *os = os_new();
316
317 o = os_object_new(*os);
318
319 i = 0;
320 le = ldapvcard_entry[i];
321 while( le.ldapentry != NULL ) {
322 if ( (strlen(le.ldapentry) == 9) && (!strncmp("jpegPhoto",le.ldapentry,9)))
323 {
324 struct berval **valphoto=(struct berval **)ldap_get_values_len(data->ld,entry,le.ldapentry);
325 if ( ldap_count_values_len(valphoto) > 0 )
326 {
327 char *VALJPG = b64_encode(valphoto[0]->bv_val, valphoto[0]->bv_len);
328 os_object_put(o, "photo-binval", VALJPG, os_type_STRING);
329 if( !strncmp(VALJPG, "/9j/4", 5) ) {
330 os_object_put(o, "photo-type", "image/jpeg", os_type_STRING);
331 } else if( !strncmp(VALJPG, "iVBOR", 5) ) {
332 os_object_put(o, "photo-type", "image/png", os_type_STRING);
333 } else if( !strncmp(VALJPG, "R0lGO", 5) ) {
334 os_object_put(o, "photo-type", "image/gif", os_type_STRING);
335 } else {
336 log_write(drv->st->log, LOG_ERR, "ldap: unknown photo fprmat photo %s", VALJPG);
337 os_object_put(o, "photo-type", "image/jpeg", os_type_STRING);
338 }
339 free(VALJPG);
340 }
341 ldap_value_free_len(valphoto);
342 } else {
343 vals=(char **)ldap_get_values(data->ld,entry,le.ldapentry);
344 if( ldap_count_values(vals) > 0 ) {
345 switch(le.ot) {
346 case os_type_BOOLEAN:
347 case os_type_INTEGER:
348 ival=atoi(vals[0]);
349 os_object_put(o, le.vcardentry, &ival, le.ot);
350 break;
351 case os_type_STRING:
352 os_object_put(o, le.vcardentry, vals[0], le.ot);
353 break;
354 case os_type_UNKNOWN: /* TODO: os_type_DATE? */
355 if( strlen(vals[0])==15 && vals[0][14]=='Z' ) { /* YYYYMMDDHHmmssZ */
356 /* convert generalizedTime to ISO-8601 date */
357 vals[0][10]='\0';
358 vals[0][9]=vals[0][7];
359 vals[0][8]=vals[0][6];
360 vals[0][7]='-';
361 vals[0][6]=vals[0][5];
362 vals[0][5]=vals[0][4];
363 vals[0][4]='-';
364 os_object_put(o, le.vcardentry, vals[0], os_type_STRING);
365 }
366 break;
367 case os_type_NAD:
368 log_write(drv->st->log, LOG_ERR, "ldapvcard: got unsupported os_type_NAD");
369 break;
370 }
371 }
372 ldap_value_free(vals);
373 }
374 le = ldapvcard_entry[++i];
375 }
376 ldap_msgfree(result);
377 } else if( strncmp(type,"published-roster",17) == 0 ) {
378 #ifndef NO_SM_CACHE
379 if( data->cache_ttl && data->cache && (time(NULL) - data->cache_time < data->cache_ttl) ) {
380 *os = os_new();
381 os_copy(data->cache, *os);
382 } else {
383 #endif
384 validfilter[0] = '\0';
385 if( data->srvtype == LDAPVCARD_SRVTYPE_AD ) {
386 if( data->validattr ) {
387 snprintf(validfilter, 256, "(%s=TRUE)(%s=TRUE)", data->publishedattr, data->validattr);
388 } else {
389 snprintf(validfilter, 256, "(%s=TRUE)", data->publishedattr);
390 }
391 } else {
392 if( data->validattr ) {
393 snprintf(validfilter, 256, "(&(%s=*)(!(%s=0)))(%s=1)", data->publishedattr, data->publishedattr, data->validattr);
394 } else {
395 snprintf(validfilter, 256, "(&(%s=*)(!(%s=0)))", data->publishedattr, data->publishedattr);
396 }
397 }
398
399 snprintf(ldapfilter, 1024, "(&%s(objectClass=%s)(%s=*))", validfilter, data->objectclass, data->uidattr);
400
401 log_debug(ZONE, "search filter: %s", ldapfilter);
402
403 retry_pubrost:
404 if(ldap_search_s(data->ld, data->basedn, LDAP_SCOPE_SUBTREE, ldapfilter, (char**)attrs_pr, 0, &result))
405 {
406 if( tried++ < LDAPVCARD_SEARCH_MAX_RETRIES ) {
407 log_debug(ZONE, "ldapvcard: search fail, will retry; %s: %s", ldapfilter, ldap_err2string(_st_ldapvcard_get_lderrno(data->ld)));
408 _st_ldapvcard_unbind(drv);
409 if( _st_ldapvcard_connect_bind(drv) == 0 ) {
410 goto retry_pubrost;
411 } else {
412 return st_FAILED;
413 }
414 }
415 log_write(drv->st->log, LOG_ERR, "ldapvcard: search %s failed: %s", ldapfilter, ldap_err2string(_st_ldapvcard_get_lderrno(data->ld)));
416 _st_ldapvcard_unbind(drv);
417 return st_FAILED;
418 }
419
420 entry = ldap_first_entry(data->ld, result);
421 if(entry == NULL)
422 {
423 ldap_msgfree(result);
424 return st_FAILED;
425 }
426
427 *os = os_new();
428
429 do {
430 vals = (char **)ldap_get_values(data->ld,entry,data->groupattr);
431 if( ldap_count_values(vals) <= 0 ) {
432 ldap_value_free(vals);
433 continue;
434 }
435 if (data->groupattr_regex == NULL || processregex(vals[0],data->groupattr_regex,2,1,group,sizeof(group),drv) !=0) {
436 // if there is no regex defined or processing the regex failed - take value as is
437 strncpy(group,vals[0],sizeof(group)-1);
438 }
439 group[sizeof(group)-1]='\0';
440 ldap_value_free(vals);
441
442 vals = (char **)ldap_get_values(data->ld,entry,data->uidattr);
443 if( ldap_count_values(vals) <= 0 ) {
444 ldap_value_free(vals);
445 continue;
446 }
447 if( data->realm == NULL ) {
448 strncpy(jid,vals[0],sizeof(jid)-1); jid[sizeof(jid)-1]='\0';
449 } else {
450 snprintf(jid, 2048, "%s@%s", vals[0], data->realm);
451 }
452
453 ldap_value_free(vals);
454
455 vals = (char **)ldap_get_values(data->ld,entry,"displayName");
456 if( ldap_count_values(vals) <= 0 ) {
457 ldap_value_free(vals);
458 vals = (char **)ldap_get_values(data->ld,entry,"cn");
459 if( ldap_count_values(vals) <= 0 ) {
460 strncpy(name,jid,sizeof(name)-1); name[sizeof(name)-1]='\0';
461 } else {
462 strncpy(name,vals[0],sizeof(name)-1); name[sizeof(name)-1]='\0';
463 }
464 } else {
465 strncpy(name,vals[0],1023); name[1023]='\0';
466 }
467 ldap_value_free(vals);
468
469 o = os_object_new(*os);
470 os_object_put(o,"jid",jid,os_type_STRING);
471 os_object_put(o,"group",group,os_type_STRING);
472 os_object_put(o,"name",name,os_type_STRING);
473 ival=1;
474 os_object_put(o,"to",&ival,os_type_BOOLEAN);
475 os_object_put(o,"from",&ival,os_type_BOOLEAN);
476 ival=0;
477 os_object_put(o,"ask",&ival,os_type_INTEGER);
478 } while( (entry = ldap_next_entry(data->ld, entry)) );
479 ldap_msgfree(result);
480 #ifndef NO_SM_CACHE
481 if( data->cache_ttl ) {
482 if( data->cache ) {
483 os_free(data->cache);
484 }
485 data->cache = os_new();
486 os_copy(*os, data->cache);
487 data->cache_time = time(NULL);
488 }
489 #endif
490 #ifndef NO_SM_CACHE
491 } // if !cached
492 #endif
493 } else if( strncmp(type,"published-roster-groups",24) == 0 ) {
494 snprintf(ldapfilter, 1024, "(&(objectClass=%s)(%s=%s))", data->groupsoc, data->groupsidattr, owner);
495 log_debug(ZONE, "search filter: %s", ldapfilter);
496 retry_pubrostgr:
497 if(ldap_search_s(data->ld, data->basedn, LDAP_SCOPE_SUBTREE, ldapfilter, (char**)attrs_prg, 0, &result))
498 {
499 if( tried++ < LDAPVCARD_SEARCH_MAX_RETRIES ) {
500 log_debug(ZONE, "ldapvcard: search fail, will retry; %s: %s", ldapfilter, ldap_err2string(_st_ldapvcard_get_lderrno(data->ld)));
501 _st_ldapvcard_unbind(drv);
502 if( _st_ldapvcard_connect_bind(drv) == 0 ) {
503 goto retry_pubrostgr;
504 } else {
505 return st_FAILED;
506 }
507 }
508 log_write(drv->st->log, LOG_ERR, "ldapvcard: search %s failed: %s", ldapfilter, ldap_err2string(_st_ldapvcard_get_lderrno(data->ld)));
509 _st_ldapvcard_unbind(drv);
510 return st_FAILED;
511 }
512
513 entry = ldap_first_entry(data->ld, result);
514 if(entry == NULL)
515 {
516 ldap_msgfree(result);
517 return st_FAILED;
518 }
519
520 *os = os_new();
521
522 // use only the first found entry and the first found attribute value
523 vals = (char **)ldap_get_values(data->ld,entry,data->groupnameattr);
524 if( ldap_count_values(vals) <= 0 ) {
525 ldap_value_free(vals);
526 ldap_msgfree(result);
527 return st_FAILED;
528 }
529 strncpy(group,vals[0],sizeof(group)-1); group[sizeof(group)-1]='\0';
530 ldap_value_free(vals);
531 ldap_msgfree(result);
532
533 o = os_object_new(*os);
534 os_object_put(o,"groupname",group,os_type_STRING);
535 } else {
536 log_write(drv->st->log, LOG_ERR, "ldapvcard: unknown storage type: '%s'", type);
537 return st_FAILED;
538 }
539
540 return st_SUCCESS;
541 }
542
_st_ldapvcard_put(st_driver_t drv,const char * type,const char * owner,os_t os)543 static st_ret_t _st_ldapvcard_put(st_driver_t drv, const char *type, const char *owner, os_t os) {
544 return st_FAILED;
545 }
_st_ldapvcard_delete(st_driver_t drv,const char * type,const char * owner,const char * filter)546 static st_ret_t _st_ldapvcard_delete(st_driver_t drv, const char *type, const char *owner, const char *filter) {
547 return st_SUCCESS;
548 }
_st_ldapvcard_replace(st_driver_t drv,const char * type,const char * owner,const char * filter,os_t os)549 static st_ret_t _st_ldapvcard_replace(st_driver_t drv, const char *type, const char *owner, const char *filter, os_t os) {
550 return st_FAILED;
551 }
552
_st_ldapvcard_free(st_driver_t drv)553 static void _st_ldapvcard_free(st_driver_t drv) {
554 drvdata_t data = (drvdata_t) drv->private;
555 if( data->ld ) {
556 _st_ldapvcard_unbind(drv);
557 }
558 free(data);
559 }
560
st_init(st_driver_t drv)561 DLLEXPORT st_ret_t st_init(st_driver_t drv)
562 {
563 drvdata_t data;
564 const char *uri, *realm, *basedn, *srvtype_s;
565 int srvtype_i;
566
567 log_write(drv->st->log, LOG_NOTICE, "ldapvcard: initializing");
568
569 uri = config_get_one(drv->st->config, "storage.ldapvcard.uri", 0);
570 if(uri == NULL) {
571 log_write(drv->st->log, LOG_ERR, "ldapvcard: no uri specified in config file");
572 return st_FAILED;
573 }
574
575 realm = config_get_one(drv->st->config, "storage.ldapvcard.realm", 0);
576 if(realm != NULL) {
577 log_write(drv->st->log, LOG_NOTICE, "ldapvcard: defined realm %s", realm);
578 }
579
580 basedn = config_get_one(drv->st->config, "storage.ldapvcard.basedn", 0);
581 if(basedn == NULL) {
582 log_write(drv->st->log, LOG_ERR, "ldapvcard: no basedn specified in config file");
583 return st_FAILED;
584 }
585
586 srvtype_s = config_get_one(drv->st->config, "storage.ldapvcard.type", 0);
587 if( srvtype_s == NULL ) {
588 srvtype_i = LDAPVCARD_SRVTYPE_LDAP;
589 } else if( !strcmp(srvtype_s, "ldap") ) {
590 srvtype_i = LDAPVCARD_SRVTYPE_LDAP;
591 } else if( !strcmp(srvtype_s, "ad") ) {
592 srvtype_i = LDAPVCARD_SRVTYPE_AD;
593 } else {
594 log_write(drv->st->log, LOG_ERR, "ldapvcard: unknown server type: %s", srvtype_s);
595 return 1;
596 }
597
598 data = (drvdata_t) calloc(1, sizeof(struct drvdata_st));
599
600 drv->private = (void *) data;
601
602 data->uri = uri;
603 data->realm = realm;
604 data->basedn = basedn;
605 data->srvtype = srvtype_i;
606
607 data->binddn = config_get_one(drv->st->config, "storage.ldapvcard.binddn", 0);
608 if(data->binddn != NULL)
609 data->bindpw = config_get_one(drv->st->config, "storage.ldapvcard.bindpw", 0);
610
611 data->uidattr = config_get_one(drv->st->config, "storage.ldapvcard.uidattr", 0);
612 if(data->uidattr == NULL)
613 data->uidattr = "uid";
614
615 data->validattr = config_get_one(drv->st->config, "storage.ldapvcard.validattr", 0);
616
617 data->groupattr = config_get_one(drv->st->config, "storage.ldapvcard.groupattr", 0);
618 if(data->groupattr == NULL)
619 data->groupattr = "jabberPublishedGroup";
620
621 data->groupattr_regex = config_get_one(drv->st->config, "storage.ldapvcard.groupattr_regex", 0);
622
623 data->publishedattr = config_get_one(drv->st->config, "storage.ldapvcard.publishedattr", 0);
624 if(data->publishedattr == NULL)
625 data->publishedattr = "jabberPublishedItem";
626
627 #ifndef NO_SM_CACHE
628 data->cache_ttl = j_atoi(config_get_one(drv->st->config, "storage.ldapvcard.publishedcachettl", 0), 0);
629 data->cache = NULL;
630 data->cache_time = 0;
631 #endif
632
633 data->objectclass = config_get_one(drv->st->config, "storage.ldapvcard.objectclass", 0);
634 if(data->objectclass == NULL)
635 data->objectclass = "jabberUser";
636
637 data->mappedgroups = j_atoi(config_get_one(drv->st->config, "storage.ldapvcard.mapped-groups.map-groups", 0), 0);
638 if( data->mappedgroups ) {
639 data->groupsdn = config_get_one(drv->st->config, "storage.ldapvcard.mapped-groups.basedn", 0);
640 if(data->groupsdn == NULL) {
641 log_write(drv->st->log, LOG_ERR, "ldapvcard: no basedn for mapped-groups specified in config file");
642 return st_FAILED;
643 }
644
645 data->groupsoc = config_get_one(drv->st->config, "storage.ldapvcard.mapped-groups.objectclass", 0);
646 if(data->groupsoc == NULL)
647 data->groupsoc = "jabberGroup";
648
649 data->groupsidattr = config_get_one(drv->st->config, "storage.ldapvcard.mapped-groups.idattr", 0);
650 if(data->groupsidattr == NULL)
651 data->groupsidattr = "cn";
652
653 data->groupnameattr = config_get_one(drv->st->config, "storage.ldapvcard.mapped-groups.nameattr", 0);
654 if(data->groupnameattr == NULL)
655 data->groupnameattr = "description";
656 }
657
658 drv->add_type = _st_ldapvcard_add_type;
659 drv->put = _st_ldapvcard_put;
660 drv->get = _st_ldapvcard_get;
661 drv->delete = _st_ldapvcard_delete;
662 drv->replace = _st_ldapvcard_replace;
663 drv->free = _st_ldapvcard_free;
664
665 return st_SUCCESS;
666 }
667
668 #endif
669