Skip to content

Commit

Permalink
upstream: Start the process of splitting sshd into separate
Browse files Browse the repository at this point in the history
binaries. This step splits sshd into a listener and a session binary. More
splits are planned.

After this changes, the listener binary will validate the configuration,
load the hostkeys, listen on port 22 and manage MaxStartups only. All
session handling will be performed by a new sshd-session binary that the
listener fork+execs.

This reduces the listener process to the minimum necessary and sets us
up for future work on the sshd-session binary.

feedback/ok markus@ deraadt@

NB. if you're updating via source, please restart sshd after installing,
otherwise you run the risk of locking yourself out.

OpenBSD-Commit-ID: 43c04a1ab96cdbdeb53d2df0125a6d42c5f19934
  • Loading branch information
djmdjm committed May 17, 2024
1 parent 1c0d813 commit 03e3de4
Show file tree
Hide file tree
Showing 33 changed files with 2,096 additions and 1,931 deletions.
23 changes: 11 additions & 12 deletions auth-pam.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ static struct pam_conv store_conv = { sshpam_store_conv, NULL };
void
sshpam_cleanup(void)
{
if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor()))
if (sshpam_handle == NULL || !mm_is_monitor())
return;
debug("PAM: cleanup");
pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
Expand Down Expand Up @@ -705,7 +705,8 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt)
fatal("%s: called initially with no "
"packet context", __func__);
}
} if (sshpam_handle != NULL) {
}
if (sshpam_handle != NULL) {
/* We already have a PAM context; check if the user matches */
sshpam_err = pam_get_item(sshpam_handle,
PAM_USER, (sshpam_const void **)ptr_pam_user);
Expand Down Expand Up @@ -1101,20 +1102,15 @@ do_pam_account(void)
}

void
do_pam_setcred(int init)
do_pam_setcred(void)
{
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&store_conv);
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: failed to set PAM_CONV: %s",
pam_strerror(sshpam_handle, sshpam_err));
if (init) {
debug("PAM: establishing credentials");
sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED);
} else {
debug("PAM: reinitializing credentials");
sshpam_err = pam_setcred(sshpam_handle, PAM_REINITIALIZE_CRED);
}
debug("PAM: establishing credentials");
sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED);
if (sshpam_err == PAM_SUCCESS) {
sshpam_cred_established = 1;
return;
Expand All @@ -1127,6 +1123,7 @@ do_pam_setcred(int init)
pam_strerror(sshpam_handle, sshpam_err));
}

#if 0
static int
sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
Expand Down Expand Up @@ -1182,6 +1179,7 @@ sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
}

static struct pam_conv tty_conv = { sshpam_tty_conv, NULL };
#endif

/*
* XXX this should be done in the authentication phase, but ssh1 doesn't
Expand All @@ -1190,8 +1188,8 @@ static struct pam_conv tty_conv = { sshpam_tty_conv, NULL };
void
do_pam_chauthtok(void)
{
if (use_privsep)
fatal("Password expired (unable to change with privsep)");
fatal("Password expired");
#if 0
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&tty_conv);
if (sshpam_err != PAM_SUCCESS)
Expand All @@ -1202,6 +1200,7 @@ do_pam_chauthtok(void)
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: pam_chauthtok(): %s",
pam_strerror(sshpam_handle, sshpam_err));
#endif
}

void
Expand Down
2 changes: 1 addition & 1 deletion auth-pam.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void start_pam(struct ssh *);
void finish_pam(void);
u_int do_pam_account(void);
void do_pam_session(struct ssh *);
void do_pam_setcred(int );
void do_pam_setcred(void);
void do_pam_chauthtok(void);
int do_pam_putenv(char *, char *);
char ** fetch_pam_environment(void);
Expand Down
3 changes: 1 addition & 2 deletions auth-rhosts.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: auth-rhosts.c,v 1.57 2022/12/09 00:17:40 dtucker Exp $ */
/* $OpenBSD: auth-rhosts.c,v 1.58 2024/05/17 00:30:23 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
Expand Down Expand Up @@ -46,7 +46,6 @@

/* import */
extern ServerOptions options;
extern int use_privsep;

