Skip to content

Commit

Permalink
First simple ldap authentication support
Browse files Browse the repository at this point in the history
We currently assume that the users DLAP entry is
uid=<user name>,<LDAP user base>
and that their id is the uidNumber attribute.
  • Loading branch information
sfrothwell authored and cooldavid committed Jun 4, 2011
1 parent 950bbfc commit b1db7a2
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 25 deletions.
3 changes: 2 additions & 1 deletion Makefile
Expand Up @@ -22,8 +22,9 @@

MYSQL_CFLAGS=$(shell mysql_config --include)
MYSQL_LDFLAGS=$(shell mysql_config --libs_r)
LDAP_LDFLAGS=-lldap
CFLAGS+=-Wall
LDFLAGS+=-lpthread -lrt -lexpat $(MYSQL_LDFLAGS) -lssl
LDFLAGS+=-lpthread -lrt -lexpat $(MYSQL_LDFLAGS) $(LDAP_LDFLAGS) -lssl

ifdef DBG
CFLAGS+=-DDEBUG_$(DBG) -g
Expand Down
138 changes: 138 additions & 0 deletions ldap.c
@@ -0,0 +1,138 @@
/*
* TSP Server
*
* A TSP Server implementation that follows RFC5572 as much as possible.
* It is designed to be compatible with FreeNET6 service.
*
* LDAP support
* Copyright (C) 2011 Stephen Rothwell <sfr@canb.auug.or.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <ldap.h>

#include "tsps.h"

static LDAP *ldp;

int tsps_ldap_initialize(void)
{
int res;
int val;
struct berval passwd;

res = ldap_initialize(&ldp, server.ldap_uri);
if (res != LDAP_SUCCESS) {
fprintf(stderr, "LDAP initialization error: %s\n",
ldap_err2string(res));
return -1;
}
val = LDAP_VERSION3;
res = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &val);
if (res != LDAP_SUCCESS) {
fprintf(stderr, "LDAP set_option error: %s\n",
ldap_err2string(res));
return -1;
}
/*
* do an anoymous bind
*/
memset(&passwd, 0, sizeof(passwd));
res = ldap_sasl_bind_s(ldp, NULL, LDAP_SASL_SIMPLE, &passwd,
NULL, NULL, NULL);
if (res != LDAP_SUCCESS) {
fprintf(stderr, "LDAP anonymous bind error: %s\n",
ldap_err2string(res));
return -1;
}
return 0;
}

int tsps_ldap_login(const char *user, const char *pass)
{
char dn[1024];
LDAP *lp;
int res;
int val;
struct berval passwd;

res = ldap_initialize(&lp, server.ldap_uri);
if (res != LDAP_SUCCESS) {
fprintf(stderr, "LDAP initialization error: %s\n",
ldap_err2string(res));
return -1;
}
val = LDAP_VERSION3;
res = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &val);
if (res != LDAP_SUCCESS) {
fprintf(stderr, "LDAP set_option error: %s\n",
ldap_err2string(res));
return -1;
}
/*
* Attempt to bind to the ldap server as the user
*/
snprintf(dn, sizeof(dn), "uid=%s,%s", user, server.ldap_user_base);
memset(&passwd, 0, sizeof(passwd));
passwd.bv_val = ber_strdup(pass);
passwd.bv_len = strlen(pass);
res = ldap_sasl_bind_s(lp, dn, LDAP_SASL_SIMPLE, &passwd,
NULL, NULL, NULL);
ldap_unbind_ext_s(lp, NULL, NULL);
if (res != LDAP_SUCCESS) {
fprintf(stderr, "LDAP bind error: %s\n",
ldap_err2string(res));
return -1;
}
return 0;
}

