Esempio n. 1
0
/*
 *	If we have something to log, then we log it.
 *	Otherwise we return the retcode as soon as possible
 */
static int do_logging(REQUEST *request, char const *str, int rcode)
{
	char *expanded = NULL;

	if (!str || !*str) return rcode;

	if (radius_axlat(&expanded, request, str, NULL, NULL) < 0) {
		return rcode;
	}

	pair_make_config("Module-Success-Message", expanded, T_OP_SET);

	talloc_free(expanded);

	return rcode;
}
Esempio n. 2
0
static rlm_rcode_t CC_HINT(nonnull) mod_authorize(UNUSED void *instance, REQUEST *request)
{
	if (!fr_pair_find_by_num(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) {
		return RLM_MODULE_NOOP;
	}

	if (fr_pair_find_by_num(request->config, PW_AUTH_TYPE, 0, TAG_ANY) != NULL) {
		RWDEBUG2("&control:Auth-Type already set.  Not setting to CHAP");
		return RLM_MODULE_NOOP;
	}

	RINDENT();
	RDEBUG("&control:Auth-Type := CHAP");
	REXDENT();
	pair_make_config("Auth-Type", "CHAP", T_OP_EQ);

	return RLM_MODULE_OK;
}
Esempio n. 3
0
/*
 *	Find the named user in this modules database.  Create the set
 *	of attribute-value pairs to check and reply with for this user
 *	from the database. The authentication code only needs to check
 *	the password, the rest is done here.
 */
static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, REQUEST *request)
{
	VALUE_PAIR *state;
	rlm_smsotp_t *inst = instance;

	/*
	 *  Look for the 'state' attribute.
	 */
	state = fr_pair_find_by_num(request->packet->vps, PW_STATE, 0, TAG_ANY);
	if (state != NULL) {
		DEBUG("rlm_smsotp: Found reply to access challenge (AUTZ), Adding Auth-Type '%s'",inst->authtype);

		fr_pair_delete_by_num(&request->config, PW_AUTH_TYPE, 0, TAG_ANY); /* delete old auth-type */
		pair_make_config("Auth-Type", inst->authtype, T_OP_SET);
	}

	return RLM_MODULE_OK;
}
Esempio n. 4
0
/*
 *	Run a virtual server auth and postauth
 *
 */
int rad_virtual_server(REQUEST *request)
{
	VALUE_PAIR *vp;
	int result;

	RDEBUG("Virtual server %s received request", request->server);
	rdebug_pair_list(L_DBG_LVL_1, request, request->packet->vps, NULL);

	RDEBUG("server %s {", request->server);
	RINDENT();

	/*
	 *	We currently only handle AUTH packets here.
	 *	This could be expanded to handle other packets as well if required.
	 */
	rad_assert(request->packet->code == PW_CODE_ACCESS_REQUEST);

	result = rad_authenticate(request);

	if (request->reply->code == PW_CODE_ACCESS_REJECT) {
		fr_pair_delete_by_num(&request->config, PW_POST_AUTH_TYPE, 0, TAG_ANY);
		vp = pair_make_config("Post-Auth-Type", "Reject", T_OP_SET);
		if (vp) rad_postauth(request);
	}

	if (request->reply->code == PW_CODE_ACCESS_ACCEPT) {
		rad_postauth(request);
	}

	REXDENT();
	RDEBUG("} # server %s", request->server);

	RDEBUG("Virtual server sending reply");
	rdebug_pair_list(L_DBG_LVL_1, request, request->reply->vps, NULL);

	return result;
}
Esempio n. 5
0
/*
 *	Generate a challenge to be presented to the user.
 */
