Skip to content

Commit

Permalink
upstream: switch over to the new authorized_keys options API and
Browse files Browse the repository at this point in the history
remove the legacy one.

Includes a fairly big refactor of auth2-pubkey.c to retain less state
between key file lines.

feedback and ok markus@

OpenBSD-Commit-ID: dece6cae0f47751b9892080eb13d6625599573df
  • Loading branch information
djmdjm committed Mar 3, 2018
1 parent 90c4bec commit 7c85685
Show file tree
Hide file tree
Showing 19 changed files with 767 additions and 984 deletions.
7 changes: 3 additions & 4 deletions .depend

Large diffs are not rendered by default.

650 changes: 3 additions & 647 deletions auth-options.c

Large diffs are not rendered by default.

46 changes: 13 additions & 33 deletions auth-options.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
/* $OpenBSD: auth-options.h,v 1.24 2018/03/03 03:06:02 djm Exp $ */
/* $OpenBSD: auth-options.h,v 1.25 2018/03/03 03:15:51 djm Exp $ */

/*
* Author: Tatu Ylonen <[email protected]>
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
* All rights reserved
* Copyright (c) 2018 Damien Miller <[email protected]>
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef AUTH_OPTIONS_H
Expand All @@ -18,30 +22,6 @@
struct passwd;
struct sshkey;

/* Linked list of custom environment strings */
struct envstring {
struct envstring *next;
char *s;
};

/* Flags that may be set in authorized_keys options. */
extern int no_port_forwarding_flag;
extern int no_agent_forwarding_flag;
extern int no_x11_forwarding_flag;
extern int no_pty_flag;
extern int no_user_rc;
extern char *forced_command;
extern struct envstring *custom_environment;
extern int forced_tun_device;
extern int key_is_cert_authority;
extern char *authorized_principals;

int auth_parse_options(struct passwd *, char *, const char *, u_long);
void auth_clear_options(void);
int auth_cert_options(struct sshkey *, struct passwd *, const char **);

/* authorized_keys options handling */

/*
* sshauthopt represents key options parsed from authorized_keys or
* from certificate extensions/options.
Expand Down
4 changes: 2 additions & 2 deletions auth-pam.c
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ do_pam_chauthtok(void)
}

void
do_pam_session(void)
do_pam_session(struct ssh *ssh)
{
debug3("PAM: opening session");

Expand All @@ -1093,7 +1093,7 @@ do_pam_session(void)
sshpam_session_open = 1;
else {
sshpam_session_open = 0;
disable_forwarding();
auth_restrict_session(ssh);
error("PAM: pam_open_session(): %s",
pam_strerror(sshpam_handle, sshpam_err));
}
Expand Down
4 changes: 3 additions & 1 deletion auth-pam.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
#include "includes.h"
#ifdef USE_PAM

struct ssh;

void start_pam(Authctxt *);
void finish_pam(void);
u_int do_pam_account(void);
void do_pam_session(void);
void do_pam_session(struct ssh *);
void do_pam_setcred(int );
void do_pam_chauthtok(void);
int do_pam_putenv(char *, char *);
Expand Down
30 changes: 12 additions & 18 deletions auth-passwd.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: auth-passwd.c,v 1.45 2016/07/21 01:39:35 dtucker Exp $ */
/* $OpenBSD: auth-passwd.c,v 1.46 2018/03/03 03:15:51 djm Exp $ */
/*
* Author: Tatu Ylonen <[email protected]>
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
Expand Down Expand Up @@ -68,22 +68,15 @@ extern login_cap_t *lc;

#define MAX_PASSWORD_LEN 1024

void
disable_forwarding(void)
{
no_port_forwarding_flag = 1;
no_agent_forwarding_flag = 1;
no_x11_forwarding_flag = 1;
}

/*
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int
auth_password(Authctxt *authctxt, const char *password)
auth_password(struct ssh *ssh, const char *password)
{
struct passwd * pw = authctxt->pw;
Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
int result, ok = authctxt->valid;
#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
static int expire_checked = 0;
Expand Down Expand Up @@ -128,9 +121,9 @@ auth_password(Authctxt *authctxt, const char *password)
authctxt->force_pwchange = 1;
}
#endif
result = sys_auth_passwd(authctxt, password);
result = sys_auth_passwd(ssh, password);
if (authctxt->force_pwchange)
disable_forwarding();
auth_restrict_session(ssh);
return (result && ok);
}

Expand Down Expand Up @@ -170,19 +163,19 @@ warn_expiry(Authctxt *authctxt, auth_session_t *as)
}

int
sys_auth_passwd(Authctxt *authctxt, const char *password)
sys_auth_passwd(struct ssh *ssh, const char *password)
{
struct passwd *pw = authctxt->pw;
Authctxt *authctxt = ssh->authctxt;
auth_session_t *as;
static int expire_checked = 0;

as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh",
as = auth_usercheck(authctxt->pw->pw_name, authctxt->style, "auth-ssh",
(char *)password);
if (as == NULL)
return (0);
if (auth_getstate(as) & AUTH_PWEXPIRED) {
auth_close(as);
disable_forwarding();
auth_restrict_session(ssh);
authctxt->force_pwchange = 1;
return (1);
} else {
Expand All @@ -195,8 +188,9 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
}
#elif !defined(CUSTOM_SYS_AUTH_PASSWD)
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
sys_auth_passwd(struct ssh *ssh, const char *password)
{
Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
char *encrypted_password, *salt = NULL;

Expand Down
180 changes: 175 additions & 5 deletions auth.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.125 2018/01/08 15:21:49 markus Exp $ */
/* $OpenBSD: auth.c,v 1.126 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
Expand Down Expand Up @@ -74,12 +74,14 @@
#include "authfile.h"
#include "ssherr.h"
#include "compat.h"
#include "channels.h"

/* import */
extern ServerOptions options;
extern int use_privsep;
extern Buffer loginmsg;
extern struct passwd *privsep_pw;
extern struct sshauthopt *auth_opts;

