📄 rlm_eap_mschapv2.c
字号:
/* * rlm_eap_mschapv2.c Handles that are called from eap * * Version: $Id: rlm_eap_mschapv2.c,v 1.8 2004/04/19 20:15:30 aland Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright 2003 The FreeRADIUS server project */#include "autoconf.h"#include <stdio.h>#include <stdlib.h>#include "eap_mschapv2.h"#include <rad_assert.h>typedef struct rlm_eap_mschapv2_t { int with_ntdomain_hack;} rlm_eap_mschapv2_t;static CONF_PARSER module_config[] = { { "with_ntdomain_hack", PW_TYPE_BOOLEAN, offsetof(rlm_eap_mschapv2_t,with_ntdomain_hack), NULL, "no" }, { NULL, -1, 0, NULL, NULL } /* end the list */};/* * Detach the module. */static int mschapv2_detach(void *arg){ rlm_eap_mschapv2_t *inst = (rlm_eap_mschapv2_t *) arg; free(inst); return 0;}/* * Attach the module. */static int mschapv2_attach(CONF_SECTION *cs, void **instance){ rlm_eap_mschapv2_t *inst; inst = malloc(sizeof(*inst)); if (!inst) { radlog(L_ERR, "rlm_eap_mschapv2: out of memory"); return -1; } memset(inst, 0, sizeof(*inst)); /* * Parse the configuration attributes. */ if (cf_section_parse(cs, inst, module_config) < 0) { mschapv2_detach(inst); return -1; } *instance = inst; return 0;}/* * Compose the response. */static int eapmschapv2_compose(EAP_HANDLER *handler, VALUE_PAIR *reply){ uint8_t *ptr; int16_t length; mschapv2_header_t *hdr; EAP_DS *eap_ds = handler->eap_ds; eap_ds->request->code = PW_EAP_REQUEST; eap_ds->request->type.type = PW_EAP_MSCHAPV2; switch (reply->attribute) { case PW_MSCHAP_CHALLENGE: /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Code | Identifier | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | OpCode | MS-CHAPv2-ID | MS-Length... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MS-Length | Value-Size | Challenge... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Challenge... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Name... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ length = MSCHAPV2_HEADER_LEN + MSCHAPV2_CHALLENGE_LEN + strlen(handler->identity); eap_ds->request->type.data = malloc(length); /* * Allocate room for the EAP-MS-CHAPv2 data. */ if (eap_ds->request->type.data == NULL) { radlog(L_ERR, "rlm_eap_mschapv2: out of memory"); return 0; } eap_ds->request->type.length = length; ptr = eap_ds->request->type.data; hdr = eap_ds->request->type.data; hdr->opcode = PW_EAP_MSCHAPV2_CHALLENGE; hdr->mschapv2_id = eap_ds->response->id + 1; length = htons(length); memcpy(hdr->ms_length, &length, sizeof(uint16_t)); hdr->value_size = MSCHAPV2_CHALLENGE_LEN; ptr += MSCHAPV2_HEADER_LEN; /* * Copy the Challenge, success, or error over. */ memcpy(ptr, reply->strvalue, reply->length); memcpy((ptr + reply->length), handler->identity, strlen(handler->identity)); break; case PW_MSCHAP2_SUCCESS: /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Code | Identifier | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | OpCode | MS-CHAPv2-ID | MS-Length... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MS-Length | Message... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ DEBUG2("MSCHAP Success\n"); length = 46; eap_ds->request->type.data = malloc(length); memset(eap_ds->request->type.data, 0, length); /* * Allocate room for the EAP-MS-CHAPv2 data. */ if (eap_ds->request->type.data == NULL) { radlog(L_ERR, "rlm_eap_mschapv2: out of memory"); return 0; } eap_ds->request->type.length = length; eap_ds->request->type.data[0] = PW_EAP_MSCHAPV2_SUCCESS; eap_ds->request->type.data[1] = eap_ds->response->id; length = htons(length); memcpy((eap_ds->request->type.data + 2), &length, sizeof(uint16_t)); memcpy((eap_ds->request->type.data + 4), reply->strvalue + 1, 42); break; case PW_MSCHAP_ERROR: DEBUG2("MSCHAP Failure\n"); length = 4 + MSCHAPV2_FAILURE_MESSAGE_LEN; eap_ds->request->type.data = malloc(length); memset(eap_ds->request->type.data, 0, length); /* * Allocate room for the EAP-MS-CHAPv2 data. */ if (eap_ds->request->type.data == NULL) { radlog(L_ERR, "rlm_eap_mschapv2: out of memory"); return 0; } eap_ds->request->type.length = length; eap_ds->request->type.data[0] = PW_EAP_MSCHAPV2_FAILURE; eap_ds->request->type.data[1] = eap_ds->response->id; length = htons(length); memcpy((eap_ds->request->type.data + 2), &length, sizeof(uint16_t)); memcpy((eap_ds->request->type.data + 4), MSCHAPV2_FAILURE_MESSAGE, MSCHAPV2_FAILURE_MESSAGE_LEN); break; default: radlog(L_ERR, "rlm_eap_mschapv2: Internal sanity check failed"); return 0; break; } return 1;}/* * Initiate the EAP-MSCHAPV2 session by sending a challenge to the peer. */static int mschapv2_initiate(void *type_data, EAP_HANDLER *handler){ int i; VALUE_PAIR *challenge; mschapv2_opaque_t *data; type_data = type_data; /* -Wunused */ challenge = pairmake("MS-CHAP-Challenge", "0x00", T_OP_EQ); if (!challenge) { radlog(L_ERR, "rlm_eap_mschapv2: out of memory"); return 0; } /* * Get a random challenge. */ challenge->length = MSCHAPV2_CHALLENGE_LEN; for (i = 0; i < MSCHAPV2_CHALLENGE_LEN; i++) { challenge->strvalue[i] = lrad_rand(); } radlog(L_INFO, "rlm_eap_mschapv2: Issuing Challenge"); /* * Keep track of the challenge. */ data = malloc(sizeof(mschapv2_opaque_t)); rad_assert(data != NULL); /* * We're at the stage where we're challenging the user. */ data->code = PW_EAP_MSCHAPV2_CHALLENGE; memcpy(data->challenge, challenge->strvalue, MSCHAPV2_CHALLENGE_LEN); handler->opaque = data; handler->free_opaque = free; /* * Compose the EAP-MSCHAPV2 packet out of the data structure, * and free it. */ eapmschapv2_compose(handler, challenge); pairfree(&challenge); /* * The EAP session doesn't have enough information to * proxy the "inside EAP" protocol. Disable EAP proxying. */ handler->request->options &= ~RAD_REQUEST_OPTION_PROXY_EAP; /* * We don't need to authorize the user at this point. * * We also don't need to keep the challenge, as it's * stored in 'handler->eap_ds', which will be given back * to us... */ handler->stage = AUTHENTICATE; return 1;}/* * Do post-proxy processing, * 0 = fail * 1 = OK. * * Called from rlm_eap.c, eap_postproxy(). */static int mschap_postproxy(EAP_HANDLER *handler, void *tunnel_data){ VALUE_PAIR *response = NULL; mschapv2_opaque_t *data; data = (mschapv2_opaque_t *) handler->opaque; rad_assert(data != NULL); tunnel_data = tunnel_data; /* -Wunused */ DEBUG2(" rlm_eap_mschapv2: Passing reply from proxy back into the tunnel %p %d.", handler->request, handler->request->reply->code); /* * There is only a limited number of possibilities. */ switch (handler->request->reply->code) { case PW_AUTHENTICATION_ACK: DEBUG(" rlm_eap_mschapv2: Authentication succeeded."); /* * Move the attribute, so it doesn't go into * the reply. */ pairmove2(&response, &handler->request->reply->vps, PW_MSCHAP2_SUCCESS); break; default: case PW_AUTHENTICATION_REJECT: DEBUG(" rlm_eap_mschapv2: Authentication did not succeed."); return 0; } /* * No response, die. */ if (!response) { radlog(L_ERR, "rlm_eap_mschapv2: No MS-CHAPv2-Success or MS-CHAP-Error was found."); return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -