[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.205 and 1.206

version 1.205, 2013/08/20 00:11:37 version 1.206, 2013/10/14 22:22:02
Line 15 
Line 15 
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/socket.h>  #include <sys/socket.h>
   #include <sys/wait.h>
   
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netinet/in_systm.h>  #include <netinet/in_systm.h>
Line 22 
Line 23 
   
 #include <ctype.h>  #include <ctype.h>
 #include <errno.h>  #include <errno.h>
   #include <fcntl.h>
 #include <netdb.h>  #include <netdb.h>
   #include <paths.h>
   #include <pwd.h>
 #include <signal.h>  #include <signal.h>
 #include <stdio.h>  #include <stdio.h>
 #include <string.h>  #include <string.h>
Line 42 
Line 46 
 #include "buffer.h"  #include "buffer.h"
 #include "kex.h"  #include "kex.h"
 #include "mac.h"  #include "mac.h"
   #include "uidswap.h"
   
 /* Format of the configuration file:  /* Format of the configuration file:
   
Line 110 
Line 115 
   
 typedef enum {  typedef enum {
         oBadOption,          oBadOption,
           oHost, oMatch,
         oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,          oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
         oGatewayPorts, oExitOnForwardFailure,          oGatewayPorts, oExitOnForwardFailure,
         oPasswordAuthentication, oRSAAuthentication,          oPasswordAuthentication, oRSAAuthentication,
         oChallengeResponseAuthentication, oXAuthLocation,          oChallengeResponseAuthentication, oXAuthLocation,
         oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,          oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
         oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,          oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,          oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,          oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
         oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,          oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
Line 189 
Line 195 
         { "localforward", oLocalForward },          { "localforward", oLocalForward },
         { "user", oUser },          { "user", oUser },
         { "host", oHost },          { "host", oHost },
           { "match", oMatch },
         { "escapechar", oEscapeChar },          { "escapechar", oEscapeChar },
         { "globalknownhostsfile", oGlobalKnownHostsFile },          { "globalknownhostsfile", oGlobalKnownHostsFile },
         { "globalknownhostsfile2", oDeprecated },          { "globalknownhostsfile2", oDeprecated },
Line 343 
Line 350 
         options->identity_files[options->num_identity_files++] = path;          options->identity_files[options->num_identity_files++] = path;
 }  }
   
   int
   default_ssh_port(void)
   {
           static int port;
           struct servent *sp;
   
           if (port == 0) {
                   sp = getservbyname(SSH_SERVICE_NAME, "tcp");
                   port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
           }
           return port;
   }
   
 /*  /*
  * Returns the number of the token pointed to by cp or oBadOption.   * Execute a command in a shell.
    * Return its exit status or -1 on abnormal exit.
  */   */
   static int
   execute_in_shell(const char *cmd)
   {
           char *shell, *command_string;
           pid_t pid;
           int devnull, status;
           extern uid_t original_real_uid;
   
           if ((shell = getenv("SHELL")) == NULL)
                   shell = _PATH_BSHELL;
   
           /*
            * Use "exec" to avoid "sh -c" processes on some platforms
            * (e.g. Solaris)
            */
           xasprintf(&command_string, "exec %s", cmd);
   
           /* Need this to redirect subprocess stdin/out */
           if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
                   fatal("open(/dev/null): %s", strerror(errno));
   
           debug("Executing command: '%.500s'", cmd);
   
           /* Fork and execute the command. */
           if ((pid = fork()) == 0) {
                   char *argv[4];
   
                   /* Child.  Permanently give up superuser privileges. */
                   permanently_drop_suid(original_real_uid);
   
                   /* Redirect child stdin and stdout. Leave stderr */
                   if (dup2(devnull, STDIN_FILENO) == -1)
                           fatal("dup2: %s", strerror(errno));
                   if (dup2(devnull, STDOUT_FILENO) == -1)
                           fatal("dup2: %s", strerror(errno));
                   if (devnull > STDERR_FILENO)
                           close(devnull);
                   closefrom(STDERR_FILENO + 1);
   
                   argv[0] = shell;
                   argv[1] = "-c";
                   argv[2] = command_string;
                   argv[3] = NULL;
   
                   execv(argv[0], argv);
                   error("Unable to execute '%.100s': %s", cmd, strerror(errno));
                   /* Die with signal to make this error apparent to parent. */
                   signal(SIGTERM, SIG_DFL);
                   kill(getpid(), SIGTERM);
                   _exit(1);
           }
           /* Parent. */
           if (pid < 0)
                   fatal("%s: fork: %.100s", __func__, strerror(errno));
   
           close(devnull);
           free(command_string);
   
           while (waitpid(pid, &status, 0) == -1) {
                   if (errno != EINTR && errno != EAGAIN)
                           fatal("%s: waitpid: %s", __func__, strerror(errno));
           }
           if (!WIFEXITED(status)) {
                   error("command '%.100s' exited abnormally", cmd);
                   return -1;
           }
           debug3("command returned status %d", WEXITSTATUS(status));
           return WEXITSTATUS(status);
   }
   
   /*
    * Parse and execute a Match directive.
    */
   static int
   match_cfg_line(Options *options, char **condition, struct passwd *pw,
       const char *host_arg, const char *filename, int linenum)
   {
           char *arg, *attrib, *cmd, *cp = *condition;
           const char *ruser, *host;
           int r, port, result = 1;
           size_t len;
           char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
   
           /*
            * Configuration is likely to be incomplete at this point so we
            * must be prepared to use default values.
            */
           port = options->port <= 0 ? default_ssh_port() : options->port;
           ruser = options->user == NULL ? pw->pw_name : options->user;
           host = options->hostname == NULL ? host_arg : options->hostname;
   
           debug3("checking match for '%s' host %s", cp, host);
           while ((attrib = strdelim(&cp)) && *attrib != '\0') {
                   if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
                           error("Missing Match criteria for %s", attrib);
                           return -1;
                   }
                   len = strlen(arg);
                   if (strcasecmp(attrib, "host") == 0) {
                           if (match_hostname(host, arg, len) != 1)
                                   result = 0;
                           else
                                   debug("%.200s line %d: matched 'Host %.100s' ",
                                       filename, linenum, host);
                   } else if (strcasecmp(attrib, "originalhost") == 0) {
                           if (match_hostname(host_arg, arg, len) != 1)
                                   result = 0;
                           else
                                   debug("%.200s line %d: matched "
                                       "'OriginalHost %.100s' ",
                                       filename, linenum, host_arg);
                   } else if (strcasecmp(attrib, "user") == 0) {
                           if (match_pattern_list(ruser, arg, len, 0) != 1)
                                   result = 0;
                           else
                                   debug("%.200s line %d: matched 'User %.100s' ",
                                       filename, linenum, ruser);
                   } else if (strcasecmp(attrib, "localuser") == 0) {
                           if (match_pattern_list(pw->pw_name, arg, len, 0) != 1)
                                   result = 0;
                           else
                                   debug("%.200s line %d: matched "
                                       "'LocalUser %.100s' ",
                                       filename, linenum, pw->pw_name);
                   } else if (strcasecmp(attrib, "command") == 0) {
                           if (gethostname(thishost, sizeof(thishost)) == -1)
                                   fatal("gethostname: %s", strerror(errno));
                           strlcpy(shorthost, thishost, sizeof(shorthost));
                           shorthost[strcspn(thishost, ".")] = '\0';
                           snprintf(portstr, sizeof(portstr), "%d", port);
   
                           cmd = percent_expand(arg,
                               "L", shorthost,
                               "d", pw->pw_dir,
                               "h", host,
                               "l", thishost,
                               "n", host_arg,
                               "p", portstr,
                               "r", ruser,
                               "u", pw->pw_name,
                               (char *)NULL);
                           r = execute_in_shell(cmd);
                           if (r == -1) {
                                   fatal("%.200s line %d: match command '%.100s' "
                                       "error", filename, linenum, cmd);
                           } else if (r == 0) {
                                   debug("%.200s line %d: matched "
                                       "'Command \"%.100s\"' ",
                                       filename, linenum, cmd);
                           } else
                                   result = 0;
                           free(cmd);
                   } else {
                           error("Unsupported Match attribute %s", attrib);
                           return -1;
                   }
           }
           debug3("match %sfound", result ? "" : "not ");
           *condition = cp;
           return result;
   }
   
   /*
    * Returns the number of the token pointed to by cp or oBadOption.
    */
 static OpCodes  static OpCodes
 parse_token(const char *cp, const char *filename, int linenum,  parse_token(const char *cp, const char *filename, int linenum,
     const char *ignored_unknown)      const char *ignored_unknown)
