]> andersk Git - openssh.git/blob - auth-pam.c
- Cleanup of auth.c, login.c and fake-*
[openssh.git] / auth-pam.c
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
16 RCSID("$Id$");
17
18 #define NEW_AUTHTOK_MSG \
19         "Warning: You password has expired, please change it now"
20
21 /* Callbacks */
22 static int pamconv(int num_msg, const struct pam_message **msg,
23           struct pam_response **resp, void *appdata_ptr);
24 void pam_cleanup_proc(void *context);
25 void pam_msg_cat(const char *msg);
26
27 /* module-local variables */
28 static struct pam_conv conv = {
29         pamconv,
30         NULL
31 };
32 static struct pam_handle_t *pamh = NULL;
33 static const char *pampasswd = NULL;
34 static char *pam_msg = NULL;
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 */
38 static 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;
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;
59                         case PAM_TEXT_INFO:
60                                 reply[count].resp_retcode = PAM_SUCCESS;
61                                 reply[count].resp = xstrdup("");
62
63                                 if (msg[count]->msg != NULL)
64                                         pam_msg_cat(msg[count]->msg);
65
66                                 break;
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 */
79 void 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", 
88                                 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
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", 
94                                 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
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", 
100                                 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
101                 }
102         }
103 }
104
105 /* Attempt password authentation using PAM */
106 int 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) {
123                 debug("PAM Password authentication accepted for user \"%.100s\"", 
124                         pw->pw_name);
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 */
134 int do_pam_account(char *username, char *remote_user)
135 {
136         int pam_retval;
137         
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) {
142                 fatal("PAM set rhost failed: %.200s", 
143                         PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
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) {
150                         fatal("PAM set ruser failed: %.200s", 
151                                 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
152                 }
153         }
154
155         pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0);
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);
167         }
168         
169         return(1);
170 }
171
172 /* Do PAM-specific session initialisation */
173 void do_pam_session(char *username, const char *ttyname)
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);
180                 if (pam_retval != PAM_SUCCESS) {
181                         fatal("PAM set tty failed: %.200s", 
182                                 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
183                 }
184         }
185
186         pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
187         if (pam_retval != PAM_SUCCESS) {
188                 fatal("PAM session setup failed: %.200s", 
189                         PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
190         }
191 }
192
193 /* Set PAM credentials */ 
194 void 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);
200         if (pam_retval != PAM_SUCCESS) {
201                 fatal("PAM setcred failed: %.200s", 
202                         PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
203         }
204 }
205
206 /* Cleanly shutdown PAM */
207 void 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 */
214 void start_pam(struct passwd *pw)
215 {
216         int pam_retval;
217
218         debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
219
220         pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv, 
221                 (pam_handle_t**)&pamh);
222
223         if (pam_retval != PAM_SUCCESS) {
224                 fatal("PAM initialisation failed: %.200s", 
225                         PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
226         }
227         
228         fatal_add_cleanup(&pam_cleanup_proc, NULL);
229 }
230
231 /* Return list of PAM enviornment strings */
232 char **fetch_pam_environment(void)
233 {
234 #ifdef HAVE_PAM_GETENVLIST
235         return(pam_getenvlist((pam_handle_t *)pamh));
236 #else /* HAVE_PAM_GETENVLIST */
237         return(NULL);
238 #endif /* HAVE_PAM_GETENVLIST */
239 }
240
241 /* Print any messages that have been generated during authentication */
242 /* or account checking to stderr */
243 void print_pam_messages(void)
244 {
245         if (pam_msg != NULL)
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';
269 }
270
271 #endif /* USE_PAM */
This page took 0.057625 seconds and 5 git commands to generate.