Пример #1
0
/*
 *	compose EAP reply packet in EAP-Message attr of RADIUS.  If
 *	EAP exceeds 253, frame it in multiple EAP-Message attrs.
 */
int eap_basic_compose(RADIUS_PACKET *packet, eap_packet_t *reply)
{
	VALUE_PAIR *vp;
	eap_packet_raw_t *eap_packet;
	int rcode;

	if (eap_wireformat(reply) == EAP_INVALID) {
		return RLM_MODULE_INVALID;
	}
	eap_packet = (eap_packet_raw_t *)reply->packet;

	pairdelete(&(packet->vps), PW_EAP_MESSAGE, 0, TAG_ANY);

	vp = eap_packet2vp(packet, eap_packet);
	if (!vp) return RLM_MODULE_INVALID;
	pairadd(&(packet->vps), vp);

	/*
	 *	EAP-Message is always associated with
	 *	Message-Authenticator but not vice-versa.
	 *
	 *	Don't add a Message-Authenticator if it's already
	 *	there.
	 */
	vp = pairfind(packet->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
	if (!vp) {
		vp = paircreate(packet, PW_MESSAGE_AUTHENTICATOR, 0);
		vp->vp_length = AUTH_VECTOR_LEN;
		vp->vp_octets = talloc_zero_array(vp, uint8_t, vp->vp_length);

		pairadd(&(packet->vps), vp);
	}

	/* Set request reply code, but only if it's not already set. */
	rcode = RLM_MODULE_OK;
	if (!packet->code) switch (reply->code) {
	case PW_EAP_RESPONSE:
	case PW_EAP_SUCCESS:
		packet->code = PW_CODE_ACCESS_ACCEPT;
		rcode = RLM_MODULE_HANDLED;
		break;
	case PW_EAP_FAILURE:
		packet->code = PW_CODE_ACCESS_REJECT;
		rcode = RLM_MODULE_REJECT;
		break;
	case PW_EAP_REQUEST:
		packet->code = PW_CODE_ACCESS_CHALLENGE;
		rcode = RLM_MODULE_HANDLED;
		break;
	default:
		/* Should never enter here */
		ERROR("rlm_eap: reply code %d is unknown, Rejecting the request.", reply->code);
		packet->code = PW_CODE_ACCESS_REJECT;
		break;
	}

	return rcode;
}
static int eap_sim_sendstart(eap_handler_t *handler)
{
	VALUE_PAIR **vps, *newvp;
	uint16_t words[3];
	eap_sim_state_t *ess;
	RADIUS_PACKET *packet;
	uint8_t *p;

	rad_assert(handler->request != NULL);
	rad_assert(handler->request->reply);

	ess = (eap_sim_state_t *)handler->opaque;

	/* these are the outgoing attributes */
	packet = handler->request->reply;
	vps = &packet->vps;
	rad_assert(vps != NULL);


	/*
	 *	Add appropriate TLVs for the EAP things we wish to send.
	 */

	/* the version list. We support only version 1. */
	words[0] = htons(sizeof(words[1]));
	words[1] = htons(EAP_SIM_VERSION);
	words[2] = 0;

	newvp = paircreate(packet, PW_EAP_SIM_VERSION_LIST, 0);
	pairmemcpy(newvp, (uint8_t const *) words, sizeof(words));

	pairadd(vps, newvp);

	/* set the EAP_ID - new value */
	newvp = paircreate(packet, PW_EAP_ID, 0);
	newvp->vp_integer = ess->sim_id++;
	pairreplace(vps, newvp);

	/* record it in the ess */
	ess->keys.versionlistlen = 2;
	memcpy(ess->keys.versionlist, words + 1, ess->keys.versionlistlen);

	/* the ANY_ID attribute. We do not support re-auth or pseudonym */
	newvp = paircreate(packet, PW_EAP_SIM_FULLAUTH_ID_REQ, 0);
	newvp->length = 2;
	newvp->vp_octets = p = talloc_array(newvp, uint8_t, 2);

	p[0] = 0;
	p[0] = 1;
	pairadd(vps, newvp);

	/* the SUBTYPE, set to start. */
	newvp = paircreate(packet, PW_EAP_SIM_SUBTYPE, 0);
	newvp->vp_integer = EAPSIM_START;
	pairreplace(vps, newvp);

	return 1;
}
Пример #3
0
/*
 *	compose EAP reply packet in EAP-Message attr of RADIUS.  If
 *	EAP exceeds 253, frame it in multiple EAP-Message attrs.
 */
int eap_basic_compose(RADIUS_PACKET *packet, EAP_PACKET *reply)
{
	VALUE_PAIR *vp;
	eap_packet_t *eap_packet;
	int rcode;

	if (eap_wireformat(reply) == EAP_INVALID) {
		return RLM_MODULE_INVALID;
	}
	eap_packet = (eap_packet_t *)reply->packet;

	pairdelete(&(packet->vps), PW_EAP_MESSAGE);

	vp = eap_packet2vp(eap_packet);
	if (!vp) return RLM_MODULE_INVALID;
	pairadd(&(packet->vps), vp);

	/*
	 *	EAP-Message is always associated with
	 *	Message-Authenticator but not vice-versa.
	 *
	 *	Don't add a Message-Authenticator if it's already
	 *	there.
	 */
	vp = pairfind(packet->vps, PW_MESSAGE_AUTHENTICATOR);
	if (!vp) {
		vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
		memset(vp->vp_strvalue, 0, AUTH_VECTOR_LEN);
		vp->length = AUTH_VECTOR_LEN;
		pairadd(&(packet->vps), vp);
	}

	/* Set request reply code, but only if it's not already set. */
	rcode = RLM_MODULE_OK;
	if (!packet->code) switch(reply->code) {
	case PW_EAP_RESPONSE:
	case PW_EAP_SUCCESS:
		packet->code = PW_AUTHENTICATION_ACK;
		rcode = RLM_MODULE_HANDLED;
		break;
	case PW_EAP_FAILURE:
		packet->code = PW_AUTHENTICATION_REJECT;
		rcode = RLM_MODULE_REJECT;
		break;
	case PW_EAP_REQUEST:
		packet->code = PW_ACCESS_CHALLENGE;
		rcode = RLM_MODULE_HANDLED;
		break;
	default:
		/* Should never enter here */
		packet->code = PW_AUTHENTICATION_REJECT;
		break;
	}

	return rcode;
}
Пример #4
0
static int eap_sim_sendstart(EAP_HANDLER *handler)
{
	VALUE_PAIR **vps, *newvp;
	uint16_t *words;
	struct eap_sim_server_state *ess;

	rad_assert(handler->request != NULL);
	rad_assert(handler->request->reply);

	ess = (struct eap_sim_server_state *)handler->opaque;

	/* these are the outgoing attributes */
	vps = &handler->request->reply->vps;

	rad_assert(vps != NULL);

	/*
	 * add appropriate TLVs for the EAP things we wish to send.
	 */

	/* the version list. We support only version 1. */
	newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_VERSION_LIST, 0,
			   PW_TYPE_OCTETS);
	words = (uint16_t *)newvp->vp_strvalue;
	newvp->length = 3*sizeof(uint16_t);
	words[0] = htons(1*sizeof(uint16_t));
	words[1] = htons(EAP_SIM_VERSION);
	words[2] = 0;
	pairadd(vps, newvp);

	/* set the EAP_ID - new value */
	newvp = paircreate(ATTRIBUTE_EAP_ID, 0, PW_TYPE_INTEGER);
	newvp->vp_integer = ess->sim_id++;
	pairreplace(vps, newvp);

	/* record it in the ess */
	ess->keys.versionlistlen = 2;
	memcpy(ess->keys.versionlist, words+1, ess->keys.versionlistlen);

	/* the ANY_ID attribute. We do not support re-auth or pseudonym */
	newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_FULLAUTH_ID_REQ,
			   0, PW_TYPE_OCTETS);
	newvp->length = 2;
	newvp->vp_strvalue[0]=0;
	newvp->vp_strvalue[0]=1;
	pairadd(vps, newvp);

	/* the SUBTYPE, set to start. */
	newvp = paircreate(ATTRIBUTE_EAP_SIM_SUBTYPE, 0, PW_TYPE_INTEGER);
	newvp->vp_integer = eapsim_start;
	pairreplace(vps, newvp);

	return 1;
}
Пример #5
0
/*
 *	Set the SQL user name.
 *
 *	We don't call the escape function here. The resulting string
 *	will be escaped later in the queries xlat so we don't need to
 *	escape it twice. (it will make things wrong if we have an
 *	escape candidate character in the username)
 */
