diff options
Diffstat (limited to 'readconf.c')
| -rw-r--r-- | readconf.c | 190 | 
1 files changed, 142 insertions, 48 deletions
| diff --git a/readconf.c b/readconf.c index 88051db5789b9..db5f2d5476ad2 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.283 2018/02/23 15:58:37 markus Exp $ */ +/* $OpenBSD: readconf.c,v 1.297 2018/08/12 20:19:13 djm Exp $ */  /*   * Author: Tatu Ylonen <ylo@cs.hut.fi>   * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -53,6 +53,7 @@  #include "xmalloc.h"  #include "ssh.h" +#include "ssherr.h"  #include "compat.h"  #include "cipher.h"  #include "pathnames.h" @@ -161,7 +162,7 @@ typedef enum {  	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,  	oAddressFamily, oGssAuthentication, oGssDelegateCreds,  	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, -	oSendEnv, oControlPath, oControlMaster, oControlPersist, +	oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,  	oHashKnownHosts,  	oTunnel, oTunnelDevice,  	oLocalCommand, oPermitLocalCommand, oRemoteCommand, @@ -190,6 +191,7 @@ static struct {  	{ "userknownhostsfile2", oDeprecated },  	{ "useroaming", oDeprecated },  	{ "usersh", oDeprecated }, +	{ "useprivilegedport", oDeprecated },  	/* Unsupported options */  	{ "afstokenpassing", oUnsupported }, @@ -222,7 +224,6 @@ static struct {  	{ "exitonforwardfailure", oExitOnForwardFailure },  	{ "xauthlocation", oXAuthLocation },  	{ "gatewayports", oGatewayPorts }, -	{ "useprivilegedport", oUsePrivilegedPort },  	{ "passwordauthentication", oPasswordAuthentication },  	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },  	{ "kbdinteractivedevices", oKbdInteractiveDevices }, @@ -230,7 +231,7 @@ static struct {  	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */  	{ "hostbasedauthentication", oHostbasedAuthentication },  	{ "challengeresponseauthentication", oChallengeResponseAuthentication }, -	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ +	{ "skeyauthentication", oUnsupported },  	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */  	{ "identityfile", oIdentityFile },  	{ "identityfile2", oIdentityFile },			/* obsolete */ @@ -277,6 +278,7 @@ static struct {  	{ "serveraliveinterval", oServerAliveInterval },  	{ "serveralivecountmax", oServerAliveCountMax },  	{ "sendenv", oSendEnv }, +	{ "setenv", oSetEnv },  	{ "controlpath", oControlPath },  	{ "controlmaster", oControlMaster },  	{ "controlpersist", oControlPersist }, @@ -319,12 +321,8 @@ void  add_local_forward(Options *options, const struct Forward *newfwd)  {  	struct Forward *fwd; -	extern uid_t original_real_uid;  	int i; -	if (!bind_permitted(newfwd->listen_port, original_real_uid) && -	    newfwd->listen_path == NULL) -		fatal("Privileged ports can only be forwarded by root.");  	/* Don't add duplicates */  	for (i = 0; i < options->num_local_forwards; i++) {  		if (forward_equals(newfwd, options->local_forwards + i)) @@ -482,7 +480,6 @@ execute_in_shell(const char *cmd)  	char *shell;  	pid_t pid;  	int devnull, status; -	extern uid_t original_real_uid;  	if ((shell = getenv("SHELL")) == NULL)  		shell = _PATH_BSHELL; @@ -497,9 +494,6 @@ execute_in_shell(const char *cmd)  	if ((pid = fork()) == 0) {  		char *argv[4]; -		/* Child.  Permanently give up superuser privileges. */ -		permanently_drop_suid(original_real_uid); -  		/* Redirect child stdin and stdout. Leave stderr */  		if (dup2(devnull, STDIN_FILENO) == -1)  			fatal("dup2: %s", strerror(errno)); @@ -551,6 +545,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,  	const char *ruser;  	int r, port, this_result, result = 1, attributes = 0, negate;  	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; +	char uidstr[32];  	/*  	 * Configuration is likely to be incomplete at this point so we @@ -631,6 +626,8 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,  			strlcpy(shorthost, thishost, sizeof(shorthost));  			shorthost[strcspn(thishost, ".")] = '\0';  			snprintf(portstr, sizeof(portstr), "%d", port); +			snprintf(uidstr, sizeof(uidstr), "%llu", +			    (unsigned long long)pw->pw_uid);  			cmd = percent_expand(arg,  			    "L", shorthost, @@ -641,6 +638,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,  			    "p", portstr,  			    "r", ruser,  			    "u", pw->pw_name, +			    "i", uidstr,  			    (char *)NULL);  			if (result != 1) {  				/* skip execution if prior predicate failed */ @@ -684,6 +682,35 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,  	return result;  } +/* Remove environment variable by pattern */ +static void +rm_env(Options *options, const char *arg, const char *filename, int linenum) +{ +	int i, j; +	char *cp; + +	/* Remove an environment variable */ +	for (i = 0; i < options->num_send_env; ) { +		cp = xstrdup(options->send_env[i]); +		if (!match_pattern(cp, arg + 1)) { +			free(cp); +			i++; +			continue; +		} +		debug3("%s line %d: removing environment %s", +		    filename, linenum, cp); +		free(cp); +		free(options->send_env[i]); +		options->send_env[i] = NULL; +		for (j = i; j < options->num_send_env - 1; j++) { +			options->send_env[j] = options->send_env[j + 1]; +			options->send_env[j + 1] = NULL; +		} +		options->num_send_env--; +		/* NB. don't increment i */ +	} +} +  /*   * Returns the number of the token pointed to by cp or oBadOption.   */ @@ -918,10 +945,6 @@ parse_time:  		intptr = &options->exit_on_forward_failure;  		goto parse_flag; -	case oUsePrivilegedPort: -		intptr = &options->use_privileged_port; -		goto parse_flag; -  	case oPasswordAuthentication:  		intptr = &options->password_authentication;  		goto parse_flag; @@ -1359,11 +1382,41 @@ parse_keytypes:  				    filename, linenum);  			if (!*activep)  				continue; -			if (options->num_send_env >= MAX_SEND_ENV) -				fatal("%s line %d: too many send env.", +			if (*arg == '-') { +				/* Removing an env var */ +				rm_env(options, arg, filename, linenum); +				continue; +			} else { +				/* Adding an env var */ +				if (options->num_send_env >= INT_MAX) +					fatal("%s line %d: too many send env.", +					    filename, linenum); +				options->send_env = xrecallocarray( +				    options->send_env, options->num_send_env, +				    options->num_send_env + 1, +				    sizeof(*options->send_env)); +				options->send_env[options->num_send_env++] = +				    xstrdup(arg); +			} +		} +		break; + +	case oSetEnv: +		value = options->num_setenv; +		while ((arg = strdelimw(&s)) != NULL && *arg != '\0') { +			if (strchr(arg, '=') == NULL) +				fatal("%s line %d: Invalid SetEnv.", +				    filename, linenum); +			if (!*activep || value != 0) +				continue; +			/* Adding a setenv var */ +			if (options->num_setenv >= INT_MAX) +				fatal("%s line %d: too many SetEnv.",  				    filename, linenum); -			options->send_env[options->num_send_env++] = -			    xstrdup(arg); +			options->setenv = xrecallocarray( +			    options->setenv, options->num_setenv, +			    options->num_setenv + 1, sizeof(*options->setenv)); +			options->setenv[options->num_setenv++] = xstrdup(arg);  		}  		break; @@ -1688,7 +1741,8 @@ read_config_file_depth(const char *filename, struct passwd *pw,      int flags, int *activep, int depth)  {  	FILE *f; -	char line[4096]; +	char *line = NULL; +	size_t linesize = 0;  	int linenum;  	int bad_options = 0; @@ -1715,15 +1769,14 @@ read_config_file_depth(const char *filename, struct passwd *pw,  	 * on/off by Host specifications.  	 */  	linenum = 0; -	while (fgets(line, sizeof(line), f)) { +	while (getline(&line, &linesize, f) != -1) {  		/* Update line number counter. */  		linenum++; -		if (strlen(line) == sizeof(line) - 1) -			fatal("%s line %d too long", filename, linenum);  		if (process_config_line_depth(options, pw, host, original_host,  		    line, filename, linenum, activep, flags, depth) != 0)  			bad_options++;  	} +	free(line);  	fclose(f);  	if (bad_options > 0)  		fatal("%s: terminating, %d bad configuration options", @@ -1761,7 +1814,6 @@ initialize_options(Options * options)  	options->fwd_opts.gateway_ports = -1;  	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;  	options->fwd_opts.streamlocal_bind_unlink = -1; -	options->use_privileged_port = -1;  	options->pubkey_authentication = -1;  	options->challenge_response_authentication = -1;  	options->gss_authentication = -1; @@ -1815,7 +1867,10 @@ initialize_options(Options * options)  	options->verify_host_key_dns = -1;  	options->server_alive_interval = -1;  	options->server_alive_count_max = -1; +	options->send_env = NULL;  	options->num_send_env = 0; +	options->setenv = NULL; +	options->num_setenv = 0;  	options->control_path = NULL;  	options->control_master = -1;  	options->control_persist = -1; @@ -1869,6 +1924,9 @@ fill_default_options_for_canonicalization(Options *options)  void  fill_default_options(Options * options)  { +	char *all_cipher, *all_mac, *all_kex, *all_key; +	int r; +  	if (options->forward_agent == -1)  		options->forward_agent = 0;  	if (options->forward_x11 == -1) @@ -1898,8 +1956,6 @@ fill_default_options(Options * options)  		options->fwd_opts.streamlocal_bind_mask = 0177;  	if (options->fwd_opts.streamlocal_bind_unlink == -1)  		options->fwd_opts.streamlocal_bind_unlink = 0; -	if (options->use_privileged_port == -1) -		options->use_privileged_port = 0;  	if (options->pubkey_authentication == -1)  		options->pubkey_authentication = 1;  	if (options->challenge_response_authentication == -1) @@ -1998,9 +2054,9 @@ fill_default_options(Options * options)  	if (options->visual_host_key == -1)  		options->visual_host_key = 0;  	if (options->ip_qos_interactive == -1) -		options->ip_qos_interactive = IPTOS_LOWDELAY; +		options->ip_qos_interactive = IPTOS_DSCP_AF21;  	if (options->ip_qos_bulk == -1) -		options->ip_qos_bulk = IPTOS_THROUGHPUT; +		options->ip_qos_bulk = IPTOS_DSCP_CS1;  	if (options->request_tty == -1)  		options->request_tty = REQUEST_TTY_AUTO;  	if (options->proxy_use_fdpass == -1) @@ -2015,14 +2071,28 @@ fill_default_options(Options * options)  		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;  	if (options->update_hostkeys == -1)  		options->update_hostkeys = 0; -	if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || -	    kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 || -	    kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 || -	    kex_assemble_names(KEX_DEFAULT_PK_ALG, -	    &options->hostbased_key_types) != 0 || -	    kex_assemble_names(KEX_DEFAULT_PK_ALG, -	    &options->pubkey_key_types) != 0) -		fatal("%s: kex_assemble_names failed", __func__); + +	/* Expand KEX name lists */ +	all_cipher = cipher_alg_list(',', 0); +	all_mac = mac_alg_list(','); +	all_kex = kex_alg_list(','); +	all_key = sshkey_alg_list(0, 0, 1, ','); +#define ASSEMBLE(what, defaults, all) \ +	do { \ +		if ((r = kex_assemble_names(&options->what, \ +		    defaults, all)) != 0) \ +			fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \ +	} while (0) +	ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher); +	ASSEMBLE(macs, KEX_SERVER_MAC, all_mac); +	ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex); +	ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key); +	ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key); +#undef ASSEMBLE +	free(all_cipher); +	free(all_mac); +	free(all_kex); +	free(all_key);  #define CLEAR_ON_NONE(v) \  	do { \ @@ -2036,6 +2106,12 @@ fill_default_options(Options * options)  	CLEAR_ON_NONE(options->proxy_command);  	CLEAR_ON_NONE(options->control_path);  	CLEAR_ON_NONE(options->revoked_host_keys); +	if (options->jump_host != NULL && +	    strcmp(options->jump_host, "none") == 0 && +	    options->jump_port == 0 && options->jump_user == NULL) { +		free(options->jump_host); +		options->jump_host = NULL; +	}  	/* options->identity_agent distinguishes NULL from 'none' */  	/* options->user will be set in the main program if appropriate */  	/* options->hostname will be set in the main program if appropriate */ @@ -2264,6 +2340,8 @@ parse_jump(const char *s, Options *o, int active)  	orig = sdup = xstrdup(s);  	first = active;  	do { +		if (strcasecmp(s, "none") == 0) +			break;  		if ((cp = strrchr(sdup, ',')) == NULL)  			cp = sdup; /* last */  		else @@ -2284,14 +2362,19 @@ parse_jump(const char *s, Options *o, int active)  	} while (cp != sdup);  	/* success */  	if (active) { -		o->jump_user = user; -		o->jump_host = host; -		o->jump_port = port; -		o->proxy_command = xstrdup("none"); -		user = host = NULL; -		if ((cp = strrchr(s, ',')) != NULL && cp != s) { -			o->jump_extra = xstrdup(s); -			o->jump_extra[cp - s] = '\0'; +		if (strcasecmp(s, "none") == 0) { +			o->jump_host = xstrdup("none"); +			o->jump_port = 0; +		} else { +			o->jump_user = user; +			o->jump_host = host; +			o->jump_port = port; +			o->proxy_command = xstrdup("none"); +			user = host = NULL; +			if ((cp = strrchr(s, ',')) != NULL && cp != s) { +				o->jump_extra = xstrdup(s); +				o->jump_extra[cp - s] = '\0'; +			}  		}  	}  	ret = 0; @@ -2348,6 +2431,8 @@ fmt_intarg(OpCodes code, int val)  		return fmt_multistate_int(val, multistate_requesttty);  	case oCanonicalizeHostname:  		return fmt_multistate_int(val, multistate_canonicalizehostname); +	case oAddKeysToAgent: +		return fmt_multistate_int(val, multistate_yesnoaskconfirm);  	case oFingerprintHash:  		return ssh_digest_alg_name(val);  	default: @@ -2455,11 +2540,14 @@ void  dump_client_config(Options *o, const char *host)  {  	int i; -	char buf[8]; +	char buf[8], *all_key;  	/* This is normally prepared in ssh_kex2 */ -	if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0) +	all_key = sshkey_alg_list(0, 0, 1, ','); +	if (kex_assemble_names( &o->hostkeyalgorithms, +	    KEX_DEFAULT_PK_ALG, all_key) != 0)  		fatal("%s: kex_assemble_names failed", __func__); +	free(all_key);  	/* Most interesting options first: user, host, port */  	dump_cfg_string(oUser, o->user); @@ -2467,6 +2555,7 @@ dump_client_config(Options *o, const char *host)  	dump_cfg_int(oPort, o->port);  	/* Flag options */ +	dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);  	dump_cfg_fmtint(oAddressFamily, o->address_family);  	dump_cfg_fmtint(oBatchMode, o->batch_mode);  	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); @@ -2501,7 +2590,6 @@ dump_client_config(Options *o, const char *host)  	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);  	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);  	dump_cfg_fmtint(oTunnel, o->tun_open); -	dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);  	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);  	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);  	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); @@ -2523,6 +2611,7 @@ dump_client_config(Options *o, const char *host)  	dump_cfg_string(oHostKeyAlias, o->host_key_alias);  	dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);  	dump_cfg_string(oIdentityAgent, o->identity_agent); +	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);  	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);  	dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);  	dump_cfg_string(oLocalCommand, o->local_command); @@ -2545,9 +2634,11 @@ dump_client_config(Options *o, const char *host)  	/* String array options */  	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);  	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); +	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);  	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);  	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);  	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); +	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);  	/* Special cases */ @@ -2605,6 +2696,9 @@ dump_client_config(Options *o, const char *host)  	printf("streamlocalbindmask 0%o\n",  	    o->fwd_opts.streamlocal_bind_mask); +	/* oLogFacility */ +	printf("syslogfacility %s\n", log_facility_name(o->log_facility)); +  	/* oProxyCommand / oProxyJump */  	if (o->jump_host == NULL)  		dump_cfg_string(oProxyCommand, o->proxy_command); | 
