summaryrefslogtreecommitdiff
path: root/daemon/ldap.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/ldap.c')
-rw-r--r--daemon/ldap.c98
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;