+/* $OpenBSD: monitor.c,v 1.89 2006/11/07 10:31:31 markus Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
*/
#include "includes.h"
-RCSID("$OpenBSD: monitor.c,v 1.62 2005/01/30 11:18:08 dtucker Exp $");
-#include <openssl/dh.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include "openbsd-compat/sys-tree.h"
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#ifdef SKEY
#include <skey.h>
#endif
+#include <openssl/dh.h>
+
+#include "xmalloc.h"
#include "ssh.h"
+#include "key.h"
+#include "buffer.h"
+#include "hostfile.h"
#include "auth.h"
+#include "cipher.h"
#include "kex.h"
#include "dh.h"
#ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */
#include "servconf.h"
#include "monitor.h"
#include "monitor_mm.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
#include "monitor_wrap.h"
#include "monitor_fdpass.h"
-#include "xmalloc.h"
#include "misc.h"
-#include "buffer.h"
-#include "bufaux.h"
#include "compat.h"
#include "ssh2.h"
#ifdef GSSAPI
-#include "ssh-gss.h"
static Gssctxt *gsscontext = NULL;
#endif
int mm_answer_gss_accept_ctx(int, Buffer *);
int mm_answer_gss_userok(int, Buffer *);
int mm_answer_gss_checkmic(int, Buffer *);
-#endif
-
-#ifdef GSSAPI
-int mm_answer_gss_setup_ctx(int, Buffer *);
-int mm_answer_gss_accept_ctx(int, Buffer *);
-int mm_answer_gss_userok(int, Buffer *);
int mm_answer_gss_sign(int, Buffer *);
int mm_answer_gss_error(int, Buffer *);
int mm_answer_gss_indicate_mechs(int, Buffer *);
#define MON_ISAUTH 0x0004 /* Required for Authentication */
#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */
#define MON_ONCE 0x0010 /* Disable after calling */
+#define MON_ALOG 0x0020 /* Log auth attempt without authenticating */
#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE)
#endif
#ifdef BSD_AUTH
{MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
- {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
+ {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
#endif
#ifdef SKEY
{MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
{MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
{MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
{MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
+ {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
{MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
{MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error},
{MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs},
{MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname},
- {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
#endif
{0, 0, NULL}
};
{MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
{MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
- {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed},
- {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
+ {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed},
+ {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed},
{MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
{MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
#ifdef BSD_AUTH
{MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
- {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
+ {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
#endif
#ifdef SKEY
{MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#ifdef SSH_AUDIT_EVENTS
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
- {MONITOR_REQ_AUDIT_COMMAND, MON_ONCE, mm_answer_audit_command},
+ {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
#endif
{0, 0, NULL}
};
authctxt = _authctxt;
memset(authctxt, 0, sizeof(*authctxt));
+ authctxt->loginmsg = &loginmsg;
+
if (compat20) {
mon_dispatch = mon_dispatch_proto20;
/* The first few requests do not require asynchronous access */
while (!authenticated) {
- authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
+ auth_method = "unknown";
+ authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
if (authenticated) {
if (!(ent->flags & MON_AUTHDECIDE))
fatal("%s: unexpected authentication from %d",
#endif
}
- if (ent->flags & MON_AUTHDECIDE) {
+ if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
auth_log(authctxt, authenticated, auth_method,
compat20 ? " ssh2" : "");
if (!authenticated)
if (!authctxt->valid)
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",
__func__, authctxt->user);
keyid = buffer_get_int(m);
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);
/* save session id, it will be passed on the first call */
if (options.use_pam)
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
#endif
-#ifdef SSH_AUDIT_EVENTS
- monitor_permit(mon_dispatch, MONITOR_REQ_AUDIT_COMMAND, 1);
-#endif
return (0);
}
ret = do_pam_account();
buffer_put_int(m, ret);
- buffer_append(&loginmsg, "\0", 1);
- buffer_put_cstring(m, buffer_ptr(&loginmsg));
- buffer_clear(&loginmsg);
+ buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m);
mm_answer_pam_query(int sock, Buffer *m)
{
char *name, *info, **prompts;
- u_int num, *echo_on;
- int i, ret;
+ u_int i, num, *echo_on;
+ int ret;
debug3("%s", __func__);
sshpam_authok = NULL;
xfree(prompts);
if (echo_on != NULL)
xfree(echo_on);
+ auth_method = "keyboard-interactive/pam";
mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
return (0);
}
mm_answer_pam_respond(int sock, Buffer *m)
{
char **resp;
- u_int num;
- int i, ret;
+ u_int i, num;
+ int ret;
debug3("%s", __func__);
sshpam_authok = NULL;
num = buffer_get_int(m);
if (num > 0) {
- resp = xmalloc(num * sizeof(char *));
+ resp = xcalloc(num, sizeof(char *));
for (i = 0; i < num; ++i)
resp[i] = buffer_get_string(m, NULL);
ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
(sshpam_device.free_ctx)(sshpam_ctxt);
buffer_clear(m);
mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
+ auth_method = "keyboard-interactive/pam";
return (sshpam_authok == sshpam_ctxt);
}
#endif
debug3("%s: key_from_blob: %p", __func__, key);
if (key != NULL && authctxt->valid) {
- switch(type) {
+ switch (type) {
case MM_USERKEY:
allowed = options.pubkey_authentication &&
user_key_allowed(authctxt->pw, key);
+ auth_method = "publickey";
break;
case MM_HOSTKEY:
allowed = options.hostbased_authentication &&
hostbased_key_allowed(authctxt->pw,
cuser, chost, key);
+ auth_method = "hostbased";
break;
case MM_RSAHOSTKEY:
key->type = KEY_RSA1; /* XXX */
allowed = options.rhosts_rsa_authentication &&
auth_rhosts_rsa_key_allowed(authctxt->pw,
cuser, chost, key);
+ auth_method = "rsa";
break;
default:
fatal("%s: unknown key type %d", __func__, type);
key_blobtype = type;
hostbased_cuser = cuser;
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",
verified = key_verify(key, signature, signaturelen, data, datalen);
debug3("%s: key %p signature %s",
- __func__, key, verified ? "verified" : "unverified");
+ __func__, key, (verified == 1) ? "verified" : "unverified");
key_free(key);
xfree(blob);
buffer_put_int(m, verified);
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
- return (verified);
+ return (verified == 1);
}
static void
fromlen = sizeof(from);
if (packet_connection_is_on_socket()) {
if (getpeername(packet_get_connection_in(),
- (struct sockaddr *) & from, &fromlen) < 0) {
+ (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername: %.100s", strerror(errno));
cleanup_exit(255);
}
{
debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);
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);
}
s->used = 0;
/* no need to dup() because nobody closes 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);
debug3("%s entering", __func__);
+ auth_method = "rsa";
if (options.rsa_authentication && authctxt->valid) {
if ((client_n = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
debug3("%s entering", __func__);
event = buffer_get_int(m);
- buffer_free(m);
switch(event) {
case SSH_AUTH_FAIL_PUBKEY:
case SSH_AUTH_FAIL_HOSTBASED:
/* sanity check command, if so how? */
audit_run_command(cmd);
xfree(cmd);
- buffer_free(m);
return (0);
}
#endif /* SSH_AUDIT_EVENTS */
void *blob;
u_int bloblen;
- kex = xmalloc(sizeof(*kex));
- memset(kex, 0, sizeof(*kex));
+ kex = xcalloc(1, sizeof(*kex));
kex->session_id = buffer_get_string(m, &kex->session_id_len);
if ((session_id2 == NULL) ||
(kex->session_id_len != session_id2_len) ||
kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+ kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
#ifdef GSSAPI
kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
#endif
kex->server = 1;
kex->hostkey_type = buffer_get_int(m);
struct monitor *mon;
int pair[2];
- mon = xmalloc(sizeof(*mon));
+ mon = xcalloc(1, sizeof(*mon));
- mon->m_pid = 0;
monitor_socketpair(pair);
mon->m_recvfd = pair[0];
buffer_clear(m);
buffer_put_int(m, major);
- mm_request_send(sock,MONITOR_ANS_GSSSETUP, m);
+ mm_request_send(sock, MONITOR_ANS_GSSSETUP, m);
/* Now we have a context, enable the step */
monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1);
{
gss_buffer_desc in;
gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
- OM_uint32 major,minor;
+ OM_uint32 major, minor;
OM_uint32 flags = 0; /* GSI needs this */
u_int len;
gss_release_buffer(&minor, &out);
- if (major==GSS_S_COMPLETE) {
+ if (major == GSS_S_COMPLETE) {
monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
}
return (0);
}
debug3("%s: sending result %d", __func__, authenticated);
mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
- auth_method="gssapi-with-mic";
+ auth_method = "gssapi-with-mic";
/* Monitor loop will terminate if authenticated */
return (authenticated);
}
-int
-mm_answer_gss_sign(int socket, Buffer *m) {
- gss_buffer_desc data,hash;
- OM_uint32 major,minor;
+int
+mm_answer_gss_sign(int socket, Buffer *m)
+{
+ gss_buffer_desc data;
+ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
+ OM_uint32 major, minor;
u_int len;
- data.value = buffer_get_string(m, &len);
+ data.value = buffer_get_string(m, &len);
data.length = len;
- if (data.length != 20)
- fatal("%s: data length incorrect: %d", __func__,
- (int)data.length);
+ if (data.length != 20)
+ fatal("%s: data length incorrect: %d", __func__, data.length);
- /* Save the session ID - only first time round */
- if (session_id2_len == 0) {
- session_id2_len=data.length;
- session_id2 = xmalloc(session_id2_len);
- memcpy(session_id2, data.value, session_id2_len);
- }
- major=ssh_gssapi_sign(gsscontext, &data, &hash);
+ /* Save the session ID on the first time around */
+ if (session_id2_len == 0) {
+ session_id2_len = data.length;
+ session_id2 = xmalloc(session_id2_len);
+ memcpy(session_id2, data.value, session_id2_len);
+ }
+ major = ssh_gssapi_sign(gsscontext, &data, &hash);
- xfree(data.value);
+ xfree(data.value);
- buffer_clear(m);
- buffer_put_int(m, major);
- buffer_put_string(m, hash.value, hash.length);
+ buffer_clear(m);
+ buffer_put_int(m, major);
+ buffer_put_string(m, hash.value, hash.length);
- mm_request_send(socket,MONITOR_ANS_GSSSIGN,m);
+ mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
- gss_release_buffer(&minor,&hash);
+ gss_release_buffer(&minor, &hash);
- /* Turn on permissions for getpwnam */
+ /* Turn on getpwnam permissions */
monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
-
- return(0);
+
+ return (0);
}
int
mm_answer_gss_indicate_mechs(int socket, Buffer *m) {
OM_uint32 major,minor;
gss_OID_set mech_set;
- int i;
+ size_t i;
major=gss_indicate_mechs(&minor, &mech_set);