From f0b46f7a343a79d1eeb29c0d45942df646e9cc35 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 18 Mar 2014 19:32:40 +0100 Subject: First working version with user and group support, login relaying --- server.c | 111 +++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 31 deletions(-) (limited to 'server.c') diff --git a/server.c b/server.c index 91f5703..2c3aebe 100644 --- a/server.c +++ b/server.c @@ -11,35 +11,19 @@ #include #include -#define ADDRLEN 40 -#define BINDLEN 200 -#define PWLEN 40 -#define BASELEN 100 -#define ALIASLEN 40 - #define AD_PORT 3268 #define MSGID_BIND 1 -typedef struct { - size_t baseLen; - char ip[4]; - time_t lastLookup; - char addr[ADDRLEN]; - char bind[BINDLEN]; - char password[PWLEN]; - char base[BASELEN]; - epoll_server_t con; -} server_t; - #define MAX_SERVERS 10 static server_t *servers = NULL; static int serverCount = 0; static void server_init(); static server_t *server_create(const char *server); +static void server_free(epoll_server_t *server); static void server_callback(void *data, int haveIn, int haveOut, int doCleanup); static void server_flush(epoll_server_t * const server); -static BOOL server_ensureConnected(const int index); +static BOOL server_ensureConnected(server_t *server); static void server_ensureSendBuffer(epoll_server_t * const s, const size_t len); // Generate a message ID for request to AD @@ -81,13 +65,13 @@ void server_initServers() printf("%d servers configured.\n", serverCount); for (i = 0; i < serverCount; ++i) { printf("%s:\n Bind: %s\n Base: %s\n", servers[i].addr, servers[i].bind, servers[i].base); - server_ensureConnected(i); + server_ensureConnected(&servers[i]); } } // What the proxy calls -int server_getFromBase(struct string *in) +server_t *server_getFromBase(struct string *in) { int i; char buffer[TMPLEN]; @@ -97,13 +81,13 @@ int server_getFromBase(struct string *in) for (i = 0; i < serverCount; ++i) { if (searchLen < servers[i].baseLen) continue; if (strcmp(servers[i].base, buffer + (searchLen - servers[i].baseLen)) == 0) { - return i; + return &servers[i]; } } - return -1; + return NULL; } -uint32_t server_searchRequest(int server, struct SearchRequest *req) +uint32_t server_searchRequest(server_t *server, struct SearchRequest *req) { if (!server_ensureConnected(server)) return 0; const uint32_t msgid = msgId(); @@ -113,11 +97,68 @@ uint32_t server_searchRequest(int server, struct SearchRequest *req) char *bufoff = buffer + 50; fmt_ldapsearchrequest(bufoff, req); fmt_ldapmessage(bufoff - headerLen, msgid, SearchRequest, bodyLen); - epoll_server_t * const s = &servers[server].con; + epoll_server_t * const s = &server->con; server_send(s, bufoff - headerLen, headerLen + bodyLen, FALSE); return msgid; } +uint32_t server_tryUserBind(server_t *server, struct string *binddn, struct string *password) +{ + epoll_server_t *con = calloc(1, sizeof(epoll_server_t)); + con->serverData = server; + con->fd = -1; + con->bound = FALSE; + con->dynamic = TRUE; + printf("Connecting to AD '%s' for %.*ss bind...\n", server->addr, (int)binddn->l, binddn->s); + con->sbPos = con->sbFill = 0; + int sock; + if (server->lastLookup + 300 < time(NULL)) { + sock = helper_connect4(server->addr, AD_PORT, server->ip); + if (sock == -1) { + printf("[ADB] Could not resolve/connect to AD server %s\n", server->addr); + server_free(con); + return 0; + } + } else { + sock = socket_tcp4b(); + if (sock == -1) { + printf("[ADB] Could not allocate socket for connection to AD\n"); + server_free(con); + return 0; + } + if (socket_connect4(sock, server->ip, AD_PORT) == -1) { + printf("[ADB] Could not connect to cached IP of %s\n", server->addr); + close(sock); + server_free(con); + return 0; + } + } + printf("[ADB] Connected, binding....\n"); + helper_nonblock(sock); + con->fd = sock; + con->callback = &server_callback; + if (ePoll_add(EPOLLIN | EPOLLOUT | EPOLLET, (epoll_item_t*)con) == -1) { + printf("[ADB] epoll_add failed for ad server %s\n", server->addr); + server_free(con); + return 0; + } + // Now bind - TODO: SASL (DIGEST-MD5?) + const uint32_t id = msgId(); + const size_t bodyLen = fmt_ldapbindrequeststring(NULL, 3, binddn, password); + const size_t headerLen = fmt_ldapmessage(NULL, id, BindRequest, bodyLen); + char buffer[bodyLen + 50]; + char *bufoff = buffer + 50; + if (headerLen >= 50) { + printf("[ADB] bind too long for %s\n", server->addr); + server_free(con); + return 0; + } + fmt_ldapbindrequeststring(bufoff, 3, binddn, password); + fmt_ldapmessage(bufoff - headerLen, id, BindRequest, bodyLen); + server_send(con, bufoff - headerLen, bodyLen + headerLen, FALSE); + return id; +} + // // Private stuff @@ -140,6 +181,7 @@ static server_t *server_create(const char *server) } snprintf(servers[serverCount].addr, ADDRLEN, "%s", server); servers[serverCount].con.fd = -1; + servers[serverCount].con.serverData = &servers[serverCount]; return &servers[serverCount++]; } @@ -149,6 +191,11 @@ static void server_free(epoll_server_t *server) if (server->fd != -1) close(server->fd); server->fd = -1; server->sbPos = server->sbFill = 0; + if (server->dynamic) { + printf("Freeing Bind-AD-Connection\n"); + free(server->sendBuffer); + free(server); + } } static void server_callback(void *data, int haveIn, int haveOut, int doCleanup) @@ -185,9 +232,12 @@ static void server_callback(void *data, int haveIn, int haveOut, int doCleanup) if (len > server->rbPos) break; // Body not complete printf("[AD] Received complete reply...\n"); if (proxy_fromServer(server, len) == -1) { + if (server->dynamic) { + server_free(server); + return; + } printf("Error parsing reply from AD.\n"); - server_free(server); - return; + // Let's try to go on with the next message.... } // Shift remaining buffer contents if (len == server->rbPos) { @@ -248,14 +298,13 @@ static void server_flush(epoll_server_t * const server) server->sbPos = server->sbFill = 0; } -static BOOL server_ensureConnected(const int index) +static BOOL server_ensureConnected(server_t *server) { - server_t * const server = &servers[index]; epoll_server_t * const con = &server->con; if (con->fd != -1 && con->lastActive + 120 > time(NULL)) return TRUE; if (con->fd != -1) close(con->fd); con->bound = FALSE; - printf("Connecting to AD %s...\n", server->addr); + printf("Connecting to AD '%s'...\n", server->addr); con->sbPos = con->sbFill = 0; int sock; if (server->lastLookup + 300 < time(NULL)) { @@ -286,9 +335,9 @@ static BOOL server_ensureConnected(const int index) con->fd = -1; return FALSE; } - // Now bind + // Now bind - TODO: SASL (DIGEST-MD5?) const size_t bodyLen = fmt_ldapbindrequest(NULL, 3, server->bind, server->password); - const size_t headerLen = fmt_ldapmessage(NULL, MSGID_BIND, BindResponse, bodyLen); + const size_t headerLen = fmt_ldapmessage(NULL, MSGID_BIND, BindRequest, bodyLen); char buffer[bodyLen + 50]; char *bufoff = buffer + 50; if (headerLen >= 50) { -- cgit v1.2.3-55-g7522