📄 ttlsphase2.cpp
字号:
/**************************************************************************/
/* WIRE1x Version 1.0: A client-side 802.1x implementation */
/* based on xsupplicant of Open1x for Windows XP, 2000, 98, and Me */
/* */
/* 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) 2004, WIRE Lab, National Tsing Hua Univ., Hsinchu, Taiwan*/
/* 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.
*/
#include <stdafx.h>
#include <stdlib.h>#include <string.h>#include <unistd.h>#include <stdio.h>#include <ctype.h>#include <assert.h>#include <winsock.h>
#include <openssl/ssl.h>#include "eapcrypt.h"#include "userconf.h"#include "ttlsphase2.h"#include "eapmschapv2.h"#ifndef TTLS_PHASE2_DEBUG#define TTLS_PHASE2_DEBUG 0#endif//*********************************************
//for uint32_t
typedef unsigned int uint32_t;
//for uint8_t
typedef unsigned char uint8_t;
//not sure
typedef unsigned long uint64_t;
//**********************************************// 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 14uint32_t avp_code;uint32_t bitmask_avp_len;// If we add a new phase 2 type, it needs to be defined here.char *phase2_auth_types[] = { "PAP", "CHAP", "MSCHAP", "MSCHAPV2", NULL};void (*phase2_method[])(char *, int *) = { ttls_do_pap, ttls_do_chap, ttls_do_mschap, ttls_do_mschapv2};// This is from section 10.1 of the TTLS RFC.char *implicit_challenge(){ return (char *)eapcrypt_gen_keyblock((u_char *)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); memset(out_value, 0, 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(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; username = get_phase2id(); username_size = strlen(username); // Send the Username AVP build_avp(USER_NAME_AVP, 0, MANDITORY_FLAG, (u_char *)username, username_size, (u_char *)out_data, &avp_out_size); avp_offset = avp_out_size; challenge = implicit_challenge(); 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), (u_char *)&mschap_challenge, 16, (u_char *)&out_data[avp_offset], &avp_out_size); avp_offset+=avp_out_size; memset(&mschap_answer, 0, 50);
memcpy(&mschap_answer, &mschap_challenge, 16); // The first 24 bytes should be left as 0s. password = get_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), (u_char *)&mschap_answer, 50, (u_char *)&out_data[avp_offset], &avp_out_size); avp_offset+=avp_out_size; *out_size = avp_offset; if (username != NULL) { free(username); username = NULL; } if (password != NULL) { free(password); password = NULL; }}// For phase 2 MS-CHAP, we get 8 bytes implicit challenge, and 1 byte for ID.void ttls_do_mschap(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; username = get_phase2id(); username_size = strlen(username); // Send the Username AVP build_avp(USER_NAME_AVP, 0, MANDITORY_FLAG, (u_char *)username, username_size, (u_char *)out_data, &avp_out_size); avp_offset = avp_out_size; challenge = implicit_challenge(); 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), (u_char *)&mschap_challenge, 8, (u_char *)&out_data[avp_offset], &avp_out_size); avp_offset+=avp_out_size; memset((char *)&mschap_answer[0], 0, 49); password = get_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), (u_char *)&mschap_answer, 50, (u_char *)&out_data[avp_offset], &avp_out_size); avp_offset+=avp_out_size; *out_size = avp_offset; if (username != NULL) { free(username); username = NULL; } if (password != NULL) { free(password); password = NULL; }}// 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(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]; uint8_t session_id; int username_size, avp_out_size; int avp_offset, md5_length, hashlen; EVP_MD_CTX *ctx=NULL; char *username = NULL; username = get_phase2id(); username_size = strlen(username); build_avp(USER_NAME_AVP, 0, MANDITORY_FLAG, (u_char *)username, username_size, (u_char *)out_data, &avp_out_size); avp_offset = avp_out_size; // Get the implicit challenge. challenge = (u_char *)implicit_challenge(); assert(challenge != NULL); memcpy(&chap_challenge, challenge, 16); session_id = challenge[16]; // Build the password hash. ctx = (EVP_MD_CTX *)malloc(sizeof(EVP_MD_CTX)); if (ctx == NULL) { return; } user_passwd = (u_char *)get_password(); if(username!=NULL) { free(username); username = NULL; } tohash = (u_char *)malloc(1+16+strlen((char *)user_passwd)); if (tohash == NULL) { return; } tohash[0] = session_id; memcpy(&tohash[1], user_passwd, strlen((char *)user_passwd)); memcpy(&tohash[1+strlen((char *)user_passwd)], &chap_challenge, 16); hashlen = 1+strlen((char *)user_passwd)+16; free(user_passwd); // We are done with it. user_passwd = NULL; EVP_DigestInit(ctx, EVP_md5()); EVP_DigestUpdate(ctx, tohash, hashlen); EVP_DigestFinal(ctx, (u_char *)&chap_hash[1], (uint32_t *)&md5_length); if (md5_length != 16) // We didn't get back a valid hash! { } chap_hash[0]=session_id; build_avp(CHAP_PASSWORD_AVP, 0, MANDITORY_FLAG, (u_char *)chap_hash, 17, (u_char *)&out_data[avp_offset], &avp_out_size); avp_offset += avp_out_size; build_avp(CHAP_CHALLENGE_AVP, 0, MANDITORY_FLAG, (u_char *)&chap_challenge, 16, (u_char *)&out_data[avp_offset], &avp_out_size); if (tohash != NULL) { free(tohash); tohash = NULL; } if (ctx != NULL) { free(ctx); ctx = NULL; } if (user_passwd != NULL) free(user_passwd); *out_size = avp_offset+avp_out_size;}void ttls_do_pap(char *out_data, int *out_size){ char *username, *password, *tempbuf; int username_size, passwd_size, avp_out_size, avp_offset; // Get the username from our configuration. (We should probably change this // to allow a different username in phase 2... But, for now use the phase // one name.) username = get_phase2id(); password = get_password(); avp_offset = 0; username_size = strlen(username); build_avp(USER_NAME_AVP, 0, MANDITORY_FLAG, (u_char *)username, username_size, (u_char *)out_data, &avp_out_size); avp_offset += avp_out_size; // We have the username AVP loaded, so it's time to build the password AVP. passwd_size = (strlen(password) + (16-(strlen(password) % 16))); tempbuf = (char *)malloc(passwd_size); if (tempbuf == NULL) { return; } memset(tempbuf, 0, passwd_size);
memcpy(tempbuf, password, strlen(password)); build_avp(USER_PASSWORD_AVP, 0, MANDITORY_FLAG, (u_char *)tempbuf, passwd_size, (u_char *)&out_data[avp_offset], &avp_out_size); *out_size = avp_offset + avp_out_size; if (password != NULL) { free(password); password=NULL; } if (username != NULL) { free(username); username=NULL; } if (tempbuf != NULL) { free(tempbuf); tempbuf = NULL; }}// We don't do anything with the "in" stuff for now..void ttls_do_phase2(char *in, int in_size, char *out, int *out_size){ int i; char *phase2name=NULL; // We need to see what phase 2 method we should use. // First, make sure that the method name is in all caps. phase2name = get_phase2auth(); if (phase2name != NULL) { for (i=0;i<strlen(phase2name);i++) { phase2name[i] = toupper(phase2name[i]); } i = 0; while ((phase2_auth_types[i]!=NULL) && (strncmp(phase2name, phase2_auth_types[i], strlen(phase2name)) != 0)) { i++; } if (phase2_auth_types[i] == NULL) { ttls_do_pap(out, out_size); } else { (*phase2_method[i])(out, out_size); } } else { ttls_do_pap(out, out_size); }
if (phase2name != NULL) { free(phase2name); phase2name = NULL; }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -