version 1.68, 2006/02/20 17:02:44 |
version 1.68.2.1, 2006/09/30 04:06:50 |
|
|
|
/* $OpenBSD$ */ |
/* |
/* |
* Copyright 2002 Niels Provos <provos@citi.umich.edu> |
* Copyright 2002 Niels Provos <provos@citi.umich.edu> |
* Copyright 2002 Markus Friedl <markus@openbsd.org> |
* Copyright 2002 Markus Friedl <markus@openbsd.org> |
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
*/ |
|
|
#include "includes.h" |
|
RCSID("$OpenBSD$"); |
|
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/wait.h> |
#include <sys/wait.h> |
|
#include <sys/socket.h> |
|
#include <sys/tree.h> |
|
#include <sys/param.h> |
|
|
|
#include <openssl/dh.h> |
|
|
|
#include <errno.h> |
|
#include <fcntl.h> |
#include <paths.h> |
#include <paths.h> |
|
#include <pwd.h> |
#include <signal.h> |
#include <signal.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
#ifdef SKEY |
#ifdef SKEY |
#include <skey.h> |
#include <skey.h> |
#endif |
#endif |
|
|
#include <openssl/dh.h> |
#include "xmalloc.h" |
|
|
#include "ssh.h" |
#include "ssh.h" |
|
#include "key.h" |
|
#include "buffer.h" |
|
#include "hostfile.h" |
#include "auth.h" |
#include "auth.h" |
|
#include "cipher.h" |
#include "kex.h" |
#include "kex.h" |
#include "dh.h" |
#include "dh.h" |
#include "zlib.h" |
#include <zlib.h> |
#include "packet.h" |
#include "packet.h" |
#include "auth-options.h" |
#include "auth-options.h" |
#include "sshpty.h" |
#include "sshpty.h" |
|
|
#include "servconf.h" |
#include "servconf.h" |
#include "monitor.h" |
#include "monitor.h" |
#include "monitor_mm.h" |
#include "monitor_mm.h" |
|
#ifdef GSSAPI |
|
#include "ssh-gss.h" |
|
#endif |
#include "monitor_wrap.h" |
#include "monitor_wrap.h" |
#include "monitor_fdpass.h" |
#include "monitor_fdpass.h" |
#include "xmalloc.h" |
|
#include "misc.h" |
#include "misc.h" |
#include "buffer.h" |
|
#include "bufaux.h" |
|
#include "compat.h" |
#include "compat.h" |
#include "ssh2.h" |
#include "ssh2.h" |
|
|
#ifdef GSSAPI |
#ifdef GSSAPI |
#include "ssh-gss.h" |
|
static Gssctxt *gsscontext = NULL; |
static Gssctxt *gsscontext = NULL; |
#endif |
#endif |
|
|
|
|
#define MON_ISAUTH 0x0004 /* Required for Authentication */ |
#define MON_ISAUTH 0x0004 /* Required for Authentication */ |
#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ |
#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ |
#define MON_ONCE 0x0010 /* Disable after calling */ |
#define MON_ONCE 0x0010 /* Disable after calling */ |
|
#define MON_ALOG 0x0020 /* Log auth attempt without authenticating */ |
|
|
#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) |
#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) |
|
|
|
|
{MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, |
{MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, |
{MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, |
{MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, |
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, |
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, |
{MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed}, |
{MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed}, |
{MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, |
{MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed}, |
{MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, |
{MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, |
{MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, |
{MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, |
#ifdef BSD_AUTH |
#ifdef BSD_AUTH |
|
|
|
|
/* The first few requests do not require asynchronous access */ |
/* The first few requests do not require asynchronous access */ |
while (!authenticated) { |
while (!authenticated) { |
|
auth_method = "unknown"; |
authenticated = monitor_read(pmonitor, mon_dispatch, &ent); |
authenticated = monitor_read(pmonitor, mon_dispatch, &ent); |
if (authenticated) { |
if (authenticated) { |
if (!(ent->flags & MON_AUTHDECIDE)) |
if (!(ent->flags & MON_AUTHDECIDE)) |
|
|
authenticated = 0; |
authenticated = 0; |
} |
} |
|
|
if (ent->flags & MON_AUTHDECIDE) { |
if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { |
auth_log(authctxt, authenticated, auth_method, |
auth_log(authctxt, authenticated, auth_method, |
compat20 ? " ssh2" : ""); |
compat20 ? " ssh2" : ""); |
if (!authenticated) |
if (!authenticated) |
|
|
|
|
if (!authctxt->valid) |
if (!authctxt->valid) |
fatal("%s: authenticated invalid user", __func__); |
fatal("%s: authenticated invalid user", __func__); |
|
if (strcmp(auth_method, "unknown") == 0) |
|
fatal("%s: authentication method name unknown", __func__); |
|
|
debug("%s: %s has been authenticated by privileged process", |
debug("%s: %s has been authenticated by privileged process", |
__func__, authctxt->user); |
__func__, authctxt->user); |
|
|
keyid = buffer_get_int(m); |
keyid = buffer_get_int(m); |
p = buffer_get_string(m, &datlen); |
p = buffer_get_string(m, &datlen); |
|
|
if (datlen != 20) |
/* |
|
* Supported KEX types will only return SHA1 (20 byte) or |
|
* SHA256 (32 byte) hashes |
|
*/ |
|
if (datlen != 20 && datlen != 32) |
fatal("%s: data length incorrect: %u", __func__, datlen); |
fatal("%s: data length incorrect: %u", __func__, datlen); |
|
|
/* save session id, it will be passed on the first call */ |
/* save session id, it will be passed on the first call */ |
|
|
case MM_USERKEY: |
case MM_USERKEY: |
allowed = options.pubkey_authentication && |
allowed = options.pubkey_authentication && |
user_key_allowed(authctxt->pw, key); |
user_key_allowed(authctxt->pw, key); |
|
auth_method = "publickey"; |
break; |
break; |
case MM_HOSTKEY: |
case MM_HOSTKEY: |
allowed = options.hostbased_authentication && |
allowed = options.hostbased_authentication && |
hostbased_key_allowed(authctxt->pw, |
hostbased_key_allowed(authctxt->pw, |
cuser, chost, key); |
cuser, chost, key); |
|
auth_method = "hostbased"; |
break; |
break; |
case MM_RSAHOSTKEY: |
case MM_RSAHOSTKEY: |
key->type = KEY_RSA1; /* XXX */ |
key->type = KEY_RSA1; /* XXX */ |
allowed = options.rhosts_rsa_authentication && |
allowed = options.rhosts_rsa_authentication && |
auth_rhosts_rsa_key_allowed(authctxt->pw, |
auth_rhosts_rsa_key_allowed(authctxt->pw, |
cuser, chost, key); |
cuser, chost, key); |
|
auth_method = "rsa"; |
break; |
break; |
default: |
default: |
fatal("%s: unknown key type %d", __func__, type); |
fatal("%s: unknown key type %d", __func__, type); |
|
|
key_blobtype = type; |
key_blobtype = type; |
hostbased_cuser = cuser; |
hostbased_cuser = cuser; |
hostbased_chost = chost; |
hostbased_chost = chost; |
|
} else { |
|
/* Log failed attempt */ |
|
auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : ""); |
|
xfree(blob); |
|
xfree(cuser); |
|
xfree(chost); |
} |
} |
|
|
debug3("%s: key %p is %s", |
debug3("%s: key %p is %s", |
|
|
fromlen = sizeof(from); |
fromlen = sizeof(from); |
if (packet_connection_is_on_socket()) { |
if (packet_connection_is_on_socket()) { |
if (getpeername(packet_get_connection_in(), |
if (getpeername(packet_get_connection_in(), |
(struct sockaddr *) & from, &fromlen) < 0) { |
(struct sockaddr *)&from, &fromlen) < 0) { |
debug("getpeername: %.100s", strerror(errno)); |
debug("getpeername: %.100s", strerror(errno)); |
cleanup_exit(255); |
cleanup_exit(255); |
} |
} |
|
|
{ |
{ |
debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); |
debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); |
if (s->ttyfd != -1) { |
if (s->ttyfd != -1) { |
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); |
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); |
session_pty_cleanup2(s); |
session_pty_cleanup2(s); |
} |
} |
s->used = 0; |
s->used = 0; |
|
|
/* no need to dup() because nobody closes ptyfd */ |
/* no need to dup() because nobody closes ptyfd */ |
s->ptymaster = s->ptyfd; |
s->ptymaster = s->ptyfd; |
|
|
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); |
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); |
|
|
return (0); |
return (0); |
|
|
|
|
|
|
debug3("%s entering", __func__); |
debug3("%s entering", __func__); |
|
|
|
auth_method = "rsa"; |
if (options.rsa_authentication && authctxt->valid) { |
if (options.rsa_authentication && authctxt->valid) { |
if ((client_n = BN_new()) == NULL) |
if ((client_n = BN_new()) == NULL) |
fatal("%s: BN_new", __func__); |
fatal("%s: BN_new", __func__); |
|
|
void *blob; |
void *blob; |
u_int bloblen; |
u_int bloblen; |
|
|
kex = xmalloc(sizeof(*kex)); |
kex = xcalloc(1, sizeof(*kex)); |
memset(kex, 0, sizeof(*kex)); |
|
kex->session_id = buffer_get_string(m, &kex->session_id_len); |
kex->session_id = buffer_get_string(m, &kex->session_id_len); |
if ((session_id2 == NULL) || |
if ((session_id2 == NULL) || |
(kex->session_id_len != session_id2_len) || |
(kex->session_id_len != session_id2_len) || |
|
|
kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
|
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
kex->server = 1; |
kex->server = 1; |
kex->hostkey_type = buffer_get_int(m); |
kex->hostkey_type = buffer_get_int(m); |
kex->kex_type = buffer_get_int(m); |
kex->kex_type = buffer_get_int(m); |
|
|
struct monitor *mon; |
struct monitor *mon; |
int pair[2]; |
int pair[2]; |
|
|
mon = xmalloc(sizeof(*mon)); |
mon = xcalloc(1, sizeof(*mon)); |
|
|
mon->m_pid = 0; |
|
monitor_socketpair(pair); |
monitor_socketpair(pair); |
|
|
mon->m_recvfd = pair[0]; |
mon->m_recvfd = pair[0]; |