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