eapfast_phase2.c

来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 1,907 行 · 第 1/4 页

C
1,907
字号

  tempaidi = Malloc(ntohs(fasttlv->length));
  if (tempaidi == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store AID "
		   "info.\n");
      return 0;
    }

  memcpy(tempaidi, indata+4, ntohs(fasttlv->length));

  (*aid_info) = tempaidi;
  
  return (ntohs(fasttlv->length)+4);
}

/*******************************************************************
 *
 *  Process a PAC-Info Credential Lifetime message.
 *
 *******************************************************************/
uint16_t eapfast_phase2_process_cred_lifetime(uint8_t *indata, uint8_t *cred)
{
  struct eapfast_tlv *fasttlv;
  
  if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
    return 0;

  if (!xsup_assert((cred != NULL), "cred != NULL", FALSE))
    return 0;

  fasttlv = (struct eapfast_tlv *)cred;

  if (fasttlv->length != 4)
    {
      debug_printf(DEBUG_NORMAL, "Invalid Credential length!  Expected a "
		   "length of 4, got a length of %d.\n", fasttlv->length);
      return fasttlv->length+4;
    }

  memcpy(cred, fasttlv->data, 4);

  return fasttlv->length+4;
}


/*******************************************************************
 *
 *  Process a PAC Info TLV and all of it's children.
 *
 *******************************************************************/
uint16_t eapfast_phase2_process_pac_info(uint8_t *indata, 
					 struct pac_info *pacinfo)
{
  struct eapfast_tlv *fasttlv;
  uint16_t consumed = 0, result = 0, size = 0;

  if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
    return 0;

  if (!xsup_assert((pacinfo != NULL), "pacinfo != NULL", FALSE))
    return 0;

  fasttlv = (struct eapfast_tlv *)indata;

  size = ntohs(fasttlv->length);

  debug_printf(DEBUG_AUTHTYPES, "Processing %d byte(s) of data.\n", size);

  indata+=4;

  while (consumed < size)
    {
      fasttlv = (struct eapfast_tlv *)&indata[consumed];

      debug_printf(DEBUG_AUTHTYPES, "Data (%d) : \n", (size - consumed));
      debug_hex_dump(DEBUG_AUTHTYPES, &indata[consumed], (size - consumed));

      switch ((ntohs(fasttlv->type) & MANDATORY_TLV_MASK_OUT))
        {
        case FAST_CRED_LIFETIME:
	  debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info  CRED_LIFETIME TLV\n");
	  result = eapfast_phase2_process_cred_lifetime(&indata[consumed],
							(uint8_t *)&pacinfo->cred_lifetime);
          break;

        case FAST_AUTHORITY_ID:
	  debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info  AUTHORITY_ID TLV.\n");
	  result = eapfast_phase2_process_aid(&indata[consumed],
					      &pacinfo->aid, 
					      &pacinfo->aid_len);
          break;

        case FAST_INFO_ID:
	  debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info  INFO_ID TLV.\n");
	  result = eapfast_phase2_process_iid(&indata[consumed],
					      &pacinfo->iid,
					      &pacinfo->iid_len);
          break;

        case FAST_AUTH_ID_INFO:
	  debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info  AUTH_ID_INFO TLV.\n");
	  result = eapfast_phase2_process_pac_aidinfo(&indata[consumed],
						      &pacinfo->aid_info,
						      &pacinfo->aid_info_len);
          break;

	case FAST_PAC_TYPE:
	  debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info  PAC_TYPE TLV.\n");
	  result = eapfast_phase2_process_pac_type(&indata[consumed], 
						   &pacinfo->pac_type);
          break;

	default:
	  debug_printf(DEBUG_NORMAL, "Unknown/unexpected PAC-Info sub-value "
		       "of %d found!\n", ntohs(fasttlv->type));
	  return 0;
	}

      consumed += result;
    }

  return (consumed + 4);
}

/*******************************************************************
 *
 *  Write the PAC to a file for later use.
 *
 *******************************************************************/
int eapfast_phase2_store_pac(eap_type_data *eapdata, struct pac_values *pacs)
{
  xmlDocPtr doc;
  struct config_eap_fast *fastconf;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return -1;

  if (!xsup_assert((eapdata->eap_conf_data != NULL),
		   "eapdata->eap_conf_data != NULL", FALSE))
    return -1;

  fastconf = (struct config_eap_fast *)eapdata->eap_conf_data;

  eapfast_xml_init();

  if (fastconf->pac_location == NULL)
    {
      debug_printf(DEBUG_NORMAL, "You need to specify a location to store PAC"
		   " data in your configuration file!\n");
      return -1;
    }

  doc = eapfast_xml_open_pac(fastconf->pac_location);
  if (doc == NULL)
    {
      // We need to create a new PAC file.
      doc = eapfast_xml_create_pac_struct();
    }

  if (eapfast_xml_add_pac(doc, pacs) != 0)
    {
      debug_printf(DEBUG_NORMAL, "Error adding PAC data to PAC data structure "
		   "in memory!\n");
      return -1;
    }

  if (eapfast_xml_save(fastconf->pac_location, doc) != 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't save PAC file to location '%s'.\n");
      debug_printf(DEBUG_NORMAL, "You will be forced to provision again.\n");
      return -1;
    }

  return 0;
}

