1 /* ========================================================================
2  * Copyright 1988-2006 University of Washington
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *
11  * ========================================================================
12  */
13 
14 /*
15  * Program:	Pluggable Authentication Modules login services, buggy systems
16  *		(use this instead of ckp_pam.c on Solaris)
17  *
18  * Author:	Mark Crispin
19  *		Networks and Distributed Computing
20  *		Computing & Communications
21  *		University of Washington
22  *		Administration Building, AG-44
23  *		Seattle, WA  98195
24  *		Internet: MRC@CAC.Washington.EDU
25  *
26  * Date:	1 August 1988
27  * Last Edited:	31 August 2006
28  */
29 
30 
31 #include <security/pam_appl.h>
32 
33 static char *pam_uname;		/* user name */
34 static char *pam_pass;		/* password */
35 
36 /* PAM conversation function
37  * Accepts: number of messages
38  *	    vector of messages
39  *	    pointer to response return
40  *	    application data
41  * Returns: PAM_SUCCESS if OK, response vector filled in, else PAM_CONV_ERR
42  */
43 
checkpw_conv(int num_msg,const struct pam_message ** msg,struct pam_response ** resp,void * appdata_ptr)44 static int checkpw_conv (int num_msg,const struct pam_message **msg,
45 			 struct pam_response **resp,void *appdata_ptr)
46 {
47   int i;
48   struct pam_response *reply = fs_get (sizeof (struct pam_response) * num_msg);
49   for (i = 0; i < num_msg; i++) switch (msg[i]->msg_style) {
50   case PAM_PROMPT_ECHO_ON:	/* assume want user name */
51     reply[i].resp_retcode = PAM_SUCCESS;
52     reply[i].resp = cpystr (pam_uname);
53     break;
54   case PAM_PROMPT_ECHO_OFF:	/* assume want password */
55     reply[i].resp_retcode = PAM_SUCCESS;
56     reply[i].resp = cpystr (pam_pass);
57     break;
58   case PAM_TEXT_INFO:
59   case PAM_ERROR_MSG:
60     reply[i].resp_retcode = PAM_SUCCESS;
61     reply[i].resp = NULL;
62     break;
63   default:			/* unknown message style */
64     fs_give ((void **) &reply);
65     return PAM_CONV_ERR;
66   }
67   *resp = reply;
68   return PAM_SUCCESS;
69 }
70 
71 
72 /* PAM cleanup
73  * Accepts: handle
74  */
75 
checkpw_cleanup(pam_handle_t * hdl)76 static void checkpw_cleanup (pam_handle_t *hdl)
77 {
78 #if 0	/* see checkpw() for why this is #if 0 */
79   pam_close_session (hdl,NIL);	/* close session [uw]tmp */
80 #endif
81   pam_setcred (hdl,PAM_DELETE_CRED);
82   pam_end (hdl,PAM_SUCCESS);
83 }
84 
85 /* Server log in
86  * Accepts: user name string
87  *	    password string
88  * Returns: T if password validated, NIL otherwise
89  */
90 
checkpw(struct passwd * pw,char * pass,int argc,char * argv[])91 struct passwd *checkpw (struct passwd *pw,char *pass,int argc,char *argv[])
92 {
93   pam_handle_t *hdl;
94   struct pam_conv conv;
95   char *name = cpystr (pw->pw_name);
96   conv.conv = &checkpw_conv;
97   pam_uname = pw->pw_name;
98   pam_pass = pass;
99   if (pw = ((pam_start ((char *) mail_parameters (NIL,GET_SERVICENAME,NIL),
100 			pw->pw_name,&conv,&hdl) == PAM_SUCCESS) &&
101 	    (pam_set_item (hdl,PAM_RHOST,tcp_clientaddr ()) == PAM_SUCCESS) &&
102 	    (pam_authenticate (hdl,NIL) == PAM_SUCCESS) &&
103 	    (pam_acct_mgmt (hdl,NIL) == PAM_SUCCESS) &&
104 	    (pam_setcred (hdl,PAM_ESTABLISH_CRED) == PAM_SUCCESS)) ?
105       getpwnam (name) : NIL) {
106 #if 0
107     /*
108      * Some people have reported that this causes a SEGV in strncpy() from
109      * pam_unix.so.1
110      */
111     /*
112      * This pam_open_session() call is inconsistant with how we handle other
113      * platforms, where we don't write [uw]tmp records.  However, unlike our
114      * code on other platforms, pam_acct_mgmt() will check those records for
115      * inactivity and deny the authentication.
116      */
117     pam_open_session (hdl,NIL);	/* make sure account doesn't go inactive */
118 #endif
119 				/* arm hook to delete credentials */
120     mail_parameters (NIL,SET_LOGOUTHOOK,(void *) checkpw_cleanup);
121     mail_parameters (NIL,SET_LOGOUTDATA,(void *) hdl);
122   }
123   else checkpw_cleanup (hdl);	/* clean up */
124   fs_give ((void **) &name);
125 				/* reset log facility in case PAM broke it */
126   if (myServerName) openlog (myServerName,LOG_PID,syslog_facility);
127   return pw;
128 }
129