📄 eap.c
字号:
eap_msg->strvalue[1], eap_msg->length); } /* * We handle request and responses. The only other defined * codes are success and fail. The client SHOULD NOT be * sending success/fail packets to us, as it doesn't make * sense. */ if ((eap_msg->strvalue[0] != PW_EAP_REQUEST) && (eap_msg->strvalue[0] != PW_EAP_RESPONSE)) { DEBUG2(" rlm_eap: Ignoring EAP packet which we don't know how to handle."); return EAP_FAIL; } /* * We've been told to ignore unknown EAP types, AND it's * an unknown type. Return "NOOP", which will cause the * eap_authorize() to return NOOP. * * EAP-Identity, Notification, and NAK are all handled * internally, so they never have handlers. */ if ((eap_msg->strvalue[4] >= PW_EAP_MD5) && inst->ignore_unknown_eap_types && ((eap_msg->strvalue[4] == 0) || (eap_msg->strvalue[4] > PW_EAP_MAX_TYPES) || (inst->types[eap_msg->strvalue[4]] == NULL))) { DEBUG2(" rlm_eap: Ignoring Unknown EAP type"); return EAP_NOOP; } /* * They're NAKing the EAP type we wanted to use, and * asking for one which we don't support. * * NAK is code + id + length1 + length + NAK * + requested EAP type(s). * * We know at this point that we can't handle the * request. We could either return an EAP-Fail here, but * it's not too critical. * * By returning "noop", we can ensure that authorize() * returns NOOP, and another module may choose to proxy * the request. */ if ((eap_msg->strvalue[4] == PW_EAP_NAK) && (eap_msg->length >= (EAP_HEADER_LEN + 2)) && inst->ignore_unknown_eap_types && ((eap_msg->strvalue[5] == 0) || (eap_msg->strvalue[5] > PW_EAP_MAX_TYPES) || (inst->types[eap_msg->strvalue[5]] == NULL))) { DEBUG2(" rlm_eap: Ignoring NAK with request for unknown EAP type"); return EAP_NOOP; } /* * Later EAP messages are longer than the 'start' * message, so if everything is OK, this function returns * 'no start found', so that the rest of the EAP code can * use the State attribute to match this EAP-Message to * an ongoing conversation. */ DEBUG2(" rlm_eap: No EAP Start, assuming it's an on-going EAP conversation"); return EAP_NOTFOUND;}/* * compose EAP FAILURE packet in EAP-Message */void eap_fail(EAP_HANDLER *handler){ handler->eap_ds->request->code = PW_EAP_FAILURE; eap_compose(handler);}/* * compose EAP SUCCESS packet in EAP-Message */void eap_success(EAP_HANDLER *handler){ handler->eap_ds->request->code = PW_EAP_SUCCESS; eap_compose(handler);}/* * Basic EAP packet verfications & validations */static int eap_validation(eap_packet_t *eap_packet){ uint16_t len; memcpy(&len, eap_packet->length, sizeof(uint16_t)); len = ntohs(len); /* * High level EAP packet checks */ if ((len <= EAP_HEADER_LEN) || ((eap_packet->code != PW_EAP_RESPONSE) && (eap_packet->code != PW_EAP_REQUEST)) || (eap_packet->data[0] <= 0) || (eap_packet->data[0] > PW_EAP_MAX_TYPES)) { radlog(L_AUTH, "rlm_eap: Incorrect EAP Message, " "Ignoring the packet"); return EAP_INVALID; } /* we don't expect notification, but we send it */ if (eap_packet->data[0] == PW_EAP_NOTIFICATION) { radlog(L_AUTH, "rlm_eap: Got NOTIFICATION, " "Ignoring the packet"); return EAP_INVALID; } return EAP_VALID;}/* * Get the user Identity only from EAP-Identity packets */static char *eap_identity(eap_packet_t *eap_packet){ int size; uint16_t len; char *identity; if ((eap_packet == NULL) || (eap_packet->code != PW_EAP_RESPONSE) || (eap_packet->data[0] != PW_EAP_IDENTITY)) { return NULL; } memcpy(&len, eap_packet->length, sizeof(uint16_t)); len = ntohs(len); if ((len <= 5) || (eap_packet->data[1] == 0x00)) { radlog(L_ERR, "rlm_eap: UserIdentity Unknown "); return NULL; } size = len - 5; identity = (char *)malloc(size + 1); if (identity == NULL) { radlog(L_ERR, "rlm_eap: out of memory"); return NULL; } memcpy(identity, &eap_packet->data[1], size); identity[size] = '\0'; return identity;}/* * Create our Request-Response data structure with the eap packet */static EAP_DS *eap_buildds(eap_packet_t **eap_packet_p){ EAP_DS *eap_ds = NULL; eap_packet_t *eap_packet = *eap_packet_p; int typelen; uint16_t len; if ((eap_ds = eap_ds_alloc()) == NULL) { return NULL; } eap_ds->response->packet = (unsigned char *)eap_packet; eap_ds->response->code = eap_packet->code; eap_ds->response->id = eap_packet->id; eap_ds->response->type.type = eap_packet->data[0]; memcpy(&len, eap_packet->length, sizeof(uint16_t)); len = ntohs(len); eap_ds->response->length = len; /* * We've eaten the eap packet into the eap_ds. */ *eap_packet_p = NULL; /* * First 5 bytes in eap, are code + id + length(2) + type. * * The rest is type-specific data. We skip type while * getting typedata from data. */ typelen = len - 5/*code + id + length + type */; if (typelen > 0) { /* * Since the packet contains the complete * eap_packet, typedata will be a ptr in packet * to its typedata */ eap_ds->response->type.data = eap_ds->response->packet + 5/*code+id+length+type*/; eap_ds->response->type.length = typelen; } else { eap_ds->response->type.length = 0; eap_ds->response->type.data = NULL; } return eap_ds;}/* * If identity response then create a fresh handler & fill the identity * else handler MUST be in our list, get that. * This handler creation cannot fail * * username contains REQUEST->username which might have been stripped. * identity contains the one sent in EAP-Identity response */EAP_HANDLER *eap_handler(rlm_eap_t *inst, eap_packet_t **eap_packet_p, REQUEST *request){ EAP_HANDLER *handler = NULL; eap_packet_t *eap_packet = *eap_packet_p; VALUE_PAIR *vp; /* * Ensure it's a valid EAP-Request, or EAP-Response. */ if (eap_validation(eap_packet) == EAP_INVALID) { free(*eap_packet_p); *eap_packet_p = NULL; return NULL; } /* * EAP_HANDLER MUST be found in the list if it is not * EAP-Identity response */ if (eap_packet->data[0] != PW_EAP_IDENTITY) { handler = eaplist_find(inst, request, eap_packet); if (handler == NULL) { /* Either send EAP_Identity or EAP-Fail */ radlog(L_ERR, "rlm_eap: Either EAP-request timed out OR" " EAP-response to an unknown EAP-request"); free(*eap_packet_p); *eap_packet_p = NULL; return NULL; } /* * Even more paranoia. Without this, some weird * clients could do crazy things. * * It's ok to send EAP sub-type NAK in response * to a request for a particular type, but it's NOT * OK to blindly return data for another type. */ if ((eap_packet->data[0] != PW_EAP_NAK) && (eap_packet->data[0] != handler->eap_type)) { radlog(L_ERR, "rlm_eap: Response appears to match, but EAP type is wrong."); free(*eap_packet_p); *eap_packet_p = NULL; return NULL; } vp = pairfind(request->packet->vps, PW_USER_NAME); if (!vp) { /* * NAS did not set the User-Name * attribute, so we set it here and * prepend it to the beginning of the * request vps so that autz's work * correctly */ radlog(L_INFO, "rlm_eap: Broken NAS did not set User-Name, setting from EAP Identity"); vp = pairmake("User-Name", handler->identity, T_OP_EQ); if (vp == NULL) { radlog(L_ERR, "rlm_eap: out of memory"); free(*eap_packet_p); *eap_packet_p = NULL; return NULL; } vp->next = request->packet->vps; request->packet->vps = vp; } else { /* * A little more paranoia. If the NAS * *did* set the User-Name, and it doesn't * match the identity, (i.e. If they * change their User-Name part way through * the EAP transaction), then reject the * request as the NAS is doing something * funny. */ if (strncmp(handler->identity, vp->strvalue, MAX_STRING_LEN) != 0) { radlog(L_ERR, "rlm_eap: Identity does not match User-Name. Authentication failed."); free(*eap_packet_p); *eap_packet_p = NULL; return NULL; } } } else { /* packet was EAP identity */ handler = eap_handler_alloc(); if (handler == NULL) { radlog(L_ERR, "rlm_eap: out of memory"); free(*eap_packet_p); *eap_packet_p = NULL; return NULL; } /* * All fields in the handler are set to zero. */ handler->identity = eap_identity(eap_packet); if (handler->identity == NULL) { radlog(L_ERR, "rlm_eap: Identity Unknown, authentication failed"); free(*eap_packet_p); *eap_packet_p = NULL; eap_handler_free(handler); return NULL; } vp = pairfind(request->packet->vps, PW_USER_NAME); if (!vp) { /* * NAS did not set the User-Name * attribute, so we set it here and * prepend it to the beginning of the * request vps so that autz's work * correctly */ radlog(L_INFO, "rlm_eap: WARNING NAS did not set User-Name. Setting it locally from EAP Identity"); vp = pairmake("User-Name", handler->identity, T_OP_EQ); if (vp == NULL) { radlog(L_ERR, "rlm_eap: out of memory"); free(*eap_packet_p); *eap_packet_p = NULL; return NULL; } vp->next = request->packet->vps; request->packet->vps = vp; } else { /* * Paranoia. If the NAS *did* set the * User-Name, and it doesn't match the * identity, the NAS is doing something * funny, so reject the request. */ if (strncmp(handler->identity, vp->strvalue, MAX_STRING_LEN) != 0) { radlog(L_ERR, "rlm_eap: Identity does not match User-Name, setting from EAP Identity."); free(*eap_packet_p); *eap_packet_p = NULL; eap_handler_free(handler); return NULL; } } } handler->eap_ds = eap_buildds(eap_packet_p); if (handler->eap_ds == NULL) { free(*eap_packet_p); *eap_packet_p = NULL; eap_handler_free(handler); return NULL; } handler->timestamp = request->timestamp; handler->request = request; /* LEAP needs this */ return handler;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -