#include "ldap_headers.h"
#include <malloc.h>
int
__ldap_to_pamerror(int ldaperror)
{
switch (ldaperror) {
case NS_LDAP_SUCCESS:
return (PAM_SUCCESS);
case NS_LDAP_OP_FAILED:
return (PAM_PERM_DENIED);
case NS_LDAP_MEMORY:
return (PAM_BUF_ERR);
case NS_LDAP_CONFIG:
return (PAM_SERVICE_ERR);
case NS_LDAP_NOTFOUND:
case NS_LDAP_INTERNAL:
case NS_LDAP_PARTIAL:
case NS_LDAP_INVALID_PARAM:
return (PAM_SYSTEM_ERR);
default:
return (PAM_SYSTEM_ERR);
}
}
int
authenticate(ns_cred_t **credpp, const char *usrname, const char *pwd,
int *sec_until_expired)
{
int result = PAM_AUTH_ERR;
int ldaprc;
int authstried = 0;
char *binddn = NULL;
char **certpath = NULL;
ns_auth_t **app;
ns_auth_t **authpp = NULL;
ns_auth_t *authp = NULL;
ns_cred_t *credp;
ns_ldap_error_t *errorp = NULL;
if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL)
return (PAM_BUF_ERR);
if ((usrname == NULL) || (pwd == NULL) || (usrname[0] == '\0') ||
(pwd[0] == '\0'))
goto out;
ldaprc = __ns_ldap_uid2dn(usrname, &binddn, NULL, &errorp);
if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS)
goto out;
credp->cred.unix_cred.userID = strdup(binddn);
credp->cred.unix_cred.passwd = strdup(pwd);
if ((credp->cred.unix_cred.userID == NULL) ||
(credp->cred.unix_cred.passwd == NULL)) {
result = PAM_BUF_ERR;
goto out;
}
ldaprc = __ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P,
(void ***)&certpath, &errorp);
if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS)
goto out;
if (certpath && *certpath)
credp->hostcertpath = *certpath;
ldaprc = __ns_ldap_getServiceAuthMethods("pam_ldap", &authpp, &errorp);
if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS)
goto out;
if (authpp == NULL) {
ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp,
&errorp);
if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS)
goto out;
}
if (authpp == NULL) {
syslog(LOG_ERR,
"pam_ldap: no authentication method configured");
result = PAM_AUTH_ERR;
goto out;
}
for (app = authpp; *app; app++) {
authp = *app;
if (authp->type == NS_LDAP_AUTH_NONE)
continue;
authstried++;
credp->auth.type = authp->type;
credp->auth.tlstype = authp->tlstype;
credp->auth.saslmech = authp->saslmech;
credp->auth.saslopt = authp->saslopt;
ldaprc = __ns_ldap_auth(credp, 0, &errorp, NULL, NULL);
if (ldaprc == NS_LDAP_SUCCESS) {
result = PAM_SUCCESS;
goto out;
} else if (ldaprc == NS_LDAP_SUCCESS_WITH_INFO) {
result = PAM_SUCCESS;
if (sec_until_expired)
*sec_until_expired = 0;
if (errorp) {
if (errorp->pwd_mgmt.status ==
NS_PASSWD_ABOUT_TO_EXPIRE) {
if (sec_until_expired)
*sec_until_expired =
errorp->
pwd_mgmt.sec_until_expired;
} else if (errorp->pwd_mgmt.status ==
NS_PASSWD_CHANGE_NEEDED)
result = PAM_NEW_AUTHTOK_REQD;
(void) __ns_ldap_freeError(&errorp);
}
goto out;
} else if (ldaprc == NS_LDAP_INTERNAL) {
if (errorp) {
if (errorp->pwd_mgmt.status ==
NS_PASSWD_RETRY_EXCEEDED)
result = PAM_MAXTRIES;
else if (errorp->pwd_mgmt.status ==
NS_PASSWD_EXPIRED)
result = PAM_AUTHTOK_EXPIRED;
else {
if (errorp->status ==
LDAP_INVALID_CREDENTIALS)
result = PAM_AUTH_ERR;
}
(void) __ns_ldap_freeError(&errorp);
goto out;
}
}
if (errorp)
(void) __ns_ldap_freeError(&errorp);
}
if (authstried == 0) {
syslog(LOG_ERR,
"pam_ldap: no legal authentication method configured");
result = PAM_AUTH_ERR;
goto out;
}
result = PAM_PERM_DENIED;
out:
if (binddn)
free(binddn);
if (credp && (result == PAM_SUCCESS ||
result == PAM_NEW_AUTHTOK_REQD))
if (credpp)
*credpp = credp;
else
(void) __ns_ldap_freeCred(&credp);
if (authpp)
(void) __ns_ldap_freeParam((void ***)&authpp);
if (errorp)
(void) __ns_ldap_freeError(&errorp);
return (result);
}