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.78 2001/04/15 21:28:35 stevesk Exp $");
27 #include "pathnames.h"
28 #include "tildexpand.h"
34 void add_listen_addr(ServerOptions *options, char *addr, u_short port);
35 void add_one_listen_addr(ServerOptions *options, char *addr, u_short port);
37 /* AF_UNSPEC or AF_INET or AF_INET6 */
40 /* Initializes the server options to their default values. */
43 initialize_server_options(ServerOptions *options)
45 memset(options, 0, sizeof(*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->check_mail = -1;
60 options->x11_forwarding = -1;
61 options->x11_display_offset = -1;
62 options->xauth_location = NULL;
63 options->strict_modes = -1;
64 options->keepalives = -1;
65 options->log_facility = (SyslogFacility) - 1;
66 options->log_level = (LogLevel) - 1;
67 options->rhosts_authentication = -1;
68 options->rhosts_rsa_authentication = -1;
69 options->hostbased_authentication = -1;
70 options->hostbased_uses_name_from_packet_only = -1;
71 options->rsa_authentication = -1;
72 options->pubkey_authentication = -1;
74 options->kerberos_authentication = -1;
75 options->kerberos_or_local_passwd = -1;
76 options->kerberos_ticket_cleanup = -1;
79 options->kerberos_tgt_passing = -1;
80 options->afs_token_passing = -1;
82 options->password_authentication = -1;
83 options->kbd_interactive_authentication = -1;
84 options->challenge_reponse_authentication = -1;
85 options->permit_empty_passwd = -1;
86 options->use_login = -1;
87 options->allow_tcp_forwarding = -1;
88 options->num_allow_users = 0;
89 options->num_deny_users = 0;
90 options->num_allow_groups = 0;
91 options->num_deny_groups = 0;
92 options->ciphers = NULL;
94 options->protocol = SSH_PROTO_UNKNOWN;
95 options->gateway_ports = -1;
96 options->num_subsystems = 0;
97 options->max_startups_begin = -1;
98 options->max_startups_rate = -1;
99 options->max_startups = -1;
100 options->banner = NULL;
101 options->reverse_mapping_check = -1;
102 options->client_alive_interval = -1;
103 options->client_alive_count_max = -1;
107 fill_default_server_options(ServerOptions *options)
109 if (options->protocol == SSH_PROTO_UNKNOWN)
110 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
111 if (options->num_host_key_files == 0) {
112 /* fill default hostkeys for protocols */
113 if (options->protocol & SSH_PROTO_1)
114 options->host_key_files[options->num_host_key_files++] = _PATH_HOST_KEY_FILE;
115 if (options->protocol & SSH_PROTO_2)
116 options->host_key_files[options->num_host_key_files++] = _PATH_HOST_DSA_KEY_FILE;
118 if (options->num_ports == 0)
119 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
120 if (options->listen_addrs == NULL)
121 add_listen_addr(options, NULL, 0);
122 if (options->pid_file == NULL)
123 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
124 if (options->server_key_bits == -1)
125 options->server_key_bits = 768;
126 if (options->login_grace_time == -1)
127 options->login_grace_time = 600;
128 if (options->key_regeneration_time == -1)
129 options->key_regeneration_time = 3600;
130 if (options->permit_root_login == PERMIT_NOT_SET)
131 options->permit_root_login = PERMIT_YES;
132 if (options->ignore_rhosts == -1)
133 options->ignore_rhosts = 1;
134 if (options->ignore_user_known_hosts == -1)
135 options->ignore_user_known_hosts = 0;
136 if (options->check_mail == -1)
137 options->check_mail = 0;
138 if (options->print_motd == -1)
139 options->print_motd = 1;
140 if (options->print_lastlog == -1)
141 options->print_lastlog = 1;
142 if (options->x11_forwarding == -1)
143 options->x11_forwarding = 0;
144 if (options->x11_display_offset == -1)
145 options->x11_display_offset = 10;
147 if (options->xauth_location == NULL)
148 options->xauth_location = XAUTH_PATH;
149 #endif /* XAUTH_PATH */
150 if (options->strict_modes == -1)
151 options->strict_modes = 1;
152 if (options->keepalives == -1)
153 options->keepalives = 1;
154 if (options->log_facility == (SyslogFacility) (-1))
155 options->log_facility = SYSLOG_FACILITY_AUTH;
156 if (options->log_level == (LogLevel) (-1))
157 options->log_level = SYSLOG_LEVEL_INFO;
158 if (options->rhosts_authentication == -1)
159 options->rhosts_authentication = 0;
160 if (options->rhosts_rsa_authentication == -1)
161 options->rhosts_rsa_authentication = 0;
162 if (options->hostbased_authentication == -1)
163 options->hostbased_authentication = 0;
164 if (options->hostbased_uses_name_from_packet_only == -1)
165 options->hostbased_uses_name_from_packet_only = 0;
166 if (options->rsa_authentication == -1)
167 options->rsa_authentication = 1;
168 if (options->pubkey_authentication == -1)
169 options->pubkey_authentication = 1;
171 if (options->kerberos_authentication == -1)
172 options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
173 if (options->kerberos_or_local_passwd == -1)
174 options->kerberos_or_local_passwd = 1;
175 if (options->kerberos_ticket_cleanup == -1)
176 options->kerberos_ticket_cleanup = 1;
179 if (options->kerberos_tgt_passing == -1)
180 options->kerberos_tgt_passing = 0;
181 if (options->afs_token_passing == -1)
182 options->afs_token_passing = k_hasafs();
184 if (options->password_authentication == -1)
185 options->password_authentication = 1;
186 if (options->kbd_interactive_authentication == -1)
187 options->kbd_interactive_authentication = 0;
188 if (options->challenge_reponse_authentication == -1)
189 options->challenge_reponse_authentication = 1;
190 if (options->permit_empty_passwd == -1)
191 options->permit_empty_passwd = 0;
192 if (options->use_login == -1)
193 options->use_login = 0;
194 if (options->allow_tcp_forwarding == -1)
195 options->allow_tcp_forwarding = 1;
196 if (options->gateway_ports == -1)
197 options->gateway_ports = 0;
198 if (options->max_startups == -1)
199 options->max_startups = 10;
200 if (options->max_startups_rate == -1)
201 options->max_startups_rate = 100; /* 100% */
202 if (options->max_startups_begin == -1)
203 options->max_startups_begin = options->max_startups;
204 if (options->reverse_mapping_check == -1)
205 options->reverse_mapping_check = 0;
206 if (options->client_alive_interval == -1)
207 options->client_alive_interval = 0;
208 if (options->client_alive_count_max == -1)
209 options->client_alive_count_max = 3;
212 /* Keyword tokens. */
214 sBadOption, /* == unknown option */
215 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
216 sPermitRootLogin, sLogFacility, sLogLevel,
217 sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
219 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
222 sKerberosTgtPassing, sAFSTokenPassing,
224 sChallengeResponseAuthentication,
225 sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
226 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
227 sX11Forwarding, sX11DisplayOffset,
228 sStrictModes, sEmptyPasswd, sKeepAlives, sCheckMail,
229 sUseLogin, sAllowTcpForwarding,
230 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
231 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
232 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
233 sBanner, sReverseMappingCheck, sHostbasedAuthentication,
234 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
238 /* Textual representation of the tokens. */
241 ServerOpCodes opcode;
244 { "hostkey", sHostKeyFile },
245 { "hostdsakey", sHostKeyFile }, /* alias */
246 { "pidfile", sPidFile },
247 { "serverkeybits", sServerKeyBits },
248 { "logingracetime", sLoginGraceTime },
249 { "keyregenerationinterval", sKeyRegenerationTime },
250 { "permitrootlogin", sPermitRootLogin },
251 { "syslogfacility", sLogFacility },
252 { "loglevel", sLogLevel },
253 { "rhostsauthentication", sRhostsAuthentication },
254 { "rhostsrsaauthentication", sRhostsRSAAuthentication },
255 { "hostbasedauthentication", sHostbasedAuthentication },
256 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
257 { "rsaauthentication", sRSAAuthentication },
258 { "pubkeyauthentication", sPubkeyAuthentication },
259 { "dsaauthentication", sPubkeyAuthentication }, /* alias */
261 { "kerberosauthentication", sKerberosAuthentication },
262 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
263 { "kerberosticketcleanup", sKerberosTicketCleanup },
266 { "kerberostgtpassing", sKerberosTgtPassing },
267 { "afstokenpassing", sAFSTokenPassing },
269 { "passwordauthentication", sPasswordAuthentication },
270 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
271 { "challengeresponseauthentication", sChallengeResponseAuthentication },
272 { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
273 { "checkmail", sCheckMail },
274 { "listenaddress", sListenAddress },
275 { "printmotd", sPrintMotd },
276 { "printlastlog", sPrintLastLog },
277 { "ignorerhosts", sIgnoreRhosts },
278 { "ignoreuserknownhosts", sIgnoreUserKnownHosts },
279 { "x11forwarding", sX11Forwarding },
280 { "x11displayoffset", sX11DisplayOffset },
281 { "xauthlocation", sXAuthLocation },
282 { "strictmodes", sStrictModes },
283 { "permitemptypasswords", sEmptyPasswd },
284 { "uselogin", sUseLogin },
285 { "keepalive", sKeepAlives },
286 { "allowtcpforwarding", sAllowTcpForwarding },
287 { "allowusers", sAllowUsers },
288 { "denyusers", sDenyUsers },
289 { "allowgroups", sAllowGroups },
290 { "denygroups", sDenyGroups },
291 { "ciphers", sCiphers },
293 { "protocol", sProtocol },
294 { "gatewayports", sGatewayPorts },
295 { "subsystem", sSubsystem },
296 { "maxstartups", sMaxStartups },
297 { "banner", sBanner },
298 { "reversemappingcheck", sReverseMappingCheck },
299 { "clientaliveinterval", sClientAliveInterval },
300 { "clientalivecountmax", sClientAliveCountMax },
305 * Returns the number of the token pointed to by cp or sBadOption.
309 parse_token(const char *cp, const char *filename,
314 for (i = 0; keywords[i].name; i++)
315 if (strcasecmp(cp, keywords[i].name) == 0)
316 return keywords[i].opcode;
318 error("%s: line %d: Bad configuration option: %s",
319 filename, linenum, cp);
324 add_listen_addr(ServerOptions *options, char *addr, u_short port)
328 if (options->num_ports == 0)
329 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
331 for (i = 0; i < options->num_ports; i++)
332 add_one_listen_addr(options, addr, options->ports[i]);
334 add_one_listen_addr(options, addr, port);
338 add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
340 struct addrinfo hints, *ai, *aitop;
341 char strport[NI_MAXSERV];
344 memset(&hints, 0, sizeof(hints));
345 hints.ai_family = IPv4or6;
346 hints.ai_socktype = SOCK_STREAM;
347 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
348 snprintf(strport, sizeof strport, "%d", port);
349 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
350 fatal("bad addr or host: %s (%s)",
351 addr ? addr : "<NULL>",
352 gai_strerror(gaierr));
353 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
355 ai->ai_next = options->listen_addrs;
356 options->listen_addrs = aitop;
359 /* Reads the server configuration file. */
362 read_server_config(ServerOptions *options, const char *filename)
366 char *cp, **charptr, *arg, *p;
367 int linenum, *intptr, value;
369 ServerOpCodes opcode;
372 f = fopen(filename, "r");
378 while (fgets(line, sizeof(line), f)) {
382 /* Ignore leading whitespace */
385 if (!arg || !*arg || *arg == '#')
389 opcode = parse_token(arg, filename, linenum);
395 /* ignore ports from configfile if cmdline specifies ports */
396 if (options->ports_from_cmdline)
398 if (options->listen_addrs != NULL)
399 fatal("%s line %d: ports must be specified before "
400 "ListenAdress.\n", filename, linenum);
401 if (options->num_ports >= MAX_PORTS)
402 fatal("%s line %d: too many ports.",
405 if (!arg || *arg == '\0')
406 fatal("%s line %d: missing port number.",
408 options->ports[options->num_ports++] = a2port(arg);
409 if (options->ports[options->num_ports-1] == 0)
410 fatal("%s line %d: Badly formatted port number.",
415 intptr = &options->server_key_bits;
418 if (!arg || *arg == '\0')
419 fatal("%s line %d: missing integer value.",
426 case sLoginGraceTime:
427 intptr = &options->login_grace_time;
430 case sKeyRegenerationTime:
431 intptr = &options->key_regeneration_time;
436 if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
437 fatal("%s line %d: missing inet addr.",
440 if ((p = strchr(arg, ']')) == NULL)
441 fatal("%s line %d: bad ipv6 inet addr usage.",
444 memmove(p, p+1, strlen(p+1)+1);
445 } else if (((p = strchr(arg, ':')) == NULL) ||
446 (strchr(p+1, ':') != NULL)) {
447 add_listen_addr(options, arg, 0);
455 fatal("%s line %d: bad inet addr:port usage.",
459 if ((port = a2port(p)) == 0)
460 fatal("%s line %d: bad port number.",
462 add_listen_addr(options, arg, port);
464 } else if (*p == '\0')
465 add_listen_addr(options, arg, 0);
467 fatal("%s line %d: bad inet addr usage.",
472 intptr = &options->num_host_key_files;
473 if (*intptr >= MAX_HOSTKEYS)
474 fatal("%s line %d: too many host keys specified (max %d).",
475 filename, linenum, MAX_HOSTKEYS);
476 charptr = &options->host_key_files[*intptr];
479 if (!arg || *arg == '\0')
480 fatal("%s line %d: missing file name.",
482 if (*charptr == NULL) {
483 *charptr = tilde_expand_filename(arg, getuid());
484 /* increase optional counter */
486 *intptr = *intptr + 1;
491 charptr = &options->pid_file;
494 case sPermitRootLogin:
495 intptr = &options->permit_root_login;
497 if (!arg || *arg == '\0')
498 fatal("%s line %d: missing yes/"
499 "without-password/forced-commands-only/no "
500 "argument.", filename, linenum);
501 value = 0; /* silence compiler */
502 if (strcmp(arg, "without-password") == 0)
503 value = PERMIT_NO_PASSWD;
504 else if (strcmp(arg, "forced-commands-only") == 0)
505 value = PERMIT_FORCED_ONLY;
506 else if (strcmp(arg, "yes") == 0)
508 else if (strcmp(arg, "no") == 0)
511 fatal("%s line %d: Bad yes/"
512 "without-password/forced-commands-only/no "
513 "argument: %s", filename, linenum, arg);
519 intptr = &options->ignore_rhosts;
522 if (!arg || *arg == '\0')
523 fatal("%s line %d: missing yes/no argument.",
525 value = 0; /* silence compiler */
526 if (strcmp(arg, "yes") == 0)
528 else if (strcmp(arg, "no") == 0)
531 fatal("%s line %d: Bad yes/no argument: %s",
532 filename, linenum, arg);
537 case sIgnoreUserKnownHosts:
538 intptr = &options->ignore_user_known_hosts;
541 case sRhostsAuthentication:
542 intptr = &options->rhosts_authentication;
545 case sRhostsRSAAuthentication:
546 intptr = &options->rhosts_rsa_authentication;
549 case sHostbasedAuthentication:
550 intptr = &options->hostbased_authentication;
553 case sHostbasedUsesNameFromPacketOnly:
554 intptr = &options->hostbased_uses_name_from_packet_only;
557 case sRSAAuthentication:
558 intptr = &options->rsa_authentication;
561 case sPubkeyAuthentication:
562 intptr = &options->pubkey_authentication;
566 case sKerberosAuthentication:
567 intptr = &options->kerberos_authentication;
570 case sKerberosOrLocalPasswd:
571 intptr = &options->kerberos_or_local_passwd;
574 case sKerberosTicketCleanup:
575 intptr = &options->kerberos_ticket_cleanup;
580 case sKerberosTgtPassing:
581 intptr = &options->kerberos_tgt_passing;
584 case sAFSTokenPassing:
585 intptr = &options->afs_token_passing;
589 case sPasswordAuthentication:
590 intptr = &options->password_authentication;
593 case sKbdInteractiveAuthentication:
594 intptr = &options->kbd_interactive_authentication;
598 intptr = &options->check_mail;
601 case sChallengeResponseAuthentication:
602 intptr = &options->challenge_reponse_authentication;
606 intptr = &options->print_motd;
610 intptr = &options->print_lastlog;
614 intptr = &options->x11_forwarding;
617 case sX11DisplayOffset:
618 intptr = &options->x11_display_offset;
622 charptr = &options->xauth_location;
626 intptr = &options->strict_modes;
630 intptr = &options->keepalives;
634 intptr = &options->permit_empty_passwd;
638 intptr = &options->use_login;
642 intptr = &options->gateway_ports;
645 case sReverseMappingCheck:
646 intptr = &options->reverse_mapping_check;
650 intptr = (int *) &options->log_facility;
652 value = log_facility_number(arg);
653 if (value == (SyslogFacility) - 1)
654 fatal("%.200s line %d: unsupported log facility '%s'",
655 filename, linenum, arg ? arg : "<NONE>");
657 *intptr = (SyslogFacility) value;
661 intptr = (int *) &options->log_level;
663 value = log_level_number(arg);
664 if (value == (LogLevel) - 1)
665 fatal("%.200s line %d: unsupported log level '%s'",
666 filename, linenum, arg ? arg : "<NONE>");
668 *intptr = (LogLevel) value;
671 case sAllowTcpForwarding:
672 intptr = &options->allow_tcp_forwarding;
676 while ((arg = strdelim(&cp)) && *arg != '\0') {
677 if (options->num_allow_users >= MAX_ALLOW_USERS)
678 fatal("%s line %d: too many allow users.",
680 options->allow_users[options->num_allow_users++] = xstrdup(arg);
685 while ((arg = strdelim(&cp)) && *arg != '\0') {
686 if (options->num_deny_users >= MAX_DENY_USERS)
687 fatal( "%s line %d: too many deny users.",
689 options->deny_users[options->num_deny_users++] = xstrdup(arg);
694 while ((arg = strdelim(&cp)) && *arg != '\0') {
695 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
696 fatal("%s line %d: too many allow groups.",
698 options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
703 while ((arg = strdelim(&cp)) && *arg != '\0') {
704 if (options->num_deny_groups >= MAX_DENY_GROUPS)
705 fatal("%s line %d: too many deny groups.",
707 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
713 if (!arg || *arg == '\0')
714 fatal("%s line %d: Missing argument.", filename, linenum);
715 if (!ciphers_valid(arg))
716 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
717 filename, linenum, arg ? arg : "<NONE>");
718 if (options->ciphers == NULL)
719 options->ciphers = xstrdup(arg);
724 if (!arg || *arg == '\0')
725 fatal("%s line %d: Missing argument.", filename, linenum);
727 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
728 filename, linenum, arg ? arg : "<NONE>");
729 if (options->macs == NULL)
730 options->macs = xstrdup(arg);
734 intptr = &options->protocol;
736 if (!arg || *arg == '\0')
737 fatal("%s line %d: Missing argument.", filename, linenum);
738 value = proto_spec(arg);
739 if (value == SSH_PROTO_UNKNOWN)
740 fatal("%s line %d: Bad protocol spec '%s'.",
741 filename, linenum, arg ? arg : "<NONE>");
742 if (*intptr == SSH_PROTO_UNKNOWN)
747 if(options->num_subsystems >= MAX_SUBSYSTEMS) {
748 fatal("%s line %d: too many subsystems defined.",
752 if (!arg || *arg == '\0')
753 fatal("%s line %d: Missing subsystem name.",
755 for (i = 0; i < options->num_subsystems; i++)
756 if(strcmp(arg, options->subsystem_name[i]) == 0)
757 fatal("%s line %d: Subsystem '%s' already defined.",
758 filename, linenum, arg);
759 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
761 if (!arg || *arg == '\0')
762 fatal("%s line %d: Missing subsystem command.",
764 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
765 options->num_subsystems++;
770 if (!arg || *arg == '\0')
771 fatal("%s line %d: Missing MaxStartups spec.",
773 if (sscanf(arg, "%d:%d:%d",
774 &options->max_startups_begin,
775 &options->max_startups_rate,
776 &options->max_startups) == 3) {
777 if (options->max_startups_begin >
778 options->max_startups ||
779 options->max_startups_rate > 100 ||
780 options->max_startups_rate < 1)
781 fatal("%s line %d: Illegal MaxStartups spec.",
785 intptr = &options->max_startups;
789 charptr = &options->banner;
791 case sClientAliveInterval:
792 intptr = &options->client_alive_interval;
794 case sClientAliveCountMax:
795 intptr = &options->client_alive_count_max;
798 fatal("%s line %d: Missing handler for opcode %s (%d)",
799 filename, linenum, arg, opcode);
801 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
802 fatal("%s line %d: garbage at end of line; \"%.200s\".",
803 filename, linenum, arg);
807 fatal("%s: terminating, %d bad configuration options",
808 filename, bad_options);