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

Diff for /src/usr.bin/ssh/hostfile.c between version 1.6 and 1.7

version 1.6, 1999/11/16 15:44:41 version 1.7, 1999/11/23 22:25:53
Line 26 
Line 26 
    modify the buffer containing the number. */     modify the buffer containing the number. */
   
 int  int
 auth_rsa_read_bignum(char **cpp, BIGNUM *value)  auth_rsa_read_bignum(char **cpp, BIGNUM * value)
 {  {
   char *cp = *cpp;          char *cp = *cpp;
   int len, old;          int len, old;
   
   /* Skip any leading whitespace. */          /* Skip any leading whitespace. */
   for (; *cp == ' ' || *cp == '\t'; cp++)          for (; *cp == ' ' || *cp == '\t'; cp++);
     ;  
   
   /* Check that it begins with a hex digit. */          /* Check that it begins with a hex digit. */
   if (*cp < '0' || *cp > '9')          if (*cp < '0' || *cp > '9')
     return 0;                  return 0;
   
   /* Save starting position. */          /* Save starting position. */
   *cpp = cp;          *cpp = cp;
   
   /* Move forward until all hex digits skipped. */          /* Move forward until all hex digits skipped. */
   for (; *cp >= '0' && *cp <= '9'; cp++)          for (; *cp >= '0' && *cp <= '9'; cp++);
     ;  
   
   /* Compute the length of the hex number. */          /* Compute the length of the hex number. */
   len = cp - *cpp;          len = cp - *cpp;
   
   /* Save the old terminating character, and replace it by \0. */          /* Save the old terminating character, and replace it by \0. */
   old = *cp;          old = *cp;
   *cp = 0;          *cp = 0;
   
   
   /* Parse the number. */  
   if (BN_dec2bn(&value, *cpp) == 0)  
     return 0;  
   
   /* Restore old terminating character. */          /* Parse the number. */
   *cp = old;          if (BN_dec2bn(&value, *cpp) == 0)
                   return 0;
   
   /* Move beyond the number and return success. */          /* Restore old terminating character. */
   *cpp = cp;          *cp = old;
   return 1;  
           /* Move beyond the number and return success. */
           *cpp = cp;
           return 1;
 }  }
   
 /* Parses an RSA key (number of bits, e, n) from a string.  Moves the pointer  /* Parses an RSA key (number of bits, e, n) from a string.  Moves the pointer
    over the key.  Skips any whitespace at the beginning and at end. */     over the key.  Skips any whitespace at the beginning and at end. */
   
 int  int
 auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM *e, BIGNUM *n)  auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
 {  {
   unsigned int bits;          unsigned int bits;
   char *cp;          char *cp;
   
   /* Skip leading whitespace. */          /* Skip leading whitespace. */
   for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)          for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++);
     ;  
   
   /* Get number of bits. */          /* Get number of bits. */
   if (*cp < '0' || *cp > '9')          if (*cp < '0' || *cp > '9')
     return 0; /* Bad bit count... */                  return 0;       /* Bad bit count... */
   for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)          for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
     bits = 10 * bits + *cp - '0';                  bits = 10 * bits + *cp - '0';
   
   /* Get public exponent. */          /* Get public exponent. */
   if (!auth_rsa_read_bignum(&cp, e))          if (!auth_rsa_read_bignum(&cp, e))
     return 0;                  return 0;
   
   /* Get public modulus. */          /* Get public modulus. */
   if (!auth_rsa_read_bignum(&cp, n))          if (!auth_rsa_read_bignum(&cp, n))
     return 0;                  return 0;
   
   /* Skip trailing whitespace. */          /* Skip trailing whitespace. */
   for (; *cp == ' ' || *cp == '\t'; cp++)          for (; *cp == ' ' || *cp == '\t'; cp++);
     ;  
           /* Return results. */
   /* Return results. */          *cpp = cp;
   *cpp = cp;          *bitsp = bits;
   *bitsp = bits;          return 1;
   return 1;  
 }  }
   
 /* Tries to match the host name (which must be in all lowercase) against the  /* Tries to match the host name (which must be in all lowercase) against the
    comma-separated sequence of subpatterns (each possibly preceded by ! to     comma-separated sequence of subpatterns (each possibly preceded by ! to
    indicate negation).  Returns true if there is a positive match; zero     indicate negation).  Returns true if there is a positive match; zero
    otherwise. */     otherwise. */
   
 int  int
 match_hostname(const char *host, const char *pattern, unsigned int len)  match_hostname(const char *host, const char *pattern, unsigned int len)
 {  {
   char sub[1024];          char sub[1024];
   int negated;          int negated;
   int got_positive;          int got_positive;
   unsigned int i, subi;          unsigned int i, subi;
   
   got_positive = 0;          got_positive = 0;
   for (i = 0; i < len;)          for (i = 0; i < len;) {
     {                  /* Check if the subpattern is negated. */
       /* Check if the subpattern is negated. */                  if (pattern[i] == '!') {
       if (pattern[i] == '!')                          negated = 1;
         {                          i++;
           negated = 1;                  } else
           i++;                          negated = 0;
         }  
       else  
         negated = 0;  
   
       /* Extract the subpattern up to a comma or end.  Convert the subpattern  
          to lowercase. */  
       for (subi = 0;  
            i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';  
            subi++, i++)  
         sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];  
       /* If subpattern too long, return failure (no match). */  
       if (subi >= sizeof(sub) - 1)  
         return 0;  
   
       /* If the subpattern was terminated by a comma, skip the comma. */                  /* Extract the subpattern up to a comma or end.  Convert
       if (i < len && pattern[i] == ',')                     the subpattern to lowercase. */
         i++;                  for (subi = 0;
                     i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
       /* Null-terminate the subpattern. */                       subi++, i++)
       sub[subi] = '\0';                          sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];
                   /* If subpattern too long, return failure (no match). */
                   if (subi >= sizeof(sub) - 1)
                           return 0;
   
       /* Try to match the subpattern against the host name. */                  /* If the subpattern was terminated by a comma, skip the
       if (match_pattern(host, sub)) {                     comma. */
         if (negated)                  if (i < len && pattern[i] == ',')
           return 0;  /* Fail if host matches any negated subpattern. */                          i++;
         else  
           got_positive = 1;  
       }  
     }  
   
   /* Return success if got a positive match.  If there was a negative match,                  /* Null-terminate the subpattern. */
      we have already returned zero and never get here. */                  sub[subi] = '\0';
   return got_positive;  
                   /* Try to match the subpattern against the host name. */
                   if (match_pattern(host, sub)) {
                           if (negated)
                                   return 0;       /* Fail if host matches
                                                      any negated subpattern. */
                           else
                                   got_positive = 1;
                   }
           }
   
           /* Return success if got a positive match.  If there was a
              negative match, we have already returned zero and never get
              here. */
           return got_positive;
 }  }
   
 /* Checks whether the given host (which must be in all lowercase) is  /* Checks whether the given host (which must be in all lowercase) is
    already in the list of our known hosts.     already in the list of our known hosts.
    Returns HOST_OK if the host is known and has the specified key,     Returns HOST_OK if the host is known and has the specified key,
    HOST_NEW if the host is not known, and HOST_CHANGED if the host is known     HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
Line 167 
Line 163 
   
 HostStatus  HostStatus
 check_host_in_hostfile(const char *filename, const char *host,  check_host_in_hostfile(const char *filename, const char *host,
                        BIGNUM *e, BIGNUM *n, BIGNUM *ke, BIGNUM *kn)                         BIGNUM * e, BIGNUM * n, BIGNUM * ke, BIGNUM * kn)
 {  {
   FILE *f;          FILE *f;
   char line[8192];          char line[8192];
   int linenum = 0;          int linenum = 0;
   unsigned int bits, kbits, hostlen;          unsigned int bits, kbits, hostlen;
   char *cp, *cp2;          char *cp, *cp2;
   HostStatus end_return;          HostStatus end_return;
   
   /* Open the file containing the list of known hosts. */          /* Open the file containing the list of known hosts. */
   f = fopen(filename, "r");          f = fopen(filename, "r");
   if (!f)          if (!f)
     return HOST_NEW;                  return HOST_NEW;
   
   /* Cache the length of the host name. */          /* Cache the length of the host name. */
   hostlen = strlen(host);          hostlen = strlen(host);
   
   /* Return value when the loop terminates.  This is set to HOST_CHANGED if  
      we have seen a different key for the host and have not found the proper  
      one. */  
   end_return = HOST_NEW;  
   
   /* size of modulus 'n' */          /* Return value when the loop terminates.  This is set to
   bits = BN_num_bits(n);             HOST_CHANGED if we have seen a different key for the host and
              have not found the proper one. */
           end_return = HOST_NEW;
   
   /* Go trough the file. */          /* size of modulus 'n' */
   while (fgets(line, sizeof(line), f))          bits = BN_num_bits(n);
     {  
       cp = line;  
       linenum++;  
   
       /* Skip any leading whitespace. */          /* Go trough the file. */
       for (; *cp == ' ' || *cp == '\t'; cp++)          while (fgets(line, sizeof(line), f)) {
         ;                  cp = line;
                   linenum++;
   
       /* Ignore comment lines and empty lines. */                  /* Skip any leading whitespace. */
       if (!*cp || *cp == '#' || *cp == '\n')                  for (; *cp == ' ' || *cp == '\t'; cp++);
         continue;  
   
       /* Find the end of the host name portion. */  
       for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)  
         ;  
   
       /* Check if the host name matches. */                  /* Ignore comment lines and empty lines. */
       if (!match_hostname(host, cp, (unsigned int)(cp2 - cp)))                  if (!*cp || *cp == '#' || *cp == '\n')
         continue;                          continue;
   
       /* Got a match.  Skip host name. */  
       cp = cp2;  
   
       /* Extract the key from the line.  This will skip any leading  
          whitespace.  Ignore badly formatted lines. */  
       if (!auth_rsa_read_key(&cp, &kbits, ke, kn))  
         continue;  
   
       if (kbits != BN_num_bits(kn)) {                  /* Find the end of the host name portion. */
         error("Warning: error in %s, line %d: keysize mismatch for host %s: "                  for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++);
               "actual size %d vs. announced %d.",  
               filename, linenum, host, BN_num_bits(kn), kbits);  
         error("Warning: replace %d with %d in %s, line %d.",  
               kbits, BN_num_bits(kn), filename, linenum);  
       }  
   
       /* Check if the current key is the same as the given key. */                  /* Check if the host name matches. */
       if (BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0)                  if (!match_hostname(host, cp, (unsigned int) (cp2 - cp)))
         {                          continue;
           /* Ok, they match. */  
           fclose(f);                  /* Got a match.  Skip host name. */
           return HOST_OK;                  cp = cp2;
   
                   /* Extract the key from the line.  This will skip any
                      leading whitespace.  Ignore badly formatted lines. */
                   if (!auth_rsa_read_key(&cp, &kbits, ke, kn))
                           continue;
   
                   if (kbits != BN_num_bits(kn)) {
                           error("Warning: error in %s, line %d: keysize mismatch for host %s: "
                                 "actual size %d vs. announced %d.",
                           filename, linenum, host, BN_num_bits(kn), kbits);
                           error("Warning: replace %d with %d in %s, line %d.",
                                 kbits, BN_num_bits(kn), filename, linenum);
                   }
                   /* Check if the current key is the same as the given key. */
                   if (BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0) {
                           /* Ok, they match. */
                           fclose(f);
                           return HOST_OK;
                   }
                   /* They do not match.  We will continue to go through the
                      file; however, we note that we will not return that it
                      is new. */
                   end_return = HOST_CHANGED;
         }          }
           /* Clear variables and close the file. */
       /* They do not match.  We will continue to go through the file; however,          fclose(f);
          we note that we will not return that it is new. */  
       end_return = HOST_CHANGED;  
     }  
   /* Clear variables and close the file. */  
   fclose(f);  
   
   /* Return either HOST_NEW or HOST_CHANGED, depending on whether we saw a          /* Return either HOST_NEW or HOST_CHANGED, depending on whether we
      different key for the host. */             saw a different key for the host. */
   return end_return;          return end_return;
 }  }
   
 /* Appends an entry to the host file.  Returns false if the entry  /* Appends an entry to the host file.  Returns false if the entry
Line 255 
Line 246 
   
 int  int
 add_host_to_hostfile(const char *filename, const char *host,  add_host_to_hostfile(const char *filename, const char *host,
                      BIGNUM *e, BIGNUM *n)                       BIGNUM * e, BIGNUM * n)
 {  {
   FILE *f;          FILE *f;
   char *buf;          char *buf;
   unsigned int bits;          unsigned int bits;
   
   /* Open the file for appending. */  
   f = fopen(filename, "a");  
   if (!f)  
     return 0;  
   
   /* size of modulus 'n' */          /* Open the file for appending. */
   bits = BN_num_bits(n);          f = fopen(filename, "a");
           if (!f)
                   return 0;
   
   /* Print the host name and key to the file. */          /* size of modulus 'n' */
   fprintf(f, "%s %u ", host, bits);          bits = BN_num_bits(n);
   buf = BN_bn2dec(e);  
   if (buf == NULL) {  
     error("add_host_to_hostfile: BN_bn2dec(e) failed");  
     fclose(f);  
     return 0;  
   }  
   fprintf(f, "%s ", buf);  
   free (buf);  
   buf = BN_bn2dec(n);  
   if (buf == NULL) {  
     error("add_host_to_hostfile: BN_bn2dec(n) failed");  
     fclose(f);  
     return 0;  
   }  
   fprintf(f, "%s\n", buf);  
   free (buf);  
   
   /* Close the file. */          /* Print the host name and key to the file. */
   fclose(f);          fprintf(f, "%s %u ", host, bits);
   return 1;          buf = BN_bn2dec(e);
           if (buf == NULL) {
                   error("add_host_to_hostfile: BN_bn2dec(e) failed");
                   fclose(f);
                   return 0;
           }
           fprintf(f, "%s ", buf);
           free(buf);
           buf = BN_bn2dec(n);
           if (buf == NULL) {
                   error("add_host_to_hostfile: BN_bn2dec(n) failed");
                   fclose(f);
                   return 0;
           }
           fprintf(f, "%s\n", buf);
           free(buf);
   
           /* Close the file. */
           fclose(f);
           return 1;
 }  }

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7