Ejemplo n.º 1
0
/*
 * sysctl helper routine for kern.urandom node. Picks a random number
 * for you.
 */
static int
sysctl_kern_urnd(SYSCTLFN_ARGS)
{
	static ONCE_DECL(control);
	int v, rv;

	RUN_ONCE(&control, makeprng);
	rv = cprng_strong(sysctl_prng, &v, sizeof(v), 0);
	if (rv == sizeof(v)) {
		struct sysctlnode node = *rnode;
		node.sysctl_data = &v;
		return (sysctl_lookup(SYSCTLFN_CALL(&node)));
	}
	else
		return (EIO);	/*XXX*/
}
Ejemplo n.º 2
0
int
assemble_security_parameters(connection_t *conn, ccb_t *ccb, pdu_t *rx_pdu,
							 pdu_t *tx_pdu)
{
	negotiation_state_t *state = (negotiation_state_t *) ccb->temp_data;
	iscsi_login_parameters_t *par = conn->login_par;
	negotiation_parameter_t rxp, *cpar;
	uint8_t *rxpars;
	int rc, next;
	uint8_t identifier = 0;
	uint8_t *challenge = NULL;
	int challenge_size = 0;
	uint8_t *response = NULL;
	int response_size = 0;

	state->num_pars = 0;
	next = 0;

	rxpars = (uint8_t *) rx_pdu->temp_data;
	if (rxpars == NULL) {
		DEBOUT(("No received parameters!\n"));
		return ISCSI_STATUS_NEGOTIATION_ERROR;
	}
	/* Note: There are always at least 2 extra bytes past temp_data_len */
	rxpars[rx_pdu->temp_data_len] = '\0';
	rxpars[rx_pdu->temp_data_len + 1] = '\0';

	while (*rxpars) {
		if ((rxpars = get_parameter(rxpars, &rxp)) == NULL) {
			DEBOUT(("get_parameter returned error\n"));
			return ISCSI_STATUS_NEGOTIATION_ERROR;
		}

		state->kflags[rxp.key] |= NS_RECEIVED;

		switch (rxp.key) {
		case K_AuthMethod:
			if (state->auth_state != AUTH_INITIAL) {
				DEBOUT(("AuthMethod received, auth_state = %d\n",
						state->auth_state));
				return ISCSI_STATUS_NEGOTIATION_ERROR;
			}

			/* Note: if the selection is None, we shouldn't be here,
			 * the target should have transited the state to op-neg.
			 */
			if (rxp.val.nval[0] != ISCSI_AUTH_CHAP) {
				DEBOUT(("AuthMethod isn't CHAP (%d)\n", rxp.val.nval[0]));
				return ISCSI_STATUS_NEGOTIATION_ERROR;
			}

			state->auth_state = AUTH_METHOD_SELECTED;
			state->auth_alg = rxp.val.nval[0];
			break;

		case K_Auth_CHAP_Algorithm:
			if (state->auth_state != AUTH_CHAP_ALG_SENT ||
				rxp.val.nval[0] != 5) {
				DEBOUT(("Bad algorithm, auth_state = %d, alg %d\n",
						state->auth_state, rxp.val.nval[0]));
				return ISCSI_STATUS_NEGOTIATION_ERROR;
			}
			break;

		case K_Auth_CHAP_Challenge:
			if (state->auth_state != AUTH_CHAP_ALG_SENT || !rxp.list_num) {
				DEBOUT(("Bad Challenge, auth_state = %d, len %d\n",
						state->auth_state, rxp.list_num));
				return ISCSI_STATUS_NEGOTIATION_ERROR;
			}
			challenge = rxp.val.sval;
			challenge_size = rxp.list_num;
			break;

		case K_Auth_CHAP_Identifier:
			if (state->auth_state != AUTH_CHAP_ALG_SENT) {
				DEBOUT(("Bad ID, auth_state = %d, id %d\n",
						state->auth_state, rxp.val.nval[0]));
				return ISCSI_STATUS_NEGOTIATION_ERROR;
			}
			identifier = (uint8_t) rxp.val.nval[0];
			break;

		case K_Auth_CHAP_Name:
			if (state->auth_state != AUTH_CHAP_RSP_SENT) {
				DEBOUT(("Bad Name, auth_state = %d, name <%s>\n",
						state->auth_state, rxp.val.sval));
				return ISCSI_STATUS_NEGOTIATION_ERROR;
			}
			/* what do we do with the name?? */
			break;

		case K_Auth_CHAP_Response:
			if (state->auth_state != AUTH_CHAP_RSP_SENT) {
				DEBOUT(("Bad Response, auth_state = %d, size %d\n",
						state->auth_state, rxp.list_num));
				return ISCSI_STATUS_NEGOTIATION_ERROR;
			}
			response = rxp.val.sval;
			response_size = rxp.list_num;
			if (response_size != CHAP_MD5_SIZE)
				return ISCSI_STATUS_NEGOTIATION_ERROR;
			break;

		default:
			rc = eval_parameter(conn, state, &rxp);
			if (rc)
				return rc;
			break;
		}
	}

	switch (state->auth_state) {
	case AUTH_INITIAL:
		DEBOUT(("Didn't receive Method\n"));
		return ISCSI_STATUS_NEGOTIATION_ERROR;

	case AUTH_METHOD_SELECTED:
		set_key_n(state, K_Auth_CHAP_Algorithm, 5);
		state->auth_state = AUTH_CHAP_ALG_SENT;
		next = -1;
		break;

	case AUTH_CHAP_ALG_SENT:
		if (!RX(state, K_Auth_CHAP_Algorithm) ||
			!RX(state, K_Auth_CHAP_Identifier) ||
			!RX(state, K_Auth_CHAP_Challenge)) {
			DEBOUT(("Didn't receive all parameters\n"));
			return ISCSI_STATUS_NEGOTIATION_ERROR;
		}

		set_key_s(state, K_Auth_CHAP_Name, state->user_name);

		chap_md5_response(state->temp_buf, identifier, state->password,
						  challenge, challenge_size);

		cpar = set_key_s(state, K_Auth_CHAP_Response, state->temp_buf);
		if (cpar != NULL)
			cpar->list_num = CHAP_MD5_SIZE;

		if (par->auth_info.mutual_auth) {
			if (!state->target_password[0]) {
				DEBOUT(("No target password with mutual authentication!\n"));
				return ISCSI_STATUS_PARAMETER_MISSING;
			}

			cprng_strong(kern_cprng,
				     &state->temp_buf[CHAP_MD5_SIZE],
				     CHAP_CHALLENGE_LEN + 1, 0);
			set_key_n(state, K_Auth_CHAP_Identifier,
					  state->temp_buf[CHAP_MD5_SIZE]);
			cpar = set_key_s(state, K_Auth_CHAP_Challenge,
							 &state->temp_buf[CHAP_MD5_SIZE + 1]);
			if (cpar != NULL)
				cpar->list_num = CHAP_CHALLENGE_LEN;
			next = -1;
		}
		state->auth_state = AUTH_CHAP_RSP_SENT;
		break;

	case AUTH_CHAP_RSP_SENT:
		/* we can only be here for mutual authentication */
		if (!par->auth_info.mutual_auth || response == NULL) {
			DEBOUT(("Mutual authentication not requested\n"));
			return ISCSI_STATUS_NEGOTIATION_ERROR;
		}

		chap_md5_response(state->temp_buf,
				state->temp_buf[CHAP_MD5_SIZE],
				state->password,
				&state->temp_buf[CHAP_MD5_SIZE + 1],
				CHAP_CHALLENGE_LEN);

		if (memcmp(state->temp_buf, response, response_size)) {
			DEBOUT(("Mutual authentication mismatch\n"));
			return ISCSI_STATUS_AUTHENTICATION_FAILED;
		}
		break;

	default:
		break;
	}

	complete_pars(state, tx_pdu);

	return next;
}
Ejemplo n.º 3
0
static int
rnd_read(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
    int flags)
{
	int error = 0;

	DPRINTF(RND_DEBUG_READ,
	    ("Random: Read of %zu requested, flags 0x%08x\n",
		uio->uio_resid, flags));

	if (uio->uio_resid == 0)
		return 0;

	struct rnd_ctx *const ctx = fp->f_data;
	uint8_t *const buf = pool_cache_get(rnd_temp_buffer_cache, PR_WAITOK);

	/*
	 * Choose a CPRNG to use -- either the per-open CPRNG, if this
	 * is /dev/random or a long read, or the per-CPU one otherwise.
	 *
	 * XXX NIST_BLOCK_KEYLEN_BYTES is a detail of the cprng(9)
	 * implementation and as such should not be mentioned here.
	 */
	struct cprng_strong *const cprng =
	    ((ctx->rc_hard || (uio->uio_resid > NIST_BLOCK_KEYLEN_BYTES))?
		rnd_ctx_cprng(ctx) : rnd_percpu_cprng());

	/*
	 * Generate the data in RND_TEMP_BUFFER_SIZE chunks.
	 */
	while (uio->uio_resid > 0) {
		const size_t n_req = MIN(uio->uio_resid, RND_TEMP_BUFFER_SIZE);

		CTASSERT(RND_TEMP_BUFFER_SIZE <= CPRNG_MAX_LEN);
		const size_t n_read = cprng_strong(cprng, buf, n_req,
		    ((ctx->rc_hard && ISSET(fp->f_flag, FNONBLOCK))?
			FNONBLOCK : 0));

		/*
		 * Equality will hold unless this is /dev/random, in
		 * which case we get only as many bytes as are left
		 * from the CPRNG's `information-theoretic strength'
		 * since the last rekey.
		 */
		KASSERT(n_read <= n_req);
		KASSERT(ctx->rc_hard || (n_read == n_req));

		error = uiomove(buf, n_read, uio);
		if (error)
			goto out;

		/*
		 * Do at most one iteration for /dev/random and return
		 * a short read without hanging further.  Hanging
		 * breaks applications worse than short reads.  Reads
		 * can't be zero unless nonblocking from /dev/random;
		 * in that case, ask caller to retry, instead of just
		 * returning zero bytes, which means EOF.
		 */
		KASSERT((0 < n_read) || (ctx->rc_hard &&
			ISSET(fp->f_flag, FNONBLOCK)));
		if (ctx->rc_hard) {
			if (n_read == 0)
				error = EAGAIN;
			goto out;
		}
	}

out:	pool_cache_put(rnd_temp_buffer_cache, buf);
	return error;
}