2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-2001
6 Copyright (C) John H Terpsta 1999-2001
7 Copyright (C) Andrew Bartlett 2001
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 * This module provides PAM based functions for validation of
26 * username/password pairs, account managment, session and access control.
27 * Note: SMB password checking is done in smbpass.c
32 extern int DEBUGLEVEL
;
36 /*******************************************************************
37 * Handle PAM authentication
38 * - Access, Authentication, Session, Password
39 * Note: See PAM Documentation and refer to local system PAM implementation
40 * which determines what actions/limitations/allowances become affected.
41 *********************************************************************/
43 #include <security/pam_appl.h>
46 * Static variables used to communicate between the conversation function
47 * and the server_login function
50 static char *PAM_username
;
51 static char *PAM_password
;
54 * Macros to help make life easy
56 #define COPY_STRING(s) (s) ? strdup(s) : NULL
61 static BOOL
pam_error_handler(pam_handle_t
*pamh
, int pam_error
, char *msg
, int dbglvl
)
64 if( pam_error
!= PAM_SUCCESS
)
66 DEBUG(dbglvl
, ("PAM: %s : %s\n", msg
, pam_strerror(pamh
, pam_error
)));
73 * PAM conversation function
74 * Here we assume (for now, at least) that echo on means login name, and
75 * echo off means password.
78 static int PAM_conv(int num_msg
,
79 const struct pam_message
**msg
,
80 struct pam_response
**resp
,
84 struct pam_response
*reply
= NULL
;
86 reply
= malloc(sizeof(struct pam_response
) * num_msg
);
90 for (replies
= 0; replies
< num_msg
; replies
++)
92 switch (msg
[replies
]->msg_style
)
94 case PAM_PROMPT_ECHO_ON
:
95 reply
[replies
].resp_retcode
= PAM_SUCCESS
;
97 COPY_STRING(PAM_username
);
101 case PAM_PROMPT_ECHO_OFF
:
102 reply
[replies
].resp_retcode
= PAM_SUCCESS
;
103 reply
[replies
].resp
=
104 COPY_STRING(PAM_password
);
113 reply
[replies
].resp_retcode
= PAM_SUCCESS
;
114 reply
[replies
].resp
= NULL
;
118 /* Must be an error of some sort... */
128 static struct pam_conv PAM_conversation
= {
134 * PAM Closing out cleanup handler
136 static BOOL
proc_pam_end(pam_handle_t
*pamh
)
142 pam_error
= pam_end(pamh
, 0);
143 if(pam_error_handler(pamh
, pam_error
, "End Cleanup Failed", 2) == True
) {
144 DEBUG(4, ("PAM: PAM_END OK.\n"));
148 DEBUG(2,("PAM: not initialised"));
153 * Start PAM authentication for specified account
155 static BOOL
proc_pam_start(pam_handle_t
**pamh
, char *user
)
160 DEBUG(4,("PAM: Init user: %s\n", user
));
162 pam_error
= pam_start("samba", user
, &PAM_conversation
, pamh
);
163 if( !pam_error_handler(*pamh
, pam_error
, "Init Failed", 0)) {
168 rhost
= client_name();
169 if (strcmp(rhost
,"UNKNOWN") == 0)
170 rhost
= client_addr();
173 DEBUG(4,("PAM: setting rhost to: %s\n", rhost
));
174 pam_error
= pam_set_item(*pamh
, PAM_RHOST
, rhost
);
175 if(!pam_error_handler(*pamh
, pam_error
, "set rhost failed", 0)) {
181 DEBUG(4,("PAM: setting tty\n"));
182 pam_error
= pam_set_item(*pamh
, PAM_TTY
, "samba");
183 if (!pam_error_handler(*pamh
, pam_error
, "set tty failed", 0)) {
188 DEBUG(4,("PAM: Init passed for user: %s\n", user
));
193 * PAM Authentication Handler
195 static BOOL
pam_auth(pam_handle_t
*pamh
, char *user
, char *password
)
200 * To enable debugging set in /etc/pam.d/samba:
201 * auth required /lib/security/pam_pwdb.so nullok shadow audit
204 DEBUG(4,("PAM: Authenticate User: %s\n", user
));
205 pam_error
= pam_authenticate(pamh
, PAM_SILENT
); /* Can we authenticate user? */
208 DEBUG(2, ("PAM: Athentication Error\n"));
210 case PAM_CRED_INSUFFICIENT
:
211 DEBUG(2, ("PAM: Insufficient Credentials\n"));
213 case PAM_AUTHINFO_UNAVAIL
:
214 DEBUG(2, ("PAM: Authentication Information Unavailable\n"));
216 case PAM_USER_UNKNOWN
:
217 DEBUG(2, ("PAM: Username NOT known to Authentication system\n"));
220 DEBUG(2, ("PAM: One or more authentication modules reports user limit exceeeded\n"));
223 DEBUG(0, ("PAM: One or more PAM modules failed to load\n"));
226 DEBUG(4, ("PAM: User %s Authenticated OK\n", user
));
229 DEBUG(0, ("PAM: UNKNOWN ERROR while authenticating user %s\n", user
));
231 if(!pam_error_handler(pamh
, pam_error
, "Authentication Failure", 2)) {
235 /* If this point is reached, the user has been authenticated. */
240 * PAM Account Handler
242 static BOOL
pam_account(pam_handle_t
*pamh
, char * user
, char * password
, BOOL pam_auth
)
246 DEBUG(4,("PAM: Account Management for User: %s\n", user
));
247 pam_error
= pam_acct_mgmt(pamh
, PAM_SILENT
); /* Is user account enabled? */
248 switch( pam_error
) {
249 case PAM_AUTHTOK_EXPIRED
:
250 DEBUG(2, ("PAM: User is valid but password is expired\n"));
252 case PAM_ACCT_EXPIRED
:
253 DEBUG(2, ("PAM: User no longer permitted to access system\n"));
256 DEBUG(2, ("PAM: There was an authentication error\n"));
258 case PAM_PERM_DENIED
:
259 DEBUG(0, ("PAM: User is NOT permitted to access system at this time\n"));
261 case PAM_USER_UNKNOWN
:
262 DEBUG(0, ("PAM: User \"%s\" is NOT known to account management\n", user
));
265 DEBUG(4, ("PAM: Account OK for User: %s\n", user
));
268 DEBUG(0, ("PAM: UNKNOWN ERROR for User: %s\n", user
));
270 if(!pam_error_handler(pamh
, pam_error
, "Account Check Failed", 2)) {
275 /* Skip the pam_setcred() call if we didn't use pam_authenticate()
276 for authentication -- it's an error to call pam_setcred without
277 calling pam_authenticate first */
279 DEBUG(4, ("PAM: Skipping setcred for user: %s (using encrypted passwords)\n", user
));
284 * This will allow samba to aquire a kerberos token. And, when
285 * exporting an AFS cell, be able to /write/ to this cell.
288 DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user
));
289 pam_error
= pam_setcred(pamh
, (PAM_ESTABLISH_CRED
|PAM_SILENT
));
290 switch( pam_error
) {
291 case PAM_CRED_UNAVAIL
:
292 DEBUG(0, ("PAM: Credentials not found for user:%s", user
));
294 case PAM_CRED_EXPIRED
:
295 DEBUG(0, ("PAM: Credentials for user: \"%s\" EXPIRED!", user
));
297 case PAM_CRED_UNKNOWN
:
298 DEBUG(0, ("PAM: User: \"%s\" is NOT known so can not set credentials!", user
));
300 case PAM_CRED_UNKNOWN
:
301 DEBUG(0, ("PAM: Unknown setcredentials error - unable to set credentials for %s", user
));
304 DEBUG(4, ("PAM: SetCredentials OK for User: %s\n", user
));
307 DEBUG(0, ("PAM: Error Condition Unknown in pam_setcred function call!"));
309 if(!pam_error_handler(pamh
, pam_error
, "Set Credential Failure", 2)) {
314 /* If this point is reached, the user has been authenticated. */
320 * PAM Internal Session Handler
322 static BOOL
proc_pam_session(pam_handle_t
*pamh
, char *user
, char *tty
, BOOL flag
)
330 DEBUG(4,("PAM: tty set to: %s\n", tty
));
331 pam_error
= pam_set_item(pamh
, PAM_TTY
, tty
);
332 if (!pam_error_handler(pamh
, pam_error
, "set tty failed", 0)) {
339 pam_error
= pam_open_session(pamh
, PAM_SILENT
);
340 if (!pam_error_handler(pamh
, pam_error
, "session setup failed", 0)) {
347 pam_error
= pam_close_session(pamh
, PAM_SILENT
);
348 if (!pam_error_handler(pamh
, pam_error
, "session close failed", 0)) {
357 * PAM Externally accessible Session handler
359 BOOL
pam_session(BOOL flag
, const char *in_user
, char *tty
)
361 pam_handle_t
*pamh
= NULL
;
364 user
= malloc(strlen(in_user
)+1);
367 DEBUG(0, ("PAM: PAM_session Malloc Failed!\n"));
371 /* This is freed by PAM */
372 StrnCpy(user
, in_user
, strlen(in_user
)+1);
374 if (!proc_pam_start(&pamh
, user
))
380 if (proc_pam_session(pamh
, user
, tty
, flag
))
382 return proc_pam_end(pamh
);
392 * PAM Externally accessible Account handler
394 BOOL
pam_accountcheck(char * user
)
396 pam_handle_t
*pamh
= NULL
;
401 if( proc_pam_start(&pamh
, user
))
403 if ( pam_account(pamh
, user
, NULL
, False
))
405 return( proc_pam_end(pamh
));
408 DEBUG(0, ("PAM: Account Validation Failed - Rejecting User!\n"));
413 * PAM Password Validation Suite
415 BOOL
pam_passcheck(char * user
, char * password
)
417 pam_handle_t
*pamh
= NULL
;
420 PAM_password
= password
;
422 if( proc_pam_start(&pamh
, user
))
424 if ( pam_auth(pamh
, user
, password
))
426 if ( pam_account(pamh
, user
, password
, True
))
428 return( proc_pam_end(pamh
));
432 DEBUG(0, ("PAM: System Validation Failed - Rejecting User!\n"));
438 /* Do *NOT* make this function static. Doing so breaks the compile on gcc */
440 void pampass_dummy_function( void ) { } /*This stops compiler complaints */
442 #endif /* WITH_PAM */