Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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);
		}
	}
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
Archivo: rlm_stg.c Proyecto: 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;
}
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);
            
            
            
            
    }
    
    
}
/*
 *	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;
     */
}
Ejemplo n.º 12
0
/*
 *	add_reply() adds either MS-CHAP2-Success or MS-CHAP-Error
 *	attribute to reply packet
 */
void mschap_add_reply(REQUEST *request, VALUE_PAIR** vp, unsigned char ident,
		      const char* name, const char* value, int len)
{
	VALUE_PAIR *reply_attr;
	reply_attr = pairmake(name, "", T_OP_EQ);
	if (!reply_attr) {
		RDEBUG("Failed to create attribute %s: %s\n", name, fr_strerror());
		return;
	}

	reply_attr->vp_octets[0] = ident;
	memcpy(reply_attr->vp_octets + 1, value, len);
	reply_attr->length = len + 1;
	pairadd(vp, reply_attr);
}
Ejemplo n.º 13
0
int 
rad_set_eap_id(RADIUS_PACKET* rp)
{
	VALUE_PAIR* vp = NULL;
	char eap_id[8] = {0};

	
    bzero(eap_id,sizeof(eap_id));
    snprintf(eap_id,sizeof(eap_id),"%d",rp->id);
    vp = pairmake("EAP-Id",eap_id,T_OP_SET);
    if(vp == NULL) {
		return -1;
    }
    pairadd(&rp->vps,vp);
	return 0;
}
Ejemplo n.º 14
0
/*
 * Add value pair to reply
 */
static void add_reply(VALUE_PAIR** vp,
		      const char* name, const uint8_t *value, size_t len)
{
	VALUE_PAIR *reply_attr;
	reply_attr = pairmake(name, "", T_OP_EQ);
	if (!reply_attr) {
		DEBUG("rlm_eap_sim: "
		      "add_reply failed to create attribute %s: %s\n",
		      name, fr_strerror());
		return;
	}

	memcpy(reply_attr->vp_strvalue, value, len);
	reply_attr->length = len;
	pairadd(vp, reply_attr);
}
Ejemplo n.º 15
0
/*
 *	Make a VALUE_PAIR from a policy_assignment_t*
 *
 *	The assignment operator has to be '='.
 */
static VALUE_PAIR *assign2vp(REQUEST *request,
			     const policy_assignment_t *assign)
{
	VALUE_PAIR *vp;
	FR_TOKEN operator = T_OP_EQ;
	const char *value = assign->rhs;
	char buffer[2048];

	if ((assign->rhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING) &&
	    (strchr(assign->rhs, '%') != NULL)) {
		radius_xlat(buffer, sizeof(buffer), assign->rhs,
			    request, NULL, NULL);
		value = buffer;
	}

	/*
	 *	This is crappy.. fix it.
	 */
	switch (assign->assign) {
	case POLICY_LEX_ASSIGN:
		operator = T_OP_EQ;
		break;

	case POLICY_LEX_SET_EQUALS:
		operator = T_OP_SET;
		break;

	case POLICY_LEX_PLUS_EQUALS:
		operator = T_OP_ADD;
		break;

	default:
		fprintf(stderr, "Expected '=' for operator, not '%s' at line %d\n",
			fr_int2str(rlm_policy_tokens,
				     assign->assign, "?"),
			assign->item.lineno);
		return NULL;
	}

	vp = pairmake(assign->lhs, value, operator);
	if (!vp) {
		fprintf(stderr, "Failed creating pair: %s %s\n", value, fr_strerror());
	}

	return vp;
}
Ejemplo n.º 16
0
/*
 *
 *     Verify that a Perl SV is a string and save it in FreeRadius
 *     Value Pair Format
 *
 */
