Compare commits

...
Author SHA1 Message Date
Damien Miller 3d112efc67 Big PAM cleanup
Added header for arc4random to mktemp.c

Fixed return type of arc4random
1999-10-28 13:20:30 +10:00
Damien Miller 332e67fde2 Attempt to clean up PAM code
Use PWDB getpw* functions if HAVE_PWDB defined

Minor other tidyups
1999-10-27 23:42:05 +10:00
Damien Miller 726a5b3be1 Added compatibility macros 1999-10-27 18:00:50 +10:00
7 changed files with 202 additions and 150 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
OPT_FLAGS=-g
CFLAGS=$(OPT_FLAGS) -Wall -DETCDIR=\"/etc/ssh\" -DHAVE_PAM
CFLAGS=$(OPT_FLAGS) -Wall -DETCDIR=\"/etc/ssh\" -DHAVE_PAM -DHAVE_PWDB
TARGETS=bin/libssh.a bin/ssh bin/sshd bin/ssh-add bin/ssh-keygen bin/ssh-agent bin/scp
LFLAGS=-L./bin
LIBS=-lssh -lcrypto -lz -lutil -lpam -ldl
LIBS=-lssh -lcrypto -lz -lutil -lpwdb -lpam -ldl
AR=ar
RANLIB=ranlib
+1 -30
View File
@@ -15,7 +15,7 @@ the password is valid for the user.
*/
#include "includes.h"
RCSID("$Id: auth-passwd.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
RCSID("$Id: auth-passwd.c,v 1.2 1999/10/27 13:42:05 damien Exp $");
#include "packet.h"
#include "ssh.h"
@@ -26,14 +26,6 @@ RCSID("$Id: auth-passwd.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
extern char *ticket;
#endif /* KRB4 */
#ifdef HAVE_PAM
#include <security/pam_appl.h>
extern pam_handle_t *pamh;
extern int retval;
extern char* pampasswd;
extern int origretval;
#endif /* HAVE_PAM */
/* Tries to authenticate the user using password. Returns true if
authentication succeeds. */
@@ -58,26 +50,6 @@ int auth_password(struct passwd *pw, const char *password)
if (pw == NULL)
return 0;
#ifdef HAVE_PAM
retval = origretval;
pampasswd = xstrdup(password);
if (retval == PAM_SUCCESS)
retval = pam_authenticate ((pam_handle_t *)pamh, 0);
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt ((pam_handle_t *)pamh, 0);
xfree(pampasswd);
if (retval == PAM_SUCCESS)
retval = pam_open_session ((pam_handle_t *)pamh, 0);
return (retval == PAM_SUCCESS);
#else /* HAVE_PAM */
#ifdef SKEY
if (options.skey_authentication == 1) {
if (strncasecmp(password, "s/key", 5) == 0) {
@@ -205,5 +177,4 @@ int auth_password(struct passwd *pw, const char *password)
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
#endif /* HAVE_PAM */
}
+3 -3
View File
@@ -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);
}
+1 -1
View File
@@ -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, ...);
+14
View File
@@ -61,6 +61,14 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
#include "mktemp.h"
#include "strlcpy.h"
#ifdef HAVE_PAM
#include <security/pam_appl.h>
#endif /* HAVE_PAM */
#ifdef HAVE_PWDB
#include <pwdb/pwdb_map.h>
#endif /* HAVE_PWDB */
/* Define this to be the path of the xauth program. */
#ifndef XAUTH_PATH
#define XAUTH_PATH "/usr/X11R6/bin/xauth"
@@ -75,4 +83,10 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
client program. Socketpairs do not seem to work on all systems. */
#define USE_PIPES 1
#ifndef SHUT_RD
#define SHUT_RD 0
#define SHUT_WR 1
#define SHUT_RDWR 2
#endif /* SHUT_RD */
#endif /* INCLUDES_H */
+2
View File
@@ -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
+179 -114
View File
@@ -18,7 +18,7 @@ agent connections.
*/
#include "includes.h"
RCSID("$Id: sshd.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
RCSID("$Id: sshd.c,v 1.3 1999/10/28 03:20:30 damien Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -47,14 +47,6 @@ int deny_severity = LOG_WARNING;
char *ticket = NULL;
#endif /* KRB4 */
#ifdef HAVE_PAM
#include <security/pam_appl.h>
struct pam_handle_t *pamh=NULL;
char *pampasswd=NULL;
int retval;
int origretval;
#endif /* HAVE_PAM */
/* Local Xauthority file. */
char *xauthfile = NULL;
@@ -125,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,
@@ -139,69 +132,98 @@ 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_account_and_session(const char *username, const char *password,
const char *remote_user, const char *remote_host);
void pam_cleanup_proc(void *context);
static struct pam_conv conv = {
pamconv,
NULL
};
struct pam_handle_t *pamh = NULL;
const char *pampasswd = NULL;
static int pamconv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int count = 0;
int replies = 0;
struct pam_response *reply = NULL;
int size = sizeof(struct pam_response);
/* PAM will free this later */
reply = malloc(num_msg * sizeof(*reply));
if (reply == NULL)
return PAM_CONV_ERR;
for(count = 0; count < num_msg; count++)
{
switch (msg[count]->msg_style)
{
case PAM_PROMPT_ECHO_ON:
case PAM_PROMPT_ECHO_OFF:
if (reply == NULL)
reply = xmalloc(size);
else
reply = realloc(reply, size);
if (reply == NULL)
return PAM_CONV_ERR;
size += sizeof(struct pam_response);
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies++].resp = xstrdup(pampasswd);
/* PAM frees resp */
break;
case PAM_TEXT_INFO:
/* ignore it... */
break;
case PAM_ERROR_MSG:
default:
/* Must be an error of some sort... */
if (reply != NULL)
if (pampasswd == NULL)
{
free(reply);
return PAM_CONV_ERR;
}
reply[count].resp_retcode = PAM_SUCCESS;
reply[count].resp = xstrdup(pampasswd);
break;
return PAM_CONV_ERR;
}
case PAM_TEXT_INFO:
reply[count].resp_retcode = PAM_SUCCESS;
reply[count].resp = xstrdup("");
break;
case PAM_PROMPT_ECHO_ON:
case PAM_ERROR_MSG:
default:
free(reply);
return PAM_CONV_ERR;
}
}
if (reply != NULL)
*resp = reply;
*resp = reply;
return PAM_SUCCESS;
}
void pam_cleanup_proc(void *context)
{
if (retval == PAM_SUCCESS)
int retval;
if (pamh != NULL)
{
retval = pam_close_session((pam_handle_t *)pamh, 0);
if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
log("Cannot release PAM authentication.");
if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
log("Cannot release PAM authentication.");
}
}
void do_pam_account_and_session(const char *username, const char *password, const char *remote_user, const char *remote_host)
{
if (remote_host && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RHOST, remote_host)))
{
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)))
{
log("PAM setup failed.");
eat_packets_and_disconnect(username);
}
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))
{
log("PAM session setup failed.");
eat_packets_and_disconnect(username);
}
}
#endif /* HAVE_PAM */
@@ -788,13 +810,19 @@ main(int ac, char **av)
log("Closing connection to %.100s", inet_ntoa(sin.sin_addr));
#ifdef HAVE_PAM
if (retval == PAM_SUCCESS)
retval = pam_close_session((pam_handle_t *)pamh, 0);
{
int retval;
if (pamh != NULL)
{
retval = pam_close_session((pam_handle_t *)pamh, 0);
if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
log("Cannot release PAM authentication.");
if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
log("Cannot release PAM authentication.");
fatal_remove_cleanup(&pam_cleanup_proc, NULL);
fatal_remove_cleanup(&pam_cleanup_proc, NULL);
}
}
#endif /* HAVE_PAM */
packet_close();
@@ -1078,14 +1106,11 @@ do_authentication(char *user, int privileged_port)
int type;
int authenticated = 0;
int authentication_failures = 0;
char *password;
char *password = NULL;
struct passwd *pw, pwcopy;
char *client_user;
char *client_user = NULL;
unsigned int client_host_key_bits;
BIGNUM *client_host_key_e, *client_host_key_n;
#ifdef HAVE_PAM
int pam_auth_ok;
#endif /* HAVE_PAM */
#ifdef AFS
/* If machine has AFS, set process authentication group. */
@@ -1097,63 +1122,9 @@ do_authentication(char *user, int privileged_port)
/* Verify that the user is a valid user. */
pw = getpwnam(user);
#ifdef HAVE_PAM
if ((pw != NULL) && allowed_user(pw))
{
/* Initialise PAM */
retval = pam_start("ssh", pw->pw_name, &conv, (pam_handle_t **)&pamh);
fatal_add_cleanup(&pam_cleanup_proc, NULL);
origretval = retval;
if (retval == PAM_SUCCESS)
pam_auth_ok = 1;
}
if (pam_auth_ok == 0)
#else /* HAVE_PAM */
if (!pw || !allowed_user(pw))
#endif /* HAVE_PAM */
{
/* 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);
@@ -1164,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())
@@ -1306,12 +1289,16 @@ do_authentication(char *user, int privileged_port)
log("Rhosts authentication accepted for %.100s, remote %.100s on %.700s.",
user, client_user, get_canonical_hostname());
authenticated = 1;
#ifndef HAVE_PAM
xfree(client_user);
#endif /* HAVE_PAM */
break;
}
log("Rhosts authentication failed for %.100s, remote %.100s.",
user, client_user);
#ifndef HAVE_PAM
xfree(client_user);
#endif /* HAVE_PAM */
break;
case SSH_CMSG_AUTH_RHOSTS_RSA:
@@ -1354,14 +1341,18 @@ do_authentication(char *user, int privileged_port)
{
/* Authentication accepted. */
authenticated = 1;
#ifndef HAVE_PAM
xfree(client_user);
#endif /* HAVE_PAM */
BN_clear_free(client_host_key_e);
BN_clear_free(client_host_key_n);
break;
}
log("Rhosts authentication failed for %.100s, remote %.100s.",
user, client_user);
xfree(client_user);
#ifndef HAVE_PAM
xfree(client_user);
#endif /* HAVE_PAM */
BN_clear_free(client_host_key_e);
BN_clear_free(client_host_key_n);
break;
@@ -1412,6 +1403,20 @@ do_authentication(char *user, int privileged_port)
packet_integrity_check(plen, 4 + passw_len, type);
}
#ifdef HAVE_PAM
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))
{
@@ -1427,6 +1432,7 @@ do_authentication(char *user, int privileged_port)
memset(password, 0, strlen(password));
xfree(password);
break;
#endif /* HAVE_PAM */
case SSH_CMSG_AUTH_TIS:
/* TIS Authentication is unsupported */
@@ -1464,6 +1470,20 @@ do_authentication(char *user, int privileged_port)
get_canonical_hostname());
}
#ifdef HAVE_PAM
do_pam_account_and_session(pw->pw_name, password, client_user, get_canonical_hostname());
/* Clean up */
if (client_user != NULL)
xfree(client_user);
if (password != NULL)
{
memset(password, 0, strlen(password));
xfree(password);
}
#endif /* HAVE_PAM */
/* The user has been authenticated and accepted. */
packet_start(SSH_SMSG_SUCCESS);
packet_send();
@@ -1473,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
@@ -2151,10 +2220,6 @@ void do_child(const char *command, struct passwd *pw, const char *term,
exit(254);
}
/* Set login name in the kernel. */
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
/* Set uid, gid, and groups. */
/* Login(1) does this as well, and it needs uid 0 for the "-h" switch,
so we let login(1) to this for us. */