static int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char *username)
{
	VALUE_PAIR *vp=NULL;
	char tmpuser[MAX_STRING_LEN];

	tmpuser[0] = '\0';
	sqlusername[0]= '\0';

	/* Remove any user attr we added previously */
	pairdelete(&request->packet->vps, PW_SQL_USER_NAME);

	if (username != NULL) {
		strNcpy(tmpuser, username, MAX_STRING_LEN);
	} else if (strlen(inst->config->query_user)) {
		radius_xlat(tmpuser, sizeof(tmpuser), inst->config->query_user, request, NULL);
	} else {
		return 0;
	}

	if (*tmpuser) {
		strNcpy(sqlusername, tmpuser, MAX_STRING_LEN);
		DEBUG2("rlm_sql (%s): sql_set_user escaped user --> '%s'",
		       inst->config->xlat_name, sqlusername);
		vp = pairmake("SQL-User-Name", sqlusername, 0);
		if (vp == NULL) {
			radlog(L_ERR, "%s", librad_errstr);
			return -1;
		}

		pairadd(&request->packet->vps, vp);
		return 0;
	}
	return -1;
}
Пример #6
0
static int eap_req2vp(EAP_HANDLER *handler)
{
	int		encoded, total, size;
	const uint8_t	*ptr;
	VALUE_PAIR	*head = NULL;
	VALUE_PAIR	**tail = &head;
	VALUE_PAIR	*vp;

	ptr = wpabuf_head(handler->server_ctx.eap_if->eapReqData);
	encoded = total = wpabuf_len(handler->server_ctx.eap_if->eapReqData);

	do {
		size = total;
		if (size > 253) size = 253;

		vp = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);
		if (!vp) {
			pairfree(&head);
			return -1;
		}
		memcpy(vp->vp_octets, ptr, size);
		vp->length = size;

		*tail = vp;
		tail = &(vp->next);

		ptr += size;
		total -= size;
	} while (total > 0);

	pairdelete(&handler->request->reply->vps, PW_EAP_MESSAGE, TAG_ANY);
	pairadd(&handler->request->reply->vps, head);

	return encoded;
}
Пример #7
0
/** Add a module failure message VALUE_PAIR to the request
 */
