summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>1999-10-28 13:20:30 +1000
committerDamien Miller <djm@mindrot.org>1999-10-28 13:20:30 +1000
commit3d112efc672b877c74893229d3fd30f99489b9ff (patch)
tree7542e5627242ff533087a4fe103c2690dd97782f
parent332e67fde27c4017d2df8dafe05a55be3c7597cd (diff)
Big PAM cleanup
Added header for arc4random to mktemp.c Fixed return type of arc4random
-rw-r--r--helper.c6
-rw-r--r--helper.h2
-rw-r--r--mktemp.c2
-rw-r--r--sshd.c195
4 files changed, 104 insertions, 101 deletions
diff --git a/helper.c b/helper.c
index 3b0402ecf..c9aa51e4f 100644
--- a/helper.c
+++ b/helper.c
@@ -57,14 +57,14 @@ void setproctitle(const char *fmt, ...)
57 /* FIXME */ 57 /* FIXME */
58} 58}
59 59
60unsigned char arc4random(void) 60unsigned int arc4random(void)
61{ 61{
62 unsigned char r; 62 unsigned int r;
63 63
64 if (rc4 == NULL) 64 if (rc4 == NULL)
65 arc4random_stir(); 65 arc4random_stir();
66 66
67 rc4_getbytes(rc4, &r, 1); 67 rc4_getbytes(rc4, (unsigned char *)&r, sizeof(r));
68 68
69 return(r); 69 return(r);
70} 70}
diff --git a/helper.h b/helper.h
index 2f09daa8e..309156a2c 100644
--- a/helper.h
+++ b/helper.h
@@ -36,7 +36,7 @@
36#ifndef _HELPER_H 36#ifndef _HELPER_H
37#define _HELPER_H 37#define _HELPER_H
38 38
39unsigned char arc4random(void); 39unsigned int arc4random(void);
40void arc4random_stir(void); 40void arc4random_stir(void);
41void setproctitle(const char *fmt, ...); 41void setproctitle(const char *fmt, ...);
42 42
diff --git a/mktemp.c b/mktemp.c
index 919c53178..69dc4dc6f 100644
--- a/mktemp.c
+++ b/mktemp.c
@@ -47,6 +47,8 @@ static char rcsid[] = "$OpenBSD: mktemp.c,v 1.13 1998/06/30 23:03:13 deraadt Exp
47#include <ctype.h> 47#include <ctype.h>
48#include <unistd.h> 48#include <unistd.h>
49 49
50#include "helper.h"
51
50static int _gettemp __P((char *, int *, int, int)); 52static int _gettemp __P((char *, int *, int, int));
51 53
52int 54int
diff --git a/sshd.c b/sshd.c
index 08fb30e3f..b2cb5a320 100644
--- a/sshd.c
+++ b/sshd.c
@@ -18,7 +18,7 @@ agent connections.
18*/ 18*/
19 19
20#include "includes.h" 20#include "includes.h"
21RCSID("$Id: sshd.c,v 1.2 1999/10/27 13:42:05 damien Exp $"); 21RCSID("$Id: sshd.c,v 1.3 1999/10/28 03:20:30 damien Exp $");
22 22
23#include "xmalloc.h" 23#include "xmalloc.h"
24#include "rsa.h" 24#include "rsa.h"
@@ -117,6 +117,7 @@ RSA *public_key;
117/* Prototypes for various functions defined later in this file. */ 117/* Prototypes for various functions defined later in this file. */
118void do_connection(int privileged_port); 118void do_connection(int privileged_port);
119void do_authentication(char *user, int privileged_port); 119void do_authentication(char *user, int privileged_port);
120void eat_packets_and_disconnect(const char *user);
120void do_authenticated(struct passwd *pw); 121void do_authenticated(struct passwd *pw);
121void do_exec_pty(const char *command, int ptyfd, int ttyfd, 122void do_exec_pty(const char *command, int ptyfd, int ttyfd,
122 const char *ttyname, struct passwd *pw, const char *term, 123 const char *ttyname, struct passwd *pw, const char *term,
@@ -131,7 +132,7 @@ void do_child(const char *command, struct passwd *pw, const char *term,
131#ifdef HAVE_PAM 132#ifdef HAVE_PAM
132static int pamconv(int num_msg, const struct pam_message **msg, 133static int pamconv(int num_msg, const struct pam_message **msg,
133 struct pam_response **resp, void *appdata_ptr); 134 struct pam_response **resp, void *appdata_ptr);
134void do_pam_authentication(const char *username, const char *password, 135void do_pam_account_and_session(const char *username, const char *password,
135 const char *remote_user, const char *remote_host); 136 const char *remote_user, const char *remote_host);
136void pam_cleanup_proc(void *context); 137void pam_cleanup_proc(void *context);
137 138
@@ -158,7 +159,7 @@ static int pamconv(int num_msg, const struct pam_message **msg,
158 switch (msg[count]->msg_style) 159 switch (msg[count]->msg_style)
159 { 160 {
160 case PAM_PROMPT_ECHO_OFF: 161 case PAM_PROMPT_ECHO_OFF:
161 if (pampasswd == NULL) 162 if (pampasswd == NULL)
162 { 163 {
163 free(reply); 164 free(reply);
164 return PAM_CONV_ERR; 165 return PAM_CONV_ERR;
@@ -198,59 +199,30 @@ void pam_cleanup_proc(void *context)
198 } 199 }
199} 200}
200 201
201void do_pam_authentication(const char *username, const char *password, const char *remote_user, const char *remote_host) 202void do_pam_account_and_session(const char *username, const char *password, const char *remote_user, const char *remote_host)
202{ 203{
203 int pam_auth_ok = 1; 204 if (remote_host && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RHOST, remote_host)))
204
205 pampasswd = password;
206
207 do
208 { 205 {
209 if (PAM_SUCCESS != pam_start("ssh", username, &conv, (pam_handle_t**)&pamh)) 206 log("PAM setup failed.");
210 { 207 eat_packets_and_disconnect(username);
211 pam_auth_ok = 0; 208 }
212 break;
213 }
214
215 fatal_add_cleanup(&pam_cleanup_proc, NULL);
216
217 if (remote_host && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RHOST, remote_host)))
218 {
219 pam_auth_ok = 0;
220 break;
221 }
222 209
223 if (remote_user && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user))) 210 if (remote_user && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user)))
224 { 211 {
225 pam_auth_ok = 0; 212 log("PAM setup failed.");
226 break; 213 eat_packets_and_disconnect(username);
227 } 214 }
228 215
229 if (PAM_SUCCESS != pam_authenticate((pam_handle_t *)pamh, 0)) 216 if (PAM_SUCCESS != pam_acct_mgmt((pam_handle_t *)pamh, 0))
230 { 217 {
231 pam_auth_ok = 0; 218 log("PAM rejected by account configuration.");
232 break; 219 eat_packets_and_disconnect(username);
233 } 220 }
234
235 if (PAM_SUCCESS != pam_acct_mgmt((pam_handle_t *)pamh, 0))
236 {
237 pam_auth_ok = 0;
238 break;
239 }
240 221
241 if (PAM_SUCCESS != pam_open_session((pam_handle_t *)pamh, 0)) 222 if (PAM_SUCCESS != pam_open_session((pam_handle_t *)pamh, 0))
242 {
243 pam_auth_ok = 0;
244 break;
245 }
246 } while (0);
247
248 if (!pam_auth_ok)
249 { 223 {
250 packet_start(SSH_SMSG_FAILURE); 224 log("PAM session setup failed.");
251 packet_send(); 225 eat_packets_and_disconnect(username);
252 packet_write_wait();
253 packet_disconnect("PAM authentication failed.");
254 } 226 }
255} 227}
256#endif /* HAVE_PAM */ 228#endif /* HAVE_PAM */
@@ -1151,48 +1123,8 @@ do_authentication(char *user, int privileged_port)
1151 /* Verify that the user is a valid user. */ 1123 /* Verify that the user is a valid user. */
1152 pw = getpwnam(user); 1124 pw = getpwnam(user);
1153 if (!pw || !allowed_user(pw)) 1125 if (!pw || !allowed_user(pw))
1154 { 1126 eat_packets_and_disconnect(user);
1155 /* The user does not exist or access is denied, 1127
1156 but fake indication that authentication is needed. */
1157 packet_start(SSH_SMSG_FAILURE);
1158 packet_send();
1159 packet_write_wait();
1160
1161 /* Keep reading packets, and always respond with a failure. This is to
1162 avoid disclosing whether such a user really exists. */
1163 for (;;)
1164 {
1165 /* Read a packet. This will not return if the client disconnects. */
1166 int plen;
1167 int type = packet_read(&plen);
1168#ifdef SKEY
1169 int passw_len;
1170 char *password, *skeyinfo;
1171 if (options.password_authentication &&
1172 options.skey_authentication == 1 &&
1173 type == SSH_CMSG_AUTH_PASSWORD &&
1174 (password = packet_get_string(&passw_len)) != NULL &&
1175 passw_len == 5 &&
1176 strncasecmp(password, "s/key", 5) == 0 &&
1177 (skeyinfo = skey_fake_keyinfo(user)) != NULL ){
1178 /* Send a fake s/key challenge. */
1179 packet_send_debug(skeyinfo);
1180 }
1181#endif
1182 /* Send failure. This should be indistinguishable from a failed
1183 authentication. */
1184 packet_start(SSH_SMSG_FAILURE);
1185 packet_send();
1186 packet_write_wait();
1187 if (++authentication_failures >= MAX_AUTH_FAILURES) {
1188 packet_disconnect("Too many authentication failures for %.100s from %.200s",
1189 user, get_canonical_hostname());
1190 }
1191 }
1192 /*NOTREACHED*/
1193 abort();
1194 }
1195
1196 /* Take a copy of the returned structure. */ 1128 /* Take a copy of the returned structure. */
1197 memset(&pwcopy, 0, sizeof(pwcopy)); 1129 memset(&pwcopy, 0, sizeof(pwcopy));
1198 pwcopy.pw_name = xstrdup(pw->pw_name); 1130 pwcopy.pw_name = xstrdup(pw->pw_name);
@@ -1203,6 +1135,18 @@ do_authentication(char *user, int privileged_port)
1203 pwcopy.pw_shell = xstrdup(pw->pw_shell); 1135 pwcopy.pw_shell = xstrdup(pw->pw_shell);
1204 pw = &pwcopy; 1136 pw = &pwcopy;
1205 1137
1138#ifdef HAVE_PAM
1139 if (PAM_SUCCESS != pam_start("ssh", pw->pw_name, &conv, (pam_handle_t**)&pamh))
1140 {
1141 packet_start(SSH_SMSG_FAILURE);
1142 packet_send();
1143 packet_write_wait();
1144 packet_disconnect("PAM initialisation failed.");
1145 }
1146#endif
1147
1148 fatal_add_cleanup(&pam_cleanup_proc, NULL);
1149
1206 /* If we are not running as root, the user must have the same uid as the 1150 /* If we are not running as root, the user must have the same uid as the
1207 server. */ 1151 server. */
1208 if (getuid() != 0 && pw->pw_uid != getuid()) 1152 if (getuid() != 0 && pw->pw_uid != getuid())
@@ -1460,10 +1404,18 @@ do_authentication(char *user, int privileged_port)
1460 } 1404 }
1461 1405
1462#ifdef HAVE_PAM 1406#ifdef HAVE_PAM
1463 /* Authentication will be handled later */ 1407 pampasswd = password;
1464 /* keep password around until then */ 1408
1465 authenticated = 1; 1409 if (PAM_SUCCESS == pam_authenticate((pam_handle_t *)pamh, 0))
1466 break; 1410 {
1411 log("PAM Password authentication accepted for %.100s.", user);
1412 authenticated = 1;
1413 break;
1414 } else
1415 {
1416 log("PAM Password authentication for %.100s failed.", user);
1417 break;
1418 }
1467#else /* HAVE_PAM */ 1419#else /* HAVE_PAM */
1468 /* Try authentication with the password. */ 1420 /* Try authentication with the password. */
1469 if (auth_password(pw, password)) 1421 if (auth_password(pw, password))
@@ -1519,7 +1471,7 @@ do_authentication(char *user, int privileged_port)
1519 } 1471 }
1520 1472
1521#ifdef HAVE_PAM 1473#ifdef HAVE_PAM
1522 do_pam_authentication(pw->pw_name, password, client_user, get_canonical_hostname()); 1474 do_pam_account_and_session(pw->pw_name, password, client_user, get_canonical_hostname());
1523 1475
1524 /* Clean up */ 1476 /* Clean up */
1525 if (client_user != NULL) 1477 if (client_user != NULL)
@@ -1541,6 +1493,55 @@ do_authentication(char *user, int privileged_port)
1541 do_authenticated(pw); 1493 do_authenticated(pw);
1542} 1494}
1543 1495
1496/* Read authentication messages, but return only failures until */
1497/* max auth attempts exceeded, then disconnect */
1498void eat_packets_and_disconnect(const char *user)
1499{
1500 int authentication_failures = 0;
1501
1502 packet_start(SSH_SMSG_FAILURE);
1503 packet_send();
1504 packet_write_wait();
1505
1506 /* Keep reading packets, and always respond with a failure. This is to
1507 avoid disclosing whether such a user really exists. */
1508 while(1)
1509 {
1510 /* Read a packet. This will not return if the client disconnects. */
1511 int plen;
1512#ifndef SKEY
1513 (void) packet_read(&plen);
1514#else /* SKEY */
1515 int type = packet_read(&plen);
1516 int passw_len;
1517 char *password, *skeyinfo;
1518 if (options.password_authentication &&
1519 options.skey_authentication == 1 &&
1520 type == SSH_CMSG_AUTH_PASSWORD &&
1521 (password = packet_get_string(&passw_len)) != NULL &&
1522 passw_len == 5 &&
1523 strncasecmp(password, "s/key", 5) == 0 &&
1524 (skeyinfo = skey_fake_keyinfo(user)) != NULL )
1525 {
1526 /* Send a fake s/key challenge. */
1527 packet_send_debug(skeyinfo);
1528 }
1529#endif /* SKEY */
1530 /* Send failure. This should be indistinguishable from a failed
1531 authentication. */
1532 packet_start(SSH_SMSG_FAILURE);
1533 packet_send();
1534 packet_write_wait();
1535 if (++authentication_failures >= MAX_AUTH_FAILURES)
1536 {
1537 packet_disconnect("Too many authentication failures for %.100s from %.200s",
1538 user, get_canonical_hostname());
1539 }
1540 }
1541 /*NOTREACHED*/
1542 abort();
1543}
1544
1544/* Prepares for an interactive session. This is called after the user has 1545/* Prepares for an interactive session. This is called after the user has
1545 been successfully authenticated. During this message exchange, pseudo 1546 been successfully authenticated. During this message exchange, pseudo
1546 terminals are allocated, X11, TCP/IP, and authentication agent forwardings 1547 terminals are allocated, X11, TCP/IP, and authentication agent forwardings