📄 ttlsphase2.c
字号:
/** * A client-side 802.1x implementation supporting EAP/TLS * * This code is released under both the GPL version 2 and BSD licenses. * Either license may be used. The respective licenses are found below. * * Copyright (C) 2002 Bryan D. Payne & Nick L. Petroni Jr. * All Rights Reserved * * --- GPL Version 2 License --- * 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. * * --- BSD License --- * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * Maryland at College Park and its contributors. * - Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *//******************************************************************* * EAPTTLS Phase 2 Function implementations * * File: ttlsphase2.c * * Authors: Chris.Hessing@utah.edu * * $Id: ttlsphase2.c,v 1.18 2004/06/15 03:22:32 chessing Exp $ * $Date: 2004/06/15 03:22:32 $ * $Log: ttlsphase2.c,v $ * Revision 1.18 2004/06/15 03:22:32 chessing * * XSupplicant Release 1.0 * * *******************************************************************/#include <inttypes.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <stdio.h>#include <ctype.h>#include <netinet/in.h>#include <openssl/ssl.h>#include "config.h"#include "profile.h"#include "eap.h"#include "interactive.h"#include "../tls/tls_crypt.h"#include "xsup_debug.h"#include "../mschapv2/mschapv2.h"#include "ttlsphase2.h"// A few numbers from the radius dictionary. 8-)#define USER_NAME_AVP 1#define USER_PASSWORD_AVP 2#define CHAP_PASSWORD_AVP 3#define CHAP_CHALLENGE_AVP 60// Defines for MS-CHAP values also from the dictionary.#define MS_VENDOR_ATTR 311#define MS_CHAP_RESPONSE 1#define MS_CHAP_CHALLENGE 11#define MS_CHAP2_RESPONSE 25#define MANDITORY_FLAG 0x40#define VENDOR_FLAG 0x80#define TTLS_CHALLENGE "ttls challenge" // Need to generate implied challenge.#define TTLS_CHALLENGE_SIZE 14#define TTLS_PHASE2_DEBUG 1uint32_t avp_code;uint32_t bitmask_avp_len;struct phase2_handler { char *phase2name; void (*phase2handler)(struct generic_eap_data *, char *, int *); ttls_phase2_type phase2type;};struct phase2_handler phase2types[] = { {"UNDEFINED", ttls_do_bogus, TTLS_PHASE2_UNDEFINED}, {"PAP", ttls_do_pap, TTLS_PHASE2_PAP}, {"CHAP", ttls_do_chap, TTLS_PHASE2_CHAP}, {"MSCHAP", ttls_do_mschap, TTLS_PHASE2_MSCHAP}, {"MSCHAPV2", ttls_do_mschapv2, TTLS_PHASE2_MSCHAPV2}, {NULL, ttls_do_bogus, -1}};// This is from section 10.1 of the TTLS RFC.char *implicit_challenge(struct generic_eap_data *thisint){ if (!thisint) { debug_printf(DEBUG_NORMAL, "Invalid structure passed to implicit_challenge()!\n"); return NULL; } return tls_crypt_gen_keyblock(thisint, TTLS_CHALLENGE, TTLS_CHALLENGE_SIZE);}void build_avp(uint32_t avp_value, uint32_t avp_vendor, uint64_t avp_flags, uint8_t *in_value, uint64_t in_value_len, uint8_t *out_value, int *out_size){ int avp_padded; uint32_t avp_vendor_stuff; avp_code = htonl(avp_value); avp_vendor_stuff = htonl(avp_vendor); if (avp_vendor != 0) { in_value_len = in_value_len +4; } if ((in_value_len % 4) != 0) { avp_padded = (in_value_len + (4 - (in_value_len % 4))); } else { avp_padded = in_value_len; } bitmask_avp_len = htonl((avp_flags << 24) + in_value_len + 8); bzero(out_value, avp_padded+12); memcpy(&out_value[0], &avp_code, 4); memcpy(&out_value[4], &bitmask_avp_len, 4); if (avp_vendor != 0) { memcpy(&out_value[8], &avp_vendor_stuff, 4); memcpy(&out_value[12], in_value, in_value_len); *out_size = avp_padded+8; } else { memcpy(&out_value[8], in_value, in_value_len); *out_size = avp_padded+8; }}void ttls_do_mschapv2(struct generic_eap_data *thisint, char *out_data, int *out_size){ u_char mschap_challenge[16], mschap_answer[50]; u_char mschap_result[24]; char *username = NULL, *password = NULL, *challenge = NULL; int avp_offset, avp_out_size, username_size, id; struct config_mschapv2 *phase2data; struct config_eap_ttls *outerdata; struct config_ttls_phase2 *userdata; if ((!thisint) || (!thisint->eap_conf_data)) { debug_printf(DEBUG_NORMAL, "Invalid configuration structure in ttls_do_mschapv2().\n"); return; } outerdata = (struct config_eap_ttls *)thisint->eap_conf_data; if (!outerdata->phase2) { debug_printf(DEBUG_NORMAL, "Invalid phase 2 data.\n"); return; } userdata = (struct config_ttls_phase2 *)outerdata->phase2; while ((userdata != NULL) && (userdata->phase2_type != TTLS_PHASE2_MSCHAPV2)) { userdata = userdata->next; } if (!userdata->phase2_data) { debug_printf(DEBUG_NORMAL, "Invalid phase 2 config in MS-CHAPv2!\n"); return; } phase2data = (struct config_mschapv2 *)userdata->phase2_data; // Check that we have a password. if ((phase2data->password == NULL) && (thisint->tempPwd == NULL)) { debug_printf(DEBUG_AUTHTYPES, "Phase 2 doesn't appear to have a password. Requesting one!\n"); thisint->need_password = 1; thisint->eaptype = strdup("EAP-TTLS Phase 2 (MS-CHAPv2)"); thisint->eapchallenge = NULL; *out_size = 0; return; } if ((phase2data->password == NULL) && (thisint->tempPwd != NULL)) { phase2data->password = thisint->tempPwd; thisint->tempPwd = NULL; } if (phase2data->username == NULL) { username = thisint->identity; } else { username = phase2data->username; } username_size = strlen(username); // Send the Username AVP build_avp(USER_NAME_AVP, 0, MANDITORY_FLAG, username, username_size, out_data, &avp_out_size); avp_offset = avp_out_size; challenge = implicit_challenge(thisint); if (challenge == NULL) { debug_printf(DEBUG_NORMAL, "Invalid implicit challenge in MS-CHAPv2!\n"); return; } memcpy(&mschap_challenge, challenge, 16); id = challenge[17]; // Send the MS-CHAP AVP build_avp(MS_CHAP_CHALLENGE, MS_VENDOR_ATTR, (MANDITORY_FLAG | VENDOR_FLAG), (char *)&mschap_challenge, 16, &out_data[avp_offset], &avp_out_size); avp_offset+=avp_out_size; bzero(&mschap_answer, 50); // Clear it out. memcpy(&mschap_answer, &mschap_challenge, 16); // The first 24 bytes should be left as 0s. password = phase2data->password; // Get our password. GenerateNTResponse((char *)&mschap_challenge, (char *)&mschap_challenge, username, password, (char *)&mschap_result); mschap_answer[0] = id; mschap_answer[1] = 0; memcpy(&mschap_answer[2], &mschap_challenge, 16); memcpy(&mschap_answer[26], &mschap_result, 24); build_avp(MS_CHAP2_RESPONSE, MS_VENDOR_ATTR, (MANDITORY_FLAG | VENDOR_FLAG), (char *)&mschap_answer, 50, &out_data[avp_offset], &avp_out_size); avp_offset+=avp_out_size; *out_size = avp_offset;}// For phase 2 MS-CHAP, we get 8 bytes implicit challenge, and 1 byte for ID.void ttls_do_mschap(struct generic_eap_data *thisint, char *out_data, int *out_size){ u_char mschap_challenge[8], mschap_answer[49]; u_char mschap_result[24]; char *username = NULL, *password = NULL, *challenge = NULL; int avp_offset, avp_out_size, username_size, id; struct config_ttls_phase2 *userdata; struct config_eap_ttls *outerdata; struct config_mschap *phase2data; if ((!thisint) || (!thisint->eap_conf_data)) { debug_printf(DEBUG_NORMAL, "Invalid configuration struct in MS-CHAP!\n"); return; } outerdata = (struct config_eap_ttls *)thisint->eap_conf_data; if (!outerdata) { debug_printf(DEBUG_NORMAL, "Invalid configuration data in MS-CHAP!\n"); return; } userdata = (struct config_ttls_phase2 *)outerdata->phase2; while ((userdata != NULL) && (userdata->phase2_type != TTLS_PHASE2_MSCHAP)) { userdata = userdata->next; } phase2data = (struct config_mschap *)userdata->phase2_data; // Check that we have a password. if ((phase2data->password == NULL) && (thisint->tempPwd == NULL)) { debug_printf(DEBUG_AUTHTYPES, "Phase 2 doesn't appear to have a password. Requesting one!\n"); thisint->need_password = 1; thisint->eaptype = strdup("EAP-TTLS Phase 2 (MS-CHAP)"); thisint->eapchallenge = NULL; *out_size = 0; return; } if ((phase2data->password == NULL) && (thisint->tempPwd != NULL)) { phase2data->password = thisint->tempPwd; thisint->tempPwd = NULL; } if (phase2data->username == NULL) { username = thisint->identity; } else { username = phase2data->username; } username_size = strlen(username); // Send the Username AVP build_avp(USER_NAME_AVP, 0, MANDITORY_FLAG, username, username_size, out_data, &avp_out_size); avp_offset = avp_out_size; challenge = implicit_challenge(thisint); if (challenge == NULL) { debug_printf(DEBUG_NORMAL, "Invalid implicit challenge!\n"); return; } memcpy((char *)&mschap_challenge[0], challenge, 8); id = challenge[9]; // Send the MS-CHAP AVP build_avp(MS_CHAP_CHALLENGE, MS_VENDOR_ATTR, (MANDITORY_FLAG | VENDOR_FLAG), (char *)&mschap_challenge, 8, &out_data[avp_offset], &avp_out_size); avp_offset+=avp_out_size; bzero((char *)&mschap_answer[0], 49); // Clear it out. password = phase2data->password; // Get our password. NtChallengeResponse((char *)&mschap_challenge, password, (char *)&mschap_result); mschap_answer[0] = id; mschap_answer[1] = 1; // Use NT Style Passwords. memcpy((char *)&mschap_answer[26], (char *)&mschap_result, 24); build_avp(MS_CHAP_RESPONSE, MS_VENDOR_ATTR, (MANDITORY_FLAG | VENDOR_FLAG), (char *)&mschap_answer, 50, &out_data[avp_offset], &avp_out_size); avp_offset+=avp_out_size; *out_size = avp_offset;} // For phase 2 CHAP, we need to get an implicit_challenge from the phase 1,// and use the first 16 bytes for challenge, and the 17th byte as the ID.// Then, to find the CHAP password hash, we find MD5(id + password + // challenge). Then, we need to send 3 AVPs back to the authenticator.// The username, challenge, and password AVPs. Where the challenge is the// 16 bytes from the implicit challenge. void ttls_do_chap(struct generic_eap_data *thisint, char *out_data, int *out_size){ u_char *challenge = NULL, *tohash = NULL; u_char *user_passwd = NULL; u_char chap_challenge[18], chap_hash[17];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -