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

Diff for /src/usr.bin/ssh/auth2-pubkey.c between version 1.30 and 1.31

version 1.30, 2011/09/25 05:44:47 version 1.31, 2012/10/30 21:29:54
Line 26 
Line 26 
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/stat.h>  #include <sys/stat.h>
   #include <sys/wait.h>
   
   #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
   #include <paths.h>
 #include <pwd.h>  #include <pwd.h>
   #include <signal.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdarg.h>  #include <stdarg.h>
 #include <string.h>  #include <string.h>
Line 239 
Line 243 
                         if (strcmp(cp, cert->principals[i]) == 0) {                          if (strcmp(cp, cert->principals[i]) == 0) {
                                 debug3("matched principal \"%.100s\" "                                  debug3("matched principal \"%.100s\" "
                                     "from file \"%s\" on line %lu",                                      "from file \"%s\" on line %lu",
                                     cert->principals[i], file, linenum);                                      cert->principals[i], file, linenum);
                                 if (auth_parse_options(pw, line_opts,                                  if (auth_parse_options(pw, line_opts,
                                     file, linenum) != 1)                                      file, linenum) != 1)
                                         continue;                                          continue;
Line 252 
Line 256 
         fclose(f);          fclose(f);
         restore_uid();          restore_uid();
         return 0;          return 0;
 }  }
   
 /* return 1 if user allows given key */  /*
    * Checks whether key is allowed in authorized_keys-format file,
    * returns 1 if the key is allowed or 0 otherwise.
    */
 static int  static int
 user_key_allowed2(struct passwd *pw, Key *key, char *file)  check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
 {  {
         char line[SSH_MAX_PUBKEY_BYTES];          char line[SSH_MAX_PUBKEY_BYTES];
         const char *reason;          const char *reason;
         int found_key = 0;          int found_key = 0;
         FILE *f;  
         u_long linenum = 0;          u_long linenum = 0;
         Key *found;          Key *found;
         char *fp;          char *fp;
   
         /* Temporarily use the user's uid. */  
         temporarily_use_uid(pw);  
   
         debug("trying public key file %s", file);  
         f = auth_openkeyfile(file, pw, options.strict_modes);  
   
         if (!f) {  
                 restore_uid();  
                 return 0;  
         }  
   
         found_key = 0;          found_key = 0;
         found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);          found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
   
Line 369 
Line 364 
                         break;                          break;
                 }                  }
         }          }
         restore_uid();  
         fclose(f);  
         key_free(found);          key_free(found);
         if (!found_key)          if (!found_key)
                 debug2("key not found");                  debug2("key not found");