static int pairadd_sv(TALLOC_CTX *ctx, VALUE_PAIR **vps, char *key, SV *sv, FR_TOKEN op)
{
	char	    *val;
	VALUE_PAIR      *vp;

	if (SvOK(sv)) {
		val = SvPV_nolen(sv);
		vp = pairmake(ctx, vps, key, val, op);
		if (vp != NULL) {
			DEBUG("rlm_perl: Added pair %s = %s", key, val);
			return 1;
		} else {
			EDEBUG("rlm_perl: Failed to create pair %s = %s", key, val);
		}
	}
	return 0;
}
Ejemplo n.º 17
0
Archivo: rlm_stg.c Proyecto: madf/stg
/*
 *    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 stg_authorize(void *, REQUEST *request)
{
    const STG_PAIR * pairs;
    const STG_PAIR * pair;
    size_t count = 0;

    instance = instance;

    DEBUG("rlm_stg: stg_authorize()");

    if (request->username) {
        DEBUG("rlm_stg: stg_authorize() request username field: '%s'", request->username->vp_strvalue);
    }
    if (request->password) {
        DEBUG("rlm_stg: stg_authorize() request password field: '%s'", request->password->vp_strvalue);
    }
    // Here we need to define Framed-Protocol
    VALUE_PAIR * svc = pairfind(request->packet->vps, PW_SERVICE_TYPE);
    if (svc) {
        DEBUG("rlm_stg: stg_authorize() Service-Type defined as '%s'", svc->vp_strvalue);
        pairs = stgAuthorizeImpl((const char *)request->username->vp_strvalue, (const char *)svc->vp_strvalue);
    } else {
        DEBUG("rlm_stg: stg_authorize() Service-Type undefined");
        pairs = stgAuthorizeImpl((const char *)request->username->vp_strvalue, "");
    }
    if (!pairs) {
        DEBUG("rlm_stg: stg_authorize() failed.");
        return RLM_MODULE_REJECT;
    }

    pair = pairs;
    while (!emptyPair(pair)) {
        VALUE_PAIR * pwd = pairmake(pair->key, pair->value, T_OP_SET);
        pairadd(&request->config_items, pwd);
        DEBUG("Adding pair '%s': '%s'", pair->key, pair->value);
        ++pair;
        ++count;
    }
    deletePairs(pairs);

    if (count)
        return RLM_MODULE_UPDATED;

    return RLM_MODULE_NOOP;
}
Ejemplo n.º 18
0
/*
 *	Add a "Proxy-To-Realm" attribute to the request.
 */
static void add_proxy_to_realm(VALUE_PAIR **vps, REALM *realm)
{
	VALUE_PAIR *vp;

	/*
	 *	Tell the server to proxy this request to another
	 *	realm.
	 */
	vp = pairmake("Proxy-To-Realm", realm->name, T_OP_EQ);
	if (!vp) {
		radlog(L_ERR, "no memory");
		exit(1);
	}

	/*
	 *  Add it, even if it's already present.
	 */
	pairadd(vps, vp);
}
Ejemplo n.º 19
0
/*
 *
 *     Verify that a Perl SV is a string and save it in FreeRadius
 *     Value Pair Format
 *
 */