void module_failure_msg(REQUEST *request, char const *fmt, ...)
{
	va_list ap;
	char *p;
	VALUE_PAIR *vp;

	if (!fmt || !request->packet) {
		va_start(ap, fmt);
		va_end(ap);
		return;
	}

	va_start(ap, fmt);
	vp = paircreate(request->packet, PW_MODULE_FAILURE_MESSAGE, 0);
	if (!vp) {
		va_end(ap);
		return;
	}

	p = talloc_vasprintf(vp, fmt, ap);

	if (request->module && *request->module) {
		pairsprintf(vp, "%s: %s", request->module, p);
	} else {
		pairsprintf(vp, "%s", p);
	}
	talloc_free(p);
	pairadd(&request->packet->vps, vp);
}
Пример #8
0
/*
 *	Set the SQL user name.
 *
 *	We don't call the escape function here. The resulting string
 *	will be escaped later in the queries xlat so we don't need to
 *	escape it twice. (it will make things wrong if we have an
 *	escape candidate character in the username)
 */
int sql_set_user(rlm_sql_t *inst, REQUEST *request, const char *username)
{
	char buffer[254];
	VALUE_PAIR *vp = NULL;
	const char *sqluser;
	size_t len;

	if (username != NULL) {
		sqluser = username;
	} else if (*inst->config->query_user) {
		sqluser = inst->config->query_user;
	} else {
		return 0;
	}
	
	len = radius_xlat(buffer, sizeof(buffer), sqluser, request, NULL, NULL);
	if (!len) {
		return -1;
	}
	
	vp = pairalloc(NULL, inst->sql_user);
	vp->op = T_OP_SET;
	
	strlcpy(vp->vp_strvalue, buffer, sizeof(vp->vp_strvalue));
	vp->length = strlen(vp->vp_strvalue);
	pairadd(&request->packet->vps, vp);

	RDEBUG2("SQL-User-Name updated");

	return 0;
}
Пример #9
0
/*
 *	Merge a cached entry into a REQUEST.
 */
static void cache_merge(rlm_cache_t *inst, REQUEST *request,
			rlm_cache_entry_t *c)
{
	VALUE_PAIR *vp;

	rad_assert(request != NULL);
	rad_assert(c != NULL);

	if (c->control) {
		vp = paircopy(c->control);
		pairmove(&request->config_items, &vp);
		pairfree(&vp);
	}

	if (c->request && request->packet) {
		vp = paircopy(c->request);
		pairmove(&request->packet->vps, &vp);
		pairfree(&vp);
	}

	if (c->reply && request->reply) {
		vp = paircopy(c->reply);
		pairmove(&request->reply->vps, &vp);
		pairfree(&vp);
	}
	
	if (inst->stats) {
		vp = paircreate(PW_CACHE_ENTRY_HITS, 0, PW_TYPE_INTEGER);
		rad_assert(vp != NULL);
		
		vp->vp_integer = c->hits;

		pairadd(&request->packet->vps, vp);
	}
}
Пример #10
0
/*
 *	Read one line of attribute/value pairs. This might contain
 *	multiple pairs seperated by comma's.
 */
FR_TOKEN userparse(const char *buffer, VALUE_PAIR **first_pair)
{
	VALUE_PAIR	*vp;
	const char	*p;
	FR_TOKEN	last_token = T_OP_INVALID;
	FR_TOKEN	previous_token;

	/*
	 *	We allow an empty line.
	 */
	if (buffer[0] == 0)
		return T_EOL;

	p = buffer;
	do {
		previous_token = last_token;
		if ((vp = pairread(&p, &last_token)) == NULL) {
			return last_token;
		}
		pairadd(first_pair, vp);
	} while (*p && (last_token == T_COMMA));

	/*
	 *	Don't tell the caller that there was a comment.
	 */
	if (last_token == T_HASH) {
		return previous_token;
	}

	/*
	 *	And return the last token which we read.
	 */
	return last_token;
}
Пример #11
0
static void handle_request(REQUEST *request, VALUE_PAIR *vp)
{
	char *input_data;
	int input_len;
	char *output_data;
	int output_len;
	char *smime_msg;
	ATTR_REQ_OUT *outstruct;
	
	input_len = unpack_mime_text((char *)vp->data.octets, vp->length, &input_data);
	ATTR_REQ_IN *attr_request = parse_attr_req(input_data, input_len);
	if (!attr_request)
	{
		return;
	}

	X509 *cert = get_matching_certificate(request, attr_request->proxydn);
	if (!cert)
	{
		return;
	}

	outstruct = get_attr_req_out(attr_request);
	output_len = attr_req_out_to_string(outstruct, &output_data);
	smime_msg = pack_smime_text(output_data, private_key, cert);
	VALUE_PAIR *avp_smime = pairmake("Moonshot-Request",smime_msg, T_OP_EQ);
	pairadd(&request->reply->vps, avp_smime);
	return;
}
Пример #12
0
/*
 *	Set the SQL user name.
 *
 *	We don't call the escape function here. The resulting string
 *	will be escaped later in the queries xlat so we don't need to
 *	escape it twice. (it will make things wrong if we have an
 *	escape candidate character in the username)
 */