/*******************************************************************
 *
 *  Send a PAC Acknowledgement.
 *
 *******************************************************************/
void eapfast_phase2_build_pac_ack(eap_type_data *eapdata)
{
  // The ACK structure is the same as the TLV result.  So we will just
  // use that here.
  struct eapfast_tlv_result *ack;
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;
  struct eapfast_tlv *tlv;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return;

  debug_printf(DEBUG_AUTHTYPES, "Building PAC ACK!\n");
  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;

  tlv = (struct eapfast_tlv *)&phase2->result_data[phase2->result_size];
  tlv->type = htons(FAST_PAC_TLV | MANDATORY_TLV);
  tlv->length = htons(sizeof(struct eapfast_tlv_result));

  phase2->result_size += sizeof(struct eapfast_tlv);

  ack = (struct eapfast_tlv_result *)&phase2->result_data[phase2->result_size];

  ack->type = htons(FAST_PAC_ACK);
  ack->length = htons(2);
  ack->status = htons(1);   // Success.

  // And we are done.
  eapdata->methodState = DONE;

  phase2->result_size += sizeof(struct eapfast_tlv_result);
}

/*******************************************************************
 *
 *  Process a PAC TLV.
 *
 *******************************************************************/
uint16_t eapfast_phase2_pac_process(eap_type_data *eapdata, uint8_t *indata, 
				    uint16_t insize)
{
  struct eapfast_tlv *fastlv;
  uint16_t consumed = 0, result = 0, size = 0;
  struct pac_values pacs;
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;
  uint8_t *temp;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return 0;

  if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
		   FALSE))
    return 0;

  if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
    return 0;

  // We need to loop through all of the TLVs that we have in this EAP message,
  // and process each one.

  fastlv = (struct eapfast_tlv *)indata;

  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;

  size = ntohs(fastlv->length);

  debug_printf(DEBUG_AUTHTYPES, "Processing %d byte(s) of data.\n", size);
  
  indata+=4;

  while (consumed < size)
    {
      fastlv = (struct eapfast_tlv *)&indata[consumed];

      debug_printf(DEBUG_AUTHTYPES, "Remaining (%d) : \n", insize - consumed);
      debug_hex_dump(DEBUG_AUTHTYPES, &indata[consumed], (insize - consumed));

      switch ((ntohs(fastlv->type) & MANDATORY_TLV_MASK_OUT))
	{
	case FAST_PAC_KEY:
	  debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Key TLV.\n");
	  result = eapfast_phase2_process_pac_key(&indata[consumed], 
						  (uint8_t *)&pacs.pac_key);
	  break;
	  
	case FAST_PAC_OPAQUE:
	  debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Opaque TLV.\n");
	  result = eapfast_phase2_process_pac_opaque(&indata[consumed], 
						     &pacs.pac_opaque,
						     &pacs.pac_opaque_len);
	  break;
	  
	case FAST_PAC_INFO:
	  debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info TLV.\n");
	  result = eapfast_phase2_process_pac_info(&indata[consumed], 
						   &pacs.pacinfo);
	  break;
	  
	default:
	  debug_printf(DEBUG_NORMAL, "Unknown/unexpected PAC TLV request %d."
		       "\n", fastlv->type);
	  result = 0;
	  break;
	}

      if (result == 0) 
	{
	  debug_printf(DEBUG_NORMAL, "An error occurred processing PAC "
		       "information.  You will need to attempt to provision "
		       "again.\n");
	  return 0;
	}

      consumed += result;
    }

  if (eapfast_phase2_store_pac(eapdata, &pacs) == 0)
    {
      eapfast_phase2_build_pac_ack(eapdata);
    }
  else
    {
      // Return an error.
      temp = eapfast_phase2_gen_error_tlv(FAST_TUNNEL_COMPROMISE_ERROR,
					  (ntohs(fastlv->type) & MANDATORY_TLV));

      memcpy(&phase2->result_data[phase2->result_size], temp,
	     sizeof(struct eapfast_tlv_error));

      FREE(temp);
      phase2->result_size += sizeof(struct eapfast_tlv_error);
    }

  return (consumed + 4);
}

/**************************************************************
 *
 *  Generate the values needed to crypto bind the tunnel, and to
 *  populate EAP-MSCHAPv2 if we are going anonymous provisioning.
 *
 **************************************************************/
