/* * 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; }
/* * 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; }
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; }
/* * 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; }
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; }
/** 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); }
/* * 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; }
/* * 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); } }
/* * 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; }
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; }
/* * 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; }
/* * 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); } }
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; }
/* * 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; }
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); } } }
/* * 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; }
/* * 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; }
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; }
/* * 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); } }
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; }
/** 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; }
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; }
/* * 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; }
/* * 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; }
/* * 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); } }
/* * 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; */ }
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; }