]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/readconf.c
This commit was generated by cvs2svn to compensate for changes in r58551,
[FreeBSD/FreeBSD.git] / crypto / openssh / readconf.c
1 /*
2  * 
3  * readconf.c
4  * 
5  * Author: Tatu Ylonen <ylo@cs.hut.fi>
6  * 
7  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8  *                    All rights reserved
9  * 
10  * Created: Sat Apr 22 00:03:10 1995 ylo
11  * 
12  * Functions for reading the configuration files.
13  * 
14  * $FreeBSD$
15  */
16
17 #include "includes.h"
18 RCSID("$Id: readconf.c,v 1.23 2000/02/28 19:51:58 markus Exp $");
19
20 #include "ssh.h"
21 #include "cipher.h"
22 #include "readconf.h"
23 #include "xmalloc.h"
24
25 /* Format of the configuration file:
26
27    # Configuration data is parsed as follows:
28    #  1. command line options
29    #  2. user-specific file
30    #  3. system-wide file
31    # Any configuration value is only changed the first time it is set.
32    # Thus, host-specific definitions should be at the beginning of the
33    # configuration file, and defaults at the end.
34
35    # Host-specific declarations.  These may override anything above.  A single
36    # host may match multiple declarations; these are processed in the order
37    # that they are given in.
38
39    Host *.ngs.fi ngs.fi
40      FallBackToRsh no
41
42    Host fake.com
43      HostName another.host.name.real.org
44      User blaah
45      Port 34289
46      ForwardX11 no
47      ForwardAgent no
48
49    Host books.com
50      RemoteForward 9999 shadows.cs.hut.fi:9999
51      Cipher 3des
52
53    Host fascist.blob.com
54      Port 23123
55      User tylonen
56      RhostsAuthentication no
57      PasswordAuthentication no
58
59    Host puukko.hut.fi
60      User t35124p
61      ProxyCommand ssh-proxy %h %p
62
63    Host *.fr
64      UseRsh yes
65
66    Host *.su
67      Cipher none
68      PasswordAuthentication no
69
70    # Defaults for various options
71    Host *
72      ForwardAgent no
73      ForwardX11 yes
74      RhostsAuthentication yes
75      PasswordAuthentication yes
76      RSAAuthentication yes
77      RhostsRSAAuthentication yes
78      FallBackToRsh no
79      UseRsh no
80      StrictHostKeyChecking yes
81      KeepAlives no
82      IdentityFile ~/.ssh/identity
83      Port 22
84      EscapeChar ~
85
86 */
87
88 /* Keyword tokens. */
89
90 typedef enum {
91         oBadOption,
92         oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
93         oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
94         oSkeyAuthentication,
95 #ifdef KRB4
96         oKrb4Authentication,
97 #endif /* KRB4 */
98 #ifdef KRB5
99         oKrb5Authentication, oKrb5TgtPassing,
100 #endif /* KRB5 */
101 #ifdef AFS
102         oKrb4TgtPassing, oAFSTokenPassing,
103 #endif
104         oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
105         oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
106         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
107         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
108         oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
109         oUsePrivilegedPort, oLogLevel
110 } OpCodes;
111
112 /* Textual representations of the tokens. */
113
114 static struct {
115         const char *name;
116         OpCodes opcode;
117 } keywords[] = {
118         { "forwardagent", oForwardAgent },
119         { "forwardx11", oForwardX11 },
120         { "gatewayports", oGatewayPorts },
121         { "useprivilegedport", oUsePrivilegedPort },
122         { "rhostsauthentication", oRhostsAuthentication },
123         { "passwordauthentication", oPasswordAuthentication },
124         { "rsaauthentication", oRSAAuthentication },
125         { "skeyauthentication", oSkeyAuthentication },
126 #ifdef KRB4
127         { "kerberos4authentication", oKrb4Authentication },
128 #endif /* KRB4 */
129 #ifdef KRB5
130         { "kerberos5authentication", oKrb5Authentication },
131         { "kerberos5tgtpassing", oKrb5TgtPassing },
132 #endif /* KRB5 */
133 #ifdef AFS
134         { "kerberos4tgtpassing", oKrb4TgtPassing },
135         { "afstokenpassing", oAFSTokenPassing },
136 #endif
137         { "fallbacktorsh", oFallBackToRsh },
138         { "usersh", oUseRsh },
139         { "identityfile", oIdentityFile },
140         { "hostname", oHostName },
141         { "proxycommand", oProxyCommand },
142         { "port", oPort },
143         { "cipher", oCipher },
144         { "remoteforward", oRemoteForward },
145         { "localforward", oLocalForward },
146         { "user", oUser },
147         { "host", oHost },
148         { "escapechar", oEscapeChar },
149         { "rhostsrsaauthentication", oRhostsRSAAuthentication },
150         { "globalknownhostsfile", oGlobalKnownHostsFile },
151         { "userknownhostsfile", oUserKnownHostsFile },
152         { "connectionattempts", oConnectionAttempts },
153         { "batchmode", oBatchMode },
154         { "checkhostip", oCheckHostIP },
155         { "stricthostkeychecking", oStrictHostKeyChecking },
156         { "compression", oCompression },
157         { "compressionlevel", oCompressionLevel },
158         { "keepalive", oKeepAlives },
159         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
160         { "tisauthentication", oTISAuthentication },
161         { "loglevel", oLogLevel },
162         { NULL, 0 }
163 };
164
165 /* Characters considered whitespace in strtok calls. */
166 #define WHITESPACE " \t\r\n"
167
168
169 /*
170  * Adds a local TCP/IP port forward to options.  Never returns if there is an
171  * error.
172  */
173
174 void 
175 add_local_forward(Options *options, u_short port, const char *host,
176                   u_short host_port)
177 {
178         Forward *fwd;
179         extern uid_t original_real_uid;
180         if (port < IPPORT_RESERVED && original_real_uid != 0)
181                 fatal("Privileged ports can only be forwarded by root.\n");
182         if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
183                 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
184         fwd = &options->local_forwards[options->num_local_forwards++];
185         fwd->port = port;
186         fwd->host = xstrdup(host);
187         fwd->host_port = host_port;
188 }
189
190 /*
191  * Adds a remote TCP/IP port forward to options.  Never returns if there is
192  * an error.
193  */
194
195 void 
196 add_remote_forward(Options *options, u_short port, const char *host,
197                    u_short host_port)
198 {
199         Forward *fwd;
200         if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
201                 fatal("Too many remote forwards (max %d).",
202                       SSH_MAX_FORWARDS_PER_DIRECTION);
203         fwd = &options->remote_forwards[options->num_remote_forwards++];
204         fwd->port = port;
205         fwd->host = xstrdup(host);
206         fwd->host_port = host_port;
207 }
208
209 /*
210  * Returns the number of the token pointed to by cp of length len. Never
211  * returns if the token is not known.
212  */
213
214 static OpCodes 
215 parse_token(const char *cp, const char *filename, int linenum)
216 {
217         unsigned int i;
218
219         for (i = 0; keywords[i].name; i++)
220                 if (strcasecmp(cp, keywords[i].name) == 0)
221                         return keywords[i].opcode;
222
223         fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
224                 filename, linenum, cp);
225         return oBadOption;
226 }
227
228 /*
229  * Processes a single option line as used in the configuration files. This
230  * only sets those values that have not already been set.
231  */
232
233 int
234 process_config_line(Options *options, const char *host,
235                     char *line, const char *filename, int linenum,
236                     int *activep)
237 {
238         char buf[256], *cp, *string, **charptr, *cp2;
239         int opcode, *intptr, value;
240         u_short fwd_port, fwd_host_port;
241
242         /* Skip leading whitespace. */
243         cp = line + strspn(line, WHITESPACE);
244         if (!*cp || *cp == '\n' || *cp == '#')
245                 return 0;
246
247         /* Get the keyword. (Each line is supposed to begin with a keyword). */
248         cp = strtok(cp, WHITESPACE);
249         opcode = parse_token(cp, filename, linenum);
250
251         switch (opcode) {
252         case oBadOption:
253                 /* don't panic, but count bad options */
254                 return -1;
255                 /* NOTREACHED */
256         case oForwardAgent:
257                 intptr = &options->forward_agent;
258 parse_flag:
259                 cp = strtok(NULL, WHITESPACE);
260                 if (!cp)
261                         fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
262                 value = 0;      /* To avoid compiler warning... */
263                 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
264                         value = 1;
265                 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
266                         value = 0;
267                 else
268                         fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
269                 if (*activep && *intptr == -1)
270                         *intptr = value;
271                 break;
272
273         case oForwardX11:
274                 intptr = &options->forward_x11;
275                 goto parse_flag;
276
277         case oGatewayPorts:
278                 intptr = &options->gateway_ports;
279                 goto parse_flag;
280
281         case oUsePrivilegedPort:
282                 intptr = &options->use_privileged_port;
283                 goto parse_flag;
284
285         case oRhostsAuthentication:
286                 intptr = &options->rhosts_authentication;
287                 goto parse_flag;
288
289         case oPasswordAuthentication:
290                 intptr = &options->password_authentication;
291                 goto parse_flag;
292
293         case oRSAAuthentication:
294                 intptr = &options->rsa_authentication;
295                 goto parse_flag;
296
297         case oRhostsRSAAuthentication:
298                 intptr = &options->rhosts_rsa_authentication;
299                 goto parse_flag;
300
301         case oTISAuthentication:
302                 /* fallthrough, there is no difference on the client side */
303         case oSkeyAuthentication:
304                 intptr = &options->skey_authentication;
305                 goto parse_flag;
306
307 #ifdef KRB4
308         case oKrb4Authentication:
309                 intptr = &options->krb4_authentication;
310                 goto parse_flag;
311 #endif /* KRB4 */
312
313 #ifdef KRB5
314         case oKrb5Authentication:
315                 intptr = &options->krb5_authentication;
316                 goto parse_flag;
317
318         case oKrb5TgtPassing:
319                 intptr = &options->krb5_tgt_passing;
320                 goto parse_flag;
321 #endif /* KRB5 */
322
323 #ifdef AFS
324         case oKrb4TgtPassing:
325                 intptr = &options->krb4_tgt_passing;
326                 goto parse_flag;
327
328         case oAFSTokenPassing:
329                 intptr = &options->afs_token_passing;
330                 goto parse_flag;
331 #endif
332
333         case oFallBackToRsh:
334                 intptr = &options->fallback_to_rsh;
335                 goto parse_flag;
336
337         case oUseRsh:
338                 intptr = &options->use_rsh;
339                 goto parse_flag;
340
341         case oBatchMode:
342                 intptr = &options->batch_mode;
343                 goto parse_flag;
344
345         case oCheckHostIP:
346                 intptr = &options->check_host_ip;
347                 goto parse_flag;
348
349         case oStrictHostKeyChecking:
350                 intptr = &options->strict_host_key_checking;
351                 cp = strtok(NULL, WHITESPACE);
352                 if (!cp)
353                         fatal("%.200s line %d: Missing yes/no argument.",
354                               filename, linenum);
355                 value = 0;      /* To avoid compiler warning... */
356                 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
357                         value = 1;
358                 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
359                         value = 0;
360                 else if (strcmp(cp, "ask") == 0)
361                         value = 2;
362                 else
363                         fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
364                 if (*activep && *intptr == -1)
365                         *intptr = value;
366                 break;
367
368         case oCompression:
369                 intptr = &options->compression;
370                 goto parse_flag;
371
372         case oKeepAlives:
373                 intptr = &options->keepalives;
374                 goto parse_flag;
375
376         case oNumberOfPasswordPrompts:
377                 intptr = &options->number_of_password_prompts;
378                 goto parse_int;
379
380         case oCompressionLevel:
381                 intptr = &options->compression_level;
382                 goto parse_int;
383
384         case oIdentityFile:
385                 cp = strtok(NULL, WHITESPACE);
386                 if (!cp)
387                         fatal("%.200s line %d: Missing argument.", filename, linenum);
388                 if (*activep) {
389                         if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
390                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
391                                       filename, linenum, SSH_MAX_IDENTITY_FILES);
392                         options->identity_files[options->num_identity_files++] = xstrdup(cp);
393                 }
394                 break;
395
396         case oUser:
397                 charptr = &options->user;
398 parse_string:
399                 cp = strtok(NULL, WHITESPACE);
400                 if (!cp)
401                         fatal("%.200s line %d: Missing argument.", filename, linenum);
402                 if (*activep && *charptr == NULL)
403                         *charptr = xstrdup(cp);
404                 break;
405
406         case oGlobalKnownHostsFile:
407                 charptr = &options->system_hostfile;
408                 goto parse_string;
409
410         case oUserKnownHostsFile:
411                 charptr = &options->user_hostfile;
412                 goto parse_string;
413
414         case oHostName:
415                 charptr = &options->hostname;
416                 goto parse_string;
417
418         case oProxyCommand:
419                 charptr = &options->proxy_command;
420                 string = xstrdup("");
421                 while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
422                         string = xrealloc(string, strlen(string) + strlen(cp) + 2);
423                         strcat(string, " ");
424                         strcat(string, cp);
425                 }
426                 if (*activep && *charptr == NULL)
427                         *charptr = string;
428                 else
429                         xfree(string);
430                 return 0;
431
432         case oPort:
433                 intptr = &options->port;
434 parse_int:
435                 cp = strtok(NULL, WHITESPACE);
436                 if (!cp)
437                         fatal("%.200s line %d: Missing argument.", filename, linenum);
438                 if (cp[0] < '0' || cp[0] > '9')
439                         fatal("%.200s line %d: Bad number.", filename, linenum);
440
441                 /* Octal, decimal, or hex format? */
442                 value = strtol(cp, &cp2, 0);
443                 if (cp == cp2)
444                         fatal("%.200s line %d: Bad number.", filename, linenum);
445                 if (*activep && *intptr == -1)
446                         *intptr = value;
447                 break;
448
449         case oConnectionAttempts:
450                 intptr = &options->connection_attempts;
451                 goto parse_int;
452
453         case oCipher:
454                 intptr = &options->cipher;
455                 cp = strtok(NULL, WHITESPACE);
456                 value = cipher_number(cp);
457                 if (value == -1)
458                         fatal("%.200s line %d: Bad cipher '%s'.",
459                               filename, linenum, cp ? cp : "<NONE>");
460                 if (*activep && *intptr == -1)
461                         *intptr = value;
462                 break;
463
464         case oLogLevel:
465                 intptr = (int *) &options->log_level;
466                 cp = strtok(NULL, WHITESPACE);
467                 value = log_level_number(cp);
468                 if (value == (LogLevel) - 1)
469                         fatal("%.200s line %d: unsupported log level '%s'\n",
470                               filename, linenum, cp ? cp : "<NONE>");
471                 if (*activep && (LogLevel) * intptr == -1)
472                         *intptr = (LogLevel) value;
473                 break;
474
475         case oRemoteForward:
476                 cp = strtok(NULL, WHITESPACE);
477                 if (!cp)
478                         fatal("%.200s line %d: Missing argument.", filename, linenum);
479                 if (cp[0] < '0' || cp[0] > '9')
480                         fatal("%.200s line %d: Badly formatted port number.",
481                               filename, linenum);
482                 fwd_port = atoi(cp);
483                 cp = strtok(NULL, WHITESPACE);
484                 if (!cp)
485                         fatal("%.200s line %d: Missing second argument.",
486                               filename, linenum);
487                 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
488                         fatal("%.200s line %d: Badly formatted host:port.",
489                               filename, linenum);
490                 if (*activep)
491                         add_remote_forward(options, fwd_port, buf, fwd_host_port);
492                 break;
493
494         case oLocalForward:
495                 cp = strtok(NULL, WHITESPACE);
496                 if (!cp)
497                         fatal("%.200s line %d: Missing argument.", filename, linenum);
498                 if (cp[0] < '0' || cp[0] > '9')
499                         fatal("%.200s line %d: Badly formatted port number.",
500                               filename, linenum);
501                 fwd_port = atoi(cp);
502                 cp = strtok(NULL, WHITESPACE);
503                 if (!cp)
504                         fatal("%.200s line %d: Missing second argument.",
505                               filename, linenum);
506                 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
507                         fatal("%.200s line %d: Badly formatted host:port.",
508                               filename, linenum);
509                 if (*activep)
510                         add_local_forward(options, fwd_port, buf, fwd_host_port);
511                 break;
512
513         case oHost:
514                 *activep = 0;
515                 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
516                         if (match_pattern(host, cp)) {
517                                 debug("Applying options for %.100s", cp);
518                                 *activep = 1;
519                                 break;
520                         }
521                 /* Avoid garbage check below, as strtok already returned NULL. */
522                 return 0;
523
524         case oEscapeChar:
525                 intptr = &options->escape_char;
526                 cp = strtok(NULL, WHITESPACE);
527                 if (!cp)
528                         fatal("%.200s line %d: Missing argument.", filename, linenum);
529                 if (cp[0] == '^' && cp[2] == 0 &&
530                     (unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128)
531                         value = (unsigned char) cp[1] & 31;
532                 else if (strlen(cp) == 1)
533                         value = (unsigned char) cp[0];
534                 else if (strcmp(cp, "none") == 0)
535                         value = -2;
536                 else {
537                         fatal("%.200s line %d: Bad escape character.",
538                               filename, linenum);
539                         /* NOTREACHED */
540                         value = 0;      /* Avoid compiler warning. */
541                 }
542                 if (*activep && *intptr == -1)
543                         *intptr = value;
544                 break;
545
546         default:
547                 fatal("process_config_line: Unimplemented opcode %d", opcode);
548         }
549
550         /* Check that there is no garbage at end of line. */
551         if (strtok(NULL, WHITESPACE) != NULL)
552                 fatal("%.200s line %d: garbage at end of line.",
553                       filename, linenum);
554         return 0;
555 }
556
557
558 /*
559  * Reads the config file and modifies the options accordingly.  Options
560  * should already be initialized before this call.  This never returns if
561  * there is an error.  If the file does not exist, this returns immediately.
562  */
563
564 void 
565 read_config_file(const char *filename, const char *host, Options *options)
566 {
567         FILE *f;
568         char line[1024];
569         int active, linenum;
570         int bad_options = 0;
571
572         /* Open the file. */
573         f = fopen(filename, "r");
574         if (!f)
575                 return;
576
577         debug("Reading configuration data %.200s", filename);
578
579         /*
580          * Mark that we are now processing the options.  This flag is turned
581          * on/off by Host specifications.
582          */
583         active = 1;
584         linenum = 0;
585         while (fgets(line, sizeof(line), f)) {
586                 /* Update line number counter. */
587                 linenum++;
588                 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
589                         bad_options++;
590         }
591         fclose(f);
592         if (bad_options > 0)
593                 fatal("%s: terminating, %d bad configuration options\n",
594                       filename, bad_options);
595 }
596
597 /*
598  * Initializes options to special values that indicate that they have not yet
599  * been set.  Read_config_file will only set options with this value. Options
600  * are processed in the following order: command line, user config file,
601  * system config file.  Last, fill_default_options is called.
602  */
603
604 void 
605 initialize_options(Options * options)
606 {
607         memset(options, 'X', sizeof(*options));
608         options->forward_agent = -1;
609         options->forward_x11 = -1;
610         options->gateway_ports = -1;
611         options->use_privileged_port = -1;
612         options->rhosts_authentication = -1;
613         options->rsa_authentication = -1;
614         options->skey_authentication = -1;
615 #ifdef KRB4
616         options->krb4_authentication = -1;
617 #endif
618 #ifdef KRB5
619         options->krb5_authentication = -1;
620         options->krb5_tgt_passing = -1;
621 #endif /* KRB5 */
622 #ifdef AFS
623         options->krb4_tgt_passing = -1;
624         options->afs_token_passing = -1;
625 #endif
626         options->password_authentication = -1;
627         options->rhosts_rsa_authentication = -1;
628         options->fallback_to_rsh = -1;
629         options->use_rsh = -1;
630         options->batch_mode = -1;
631         options->check_host_ip = -1;
632         options->strict_host_key_checking = -1;
633         options->compression = -1;
634         options->keepalives = -1;
635         options->compression_level = -1;
636         options->port = -1;
637         options->connection_attempts = -1;
638         options->number_of_password_prompts = -1;
639         options->cipher = -1;
640         options->num_identity_files = 0;
641         options->hostname = NULL;
642         options->proxy_command = NULL;
643         options->user = NULL;
644         options->escape_char = -1;
645         options->system_hostfile = NULL;
646         options->user_hostfile = NULL;
647         options->num_local_forwards = 0;
648         options->num_remote_forwards = 0;
649         options->log_level = (LogLevel) - 1;
650 }
651
652 /*
653  * Called after processing other sources of option data, this fills those
654  * options for which no value has been specified with their default values.
655  */
656
657 void 
658 fill_default_options(Options * options)
659 {
660         if (options->forward_agent == -1)
661                 options->forward_agent = 1;
662         if (options->forward_x11 == -1)
663                 options->forward_x11 = 0;
664         if (options->gateway_ports == -1)
665                 options->gateway_ports = 0;
666         if (options->use_privileged_port == -1)
667                 options->use_privileged_port = 1;
668         if (options->rhosts_authentication == -1)
669                 options->rhosts_authentication = 1;
670         if (options->rsa_authentication == -1)
671                 options->rsa_authentication = 1;
672         if (options->skey_authentication == -1)
673                 options->skey_authentication = 0;
674 #ifdef KRB4
675         if (options->krb4_authentication == -1)
676                 options->krb4_authentication = 1;
677 #endif /* KRB4 */
678 #ifdef KRB5
679         if (options->krb5_authentication == -1)
680                 options->krb5_authentication = 1;
681         if (options->krb5_tgt_passing == -1)
682                 options->krb5_tgt_passing = 1;
683 #endif /* KRB5 */
684 #ifdef AFS
685         if (options->krb4_tgt_passing == -1)
686                 options->krb4_tgt_passing = 1;
687         if (options->afs_token_passing == -1)
688                 options->afs_token_passing = 1;
689 #endif /* AFS */
690         if (options->password_authentication == -1)
691                 options->password_authentication = 1;
692         if (options->rhosts_rsa_authentication == -1)
693                 options->rhosts_rsa_authentication = 1;
694         if (options->fallback_to_rsh == -1)
695                 options->fallback_to_rsh = 1;
696         if (options->use_rsh == -1)
697                 options->use_rsh = 0;
698         if (options->batch_mode == -1)
699                 options->batch_mode = 0;
700         if (options->check_host_ip == -1)
701                 options->check_host_ip = 0;
702         if (options->strict_host_key_checking == -1)
703                 options->strict_host_key_checking = 2;  /* 2 is default */
704         if (options->compression == -1)
705                 options->compression = 0;
706         if (options->keepalives == -1)
707                 options->keepalives = 1;
708         if (options->compression_level == -1)
709                 options->compression_level = 6;
710         if (options->port == -1)
711                 options->port = 0;      /* Filled in ssh_connect. */
712         if (options->connection_attempts == -1)
713                 options->connection_attempts = 4;
714         if (options->number_of_password_prompts == -1)
715                 options->number_of_password_prompts = 3;
716         /* Selected in ssh_login(). */
717         if (options->cipher == -1)
718                 options->cipher = SSH_CIPHER_NOT_SET;
719         if (options->num_identity_files == 0) {
720                 options->identity_files[0] =
721                         xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
722                 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
723                 options->num_identity_files = 1;
724         }
725         if (options->escape_char == -1)
726                 options->escape_char = '~';
727         if (options->system_hostfile == NULL)
728                 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
729         if (options->user_hostfile == NULL)
730                 options->user_hostfile = SSH_USER_HOSTFILE;
731         if (options->log_level == (LogLevel) - 1)
732                 options->log_level = SYSLOG_LEVEL_INFO;
733         /* options->proxy_command should not be set by default */
734         /* options->user will be set in the main program if appropriate */
735         /* options->hostname will be set in the main program if appropriate */
736 }