mirror of git://anongit.mindrot.org/openssh.git
Big PAM cleanup
Added header for arc4random to mktemp.c Fixed return type of arc4random
This commit is contained in:
parent
332e67fde2
commit
3d112efc67
6
helper.c
6
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);
|
||||
}
|
||||
|
|
2
helper.h
2
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, ...);
|
||||
|
||||
|
|
2
mktemp.c
2
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
|
||||
|
|
197
sshd.c
197
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;
|
||||
}
|
||||
log("PAM setup failed.");
|
||||
eat_packets_and_disconnect(username);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_open_session((pam_handle_t *)pamh, 0))
|
||||
{
|
||||
pam_auth_ok = 0;
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (!pam_auth_ok)
|
||||
if (PAM_SUCCESS != pam_acct_mgmt((pam_handle_t *)pamh, 0))
|
||||
{
|
||||
packet_start(SSH_SMSG_FAILURE);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
packet_disconnect("PAM authentication failed.");
|
||||
log("PAM rejected by account configuration.");
|
||||
eat_packets_and_disconnect(username);
|
||||
}
|
||||
|
||||
if (PAM_SUCCESS != pam_open_session((pam_handle_t *)pamh, 0))
|
||||
{
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue