[BACK]Return to readconf.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/readconf.c between version 1.220 and 1.221

version 1.220, 2014/07/15 15:54:14 version 1.221, 2014/10/08 22:20:25
Line 33 
Line 33 
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
 #include <util.h>  #include <util.h>
   #include <vis.h>
   
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "ssh.h"  #include "ssh.h"
Line 48 
Line 49 
 #include "kex.h"  #include "kex.h"
 #include "mac.h"  #include "mac.h"
 #include "uidswap.h"  #include "uidswap.h"
   #include "myproposal.h"
   
 /* Format of the configuration file:  /* Format of the configuration file:
   
Line 127 
Line 129 
         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,          oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
         oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,          oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
         oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,          oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
         oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,          oPubkeyAuthentication,
         oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,          oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
         oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,          oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
         oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,          oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
Line 204 
Line 206 
         { "globalknownhostsfile", oGlobalKnownHostsFile },          { "globalknownhostsfile", oGlobalKnownHostsFile },
         { "globalknownhostsfile2", oDeprecated },          { "globalknownhostsfile2", oDeprecated },
         { "userknownhostsfile", oUserKnownHostsFile },          { "userknownhostsfile", oUserKnownHostsFile },
         { "userknownhostsfile2", oDeprecated },          { "userknownhostsfile2", oDeprecated },
         { "connectionattempts", oConnectionAttempts },          { "connectionattempts", oConnectionAttempts },
         { "batchmode", oBatchMode },          { "batchmode", oBatchMode },
         { "checkhostip", oCheckHostIP },          { "checkhostip", oCheckHostIP },
Line 457 
Line 459 
         if (!WIFEXITED(status)) {          if (!WIFEXITED(status)) {
                 error("command '%.100s' exited abnormally", cmd);                  error("command '%.100s' exited abnormally", cmd);
                 return -1;                  return -1;
         }          }
         debug3("command returned status %d", WEXITSTATUS(status));          debug3("command returned status %d", WEXITSTATUS(status));
         return WEXITSTATUS(status);          return WEXITSTATUS(status);
 }  }
Line 467 
Line 469 
  */   */
 static int  static int
 match_cfg_line(Options *options, char **condition, struct passwd *pw,  match_cfg_line(Options *options, char **condition, struct passwd *pw,
     const char *host_arg, const char *filename, int linenum)      const char *host_arg, const char *original_host, int post_canon,
       const char *filename, int linenum)
 {  {
         char *arg, *attrib, *cmd, *cp = *condition, *host;          char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
         const char *ruser;          const char *ruser;
         int r, port, result = 1, attributes = 0;          int r, port, this_result, result = 1, attributes = 0, negate;
         size_t len;          size_t len;
         char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];          char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
   
Line 488 
Line 491 
         } else          } else
                 host = xstrdup(host_arg);                  host = xstrdup(host_arg);
   
         debug3("checking match for '%s' host %s", cp, host);          debug2("checking match for '%s' host %s originally %s",
         while ((attrib = strdelim(&cp)) && *attrib != '\0') {              cp, host, original_host);
                 attributes++;          while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
                   criteria = NULL;
                   this_result = 1;
                   if ((negate = attrib[0] == '!'))
                           attrib++;
                   /* criteria "all" and "canonical" have no argument */
                 if (strcasecmp(attrib, "all") == 0) {                  if (strcasecmp(attrib, "all") == 0) {
                         if (attributes != 1 ||                          if (attributes > 1 ||
                             ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {                              ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
                                 error("'all' cannot be combined with other "                                  error("%.200s line %d: '%s' cannot be combined "
                                     "Match attributes");                                      "with other Match attributes",
                                       filename, linenum, oattrib);
                                 result = -1;                                  result = -1;
                                 goto out;                                  goto out;
                         }                          }
                         *condition = cp;                          if (result)
                         result = 1;                                  result = negate ? 0 : 1;
                         goto out;                          goto out;
                 }                  }
                   attributes++;
                   if (strcasecmp(attrib, "canonical") == 0) {
                           r = !!post_canon;  /* force bitmask member to boolean */
                           if (r == (negate ? 1 : 0))
                                   this_result = result = 0;
                           debug3("%.200s line %d: %smatched '%s'",
                               filename, linenum,
                               this_result ? "" : "not ", oattrib);
                           continue;
                   }
                   /* All other criteria require an argument */
                 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {                  if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
                         error("Missing Match criteria for %s", attrib);                          error("Missing Match criteria for %s", attrib);
                         result = -1;                          result = -1;
Line 510 
Line 530 
                 }                  }
                 len = strlen(arg);                  len = strlen(arg);
                 if (strcasecmp(attrib, "host") == 0) {                  if (strcasecmp(attrib, "host") == 0) {
                         if (match_hostname(host, arg, len) != 1)                          criteria = xstrdup(host);
                                 result = 0;                          r = match_hostname(host, arg, len) == 1;
                         else                          if (r == (negate ? 1 : 0))
                                 debug("%.200s line %d: matched 'Host %.100s' ",                                  this_result = result = 0;
                                     filename, linenum, host);  
                 } else if (strcasecmp(attrib, "originalhost") == 0) {                  } else if (strcasecmp(attrib, "originalhost") == 0) {
                         if (match_hostname(host_arg, arg, len) != 1)                          criteria = xstrdup(original_host);
                                 result = 0;                          r = match_hostname(original_host, arg, len) == 1;
                         else                          if (r == (negate ? 1 : 0))
                                 debug("%.200s line %d: matched "                                  this_result = result = 0;
                                     "'OriginalHost %.100s' ",  
                                     filename, linenum, host_arg);  
                 } else if (strcasecmp(attrib, "user") == 0) {                  } else if (strcasecmp(attrib, "user") == 0) {
                         if (match_pattern_list(ruser, arg, len, 0) != 1)                          criteria = xstrdup(ruser);
                                 result = 0;                          r = match_pattern_list(ruser, arg, len, 0) == 1;
                         else                          if (r == (negate ? 1 : 0))
                                 debug("%.200s line %d: matched 'User %.100s' ",                                  this_result = result = 0;
                                     filename, linenum, ruser);  
                 } else if (strcasecmp(attrib, "localuser") == 0) {                  } else if (strcasecmp(attrib, "localuser") == 0) {
                         if (match_pattern_list(pw->pw_name, arg, len, 0) != 1)                          criteria = xstrdup(pw->pw_name);
                                 result = 0;                          r = match_pattern_list(pw->pw_name, arg, len, 0) == 1;
                         else                          if (r == (negate ? 1 : 0))
                                 debug("%.200s line %d: matched "                                  this_result = result = 0;
                                     "'LocalUser %.100s' ",  
                                     filename, linenum, pw->pw_name);  
                 } else if (strcasecmp(attrib, "exec") == 0) {                  } else if (strcasecmp(attrib, "exec") == 0) {
                         if (gethostname(thishost, sizeof(thishost)) == -1)                          if (gethostname(thishost, sizeof(thishost)) == -1)
                                 fatal("gethostname: %s", strerror(errno));                                  fatal("gethostname: %s", strerror(errno));
Line 547 
Line 561 
                             "d", pw->pw_dir,                              "d", pw->pw_dir,
                             "h", host,                              "h", host,
                             "l", thishost,                              "l", thishost,
                             "n", host_arg,                              "n", original_host,
                             "p", portstr,                              "p", portstr,
                             "r", ruser,                              "r", ruser,
                             "u", pw->pw_name,                              "u", pw->pw_name,
                             (char *)NULL);                              (char *)NULL);
                         if (result != 1) {                          if (result != 1) {
                                 /* skip execution if prior predicate failed */                                  /* skip execution if prior predicate failed */
                                 debug("%.200s line %d: skipped exec \"%.100s\"",                                  debug3("%.200s line %d: skipped exec "
                                     filename, linenum, cmd);                                      "\"%.100s\"", filename, linenum, cmd);
                         } else {                                  free(cmd);
                                 r = execute_in_shell(cmd);                                  continue;
                                 if (r == -1) {  
                                         fatal("%.200s line %d: match exec "  
                                             "'%.100s' error", filename,  
                                             linenum, cmd);  
                                 } else if (r == 0) {  
                                         debug("%.200s line %d: matched "  
                                             "'exec \"%.100s\"'", filename,  
                                             linenum, cmd);  
                                 } else {  
                                         debug("%.200s line %d: no match "  
                                             "'exec \"%.100s\"'", filename,  
                                             linenum, cmd);  
                                         result = 0;  
                                 }  
                         }                          }
                           r = execute_in_shell(cmd);
                           if (r == -1) {
                                   fatal("%.200s line %d: match exec "
                                       "'%.100s' error", filename,
                                       linenum, cmd);
                           }
                           criteria = xstrdup(cmd);
                         free(cmd);                          free(cmd);
                           /* Force exit status to boolean */
                           r = r == 0;
                           if (r == (negate ? 1 : 0))
                                   this_result = result = 0;
                 } else {                  } else {
                         error("Unsupported Match attribute %s", attrib);                          error("Unsupported Match attribute %s", attrib);
                         result = -1;                          result = -1;
                         goto out;                          goto out;
                 }                  }
                   debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
                       filename, linenum, this_result ? "": "not ",
                       oattrib, criteria);
                   free(criteria);
         }          }
         if (attributes == 0) {          if (attributes == 0) {
                 error("One or more attributes required for Match");                  error("One or more attributes required for Match");
                 result = -1;                  result = -1;
                 goto out;                  goto out;
         }          }
         debug3("match %sfound", result ? "" : "not ");  
         *condition = cp;  
  out:   out:
           if (result != -1)
                   debug2("match %sfound", result ? "" : "not ");
           *condition = cp;
         free(host);          free(host);
         return result;          return result;
 }  }
Line 710 
Line 726 
 #define WHITESPACE " \t\r\n"  #define WHITESPACE " \t\r\n"
 int  int
 process_config_line(Options *options, struct passwd *pw, const char *host,  process_config_line(Options *options, struct passwd *pw, const char *host,
     char *line, const char *filename, int linenum, int *activep, int userconfig)      const char *original_host, char *line, const char *filename,
       int linenum, int *activep, int flags)
 {  {
         char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;          char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
         char **cpptr, fwdarg[256];          char **cpptr, fwdarg[256];
Line 766 
Line 783 
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing time value.",                          fatal("%s line %d: missing time value.",
                             filename, linenum);                              filename, linenum);
                 if ((value = convtime(arg)) == -1)                  if (strcmp(arg, "none") == 0)
                           value = -1;
                   else if ((value = convtime(arg)) == -1)
                         fatal("%s line %d: invalid time value.",                          fatal("%s line %d: invalid time value.",
                             filename, linenum);                              filename, linenum);
                 if (*activep && *intptr == -1)                  if (*activep && *intptr == -1)
Line 803 
Line 822 
         case oForwardX11Trusted:          case oForwardX11Trusted:
                 intptr = &options->forward_x11_trusted;                  intptr = &options->forward_x11_trusted;
                 goto parse_flag;                  goto parse_flag;
   
         case oForwardX11Timeout:          case oForwardX11Timeout:
                 intptr = &options->forward_x11_timeout;                  intptr = &options->forward_x11_timeout;
                 goto parse_time;                  goto parse_time;