static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, REQUEST *request)
{
	rlm_otp_t *inst = (rlm_otp_t *) instance;

	char challenge[OTP_MAX_CHALLENGE_LEN + 1];	/* +1 for '\0' terminator */
	int auth_type_found;

	/* Early exit if Auth-Type != inst->name */
	{
		VALUE_PAIR *vp;

		auth_type_found = 0;
		vp = fr_pair_find_by_num(request->config, PW_AUTH_TYPE, 0, TAG_ANY);
		if (vp) {
			auth_type_found = 1;
			if (strcmp(vp->vp_strvalue, inst->name)) {
				return RLM_MODULE_NOOP;
			}
		}
	}

	/* The State attribute will be present if this is a response. */
	if (fr_pair_find_by_num(request->packet->vps, PW_STATE, 0, TAG_ANY) != NULL) {
		DEBUG("rlm_otp: autz: Found response to Access-Challenge");

		return RLM_MODULE_OK;
	}

	/* User-Name attribute required. */
	if (!request->username) {
		RWDEBUG("Attribute \"User-Name\" "
		       "required for authentication");

		return RLM_MODULE_INVALID;
	}

	if (otp_pwe_present(request) == 0) {
		RWDEBUG("Attribute "
			"\"User-Password\" or equivalent required "
			"for authentication");

		return RLM_MODULE_INVALID;
	}

	/*
	 * 	We used to check for special "challenge" and "resync" passcodes
	 * 	here, but these are complicated to explain and application is
	 * 	limited.  More importantly, since we've removed all actual OTP
	 * 	code (now we ask otpd), it's awkward for us to support them.
	 * 	Should the need arise to reinstate these options, the most
	 *	likely choice is to duplicate some otpd code here.
	 */
	if (inst->allow_sync && !inst->allow_async) {
		/* This is the token sync response. */
		if (!auth_type_found) {
			pair_make_config("Auth-Type", inst->name, T_OP_EQ);
		}

		return RLM_MODULE_OK;
	}

	/*
	 *	Generate a random challenge.
	 */
	otp_async_challenge(challenge, inst->challenge_len);

	/*
	 *	Create the State attribute, which will be returned to
	 *	us along with the response.
	 *
	 *	We will need this to verify the response.
	 *
	 *	It must be hmac protected to prevent insertion of arbitrary
	 *	State by an inside attacker.
	 *
	 *	If we won't actually use the State (server config doesn't
	 *	allow async), we just use a trivial State.
	 *
	 *	We always create at least a trivial State, so mod_authorize()
	 *	can quickly pass on to mod_authenticate().
	 */
	{
		int32_t now = htonl(time(NULL)); //!< Low-order 32 bits on LP64.

		char gen_state[OTP_MAX_RADSTATE_LEN];
		size_t len;
		VALUE_PAIR *vp;

		len = otp_gen_state(gen_state, challenge, inst->challenge_len,
				    0, now, inst->hmac_key);

		vp = fr_pair_afrom_num(request->reply, PW_STATE, 0);
		if (!vp) {
			return RLM_MODULE_FAIL;
		}

		fr_pair_value_memcpy(vp, (uint8_t const *) gen_state, len);
		fr_pair_add(&request->reply->vps, vp);
	}

	/*
	 *	Add the challenge to the reply.
	 */
	{
		VALUE_PAIR *vp;

		char *expanded = NULL;
		ssize_t len;

		/*
		 *	First add the internal OTP challenge attribute to
		 *	the reply list.
		 */
		vp = fr_pair_afrom_num(request->reply, PW_OTP_CHALLENGE, 0);
		if (!vp) {
			return RLM_MODULE_FAIL;
		}

		fr_pair_value_strcpy(vp, challenge);
		vp->op = T_OP_SET;

		fr_pair_add(&request->reply->vps, vp);

		/*
		 *	Then add the message to the user to they known
		 *	what the challenge value is.
		 */

		len = radius_axlat(&expanded, request, inst->chal_prompt, NULL, NULL);
		if (len < 0) {
			return RLM_MODULE_FAIL;
		}

		vp = fr_pair_afrom_num(request->reply, PW_REPLY_MESSAGE, 0);
		if (!vp) {
			talloc_free(expanded);
			return RLM_MODULE_FAIL;
		}

		(void) talloc_steal(vp, expanded);
		vp->vp_strvalue = expanded;
		vp->vp_length = len;
		vp->op = T_OP_SET;
		vp->type = VT_DATA;

		fr_pair_add(&request->reply->vps, vp);
	}

	/*
	 *	Mark the packet as an Access-Challenge packet.
	 * 	The server will take care of sending it to the user.
	 */
	request->reply->code = PW_CODE_ACCESS_CHALLENGE;
	DEBUG("rlm_otp: Sending Access-Challenge");

	if (!auth_type_found) {
		pair_make_config("Auth-Type", inst->name, T_OP_EQ);
	}

	return RLM_MODULE_HANDLED;
}
Esempio n. 6
0
/** Convert group membership information into attributes
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[in] request Current request.
 * @param[in,out] pconn to use. May change as this function calls functions which auto re-connect.
 * @return One of the RLM_MODULE_* values.
 */