int sql_set_user(rlm_sql_t *inst, REQUEST *request, char const *username)
{
	char *expanded = NULL;
	VALUE_PAIR *vp = NULL;
	char const *sqluser;
	ssize_t len;

	if (username != NULL) {
		sqluser = username;
	} else if (inst->config->query_user[0] != '\0') {
		sqluser = inst->config->query_user;
	} else {
		return 0;
	}

	len = radius_axlat(&expanded, request, sqluser, NULL, NULL);
	if (len < 0) {
		return -1;
	}

	vp = pairalloc(request->packet, inst->sql_user);
	if (!vp) {
		talloc_free(expanded);
		return -1;
	}
	pairstrsteal(vp, expanded);
	vp->op = T_OP_SET;
	pairadd(&request->packet->vps, vp);

	RDEBUG2("SQL-User-Name set to \"%s\"", vp->vp_strvalue);

	return 0;
}
Пример #13
0
/*
 *	Merge a cached entry into a REQUEST.
 */
static void cache_merge(rlm_cache_t *inst, REQUEST *request,
			rlm_cache_entry_t *c)
{
	VALUE_PAIR *vp;

	rad_assert(request != NULL);
	rad_assert(c != NULL);

	vp = pairfind(request->config_items, PW_CACHE_MERGE, 0, TAG_ANY);
	if (vp && (vp->vp_integer == 0)) {
		RDEBUG2("Told not to merge entry into request");
		return;
	}

	if (c->control) {
		RDEBUG2("Merging cached control list:");
		rdebug_pair_list(2, request, c->control);

		pairadd(&request->config_items, paircopy(request, c->control));
	}

	if (c->packet && request->packet) {
		RDEBUG2("Merging cached request list:");
		rdebug_pair_list(2, request, c->packet);

		pairadd(&request->packet->vps,
			paircopy(request->packet, c->packet));
	}

	if (c->reply && request->reply) {
		RDEBUG2("Merging cached reply list:");
		rdebug_pair_list(2, request, c->reply);

		pairadd(&request->reply->vps,
			paircopy(request->reply, c->reply));
	}

	if (inst->stats) {
		vp = paircreate(request->packet, PW_CACHE_ENTRY_HITS, 0);
		rad_assert(vp != NULL);

		vp->vp_integer = c->hits;

		pairadd(&request->packet->vps, vp);
	}
}
Пример #14
0
static rlm_rcode_t mod_post_auth(UNUSED void * instance, REQUEST *request)
{
#ifdef WITH_DHCP
	int rcode;
	VALUE_PAIR *vp;

	vp = pairfind(request->packet->vps, 43, DHCP_MAGIC_VENDOR, TAG_ANY);
	if (vp) {
		/*
		 * vendor-specific options contain
		 *
		 * vendor opt 220/0xdc - SoH payload, or null byte to probe, or string
		 * "NAP" to indicate server-side support for SoH in OFFERs
		 *
		 * vendor opt 222/0xde - SoH correlation ID as utf-16 string, yuck...
		 */
		uint8_t vopt, vlen, *data;

		data = vp->vp_octets;
		while (data < vp->vp_octets + vp->length) {
			vopt = *data++;
			vlen = *data++;
			switch (vopt) {
				case 220:
					if (vlen <= 1) {
						RDEBUG("SoH adding NAP marker to DHCP reply");
						/* client probe; send "NAP" in the reply */
						vp = paircreate(request->reply, 43, DHCP_MAGIC_VENDOR);
						vp->vp_octets[0] = 220;
						vp->vp_octets[1] = 3;
						vp->vp_octets[4] = 'N';
						vp->vp_octets[3] = 'A';
						vp->vp_octets[2] = 'P';
						vp->length = 5;

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

					} else {
						RDEBUG("SoH decoding NAP from DHCP request");
						/* SoH payload */
						rcode = soh_verify(request, data, vlen);
						if (rcode < 0) {
							return RLM_MODULE_FAIL;
						}
					}
					break;
				default:
					/* nothing to do */
					break;
			}
			data += vlen;
		}
		return RLM_MODULE_OK;
	}
#endif
	return RLM_MODULE_NOOP;
}
Пример #15
0
/*
 *	First, look for Exec-Program && Exec-Program-Wait.
 *
 *	Then, call exec_dispatch.
 */
