Annotation of src/usr.bin/ssh/readconf.c, Revision 1.100.2.2
1.1 deraadt 1: /*
1.18 deraadt 2: * Author: Tatu Ylonen <ylo@cs.hut.fi>
3: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4: * All rights reserved
5: * Functions for reading the configuration files.
1.26 markus 6: *
1.46 deraadt 7: * As far as I am concerned, the code I have written for this software
8: * can be used freely for any purpose. Any derived versions of this
9: * software must be clearly marked as such, and if the derived work is
10: * incompatible with the protocol description in the RFC file, it must be
11: * called by a name other than "ssh" or "Secure Shell".
1.18 deraadt 12: */
1.1 deraadt 13:
14: #include "includes.h"
1.100.2.2! brad 15: RCSID("$OpenBSD: readconf.c,v 1.121 2003/09/01 18:15:50 markus Exp $");
1.1 deraadt 16:
17: #include "ssh.h"
18: #include "xmalloc.h"
1.25 markus 19: #include "compat.h"
1.58 markus 20: #include "cipher.h"
1.55 markus 21: #include "pathnames.h"
1.58 markus 22: #include "log.h"
23: #include "readconf.h"
24: #include "match.h"
25: #include "misc.h"
1.62 markus 26: #include "kex.h"
27: #include "mac.h"
1.1 deraadt 28:
29: /* Format of the configuration file:
30:
31: # Configuration data is parsed as follows:
32: # 1. command line options
33: # 2. user-specific file
34: # 3. system-wide file
35: # Any configuration value is only changed the first time it is set.
36: # Thus, host-specific definitions should be at the beginning of the
37: # configuration file, and defaults at the end.
38:
39: # Host-specific declarations. These may override anything above. A single
40: # host may match multiple declarations; these are processed in the order
41: # that they are given in.
42:
43: Host *.ngs.fi ngs.fi
1.96 markus 44: User foo
1.1 deraadt 45:
46: Host fake.com
47: HostName another.host.name.real.org
48: User blaah
49: Port 34289
50: ForwardX11 no
51: ForwardAgent no
52:
53: Host books.com
54: RemoteForward 9999 shadows.cs.hut.fi:9999
55: Cipher 3des
56:
57: Host fascist.blob.com
58: Port 23123
59: User tylonen
60: PasswordAuthentication no
61:
62: Host puukko.hut.fi
63: User t35124p
64: ProxyCommand ssh-proxy %h %p
65:
66: Host *.fr
1.96 markus 67: PublicKeyAuthentication no
1.1 deraadt 68:
69: Host *.su
70: Cipher none
71: PasswordAuthentication no
72:
73: # Defaults for various options
74: Host *
75: ForwardAgent no
1.50 markus 76: ForwardX11 no
1.1 deraadt 77: PasswordAuthentication yes
78: RSAAuthentication yes
79: RhostsRSAAuthentication yes
80: StrictHostKeyChecking yes
81: KeepAlives no
82: IdentityFile ~/.ssh/identity
83: Port 22
84: EscapeChar ~
85:
86: */
87:
88: /* Keyword tokens. */
89:
1.17 markus 90: typedef enum {
91: oBadOption,
1.100.2.2! brad 92: oForwardAgent, oForwardX11, oGatewayPorts,
1.100 deraadt 93: oPasswordAuthentication, oRSAAuthentication,
1.59 markus 94: oChallengeResponseAuthentication, oXAuthLocation,
1.17 markus 95: oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
96: oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
97: oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
98: oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
1.59 markus 99: oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
1.62 markus 100: oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
1.50 markus 101: oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
1.67 markus 102: oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
1.76 markus 103: oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
1.90 stevesk 104: oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
1.96 markus 105: oClearAllForwardings, oNoHostAuthenticationForLocalhost,
1.100.2.2! brad 106: oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
! 107: oAddressFamily, oGssAuthentication, oGssDelegateCreds,
! 108: oDeprecated, oUnsupported
1.1 deraadt 109: } OpCodes;
110:
111: /* Textual representations of the tokens. */
112:
1.17 markus 113: static struct {
114: const char *name;
115: OpCodes opcode;
116: } keywords[] = {
117: { "forwardagent", oForwardAgent },
118: { "forwardx11", oForwardX11 },
1.34 markus 119: { "xauthlocation", oXAuthLocation },
1.17 markus 120: { "gatewayports", oGatewayPorts },
121: { "useprivilegedport", oUsePrivilegedPort },
1.100.2.2! brad 122: { "rhostsauthentication", oDeprecated },
1.17 markus 123: { "passwordauthentication", oPasswordAuthentication },
1.48 markus 124: { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
125: { "kbdinteractivedevices", oKbdInteractiveDevices },
1.17 markus 126: { "rsaauthentication", oRSAAuthentication },
1.50 markus 127: { "pubkeyauthentication", oPubkeyAuthentication },
1.59 markus 128: { "dsaauthentication", oPubkeyAuthentication }, /* alias */
1.72 markus 129: { "rhostsrsaauthentication", oRhostsRSAAuthentication },
1.73 markus 130: { "hostbasedauthentication", oHostbasedAuthentication },
1.59 markus 131: { "challengeresponseauthentication", oChallengeResponseAuthentication },
132: { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
133: { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
1.100.2.2! brad 134: { "kerberosauthentication", oUnsupported },
! 135: { "kerberostgtpassing", oUnsupported },
! 136: { "afstokenpassing", oUnsupported },
! 137: #if defined(GSSAPI)
! 138: { "gssapiauthentication", oGssAuthentication },
! 139: { "gssapidelegatecredentials", oGssDelegateCreds },
! 140: #else
! 141: { "gssapiauthentication", oUnsupported },
! 142: { "gssapidelegatecredentials", oUnsupported },
1.1 deraadt 143: #endif
1.96 markus 144: { "fallbacktorsh", oDeprecated },
145: { "usersh", oDeprecated },
1.17 markus 146: { "identityfile", oIdentityFile },
1.50 markus 147: { "identityfile2", oIdentityFile }, /* alias */
1.17 markus 148: { "hostname", oHostName },
1.52 markus 149: { "hostkeyalias", oHostKeyAlias },
1.17 markus 150: { "proxycommand", oProxyCommand },
151: { "port", oPort },
152: { "cipher", oCipher },
1.25 markus 153: { "ciphers", oCiphers },
1.62 markus 154: { "macs", oMacs },
1.25 markus 155: { "protocol", oProtocol },
1.17 markus 156: { "remoteforward", oRemoteForward },
157: { "localforward", oLocalForward },
158: { "user", oUser },
159: { "host", oHost },
160: { "escapechar", oEscapeChar },
161: { "globalknownhostsfile", oGlobalKnownHostsFile },
1.81 markus 162: { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */
1.27 markus 163: { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
1.81 markus 164: { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */
1.17 markus 165: { "connectionattempts", oConnectionAttempts },
166: { "batchmode", oBatchMode },
167: { "checkhostip", oCheckHostIP },
168: { "stricthostkeychecking", oStrictHostKeyChecking },
169: { "compression", oCompression },
170: { "compressionlevel", oCompressionLevel },
171: { "keepalive", oKeepAlives },
172: { "numberofpasswordprompts", oNumberOfPasswordPrompts },
173: { "loglevel", oLogLevel },
1.71 markus 174: { "dynamicforward", oDynamicForward },
1.67 markus 175: { "preferredauthentications", oPreferredAuthentications },
1.76 markus 176: { "hostkeyalgorithms", oHostKeyAlgorithms },
1.77 markus 177: { "bindaddress", oBindAddress },
1.100.2.2! brad 178: #ifdef SMARTCARD
1.85 jakob 179: { "smartcarddevice", oSmartcardDevice },
1.100.2.2! brad 180: #else
! 181: { "smartcarddevice", oUnsupported },
! 182: #endif
1.93 deraadt 183: { "clearallforwardings", oClearAllForwardings },
1.100.2.1 margarid 184: { "enablesshkeysign", oEnableSSHKeysign },
1.100.2.2! brad 185: #ifdef DNS
! 186: { "verifyhostkeydns", oVerifyHostKeyDNS },
! 187: #else
! 188: { "verifyhostkeydns", oUnsupported },
! 189: #endif
1.93 deraadt 190: { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
1.100.2.2! brad 191: { "rekeylimit", oRekeyLimit },
! 192: { "connecttimeout", oConnectTimeout },
! 193: { "addressfamily", oAddressFamily },
1.92 stevesk 194: { NULL, oBadOption }
1.13 markus 195: };
196:
1.19 markus 197: /*
198: * Adds a local TCP/IP port forward to options. Never returns if there is an
199: * error.
200: */
1.1 deraadt 201:
1.26 markus 202: void
1.22 markus 203: add_local_forward(Options *options, u_short port, const char *host,
204: u_short host_port)
1.1 deraadt 205: {
1.17 markus 206: Forward *fwd;
207: extern uid_t original_real_uid;
208: if (port < IPPORT_RESERVED && original_real_uid != 0)
1.64 millert 209: fatal("Privileged ports can only be forwarded by root.");
1.17 markus 210: if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
211: fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
212: fwd = &options->local_forwards[options->num_local_forwards++];
213: fwd->port = port;
214: fwd->host = xstrdup(host);
215: fwd->host_port = host_port;
1.1 deraadt 216: }
217:
1.19 markus 218: /*
219: * Adds a remote TCP/IP port forward to options. Never returns if there is
220: * an error.
221: */
1.1 deraadt 222:
1.26 markus 223: void
1.22 markus 224: add_remote_forward(Options *options, u_short port, const char *host,
225: u_short host_port)
1.1 deraadt 226: {
1.17 markus 227: Forward *fwd;
228: if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
229: fatal("Too many remote forwards (max %d).",
1.93 deraadt 230: SSH_MAX_FORWARDS_PER_DIRECTION);
1.17 markus 231: fwd = &options->remote_forwards[options->num_remote_forwards++];
232: fwd->port = port;
233: fwd->host = xstrdup(host);
234: fwd->host_port = host_port;
1.1 deraadt 235: }
236:
1.90 stevesk 237: static void
238: clear_forwardings(Options *options)
239: {
240: int i;
241:
242: for (i = 0; i < options->num_local_forwards; i++)
243: xfree(options->local_forwards[i].host);
244: options->num_local_forwards = 0;
245: for (i = 0; i < options->num_remote_forwards; i++)
246: xfree(options->remote_forwards[i].host);
247: options->num_remote_forwards = 0;
248: }
249:
1.19 markus 250: /*
1.70 stevesk 251: * Returns the number of the token pointed to by cp or oBadOption.
1.19 markus 252: */
1.1 deraadt 253:
1.26 markus 254: static OpCodes
1.17 markus 255: parse_token(const char *cp, const char *filename, int linenum)
1.1 deraadt 256: {
1.51 markus 257: u_int i;
1.1 deraadt 258:
1.17 markus 259: for (i = 0; keywords[i].name; i++)
1.20 markus 260: if (strcasecmp(cp, keywords[i].name) == 0)
1.17 markus 261: return keywords[i].opcode;
262:
1.75 stevesk 263: error("%s: line %d: Bad configuration option: %s",
264: filename, linenum, cp);
1.17 markus 265: return oBadOption;
1.1 deraadt 266: }
267:
1.19 markus 268: /*
269: * Processes a single option line as used in the configuration files. This
270: * only sets those values that have not already been set.
271: */
1.100.2.1 margarid 272: #define WHITESPACE " \t\r\n"
1.1 deraadt 273:
1.14 markus 274: int
275: process_config_line(Options *options, const char *host,
1.17 markus 276: char *line, const char *filename, int linenum,
277: int *activep)
1.1 deraadt 278: {
1.100.2.1 margarid 279: char buf[256], *s, **charptr, *endofnumber, *keyword, *arg;
1.22 markus 280: int opcode, *intptr, value;
1.100.2.1 margarid 281: size_t len;
1.22 markus 282: u_short fwd_port, fwd_host_port;
1.88 stevesk 283: char sfwd_host_port[6];
1.1 deraadt 284:
1.100.2.2! brad 285: /* Strip trailing whitespace */
! 286: for(len = strlen(line) - 1; len > 0; len--) {
! 287: if (strchr(WHITESPACE, line[len]) == NULL)
! 288: break;
! 289: line[len] = '\0';
! 290: }
! 291:
1.42 provos 292: s = line;
293: /* Get the keyword. (Each line is supposed to begin with a keyword). */
294: keyword = strdelim(&s);
295: /* Ignore leading whitespace. */
296: if (*keyword == '\0')
1.43 markus 297: keyword = strdelim(&s);
1.56 deraadt 298: if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
1.17 markus 299: return 0;
300:
1.38 provos 301: opcode = parse_token(keyword, filename, linenum);
1.17 markus 302:
303: switch (opcode) {
304: case oBadOption:
1.19 markus 305: /* don't panic, but count bad options */
306: return -1;
1.17 markus 307: /* NOTREACHED */
1.100.2.2! brad 308: case oConnectTimeout:
! 309: intptr = &options->connection_timeout;
! 310: /* parse_time: */
! 311: arg = strdelim(&s);
! 312: if (!arg || *arg == '\0')
! 313: fatal("%s line %d: missing time value.",
! 314: filename, linenum);
! 315: if ((value = convtime(arg)) == -1)
! 316: fatal("%s line %d: invalid time value.",
! 317: filename, linenum);
! 318: if (*intptr == -1)
! 319: *intptr = value;
! 320: break;
! 321:
1.17 markus 322: case oForwardAgent:
323: intptr = &options->forward_agent;
324: parse_flag:
1.42 provos 325: arg = strdelim(&s);
1.40 ho 326: if (!arg || *arg == '\0')
1.17 markus 327: fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
328: value = 0; /* To avoid compiler warning... */
1.38 provos 329: if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1.17 markus 330: value = 1;
1.38 provos 331: else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1.17 markus 332: value = 0;
333: else
334: fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
335: if (*activep && *intptr == -1)
336: *intptr = value;
337: break;
338:
339: case oForwardX11:
340: intptr = &options->forward_x11;
341: goto parse_flag;
342:
343: case oGatewayPorts:
344: intptr = &options->gateway_ports;
345: goto parse_flag;
346:
347: case oUsePrivilegedPort:
348: intptr = &options->use_privileged_port;
349: goto parse_flag;
350:
351: case oPasswordAuthentication:
352: intptr = &options->password_authentication;
353: goto parse_flag;
354:
1.48 markus 355: case oKbdInteractiveAuthentication:
356: intptr = &options->kbd_interactive_authentication;
357: goto parse_flag;
358:
359: case oKbdInteractiveDevices:
360: charptr = &options->kbd_interactive_devices;
361: goto parse_string;
362:
1.50 markus 363: case oPubkeyAuthentication:
364: intptr = &options->pubkey_authentication;
1.30 markus 365: goto parse_flag;
366:
1.17 markus 367: case oRSAAuthentication:
368: intptr = &options->rsa_authentication;
369: goto parse_flag;
370:
371: case oRhostsRSAAuthentication:
372: intptr = &options->rhosts_rsa_authentication;
373: goto parse_flag;
374:
1.72 markus 375: case oHostbasedAuthentication:
376: intptr = &options->hostbased_authentication;
377: goto parse_flag;
378:
1.59 markus 379: case oChallengeResponseAuthentication:
1.78 markus 380: intptr = &options->challenge_response_authentication;
1.17 markus 381: goto parse_flag;
1.100.2.2! brad 382:
! 383: case oGssAuthentication:
! 384: intptr = &options->gss_authentication;
1.17 markus 385: goto parse_flag;
1.100.2.2! brad 386:
! 387: case oGssDelegateCreds:
! 388: intptr = &options->gss_deleg_creds;
1.17 markus 389: goto parse_flag;
1.100.2.2! brad 390:
1.17 markus 391: case oBatchMode:
392: intptr = &options->batch_mode;
393: goto parse_flag;
394:
395: case oCheckHostIP:
396: intptr = &options->check_host_ip;
397: goto parse_flag;
398:
1.100.2.2! brad 399: case oVerifyHostKeyDNS:
! 400: intptr = &options->verify_host_key_dns;
! 401: goto parse_flag;
! 402:
1.17 markus 403: case oStrictHostKeyChecking:
404: intptr = &options->strict_host_key_checking;
1.42 provos 405: arg = strdelim(&s);
1.40 ho 406: if (!arg || *arg == '\0')
1.60 stevesk 407: fatal("%.200s line %d: Missing yes/no/ask argument.",
1.93 deraadt 408: filename, linenum);
1.17 markus 409: value = 0; /* To avoid compiler warning... */
1.38 provos 410: if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1.17 markus 411: value = 1;
1.38 provos 412: else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1.17 markus 413: value = 0;
1.38 provos 414: else if (strcmp(arg, "ask") == 0)
1.17 markus 415: value = 2;
416: else
417: fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
418: if (*activep && *intptr == -1)
419: *intptr = value;
420: break;
421:
422: case oCompression:
423: intptr = &options->compression;
424: goto parse_flag;
425:
426: case oKeepAlives:
427: intptr = &options->keepalives;
428: goto parse_flag;
429:
1.91 markus 430: case oNoHostAuthenticationForLocalhost:
431: intptr = &options->no_host_authentication_for_localhost;
432: goto parse_flag;
433:
1.17 markus 434: case oNumberOfPasswordPrompts:
435: intptr = &options->number_of_password_prompts;
436: goto parse_int;
437:
438: case oCompressionLevel:
439: intptr = &options->compression_level;
440: goto parse_int;
441:
1.100.2.2! brad 442: case oRekeyLimit:
! 443: intptr = &options->rekey_limit;
! 444: arg = strdelim(&s);
! 445: if (!arg || *arg == '\0')
! 446: fatal("%.200s line %d: Missing argument.", filename, linenum);
! 447: if (arg[0] < '0' || arg[0] > '9')
! 448: fatal("%.200s line %d: Bad number.", filename, linenum);
! 449: value = strtol(arg, &endofnumber, 10);
! 450: if (arg == endofnumber)
! 451: fatal("%.200s line %d: Bad number.", filename, linenum);
! 452: switch (toupper(*endofnumber)) {
! 453: case 'K':
! 454: value *= 1<<10;
! 455: break;
! 456: case 'M':
! 457: value *= 1<<20;
! 458: break;
! 459: case 'G':
! 460: value *= 1<<30;
! 461: break;
! 462: }
! 463: if (*activep && *intptr == -1)
! 464: *intptr = value;
! 465: break;
! 466:
1.17 markus 467: case oIdentityFile:
1.42 provos 468: arg = strdelim(&s);
1.40 ho 469: if (!arg || *arg == '\0')
1.17 markus 470: fatal("%.200s line %d: Missing argument.", filename, linenum);
471: if (*activep) {
1.50 markus 472: intptr = &options->num_identity_files;
1.27 markus 473: if (*intptr >= SSH_MAX_IDENTITY_FILES)
1.17 markus 474: fatal("%.200s line %d: Too many identity files specified (max %d).",
1.93 deraadt 475: filename, linenum, SSH_MAX_IDENTITY_FILES);
1.50 markus 476: charptr = &options->identity_files[*intptr];
1.38 provos 477: *charptr = xstrdup(arg);
1.27 markus 478: *intptr = *intptr + 1;
1.17 markus 479: }
480: break;
481:
1.34 markus 482: case oXAuthLocation:
483: charptr=&options->xauth_location;
484: goto parse_string;
485:
1.17 markus 486: case oUser:
487: charptr = &options->user;
488: parse_string:
1.42 provos 489: arg = strdelim(&s);
1.40 ho 490: if (!arg || *arg == '\0')
1.17 markus 491: fatal("%.200s line %d: Missing argument.", filename, linenum);
492: if (*activep && *charptr == NULL)
1.38 provos 493: *charptr = xstrdup(arg);
1.17 markus 494: break;
495:
496: case oGlobalKnownHostsFile:
497: charptr = &options->system_hostfile;
498: goto parse_string;
499:
500: case oUserKnownHostsFile:
501: charptr = &options->user_hostfile;
502: goto parse_string;
503:
1.27 markus 504: case oGlobalKnownHostsFile2:
505: charptr = &options->system_hostfile2;
506: goto parse_string;
507:
508: case oUserKnownHostsFile2:
509: charptr = &options->user_hostfile2;
510: goto parse_string;
511:
1.17 markus 512: case oHostName:
513: charptr = &options->hostname;
514: goto parse_string;
515:
1.52 markus 516: case oHostKeyAlias:
517: charptr = &options->host_key_alias;
518: goto parse_string;
519:
1.67 markus 520: case oPreferredAuthentications:
521: charptr = &options->preferred_authentications;
522: goto parse_string;
523:
1.77 markus 524: case oBindAddress:
525: charptr = &options->bind_address;
526: goto parse_string;
527:
1.85 jakob 528: case oSmartcardDevice:
1.86 markus 529: charptr = &options->smartcard_device;
530: goto parse_string;
1.85 jakob 531:
1.17 markus 532: case oProxyCommand:
1.100.2.2! brad 533: if (s == NULL)
! 534: fatal("%.200s line %d: Missing argument.", filename, linenum);
1.17 markus 535: charptr = &options->proxy_command;
1.100.2.1 margarid 536: len = strspn(s, WHITESPACE "=");
1.17 markus 537: if (*activep && *charptr == NULL)
1.100.2.1 margarid 538: *charptr = xstrdup(s + len);
1.17 markus 539: return 0;
540:
541: case oPort:
542: intptr = &options->port;
543: parse_int:
1.42 provos 544: arg = strdelim(&s);
1.40 ho 545: if (!arg || *arg == '\0')
1.17 markus 546: fatal("%.200s line %d: Missing argument.", filename, linenum);
1.38 provos 547: if (arg[0] < '0' || arg[0] > '9')
1.17 markus 548: fatal("%.200s line %d: Bad number.", filename, linenum);
1.21 markus 549:
550: /* Octal, decimal, or hex format? */
1.38 provos 551: value = strtol(arg, &endofnumber, 0);
552: if (arg == endofnumber)
1.21 markus 553: fatal("%.200s line %d: Bad number.", filename, linenum);
1.17 markus 554: if (*activep && *intptr == -1)
555: *intptr = value;
556: break;
557:
558: case oConnectionAttempts:
559: intptr = &options->connection_attempts;
560: goto parse_int;
561:
562: case oCipher:
563: intptr = &options->cipher;
1.42 provos 564: arg = strdelim(&s);
1.40 ho 565: if (!arg || *arg == '\0')
1.32 markus 566: fatal("%.200s line %d: Missing argument.", filename, linenum);
1.38 provos 567: value = cipher_number(arg);
1.17 markus 568: if (value == -1)
569: fatal("%.200s line %d: Bad cipher '%s'.",
1.93 deraadt 570: filename, linenum, arg ? arg : "<NONE>");
1.17 markus 571: if (*activep && *intptr == -1)
572: *intptr = value;
573: break;
574:
1.25 markus 575: case oCiphers:
1.42 provos 576: arg = strdelim(&s);
1.40 ho 577: if (!arg || *arg == '\0')
1.32 markus 578: fatal("%.200s line %d: Missing argument.", filename, linenum);
1.38 provos 579: if (!ciphers_valid(arg))
1.31 markus 580: fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1.93 deraadt 581: filename, linenum, arg ? arg : "<NONE>");
1.25 markus 582: if (*activep && options->ciphers == NULL)
1.38 provos 583: options->ciphers = xstrdup(arg);
1.25 markus 584: break;
585:
1.62 markus 586: case oMacs:
587: arg = strdelim(&s);
588: if (!arg || *arg == '\0')
589: fatal("%.200s line %d: Missing argument.", filename, linenum);
590: if (!mac_valid(arg))
591: fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1.93 deraadt 592: filename, linenum, arg ? arg : "<NONE>");
1.62 markus 593: if (*activep && options->macs == NULL)
594: options->macs = xstrdup(arg);
595: break;
596:
1.76 markus 597: case oHostKeyAlgorithms:
598: arg = strdelim(&s);
599: if (!arg || *arg == '\0')
600: fatal("%.200s line %d: Missing argument.", filename, linenum);
601: if (!key_names_valid2(arg))
602: fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
1.93 deraadt 603: filename, linenum, arg ? arg : "<NONE>");
1.76 markus 604: if (*activep && options->hostkeyalgorithms == NULL)
605: options->hostkeyalgorithms = xstrdup(arg);
606: break;
607:
1.25 markus 608: case oProtocol:
609: intptr = &options->protocol;
1.42 provos 610: arg = strdelim(&s);
1.40 ho 611: if (!arg || *arg == '\0')
1.32 markus 612: fatal("%.200s line %d: Missing argument.", filename, linenum);
1.38 provos 613: value = proto_spec(arg);
1.25 markus 614: if (value == SSH_PROTO_UNKNOWN)
615: fatal("%.200s line %d: Bad protocol spec '%s'.",
1.93 deraadt 616: filename, linenum, arg ? arg : "<NONE>");
1.25 markus 617: if (*activep && *intptr == SSH_PROTO_UNKNOWN)
618: *intptr = value;
619: break;
620:
1.17 markus 621: case oLogLevel:
622: intptr = (int *) &options->log_level;
1.42 provos 623: arg = strdelim(&s);
1.38 provos 624: value = log_level_number(arg);
1.95 markus 625: if (value == SYSLOG_LEVEL_NOT_SET)
1.64 millert 626: fatal("%.200s line %d: unsupported log level '%s'",
1.93 deraadt 627: filename, linenum, arg ? arg : "<NONE>");
1.95 markus 628: if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
1.17 markus 629: *intptr = (LogLevel) value;
630: break;
631:
1.88 stevesk 632: case oLocalForward:
1.17 markus 633: case oRemoteForward:
1.42 provos 634: arg = strdelim(&s);
1.40 ho 635: if (!arg || *arg == '\0')
1.88 stevesk 636: fatal("%.200s line %d: Missing port argument.",
637: filename, linenum);
638: if ((fwd_port = a2port(arg)) == 0)
639: fatal("%.200s line %d: Bad listen port.",
640: filename, linenum);
1.42 provos 641: arg = strdelim(&s);
1.40 ho 642: if (!arg || *arg == '\0')
1.17 markus 643: fatal("%.200s line %d: Missing second argument.",
1.88 stevesk 644: filename, linenum);
645: if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
646: sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
647: fatal("%.200s line %d: Bad forwarding specification.",
648: filename, linenum);
649: if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
650: fatal("%.200s line %d: Bad forwarding port.",
651: filename, linenum);
652: if (*activep) {
653: if (opcode == oLocalForward)
654: add_local_forward(options, fwd_port, buf,
655: fwd_host_port);
656: else if (opcode == oRemoteForward)
657: add_remote_forward(options, fwd_port, buf,
658: fwd_host_port);
659: }
1.17 markus 660: break;
1.71 markus 661:
662: case oDynamicForward:
663: arg = strdelim(&s);
664: if (!arg || *arg == '\0')
665: fatal("%.200s line %d: Missing port argument.",
666: filename, linenum);
1.74 stevesk 667: fwd_port = a2port(arg);
668: if (fwd_port == 0)
1.71 markus 669: fatal("%.200s line %d: Badly formatted port number.",
670: filename, linenum);
1.87 markus 671: if (*activep)
1.100.2.2! brad 672: add_local_forward(options, fwd_port, "socks", 0);
1.72 markus 673: break;
1.17 markus 674:
1.90 stevesk 675: case oClearAllForwardings:
676: intptr = &options->clear_forwardings;
677: goto parse_flag;
678:
1.17 markus 679: case oHost:
680: *activep = 0;
1.42 provos 681: while ((arg = strdelim(&s)) != NULL && *arg != '\0')
1.38 provos 682: if (match_pattern(host, arg)) {
683: debug("Applying options for %.100s", arg);
1.17 markus 684: *activep = 1;
685: break;
686: }
1.42 provos 687: /* Avoid garbage check below, as strdelim is done. */
1.17 markus 688: return 0;
689:
690: case oEscapeChar:
691: intptr = &options->escape_char;
1.42 provos 692: arg = strdelim(&s);
1.40 ho 693: if (!arg || *arg == '\0')
1.17 markus 694: fatal("%.200s line %d: Missing argument.", filename, linenum);
1.38 provos 695: if (arg[0] == '^' && arg[2] == 0 &&
1.51 markus 696: (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
697: value = (u_char) arg[1] & 31;
1.38 provos 698: else if (strlen(arg) == 1)
1.51 markus 699: value = (u_char) arg[0];
1.38 provos 700: else if (strcmp(arg, "none") == 0)
1.79 stevesk 701: value = SSH_ESCAPECHAR_NONE;
1.17 markus 702: else {
703: fatal("%.200s line %d: Bad escape character.",
1.93 deraadt 704: filename, linenum);
1.17 markus 705: /* NOTREACHED */
706: value = 0; /* Avoid compiler warning. */
707: }
708: if (*activep && *intptr == -1)
709: *intptr = value;
710: break;
711:
1.100.2.2! brad 712: case oAddressFamily:
! 713: arg = strdelim(&s);
! 714: intptr = &options->address_family;
! 715: if (strcasecmp(arg, "inet") == 0)
! 716: value = AF_INET;
! 717: else if (strcasecmp(arg, "inet6") == 0)
! 718: value = AF_INET6;
! 719: else if (strcasecmp(arg, "any") == 0)
! 720: value = AF_UNSPEC;
! 721: else
! 722: fatal("Unsupported AddressFamily \"%s\"", arg);
! 723: if (*activep && *intptr == -1)
! 724: *intptr = value;
! 725: break;
! 726:
1.100.2.1 margarid 727: case oEnableSSHKeysign:
728: intptr = &options->enable_ssh_keysign;
729: goto parse_flag;
730:
1.96 markus 731: case oDeprecated:
1.98 markus 732: debug("%s line %d: Deprecated option \"%s\"",
1.96 markus 733: filename, linenum, keyword);
1.98 markus 734: return 0;
1.96 markus 735:
1.100.2.2! brad 736: case oUnsupported:
! 737: error("%s line %d: Unsupported option \"%s\"",
! 738: filename, linenum, keyword);
! 739: return 0;
! 740:
1.17 markus 741: default:
742: fatal("process_config_line: Unimplemented opcode %d", opcode);
743: }
744:
745: /* Check that there is no garbage at end of line. */
1.57 djm 746: if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1.39 ho 747: fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1.93 deraadt 748: filename, linenum, arg);
1.39 ho 749: }
1.17 markus 750: return 0;
1.1 deraadt 751: }
752:
753:
1.19 markus 754: /*
755: * Reads the config file and modifies the options accordingly. Options
756: * should already be initialized before this call. This never returns if
1.89 stevesk 757: * there is an error. If the file does not exist, this returns 0.
1.19 markus 758: */
1.1 deraadt 759:
1.89 stevesk 760: int
1.17 markus 761: read_config_file(const char *filename, const char *host, Options *options)
1.1 deraadt 762: {
1.17 markus 763: FILE *f;
764: char line[1024];
765: int active, linenum;
766: int bad_options = 0;
767:
768: /* Open the file. */
769: f = fopen(filename, "r");
770: if (!f)
1.89 stevesk 771: return 0;
1.17 markus 772:
773: debug("Reading configuration data %.200s", filename);
774:
1.19 markus 775: /*
776: * Mark that we are now processing the options. This flag is turned
777: * on/off by Host specifications.
778: */
1.17 markus 779: active = 1;
780: linenum = 0;
781: while (fgets(line, sizeof(line), f)) {
782: /* Update line number counter. */
783: linenum++;
784: if (process_config_line(options, host, line, filename, linenum, &active) != 0)
785: bad_options++;
786: }
787: fclose(f);
788: if (bad_options > 0)
1.64 millert 789: fatal("%s: terminating, %d bad configuration options",
1.93 deraadt 790: filename, bad_options);
1.89 stevesk 791: return 1;
1.1 deraadt 792: }
793:
1.19 markus 794: /*
795: * Initializes options to special values that indicate that they have not yet
796: * been set. Read_config_file will only set options with this value. Options
797: * are processed in the following order: command line, user config file,
798: * system config file. Last, fill_default_options is called.
799: */
1.1 deraadt 800:
1.26 markus 801: void
1.17 markus 802: initialize_options(Options * options)
1.1 deraadt 803: {
1.17 markus 804: memset(options, 'X', sizeof(*options));
805: options->forward_agent = -1;
806: options->forward_x11 = -1;
1.34 markus 807: options->xauth_location = NULL;
1.17 markus 808: options->gateway_ports = -1;
809: options->use_privileged_port = -1;
810: options->rsa_authentication = -1;
1.50 markus 811: options->pubkey_authentication = -1;
1.78 markus 812: options->challenge_response_authentication = -1;
1.100.2.2! brad 813: options->gss_authentication = -1;
! 814: options->gss_deleg_creds = -1;
1.17 markus 815: options->password_authentication = -1;
1.48 markus 816: options->kbd_interactive_authentication = -1;
817: options->kbd_interactive_devices = NULL;
1.17 markus 818: options->rhosts_rsa_authentication = -1;
1.72 markus 819: options->hostbased_authentication = -1;
1.17 markus 820: options->batch_mode = -1;
821: options->check_host_ip = -1;
822: options->strict_host_key_checking = -1;
823: options->compression = -1;
824: options->keepalives = -1;
825: options->compression_level = -1;
826: options->port = -1;
1.100.2.2! brad 827: options->address_family = -1;
1.17 markus 828: options->connection_attempts = -1;
1.100.2.2! brad 829: options->connection_timeout = -1;
1.17 markus 830: options->number_of_password_prompts = -1;
831: options->cipher = -1;
1.25 markus 832: options->ciphers = NULL;
1.62 markus 833: options->macs = NULL;
1.76 markus 834: options->hostkeyalgorithms = NULL;
1.25 markus 835: options->protocol = SSH_PROTO_UNKNOWN;
1.17 markus 836: options->num_identity_files = 0;
837: options->hostname = NULL;
1.52 markus 838: options->host_key_alias = NULL;
1.17 markus 839: options->proxy_command = NULL;
840: options->user = NULL;
841: options->escape_char = -1;
842: options->system_hostfile = NULL;
843: options->user_hostfile = NULL;
1.27 markus 844: options->system_hostfile2 = NULL;
845: options->user_hostfile2 = NULL;
1.17 markus 846: options->num_local_forwards = 0;
847: options->num_remote_forwards = 0;
1.90 stevesk 848: options->clear_forwardings = -1;
1.95 markus 849: options->log_level = SYSLOG_LEVEL_NOT_SET;
1.67 markus 850: options->preferred_authentications = NULL;
1.77 markus 851: options->bind_address = NULL;
1.86 markus 852: options->smartcard_device = NULL;
1.100.2.1 margarid 853: options->enable_ssh_keysign = - 1;
1.91 markus 854: options->no_host_authentication_for_localhost = - 1;
1.100.2.2! brad 855: options->rekey_limit = - 1;
! 856: options->verify_host_key_dns = -1;
1.1 deraadt 857: }
858:
1.19 markus 859: /*
860: * Called after processing other sources of option data, this fills those
861: * options for which no value has been specified with their default values.
862: */
1.1 deraadt 863:
1.26 markus 864: void
1.17 markus 865: fill_default_options(Options * options)
1.1 deraadt 866: {
1.61 deraadt 867: int len;
868:
1.17 markus 869: if (options->forward_agent == -1)
1.33 markus 870: options->forward_agent = 0;
1.17 markus 871: if (options->forward_x11 == -1)
1.23 markus 872: options->forward_x11 = 0;
1.34 markus 873: if (options->xauth_location == NULL)
1.80 markus 874: options->xauth_location = _PATH_XAUTH;
1.17 markus 875: if (options->gateway_ports == -1)
876: options->gateway_ports = 0;
877: if (options->use_privileged_port == -1)
1.65 markus 878: options->use_privileged_port = 0;
1.17 markus 879: if (options->rsa_authentication == -1)
880: options->rsa_authentication = 1;
1.50 markus 881: if (options->pubkey_authentication == -1)
882: options->pubkey_authentication = 1;
1.78 markus 883: if (options->challenge_response_authentication == -1)
1.83 markus 884: options->challenge_response_authentication = 1;
1.100.2.2! brad 885: if (options->gss_authentication == -1)
! 886: options->gss_authentication = 1;
! 887: if (options->gss_deleg_creds == -1)
! 888: options->gss_deleg_creds = 0;
1.17 markus 889: if (options->password_authentication == -1)
890: options->password_authentication = 1;
1.48 markus 891: if (options->kbd_interactive_authentication == -1)
1.59 markus 892: options->kbd_interactive_authentication = 1;
1.17 markus 893: if (options->rhosts_rsa_authentication == -1)
1.99 stevesk 894: options->rhosts_rsa_authentication = 0;
1.72 markus 895: if (options->hostbased_authentication == -1)
896: options->hostbased_authentication = 0;
1.17 markus 897: if (options->batch_mode == -1)
898: options->batch_mode = 0;
899: if (options->check_host_ip == -1)
900: options->check_host_ip = 1;
901: if (options->strict_host_key_checking == -1)
902: options->strict_host_key_checking = 2; /* 2 is default */
903: if (options->compression == -1)
904: options->compression = 0;
905: if (options->keepalives == -1)
906: options->keepalives = 1;
907: if (options->compression_level == -1)
908: options->compression_level = 6;
909: if (options->port == -1)
910: options->port = 0; /* Filled in ssh_connect. */
1.100.2.2! brad 911: if (options->address_family == -1)
! 912: options->address_family = AF_UNSPEC;
1.17 markus 913: if (options->connection_attempts == -1)
1.84 markus 914: options->connection_attempts = 1;
1.17 markus 915: if (options->number_of_password_prompts == -1)
916: options->number_of_password_prompts = 3;
917: /* Selected in ssh_login(). */
918: if (options->cipher == -1)
919: options->cipher = SSH_CIPHER_NOT_SET;
1.31 markus 920: /* options->ciphers, default set in myproposals.h */
1.62 markus 921: /* options->macs, default set in myproposals.h */
1.76 markus 922: /* options->hostkeyalgorithms, default set in myproposals.h */
1.25 markus 923: if (options->protocol == SSH_PROTO_UNKNOWN)
1.69 markus 924: options->protocol = SSH_PROTO_1|SSH_PROTO_2;
1.17 markus 925: if (options->num_identity_files == 0) {
1.50 markus 926: if (options->protocol & SSH_PROTO_1) {
1.61 deraadt 927: len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1.50 markus 928: options->identity_files[options->num_identity_files] =
1.61 deraadt 929: xmalloc(len);
930: snprintf(options->identity_files[options->num_identity_files++],
931: len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1.50 markus 932: }
933: if (options->protocol & SSH_PROTO_2) {
1.63 deraadt 934: len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
935: options->identity_files[options->num_identity_files] =
936: xmalloc(len);
937: snprintf(options->identity_files[options->num_identity_files++],
938: len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
939:
1.61 deraadt 940: len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1.50 markus 941: options->identity_files[options->num_identity_files] =
1.61 deraadt 942: xmalloc(len);
943: snprintf(options->identity_files[options->num_identity_files++],
944: len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1.50 markus 945: }
1.27 markus 946: }
1.17 markus 947: if (options->escape_char == -1)
948: options->escape_char = '~';
949: if (options->system_hostfile == NULL)
1.55 markus 950: options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1.17 markus 951: if (options->user_hostfile == NULL)
1.55 markus 952: options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1.27 markus 953: if (options->system_hostfile2 == NULL)
1.55 markus 954: options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1.27 markus 955: if (options->user_hostfile2 == NULL)
1.55 markus 956: options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1.95 markus 957: if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1.54 markus 958: options->log_level = SYSLOG_LEVEL_INFO;
1.90 stevesk 959: if (options->clear_forwardings == 1)
960: clear_forwardings(options);
1.91 markus 961: if (options->no_host_authentication_for_localhost == - 1)
962: options->no_host_authentication_for_localhost = 0;
1.100.2.1 margarid 963: if (options->enable_ssh_keysign == -1)
964: options->enable_ssh_keysign = 0;
1.100.2.2! brad 965: if (options->rekey_limit == -1)
! 966: options->rekey_limit = 0;
! 967: if (options->verify_host_key_dns == -1)
! 968: options->verify_host_key_dns = 0;
1.17 markus 969: /* options->proxy_command should not be set by default */
970: /* options->user will be set in the main program if appropriate */
971: /* options->hostname will be set in the main program if appropriate */
1.52 markus 972: /* options->host_key_alias should not be set by default */
1.67 markus 973: /* options->preferred_authentications will be set in ssh */
1.1 deraadt 974: }