dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / pam_modules / ldap / ldap_utils.c
blobfa68f5fb3936634b67fb7c82a64c55a5f0c43a66
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include "ldap_headers.h"
28 #include <malloc.h>
30 /* ******************************************************************** */
31 /* */
32 /* Utilities Functions */
33 /* */
34 /* ******************************************************************** */
37 * __ldap_to_pamerror():
38 * converts Native LDAP errors to an equivalent PAM error
40 int
41 __ldap_to_pamerror(int ldaperror)
43 switch (ldaperror) {
44 case NS_LDAP_SUCCESS:
45 return (PAM_SUCCESS);
47 case NS_LDAP_OP_FAILED:
48 return (PAM_PERM_DENIED);
50 case NS_LDAP_MEMORY:
51 return (PAM_BUF_ERR);
53 case NS_LDAP_CONFIG:
54 return (PAM_SERVICE_ERR);
56 case NS_LDAP_NOTFOUND:
57 case NS_LDAP_INTERNAL:
58 case NS_LDAP_PARTIAL:
59 case NS_LDAP_INVALID_PARAM:
60 return (PAM_SYSTEM_ERR);
62 default:
63 return (PAM_SYSTEM_ERR);
69 * authenticate():
70 * Returns
71 * PAM_SUCCESS if authenticated successfully
72 * PAM_NEW_AUTHTOK_REQD if authenticated but user needs to
73 * change password immediately
74 * PAM_MAXTRIES if authentication fails due to too
75 * many login failures
76 * PAM_AUTHTOK_EXPIRED if user password expired
77 * PAM_PERM_DENIED if fail to authenticate
78 * PAM_AUTH_ERR other errors
80 * Also output the second-until-expired data if authenticated
81 * but the password is about to expire.
82 * Authentication is checked by calling __ns_ldap_auth.
84 int
85 authenticate(ns_cred_t **credpp, char *usrname, char *pwd,
86 int *sec_until_expired)
88 int result = PAM_AUTH_ERR;
89 int ldaprc;
90 int authstried = 0;
91 char *binddn = NULL;
92 char **certpath = NULL;
93 ns_auth_t **app;
94 ns_auth_t **authpp = NULL;
95 ns_auth_t *authp = NULL;
96 ns_cred_t *credp;
97 ns_ldap_error_t *errorp = NULL;
99 if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL)
100 return (PAM_BUF_ERR);
102 /* Fill in the user name and password */
103 if ((usrname == NULL) || (pwd == NULL) || (usrname[0] == '\0') ||
104 (pwd[0] == '\0'))
105 goto out;
107 ldaprc = __ns_ldap_uid2dn(usrname, &binddn, NULL, &errorp);
108 if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS)
109 goto out;
111 credp->cred.unix_cred.userID = strdup(binddn);
112 credp->cred.unix_cred.passwd = strdup(pwd);
113 if ((credp->cred.unix_cred.userID == NULL) ||
114 (credp->cred.unix_cred.passwd == NULL)) {
115 result = PAM_BUF_ERR;
116 goto out;
119 /* get host certificate path, if one is configured */
120 ldaprc = __ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P,
121 (void ***)&certpath, &errorp);
122 if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS)
123 goto out;
124 if (certpath && *certpath)
125 credp->hostcertpath = *certpath;
127 /* Load the service specific authentication method */
128 ldaprc = __ns_ldap_getServiceAuthMethods("pam_ldap", &authpp, &errorp);
129 if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS)
130 goto out;
133 * if authpp is null, there is no serviceAuthenticationMethod
134 * try default authenticationMethod
136 if (authpp == NULL) {
137 ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp,
138 &errorp);
139 if ((result = __ldap_to_pamerror(ldaprc)) != PAM_SUCCESS)
140 goto out;
144 * if authpp is still null, then can not authenticate, syslog
145 * error message and return error
147 if (authpp == NULL) {
148 syslog(LOG_ERR,
149 "pam_ldap: no authentication method configured");
150 result = PAM_AUTH_ERR;
151 goto out;
155 * Walk the array and try all authentication methods in order except
156 * for "none".
158 for (app = authpp; *app; app++) {
159 authp = *app;
160 /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */
161 if (authp->type == NS_LDAP_AUTH_NONE)
162 continue;
163 authstried++;
164 credp->auth.type = authp->type;
165 credp->auth.tlstype = authp->tlstype;
166 credp->auth.saslmech = authp->saslmech;
167 credp->auth.saslopt = authp->saslopt;
168 ldaprc = __ns_ldap_auth(credp, 0, &errorp, NULL, NULL);
171 * If rc is NS_LDAP_SUCCESS, done. If not,
172 * check rc and error info to see if
173 * there's any password management data.
174 * If yes, set appropriate PAM result code
175 * and exit.
177 if (ldaprc == NS_LDAP_SUCCESS) {
179 * authenticated and no
180 * password management info, done.
182 result = PAM_SUCCESS;
183 goto out;
184 } else if (ldaprc == NS_LDAP_SUCCESS_WITH_INFO) {
186 * authenticated but need to deal with
187 * password management info
189 result = PAM_SUCCESS;
192 * clear sec_until_expired just in case
193 * there's no error info
195 if (sec_until_expired)
196 *sec_until_expired = 0;
198 if (errorp) {
199 if (errorp->pwd_mgmt.status ==
200 NS_PASSWD_ABOUT_TO_EXPIRE) {
202 * password about to expire;
203 * retrieve "seconds until expired"
205 if (sec_until_expired)
206 *sec_until_expired =
207 errorp->
208 pwd_mgmt.sec_until_expired;
209 } else if (errorp->pwd_mgmt.status ==
210 NS_PASSWD_CHANGE_NEEDED)
212 * indicate that passwd need to change
213 * right away
215 result = PAM_NEW_AUTHTOK_REQD;
217 (void) __ns_ldap_freeError(&errorp);
219 goto out;
220 } else if (ldaprc == NS_LDAP_INTERNAL) {
222 if (errorp) {
224 * If error due to password policy, set
225 * appropriate PAM result code and exit.
227 if (errorp->pwd_mgmt.status ==
228 NS_PASSWD_RETRY_EXCEEDED)
229 result = PAM_MAXTRIES;
230 else if (errorp->pwd_mgmt.status ==
231 NS_PASSWD_EXPIRED)
232 result = PAM_AUTHTOK_EXPIRED;
233 else {
235 * If invalid credential,
236 * return PAM_AUTH_ERR.
238 if (errorp->status ==
239 LDAP_INVALID_CREDENTIALS)
240 result = PAM_AUTH_ERR;
242 (void) __ns_ldap_freeError(&errorp);
243 goto out;
247 /* done with the error info, clean it up */
248 if (errorp)
249 (void) __ns_ldap_freeError(&errorp);
251 if (authstried == 0) {
252 syslog(LOG_ERR,
253 "pam_ldap: no legal authentication method configured");
254 result = PAM_AUTH_ERR;
255 goto out;
257 result = PAM_PERM_DENIED;
259 out:
260 free(binddn);
262 if (credp && (result == PAM_SUCCESS ||
263 result == PAM_NEW_AUTHTOK_REQD))
264 if (credpp)
265 *credpp = credp;
266 else
267 (void) __ns_ldap_freeCred(&credp);
269 if (authpp)
270 (void) __ns_ldap_freeParam((void ***)&authpp);
272 if (errorp)
273 (void) __ns_ldap_freeError(&errorp);
275 return (result);