From 87a5f72b2eef3beb10ad50bfbd2a131bd278e67b Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 19 Mar 2014 14:14:06 +0100 Subject: Work --- proxy.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 12 deletions(-) (limited to 'proxy.c') diff --git a/proxy.c b/proxy.c index c396cc7..b49946c 100644 --- a/proxy.c +++ b/proxy.c @@ -15,11 +15,14 @@ typedef struct { BOOL homeDirectory; + BOOL homeMount; BOOL gidNumber; BOOL gecos; BOOL loginShell; BOOL uid; BOOL uidNumber; + // Internal + BOOL hasUser; } attr_t; typedef struct @@ -42,7 +45,7 @@ static int _pendingCount = 0; static struct string s_shadowAccount, s_posixAccount, s_user, s_uid, s_sAMAccountName, s_objectSid; static struct string s_objectClass, s_objectclass, s_homeDirectory, s_gidNumber, s_gecos, s_cn, s_dn, s_posixGroup; static struct string s_loginShell, s_uidNumber, s_mail, s_objectCategory, s_memberOf, s_distinguishedName; -static struct string s_1001; +static struct string s_1001, s_homeMount; static struct string str_ADUSER; // @@ -73,6 +76,7 @@ void proxy_init() SETSTR(objectClass); SETSTR(objectclass); SETSTR(homeDirectory); + SETSTR(homeMount); SETSTR(gidNumber); SETSTR(gecos); SETSTR(loginShell); @@ -196,7 +200,7 @@ static BOOL request_isUserFilter(struct Filter *filter); static BOOL request_getGroupFilter(struct Filter *filter, struct string *wantedGroupName, uint32_t *wantedGroupId); static void request_replaceFilter(server_t *server, struct Filter *filter); static void request_replaceAdl(server_t *server, struct AttributeDescriptionList **adl, attr_t *attr); -static void request_replaceAttribute(server_t *server, struct string *attribute, struct string *value); +static void request_replaceAttribute(server_t *server, struct string *attribute, struct string *value, attr_t *attr); static BOOL request_isUserFilter(struct Filter *filter) { @@ -229,6 +233,11 @@ static BOOL request_isUserFilter(struct Filter *filter) * This is REALLY cheap. It doesn't really look at the logic operators in the filter as we assume that pam_ldap * or nss_ldap etc. won't do anything fancy like "!(objectClass=groupAccount)", just simple AND and OR combined * with EQUAL. + * You could actually get real group memberships using the memberOf attributes of the user, and do additional + * queries for these groups, but for that to make any sense you'd also have to implement useful permission + * handling.... So as all we really want is authentication and optionally mounting a home directory, we pretend + * there is just one group with id 1001 and name ad_user. + * This function will try to figure out if the given filter is a lookup for a group name or group id. */ static BOOL request_getGroupFilter(struct Filter *filter, struct string *wantedGroupName, uint32_t *wantedGroupId) { @@ -267,13 +276,13 @@ static void request_replaceFilter(server_t *server, struct Filter *filter) break; case PRESENT: case SUBSTRING: - request_replaceAttribute(server, &filter->ava.desc, NULL); + request_replaceAttribute(server, &filter->ava.desc, NULL, NULL); break; case EQUAL: case GREATEQUAL: case LESSEQUAL: case APPROX: - request_replaceAttribute(server, &filter->ava.desc, &filter->ava.value); + request_replaceAttribute(server, &filter->ava.desc, &filter->ava.value, NULL); break; default: break; } @@ -290,17 +299,29 @@ static void request_replaceAdl(server_t *server, struct AttributeDescriptionList elifSETATTR(gidNumber); elifSETATTR(gecos); elifSETATTR(loginShell); - else request_replaceAttribute(server, &(*adl)->a, NULL); + else request_replaceAttribute(server, &(*adl)->a, NULL, attr); if (*adl == NULL) break; if (next == NULL) adl = &(*adl)->next; // If next is not NULL, we removed an entry, so we don't need to shift } + if (!attr->hasUser) { + if (attr->homeDirectory || attr->gecos || attr->homeMount) { + struct AttributeDescriptionList *user = calloc(1, sizeof(struct AttributeDescriptionList)); + user->a = s_sAMAccountName; + user->next = *adl; + *adl = user; + } + } } #undef elifSETATTR -static void request_replaceAttribute(server_t *server, struct string *attribute, struct string *value) +static void request_replaceAttribute(server_t *server, struct string *attribute, struct string *value, attr_t *attr) { if (equals(attribute, &s_uid)) { *attribute = s_sAMAccountName; + if (attr) attr->hasUser = TRUE; + } else if (equals(attribute, &s_homeMount)) { + *attribute = s_homeDirectory; + if (attr != NULL) attr->homeMount = TRUE; } else if (iequals(attribute, &s_objectclass)) { if (value == NULL) return; if (equals(value, &s_shadowAccount)) *value = s_user; @@ -321,6 +342,7 @@ static void request_replaceAttribute(server_t *server, struct string *attribute, static void response_replacePal(server_t *server, struct PartialAttributeList **pal, attr_t *attr); static void response_replaceAdl(server_t *server, struct string *type, struct AttributeDescriptionList **adl, attr_t *attr); static void response_replaceAttribute(server_t *server, struct string *attribute, struct string *value); +static struct PartialAttributeList* response_filterHomeDir(struct PartialAttributeList *pal); static struct PartialAttributeList* response_addPal(struct PartialAttributeList *pal, struct string *attribute, const char *format, ...); #define ADDATTR(x,...) do { if (attr->x) last = response_addPal(last, &s_ ## x, __VA_ARGS__); } while (0) @@ -333,13 +355,19 @@ static void response_replacePal(server_t *server, struct PartialAttributeList ** while (*pal != NULL) { last = *pal; struct PartialAttributeList *next = NULL; - if (0) { } - elifDELATTR(homeDirectory); + if (0) { } // Remove fields we don't want from AD elifDELATTR(gidNumber); elifDELATTR(gecos); elifDELATTR(loginShell); elifDELATTR(uidNumber); elifDELATTR(mail); + else if (equals(&(*pal)->type, &s_homeDirectory)) { + // homeDirectory is set in AD - it can either be a local path (in which case it's useless) + // or a UNC path, which we can easily mount via mount.cifs + next = response_filterHomeDir(*pal); + if (next == NULL) attr->homeMount = FALSE; + } + // Entry should be removed, free structs if (next != NULL) { free_ldapadl((*pal)->values); free(*pal); @@ -362,12 +390,18 @@ static void response_replacePal(server_t *server, struct PartialAttributeList ** pal = &(*pal)->next; } if (username != NULL) { - ADDATTR(homeDirectory, "/home/%.*s", (int)username->l, username->s); - ADDATTR(gecos, "%.*s,,,", (int)username->l, username->s); - ADDATTR(loginShell, "/bin/bash"); - ADDATTR(gidNumber, "1001"); + char *user = tmpbuffer_get(); + snprintf(user, TMPLEN, "%.*s", (int)username->l, username->s); + ADDATTR(homeDirectory, "/home/%s", user); + ADDATTR(gecos, "%.*s,,,", user); + if (attr->homeMount && server->homeTemplate[0] != '\0') { + ADDATTR(homeMount, server->homeTemplate, user, user, user, user, user, user); + } } if (lastObjectClass != NULL) { + ADDATTR(loginShell, "/bin/bash"); + ADDATTR(gidNumber, "1001"); + // TODO: Nicer lastObjectClass->next = calloc(1, sizeof(struct AttributeDescriptionList)); lastObjectClass->next->a = s_posixAccount; lastObjectClass = lastObjectClass->next; @@ -412,6 +446,22 @@ static void response_replaceAttribute(server_t *server, struct string *attribute } } +static struct PartialAttributeList* response_filterHomeDir(struct PartialAttributeList *pal) +{ + for (struct AttributeDescriptionList *adl = pal->values; adl != NULL; adl = pal->values /* sic */) { + if (adl->a.l > 2 && adl->a.s[0] == '\\' && adl->a.s[1] == '\\') { + for (size_t i = 0; i < adl->a.l; ++i) if (adl->a.s[i] == '\\') *((char*)adl->a.s + i) = '/'; + free_ldapadl(adl->next); + adl->next = NULL; + pal->type = s_homeMount; + return NULL; + } + pal->values = adl->next; + free(adl); + } + return pal->next; +} + static struct PartialAttributeList* response_addPal(struct PartialAttributeList *pal, struct string *attribute, const char *format, ...) { struct PartialAttributeList *next = malloc(sizeof(struct PartialAttributeList)); -- cgit v1.2.3-55-g7522