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