diff -r 019c22775f7c -r 4d038bc6f86e src/server/daemon/ldap_auth.c --- 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 #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;inmembers;i++) { char *member = group->members[i].name; if(!strcmp(member, u->name)) {