/*
* This function processes an rhosts-style file (.rhosts, .shosts, or
Expand Down
108 changes: 7 additions & 101 deletions auth.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.160 2023/03/05 05:34:09 dtucker Exp $ */
/* $OpenBSD: auth.c,v 1.161 2024/05/17 00:30:23 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
Expand Down Expand Up @@ -79,7 +79,6 @@
/* import */
extern ServerOptions options;
extern struct include_list includes;
extern int use_privsep;
extern struct sshbuf *loginmsg;
extern struct passwd *privsep_pw;
extern struct sshauthopt *auth_opts;
Expand Down Expand Up @@ -272,7 +271,7 @@ auth_log(struct ssh *ssh, int authenticated, int partial,
const char *authmsg;
char *extra = NULL;

if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
if (!mm_is_monitor() && !authctxt->postponed)
return;

/* Raise logging level */
Expand Down Expand Up @@ -472,14 +471,14 @@ getpwnamallow(struct ssh *ssh, const char *user)
struct connection_info *ci;
u_int i;

ci = get_connection_info(ssh, 1, options.use_dns);
ci = server_get_connection_info(ssh, 1, options.use_dns);
ci->user = user;
parse_server_match_config(&options, &includes, ci);
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]);
process_permitopen(ssh, &options);
server_process_permitopen(ssh);

#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_setauthdb(user);
Expand Down Expand Up @@ -637,97 +636,6 @@ fakepw(void)
return (&fake);
}

/*
* Returns the remote DNS hostname as a string. The returned string must not
* be freed. NB. this will usually trigger a DNS query the first time it is
* called.
* This function does additional checks on the hostname to mitigate some
* attacks on based on conflation of hostnames and IP addresses.
*/

static char *
remote_hostname(struct ssh *ssh)
{
struct sockaddr_storage from;
socklen_t fromlen;
struct addrinfo hints, *ai, *aitop;
char name[NI_MAXHOST], ntop2[NI_MAXHOST];
const char *ntop = ssh_remote_ipaddr(ssh);

/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(ssh_packet_get_connection_in(ssh),
(struct sockaddr *)&from, &fromlen) == -1) {
debug("getpeername failed: %.100s", strerror(errno));
return xstrdup(ntop);
}

ipv64_normalise_mapped(&from, &fromlen);
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);

debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
NULL, 0, NI_NAMEREQD) != 0) {
/* Host name not found. Use ip address. */
return xstrdup(ntop);
}

/*
* if reverse lookup result looks like a numeric hostname,
* someone is trying to trick us by PTR record like following:
* 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
*/
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
name, ntop);
freeaddrinfo(ai);
return xstrdup(ntop);
}

/* Names are stored in lowercase. */
lowercase(name);

/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
* necessary because anyone with access to a name server can
* define arbitrary names for an IP address. Mapping from
* name to IP address can be trusted better (but can still be
* fooled if the intruder has access to the name server of
* the domain).
*/
memset(&hints, 0, sizeof(hints));
hints.ai_family = from.ss_family;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
logit("reverse mapping checking getaddrinfo for %.700s "
"[%s] failed.", name, ntop);
return xstrdup(ntop);
}
/* Look for the address from the list of addresses. */
for (ai = aitop; ai; ai = ai->ai_next) {
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
(strcmp(ntop, ntop2) == 0))
break;
}
freeaddrinfo(aitop);
/* If we reached the end of the list, the address was not there. */
if (ai == NULL) {
/* Address not found for the host name. */
logit("Address %.100s maps to %.600s, but this does not "
"map back to the address.", ntop, name);
return xstrdup(ntop);
}
return xstrdup(name);
}

/*
* Return the canonical name of the host in the other side of the current
* connection. The host name is cached, so it is efficient to call this
Expand All @@ -741,12 +649,10 @@ auth_get_canonical_hostname(struct ssh *ssh, int use_dns)

if (!use_dns)
return ssh_remote_ipaddr(ssh);
else if (dnsname != NULL)
return dnsname;
else {
dnsname = remote_hostname(ssh);
if (dnsname != NULL)
return dnsname;
}
dnsname = ssh_remote_hostname(ssh);
return dnsname;
}

/* These functions link key/cert options to the auth framework */
Expand Down
12 changes: 8 additions & 4 deletions auth.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: auth.h,v 1.106 2022/06/15 16:08:25 djm Exp $ */
/* $OpenBSD: auth.h,v 1.107 2024/05/17 00:30:23 djm Exp $ */

/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
Expand Down Expand Up @@ -104,11 +104,15 @@ struct Authctxt {
* the client.
*/

struct authmethod_cfg {
const char *name;
const char *synonym;
int *enabled;
};

struct Authmethod {
char *name;
char *synonym;
struct authmethod_cfg *cfg;
int (*userauth)(struct ssh *, const char *);
int *enabled;
};

/*
Expand Down

0 comments on commit 03e3de4

Please sign in to comment.