Annotation of src/usr.bin/ssh/servconf.c, Revision 1.34
1.1 deraadt 1: /*
1.34 ! markus 2: *
1.26 deraadt 3: * servconf.c
1.34 ! markus 4: *
1.26 deraadt 5: * Author: Tatu Ylonen <ylo@cs.hut.fi>
1.34 ! markus 6: *
1.26 deraadt 7: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8: * All rights reserved
1.34 ! markus 9: *
1.26 deraadt 10: * Created: Mon Aug 21 15:48:58 1995 ylo
1.34 ! markus 11: *
1.26 deraadt 12: */
1.1 deraadt 13:
14: #include "includes.h"
1.34 ! markus 15: RCSID("$Id: servconf.c,v 1.33 2000/04/12 07:45:44 markus Exp $");
1.1 deraadt 16:
17: #include "ssh.h"
18: #include "servconf.h"
19: #include "xmalloc.h"
1.33 markus 20: #include "compat.h"
1.1 deraadt 21:
1.29 markus 22: /* add listen address */
23: void add_listen_addr(ServerOptions *options, char *addr);
24:
1.1 deraadt 25: /* Initializes the server options to their default values. */
26:
1.34 ! markus 27: void
1.25 markus 28: initialize_server_options(ServerOptions *options)
1.1 deraadt 29: {
1.25 markus 30: memset(options, 0, sizeof(*options));
1.29 markus 31: options->num_ports = 0;
32: options->ports_from_cmdline = 0;
33: options->listen_addrs = NULL;
1.25 markus 34: options->host_key_file = NULL;
1.32 markus 35: options->dsa_key_file = NULL;
1.25 markus 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;
1.1 deraadt 53: #ifdef KRB4
1.25 markus 54: options->kerberos_authentication = -1;
55: options->kerberos_or_local_passwd = -1;
56: options->kerberos_ticket_cleanup = -1;
1.1 deraadt 57: #endif
1.4 dugsong 58: #ifdef AFS
1.25 markus 59: options->kerberos_tgt_passing = -1;
60: options->afs_token_passing = -1;
1.1 deraadt 61: #endif
1.25 markus 62: options->password_authentication = -1;
1.10 markus 63: #ifdef SKEY
1.25 markus 64: options->skey_authentication = -1;
1.10 markus 65: #endif
1.25 markus 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;
1.33 markus 72: options->ciphers = NULL;
73: options->protocol = SSH_PROTO_UNKNOWN;
1.1 deraadt 74: }
75:
1.34 ! markus 76: void
1.25 markus 77: fill_default_server_options(ServerOptions *options)
1.1 deraadt 78: {
1.29 markus 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);
1.25 markus 83: if (options->host_key_file == NULL)
84: options->host_key_file = HOST_KEY_FILE;
1.32 markus 85: if (options->dsa_key_file == NULL)
86: options->dsa_key_file = DSA_KEY_FILE;
1.25 markus 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)
1.30 markus 96: options->ignore_rhosts = 1;
1.25 markus 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)
1.30 markus 104: options->x11_forwarding = 0;
1.25 markus 105: if (options->x11_display_offset == -1)
1.30 markus 106: options->x11_display_offset = 10;
1.25 markus 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)
1.30 markus 118: options->rhosts_rsa_authentication = 0;
1.25 markus 119: if (options->rsa_authentication == -1)
120: options->rsa_authentication = 1;
1.1 deraadt 121: #ifdef KRB4
1.25 markus 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;
1.4 dugsong 128: #endif /* KRB4 */
129: #ifdef AFS
1.25 markus 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();
1.4 dugsong 134: #endif /* AFS */
1.25 markus 135: if (options->password_authentication == -1)
136: options->password_authentication = 1;
1.10 markus 137: #ifdef SKEY
1.25 markus 138: if (options->skey_authentication == -1)
139: options->skey_authentication = 1;
1.10 markus 140: #endif
1.25 markus 141: if (options->permit_empty_passwd == -1)
1.30 markus 142: options->permit_empty_passwd = 0;
1.25 markus 143: if (options->use_login == -1)
144: options->use_login = 0;
1.33 markus 145: if (options->protocol == SSH_PROTO_UNKNOWN)
146: options->protocol = SSH_PROTO_1;
1.1 deraadt 147: }
148:
149: #define WHITESPACE " \t\r\n"
150:
151: /* Keyword tokens. */
1.25 markus 152: typedef enum {
153: sBadOption, /* == unknown option */
154: sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
155: sPermitRootLogin, sLogFacility, sLogLevel,
156: sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
1.1 deraadt 157: #ifdef KRB4
1.25 markus 158: sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
1.1 deraadt 159: #endif
160: #ifdef AFS
1.25 markus 161: sKerberosTgtPassing, sAFSTokenPassing,
1.1 deraadt 162: #endif
1.10 markus 163: #ifdef SKEY
1.25 markus 164: sSkeyAuthentication,
1.10 markus 165: #endif
1.25 markus 166: sPasswordAuthentication, sListenAddress,
167: sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
168: sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
169: sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
1.33 markus 170: sIgnoreUserKnownHosts, sDSAKeyFile, sCiphers, sProtocol
1.1 deraadt 171: } ServerOpCodes;
172:
173: /* Textual representation of the tokens. */
1.25 markus 174: static struct {
175: const char *name;
176: ServerOpCodes opcode;
177: } keywords[] = {
178: { "port", sPort },
179: { "hostkey", sHostKeyFile },
1.32 markus 180: { "dsakey", sDSAKeyFile },
1.25 markus 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 },
1.1 deraadt 190: #ifdef KRB4
1.25 markus 191: { "kerberosauthentication", sKerberosAuthentication },
192: { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
193: { "kerberosticketcleanup", sKerberosTicketCleanup },
1.1 deraadt 194: #endif
1.4 dugsong 195: #ifdef AFS
1.25 markus 196: { "kerberostgtpassing", sKerberosTgtPassing },
197: { "afstokenpassing", sAFSTokenPassing },
1.1 deraadt 198: #endif
1.25 markus 199: { "passwordauthentication", sPasswordAuthentication },
1.10 markus 200: #ifdef SKEY
1.25 markus 201: { "skeyauthentication", sSkeyAuthentication },
1.10 markus 202: #endif
1.25 markus 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 },
1.33 markus 219: { "ciphers", sCiphers },
220: { "protocol", sProtocol },
1.25 markus 221: { NULL, 0 }
1.1 deraadt 222: };
223:
1.27 markus 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: */
1.1 deraadt 228:
1.34 ! markus 229: static ServerOpCodes
1.25 markus 230: parse_token(const char *cp, const char *filename,
231: int linenum)
1.1 deraadt 232: {
1.25 markus 233: unsigned int i;
1.1 deraadt 234:
1.25 markus 235: for (i = 0; keywords[i].name; i++)
1.28 markus 236: if (strcasecmp(cp, keywords[i].name) == 0)
1.25 markus 237: return keywords[i].opcode;
238:
239: fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
240: filename, linenum, cp);
241: return sBadOption;
1.1 deraadt 242: }
243:
1.29 markus 244: /*
245: * add listen address
246: */
1.34 ! markus 247: void
1.29 markus 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:
1.1 deraadt 275: /* Reads the server configuration file. */
276:
1.34 ! markus 277: void
1.25 markus 278: read_server_config(ServerOptions *options, const char *filename)
1.1 deraadt 279: {
1.25 markus 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);
1.1 deraadt 290: exit(1);
1.25 markus 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:
1.29 markus 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",
1.34 ! markus 313: filename, linenum);
1.29 markus 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;
1.25 markus 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);
1.29 markus 345: if (!cp)
346: fatal("%s line %d: missing inet addr.\n",
347: filename, linenum);
348: add_listen_addr(options, cp);
1.25 markus 349: break;
350:
351: case sHostKeyFile:
1.32 markus 352: case sDSAKeyFile:
353: charptr = (opcode == sHostKeyFile ) ?
354: &options->host_key_file : &options->dsa_key_file;
1.25 markus 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;
1.31 markus 418: goto parse_flag;
1.25 markus 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:
1.1 deraadt 432: #ifdef KRB4
1.25 markus 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;
1.1 deraadt 444: #endif
1.25 markus 445:
1.4 dugsong 446: #ifdef AFS
1.25 markus 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;
1.10 markus 463:
464: #ifdef SKEY
1.25 markus 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",
1.33 markus 504: filename, linenum, cp ? cp : "<NONE>");
1.25 markus 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",
1.33 markus 515: filename, linenum, cp ? cp : "<NONE>");
1.25 markus 516: if (*intptr == -1)
517: *intptr = (LogLevel) value;
518: break;
519:
520: case sAllowUsers:
521: while ((cp = strtok(NULL, WHITESPACE))) {
1.33 markus 522: if (options->num_allow_users >= MAX_ALLOW_USERS)
523: fatal("%s line %d: too many allow users.\n",
524: filename, linenum);
1.25 markus 525: options->allow_users[options->num_allow_users++] = xstrdup(cp);
526: }
527: break;
528:
529: case sDenyUsers:
530: while ((cp = strtok(NULL, WHITESPACE))) {
1.33 markus 531: if (options->num_deny_users >= MAX_DENY_USERS)
532: fatal( "%s line %d: too many deny users.\n",
533: filename, linenum);
1.25 markus 534: options->deny_users[options->num_deny_users++] = xstrdup(cp);
535: }
536: break;
537:
538: case sAllowGroups:
539: while ((cp = strtok(NULL, WHITESPACE))) {
1.33 markus 540: if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
541: fatal("%s line %d: too many allow groups.\n",
542: filename, linenum);
1.25 markus 543: options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
544: }
545: break;
546:
547: case sDenyGroups:
548: while ((cp = strtok(NULL, WHITESPACE))) {
1.33 markus 549: if (options->num_deny_groups >= MAX_DENY_GROUPS)
550: fatal("%s line %d: too many deny groups.\n",
551: filename, linenum);
1.25 markus 552: options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
553: }
1.33 markus 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;
1.25 markus 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);
1.13 markus 580: }
1.25 markus 581: if (strtok(NULL, WHITESPACE) != NULL) {
582: fprintf(stderr, "%s line %d: garbage at end of line.\n",
583: filename, linenum);
584: exit(1);
1.13 markus 585: }
1.1 deraadt 586: }
1.25 markus 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);
1.1 deraadt 592: }
593: }