Generic gssapi support
[openssh.git] / readconf.c
1 /* $OpenBSD: readconf.c,v 1.193 2011/05/24 07:15:47 djm Exp $ */
2 /*
3  * Author: Tatu Ylonen <ylo@cs.hut.fi>
4  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5  *                    All rights reserved
6  * Functions for reading the configuration files.
7  *
8  * As far as I am concerned, the code I have written for this software
9  * can be used freely for any purpose.  Any derived versions of this
10  * software must be clearly marked as such, and if the derived work is
11  * incompatible with the protocol description in the RFC file, it must be
12  * called by a name other than "ssh" or "Secure Shell".
13  */
14
15 #include "includes.h"
16
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/socket.h>
20
21 #include <netinet/in.h>
22 #include <netinet/in_systm.h>
23 #include <netinet/ip.h>
24
25 #include <ctype.h>
26 #include <errno.h>
27 #include <netdb.h>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #include "xmalloc.h"
35 #include "ssh.h"
36 #include "compat.h"
37 #include "cipher.h"
38 #include "pathnames.h"
39 #include "log.h"
40 #include "key.h"
41 #include "readconf.h"
42 #include "match.h"
43 #include "misc.h"
44 #include "buffer.h"
45 #include "kex.h"
46 #include "mac.h"
47
48 /* Format of the configuration file:
49
50    # Configuration data is parsed as follows:
51    #  1. command line options
52    #  2. user-specific file
53    #  3. system-wide file
54    # Any configuration value is only changed the first time it is set.
55    # Thus, host-specific definitions should be at the beginning of the
56    # configuration file, and defaults at the end.
57
58    # Host-specific declarations.  These may override anything above.  A single
59    # host may match multiple declarations; these are processed in the order
60    # that they are given in.
61
62    Host *.ngs.fi ngs.fi
63      User foo
64
65    Host fake.com
66      HostName another.host.name.real.org
67      User blaah
68      Port 34289
69      ForwardX11 no
70      ForwardAgent no
71
72    Host books.com
73      RemoteForward 9999 shadows.cs.hut.fi:9999
74      Cipher 3des
75
76    Host fascist.blob.com
77      Port 23123
78      User tylonen
79      PasswordAuthentication no
80
81    Host puukko.hut.fi
82      User t35124p
83      ProxyCommand ssh-proxy %h %p
84
85    Host *.fr
86      PublicKeyAuthentication no
87
88    Host *.su
89      Cipher none
90      PasswordAuthentication no
91
92    Host vpn.fake.com
93      Tunnel yes
94      TunnelDevice 3
95
96    # Defaults for various options
97    Host *
98      ForwardAgent no
99      ForwardX11 no
100      PasswordAuthentication yes
101      RSAAuthentication yes
102      RhostsRSAAuthentication yes
103      StrictHostKeyChecking yes
104      TcpKeepAlive no
105      IdentityFile ~/.ssh/identity
106      Port 22
107      EscapeChar ~
108
109 */
110
111 /* Keyword tokens. */
112
113 typedef enum {
114         oBadOption,
115         oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
116         oGatewayPorts, oExitOnForwardFailure,
117         oPasswordAuthentication, oRSAAuthentication,
118         oChallengeResponseAuthentication, oXAuthLocation,
119         oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
120         oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
121         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
122         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
123         oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
124         oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
125         oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
126         oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
127         oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
128         oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
129         oClearAllForwardings, oNoHostAuthenticationForLocalhost,
130         oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
131         oAddressFamily, oGssAuthentication, oGssDelegateCreds,
132         oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
133         oGssServerIdentity, 
134         oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
135         oSendEnv, oControlPath, oControlMaster, oControlPersist,
136         oHashKnownHosts,
137         oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
138         oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
139         oKexAlgorithms, oIPQoS, oRequestTTY,
140         oDeprecated, oUnsupported
141 } OpCodes;
142
143 /* Textual representations of the tokens. */
144
145 static struct {
146         const char *name;
147         OpCodes opcode;
148 } keywords[] = {
149         { "forwardagent", oForwardAgent },
150         { "forwardx11", oForwardX11 },
151         { "forwardx11trusted", oForwardX11Trusted },
152         { "forwardx11timeout", oForwardX11Timeout },
153         { "exitonforwardfailure", oExitOnForwardFailure },
154         { "xauthlocation", oXAuthLocation },
155         { "gatewayports", oGatewayPorts },
156         { "useprivilegedport", oUsePrivilegedPort },
157         { "rhostsauthentication", oDeprecated },
158         { "passwordauthentication", oPasswordAuthentication },
159         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
160         { "kbdinteractivedevices", oKbdInteractiveDevices },
161         { "rsaauthentication", oRSAAuthentication },
162         { "pubkeyauthentication", oPubkeyAuthentication },
163         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
164         { "rhostsrsaauthentication", oRhostsRSAAuthentication },
165         { "hostbasedauthentication", oHostbasedAuthentication },
166         { "challengeresponseauthentication", oChallengeResponseAuthentication },
167         { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
168         { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
169         { "kerberosauthentication", oUnsupported },
170         { "kerberostgtpassing", oUnsupported },
171         { "afstokenpassing", oUnsupported },
172 #if defined(GSSAPI)
173         { "gssapiauthentication", oGssAuthentication },
174         { "gssapikeyexchange", oGssKeyEx },
175         { "gssapidelegatecredentials", oGssDelegateCreds },
176         { "gssapitrustdns", oGssTrustDns },
177         { "gssapiclientidentity", oGssClientIdentity },
178         { "gssapiserveridentity", oGssServerIdentity },
179         { "gssapirenewalforcesrekey", oGssRenewalRekey },
180 #else
181         { "gssapiauthentication", oUnsupported },
182         { "gssapikeyexchange", oUnsupported },
183         { "gssapidelegatecredentials", oUnsupported },
184         { "gssapitrustdns", oUnsupported },
185         { "gssapiclientidentity", oUnsupported },
186         { "gssapirenewalforcesrekey", oUnsupported },
187 #endif
188         { "fallbacktorsh", oDeprecated },
189         { "usersh", oDeprecated },
190         { "identityfile", oIdentityFile },
191         { "identityfile2", oIdentityFile },                     /* obsolete */
192         { "identitiesonly", oIdentitiesOnly },
193         { "hostname", oHostName },
194         { "hostkeyalias", oHostKeyAlias },
195         { "proxycommand", oProxyCommand },
196         { "port", oPort },
197         { "cipher", oCipher },
198         { "ciphers", oCiphers },
199         { "macs", oMacs },
200         { "protocol", oProtocol },
201         { "remoteforward", oRemoteForward },
202         { "localforward", oLocalForward },
203         { "user", oUser },
204         { "host", oHost },
205         { "escapechar", oEscapeChar },
206         { "globalknownhostsfile", oGlobalKnownHostsFile },
207         { "globalknownhostsfile2", oDeprecated },
208         { "userknownhostsfile", oUserKnownHostsFile },
209         { "userknownhostsfile2", oDeprecated }, 
210         { "connectionattempts", oConnectionAttempts },
211         { "batchmode", oBatchMode },
212         { "checkhostip", oCheckHostIP },
213         { "stricthostkeychecking", oStrictHostKeyChecking },
214         { "compression", oCompression },
215         { "compressionlevel", oCompressionLevel },
216         { "tcpkeepalive", oTCPKeepAlive },
217         { "keepalive", oTCPKeepAlive },                         /* obsolete */
218         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
219         { "loglevel", oLogLevel },
220         { "dynamicforward", oDynamicForward },
221         { "preferredauthentications", oPreferredAuthentications },
222         { "hostkeyalgorithms", oHostKeyAlgorithms },
223         { "bindaddress", oBindAddress },
224 #ifdef ENABLE_PKCS11
225         { "smartcarddevice", oPKCS11Provider },
226         { "pkcs11provider", oPKCS11Provider },
227 #else
228         { "smartcarddevice", oUnsupported },
229         { "pkcs11provider", oUnsupported },
230 #endif
231         { "clearallforwardings", oClearAllForwardings },
232         { "enablesshkeysign", oEnableSSHKeysign },
233         { "verifyhostkeydns", oVerifyHostKeyDNS },
234         { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
235         { "rekeylimit", oRekeyLimit },
236         { "connecttimeout", oConnectTimeout },
237         { "addressfamily", oAddressFamily },
238         { "serveraliveinterval", oServerAliveInterval },
239         { "serveralivecountmax", oServerAliveCountMax },
240         { "sendenv", oSendEnv },
241         { "controlpath", oControlPath },
242         { "controlmaster", oControlMaster },
243         { "controlpersist", oControlPersist },
244         { "hashknownhosts", oHashKnownHosts },
245         { "tunnel", oTunnel },
246         { "tunneldevice", oTunnelDevice },
247         { "localcommand", oLocalCommand },
248         { "permitlocalcommand", oPermitLocalCommand },
249         { "visualhostkey", oVisualHostKey },
250         { "useroaming", oUseRoaming },
251 #ifdef JPAKE
252         { "zeroknowledgepasswordauthentication",
253             oZeroKnowledgePasswordAuthentication },
254 #else
255         { "zeroknowledgepasswordauthentication", oUnsupported },
256 #endif
257         { "kexalgorithms", oKexAlgorithms },
258         { "ipqos", oIPQoS },
259         { "requesttty", oRequestTTY },
260
261         { NULL, oBadOption }
262 };
263
264 /*
265  * Adds a local TCP/IP port forward to options.  Never returns if there is an
266  * error.
267  */
268
269 void
270 add_local_forward(Options *options, const Forward *newfwd)
271 {
272         Forward *fwd;
273 #ifndef NO_IPPORT_RESERVED_CONCEPT
274         extern uid_t original_real_uid;
275         if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
276                 fatal("Privileged ports can only be forwarded by root.");
277 #endif
278         options->local_forwards = xrealloc(options->local_forwards,
279             options->num_local_forwards + 1,
280             sizeof(*options->local_forwards));
281         fwd = &options->local_forwards[options->num_local_forwards++];
282
283         fwd->listen_host = newfwd->listen_host;
284         fwd->listen_port = newfwd->listen_port;
285         fwd->connect_host = newfwd->connect_host;
286         fwd->connect_port = newfwd->connect_port;
287 }
288
289 /*
290  * Adds a remote TCP/IP port forward to options.  Never returns if there is
291  * an error.
292  */
293
294 void
295 add_remote_forward(Options *options, const Forward *newfwd)
296 {
297         Forward *fwd;
298
299         options->remote_forwards = xrealloc(options->remote_forwards,
300             options->num_remote_forwards + 1,
301             sizeof(*options->remote_forwards));
302         fwd = &options->remote_forwards[options->num_remote_forwards++];
303
304         fwd->listen_host = newfwd->listen_host;
305         fwd->listen_port = newfwd->listen_port;
306         fwd->connect_host = newfwd->connect_host;
307         fwd->connect_port = newfwd->connect_port;
308         fwd->allocated_port = 0;
309 }
310
311 static void
312 clear_forwardings(Options *options)
313 {
314         int i;
315
316         for (i = 0; i < options->num_local_forwards; i++) {
317                 if (options->local_forwards[i].listen_host != NULL)
318                         xfree(options->local_forwards[i].listen_host);
319                 xfree(options->local_forwards[i].connect_host);
320         }
321         if (options->num_local_forwards > 0) {
322                 xfree(options->local_forwards);
323                 options->local_forwards = NULL;
324         }
325         options->num_local_forwards = 0;
326         for (i = 0; i < options->num_remote_forwards; i++) {
327                 if (options->remote_forwards[i].listen_host != NULL)
328                         xfree(options->remote_forwards[i].listen_host);
329                 xfree(options->remote_forwards[i].connect_host);
330         }
331         if (options->num_remote_forwards > 0) {
332                 xfree(options->remote_forwards);
333                 options->remote_forwards = NULL;
334         }
335         options->num_remote_forwards = 0;
336         options->tun_open = SSH_TUNMODE_NO;
337 }
338
339 /*
340  * Returns the number of the token pointed to by cp or oBadOption.
341  */
342
343 static OpCodes
344 parse_token(const char *cp, const char *filename, int linenum)
345 {
346         u_int i;
347
348         for (i = 0; keywords[i].name; i++)
349                 if (strcasecmp(cp, keywords[i].name) == 0)
350                         return keywords[i].opcode;
351
352         error("%s: line %d: Bad configuration option: %s",
353             filename, linenum, cp);
354         return oBadOption;
355 }
356
357 /*
358  * Processes a single option line as used in the configuration files. This
359  * only sets those values that have not already been set.
360  */
361 #define WHITESPACE " \t\r\n"
362
363 int
364 process_config_line(Options *options, const char *host,
365                     char *line, const char *filename, int linenum,
366                     int *activep)
367 {
368         char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
369         char **cpptr, fwdarg[256];
370         u_int *uintptr, max_entries = 0;
371         int negated, opcode, *intptr, value, value2, scale;
372         LogLevel *log_level_ptr;
373         long long orig, val64;
374         size_t len;
375         Forward fwd;
376
377         /* Strip trailing whitespace */
378         for (len = strlen(line) - 1; len > 0; len--) {
379                 if (strchr(WHITESPACE, line[len]) == NULL)
380                         break;
381                 line[len] = '\0';
382         }
383
384         s = line;
385         /* Get the keyword. (Each line is supposed to begin with a keyword). */
386         if ((keyword = strdelim(&s)) == NULL)
387                 return 0;
388         /* Ignore leading whitespace. */
389         if (*keyword == '\0')
390                 keyword = strdelim(&s);
391         if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
392                 return 0;
393
394         opcode = parse_token(keyword, filename, linenum);
395
396         switch (opcode) {
397         case oBadOption:
398                 /* don't panic, but count bad options */
399                 return -1;
400                 /* NOTREACHED */
401         case oConnectTimeout:
402                 intptr = &options->connection_timeout;
403 parse_time:
404                 arg = strdelim(&s);
405                 if (!arg || *arg == '\0')
406                         fatal("%s line %d: missing time value.",
407                             filename, linenum);
408                 if ((value = convtime(arg)) == -1)
409                         fatal("%s line %d: invalid time value.",
410                             filename, linenum);
411                 if (*activep && *intptr == -1)
412                         *intptr = value;
413                 break;
414
415         case oForwardAgent:
416                 intptr = &options->forward_agent;
417 parse_flag:
418                 arg = strdelim(&s);
419                 if (!arg || *arg == '\0')
420                         fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
421                 value = 0;      /* To avoid compiler warning... */
422                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
423                         value = 1;
424                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
425                         value = 0;
426                 else
427                         fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
428                 if (*activep && *intptr == -1)
429                         *intptr = value;
430                 break;
431
432         case oForwardX11:
433                 intptr = &options->forward_x11;
434                 goto parse_flag;
435
436         case oForwardX11Trusted:
437                 intptr = &options->forward_x11_trusted;
438                 goto parse_flag;
439         
440         case oForwardX11Timeout:
441                 intptr = &options->forward_x11_timeout;
442                 goto parse_time;
443
444         case oGatewayPorts:
445                 intptr = &options->gateway_ports;
446                 goto parse_flag;
447
448         case oExitOnForwardFailure:
449                 intptr = &options->exit_on_forward_failure;
450                 goto parse_flag;
451
452         case oUsePrivilegedPort:
453                 intptr = &options->use_privileged_port;
454                 goto parse_flag;
455
456         case oPasswordAuthentication:
457                 intptr = &options->password_authentication;
458                 goto parse_flag;
459
460         case oZeroKnowledgePasswordAuthentication:
461                 intptr = &options->zero_knowledge_password_authentication;
462                 goto parse_flag;
463
464         case oKbdInteractiveAuthentication:
465                 intptr = &options->kbd_interactive_authentication;
466                 goto parse_flag;
467
468         case oKbdInteractiveDevices:
469                 charptr = &options->kbd_interactive_devices;
470                 goto parse_string;
471
472         case oPubkeyAuthentication:
473                 intptr = &options->pubkey_authentication;
474                 goto parse_flag;
475
476         case oRSAAuthentication:
477                 intptr = &options->rsa_authentication;
478                 goto parse_flag;
479
480         case oRhostsRSAAuthentication:
481                 intptr = &options->rhosts_rsa_authentication;
482                 goto parse_flag;
483
484         case oHostbasedAuthentication:
485                 intptr = &options->hostbased_authentication;
486                 goto parse_flag;
487
488         case oChallengeResponseAuthentication:
489                 intptr = &options->challenge_response_authentication;
490                 goto parse_flag;
491
492         case oGssAuthentication:
493                 intptr = &options->gss_authentication;
494                 goto parse_flag;
495
496         case oGssKeyEx:
497                 intptr = &options->gss_keyex;
498                 goto parse_flag;
499
500         case oGssDelegateCreds:
501                 intptr = &options->gss_deleg_creds;
502                 goto parse_flag;
503
504         case oGssTrustDns:
505                 intptr = &options->gss_trust_dns;
506                 goto parse_flag;
507
508         case oGssClientIdentity:
509                 charptr = &options->gss_client_identity;
510                 goto parse_string;
511
512         case oGssServerIdentity:
513                 charptr = &options->gss_server_identity;
514                 goto parse_string;
515
516         case oGssRenewalRekey:
517                 intptr = &options->gss_renewal_rekey;
518                 goto parse_flag;
519
520         case oBatchMode:
521                 intptr = &options->batch_mode;
522                 goto parse_flag;
523
524         case oCheckHostIP:
525                 intptr = &options->check_host_ip;
526                 goto parse_flag;
527
528         case oVerifyHostKeyDNS:
529                 intptr = &options->verify_host_key_dns;
530                 goto parse_yesnoask;
531
532         case oStrictHostKeyChecking:
533                 intptr = &options->strict_host_key_checking;
534 parse_yesnoask:
535                 arg = strdelim(&s);
536                 if (!arg || *arg == '\0')
537                         fatal("%.200s line %d: Missing yes/no/ask argument.",
538                             filename, linenum);
539                 value = 0;      /* To avoid compiler warning... */
540                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
541                         value = 1;
542                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
543                         value = 0;
544                 else if (strcmp(arg, "ask") == 0)
545                         value = 2;
546                 else
547                         fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
548                 if (*activep && *intptr == -1)
549                         *intptr = value;
550                 break;
551
552         case oCompression:
553                 intptr = &options->compression;
554                 goto parse_flag;
555
556         case oTCPKeepAlive:
557                 intptr = &options->tcp_keep_alive;
558                 goto parse_flag;
559
560         case oNoHostAuthenticationForLocalhost:
561                 intptr = &options->no_host_authentication_for_localhost;
562                 goto parse_flag;
563
564         case oNumberOfPasswordPrompts:
565                 intptr = &options->number_of_password_prompts;
566                 goto parse_int;
567
568         case oCompressionLevel:
569                 intptr = &options->compression_level;
570                 goto parse_int;
571
572         case oRekeyLimit:
573                 arg = strdelim(&s);
574                 if (!arg || *arg == '\0')
575                         fatal("%.200s line %d: Missing argument.", filename, linenum);
576                 if (arg[0] < '0' || arg[0] > '9')
577                         fatal("%.200s line %d: Bad number.", filename, linenum);
578                 orig = val64 = strtoll(arg, &endofnumber, 10);
579                 if (arg == endofnumber)
580                         fatal("%.200s line %d: Bad number.", filename, linenum);
581                 switch (toupper(*endofnumber)) {
582                 case '\0':
583                         scale = 1;
584                         break;
585                 case 'K':
586                         scale = 1<<10;
587                         break;
588                 case 'M':
589                         scale = 1<<20;
590                         break;
591                 case 'G':
592                         scale = 1<<30;
593                         break;
594                 default:
595                         fatal("%.200s line %d: Invalid RekeyLimit suffix",
596                             filename, linenum);
597                 }
598                 val64 *= scale;
599                 /* detect integer wrap and too-large limits */
600                 if ((val64 / scale) != orig || val64 > UINT_MAX)
601                         fatal("%.200s line %d: RekeyLimit too large",
602                             filename, linenum);
603                 if (val64 < 16)
604                         fatal("%.200s line %d: RekeyLimit too small",
605                             filename, linenum);
606                 if (*activep && options->rekey_limit == -1)
607                         options->rekey_limit = (u_int32_t)val64;
608                 break;
609
610         case oIdentityFile:
611                 arg = strdelim(&s);
612                 if (!arg || *arg == '\0')
613                         fatal("%.200s line %d: Missing argument.", filename, linenum);
614                 if (*activep) {
615                         intptr = &options->num_identity_files;
616                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
617                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
618                                     filename, linenum, SSH_MAX_IDENTITY_FILES);
619                         charptr = &options->identity_files[*intptr];
620                         *charptr = xstrdup(arg);
621                         *intptr = *intptr + 1;
622                 }
623                 break;
624
625         case oXAuthLocation:
626                 charptr=&options->xauth_location;
627                 goto parse_string;
628
629         case oUser:
630                 charptr = &options->user;
631 parse_string:
632                 arg = strdelim(&s);
633                 if (!arg || *arg == '\0')
634                         fatal("%.200s line %d: Missing argument.",
635                             filename, linenum);
636                 if (*activep && *charptr == NULL)
637                         *charptr = xstrdup(arg);
638                 break;
639
640         case oGlobalKnownHostsFile:
641                 cpptr = (char **)&options->system_hostfiles;
642                 uintptr = &options->num_system_hostfiles;
643                 max_entries = SSH_MAX_HOSTS_FILES;
644 parse_char_array:
645                 if (*activep && *uintptr == 0) {
646                         while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
647                                 if ((*uintptr) >= max_entries)
648                                         fatal("%s line %d: "
649                                             "too many authorized keys files.",
650                                             filename, linenum);
651                                 cpptr[(*uintptr)++] = xstrdup(arg);
652                         }
653                 }
654                 return 0;
655
656         case oUserKnownHostsFile:
657                 cpptr = (char **)&options->user_hostfiles;
658                 uintptr = &options->num_user_hostfiles;
659                 max_entries = SSH_MAX_HOSTS_FILES;
660                 goto parse_char_array;
661
662         case oHostName:
663                 charptr = &options->hostname;
664                 goto parse_string;
665
666         case oHostKeyAlias:
667                 charptr = &options->host_key_alias;
668                 goto parse_string;
669
670         case oPreferredAuthentications:
671                 charptr = &options->preferred_authentications;
672                 goto parse_string;
673
674         case oBindAddress:
675                 charptr = &options->bind_address;
676                 goto parse_string;
677
678         case oPKCS11Provider:
679                 charptr = &options->pkcs11_provider;
680                 goto parse_string;
681
682         case oProxyCommand:
683                 charptr = &options->proxy_command;
684 parse_command:
685                 if (s == NULL)
686                         fatal("%.200s line %d: Missing argument.", filename, linenum);
687                 len = strspn(s, WHITESPACE "=");
688                 if (*activep && *charptr == NULL)
689                         *charptr = xstrdup(s + len);
690                 return 0;
691
692         case oPort:
693                 intptr = &options->port;
694 parse_int:
695                 arg = strdelim(&s);
696                 if (!arg || *arg == '\0')
697                         fatal("%.200s line %d: Missing argument.", filename, linenum);
698                 if (arg[0] < '0' || arg[0] > '9')
699                         fatal("%.200s line %d: Bad number.", filename, linenum);
700
701                 /* Octal, decimal, or hex format? */
702                 value = strtol(arg, &endofnumber, 0);
703                 if (arg == endofnumber)
704                         fatal("%.200s line %d: Bad number.", filename, linenum);
705                 if (*activep && *intptr == -1)
706                         *intptr = value;
707                 break;
708
709         case oConnectionAttempts:
710                 intptr = &options->connection_attempts;
711                 goto parse_int;
712
713         case oCipher:
714                 intptr = &options->cipher;
715                 arg = strdelim(&s);
716                 if (!arg || *arg == '\0')
717                         fatal("%.200s line %d: Missing argument.", filename, linenum);
718                 value = cipher_number(arg);
719                 if (value == -1)
720                         fatal("%.200s line %d: Bad cipher '%s'.",
721                             filename, linenum, arg ? arg : "<NONE>");
722                 if (*activep && *intptr == -1)
723                         *intptr = value;
724                 break;
725
726         case oCiphers:
727                 arg = strdelim(&s);
728                 if (!arg || *arg == '\0')
729                         fatal("%.200s line %d: Missing argument.", filename, linenum);
730                 if (!ciphers_valid(arg))
731                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
732                             filename, linenum, arg ? arg : "<NONE>");
733                 if (*activep && options->ciphers == NULL)
734                         options->ciphers = xstrdup(arg);
735                 break;
736
737         case oMacs:
738                 arg = strdelim(&s);
739                 if (!arg || *arg == '\0')
740                         fatal("%.200s line %d: Missing argument.", filename, linenum);
741                 if (!mac_valid(arg))
742                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
743                             filename, linenum, arg ? arg : "<NONE>");
744                 if (*activep && options->macs == NULL)
745                         options->macs = xstrdup(arg);
746                 break;
747
748         case oKexAlgorithms:
749                 arg = strdelim(&s);
750                 if (!arg || *arg == '\0')
751                         fatal("%.200s line %d: Missing argument.",
752                             filename, linenum);
753                 if (!kex_names_valid(arg))
754                         fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
755                             filename, linenum, arg ? arg : "<NONE>");
756                 if (*activep && options->kex_algorithms == NULL)
757                         options->kex_algorithms = xstrdup(arg);
758                 break;
759
760         case oHostKeyAlgorithms:
761                 arg = strdelim(&s);
762                 if (!arg || *arg == '\0')
763                         fatal("%.200s line %d: Missing argument.", filename, linenum);
764                 if (!key_names_valid2(arg))
765                         fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
766                             filename, linenum, arg ? arg : "<NONE>");
767                 if (*activep && options->hostkeyalgorithms == NULL)
768                         options->hostkeyalgorithms = xstrdup(arg);
769                 break;
770
771         case oProtocol:
772                 intptr = &options->protocol;
773                 arg = strdelim(&s);
774                 if (!arg || *arg == '\0')
775                         fatal("%.200s line %d: Missing argument.", filename, linenum);
776                 value = proto_spec(arg);
777                 if (value == SSH_PROTO_UNKNOWN)
778                         fatal("%.200s line %d: Bad protocol spec '%s'.",
779                             filename, linenum, arg ? arg : "<NONE>");
780                 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
781                         *intptr = value;
782                 break;
783
784         case oLogLevel:
785                 log_level_ptr = &options->log_level;
786                 arg = strdelim(&s);
787                 value = log_level_number(arg);
788                 if (value == SYSLOG_LEVEL_NOT_SET)
789                         fatal("%.200s line %d: unsupported log level '%s'",
790                             filename, linenum, arg ? arg : "<NONE>");
791                 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
792                         *log_level_ptr = (LogLevel) value;
793                 break;
794
795         case oLocalForward:
796         case oRemoteForward:
797         case oDynamicForward:
798                 arg = strdelim(&s);
799                 if (arg == NULL || *arg == '\0')
800                         fatal("%.200s line %d: Missing port argument.",
801                             filename, linenum);
802
803                 if (opcode == oLocalForward ||
804                     opcode == oRemoteForward) {
805                         arg2 = strdelim(&s);
806                         if (arg2 == NULL || *arg2 == '\0')
807                                 fatal("%.200s line %d: Missing target argument.",
808                                     filename, linenum);
809
810                         /* construct a string for parse_forward */
811                         snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
812                 } else if (opcode == oDynamicForward) {
813                         strlcpy(fwdarg, arg, sizeof(fwdarg));
814                 }
815
816                 if (parse_forward(&fwd, fwdarg,
817                     opcode == oDynamicForward ? 1 : 0,
818                     opcode == oRemoteForward ? 1 : 0) == 0)
819                         fatal("%.200s line %d: Bad forwarding specification.",
820                             filename, linenum);
821
822                 if (*activep) {
823                         if (opcode == oLocalForward ||
824                             opcode == oDynamicForward)
825                                 add_local_forward(options, &fwd);
826                         else if (opcode == oRemoteForward)
827                                 add_remote_forward(options, &fwd);
828                 }
829                 break;
830
831         case oClearAllForwardings:
832                 intptr = &options->clear_forwardings;
833                 goto parse_flag;
834
835         case oHost:
836                 *activep = 0;
837                 arg2 = NULL;
838                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
839                         negated = *arg == '!';
840                         if (negated)
841                                 arg++;
842                         if (match_pattern(host, arg)) {
843                                 if (negated) {
844                                         debug("%.200s line %d: Skipping Host "
845                                             "block because of negated match "
846                                             "for %.100s", filename, linenum,
847                                             arg);
848                                         *activep = 0;
849                                         break;
850                                 }
851                                 if (!*activep)
852                                         arg2 = arg; /* logged below */
853                                 *activep = 1;
854                         }
855                 }
856                 if (*activep)
857                         debug("%.200s line %d: Applying options for %.100s",
858                             filename, linenum, arg2);
859                 /* Avoid garbage check below, as strdelim is done. */
860                 return 0;
861
862         case oEscapeChar:
863                 intptr = &options->escape_char;
864                 arg = strdelim(&s);
865                 if (!arg || *arg == '\0')
866                         fatal("%.200s line %d: Missing argument.", filename, linenum);
867                 if (arg[0] == '^' && arg[2] == 0 &&
868                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
869                         value = (u_char) arg[1] & 31;
870                 else if (strlen(arg) == 1)
871                         value = (u_char) arg[0];
872                 else if (strcmp(arg, "none") == 0)
873                         value = SSH_ESCAPECHAR_NONE;
874                 else {
875                         fatal("%.200s line %d: Bad escape character.",
876                             filename, linenum);
877                         /* NOTREACHED */
878                         value = 0;      /* Avoid compiler warning. */
879                 }
880                 if (*activep && *intptr == -1)
881                         *intptr = value;
882                 break;
883
884         case oAddressFamily:
885                 arg = strdelim(&s);
886                 if (!arg || *arg == '\0')
887                         fatal("%s line %d: missing address family.",
888                             filename, linenum);
889                 intptr = &options->address_family;
890                 if (strcasecmp(arg, "inet") == 0)
891                         value = AF_INET;
892                 else if (strcasecmp(arg, "inet6") == 0)
893                         value = AF_INET6;
894                 else if (strcasecmp(arg, "any") == 0)
895                         value = AF_UNSPEC;
896                 else
897                         fatal("Unsupported AddressFamily \"%s\"", arg);
898                 if (*activep && *intptr == -1)
899                         *intptr = value;
900                 break;
901
902         case oEnableSSHKeysign:
903                 intptr = &options->enable_ssh_keysign;
904                 goto parse_flag;
905
906         case oIdentitiesOnly:
907                 intptr = &options->identities_only;
908                 goto parse_flag;
909
910         case oServerAliveInterval:
911                 intptr = &options->server_alive_interval;
912                 goto parse_time;
913
914         case oServerAliveCountMax:
915                 intptr = &options->server_alive_count_max;
916                 goto parse_int;
917
918         case oSendEnv:
919                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
920                         if (strchr(arg, '=') != NULL)
921                                 fatal("%s line %d: Invalid environment name.",
922                                     filename, linenum);
923                         if (!*activep)
924                                 continue;
925                         if (options->num_send_env >= MAX_SEND_ENV)
926                                 fatal("%s line %d: too many send env.",
927                                     filename, linenum);
928                         options->send_env[options->num_send_env++] =
929                             xstrdup(arg);
930                 }
931                 break;
932
933         case oControlPath:
934                 charptr = &options->control_path;
935                 goto parse_string;
936
937         case oControlMaster:
938                 intptr = &options->control_master;
939                 arg = strdelim(&s);
940                 if (!arg || *arg == '\0')
941                         fatal("%.200s line %d: Missing ControlMaster argument.",
942                             filename, linenum);
943                 value = 0;      /* To avoid compiler warning... */
944                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
945                         value = SSHCTL_MASTER_YES;
946                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
947                         value = SSHCTL_MASTER_NO;
948                 else if (strcmp(arg, "auto") == 0)
949                         value = SSHCTL_MASTER_AUTO;
950                 else if (strcmp(arg, "ask") == 0)
951                         value = SSHCTL_MASTER_ASK;
952                 else if (strcmp(arg, "autoask") == 0)
953                         value = SSHCTL_MASTER_AUTO_ASK;
954                 else
955                         fatal("%.200s line %d: Bad ControlMaster argument.",
956                             filename, linenum);
957                 if (*activep && *intptr == -1)
958                         *intptr = value;
959                 break;
960
961         case oControlPersist:
962                 /* no/false/yes/true, or a time spec */
963                 intptr = &options->control_persist;
964                 arg = strdelim(&s);
965                 if (!arg || *arg == '\0')
966                         fatal("%.200s line %d: Missing ControlPersist"
967                             " argument.", filename, linenum);
968                 value = 0;
969                 value2 = 0;     /* timeout */
970                 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
971                         value = 0;
972                 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
973                         value = 1;
974                 else if ((value2 = convtime(arg)) >= 0)
975                         value = 1;
976                 else
977                         fatal("%.200s line %d: Bad ControlPersist argument.",
978                             filename, linenum);
979                 if (*activep && *intptr == -1) {
980                         *intptr = value;
981                         options->control_persist_timeout = value2;
982                 }
983                 break;
984
985         case oHashKnownHosts:
986                 intptr = &options->hash_known_hosts;
987                 goto parse_flag;
988
989         case oTunnel:
990                 intptr = &options->tun_open;
991                 arg = strdelim(&s);
992                 if (!arg || *arg == '\0')
993                         fatal("%s line %d: Missing yes/point-to-point/"
994                             "ethernet/no argument.", filename, linenum);
995                 value = 0;      /* silence compiler */
996                 if (strcasecmp(arg, "ethernet") == 0)
997                         value = SSH_TUNMODE_ETHERNET;
998                 else if (strcasecmp(arg, "point-to-point") == 0)
999                         value = SSH_TUNMODE_POINTOPOINT;
1000                 else if (strcasecmp(arg, "yes") == 0)
1001                         value = SSH_TUNMODE_DEFAULT;
1002                 else if (strcasecmp(arg, "no") == 0)
1003                         value = SSH_TUNMODE_NO;
1004                 else
1005                         fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1006                             "no argument: %s", filename, linenum, arg);
1007                 if (*activep)
1008                         *intptr = value;
1009                 break;
1010
1011         case oTunnelDevice:
1012                 arg = strdelim(&s);
1013                 if (!arg || *arg == '\0')
1014                         fatal("%.200s line %d: Missing argument.", filename, linenum);
1015                 value = a2tun(arg, &value2);
1016                 if (value == SSH_TUNID_ERR)
1017                         fatal("%.200s line %d: Bad tun device.", filename, linenum);
1018                 if (*activep) {
1019                         options->tun_local = value;
1020                         options->tun_remote = value2;
1021                 }
1022                 break;
1023
1024         case oLocalCommand:
1025                 charptr = &options->local_command;
1026                 goto parse_command;
1027
1028         case oPermitLocalCommand:
1029                 intptr = &options->permit_local_command;
1030                 goto parse_flag;
1031
1032         case oVisualHostKey:
1033                 intptr = &options->visual_host_key;
1034                 goto parse_flag;
1035
1036         case oIPQoS:
1037                 arg = strdelim(&s);
1038                 if ((value = parse_ipqos(arg)) == -1)
1039                         fatal("%s line %d: Bad IPQoS value: %s",
1040                             filename, linenum, arg);
1041                 arg = strdelim(&s);
1042                 if (arg == NULL)
1043                         value2 = value;
1044                 else if ((value2 = parse_ipqos(arg)) == -1)
1045                         fatal("%s line %d: Bad IPQoS value: %s",
1046                             filename, linenum, arg);
1047                 if (*activep) {
1048                         options->ip_qos_interactive = value;
1049                         options->ip_qos_bulk = value2;
1050                 }
1051                 break;
1052
1053         case oUseRoaming:
1054                 intptr = &options->use_roaming;
1055                 goto parse_flag;
1056
1057         case oRequestTTY:
1058                 arg = strdelim(&s);
1059                 if (!arg || *arg == '\0')
1060                         fatal("%s line %d: missing argument.",
1061                             filename, linenum);
1062                 intptr = &options->request_tty;
1063                 if (strcasecmp(arg, "yes") == 0)
1064                         value = REQUEST_TTY_YES;
1065                 else if (strcasecmp(arg, "no") == 0)
1066                         value = REQUEST_TTY_NO;
1067                 else if (strcasecmp(arg, "force") == 0)
1068                         value = REQUEST_TTY_FORCE;
1069                 else if (strcasecmp(arg, "auto") == 0)
1070                         value = REQUEST_TTY_AUTO;
1071                 else
1072                         fatal("Unsupported RequestTTY \"%s\"", arg);
1073                 if (*activep && *intptr == -1)
1074                         *intptr = value;
1075                 break;
1076
1077         case oDeprecated:
1078                 debug("%s line %d: Deprecated option \"%s\"",
1079                     filename, linenum, keyword);
1080                 return 0;
1081
1082         case oUnsupported:
1083                 error("%s line %d: Unsupported option \"%s\"",
1084                     filename, linenum, keyword);
1085                 return 0;
1086
1087         default:
1088                 fatal("process_config_line: Unimplemented opcode %d", opcode);
1089         }
1090
1091         /* Check that there is no garbage at end of line. */
1092         if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1093                 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1094                     filename, linenum, arg);
1095         }
1096         return 0;
1097 }
1098
1099
1100 /*
1101  * Reads the config file and modifies the options accordingly.  Options
1102  * should already be initialized before this call.  This never returns if
1103  * there is an error.  If the file does not exist, this returns 0.
1104  */
1105
1106 int
1107 read_config_file(const char *filename, const char *host, Options *options,
1108     int checkperm)
1109 {
1110         FILE *f;
1111         char line[1024];
1112         int active, linenum;
1113         int bad_options = 0;
1114
1115         if ((f = fopen(filename, "r")) == NULL)
1116                 return 0;
1117
1118         if (checkperm) {
1119                 struct stat sb;
1120
1121                 if (fstat(fileno(f), &sb) == -1)
1122                         fatal("fstat %s: %s", filename, strerror(errno));
1123                 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1124                     (sb.st_mode & 022) != 0))
1125                         fatal("Bad owner or permissions on %s", filename);
1126         }
1127
1128         debug("Reading configuration data %.200s", filename);
1129
1130         /*
1131          * Mark that we are now processing the options.  This flag is turned
1132          * on/off by Host specifications.
1133          */
1134         active = 1;
1135         linenum = 0;
1136         while (fgets(line, sizeof(line), f)) {
1137                 /* Update line number counter. */
1138                 linenum++;
1139                 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
1140                         bad_options++;
1141         }
1142         fclose(f);
1143         if (bad_options > 0)
1144                 fatal("%s: terminating, %d bad configuration options",
1145                     filename, bad_options);
1146         return 1;
1147 }
1148
1149 /*
1150  * Initializes options to special values that indicate that they have not yet
1151  * been set.  Read_config_file will only set options with this value. Options
1152  * are processed in the following order: command line, user config file,
1153  * system config file.  Last, fill_default_options is called.
1154  */
1155
1156 void
1157 initialize_options(Options * options)
1158 {
1159         memset(options, 'X', sizeof(*options));
1160         options->forward_agent = -1;
1161         options->forward_x11 = -1;
1162         options->forward_x11_trusted = -1;
1163         options->forward_x11_timeout = -1;
1164         options->exit_on_forward_failure = -1;
1165         options->xauth_location = NULL;
1166         options->gateway_ports = -1;
1167         options->use_privileged_port = -1;
1168         options->rsa_authentication = -1;
1169         options->pubkey_authentication = -1;
1170         options->challenge_response_authentication = -1;
1171         options->gss_authentication = -1;
1172         options->gss_keyex = -1;
1173         options->gss_deleg_creds = -1;
1174         options->gss_trust_dns = -1;
1175         options->gss_renewal_rekey = -1;
1176         options->gss_client_identity = NULL;
1177         options->gss_server_identity = NULL;
1178         options->password_authentication = -1;
1179         options->kbd_interactive_authentication = -1;
1180         options->kbd_interactive_devices = NULL;
1181         options->rhosts_rsa_authentication = -1;
1182         options->hostbased_authentication = -1;
1183         options->batch_mode = -1;
1184         options->check_host_ip = -1;
1185         options->strict_host_key_checking = -1;
1186         options->compression = -1;
1187         options->tcp_keep_alive = -1;
1188         options->compression_level = -1;
1189         options->port = -1;
1190         options->address_family = -1;
1191         options->connection_attempts = -1;
1192         options->connection_timeout = -1;
1193         options->number_of_password_prompts = -1;
1194         options->cipher = -1;
1195         options->ciphers = NULL;
1196         options->macs = NULL;
1197         options->kex_algorithms = NULL;
1198         options->hostkeyalgorithms = NULL;
1199         options->protocol = SSH_PROTO_UNKNOWN;
1200         options->num_identity_files = 0;
1201         options->hostname = NULL;
1202         options->host_key_alias = NULL;
1203         options->proxy_command = NULL;
1204         options->user = NULL;
1205         options->escape_char = -1;
1206         options->num_system_hostfiles = 0;
1207         options->num_user_hostfiles = 0;
1208         options->local_forwards = NULL;
1209         options->num_local_forwards = 0;
1210         options->remote_forwards = NULL;
1211         options->num_remote_forwards = 0;
1212         options->clear_forwardings = -1;
1213         options->log_level = SYSLOG_LEVEL_NOT_SET;
1214         options->preferred_authentications = NULL;
1215         options->bind_address = NULL;
1216         options->pkcs11_provider = NULL;
1217         options->enable_ssh_keysign = - 1;
1218         options->no_host_authentication_for_localhost = - 1;
1219         options->identities_only = - 1;
1220         options->rekey_limit = - 1;
1221         options->verify_host_key_dns = -1;
1222         options->server_alive_interval = -1;
1223         options->server_alive_count_max = -1;
1224         options->num_send_env = 0;
1225         options->control_path = NULL;
1226         options->control_master = -1;
1227         options->control_persist = -1;
1228         options->control_persist_timeout = 0;
1229         options->hash_known_hosts = -1;
1230         options->tun_open = -1;
1231         options->tun_local = -1;
1232         options->tun_remote = -1;
1233         options->local_command = NULL;
1234         options->permit_local_command = -1;
1235         options->use_roaming = -1;
1236         options->visual_host_key = -1;
1237         options->zero_knowledge_password_authentication = -1;
1238         options->ip_qos_interactive = -1;
1239         options->ip_qos_bulk = -1;
1240         options->request_tty = -1;
1241 }
1242
1243 /*
1244  * Called after processing other sources of option data, this fills those
1245  * options for which no value has been specified with their default values.
1246  */
1247
1248 void
1249 fill_default_options(Options * options)
1250 {
1251         int len;
1252
1253         if (options->forward_agent == -1)
1254                 options->forward_agent = 0;
1255         if (options->forward_x11 == -1)
1256                 options->forward_x11 = 0;
1257         if (options->forward_x11_trusted == -1)
1258                 options->forward_x11_trusted = 0;
1259         if (options->forward_x11_timeout == -1)
1260                 options->forward_x11_timeout = 1200;
1261         if (options->exit_on_forward_failure == -1)
1262                 options->exit_on_forward_failure = 0;
1263         if (options->xauth_location == NULL)
1264                 options->xauth_location = _PATH_XAUTH;
1265         if (options->gateway_ports == -1)
1266                 options->gateway_ports = 0;
1267         if (options->use_privileged_port == -1)
1268                 options->use_privileged_port = 0;
1269         if (options->rsa_authentication == -1)
1270                 options->rsa_authentication = 1;
1271         if (options->pubkey_authentication == -1)
1272                 options->pubkey_authentication = 1;
1273         if (options->challenge_response_authentication == -1)
1274                 options->challenge_response_authentication = 1;
1275         if (options->gss_authentication == -1)
1276                 options->gss_authentication = 0;
1277         if (options->gss_keyex == -1)
1278                 options->gss_keyex = 0;
1279         if (options->gss_deleg_creds == -1)
1280                 options->gss_deleg_creds = 0;
1281         if (options->gss_trust_dns == -1)
1282                 options->gss_trust_dns = 0;
1283         if (options->gss_renewal_rekey == -1)
1284                 options->gss_renewal_rekey = 0;
1285         if (options->password_authentication == -1)
1286                 options->password_authentication = 1;
1287         if (options->kbd_interactive_authentication == -1)
1288                 options->kbd_interactive_authentication = 1;
1289         if (options->rhosts_rsa_authentication == -1)
1290                 options->rhosts_rsa_authentication = 0;
1291         if (options->hostbased_authentication == -1)
1292                 options->hostbased_authentication = 0;
1293         if (options->batch_mode == -1)
1294                 options->batch_mode = 0;
1295         if (options->check_host_ip == -1)
1296                 options->check_host_ip = 1;
1297         if (options->strict_host_key_checking == -1)
1298                 options->strict_host_key_checking = 2;  /* 2 is default */
1299         if (options->compression == -1)
1300                 options->compression = 0;
1301         if (options->tcp_keep_alive == -1)
1302                 options->tcp_keep_alive = 1;
1303         if (options->compression_level == -1)
1304                 options->compression_level = 6;
1305         if (options->port == -1)
1306                 options->port = 0;      /* Filled in ssh_connect. */
1307         if (options->address_family == -1)
1308                 options->address_family = AF_UNSPEC;
1309         if (options->connection_attempts == -1)
1310                 options->connection_attempts = 1;
1311         if (options->number_of_password_prompts == -1)
1312                 options->number_of_password_prompts = 3;
1313         /* Selected in ssh_login(). */
1314         if (options->cipher == -1)
1315                 options->cipher = SSH_CIPHER_NOT_SET;
1316         /* options->ciphers, default set in myproposals.h */
1317         /* options->macs, default set in myproposals.h */
1318         /* options->kex_algorithms, default set in myproposals.h */
1319         /* options->hostkeyalgorithms, default set in myproposals.h */
1320         if (options->protocol == SSH_PROTO_UNKNOWN)
1321                 options->protocol = SSH_PROTO_2;
1322         if (options->num_identity_files == 0) {
1323                 if (options->protocol & SSH_PROTO_1) {
1324                         len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1325                         options->identity_files[options->num_identity_files] =
1326                             xmalloc(len);
1327                         snprintf(options->identity_files[options->num_identity_files++],
1328                             len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1329                 }
1330                 if (options->protocol & SSH_PROTO_2) {
1331                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1332                         options->identity_files[options->num_identity_files] =
1333                             xmalloc(len);
1334                         snprintf(options->identity_files[options->num_identity_files++],
1335                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1336
1337                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1338                         options->identity_files[options->num_identity_files] =
1339                             xmalloc(len);
1340                         snprintf(options->identity_files[options->num_identity_files++],
1341                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1342 #ifdef OPENSSL_HAS_ECC
1343                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
1344                         options->identity_files[options->num_identity_files] =
1345                             xmalloc(len);
1346                         snprintf(options->identity_files[options->num_identity_files++],
1347                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
1348 #endif
1349                 }
1350         }
1351         if (options->escape_char == -1)
1352                 options->escape_char = '~';
1353         if (options->num_system_hostfiles == 0) {
1354                 options->system_hostfiles[options->num_system_hostfiles++] =
1355                     xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1356                 options->system_hostfiles[options->num_system_hostfiles++] =
1357                     xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1358         }
1359         if (options->num_user_hostfiles == 0) {
1360                 options->user_hostfiles[options->num_user_hostfiles++] =
1361                     xstrdup(_PATH_SSH_USER_HOSTFILE);
1362                 options->user_hostfiles[options->num_user_hostfiles++] =
1363                     xstrdup(_PATH_SSH_USER_HOSTFILE2);
1364         }
1365         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1366                 options->log_level = SYSLOG_LEVEL_INFO;
1367         if (options->clear_forwardings == 1)
1368                 clear_forwardings(options);
1369         if (options->no_host_authentication_for_localhost == - 1)
1370                 options->no_host_authentication_for_localhost = 0;
1371         if (options->identities_only == -1)
1372                 options->identities_only = 0;
1373         if (options->enable_ssh_keysign == -1)
1374                 options->enable_ssh_keysign = 0;
1375         if (options->rekey_limit == -1)
1376                 options->rekey_limit = 0;
1377         if (options->verify_host_key_dns == -1)
1378                 options->verify_host_key_dns = 0;
1379         if (options->server_alive_interval == -1)
1380                 options->server_alive_interval = 0;
1381         if (options->server_alive_count_max == -1)
1382                 options->server_alive_count_max = 3;
1383         if (options->control_master == -1)
1384                 options->control_master = 0;
1385         if (options->control_persist == -1) {
1386                 options->control_persist = 0;
1387                 options->control_persist_timeout = 0;
1388         }
1389         if (options->hash_known_hosts == -1)
1390                 options->hash_known_hosts = 0;
1391         if (options->tun_open == -1)
1392                 options->tun_open = SSH_TUNMODE_NO;
1393         if (options->tun_local == -1)
1394                 options->tun_local = SSH_TUNID_ANY;
1395         if (options->tun_remote == -1)
1396                 options->tun_remote = SSH_TUNID_ANY;
1397         if (options->permit_local_command == -1)
1398                 options->permit_local_command = 0;
1399         if (options->use_roaming == -1)
1400                 options->use_roaming = 1;
1401         if (options->visual_host_key == -1)
1402                 options->visual_host_key = 0;
1403         if (options->zero_knowledge_password_authentication == -1)
1404                 options->zero_knowledge_password_authentication = 0;
1405         if (options->ip_qos_interactive == -1)
1406                 options->ip_qos_interactive = IPTOS_LOWDELAY;
1407         if (options->ip_qos_bulk == -1)
1408                 options->ip_qos_bulk = IPTOS_THROUGHPUT;
1409         if (options->request_tty == -1)
1410                 options->request_tty = REQUEST_TTY_AUTO;
1411         /* options->local_command should not be set by default */
1412         /* options->proxy_command should not be set by default */
1413         /* options->user will be set in the main program if appropriate */
1414         /* options->hostname will be set in the main program if appropriate */
1415         /* options->host_key_alias should not be set by default */
1416         /* options->preferred_authentications will be set in ssh */
1417 }
1418
1419 /*
1420  * parse_forward
1421  * parses a string containing a port forwarding specification of the form:
1422  *   dynamicfwd == 0
1423  *      [listenhost:]listenport:connecthost:connectport
1424  *   dynamicfwd == 1
1425  *      [listenhost:]listenport
1426  * returns number of arguments parsed or zero on error
1427  */
1428 int
1429 parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1430 {
1431         int i;
1432         char *p, *cp, *fwdarg[4];
1433
1434         memset(fwd, '\0', sizeof(*fwd));
1435
1436         cp = p = xstrdup(fwdspec);
1437
1438         /* skip leading spaces */
1439         while (isspace(*cp))
1440                 cp++;
1441
1442         for (i = 0; i < 4; ++i)
1443                 if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1444                         break;
1445
1446         /* Check for trailing garbage */
1447         if (cp != NULL)
1448                 i = 0;  /* failure */
1449
1450         switch (i) {
1451         case 1:
1452                 fwd->listen_host = NULL;
1453                 fwd->listen_port = a2port(fwdarg[0]);
1454                 fwd->connect_host = xstrdup("socks");
1455                 break;
1456
1457         case 2:
1458                 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1459                 fwd->listen_port = a2port(fwdarg[1]);
1460                 fwd->connect_host = xstrdup("socks");
1461                 break;
1462
1463         case 3:
1464                 fwd->listen_host = NULL;
1465                 fwd->listen_port = a2port(fwdarg[0]);
1466                 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1467                 fwd->connect_port = a2port(fwdarg[2]);
1468                 break;
1469
1470         case 4:
1471                 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1472                 fwd->listen_port = a2port(fwdarg[1]);
1473                 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1474                 fwd->connect_port = a2port(fwdarg[3]);
1475                 break;
1476         default:
1477                 i = 0; /* failure */
1478         }
1479
1480         xfree(p);
1481
1482         if (dynamicfwd) {
1483                 if (!(i == 1 || i == 2))
1484                         goto fail_free;
1485         } else {
1486                 if (!(i == 3 || i == 4))
1487                         goto fail_free;
1488                 if (fwd->connect_port <= 0)
1489                         goto fail_free;
1490         }
1491
1492         if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1493                 goto fail_free;
1494
1495         if (fwd->connect_host != NULL &&
1496             strlen(fwd->connect_host) >= NI_MAXHOST)
1497                 goto fail_free;
1498         if (fwd->listen_host != NULL &&
1499             strlen(fwd->listen_host) >= NI_MAXHOST)
1500                 goto fail_free;
1501
1502
1503         return (i);
1504
1505  fail_free:
1506         if (fwd->connect_host != NULL) {
1507                 xfree(fwd->connect_host);
1508                 fwd->connect_host = NULL;
1509         }
1510         if (fwd->listen_host != NULL) {
1511                 xfree(fwd->listen_host);
1512                 fwd->listen_host = NULL;
1513         }
1514         return (0);
1515 }