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
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include "ldap_headers.h"
30 /* ******************************************************************** */
32 /* Utilities Functions */
34 /* ******************************************************************** */
37 * __ldap_to_pamerror():
38 * converts Native LDAP errors to an equivalent PAM error
41 __ldap_to_pamerror(int ldaperror
)
47 case NS_LDAP_OP_FAILED
:
48 return (PAM_PERM_DENIED
);
54 return (PAM_SERVICE_ERR
);
56 case NS_LDAP_NOTFOUND
:
57 case NS_LDAP_INTERNAL
:
59 case NS_LDAP_INVALID_PARAM
:
60 return (PAM_SYSTEM_ERR
);
63 return (PAM_SYSTEM_ERR
);
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
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.
85 authenticate(ns_cred_t
**credpp
, char *usrname
, char *pwd
,
86 int *sec_until_expired
)
88 int result
= PAM_AUTH_ERR
;
92 char **certpath
= NULL
;
94 ns_auth_t
**authpp
= NULL
;
95 ns_auth_t
*authp
= NULL
;
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') ||
107 ldaprc
= __ns_ldap_uid2dn(usrname
, &binddn
, NULL
, &errorp
);
108 if ((result
= __ldap_to_pamerror(ldaprc
)) != PAM_SUCCESS
)
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
;
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
)
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
)
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
,
139 if ((result
= __ldap_to_pamerror(ldaprc
)) != PAM_SUCCESS
)
144 * if authpp is still null, then can not authenticate, syslog
145 * error message and return error
147 if (authpp
== NULL
) {
149 "pam_ldap: no authentication method configured");
150 result
= PAM_AUTH_ERR
;
155 * Walk the array and try all authentication methods in order except
158 for (app
= authpp
; *app
; app
++) {
160 /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */
161 if (authp
->type
== NS_LDAP_AUTH_NONE
)
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
177 if (ldaprc
== NS_LDAP_SUCCESS
) {
179 * authenticated and no
180 * password management info, done.
182 result
= PAM_SUCCESS
;
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;
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
)
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
215 result
= PAM_NEW_AUTHTOK_REQD
;
217 (void) __ns_ldap_freeError(&errorp
);
220 } else if (ldaprc
== NS_LDAP_INTERNAL
) {
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
==
232 result
= PAM_AUTHTOK_EXPIRED
;
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
);
247 /* done with the error info, clean it up */
249 (void) __ns_ldap_freeError(&errorp
);
251 if (authstried
== 0) {
253 "pam_ldap: no legal authentication method configured");
254 result
= PAM_AUTH_ERR
;
257 result
= PAM_PERM_DENIED
;
262 if (credp
&& (result
== PAM_SUCCESS
||
263 result
== PAM_NEW_AUTHTOK_REQD
))
267 (void) __ns_ldap_freeCred(&credp
);
270 (void) __ns_ldap_freeParam((void ***)&authpp
);
273 (void) __ns_ldap_freeError(&errorp
);