/**
 * 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    1

uint32_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];
  uint8_t session_id;
  int username_size, avp_out_size;
  int avp_offset, md5_length, hashlen;
  EVP_MD_CTX *ctx=NULL;
  char *username = NULL;
  struct config_ttls_phase2 *userdata;
  struct config_eap_ttls *outerdata;
  struct config_chap *phase2data;

  if ((!thisint) || (!thisint->eap_conf_data))
    {
      debug_printf(DEBUG_NORMAL, "Invalid structure passed in to ttls_do_chap()!\n");
      return;
    }

  outerdata = (struct config_eap_ttls *)thisint->eap_conf_data;

  if (!outerdata->phase2)
    {
      debug_printf(DEBUG_NORMAL, "Invalid phase 2 data in ttls_do_chap()!\n");
      return;
    }

  userdata = (struct config_ttls_phase2 *)outerdata->phase2;

  while ((userdata != NULL) && (userdata->phase2_type != TTLS_PHASE2_CHAP))
    {
      userdata = userdata->next;
    }

  phase2data = (struct config_chap *)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 (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);
  build_avp(USER_NAME_AVP, 0, MANDITORY_FLAG, username, username_size, out_data, &avp_out_size);

  avp_offset = avp_out_size;

  // Get the implicit challenge.
  challenge = implicit_challenge(thisint);
  if (challenge == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Invalid implicit challenge in ttls_do_chap()!\n");
      return;
    }

  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)
    {
      debug_printf(DEBUG_NORMAL, "Error with malloc of ctx in ttls_do_chap().\n");
      return;
    }

  user_passwd = phase2data->password;

  tohash = (char *)malloc(1+16+strlen(user_passwd));
  if (tohash == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Error with malloc of \"tohash\" in ttls_do_chap().\n");
      return;
    }

  tohash[0] = session_id;
  memcpy(&tohash[1], user_passwd, strlen(user_passwd));
  memcpy(&tohash[1+strlen(user_passwd)], &chap_challenge, 16);
  hashlen = 1+strlen(user_passwd)+16;

  EVP_DigestInit(ctx, EVP_md5());
  EVP_DigestUpdate(ctx, tohash, hashlen);
  EVP_DigestFinal(ctx, (char *)&chap_hash[1], (int *)&md5_length);
  
  if (md5_length != 16)  // We didn't get back a valid hash!
    {
      debug_printf(DEBUG_NORMAL, "CHAP (MD5) hash length was not 16!\n");
    }
  chap_hash[0]=session_id;

  build_avp(CHAP_PASSWORD_AVP, 0, MANDITORY_FLAG, chap_hash, 17, &out_data[avp_offset], &avp_out_size);

  avp_offset += avp_out_size;

  build_avp(CHAP_CHALLENGE_AVP, 0, MANDITORY_FLAG, (char *)&chap_challenge, 16, &out_data[avp_offset], &avp_out_size);

  if (tohash != NULL)
    {
      free(tohash);
      tohash = NULL;
    }

  if (ctx != NULL)
    {
      free(ctx);
      ctx = NULL;
    }

  *out_size = avp_offset+avp_out_size;
}

void ttls_do_bogus(struct generic_eap_data *thisint, char *out_data, int *out_size)
{
  debug_printf(DEBUG_NORMAL, "Attempting to call an undefined Phase 2!\n");

  // We probably really don't want to die here.  We need to reconsider.
  exit(255);
}

void ttls_do_pap(struct generic_eap_data *thisint, char *out_data, int *out_size)
{
  char *tempbuf, *username;
  int passwd_size, avp_out_size, avp_offset;
  struct config_ttls_phase2 *userdata;
  struct config_eap_ttls *outerdata;
  struct config_pap *phase2data;

  if ((!thisint) || (!thisint->eap_conf_data))
    {
      debug_printf(DEBUG_NORMAL, "Invalid structure passed in to ttls_do_pap()!\n");
      return;
    }

  outerdata = (struct config_eap_ttls *)thisint->eap_conf_data;

  if (!outerdata->phase2)
    {
      debug_printf(DEBUG_NORMAL, "Invalid phase 2 data in ttls_do_pap()!\n");
      return;
    }

  userdata = (struct config_ttls_phase2 *)outerdata->phase2;

  while ((userdata != NULL) && (userdata->phase2_type != TTLS_PHASE2_PAP))
    {
      userdata =userdata->next;
    }

  phase2data = (struct config_pap *)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 (PAP)");
      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;
    }

  debug_printf(DEBUG_AUTHTYPES, "Phase 2 Username : %s\n",username);

  avp_offset = 0;

  build_avp(USER_NAME_AVP, 0, MANDITORY_FLAG, username, 
	    strlen(username), 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(phase2data->password) + 
		 (16-(strlen(phase2data->password) % 16)));

  tempbuf = (char *)malloc(passwd_size);
  if (tempbuf == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Error with malloc of tempbuf in ttls_do_pap().\n");
      return;
    }

  bzero(tempbuf, passwd_size);
  memcpy(tempbuf, phase2data->password, strlen(phase2data->password));

  build_avp(USER_PASSWORD_AVP, 0, MANDITORY_FLAG, tempbuf, passwd_size, &out_data[avp_offset], &avp_out_size);

  *out_size = avp_offset + avp_out_size;
  
  if (tempbuf != NULL)
    {
      free(tempbuf);
      tempbuf = NULL;
    }

  debug_printf(DEBUG_AUTHTYPES, "Returning from do_pap :\n");
  debug_hex_dump(DEBUG_AUTHTYPES, out_data, *out_size);
}

// We don't do anything with the "in" stuff for now..
void ttls_do_phase2(struct generic_eap_data *thisint, char *in, int in_size, char *out, int *out_size)
{
  int toencsize, i;
  char *toencout;
  struct config_eap_ttls *userdata;
  struct config_ttls_phase2 *phase2data;

  if ((!thisint) || (!thisint->eap_conf_data) || (!out))
    {
      debug_printf(DEBUG_NORMAL, "Invalid data pased in to ttls_do_phase2()!\n");
      return;
    }

  userdata = (struct config_eap_ttls *)thisint->eap_conf_data;

  if (!userdata->phase2)
    {
      debug_printf(DEBUG_NORMAL, "Invalid userdata in ttls_do_phase2()!\n");
      return;
    }

  phase2data = (struct config_ttls_phase2 *)userdata->phase2;

  toencout = (char *)malloc(1550);
  if (toencout == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory needed for encryption!\n");
      return;
    }

  toencsize = 1550;

  // We need to see what phase 2 method we should use.
  i = 0;

  while ((phase2types[i].phase2type != -1) && 
	 (userdata->phase2_type != phase2types[i].phase2type))
    {
      i++;
    }

  if (phase2types[i].phase2type > 0)
    {
      debug_printf(DEBUG_AUTHTYPES, "Doing Phase 2 %s!\n", phase2types[i].phase2name);
      (*phase2types[i].phase2handler)(thisint, toencout, &toencsize);
    } else {
      debug_printf(DEBUG_NORMAL, "ERROR!  : No phase 2 TTLS method was defined!\n");
      toencsize = 0;
    }

  if (toencsize == 0)
    {
      *out_size = 0;
      free(toencout);
      return;
    }

  tls_crypt_encrypt_nolen(thisint, toencout, toencsize, out, out_size);
  free(toencout);

  debug_printf(DEBUG_AUTHTYPES, "Returning from (TTLS) do_phase2 : \n");
  debug_hex_dump(DEBUG_AUTHTYPES, out, *out_size);
}


void ttls_phase2_failed(struct generic_eap_data *thisint)
{
  struct config_eap_ttls *userdata;
  /*
  struct config_ttls_phase2 *phase2data;
  struct config_pap *papphase2;
  struct config_chap *chapphase2;
  struct config_mschap *mschapphase2;
  struct config_mschapv2 *mschapv2phase2;
  int i=0;
  */

  if ((!thisint) || (!thisint->eap_conf_data))
    {
      debug_printf(DEBUG_NORMAL, "Invalid data passed to ttls_phase2_failed()!\n");
      return;
    }

  userdata = (struct config_eap_ttls *)thisint->eap_conf_data;

  if (!userdata->phase2)
    {
      debug_printf(DEBUG_NORMAL, "Invalid userdata in ttls_phase2_failed()!\n");
      return;
    }
  /*
  phase2data = (struct config_ttls_phase2 *)userdata->phase2;

  while ((phase2types[i].phase2type != -1) && 
	 (userdata->phase2_type != phase2types[i].phase2type))
    {
      i++;
    }

  if (!phase2data->phase2_data)
    {
      debug_printf(DEBUG_NORMAL, "No phase 2 user data!\n");
      return;
    }

  if (thisint->tempPwd != NULL)
    {
      debug_printf(DEBUG_AUTHTYPES, "Freeing tempPwd!\n");
      free(thisint->tempPwd);
      thisint->tempPwd = NULL;
    }

  switch(phase2types[i].phase2type)
    {
    case TTLS_PHASE2_PAP:
      papphase2 = (struct config_pap *)phase2data->phase2_data;
      if (papphase2->password)
	{
	  debug_printf(DEBUG_NORMAL, "Freed inner PAP password!\n");
	  free(papphase2->password);
	  papphase2->password = NULL;
	}
      break;

    case TTLS_PHASE2_CHAP:
      chapphase2 = (struct config_chap *)phase2data->phase2_data;
      if (chapphase2->password)
	{
	  free(chapphase2->password);
	  chapphase2->password = NULL;
	}
      break;

    case TTLS_PHASE2_MSCHAP:
      mschapphase2 = (struct config_mschap *)phase2data->phase2_data;
      if (mschapphase2->password)
	{
	  free(mschapphase2->password);
	  mschapphase2->password = NULL;
	}
      break;

    case TTLS_PHASE2_MSCHAPV2:
      mschapv2phase2 = (struct config_mschapv2 *)phase2data->phase2_data;
      if (mschapv2phase2->password)
	{
	  free(mschapv2phase2->password);
	  mschapv2phase2->password = NULL;
	}
      break;

    default :
      // Do nothing for now....
      break;
    }
  */
}


