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