]> andersk Git - openssh.git/blame - auth-pam.c
- (djm) Fix for configure on bash2 from Jim Knoble <jmknoble@jmknoble.cx>
[openssh.git] / auth-pam.c
CommitLineData
a5c9cd31 1/*
2 * Author: Damien Miller
3 * Copyright (c) 1999 Damien Miller <djm@mindrot.org>
4 * All rights reserved
5 * Created: Thursday December 30 1999
6 * PAM authentication and session management code.
7 */
8
9#include "includes.h"
10
11#ifdef USE_PAM
12#include "ssh.h"
13#include "xmalloc.h"
14#include "servconf.h"
15
16RCSID("$Id$");
17
5daf7064 18#define NEW_AUTHTOK_MSG \
19 "Warning: You password has expired, please change it now"
20
a5c9cd31 21/* Callbacks */
22static int pamconv(int num_msg, const struct pam_message **msg,
23 struct pam_response **resp, void *appdata_ptr);
24void pam_cleanup_proc(void *context);
5daf7064 25void pam_msg_cat(const char *msg);
a5c9cd31 26
27/* module-local variables */
28static struct pam_conv conv = {
29 pamconv,
30 NULL
31};
32static struct pam_handle_t *pamh = NULL;
33static const char *pampasswd = NULL;
5daf7064 34static char *pam_msg = NULL;
a5c9cd31 35
36/* PAM conversation function. This is really a kludge to get the password */
37/* into PAM and to pick up any messages generated by PAM into pamconv_msg */
38static int pamconv(int num_msg, const struct pam_message **msg,
39 struct pam_response **resp, void *appdata_ptr)
40{
41 struct pam_response *reply;
42 int count;
a5c9cd31 43
44 /* PAM will free this later */
45 reply = malloc(num_msg * sizeof(*reply));
46 if (reply == NULL)
47 return PAM_CONV_ERR;
48
49 for(count = 0; count < num_msg; count++) {
50 switch (msg[count]->msg_style) {
51 case PAM_PROMPT_ECHO_OFF:
52 if (pampasswd == NULL) {
53 free(reply);
54 return PAM_CONV_ERR;
55 }
56 reply[count].resp_retcode = PAM_SUCCESS;
57 reply[count].resp = xstrdup(pampasswd);
58 break;
a5c9cd31 59 case PAM_TEXT_INFO:
60 reply[count].resp_retcode = PAM_SUCCESS;
61 reply[count].resp = xstrdup("");
62
5daf7064 63 if (msg[count]->msg != NULL)
64 pam_msg_cat(msg[count]->msg);
a5c9cd31 65
a5c9cd31 66 break;
a5c9cd31 67 default:
68 free(reply);
69 return PAM_CONV_ERR;
70 }
71 }
72
73 *resp = reply;
74
75 return PAM_SUCCESS;
76}
77
78/* Called at exit to cleanly shutdown PAM */
79void pam_cleanup_proc(void *context)
80{
81 int pam_retval;
82
83 if (pamh != NULL)
84 {
85 pam_retval = pam_close_session((pam_handle_t *)pamh, 0);
86 if (pam_retval != PAM_SUCCESS) {
87 log("Cannot close PAM session: %.200s",
5daf7064 88 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
a5c9cd31 89 }
90
91 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED);
92 if (pam_retval != PAM_SUCCESS) {
93 log("Cannot delete credentials: %.200s",
5daf7064 94 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
a5c9cd31 95 }
96
97 pam_retval = pam_end((pam_handle_t *)pamh, pam_retval);
98 if (pam_retval != PAM_SUCCESS) {
99 log("Cannot release PAM authentication: %.200s",
5daf7064 100 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
a5c9cd31 101 }
102 }
103}
104
105/* Attempt password authentation using PAM */
106int auth_pam_password(struct passwd *pw, const char *password)
107{
108 extern ServerOptions options;
109 int pam_retval;
110
111 /* deny if no user. */
112 if (pw == NULL)
113 return 0;
114 if (pw->pw_uid == 0 && options.permit_root_login == 2)
115 return 0;
116 if (*password == '\0' && options.permit_empty_passwd == 0)
117 return 0;
118
119 pampasswd = password;
120
121 pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
122 if (pam_retval == PAM_SUCCESS) {
5daf7064 123 debug("PAM Password authentication accepted for user \"%.100s\"",
124 pw->pw_name);
a5c9cd31 125 return 1;
126 } else {
127 debug("PAM Password authentication for \"%.100s\" failed: %s",
128 pw->pw_name, PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
129 return 0;
130 }
131}
132
133/* Do account management using PAM */
134int do_pam_account(char *username, char *remote_user)
135{
136 int pam_retval;
5daf7064 137
a5c9cd31 138 debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname());
139 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST,
140 get_canonical_hostname());
141 if (pam_retval != PAM_SUCCESS) {
5daf7064 142 fatal("PAM set rhost failed: %.200s",
143 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
a5c9cd31 144 }
145
146 if (remote_user != NULL) {
147 debug("PAM setting ruser to \"%.200s\"", remote_user);
148 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user);
149 if (pam_retval != PAM_SUCCESS) {
5daf7064 150 fatal("PAM set ruser failed: %.200s",
151 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
a5c9cd31 152 }
153 }
154
155 pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0);
5daf7064 156 switch (pam_retval) {
157 case PAM_SUCCESS:
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);
a5c9cd31 167 }
168
169 return(1);
170}
171
172/* Do PAM-specific session initialisation */
fd094f49 173void do_pam_session(char *username, const char *ttyname)
a5c9cd31 174{
175 int pam_retval;
176
177 if (ttyname != NULL) {
178 debug("PAM setting tty to \"%.200s\"", ttyname);
179 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname);
5daf7064 180 if (pam_retval != PAM_SUCCESS) {
181 fatal("PAM set tty failed: %.200s",
182 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
183 }
a5c9cd31 184 }
185
186 pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
5daf7064 187 if (pam_retval != PAM_SUCCESS) {
188 fatal("PAM session setup failed: %.200s",
189 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
190 }
a5c9cd31 191}
192
193/* Set PAM credentials */
194void do_pam_setcred()
195{
196 int pam_retval;
197
198 debug("PAM establishing creds");
199 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED);
5daf7064 200 if (pam_retval != PAM_SUCCESS) {
201 fatal("PAM setcred failed: %.200s",
202 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
203 }
a5c9cd31 204}
205
206/* Cleanly shutdown PAM */
207void finish_pam(void)
208{
209 pam_cleanup_proc(NULL);
210 fatal_remove_cleanup(&pam_cleanup_proc, NULL);
211}
212
213/* Start PAM authentication for specified account */
214void start_pam(struct passwd *pw)
215{
216 int pam_retval;
217
218 debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
219
4e577b89 220 pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv,
221 (pam_handle_t**)&pamh);
a5c9cd31 222
5daf7064 223 if (pam_retval != PAM_SUCCESS) {
224 fatal("PAM initialisation failed: %.200s",
225 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
226 }
227
a5c9cd31 228 fatal_add_cleanup(&pam_cleanup_proc, NULL);
229}
230
231/* Return list of PAM enviornment strings */
232char **fetch_pam_environment(void)
233{
2b763e31 234#ifdef HAVE_PAM_GETENVLIST
a5c9cd31 235 return(pam_getenvlist((pam_handle_t *)pamh));
2b763e31 236#else /* HAVE_PAM_GETENVLIST */
237 return(NULL);
238#endif /* HAVE_PAM_GETENVLIST */
a5c9cd31 239}
240
241/* Print any messages that have been generated during authentication */
242/* or account checking to stderr */
243void print_pam_messages(void)
244{
5daf7064 245 if (pam_msg != NULL)
246 fprintf(stderr, pam_msg);
247}
248
249/* Append a message to the PAM message buffer */
250void 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';
a5c9cd31 269}
270
271#endif /* USE_PAM */
This page took 0.096367 seconds and 5 git commands to generate.