441 ldap_msgfree(result); |
446 ldap_msgfree(result); |
442 |
447 |
443 return (User*)user; |
448 return (User*)user; |
444 } |
449 } |
445 |
450 |
|
451 |
|
452 static int is_member_attribute(LDAPAuthDB *auth, const char *attribute) { |
|
453 LDAPConfig *config = &auth->config; |
|
454 cxstring attr = cx_str(attribute); |
|
455 for(int i=0;i<config->numMemberAttributes;i++) { |
|
456 if(!cx_strcmp(config->memberAttributes[i], attr)) { |
|
457 return 1; |
|
458 } |
|
459 } |
|
460 return 0; |
|
461 } |
|
462 |
|
463 static int group_add_member(LDAPGroup *group, LDAP *ldap, LDAPMessage *msg, char *attribute) { |
|
464 struct berval **values = ldap_get_values_len(ldap, msg, attribute); |
|
465 int ret = 0; |
|
466 if(values) { |
|
467 int count = ldap_count_values_len(values); |
|
468 for(int i=0;i<count;i++) { |
|
469 cxstring memberValue = cx_strn(values[i]->bv_val, values[i]->bv_len); |
|
470 CxHashKey key = cx_hash_key(memberValue.ptr, memberValue.length); |
|
471 char *g_member = cxMapGet(group->members, key); |
|
472 if(!g_member) { |
|
473 cxmutstr member = cx_strdup_a(group->members->allocator, memberValue); |
|
474 if(!member.ptr) { |
|
475 ret = 1; |
|
476 break; |
|
477 } |
|
478 if(cxMapPut(group->members, key, member.ptr)) { |
|
479 ret = 1; |
|
480 break; |
|
481 } |
|
482 } |
|
483 } |
|
484 ldap_value_free_len(values); |
|
485 } |
|
486 return ret; |
|
487 } |
|
488 |
|
489 static LDAPGroup* ldap_msg_to_group( |
|
490 Session *sn, |
|
491 Request *rq, |
|
492 LDAPAuthDB *authdb, |
|
493 LDAP *ldap, |
|
494 LDAPMessage *msg, |
|
495 const char *group_name) |
|
496 { |
|
497 CxAllocator *a = pool_allocator(sn->pool); |
|
498 |
|
499 LDAPGroup *group = pool_malloc(sn->pool, sizeof(LDAPGroup)); |
|
500 if(!group) { |
|
501 return NULL; |
|
502 } |
|
503 group->members = cxHashMapCreate(a, 32); |
|
504 if(!group->members) { |
|
505 pool_free(sn->pool, group); |
|
506 return NULL; |
|
507 } |
|
508 group->name = pool_strdup(sn->pool, group_name); |
|
509 |
|
510 BerElement *ber = NULL; |
|
511 char *attribute = ldap_first_attribute(ldap, msg, &ber); |
|
512 while(attribute) { |
|
513 if(is_member_attribute(authdb, attribute)) { |
|
514 if(group_add_member(group, ldap, msg, attribute)) { |
|
515 // OOM |
|
516 ldap_memfree(attribute); |
|
517 // free at least some memory |
|
518 cxMapDestroy(group->members); |
|
519 pool_free(sn->pool, group); |
|
520 group = NULL; |
|
521 break; |
|
522 } |
|
523 } |
|
524 |
|
525 ldap_memfree(attribute); |
|
526 attribute = ldap_next_attribute(ldap, msg, ber); |
|
527 } |
|
528 if(ber) { |
|
529 ber_free(ber, 0); |
|
530 } |
|
531 |
|
532 return group; |
|
533 } |
|
534 |
446 LDAPGroup* ldap_get_group(Session *sn, Request *rq, LDAPAuthDB *authdb, const char *group) { |
535 LDAPGroup* ldap_get_group(Session *sn, Request *rq, LDAPAuthDB *authdb, const char *group) { |
447 printf("ldap_get_group: %s\n", group); |
|
448 |
|
449 LDAPConfig *config = &authdb->config; |
536 LDAPConfig *config = &authdb->config; |
|
537 CxAllocator *a = pool_allocator(sn->pool); |
450 |
538 |
451 LDAP *ld = get_ldap_session(sn, rq, authdb); |
539 LDAP *ld = get_ldap_session(sn, rq, authdb); |
452 if (ld == NULL) { |
540 if (ld == NULL) { |
453 fprintf(stderr, "ldap_init failed\n"); |
541 return NULL; |
454 return NULL; |
542 } |
455 } |
543 |
456 |
544 cxstring groupSearch = cx_str(config->groupSearchFilter); |
457 // get the user dn |
545 cxmutstr filter = cx_strreplace_a(a, groupSearch, cx_str("%s"), cx_str(group)); |
458 // TODO: use config for filter |
546 if(!filter.ptr) { |
459 // TODO: use asprintf |
547 return NULL; |
460 char filter[128]; |
548 } |
461 int s = snprintf(filter, 127, "cn=%s", group); |
|
462 filter[s] = 0; |
|
463 |
549 |
464 LDAPMessage *result; |
550 LDAPMessage *result; |
465 struct timeval timeout; |
551 struct timeval timeout; |
466 timeout.tv_sec = 8; |
552 timeout.tv_sec = 8; |
467 timeout.tv_usec = 0; |
553 timeout.tv_usec = 0; |
468 int r = ldap_search_ext_s( |
554 int r = ldap_search_ext_s( |
469 ld, |
555 ld, |
470 config->basedn, |
556 config->basedn, |
471 LDAP_SCOPE_SUBTREE, |
557 LDAP_SCOPE_SUBTREE, |
472 filter, |
558 filter.ptr, |
473 NULL, |
559 NULL, |
474 0, |
560 0, |
475 NULL, // server controls |
561 NULL, // server controls |
476 NULL, // client controls |
562 NULL, // client controls |
477 &timeout, |
563 &timeout, |
478 1, // size limit |
564 2, // size limit |
479 &result); |
565 &result); |
480 if (r != LDAP_SUCCESS) { |
566 if (r != LDAP_SUCCESS) { |
481 //ws_ldap_close(ld); |
567 if(result) { |
482 |
568 ldap_msgfree(result); |
483 fprintf(stderr, "ldap_search_ext_s failed\n"); |
569 } |
484 return NULL; |
570 log_ereport(LOG_FAILURE, "ldap_get_group: search failed: %s", ldap_err2string(r)); |
485 } |
571 return NULL; |
486 |
572 } |
|
573 |
|
574 LDAPMessage *msg = ldap_first_entry(ld, result); |
487 LDAPGroup *wsgroup = NULL; |
575 LDAPGroup *wsgroup = NULL; |
|
576 if(msg) { |
|
577 if(ldap_count_entries(ld, msg) > 1) { |
|
578 log_ereport(LOG_FAILURE, "ldap_get_user: more than one search result"); |
|
579 } else { |
|
580 wsgroup = ldap_msg_to_group(sn, rq, authdb, ld, msg, group); |
|
581 } |
|
582 } |
|
583 ldap_msgfree(result); |
|
584 |
|
585 /* |
488 LDAPMessage *msg = ldap_first_entry(ld, result); |
586 LDAPMessage *msg = ldap_first_entry(ld, result); |
489 if (msg) { |
587 if (msg) { |
490 // create group object |
588 // create group object |
491 wsgroup = malloc(sizeof(LDAPGroup)); |
589 wsgroup = malloc(sizeof(LDAPGroup)); |
492 wsgroup->name = strdup(group); |
590 wsgroup->name = strdup(group); |