void eapfast_phase2_provision_gen_crypt(eap_type_data *eapdata)
{
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;
  uint8_t *keyblock, *temp;
  int offset_to_prov_keys;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return;

  if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
                   FALSE))
    {
      eap_type_common_fail(eapdata);
      return;
    }

  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
  
  offset_to_prov_keys = tls_funcs_get_keyblock_len(mytls_vars);

  keyblock = tls_funcs_gen_keyblock(mytls_vars, TLS_FUNCS_SERVER_FIRST,
				    FAST_PROVISIONING_SESSION_KEY,
				    FAST_PROVISIONING_SESSION_KEY_LEN);

  temp = &keyblock[offset_to_prov_keys];

  phase2->pkeys = Malloc(sizeof (struct provisioning_keys));
  if (phase2->pkeys == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Failed to allocate memory to store keys "
		   "needed to complete provisioning.\n");
      FREE(keyblock);
      return;
    }

  memcpy(phase2->pkeys, temp, sizeof(struct provisioning_keys));

  FREE(keyblock);
}

/**************************************************************
 *
 *  Process a phase 2 EAP message.
 *
 **************************************************************/
uint16_t eapfast_phase2_eap_process(eap_type_data *eapdata, uint8_t *indata, 
				    uint16_t insize)
{
  struct tls_vars *mytls_vars;
  struct eapfast_phase2 *phase2;
  uint16_t eapsize;
  uint8_t doneinit = 0;
  struct eapfast_tlv *fasttlv;
  struct config_eap_fast *fastconfig;

  if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
    return 0;

  if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
		   FALSE))
    {
      eap_type_common_fail(eapdata);
      return 0;
    }

  if (!xsup_assert((eapdata->eap_conf_data != NULL),
		   "eapdata->eap_conf_data != NULL", FALSE))
    {
      eap_type_common_fail(eapdata);
      return 0;
    }

  fasttlv = (struct eapfast_tlv *)indata;

  debug_printf(DEBUG_AUTHTYPES, "Processing phase 2 EAP.\n");
  debug_printf(DEBUG_AUTHTYPES, "EAP portion (%d) : \n", insize - 4);
  debug_hex_dump(DEBUG_AUTHTYPES, indata + 4, ntohs(fasttlv->length));

  mytls_vars = (struct tls_vars *)eapdata->eap_data;
  phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
  fastconfig = (struct config_eap_fast *)eapdata->eap_conf_data;

  phase2->sm->eapReqData = &indata[4];
  phase2->sm->eapReq = TRUE;

  if (phase2->sm->methodState == INIT)
    {
      doneinit = TRUE;

      // Need to generate some crypto data.
      eapfast_phase2_provision_gen_crypt(eapdata);

      if ((phase2->provisioning == TRUE) && 
	  (fastconfig->phase2->method_num == EAP_TYPE_MSCHAPV2))
	{
	  debug_printf(DEBUG_AUTHTYPES, "Setting up EAP-MS-CHAPv2.\n");
	  debug_printf(DEBUG_AUTHTYPES, "Peer Challenge : ");
	  debug_hex_printf(DEBUG_AUTHTYPES, phase2->pkeys->MSCHAPv2_ClientChallenge, 16);
	  debug_printf(DEBUG_AUTHTYPES, "Authenticator Challenge : ");
	  debug_hex_printf(DEBUG_AUTHTYPES, phase2->pkeys->MSCHAPv2_ServerChallenge, 16);

	  // Tweak MS-CHAPv2 to work properly for provisioning.
	  if (eapmschapv2_set_challenges(phase2->pkeys->MSCHAPv2_ClientChallenge,
					 phase2->pkeys->MSCHAPv2_ServerChallenge) != TRUE)
	    {
	      debug_printf(DEBUG_NORMAL, "Couldn't configure challenge values"
			   " needed for MS-CHAPv2.\n");
	      eap_type_common_fail(eapdata);
	      return 0;
	    }
	}

      if (phase2->provisioning == FALSE)
	{
	  debug_printf(DEBUG_AUTHTYPES, "Clearing EAP-FAST provisioning mode "
		       "from MS-CHAPv2.\n");
	  if (eapmschapv2_set_challenges(NULL, NULL) != TRUE)
	    {
	      debug_printf(DEBUG_NORMAL, "Couldn't clear MS-CHAPv2 challenges"
			   "! If you are using MS-CHAPv2 as an inner "
			   "authentication method, it will probably fail!\n");
	    }
	}
    }

  eap_sm_run(phase2->sm);

  if (doneinit) 
    {
      if (phase2->provisioning == TRUE)
	{
	  eapmschapv2_set_eap_fast_mode((eap_type_data *)phase2->sm->active, 
					TRUE);
	}
      else
	{
	  eapmschapv2_set_eap_fast_mode((eap_type_data *)phase2->sm->active, 
					FALSE);
	}
    }

  if (phase2->sm->eapRespData != NULL)
    {
      // Build up the response data.
      eapsize = eap_type_common_get_eap_length(phase2->sm->eapRespData);

      memcpy(&phase2->result_data[phase2->result_size + 4], 
	     phase2->sm->eapRespData, eapsize);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?