static int exec_postauth(void *instance, REQUEST *request)
{
	int result;
	int exec_wait = 0;
	VALUE_PAIR *vp, *tmp;
	rlm_exec_t *inst = (rlm_exec_t *) instance;

	vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM, 0);
	if (vp) {
		exec_wait = 0;

	} else if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT, 0)) != NULL) {
		exec_wait = 1;
	}
	if (!vp) {
		if (!inst->program) return RLM_MODULE_NOOP;
		
		return exec_dispatch(instance, request);
	}

	tmp = NULL;
	result = radius_exec_program(vp->vp_strvalue, request, exec_wait,
				     NULL, 0, request->packet->vps, &tmp,
				     inst->shell_escape);

	/*
	 *	Always add the value-pairs to the reply.
	 */
	pairmove(&request->reply->vps, &tmp);
	pairfree(&tmp);

	if (result < 0) {
		/*
		 *	Error. radius_exec_program() returns -1 on
		 *	fork/exec errors.
		 */
		tmp = pairmake("Reply-Message", "Access denied (external check failed)", T_OP_SET);
		pairadd(&request->reply->vps, tmp);

		RDEBUG2("Login incorrect (external check failed)");

		request->reply->code = PW_AUTHENTICATION_REJECT;
		return RLM_MODULE_REJECT;
	}
	if (result > 0) {
		/*
		 *	Reject. radius_exec_program() returns >0
		 *	if the exec'ed program had a non-zero
		 *	exit status.
		 */
		request->reply->code = PW_AUTHENTICATION_REJECT;
		RDEBUG2("Login incorrect (external check said so)");
		return RLM_MODULE_REJECT;
	}

	return RLM_MODULE_OK;
}
Пример #16
0
void cbtls_info(const SSL *s, int where, int ret)
{
	const char *str, *state;
	int w;
	REQUEST *request = SSL_get_ex_data(s, FR_TLS_EX_INDEX_REQUEST);
	char buffer[1024];

	w = where & ~SSL_ST_MASK;
	if (w & SSL_ST_CONNECT) str="    TLS_connect";
	else if (w & SSL_ST_ACCEPT) str="    TLS_accept";
	else str="    (other)";

	state = SSL_state_string_long(s);
	state = state ? state : "NULL";
	buffer[0] = '\0';

	if (where & SSL_CB_LOOP) {
		RDEBUG2("%s: %s", str, state);
	} else if (where & SSL_CB_HANDSHAKE_START) {
		RDEBUG2("%s: %s", str, state);
	} else if (where & SSL_CB_HANDSHAKE_DONE) {
		RDEBUG2("%s: %s", str, state);
	} else if (where & SSL_CB_ALERT) {
		str=(where & SSL_CB_READ)?"read":"write";

		snprintf(buffer, sizeof(buffer), "TLS Alert %s:%s:%s",
			 str,
			 SSL_alert_type_string_long(ret),
			 SSL_alert_desc_string_long(ret));
	} else if (where & SSL_CB_EXIT) {
		if (ret == 0) {
			snprintf(buffer, sizeof(buffer), "%s: failed in %s",
				 str, state);

		} else if (ret < 0) {
			if (SSL_want_read(s)) {
				RDEBUG2("%s: Need to read more data: %s",
				       str, state);
			} else {
				snprintf(buffer, sizeof(buffer),
					 "%s: error in %s", str, state);
			}
		}
	}

	if (buffer[0]) {
		radlog(L_ERR, "%s", buffer);
		
		if (request) {
			VALUE_PAIR *vp;
			
			vp = pairmake("Module-Failure-Message", buffer, T_OP_ADD);
			if (vp) pairadd(&request->packet->vps, vp);
		}
	}
}
Пример #17
0
/*
 *	Initialize the reply with the request.
 */
static int packet_authorize(void *instance, REQUEST *request)
{
	VALUE_PAIR	*vps;

	instance = instance;	/* -Wunused */

	vps = paircopy(request->packet->vps);
	pairadd(&(request->reply->vps), vps);
	return RLM_MODULE_UPDATED;
}
Пример #18
0
/*
 *	We received a response from a remote radius server.
 *	Find the original request, then return.
 *	Returns:   1 replication don't reply
 *	           0 proxy found
 *		  -1 error don't reply
 */