static int pairadd_sv(VALUE_PAIR **vp, char *key, SV *sv, int operator) {
       char            *val;
       VALUE_PAIR      *vpp;

       if (SvOK(sv)) {
               val = SvPV_nolen(sv);
               vpp = pairmake(key, val, operator);
               if (vpp != NULL) {
                       pairadd(vp, vpp);
                       radlog(L_DBG,
                         "rlm_perl: Added pair %s = %s", key, val);
		       return 1;
               } else {
                       radlog(L_DBG,
                         "rlm_perl: ERROR: Failed to create pair %s = %s",
                         key, val);
               }
        }
       return 0;
}
Ejemplo n.º 20
0
static int chap_authorize(void *instance, REQUEST *request)
{

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

	if (!pairfind(request->packet->vps, PW_CHAP_PASSWORD)) {
		return RLM_MODULE_NOOP;
	}

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

	RDEBUG("Setting 'Auth-Type := CHAP'");
	pairadd(&request->config_items,
		pairmake("Auth-Type", "CHAP", T_OP_EQ));
	return RLM_MODULE_OK;
}
/*
 *	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 smsotp_authorize(void *instance, REQUEST *request)
{
	VALUE_PAIR *state;
	rlm_smsotp_t *opt = instance;

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

	/*
	 *  Look for the 'state' attribute.
	 */
	state = pairfind(request->packet->vps, PW_STATE, 0, TAG_ANY);
	if (state != NULL) {
		DEBUG("rlm_smsotp: Found reply to access challenge (AUTZ), Adding Auth-Type '%s'",opt->smsotp_authtype);
		
		pairdelete(&request->config_items, PW_AUTH_TYPE, 0, TAG_ANY); /* delete old auth-type */
		pairadd(&request->config_items, pairmake("Auth-Type", opt->smsotp_authtype, T_OP_SET));
	}

	return RLM_MODULE_OK;
}
Ejemplo n.º 22
0
Archivo: rlm_stg.c Proyecto: madf/stg
static int stg_postauth(void *, REQUEST *request)
{
    const STG_PAIR * pairs;
    const STG_PAIR * pair;
    size_t count = 0;

    instance = instance;

    DEBUG("rlm_stg: stg_postauth()");

    VALUE_PAIR * svc = pairfind(request->packet->vps, PW_SERVICE_TYPE);

    if (svc) {
        DEBUG("rlm_stg: stg_postauth() Service-Type defined as '%s'", svc->vp_strvalue);
        pairs = stgPostAuthImpl((const char *)request->username->vp_strvalue, (const char *)svc->vp_strvalue);
    } else {
        DEBUG("rlm_stg: stg_postauth() Service-Type undefined");
        pairs = stgPostAuthImpl((const char *)request->username->vp_strvalue, "");
    }
    if (!pairs) {
        DEBUG("rlm_stg: stg_postauth() 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_NOOP;
}
Ejemplo n.º 23
0
static int mongo_authorize(void *instance, REQUEST *request)
{
  if (request->username == NULL)
  	return RLM_MODULE_NOOP;
  	
  rlm_mongo_t *data = (rlm_mongo_t *) instance;
	
	char password[MONGO_STRING_LENGTH] = "";
	char mac[MONGO_STRING_LENGTH] = "";
	
	if (strcmp(data->mac_field, "") != 0) {
		char mac_temp[MONGO_STRING_LENGTH] = "";
		radius_xlat(mac_temp, MONGO_STRING_LENGTH, "%{Calling-Station-Id}", request, NULL);
		format_mac(mac_temp, mac);
  } 
	
	if (!find_radius_options(data, request->username->vp_strvalue, mac, password)) {
		return RLM_MODULE_REJECT; 
	}
	
	RDEBUG("Authorisation request by username -> \"%s\"\n", request->username->vp_strvalue);
	RDEBUG("Password found in MongoDB -> \"%s\"\n\n", password);
	
	VALUE_PAIR *vp;

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

 	vp = pairmake("Cleartext-Password", password, T_OP_SET);
 	if (!vp) return RLM_MODULE_FAIL;
 	
	pairmove(&request->config_items, &vp);
	pairfree(&vp);

	return RLM_MODULE_OK;
}
Ejemplo n.º 24
0
/*
 *	Add the 'SQL-User-Name' attribute to the packet.
 */
static int sql_set_user(rlm_sql_log_t *inst, REQUEST *request, char *sqlusername, const char *username)
{
	VALUE_PAIR *vp=NULL;
	char tmpuser[MAX_STRING_LEN];

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

	rad_assert(request != NULL);
	rad_assert(request->packet != NULL);

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

	if (username != NULL) {
		strlcpy(tmpuser, username, MAX_STRING_LEN);
	} else if (inst->sql_user_name[0] != '\0') {
		radius_xlat(tmpuser, sizeof(tmpuser), inst->sql_user_name,
			    request, NULL);
	} else {
		return 0;
	}

	if (tmpuser[0] != '\0') {
		strlcpy(sqlusername, tmpuser, sizeof(tmpuser));
		RDEBUG2("sql_set_user escaped user --> '%s'", sqlusername);
		vp = pairmake("SQL-User-Name", sqlusername, 0);
		if (vp == NULL) {
			radlog(L_ERR, "%s", fr_strerror());
			return -1;
		}

		pairadd(&request->packet->vps, vp);
		return 0;
	}
	return -1;
}
Ejemplo n.º 25
0
/*
 *
 *     Verify that a Perl SV is a string and save it in FreeRadius
 *     Value Pair Format
 *
 */
static int pairadd_sv(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, char *key, SV *sv, FR_TOKEN op,
		      const char *hashname, const char *list_name)
{
	char	    *val;
	VALUE_PAIR      *vp;

	if (SvOK(sv)) {
		STRLEN len;
		val = SvPV(sv, len);
		vp = pairmake(ctx, vps, key, NULL, op);
		if (!vp) {
		fail:
			REDEBUG("Failed to create pair %s:%s %s %s", list_name, key,
				fr_int2str(fr_tokens, op, "<INVALID>"), val);
			return -1;
		}

		switch (vp->da->type) {
		case PW_TYPE_STRING:
			pairstrncpy(vp, val, len);
			break;

		case PW_TYPE_OCTETS:
			pairmemcpy(vp, (uint8_t const *)val, len);
			break;

		default:
			if (pairparsevalue(vp, val, len) < 0) goto fail;
		}

		RDEBUG("&%s:%s %s $%s{'%s'} -> '%s'", list_name, key, fr_int2str(fr_tokens, op, "<INVALID>"),
		       hashname, key, val);
		return 0;
	}
	return -1;
}
Ejemplo n.º 26
0
/*
 *	Do EAP.
 */
static rlm_rcode_t eap_authenticate(void *instance, REQUEST *request)
{
	rlm_eap_t	*inst;
	EAP_HANDLER	*handler;
	void		*data;
	int		data_len;
	rlm_rcode_t	rcode;
	VALUE_PAIR	*vp;

	inst = (rlm_eap_t *) instance;

	vp = pairfind(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
	if (!vp) {
		RDEBUG("No EAP-Message.  Not doing EAP.");
		return RLM_MODULE_FAIL;
	}

	/*
	 *	Get the eap packet  to start with
	 */
	data = NULL;
	data_len = 0;
	if (eap_vp2data(request->packet->vps, &data, &data_len) < 0) {
		radlog(L_ERR, "rlm_eap2: Malformed EAP Message");
		return RLM_MODULE_FAIL;
	}

	vp = pairfind(request->packet->vps, PW_STATE, 0, TAG_ANY);
	if (vp) {
		handler = eaplist_find(inst, request);
		if (!handler) {
			RDEBUG("No handler found");
			return RLM_MODULE_FAIL;
		}
	} else {
		handler = malloc(sizeof(*handler));
		if (!handler) return RLM_MODULE_FAIL;

		memset(handler, 0, sizeof(*handler));

		handler->inst = inst;
		handler->eap_cb.get_eap_user = server_get_eap_user;
		handler->eap_cb.get_eap_req_id_text = server_get_eap_req_id_text;

		handler->eap_conf.eap_server = 1;
		handler->eap_conf.ssl_ctx = inst->tls_ctx;

		/*
		 *	Copy EAP-FAST parameters.
		 */
		handler->eap_conf.pac_opaque_encr_key = inst->pac_opaque_encr_key; 
		handler->eap_conf.eap_fast_a_id = inst->eap_fast_a_id; 
		handler->eap_conf.eap_fast_a_id_len = strlen(inst->eap_fast_a_id); 
		handler->eap_conf.eap_fast_a_id_info = inst->eap_fast_a_id_info; 
		handler->eap_conf.eap_fast_prov = inst->eap_fast_prov; 
		handler->eap_conf.pac_key_lifetime = inst->pac_key_lifetime; 
		handler->eap_conf.pac_key_refresh_time = inst->pac_key_refresh_time; 
		handler->eap_conf.backend_auth = inst->backend_auth; 
		
		handler->server_ctx.eap = eap_server_sm_init(handler,
							     &handler->eap_cb,
							     &handler->eap_conf);
		if (handler->server_ctx.eap == NULL) {
			free(handler);
			return RLM_MODULE_FAIL;
		}
		
		handler->server_ctx.eap_if = eap_get_interface(handler->server_ctx.eap);
		
		/* Enable "port" and request EAP to start authentication. */
		handler->server_ctx.eap_if->portEnabled = TRUE;
		handler->server_ctx.eap_if->eapRestart = TRUE;
	}

	handler->request = request;
	wpabuf_free(handler->server_ctx.eap_if->eapRespData);
	handler->server_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len);
	if (handler->server_ctx.eap_if->eapRespData) {
		handler->server_ctx.eap_if->eapResp = TRUE;
	}
	
	if (eap_example_server_step(handler) < 0) {
		RDEBUG("Failed in EAP library");
		goto fail;
	}

	if (handler->server_ctx.eap_if->eapSuccess) {
		request->reply->code = PW_AUTHENTICATION_ACK;
		rcode = RLM_MODULE_OK;

	} else if (handler->server_ctx.eap_if->eapFail) {
	fail:
		request->reply->code = PW_AUTHENTICATION_REJECT;
		rcode = RLM_MODULE_REJECT;

	} else {
		request->reply->code = PW_ACCESS_CHALLENGE;
		rcode = RLM_MODULE_HANDLED;
	}

	if (handler->server_ctx.eap_if->eapFail ||
	    handler->server_ctx.eap_if->eapSuccess) {
		RDEBUG2("Freeing handler");
		/* handler is not required any more, free it now */
		eap_handler_free(handler);
		handler = NULL;
	} else {
		eaplist_add(inst, handler);
	}

	/*
	 *	If it's an Access-Accept, RFC 2869, Section 2.3.1
	 *	says that we MUST include a User-Name attribute in the
	 *	Access-Accept.
	 */
	if ((request->reply->code == PW_AUTHENTICATION_ACK) &&
	    request->username) {
		/*
		 *	Doesn't exist, add it in.
		 */
		vp = pairfind(request->reply->vps, PW_USER_NAME, 0, TAG_ANY);
		if (!vp) {
			vp = pairmake("User-Name", request->username->vp_strvalue,
				      T_OP_EQ);
			rad_assert(vp != NULL);
			pairadd(&(request->reply->vps), vp);
		}

		/*
		 *	Cisco AP1230 has a bug and needs a zero
		 *	terminated string in Access-Accept.
		 */
		if ((inst->cisco_accounting_username_bug) &&
		    (vp->length < (int) sizeof(vp->vp_strvalue))) {
			vp->vp_strvalue[vp->length] = '\0';
			vp->length++;
		}
	}

	vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
	if (!vp) {
		vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
		memset(vp->vp_strvalue, 0, AUTH_VECTOR_LEN);
		vp->length = AUTH_VECTOR_LEN;
		pairadd(&(request->reply->vps), vp);
	}
	return rcode;
}
Ejemplo n.º 27
0
/*
 *	Add a handler to the set of active sessions.
 *
 *	Since we're adding it to the list, we guess that this means
 *	the packet needs a State attribute.  So add one.
 */
static int eaplist_add(rlm_eap_t *inst, EAP_HANDLER *handler)
{
	int		i, status;
	uint32_t	lvalue;
	VALUE_PAIR	*state;

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

	/*
	 *	Generate State, since we've been asked to add it to
	 *	the list.
	 */
	state = pairmake("State", "0x00", T_OP_EQ);
	if (!state) return 0;
	pairadd(&(handler->request->reply->vps), state);
	state->length = EAP_STATE_LEN;

	/*
	 *	The time at which this request was made was the time
	 *	at which it was received by the RADIUS server.
	 */
	handler->timestamp = handler->request->timestamp;

	handler->src_ipaddr = handler->request->packet->src_ipaddr;

	/*
	 *	We don't need this any more.
	 */
	handler->request = NULL;

	/*
	 *	Playing with a data structure shared among threads
	 *	means that we need a lock, to avoid conflict.
	 */
	pthread_mutex_lock(&(inst->session_mutex));

	/*
	 *	Create a completely random state.
	 */
	for (i = 0; i < 4; i++) {
		lvalue = eap_rand(&inst->rand_pool);
		memcpy(state->vp_octets + i * 4, &lvalue, sizeof(lvalue));
	}
	memcpy(handler->state, state->vp_strvalue, sizeof(handler->state));

	/*
	 *	Big-time failure.
	 */
	status = rbtree_insert(inst->session_tree, handler);

	if (status) {
		EAP_HANDLER *prev;

		prev = inst->session_tail;
		if (prev) {
			prev->next = handler;
			handler->prev = prev;
			handler->next = NULL;
			inst->session_tail = handler;
		} else {
			inst->session_head = inst->session_tail = handler;
			handler->next = handler->prev = NULL;
		}
	}

	/*
	 *	Now that we've finished mucking with the list,
	 *	unlock it.
	 */
	pthread_mutex_unlock(&(inst->session_mutex));

	if (!status) {
		radlog(L_ERR, "rlm_eap2: Failed to remember handler!");
		eap_handler_free(handler);
		return 0;
	}

	return 1;
}
Ejemplo n.º 28
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 sqlcounter_authorize(void *instance, REQUEST *request)
{
	rlm_sqlcounter_t *data = (rlm_sqlcounter_t *) instance;
	int ret=RLM_MODULE_NOOP;
	int counter=0;
	int res=0;
	DICT_ATTR *dattr;
	VALUE_PAIR *key_vp, *check_vp;
	VALUE_PAIR *reply_item;
	char msg[128];
	char querystr[MAX_QUERY_LEN];
	char responsestr[MAX_QUERY_LEN];

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

	/*
	 *	Before doing anything else, see if we have to reset
	 *	the counters.
	 */
	if (data->reset_time && (data->reset_time <= request->timestamp)) {

		/*
		 *	Re-set the next time and prev_time for this counters range
		 */
		data->last_reset = data->reset_time;
		find_next_reset(data,request->timestamp);
	}


	/*
	 *      Look for the key.  User-Name is special.  It means
	 *      The REAL username, after stripping.
	 */
	DEBUG2("rlm_sqlcounter: Entering module authorize code");
	key_vp = (data->key_attr == PW_USER_NAME) ? request->username : pairfind(request->packet->vps, data->key_attr);
	if (key_vp == NULL) {
		DEBUG2("rlm_sqlcounter: Could not find Key value pair");
		return ret;
	}

	/*
	 *      Look for the check item
	 */
	if ((dattr = dict_attrbyname(data->check_name)) == NULL) {
		return ret;
	}
	/* DEBUG2("rlm_sqlcounter: Found Check item attribute %d", dattr->attr); */
	if ((check_vp= pairfind(request->config_items, dattr->attr)) == NULL) {
		DEBUG2("rlm_sqlcounter: Could not find Check item value pair");
		return ret;
	}

	/* first, expand %k, %b and %e in query */
	sqlcounter_expand(querystr, MAX_QUERY_LEN, data->query, instance);

	/* second, xlat any request attribs in query */
	radius_xlat(responsestr, MAX_QUERY_LEN, querystr, request, sql_escape_func);

	/* third, wrap query with sql module & expand */
	snprintf(querystr, sizeof(querystr), "%%{%%S:%s}", responsestr);
	sqlcounter_expand(responsestr, MAX_QUERY_LEN, querystr, instance);

	/* Finally, xlat resulting SQL query */
	radius_xlat(querystr, MAX_QUERY_LEN, responsestr, request, sql_escape_func);

	counter = atoi(querystr);


	/*
	 * Check if check item > counter
	 */
	res=check_vp->lvalue - counter;
	if (res > 0) {
		DEBUG2("rlm_sqlcounter: (Check item - counter) is greater than zero");
		/*
		 *	We are assuming that simultaneous-use=1. But
		 *	even if that does not happen then our user
		 *	could login at max for 2*max-usage-time Is
		 *	that acceptable?
		 */

		/*
		 *	User is allowed, but set Session-Timeout.
		 *	Stolen from main/auth.c
		 */

		/*
		 *	If we are near a reset then add the next
		 *	limit, so that the user will not need to
		 *	login again
		 */
		if (data->reset_time && (
			res >= (data->reset_time - request->timestamp))) {
			res = data->reset_time - request->timestamp;
			res += check_vp->lvalue;
		}

		if ((reply_item = pairfind(request->reply->vps, PW_SESSION_TIMEOUT)) != NULL) {
			if (reply_item->lvalue > res)
				reply_item->lvalue = res;
		} else {
			if ((reply_item = paircreate(PW_SESSION_TIMEOUT, PW_TYPE_INTEGER)) == NULL) {
				radlog(L_ERR|L_CONS, "no memory");
				return RLM_MODULE_NOOP;
			}
			reply_item->lvalue = res;
			pairadd(&request->reply->vps, reply_item);
		}

		ret=RLM_MODULE_OK;

		DEBUG2("rlm_sqlcounter: Authorized user %s, check_item=%d, counter=%d",
				key_vp->strvalue,check_vp->lvalue,counter);
		DEBUG2("rlm_sqlcounter: Sent Reply-Item for user %s, Type=Session-Timeout, value=%d",
				key_vp->strvalue,reply_item->lvalue);
	}
	else{
		char module_fmsg[MAX_STRING_LEN];
		VALUE_PAIR *module_fmsg_vp;

		DEBUG2("rlm_sqlcounter: (Check item - counter) is less than zero");

		/*
		 * User is denied access, send back a reply message
		 */
		snprintf(msg, sizeof(msg), "Your maximum %s usage time has been reached", data->reset);
		reply_item=pairmake("Reply-Message", msg, T_OP_EQ);
		pairadd(&request->reply->vps, reply_item);

		snprintf(module_fmsg, sizeof(module_fmsg), "rlm_sqlcounter: Maximum %s usage time reached", data->reset);
		module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);
		pairadd(&request->packet->vps, module_fmsg_vp);

		ret=RLM_MODULE_REJECT;

		DEBUG2("rlm_sqlcounter: Rejected user %s, check_item=%d, counter=%d",
				key_vp->strvalue,check_vp->lvalue,counter);
	}

	return ret;
}
Ejemplo n.º 29
0
/*
 *	Add a session to the set of active sessions.
 *
 *	Since we're adding it to the list, we guess that this means
 *	the packet needs a State attribute.  So add one.
 */
int securid_sessionlist_add(rlm_securid_t *inst,REQUEST *request,
			    SECURID_SESSION *session)
{
	int		status = 0;
	VALUE_PAIR	*state;

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

	/*
	 *	The time at which this request was made was the time
	 *	at which it was received by the RADIUS server.
	 */
	session->timestamp = request->timestamp;

	session->src_ipaddr = request->packet->src_ipaddr;

	/*
	 *	Playing with a data structure shared among threads
	 *	means that we need a lock, to avoid conflict.
	 */
	pthread_mutex_lock(&(inst->session_mutex));

	/*
	 *	If we have a DoS attack, discard new sessions.
	 */
	if (rbtree_num_elements(inst->session_tree) >= inst->max_sessions) {
		securid_sessionlist_clean_expired(inst, request, session->timestamp);
		goto done;
	}
	
	if (session->session_id == 0) {
		/* this is a NEW session (we are not inserting an updated session) */
		inst->last_session_id++;
		session->session_id = inst->last_session_id;
		RDEBUG2("Creating a new session with id=%d\n",session->session_id);
	}
	snprintf(session->state,sizeof(session->state)-1,"FRR-CH %d|%d",session->session_id,session->trips+1);
	RDEBUG2("Inserting session id=%d identity='%s' state='%s' to the session list",
			 session->session_id,SAFE_STR(session->identity),session->state);


	/*
	 *	Generate State, since we've been asked to add it to
	 *	the list.
	 */
	state = pairmake("State", session->state, T_OP_EQ);
	if (!state) return -1;
	state->length = SECURID_STATE_LEN;



	status = rbtree_insert(inst->session_tree, session);
	if (status) {
		/* tree insert SUCCESS */
		/* insert the session to the linked list of sessions */
		SECURID_SESSION *prev;

		prev = inst->session_tail;
		if (prev) {
			/* insert to the tail of the list */
			prev->next = session;
			session->prev = prev;
			session->next = NULL;
			inst->session_tail = session;
		} else {
		        /* 1st time */
			inst->session_head = inst->session_tail = session;
			session->next = session->prev = NULL;
		}
	}

	/*
	 *	Now that we've finished mucking with the list,
	 *	unlock it.
	 */
 done:
	pthread_mutex_unlock(&(inst->session_mutex));

	if (!status) {
		pairfree(&state);
		radlog(L_ERR, "rlm_securid: Failed to store session");
		return -1;
	}

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

	return 0;
}
Ejemplo n.º 30
0
/*
 *	*presult is "did comparison match or not"
 */
static int radius_do_cmp(REQUEST *request, int *presult,
			 FR_TOKEN lt, const char *pleft, FR_TOKEN token,
			 FR_TOKEN rt, const char *pright,
			 int cflags, int modreturn)
{
	int result;
	uint32_t lint, rint;
	VALUE_PAIR *vp = NULL;
#ifdef HAVE_REGEX_H
	char buffer[8192];
#else
	cflags = cflags;	/* -Wunused */
#endif

	rt = rt;		/* -Wunused */

	if (lt == T_BARE_WORD) {
		/*
		 *	Maybe check the last return code.
		 */
		if (token == T_OP_CMP_TRUE) {
			int isreturn;

			/*
			 *	Looks like a return code, treat is as such.
			 */
			isreturn = fr_str2int(modreturn_table, pleft, -1);
			if (isreturn != -1) {
				*presult = (modreturn == isreturn);
				return TRUE;
			}
		}

		/*
		 *	Bare words on the left can be attribute names.
		 */
		if (radius_get_vp(request, pleft, &vp)) {
			VALUE_PAIR myvp;

			/*
			 *	VP exists, and that's all we're looking for.
			 */
			if (token == T_OP_CMP_TRUE) {
				*presult = (vp != NULL);
				return TRUE;
			}

			if (!vp) {
				DICT_ATTR *da;
				
				/*
				 *	The attribute on the LHS may
				 *	have been a dynamically
				 *	registered callback.  i.e. it
				 *	doesn't exist as a VALUE_PAIR.
				 *	If so, try looking for it.
				 */
				da = dict_attrbyname(pleft);
				if (da && (da->vendor == 0) && radius_find_compare(da->attr)) {
					VALUE_PAIR *check = pairmake(pleft, pright, token);
					*presult = (radius_callback_compare(request, NULL, check, NULL, NULL) == 0);
					RDEBUG3("  Callback returns %d",
						*presult);
					pairfree(&check);
					return TRUE;
				}
				
				RDEBUG2("    (Attribute %s was not found)",
				       pleft);
				*presult = 0;
				return TRUE;
			}

#ifdef HAVE_REGEX_H
			/*
			 * 	Regex comparisons treat everything as
			 *	strings.
			 */
			if ((token == T_OP_REG_EQ) ||
			    (token == T_OP_REG_NE)) {
				vp_prints_value(buffer, sizeof(buffer), vp, 0);
				pleft = buffer;
				goto do_checks;
			}
#endif

			memcpy(&myvp, vp, sizeof(myvp));
			if (!pairparsevalue(&myvp, pright)) {
				RDEBUG2("Failed parsing \"%s\": %s",
				       pright, fr_strerror());
				return FALSE;
			}

			myvp.operator = token;
			*presult = paircmp(&myvp, vp);
			RDEBUG3("  paircmp -> %d", *presult);
			return TRUE;
		} /* else it's not a VP in a list */
	}

#ifdef HAVE_REGEX_H
	do_checks:
#endif
	switch (token) {
	case T_OP_GE:
	case T_OP_GT:
	case T_OP_LE:
	case T_OP_LT:
		if (!all_digits(pright)) {
			RDEBUG2("    (Right field is not a number at: %s)", pright);
			return FALSE;
		}
		rint = strtoul(pright, NULL, 0);
		if (!all_digits(pleft)) {
			RDEBUG2("    (Left field is not a number at: %s)", pleft);
			return FALSE;
		}
		lint = strtoul(pleft, NULL, 0);
		break;
		
	default:
		lint = rint = 0;  /* quiet the compiler */
		break;
	}
	
	switch (token) {
	case T_OP_CMP_TRUE:
		/*
		 *	Check for truth or falsehood.
		 */
		if (all_digits(pleft)) {
			lint = strtoul(pleft, NULL, 0);
			result = (lint != 0);
			
		} else {
			result = (*pleft != '\0');
		}
		break;
		

	case T_OP_CMP_EQ:
		result = (strcmp(pleft, pright) == 0);
		break;
		
	case T_OP_NE:
		result = (strcmp(pleft, pright) != 0);
		break;
		
	case T_OP_GE:
		result = (lint >= rint);
		break;
		
	case T_OP_GT:
		result = (lint > rint);
		break;
		
	case T_OP_LE:
		result = (lint <= rint);
		break;
		
	case T_OP_LT:
		result = (lint < rint);
		break;

#ifdef HAVE_REGEX_H
	case T_OP_REG_EQ: {
		int i, compare;
		regex_t reg;
		regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
		
		/*
		 *	Include substring matches.
		 */
		compare = regcomp(&reg, pright, cflags);
		if (compare != 0) {
			if (debug_flag) {
				char errbuf[128];

				regerror(compare, &reg, errbuf, sizeof(errbuf));
				DEBUG("ERROR: Failed compiling regular expression: %s", errbuf);
			}
			return FALSE;
		}

		compare = regexec(&reg, pleft,
				  REQUEST_MAX_REGEX + 1,
				  rxmatch, 0);
		regfree(&reg);
		
		/*
		 *	Add new %{0}, %{1}, etc.
		 */
		if (compare == 0) for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
			char *r;

			free(request_data_get(request, request,
					      REQUEST_DATA_REGEX | i));

			/*
			 *	No %{i}, skip it.
			 *	We MAY have %{2} without %{1}.
			 */
			if (rxmatch[i].rm_so == -1) continue;
			
			/*
			 *	Copy substring into allocated buffer
			 */
			r = rad_malloc(rxmatch[i].rm_eo -rxmatch[i].rm_so + 1);
			memcpy(r, pleft + rxmatch[i].rm_so,
			       rxmatch[i].rm_eo - rxmatch[i].rm_so);
			r[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0';

			request_data_add(request, request,
					 REQUEST_DATA_REGEX | i,
					 r, free);
		}
		result = (compare == 0);
	}
		break;
		
	case T_OP_REG_NE: {
		int compare;
		regex_t reg;
		regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
		
		/*
		 *	Include substring matches.
		 */
		compare = regcomp(&reg, pright, cflags);
		if (compare != 0) {
			if (debug_flag) {
				char errbuf[128];

				regerror(compare, &reg, errbuf, sizeof(errbuf));
				DEBUG("ERROR: Failed compiling regular expression: %s", errbuf);
			}
			return FALSE;
		}

		compare = regexec(&reg, pleft,
				  REQUEST_MAX_REGEX + 1,
				  rxmatch, 0);
		regfree(&reg);
		
		result = (compare != 0);
	}
		break;
#endif
		
	default:
		DEBUG("ERROR: Comparison operator %s is not supported",
		      fr_token_name(token));
		result = FALSE;
		break;
	}
	
	*presult = result;
	return TRUE;
}