summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2014-03-19 14:14:06 +0100
committerSimon Rettberg2014-03-19 14:14:06 +0100
commit87a5f72b2eef3beb10ad50bfbd2a131bd278e67b (patch)
tree4e75715308afcd6211f304ee198eea735416a5d9
parent(Forgot commit) Add fmt_ldapbindrequeststring that takes struct string as arg... (diff)
downloadldadp-87a5f72b2eef3beb10ad50bfbd2a131bd278e67b.tar.gz
ldadp-87a5f72b2eef3beb10ad50bfbd2a131bd278e67b.tar.xz
ldadp-87a5f72b2eef3beb10ad50bfbd2a131bd278e67b.zip
Work
-rw-r--r--ldadp.c3
-rw-r--r--proxy.c74
-rw-r--r--server.c21
-rw-r--r--server.h2
-rw-r--r--types.h2
5 files changed, 90 insertions, 12 deletions
diff --git a/ldadp.c b/ldadp.c
index 90647df..9c9a579 100644
--- a/ldadp.c
+++ b/ldadp.c
@@ -75,6 +75,9 @@ static int loadConfig_handler(void *stuff, const char *section, const char *key,
if (strcmp(key, "base") == 0) {
server_setBase(section, value);
}
+ if (strcmp(key, "home") == 0) {
+ server_setHomeTemplate(section, value);
+ }
return 1;
}
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));
diff --git a/server.c b/server.c
index 2c3aebe..13202f8 100644
--- a/server.c
+++ b/server.c
@@ -59,6 +59,27 @@ void server_setBase(const char *server, const char *base)
entry->base[entry->baseLen] = '\0';
}
+void server_setHomeTemplate(const char *server, const char *hometemplate)
+{
+ server_t *entry = server_create(server);
+ if (entry == NULL) return;
+ if (snprintf(entry->homeTemplate, MOUNTLEN, "%s", hometemplate) >= MOUNTLEN) printf("Warning: Home Template for %s is too long.\n", server);
+ // TODO: Better template system. Using a format string is too lazy
+ BOOL b = FALSE;
+ char *s = entry->homeTemplate;
+ int count = 0;
+ while (*s) {
+ if (b) {
+ if (*s != '%') count++;
+ b = FALSE;
+ } else if (*s == '%') b = TRUE;
+ if (count > 5) *s = '_';
+ if (*s == '\\') *s = '/';
+ s++;
+ }
+ if (count > 5) printf("WARNING: Too many '%%' in Home Template for %s. Don't forget to replace literal '%%' with '%%%%'\n", server);
+}
+
void server_initServers()
{
int i;
diff --git a/server.h b/server.h
index 5252048..4923d6e 100644
--- a/server.h
+++ b/server.h
@@ -12,6 +12,8 @@ void server_setPassword(const char *server, const char *password);
void server_setBase(const char *server, const char *base);
+void server_setHomeTemplate(const char *server, const char *hometemplate);
+
void server_initServers();
int server_send(epoll_server_t *server, const char *buffer, size_t len, const BOOL cork);
diff --git a/types.h b/types.h
index 6959197..692042a 100644
--- a/types.h
+++ b/types.h
@@ -10,6 +10,7 @@
#define PWLEN 40
#define BASELEN 250
#define SIDLEN 28
+#define MOUNTLEN 100
#define REQLEN 4000
#define MAXMSGLEN 100000
@@ -68,6 +69,7 @@ struct _server_t_ {
char password[PWLEN];
char base[BASELEN];
char sid[SIDLEN];
+ char homeTemplate[MOUNTLEN];
epoll_server_t con;
};