/* Debugging messages */
Buffer auth_debug;
Expand Down Expand Up @@ -386,10 +388,8 @@ auth_maxtries_exceeded(Authctxt *authctxt)
* Check whether root logins are disallowed.
*/
int
auth_root_allowed(const char *method)
auth_root_allowed(struct ssh *ssh, const char *method)
{
struct ssh *ssh = active_state; /* XXX */

switch (options.permit_root_login) {
case PERMIT_YES:
return 1;
Expand All @@ -400,7 +400,7 @@ auth_root_allowed(const char *method)
return 1;
break;
case PERMIT_FORCED_ONLY:
if (forced_command) {
if (auth_opts->force_command != NULL) {
logit("Root login accepted for forced command.");
return 1;
}
Expand Down Expand Up @@ -993,3 +993,173 @@ subprocess(const char *tag, struct passwd *pw, const char *command,
*child = f;
return pid;
}

/* These functions link key/cert options to the auth framework */

/* Log sshauthopt options locally and (optionally) for remote transmission */
void
auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote)
{
int do_env = options.permit_user_env && opts->nenv > 0;
int do_permitopen = opts->npermitopen > 0 &&
(options.allow_tcp_forwarding & FORWARD_LOCAL) != 0;
size_t i;
char msg[1024], tbuf[32];

snprintf(tbuf, sizeof(tbuf), "%d", opts->force_tun_device);
/* Try to keep this alphabetically sorted */
snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s",
opts->permit_agent_forwarding_flag ? " agent-forwarding" : "",
opts->force_command == NULL ? "" : " command",
do_env ? " environment" : "",
do_permitopen ? " permitopen" : "",
opts->permit_port_forwarding_flag ? " port-forwarding" : "",
opts->cert_principals == NULL ? "" : " principals",
opts->permit_pty_flag ? " pty" : "",
opts->force_tun_device == -1 ? "" : " tun=",
opts->force_tun_device == -1 ? "" : tbuf,
opts->permit_user_rc ? " user-rc" : "",
opts->permit_x11_forwarding_flag ? " x11-forwarding" : "");

debug("%s: %s", loc, msg);
if (do_remote)
auth_debug_add("%s: %s", loc, msg);

if (options.permit_user_env) {
for (i = 0; i < opts->nenv; i++) {
debug("%s: environment: %s", loc, opts->env[i]);
if (do_remote) {
auth_debug_add("%s: environment: %s",
loc, opts->env[i]);
}
}
}

/* Go into a little more details for the local logs. */
if (opts->cert_principals != NULL) {
debug("%s: authorized principals: \"%s\"",
loc, opts->cert_principals);
}
if (opts->force_command != NULL)
debug("%s: forced command: \"%s\"", loc, opts->force_command);
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) {
for (i = 0; i < opts->npermitopen; i++) {
debug("%s: permitted open: %s",
loc, opts->permitopen[i]);
}
}
}