int tsps_ldap_get_userid(const char *user)
{
char user_filt[128];
int res;
char *attrs[] = { "uidNumber", NULL };
LDAPMessage *vals = NULL;
LDAPMessage *val;
int uidnum = -1;

snprintf(user_filt, sizeof(user_filt), "(uid=%s)", user);

res = ldap_search_ext_s(ldp, server.ldap_user_base,
LDAP_SCOPE_ONELEVEL, user_filt, attrs, 0, NULL, NULL,
NULL, 0, &vals);
if (res != LDAP_SUCCESS) {
fprintf(stderr, "LDAP search error: %s\n",
ldap_err2string(res));
return -1;
}

for (val = ldap_first_message(ldp, vals); val;
val = ldap_next_message(ldp, val)) {
struct berval **uid_val =
ldap_get_values_len(ldp, val, "uidNumber");

if (uid_val) {
uidnum = (int)strtol(uid_val[0]->bv_val, NULL, 0);
ldap_value_free_len(uid_val);
break;
}
}

ldap_msgfree(vals);
return uidnum;
}
39 changes: 23 additions & 16 deletions login.c
Expand Up @@ -333,23 +333,30 @@ int login_plain(struct client_session *session, const char *user, const char *pa
int i, id;

dbg_login("Plain-login: %s %s", user, pass);
if (mysql_get_passhash(user, passhash))
return -1;

dbg_login("Plain-login: Stored hash %s", passhash);
if (strlen(passhash) != 32)
return -1;

sprintf(buf, "%s:" REALM ":%s", user, pass);
MD5((unsigned char *)buf, strlen(buf), HA1);
for (i = 0; i < 16; ++i)
sprintf((char *)(HEXHA1 + (i * 2)), "%02x", HA1[i]);

dbg_login("Plain-login: Gened hash %s", (char *)HEXHA1);
if (strcmp(passhash, (char *)HEXHA1))
return -1;
if (server.dbhost) {
if (mysql_get_passhash(user, passhash))
return -1;

dbg_login("Plain-login: Stored hash %s", passhash);
if (strlen(passhash) != 32)
return -1;

sprintf(buf, "%s:" REALM ":%s", user, pass);
MD5((unsigned char *)buf, strlen(buf), HA1);
for (i = 0; i < 16; ++i)
sprintf((char *)(HEXHA1 + (i * 2)), "%02x", HA1[i]);

dbg_login("Plain-login: Gened hash %s", (char *)HEXHA1);
if (strcmp(passhash, (char *)HEXHA1))
return -1;

id = mysql_get_userid(user);
} else /* if (server.ldap_uri) */ {
if (tsps_ldap_login(user, pass))
return -1;
id = tsps_ldap_get_userid(user);
}

id = mysql_get_userid(user);
if (id == -1)
return -1;

Expand Down
31 changes: 23 additions & 8 deletions tsps.c
Expand Up @@ -41,7 +41,7 @@ static int parse_args(int argc, char *argv[])
server.mode = UNDEFINED_MODE;
server.v4sockaddr.sin_port = htons(3653);

while ((opt = getopt(argc, argv, "t:b:p:n:NAHh:u:P:d:D")) != -1) {
while ((opt = getopt(argc, argv, "t:b:p:n:NAHh:u:P:d:Dl:B:")) != -1) {
switch (opt) {
case 't':
strncpy(server.tundev, optarg, 31);
Expand Down Expand Up @@ -135,6 +135,12 @@ static int parse_args(int argc, char *argv[])
case 'D':
server.debug = 1;
break;
case 'l':
server.ldap_uri = strdup(optarg);
break;
case 'B':
server.ldap_user_base = strdup(optarg);
break;
default:

return -1;
Expand All @@ -150,8 +156,10 @@ static int parse_args(int argc, char *argv[])
static void usage(const char *progname)
{
fprintf(stderr, "\n"
"Usage: %s %s -b IPv4_bind_address [-p IPv4_bind_port] -n IPv6_prefix [-A|-N|-H]\n"
" -h MySQL_Host -u MySQL_User -P MySQL_Pass -d MySQL_DBName -D\n"
"Usage: %s %s -b IPv4_bind_address [-p IPv4_bind_port] -n IPv6_prefix\n"
" [-A|-N|-H] [-D]\n"
" [-h MySQL_Host -u MySQL_User -P MySQL_Pass -d MySQL_DBName]\n"
" [-l LDAP_URI -B LDAP_user_base]\n"
" IPv4_bind_address: Used for client to connect\n"
" ex: 123.123.123.123\n"
" IPv4_bind_port: Used for client to connect\n"
Expand Down Expand Up @@ -189,8 +197,9 @@ static int check_server_configure(void)
}

if (server.mode != ANONYMOUS_MODE &&
(!server.dbhost || !server.dbuser || !server.dbpass || !server.dbname)) {
fprintf(stderr, "Must specify MySQL parameters in authenticated mode\n");
(!server.dbhost || !server.dbuser || !server.dbpass || !server.dbname) &&
!server.ldap_uri) {
fprintf(stderr, "Must specify MySQL or LDAP parameters in authenticated mode\n");
return -1;
}

Expand Down Expand Up @@ -243,9 +252,15 @@ int main(int argc, char *argv[], char *envv[])
return EXIT_FAILURE;
}

if (server.mode != ANONYMOUS_MODE && mysql_initialize()) {
fprintf(stderr, "Initialize MySQL error\n");
return EXIT_FAILURE;
if (server.mode != ANONYMOUS_MODE) {
if (server.dbhost && mysql_initialize()) {
fprintf(stderr, "Initialize MySQL error\n");
return EXIT_FAILURE;
}
if (server.ldap_uri && tsps_ldap_initialize()) {
fprintf(stderr, "Initialize LDAP error\n");
return EXIT_FAILURE;
}
}

if (!server.debug) {
Expand Down
7 changes: 7 additions & 0 deletions tsps.h
Expand Up @@ -94,6 +94,8 @@ struct tspserver {
char *dbuser;
char *dbpass;
char *dbname;
const char *ldap_uri;
const char *ldap_user_base;
};

enum {
Expand Down Expand Up @@ -200,6 +202,11 @@ int mysql_initialize(void);
int mysql_get_userid(const char *user);
int mysql_get_passhash(const char *user, char *pass);

/* ldap.c */
int tsps_ldap_initialize(void);
int tsps_ldap_get_userid(const char *user);
int tsps_ldap_login(const char *user, const char *pass);

/* log.c */
void tspslog(int prio, const char *msg, ...);

Expand Down

0 comments on commit b1db7a2

Please sign in to comment.