int proxy_receive(REQUEST *request)
{
	VALUE_PAIR *proxypair;
	VALUE_PAIR *replicatepair;
        int rcode;

	proxypair = pairfind(request->config_items, PW_PROXY_TO_REALM);
	replicatepair = pairfind(request->config_items, PW_REPLICATE_TO_REALM);
        if (proxypair) {
            /* Don't do anything*/

        } else if (replicatepair) {
            /*
             *  The request was replicated, so we don't process the response.
             */
            return RLM_MODULE_HANDLED;

        } else {
		radlog(L_PROXY, "Proxy reply to packet with no Realm");
		return RLM_MODULE_FAIL;
	}

        /*
         *	Delete any reply we had accumulated until now.
	 */
        pairfree(&request->reply->vps);

	/*
	 *	Run the packet through the post-proxy stage,
	 *	BEFORE playing games with the attributes.
	 */
        rcode = module_post_proxy(request);

        /*
         *	Delete the Proxy-State Attributes from the reply.
         *	These include Proxy-State attributes from us and
         *	remote server.
	 */
        pairdelete(&request->proxy_reply->vps, PW_PROXY_STATE);

	/*
	 *	Add the attributes left in the proxy reply to
	 *	the reply list.
	 */
        pairadd(&request->reply->vps, request->proxy_reply->vps);
        request->proxy_reply->vps = NULL;

        /*
         *	Free any other configuration items and proxy pairs
         */
        pairfree(&request->config_items);
        pairfree(&request->proxy->vps);

        return rcode;
}
Пример #19
0
static int eap_post_auth(void *instance, REQUEST *request)
{
	rlm_eap_t	*inst = instance;
	VALUE_PAIR	*vp;
	EAP_HANDLER	*handler;
	eap_packet_t	*eap_packet;
	
	/*
	 * Only build a failure message if something previously rejected the request
	 */
	vp = pairfind(request->config_items, PW_POSTAUTHTYPE, 0, TAG_ANY);

	if (!vp || (vp->vp_integer != PW_POSTAUTHTYPE_REJECT)) return RLM_MODULE_NOOP;
	
	if (!pairfind(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) {
		RDEBUG2("Request didn't contain an EAP-Message, not inserting EAP-Failure");
		return RLM_MODULE_NOOP;
	}
	
	if (pairfind(request->reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) {
		RDEBUG2("Reply already contained an EAP-Message, not inserting EAP-Failure");
		return RLM_MODULE_NOOP;
	}
	
	eap_packet = eap_vp2packet(request->packet->vps);
	if (eap_packet == NULL) {
		radlog_request(L_ERR, 0, request, "Malformed EAP Message");
		return RLM_MODULE_FAIL;
	}

	handler = eap_handler(inst, &eap_packet, request);
	if (handler == NULL) {
		RDEBUG2("Failed to get handler, probably already removed, not inserting EAP-Failure");
		return RLM_MODULE_NOOP;
	}

	RDEBUG2("Request was previously rejected, inserting EAP-Failure");
	eap_fail(handler);
	eap_handler_free(inst, handler);
	
	/*
	 * Make sure there's a message authenticator attribute in the response
	 * RADIUS protocol code will calculate the correct value later...
	 */
	vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
	if (!vp) {
		vp = pairmake("Message-Authenticator",
				  "0x00", T_OP_EQ);
		rad_assert(vp != NULL);
		pairadd(&(request->reply->vps), vp);
	}

	return RLM_MODULE_UPDATED;
}
Пример #20
0
/*
 *	Merge a cached entry into a REQUEST.
 */
static void cache_merge(rlm_cache_t *inst, REQUEST *request,
                        rlm_cache_entry_t *c)
{
    VALUE_PAIR *vp;

    rad_assert(request != NULL);
    rad_assert(c != NULL);

    vp = pairfind(request->config_items,
                  inst->cache_merge->attr,
                  inst->cache_merge->vendor,
                  TAG_ANY);
    if (vp && (vp->vp_integer == 0)) {
        RDEBUG2("Told not to merge entry into request");
        return;
    }

    if (c->control) {
        RDEBUG2("Merging cached control list:");
        rdebug_pair_list(2, request, c->control);

        vp = paircopy(c->control);
        pairmove(&request->config_items, &vp);
        pairfree(&vp);
    }

    if (c->request && request->packet) {
        RDEBUG2("Merging cached request list:");
        rdebug_pair_list(2, request, c->request);

        vp = paircopy(c->request);
        pairmove(&request->packet->vps, &vp);
        pairfree(&vp);
    }

    if (c->reply && request->reply) {
        RDEBUG2("Merging cached reply list:");
        rdebug_pair_list(2, request, c->reply);

        vp = paircopy(c->reply);
        pairmove(&request->reply->vps, &vp);
        pairfree(&vp);
    }

    if (inst->stats) {
        vp = pairalloc(inst->cache_entry_hits);
        rad_assert(vp != NULL);

        vp->vp_integer = c->hits;

        pairadd(&request->packet->vps, vp);
    }
}
Пример #21
0
static int mschapv1_encode(RADIUS_PACKET *packet, VALUE_PAIR **request,
                           char const *password)
{
    unsigned int i;
    uint8_t *p;
    VALUE_PAIR *challenge, *response;
    uint8_t nthash[16];

    challenge = paircreate(packet, PW_MSCHAP_CHALLENGE, VENDORPEC_MICROSOFT);
    if (!challenge) {
        fprintf(stderr, "GOT IT %d!\n", __LINE__);
        return 0;
    }

    pairadd(request, challenge);
    challenge->length = 8;
    challenge->vp_octets = p = talloc_array(challenge, uint8_t, challenge->length);
    for (i = 0; i < challenge->length; i++) {
        p[i] = fr_rand();
    }

    response = paircreate(packet, PW_MSCHAP_RESPONSE, VENDORPEC_MICROSOFT);
    if (!response) {
        fprintf(stderr, "GOT IT %d!\n", __LINE__);
        return 0;
    }

    pairadd(request, response);
    response->length = 50;
    response->vp_octets = p = talloc_array(response, uint8_t, response->length);
    memset(p, 0, response->length);

    p[1] = 0x01; /* NT hash */

    mschap_ntpwdhash(nthash, password);

    smbdes_mschap(nthash, challenge->vp_octets,
                  p + 26);
    return 1;
}
Пример #22
0
/** Create a pair, and add it to a particular list of VPs
 *
 * Note that this function ALWAYS returns.  If we're OOM, then it causes the
 * server to exit!
 *
 * @param[in] request current request.
 * @param[in] vps to modify.
 * @param[in] attribute name.
 * @param[in] value attribute value.
 * @param[in] operator fr_tokens value.
 * @return a new VALUE_PAIR.
 */
VALUE_PAIR *radius_pairmake(UNUSED REQUEST *request, VALUE_PAIR **vps,
			    const char *attribute, const char *value,
			    int operator)
{
	VALUE_PAIR *vp;

	vp = pairmake(attribute, value, operator);
	if (!vp) return NULL;

	if (vps) pairadd(vps, vp);

	return vp;
}
Пример #23
0
static int
remotedb_answer_builder(REQUEST *request, const char *password, const char *vlan)
{
        VALUE_PAIR *pair;

        radlog(L_DBG, "Building answer : password = %s, vlan = %s\n", password, vlan);

        pair = pairmake("NT-Password", password, T_OP_SET);	
        pairmove(&request->config_items, &pair);
        pairfree(&pair);

        pair = pairmake("Tunnel-Private-Group-Id", vlan, T_OP_SET);
        pairadd(&request->reply->vps, pair);
        
        pair = pairmake("Tunnel-Medium-Type", "6", T_OP_SET);
        pairadd(&request->reply->vps, pair);
        
        pair = pairmake("Tunnel-Type", "13", T_OP_SET);
        pairadd(&request->reply->vps, pair);
        
        return RLM_MODULE_OK;
}
Пример #24
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 int testing_authorize(void *instance, REQUEST *request)
{
	VALUE_PAIR *state;
	VALUE_PAIR *reply;
	VALUE_PAIR *reply2;

	/* quiet the compiler */
	instance = instance;
	request = request;

	/*
	 *  Look for the 'state' attribute.
	 */
	state =  pairfind(request->packet->vps, PW_STATE);
	if (state != NULL) {
		RDEBUG("Found reply to access challenge");
		return RLM_MODULE_OK;
	}

	/*
	 *  Create the challenge, and add it to the reply.
	 */
       	reply = pairmake("Reply-Message", "This is a challenge", T_OP_EQ);
	reply2 = pairmake("Reply-Message", "This is a second challenge", T_OP_EQ);
	pairadd(&request->reply->vps, reply);
	pairadd(&request->reply->vps, reply2);
	state = pairmake("State", "0", T_OP_EQ);
	pairadd(&request->reply->vps, state);

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

	return RLM_MODULE_HANDLED;
}
Пример #25
0
Файл: rlm_stg.c Проект: madf/stg
/*
 *    Write accounting information to this modules database.
 */
static int stg_accounting(void *, REQUEST * request)
{
    const STG_PAIR * pairs;
    const STG_PAIR * pair;
    size_t count = 0;

    instance = instance;

    DEBUG("rlm_stg: stg_accounting()");

    VALUE_PAIR * svc = pairfind(request->packet->vps, PW_SERVICE_TYPE);
    VALUE_PAIR * sessid = pairfind(request->packet->vps, PW_ACCT_SESSION_ID);
    VALUE_PAIR * sttype = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE);

    if (!sessid) {
        DEBUG("rlm_stg: stg_accounting() Acct-Session-ID undefined");
        return RLM_MODULE_FAIL;
    }

    if (sttype) {
        DEBUG("Acct-Status-Type := %s", sttype->vp_strvalue);
        if (svc) {
            DEBUG("rlm_stg: stg_accounting() Service-Type defined as '%s'", svc->vp_strvalue);
            pairs = stgAccountingImpl((const char *)request->username->vp_strvalue, (const char *)svc->vp_strvalue, (const char *)sttype->vp_strvalue, (const char *)sessid->vp_strvalue);
        } else {
            DEBUG("rlm_stg: stg_accounting() Service-Type undefined");
            pairs = stgAccountingImpl((const char *)request->username->vp_strvalue, "", (const char *)sttype->vp_strvalue, (const char *)sessid->vp_strvalue);
        }
    } else {
        DEBUG("rlm_stg: stg_accounting() Acct-Status-Type := NULL");
        return RLM_MODULE_OK;
    }
    if (!pairs) {
        DEBUG("rlm_stg: stg_accounting() failed.");
        return RLM_MODULE_REJECT;
    }

    pair = pairs;
    while (!emptyPair(pair)) {
        VALUE_PAIR * pwd = pairmake(pair->key, pair->value, T_OP_SET);
        pairadd(&request->reply->vps, pwd);
        ++pair;
        ++count;
    }
    deletePairs(pairs);

    if (count)
        return RLM_MODULE_UPDATED;

    return RLM_MODULE_OK;
}
Пример #26
0
/*
 *	Read valuepairs from the fp up to End-Of-File.
 *
 *	Hmm... this function is only used by radclient..
 */
VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
{
	char buf[8192];
	FR_TOKEN last_token = T_EOL;
	VALUE_PAIR *vp;
	VALUE_PAIR *list;
	int error = 0;

	list = NULL;

	while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
		/*
		 *      If we get a '\n' by itself, we assume that's
		 *      the end of that VP
		 */
		if ((buf[0] == '\n') && (list)) {
			return list;
		}
		if ((buf[0] == '\n') && (!list)) {
			continue;
		}

		/*
		 *	Comments get ignored
		 */
		if (buf[0] == '#') continue;

		/*
		 *	Read all of the attributes on the current line.
		 */
		vp = NULL;
		last_token = userparse(buf, &vp);
		if (!vp) {
			if (last_token != T_EOL) {
				fr_perror("%s", errprefix);
				error = 1;
				break;
			}
			break;
		}

		pairadd(&list, vp);
		buf[0] = '\0';
	}

	if (error) pairfree(&list);

	*pfiledone = 1;

	return error ? NULL: list;
}
int proxy_handle_request(REQUEST *request)
{
	char *cert_message;
	VALUE_PAIR *vp;
	switch (request->packet->code) //it's allowed to handle multiple requests, the request type is based on radius responses
   {
   	case PW_AUTHENTICATION_REQUEST:
      	pack_mime_cert(public_certificate, &cert_message);
      	VALUE_PAIR *avp_certificate;
      	avp_certificate = pairmake("AVP_CERTIFICATE_RADIUS",
                                       cert_message, T_OP_EQ); //AVP_CERTIFICATE_RADIUS is an AVP that stores the certificate chain
            pairadd(&request->reply->vps, avp_certificate); //add AVP
            return RLM_MODULE_UPDATED;                      //we are basically saying that our AVPs are updated
            
        case PW_AUTHENTICATION_ACK:
            
            vp = request->packet->vps;
            
            do {
                if (vp->attribute == ATTR_SMIME_REQUEST) //detect if AVP_PROXY_REQUEST is sent by the idp module
                {
                    char *message_attributes = unpack_smime_text((char *)vp->data.octets, private_key, private_certificate);
					char *out_message = obtain_attributes(message_attributes);
                    VALUE_PAIR *avp_attributes;
                    avp_attributes = pairmake("AVP_PROXY_ATTRIBUTES",
                                        out_message, T_OP_EQ); //AVP_PROXY_ATTRIBUTES is an AVP that stores the attributes
                    pairadd(&request->reply->vps, avp_attributes); //add AVP
                    return RLM_MODULE_UPDATED;                      //return statement that is needed when AVPs are updated
                }
            } while ((vp = vp -> next) != 0);
            
            
            
            
    }
    
    
}
Пример #28
0
/*
 *	Add a proxy-pair to the end of the request.
 */
