+/* $OpenBSD: monitor_wrap.c,v 1.48 2006/07/22 20:48:23 stevesk Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
*/
#include "includes.h"
-RCSID("$OpenBSD: monitor_wrap.c,v 1.30 2003/08/24 17:36:52 deraadt Exp $");
+
+#include <sys/types.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
+#include <errno.h>
+#include <pwd.h>
+#include <string.h>
+
#include "ssh.h"
#include "dh.h"
#include "kex.h"
#include "packet.h"
#include "mac.h"
#include "log.h"
+#ifdef TARGET_OS_MAC /* XXX Broken krb5 headers on Mac */
+#undef TARGET_OS_MAC
+#include "zlib.h"
+#define TARGET_OS_MAC 1
+#else
#include "zlib.h"
+#endif
#include "monitor.h"
#include "monitor_wrap.h"
#include "xmalloc.h"
#include "atomicio.h"
#include "monitor_fdpass.h"
-#include "getput.h"
+#include "misc.h"
#include "servconf.h"
#include "auth.h"
extern z_stream outgoing_stream;
extern struct monitor *pmonitor;
extern Buffer input, output;
+extern Buffer loginmsg;
extern ServerOptions options;
+int
+mm_is_monitor(void)
+{
+ /*
+ * m_pid is only set in the privileged part, and
+ * points to the unprivileged child.
+ */
+ return (pmonitor && pmonitor->m_pid > 0);
+}
+
void
-mm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
+mm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
{
u_int mlen = buffer_len(m);
u_char buf[5];
debug3("%s entering: type %d", __func__, type);
- PUT_32BIT(buf, mlen + 1);
+ put_u32(buf, mlen + 1);
buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
- if (atomicio(vwrite, socket, buf, sizeof(buf)) != sizeof(buf))
- fatal("%s: write", __func__);
- if (atomicio(vwrite, socket, buffer_ptr(m), mlen) != mlen)
- fatal("%s: write", __func__);
+ if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
+ fatal("%s: write: %s", __func__, strerror(errno));
+ if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
+ fatal("%s: write: %s", __func__, strerror(errno));
}
void
-mm_request_receive(int socket, Buffer *m)
+mm_request_receive(int sock, Buffer *m)
{
u_char buf[4];
u_int msg_len;
- ssize_t res;
debug3("%s entering", __func__);
- res = atomicio(read, socket, buf, sizeof(buf));
- if (res != sizeof(buf)) {
- if (res == 0)
- fatal_cleanup();
- fatal("%s: read: %ld", __func__, (long)res);
+ if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
+ if (errno == EPIPE)
+ cleanup_exit(255);
+ fatal("%s: read: %s", __func__, strerror(errno));
}
- msg_len = GET_32BIT(buf);
+ msg_len = get_u32(buf);
if (msg_len > 256 * 1024)
fatal("%s: read: bad msg_len %d", __func__, msg_len);
buffer_clear(m);
buffer_append_space(m, msg_len);
- res = atomicio(read, socket, buffer_ptr(m), msg_len);
- if (res != msg_len)
- fatal("%s: read: %ld != msg_len", __func__, (long)res);
+ if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
+ fatal("%s: read: %s", __func__, strerror(errno));
}
void
-mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
+mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
{
u_char rtype;
debug3("%s entering: type %d", __func__, type);
- mm_request_receive(socket, m);
+ mm_request_receive(sock, m);
rtype = buffer_get_char(m);
if (rtype != type)
fatal("%s: read: rtype %d != type %d", __func__,
}
struct passwd *
-mm_getpwnamallow(const char *login)
+mm_getpwnamallow(const char *username)
{
Buffer m;
struct passwd *pw;
debug3("%s entering", __func__);
buffer_init(&m);
- buffer_put_cstring(&m, login);
+ buffer_put_cstring(&m, username);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
return (pw);
}
-char *mm_auth2_read_banner(void)
+char *
+mm_auth2_read_banner(void)
{
Buffer m;
char *banner;
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
buffer_clear(&m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_AUTH2_READ_BANNER, &m);
banner = buffer_get_string(&m, NULL);
buffer_free(&m);
+ /* treat empty banner as missing banner */
+ if (strlen(banner) == 0) {
+ xfree(banner);
+ banner = NULL;
+ }
return (banner);
}
}
void
-mm_send_keystate(struct monitor *pmonitor)
+mm_send_keystate(struct monitor *monitor)
{
Buffer m;
u_char *blob, *p;
goto skip;
} else {
/* Kex for rekeying */
- mm_send_kex(&m, *pmonitor->m_pkex);
+ mm_send_kex(&m, *monitor->m_pkex);
}
debug3("%s: Sending new keys: %p %p",
buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
+ mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
debug3("%s: Finished sending state", __func__);
buffer_free(&m);
}
int
-mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
+mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
{
Buffer m;
- char *p;
+ char *p, *msg;
int success = 0;
buffer_init(&m);
return (0);
}
p = buffer_get_string(&m, NULL);
+ msg = buffer_get_string(&m, NULL);
buffer_free(&m);
strlcpy(namebuf, p, namebuflen); /* Possible truncation */
xfree(p);
+ buffer_append(&loginmsg, msg, strlen(msg));
+ xfree(msg);
+
*ptyfd = mm_receive_fd(pmonitor->m_recvfd);
*ttyfd = mm_receive_fd(pmonitor->m_recvfd);
}
void
-mm_session_pty_cleanup2(void *session)
+mm_session_pty_cleanup2(Session *s)
{
- Session *s = session;
Buffer m;
if (s->ttyfd == -1)
#ifdef USE_PAM
void
-mm_start_pam(char *user)
+mm_start_pam(Authctxt *authctxt)
{
Buffer m;
fatal("UsePAM=no, but ended up in %s anyway", __func__);
buffer_init(&m);
- buffer_put_cstring(&m, user);
-
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
buffer_free(&m);
{
Buffer m;
u_int ret;
+ char *msg;
debug3("%s entering", __func__);
if (!options.use_pam)
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
- mm_request_receive_expect(pmonitor->m_recvfd,
+ mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_PAM_ACCOUNT, &m);
ret = buffer_get_int(&m);
+ msg = buffer_get_string(&m, NULL);
+ buffer_append(&loginmsg, msg, strlen(msg));
+ xfree(msg);
buffer_free(&m);
-
+
debug3("%s returning %d", __func__, ret);
return (ret);
u_int *num, char ***prompts, u_int **echo_on)
{
Buffer m;
- int i, ret;
+ u_int i;
+ int ret;
debug3("%s", __func__);
buffer_init(&m);
*name = buffer_get_string(&m, NULL);
*info = buffer_get_string(&m, NULL);
*num = buffer_get_int(&m);
- *prompts = xmalloc((*num + 1) * sizeof(char *));
- *echo_on = xmalloc((*num + 1) * sizeof(u_int));
+ if (*num > PAM_MAX_NUM_MSG)
+ fatal("%s: recieved %u PAM messages, expected <= %u",
+ __func__, *num, PAM_MAX_NUM_MSG);
+ *prompts = xcalloc((*num + 1), sizeof(char *));
+ *echo_on = xcalloc((*num + 1), sizeof(u_int));
for (i = 0; i < *num; ++i) {
(*prompts)[i] = buffer_get_string(&m, NULL);
(*echo_on)[i] = buffer_get_int(&m);
mm_sshpam_respond(void *ctx, u_int num, char **resp)
{
Buffer m;
- int i, ret;
+ u_int i;
+ int ret;
debug3("%s", __func__);
buffer_init(&m);
*name = xstrdup("");
*infotxt = xstrdup("");
*numprompts = 1;
- *prompts = xmalloc(*numprompts * sizeof(char *));
- *echo_on = xmalloc(*numprompts * sizeof(u_int));
+ *prompts = xcalloc(*numprompts, sizeof(char *));
+ *echo_on = xcalloc(*numprompts, sizeof(u_int));
(*echo_on)[0] = 0;
}
return ((authok == 0) ? -1 : 0);
}
+#ifdef SKEY
int
mm_skey_query(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on)
mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
- len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
- p = xmalloc(len);
- strlcpy(p, challenge, len);
- strlcat(p, SKEY_PROMPT, len);
- (*prompts)[0] = p;
+ xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
xfree(challenge);
return (0);
return ((authok == 0) ? -1 : 0);
}
+#endif /* SKEY */
void
mm_ssh1_session_id(u_char session_id[16])
return (success);
}
-#ifdef KRB5
-int
-mm_auth_krb5(void *ctx, void *argp, char **userp, void *resp)
+#ifdef SSH_AUDIT_EVENTS
+void
+mm_audit_event(ssh_audit_event_t event)
{
- krb5_data *tkt, *reply;
Buffer m;
- int success;
debug3("%s entering", __func__);
- tkt = (krb5_data *) argp;
- reply = (krb5_data *) resp;
buffer_init(&m);
- buffer_put_string(&m, tkt->data, tkt->length);
+ buffer_put_int(&m, event);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
+ buffer_free(&m);
+}
- mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5, &m);
- mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5, &m);
+void
+mm_audit_run_command(const char *command)
+{
+ Buffer m;
- success = buffer_get_int(&m);
- if (success) {
- u_int len;
+ debug3("%s entering command %s", __func__, command);
- *userp = buffer_get_string(&m, NULL);
- reply->data = buffer_get_string(&m, &len);
- reply->length = len;
- } else {
- memset(reply, 0, sizeof(*reply));
- *userp = NULL;
- }
+ buffer_init(&m);
+ buffer_put_cstring(&m, command);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
buffer_free(&m);
- return (success);
}
-#endif /* KRB5 */
+#endif /* SSH_AUDIT_EVENTS */
#ifdef GSSAPI
OM_uint32
-mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
+mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
{
Buffer m;
OM_uint32 major;
*ctx = NULL;
buffer_init(&m);
- buffer_put_string(&m, oid->elements, oid->length);
+ buffer_put_string(&m, goid->elements, goid->length);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
return (major);
}
+OM_uint32
+mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+{
+ Buffer m;
+ OM_uint32 major;
+
+ buffer_init(&m);
+ buffer_put_string(&m, gssbuf->value, gssbuf->length);
+ buffer_put_string(&m, gssmic->value, gssmic->length);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
+ &m);
+
+ major = buffer_get_int(&m);
+ buffer_free(&m);
+ return(major);
+}
+
int
mm_ssh_gssapi_userok(char *user)
{