Line 432 
Line 425 
         return ret;          return ret;
 }  }
   
 /* check whether given key is in .ssh/authorized_keys* */  /*
    * Checks whether key is allowed in file.
    * returns 1 if the key is allowed or 0 otherwise.
    */
   static int
   user_key_allowed2(struct passwd *pw, Key *key, char *file)
   {
           FILE *f;
           int found_key = 0;
   
           /* Temporarily use the user's uid. */
           temporarily_use_uid(pw);
   
           debug("trying public key file %s", file);
           if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
                   found_key = check_authkeys_file(f, file, key, pw);
                   fclose(f);
           }
   
           restore_uid();
           return found_key;
   }
   
   /*
    * Checks whether key is allowed in output of command.
    * returns 1 if the key is allowed or 0 otherwise.
    */
   static int
   user_key_command_allowed2(struct passwd *user_pw, Key *key)
   {
           FILE *f;
           int ok, found_key = 0;
           struct passwd *pw;
           struct stat st;
           int status, devnull, p[2], i;
           pid_t pid;
           char errmsg[512];
   
           if (options.authorized_keys_command == NULL ||
               options.authorized_keys_command[0] != '/')
                   return 0;
   
           /* If no user specified to run commands the default to target user */
           if (options.authorized_keys_command_user == NULL)
                   pw = user_pw;
           else {
                   pw = getpwnam(options.authorized_keys_command_user);
                   if (pw == NULL) {
                           error("AuthorizedKeyCommandUser \"%s\" not found: %s",
                               options.authorized_keys_command, strerror(errno));
                           return 0;
                   }
           }
   
           temporarily_use_uid(pw);
   
           if (stat(options.authorized_keys_command, &st) < 0) {
                   error("Could not stat AuthorizedKeysCommand \"%s\": %s",
                       options.authorized_keys_command, strerror(errno));
                   goto out;
           }
           if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
               errmsg, sizeof(errmsg)) != 0) {
                   error("Unsafe AuthorizedKeysCommand: %s", errmsg);
                   goto out;
           }
   
           if (pipe(p) != 0) {
                   error("%s: pipe: %s", __func__, strerror(errno));
                   goto out;
           }
   
           debug3("Running AuthorizedKeysCommand: \"%s\" as \"%s\"",
               options.authorized_keys_command, pw->pw_name);
   
           /*
            * Don't want to call this in the child, where it can fatal() and
            * run cleanup_exit() code.
            */
           restore_uid();
   
           switch ((pid = fork())) {
           case -1: /* error */
                   error("%s: fork: %s", __func__, strerror(errno));
                   close(p[0]);
                   close(p[1]);
                   return 0;
           case 0: /* child */
                   for (i = 0; i < NSIG; i++)
                           signal(i, SIG_DFL);
   
                   /* Don't use permanently_set_uid() here to avoid fatal() */
                   if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
                           error("setresgid %u: %s", (u_int)pw->pw_gid,
                               strerror(errno));
                           _exit(1);
                   }
                   if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
                           error("setresuid %u: %s", (u_int)pw->pw_uid,
                               strerror(errno));
                           _exit(1);
                   }
   
                   close(p[0]);
                   if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
                           error("%s: open %s: %s", __func__, _PATH_DEVNULL,
                               strerror(errno));
                           _exit(1);
                   }
                   if (dup2(devnull, STDIN_FILENO) == -1 ||
                       dup2(p[1], STDOUT_FILENO) == -1 ||
                       dup2(devnull, STDERR_FILENO) == -1) {
                           error("%s: dup2: %s", __func__, strerror(errno));
                           _exit(1);
                   }
                   closefrom(STDERR_FILENO + 1);
   
                   execl(options.authorized_keys_command,
                       options.authorized_keys_command, pw->pw_name, NULL);
   
                   error("AuthorizedKeysCommand %s exec failed: %s",
                       options.authorized_keys_command, strerror(errno));
                   _exit(127);
           default: /* parent */
                   break;
           }
   
           temporarily_use_uid(pw);
   
           close(p[1]);
           if ((f = fdopen(p[0], "r")) == NULL) {
                   error("%s: fdopen: %s", __func__, strerror(errno));
                   close(p[0]);
                   /* Don't leave zombie child */
                   kill(pid, SIGTERM);
                   while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
                           ;
                   goto out;
           }
           ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
           fclose(f);
   
           while (waitpid(pid, &status, 0) == -1) {
                   if (errno != EINTR) {
                           error("%s: waitpid: %s", __func__, strerror(errno));
                           goto out;
                   }
           }
           if (WIFSIGNALED(status)) {
                   error("AuthorizedKeysCommand %s exited on signal %d",
                       options.authorized_keys_command, WTERMSIG(status));
                   goto out;
           } else if (WEXITSTATUS(status) != 0) {
                   error("AuthorizedKeysCommand %s returned status %d",
                       options.authorized_keys_command, WEXITSTATUS(status));
                   goto out;
           }
           found_key = ok;
    out:
           restore_uid();
           return found_key;
   }
   
   /*
    * Check whether key authenticates and authorises the user.
    */
 int  int
 user_key_allowed(struct passwd *pw, Key *key)  user_key_allowed(struct passwd *pw, Key *key)
 {  {
Line 448 
Line 606 
         if (success)          if (success)
                 return success;                  return success;
   
           success = user_key_command_allowed2(pw, key);
           if (success > 0)
                   return success;
   
         for (i = 0; !success && i < options.num_authkeys_files; i++) {          for (i = 0; !success && i < options.num_authkeys_files; i++) {
   
                   if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
                           continue;
                 file = expand_authorized_keys(                  file = expand_authorized_keys(
                     options.authorized_keys_files[i], pw);                      options.authorized_keys_files[i], pw);
   
                 success = user_key_allowed2(pw, key, file);                  success = user_key_allowed2(pw, key, file);
                 xfree(file);                  xfree(file);
         }          }

Legend:
Removed from v.1.30  
changed lines
  Added in v.1.31