summaryrefslogtreecommitdiff
path: root/sshd.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>1999-12-30 15:08:44 +1100
committerDamien Miller <djm@mindrot.org>1999-12-30 15:08:44 +1100
commite72b7af17e519eb1d433b5119ef551f2584f8be6 (patch)
tree7ebbc8fefdfcfd9669dbe05718b142996df69a85 /sshd.c
parentece22a8312357e1f34916659d77fa7dd8d15ae32 (diff)
- Removed most of the pam code into its own file auth-pam.[ch]. This
cleaned up sshd.c up significantly. - Several other cleanups
Diffstat (limited to 'sshd.c')
-rw-r--r--sshd.c321
1 files changed, 59 insertions, 262 deletions
diff --git a/sshd.c b/sshd.c
index 73a33b785..0cf664087 100644
--- a/sshd.c
+++ b/sshd.c
@@ -11,15 +11,7 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$Id: sshd.c,v 1.48 1999/12/28 23:25:41 damien Exp $"); 14RCSID("$Id: sshd.c,v 1.49 1999/12/30 04:08:44 damien Exp $");
15
16#ifdef HAVE_POLL_H
17# include <poll.h>
18#else /* HAVE_POLL_H */
19# ifdef HAVE_SYS_POLL_H
20# include <sys/poll.h>
21# endif /* HAVE_SYS_POLL_H */
22#endif /* HAVE_POLL_H */
23 15
24#include "xmalloc.h" 16#include "xmalloc.h"
25#include "rsa.h" 17#include "rsa.h"
@@ -143,183 +135,6 @@ void do_child(const char *command, struct passwd * pw, const char *term,
143 const char *display, const char *auth_proto, 135 const char *display, const char *auth_proto,
144 const char *auth_data, const char *ttyname); 136 const char *auth_data, const char *ttyname);
145 137
146#ifdef USE_PAM
147static int pamconv(int num_msg, const struct pam_message **msg,
148 struct pam_response **resp, void *appdata_ptr);
149int do_pam_auth(const char *user, const char *password);
150void do_pam_account(char *username, char *remote_user);
151void do_pam_session(char *username, char *ttyname);
152void do_pam_setcred();
153void pam_cleanup_proc(void *context);
154
155static struct pam_conv conv = {
156 pamconv,
157 NULL
158};
159struct pam_handle_t *pamh = NULL;
160const char *pampasswd = NULL;
161char *pamconv_msg = NULL;
162
163static int pamconv(int num_msg, const struct pam_message **msg,
164 struct pam_response **resp, void *appdata_ptr)
165{
166 struct pam_response *reply;
167 int count;
168 size_t msg_len;
169 char *p;
170
171 /* PAM will free this later */
172 reply = malloc(num_msg * sizeof(*reply));
173 if (reply == NULL)
174 return PAM_CONV_ERR;
175
176 for(count = 0; count < num_msg; count++) {
177 switch (msg[count]->msg_style) {
178 case PAM_PROMPT_ECHO_OFF:
179 if (pampasswd == NULL) {
180 free(reply);
181 return PAM_CONV_ERR;
182 }
183 reply[count].resp_retcode = PAM_SUCCESS;
184 reply[count].resp = xstrdup(pampasswd);
185 break;
186
187 case PAM_TEXT_INFO:
188 reply[count].resp_retcode = PAM_SUCCESS;
189 reply[count].resp = xstrdup("");
190
191 if (msg[count]->msg == NULL)
192 break;
193
194 debug("Adding PAM message: %s", msg[count]->msg);
195
196 msg_len = strlen(msg[count]->msg);
197 if (pamconv_msg) {
198 size_t n = strlen(pamconv_msg);
199 pamconv_msg = xrealloc(pamconv_msg, n + msg_len + 2);
200 p = pamconv_msg + n;
201 } else {
202 pamconv_msg = p = xmalloc(msg_len + 2);
203 }
204 memcpy(p, msg[count]->msg, msg_len);
205 p[msg_len] = '\n';
206 p[msg_len + 1] = '\0';
207 break;
208
209 case PAM_PROMPT_ECHO_ON:
210 case PAM_ERROR_MSG:
211 default:
212 free(reply);
213 return PAM_CONV_ERR;
214 }
215 }
216
217 *resp = reply;
218
219 return PAM_SUCCESS;
220}
221
222void pam_cleanup_proc(void *context)
223{
224 int pam_retval;
225
226 if (pamh != NULL)
227 {
228 pam_retval = pam_close_session((pam_handle_t *)pamh, 0);
229 if (pam_retval != PAM_SUCCESS) {
230 log("Cannot close PAM session: %.200s",
231 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
232 }
233
234 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED);
235 if (pam_retval != PAM_SUCCESS) {
236 log("Cannot delete credentials: %.200s",
237 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
238 }
239
240 pam_retval = pam_end((pam_handle_t *)pamh, pam_retval);
241 if (pam_retval != PAM_SUCCESS) {
242 log("Cannot release PAM authentication: %.200s",
243 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
244 }
245 }
246}
247
248int do_pam_auth(const char *user, const char *password)
249{
250 int pam_retval;
251
252 if ((options.permit_empty_passwd == 0) && (password[0] == '\0'))
253 return 0;
254
255 pampasswd = password;
256
257 pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
258 if (pam_retval == PAM_SUCCESS) {
259 debug("PAM Password authentication accepted for user \"%.100s\"", user);
260 return 1;
261 } else {
262 debug("PAM Password authentication for \"%.100s\" failed: %s",
263 user, PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
264 return 0;
265 }
266}
267
268void do_pam_account(char *username, char *remote_user)
269{
270 int pam_retval;
271
272 debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname());
273 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST,
274 get_canonical_hostname());
275 if (pam_retval != PAM_SUCCESS) {
276 log("PAM set rhost failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
277 do_fake_authloop(username);
278 }
279
280 if (remote_user != NULL) {
281 debug("PAM setting ruser to \"%.200s\"", remote_user);
282 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user);
283 if (pam_retval != PAM_SUCCESS) {
284 log("PAM set ruser failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
285 do_fake_authloop(username);
286 }
287 }
288
289 pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0);
290 if (pam_retval != PAM_SUCCESS) {
291 log("PAM rejected by account configuration: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
292 do_fake_authloop(username);
293 }
294}
295
296void do_pam_session(char *username, char *ttyname)
297{
298 int pam_retval;
299
300 if (ttyname != NULL) {
301 debug("PAM setting tty to \"%.200s\"", ttyname);
302 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname);
303 if (pam_retval != PAM_SUCCESS)
304 fatal("PAM set tty failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
305 }
306
307 pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
308 if (pam_retval != PAM_SUCCESS)
309 fatal("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
310}
311
312void do_pam_setcred()
313{
314 int pam_retval;
315
316 debug("PAM establishing creds");
317 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED);
318 if (pam_retval != PAM_SUCCESS)
319 fatal("PAM setcred failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
320}
321#endif /* USE_PAM */
322
323/* 138/*
324 * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; 139 * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP;
325 * the effect is to reread the configuration file (and to regenerate 140 * the effect is to reread the configuration file (and to regenerate
@@ -973,20 +788,7 @@ main(int ac, char **av)
973 verbose("Closing connection to %.100s", remote_ip); 788 verbose("Closing connection to %.100s", remote_ip);
974 789
975#ifdef USE_PAM 790#ifdef USE_PAM
976 { 791 finish_pam();
977 int retval;
978
979 if (pamh != NULL) {
980 debug("Closing PAM session.");
981 retval = pam_close_session((pam_handle_t *)pamh, 0);
982
983 debug("Terminating PAM library.");
984 if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
985 log("Cannot release PAM authentication.");
986
987 fatal_remove_cleanup(&pam_cleanup_proc, NULL);
988 }
989 }
990#endif /* USE_PAM */ 792#endif /* USE_PAM */
991 793
992 packet_close(); 794 packet_close();
@@ -1306,17 +1108,7 @@ do_authentication(char *user)
1306 pw = &pwcopy; 1108 pw = &pwcopy;
1307 1109
1308#ifdef USE_PAM 1110#ifdef USE_PAM
1309 { 1111 start_pam(pw);
1310 int pam_retval;
1311
1312 debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
1313
1314 pam_retval = pam_start("sshd", pw->pw_name, &conv, (pam_handle_t**)&pamh);
1315 if (pam_retval != PAM_SUCCESS)
1316 fatal("PAM initialisation failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
1317
1318 fatal_add_cleanup(&pam_cleanup_proc, NULL);
1319 }
1320#endif 1112#endif
1321 1113
1322 /* 1114 /*
@@ -1334,7 +1126,7 @@ do_authentication(char *user)
1334 (!options.kerberos_authentication || options.kerberos_or_local_passwd) && 1126 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
1335#endif /* KRB4 */ 1127#endif /* KRB4 */
1336#ifdef USE_PAM 1128#ifdef USE_PAM
1337 do_pam_auth(pw->pw_name, "")) { 1129 auth_pam_password(pw, "")) {
1338#else /* USE_PAM */ 1130#else /* USE_PAM */
1339 auth_password(pw, "")) { 1131 auth_password(pw, "")) {
1340#endif /* USE_PAM */ 1132#endif /* USE_PAM */
@@ -1477,9 +1269,6 @@ do_authloop(struct passwd * pw)
1477 authenticated = auth_rhosts(pw, client_user); 1269 authenticated = auth_rhosts(pw, client_user);
1478 1270
1479 snprintf(user, sizeof user, " ruser %s", client_user); 1271 snprintf(user, sizeof user, " ruser %s", client_user);
1480#ifndef USE_PAM
1481 xfree(client_user);
1482#endif /* USE_PAM */
1483 break; 1272 break;
1484 1273
1485 case SSH_CMSG_AUTH_RHOSTS_RSA: 1274 case SSH_CMSG_AUTH_RHOSTS_RSA:
@@ -1512,9 +1301,6 @@ do_authloop(struct passwd * pw)
1512 BN_clear_free(client_host_key_n); 1301 BN_clear_free(client_host_key_n);
1513 1302
1514 snprintf(user, sizeof user, " ruser %s", client_user); 1303 snprintf(user, sizeof user, " ruser %s", client_user);
1515#ifndef USE_PAM
1516 xfree(client_user);
1517#endif /* USE_PAM */
1518 break; 1304 break;
1519 1305
1520 case SSH_CMSG_AUTH_RSA: 1306 case SSH_CMSG_AUTH_RSA:
@@ -1545,7 +1331,7 @@ do_authloop(struct passwd * pw)
1545 1331
1546#ifdef USE_PAM 1332#ifdef USE_PAM
1547 /* Do PAM auth with password */ 1333 /* Do PAM auth with password */
1548 authenticated = do_pam_auth(pw->pw_name, password); 1334 authenticated = auth_pam_password(pw, password);
1549#else /* USE_PAM */ 1335#else /* USE_PAM */
1550 /* Try authentication with the password. */ 1336 /* Try authentication with the password. */
1551 authenticated = auth_password(pw, password); 1337 authenticated = auth_password(pw, password);
@@ -1615,29 +1401,24 @@ do_authloop(struct passwd * pw)
1615 get_remote_port(), 1401 get_remote_port(),
1616 user); 1402 user);
1617 1403
1618#ifndef USE_PAM
1619 if (authenticated)
1620 return;
1621
1622 if (attempt > AUTH_FAIL_MAX)
1623 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
1624#else /* USE_PAM */
1625 if (authenticated) { 1404 if (authenticated) {
1626 do_pam_account(pw->pw_name, client_user); 1405#ifdef USE_PAM
1627 1406 if (!do_pam_account(pw->pw_name, client_user))
1628 if (client_user != NULL) 1407 {
1629 xfree(client_user); 1408 if (client_user != NULL)
1409 xfree(client_user);
1630 1410
1411 do_fake_authloop(pw->pw_name);
1412 }
1413#endif /* USE_PAM */
1631 return; 1414 return;
1632 } 1415 }
1633 1416
1634 if (attempt > AUTH_FAIL_MAX) { 1417 if (client_user != NULL)
1635 if (client_user != NULL) 1418 xfree(client_user);
1636 xfree(client_user);
1637 1419
1420 if (attempt > AUTH_FAIL_MAX)
1638 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name); 1421 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
1639 }
1640#endif /* USE_PAM */
1641 1422
1642 /* Send a message indicating that the authentication attempt failed. */ 1423 /* Send a message indicating that the authentication attempt failed. */
1643 packet_start(SSH_SMSG_FAILURE); 1424 packet_start(SSH_SMSG_FAILURE);
@@ -1672,8 +1453,10 @@ do_fake_authloop(char *user)
1672 for (attempt = 1;; attempt++) { 1453 for (attempt = 1;; attempt++) {
1673 /* Read a packet. This will not return if the client disconnects. */ 1454 /* Read a packet. This will not return if the client disconnects. */
1674 int plen; 1455 int plen;
1456#ifndef SKEY
1457 (void)packet_read(&plen);
1458#else /* SKEY */
1675 int type = packet_read(&plen); 1459 int type = packet_read(&plen);
1676#ifdef SKEY
1677 int dlen; 1460 int dlen;
1678 char *password, *skeyinfo; 1461 char *password, *skeyinfo;
1679 /* Try to send a fake s/key challenge. */ 1462 /* Try to send a fake s/key challenge. */
@@ -1845,7 +1628,7 @@ do_authenticated(struct passwd * pw)
1845 1628
1846#ifdef USE_PAM 1629#ifdef USE_PAM
1847 /* do the pam_open_session since we have the pty */ 1630 /* do the pam_open_session since we have the pty */
1848 do_pam_session(pw->pw_name,ttyname); 1631 do_pam_session(pw->pw_name, ttyname);
1849#endif /* USE_PAM */ 1632#endif /* USE_PAM */
1850 1633
1851 break; 1634 break;
@@ -1925,7 +1708,7 @@ do_authenticated(struct passwd * pw)
1925 1708
1926#ifdef USE_PAM 1709#ifdef USE_PAM
1927 do_pam_setcred(); 1710 do_pam_setcred();
1928#endif 1711#endif /* USE_PAM */
1929 if (forced_command != NULL) 1712 if (forced_command != NULL)
1930 goto do_forced_command; 1713 goto do_forced_command;
1931 debug("Forking shell."); 1714 debug("Forking shell.");
@@ -1943,7 +1726,7 @@ do_authenticated(struct passwd * pw)
1943 1726
1944#ifdef USE_PAM 1727#ifdef USE_PAM
1945 do_pam_setcred(); 1728 do_pam_setcred();
1946#endif 1729#endif /* USE_PAM */
1947 if (forced_command != NULL) 1730 if (forced_command != NULL)
1948 goto do_forced_command; 1731 goto do_forced_command;
1949 /* Get command from the packet. */ 1732 /* Get command from the packet. */
@@ -2221,10 +2004,9 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
2221 quiet_login = stat(line, &st) >= 0; 2004 quiet_login = stat(line, &st) >= 0;
2222 2005
2223#ifdef USE_PAM 2006#ifdef USE_PAM
2224 /* output the results of the pamconv() */ 2007 if (!quiet_login)
2225 if (!quiet_login && pamconv_msg != NULL) 2008 print_pam_messages();
2226 fprintf(stderr, pamconv_msg); 2009#endif /* USE_PAM */
2227#endif
2228 2010
2229 /* 2011 /*
2230 * If the user has logged in before, display the time of last 2012 * If the user has logged in before, display the time of last
@@ -2389,6 +2171,39 @@ read_environment_file(char ***env, unsigned int *envsize,
2389 fclose(f); 2171 fclose(f);
2390} 2172}
2391 2173
2174#ifdef USE_PAM
2175/*
2176 * Sets any environment variables which have been specified by PAM
2177 */
2178void do_pam_environment(char ***env, int *envsize)
2179{
2180 char *equals, var_name[512], var_val[512];
2181 char **pam_env;
2182 int i;
2183
2184 if ((pam_env = fetch_pam_environment()) == NULL)
2185 return;
2186
2187 for(i = 0; pam_env[i] != NULL; i++) {
2188 if ((equals = strstr(pam_env[i], "=")) == NULL)
2189 continue;
2190
2191 if (strlen(pam_env[i]) < (sizeof(var_name) - 1))
2192 {
2193 memset(var_name, '\0', sizeof(var_name));
2194 memset(var_val, '\0', sizeof(var_val));
2195
2196 strncpy(var_name, pam_env[i], equals - pam_env[i]);
2197 strcpy(var_val, equals + 1);
2198
2199 debug("PAM environment: %s=%s", var_name, var_val);
2200
2201 child_set_env(env, envsize, var_name, var_val);
2202 }
2203 }
2204}
2205#endif /* USE_PAM */
2206
2392/* 2207/*
2393 * Performs common processing for the child, such as setting up the 2208 * Performs common processing for the child, such as setting up the
2394 * environment, closing extra file descriptors, setting the user and group 2209 * environment, closing extra file descriptors, setting the user and group
@@ -2421,11 +2236,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
2421 } 2236 }
2422#endif /* USE_PAM */ 2237#endif /* USE_PAM */
2423 2238
2424#ifdef HAVE_SETLOGIN
2425 /* Set login name in the kernel. */ 2239 /* Set login name in the kernel. */
2426 if (setlogin(pw->pw_name) < 0) 2240 if (setlogin(pw->pw_name) < 0)
2427 error("setlogin failed: %s", strerror(errno)); 2241 error("setlogin failed: %s", strerror(errno));
2428#endif /* HAVE_SETLOGIN */
2429 2242
2430 /* Set uid, gid, and groups. */ 2243 /* Set uid, gid, and groups. */
2431 /* Login(1) does this as well, and it needs uid 0 for the "-h" 2244 /* Login(1) does this as well, and it needs uid 0 for the "-h"
@@ -2526,23 +2339,7 @@ do_child(const char *command, struct passwd * pw, const char *term,
2526 2339
2527#ifdef USE_PAM 2340#ifdef USE_PAM
2528 /* Pull in any environment variables that may have been set by PAM. */ 2341 /* Pull in any environment variables that may have been set by PAM. */
2529 { 2342 do_pam_environment(&env, &envsize);
2530 char *equals, var_name[512], var_val[512];
2531 char **pam_env = pam_getenvlist((pam_handle_t *)pamh);
2532 int i;
2533 for(i = 0; pam_env && pam_env[i]; i++) {
2534 equals = strstr(pam_env[i], "=");
2535 if ((strlen(pam_env[i]) < (sizeof(var_name) - 1)) && (equals != NULL))
2536 {
2537 debug("PAM environment: %s=%s", var_name, var_val);
2538 memset(var_name, '\0', sizeof(var_name));
2539 memset(var_val, '\0', sizeof(var_val));
2540 strncpy(var_name, pam_env[i], equals - pam_env[i]);
2541 strcpy(var_val, equals + 1);
2542 child_set_env(&env, &envsize, var_name, var_val);
2543 }
2544 }
2545 }
2546#endif /* USE_PAM */ 2343#endif /* USE_PAM */
2547 2344
2548 if (xauthfile) 2345 if (xauthfile)