src/server/daemon/ldap_auth.c

changeset 467
4d038bc6f86e
parent 415
d938228c382e
child 468
73e80eb953f5
--- a/src/server/daemon/ldap_auth.c	Sun Mar 12 11:42:17 2023 +0100
+++ b/src/server/daemon/ldap_auth.c	Sun Mar 12 20:02:04 2023 +0100
@@ -39,86 +39,138 @@
 #include <cx/hash_map.h>
 
 #include "ldap_auth.h"
+#include "ldap_resource.h"
 
-static void ws_ldap_close(LDAP *ldap) {
-#ifdef SOLARIS
-    ldap_unbind(ldap);
-#else
-    ldap_unbind_ext_s(ldap, NULL, NULL);
-#endif
-}
+
+static LDAPConfig ws_ldap_default_config = {
+    NULL, // resource
+    NULL, // basedn
+    NULL, // binddn
+    NULL, // bindpw
+    "(&(objectclass=inetorgperson)(!(cn=%s)(uid=%s)))", // userSearchFilter
+    {"uid"}, // uidAttributes
+    1, // numUidAttributes
+    "(&(|(objectclass=groupOfNames)(objectclass=groupOfUniqueNames))(cn=%s))", // groupSearchFilter
+    {"member", "uniqueMember"}, // memberAttributes
+    2, // numMemberAttributes
+    WS_LDAP_GROUP_MEMBER_DN, // groupMemberType
+    TRUE, // enableGroups
+    FALSE // userNameIsDN
+};
 
