added ldap group support

Sun, 17 Aug 2014 15:15:32 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 17 Aug 2014 15:15:32 +0200
changeset 97
09fbefc0e6a9
parent 96
0185b13bf41f
child 98
59656cd16411

added ldap group support

make/gcc.mk file | annotate | diff | comparison | revisions
src/server/config/acl.c file | annotate | diff | comparison | revisions
src/server/config/keyfile.c file | annotate | diff | comparison | revisions
src/server/config/mimeconf.c file | annotate | diff | comparison | revisions
src/server/daemon/keyfile_auth.c file | annotate | diff | comparison | revisions
src/server/daemon/ldap_auth.c file | annotate | diff | comparison | revisions
src/server/daemon/ldap_auth.h file | annotate | diff | comparison | revisions
src/server/daemon/vfs.c file | annotate | diff | comparison | revisions
src/server/safs/nametrans.c file | annotate | diff | comparison | revisions
--- a/make/gcc.mk	Mon Nov 04 10:55:27 2013 +0100
+++ b/make/gcc.mk	Sun Aug 17 15:15:32 2014 +0200
@@ -31,7 +31,7 @@
 
 CC  = gcc
 CXX = g++
-LD = gcc
+LD = g++
 
 SHLIB_CFLAGS = -fPIC
 SHLIB_LDFLAGS = -shared
--- a/src/server/config/acl.c	Mon Nov 04 10:55:27 2013 +0100
+++ b/src/server/config/acl.c	Sun Aug 17 15:15:32 2014 +0200
@@ -64,7 +64,7 @@
     ACLFile *aclf = p;
     UcxAllocator *mp = aclf->parser.mp;
     
