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