2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * As far as I am concerned, the code I have written for this software
6 * can be used freely for any purpose. Any derived versions of this
7 * software must be clearly marked as such, and if the derived work is
8 * incompatible with the protocol description in the RFC file, it must be
9 * called by a name other than "ssh" or "Secure Shell".
13 RCSID("$OpenBSD: servconf.c,v 1.130 2003/12/23 16:12:10 jakob Exp $");
20 #include "pathnames.h"
21 #include "tildexpand.h"
27 static void add_listen_addr(ServerOptions *, char *, u_short);
28 static void add_one_listen_addr(ServerOptions *, char *, u_short);
30 /* AF_UNSPEC or AF_INET or AF_INET6 */
32 /* Use of privilege separation or not */
33 extern int use_privsep;
35 /* Initializes the server options to their default values. */
38 initialize_server_options(ServerOptions *options)
40 memset(options, 0, sizeof(*options));
42 /* Portable-specific options */
43 options->use_pam = -1;
45 /* Standard Options */
46 options->num_ports = 0;
47 options->ports_from_cmdline = 0;
48 options->listen_addrs = NULL;
49 options->num_host_key_files = 0;
50 options->pid_file = NULL;
51 options->server_key_bits = -1;
52 options->login_grace_time = -1;
53 options->key_regeneration_time = -1;
54 options->permit_root_login = PERMIT_NOT_SET;
55 options->ignore_rhosts = -1;
56 options->ignore_user_known_hosts = -1;
57 options->print_motd = -1;
58 options->print_lastlog = -1;
59 options->x11_forwarding = -1;
60 options->x11_display_offset = -1;
61 options->x11_use_localhost = -1;
62 options->xauth_location = NULL;
63 options->strict_modes = -1;
64 options->tcp_keep_alive = -1;
65 options->log_facility = SYSLOG_FACILITY_NOT_SET;
66 options->log_level = SYSLOG_LEVEL_NOT_SET;
67 options->rhosts_rsa_authentication = -1;
68 options->hostbased_authentication = -1;
69 options->hostbased_uses_name_from_packet_only = -1;
70 options->rsa_authentication = -1;
71 options->pubkey_authentication = -1;
72 options->kerberos_authentication = -1;
73 options->kerberos_or_local_passwd = -1;
74 options->kerberos_ticket_cleanup = -1;
75 options->kerberos_get_afs_token = -1;
76 options->gss_authentication=-1;
77 options->gss_cleanup_creds = -1;
78 options->password_authentication = -1;
79 options->kbd_interactive_authentication = -1;
80 options->challenge_response_authentication = -1;
81 options->permit_empty_passwd = -1;
82 options->permit_user_env = -1;
83 options->use_login = -1;
84 options->compression = -1;
85 options->allow_tcp_forwarding = -1;
86 options->num_allow_users = 0;
87 options->num_deny_users = 0;
88 options->num_allow_groups = 0;
89 options->num_deny_groups = 0;
90 options->ciphers = NULL;
92 options->protocol = SSH_PROTO_UNKNOWN;
93 options->gateway_ports = -1;
94 options->num_subsystems = 0;
95 options->max_startups_begin = -1;
96 options->max_startups_rate = -1;
97 options->max_startups = -1;
98 options->banner = NULL;
99 options->use_dns = -1;
100 options->client_alive_interval = -1;
101 options->client_alive_count_max = -1;
102 options->authorized_keys_file = NULL;
103 options->authorized_keys_file2 = NULL;
105 /* Needs to be accessable in many places */
110 fill_default_server_options(ServerOptions *options)
112 /* Portable-specific options */
113 if (options->use_pam == -1)
114 options->use_pam = 0;
116 /* Standard Options */
117 if (options->protocol == SSH_PROTO_UNKNOWN)
118 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
119 if (options->num_host_key_files == 0) {
120 /* fill default hostkeys for protocols */
121 if (options->protocol & SSH_PROTO_1)
122 options->host_key_files[options->num_host_key_files++] =
124 if (options->protocol & SSH_PROTO_2) {
125 options->host_key_files[options->num_host_key_files++] =
126 _PATH_HOST_RSA_KEY_FILE;
127 options->host_key_files[options->num_host_key_files++] =
128 _PATH_HOST_DSA_KEY_FILE;
131 if (options->num_ports == 0)
132 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
133 if (options->listen_addrs == NULL)
134 add_listen_addr(options, NULL, 0);
135 if (options->pid_file == NULL)
136 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
137 if (options->server_key_bits == -1)
138 options->server_key_bits = 768;
139 if (options->login_grace_time == -1)
140 options->login_grace_time = 120;
141 if (options->key_regeneration_time == -1)
142 options->key_regeneration_time = 3600;
143 if (options->permit_root_login == PERMIT_NOT_SET)
144 options->permit_root_login = PERMIT_YES;
145 if (options->ignore_rhosts == -1)
146 options->ignore_rhosts = 1;
147 if (options->ignore_user_known_hosts == -1)
148 options->ignore_user_known_hosts = 0;
149 if (options->print_motd == -1)
150 options->print_motd = 1;
151 if (options->print_lastlog == -1)
152 options->print_lastlog = 1;
153 if (options->x11_forwarding == -1)
154 options->x11_forwarding = 0;
155 if (options->x11_display_offset == -1)
156 options->x11_display_offset = 10;
157 if (options->x11_use_localhost == -1)
158 options->x11_use_localhost = 1;
159 if (options->xauth_location == NULL)
160 options->xauth_location = _PATH_XAUTH;
161 if (options->strict_modes == -1)
162 options->strict_modes = 1;
163 if (options->tcp_keep_alive == -1)
164 options->tcp_keep_alive = 1;
165 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
166 options->log_facility = SYSLOG_FACILITY_AUTH;
167 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
168 options->log_level = SYSLOG_LEVEL_INFO;
169 if (options->rhosts_rsa_authentication == -1)
170 options->rhosts_rsa_authentication = 0;
171 if (options->hostbased_authentication == -1)
172 options->hostbased_authentication = 0;
173 if (options->hostbased_uses_name_from_packet_only == -1)
174 options->hostbased_uses_name_from_packet_only = 0;
175 if (options->rsa_authentication == -1)
176 options->rsa_authentication = 1;
177 if (options->pubkey_authentication == -1)
178 options->pubkey_authentication = 1;
179 if (options->kerberos_authentication == -1)
180 options->kerberos_authentication = 0;
181 if (options->kerberos_or_local_passwd == -1)
182 options->kerberos_or_local_passwd = 1;
183 if (options->kerberos_ticket_cleanup == -1)
184 options->kerberos_ticket_cleanup = 1;
185 if (options->kerberos_get_afs_token == -1)
186 options->kerberos_get_afs_token = 0;
187 if (options->gss_authentication == -1)
188 options->gss_authentication = 0;
189 if (options->gss_cleanup_creds == -1)
190 options->gss_cleanup_creds = 1;
191 if (options->password_authentication == -1)
192 options->password_authentication = 1;
193 if (options->kbd_interactive_authentication == -1)
194 options->kbd_interactive_authentication = 0;
195 if (options->challenge_response_authentication == -1)
196 options->challenge_response_authentication = 1;
197 if (options->permit_empty_passwd == -1)
198 options->permit_empty_passwd = 0;
199 if (options->permit_user_env == -1)
200 options->permit_user_env = 0;
201 if (options->use_login == -1)
202 options->use_login = 0;
203 if (options->compression == -1)
204 options->compression = 1;
205 if (options->allow_tcp_forwarding == -1)
206 options->allow_tcp_forwarding = 1;
207 if (options->gateway_ports == -1)
208 options->gateway_ports = 0;
209 if (options->max_startups == -1)
210 options->max_startups = 10;
211 if (options->max_startups_rate == -1)
212 options->max_startups_rate = 100; /* 100% */
213 if (options->max_startups_begin == -1)
214 options->max_startups_begin = options->max_startups;
215 if (options->use_dns == -1)
216 options->use_dns = 1;
217 if (options->client_alive_interval == -1)
218 options->client_alive_interval = 0;
219 if (options->client_alive_count_max == -1)
220 options->client_alive_count_max = 3;
221 if (options->authorized_keys_file2 == NULL) {
222 /* authorized_keys_file2 falls back to authorized_keys_file */
223 if (options->authorized_keys_file != NULL)
224 options->authorized_keys_file2 = options->authorized_keys_file;
226 options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
228 if (options->authorized_keys_file == NULL)
229 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
231 /* Turn privilege separation on by default */
232 if (use_privsep == -1)
236 if (use_privsep && options->compression == 1) {
237 error("This platform does not support both privilege "
238 "separation and compression");
239 error("Compression disabled");
240 options->compression = 0;
246 /* Keyword tokens. */
248 sBadOption, /* == unknown option */
249 /* Portable-specific options */
251 /* Standard Options */
252 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
253 sPermitRootLogin, sLogFacility, sLogLevel,
254 sRhostsRSAAuthentication, sRSAAuthentication,
255 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
256 sKerberosGetAFSToken,
257 sKerberosTgtPassing, sChallengeResponseAuthentication,
258 sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
259 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
260 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
261 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
262 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
263 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
264 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
265 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
266 sBanner, sUseDNS, sHostbasedAuthentication,
267 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
268 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
269 sGssAuthentication, sGssCleanupCreds,
270 sUsePrivilegeSeparation,
271 sDeprecated, sUnsupported
274 /* Textual representation of the tokens. */
277 ServerOpCodes opcode;
279 /* Portable-specific options */
281 { "usepam", sUsePAM },
283 { "usepam", sUnsupported },
285 { "pamauthenticationviakbdint", sDeprecated },
286 /* Standard Options */
288 { "hostkey", sHostKeyFile },
289 { "hostdsakey", sHostKeyFile }, /* alias */
290 { "pidfile", sPidFile },
291 { "serverkeybits", sServerKeyBits },
292 { "logingracetime", sLoginGraceTime },
293 { "keyregenerationinterval", sKeyRegenerationTime },
294 { "permitrootlogin", sPermitRootLogin },
295 { "syslogfacility", sLogFacility },
296 { "loglevel", sLogLevel },
297 { "rhostsauthentication", sDeprecated },
298 { "rhostsrsaauthentication", sRhostsRSAAuthentication },
299 { "hostbasedauthentication", sHostbasedAuthentication },
300 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
301 { "rsaauthentication", sRSAAuthentication },
302 { "pubkeyauthentication", sPubkeyAuthentication },
303 { "dsaauthentication", sPubkeyAuthentication }, /* alias */
305 { "kerberosauthentication", sKerberosAuthentication },
306 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
307 { "kerberosticketcleanup", sKerberosTicketCleanup },
308 { "kerberosgetafstoken", sKerberosGetAFSToken },
310 { "kerberosauthentication", sUnsupported },
311 { "kerberosorlocalpasswd", sUnsupported },
312 { "kerberosticketcleanup", sUnsupported },
313 { "kerberosgetafstoken", sUnsupported },
315 { "kerberostgtpassing", sUnsupported },
316 { "afstokenpassing", sUnsupported },
318 { "gssapiauthentication", sGssAuthentication },
319 { "gssapicleanupcredentials", sGssCleanupCreds },
321 { "gssapiauthentication", sUnsupported },
322 { "gssapicleanupcredentials", sUnsupported },
324 { "passwordauthentication", sPasswordAuthentication },
325 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
326 { "challengeresponseauthentication", sChallengeResponseAuthentication },
327 { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
328 { "checkmail", sDeprecated },
329 { "listenaddress", sListenAddress },
330 { "printmotd", sPrintMotd },
331 { "printlastlog", sPrintLastLog },
332 { "ignorerhosts", sIgnoreRhosts },
333 { "ignoreuserknownhosts", sIgnoreUserKnownHosts },
334 { "x11forwarding", sX11Forwarding },
335 { "x11displayoffset", sX11DisplayOffset },
336 { "x11uselocalhost", sX11UseLocalhost },
337 { "xauthlocation", sXAuthLocation },
338 { "strictmodes", sStrictModes },
339 { "permitemptypasswords", sEmptyPasswd },
340 { "permituserenvironment", sPermitUserEnvironment },
341 { "uselogin", sUseLogin },
342 { "compression", sCompression },
343 { "tcpkeepalive", sTCPKeepAlive },
344 { "keepalive", sTCPKeepAlive }, /* obsolete alias */
345 { "allowtcpforwarding", sAllowTcpForwarding },
346 { "allowusers", sAllowUsers },
347 { "denyusers", sDenyUsers },
348 { "allowgroups", sAllowGroups },
349 { "denygroups", sDenyGroups },
350 { "ciphers", sCiphers },
352 { "protocol", sProtocol },
353 { "gatewayports", sGatewayPorts },
354 { "subsystem", sSubsystem },
355 { "maxstartups", sMaxStartups },
356 { "banner", sBanner },
357 { "usedns", sUseDNS },
358 { "verifyreversemapping", sDeprecated },
359 { "reversemappingcheck", sDeprecated },
360 { "clientaliveinterval", sClientAliveInterval },
361 { "clientalivecountmax", sClientAliveCountMax },
362 { "authorizedkeysfile", sAuthorizedKeysFile },
363 { "authorizedkeysfile2", sAuthorizedKeysFile2 },
364 { "useprivilegeseparation", sUsePrivilegeSeparation},
369 * Returns the number of the token pointed to by cp or sBadOption.
373 parse_token(const char *cp, const char *filename,
378 for (i = 0; keywords[i].name; i++)
379 if (strcasecmp(cp, keywords[i].name) == 0)
380 return keywords[i].opcode;
382 error("%s: line %d: Bad configuration option: %s",
383 filename, linenum, cp);
388 add_listen_addr(ServerOptions *options, char *addr, u_short port)
392 if (options->num_ports == 0)
393 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
395 for (i = 0; i < options->num_ports; i++)
396 add_one_listen_addr(options, addr, options->ports[i]);
398 add_one_listen_addr(options, addr, port);
402 add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
404 struct addrinfo hints, *ai, *aitop;
405 char strport[NI_MAXSERV];
408 memset(&hints, 0, sizeof(hints));
409 hints.ai_family = IPv4or6;
410 hints.ai_socktype = SOCK_STREAM;
411 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
412 snprintf(strport, sizeof strport, "%u", port);
413 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
414 fatal("bad addr or host: %s (%s)",
415 addr ? addr : "<NULL>",
416 gai_strerror(gaierr));
417 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
419 ai->ai_next = options->listen_addrs;
420 options->listen_addrs = aitop;
424 process_server_config_line(ServerOptions *options, char *line,
425 const char *filename, int linenum)
427 char *cp, **charptr, *arg, *p;
428 int *intptr, value, i, n;
429 ServerOpCodes opcode;
433 /* Ignore leading whitespace */
436 if (!arg || !*arg || *arg == '#')
440 opcode = parse_token(arg, filename, linenum);
442 /* Portable-specific options */
444 intptr = &options->use_pam;
447 /* Standard Options */
451 /* ignore ports from configfile if cmdline specifies ports */
452 if (options->ports_from_cmdline)
454 if (options->listen_addrs != NULL)
455 fatal("%s line %d: ports must be specified before "
456 "ListenAddress.", filename, linenum);
457 if (options->num_ports >= MAX_PORTS)
458 fatal("%s line %d: too many ports.",
461 if (!arg || *arg == '\0')
462 fatal("%s line %d: missing port number.",
464 options->ports[options->num_ports++] = a2port(arg);
465 if (options->ports[options->num_ports-1] == 0)
466 fatal("%s line %d: Badly formatted port number.",
471 intptr = &options->server_key_bits;
474 if (!arg || *arg == '\0')
475 fatal("%s line %d: missing integer value.",
482 case sLoginGraceTime:
483 intptr = &options->login_grace_time;
486 if (!arg || *arg == '\0')
487 fatal("%s line %d: missing time value.",
489 if ((value = convtime(arg)) == -1)
490 fatal("%s line %d: invalid time value.",
496 case sKeyRegenerationTime:
497 intptr = &options->key_regeneration_time;
502 if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
503 fatal("%s line %d: missing inet addr.",
506 if ((p = strchr(arg, ']')) == NULL)
507 fatal("%s line %d: bad ipv6 inet addr usage.",
510 memmove(p, p+1, strlen(p+1)+1);
511 } else if (((p = strchr(arg, ':')) == NULL) ||
512 (strchr(p+1, ':') != NULL)) {
513 add_listen_addr(options, arg, 0);
521 fatal("%s line %d: bad inet addr:port usage.",
525 if ((port = a2port(p)) == 0)
526 fatal("%s line %d: bad port number.",
528 add_listen_addr(options, arg, port);
530 } else if (*p == '\0')
531 add_listen_addr(options, arg, 0);
533 fatal("%s line %d: bad inet addr usage.",
538 intptr = &options->num_host_key_files;
539 if (*intptr >= MAX_HOSTKEYS)
540 fatal("%s line %d: too many host keys specified (max %d).",
541 filename, linenum, MAX_HOSTKEYS);
542 charptr = &options->host_key_files[*intptr];
545 if (!arg || *arg == '\0')
546 fatal("%s line %d: missing file name.",
548 if (*charptr == NULL) {
549 *charptr = tilde_expand_filename(arg, getuid());
550 /* increase optional counter */
552 *intptr = *intptr + 1;
557 charptr = &options->pid_file;
560 case sPermitRootLogin:
561 intptr = &options->permit_root_login;
563 if (!arg || *arg == '\0')
564 fatal("%s line %d: missing yes/"
565 "without-password/forced-commands-only/no "
566 "argument.", filename, linenum);
567 value = 0; /* silence compiler */
568 if (strcmp(arg, "without-password") == 0)
569 value = PERMIT_NO_PASSWD;
570 else if (strcmp(arg, "forced-commands-only") == 0)
571 value = PERMIT_FORCED_ONLY;
572 else if (strcmp(arg, "yes") == 0)
574 else if (strcmp(arg, "no") == 0)
577 fatal("%s line %d: Bad yes/"
578 "without-password/forced-commands-only/no "
579 "argument: %s", filename, linenum, arg);
585 intptr = &options->ignore_rhosts;
588 if (!arg || *arg == '\0')
589 fatal("%s line %d: missing yes/no argument.",
591 value = 0; /* silence compiler */
592 if (strcmp(arg, "yes") == 0)
594 else if (strcmp(arg, "no") == 0)
597 fatal("%s line %d: Bad yes/no argument: %s",
598 filename, linenum, arg);
603 case sIgnoreUserKnownHosts:
604 intptr = &options->ignore_user_known_hosts;
607 case sRhostsRSAAuthentication:
608 intptr = &options->rhosts_rsa_authentication;
611 case sHostbasedAuthentication:
612 intptr = &options->hostbased_authentication;
615 case sHostbasedUsesNameFromPacketOnly:
616 intptr = &options->hostbased_uses_name_from_packet_only;
619 case sRSAAuthentication:
620 intptr = &options->rsa_authentication;
623 case sPubkeyAuthentication:
624 intptr = &options->pubkey_authentication;
627 case sKerberosAuthentication:
628 intptr = &options->kerberos_authentication;
631 case sKerberosOrLocalPasswd:
632 intptr = &options->kerberos_or_local_passwd;
635 case sKerberosTicketCleanup:
636 intptr = &options->kerberos_ticket_cleanup;
639 case sKerberosGetAFSToken:
640 intptr = &options->kerberos_get_afs_token;
643 case sGssAuthentication:
644 intptr = &options->gss_authentication;
647 case sGssCleanupCreds:
648 intptr = &options->gss_cleanup_creds;
651 case sPasswordAuthentication:
652 intptr = &options->password_authentication;
655 case sKbdInteractiveAuthentication:
656 intptr = &options->kbd_interactive_authentication;
659 case sChallengeResponseAuthentication:
660 intptr = &options->challenge_response_authentication;
664 intptr = &options->print_motd;
668 intptr = &options->print_lastlog;
672 intptr = &options->x11_forwarding;
675 case sX11DisplayOffset:
676 intptr = &options->x11_display_offset;
679 case sX11UseLocalhost:
680 intptr = &options->x11_use_localhost;
684 charptr = &options->xauth_location;
688 intptr = &options->strict_modes;
692 intptr = &options->tcp_keep_alive;
696 intptr = &options->permit_empty_passwd;
699 case sPermitUserEnvironment:
700 intptr = &options->permit_user_env;
704 intptr = &options->use_login;
708 intptr = &options->compression;
712 intptr = &options->gateway_ports;
716 intptr = &options->use_dns;
720 intptr = (int *) &options->log_facility;
722 value = log_facility_number(arg);
723 if (value == SYSLOG_FACILITY_NOT_SET)
724 fatal("%.200s line %d: unsupported log facility '%s'",
725 filename, linenum, arg ? arg : "<NONE>");
727 *intptr = (SyslogFacility) value;
731 intptr = (int *) &options->log_level;
733 value = log_level_number(arg);
734 if (value == SYSLOG_LEVEL_NOT_SET)
735 fatal("%.200s line %d: unsupported log level '%s'",
736 filename, linenum, arg ? arg : "<NONE>");
738 *intptr = (LogLevel) value;
741 case sAllowTcpForwarding:
742 intptr = &options->allow_tcp_forwarding;
745 case sUsePrivilegeSeparation:
746 intptr = &use_privsep;
750 while ((arg = strdelim(&cp)) && *arg != '\0') {
751 if (options->num_allow_users >= MAX_ALLOW_USERS)
752 fatal("%s line %d: too many allow users.",
754 options->allow_users[options->num_allow_users++] =
760 while ((arg = strdelim(&cp)) && *arg != '\0') {
761 if (options->num_deny_users >= MAX_DENY_USERS)
762 fatal( "%s line %d: too many deny users.",
764 options->deny_users[options->num_deny_users++] =
770 while ((arg = strdelim(&cp)) && *arg != '\0') {
771 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
772 fatal("%s line %d: too many allow groups.",
774 options->allow_groups[options->num_allow_groups++] =
780 while ((arg = strdelim(&cp)) && *arg != '\0') {
781 if (options->num_deny_groups >= MAX_DENY_GROUPS)
782 fatal("%s line %d: too many deny groups.",
784 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
790 if (!arg || *arg == '\0')
791 fatal("%s line %d: Missing argument.", filename, linenum);
792 if (!ciphers_valid(arg))
793 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
794 filename, linenum, arg ? arg : "<NONE>");
795 if (options->ciphers == NULL)
796 options->ciphers = xstrdup(arg);
801 if (!arg || *arg == '\0')
802 fatal("%s line %d: Missing argument.", filename, linenum);
804 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
805 filename, linenum, arg ? arg : "<NONE>");
806 if (options->macs == NULL)
807 options->macs = xstrdup(arg);
811 intptr = &options->protocol;
813 if (!arg || *arg == '\0')
814 fatal("%s line %d: Missing argument.", filename, linenum);
815 value = proto_spec(arg);
816 if (value == SSH_PROTO_UNKNOWN)
817 fatal("%s line %d: Bad protocol spec '%s'.",
818 filename, linenum, arg ? arg : "<NONE>");
819 if (*intptr == SSH_PROTO_UNKNOWN)
824 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
825 fatal("%s line %d: too many subsystems defined.",
829 if (!arg || *arg == '\0')
830 fatal("%s line %d: Missing subsystem name.",
832 for (i = 0; i < options->num_subsystems; i++)
833 if (strcmp(arg, options->subsystem_name[i]) == 0)
834 fatal("%s line %d: Subsystem '%s' already defined.",
835 filename, linenum, arg);
836 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
838 if (!arg || *arg == '\0')
839 fatal("%s line %d: Missing subsystem command.",
841 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
842 options->num_subsystems++;
847 if (!arg || *arg == '\0')
848 fatal("%s line %d: Missing MaxStartups spec.",
850 if ((n = sscanf(arg, "%d:%d:%d",
851 &options->max_startups_begin,
852 &options->max_startups_rate,
853 &options->max_startups)) == 3) {
854 if (options->max_startups_begin >
855 options->max_startups ||
856 options->max_startups_rate > 100 ||
857 options->max_startups_rate < 1)
858 fatal("%s line %d: Illegal MaxStartups spec.",
861 fatal("%s line %d: Illegal MaxStartups spec.",
864 options->max_startups = options->max_startups_begin;
868 charptr = &options->banner;
871 * These options can contain %X options expanded at
872 * connect time, so that you can specify paths like:
874 * AuthorizedKeysFile /etc/ssh_keys/%u
876 case sAuthorizedKeysFile:
877 case sAuthorizedKeysFile2:
878 charptr = (opcode == sAuthorizedKeysFile ) ?
879 &options->authorized_keys_file :
880 &options->authorized_keys_file2;
883 case sClientAliveInterval:
884 intptr = &options->client_alive_interval;
887 case sClientAliveCountMax:
888 intptr = &options->client_alive_count_max;
892 logit("%s line %d: Deprecated option %s",
893 filename, linenum, arg);
899 logit("%s line %d: Unsupported option %s",
900 filename, linenum, arg);
906 fatal("%s line %d: Missing handler for opcode %s (%d)",
907 filename, linenum, arg, opcode);
909 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
910 fatal("%s line %d: garbage at end of line; \"%.200s\".",
911 filename, linenum, arg);
915 /* Reads the server configuration file. */
918 read_server_config(ServerOptions *options, const char *filename)
920 int linenum, bad_options = 0;
924 debug2("read_server_config: filename %s", filename);
925 f = fopen(filename, "r");
931 while (fgets(line, sizeof(line), f)) {
932 /* Update line number counter. */
934 if (process_server_config_line(options, line, filename, linenum) != 0)
939 fatal("%s: terminating, %d bad configuration options",
940 filename, bad_options);