This might be a bit to ask but I am stumped. I am not a very experienced C programmer but have written some code in the past.
Currently I am adding some functionality to an existing authentication module for linux utilizing the openldap api and have hit a wall.
I am going to post the function in its entirety as well as how the function is being called...
This function I use to perform a simple check on struct values which were obtained from a configuration file. This works fine and returns a 1 on error or a 0 on success.
Code:
int
_check_ldap_options(struct _pam_krb5_options *options)
{
if( ( strlen(options->schema) < 0 ) || ( strlen(options->schema) > 5 ) ) { return(1); }
if( ( strlen(options->ldapservs) < 0 ) || ( strlen(options->ldapservs) > 255 ) ) { return(1); }
if( ( strlen(options->ldapport) < 0 ) || ( strlen(options->ldapport) > 4 ) ) { return(1); }
if( ( strlen(options->binddn) < 0 ) || ( strlen(options->binddn) > 255 ) ) { return(1); }
if( ( strlen(options->basedn) < 0 ) || (strlen(options->basedn) > 255 ) ) { return(1); }
if( ( strlen(options->ldapuser) < 0 ) || ( strlen(options->ldapuser) > 40 ) ) { return(1); }
if( ( strlen(options->ldappass) < 0 ) || (strlen(options->ldappass) > 40 ) ) { return(1); }
return(0);
}
This function is used to perform the init, bind, search and get values regarding the ldap api. This also works fine as each value I am looking for in active directory and ldap is returned and stored within the existing struct; struct _pam_krb5_user_info *userinfo.
Code:
int
_ldap_search(struct _pam_krb5_options *options, char *user, struct _pam_krb5_user_info *userinfo)
{
LDAP *ld;
LDAPMessage *res, *e;
BerElement *ptr;
int i, rc, port;
char *host, *base;
const char *luser, *pass;
char buffer[80], **vals;
const char *attrs;
if (options->schema == "ad") {
attrs = "homeDirectory";
} else {
attrs = "msSFUHomeDirectory";
}
host = options->ldapservs;
port = LDAP_PORT;
//port = options->ldapport;
luser = options->ldapuser;
pass = options->ldappass;
base = options->basedn;
if ((ld = ldap_init(host, port)) == NULL) {
crit("error connecting to %s", options->ldapservs);
return(1);
} else {
if (ldap_simple_bind_s(ld, luser, pass) == LDAP_SUCCESS) {
snprintf(buffer, sizeof(buffer), "(cn=%s)", user);
warn("searching '%s' for '%s'...", options->basedn, user);
if (ldap_search_s(ld, options->basedn, LDAP_SCOPE_SUBTREE, buffer, NULL, 0, &res) != LDAP_SUCCESS) {
crit( "error occured while searching for %s", buffer);
return(1);
}
if(ldap_first_entry(ld, res) == NULL) {
crit("'%s' not found in '%s' aborting authentication", user, options->basedn);
return(1);
}
for (e = ldap_first_entry(ld, res); e != NULL; e = ldap_next_entry(ld, e)) {
vals = ldap_get_values(ld, e, "uidNumber");
for (i = 0; vals[i] != NULL; i++) {
userinfo->uid = atoi(vals[i]);
debug("uid: %d", userinfo->uid);
}
vals = ldap_get_values(ld, e, "gidNumber");
for (i = 0; vals[i] != NULL; i++) {
userinfo->gid = atoi(vals[i]);
debug("gid: %d", userinfo->gid);
}
vals = ldap_get_values(ld, e, attrs);
for (i = 0; vals[i] != NULL; i++) {
snprintf(buffer, sizeof(buffer), "%s%s", vals[i], user);
userinfo->homedir = buffer;
debug("homedir: %s", userinfo->homedir);
}
vals = ldap_get_values(ld, e, "loginShell");
for (i = 0; vals[i] != NULL; i++) {
userinfo->shell = vals[i];
debug("loginshell: %s", userinfo->shell);
}
ldap_value_free(vals);
}
ldap_msgfree(res);
ldap_unbind(ld);
return(0);
} else {
crit("%s", ldap_err2string(ldap_simple_bind_s(ld, luser, pass)));
return(1);
}
}
}
This next portion is where I am running into a wall. It seems that the entire application halts when _ldap_search() is called. During testing the return value it will perform as expected
Code:
if (_check_ldap_options(options) != 0 ) {
warn("missing configuration options. aborting ad/ldap lookup, checking locally...");
} else {
if (_ldap_search(options, &local_name, &ret) != 0 ) {
warn("error looking up user in ad/ldap, checking locally...");
} else {
warn("%s => %s => %s", ret->uid, ret->gid, ret->homedir);
ret->uid = -1;
ret->gid = -1;
ret->homedir = xstrdup("/");
}
}
The second else statement is where it fails to put anything in the logs. If I perform a function call such as the following I get the desired return value and it continues without problem.
Code:
warn("results: %d", _ldap_search(options, &local_name, &ret));
Some more background... the 'options' argument is a struct of configuration options needed to connect and search active directory/ldap. the 'local_name' is the username i am searching for and '&ret' is the struct i am attempting to modify.
I do believe the problem lies in how I am attempting to modify the existing &ret struct variables. Any help is appreciated.