From b88e602f2cbdbac28d0b42034540d8370069cf23 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 8 Apr 2009 17:24:14 +0000 Subject: [PATCH] * Merge LDAP code; bindings are not yet complete --- citadel/Makefile.in | 11 +-- citadel/citadel_ldap.h | 13 +++ citadel/citserver.c | 6 ++ citadel/config.c | 3 +- citadel/ldap.c | 196 +++++++++++++++++++++++++++++++++++++++++ citadel/server.h | 1 + citadel/user_ops.c | 1 + 7 files changed, 222 insertions(+), 9 deletions(-) create mode 100644 citadel/citadel_ldap.h create mode 100644 citadel/ldap.c diff --git a/citadel/Makefile.in b/citadel/Makefile.in index 792432b0f..8b227a0fa 100644 --- a/citadel/Makefile.in +++ b/citadel/Makefile.in @@ -74,17 +74,14 @@ SOURCES=aidepost.c auth.c base64.c chkpwd.c chkpw.c citadel.c citadel_ipc.c \ citmail.c citserver.c client_chat.c client_passwords.c \ clientsocket.c commands.c config.c control.c $(DATABASE) \ domain.c serv_extensions.c file_ops.c genstamp.c getutline.c \ - housekeeping.c ical_dezonify.c \ - internet_addressing.c ecrash.c \ + housekeeping.c ical_dezonify.c internet_addressing.c ecrash.c \ ipc_c_tcp.c locate_host.c md5.c messages.c \ msgbase.c msgform.c parsedate.c policy.c \ room_ops.c rooms.c routines.c routines2.c tuiconfig.c euidindex.c \ screen.c sendcommand.c getmail.c \ - server_main.c \ - setup.c snprintf.c \ + server_main.c setup.c snprintf.c ldap.c \ stress.c support.c sysdep.c user_ops.c userlist.c \ - whobbs.c \ - journaling.c citadel_dirs.c threads.c + whobbs.c journaling.c citadel_dirs.c threads.c include Make_sources @@ -133,7 +130,7 @@ SERV_OBJS = server_main.o \ internet_addressing.o journaling.o \ parsedate.o genstamp.o ecrash.o threads.o\ clientsocket.o modules_init.o modules_upgrade.o $(AUTH) $(SERV_MODULES) \ - svn_revision.o + svn_revision.o ldap.o citserver$(EXEEXT): $(SERV_OBJS) $(CC) $(SERV_OBJS) $(LDFLAGS) $(SERVER_LDFLAGS) $(LIBS) $(SERVER_LIBS) $(RESOLV) -o citserver$(EXEEXT) diff --git a/citadel/citadel_ldap.h b/citadel/citadel_ldap.h new file mode 100644 index 000000000..0009c0093 --- /dev/null +++ b/citadel/citadel_ldap.h @@ -0,0 +1,13 @@ +/* + * + */ + +#define CTDL_LDAP_HOST "ldaptest.xand.com" +#define CTDL_LDAP_PORT LDAP_PORT /* defined as 389 */ +#define BASE_DN "dc=xand,dc=com" +#define BIND_DN NULL /* "cn=Manager,dc=xand,dc=com" for authenticated bind */ +#define BIND_PW NULL /* put pw here for authenticated bind */ +#define SEARCH_STRING "(&(objectclass=posixAccount)(uid=%s))" + +int CtdlTryUserLDAP(char *username, char *found_dn, int found_dn_size, char *fullname, int fullname_size); +int CtdlTryPasswordLDAP(char *user_dn, char *password); diff --git a/citadel/citserver.c b/citadel/citserver.c index 4e65fd6da..f127449d4 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -262,6 +262,12 @@ void RemoveContext (struct CitContext *con) CtdlLogPrintf(CTDL_DEBUG, "Closing socket %d\n", con->client_socket); close(con->client_socket); + /* If using AUTHMODE_LDAP, free the DN */ + if (con->ldap_dn) { + free(con->ldap_dn); + con->ldap_dn = NULL; + } + CtdlLogPrintf(CTDL_DEBUG, "Done with RemoveContext()\n"); } diff --git a/citadel/config.c b/citadel/config.c index 948f03005..b33e04142 100644 --- a/citadel/config.c +++ b/citadel/config.c @@ -1,8 +1,7 @@ /* * $Id$ * - * This function reads the citadel.config file. It should be called at - * the beginning of EVERY Citadel program. + * Read and write the citadel.config file * */ diff --git a/citadel/ldap.c b/citadel/ldap.c new file mode 100644 index 000000000..10eb31b51 --- /dev/null +++ b/citadel/ldap.c @@ -0,0 +1,196 @@ +/* + * + */ + + +int ldap_version = 3; + +#ifdef HAVE_LDAP + +#include "sysdep.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include "auth.h" +#include "citadel.h" +#include "server.h" +#include "database.h" +#include "user_ops.h" +#include "sysdep_decls.h" +#include "support.h" +#include "room_ops.h" +#include "file_ops.h" +#include "control.h" +#include "msgbase.h" +#include "config.h" +#include "citserver.h" +#include "citadel_dirs.h" +#include "genstamp.h" +#include "threads.h" +#include "citadel_ldap.h" + +#define LDAP_DEPRECATED 1 /* Needed to suppress misleading warnings */ + +#include + +int CtdlTryUserLDAP(char *username, char *found_dn, int found_dn_size, char *fullname, int fullname_size) +{ + LDAP *ldserver = NULL; + int i; + LDAPMessage *search_result = NULL; + LDAPMessage *entry = NULL; + char searchstring[1024]; + struct timeval tv; + char **values; + char *user_dn = NULL; + + safestrncpy(fullname, username, fullname_size); + + ldserver = ldap_init(CTDL_LDAP_HOST, CTDL_LDAP_PORT); + if (ldserver == NULL) { + CtdlLogPrintf(CTDL_ALERT, "LDAP: Could not connect to %s:%d : %s\n", + CTDL_LDAP_HOST, CTDL_LDAP_PORT, + strerror(errno)); + return(errno); + } + + ldap_set_option(ldserver, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); + + i = ldap_simple_bind_s(ldserver, BIND_DN, BIND_PW); + if (i != LDAP_SUCCESS) { + CtdlLogPrintf(CTDL_ALERT, "LDAP: Cannot bind: %s (%d)\n", ldap_err2string(i), i); + return(i); + } + + tv.tv_sec = 10; + tv.tv_usec = 0; + + sprintf(searchstring, SEARCH_STRING, username); + + i = ldap_search_st(ldserver, + BASE_DN, + LDAP_SCOPE_SUBTREE, + searchstring, + NULL, // return all attributes + 0, // attributes + values + &tv, // timeout + &search_result + ); + if (i != LDAP_SUCCESS) { + CtdlLogPrintf(CTDL_DEBUG, + "Couldn't find what I was looking for: %s (%d)\n", ldap_err2string(i), i); + ldap_unbind(ldserver); + return(i); + } + + if (search_result == NULL) { + CtdlLogPrintf(CTDL_DEBUG, "No results were returned\n"); + ldap_unbind(ldserver); + return(2); + } + + /* At this point we've got at least one result from our query. If there are multiple + * results, we still only look at the first one. + */ + entry = ldap_first_entry(ldserver, search_result); + if (entry) { + + user_dn = ldap_get_dn(ldserver, entry); + if (user_dn) { + CtdlLogPrintf(CTDL_DEBUG, "dn = %s\n", user_dn); + } + + values = ldap_get_values(ldserver, search_result, "cn"); + if (values) { + if (values[0]) { + safestrncpy(fullname, values[0], fullname_size); + CtdlLogPrintf(CTDL_DEBUG, "cn = %s\n", values[0]); + } + ldap_value_free(values); + } + + values = ldap_get_values(ldserver, search_result, "uidNumber"); + if (values) { + if (values[0]) { + CtdlLogPrintf(CTDL_DEBUG, "uidNumber = %s\n", values[0]); + } + ldap_value_free(values); + } + + values = ldap_get_values(ldserver, search_result, "objectGUID"); + if (values) { + if (values[0]) { + CtdlLogPrintf(CTDL_DEBUG, "objectGUID = (%d characers)\n", strlen(values[0])); + } + ldap_value_free(values); + } + + } + + /* free the results */ + ldap_msgfree(search_result); + + /* unbind so we can go back in as the authenticating user */ + ldap_unbind(ldserver); + + if (!user_dn) { + CtdlLogPrintf(CTDL_DEBUG, "No such user was found.\n"); + return(4); + } + + safestrncpy(found_dn, user_dn, found_dn_size); + ldap_memfree(user_dn); + return(0); +} + + +int CtdlTryPasswordLDAP(char *user_dn, char *password) +{ + LDAP *ldserver = NULL; + int i; + + ldserver = ldap_init(CTDL_LDAP_HOST, CTDL_LDAP_PORT); + if (ldserver) { + ldap_set_option(ldserver, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); + i = ldap_simple_bind_s(ldserver, user_dn, password); + if (i == LDAP_SUCCESS) { + CtdlLogPrintf(CTDL_DEBUG, "LDAP: bind succeeded\n"); + } + else { + CtdlLogPrintf(CTDL_DEBUG, "LDAP: Cannot bind: %s (%d)\n", ldap_err2string(i), i); + } + ldap_unbind(ldserver); + } + + return((i == LDAP_SUCCESS) ? 0 : 1); +} + + + + +#endif /* HAVE_LDAP */ diff --git a/citadel/server.h b/citadel/server.h index 13660559a..9fc9ca6ec 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -145,6 +145,7 @@ struct CitContext { struct ma_info *ma; /* multipart/alternative data */ const char *ServiceName; /* readable purpose of this session */ void *openid_data; /* Data stored by the OpenID module */ + char *ldap_dn; /* DN of user when using AUTHMODE_LDAP */ }; typedef struct CitContext t_context; diff --git a/citadel/user_ops.c b/citadel/user_ops.c index 60bce3fcc..b574fbd02 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -50,6 +50,7 @@ #include "citadel_dirs.h" #include "genstamp.h" #include "threads.h" +#include "citadel_ldap.h" /* These pipes are used to talk to the chkpwd daemon, which is forked during startup */ int chkpwd_write_pipe[2]; -- 2.30.2