2024-06-11 04:54:51 +02:00
|
|
|
/* $OpenBSD: monitor_wrap.c,v 1.135 2024/06/11 02:54:51 djm Exp $ */
|
2002-03-22 03:30:41 +01:00
|
|
|
/*
|
|
|
|
* 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"
|
|
|
|
|
2006-07-10 12:53:08 +02:00
|
|
|
#include <sys/types.h>
|
2006-08-05 10:46:47 +02:00
|
|
|
#include <sys/uio.h>
|
upstream: Add a facility to sshd(8) to penalise particular
problematic client behaviours, controlled by two new sshd_config(5) options:
PerSourcePenalties and PerSourcePenaltyExemptList.
When PerSourcePenalties are enabled, sshd(8) will monitor the exit
status of its child pre-auth session processes. Through the exit
status, it can observe situations where the session did not
authenticate as expected. These conditions include when the client
repeatedly attempted authentication unsucessfully (possibly indicating
an attack against one or more accounts, e.g. password guessing), or
when client behaviour caused sshd to crash (possibly indicating
attempts to exploit sshd).
When such a condition is observed, sshd will record a penalty of some
duration (e.g. 30 seconds) against the client's address. If this time
is above a minimum threshold specified by the PerSourcePenalties, then
connections from the client address will be refused (along with any
others in the same PerSourceNetBlockSize CIDR range).
Repeated offenses by the same client address will accrue greater
penalties, up to a configurable maximum. A PerSourcePenaltyExemptList
option allows certain address ranges to be exempt from all penalties.
We hope these options will make it significantly more difficult for
attackers to find accounts with weak/guessable passwords or exploit
bugs in sshd(8) itself.
PerSourcePenalties is off by default, but we expect to enable it
automatically in the near future.
much feedback markus@ and others, ok markus@
OpenBSD-Commit-ID: 89ded70eccb2b4926ef0366a4d58a693de366cca
2024-06-06 19:15:25 +02:00
|
|
|
#include <sys/wait.h>
|
2006-07-10 12:53:08 +02:00
|
|
|
|
2006-07-12 14:22:46 +02:00
|
|
|
#include <errno.h>
|
2006-07-10 12:53:08 +02:00
|
|
|
#include <pwd.h>
|
2006-08-05 04:39:39 +02:00
|
|
|
#include <signal.h>
|
2006-09-01 07:38:36 +02:00
|
|
|
#include <stdarg.h>
|
2006-08-05 03:37:59 +02:00
|
|
|
#include <stdio.h>
|
2006-07-24 06:13:33 +02:00
|
|
|
#include <string.h>
|
2006-08-05 10:46:47 +02:00
|
|
|
#include <unistd.h>
|
2006-07-10 12:53:08 +02:00
|
|
|
|
2014-05-15 06:24:09 +02:00
|
|
|
#ifdef WITH_OPENSSL
|
2006-08-05 04:39:39 +02:00
|
|
|
#include <openssl/bn.h>
|
|
|
|
#include <openssl/dh.h>
|
2008-11-05 06:20:46 +01:00
|
|
|
#include <openssl/evp.h>
|
2014-05-15 06:24:09 +02:00
|
|
|
#endif
|
2006-08-05 04:39:39 +02:00
|
|
|
|
2008-05-19 07:05:07 +02:00
|
|
|
#include "openbsd-compat/sys-queue.h"
|
2006-08-05 04:39:39 +02:00
|
|
|
#include "xmalloc.h"
|
2002-03-22 03:30:41 +01:00
|
|
|
#include "ssh.h"
|
2014-05-15 06:24:09 +02:00
|
|
|
#ifdef WITH_OPENSSL
|
2002-03-22 03:30:41 +01:00
|
|
|
#include "dh.h"
|
2014-05-15 06:24:09 +02:00
|
|
|
#endif
|
2018-07-09 23:53:45 +02:00
|
|
|
#include "sshbuf.h"
|
2018-07-11 20:53:29 +02:00
|
|
|
#include "sshkey.h"
|
2006-08-05 04:39:39 +02:00
|
|
|
#include "cipher.h"
|
2002-03-22 03:30:41 +01:00
|
|
|
#include "kex.h"
|
2006-08-05 04:39:39 +02:00
|
|
|
#include "hostfile.h"
|
2002-03-22 03:30:41 +01:00
|
|
|
#include "auth.h"
|
2003-02-24 02:03:38 +01:00
|
|
|
#include "auth-options.h"
|
2002-03-22 03:30:41 +01:00
|
|
|
#include "packet.h"
|
|
|
|
#include "mac.h"
|
|
|
|
#include "log.h"
|
2016-07-18 01:33:25 +02:00
|
|
|
#include "auth-pam.h"
|
2002-03-22 03:30:41 +01:00
|
|
|
#include "monitor.h"
|
2006-08-05 04:39:39 +02:00
|
|
|
#ifdef GSSAPI
|
|
|
|
#include "ssh-gss.h"
|
|
|
|
#endif
|
2002-03-22 03:30:41 +01:00
|
|
|
#include "atomicio.h"
|
|
|
|
#include "monitor_fdpass.h"
|
2006-03-31 14:13:02 +02:00
|
|
|
#include "misc.h"
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
#include "channels.h"
|
|
|
|
#include "session.h"
|
2007-02-19 12:25:37 +01:00
|
|
|
#include "servconf.h"
|
2024-05-17 02:30:23 +02:00
|
|
|
#include "monitor_wrap.h"
|
upstream: Add a facility to sshd(8) to penalise particular
problematic client behaviours, controlled by two new sshd_config(5) options:
PerSourcePenalties and PerSourcePenaltyExemptList.
When PerSourcePenalties are enabled, sshd(8) will monitor the exit
status of its child pre-auth session processes. Through the exit
status, it can observe situations where the session did not
authenticate as expected. These conditions include when the client
repeatedly attempted authentication unsucessfully (possibly indicating
an attack against one or more accounts, e.g. password guessing), or
when client behaviour caused sshd to crash (possibly indicating
attempts to exploit sshd).
When such a condition is observed, sshd will record a penalty of some
duration (e.g. 30 seconds) against the client's address. If this time
is above a minimum threshold specified by the PerSourcePenalties, then
connections from the client address will be refused (along with any
others in the same PerSourceNetBlockSize CIDR range).
Repeated offenses by the same client address will accrue greater
penalties, up to a configurable maximum. A PerSourcePenaltyExemptList
option allows certain address ranges to be exempt from all penalties.
We hope these options will make it significantly more difficult for
attackers to find accounts with weak/guessable passwords or exploit
bugs in sshd(8) itself.
PerSourcePenalties is off by default, but we expect to enable it
automatically in the near future.
much feedback markus@ and others, ok markus@
OpenBSD-Commit-ID: 89ded70eccb2b4926ef0366a4d58a693de366cca
2024-06-06 19:15:25 +02:00
|
|
|
#include "srclimit.h"
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2015-01-19 20:52:16 +01:00
|
|
|
#include "ssherr.h"
|
|
|
|
|
2002-03-22 03:30:41 +01:00
|
|
|
/* Imports */
|
2002-05-15 18:25:01 +02:00
|
|
|
extern struct monitor *pmonitor;
|
2018-07-09 23:26:02 +02:00
|
|
|
extern struct sshbuf *loginmsg;
|
2003-05-14 07:11:48 +02:00
|
|
|
extern ServerOptions options;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2011-06-20 06:42:23 +02:00
|
|
|
void
|
2021-04-15 18:24:31 +02:00
|
|
|
mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx)
|
2011-06-20 06:42:23 +02:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *log_msg;
|
2011-06-20 06:42:23 +02:00
|
|
|
struct monitor *mon = (struct monitor *)ctx;
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
|
|
|
size_t len;
|
2011-06-20 06:42:23 +02:00
|
|
|
|
|
|
|
if (mon->m_log_sendfd == -1)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("no log channel");
|
2011-06-20 06:42:23 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((log_msg = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2011-06-20 06:42:23 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */
|
|
|
|
(r = sshbuf_put_u32(log_msg, level)) != 0 ||
|
2021-04-15 18:24:31 +02:00
|
|
|
(r = sshbuf_put_u32(log_msg, forced)) != 0 ||
|
2018-07-09 23:53:45 +02:00
|
|
|
(r = sshbuf_put_cstring(log_msg, msg)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("bad length %zu", len);
|
2018-07-09 23:53:45 +02:00
|
|
|
POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4);
|
|
|
|
if (atomicio(vwrite, mon->m_log_sendfd,
|
|
|
|
sshbuf_mutable_ptr(log_msg), len) != len)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("write: %s", strerror(errno));
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(log_msg);
|
2011-06-20 06:42:23 +02:00
|
|
|
}
|
|
|
|
|
2003-10-02 08:12:36 +02:00
|
|
|
int
|
|
|
|
mm_is_monitor(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* m_pid is only set in the privileged part, and
|
|
|
|
* points to the unprivileged child.
|
|
|
|
*/
|
2003-11-03 10:03:25 +01:00
|
|
|
return (pmonitor && pmonitor->m_pid > 0);
|
2003-10-02 08:12:36 +02:00
|
|
|
}
|
|
|
|
|
2024-06-11 04:54:51 +02:00
|
|
|
void
|
|
|
|
mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
|
|
|
|
{
|
|
|
|
size_t mlen = sshbuf_len(m);
|
|
|
|
u_char buf[5];
|
|
|
|
|
|
|
|
debug3_f("entering, type %d", type);
|
|
|
|
|
|
|
|
if (mlen >= 0xffffffff)
|
|
|
|
fatal_f("bad length %zu", mlen);
|
|
|
|
POKE_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_f("write: %s", strerror(errno));
|
|
|
|
if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen)
|
|
|
|
fatal_f("write: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
|
upstream: Add a facility to sshd(8) to penalise particular
problematic client behaviours, controlled by two new sshd_config(5) options:
PerSourcePenalties and PerSourcePenaltyExemptList.
When PerSourcePenalties are enabled, sshd(8) will monitor the exit
status of its child pre-auth session processes. Through the exit
status, it can observe situations where the session did not
authenticate as expected. These conditions include when the client
repeatedly attempted authentication unsucessfully (possibly indicating
an attack against one or more accounts, e.g. password guessing), or
when client behaviour caused sshd to crash (possibly indicating
attempts to exploit sshd).
When such a condition is observed, sshd will record a penalty of some
duration (e.g. 30 seconds) against the client's address. If this time
is above a minimum threshold specified by the PerSourcePenalties, then
connections from the client address will be refused (along with any
others in the same PerSourceNetBlockSize CIDR range).
Repeated offenses by the same client address will accrue greater
penalties, up to a configurable maximum. A PerSourcePenaltyExemptList
option allows certain address ranges to be exempt from all penalties.
We hope these options will make it significantly more difficult for
attackers to find accounts with weak/guessable passwords or exploit
bugs in sshd(8) itself.
PerSourcePenalties is off by default, but we expect to enable it
automatically in the near future.
much feedback markus@ and others, ok markus@
OpenBSD-Commit-ID: 89ded70eccb2b4926ef0366a4d58a693de366cca
2024-06-06 19:15:25 +02:00
|
|
|
static void
|
|
|
|
mm_reap(void)
|
|
|
|
{
|
|
|
|
int status = -1;
|
|
|
|
|
|
|
|
if (!mm_is_monitor())
|
|
|
|
return;
|
|
|
|
while (waitpid(pmonitor->m_pid, &status, 0) == -1) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
pmonitor->m_pid = -1;
|
|
|
|
fatal_f("waitpid: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
if (WIFEXITED(status)) {
|
|
|
|
if (WEXITSTATUS(status) != 0) {
|
|
|
|
debug_f("preauth child exited with status %d",
|
|
|
|
WEXITSTATUS(status));
|
|
|
|
cleanup_exit(255);
|
|
|
|
}
|
|
|
|
} else if (WIFSIGNALED(status)) {
|
|
|
|
error_f("preauth child terminated by signal %d",
|
|
|
|
WTERMSIG(status));
|
|
|
|
cleanup_exit(signal_is_crash(WTERMSIG(status)) ?
|
|
|
|
EXIT_CHILD_CRASH : 255);
|
|
|
|
} else {
|
2024-06-11 02:40:21 +02:00
|
|
|
error_f("preauth child terminated abnormally (status=0x%x)",
|
|
|
|
status);
|
upstream: Add a facility to sshd(8) to penalise particular
problematic client behaviours, controlled by two new sshd_config(5) options:
PerSourcePenalties and PerSourcePenaltyExemptList.
When PerSourcePenalties are enabled, sshd(8) will monitor the exit
status of its child pre-auth session processes. Through the exit
status, it can observe situations where the session did not
authenticate as expected. These conditions include when the client
repeatedly attempted authentication unsucessfully (possibly indicating
an attack against one or more accounts, e.g. password guessing), or
when client behaviour caused sshd to crash (possibly indicating
attempts to exploit sshd).
When such a condition is observed, sshd will record a penalty of some
duration (e.g. 30 seconds) against the client's address. If this time
is above a minimum threshold specified by the PerSourcePenalties, then
connections from the client address will be refused (along with any
others in the same PerSourceNetBlockSize CIDR range).
Repeated offenses by the same client address will accrue greater
penalties, up to a configurable maximum. A PerSourcePenaltyExemptList
option allows certain address ranges to be exempt from all penalties.
We hope these options will make it significantly more difficult for
attackers to find accounts with weak/guessable passwords or exploit
bugs in sshd(8) itself.
PerSourcePenalties is off by default, but we expect to enable it
automatically in the near future.
much feedback markus@ and others, ok markus@
OpenBSD-Commit-ID: 89ded70eccb2b4926ef0366a4d58a693de366cca
2024-06-06 19:15:25 +02:00
|
|
|
cleanup_exit(EXIT_CHILD_CRASH);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-03-22 03:30:41 +01:00
|
|
|
void
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive(int sock, struct sshbuf *m)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
u_char buf[4], *p = NULL;
|
2002-03-22 03:30:41 +01:00
|
|
|
u_int msg_len;
|
2024-06-11 04:54:51 +02:00
|
|
|
int oerrno, r;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2005-05-26 04:23:44 +02:00
|
|
|
if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
|
2024-05-17 02:30:23 +02:00
|
|
|
if (errno == EPIPE) {
|
|
|
|
debug3_f("monitor fd closed");
|
upstream: Add a facility to sshd(8) to penalise particular
problematic client behaviours, controlled by two new sshd_config(5) options:
PerSourcePenalties and PerSourcePenaltyExemptList.
When PerSourcePenalties are enabled, sshd(8) will monitor the exit
status of its child pre-auth session processes. Through the exit
status, it can observe situations where the session did not
authenticate as expected. These conditions include when the client
repeatedly attempted authentication unsucessfully (possibly indicating
an attack against one or more accounts, e.g. password guessing), or
when client behaviour caused sshd to crash (possibly indicating
attempts to exploit sshd).
When such a condition is observed, sshd will record a penalty of some
duration (e.g. 30 seconds) against the client's address. If this time
is above a minimum threshold specified by the PerSourcePenalties, then
connections from the client address will be refused (along with any
others in the same PerSourceNetBlockSize CIDR range).
Repeated offenses by the same client address will accrue greater
penalties, up to a configurable maximum. A PerSourcePenaltyExemptList
option allows certain address ranges to be exempt from all penalties.
We hope these options will make it significantly more difficult for
attackers to find accounts with weak/guessable passwords or exploit
bugs in sshd(8) itself.
PerSourcePenalties is off by default, but we expect to enable it
automatically in the near future.
much feedback markus@ and others, ok markus@
OpenBSD-Commit-ID: 89ded70eccb2b4926ef0366a4d58a693de366cca
2024-06-06 19:15:25 +02:00
|
|
|
mm_reap();
|
2003-10-02 08:12:36 +02:00
|
|
|
cleanup_exit(255);
|
2024-05-17 02:30:23 +02:00
|
|
|
}
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("read: %s", strerror(errno));
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
2018-07-09 23:53:45 +02:00
|
|
|
msg_len = PEEK_U32(buf);
|
2002-03-22 03:30:41 +01:00
|
|
|
if (msg_len > 256 * 1024)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("read: bad msg_len %d", msg_len);
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_reset(m);
|
|
|
|
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "reserve");
|
2024-06-11 02:44:52 +02:00
|
|
|
if (atomicio(read, sock, p, msg_len) != msg_len) {
|
2024-06-11 04:54:51 +02:00
|
|
|
oerrno = errno;
|
|
|
|
error_f("read: %s", strerror(errno));
|
|
|
|
if (oerrno == EPIPE)
|
2024-06-11 02:44:52 +02:00
|
|
|
mm_reap();
|
2024-06-11 04:54:51 +02:00
|
|
|
cleanup_exit(255);
|
2024-06-11 02:44:52 +02:00
|
|
|
}
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
|
|
|
u_char rtype;
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering, type %d", type);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2004-06-22 04:56:01 +02:00
|
|
|
mm_request_receive(sock, m);
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u8(m, &rtype)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2002-03-22 03:30:41 +01:00
|
|
|
if (rtype != type)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("read: rtype %d != type %d", rtype, type);
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
2014-05-15 06:24:09 +02:00
|
|
|
#ifdef WITH_OPENSSL
|
2002-03-22 03:30:41 +01:00
|
|
|
DH *
|
|
|
|
mm_choose_dh(int min, int nbits, int max)
|
|
|
|
{
|
|
|
|
BIGNUM *p, *g;
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
|
|
|
u_char success = 0;
|
|
|
|
struct sshbuf *m;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_u32(m, min)) != 0 ||
|
|
|
|
(r = sshbuf_put_u32(m, nbits)) != 0 ||
|
|
|
|
(r = sshbuf_put_u32(m, max)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("waiting for MONITOR_ANS_MODULI");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u8(m, &success)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse success");
|
2002-03-22 03:30:41 +01:00
|
|
|
if (success == 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("MONITOR_ANS_MODULI failed");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2019-01-21 10:54:11 +01:00
|
|
|
if ((r = sshbuf_get_bignum2(m, &p)) != 0 ||
|
|
|
|
(r = sshbuf_get_bignum2(m, &g)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse group");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("remaining %zu", sshbuf_len(m));
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
return (dh_new_group(g, p));
|
|
|
|
}
|
2014-05-15 06:24:09 +02:00
|
|
|
#endif
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
int
|
2019-01-19 22:43:56 +01:00
|
|
|
mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
|
2019-10-31 22:23:19 +01:00
|
|
|
const u_char *data, size_t datalen, const char *hostkey_alg,
|
2020-08-27 03:06:18 +02:00
|
|
|
const char *sk_provider, const char *sk_pin, u_int compat)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2015-01-19 21:16:15 +01:00
|
|
|
struct kex *kex = *pmonitor->m_pkex;
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2019-01-19 22:43:56 +01:00
|
|
|
u_int ndx = kex->host_key_index(key, 0, ssh);
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_u32(m, ndx)) != 0 ||
|
|
|
|
(r = sshbuf_put_string(m, data, datalen)) != 0 ||
|
2018-07-11 20:53:29 +02:00
|
|
|
(r = sshbuf_put_cstring(m, hostkey_alg)) != 0 ||
|
|
|
|
(r = sshbuf_put_u32(m, compat)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("waiting for MONITOR_ANS_SIGN");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m);
|
2018-07-11 20:53:29 +02:00
|
|
|
if ((r = sshbuf_get_string(m, sigp, lenp)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2024-05-17 02:30:23 +02:00
|
|
|
void
|
|
|
|
mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m)
|
|
|
|
{
|
|
|
|
const u_char *p;
|
|
|
|
size_t len;
|
|
|
|
u_int i;
|
|
|
|
ServerOptions *newopts;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
|
|
|
|
fatal_fr(r, "parse opts");
|
|
|
|
if (len != sizeof(*newopts))
|
|
|
|
fatal_f("option block size mismatch");
|
|
|
|
newopts = xcalloc(sizeof(*newopts), 1);
|
|
|
|
memcpy(newopts, p, sizeof(*newopts));
|
|
|
|
|
|
|
|
#define M_CP_STROPT(x) do { \
|
|
|
|
if (newopts->x != NULL && \
|
|
|
|
(r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \
|
|
|
|
fatal_fr(r, "parse %s", #x); \
|
|
|
|
} while (0)
|
|
|
|
#define M_CP_STRARRAYOPT(x, nx) do { \
|
|
|
|
newopts->x = newopts->nx == 0 ? \
|
|
|
|
NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
|
|
|
|
for (i = 0; i < newopts->nx; i++) { \
|
|
|
|
if ((r = sshbuf_get_cstring(m, \
|
|
|
|
&newopts->x[i], NULL)) != 0) \
|
|
|
|
fatal_fr(r, "parse %s", #x); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
/* See comment in servconf.h */
|
|
|
|
COPY_MATCH_STRING_OPTS();
|
|
|
|
#undef M_CP_STROPT
|
|
|
|
#undef M_CP_STRARRAYOPT
|
|
|
|
|
|
|
|
copy_set_server_options(&options, newopts, 1);
|
|
|
|
log_change_level(options.log_level);
|
|
|
|
log_verbose_reset();
|
|
|
|
for (i = 0; i < options.num_log_verbose; i++)
|
|
|
|
log_verbose_add(options.log_verbose[i]);
|
|
|
|
free(newopts);
|
|
|
|
}
|
|
|
|
|
2020-11-27 01:37:10 +01:00
|
|
|
#define GETPW(b, id) \
|
|
|
|
do { \
|
|
|
|
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) \
|
|
|
|
fatal_fr(r, "parse pw %s", #id); \
|
|
|
|
if (len != sizeof(pw->id)) \
|
|
|
|
fatal_fr(r, "bad length for %s", #id); \
|
|
|
|
memcpy(&pw->id, p, len); \
|
|
|
|
} while (0)
|
|
|
|
|
2002-03-22 03:30:41 +01:00
|
|
|
struct passwd *
|
2019-01-19 22:41:18 +01:00
|
|
|
mm_getpwnamallow(struct ssh *ssh, const char *username)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2002-03-22 03:30:41 +01:00
|
|
|
struct passwd *pw;
|
2018-07-09 23:53:45 +02:00
|
|
|
size_t len;
|
|
|
|
int r;
|
|
|
|
u_char ok;
|
|
|
|
const u_char *p;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_cstring(m, username)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("waiting for MONITOR_ANS_PWNAM");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u8(m, &ok)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse success");
|
2018-07-09 23:53:45 +02:00
|
|
|
if (ok == 0) {
|
2007-12-02 13:02:15 +01:00
|
|
|
pw = NULL;
|
|
|
|
goto out;
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
2018-07-09 23:53:45 +02:00
|
|
|
|
|
|
|
/* XXX don't like passing struct passwd like this */
|
|
|
|
pw = xcalloc(sizeof(*pw), 1);
|
2020-11-27 01:37:10 +01:00
|
|
|
GETPW(m, pw_uid);
|
|
|
|
GETPW(m, pw_gid);
|
|
|
|
#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
|
|
|
|
GETPW(m, pw_change);
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
|
|
|
|
GETPW(m, pw_expire);
|
|
|
|
#endif
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
|
|
|
|
(r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
|
2013-04-23 06:25:52 +02:00
|
|
|
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
|
2018-07-09 23:53:45 +02:00
|
|
|
(r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 ||
|
2013-04-23 06:25:52 +02:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
|
2018-07-09 23:53:45 +02:00
|
|
|
(r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 ||
|
2002-03-22 19:07:17 +01:00
|
|
|
#endif
|
2018-07-09 23:53:45 +02:00
|
|
|
(r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
|
|
|
|
(r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse pw");
|
2007-02-19 12:25:37 +01:00
|
|
|
|
2007-12-02 13:02:15 +01:00
|
|
|
out:
|
2007-02-19 12:25:37 +01:00
|
|
|
/* copy options block as a Match directive may have changed some */
|
2024-05-17 02:30:23 +02:00
|
|
|
mm_decode_activate_server_options(ssh, m);
|
|
|
|
server_process_permitopen(ssh);
|
|
|
|
server_process_channel_timeouts(ssh);
|
2023-12-18 15:45:49 +01:00
|
|
|
kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos);
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
return (pw);
|
|
|
|
}
|
|
|
|
|
2003-10-15 07:56:58 +02:00
|
|
|
char *
|
|
|
|
mm_auth2_read_banner(void)
|
2002-05-13 03:07:41 +02:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2002-05-13 03:07:41 +02:00
|
|
|
char *banner;
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
2002-05-13 03:07:41 +02:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-05-13 03:07:41 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m);
|
|
|
|
sshbuf_reset(m);
|
2002-05-13 03:07:41 +02:00
|
|
|
|
2003-10-15 07:56:58 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
2018-07-09 23:53:45 +02:00
|
|
|
MONITOR_ANS_AUTH2_READ_BANNER, m);
|
|
|
|
if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-06-21 02:41:51 +02:00
|
|
|
|
2003-10-15 07:56:58 +02:00
|
|
|
/* treat empty banner as missing banner */
|
|
|
|
if (strlen(banner) == 0) {
|
2013-06-01 23:31:17 +02:00
|
|
|
free(banner);
|
2003-10-15 07:56:58 +02:00
|
|
|
banner = NULL;
|
|
|
|
}
|
2002-05-13 03:07:41 +02:00
|
|
|
return (banner);
|
|
|
|
}
|
|
|
|
|
2002-03-22 03:30:41 +01:00
|
|
|
/* Inform the privileged process about service and style */
|
|
|
|
|
|
|
|
void
|
|
|
|
mm_inform_authserv(char *service, char *style)
|
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
|
|
|
int r;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_cstring(m, service)) != 0 ||
|
|
|
|
(r = sshbuf_put_cstring(m, style ? style : "")) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Do the password authentication */
|
|
|
|
int
|
2018-03-03 04:15:51 +01:00
|
|
|
mm_auth_password(struct ssh *ssh, char *password)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2018-07-10 11:39:52 +02:00
|
|
|
int r, authenticated = 0;
|
|
|
|
#ifdef USE_PAM
|
|
|
|
u_int maxtries = 0;
|
|
|
|
#endif
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_cstring(m, password)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("waiting for MONITOR_ANS_AUTHPASSWORD");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
|
|
|
MONITOR_ANS_AUTHPASSWORD, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2016-07-18 01:33:25 +02:00
|
|
|
#ifdef USE_PAM
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &maxtries)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse PAM");
|
2018-07-10 11:39:52 +02:00
|
|
|
if (maxtries > INT_MAX)
|
2020-10-19 01:54:41 +02:00
|
|
|
fatal_fr(r, "bad maxtries");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshpam_set_maxtries_reached(maxtries);
|
2016-07-18 01:33:25 +02:00
|
|
|
#endif
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("user %sauthenticated", authenticated ? "" : "not ");
|
2002-03-22 03:30:41 +01:00
|
|
|
return (authenticated);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2022-06-15 18:08:25 +02:00
|
|
|
mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
|
|
|
|
int pubkey_auth_attempt, struct sshauthopt **authoptp)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2015-05-01 05:23:51 +02:00
|
|
|
return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
|
2018-03-03 04:15:51 +01:00
|
|
|
pubkey_auth_attempt, authoptp));
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-01-19 22:43:56 +01:00
|
|
|
mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
|
|
|
|
const char *user, const char *host, struct sshkey *key)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2018-03-03 04:15:51 +01:00
|
|
|
return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL));
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2016-03-07 20:02:43 +01:00
|
|
|
mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
|
2018-03-03 04:15:51 +01:00
|
|
|
struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2018-03-03 04:15:51 +01:00
|
|
|
int r, allowed = 0;
|
|
|
|
struct sshauthopt *opts = NULL;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-03-03 04:15:51 +01:00
|
|
|
if (authoptp != NULL)
|
|
|
|
*authoptp = NULL;
|
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_u32(m, type)) != 0 ||
|
|
|
|
(r = sshbuf_put_cstring(m, user ? user : "")) != 0 ||
|
|
|
|
(r = sshbuf_put_cstring(m, host ? host : "")) != 0 ||
|
|
|
|
(r = sshkey_puts(key, m)) != 0 ||
|
|
|
|
(r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("waiting for MONITOR_ANS_KEYALLOWED");
|
2018-03-03 04:15:51 +01:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
2018-07-09 23:53:45 +02:00
|
|
|
MONITOR_ANS_KEYALLOWED, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &allowed)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
|
|
|
if (allowed && type == MM_USERKEY &&
|
|
|
|
(r = sshauthopt_deserialise(m, &opts)) != 0)
|
|
|
|
fatal_fr(r, "sshauthopt_deserialise");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-03-03 04:15:51 +01:00
|
|
|
if (authoptp != NULL) {
|
|
|
|
*authoptp = opts;
|
|
|
|
opts = NULL;
|
|
|
|
}
|
|
|
|
sshauthopt_free(opts);
|
|
|
|
|
|
|
|
return allowed;
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This key verify needs to send the key type along, because the
|
|
|
|
* privileged parent makes the decision if the key is allowed
|
|
|
|
* for authentication.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
2017-05-30 16:10:53 +02:00
|
|
|
mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
|
2019-11-25 01:51:37 +01:00
|
|
|
const u_char *data, size_t datalen, const char *sigalg, u_int compat,
|
|
|
|
struct sshkey_sig_details **sig_detailsp)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2017-05-30 16:10:53 +02:00
|
|
|
u_int encoded_ret = 0;
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
2019-11-25 01:51:37 +01:00
|
|
|
u_char sig_details_present, flags;
|
|
|
|
u_int counter;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2019-11-25 01:51:37 +01:00
|
|
|
if (sig_detailsp != NULL)
|
|
|
|
*sig_detailsp = NULL;
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshkey_puts(key, m)) != 0 ||
|
|
|
|
(r = sshbuf_put_string(m, sig, siglen)) != 0 ||
|
|
|
|
(r = sshbuf_put_string(m, data, datalen)) != 0 ||
|
|
|
|
(r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("waiting for MONITOR_ANS_KEYVERIFY");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
|
|
|
MONITOR_ANS_KEYVERIFY, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2019-11-25 01:51:37 +01:00
|
|
|
if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 ||
|
|
|
|
(r = sshbuf_get_u8(m, &sig_details_present)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2019-11-25 01:51:37 +01:00
|
|
|
if (sig_details_present && encoded_ret == 0) {
|
|
|
|
if ((r = sshbuf_get_u32(m, &counter)) != 0 ||
|
|
|
|
(r = sshbuf_get_u8(m, &flags)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse sig_details");
|
2019-11-25 01:51:37 +01:00
|
|
|
if (sig_detailsp != NULL) {
|
|
|
|
*sig_detailsp = xcalloc(1, sizeof(**sig_detailsp));
|
|
|
|
(*sig_detailsp)->sk_counter = counter;
|
|
|
|
(*sig_detailsp)->sk_flags = flags;
|
|
|
|
}
|
|
|
|
}
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2017-05-30 16:10:53 +02:00
|
|
|
if (encoded_ret != 0)
|
|
|
|
return SSH_ERR_SIGNATURE_INVALID;
|
|
|
|
return 0;
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-01-19 22:43:56 +01:00
|
|
|
mm_send_keystate(struct ssh *ssh, struct monitor *monitor)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2015-01-19 20:52:16 +01:00
|
|
|
struct sshbuf *m;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2015-01-19 20:52:16 +01:00
|
|
|
if ((r = ssh_packet_get_state(ssh, m)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "ssh_packet_get_state");
|
2015-01-19 20:52:16 +01:00
|
|
|
mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("Finished sending state");
|
2015-01-19 20:52:16 +01:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2006-03-26 05:04:36 +02:00
|
|
|
mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2004-07-17 09:05:14 +02:00
|
|
|
char *p, *msg;
|
2018-07-09 23:26:02 +02:00
|
|
|
int success = 0, tmp1 = -1, tmp2 = -1, r;
|
2008-05-19 07:34:50 +02:00
|
|
|
|
|
|
|
/* Kludge: ensure there are fds free to receive the pty/tty */
|
|
|
|
if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
|
|
|
|
(tmp2 = dup(pmonitor->m_recvfd)) == -1) {
|
2020-10-18 13:32:01 +02:00
|
|
|
error_f("cannot allocate fds for pty");
|
2023-03-31 02:44:29 +02:00
|
|
|
if (tmp1 >= 0)
|
2008-05-19 07:34:50 +02:00
|
|
|
close(tmp1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
close(tmp1);
|
|
|
|
close(tmp2);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("waiting for MONITOR_ANS_PTY");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &success)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse success");
|
2002-03-22 03:30:41 +01:00
|
|
|
if (success == 0) {
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("pty alloc failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
return (0);
|
|
|
|
}
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 ||
|
|
|
|
(r = sshbuf_get_cstring(m, &msg, NULL)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
strlcpy(namebuf, p, namebuflen); /* Possible truncation */
|
2013-06-01 23:31:17 +02:00
|
|
|
free(p);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:26:02 +02:00
|
|
|
if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "put loginmsg");
|
2013-06-01 23:31:17 +02:00
|
|
|
free(msg);
|
2004-07-17 09:05:14 +02:00
|
|
|
|
2007-09-17 04:04:08 +02:00
|
|
|
if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
|
|
|
|
(*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("receive fds failed");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
/* Success */
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-10-02 08:12:36 +02:00
|
|
|
mm_session_pty_cleanup2(Session *s)
|
2002-03-22 03:30:41 +01:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
|
|
|
int r;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
if (s->ttyfd == -1)
|
|
|
|
return;
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_cstring(m, s->tty)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assmble");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m);
|
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
/* closed dup'ed master */
|
2019-06-28 15:35:04 +02:00
|
|
|
if (s->ptymaster != -1 && close(s->ptymaster) == -1)
|
2008-05-19 07:34:50 +02:00
|
|
|
error("close(s->ptymaster/%d): %s",
|
|
|
|
s->ptymaster, strerror(errno));
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
/* unlink pty from session */
|
|
|
|
s->ttyfd = -1;
|
|
|
|
}
|
|
|
|
|
2002-04-23 12:28:48 +02:00
|
|
|
#ifdef USE_PAM
|
|
|
|
void
|
2019-01-20 00:22:18 +01:00
|
|
|
mm_start_pam(struct ssh *ssh)
|
2002-04-23 12:28:48 +02:00
|
|
|
{
|
2018-07-10 11:39:52 +02:00
|
|
|
struct sshbuf *m;
|
2002-04-23 12:28:48 +02:00
|
|
|
|
2002-06-06 23:40:51 +02:00
|
|
|
debug3("%s entering", __func__);
|
2003-05-14 07:11:48 +02:00
|
|
|
if (!options.use_pam)
|
|
|
|
fatal("UsePAM=no, but ended up in %s anyway", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
|
|
|
fatal("%s: sshbuf_new failed", __func__);
|
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m);
|
2002-04-23 12:28:48 +02:00
|
|
|
|
2018-07-10 11:39:52 +02:00
|
|
|
sshbuf_free(m);
|
2002-04-23 12:28:48 +02:00
|
|
|
}
|
2003-05-10 11:28:02 +02:00
|
|
|
|
2003-08-25 05:08:49 +02:00
|
|
|
u_int
|
|
|
|
mm_do_pam_account(void)
|
|
|
|
{
|
2018-07-10 11:39:52 +02:00
|
|
|
struct sshbuf *m;
|
2003-08-25 05:08:49 +02:00
|
|
|
u_int ret;
|
2004-09-11 15:07:03 +02:00
|
|
|
char *msg;
|
2018-07-10 11:39:52 +02:00
|
|
|
size_t msglen;
|
|
|
|
int r;
|
2003-08-25 05:08:49 +02:00
|
|
|
|
|
|
|
debug3("%s entering", __func__);
|
|
|
|
if (!options.use_pam)
|
|
|
|
fatal("UsePAM=no, but ended up in %s anyway", __func__);
|
|
|
|
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
|
|
|
fatal("%s: sshbuf_new failed", __func__);
|
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m);
|
2003-08-25 05:08:49 +02:00
|
|
|
|
2003-11-21 13:48:55 +01:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
2018-07-10 11:39:52 +02:00
|
|
|
MONITOR_ANS_PAM_ACCOUNT, m);
|
|
|
|
if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
|
|
|
|
(r = sshbuf_get_cstring(m, &msg, &msglen)) != 0 ||
|
|
|
|
(r = sshbuf_put(loginmsg, msg, msglen)) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
2003-08-25 05:08:49 +02:00
|
|
|
|
2018-07-10 11:39:52 +02:00
|
|
|
free(msg);
|
|
|
|
sshbuf_free(m);
|
2003-11-21 13:56:47 +01:00
|
|
|
|
2003-08-25 05:08:49 +02:00
|
|
|
debug3("%s returning %d", __func__, ret);
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2003-05-10 11:28:02 +02:00
|
|
|
void *
|
|
|
|
mm_sshpam_init_ctx(Authctxt *authctxt)
|
|
|
|
{
|
2018-07-10 11:39:52 +02:00
|
|
|
struct sshbuf *m;
|
|
|
|
int r, success;
|
2003-05-10 11:28:02 +02:00
|
|
|
|
|
|
|
debug3("%s", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
|
|
|
fatal("%s: sshbuf_new failed", __func__);
|
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m);
|
2003-05-10 11:28:02 +02:00
|
|
|
debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
|
|
|
MONITOR_ANS_PAM_INIT_CTX, m);
|
|
|
|
if ((r = sshbuf_get_u32(m, &success)) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
2003-05-10 11:28:02 +02:00
|
|
|
if (success == 0) {
|
|
|
|
debug3("%s: pam_init_ctx failed", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
sshbuf_free(m);
|
2003-05-10 11:28:02 +02:00
|
|
|
return (NULL);
|
|
|
|
}
|
2018-07-10 11:39:52 +02:00
|
|
|
sshbuf_free(m);
|
2003-05-10 11:28:02 +02:00
|
|
|
return (authctxt);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
mm_sshpam_query(void *ctx, char **name, char **info,
|
|
|
|
u_int *num, char ***prompts, u_int **echo_on)
|
|
|
|
{
|
2018-07-10 11:39:52 +02:00
|
|
|
struct sshbuf *m;
|
|
|
|
u_int i, n;
|
|
|
|
int r, ret;
|
2003-05-10 11:28:02 +02:00
|
|
|
|
|
|
|
debug3("%s", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
|
|
|
fatal("%s: sshbuf_new failed", __func__);
|
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m);
|
2003-05-10 11:28:02 +02:00
|
|
|
debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m);
|
|
|
|
if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
|
|
|
|
(r = sshbuf_get_cstring(m, name, NULL)) != 0 ||
|
|
|
|
(r = sshbuf_get_cstring(m, info, NULL)) != 0 ||
|
|
|
|
(r = sshbuf_get_u32(m, &n)) != 0 ||
|
|
|
|
(r = sshbuf_get_u32(m, num)) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
2003-05-10 11:28:02 +02:00
|
|
|
debug3("%s: pam_query returned %d", __func__, ret);
|
2018-07-10 11:39:52 +02:00
|
|
|
sshpam_set_maxtries_reached(n);
|
2006-05-04 08:24:34 +02:00
|
|
|
if (*num > PAM_MAX_NUM_MSG)
|
2018-04-10 02:19:02 +02:00
|
|
|
fatal("%s: received %u PAM messages, expected <= %u",
|
2006-05-04 08:24:34 +02:00
|
|
|
__func__, *num, PAM_MAX_NUM_MSG);
|
|
|
|
*prompts = xcalloc((*num + 1), sizeof(char *));
|
|
|
|
*echo_on = xcalloc((*num + 1), sizeof(u_int));
|
2003-05-10 11:28:02 +02:00
|
|
|
for (i = 0; i < *num; ++i) {
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((r = sshbuf_get_cstring(m, &((*prompts)[i]), NULL)) != 0 ||
|
|
|
|
(r = sshbuf_get_u32(m, &((*echo_on)[i]))) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
2003-05-10 11:28:02 +02:00
|
|
|
}
|
2018-07-10 11:39:52 +02:00
|
|
|
sshbuf_free(m);
|
2003-05-10 11:28:02 +02:00
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
mm_sshpam_respond(void *ctx, u_int num, char **resp)
|
|
|
|
{
|
2018-07-10 11:39:52 +02:00
|
|
|
struct sshbuf *m;
|
|
|
|
u_int n, i;
|
|
|
|
int r, ret;
|
2003-05-10 11:28:02 +02:00
|
|
|
|
|
|
|
debug3("%s", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
|
|
|
fatal("%s: sshbuf_new failed", __func__);
|
|
|
|
if ((r = sshbuf_put_u32(m, num)) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
|
for (i = 0; i < num; ++i) {
|
|
|
|
if ((r = sshbuf_put_cstring(m, resp[i])) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
|
}
|
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m);
|
2003-05-10 11:28:02 +02:00
|
|
|
debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
|
|
|
MONITOR_ANS_PAM_RESPOND, m);
|
|
|
|
if ((r = sshbuf_get_u32(m, &n)) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
|
ret = (int)n; /* XXX */
|
2003-05-10 11:28:02 +02:00
|
|
|
debug3("%s: pam_respond returned %d", __func__, ret);
|
2018-07-10 11:39:52 +02:00
|
|
|
sshbuf_free(m);
|
2003-05-10 11:28:02 +02:00
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mm_sshpam_free_ctx(void *ctxtp)
|
|
|
|
{
|
2018-07-10 11:39:52 +02:00
|
|
|
struct sshbuf *m;
|
2003-05-10 11:28:02 +02:00
|
|
|
|
|
|
|
debug3("%s", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
|
|
|
fatal("%s: sshbuf_new failed", __func__);
|
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m);
|
2003-05-10 11:28:02 +02:00
|
|
|
debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
|
|
|
MONITOR_ANS_PAM_FREE_CTX, m);
|
|
|
|
sshbuf_free(m);
|
2003-05-10 11:28:02 +02:00
|
|
|
}
|
2002-04-23 12:28:48 +02:00
|
|
|
#endif /* USE_PAM */
|
|
|
|
|
2002-03-22 03:30:41 +01:00
|
|
|
/* Request process termination */
|
|
|
|
|
|
|
|
void
|
|
|
|
mm_terminate(void)
|
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m);
|
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
|
|
|
|
char ***prompts, u_int **echo_on)
|
|
|
|
{
|
2002-06-21 02:41:51 +02:00
|
|
|
*name = xstrdup("");
|
|
|
|
*infotxt = xstrdup("");
|
2002-03-22 03:30:41 +01:00
|
|
|
*numprompts = 1;
|
2006-03-26 05:19:21 +02:00
|
|
|
*prompts = xcalloc(*numprompts, sizeof(char *));
|
|
|
|
*echo_on = xcalloc(*numprompts, sizeof(u_int));
|
2002-03-22 03:30:41 +01:00
|
|
|
(*echo_on)[0] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
mm_bsdauth_query(void *ctx, char **name, char **infotxt,
|
|
|
|
u_int *numprompts, char ***prompts, u_int **echo_on)
|
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2003-02-24 01:55:46 +01:00
|
|
|
u_int success;
|
2002-03-22 03:30:41 +01:00
|
|
|
char *challenge;
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
|
|
|
MONITOR_ANS_BSDAUTHQUERY, m);
|
|
|
|
if ((r = sshbuf_get_u32(m, &success)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse success");
|
2003-02-24 01:55:46 +01:00
|
|
|
if (success == 0) {
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("no challenge");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the challenge, and format the response */
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse challenge");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
|
|
|
|
(*prompts)[0] = challenge;
|
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("received challenge: %s", challenge);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
|
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
|
|
|
int r, authok;
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("entering");
|
2002-03-22 03:30:41 +01:00
|
|
|
if (numresponses != 1)
|
|
|
|
return (-1);
|
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_cstring(m, responses[0])) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2002-05-15 18:25:01 +02:00
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
2018-07-09 23:53:45 +02:00
|
|
|
MONITOR_ANS_BSDAUTHRESPOND, m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &authok)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2002-03-22 03:30:41 +01:00
|
|
|
|
|
|
|
return ((authok == 0) ? -1 : 0);
|
|
|
|
}
|
|
|
|
|
2005-02-08 11:52:47 +01:00
|
|
|
#ifdef SSH_AUDIT_EVENTS
|
2005-02-02 14:20:53 +01:00
|
|
|
void
|
2019-01-20 04:55:27 +01:00
|
|
|
mm_audit_event(struct ssh *ssh, ssh_audit_event_t event)
|
2005-02-02 14:20:53 +01:00
|
|
|
{
|
2018-07-10 11:39:52 +02:00
|
|
|
struct sshbuf *m;
|
2018-07-13 05:38:10 +02:00
|
|
|
int r;
|
2005-02-02 14:20:53 +01:00
|
|
|
|
|
|
|
debug3("%s entering", __func__);
|
|
|
|
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2018-07-13 05:38:10 +02:00
|
|
|
fatal("%s: sshbuf_new failed", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((r = sshbuf_put_u32(m, event)) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
2005-02-02 14:20:53 +01:00
|
|
|
|
2018-07-10 11:39:52 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m);
|
|
|
|
sshbuf_free(m);
|
2005-02-02 14:20:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mm_audit_run_command(const char *command)
|
|
|
|
{
|
2018-07-10 11:39:52 +02:00
|
|
|
struct sshbuf *m;
|
2018-07-13 05:38:10 +02:00
|
|
|
int r;
|
2005-02-02 14:20:53 +01:00
|
|
|
|
|
|
|
debug3("%s entering command %s", __func__, command);
|
|
|
|
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2018-07-13 05:38:10 +02:00
|
|
|
fatal("%s: sshbuf_new failed", __func__);
|
2018-07-10 11:39:52 +02:00
|
|
|
if ((r = sshbuf_put_cstring(m, command)) != 0)
|
|
|
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
2005-02-02 14:20:53 +01:00
|
|
|
|
2018-07-10 11:39:52 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m);
|
|
|
|
sshbuf_free(m);
|
2005-02-02 14:20:53 +01:00
|
|
|
}
|
2005-02-08 11:52:47 +01:00
|
|
|
#endif /* SSH_AUDIT_EVENTS */
|
2005-02-02 14:20:53 +01:00
|
|
|
|
2003-08-26 03:49:55 +02:00
|
|
|
#ifdef GSSAPI
|
|
|
|
OM_uint32
|
2004-06-22 04:56:01 +02:00
|
|
|
mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
|
2003-08-26 03:49:55 +02:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2003-08-26 03:49:55 +02:00
|
|
|
OM_uint32 major;
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
2003-08-26 03:49:55 +02:00
|
|
|
|
|
|
|
/* Client doesn't get to see the context */
|
|
|
|
*ctx = NULL;
|
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m);
|
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m);
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &major)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2003-08-26 03:49:55 +02:00
|
|
|
return (major);
|
|
|
|
}
|
|
|
|
|
|
|
|
OM_uint32
|
|
|
|
mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
|
2018-07-09 23:53:45 +02:00
|
|
|
gss_buffer_desc *out, OM_uint32 *flagsp)
|
2003-08-26 03:49:55 +02:00
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2003-08-26 03:49:55 +02:00
|
|
|
OM_uint32 major;
|
2018-07-09 23:53:45 +02:00
|
|
|
u_int flags;
|
|
|
|
int r;
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_string(m, in->value, in->length)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m);
|
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m);
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &major)) != 0 ||
|
2018-07-10 11:13:30 +02:00
|
|
|
(r = ssh_gssapi_get_buffer_desc(m, out)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2018-07-09 23:53:45 +02:00
|
|
|
if (flagsp != NULL) {
|
|
|
|
if ((r = sshbuf_get_u32(m, &flags)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse flags");
|
2018-07-09 23:53:45 +02:00
|
|
|
*flagsp = flags;
|
|
|
|
}
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2003-08-26 03:49:55 +02:00
|
|
|
|
|
|
|
return (major);
|
|
|
|
}
|
|
|
|
|
2003-11-17 12:18:21 +01:00
|
|
|
OM_uint32
|
|
|
|
mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
|
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
2003-11-17 12:18:21 +01:00
|
|
|
OM_uint32 major;
|
2018-07-09 23:53:45 +02:00
|
|
|
int r;
|
2003-11-17 12:18:21 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 ||
|
|
|
|
(r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "assemble");
|
2003-11-17 12:18:21 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m);
|
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
|
|
|
MONITOR_ANS_GSSCHECKMIC, m);
|
2003-11-17 12:18:21 +01:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &major)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2003-11-17 12:18:21 +01:00
|
|
|
return(major);
|
|
|
|
}
|
|
|
|
|
2003-08-26 03:49:55 +02:00
|
|
|
int
|
|
|
|
mm_ssh_gssapi_userok(char *user)
|
|
|
|
{
|
2018-07-09 23:53:45 +02:00
|
|
|
struct sshbuf *m;
|
|
|
|
int r, authenticated = 0;
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((m = sshbuf_new()) == NULL)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_f("sshbuf_new failed");
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
|
|
|
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
|
|
|
MONITOR_ANS_GSSUSEROK, m);
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
|
2020-10-18 13:32:01 +02:00
|
|
|
fatal_fr(r, "parse");
|
2003-08-26 03:49:55 +02:00
|
|
|
|
2018-07-09 23:53:45 +02:00
|
|
|
sshbuf_free(m);
|
2020-10-18 13:32:01 +02:00
|
|
|
debug3_f("user %sauthenticated", authenticated ? "" : "not ");
|
2003-08-26 03:49:55 +02:00
|
|
|
return (authenticated);
|
|
|
|
}
|
|
|
|
#endif /* GSSAPI */
|
2024-05-17 02:30:23 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Inform channels layer of permitopen options for a single forwarding
|
|
|
|
* direction (local/remote).
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
server_process_permitopen_list(struct ssh *ssh, int listen,
|
|
|
|
char **opens, u_int num_opens)
|
|
|
|
{
|
|
|
|
u_int i;
|
|
|
|
int port;
|
|
|
|
char *host, *arg, *oarg;
|
|
|
|
int where = listen ? FORWARD_REMOTE : FORWARD_LOCAL;
|
|
|
|
const char *what = listen ? "permitlisten" : "permitopen";
|
|
|
|
|
|
|
|
channel_clear_permission(ssh, FORWARD_ADM, where);
|
|
|
|
if (num_opens == 0)
|
|
|
|
return; /* permit any */
|
|
|
|
|
|
|
|
/* handle keywords: "any" / "none" */
|
|
|
|
if (num_opens == 1 && strcmp(opens[0], "any") == 0)
|
|
|
|
return;
|
|
|
|
if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
|
|
|
|
channel_disable_admin(ssh, where);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Otherwise treat it as a list of permitted host:port */
|
|
|
|
for (i = 0; i < num_opens; i++) {
|
|
|
|
oarg = arg = xstrdup(opens[i]);
|
|
|
|
host = hpdelim(&arg);
|
|
|
|
if (host == NULL)
|
|
|
|
fatal_f("missing host in %s", what);
|
|
|
|
host = cleanhostname(host);
|
|
|
|
if (arg == NULL || ((port = permitopen_port(arg)) < 0))
|
|
|
|
fatal_f("bad port number in %s", what);
|
|
|
|
/* Send it to channels layer */
|
|
|
|
channel_add_permission(ssh, FORWARD_ADM,
|
|
|
|
where, host, port);
|
|
|
|
free(oarg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Inform channels layer of permitopen options from configuration.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
server_process_permitopen(struct ssh *ssh)
|
|
|
|
{
|
|
|
|
server_process_permitopen_list(ssh, 0,
|
|
|
|
options.permitted_opens, options.num_permitted_opens);
|
|
|
|
server_process_permitopen_list(ssh, 1,
|
|
|
|
options.permitted_listens, options.num_permitted_listens);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
server_process_channel_timeouts(struct ssh *ssh)
|
|
|
|
{
|
|
|
|
u_int i, secs;
|
|
|
|
char *type;
|
|
|
|
|
|
|
|
debug3_f("setting %u timeouts", options.num_channel_timeouts);
|
|
|
|
channel_clear_timeouts(ssh);
|
|
|
|
for (i = 0; i < options.num_channel_timeouts; i++) {
|
|
|
|
if (parse_pattern_interval(options.channel_timeouts[i],
|
|
|
|
&type, &secs) != 0) {
|
|
|
|
fatal_f("internal error: bad timeout %s",
|
|
|
|
options.channel_timeouts[i]);
|
|
|
|
}
|
|
|
|
channel_add_timeout(ssh, type, secs);
|
|
|
|
free(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct connection_info *
|
|
|
|
server_get_connection_info(struct ssh *ssh, int populate, int use_dns)
|
|
|
|
{
|
|
|
|
static struct connection_info ci;
|
|
|
|
|
|
|
|
if (ssh == NULL || !populate)
|
|
|
|
return &ci;
|
|
|
|
ci.host = use_dns ? ssh_remote_hostname(ssh) : ssh_remote_ipaddr(ssh);
|
|
|
|
ci.address = ssh_remote_ipaddr(ssh);
|
|
|
|
ci.laddress = ssh_local_ipaddr(ssh);
|
|
|
|
ci.lport = ssh_local_port(ssh);
|
|
|
|
ci.rdomain = ssh_packet_rdomain_in(ssh);
|
|
|
|
return &ci;
|
|
|
|
}
|
|
|
|
|