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

Diff for /src/usr.bin/ssh/ssh-keygen.c between version 1.255 and 1.256

version 1.255, 2015/01/18 13:22:28 version 1.256, 2015/01/18 21:49:42
Line 1012 
Line 1012 
                 printf("\n");                  printf("\n");
 }  }
   
 static void  struct known_hosts_ctx {
 printhost(FILE *f, const char *name, struct sshkey *public,          FILE *out;
     int ca, int revoked, int hash)          const char *host;
           int has_unhashed, found_key, inplace, invalid;
   };
   
   static int
   known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
 {  {
         if (print_fingerprint) {          struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
                 enum sshkey_fp_rep rep;          char *hashed, *cp, *hosts, *ohosts;
                 int fptype;          int has_wild = l->hosts && strcspn(l->hosts, "*?!") != strlen(l->hosts);
                 char *fp, *ra;  
   
                 fptype = print_bubblebabble ?          /* Retain invalid lines when hashing, but mark file as invalid. */
                     SSH_DIGEST_SHA1 : fingerprint_hash;          if (l->status == HKF_STATUS_INVALID) {
                 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;                  ctx->invalid = 1;
                 fp = sshkey_fingerprint(public, fptype, rep);                  fprintf(stderr, "%s:%ld: invalid line\n", l->path, l->linenum);
                 ra = sshkey_fingerprint(public, fingerprint_hash,                  fprintf(ctx->out, "%s\n", l->line);
                     SSH_FP_RANDOMART);                  return 0;
                 printf("%u %s %s (%s)\n", sshkey_size(public), fp, name,          }
                     sshkey_type(public));  
                 if (log_level >= SYSLOG_LEVEL_VERBOSE)  
                         printf("%s\n", ra);  
                 free(ra);  
                 free(fp);  
         } else {  
                 int r;  
   
                 if (hash && (name = host_hash(name, NULL, 0)) == NULL)          /*
            * Don't hash hosts already already hashed, with wildcard characters
            * or a CA/revocation marker.
            */
           if (l->was_hashed || has_wild || l->marker != MRK_NONE) {
                   fprintf(ctx->out, "%s\n", l->line);
                   if (has_wild && !find_host) {
                           fprintf(stderr, "%s:%ld: ignoring host name "
                               "with wildcard: %.64s\n", l->path,
                               l->linenum, l->hosts);
                           ctx->has_unhashed = 1;
                   }
                   return 0;
           }
           /*
            * Split any comma-separated hostnames from the host list,
            * hash and store separately.
            */
           ohosts = hosts = xstrdup(l->hosts);
           while ((cp = strsep(&hosts, ",")) != NULL && *cp != '\0') {
                   if ((hashed = host_hash(cp, NULL, 0)) == NULL)
                         fatal("hash_host failed");                          fatal("hash_host failed");
                 fprintf(f, "%s%s%s ", ca ? CA_MARKER " " : "",                  fprintf(ctx->out, "%s %s\n", hashed, l->rawkey);
                     revoked ? REVOKE_MARKER " " : "" , name);                  ctx->has_unhashed = 1;
                 if ((r = sshkey_write(public, f)) != 0)  
                         fatal("key_write failed: %s", ssh_err(r));  
                 fprintf(f, "\n");  
         }          }
           free(ohosts);
           return 0;
 }  }
   
   static int
   known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
   {
           struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
   
           if (l->status == HKF_STATUS_HOST_MATCHED) {
                   if (delete_host) {
                           if (l->marker != MRK_NONE) {
                                   /* Don't remove CA and revocation lines */
                                   fprintf(ctx->out, "%s\n", l->line);
                           } else {
                                   /*
                                    * Hostname matches and has no CA/revoke
                                    * marker, delete it by *not* writing the
                                    * line to ctx->out.
                                    */
                                   ctx->found_key = 1;
                                   if (!quiet)
                                           printf("# Host %s found: line %ld\n",
                                               ctx->host, l->linenum);
                           }
                           return 0;
                   } else if (find_host) {
                           ctx->found_key = 1;
                           if (!quiet) {
                                   printf("# Host %s found: line %ld %s\n",
                                       ctx->host,
                                       l->linenum, l->marker == MRK_CA ? "CA" :
                                       (l->marker == MRK_REVOKE ? "REVOKED" : ""));
                           }
                           if (hash_hosts)
                                   known_hosts_hash(l, ctx);
                           else
                                   fprintf(ctx->out, "%s\n", l->line);
                           return 0;
                   }
           } else if (delete_host) {
                   /* Retain non-matching hosts when deleting */
                   if (l->status == HKF_STATUS_INVALID) {
                           ctx->invalid = 1;
                           fprintf(stderr, "%s:%ld: invalid line\n",
                               l->path, l->linenum);
                   }
                   fprintf(ctx->out, "%s\n", l->line);
           }
           return 0;
   }
   
 static void  static void
 do_known_hosts(struct passwd *pw, const char *name)  do_known_hosts(struct passwd *pw, const char *name)
 {  {
         FILE *in, *out = stdout;          char *cp, tmp[MAXPATHLEN], old[MAXPATHLEN];
         struct sshkey *pub;          int r, fd, oerrno;
         char *cp, *cp2, *kp, *kp2;          struct known_hosts_ctx ctx;
         char line[16*1024], tmp[PATH_MAX], old[PATH_MAX];  
         int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;  
         int r, ca, revoked;  
         int found_key = 0;  
   
         if (!have_identity) {          if (!have_identity) {
                 cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);                  cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
Line 1065 
Line 1125 
                 free(cp);                  free(cp);
                 have_identity = 1;                  have_identity = 1;
         }          }
         if ((in = fopen(identity_file, "r")) == NULL)  
                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));  
   
         /* XXX this code is a mess; refactor -djm */          memset(&ctx, 0, sizeof(ctx));
           ctx.out = stdout;
           ctx.host = name;
   
         /*          /*
          * Find hosts goes to stdout, hash and deletions happen in-place           * Find hosts goes to stdout, hash and deletions happen in-place
          * A corner case is ssh-keygen -HF foo, which should go to stdout           * A corner case is ssh-keygen -HF foo, which should go to stdout
Line 1080 
Line 1141 
                     strlcat(old, ".old", sizeof(old)) >= sizeof(old))                      strlcat(old, ".old", sizeof(old)) >= sizeof(old))
                         fatal("known_hosts path too long");                          fatal("known_hosts path too long");
                 umask(077);                  umask(077);
                 if ((c = mkstemp(tmp)) == -1)                  if ((fd = mkstemp(tmp)) == -1)
                         fatal("mkstemp: %s", strerror(errno));                          fatal("mkstemp: %s", strerror(errno));
                 if ((out = fdopen(c, "w")) == NULL) {                  if ((ctx.out = fdopen(fd, "w")) == NULL) {
                         c = errno;                          oerrno = errno;
                         unlink(tmp);                          unlink(tmp);
                         fatal("fdopen: %s", strerror(c));                          fatal("fdopen: %s", strerror(oerrno));
                 }                  }
                 inplace = 1;                  ctx.inplace = 1;
         }          }
   
         while (fgets(line, sizeof(line), in)) {          /* XXX support identity_file == "-" for stdin */
                 if ((cp = strchr(line, '\n')) == NULL) {          if ((r = hostkeys_foreach(identity_file,
                         error("line %d too long: %.40s...", num + 1, line);              hash_hosts ? known_hosts_hash : known_hosts_find_delete, &ctx,
                         skip = 1;              name, find_host ? HKF_WANT_MATCH_HOST : 0)) != 0)
                         invalid = 1;                  fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
                         continue;  
                 }  
                 num++;  
                 if (skip) {  
                         skip = 0;  
                         continue;  
                 }  
                 *cp = '\0';  
   
                 /* Skip leading whitespace, empty and comment lines. */          if (ctx.inplace)
                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)                  fclose(ctx.out);
                         ;  
                 if (!*cp || *cp == '\n' || *cp == '#') {  
                         if (inplace)  
                                 fprintf(out, "%s\n", cp);  
                         continue;  
                 }  
                 /* Check whether this is a CA key or revocation marker */  
                 if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 &&  
                     (cp[sizeof(CA_MARKER) - 1] == ' ' ||  
                     cp[sizeof(CA_MARKER) - 1] == '\t')) {  
                         ca = 1;  
                         cp += sizeof(CA_MARKER);  
                 } else  
                         ca = 0;  
                 if (strncasecmp(cp, REVOKE_MARKER,  
                     sizeof(REVOKE_MARKER) - 1) == 0 &&  
                     (cp[sizeof(REVOKE_MARKER) - 1] == ' ' ||  
                     cp[sizeof(REVOKE_MARKER) - 1] == '\t')) {  
                         revoked = 1;  
                         cp += sizeof(REVOKE_MARKER);  
                 } else  
                         revoked = 0;  
   
                 /* Find the end of the host name portion. */          if (ctx.invalid) {
                 for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)  
                         ;  
   
                 if (*kp == '\0' || *(kp + 1) == '\0') {  
                         error("line %d missing key: %.40s...",  
                             num, line);  
                         invalid = 1;  
                         continue;  
                 }  
                 *kp++ = '\0';  
                 kp2 = kp;  
   
                 if ((pub = sshkey_new(KEY_RSA1)) == NULL)  
                         fatal("sshkey_new failed");  
                 if ((r = sshkey_read(pub, &kp)) != 0) {  
                         kp = kp2;  
                         sshkey_free(pub);  
                         if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)  
                                 fatal("sshkey_new failed");  
                         if ((r = sshkey_read(pub, &kp)) != 0) {  
                                 error("line %d invalid key: %.40s...",  
                                     num, line);  
                                 sshkey_free(pub);  
                                 invalid = 1;  
                                 continue;  
                         }  
                 }  
   
                 if (*cp == HASH_DELIM) {  
                         if (find_host || delete_host) {  
                                 cp2 = host_hash(name, cp, strlen(cp));  
                                 if (cp2 == NULL) {  
                                         error("line %d: invalid hashed "  
                                             "name: %.64s...", num, line);  
                                         invalid = 1;  
                                         continue;  
                                 }  
                                 c = (strcmp(cp2, cp) == 0);  
                                 if (find_host && c) {  
                                         if (!quiet)  
                                                 printf("# Host %s found: "  
                                                     "line %d type %s%s\n", name,  
                                                     num, sshkey_type(pub),  
                                                     ca ? " (CA key)" :  
                                                     revoked? " (revoked)" : "");  
                                         printhost(out, cp, pub, ca, revoked, 0);  
                                         found_key = 1;  
                                 }  
                                 if (delete_host) {  
                                         if (!c || ca || revoked) {  
                                                 printhost(out, cp, pub,  
                                                     ca, revoked, 0);  
                                         } else {  
                                                 printf("# Host %s found: "  
                                                     "line %d type %s\n", name,  
                                                     num, sshkey_type(pub));  
                                         }  
                                 }  
                         } else if (hash_hosts)  
                                 printhost(out, cp, pub, ca, revoked, 0);  
                 } else {  
                         if (find_host || delete_host) {  
                                 c = (match_hostname(name, cp,  
                                     strlen(cp)) == 1);  
                                 if (find_host && c) {  
                                         if (!quiet)  
                                                 printf("# Host %s found: "  
                                                     "line %d type %s%s\n", name,  
                                                     num, sshkey_type(pub),  
                                                     ca ? " (CA key)" : "");  
                                         printhost(out, name, pub, ca, revoked,  
                                             hash_hosts && !(ca || revoked));  
                                         found_key = 1;  
                                 }  
                                 if (delete_host) {  
                                         if (!c || ca || revoked) {  
                                                 printhost(out, cp, pub,  
                                                     ca, revoked, 0);  
                                         } else {  
                                                 printf("# Host %s found: "  
                                                     "line %d type %s\n", name,  
                                                     num, sshkey_type(pub));  
                                         }  
                                 }  
                         } else if (hash_hosts && (ca || revoked)) {  
                                 /* Don't hash CA and revoked keys' hostnames */  
                                 printhost(out, cp, pub, ca, revoked, 0);  
                                 has_unhashed = 1;  
                         } else if (hash_hosts) {  
                                 /* Hash each hostname separately */  
                                 for (cp2 = strsep(&cp, ",");  
                                     cp2 != NULL && *cp2 != '\0';  
                                     cp2 = strsep(&cp, ",")) {  
                                         if (strcspn(cp2, "*?!") !=  
                                             strlen(cp2)) {  
                                                 fprintf(stderr, "Warning: "  
                                                     "ignoring host name with "  
                                                     "metacharacters: %.64s\n",  
                                                     cp2);  
                                                 printhost(out, cp2, pub, ca,  
                                                     revoked, 0);  
                                                 has_unhashed = 1;  
                                         } else {  
                                                 printhost(out, cp2, pub, ca,  
                                                     revoked, 1);  
                                         }  
                                 }  
                         }  
                 }  
                 sshkey_free(pub);  
         }  
         fclose(in);  
   
         if (invalid) {  
                 fprintf(stderr, "%s is not a valid known_hosts file.\n",                  fprintf(stderr, "%s is not a valid known_hosts file.\n",
                     identity_file);                      identity_file);
                 if (inplace) {                  if (ctx.inplace) {
                         fprintf(stderr, "Not replacing existing known_hosts "                          fprintf(stderr, "Not replacing existing known_hosts "
                             "file because of errors\n");                              "file because of errors\n");
                         fclose(out);  
                         unlink(tmp);                          unlink(tmp);
                 }                  }
                 exit(1);                  exit(1);
         }          } else if (delete_host && !ctx.found_key) {
                   fprintf(stderr, "Host %s not found in %s\n",
         if (inplace) {                      name, identity_file);
                 fclose(out);                  unlink(tmp);
           } else if (ctx.inplace) {
                 /* Backup existing file */                  /* Backup existing file */
                 if (unlink(old) == -1 && errno != ENOENT)                  if (unlink(old) == -1 && errno != ENOENT)
                         fatal("unlink %.100s: %s", old, strerror(errno));                          fatal("unlink %.100s: %s", old, strerror(errno));
Line 1275 
Line 1191 
   
                 fprintf(stderr, "%s updated.\n", identity_file);                  fprintf(stderr, "%s updated.\n", identity_file);
                 fprintf(stderr, "Original contents retained as %s\n", old);                  fprintf(stderr, "Original contents retained as %s\n", old);
                 if (has_unhashed) {                  if (ctx.has_unhashed) {
                         fprintf(stderr, "WARNING: %s contains unhashed "                          fprintf(stderr, "WARNING: %s contains unhashed "
                             "entries\n", old);                              "entries\n", old);
                         fprintf(stderr, "Delete this file to ensure privacy "                          fprintf(stderr, "Delete this file to ensure privacy "
Line 1283 
Line 1199 
                 }                  }
         }          }
   
         exit (find_host && !found_key);          exit (find_host && !ctx.found_key);
 }  }
   
 /*  /*

Legend:
Removed from v.1.255  
changed lines
  Added in v.1.256