Line 938 
Line 957 
                         if (*intptr >= SSH_MAX_IDENTITY_FILES)                          if (*intptr >= SSH_MAX_IDENTITY_FILES)
                                 fatal("%.200s line %d: Too many identity files specified (max %d).",                                  fatal("%.200s line %d: Too many identity files specified (max %d).",
                                     filename, linenum, SSH_MAX_IDENTITY_FILES);                                      filename, linenum, SSH_MAX_IDENTITY_FILES);
                         add_identity_file(options, NULL, arg, userconfig);                          add_identity_file(options, NULL,
                               arg, flags & SSHCONF_USERCONF);
                 }                  }
                 break;                  break;
   
Line 1186 
Line 1206 
                 if (cmdline)                  if (cmdline)
                         fatal("Host directive not supported as a command-line "                          fatal("Host directive not supported as a command-line "
                             "option");                              "option");
                 value = match_cfg_line(options, &s, pw, host,                  value = match_cfg_line(options, &s, pw, host, original_host,
                     filename, linenum);                      flags & SSHCONF_POSTCANON, filename, linenum);
                 if (value < 0)                  if (value < 0)
                         fatal("%.200s line %d: Bad Match condition", filename,                          fatal("%.200s line %d: Bad Match condition", filename,
                             linenum);                              linenum);
Line 1435 
Line 1455 
                 return 0;                  return 0;
   
         default:          default:
                 fatal("process_config_line: Unimplemented opcode %d", opcode);                  fatal("%s: Unimplemented opcode %d", __func__, opcode);
         }          }
   
         /* Check that there is no garbage at end of line. */          /* Check that there is no garbage at end of line. */
