11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: auth-options.c,v 1.54 2010/12/24 21:41:48 djm Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Author: Tatu Ylonen <ylo@cs.hut.fi>
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *                    All rights reserved
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose.  Any derived versions of this
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell".
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netdb.h>
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h>
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h"
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "match.h"
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "canohost.h"
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "channels.h"
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "servconf.h"
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth-options.h"
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "hostfile.h"
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth.h"
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-gss.h"
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "monitor_wrap.h"
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Flags set authorized_keys flags */
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint no_port_forwarding_flag = 0;
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint no_agent_forwarding_flag = 0;
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint no_x11_forwarding_flag = 0;
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint no_pty_flag = 0;
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint no_user_rc = 0;
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint key_is_cert_authority = 0;
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* "command=" option. */
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *forced_command = NULL;
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* "environment=" options. */
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct envstring *custom_environment = NULL;
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* "tunnel=" option. */
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint forced_tun_device = -1;
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* "principals=" option. */
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *authorized_principals = NULL;
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern ServerOptions options;
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth_clear_options(void)
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_agent_forwarding_flag = 0;
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_port_forwarding_flag = 0;
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_pty_flag = 0;
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_x11_forwarding_flag = 0;
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_user_rc = 0;
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_is_cert_authority = 0;
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (custom_environment) {
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		struct envstring *ce = custom_environment;
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		custom_environment = ce->next;
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(ce->s);
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(ce);
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (forced_command) {
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(forced_command);
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		forced_command = NULL;
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authorized_principals) {
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(authorized_principals);
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authorized_principals = NULL;
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	forced_tun_device = -1;
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_clear_permitted_opens();
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * return 1 if access is granted, 0 if not.
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * side effect: sets key option flags
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *cp;
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* reset options */
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	auth_clear_options();
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!opts)
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (*opts && *opts != ' ' && *opts != '\t') {
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "cert-authority";
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_is_cert_authority = 1;
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "no-port-forwarding";
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Port forwarding disabled.");
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			no_port_forwarding_flag = 1;
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "no-agent-forwarding";
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Agent forwarding disabled.");
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			no_agent_forwarding_flag = 1;
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "no-X11-forwarding";
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("X11 forwarding disabled.");
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			no_x11_forwarding_flag = 1;
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "no-pty";
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Pty allocation disabled.");
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			no_pty_flag = 1;
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "no-user-rc";
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("User rc file execution disabled.");
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			no_user_rc = 1;
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "command=\"";
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (forced_command != NULL)
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(forced_command);
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			forced_command = xmalloc(strlen(opts) + 1);
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			i = 0;
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			while (*opts) {
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '"')
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '\\' && opts[1] == '"') {
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					opts += 2;
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					forced_command[i++] = '"';
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				forced_command[i++] = *opts++;
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!*opts) {
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: missing end quote",
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: missing end quote",
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(forced_command);
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				forced_command = NULL;
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			forced_command[i] = '\0';
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Forced command.");
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts++;
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "principals=\"";
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (authorized_principals != NULL)
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(authorized_principals);
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			authorized_principals = xmalloc(strlen(opts) + 1);
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			i = 0;
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			while (*opts) {
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '"')
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '\\' && opts[1] == '"') {
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					opts += 2;
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					authorized_principals[i++] = '"';
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				authorized_principals[i++] = *opts++;
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!*opts) {
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: missing end quote",
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: missing end quote",
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(authorized_principals);
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				authorized_principals = NULL;
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			authorized_principals[i] = '\0';
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("principals: %.900s",
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    authorized_principals);
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts++;
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "environment=\"";
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (options.permit_user_env &&
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strncasecmp(opts, cp, strlen(cp)) == 0) {
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			char *s;
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			struct envstring *new_envstring;
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s = xmalloc(strlen(opts) + 1);
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			i = 0;
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			while (*opts) {
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '"')
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '\\' && opts[1] == '"') {
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					opts += 2;
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					s[i++] = '"';
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				s[i++] = *opts++;
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!*opts) {
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: missing end quote",
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: missing end quote",
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(s);
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s[i] = '\0';
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Adding to environment: %.900s", s);
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Adding to environment: %.900s", s);
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts++;
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			new_envstring = xmalloc(sizeof(struct envstring));
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			new_envstring->s = s;
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			new_envstring->next = custom_environment;
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			custom_environment = new_envstring;
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "from=\"";
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			const char *remote_ip = get_remote_ipaddr();
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			const char *remote_host = get_canonical_hostname(
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    options.use_dns);
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			char *patterns = xmalloc(strlen(opts) + 1);
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			i = 0;
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			while (*opts) {
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '"')
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '\\' && opts[1] == '"') {
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					opts += 2;
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					patterns[i++] = '"';
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				patterns[i++] = *opts++;
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!*opts) {
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: missing end quote",
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: missing end quote",
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(patterns);
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			patterns[i] = '\0';
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts++;
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			switch (match_host_and_ip(remote_host, remote_ip,
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    patterns)) {
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 1:
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(patterns);
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Host name matches. */
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto next_option;
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case -1:
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: invalid criteria",
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: "
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "invalid criteria", file, linenum);
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* FALLTHROUGH */
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 0:
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(patterns);
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				logit("Authentication tried for %.100s with "
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "correct key but not from a permitted "
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "host (host=%.200s, ip=%.200s).",
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    pw->pw_name, remote_host, remote_ip);
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("Your host '%.200s' is not "
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "permitted to use this key for login.",
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    remote_host);
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* deny access */
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "permitopen=\"";
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			char *host, *p;
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			int port;
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			char *patterns = xmalloc(strlen(opts) + 1);
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			i = 0;
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			while (*opts) {
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '"')
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '\\' && opts[1] == '"') {
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					opts += 2;
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					patterns[i++] = '"';
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				patterns[i++] = *opts++;
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!*opts) {
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: missing end quote",
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: missing "
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "end quote", file, linenum);
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(patterns);
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			patterns[i] = '\0';
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts++;
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			p = patterns;
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			host = hpdelim(&p);
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (host == NULL || strlen(host) >= NI_MAXHOST) {
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: Bad permitopen "
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "specification <%.100s>", file, linenum,
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    patterns);
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: "
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "Bad permitopen specification", file,
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    linenum);
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(patterns);
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			host = cleanhostname(host);
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (p == NULL || (port = a2port(p)) <= 0) {
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: Bad permitopen port "
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "<%.100s>", file, linenum, p ? p : "");
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: "
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "Bad permitopen port", file, linenum);
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(patterns);
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (options.allow_tcp_forwarding)
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				channel_add_permitted_opens(host, port);
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(patterns);
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp = "tunnel=\"";
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			char *tun = NULL;
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts += strlen(cp);
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			tun = xmalloc(strlen(opts) + 1);
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			i = 0;
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			while (*opts) {
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*opts == '"')
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				tun[i++] = *opts++;
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!*opts) {
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: missing end quote",
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: missing end quote",
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(tun);
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				forced_tun_device = -1;
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			tun[i] = '\0';
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			forced_tun_device = a2tun(tun, NULL);
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(tun);
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (forced_tun_device == SSH_TUNID_ERR) {
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("%.100s, line %lu: invalid tun device",
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				auth_debug_add("%.100s, line %lu: invalid tun device",
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    file, linenum);
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				forced_tun_device = -1;
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto bad_option;
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Forced tun device: %d", forced_tun_device);
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			opts++;
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto next_option;
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodnext_option:
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Skip the comma, and move to the next option
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * (or break out if there are no more).
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!*opts)
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("Bugs in auth-options.c option processing.");
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*opts == ' ' || *opts == '\t')
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;		/* End of options. */
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*opts != ',')
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto bad_option;
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		opts++;
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Process the next option. */
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* grant access */
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodbad_option:
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	logit("Bad options in %.100s file, line %lu: %.50s",
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    file, linenum, opts);
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    file, linenum, opts);
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* deny access */
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define OPTIONS_CRITICAL	1
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define OPTIONS_EXTENSIONS	2
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodparse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    u_int which, int crit,
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int *cert_no_port_forwarding_flag,
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int *cert_no_agent_forwarding_flag,
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int *cert_no_x11_forwarding_flag,
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int *cert_no_pty_flag,
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int *cert_no_user_rc,
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    char **cert_forced_command,
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int *cert_source_address_done)
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *command, *allowed;
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *remote_ip;
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *name = NULL, *data_blob = NULL;
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int nlen, dlen, clen;
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer c, data;
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = -1, found;
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&data);
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Make copy to avoid altering original */
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&c);
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&c, optblob, optblob_len);
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (buffer_len(&c) > 0) {
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL ||
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Certificate options corrupt");
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_append(&data, data_blob, dlen);
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("found certificate option \"%.100s\" len %u",
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    name, dlen);
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strlen(name) != nlen) {
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Certificate constraint name contains \\0");
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		found = 0;
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((which & OPTIONS_EXTENSIONS) != 0) {
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strcmp(name, "permit-X11-forwarding") == 0) {
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*cert_no_x11_forwarding_flag = 0;
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				found = 1;
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else if (strcmp(name,
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "permit-agent-forwarding") == 0) {
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*cert_no_agent_forwarding_flag = 0;
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				found = 1;
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else if (strcmp(name,
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "permit-port-forwarding") == 0) {
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*cert_no_port_forwarding_flag = 0;
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				found = 1;
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else if (strcmp(name, "permit-pty") == 0) {
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*cert_no_pty_flag = 0;
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				found = 1;
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else if (strcmp(name, "permit-user-rc") == 0) {
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*cert_no_user_rc = 0;
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				found = 1;
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!found && (which & OPTIONS_CRITICAL) != 0) {
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strcmp(name, "force-command") == 0) {
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if ((command = buffer_get_cstring_ret(&data,
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    &clen)) == NULL) {
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("Certificate constraint \"%s\" "
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "corrupt", name);
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto out;
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (strlen(command) != clen) {
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("force-command constraint "
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "contains \\0");
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto out;
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (*cert_forced_command != NULL) {
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("Certificate has multiple "
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "force-command options");
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					xfree(command);
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto out;
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*cert_forced_command = command;
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				found = 1;
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strcmp(name, "source-address") == 0) {
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if ((allowed = buffer_get_cstring_ret(&data,
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    &clen)) == NULL) {
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("Certificate constraint "
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "\"%s\" corrupt", name);
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto out;
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (strlen(allowed) != clen) {
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("source-address constraint "
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "contains \\0");
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto out;
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if ((*cert_source_address_done)++) {
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("Certificate has multiple "
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "source-address options");
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					xfree(allowed);
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto out;
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				remote_ip = get_remote_ipaddr();
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				switch (addr_match_cidr_list(remote_ip,
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    allowed)) {
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				case 1:
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					/* accepted */
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					xfree(allowed);
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				case 0:
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					/* no match */
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					logit("Authentication tried for %.100s "
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "with valid certificate but not "
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "from a permitted host "
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "(ip=%.200s).", pw->pw_name,
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    remote_ip);
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					auth_debug_add("Your address '%.200s' "
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "is not permitted to use this "
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "certificate for login.",
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    remote_ip);
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					xfree(allowed);
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto out;
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				case -1:
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("Certificate source-address "
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "contents invalid");
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					xfree(allowed);
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto out;
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				found = 1;
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!found) {
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (crit) {
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				error("Certificate critical option \"%s\" "
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "is not supported", name);
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto out;
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else {
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				logit("Certificate extension \"%s\" "
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "is not supported", name);
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (buffer_len(&data) != 0) {
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Certificate option \"%s\" corrupt "
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "(extra data)", name);
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&data);
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(name);
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(data_blob);
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		name = data_blob = NULL;
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* successfully parsed all options */
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = 0;
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out:
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ret != 0 &&
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    cert_forced_command != NULL &&
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    *cert_forced_command != NULL) {
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(*cert_forced_command);
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*cert_forced_command = NULL;
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (name != NULL)
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(name);
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (data_blob != NULL)
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(data_blob);
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&data);
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&c);
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Set options from critical certificate options. These supersede user key
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * options so this must be called after auth_parse_options().
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth_cert_options(Key *k, struct passwd *pw)
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cert_no_port_forwarding_flag = 1;
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cert_no_agent_forwarding_flag = 1;
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cert_no_x11_forwarding_flag = 1;
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cert_no_pty_flag = 1;
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cert_no_user_rc = 1;
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *cert_forced_command = NULL;
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cert_source_address_done = 0;
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_cert_is_legacy(k)) {
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* All options are in the one field for v00 certs */
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (parse_option_list(buffer_ptr(&k->cert->critical),
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(&k->cert->critical), pw,
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_port_forwarding_flag,
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_agent_forwarding_flag,
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_x11_forwarding_flag,
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_pty_flag,
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_user_rc,
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_forced_command,
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_source_address_done) == -1)
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Separate options and extensions for v01 certs */
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (parse_option_list(buffer_ptr(&k->cert->critical),
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(&k->cert->critical), pw,
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_forced_command,
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_source_address_done) == -1)
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (parse_option_list(buffer_ptr(&k->cert->extensions),
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(&k->cert->extensions), pw,
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    OPTIONS_EXTENSIONS, 1,
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_port_forwarding_flag,
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_agent_forwarding_flag,
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_x11_forwarding_flag,
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_pty_flag,
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &cert_no_user_rc,
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    NULL, NULL) == -1)
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_port_forwarding_flag |= cert_no_port_forwarding_flag;
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_pty_flag |= cert_no_pty_flag;
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	no_user_rc |= cert_no_user_rc;
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* CA-specified forced command supersedes key option */
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cert_forced_command != NULL) {
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (forced_command != NULL)
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(forced_command);
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		forced_command = cert_forced_command;
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
650