-AuthDB* create_ldap_authdb(ServerConfiguration *cfg, const char *name, LDAPConfig *conf) {
+// TODO
+static LDAPConfig ws_ldap_ad_config = {
+    NULL, // resource
+    NULL, // basedn
+    NULL, // binddn
+    NULL, // bindpw
+    "(&(objectclass=inetorgperson)(!(cn=%s)(uid=%s)))", // userSearchFilter
+    {"uid"}, // uidAttributes
+    1, // numUidAttributes
+    "", // groupSearchFilter
+    {"uniqueMember", "member"}, // memberAttributes
+    2, // numMemberAttributes
+    WS_LDAP_GROUP_MEMBER_DN, // groupMemberType
+    TRUE, // enableGroups
+    FALSE // userNameIsDN
+};
+
+static LDAPConfig ws_ldap_posix_config = {
+    NULL, // resource
+    NULL, // basedn
+    NULL, // binddn
+    NULL, // bindpw
+    "(&(objectclass=posixAccount)(uid=%s))", // userSearchFilter
+    {"uid"}, // uidAttributes
+    1, // numUidAttributes
+    "(&(objectclass=posixGroup)(cn=%s))", // groupSearchFilter
+    {"memberUid"}, // memberAttributes
+    1, // numMemberAttributes
+    WS_LDAP_GROUP_MEMBER_UID, // groupMemberType
+    TRUE, // enableGroups
+    FALSE // userNameIsDN
+};
+
+AuthDB* create_ldap_authdb(ServerConfiguration *cfg, const char *name, ConfigNode *node) {
     LDAPAuthDB *authdb = cxMalloc(cfg->a, sizeof(LDAPAuthDB));
+    if(!authdb) {
+        return NULL;
+    }
     authdb->authdb.name = pool_strdup(cfg->pool, name);
+    if(!authdb->authdb.name) {
+        return NULL;
+    }
     authdb->authdb.get_user = ldap_get_user;
     authdb->authdb.use_cache = 1;
-    authdb->config = *conf;
-
-    if (!authdb->config.usersearch) {
-        authdb->config.usersearch = "uid";
+    
+    // initialize default ldap config
+    cxstring dirtype = serverconfig_object_directive_value(node, cx_str("DirectoryType"));
+    LDAPConfig *default_config;
+    if(!dirtype.ptr) {
+        default_config = &ws_ldap_default_config;
+    } else if(!cx_strcmp(dirtype, cx_str("ldap"))) {
+        default_config = &ws_ldap_default_config;
+    } else if(!cx_strcmp(dirtype, cx_str("posix"))) {
+        default_config = &ws_ldap_posix_config;
+    } else if(!cx_strcmp(dirtype, cx_str("ad"))) {
+        default_config = &ws_ldap_ad_config;
+    } else {
+        log_ereport(LOG_FAILURE, "cannot create ldap authdb %s: unknown directory type %s", name, dirtype.ptr);
     }
-    if (!authdb->config.groupsearch) {
-        authdb->config.groupsearch = "uniquemember";
+    memcpy(&authdb->config, default_config, sizeof(LDAPConfig));
+    
+    // custom config
+    cxstring resource = serverconfig_object_directive_value(node, cx_str("Resource"));
+    cxstring basedn = serverconfig_object_directive_value(node, cx_str("Basedn"));
+    cxstring binddn = serverconfig_object_directive_value(node, cx_str("Binddn"));
+    cxstring bindpw = serverconfig_object_directive_value(node, cx_str("Bindpw"));
+    cxstring usersearchfilter = serverconfig_object_directive_value(node, cx_str("UserSearchFilter"));
+    // TODO ...
+    
+    if(!resource.ptr) {
+        // TODO: create resource pool
+    } else {
+        authdb->config.resource = resource.ptr;
     }
     
     // initialize group cache
     authdb->groups.first = NULL;
     authdb->groups.last = NULL;
     authdb->groups.map = cxHashMapCreate(cfg->a, 32);
+    if(!authdb->groups.map) {
+        return NULL;
+    }
 
     return (AuthDB*) authdb;
 }
 
-LDAP* get_ldap_session(LDAPAuthDB *authdb) {
-    LDAPConfig *config = &authdb->config;
-    LDAP *ld = NULL;
-    
-#ifdef SOLARIS
-    ld = ldap_init(config->hostname, config->port);
-#else
-    char *ldap_uri = NULL;
-    asprintf(&ldap_uri, "ldap://%s:%d", config->hostname, config->port);
-    int init_ret = ldap_initialize(&ld, ldap_uri);
-    free(ldap_uri);
-    if(init_ret) {
-        fprintf(stderr, "ldap_initialize failed\n");
-    }
-#endif
-    if(!ld) {
+LDAP* get_ldap_session(Session *sn, Request *rq, LDAPAuthDB *authdb) {
+    ResourceData *res = resourcepool_lookup(sn, rq, authdb->config.resource, 0);
+    if(!res) {
+        log_ereport(LOG_FAILURE, "AuthDB %s: cannot get resource %s", authdb->authdb.name, authdb->config.resource);
         return NULL;
     }
     
-    int ldapv = LDAP_VERSION3;
-    ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapv);
+    LDAP *ldap = res->data;
     
-    // admin bind
-    struct berval cred;
-    cred.bv_val = config->bindpw;
-    cred.bv_len = strlen(config->bindpw);
-    struct berval *server_cred;
-    int r = ldap_sasl_bind_s(
-            ld,
-            config->binddn,
-            LDAP_SASL_SIMPLE,
-            &cred,
-            NULL,
-            NULL,
-            &server_cred);
-    if (r != LDAP_SUCCESS) {
-        ws_ldap_close(ld);
-        fprintf(stderr, "ldap_simple_bind_s failed: %s\n", ldap_err2string(r));
-        return NULL;
+    if(authdb->config.binddn) {
+        struct berval *server_cred;
+        int r = ws_ldap_bind(ldap, authdb->config.binddn, authdb->config.bindpw, &server_cred);
+        if(r != LDAP_SUCCESS) {
+            log_ereport(LOG_FAILURE, "AuthDB %s: bind to %s failed: %s", authdb->config.binddn, ldap_err2string(r));
+            resourcepool_free(sn, rq, res);
+            return NULL;
+        }
     }
     
-    return ld;
+    return ldap;
 }
 
-User* ldap_get_user(AuthDB *db, const char *username) {
+User* ldap_get_user(AuthDB *db, Session *sn, Request *rq, const char *username) {
     LDAPAuthDB *authdb = (LDAPAuthDB*) db;
     LDAPConfig *config = &authdb->config;
 
-    LDAP *ld = get_ldap_session(authdb);
+    LDAP *ld = get_ldap_session(sn, rq, authdb);
     if (ld == NULL) {
         fprintf(stderr, "ldap_init failed\n");
         return NULL;
@@ -156,13 +208,15 @@
 
     LDAPMessage *msg = ldap_first_entry(ld, result);
     if (msg) {
-        LDAPUser *user = malloc(sizeof(LDAPUser));
+        LDAPUser *user = pool_malloc(sn->pool, sizeof(LDAPUser));
         if (user != NULL) {
             user->authdb = authdb;
             user->user.verify_password = ldap_user_verify_password;
             user->user.check_group = ldap_user_check_group;
             user->user.free = ldap_user_free;
-            user->user.name = (char*)username; // must not be freed TODO: maybe copy
+            user->user.name = pool_strdup(sn->pool, username);
+            user->sn = sn;
+            user->rq = rq;
             
             // TODO: get uid/gid from ldap
             user->user.uid = -1;
@@ -181,12 +235,12 @@
     return NULL;
 }
 
-LDAPGroup* ldap_get_group(LDAPAuthDB *authdb, const char *group) {
+LDAPGroup* ldap_get_group(Session *sn, Request *rq, LDAPAuthDB *authdb, const char *group) {
     printf("ldap_get_group: %s\n", group);
     
     LDAPConfig *config = &authdb->config;
     
-    LDAP *ld = get_ldap_session(authdb);
+    LDAP *ld = get_ldap_session(sn, rq, authdb);
     if (ld == NULL) {
         fprintf(stderr, "ldap_init failed\n");
         return NULL;
@@ -302,7 +356,7 @@
     
     int ret = 0;
     
-    LDAPGroup *group = ldap_get_group(user->authdb, group_str);
+    LDAPGroup *group = ldap_get_group(user->sn, user->rq, user->authdb, group_str);
     for(int i=0;i<group->nmembers;i++) {
         char *member = group->members[i].name;
         if(!strcmp(member, u->name)) {

mercurial