From fc3a2bdd1082832c5889be65c2849d300e2985e2 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sun, 24 Sep 2017 16:59:50 -0400 Subject: [PATCH] LDAP search --- citadel/citadel_ldap.h | 1 + citadel/citserver.c | 24 +++++------ citadel/housekeeping.c | 6 ++- citadel/ldap.c | 92 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 15 deletions(-) diff --git a/citadel/citadel_ldap.h b/citadel/citadel_ldap.h index fdf199b01..ed9373455 100644 --- a/citadel/citadel_ldap.h +++ b/citadel/citadel_ldap.h @@ -16,3 +16,4 @@ int CtdlTryUserLDAP(char *username, char *found_dn, int found_dn_size, char *ful int CtdlTryPasswordLDAP(char *user_dn, const char *password); int Ctdl_LDAP_to_vCard(char *ldap_dn, struct vCard *v); int extract_email_addresses_from_ldap(char *ldap_dn, char *emailaddrs); +void CtdlPopulateUsersFromLDAP(void); diff --git a/citadel/citserver.c b/citadel/citserver.c index babade1fb..3ac69266d 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -128,7 +128,7 @@ void master_startup(void) { struct passwd *pw; gid_t gid; - syslog(LOG_DEBUG, "master_startup() started\n"); + syslog(LOG_DEBUG, "master_startup() started"); time(&server_startup_time); syslog(LOG_INFO, "Checking directory access"); @@ -154,7 +154,7 @@ void master_startup(void) { /* Check floor reference counts */ check_ref_counts(); - syslog(LOG_INFO, "Creating base rooms (if necessary)\n"); + syslog(LOG_INFO, "Creating base rooms (if necessary)"); CtdlCreateRoom(CtdlGetConfigStr("c_baseroom"), 0, "", 0, 1, 0, VIEW_BBS); CtdlCreateRoom(AIDEROOM, 3, "", 0, 1, 0, VIEW_BBS); CtdlCreateRoom(SYSCONFIGROOM, 3, "", 0, 1, 0, VIEW_BBS); @@ -172,7 +172,7 @@ void master_startup(void) { CtdlPutRoomLock(&qrbuf); } - syslog(LOG_INFO, "Seeding the pseudo-random number generator...\n"); + syslog(LOG_INFO, "Seeding the pseudo-random number generator..."); urandom = fopen("/dev/urandom", "r"); if (urandom != NULL) { rv = fread(&seed, sizeof seed, 1, urandom); @@ -188,7 +188,7 @@ void master_startup(void) { srand(seed); srandom(seed); - syslog(LOG_DEBUG, "master_startup() finished\n"); + syslog(LOG_DEBUG, "master_startup() finished"); } @@ -222,7 +222,7 @@ int master_cleanup(int exitcode) { /* If the operator requested a halt but not an exit, halt here. */ if (shutdown_and_halt) { - syslog(LOG_NOTICE, "citserver: Halting server without exiting.\n"); + syslog(LOG_ERR, "citserver: Halting server without exiting."); fflush(stdout); fflush(stderr); while(1) { sleep(32767); @@ -230,7 +230,7 @@ int master_cleanup(int exitcode) { } /* Now go away. */ - syslog(LOG_NOTICE, "citserver: Exiting with status %d\n", exitcode); + syslog(LOG_ERR, "citserver: Exiting with status %d", exitcode); fflush(stdout); fflush(stderr); if (restart_server != 0) { @@ -290,14 +290,13 @@ int CtdlIsPublicClient(void) */ if (stat(public_clients_file, &statbuf) != 0) { /* No public_clients file exists, so bail out */ - syslog(LOG_WARNING, "Warning: '%s' does not exist\n", - public_clients_file); + syslog(LOG_WARNING, "Warning: '%s' does not exist", public_clients_file); return(0); } if (statbuf.st_mtime > pc_timestamp) { begin_critical_section(S_PUBLIC_CLIENTS); - syslog(LOG_INFO, "Loading %s\n", public_clients_file); + syslog(LOG_INFO, "Loading %s", public_clients_file); public_clientspos = &public_clients[0]; public_clientsend = public_clientspos + SIZ; @@ -343,18 +342,17 @@ int CtdlIsPublicClient(void) end_critical_section(S_PUBLIC_CLIENTS); } - syslog(LOG_DEBUG, "Checking whether %s is a local or public client\n", - CC->cs_addr); + syslog(LOG_DEBUG, "Checking whether %s is a local or public client", CC->cs_addr); for (i=0; ics_addr, addrbuf)) { - syslog(LOG_DEBUG, "... yes its local.\n"); + syslog(LOG_DEBUG, "... yes its local."); return(1); } } /* No hits. This is not a public client. */ - syslog(LOG_DEBUG, "... no it isn't.\n"); + syslog(LOG_DEBUG, "... no it isn't."); return(0); } diff --git a/citadel/housekeeping.c b/citadel/housekeeping.c index dae17c3ea..ecd7519bd 100644 --- a/citadel/housekeeping.c +++ b/citadel/housekeeping.c @@ -20,6 +20,7 @@ #include "room_ops.h" #include "internet_addressing.h" #include "journaling.h" +#include "citadel_ldap.h" void check_sched_shutdown(void) { if ((ScheduledShutdown == 1) && (ContextList == NULL)) { @@ -125,8 +126,9 @@ void do_housekeeping(void) { /* Then, do the "once per minute" stuff... */ if (do_perminute_housekeeping_now) { - cdb_check_handles(); /* suggested by Justin Case */ - PerformSessionHooks(EVT_TIMER); /* Run any timer hooks */ + cdb_check_handles(); + CtdlPopulateUsersFromLDAP(); // This one isn't from a module so we put it here + PerformSessionHooks(EVT_TIMER); // Run all registered TIMER hooks } /* diff --git a/citadel/ldap.c b/citadel/ldap.c index 8e51087b9..63f9efa89 100644 --- a/citadel/ldap.c +++ b/citadel/ldap.c @@ -542,4 +542,96 @@ int extract_email_addresses_from_ldap(char *ldap_dn, char *emailaddrs) return(0); } + +/* + * Scan LDAP for users and populate Citadel's user database with everyone + */ +void CtdlPopulateUsersFromLDAP(void) +{ + LDAP *ldserver = NULL; + int i; + LDAPMessage *search_result = NULL; + LDAPMessage *entry = NULL; + char *user_dn = NULL; + char searchstring[1024]; + struct timeval tv; + // char **values; + + if ((CtdlGetConfigInt("c_auth_mode") != AUTHMODE_LDAP) && (CtdlGetConfigInt("c_auth_mode") != AUTHMODE_LDAP_AD)) { + return; // not running LDAP + } + + syslog(LOG_INFO, "ldap: populating Citadel user database from LDAP"); + + if (ctdl_ldap_initialize(&ldserver) != LDAP_SUCCESS) { + return; + } + + ldap_set_option(ldserver, LDAP_OPT_PROTOCOL_VERSION, &ctdl_require_ldap_version); + ldap_set_option(ldserver, LDAP_OPT_REFERRALS, (void *)LDAP_OPT_OFF); + + striplt(CtdlGetConfigStr("c_ldap_bind_dn")); + striplt(CtdlGetConfigStr("c_ldap_bind_pw")); + syslog(LOG_DEBUG, "ldap: bind DN: %s", CtdlGetConfigStr("c_ldap_bind_dn")); + i = ldap_simple_bind_s(ldserver, + (!IsEmptyStr(CtdlGetConfigStr("c_ldap_bind_dn")) ? CtdlGetConfigStr("c_ldap_bind_dn") : NULL), + (!IsEmptyStr(CtdlGetConfigStr("c_ldap_bind_pw")) ? CtdlGetConfigStr("c_ldap_bind_pw") : NULL) + ); + if (i != LDAP_SUCCESS) { + syslog(LOG_ERR, "ldap: Cannot bind: %s (%d)", ldap_err2string(i), i); + return; + } + + tv.tv_sec = 10; + tv.tv_usec = 0; + + if (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_LDAP_AD) { + snprintf(searchstring, sizeof(searchstring), "(&(objectClass=user)(objectClass=person)(!(objectClass=computer)))"); + } else { + snprintf(searchstring, sizeof(searchstring), "(objectClass: inetOrgPerson)"); + } + + syslog(LOG_DEBUG, "ldap: search: %s", searchstring); + (void) ldap_search_ext_s( + ldserver, // ld + CtdlGetConfigStr("c_ldap_base_dn"), // base + LDAP_SCOPE_SUBTREE, // scope + searchstring, // filter + NULL, // attrs (all attributes) + 0, // attrsonly (attrs + values) + NULL, // serverctrls (none) + NULL, // clientctrls (none) + &tv, // timeout + INT_MAX, // sizelimit (max) + &search_result // result + ); + + /* Ignore the return value of ldap_search_ext_s(). Sometimes it returns an error even when + * the search succeeds. Instead, we check to see whether search_result is still NULL. + */ + if (search_result == NULL) { + syslog(LOG_DEBUG, "ldap: zero search results were returned"); + ldap_unbind(ldserver); + return; + } + + syslog(LOG_DEBUG, "ldap: %d entries returned", ldap_count_entries(ldserver, search_result)); + entry = ldap_first_entry(ldserver, search_result); + while (entry) { + + user_dn = ldap_get_dn(ldserver, entry); + if (user_dn) { + syslog(LOG_DEBUG, "ldap: found %s", user_dn); + } + + entry = ldap_next_entry(ldserver, entry); + } + + /* free the results */ + ldap_msgfree(search_result); + + /* unbind so we can go back in as the authenticating user */ + ldap_unbind(ldserver); +} + #endif /* HAVE_LDAP */ -- 2.30.2