/**
 * A client-side 802.1x implementation
 *
 * 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.
 */

/*******************************************************************
 *
 * File: interactive.c
 *
 * Authors: Chris.Hessing@utah.edu
 *
 * $Id: interactive.c,v 1.8 2004/08/21 03:19:56 galimorerpg Exp $
 * $Date: 2004/08/21 03:19:56 $
 * $Log: interactive.c,v $
 * Revision 1.8  2004/08/21 03:19:56  galimorerpg
 * Caught an error where a null interface name would cause a crash.  We now catch and report the error (and line number).
 *
 * Revision 1.7  2004/07/15 04:15:35  chessing
 *
 * True/false int values are now bit flags in a byte.  PEAP now calls back in to functions from eap.c for phase 2 methods.  This allows for any phase 1 EAP type to work.  This resulted in some major changes the functions in eap.c, and in peap_phase2.c.  PEAP has been tested using both MS-CHAPv2, and EAP-MD5 as inner types.  More types need to be tested, and enabled.
 *
 * Revision 1.6  2004/06/15 03:22:29  chessing
 *
 * XSupplicant Release 1.0
 *
 *
 *******************************************************************/

#include <stdlib.h>
#include <string.h>
#include "xsup_err.h"
#include "xsup_debug.h"
#include "config.h"
#include "profile.h"
#include "eap.h"
#include "xsup_ipc.h"
#include "ipc_callout.h"
#include "interactive.h"

/*******************************************************************
 *
 * Check to see if we need to poke the GUI to ask for a password.  If we do,
 * then send the GUI a message, and return.  If we determine we have a 
 * password, then we should set procReady to TRUE.
 *
 * The caller should check the return to see if it is XPROMPT, or XENONE.
 * If it is XPROMPT, the caller may choose to check if the frame buffer 
 * contains anything.  If it does, it should call the 
 * interactive_store_frame() function.
 *
 * When called, **password should point to a pointer to the password for
 * the calling EAP type.  *tempPwd should point to thisint->tempPwd, and
 * eapType should point to a string that identifies the EAP type that is
 * calling the function.  (The EAP type string will be passed to the GUI
 * to be displayed in the box that prompts for a password.)  Optionally,
 * the caller may fill in a value for challenge.  This is a string that
 * will be sent to the GUI to be used to create the correct return value.
 * For EAP types like OTP and GTC, it should contain the challenge string
 * to be displayed to the user.  (Or it could be used with an OTP front-end
 * that simply requires the users password be typed, and it generates the
 * correct response sequence.  If there is no challenge data to be passed
 * up, this value should be NULL!
 *
 *******************************************************************/
int interactive_gui_prompt(char *interface, char *tempPwd, char *eapType, 
			   char *challenge)
{
  char packet[1512];
  struct ipc_header *header;
  int bufptr = 0;

  if (tempPwd == NULL)
    {
      // Ask the GUI to prompt for a password.
      debug_printf(DEBUG_AUTHTYPES, "Asking the GUI for a password.\n");
      debug_printf(DEBUG_AUTHTYPES, "EAP type is %s, challenge is %s\n",
		   eapType, challenge);

      bzero((char *)&packet[0], 512);
      header = (struct ipc_header *)&packet[0];
      header->version = 1;

      if(interface)
	{
	  strcpy(&header->interface[0], interface);
	}
      else
	{
	  debug_printf(DEBUG_NORMAL, "Invalid interface data in interactive_gui_prompt.c  Line: %d\n", __LINE__);
	  return XEBADCONFIG;
	}
      header->numcmds = 0;

      ipc_callout_request_password(&bufptr, (char *)&packet[0], 512, eapType, 
				   challenge);

      xsup_ipc_send_all_registered((char *)&packet, bufptr);
      
      // Let the caller know we are asking for a password.
      return XPROMPT;
    }

  return XENONE;
}

/***********************************************************************
 *
 * This function stores a frame in to an EAP type's data structure to be used
 * at a later time, once the needed interactive piece is complete.  (Usually
 * after the user has entered a password to the GUI.)  If there is no frame
 * to pass in, the cur_frame value should be NULL (or *NULL) and cur_size 
 * should be 0.  **frame_hook should be a pointer to a memory buffer that
 * we can allocate to store the frame passed in through cur_frame.  It should
 * be assumed that this buffer will be destroyed, and refilled in a new 
 * request frame comes in!  (Which is why we allocate the buffer in here. ;)
 * hook_size should be a pointer to an int that can hold the numeric 
 * representation of the size of frame_hook.
 *
 * In general, if the value for **cur_frame is NULL, there is no need to call
 * this function.  (It will simply waste a few cycles calling, and returning.)
 * However, calling this function with a NULL value will not fail, it will
 * simply return XENONE.
 *
 ***********************************************************************/
int interactive_store_frame(char *cur_frame, int cur_size, 
			    struct generic_eap_data *thisint)
{
  if (!thisint)
    {
      debug_printf(DEBUG_NORMAL, "Bad interface struct passed in to interactive_store_frame()\n");
      return XEMALLOC;
    }

  // First, make sure we have what we need!
  if (cur_size == 0) 
    {
      return XENONE;
    }
  if (cur_frame == NULL) 
    {
      return XENONE;
    }

  if (thisint->staleFrame != NULL)
    {
      free(thisint->staleFrame);
      thisint->staleFrame = NULL;
    }
  
  thisint->staleFrame = (char *)malloc(cur_size);
  if (thisint->staleFrame == NULL) return XEMALLOC;

  // Store the frame.
  memcpy(thisint->staleFrame, cur_frame, cur_size);
  thisint->staleSize = cur_size;
  // There were no errors to report.
  return XENONE;
}

