diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/pam_modules/ldap/ldap_utils.c | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/pam_modules/ldap/ldap_utils.c')
-rw-r--r-- | usr/src/lib/pam_modules/ldap/ldap_utils.c | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/usr/src/lib/pam_modules/ldap/ldap_utils.c b/usr/src/lib/pam_modules/ldap/ldap_utils.c new file mode 100644 index 0000000000..0b8e98728b --- /dev/null +++ b/usr/src/lib/pam_modules/ldap/ldap_utils.c @@ -0,0 +1,279 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "ldap_headers.h" +#include <malloc.h> + +/* ******************************************************************** */ +/* */ +/* Utilities Functions */ +/* */ +/* ******************************************************************** */ + +/* + * __ldap_to_pamerror(): + * converts Native LDAP errors to an equivalent PAM error + */ +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); + + } +} + +/* + * authenticate(): + * Returns + * PAM_SUCCESS if authenticated successfully + * PAM_NEW_AUTHTOK_REQD if authenticated but user needs to + * change password immediately + * PAM_MAXTRIES if authentication fails due to too + * many login failures + * PAM_AUTHTOK_EXPIRED if user password expired + * PAM_PERM_DENIED if fail to authenticate + * PAM_AUTH_ERR other errors + * + * Also output the second-until-expired data if authenticated + * but the password is about to expire. + * Authentication is checked by calling __ns_ldap_auth. + */ +int +authenticate(ns_cred_t **credpp, char *usrname, 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); + + /* Fill in the user name and password */ + 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; + } + + /* get host certificate path, if one is configured */ + 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; + + /* Load the service specific authentication method */ + ldaprc = __ns_ldap_getServiceAuthMethods("pam_ldap", &authpp, &errorp); + if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS) + goto out; + + /* + * if authpp is null, there is no serviceAuthenticationMethod + * try default authenticationMethod + */ + 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 is still null, then can not authenticate, syslog + * error message and return error + */ + if (authpp == NULL) { + syslog(LOG_ERR, + "pam_ldap: no authentication method configured"); + result = PAM_AUTH_ERR; + goto out; + } + + /* + * Walk the array and try all authentication methods in order except + * for "none". + */ + for (app = authpp; *app; app++) { + authp = *app; + /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */ + 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 rc is NS_LDAP_SUCCESS, done. If not, + * check rc and error info to see if + * there's any password management data. + * If yes, set appropriate PAM result code + * and exit. + */ + if (ldaprc == NS_LDAP_SUCCESS) { + /* + * authenticated and no + * password management info, done. + */ + result = PAM_SUCCESS; + goto out; + } else if (ldaprc == NS_LDAP_SUCCESS_WITH_INFO) { + /* + * authenticated but need to deal with + * password management info + */ + result = PAM_SUCCESS; + + /* + * clear sec_until_expired just in case + * there's no error info + */ + if (sec_until_expired) + *sec_until_expired = 0; + + if (errorp) { + if (errorp->pwd_mgmt.status == + NS_PASSWD_ABOUT_TO_EXPIRE) { + /* + * password about to expire; + * retrieve "seconds until expired" + */ + if (sec_until_expired) + *sec_until_expired = + errorp-> + pwd_mgmt.sec_until_expired; + } else if (errorp->pwd_mgmt.status == + NS_PASSWD_CHANGE_NEEDED) + /* + * indicate that passwd need to change + * right away + */ + result = PAM_NEW_AUTHTOK_REQD; + + (void) __ns_ldap_freeError(&errorp); + } + goto out; + } else if (ldaprc == NS_LDAP_INTERNAL) { + + if (errorp) { + /* + * If error due to password policy, set + * appropriate PAM result code and exit. + */ + 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 invalid credential, + * return PAM_AUTH_ERR. + */ + if (errorp->status == + LDAP_INVALID_CREDENTIALS) + result = PAM_AUTH_ERR; + } + (void) __ns_ldap_freeError(&errorp); + goto out; + } + } + + /* done with the error info, clean it up */ + 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); +} |