diff options
Diffstat (limited to 'auth-pam.c')
-rw-r--r-- | auth-pam.c | 113 |
1 files changed, 70 insertions, 43 deletions
diff --git a/auth-pam.c b/auth-pam.c index e3f4c4252..174d289f3 100644 --- a/auth-pam.c +++ b/auth-pam.c | |||
@@ -13,12 +13,16 @@ | |||
13 | #include "xmalloc.h" | 13 | #include "xmalloc.h" |
14 | #include "servconf.h" | 14 | #include "servconf.h" |
15 | 15 | ||
16 | RCSID("$Id: auth-pam.c,v 1.4 2000/04/29 14:47:29 damien Exp $"); | 16 | RCSID("$Id: auth-pam.c,v 1.5 2000/05/31 01:20:12 damien Exp $"); |
17 | |||
18 | #define NEW_AUTHTOK_MSG \ | ||
19 | "Warning: You password has expired, please change it now" | ||
17 | 20 | ||
18 | /* Callbacks */ | 21 | /* Callbacks */ |
19 | static int pamconv(int num_msg, const struct pam_message **msg, | 22 | static int pamconv(int num_msg, const struct pam_message **msg, |
20 | struct pam_response **resp, void *appdata_ptr); | 23 | struct pam_response **resp, void *appdata_ptr); |
21 | void pam_cleanup_proc(void *context); | 24 | void pam_cleanup_proc(void *context); |
25 | void pam_msg_cat(const char *msg); | ||
22 | 26 | ||
23 | /* module-local variables */ | 27 | /* module-local variables */ |
24 | static struct pam_conv conv = { | 28 | static struct pam_conv conv = { |
@@ -27,7 +31,7 @@ static struct pam_conv conv = { | |||
27 | }; | 31 | }; |
28 | static struct pam_handle_t *pamh = NULL; | 32 | static struct pam_handle_t *pamh = NULL; |
29 | static const char *pampasswd = NULL; | 33 | static const char *pampasswd = NULL; |
30 | static char *pamconv_msg = NULL; | 34 | static char *pam_msg = NULL; |
31 | 35 | ||
32 | /* PAM conversation function. This is really a kludge to get the password */ | 36 | /* PAM conversation function. This is really a kludge to get the password */ |
33 | /* into PAM and to pick up any messages generated by PAM into pamconv_msg */ | 37 | /* into PAM and to pick up any messages generated by PAM into pamconv_msg */ |
@@ -36,8 +40,6 @@ static int pamconv(int num_msg, const struct pam_message **msg, | |||
36 | { | 40 | { |
37 | struct pam_response *reply; | 41 | struct pam_response *reply; |
38 | int count; | 42 | int count; |
39 | size_t msg_len; | ||
40 | char *p; | ||
41 | 43 | ||
42 | /* PAM will free this later */ | 44 | /* PAM will free this later */ |
43 | reply = malloc(num_msg * sizeof(*reply)); | 45 | reply = malloc(num_msg * sizeof(*reply)); |
@@ -54,31 +56,14 @@ static int pamconv(int num_msg, const struct pam_message **msg, | |||
54 | reply[count].resp_retcode = PAM_SUCCESS; | 56 | reply[count].resp_retcode = PAM_SUCCESS; |
55 | reply[count].resp = xstrdup(pampasswd); | 57 | reply[count].resp = xstrdup(pampasswd); |
56 | break; | 58 | break; |
57 | |||
58 | case PAM_TEXT_INFO: | 59 | case PAM_TEXT_INFO: |
59 | reply[count].resp_retcode = PAM_SUCCESS; | 60 | reply[count].resp_retcode = PAM_SUCCESS; |
60 | reply[count].resp = xstrdup(""); | 61 | reply[count].resp = xstrdup(""); |
61 | 62 | ||
62 | if (msg[count]->msg == NULL) | 63 | if (msg[count]->msg != NULL) |
63 | break; | 64 | pam_msg_cat(msg[count]->msg); |
64 | 65 | ||
65 | debug("Adding PAM message: %s", msg[count]->msg); | ||
66 | |||
67 | msg_len = strlen(msg[count]->msg); | ||
68 | if (pamconv_msg) { | ||
69 | size_t n = strlen(pamconv_msg); | ||
70 | pamconv_msg = xrealloc(pamconv_msg, n + msg_len + 2); | ||
71 | p = pamconv_msg + n; | ||
72 | } else { | ||
73 | pamconv_msg = p = xmalloc(msg_len + 2); | ||
74 | } | ||
75 | memcpy(p, msg[count]->msg, msg_len); | ||
76 | p[msg_len] = '\n'; | ||
77 | p[msg_len + 1] = '\0'; | ||
78 | break; | 66 | break; |
79 | |||
80 | case PAM_PROMPT_ECHO_ON: | ||
81 | case PAM_ERROR_MSG: | ||
82 | default: | 67 | default: |
83 | free(reply); | 68 | free(reply); |
84 | return PAM_CONV_ERR; | 69 | return PAM_CONV_ERR; |
@@ -100,19 +85,19 @@ void pam_cleanup_proc(void *context) | |||
100 | pam_retval = pam_close_session((pam_handle_t *)pamh, 0); | 85 | pam_retval = pam_close_session((pam_handle_t *)pamh, 0); |
101 | if (pam_retval != PAM_SUCCESS) { | 86 | if (pam_retval != PAM_SUCCESS) { |
102 | log("Cannot close PAM session: %.200s", | 87 | log("Cannot close PAM session: %.200s", |
103 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 88 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); |
104 | } | 89 | } |
105 | 90 | ||
106 | pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED); | 91 | pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED); |
107 | if (pam_retval != PAM_SUCCESS) { | 92 | if (pam_retval != PAM_SUCCESS) { |
108 | log("Cannot delete credentials: %.200s", | 93 | log("Cannot delete credentials: %.200s", |
109 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 94 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); |
110 | } | 95 | } |
111 | 96 | ||
112 | pam_retval = pam_end((pam_handle_t *)pamh, pam_retval); | 97 | pam_retval = pam_end((pam_handle_t *)pamh, pam_retval); |
113 | if (pam_retval != PAM_SUCCESS) { | 98 | if (pam_retval != PAM_SUCCESS) { |
114 | log("Cannot release PAM authentication: %.200s", | 99 | log("Cannot release PAM authentication: %.200s", |
115 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 100 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); |
116 | } | 101 | } |
117 | } | 102 | } |
118 | } | 103 | } |
@@ -135,7 +120,8 @@ int auth_pam_password(struct passwd *pw, const char *password) | |||
135 | 120 | ||
136 | pam_retval = pam_authenticate((pam_handle_t *)pamh, 0); | 121 | pam_retval = pam_authenticate((pam_handle_t *)pamh, 0); |
137 | if (pam_retval == PAM_SUCCESS) { | 122 | if (pam_retval == PAM_SUCCESS) { |
138 | debug("PAM Password authentication accepted for user \"%.100s\"", pw->pw_name); | 123 | debug("PAM Password authentication accepted for user \"%.100s\"", |
124 | pw->pw_name); | ||
139 | return 1; | 125 | return 1; |
140 | } else { | 126 | } else { |
141 | debug("PAM Password authentication for \"%.100s\" failed: %s", | 127 | debug("PAM Password authentication for \"%.100s\" failed: %s", |
@@ -148,26 +134,36 @@ int auth_pam_password(struct passwd *pw, const char *password) | |||
148 | int do_pam_account(char *username, char *remote_user) | 134 | int do_pam_account(char *username, char *remote_user) |
149 | { | 135 | { |
150 | int pam_retval; | 136 | int pam_retval; |
151 | 137 | ||
152 | debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname()); | 138 | debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname()); |
153 | pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST, | 139 | pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST, |
154 | get_canonical_hostname()); | 140 | get_canonical_hostname()); |
155 | if (pam_retval != PAM_SUCCESS) { | 141 | if (pam_retval != PAM_SUCCESS) { |
156 | fatal("PAM set rhost failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 142 | fatal("PAM set rhost failed: %.200s", |
143 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | ||
157 | } | 144 | } |
158 | 145 | ||
159 | if (remote_user != NULL) { | 146 | if (remote_user != NULL) { |
160 | debug("PAM setting ruser to \"%.200s\"", remote_user); | 147 | debug("PAM setting ruser to \"%.200s\"", remote_user); |
161 | pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user); | 148 | pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user); |
162 | if (pam_retval != PAM_SUCCESS) { | 149 | if (pam_retval != PAM_SUCCESS) { |
163 | fatal("PAM set ruser failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 150 | fatal("PAM set ruser failed: %.200s", |
151 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | ||
164 | } | 152 | } |
165 | } | 153 | } |
166 | 154 | ||
167 | pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0); | 155 | pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0); |
168 | if (pam_retval != PAM_SUCCESS) { | 156 | switch (pam_retval) { |
169 | log("PAM rejected by account configuration: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 157 | case PAM_SUCCESS: |
170 | return(0); | 158 | /* This is what we want */ |
159 | break; | ||
160 | case PAM_NEW_AUTHTOK_REQD: | ||
161 | pam_msg_cat(NEW_AUTHTOK_MSG); | ||
162 | break; | ||
163 | default: | ||
164 | log("PAM rejected by account configuration: %.200s", | ||
165 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | ||
166 | return(0); | ||
171 | } | 167 | } |
172 | 168 | ||
173 | return(1); | 169 | return(1); |
@@ -181,13 +177,17 @@ void do_pam_session(char *username, const char *ttyname) | |||
181 | if (ttyname != NULL) { | 177 | if (ttyname != NULL) { |
182 | debug("PAM setting tty to \"%.200s\"", ttyname); | 178 | debug("PAM setting tty to \"%.200s\"", ttyname); |
183 | pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname); | 179 | pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname); |
184 | if (pam_retval != PAM_SUCCESS) | 180 | if (pam_retval != PAM_SUCCESS) { |
185 | fatal("PAM set tty failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 181 | fatal("PAM set tty failed: %.200s", |
182 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | ||
183 | } | ||
186 | } | 184 | } |
187 | 185 | ||
188 | pam_retval = pam_open_session((pam_handle_t *)pamh, 0); | 186 | pam_retval = pam_open_session((pam_handle_t *)pamh, 0); |
189 | if (pam_retval != PAM_SUCCESS) | 187 | if (pam_retval != PAM_SUCCESS) { |
190 | fatal("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 188 | fatal("PAM session setup failed: %.200s", |
189 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | ||
190 | } | ||
191 | } | 191 | } |
192 | 192 | ||
193 | /* Set PAM credentials */ | 193 | /* Set PAM credentials */ |
@@ -197,8 +197,10 @@ void do_pam_setcred() | |||
197 | 197 | ||
198 | debug("PAM establishing creds"); | 198 | debug("PAM establishing creds"); |
199 | pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED); | 199 | pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED); |
200 | if (pam_retval != PAM_SUCCESS) | 200 | if (pam_retval != PAM_SUCCESS) { |
201 | fatal("PAM setcred failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | 201 | fatal("PAM setcred failed: %.200s", |
202 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | ||
203 | } | ||
202 | } | 204 | } |
203 | 205 | ||
204 | /* Cleanly shutdown PAM */ | 206 | /* Cleanly shutdown PAM */ |
@@ -217,9 +219,12 @@ void start_pam(struct passwd *pw) | |||
217 | 219 | ||
218 | pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv, | 220 | pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv, |
219 | (pam_handle_t**)&pamh); | 221 | (pam_handle_t**)&pamh); |
220 | if (pam_retval != PAM_SUCCESS) | ||
221 | fatal("PAM initialisation failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | ||
222 | 222 | ||
223 | if (pam_retval != PAM_SUCCESS) { | ||
224 | fatal("PAM initialisation failed: %.200s", | ||
225 | PAM_STRERROR((pam_handle_t *)pamh, pam_retval)); | ||
226 | } | ||
227 | |||
223 | fatal_add_cleanup(&pam_cleanup_proc, NULL); | 228 | fatal_add_cleanup(&pam_cleanup_proc, NULL); |
224 | } | 229 | } |
225 | 230 | ||
@@ -237,8 +242,30 @@ char **fetch_pam_environment(void) | |||
237 | /* or account checking to stderr */ | 242 | /* or account checking to stderr */ |
238 | void print_pam_messages(void) | 243 | void print_pam_messages(void) |
239 | { | 244 | { |
240 | if (pamconv_msg != NULL) | 245 | if (pam_msg != NULL) |
241 | fprintf(stderr, pamconv_msg); | 246 | fprintf(stderr, pam_msg); |
247 | } | ||
248 | |||
249 | /* Append a message to the PAM message buffer */ | ||
250 | void pam_msg_cat(const char *msg) | ||
251 | { | ||
252 | char *p; | ||
253 | size_t new_msg_len; | ||
254 | size_t pam_msg_len; | ||
255 | |||
256 | new_msg_len = strlen(msg); | ||
257 | |||
258 | if (pam_msg) { | ||
259 | pam_msg_len = strlen(pam_msg); | ||
260 | pam_msg = xrealloc(pam_msg, new_msg_len + pam_msg_len + 2); | ||
261 | p = pam_msg + pam_msg_len; | ||
262 | } else { | ||
263 | pam_msg = p = xmalloc(new_msg_len + 2); | ||
264 | } | ||
265 | |||
266 | memcpy(p, msg, new_msg_len); | ||
267 | p[new_msg_len] = '\n'; | ||
268 | p[new_msg_len + 1] = '\0'; | ||
242 | } | 269 | } |
243 | 270 | ||
244 | #endif /* USE_PAM */ | 271 | #endif /* USE_PAM */ |