Line 1455 
Line 1475 
   
 int  int
 read_config_file(const char *filename, struct passwd *pw, const char *host,  read_config_file(const char *filename, struct passwd *pw, const char *host,
     Options *options, int flags)      const char *original_host, Options *options, int flags)
 {  {
         FILE *f;          FILE *f;
         char line[1024];          char line[1024];
Line 1486 
Line 1506 
         while (fgets(line, sizeof(line), f)) {          while (fgets(line, sizeof(line), f)) {
                 /* Update line number counter. */                  /* Update line number counter. */
                 linenum++;                  linenum++;
                 if (process_config_line(options, pw, host, line, filename,                  if (process_config_line(options, pw, host, original_host,
                     linenum, &active, flags & SSHCONF_USERCONF) != 0)                      line, filename, linenum, &active, flags) != 0)
                         bad_options++;                          bad_options++;
         }          }
         fclose(f);          fclose(f);
Line 1997 
Line 2017 
         free(fwd->listen_path);          free(fwd->listen_path);
         fwd->listen_path = NULL;          fwd->listen_path = NULL;
         return (0);          return (0);
   }
   
   /* XXX the following is a near-vebatim copy from servconf.c; refactor */
   static const char *
   fmt_multistate_int(int val, const struct multistate *m)
   {
           u_int i;
   
           for (i = 0; m[i].key != NULL; i++) {
                   if (m[i].value == val)
                           return m[i].key;
           }
           return "UNKNOWN";
   }
   
   static const char *
   fmt_intarg(OpCodes code, int val)
   {
           if (val == -1)
                   return "unset";
           switch (code) {
           case oAddressFamily:
                   return fmt_multistate_int(val, multistate_addressfamily);
           case oVerifyHostKeyDNS:
           case oStrictHostKeyChecking:
                   return fmt_multistate_int(val, multistate_yesnoask);
           case oControlMaster:
                   return fmt_multistate_int(val, multistate_controlmaster);
           case oTunnel:
                   return fmt_multistate_int(val, multistate_tunnel);
           case oRequestTTY:
                   return fmt_multistate_int(val, multistate_requesttty);
           case oCanonicalizeHostname:
                   return fmt_multistate_int(val, multistate_canonicalizehostname);
           case oProtocol:
                   switch (val) {
                   case SSH_PROTO_1:
                           return "1";
                   case SSH_PROTO_2:
                           return "2";
                   case (SSH_PROTO_1|SSH_PROTO_2):
                           return "2,1";
                   default:
                           return "UNKNOWN";
                   }
           default:
                   switch (val) {
                   case 0:
                           return "no";
                   case 1:
                           return "yes";
                   default:
                           return "UNKNOWN";
                   }
           }
   }
   
   static const char *
   lookup_opcode_name(OpCodes code)
   {
           u_int i;
   
           for (i = 0; keywords[i].name != NULL; i++)
                   if (keywords[i].opcode == code)
                           return(keywords[i].name);
           return "UNKNOWN";
   }
   
   static void
   dump_cfg_int(OpCodes code, int val)
   {
           printf("%s %d\n", lookup_opcode_name(code), val);
   }
   
   static void
   dump_cfg_fmtint(OpCodes code, int val)
   {
           printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
   }
   
   static void
   dump_cfg_string(OpCodes code, const char *val)
   {
           if (val == NULL)
                   return;
           printf("%s %s\n", lookup_opcode_name(code), val);
   }
   
   static void
   dump_cfg_strarray(OpCodes code, u_int count, char **vals)
   {
           u_int i;
   
           for (i = 0; i < count; i++)
                   printf("%s %s\n", lookup_opcode_name(code), vals[i]);
   }
   
   static void
   dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
   {
           u_int i;
   
           printf("%s", lookup_opcode_name(code));
           for (i = 0; i < count; i++)
                   printf(" %s",  vals[i]);
           printf("\n");
   }
   
   static void
   dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
   {
           const struct Forward *fwd;
           u_int i;
   
           /* oDynamicForward */
           for (i = 0; i < count; i++) {
                   fwd = &fwds[i];
                   if (code == oDynamicForward &&
                       strcmp(fwd->connect_host, "socks") != 0)
                           continue;
                   if (code == oLocalForward &&
                       strcmp(fwd->connect_host, "socks") == 0)
                           continue;
                   printf("%s", lookup_opcode_name(code));
                   if (fwd->listen_port == PORT_STREAMLOCAL)
                           printf(" %s", fwd->listen_path);
                   else if (fwd->listen_host == NULL)
                           printf(" %d", fwd->listen_port);
                   else {
                           printf(" [%s]:%d",
                               fwd->listen_host, fwd->listen_port);
                   }
                   if (code != oDynamicForward) {
                           if (fwd->connect_port == PORT_STREAMLOCAL)
                                   printf(" %s", fwd->connect_path);
                           else if (fwd->connect_host == NULL)
                                   printf(" %d", fwd->connect_port);
                           else {
                                   printf(" [%s]:%d",
                                       fwd->connect_host, fwd->connect_port);
                           }
                   }
                   printf("\n");
           }
   }
   
   void
   dump_client_config(Options *o, const char *host)
   {
           int i;
           char vbuf[5];
   
           /* Most interesting options first: user, host, port */
           dump_cfg_string(oUser, o->user);
           dump_cfg_string(oHostName, host);
           dump_cfg_int(oPort, o->port);
   
           /* Flag options */
           dump_cfg_fmtint(oAddressFamily, o->address_family);
           dump_cfg_fmtint(oBatchMode, o->batch_mode);
           dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
           dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
           dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
           dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
           dump_cfg_fmtint(oCompression, o->compression);
           dump_cfg_fmtint(oControlMaster, o->control_master);
           dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
           dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
           dump_cfg_fmtint(oForwardAgent, o->forward_agent);
           dump_cfg_fmtint(oForwardX11, o->forward_x11);
           dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
           dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
   #ifdef GSSAPI
           dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
           dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
   #endif /* GSSAPI */
           dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
           dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
           dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
           dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
           dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
           dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
           dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
           dump_cfg_fmtint(oProtocol, o->protocol);
           dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
           dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
           dump_cfg_fmtint(oRequestTTY, o->request_tty);
           dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication);
           dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication);
           dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
           dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
           dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
           dump_cfg_fmtint(oTunnel, o->tun_open);
           dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);
           dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
           dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
   
           /* Integer options */
           dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
           dump_cfg_int(oCompressionLevel, o->compression_level);
           dump_cfg_int(oConnectionAttempts, o->connection_attempts);
           dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
           dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
           dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
           dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
   
           /* String options */
           dump_cfg_string(oBindAddress, o->bind_address);
           dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
           dump_cfg_string(oControlPath, o->control_path);
           dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
           dump_cfg_string(oHostKeyAlias, o->host_key_alias);
           dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
           dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
           dump_cfg_string(oLocalCommand, o->local_command);
           dump_cfg_string(oLogLevel, log_level_name(o->log_level));
           dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
           dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
           dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
           dump_cfg_string(oProxyCommand, o->proxy_command);
           dump_cfg_string(oXAuthLocation, o->xauth_location);
   
           dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
           dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
           dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
   
           /* String array options */
           dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
           dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
           dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
           dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
           dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
   
           /* Special cases */
   
           /* oConnectTimeout */
           if (o->connection_timeout == -1)
                   printf("connecttimeout none\n");
           else
                   dump_cfg_int(oConnectTimeout, o->connection_timeout);
   
           /* oTunnelDevice */
           printf("tunneldevice");
           if (o->tun_local == SSH_TUNID_ANY)
                   printf(" any");
           else
                   printf(" %d", o->tun_local);
           if (o->tun_remote == SSH_TUNID_ANY)
                   printf(":any");
           else
                   printf(":%d", o->tun_remote);
           printf("\n");
   
           /* oCanonicalizePermittedCNAMEs */
           if ( o->num_permitted_cnames > 0) {
                   printf("canonicalizePermittedcnames");
                   for (i = 0; i < o->num_permitted_cnames; i++) {
                           printf(" %s:%s", o->permitted_cnames[i].source_list,
                               o->permitted_cnames[i].target_list);
                   }
                   printf("\n");
           }
   
           /* oCipher */
           if (o->cipher != SSH_CIPHER_NOT_SET)
                   printf("Cipher %s\n", cipher_name(o->cipher));
   
           /* oControlPersist */
           if (o->control_persist == 0 || o->control_persist_timeout == 0)
                   dump_cfg_fmtint(oControlPersist, o->control_persist);
           else
                   dump_cfg_int(oControlPersist, o->control_persist_timeout);
   
           /* oEscapeChar */
           if (o->escape_char == SSH_ESCAPECHAR_NONE)
                   printf("escapechar none\n");
           else {
                   vis(vbuf, o->escape_char, VIS_WHITE, 0);
                   printf("escapechar %s\n", vbuf);
           }
   
           /* oIPQoS */
           printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
           printf("%s\n", iptos2str(o->ip_qos_bulk));
   
           /* oRekeyLimit */
           printf("rekeylimit %lld %d\n",
               (long long)o->rekey_limit, o->rekey_interval);
   
           /* oStreamLocalBindMask */
           printf("streamlocalbindmask 0%o\n",
               o->fwd_opts.streamlocal_bind_mask);
 }  }

Legend:
Removed from v.1.220  
changed lines
  Added in v.1.221