rlm_rcode_t rlm_ldap_cacheable_groupobj(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t **pconn)
{
	rlm_rcode_t rcode = RLM_MODULE_OK;
	ldap_rcode_t status;
	int ldap_errno;

	LDAPMessage *result = NULL;
	LDAPMessage *entry;

	char const *base_dn;
	char base_dn_buff[LDAP_MAX_DN_STR_LEN];

	char const *filters[] = { inst->groupobj_filter, inst->groupobj_membership_filter };
	char filter[LDAP_MAX_FILTER_STR_LEN + 1];

	char const *attrs[] = { inst->groupobj_name_attr, NULL };

	VALUE_PAIR *vp;
	char *dn;

	rad_assert(inst->groupobj_base_dn);

	if (!inst->groupobj_membership_filter) {
		RDEBUG2("Skipping caching group objects as directive 'group.membership_filter' is not set");

		return RLM_MODULE_OK;
	}

	if (rlm_ldap_xlat_filter(request,
				 filters, sizeof(filters) / sizeof(*filters),
				 filter, sizeof(filter)) < 0) {
		return RLM_MODULE_INVALID;
	}

	if (tmpl_expand(&base_dn, base_dn_buff, sizeof(base_dn_buff), request,
			inst->groupobj_base_dn, rlm_ldap_escape_func, NULL) < 0) {
		REDEBUG("Failed creating base_dn");

		return RLM_MODULE_INVALID;
	}

	status = rlm_ldap_search(&result, inst, request, pconn, base_dn,
				 inst->groupobj_scope, filter, attrs, NULL, NULL);
	switch (status) {
	case LDAP_PROC_SUCCESS:
		break;

	case LDAP_PROC_NO_RESULT:
		RDEBUG2("No cacheable group memberships found in group objects");
		goto finish;

	default:
		rcode = RLM_MODULE_FAIL;
		goto finish;
	}

	entry = ldap_first_entry((*pconn)->handle, result);
	if (!entry) {
		ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
		REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));

		goto finish;
	}

	RDEBUG("Adding cacheable group object memberships");
	do {
		if (inst->cacheable_group_dn) {
			dn = ldap_get_dn((*pconn)->handle, entry);
			if (!dn) {
				ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
				REDEBUG("Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));

				goto finish;
			}
			rlm_ldap_normalise_dn(dn, dn);

			MEM(vp = pair_make_config(inst->cache_da->name, NULL, T_OP_ADD));
			fr_pair_value_strcpy(vp, dn);

			RINDENT();
			RDEBUG("&control:%s += \"%s\"", inst->cache_da->name, dn);
			REXDENT();
			ldap_memfree(dn);
		}

		if (inst->cacheable_group_name) {
			struct berval **values;

			values = ldap_get_values_len((*pconn)->handle, entry, inst->groupobj_name_attr);
			if (!values) continue;

			MEM(vp = pair_make_config(inst->cache_da->name, NULL, T_OP_ADD));
			fr_pair_value_bstrncpy(vp, values[0]->bv_val, values[0]->bv_len);

			RINDENT();
			RDEBUG("&control:%s += \"%.*s\"", inst->cache_da->name,
			       (int)values[0]->bv_len, values[0]->bv_val);
			REXDENT();

			ldap_value_free_len(values);
		}
	} while ((entry = ldap_next_entry((*pconn)->handle, entry)));

finish:
	if (result) ldap_msgfree(result);

	return rcode;
}