servconf.c revision 65674
157429Smarkm/*
257429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
357429Smarkm *                    All rights reserved
460576Skris *
565674Skris * As far as I am concerned, the code I have written for this software
665674Skris * can be used freely for any purpose.  Any derived versions of this
765674Skris * software must be clearly marked as such, and if the derived work is
865674Skris * incompatible with the protocol description in the RFC file, it must be
965674Skris * called by a name other than "ssh" or "Secure Shell".
1057429Smarkm */
1157429Smarkm
1257429Smarkm#include "includes.h"
1365674SkrisRCSID("$OpenBSD: servconf.c,v 1.51 2000/09/07 20:27:53 deraadt Exp $");
1465674SkrisRCSID("$FreeBSD: head/crypto/openssh/servconf.c 65674 2000-09-10 09:35:38Z kris $");
1557429Smarkm
1657429Smarkm#include "ssh.h"
1757429Smarkm#include "servconf.h"
1857429Smarkm#include "xmalloc.h"
1960576Skris#include "compat.h"
2057429Smarkm
2157429Smarkm/* add listen address */
2257429Smarkmvoid add_listen_addr(ServerOptions *options, char *addr);
2357429Smarkm
2457429Smarkm/* Initializes the server options to their default values. */
2557429Smarkm
2660576Skrisvoid
2757429Smarkminitialize_server_options(ServerOptions *options)
2857429Smarkm{
2957429Smarkm	memset(options, 0, sizeof(*options));
3057429Smarkm	options->num_ports = 0;
3157429Smarkm	options->ports_from_cmdline = 0;
3257429Smarkm	options->listen_addrs = NULL;
3357429Smarkm	options->host_key_file = NULL;
3460576Skris	options->host_dsa_key_file = NULL;
3560576Skris	options->pid_file = NULL;
3657429Smarkm	options->server_key_bits = -1;
3757429Smarkm	options->login_grace_time = -1;
3857429Smarkm	options->key_regeneration_time = -1;
3957429Smarkm	options->permit_root_login = -1;
4057429Smarkm	options->ignore_rhosts = -1;
4157429Smarkm	options->ignore_user_known_hosts = -1;
4257429Smarkm	options->print_motd = -1;
4357429Smarkm	options->check_mail = -1;
4457429Smarkm	options->x11_forwarding = -1;
4557429Smarkm	options->x11_display_offset = -1;
4665674Skris	options->xauth_location = NULL;
4757429Smarkm	options->strict_modes = -1;
4857429Smarkm	options->keepalives = -1;
4957429Smarkm	options->log_facility = (SyslogFacility) - 1;
5057429Smarkm	options->log_level = (LogLevel) - 1;
5157429Smarkm	options->rhosts_authentication = -1;
5257429Smarkm	options->rhosts_rsa_authentication = -1;
5357429Smarkm	options->rsa_authentication = -1;
5460576Skris	options->dsa_authentication = -1;
5557429Smarkm#ifdef KRB4
5657565Smarkm	options->krb4_authentication = -1;
5757565Smarkm	options->krb4_or_local_passwd = -1;
5857565Smarkm	options->krb4_ticket_cleanup = -1;
5957429Smarkm#endif
6057565Smarkm#ifdef KRB5
6157565Smarkm	options->krb5_authentication = -1;
6257565Smarkm	options->krb5_tgt_passing = -1;
6357565Smarkm#endif /* KRB5 */
6457429Smarkm#ifdef AFS
6557565Smarkm	options->krb4_tgt_passing = -1;
6657429Smarkm	options->afs_token_passing = -1;
6757429Smarkm#endif
6857429Smarkm	options->password_authentication = -1;
6957429Smarkm#ifdef SKEY
7057429Smarkm	options->skey_authentication = -1;
7157429Smarkm#endif
7257429Smarkm	options->permit_empty_passwd = -1;
7357429Smarkm	options->use_login = -1;
7457429Smarkm	options->num_allow_users = 0;
7557429Smarkm	options->num_deny_users = 0;
7657429Smarkm	options->num_allow_groups = 0;
7757429Smarkm	options->num_deny_groups = 0;
7860576Skris	options->ciphers = NULL;
7960576Skris	options->protocol = SSH_PROTO_UNKNOWN;
8060576Skris	options->gateway_ports = -1;
8157432Smarkm	options->connections_per_period = 0;
8257432Smarkm	options->connections_period = 0;
8365674Skris	options->num_subsystems = 0;
8465674Skris	options->max_startups_begin = -1;
8565674Skris	options->max_startups_rate = -1;
8665674Skris	options->max_startups = -1;
8757429Smarkm}
8857429Smarkm
8960576Skrisvoid
9057429Smarkmfill_default_server_options(ServerOptions *options)
9157429Smarkm{
9257429Smarkm	if (options->num_ports == 0)
9357429Smarkm		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
9457429Smarkm	if (options->listen_addrs == NULL)
9557429Smarkm		add_listen_addr(options, NULL);
9657429Smarkm	if (options->host_key_file == NULL)
9757429Smarkm		options->host_key_file = HOST_KEY_FILE;
9860576Skris	if (options->host_dsa_key_file == NULL)
9960576Skris		options->host_dsa_key_file = HOST_DSA_KEY_FILE;
10060576Skris	if (options->pid_file == NULL)
10160576Skris		options->pid_file = SSH_DAEMON_PID_FILE;
10257429Smarkm	if (options->server_key_bits == -1)
10357429Smarkm		options->server_key_bits = 768;
10457429Smarkm	if (options->login_grace_time == -1)
10565022Skris		options->login_grace_time = 120;
10657429Smarkm	if (options->key_regeneration_time == -1)
10757429Smarkm		options->key_regeneration_time = 3600;
10857429Smarkm	if (options->permit_root_login == -1)
10962942Speter		options->permit_root_login = 0;			/* no */
11057429Smarkm	if (options->ignore_rhosts == -1)
11157565Smarkm		options->ignore_rhosts = 1;
11257429Smarkm	if (options->ignore_user_known_hosts == -1)
11357429Smarkm		options->ignore_user_known_hosts = 0;
11457429Smarkm	if (options->check_mail == -1)
11562944Speter		options->check_mail = 1;
11657429Smarkm	if (options->print_motd == -1)
11757429Smarkm		options->print_motd = 1;
11857429Smarkm	if (options->x11_forwarding == -1)
11965357Skris		options->x11_forwarding = 1;
12057429Smarkm	if (options->x11_display_offset == -1)
12157565Smarkm		options->x11_display_offset = 10;
12265674Skris#ifdef XAUTH_PATH
12365674Skris	if (options->xauth_location == NULL)
12465674Skris		options->xauth_location = XAUTH_PATH;
12565674Skris#endif /* XAUTH_PATH */
12657429Smarkm	if (options->strict_modes == -1)
12757429Smarkm		options->strict_modes = 1;
12857429Smarkm	if (options->keepalives == -1)
12957429Smarkm		options->keepalives = 1;
13057429Smarkm	if (options->log_facility == (SyslogFacility) (-1))
13157429Smarkm		options->log_facility = SYSLOG_FACILITY_AUTH;
13257429Smarkm	if (options->log_level == (LogLevel) (-1))
13357429Smarkm		options->log_level = SYSLOG_LEVEL_INFO;
13457429Smarkm	if (options->rhosts_authentication == -1)
13557429Smarkm		options->rhosts_authentication = 0;
13657429Smarkm	if (options->rhosts_rsa_authentication == -1)
13757565Smarkm		options->rhosts_rsa_authentication = 0;
13857429Smarkm	if (options->rsa_authentication == -1)
13957429Smarkm		options->rsa_authentication = 1;
14060576Skris	if (options->dsa_authentication == -1)
14160576Skris		options->dsa_authentication = 1;
14257429Smarkm#ifdef KRB4
14357565Smarkm	if (options->krb4_authentication == -1)
14457565Smarkm		options->krb4_authentication = (access(KEYFILE, R_OK) == 0);
14557565Smarkm	if (options->krb4_or_local_passwd == -1)
14657565Smarkm		options->krb4_or_local_passwd = 1;
14757565Smarkm	if (options->krb4_ticket_cleanup == -1)
14857565Smarkm		options->krb4_ticket_cleanup = 1;
14957429Smarkm#endif /* KRB4 */
15057565Smarkm#ifdef KRB5
15157565Smarkm	if (options->krb5_authentication == -1)
15257565Smarkm	  	options->krb5_authentication = 1;
15357565Smarkm	if (options->krb5_tgt_passing == -1)
15457565Smarkm	  	options->krb5_tgt_passing = 1;
15557565Smarkm#endif /* KRB5 */
15657429Smarkm#ifdef AFS
15757565Smarkm	if (options->krb4_tgt_passing == -1)
15857565Smarkm		options->krb4_tgt_passing = 0;
15957429Smarkm	if (options->afs_token_passing == -1)
16057429Smarkm		options->afs_token_passing = k_hasafs();
16157429Smarkm#endif /* AFS */
16257429Smarkm	if (options->password_authentication == -1)
16357429Smarkm		options->password_authentication = 1;
16457429Smarkm#ifdef SKEY
16557429Smarkm	if (options->skey_authentication == -1)
16657429Smarkm		options->skey_authentication = 1;
16757429Smarkm#endif
16857429Smarkm	if (options->permit_empty_passwd == -1)
16957565Smarkm		options->permit_empty_passwd = 0;
17057429Smarkm	if (options->use_login == -1)
17157429Smarkm		options->use_login = 0;
17260576Skris	if (options->protocol == SSH_PROTO_UNKNOWN)
17360576Skris		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
17460576Skris	if (options->gateway_ports == -1)
17560576Skris		options->gateway_ports = 0;
17665674Skris	if (options->max_startups == -1)
17765674Skris		options->max_startups = 10;
17865674Skris	if (options->max_startups_rate == -1)
17965674Skris		options->max_startups_rate = 100;		/* 100% */
18065674Skris	if (options->max_startups_begin == -1)
18165674Skris		options->max_startups_begin = options->max_startups;
18257429Smarkm}
18357429Smarkm
18457429Smarkm/* Keyword tokens. */
18557429Smarkmtypedef enum {
18657429Smarkm	sBadOption,		/* == unknown option */
18757429Smarkm	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
18857429Smarkm	sPermitRootLogin, sLogFacility, sLogLevel,
18957429Smarkm	sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
19057429Smarkm#ifdef KRB4
19157565Smarkm	sKrb4Authentication, sKrb4OrLocalPasswd, sKrb4TicketCleanup,
19257429Smarkm#endif
19357565Smarkm#ifdef KRB5
19457565Smarkm	sKrb5Authentication, sKrb5TgtPassing,
19557565Smarkm#endif /* KRB5 */
19657429Smarkm#ifdef AFS
19757565Smarkm	sKrb4TgtPassing, sAFSTokenPassing,
19857429Smarkm#endif
19957429Smarkm#ifdef SKEY
20057429Smarkm	sSkeyAuthentication,
20157429Smarkm#endif
20257429Smarkm	sPasswordAuthentication, sListenAddress,
20357429Smarkm	sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
20457429Smarkm	sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
20557429Smarkm	sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
20660576Skris	sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
20765674Skris	sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod, sXAuthLocation,
20865674Skris	sSubsystem, sMaxStartups
20957429Smarkm} ServerOpCodes;
21057429Smarkm
21157429Smarkm/* Textual representation of the tokens. */
21257429Smarkmstatic struct {
21357429Smarkm	const char *name;
21457429Smarkm	ServerOpCodes opcode;
21557429Smarkm} keywords[] = {
21657429Smarkm	{ "port", sPort },
21757429Smarkm	{ "hostkey", sHostKeyFile },
21860576Skris	{ "hostdsakey", sHostDSAKeyFile },
21960576Skris 	{ "pidfile", sPidFile },
22057429Smarkm	{ "serverkeybits", sServerKeyBits },
22157429Smarkm	{ "logingracetime", sLoginGraceTime },
22257429Smarkm	{ "keyregenerationinterval", sKeyRegenerationTime },
22357429Smarkm	{ "permitrootlogin", sPermitRootLogin },
22457429Smarkm	{ "syslogfacility", sLogFacility },
22557429Smarkm	{ "loglevel", sLogLevel },
22657429Smarkm	{ "rhostsauthentication", sRhostsAuthentication },
22757429Smarkm	{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
22857429Smarkm	{ "rsaauthentication", sRSAAuthentication },
22960576Skris	{ "dsaauthentication", sDSAAuthentication },
23057429Smarkm#ifdef KRB4
23157565Smarkm	{ "kerberos4authentication", sKrb4Authentication },
23257565Smarkm	{ "kerberos4orlocalpasswd", sKrb4OrLocalPasswd },
23357565Smarkm	{ "kerberos4ticketcleanup", sKrb4TicketCleanup },
23457429Smarkm#endif
23557565Smarkm#ifdef KRB5
23657565Smarkm	{ "kerberos5authentication", sKrb5Authentication },
23757565Smarkm	{ "kerberos5tgtpassing", sKrb5TgtPassing },
23857565Smarkm#endif /* KRB5 */
23957429Smarkm#ifdef AFS
24057565Smarkm	{ "kerberos4tgtpassing", sKrb4TgtPassing },
24157429Smarkm	{ "afstokenpassing", sAFSTokenPassing },
24257429Smarkm#endif
24357429Smarkm	{ "passwordauthentication", sPasswordAuthentication },
24457429Smarkm#ifdef SKEY
24557429Smarkm	{ "skeyauthentication", sSkeyAuthentication },
24657429Smarkm#endif
24757429Smarkm	{ "checkmail", sCheckMail },
24857429Smarkm	{ "listenaddress", sListenAddress },
24957429Smarkm	{ "printmotd", sPrintMotd },
25057429Smarkm	{ "ignorerhosts", sIgnoreRhosts },
25157429Smarkm	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
25257429Smarkm	{ "x11forwarding", sX11Forwarding },
25357429Smarkm	{ "x11displayoffset", sX11DisplayOffset },
25465674Skris	{ "xauthlocation", sXAuthLocation },
25557429Smarkm	{ "strictmodes", sStrictModes },
25657429Smarkm	{ "permitemptypasswords", sEmptyPasswd },
25757429Smarkm	{ "uselogin", sUseLogin },
25857429Smarkm	{ "randomseed", sRandomSeedFile },
25957429Smarkm	{ "keepalive", sKeepAlives },
26057429Smarkm	{ "allowusers", sAllowUsers },
26157429Smarkm	{ "denyusers", sDenyUsers },
26257429Smarkm	{ "allowgroups", sAllowGroups },
26357429Smarkm	{ "denygroups", sDenyGroups },
26460576Skris	{ "ciphers", sCiphers },
26560576Skris	{ "protocol", sProtocol },
26660576Skris	{ "gatewayports", sGatewayPorts },
26757432Smarkm	{ "connectionsperperiod", sConnectionsPerPeriod },
26865674Skris	{ "subsystem", sSubsystem },
26965674Skris	{ "maxstartups", sMaxStartups },
27057429Smarkm	{ NULL, 0 }
27157429Smarkm};
27257429Smarkm
27357429Smarkm/*
27457429Smarkm * Returns the number of the token pointed to by cp of length len. Never
27557429Smarkm * returns if the token is not known.
27657429Smarkm */
27757429Smarkm
27860576Skrisstatic ServerOpCodes
27957429Smarkmparse_token(const char *cp, const char *filename,
28057429Smarkm	    int linenum)
28157429Smarkm{
28257429Smarkm	unsigned int i;
28357429Smarkm
28457429Smarkm	for (i = 0; keywords[i].name; i++)
28557429Smarkm		if (strcasecmp(cp, keywords[i].name) == 0)
28657429Smarkm			return keywords[i].opcode;
28757429Smarkm
28857429Smarkm	fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
28957429Smarkm		filename, linenum, cp);
29057429Smarkm	return sBadOption;
29157429Smarkm}
29257429Smarkm
29357429Smarkm/*
29457429Smarkm * add listen address
29557429Smarkm */
29660576Skrisvoid
29757429Smarkmadd_listen_addr(ServerOptions *options, char *addr)
29857429Smarkm{
29957429Smarkm	extern int IPv4or6;
30057429Smarkm	struct addrinfo hints, *ai, *aitop;
30157429Smarkm	char strport[NI_MAXSERV];
30257429Smarkm	int gaierr;
30357429Smarkm	int i;
30457429Smarkm
30557429Smarkm	if (options->num_ports == 0)
30657429Smarkm		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
30757429Smarkm	for (i = 0; i < options->num_ports; i++) {
30857429Smarkm		memset(&hints, 0, sizeof(hints));
30957429Smarkm		hints.ai_family = IPv4or6;
31057429Smarkm		hints.ai_socktype = SOCK_STREAM;
31157429Smarkm		hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
31257429Smarkm		snprintf(strport, sizeof strport, "%d", options->ports[i]);
31357429Smarkm		if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
31457429Smarkm			fatal("bad addr or host: %s (%s)\n",
31557429Smarkm			    addr ? addr : "<NULL>",
31657429Smarkm			    gai_strerror(gaierr));
31757429Smarkm		for (ai = aitop; ai->ai_next; ai = ai->ai_next)
31857429Smarkm			;
31957429Smarkm		ai->ai_next = options->listen_addrs;
32057429Smarkm		options->listen_addrs = aitop;
32157429Smarkm	}
32257429Smarkm}
32357429Smarkm
32457429Smarkm/* Reads the server configuration file. */
32557429Smarkm
32660576Skrisvoid
32757429Smarkmread_server_config(ServerOptions *options, const char *filename)
32857429Smarkm{
32957429Smarkm	FILE *f;
33057429Smarkm	char line[1024];
33165674Skris	char *cp, **charptr, *arg;
33257429Smarkm	int linenum, *intptr, value;
33357429Smarkm	int bad_options = 0;
33457429Smarkm	ServerOpCodes opcode;
33565674Skris	int i;
33657429Smarkm
33757429Smarkm	f = fopen(filename, "r");
33857429Smarkm	if (!f) {
33957429Smarkm		perror(filename);
34057429Smarkm		exit(1);
34157429Smarkm	}
34257429Smarkm	linenum = 0;
34357429Smarkm	while (fgets(line, sizeof(line), f)) {
34457429Smarkm		linenum++;
34565674Skris		cp = line;
34665674Skris		arg = strdelim(&cp);
34765674Skris		/* Ignore leading whitespace */
34865674Skris		if (*arg == '\0')
34965674Skris			arg = strdelim(&cp);
35065674Skris		if (!*arg || *arg == '#')
35157429Smarkm			continue;
35265674Skris		opcode = parse_token(arg, filename, linenum);
35357429Smarkm		switch (opcode) {
35457429Smarkm		case sBadOption:
35557429Smarkm			bad_options++;
35657429Smarkm			continue;
35757429Smarkm		case sPort:
35857429Smarkm			/* ignore ports from configfile if cmdline specifies ports */
35957429Smarkm			if (options->ports_from_cmdline)
36057429Smarkm				continue;
36157429Smarkm			if (options->listen_addrs != NULL)
36257429Smarkm				fatal("%s line %d: ports must be specified before "
36357429Smarkm				    "ListenAdress.\n", filename, linenum);
36457429Smarkm			if (options->num_ports >= MAX_PORTS)
36557429Smarkm				fatal("%s line %d: too many ports.\n",
36660576Skris				    filename, linenum);
36765674Skris			arg = strdelim(&cp);
36865674Skris			if (!arg || *arg == '\0')
36957429Smarkm				fatal("%s line %d: missing port number.\n",
37057429Smarkm				    filename, linenum);
37165674Skris			options->ports[options->num_ports++] = atoi(arg);
37257429Smarkm			break;
37357429Smarkm
37457429Smarkm		case sServerKeyBits:
37557429Smarkm			intptr = &options->server_key_bits;
37657429Smarkmparse_int:
37765674Skris			arg = strdelim(&cp);
37865674Skris			if (!arg || *arg == '\0') {
37957429Smarkm				fprintf(stderr, "%s line %d: missing integer value.\n",
38057429Smarkm					filename, linenum);
38157429Smarkm				exit(1);
38257429Smarkm			}
38365674Skris			value = atoi(arg);
38465674Skris			if (value == 0) {
38557432Smarkm				fprintf(stderr, "%s line %d: invalid integer value.\n",
38657432Smarkm					filename, linenum);
38757432Smarkm				exit(1);
38857432Smarkm			}
38957429Smarkm			if (*intptr == -1)
39057429Smarkm				*intptr = value;
39157429Smarkm			break;
39257429Smarkm
39357429Smarkm		case sLoginGraceTime:
39457429Smarkm			intptr = &options->login_grace_time;
39557429Smarkm			goto parse_int;
39657429Smarkm
39757429Smarkm		case sKeyRegenerationTime:
39857429Smarkm			intptr = &options->key_regeneration_time;
39957429Smarkm			goto parse_int;
40057429Smarkm
40157429Smarkm		case sListenAddress:
40265674Skris			arg = strdelim(&cp);
40365674Skris			if (!arg || *arg == '\0')
40457429Smarkm				fatal("%s line %d: missing inet addr.\n",
40557429Smarkm				    filename, linenum);
40665674Skris			add_listen_addr(options, arg);
40757429Smarkm			break;
40857429Smarkm
40957429Smarkm		case sHostKeyFile:
41060576Skris		case sHostDSAKeyFile:
41160576Skris			charptr = (opcode == sHostKeyFile ) ?
41260576Skris			    &options->host_key_file : &options->host_dsa_key_file;
41365674Skrisparse_filename:
41465674Skris			arg = strdelim(&cp);
41565674Skris			if (!arg || *arg == '\0') {
41657429Smarkm				fprintf(stderr, "%s line %d: missing file name.\n",
41760576Skris				    filename, linenum);
41857429Smarkm				exit(1);
41957429Smarkm			}
42057429Smarkm			if (*charptr == NULL)
42165674Skris				*charptr = tilde_expand_filename(arg, getuid());
42257429Smarkm			break;
42357429Smarkm
42460576Skris		case sPidFile:
42560576Skris			charptr = &options->pid_file;
42665674Skris			goto parse_filename;
42760576Skris
42857429Smarkm		case sRandomSeedFile:
42957429Smarkm			fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
43057429Smarkm				filename, linenum);
43165674Skris			arg = strdelim(&cp);
43257429Smarkm			break;
43357429Smarkm
43457429Smarkm		case sPermitRootLogin:
43557429Smarkm			intptr = &options->permit_root_login;
43665674Skris			arg = strdelim(&cp);
43765674Skris			if (!arg || *arg == '\0') {
43857429Smarkm				fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
43957429Smarkm					filename, linenum);
44057429Smarkm				exit(1);
44157429Smarkm			}
44265674Skris			if (strcmp(arg, "without-password") == 0)
44357429Smarkm				value = 2;
44465674Skris			else if (strcmp(arg, "yes") == 0)
44557429Smarkm				value = 1;
44665674Skris			else if (strcmp(arg, "no") == 0)
44757429Smarkm				value = 0;
44857429Smarkm			else {
44957429Smarkm				fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
45065674Skris					filename, linenum, arg);
45157429Smarkm				exit(1);
45257429Smarkm			}
45357429Smarkm			if (*intptr == -1)
45457429Smarkm				*intptr = value;
45557429Smarkm			break;
45657429Smarkm
45757429Smarkm		case sIgnoreRhosts:
45857429Smarkm			intptr = &options->ignore_rhosts;
45957429Smarkmparse_flag:
46065674Skris			arg = strdelim(&cp);
46165674Skris			if (!arg || *arg == '\0') {
46257429Smarkm				fprintf(stderr, "%s line %d: missing yes/no argument.\n",
46357429Smarkm					filename, linenum);
46457429Smarkm				exit(1);
46557429Smarkm			}
46665674Skris			if (strcmp(arg, "yes") == 0)
46757429Smarkm				value = 1;
46865674Skris			else if (strcmp(arg, "no") == 0)
46957429Smarkm				value = 0;
47057429Smarkm			else {
47157429Smarkm				fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
47265674Skris					filename, linenum, arg);
47357429Smarkm				exit(1);
47457429Smarkm			}
47557429Smarkm			if (*intptr == -1)
47657429Smarkm				*intptr = value;
47757429Smarkm			break;
47857429Smarkm
47957429Smarkm		case sIgnoreUserKnownHosts:
48057429Smarkm			intptr = &options->ignore_user_known_hosts;
48158463Ssheldonh			goto parse_flag;
48257429Smarkm
48357429Smarkm		case sRhostsAuthentication:
48457429Smarkm			intptr = &options->rhosts_authentication;
48557429Smarkm			goto parse_flag;
48657429Smarkm
48757429Smarkm		case sRhostsRSAAuthentication:
48857429Smarkm			intptr = &options->rhosts_rsa_authentication;
48957429Smarkm			goto parse_flag;
49057429Smarkm
49157429Smarkm		case sRSAAuthentication:
49257429Smarkm			intptr = &options->rsa_authentication;
49357429Smarkm			goto parse_flag;
49457429Smarkm
49560576Skris		case sDSAAuthentication:
49660576Skris			intptr = &options->dsa_authentication;
49760576Skris			goto parse_flag;
49860576Skris
49957429Smarkm#ifdef KRB4
50057565Smarkm		case sKrb4Authentication:
50157565Smarkm			intptr = &options->krb4_authentication;
50257429Smarkm			goto parse_flag;
50357429Smarkm
50457565Smarkm		case sKrb4OrLocalPasswd:
50557565Smarkm			intptr = &options->krb4_or_local_passwd;
50657429Smarkm			goto parse_flag;
50757429Smarkm
50857565Smarkm		case sKrb4TicketCleanup:
50957565Smarkm			intptr = &options->krb4_ticket_cleanup;
51057429Smarkm			goto parse_flag;
51157429Smarkm#endif
51257429Smarkm
51357565Smarkm#ifdef KRB5
51457565Smarkm		case sKrb5Authentication:
51557565Smarkm			intptr = &options->krb5_authentication;
51657565Smarkm			goto parse_flag;
51757565Smarkm
51857565Smarkm		case sKrb5TgtPassing:
51957565Smarkm			intptr = &options->krb5_tgt_passing;
52057565Smarkm			goto parse_flag;
52157565Smarkm#endif /* KRB5 */
52257565Smarkm
52357429Smarkm#ifdef AFS
52457565Smarkm		case sKrb4TgtPassing:
52557565Smarkm			intptr = &options->krb4_tgt_passing;
52657429Smarkm			goto parse_flag;
52757429Smarkm
52857429Smarkm		case sAFSTokenPassing:
52957429Smarkm			intptr = &options->afs_token_passing;
53057429Smarkm			goto parse_flag;
53157429Smarkm#endif
53257429Smarkm
53357429Smarkm		case sPasswordAuthentication:
53457429Smarkm			intptr = &options->password_authentication;
53557429Smarkm			goto parse_flag;
53657429Smarkm
53757429Smarkm		case sCheckMail:
53857429Smarkm			intptr = &options->check_mail;
53957429Smarkm			goto parse_flag;
54057429Smarkm
54157429Smarkm#ifdef SKEY
54257429Smarkm		case sSkeyAuthentication:
54357429Smarkm			intptr = &options->skey_authentication;
54457429Smarkm			goto parse_flag;
54557429Smarkm#endif
54657429Smarkm
54757429Smarkm		case sPrintMotd:
54857429Smarkm			intptr = &options->print_motd;
54957429Smarkm			goto parse_flag;
55057429Smarkm
55157429Smarkm		case sX11Forwarding:
55257429Smarkm			intptr = &options->x11_forwarding;
55357429Smarkm			goto parse_flag;
55457429Smarkm
55557429Smarkm		case sX11DisplayOffset:
55657429Smarkm			intptr = &options->x11_display_offset;
55757429Smarkm			goto parse_int;
55857429Smarkm
55965674Skris		case sXAuthLocation:
56065674Skris			charptr = &options->xauth_location;
56165674Skris			goto parse_filename;
56265674Skris
56357429Smarkm		case sStrictModes:
56457429Smarkm			intptr = &options->strict_modes;
56557429Smarkm			goto parse_flag;
56657429Smarkm
56757429Smarkm		case sKeepAlives:
56857429Smarkm			intptr = &options->keepalives;
56957429Smarkm			goto parse_flag;
57057429Smarkm
57157429Smarkm		case sEmptyPasswd:
57257429Smarkm			intptr = &options->permit_empty_passwd;
57357429Smarkm			goto parse_flag;
57457429Smarkm
57557429Smarkm		case sUseLogin:
57657429Smarkm			intptr = &options->use_login;
57757429Smarkm			goto parse_flag;
57857429Smarkm
57960576Skris		case sGatewayPorts:
58060576Skris			intptr = &options->gateway_ports;
58160576Skris			goto parse_flag;
58260576Skris
58357429Smarkm		case sLogFacility:
58457429Smarkm			intptr = (int *) &options->log_facility;
58565674Skris			arg = strdelim(&cp);
58665674Skris			value = log_facility_number(arg);
58757429Smarkm			if (value == (SyslogFacility) - 1)
58857429Smarkm				fatal("%.200s line %d: unsupported log facility '%s'\n",
58965674Skris				    filename, linenum, arg ? arg : "<NONE>");
59057429Smarkm			if (*intptr == -1)
59157429Smarkm				*intptr = (SyslogFacility) value;
59257429Smarkm			break;
59357429Smarkm
59457429Smarkm		case sLogLevel:
59557429Smarkm			intptr = (int *) &options->log_level;
59665674Skris			arg = strdelim(&cp);
59765674Skris			value = log_level_number(arg);
59857429Smarkm			if (value == (LogLevel) - 1)
59957429Smarkm				fatal("%.200s line %d: unsupported log level '%s'\n",
60065674Skris				    filename, linenum, arg ? arg : "<NONE>");
60157429Smarkm			if (*intptr == -1)
60257429Smarkm				*intptr = (LogLevel) value;
60357429Smarkm			break;
60457429Smarkm
60557429Smarkm		case sAllowUsers:
60665674Skris			while ((arg = strdelim(&cp)) && *arg != '\0') {
60757432Smarkm				if (options->num_allow_users >= MAX_ALLOW_USERS)
60860576Skris					fatal("%.200s line %d: too many allow users.\n",
60960576Skris					    filename, linenum);
61065674Skris				options->allow_users[options->num_allow_users++] = xstrdup(arg);
61157429Smarkm			}
61257429Smarkm			break;
61357429Smarkm
61457429Smarkm		case sDenyUsers:
61565674Skris			while ((arg = strdelim(&cp)) && *arg != '\0') {
61661320Sgreen				if (options->num_deny_users >= MAX_DENY_USERS)
61760576Skris					fatal("%.200s line %d: too many deny users.\n",
61860576Skris					    filename, linenum);
61965674Skris				options->deny_users[options->num_deny_users++] = xstrdup(arg);
62057429Smarkm			}
62157429Smarkm			break;
62257429Smarkm
62357429Smarkm		case sAllowGroups:
62465674Skris			while ((arg = strdelim(&cp)) && *arg != '\0') {
62557432Smarkm				if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
62660576Skris					fatal("%.200s line %d: too many allow groups.\n",
62760576Skris					    filename, linenum);
62865674Skris				options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
62957429Smarkm			}
63057429Smarkm			break;
63157429Smarkm
63257429Smarkm		case sDenyGroups:
63365674Skris			while ((arg = strdelim(&cp)) && *arg != '\0') {
63457432Smarkm				if (options->num_deny_groups >= MAX_DENY_GROUPS)
63560576Skris					fatal("%.200s line %d: too many deny groups.\n",
63660576Skris					    filename, linenum);
63765674Skris				options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
63857429Smarkm			}
63957429Smarkm			break;
64057429Smarkm
64160576Skris		case sCiphers:
64265674Skris			arg = strdelim(&cp);
64365674Skris			if (!arg || *arg == '\0')
64461212Skris				fatal("%s line %d: Missing argument.", filename, linenum);
64565674Skris			if (!ciphers_valid(arg))
64660576Skris				fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
64765674Skris				    filename, linenum, arg ? arg : "<NONE>");
64860576Skris			if (options->ciphers == NULL)
64965674Skris				options->ciphers = xstrdup(arg);
65060576Skris			break;
65160576Skris
65260576Skris		case sProtocol:
65360576Skris			intptr = &options->protocol;
65465674Skris			arg = strdelim(&cp);
65565674Skris			if (!arg || *arg == '\0')
65661212Skris				fatal("%s line %d: Missing argument.", filename, linenum);
65765674Skris			value = proto_spec(arg);
65860576Skris			if (value == SSH_PROTO_UNKNOWN)
65960576Skris				fatal("%s line %d: Bad protocol spec '%s'.",
66065674Skris				      filename, linenum, arg ? arg : "<NONE>");
66160576Skris			if (*intptr == SSH_PROTO_UNKNOWN)
66260576Skris				*intptr = value;
66360576Skris			break;
66460576Skris
66557432Smarkm		case sConnectionsPerPeriod:
66665674Skris			arg = strdelim(&cp);
66757432Smarkm			if (cp == NULL)
66857432Smarkm				fatal("%.200s line %d: missing (>= 0) number argument.\n",
66957432Smarkm					filename, linenum);
67065674Skris			if (sscanf(arg, "%u/%u", &options->connections_per_period,
67157432Smarkm			    &options->connections_period) != 2)
67257432Smarkm				fatal("%.200s line %d: invalid numerical argument(s).\n",
67357432Smarkm				    filename, linenum);
67457432Smarkm			if (options->connections_per_period != 0 &&
67557432Smarkm			    options->connections_period == 0)
67657432Smarkm				fatal("%.200s line %d: invalid connections period.\n",
67757432Smarkm				    filename, linenum);
67857432Smarkm			break;
67957432Smarkm
68065674Skris		case sSubsystem:
68165674Skris			if(options->num_subsystems >= MAX_SUBSYSTEMS) {
68265674Skris				fatal("%s line %d: too many subsystems defined.",
68365674Skris				      filename, linenum);
68465674Skris			}
68565674Skris			arg = strdelim(&cp);
68665674Skris			if (!arg || *arg == '\0')
68765674Skris				fatal("%s line %d: Missing subsystem name.",
68865674Skris				      filename, linenum);
68965674Skris			for (i = 0; i < options->num_subsystems; i++)
69065674Skris				if(strcmp(arg, options->subsystem_name[i]) == 0)
69165674Skris					fatal("%s line %d: Subsystem '%s' already defined.",
69265674Skris					      filename, linenum, arg);
69365674Skris			options->subsystem_name[options->num_subsystems] = xstrdup(arg);
69465674Skris			arg = strdelim(&cp);
69565674Skris			if (!arg || *arg == '\0')
69665674Skris				fatal("%s line %d: Missing subsystem command.",
69765674Skris				      filename, linenum);
69865674Skris			options->subsystem_command[options->num_subsystems] = xstrdup(arg);
69965674Skris			options->num_subsystems++;
70065674Skris			break;
70165674Skris
70265674Skris		case sMaxStartups:
70365674Skris			arg = strdelim(&cp);
70465674Skris			if (!arg || *arg == '\0')
70565674Skris				fatal("%s line %d: Missing MaxStartups spec.",
70665674Skris				      filename, linenum);
70765674Skris			if (sscanf(arg, "%d:%d:%d",
70865674Skris			    &options->max_startups_begin,
70965674Skris			    &options->max_startups_rate,
71065674Skris			    &options->max_startups) == 3) {
71165674Skris				if (options->max_startups_begin >
71265674Skris				    options->max_startups ||
71365674Skris				    options->max_startups_rate > 100 ||
71465674Skris				    options->max_startups_rate < 1)
71565674Skris				fatal("%s line %d: Illegal MaxStartups spec.",
71665674Skris				      filename, linenum);
71765674Skris				break;
71865674Skris			}
71965674Skris			intptr = &options->max_startups;
72065674Skris			goto parse_int;
72165674Skris
72257429Smarkm		default:
72357432Smarkm			fatal("%.200s line %d: Missing handler for opcode %s (%d)\n",
72465674Skris				filename, linenum,arg, opcode);
72557429Smarkm		}
72665674Skris		if ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
72765674Skris			fprintf(stderr,
72865674Skris				"%s line %d: garbage at end of line; \"%.200s\".\n",
72965674Skris				filename, linenum, arg);
73065674Skris			exit(1);
73160576Skris		}
73257429Smarkm	}
73357429Smarkm	fclose(f);
73460576Skris	if (bad_options > 0) {
73557432Smarkm		fatal("%.200s: terminating, %d bad configuration options\n",
73657429Smarkm			filename, bad_options);
73760576Skris	}
73857429Smarkm}
739