summaryrefslogtreecommitdiffstats
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 cleanupPRE_DAN_PATCH_MERGE
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 3b0402ec..c9aa51e4 100644
--- a/helper.c
+++ b/helper.c
@@ -57,14 +57,14 @@ void setproctitle(const char *fmt, ...)
/* FIXME */
}
-unsigned char arc4random(void)
+unsigned int arc4random(void)
{
- unsigned char r;
+ unsigned int r;
if (rc4 == NULL)
arc4random_stir();
- rc4_getbytes(rc4, &r, 1);
+ rc4_getbytes(rc4, (unsigned char *)&r, sizeof(r));
return(r);
}
diff --git a/helper.h b/helper.h
index 2f09daa8..309156a2 100644
--- a/helper.h
+++ b/helper.h
@@ -36,7 +36,7 @@
#ifndef _HELPER_H
#define _HELPER_H
-unsigned char arc4random(void);
+unsigned int arc4random(void);
void arc4random_stir(void);
void setproctitle(const char *fmt, ...);
diff --git a/mktemp.c b/mktemp.c
index 919c5317..69dc4dc6 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
#include <ctype.h>
#include <unistd.h>
+#include "helper.h"
+
static int _gettemp __P((char *, int *, int, int));
int
diff --git a/sshd.c b/sshd.c
index 08fb30e3..b2cb5a32 100644
--- a/sshd.c
+++ b/sshd.c
@@ -18,7 +18,7 @@ agent connections.
*/
#include "includes.h"
-RCSID("$Id: sshd.c,v 1.2 1999/10/27 13:42:05 damien Exp $");
+RCSID("$Id: sshd.c,v 1.3 1999/10/28 03:20:30 damien Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -117,6 +117,7 @@ RSA *public_key;
/* Prototypes for various functions defined later in this file. */
void do_connection(int privileged_port);
void do_authentication(char *user, int privileged_port);
+void eat_packets_and_disconnect(const char *user);
void do_authenticated(struct passwd *pw);
void do_exec_pty(const char *command, int ptyfd, int ttyfd,
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,
#ifdef HAVE_PAM
static int pamconv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr);
-void do_pam_authentication(const char *username, const char *password,
+void do_pam_account_and_session(const char *username, const char *password,
const char *remote_user, const char *remote_host);
void pam_cleanup_proc(void *context);
@@ -158,7 +159,7 @@ static int pamconv(int num_msg, const struct pam_message **msg,
switch (msg[count]->msg_style)
{
case PAM_PROMPT_ECHO_OFF:
- if (pampasswd == NULL)
+ if (pampasswd == NULL)
{
free(reply);
return PAM_CONV_ERR;
@@ -198,59 +199,30 @@ void pam_cleanup_proc(void *context)
}
}
-void do_pam_authentication(const char *username, const char *password, const char *remote_user, const char *remote_host)
+void do_pam_account_and_session(const char *username, const char *password, const char *remote_user, const char *remote_host)
{
- int pam_auth_ok = 1;
-
- pampasswd = password;
-
- do
+ if (remote_host && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RHOST, remote_host)))
{
- if (PAM_SUCCESS != pam_start("ssh", username, &conv, (pam_handle_t**)&pamh))
- {
- pam_auth_ok = 0;
- break;
- }
-
- fatal_add_cleanup(&pam_cleanup_proc, NULL);
-
- if (remote_host && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RHOST, remote_host)))
- {
- pam_auth_ok = 0;
- break;
- }
+ log("PAM setup failed.");
+ eat_packets_and_disconnect(username);
+ }
- if (remote_user && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user)))
- {
- pam_auth_ok = 0;
- break;
- }
+ if (remote_user && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user)))
+ {
+ log("PAM setup failed.");
+ eat_packets_and_disconnect(username);
+ }
- if (PAM_SUCCESS != pam_authenticate((pam_handle_t *)pamh, 0))
- {
- pam_auth_ok = 0;
- break;
- }
-
- if (PAM_SUCCESS != pam_acct_mgmt((pam_handle_t *)pamh, 0))
- {
- pam_auth_ok = 0;
- break;
- }
+ if (PAM_SUCCESS != pam_acct_mgmt((pam_handle_t *)pamh, 0))
+ {
+ log("PAM rejected by account configuration.");
+ eat_packets_and_disconnect(username);
+ }
- if (PAM_SUCCESS != pam_open_session((pam_handle_t *)pamh, 0))
- {
- pam_auth_ok = 0;
- break;
- }
- } while (0);
-
- if (!pam_auth_ok)
+ if (PAM_SUCCESS != pam_open_session((pam_handle_t *)pamh, 0))
{
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
- packet_disconnect("PAM authentication failed.");
+ log("PAM session setup failed.");
+ eat_packets_and_disconnect(username);
}
}
#endif /* HAVE_PAM */
@@ -1151,48 +1123,8 @@ do_authentication(char *user, int privileged_port)
/* Verify that the user is a valid user. */
pw = getpwnam(user);
if (!pw || !allowed_user(pw))
- {
- /* The user does not exist or access is denied,
- but fake indication that authentication is needed. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
-
- /* Keep reading packets, and always respond with a failure. This is to
- avoid disclosing whether such a user really exists. */
- for (;;)
- {
- /* Read a packet. This will not return if the client disconnects. */
- int plen;
- int type = packet_read(&plen);
-#ifdef SKEY
- int passw_len;
- char *password, *skeyinfo;
- if (options.password_authentication &&
- options.skey_authentication == 1 &&
- type == SSH_CMSG_AUTH_PASSWORD &&
- (password = packet_get_string(&passw_len)) != NULL &&
- passw_len == 5 &&
- strncasecmp(password, "s/key", 5) == 0 &&
- (skeyinfo = skey_fake_keyinfo(user)) != NULL ){
- /* Send a fake s/key challenge. */
- packet_send_debug(skeyinfo);
- }
-#endif
- /* Send failure. This should be indistinguishable from a failed
- authentication. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
- if (++authentication_failures >= MAX_AUTH_FAILURES) {
- packet_disconnect("Too many authentication failures for %.100s from %.200s",
- user, get_canonical_hostname());
- }
- }
- /*NOTREACHED*/
- abort();
- }
-
+ eat_packets_and_disconnect(user);
+
/* Take a copy of the returned structure. */
memset(&pwcopy, 0, sizeof(pwcopy));
pwcopy.pw_name = xstrdup(pw->pw_name);
@@ -1203,6 +1135,18 @@ do_authentication(char *user, int privileged_port)
pwcopy.pw_shell = xstrdup(pw->pw_shell);
pw = &pwcopy;
+#ifdef HAVE_PAM
+ if (PAM_SUCCESS != pam_start("ssh", pw->pw_name, &conv, (pam_handle_t**)&pamh))
+ {
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ packet_disconnect("PAM initialisation failed.");
+ }
+#endif
+
+ fatal_add_cleanup(&pam_cleanup_proc, NULL);
+
/* If we are not running as root, the user must have the same uid as the
server. */
if (getuid() != 0 && pw->pw_uid != getuid())
@@ -1460,10 +1404,18 @@ do_authentication(char *user, int privileged_port)
}
#ifdef HAVE_PAM
- /* Authentication will be handled later */
- /* keep password around until then */
- authenticated = 1;
- break;
+ pampasswd = password;
+
+ if (PAM_SUCCESS == pam_authenticate((pam_handle_t *)pamh, 0))
+ {
+ log("PAM Password authentication accepted for %.100s.", user);
+ authenticated = 1;
+ break;
+ } else
+ {
+ log("PAM Password authentication for %.100s failed.", user);
+ break;
+ }
#else /* HAVE_PAM */
/* Try authentication with the password. */
if (auth_password(pw, password))
@@ -1519,7 +1471,7 @@ do_authentication(char *user, int privileged_port)
}
#ifdef HAVE_PAM
- do_pam_authentication(pw->pw_name, password, client_user, get_canonical_hostname());
+ do_pam_account_and_session(pw->pw_name, password, client_user, get_canonical_hostname());
/* Clean up */
if (client_user != NULL)
@@ -1541,6 +1493,55 @@ do_authentication(char *user, int privileged_port)
do_authenticated(pw);
}
+/* Read authentication messages, but return only failures until */
+/* max auth attempts exceeded, then disconnect */
+void eat_packets_and_disconnect(const char *user)
+{
+ int authentication_failures = 0;
+
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+
+ /* Keep reading packets, and always respond with a failure. This is to
+ avoid disclosing whether such a user really exists. */
+ while(1)
+ {
+ /* Read a packet. This will not return if the client disconnects. */
+ int plen;
+#ifndef SKEY
+ (void) packet_read(&plen);
+#else /* SKEY */
+ int type = packet_read(&plen);
+ int passw_len;
+ char *password, *skeyinfo;
+ if (options.password_authentication &&
+ options.skey_authentication == 1 &&
+ type == SSH_CMSG_AUTH_PASSWORD &&
+ (password = packet_get_string(&passw_len)) != NULL &&
+ passw_len == 5 &&
+ strncasecmp(password, "s/key", 5) == 0 &&
+ (skeyinfo = skey_fake_keyinfo(user)) != NULL )
+ {
+ /* Send a fake s/key challenge. */
+ packet_send_debug(skeyinfo);
+ }
+#endif /* SKEY */
+ /* Send failure. This should be indistinguishable from a failed
+ authentication. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ if (++authentication_failures >= MAX_AUTH_FAILURES)
+ {
+ packet_disconnect("Too many authentication failures for %.100s from %.200s",
+ user, get_canonical_hostname());
+ }
+ }
+ /*NOTREACHED*/
+ abort();
+}
+
/* Prepares for an interactive session. This is called after the user has
been successfully authenticated. During this message exchange, pseudo
terminals are allocated, X11, TCP/IP, and authentication agent forwardings