/* Activate a new set of key/cert options; merging with what is there. */
int
auth_activate_options(struct ssh *ssh, struct sshauthopt *opts)
{
struct sshauthopt *old = auth_opts;
const char *emsg = NULL;

debug("%s: setting new authentication options", __func__);
if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) {
error("Inconsistent authentication options: %s", emsg);
return -1;
}
return 0;
}

/* Disable forwarding, etc for the session */
void
auth_restrict_session(struct ssh *ssh)
{
struct sshauthopt *restricted;

debug("%s: restricting session", __func__);

/* A blank sshauthopt defaults to permitting nothing */
restricted = sshauthopt_new();
restricted->restricted = 1;

if (auth_activate_options(ssh, restricted) != 0)
fatal("%s: failed to restrict session", __func__);
sshauthopt_free(restricted);
}

int
auth_authorise_keyopts(struct ssh *ssh, struct passwd *pw,
struct sshauthopt *opts, int allow_cert_authority, const char *loc)
{
const char *remote_ip = ssh_remote_ipaddr(ssh);
const char *remote_host = auth_get_canonical_hostname(ssh,
options.use_dns);

/* Consistency checks */
if (opts->cert_principals != NULL && !opts->cert_authority) {
debug("%s: principals on non-CA key", loc);
auth_debug_add("%s: principals on non-CA key", loc);
/* deny access */
return -1;
}
/* cert-authority flag isn't valid in authorized_principals files */
if (!allow_cert_authority && opts->cert_authority) {
debug("%s: cert-authority flag invalid here", loc);
auth_debug_add("%s: cert-authority flag invalid here", loc);
/* deny access */
return -1;
}

/* Perform from= checks */
if (opts->required_from_host_keys != NULL) {
switch (match_host_and_ip(remote_host, remote_ip,
opts->required_from_host_keys )) {
case 1:
/* Host name matches. */
break;
case -1:
default:
debug("%s: invalid from criteria", loc);
auth_debug_add("%s: invalid from criteria", loc);
/* FALLTHROUGH */
case 0:
logit("%s: Authentication tried for %.100s with "
"correct key but not from a permitted "
"host (host=%.200s, ip=%.200s, required=%.200s).",
loc, pw->pw_name, remote_host, remote_ip,
opts->required_from_host_keys);
auth_debug_add("%s: Your host '%.200s' is not "
"permitted to use this key for login.",
loc, remote_host);
/* deny access */
return -1;
}
}
/* Check source-address restriction from certificate */
if (opts->required_from_host_cert != NULL) {
switch (addr_match_cidr_list(remote_ip,
opts->required_from_host_cert)) {
case 1:
/* accepted */
break;
case -1:
default:
/* invalid */
error("%s: Certificate source-address invalid",
loc);
/* FALLTHROUGH */
case 0:
logit("%s: Authentication tried for %.100s with valid "
"certificate but not from a permitted source "
"address (%.200s).", loc, pw->pw_name, remote_ip);
auth_debug_add("%s: Your address '%.200s' is not "
"permitted to use this certificate for login.",
loc, remote_ip);
return -1;
}
}
/*
*
* XXX this is spammy. We should report remotely only for keys
* that are successful in actual auth attempts, and not PK_OK
* tests.
*/
auth_log_authopts(loc, opts, 1);

return 0;
}
Loading

0 comments on commit 7c85685

Please sign in to comment.