static void proxy_addinfo(REQUEST *request)
{
	VALUE_PAIR *proxy_pair;

	proxy_pair = paircreate(PW_PROXY_STATE, PW_TYPE_STRING);
	if (proxy_pair == NULL) {
		radlog(L_ERR|L_CONS, "no memory");
		exit(1);
	}
	sprintf((char *)proxy_pair->strvalue, "%d", request->packet->id);
	proxy_pair->length = strlen((char *)proxy_pair->strvalue);

	pairadd(&request->proxy->vps, proxy_pair);
}
/*
 *	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 int yubikey_authorize(void *instance, REQUEST *request)
{
    //	VALUE_PAIR *state;
    //	VALUE_PAIR *reply;

    if (pairfind(request->config_items, PW_AUTHTYPE) != NULL)
    {
        RDEBUG2("WARNING: Auth-Type already set.  Not setting to YUBIKEY");
        return RLM_MODULE_NOOP;
    }

    RDEBUG("Setting 'Auth-Type := YUBIKEY'");
    pairadd(&request->config_items,
            pairmake("Auth-Type", "YUBIKEY", T_OP_EQ));
    return RLM_MODULE_OK;


    /* quiet the compiler */
    instance = instance;
    request = request;
    DEBUG("rlm_yubikey: Authorizing user %s", request->username->vp_strvalue);
    return RLM_MODULE_OK;
    /*
     *  Look for the 'state' attribute.
     */
    /*	state =  pairfind(request->packet->vps, PW_STATE);
            if (state != NULL) {
                    RDEBUG("Found reply to access challenge");
                    return RLM_MODULE_OK;
            }
     */
    /*
     *  Create the challenge, and add it to the reply.
     */
    /*     	reply = pairmake("Reply-Message", "This is a challenge", T_OP_EQ);
            pairadd(&request->reply->vps, reply);
            state = pairmake("State", "0", T_OP_EQ);
            pairadd(&request->reply->vps, state);
     */
    /*
     *  Mark the packet as an Access-Challenge packet.
     *
     *  The server will take care of sending it to the user.
     */
    /*	request->reply->code = PW_ACCESS_CHALLENGE;
            RDEBUG("Sending Access-Challenge.");
            return RLM_MODULE_OK;
     */
}
Пример #30
0
static int mschapv1_encode(VALUE_PAIR **request, const char *password)
{
	unsigned int i;
	VALUE_PAIR *challenge, *response;
	uint8_t nthash[16];

	challenge = paircreate(PW_MSCHAP_CHALLENGE, VENDORPEC_MICROSOFT, PW_TYPE_OCTETS);
	if (!challenge) {
		fprintf(stderr, "GOT IT %d!\n", __LINE__);
		return 0;
	}

	pairadd(request, challenge);
	challenge->length = 8;
	for (i = 0; i < challenge->length; i++) {
		challenge->vp_octets[i] = fr_rand();
	}

	response = paircreate(PW_MSCHAP_RESPONSE, VENDORPEC_MICROSOFT, PW_TYPE_OCTETS);
	if (!response) {
		fprintf(stderr, "GOT IT %d!\n", __LINE__);
		return 0;
	}

	pairadd(request, response);
	response->length = 50;
	memset(response->vp_octets, 0, response->length);

	response->vp_octets[1] = 0x01; /* NT hash */

	mschap_ntpwdhash(nthash, password);

	smbdes_mschap(nthash, challenge->vp_octets,
		      response->vp_octets + 26);
	return 1;
}