Whoops, a few function call typos, here we go again... To get this into the Makefile, I had to rework the __AUTHOBJECT__ line... I'll leave that up to you maitainer folks to get working, probably best to do with the auto* scripts, ie configure.in, so that one can do this:
./configure --with-db=mysql --with-auth=ldap Aaron On Fri, 13 Dec 2002, Aaron Stone wrote: > Hey, > > I've finally gotten some time together (yeah, like I was gonna do back in > May...) and wrote up the LDAP authentication code for the new > authentication API. Everything works out very nicely with the new code! > Well, everything except for MD5 passwords. So here's the new draft of the > authldap.c, which should be a drop-in for dbauth*sql.c > > Please do NOT use this code for a production machine. It is ALPHA only! > > Some notes: > > - write operations are not implemented (such as adding users, etc) > - MD5 authentication is not implemented (I need the real password to bind) > - configuration file code is kinda sorta so so eh. needs work. > > I haven't actually tested this code yet. It does compile without warnings, > and so at this point I want to start the sharing process. I'll spend some > more time on it this weekend, getting things to actually work and whatnot, > and post an updated version next week (hopefully). > > Enjoy! > > Aaron >
/* * $Id: authldap.c $ * (c) 2002 Aaron Stone, [EMAIL PROTECTED] * User authentication functions for LDAP. */ #include "auth.h" #include <ldap.h> #include "list.h" #include "debug.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include "db.h" #include "dbmd5.h" #include <crypt.h> #include "config.h" #include <time.h> #define AUTH_QUERY_SIZE 1024 /* string to be returned by db_getencryption() */ #define _DESCSTRLEN 50 char __auth_encryption_desc_string[_DESCSTRLEN]; extern char *configFile; static LDAP *_ldap_conn; static LDAPMessage *_ldap_res; static LDAPMessage *_ldap_msg; static int _ldap_err; static int _ldap_scope = LDAP_SCOPE_SUBTREE; /* Should be a config item */ static int _ldap_attrsonly = 0; static char *_ldap_dn; static char **_ldap_vals; static char **_ldap_attrs = NULL; static char _ldap_query[AUTH_QUERY_SIZE]; static char *_cfg_ldap_bind_dn, *_cfg_ldap_bind_pw, *_cfg_ldap_base_dn, *_cfg_ldap_scope, *_cfg_ldap_hostname, *_cfg_ldap_port, *_cfg_ldap_field_uid, *_cfg_ldap_field_cid, *_cfg_ldap_field_nid, *_cfg_ldap_field_mail, *_cfg_ldap_field_mailalt, *_cfg_ldap_field_maxmail; field_t _auth_host, _auth_user, _auth_db, _auth_pass; static void _get_ldap_config() { field_t val; struct list ldapItems; ReadConfig("LDAP", configFile, &ldapItems); SetTraceLevel(&ldapItems); GetConfigValue("BIND_DN", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): bind_dn [%s]\n", val); _cfg_ldap_bind_dn = val; GetConfigValue("BIND_PW", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): bind_pw [%s]\n", val); _cfg_ldap_bind_pw = val; GetConfigValue("BASE_DN", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_base_dn = val; GetConfigValue("PORT", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_port = val; GetConfigValue("HOSTNAME", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_hostname = val; GetConfigValue("FIELD_UID", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_field_uid = val; GetConfigValue("FIELD_CID", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_field_cid = val; GetConfigValue("FIELD_NID", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_field_nid = val; GetConfigValue("FIELD_MAIL", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_field_mail = val; GetConfigValue("FIELD_MAILALT", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_field_mailalt = val; GetConfigValue("FIELD_MAXMAIL", &ldapItems, val); if (strlen(val) == 0) trace(TRACE_DEBUG, "_get_ldap_config(): no value for BIND_DN in config file"); trace(TRACE_DEBUG, "SetConfigItems(): timeout [%s] seconds", val); _cfg_ldap_field_maxmail = val; } /* * auth_connect() * * initializes the connection for authentication. * * returns 0 on success, -1 on failure */ int auth_connect() { _ldap_conn = ldap_init( _cfg_ldap_hostname, atoi( _cfg_ldap_port ) ); _ldap_err = ldap_bind_s( _ldap_conn, _cfg_ldap_bind_dn, _cfg_ldap_bind_pw, LDAP_AUTH_SIMPLE ); if( _ldap_err ) { trace(TRACE_ERROR,"auth_connect(): ldap_bind_s failed: %s", ldap_err2string( _ldap_err ) ); return -1; } return 0; } int auth_disconnect() { ldap_unbind( _ldap_conn ); return 0; } u64_t auth_user_exists(const char *username) { u64_t uid; if (!username) { trace(TRACE_ERROR,"auth_user_exists(): got NULL as username\n"); return 0; } snprintf( _ldap_query, AUTH_QUERY_SIZE, "%s=%s", _cfg_ldap_field_uid, username ); _ldap_err = ldap_search_s( _ldap_conn, _cfg_ldap_base_dn, *_cfg_ldap_scope, _ldap_query, _ldap_attrs, _ldap_attrsonly, &_ldap_res ); if ( _ldap_err ) { trace(TRACE_ERROR, "auth_user_exists(): could not execute query: %s\n", ldap_err2string( _ldap_err ) ); return -1; } _ldap_msg = ldap_first_entry( _ldap_conn, _ldap_res ); if ( _ldap_msg == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_user_exists(): ldap_first_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_uid ); uid = ( *_ldap_vals ) ? strtoull( *_ldap_vals, 0, 0 ) : 0; ldap_value_free( _ldap_vals ); return uid; } /* return a list of existing users. -2 on mem error, -1 on db-error, 0 on succes */ int auth_get_known_users(struct list *users) { int i, j; if (!users) { trace(TRACE_ERROR,"auth_get_known_users(): got a NULL pointer as argument\n"); return -2; } list_init(users); /* do a inverted (DESC) query because adding the names to the final list inverts again */ snprintf( _ldap_query, AUTH_QUERY_SIZE, "(objectClass=*)"); _ldap_err = ldap_search_s( _ldap_conn, _cfg_ldap_base_dn, *_cfg_ldap_scope, _ldap_query, _ldap_attrs, _ldap_attrsonly, &_ldap_res ); if ( _ldap_err ) { trace( TRACE_ERROR, "auth_get_known_users(): could not retrieve user list: %s", ldap_err2string( _ldap_err ) ); return -1; } /* find out how many results for our query */ j = ldap_count_entries( _ldap_conn, _ldap_res ); if( j > 0 ) { /* for the first result we use ldap_first_entry */ _ldap_msg = ldap_first_entry( _ldap_conn, _ldap_res ); if ( _ldap_msg == NULL) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_get_known_users(): ldap_first_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_uid ); if( _ldap_vals == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_get_known_users(): ldap_get_values failed: %s", ldap_err2string( _ldap_err ) ); return -1; } if ( !list_nodeadd( users, *_ldap_vals, strlen( *_ldap_vals ) + 1 ) ) { list_freelist( &users->start ); return -2; } /* for subsequent results we use ldap_next_entry */ for ( i = 0; i < j; i++ ) { /* the LDAPMessage structure has entries for "res" and "msg" so we use just one of them here */ _ldap_msg = ldap_next_entry( _ldap_conn, _ldap_msg ); if ( _ldap_msg == NULL) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_get_known_user(): ldap_next_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_uid ); if ( *_ldap_vals == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_get_known_users(): ldap_get_values failed: %s", ldap_err2string( _ldap_err ) ); return -1; } if ( !list_nodeadd( users, *_ldap_vals, strlen( *_ldap_vals ) + 1 ) ) { list_freelist( &users->start ); return -2; } } } else { trace(TRACE_ERROR,"auth_get_known_users(): no users found\n" ); } ldap_value_free( _ldap_vals ); return 0; } u64_t auth_getclientid(u64_t useridnr) { u64_t cid; if (!useridnr) { trace(TRACE_ERROR,"auth_getclientid(): got NULL as useridnr\n"); return 0; } snprintf( _ldap_query, AUTH_QUERY_SIZE, "(%s=%llu)", _cfg_ldap_field_cid, useridnr ); _ldap_err = ldap_search_s( _ldap_conn, _cfg_ldap_base_dn, *_cfg_ldap_scope, _ldap_query, _ldap_attrs, _ldap_attrsonly, &_ldap_res ); if ( _ldap_err ) { trace(TRACE_ERROR, "auth_getclientid(): could not execute query: %s\n", ldap_err2string( _ldap_err ) ); return -1; } _ldap_msg = ldap_first_entry( _ldap_conn, _ldap_res ); if ( _ldap_msg == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_getclientid(): ldap_first_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_cid ); cid = ( (char *)_ldap_vals ) ? strtoull( (char *)_ldap_vals, 0, 0 ) : 0; ldap_value_free( _ldap_vals ); return cid; } u64_t auth_getmaxmailsize(u64_t useridnr) { u64_t maxmailsize; if (!useridnr) { trace(TRACE_ERROR,"auth_getmaxmailsize(): got NULL as useridnr\n"); return 0; } snprintf( _ldap_query, AUTH_QUERY_SIZE, "(%s=%llu)", _cfg_ldap_field_maxmail, useridnr ); _ldap_err = ldap_search_s( _ldap_conn, _cfg_ldap_base_dn, *_cfg_ldap_scope, _ldap_query, _ldap_attrs, _ldap_attrsonly, &_ldap_res ); if ( _ldap_err ) { trace(TRACE_ERROR, "auth_getmaxmailsize(): could not execute query: %s\n", ldap_err2string( _ldap_err ) ); return -1; } _ldap_msg = ldap_first_entry( _ldap_conn, _ldap_res ); if ( _ldap_msg == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_getmaxmailsize(): ldap_first_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_cid ); maxmailsize = ( (char *)_ldap_vals ) ? strtoull( (char *)_ldap_vals, 0, 10 ) : -1; ldap_value_free( _ldap_vals ); return maxmailsize; } /* * auth_getencryption() * * returns a string describing the encryption used for the passwd storage * for this user. * The string is valid until the next function call; in absence of any * encryption the string will be empty (not null). * * If the specified user does not exist an empty string will be returned. */ char* auth_getencryption(u64_t useridnr) { /* ldap does not support fancy passwords */ return 0; } /* recursive function, should be called with checks == -1 from main routine */ int auth_check_user (const char *username, struct list *userids, int checks) { int occurences=0, r; int i, j; trace(TRACE_DEBUG,"auth_check_user(): checking user [%s] in alias table",username); if (checks > MAX_CHECKS_DEPTH) { trace(TRACE_ERROR, "auth_check_user(): maximum checking depth reached, there probably is a loop in your alias table\n"); return -1; } snprintf ( _ldap_query, AUTH_QUERY_SIZE, "(%s=%s)", _cfg_ldap_field_uid, username ); _ldap_err = ldap_search_s( _ldap_conn, _cfg_ldap_base_dn, *_cfg_ldap_scope, _ldap_query, _ldap_attrs, _ldap_attrsonly, &_ldap_res ); if ( _ldap_err ) { trace(TRACE_ERROR, "auth_check_user(): could not execute query: %s", ldap_err2string( _ldap_err ) ); return -1; } /* we're just using a little counter variable, since we'll use it in the for loop later */ j = ldap_count_entries( _ldap_conn, _ldap_res ); if ( j < 1 ) { if ( checks > 0 ) { /* found the last one, this is the deliver to * but checks needs to be bigger then 0 because * else it could be the first query failure */ list_nodeadd( userids, username, strlen( username ) + 1 ); trace (TRACE_DEBUG,"auth_check_user(): adding [%s] to deliver_to address\n",username); return 1; } else { trace (TRACE_DEBUG,"auth_check_user(): user [%s] not in aliases table\n",username); return 0; } } trace (TRACE_DEBUG,"auth_check_user(): into checking loop\n"); /* do the first entry here */ _ldap_msg = ldap_first_entry( _ldap_conn, _ldap_res ); if ( _ldap_msg == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_check_user(): ldap_first_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } /* we'll get the next entry at the _end_ of the loop! */ for ( i = 0; i < j; i++ ) { _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_cid ); // FIXME: what field is this? /* do a recursive search for deliver_to */ trace (TRACE_DEBUG,"auth_check_user(): checking user %s to %s",username, (char *)_ldap_vals); r = auth_check_user ((char *)_ldap_vals, userids, (checks < 0) ? 1 : checks+1); if (r < 0) { /* loop detected */ ldap_value_free( _ldap_vals ); if (checks > 0) return -1; /* still in recursive call */ if (userids->start) { list_freelist(&userids->start); userids->total_nodes = 0; } return 0; /* report to calling routine: no results */ } occurences += r; /* do the next entry here */ _ldap_msg = ldap_next_entry( _ldap_conn, _ldap_msg ); if ( _ldap_msg == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_check_user(): ldap_next_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } } trace(TRACE_DEBUG,"auth_check_user(): executing query, checks [%d]", checks); /* trace(TRACE_INFO,"auth_check_user(): user [%s] has [%d] entries",username,occurences); */ return occurences; } /* * auth_check_user_ext() * * As auth_check_user() but adds the numeric ID of the user found * to userids or the forward to the fwds. * * returns the number of occurences. */ int auth_check_user_ext(const char *username, struct list *userids, struct list *fwds, int checks) { int i, j; int occurences=0; u64_t id; char *endptr = NULL; trace(TRACE_DEBUG,"auth_check_user_ext(): checking user [%s] in alias table",username); snprintf( _ldap_query, AUTH_QUERY_SIZE, "(%s=%s)", _cfg_ldap_field_uid, username ); trace(TRACE_DEBUG,"auth_check_user_ext(): executing query, checks [%d]", checks); _ldap_err = ldap_search_s( _ldap_conn, _cfg_ldap_base_dn, *_cfg_ldap_scope, _ldap_query, _ldap_attrs, _ldap_attrsonly, &_ldap_res ); if ( _ldap_err ) { trace(TRACE_ERROR, "auth_check_user_ext(): could not execute query: %s", ldap_err2string( _ldap_err ) ); return -1; } /* we're just using a little counter variable, since we'll use it in the for loop later */ j = ldap_count_entries( _ldap_conn, _ldap_res ); if ( i < 1 ) { if (checks>0) { /* found the last one, this is the deliver to * but checks needs to be bigger then 0 because * else it could be the first query failure */ id = strtoull(username, &endptr, 10); if (*endptr == 0) list_nodeadd(userids, &id, sizeof(id)); /* numeric deliver-to --> this is a userid */ else list_nodeadd(fwds, username, strlen(username)+1); trace (TRACE_DEBUG,"auth_check_user_ext(): adding [%s] to deliver_to address",username); return 1; } else { trace (TRACE_DEBUG,"auth_check_user_ext(): user [%s] not in aliases table", username); return 0; } } trace (TRACE_DEBUG,"auth_check_user_ext(): into checking loop"); /* do the first entry here */ _ldap_msg = ldap_first_entry( _ldap_conn, _ldap_res ); if ( _ldap_msg == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_check_user_ext(): ldap_first_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } /* we'll get the next entry at the _end_ of the loop! */ for ( i = 0; i < j; i++ ) { _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_cid ); // FIXME: what field is this? /* do a recursive search for deliver_to */ trace (TRACE_DEBUG,"auth_check_user_ext(): checking user %s to %s",username, (char *)_ldap_vals); occurences += auth_check_user_ext((char *)_ldap_vals, userids, fwds, 1); /* do the next entry here */ _ldap_msg = ldap_next_entry( _ldap_conn, _ldap_msg ); if ( _ldap_msg == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_check_user_ext(): ldap_next_entry failed: %s", ldap_err2string( _ldap_err ) ); return -1; } } /* trace(TRACE_INFO,"auth_check_user(): user [%s] has [%d] entries",username,occurences); */ return occurences; } /* * auth_adduser() * * adds a new user to the database * and adds a INBOX * returns a useridnr on succes, -1 on failure */ u64_t auth_adduser (char *username, char *password, char *enctype, char *clientid, char *maxmail) { return -1; } int auth_delete_user(const char *username) { return -1; } int auth_change_username(u64_t useridnr, const char *newname) { return -1; } int auth_change_password(u64_t useridnr, const char *newpass, const char *enctype) { return -1; } int auth_change_clientid(u64_t useridnr, u64_t newcid) { return -1; } int auth_change_mailboxsize(u64_t useridnr, u64_t newsize) { return -1; } /* * auth_validate() * * tries to validate user 'user' * * returns useridnr on OK, 0 on validation failed, -1 on error */ u64_t auth_validate (char *user, char *password) { u64_t id; int is_validated = 0; char timestr[30]; time_t td; struct tm tm; time(&td); /* get time */ tm = *localtime(&td); /* get components */ strftime(timestr, sizeof(timestr), "%G-%m-%d %H:%M:%S", &tm); snprintf( _ldap_query, AUTH_QUERY_SIZE, "(%s=%s)", _cfg_ldap_field_uid, user ); _ldap_err = ldap_search_s( _ldap_conn, _cfg_ldap_base_dn, *_cfg_ldap_scope, _ldap_query, _ldap_attrs, _ldap_attrsonly, &_ldap_res ); if ( _ldap_err ) { trace(TRACE_ERROR, "auth_validate(): could not select user information: %s", ldap_err2string( _ldap_err ) ); return -1; } if ( ldap_count_entries( _ldap_conn, _ldap_res ) ) { _ldap_msg = ldap_first_entry( _ldap_conn, _ldap_res ); if( _ldap_msg == NULL ) { trace(TRACE_ERROR, "auth_validate(): could not select user information: %s", ldap_err2string( _ldap_err ) ); return -1; } } else { /* user does not exist */ ldap_value_free( _ldap_vals ); return 0; } _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, "dn" ); /* now, try to rebind as the given DN using the supplied password */ trace (TRACE_DEBUG,"auth_validate(): rebinding as [%s] to validate password\n",(char *)_ldap_vals); _ldap_err = ldap_bind_s( _ldap_conn, (char *)_ldap_vals, password, LDAP_AUTH_SIMPLE ); // FIXME: do we need to bind back to the dbmail "superuser" again? if( _ldap_err ) { trace(TRACE_ERROR,"auth_validate(): ldap_bind_s failed: %s", ldap_err2string( _ldap_err ) ); ldap_value_free( _ldap_vals ); return 0; } else { _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_nid ); id = ((char *)_ldap_vals) ? strtoull((char *)_ldap_vals, NULL, 10) : 0; /* FIXME: implement this in LDAP... log login in the dbase snprintf(__auth_query_data, AUTH_QUERY_SIZE, "UPDATE users SET last_login = '%s' " "WHERE user_idnr = %llu", timestr, id); if (__auth_query(__auth_query_data)==-1) trace(TRACE_ERROR, "auth_validate(): could not update user login time"); */ } ldap_value_free( _ldap_vals ); return id; } u64_t auth_md5_validate (char *username,unsigned char *md5_apop_he, char *apop_stamp) { /* returns useridnr on OK, 0 on validation failed, -1 on error */ return 0; } /* Given a useridnr, find the account/login name * return 0 if not found, NULL on error */ char *auth_get_userid (u64_t *useridnr) { char *returnid = NULL; if ( !useridnr ) { trace(TRACE_ERROR,"auth_get_userid(): got NULL as useridnr\n"); return 0; } snprintf( _ldap_query, AUTH_QUERY_SIZE, "(%s=%llu)", _cfg_ldap_field_nid, useridnr ); _ldap_err = ldap_search_s( _ldap_conn, _cfg_ldap_base_dn, *_cfg_ldap_scope, _ldap_query, _ldap_attrs, _ldap_attrsonly, &_ldap_res ); if ( _ldap_err ) { trace(TRACE_ERROR, "auth_get_userid(): could not execute query: %s\n", ldap_err2string( _ldap_err ) ); return NULL; } if ( ldap_count_entries( _ldap_conn, _ldap_res ) < 1 ) { trace (TRACE_DEBUG,"auth_get_userid(): user has no username?"); return 0; } _ldap_msg = ldap_first_entry( _ldap_conn, _ldap_res ); if ( _ldap_msg == NULL ) { ldap_get_option(_ldap_conn, LDAP_OPT_ERROR_NUMBER, &_ldap_err); trace(TRACE_ERROR,"auth_get_userid(): ldap_first_entry failed: %s", ldap_err2string( _ldap_err ) ); return NULL; } _ldap_vals = ldap_get_values( _ldap_conn, _ldap_msg, _cfg_ldap_field_cid ); if ( _ldap_vals ) { if ( !( returnid = (char *)my_malloc( strlen( (char *)_ldap_vals ) + 1 ) ) ) { trace( TRACE_ERROR, "auth_get_userid(): out of memory" ); return NULL; } strcpy ( returnid, (char *)_ldap_vals ); } ldap_value_free( _ldap_vals ); return returnid; }