version 1.68.2.2, 2006/11/08 00:17:14 |
version 1.69, 2006/03/07 09:07:40 |
|
|
/* $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 "xmalloc.h" |
#include <openssl/dh.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|MON_ALOG, mm_answer_rsa_keyallowed}, |
{MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed}, |
{MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed}, |
{MONITOR_REQ_KEYALLOWED, MON_ISAUTH, 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) == 1); |
|
if (authenticated) { |
if (authenticated) { |
if (!(ent->flags & MON_AUTHDECIDE)) |
if (!(ent->flags & MON_AUTHDECIDE)) |
fatal("%s: unexpected authentication from %d", |
fatal("%s: unexpected authentication from %d", |
|
|
authenticated = 0; |
authenticated = 0; |
} |
} |
|
|
if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { |
if (ent->flags & MON_AUTHDECIDE) { |
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); |
|
|
p = buffer_get_string(m, &datlen); |
p = buffer_get_string(m, &datlen); |
|
|
/* |
/* |
* Supported KEX types will only return SHA1 (20 byte) or |
* Supported KEX types will only return SHA1 (20 byte) or |
* SHA256 (32 byte) hashes |
* SHA256 (32 byte) hashes |
*/ |
*/ |
if (datlen != 20 && datlen != 32) |
if (datlen != 20 && datlen != 32) |
|
|
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", |
|
|
|
|
verified = key_verify(key, signature, signaturelen, data, datalen); |
verified = key_verify(key, signature, signaturelen, data, datalen); |
debug3("%s: key %p signature %s", |
debug3("%s: key %p signature %s", |
__func__, key, (verified == 1) ? "verified" : "unverified"); |
__func__, key, verified ? "verified" : "unverified"); |
|
|
key_free(key); |
key_free(key); |
xfree(blob); |
xfree(blob); |
|
|
buffer_put_int(m, verified); |
buffer_put_int(m, verified); |
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); |
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); |
|
|
return (verified == 1); |
return (verified); |
} |
} |
|
|
static void |
static void |
|
|
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 = xcalloc(1, sizeof(*kex)); |
kex = xmalloc(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) || |
|
|
struct monitor *mon; |
struct monitor *mon; |
int pair[2]; |
int pair[2]; |
|
|
mon = xcalloc(1, sizeof(*mon)); |
mon = xmalloc(sizeof(*mon)); |
|
|
|
mon->m_pid = 0; |
monitor_socketpair(pair); |
monitor_socketpair(pair); |
|
|
mon->m_recvfd = pair[0]; |
mon->m_recvfd = pair[0]; |