]> andersk Git - openssh.git/blob - servconf.c
8aeed3e3b00d99b6698ad8965e905125db19780b
[openssh.git] / servconf.c
1 /*
2  *
3  * servconf.c
4  *
5  * Author: Tatu Ylonen <ylo@cs.hut.fi>
6  *
7  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8  *                    All rights reserved
9  *
10  * Created: Mon Aug 21 15:48:58 1995 ylo
11  *
12  */
13
14 #include "includes.h"
15 RCSID("$Id$");
16
17 #include "ssh.h"
18 #include "servconf.h"
19 #include "xmalloc.h"
20 #include "compat.h"
21
22 /* add listen address */
23 void add_listen_addr(ServerOptions *options, char *addr);
24
25 /* Initializes the server options to their default values. */
26
27 void
28 initialize_server_options(ServerOptions *options)
29 {
30         memset(options, 0, sizeof(*options));
31         options->num_ports = 0;
32         options->ports_from_cmdline = 0;
33         options->listen_addrs = NULL;
34         options->host_key_file = NULL;
35         options->dsa_key_file = NULL;
36         options->pid_file = NULL;
37         options->server_key_bits = -1;
38         options->login_grace_time = -1;
39         options->key_regeneration_time = -1;
40         options->permit_root_login = -1;
41         options->ignore_rhosts = -1;
42         options->ignore_user_known_hosts = -1;
43         options->print_motd = -1;
44         options->check_mail = -1;
45         options->x11_forwarding = -1;
46         options->x11_display_offset = -1;
47         options->strict_modes = -1;
48         options->keepalives = -1;
49         options->log_facility = (SyslogFacility) - 1;
50         options->log_level = (LogLevel) - 1;
51         options->rhosts_authentication = -1;
52         options->rhosts_rsa_authentication = -1;
53         options->rsa_authentication = -1;
54 #ifdef KRB4
55         options->kerberos_authentication = -1;
56         options->kerberos_or_local_passwd = -1;
57         options->kerberos_ticket_cleanup = -1;
58 #endif
59 #ifdef AFS
60         options->kerberos_tgt_passing = -1;
61         options->afs_token_passing = -1;
62 #endif
63         options->password_authentication = -1;
64 #ifdef SKEY
65         options->skey_authentication = -1;
66 #endif
67         options->permit_empty_passwd = -1;
68         options->use_login = -1;
69         options->num_allow_users = 0;
70         options->num_deny_users = 0;
71         options->num_allow_groups = 0;
72         options->num_deny_groups = 0;
73         options->ciphers = NULL;
74         options->protocol = SSH_PROTO_UNKNOWN;
75 }
76
77 void
78 fill_default_server_options(ServerOptions *options)
79 {
80         if (options->num_ports == 0)
81                 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
82         if (options->listen_addrs == NULL)
83                 add_listen_addr(options, NULL);
84         if (options->host_key_file == NULL)
85                 options->host_key_file = HOST_KEY_FILE;
86         if (options->dsa_key_file == NULL)
87                 options->dsa_key_file = DSA_KEY_FILE;
88         if (options->pid_file == NULL)
89                 options->pid_file = SSH_DAEMON_PID_FILE;
90         if (options->server_key_bits == -1)
91                 options->server_key_bits = 768;
92         if (options->login_grace_time == -1)
93                 options->login_grace_time = 600;
94         if (options->key_regeneration_time == -1)
95                 options->key_regeneration_time = 3600;
96         if (options->permit_root_login == -1)
97                 options->permit_root_login = 1;                 /* yes */
98         if (options->ignore_rhosts == -1)
99                 options->ignore_rhosts = 1;
100         if (options->ignore_user_known_hosts == -1)
101                 options->ignore_user_known_hosts = 0;
102         if (options->check_mail == -1)
103                 options->check_mail = 0;
104         if (options->print_motd == -1)
105                 options->print_motd = 1;
106         if (options->x11_forwarding == -1)
107                 options->x11_forwarding = 0;
108         if (options->x11_display_offset == -1)
109                 options->x11_display_offset = 10;
110         if (options->strict_modes == -1)
111                 options->strict_modes = 1;
112         if (options->keepalives == -1)
113                 options->keepalives = 1;
114         if (options->log_facility == (SyslogFacility) (-1))
115                 options->log_facility = SYSLOG_FACILITY_AUTH;
116         if (options->log_level == (LogLevel) (-1))
117                 options->log_level = SYSLOG_LEVEL_INFO;
118         if (options->rhosts_authentication == -1)
119                 options->rhosts_authentication = 0;
120         if (options->rhosts_rsa_authentication == -1)
121                 options->rhosts_rsa_authentication = 0;
122         if (options->rsa_authentication == -1)
123                 options->rsa_authentication = 1;
124 #ifdef KRB4
125         if (options->kerberos_authentication == -1)
126                 options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
127         if (options->kerberos_or_local_passwd == -1)
128                 options->kerberos_or_local_passwd = 1;
129         if (options->kerberos_ticket_cleanup == -1)
130                 options->kerberos_ticket_cleanup = 1;
131 #endif /* KRB4 */
132 #ifdef AFS
133         if (options->kerberos_tgt_passing == -1)
134                 options->kerberos_tgt_passing = 0;
135         if (options->afs_token_passing == -1)
136                 options->afs_token_passing = k_hasafs();
137 #endif /* AFS */
138         if (options->password_authentication == -1)
139                 options->password_authentication = 1;
140 #ifdef SKEY
141         if (options->skey_authentication == -1)
142                 options->skey_authentication = 1;
143 #endif
144         if (options->permit_empty_passwd == -1)
145                 options->permit_empty_passwd = 0;
146         if (options->use_login == -1)
147                 options->use_login = 0;
148         if (options->protocol == SSH_PROTO_UNKNOWN)
149                 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
150 }
151
152 #define WHITESPACE " \t\r\n"
153
154 /* Keyword tokens. */
155 typedef enum {
156         sBadOption,             /* == unknown option */
157         sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
158         sPermitRootLogin, sLogFacility, sLogLevel,
159         sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
160 #ifdef KRB4
161         sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
162 #endif
163 #ifdef AFS
164         sKerberosTgtPassing, sAFSTokenPassing,
165 #endif
166 #ifdef SKEY
167         sSkeyAuthentication,
168 #endif
169         sPasswordAuthentication, sListenAddress,
170         sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
171         sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
172         sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
173         sIgnoreUserKnownHosts, sDSAKeyFile, sCiphers, sProtocol, sPidFile
174 } ServerOpCodes;
175
176 /* Textual representation of the tokens. */
177 static struct {
178         const char *name;
179         ServerOpCodes opcode;
180 } keywords[] = {
181         { "port", sPort },
182         { "hostkey", sHostKeyFile },
183         { "dsakey", sDSAKeyFile },
184         { "pidfile", sPidFile },
185         { "serverkeybits", sServerKeyBits },
186         { "logingracetime", sLoginGraceTime },
187         { "keyregenerationinterval", sKeyRegenerationTime },
188         { "permitrootlogin", sPermitRootLogin },
189         { "syslogfacility", sLogFacility },
190         { "loglevel", sLogLevel },
191         { "rhostsauthentication", sRhostsAuthentication },
192         { "rhostsrsaauthentication", sRhostsRSAAuthentication },
193         { "rsaauthentication", sRSAAuthentication },
194 #ifdef KRB4
195         { "kerberosauthentication", sKerberosAuthentication },
196         { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
197         { "kerberosticketcleanup", sKerberosTicketCleanup },
198 #endif
199 #ifdef AFS
200         { "kerberostgtpassing", sKerberosTgtPassing },
201         { "afstokenpassing", sAFSTokenPassing },
202 #endif
203         { "passwordauthentication", sPasswordAuthentication },
204 #ifdef SKEY
205         { "skeyauthentication", sSkeyAuthentication },
206 #endif
207         { "checkmail", sCheckMail },
208         { "listenaddress", sListenAddress },
209         { "printmotd", sPrintMotd },
210         { "ignorerhosts", sIgnoreRhosts },
211         { "ignoreuserknownhosts", sIgnoreUserKnownHosts },
212         { "x11forwarding", sX11Forwarding },
213         { "x11displayoffset", sX11DisplayOffset },
214         { "strictmodes", sStrictModes },
215         { "permitemptypasswords", sEmptyPasswd },
216         { "uselogin", sUseLogin },
217         { "randomseed", sRandomSeedFile },
218         { "keepalive", sKeepAlives },
219         { "allowusers", sAllowUsers },
220         { "denyusers", sDenyUsers },
221         { "allowgroups", sAllowGroups },
222         { "denygroups", sDenyGroups },
223         { "ciphers", sCiphers },
224         { "protocol", sProtocol },
225         { NULL, 0 }
226 };
227
228 /*
229  * Returns the number of the token pointed to by cp of length len. Never
230  * returns if the token is not known.
231  */
232
233 static ServerOpCodes
234 parse_token(const char *cp, const char *filename,
235             int linenum)
236 {
237         unsigned int i;
238
239         for (i = 0; keywords[i].name; i++)
240                 if (strcasecmp(cp, keywords[i].name) == 0)
241                         return keywords[i].opcode;
242
243         fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
244                 filename, linenum, cp);
245         return sBadOption;
246 }
247
248 /*
249  * add listen address
250  */
251 void
252 add_listen_addr(ServerOptions *options, char *addr)
253 {
254         extern int IPv4or6;
255         struct addrinfo hints, *ai, *aitop;
256         char strport[NI_MAXSERV];
257         int gaierr;
258         int i;
259
260         if (options->num_ports == 0)
261                 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
262         for (i = 0; i < options->num_ports; i++) {
263                 memset(&hints, 0, sizeof(hints));
264                 hints.ai_family = IPv4or6;
265                 hints.ai_socktype = SOCK_STREAM;
266                 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
267                 snprintf(strport, sizeof strport, "%d", options->ports[i]);
268                 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
269                         fatal("bad addr or host: %s (%s)\n",
270                             addr ? addr : "<NULL>",
271                             gai_strerror(gaierr));
272                 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
273                         ;
274                 ai->ai_next = options->listen_addrs;
275                 options->listen_addrs = aitop;
276         }
277 }
278
279 /* Reads the server configuration file. */
280
281 void
282 read_server_config(ServerOptions *options, const char *filename)
283 {
284         FILE *f;
285         char line[1024];
286         char *cp, **charptr;
287         int linenum, *intptr, value;
288         int bad_options = 0;
289         ServerOpCodes opcode;
290
291         f = fopen(filename, "r");
292         if (!f) {
293                 perror(filename);
294                 exit(1);
295         }
296         linenum = 0;
297         while (fgets(line, sizeof(line), f)) {
298                 linenum++;
299                 cp = line + strspn(line, WHITESPACE);
300                 if (!*cp || *cp == '#')
301                         continue;
302                 cp = strtok(cp, WHITESPACE);
303                 opcode = parse_token(cp, filename, linenum);
304                 switch (opcode) {
305                 case sBadOption:
306                         bad_options++;
307                         continue;
308                 case sPort:
309                         /* ignore ports from configfile if cmdline specifies ports */
310                         if (options->ports_from_cmdline)
311                                 continue;
312                         if (options->listen_addrs != NULL)
313                                 fatal("%s line %d: ports must be specified before "
314                                     "ListenAdress.\n", filename, linenum);
315                         if (options->num_ports >= MAX_PORTS)
316                                 fatal("%s line %d: too many ports.\n",
317                                     filename, linenum);
318                         cp = strtok(NULL, WHITESPACE);
319                         if (!cp)
320                                 fatal("%s line %d: missing port number.\n",
321                                     filename, linenum);
322                         options->ports[options->num_ports++] = atoi(cp);
323                         break;
324
325                 case sServerKeyBits:
326                         intptr = &options->server_key_bits;
327 parse_int:
328                         cp = strtok(NULL, WHITESPACE);
329                         if (!cp) {
330                                 fprintf(stderr, "%s line %d: missing integer value.\n",
331                                         filename, linenum);
332                                 exit(1);
333                         }
334                         value = atoi(cp);
335                         if (*intptr == -1)
336                                 *intptr = value;
337                         break;
338
339                 case sLoginGraceTime:
340                         intptr = &options->login_grace_time;
341                         goto parse_int;
342
343                 case sKeyRegenerationTime:
344                         intptr = &options->key_regeneration_time;
345                         goto parse_int;
346
347                 case sListenAddress:
348                         cp = strtok(NULL, WHITESPACE);
349                         if (!cp)
350                                 fatal("%s line %d: missing inet addr.\n",
351                                     filename, linenum);
352                         add_listen_addr(options, cp);
353                         break;
354
355                 case sHostKeyFile:
356                 case sDSAKeyFile:
357                         charptr = (opcode == sHostKeyFile ) ?
358                             &options->host_key_file : &options->dsa_key_file;
359                         cp = strtok(NULL, WHITESPACE);
360                         if (!cp) {
361                                 fprintf(stderr, "%s line %d: missing file name.\n",
362                                     filename, linenum);
363                                 exit(1);
364                         }
365                         if (*charptr == NULL)
366                                 *charptr = tilde_expand_filename(cp, getuid());
367                         break;
368
369                 case sPidFile:
370                         charptr = &options->pid_file;
371                         cp = strtok(NULL, WHITESPACE);
372                         if (!cp) {
373                                 fprintf(stderr, "%s line %d: missing file name.\n",
374                                     filename, linenum);
375                                 exit(1);
376                         }
377                         if (*charptr == NULL)
378                                 *charptr = tilde_expand_filename(cp, getuid());
379                         break;
380
381                 case sRandomSeedFile:
382                         fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
383                                 filename, linenum);
384                         cp = strtok(NULL, WHITESPACE);
385                         break;
386
387                 case sPermitRootLogin:
388                         intptr = &options->permit_root_login;
389                         cp = strtok(NULL, WHITESPACE);
390                         if (!cp) {
391                                 fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
392                                         filename, linenum);
393                                 exit(1);
394                         }
395                         if (strcmp(cp, "without-password") == 0)
396                                 value = 2;
397                         else if (strcmp(cp, "yes") == 0)
398                                 value = 1;
399                         else if (strcmp(cp, "no") == 0)
400                                 value = 0;
401                         else {
402                                 fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
403                                         filename, linenum, cp);
404                                 exit(1);
405                         }
406                         if (*intptr == -1)
407                                 *intptr = value;
408                         break;
409
410                 case sIgnoreRhosts:
411                         intptr = &options->ignore_rhosts;
412 parse_flag:
413                         cp = strtok(NULL, WHITESPACE);
414                         if (!cp) {
415                                 fprintf(stderr, "%s line %d: missing yes/no argument.\n",
416                                         filename, linenum);
417                                 exit(1);
418                         }
419                         if (strcmp(cp, "yes") == 0)
420                                 value = 1;
421                         else if (strcmp(cp, "no") == 0)
422                                 value = 0;
423                         else {
424                                 fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
425                                         filename, linenum, cp);
426                                 exit(1);
427                         }
428                         if (*intptr == -1)
429                                 *intptr = value;
430                         break;
431
432                 case sIgnoreUserKnownHosts:
433                         intptr = &options->ignore_user_known_hosts;
434                         goto parse_flag;
435
436                 case sRhostsAuthentication:
437                         intptr = &options->rhosts_authentication;
438                         goto parse_flag;
439
440                 case sRhostsRSAAuthentication:
441                         intptr = &options->rhosts_rsa_authentication;
442                         goto parse_flag;
443
444                 case sRSAAuthentication:
445                         intptr = &options->rsa_authentication;
446                         goto parse_flag;
447
448 #ifdef KRB4
449                 case sKerberosAuthentication:
450                         intptr = &options->kerberos_authentication;
451                         goto parse_flag;
452
453                 case sKerberosOrLocalPasswd:
454                         intptr = &options->kerberos_or_local_passwd;
455                         goto parse_flag;
456
457                 case sKerberosTicketCleanup:
458                         intptr = &options->kerberos_ticket_cleanup;
459                         goto parse_flag;
460 #endif
461
462 #ifdef AFS
463                 case sKerberosTgtPassing:
464                         intptr = &options->kerberos_tgt_passing;
465                         goto parse_flag;
466
467                 case sAFSTokenPassing:
468                         intptr = &options->afs_token_passing;
469                         goto parse_flag;
470 #endif
471
472                 case sPasswordAuthentication:
473                         intptr = &options->password_authentication;
474                         goto parse_flag;
475
476                 case sCheckMail:
477                         intptr = &options->check_mail;
478                         goto parse_flag;
479
480 #ifdef SKEY
481                 case sSkeyAuthentication:
482                         intptr = &options->skey_authentication;
483                         goto parse_flag;
484 #endif
485
486                 case sPrintMotd:
487                         intptr = &options->print_motd;
488                         goto parse_flag;
489
490                 case sX11Forwarding:
491                         intptr = &options->x11_forwarding;
492                         goto parse_flag;
493
494                 case sX11DisplayOffset:
495                         intptr = &options->x11_display_offset;
496                         goto parse_int;
497
498                 case sStrictModes:
499                         intptr = &options->strict_modes;
500                         goto parse_flag;
501
502                 case sKeepAlives:
503                         intptr = &options->keepalives;
504                         goto parse_flag;
505
506                 case sEmptyPasswd:
507                         intptr = &options->permit_empty_passwd;
508                         goto parse_flag;
509
510                 case sUseLogin:
511                         intptr = &options->use_login;
512                         goto parse_flag;
513
514                 case sLogFacility:
515                         intptr = (int *) &options->log_facility;
516                         cp = strtok(NULL, WHITESPACE);
517                         value = log_facility_number(cp);
518                         if (value == (SyslogFacility) - 1)
519                                 fatal("%.200s line %d: unsupported log facility '%s'\n",
520                                     filename, linenum, cp ? cp : "<NONE>");
521                         if (*intptr == -1)
522                                 *intptr = (SyslogFacility) value;
523                         break;
524
525                 case sLogLevel:
526                         intptr = (int *) &options->log_level;
527                         cp = strtok(NULL, WHITESPACE);
528                         value = log_level_number(cp);
529                         if (value == (LogLevel) - 1)
530                                 fatal("%.200s line %d: unsupported log level '%s'\n",
531                                     filename, linenum, cp ? cp : "<NONE>");
532                         if (*intptr == -1)
533                                 *intptr = (LogLevel) value;
534                         break;
535
536                 case sAllowUsers:
537                         while ((cp = strtok(NULL, WHITESPACE))) {
538                                 if (options->num_allow_users >= MAX_ALLOW_USERS)
539                                         fatal("%s line %d: too many allow users.\n",
540                                             filename, linenum);
541                                 options->allow_users[options->num_allow_users++] = xstrdup(cp);
542                         }
543                         break;
544
545                 case sDenyUsers:
546                         while ((cp = strtok(NULL, WHITESPACE))) {
547                                 if (options->num_deny_users >= MAX_DENY_USERS)
548                                         fatal( "%s line %d: too many deny users.\n",
549                                             filename, linenum);
550                                 options->deny_users[options->num_deny_users++] = xstrdup(cp);
551                         }
552                         break;
553
554                 case sAllowGroups:
555                         while ((cp = strtok(NULL, WHITESPACE))) {
556                                 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
557                                         fatal("%s line %d: too many allow groups.\n",
558                                             filename, linenum);
559                                 options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
560                         }
561                         break;
562
563                 case sDenyGroups:
564                         while ((cp = strtok(NULL, WHITESPACE))) {
565                                 if (options->num_deny_groups >= MAX_DENY_GROUPS)
566                                         fatal("%s line %d: too many deny groups.\n",
567                                             filename, linenum);
568                                 options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
569                         }
570                         break;
571
572                 case sCiphers:
573                         cp = strtok(NULL, WHITESPACE);
574                         if (!ciphers_valid(cp))
575                                 fatal("%s line %d: Bad cipher spec '%s'.",
576                                     filename, linenum, cp ? cp : "<NONE>");
577                         if (options->ciphers == NULL)
578                                 options->ciphers = xstrdup(cp);
579                         break;
580
581                 case sProtocol:
582                         intptr = &options->protocol;
583                         cp = strtok(NULL, WHITESPACE);
584                         value = proto_spec(cp);
585                         if (value == SSH_PROTO_UNKNOWN)
586                                 fatal("%s line %d: Bad protocol spec '%s'.",
587                                       filename, linenum, cp ? cp : "<NONE>");
588                         if (*intptr == SSH_PROTO_UNKNOWN)
589                                 *intptr = value;
590                         break;
591
592                 default:
593                         fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
594                                 filename, linenum, cp, opcode);
595                         exit(1);
596                 }
597                 if (strtok(NULL, WHITESPACE) != NULL) {
598                         fprintf(stderr, "%s line %d: garbage at end of line.\n",
599                                 filename, linenum);
600                         exit(1);
601                 }
602         }
603         fclose(f);
604         if (bad_options > 0) {
605                 fprintf(stderr, "%s: terminating, %d bad configuration options\n",
606                         filename, bad_options);
607                 exit(1);
608         }
609 }
This page took 0.191138 seconds and 3 git commands to generate.