Line 369 
Line 554 
  * only sets those values that have not already been set.   * only sets those values that have not already been set.
  */   */
 #define WHITESPACE " \t\r\n"  #define WHITESPACE " \t\r\n"
   
 int  int
 process_config_line(Options *options, const char *host,  process_config_line(Options *options, struct passwd *pw, const char *host,
                     char *line, const char *filename, int linenum,      char *line, const char *filename, int linenum, int *activep, int userconfig)
                     int *activep, int userconfig)  
 {  {
         char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;          char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
         char **cpptr, fwdarg[256];          char **cpptr, fwdarg[256];
         u_int i, *uintptr, max_entries = 0;          u_int i, *uintptr, max_entries = 0;
         int negated, opcode, *intptr, value, value2;          int negated, opcode, *intptr, value, value2, cmdline = 0;
         LogLevel *log_level_ptr;          LogLevel *log_level_ptr;
         long long val64;          long long val64;
         size_t len;          size_t len;
         Forward fwd;          Forward fwd;
   
           if (activep == NULL) { /* We are processing a command line directive */
                   cmdline = 1;
                   activep = &cmdline;
           }
   
         /* Strip trailing whitespace */          /* Strip trailing whitespace */
         for (len = strlen(line) - 1; len > 0; len--) {          for (len = strlen(line) - 1; len > 0; len--) {
                 if (strchr(WHITESPACE, line[len]) == NULL)                  if (strchr(WHITESPACE, line[len]) == NULL)
Line 822 
Line 1010 
                 goto parse_flag;                  goto parse_flag;
   
         case oHost:          case oHost:
                   if (cmdline)
                           fatal("Host directive not supported as a command-line "
                               "option");
                 *activep = 0;                  *activep = 0;
                 arg2 = NULL;                  arg2 = NULL;
                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {                  while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
Line 848 
Line 1039 
                 /* Avoid garbage check below, as strdelim is done. */                  /* Avoid garbage check below, as strdelim is done. */
                 return 0;                  return 0;
   
           case oMatch:
                   if (cmdline)
                           fatal("Host directive not supported as a command-line "
                               "option");
                   value = match_cfg_line(options, &s, pw, host,
                       filename, linenum);
                   if (value < 0)
                           fatal("%.200s line %d: Bad Match condition", filename,
                               linenum);
                   *activep = value;
                   break;
   
         case oEscapeChar:          case oEscapeChar:
                 intptr = &options->escape_char;                  intptr = &options->escape_char;
                 arg = strdelim(&s);                  arg = strdelim(&s);
Line 1101 
Line 1304 
  */   */
   
 int  int
 read_config_file(const char *filename, const char *host, Options *options,  read_config_file(const char *filename, struct passwd *pw, const char *host,
     int flags)      Options *options, int flags)
 {  {
         FILE *f;          FILE *f;
         char line[1024];          char line[1024];
Line 1133 
Line 1336 
         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, host, line, filename, linenum,                  if (process_config_line(options, pw, host, line, filename,
                     &active, flags & SSHCONF_USERCONF) != 0)                      linenum, &active, flags & SSHCONF_USERCONF) != 0)
                         bad_options++;                          bad_options++;
         }          }
         fclose(f);          fclose(f);

Legend:
Removed from v.1.205  
changed lines
  Added in v.1.206