diff options
Diffstat (limited to 'daemon/ldap.c')
-rw-r--r-- | daemon/ldap.c | 98 |
1 files changed, 86 insertions, 12 deletions
diff --git a/daemon/ldap.c b/daemon/ldap.c index a1aa1a1..f4324be 100644 --- a/daemon/ldap.c +++ b/daemon/ldap.c @@ -24,10 +24,16 @@ #include "md5.h" #include "sha1.h" #include "bd.h" +#include "stringx.h" #include <sys/time.h> +#include <ctype.h> + +#define __USE_XOPEN +#include <unistd.h> /* LDAP library */ +#define LDAP_DEPRECATED 1 #include <ldap.h> /* ------------------------------------------------------------------------------- @@ -73,6 +79,7 @@ typedef struct ldap_context const char* base; /* Base for the filter */ const char* pw_attr; /* The clear password attribute */ const char* ha1_attr; /* Password for an encrypted Digest H(A1) */ + const char* group_attr; /* The group attribute */ const char* user; /* User to bind as */ const char* password; /* Password to bind with */ const char* dnmap; /* For mapping users to dns */ @@ -90,8 +97,8 @@ typedef struct ldap_context ldap_context_t; /* Forward declarations for callbacks */ -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg); -static int validate_basic(ha_request_t* rq, const char* user, const char* password); +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups); +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups); static void escape_ldap(const ha_request_t* rq, ha_buffer_t* buf, const char* value); /* The defaults for the context */ @@ -104,6 +111,7 @@ static const ldap_context_t ldap_defaults = NULL, /* base */ "userPassword", /* pw_attr */ NULL, /* ha1_attr */ + NULL, /* group_attr */ NULL, /* user */ NULL, /* password */ NULL, /* dnmap */ @@ -563,10 +571,10 @@ static int retrieve_user_entry(const ha_request_t* rq, ldap_context_t* ctx, LDAP { struct timeval tv; const char* filter; - const char* attrs[3]; + const char* attrs[4]; const char* base; int scope; - int r; + int r, i; ASSERT(ctx && rq && ld && user && dn && entry && result); @@ -582,9 +590,14 @@ static int retrieve_user_entry(const ha_request_t* rq, ldap_context_t* ctx, LDAP filter = "(objectClass=*)"; } - attrs[0] = ctx->dobind ? NULL : ctx->pw_attr; - attrs[1] = ctx->dobind ? NULL : ctx->ha1_attr; - attrs[2] = NULL; + i = 0; + if (ctx->group_attr) + attrs[i++] = ctx->group_attr; + if (ctx->dobind && ctx->pw_attr) + attrs[i++] = ctx->pw_attr; + if (ctx->dobind && ctx->ha1_attr) + attrs[i++] = ctx->ha1_attr; + attrs[i] = NULL; tv.tv_sec = ctx->ldap_timeout; tv.tv_usec = 0; @@ -633,7 +646,43 @@ static int retrieve_user_entry(const ha_request_t* rq, ldap_context_t* ctx, LDAP return HA_FALSE; } -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg) +static int +get_user_groups (ldap_context_t *ctx, LDAP *ld, LDAPMessage *entry, char*** result) +{ + struct berval **vals, **v; + char **groups = NULL; + int ret = HA_OK; + + if (!ctx->group_attr) { + *result = NULL; + return HA_OK; + } + + groups = str_array_create (NULL); + vals = ldap_get_values_len (ld, entry, ctx->group_attr); + for (v = vals; v && *v; ++v) { + if ((*v)->bv_len) { + groups = str_array_appendn (groups, (*v)->bv_val, (*v)->bv_len); + if (!groups) { + ha_memerr (NULL); + ret = HA_CRITERROR; + break; + } + } + } + + if (vals) + ldap_value_free_len (vals); + if (ret != HA_OK) + str_array_free (groups); + else + *result = groups; + return ret; +} + +static int +validate_digest (ha_request_t *rq, const char *user, + digest_context_t *dg, char ***groups) { ldap_context_t* ctx = (ldap_context_t*)rq->context->ctx_data; LDAP* ld = NULL; /* freed in finally */ @@ -684,7 +733,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* for(h = ha1s; *h; ++h) { - r = parse_ldap_ha1(rq, *h, dg->ha1); + r = parse_ldap_ha1(rq, *h, dg->server_ha1); if(r == HA_FALSE) { @@ -722,7 +771,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* { foundany = 1; - digest_makeha1(dg->ha1, user, rq->context->realm, password); + digest_makeha1(dg->server_ha1, user, rq->context->realm, password); /* Run the actual check */ ret = digest_complete_check(dg, rq->context, rq->buf); @@ -739,6 +788,13 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* finally: + /* Fill in the user's groups */ + if (ret == HA_OK) { + r = get_user_groups (ctx, ld, entry, groups); + if (r < 0) + ret = r; + } + if(ha1s) ldap_value_free_len(ha1s); @@ -754,7 +810,9 @@ finally: return ret; } -static int validate_basic(ha_request_t* rq, const char* user, const char* password) +static int +validate_basic (ha_request_t *rq, const char *user, + const char *password, char ***groups) { ldap_context_t* ctx = (ldap_context_t*)rq->context->ctx_data; LDAP* ld = NULL; @@ -845,7 +903,11 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo /* Discard the connection since it's useless to us */ discard_ldap_connection(rq, ctx, ld); ld = NULL; - } + ret = HA_FALSE; + + } else { + ret = HA_OK; + } } @@ -870,6 +932,12 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo } finally: + /* Fill in the user's groups */ + if (ret == HA_OK) { + r = get_user_groups (ctx, ld, entry, groups); + if (r < 0) + ret = r; + } if(results) ldap_msgfree(results); @@ -909,6 +977,12 @@ int ldap_config(ha_context_t* context, const char* name, const char* value) return HA_OK; } + else if(strcmp(name, "ldapgroupattr") == 0) + { + ctx->group_attr = value; + return HA_OK; + } + else if(strcmp(name, "ldappwattr") == 0) { ctx->pw_attr = value; |