void load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path) { FILE *f; char line[8192]; u_long linenum = 0, num_loaded = 0; char *cp, *cp2, *hashed_host; HostkeyMarker marker; Key *key; int kbits; if ((f = fopen(path, "r")) == NULL) return; debug3("%s: loading entries for host \"%.100s\" from file \"%s\"", __func__, host, path); while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) { cp = line; /* Skip any leading whitespace, comments and empty lines. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '#' || *cp == '\n') continue; if ((marker = check_markers(&cp)) == MRK_ERROR) { verbose("%s: invalid marker at %s:%lu", __func__, path, linenum); continue; } /* Find the end of the host name portion. */ for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) ; /* Check if the host name matches. */ if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) { if (*cp != HASH_DELIM) continue; hashed_host = host_hash(host, cp, (u_int) (cp2 - cp)); if (hashed_host == NULL) { debug("Invalid hashed host line %lu of %s", linenum, path); continue; } if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0) 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. */ key = key_new(KEY_UNSPEC); if (!hostfile_read_key(&cp, &kbits, key)) { key_free(key); key = key_new(KEY_RSA1); if (!hostfile_read_key(&cp, &kbits, key)) { key_free(key); continue; } } if (!hostfile_check_key(kbits, key, host, path, linenum)) continue; debug3("%s: found %skey type %s in file %s:%lu", __func__, marker == MRK_NONE ? "" : (marker == MRK_CA ? "ca " : "revoked "), key_type(key), path, linenum); hostkeys->entries = xrealloc(hostkeys->entries, hostkeys->num_entries + 1, sizeof(*hostkeys->entries)); hostkeys->entries[hostkeys->num_entries].host = xstrdup(host); hostkeys->entries[hostkeys->num_entries].file = xstrdup(path); hostkeys->entries[hostkeys->num_entries].line = linenum; hostkeys->entries[hostkeys->num_entries].key = key; hostkeys->entries[hostkeys->num_entries].marker = marker; hostkeys->num_entries++; num_loaded++; } debug3("%s: loaded %lu keys", __func__, num_loaded); fclose(f); return; }
int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, const char *host, const char *ip, u_int options) { FILE *f; char line[8192], oline[8192], ktype[128]; u_long linenum = 0; char *cp, *cp2; u_int kbits; int hashed; int s, r = 0; struct hostkey_foreach_line lineinfo; size_t l; memset(&lineinfo, 0, sizeof(lineinfo)); if (host == NULL && (options & HKF_WANT_MATCH) != 0) return SSH_ERR_INVALID_ARGUMENT; if ((f = fopen(path, "r")) == NULL) return SSH_ERR_SYSTEM_ERROR; debug3("%s: reading file \"%s\"", __func__, path); while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) { line[strcspn(line, "\n")] = '\0'; strlcpy(oline, line, sizeof(oline)); sshkey_free(lineinfo.key); memset(&lineinfo, 0, sizeof(lineinfo)); lineinfo.path = path; lineinfo.linenum = linenum; lineinfo.line = oline; lineinfo.marker = MRK_NONE; lineinfo.status = HKF_STATUS_OK; lineinfo.keytype = KEY_UNSPEC; /* Skip any leading whitespace, comments and empty lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '#' || *cp == '\n') { if ((options & HKF_WANT_MATCH) == 0) { lineinfo.status = HKF_STATUS_COMMENT; if ((r = callback(&lineinfo, ctx)) != 0) break; } continue; } if ((lineinfo.marker = check_markers(&cp)) == MRK_ERROR) { verbose("%s: invalid marker at %s:%lu", __func__, path, linenum); if ((options & HKF_WANT_MATCH) == 0) goto bad; continue; } /* Find the end of the host name portion. */ for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) ; lineinfo.hosts = cp; *cp2++ = '\0'; /* Check if the host name matches. */ if (host != NULL) { if ((s = match_maybe_hashed(host, lineinfo.hosts, &hashed)) == -1) { debug2("%s: %s:%ld: bad host hash \"%.32s\"", __func__, path, linenum, lineinfo.hosts); goto bad; } if (s == 1) { lineinfo.status = HKF_STATUS_MATCHED; lineinfo.match |= HKF_MATCH_HOST | (hashed ? HKF_MATCH_HOST_HASHED : 0); } /* Try matching IP address if supplied */ if (ip != NULL) { if ((s = match_maybe_hashed(ip, lineinfo.hosts, &hashed)) == -1) { debug2("%s: %s:%ld: bad ip hash " "\"%.32s\"", __func__, path, linenum, lineinfo.hosts); goto bad; } if (s == 1) { lineinfo.status = HKF_STATUS_MATCHED; lineinfo.match |= HKF_MATCH_IP | (hashed ? HKF_MATCH_IP_HASHED : 0); } } /* * Skip this line if host matching requested and * neither host nor address matched. */ if ((options & HKF_WANT_MATCH) != 0 && lineinfo.status != HKF_STATUS_MATCHED) continue; } /* Got a match. Skip host name and any following whitespace */ for (; *cp2 == ' ' || *cp2 == '\t'; cp2++) ; if (*cp2 == '\0' || *cp2 == '#') { debug2("%s:%ld: truncated before key type", path, linenum); goto bad; } lineinfo.rawkey = cp = cp2; if ((options & HKF_WANT_PARSE_KEY) != 0) { /* * Extract the key from the line. This will skip * any leading whitespace. Ignore badly formatted * lines. */ if ((lineinfo.key = sshkey_new(KEY_UNSPEC)) == NULL) { error("%s: sshkey_new failed", __func__); r = SSH_ERR_ALLOC_FAIL; break; } if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) { #ifdef WITH_SSH1 sshkey_free(lineinfo.key); lineinfo.key = sshkey_new(KEY_RSA1); if (lineinfo.key == NULL) { error("%s: sshkey_new fail", __func__); r = SSH_ERR_ALLOC_FAIL; break; } if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) goto bad; #else goto bad; #endif } lineinfo.keytype = lineinfo.key->type; lineinfo.comment = cp; } else { /* Extract and parse key type */ l = strcspn(lineinfo.rawkey, " \t"); if (l <= 1 || l >= sizeof(ktype) || lineinfo.rawkey[l] == '\0') goto bad; memcpy(ktype, lineinfo.rawkey, l); ktype[l] = '\0'; lineinfo.keytype = sshkey_type_from_name(ktype); /* * Assume RSA1 if the first component is a short * decimal number. */ if (lineinfo.keytype == KEY_UNSPEC && l < 8 && strspn(ktype, "0123456789") == l) lineinfo.keytype = KEY_RSA1; /* * Check that something other than whitespace follows * the key type. This won't catch all corruption, but * it does catch trivial truncation. */ cp2 += l; /* Skip past key type */ for (; *cp2 == ' ' || *cp2 == '\t'; cp2++) ; if (*cp2 == '\0' || *cp2 == '#') { debug2("%s:%ld: truncated after key type", path, linenum); lineinfo.keytype = KEY_UNSPEC; } if (lineinfo.keytype == KEY_UNSPEC) { bad: sshkey_free(lineinfo.key); lineinfo.key = NULL; lineinfo.status = HKF_STATUS_INVALID; if ((r = callback(&lineinfo, ctx)) != 0) break; continue; } } if ((r = callback(&lineinfo, ctx)) != 0) break; } sshkey_free(lineinfo.key); fclose(f); return r; }
int auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) { char line[8192], *file; int allowed = 0; u_int bits; FILE *f; u_long linenum = 0; struct stat st; Key *key; /* Temporarily use the user's uid. */ temporarily_use_uid(pw); /* The authorized keys. */ file = authorized_keys_file(pw); debug("trying public RSA key file %s", file); /* Fail quietly if file does not exist */ if (stat(file, &st) < 0) { /* Restore the privileged uid. */ restore_uid(); xfree(file); return (0); } /* Open the file containing the authorized keys. */ f = fopen(file, "r"); if (!f) { /* Restore the privileged uid. */ restore_uid(); xfree(file); return (0); } if (options.strict_modes && secure_filename(f, file, pw, line, sizeof(line)) != 0) { xfree(file); fclose(f); log("Authentication refused: %s", line); restore_uid(); return (0); } /* Flag indicating whether the key is allowed. */ allowed = 0; key = key_new(KEY_RSA1); /* * Go though the accepted keys, looking for the current key. If * found, perform a challenge-response dialog to verify that the * user really has the corresponding private key. */ while (fgets(line, sizeof(line), f)) { char *cp; char *options; linenum++; /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') continue; /* * Check if there are options for this key, and if so, * save their starting address and skip the option part * for now. If there are no options, set the starting * address to NULL. */ if (*cp < '0' || *cp > '9') { int quoted = 0; options = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') quoted = !quoted; } } else options = NULL; /* Parse the key from the line. */ if (hostfile_read_key(&cp, &bits, key) == 0) { debug("%.100s, line %lu: non ssh1 key syntax", file, linenum); continue; } /* cp now points to the comment part. */ /* Check if the we have found the desired key (identified by its modulus). */ if (BN_cmp(key->rsa->n, client_n) != 0) continue; /* check the real bits */ if (bits != BN_num_bits(key->rsa->n)) log("Warning: %s, line %lu: keysize mismatch: " "actual %d vs. announced %d.", file, linenum, BN_num_bits(key->rsa->n), bits); /* We have found the desired key. */ /* * If our options do not allow this key to be used, * do not send challenge. */ if (!auth_parse_options(pw, options, file, linenum)) continue; /* break out, this key is allowed */ allowed = 1; break; } /* Restore the privileged uid. */ restore_uid(); /* Close the file. */ xfree(file); fclose(f); /* return key if allowed */ if (allowed && rkey != NULL) *rkey = key; else key_free(key); return (allowed); }
static int rsa_key_allowed_in_file(struct passwd *pw, char *file, const BIGNUM *client_n, struct sshkey **rkey) { char line[SSH_MAX_PUBKEY_BYTES]; int allowed = 0; u_int bits; FILE *f; u_long linenum = 0; struct sshkey *key; debug("trying public RSA key file %s", file); if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL) return 0; /* * Go though the accepted keys, looking for the current key. If * found, perform a challenge-response dialog to verify that the * user really has the corresponding private key. */ if ((key = sshkey_new(KEY_RSA1)) == NULL) fatal("%s: sshkey_new failed", __func__); while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { char *cp; char *key_options; int keybits; /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') continue; /* * Check if there are options for this key, and if so, * save their starting address and skip the option part * for now. If there are no options, set the starting * address to NULL. */ if (*cp < '0' || *cp > '9') { int quoted = 0; key_options = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') quoted = !quoted; } } else key_options = NULL; /* Parse the key from the line. */ if (hostfile_read_key(&cp, &bits, key) == 0) { debug("%.100s, line %lu: non ssh1 key syntax", file, linenum); continue; } /* cp now points to the comment part. */ /* * Check if the we have found the desired key (identified * by its modulus). */ if (BN_cmp(key->rsa->n, client_n) != 0) continue; /* check the real bits */ keybits = BN_num_bits(key->rsa->n); if (keybits < 0 || bits != (u_int)keybits) logit("Warning: %s, line %lu: keysize mismatch: " "actual %d vs. announced %d.", file, linenum, BN_num_bits(key->rsa->n), bits); /* Never accept a revoked key */ if (auth_key_is_revoked(key)) break; /* We have found the desired key. */ /* * If our options do not allow this key to be used, * do not send challenge. */ if (!auth_parse_options(pw, key_options, file, linenum)) continue; if (key_is_cert_authority) continue; /* break out, this key is allowed */ allowed = 1; break; } /* Close the file. */ fclose(f); /* return key if allowed */ if (allowed && rkey != NULL) *rkey = key; else sshkey_free(key); return allowed; }
int auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) { char *file; u_int i, allowed = 0; temporarily_use_uid(pw); #ifdef WITH_LDAP_PUBKEY if (options.lpk.on) { u_int bits; int sbits; ldap_key_t *k; /* here is the job */ Key *key = key_new(KEY_RSA1); debug("[LDAP] trying LDAP first uid=%s", pw->pw_name); if ( ldap_ismember(&options.lpk, pw->pw_name) > 0) { if ( (k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) { for (i = 0 ; i < k->num ; i++) { char *cp, *xoptions = NULL; for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') continue; /* * Check if there are options for this key, and if so, * save their starting address and skip the option part * for now. If there are no options, set the starting * address to NULL. */ if (*cp < '0' || *cp > '9') { int quoted = 0; xoptions = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') quoted = !quoted; } } else xoptions = NULL; /* Parse the key from the line. */ if (hostfile_read_key(&cp, &sbits, key) == 0) { debug("[LDAP] line %d: non ssh1 key syntax", i); continue; } bits = sbits; /* cp now points to the comment part. */ /* Check if the we have found the desired key (identified by its modulus). */ if (BN_cmp(key->rsa->n, client_n) != 0) continue; /* check the real bits */ if (bits != (unsigned int)BN_num_bits(key->rsa->n)) logit("[LDAP] Warning: ldap, line %lu: keysize mismatch: " "actual %d vs. announced %d.", (unsigned long)i, BN_num_bits(key->rsa->n), bits); /* We have found the desired key. */ /* * If our options do not allow this key to be used, * do not send challenge. */ if (!auth_parse_options(pw, xoptions, "[LDAP]", (unsigned long) i)) continue; /* break out, this key is allowed */ allowed = 1; /* add the return stuff etc... */ /* Restore the privileged uid. */ restore_uid(); /* return key if allowed */ if (allowed && rkey != NULL) *rkey = key; else key_free(key); ldap_keys_free(k); return (allowed); } } else { logit("[LDAP] no keys found for '%s'!", pw->pw_name); } } else { logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup); } } #endif for (i = 0; !allowed && i < options.num_authkeys_files; i++) { if (strcasecmp(options.authorized_keys_files[i], "none") == 0) continue; file = expand_authorized_keys( options.authorized_keys_files[i], pw); allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey); free(file); } restore_uid(); return allowed; }
int auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) { char line[SSH_MAX_PUBKEY_BYTES], *file; int allowed = 0; u_int bits; FILE *f; u_long linenum = 0; Key *key; /* Temporarily use the user's uid. */ temporarily_use_uid(pw); /* The authorized keys. */ file = authorized_keys_file(pw); debug("trying public RSA key file %s", file); f = auth_openkeyfile(file, pw, options.strict_modes); if (!f) { xfree(file); restore_uid(); return (0); } /* Flag indicating whether the key is allowed. */ allowed = 0; key = key_new(KEY_RSA1); /* * Go though the accepted keys, looking for the current key. If * found, perform a challenge-response dialog to verify that the * user really has the corresponding private key. */ while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { char *cp; char *key_options; int keybits; char *fp; /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') continue; /* * Check if there are options for this key, and if so, * save their starting address and skip the option part * for now. If there are no options, set the starting * address to NULL. */ if (*cp < '0' || *cp > '9') { int quoted = 0; key_options = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') quoted = !quoted; } } else key_options = NULL; /* Parse the key from the line. */ if (hostfile_read_key(&cp, &bits, key) == 0) { debug("%.100s, line %lu: non ssh1 key syntax", file, linenum); continue; } /* cp now points to the comment part. */ /* Check if the we have found the desired key (identified by its modulus). */ if (BN_cmp(key->rsa->n, client_n) != 0) continue; /* check the real bits */ keybits = BN_num_bits(key->rsa->n); if (keybits < 0 || bits != (u_int)keybits) logit("Warning: %s, line %lu: keysize mismatch: " "actual %d vs. announced %d.", file, linenum, BN_num_bits(key->rsa->n), bits); /* Never accept a revoked key */ if (auth_key_is_revoked(key)) break; if (blacklisted_key(key)) { fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); if (options.permit_blacklisted_keys) logit("Public key %s blacklisted (see " "ssh-vulnkey(1)); continuing anyway", fp); else logit("Public key %s blacklisted (see " "ssh-vulnkey(1))", fp); xfree(fp); if (!options.permit_blacklisted_keys) continue; } /* We have found the desired key. */ /* * If our options do not allow this key to be used, * do not send challenge. */ if (!auth_parse_options(pw, key_options, file, linenum)) continue; if (key_is_cert_authority) continue; /* break out, this key is allowed */ allowed = 1; break; } /* Restore the privileged uid. */ restore_uid(); /* Close the file. */ xfree(file); fclose(f); /* return key if allowed */ if (allowed && rkey != NULL) *rkey = key; else key_free(key); return (allowed); }
static HostStatus check_host_in_hostfile_by_key_or_type(const char *filename, const char *host, const Key *key, int keytype, Key *found, int *numret) { FILE *f; char line[8192]; int linenum = 0; u_int kbits; char *cp, *cp2, *hashed_host; HostStatus end_return; debug3("check_host_in_hostfile: filename %s", filename); /* Open the file containing the list of known hosts. */ f = fopen(filename, "r"); if (!f) return HOST_NEW; /* * 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; /* Go through the file. */ while (fgets(line, sizeof(line), f)) { cp = line; linenum++; /* Skip any leading whitespace, comments and empty lines. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '#' || *cp == '\n') continue; /* Find the end of the host name portion. */ for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) ; /* Check if the host name matches. */ if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) { if (*cp != HASH_DELIM) continue; hashed_host = host_hash(host, cp, (u_int) (cp2 - cp)); if (hashed_host == NULL) { debug("Invalid hashed host line %d of %s", linenum, filename); continue; } if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0) 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 (!hostfile_read_key(&cp, &kbits, found)) continue; if (numret != NULL) *numret = linenum; if (key == NULL) { /* we found a key of the requested type */ if (found->type == keytype) return HOST_FOUND; continue; } if (!hostfile_check_key(kbits, found, host, filename, linenum)) continue; /* Check if the current key is the same as the given key. */ if (key_equal(key, found)) { /* Ok, they match. */ debug3("check_host_in_hostfile: match line %d", linenum); 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. */ fclose(f); /* * Return either HOST_NEW or HOST_CHANGED, depending on whether we * saw a different key for the host. */ return end_return; }
int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, const char *host, u_int options) { FILE *f; char line[8192], oline[8192]; u_long linenum = 0; char *cp, *cp2; u_int kbits; int s, r = 0; struct hostkey_foreach_line lineinfo; memset(&lineinfo, 0, sizeof(lineinfo)); if (host == NULL && (options & HKF_WANT_MATCH_HOST) != 0) return SSH_ERR_INVALID_ARGUMENT; if ((f = fopen(path, "r")) == NULL) return SSH_ERR_SYSTEM_ERROR; debug3("%s: reading file \"%s\"", __func__, path); while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) { line[strcspn(line, "\n")] = '\0'; strlcpy(oline, line, sizeof(oline)); sshkey_free(lineinfo.key); memset(&lineinfo, 0, sizeof(lineinfo)); lineinfo.path = path; lineinfo.linenum = linenum; lineinfo.line = oline; lineinfo.status = HKF_STATUS_OK; /* Skip any leading whitespace, comments and empty lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '#' || *cp == '\n') { if ((options & HKF_WANT_MATCH_HOST) == 0) { lineinfo.status = HKF_STATUS_COMMENT; if ((r = callback(&lineinfo, ctx)) != 0) break; } continue; } if ((lineinfo.marker = check_markers(&cp)) == MRK_ERROR) { verbose("%s: invalid marker at %s:%lu", __func__, path, linenum); if ((options & HKF_WANT_MATCH_HOST) == 0) goto bad; continue; } /* Find the end of the host name portion. */ for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) ; lineinfo.hosts = cp; *cp2++ = '\0'; /* Check if the host name matches. */ if (host != NULL) { s = match_maybe_hashed(host, lineinfo.hosts, &lineinfo.was_hashed); if (s == 1) lineinfo.status = HKF_STATUS_HOST_MATCHED; else if ((options & HKF_WANT_MATCH_HOST) != 0) continue; else if (s == -1) { debug2("%s: %s:%ld: bad host hash \"%.32s\"", __func__, path, linenum, lineinfo.hosts); goto bad; } } /* Got a match. Skip host name and any following whitespace */ for (; *cp2 == ' ' || *cp2 == '\t'; cp2++) ; if (*cp2 == '\0' || *cp2 == '#') { debug2("%s:%ld: truncated before key", path, linenum); goto bad; } lineinfo.rawkey = cp = cp2; if ((options & HKF_WANT_PARSE_KEY) != 0) { /* * Extract the key from the line. This will skip * any leading whitespace. Ignore badly formatted * lines. */ if ((lineinfo.key = sshkey_new(KEY_UNSPEC)) == NULL) { error("%s: sshkey_new failed", __func__); return SSH_ERR_ALLOC_FAIL; } if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) { #ifdef WITH_SSH1 sshkey_free(lineinfo.key); lineinfo.key = sshkey_new(KEY_RSA1); if (lineinfo.key == NULL) { error("%s: sshkey_new fail", __func__); return SSH_ERR_ALLOC_FAIL; } if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) goto bad; #else goto bad; #endif } if (!hostfile_check_key(kbits, lineinfo.key, host, path, linenum)) { bad: lineinfo.status = HKF_STATUS_INVALID; if ((r = callback(&lineinfo, ctx)) != 0) break; continue; } } if ((r = callback(&lineinfo, ctx)) != 0) break; } sshkey_free(lineinfo.key); fclose(f); return r; }