-    if(sstrsuffix(line, sstr("ACL "))) {
+    if(sstrprefix(line, sstr("ACL "))) {
         sstr_t param = sstrsubs(line, 4);
         UcxList *plist = cfg_param_list(param, mp); 
         ACLConfig *acl = OBJ_NEW(mp, ACLConfig);
@@ -92,7 +92,7 @@
         if(type.ptr) {
             acl->type = type;
         }
-    } else if(sstrsuffix(line, sstr("Authenticate "))) {
+    } else if(sstrprefix(line, sstr("Authenticate "))) {
         sstr_t param = sstrsubs(line, 13);
         UcxList *plist = cfg_param_list(param, mp); 
         aclf->cur->authparam = plist;
--- a/src/server/config/keyfile.c	Mon Nov 04 10:55:27 2013 +0100
+++ b/src/server/config/keyfile.c	Sun Aug 17 15:15:32 2014 +0200
@@ -44,6 +44,8 @@
 
     int r = cfg_parse_basic_file((ConfigParser*)conf, in);
     if(r != 0) {
+        fclose(in);
+        free(conf);
         // TODO: free
         return NULL;
     }
--- a/src/server/config/mimeconf.c	Mon Nov 04 10:55:27 2013 +0100
+++ b/src/server/config/mimeconf.c	Sun Aug 17 15:15:32 2014 +0200
@@ -51,6 +51,8 @@
     conf->ntypes = 0;
     int r = cfg_parse_basic_file((ConfigParser*)conf, in);
     if(r != 0) {
+        fclose(in);
+        free(conf);
         // TODO: free
         return NULL;
     }
--- a/src/server/daemon/keyfile_auth.c	Mon Nov 04 10:55:27 2013 +0100
+++ b/src/server/daemon/keyfile_auth.c	Sun Aug 17 15:15:32 2014 +0200
@@ -97,8 +97,8 @@
     
     user->groups = calloc(ngroups, sizeof(sstr_t));
     for(int i=0;i<ngroups;i++) {
-        //user->groups[i] = sstrdup(groups[i]);
-        sstrdup(groups[i]);
+        user->groups[i] = sstrdup(groups[i]);
+        //sstrdup(groups[i]); // wtf?
     }
     
     // add to keyfile
@@ -139,9 +139,11 @@
 int ssha_verify(KeyfileUser *user, char *password) {
     /*
      * SSHA: SHA1(pw + salt) + 8 bytes salt
-     * the SSHA hash is already base64 decoded
+     * user->hash is already base64 decoded
      */
     
+    // TODO: variable length salt
+    
     char *salt = user->hash + user->hashlen - 8; // last 8 bytes are the salt 
     size_t pwlen = strlen(password);
     
--- a/src/server/daemon/ldap_auth.c	Mon Nov 04 10:55:27 2013 +0100
+++ b/src/server/daemon/ldap_auth.c	Sun Aug 17 15:15:32 2014 +0200
@@ -34,6 +34,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <ucx/utils.h>
+
 #include "ldap_auth.h"
 
 static void ws_ldap_close(LDAP *ldap) {
@@ -57,14 +59,17 @@
     if (!authdb->config.groupsearch) {
         authdb->config.groupsearch = "uniquemember";
     }
+    
+    // initialize group cache
+    authdb->groups.first = NULL;
+    authdb->groups.last = NULL;
+    authdb->groups.map = ucx_map_new(32);
 
     return (AuthDB*) authdb;
 }
 
-User* ldap_get_user(AuthDB *db, char *username) {
-    LDAPAuthDB *authdb = (LDAPAuthDB*) db;
+LDAP* get_ldap_session(LDAPAuthDB *authdb) {
     LDAPConfig *config = &authdb->config;
-
     LDAP *ld = NULL;
 #ifdef LINUX
     char *ldap_uri = NULL;
@@ -74,19 +79,17 @@
     if(init_ret) {
         fprintf(stderr, "ldap_initialize failed\n");
     }
-    
 #else
     ld = ldap_init(config->hostname, config->port);
 #endif
-    if (ld == NULL) {
-        fprintf(stderr, "ldap_init failed\n");
+    if(!ld) {
         return NULL;
     }
     
     int ldapv = LDAP_VERSION3;
     ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapv);
-
-    //int r = ldap_simple_bind_s(ld, config->binddn, config->bindpw);
+    
+    // admin bind
     struct berval cred;
     cred.bv_val = config->bindpw;
     cred.bv_len = strlen(config->bindpw);
@@ -101,14 +104,26 @@
             &server_cred);
     if (r != LDAP_SUCCESS) {
         ws_ldap_close(ld);
-        
         fprintf(stderr, "ldap_simple_bind_s failed: %s\n", ldap_err2string(r));
         return NULL;
     }
+    
+    return ld;
+}
+
+User* ldap_get_user(AuthDB *db, char *username) {
+    LDAPAuthDB *authdb = (LDAPAuthDB*) db;
+    LDAPConfig *config = &authdb->config;
+
+    LDAP *ld = get_ldap_session(authdb);
+    if (ld == NULL) {
+        fprintf(stderr, "ldap_init failed\n");
+        return NULL;
+    }
 
     // get the user dn
-
     // TODO: use config for filter
+    // TODO: use asprintf
     char filter[128];
     int s = snprintf(filter, 127, "uid=%s", username);
     filter[s] = 0;
@@ -117,7 +132,7 @@
     struct timeval timeout;
     timeout.tv_sec = 8;
     timeout.tv_usec = 0;
-    r = ldap_search_ext_s(
+    int r = ldap_search_ext_s(
             ld,
             config->basedn,
             LDAP_SCOPE_SUBTREE,
@@ -140,6 +155,7 @@
     if (msg) {
         LDAPUser *user = malloc(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;
@@ -162,6 +178,97 @@
     return NULL;
 }
 
+LDAPGroup* ldap_get_group(LDAPAuthDB *authdb, char *group) {
+    printf("ldap_get_group: %s\n", group);
+    
+    LDAPConfig *config = &authdb->config;
+    
+    LDAP *ld = get_ldap_session(authdb);
+    if (ld == NULL) {
+        fprintf(stderr, "ldap_init failed\n");
+        return NULL;
+    }
+    
+    // get the user dn
+    // TODO: use config for filter
+    // TODO: use asprintf
+    char filter[128];
+    int s = snprintf(filter, 127, "cn=%s", group);
+    filter[s] = 0;
+
+    LDAPMessage *result;
+    struct timeval timeout;
+    timeout.tv_sec = 8;
+    timeout.tv_usec = 0;
+    int r = ldap_search_ext_s(
+            ld,
+            config->basedn,
+            LDAP_SCOPE_SUBTREE,
+            filter,
+            NULL,
+            0,
+            NULL,        // server controls
+            NULL,        // client controls
+            &timeout,
+            1,           // size limit
+            &result);
+    if (r != LDAP_SUCCESS) {
+        ws_ldap_close(ld);
+        
+        fprintf(stderr, "ldap_search_ext_s failed\n");
+        return NULL;
+    }
+    
+    LDAPGroup *wsgroup = NULL;
+    LDAPMessage *msg = ldap_first_entry(ld, result);
+    if (msg) {
+        // create group object
+        wsgroup = malloc(sizeof(LDAPGroup));
+        wsgroup->name = strdup(group);
+        wsgroup->members = NULL;
+        wsgroup->nmembers = 0;
+        wsgroup->update = 0;
+        wsgroup->next = NULL;
+        
+        // get attributes
+        BerElement *ber = NULL;
+        char *attribute = attribute=ldap_first_attribute(ld, msg, &ber);
+        while(attribute != NULL) {
+            printf("attribute: %s\n", attribute);
+            if(!strcasecmp(attribute, "memberuid")) {
+                // get all memberuid values and add the users to the group obj
+                
+                struct berval **values = ldap_get_values_len(ld, msg, attribute);
+                if(values) {
+                    int count = ldap_count_values_len(values);
+                    wsgroup->members = calloc(count, sizeof(LDAPMember));
+                    wsgroup->nmembers = count;
+                    for(int i=0;i<count;i++) {
+                        sstr_t member = sstrn(
+                                values[i]->bv_val,
+                                values[i]->bv_len);
+                        wsgroup->members[i].name = sstrdup(member).ptr;
+                        // TODO: uid?
+                        printf("added member: %.*s\n", member.length, member.ptr);
+                    }
+                }
+            }
+            
+            attribute = ldap_next_attribute(ld, msg, ber); 
+        }
+        
+        if(ber) {
+            //ldap_ber_free(ber, 0);
+        }
+        if(attribute) {
+            ldap_memfree(attribute);
+        }
+    }
+    
+    ws_ldap_close(ld);
+    return wsgroup;
+}
+
 int ldap_user_verify_password(User *u, char *password) {
     LDAPUser *user = (LDAPUser*)u;
     
@@ -187,9 +294,23 @@
     }
 }
 
-int ldap_user_check_group(User *user, char *group) {
-    // TODO
-    return 0;
+int ldap_user_check_group(User *u, char *group_str) {
+    LDAPUser *user = (LDAPUser*)u;
+    
+    int ret = 0;
+    
+    LDAPGroup *group = ldap_get_group(user->authdb, group_str);
+    for(int i=0;i<group->nmembers;i++) {
+        char *member = group->members[i].name;
+        if(!strcmp(member, u->name)) {
+            printf("is member\n");
+            ret = 1;
+        }
+    }
+    
+    // TODO: free or cache group
+    
+    return ret;
 }
 
 void ldap_user_free(User *u) {
--- a/src/server/daemon/ldap_auth.h	Mon Nov 04 10:55:27 2013 +0100
+++ b/src/server/daemon/ldap_auth.h	Sun Aug 17 15:15:32 2014 +0200
@@ -30,16 +30,21 @@
 #define	LDAP_AUTH_H
 
 #include "../public/auth.h"
+#include <sys/types.h>
 #include <ldap.h>
+#include <ucx/map.h>
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
-typedef struct ldap_auth_db LDAPAuthDB; 
-typedef struct ldap_config  LDAPConfig;
-typedef struct ldap_user    LDAPUser;
-   
+typedef struct ldap_auth_db     LDAPAuthDB; 
+typedef struct ldap_config      LDAPConfig;
+typedef struct ldap_user        LDAPUser;
+typedef struct ldap_group       LDAPGroup;
+typedef struct ldap_member      LDAPMember;
+typedef struct ldap_group_cache LDAPGroupCache;
+
 struct ldap_config {
     char   *hostname;
     int    port;
@@ -51,9 +56,16 @@
     char   *groupsearch;
 };
 
+struct ldap_group_cache {
+    LDAPGroup *first;
+    LDAPGroup *last;
+    UcxMap    *map;
+};
+
 struct ldap_auth_db {
-    AuthDB     authdb;
-    LDAPConfig config;
+    AuthDB         authdb;
+    LDAPConfig     config;
+    LDAPGroupCache groups;
 };
 
 struct ldap_user {
@@ -61,12 +73,31 @@
     LDAPAuthDB   *authdb;
     LDAP         *ldap;
     char         *userdn;
+    int          uid;
+    int          gid;
+};
+
+struct ldap_member {
+    char *name;
+    int  uid;
+};
+
+struct ldap_group {
+    char        *name;
+    LDAPMember  *members;
+    size_t      nmembers;
+    time_t      update;
+    LDAPGroup   *next;
 };
 
 AuthDB* create_ldap_authdb(char *name, LDAPConfig *conf);
 
+LDAP* get_ldap_session(LDAPAuthDB *authdb);
+
 User* ldap_get_user(AuthDB *sb, char *username);
 
+LDAPGroup* ldap_get_group(LDAPAuthDB *authdb, char *group);
+
 int ldap_user_verify_password(User *user, char *password);
 int ldap_user_check_group(User *user, char *group);
 void ldap_user_free(User *user);
--- a/src/server/daemon/vfs.c	Mon Nov 04 10:55:27 2013 +0100
+++ b/src/server/daemon/vfs.c	Sun Aug 17 15:15:32 2014 +0200
@@ -305,9 +305,7 @@
     // open directory
 #ifdef BSD
     DIR *sys_dir = opendir(path);
-    if(sys_dir) {
-        int dir_fd = dirfd(sys_dir);
-    }
+    int dir_fd = sys_dir ? dirfd(sys_dir) : 0;
 #else
     int dir_fd = open(path, O_RDONLY);
     if(dir_fd == -1) {
--- a/src/server/safs/nametrans.c	Mon Nov 04 10:55:27 2013 +0100
+++ b/src/server/safs/nametrans.c	Sun Aug 17 15:15:32 2014 +0200
@@ -83,7 +83,7 @@
 int document_root(pblock *pb, Session *sn, Request *rq) {
     char *root = pblock_findkeyval(pb_key_root, pb);
     if(!root) {
-        log_ereport(LOG_MISCONFIG, "document-root: missing rootparameter");
+        log_ereport(LOG_MISCONFIG, "document-root: missing root parameter");
         protocol_status(sn, rq, 500, NULL);
         return REQ_ABORTED;
     }

mercurial