/* $OpenBSD: monitor_wrap.c,v 1.94 2017/10/02 19:33:20 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/uio.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef WITH_OPENSSL
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
#endif
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#ifdef WITH_OPENSSL
#include "dh.h"
#endif
#include "buffer.h"
#include "key.h"
#include "cipher.h"
#include "kex.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
#include "packet.h"
#include "mac.h"
#include "log.h"
#include "auth-pam.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"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "atomicio.h"
#include "monitor_fdpass.h"
#include "misc.h"
#include "uuencode.h"
#include "channels.h"
#include "session.h"
#include "servconf.h"
#include "ssherr.h"
/* Imports */
extern z_stream incoming_stream;
extern z_stream outgoing_stream;
extern struct monitor *pmonitor;
extern Buffer loginmsg;
extern ServerOptions options;
void
mm_log_handler(LogLevel level, const char *msg, void *ctx)
{
Buffer log_msg;
struct monitor *mon = (struct monitor *)ctx;
if (mon->m_log_sendfd == -1)
fatal("%s: no log channel", __func__);
buffer_init(&log_msg);
/*
* Placeholder for packet length. Will be filled in with the actual
* packet length once the packet has been constucted. This saves
* fragile math.
*/
buffer_put_int(&log_msg, 0);
buffer_put_int(&log_msg, level);
buffer_put_cstring(&log_msg, msg);
put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
buffer_len(&log_msg)) != buffer_len(&log_msg))
fatal("%s: write: %s", __func__, strerror(errno));
buffer_free(&log_msg);
}
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 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_u32(buf, mlen + 1);
buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
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 sock, Buffer *m)
{
u_char buf[4];
u_int msg_len;
debug3("%s entering", __func__);
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_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);
if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
fatal("%s: read: %s", __func__, strerro