⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cardif_radius.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************
 * A simple NAS implementation to allow direct authentication against a
 * RADIUS server for testing purposes!
 *
 * Licensed under a dual GPL/BSD license.  (See LICENSE file for more info.)
 *
 * File: cardif_radius.c
 *
 * Authors: Chris.Hessing@utah.edu
 *
 * $Id: cardif_radius.c,v 1.1.2.14 2006/12/29 19:28:17 chessing Exp $
 * $Date: 2006/12/29 19:28:17 $
 * $Log: cardif_radius.c,v $
 * Revision 1.1.2.14  2006/12/29 19:28:17  chessing
 * Changes to bring Mac/Linux versions in sync with Windows work.
 *
 * Revision 1.1.2.13  2006/11/15 23:28:33  chessing
 * Fixed a couple of things needed to start working on a build for Windows.
 *
 * Revision 1.1.2.12  2006/11/10 23:31:35  chessing
 * Replaced all malloc()+memset() with Malloc().
 *
 * Revision 1.1.2.11  2006/09/17 20:30:15  chessing
 * Fixes for TNC.
 *
 * Revision 1.1.2.10  2006/08/30 03:55:47  chessing
 * More work on EAP-FAST.  We can now almost complete an authentication.  Need to add the ability to provision PACs.
 *
 * Revision 1.1.2.9  2006/08/24 00:56:52  chessing
 * Added OpenSSL patch to handle TLS extensions needed by EAP-FAST.  Additional work on EAP-FAST.
 *
 * Revision 1.1.2.8  2006/08/20 18:11:06  chessing
 * Cleaned up some more #warnings from the code.
 *
 * Revision 1.1.2.7  2006/08/20 04:42:24  chessing
 * Can build under OS-X now.  Need to add wireless support.
 *
 * Revision 1.1.2.6  2006/08/17 00:36:43  chessing
 * Started to stub in EAP-FAST.  This code will not compile.
 *
 * Revision 1.1.2.5  2006/08/05 17:18:52  chessing
 * Cleaned up some warnings that are produced by GCC 4.
 *
 * Revision 1.1.2.4  2006/08/04 02:40:59  chessing
 * Fixes and updates from the plane, and work at hot stage.  EAP-TNC seems to be REALLY close to working correctly.
 *
 * Revision 1.1.2.3  2006/07/31 19:58:37  chessing
 * A few fixes for various bugs.  Started to add LEAP support back in.
 *
 * Revision 1.1.2.2  2006/07/23 21:47:04  chessing
 * Added some headers to the direct radius code, and created a README file that contains information about what it is, and how to use it.
 *
 *******************************************************************/
#ifdef USE_DIRECT_RADIUS

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <openssl/hmac.h>

#include "xsupconfig.h"
#include "context.h"
#include "xsup_common.h"
#include "xsup_debug.h"
#include "xsup_err.h"
#include "eap_sm.h"
#include "eapol.h"
#include "frame_structs.h"
#include "eap_types/eap_type_common.h"
#include "cardif_radius.h"

#warning Change the RAD_* values below to point to your RADIUS server.
#define RAD_SERVER "10.0.4.101"
#define RAD_PORT 1812
#define RAD_SECRET "secret"

#define TO_SEND_IDS  1

static struct sockaddr_in dest;

static uint8_t send_eap_id = 0;
static uint8_t packetid = 1;

int cardif_init(context *ctx, char driver)
{
  int *sock;

  ctx->sockData = Malloc(sizeof(int));
  if (ctx->sockData == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store socket "
		   "id!\n");
      return XEMALLOC;
    }
  
  sock = (int *)ctx->sockData;

  (*sock) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  printf("Got socket %d\n", (*sock));
  if ((*sock) == -1)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't get socket!\n");
      return XENOSOCK;
    }

  dest.sin_family = AF_INET;
  dest.sin_port = htons(RAD_PORT);
  if (inet_aton(RAD_SERVER, &dest.sin_addr) == 0)
    {
      debug_printf(DEBUG_NORMAL, "inet_aton() failed!\n");
      return XENOSOCK;
    }

  return XENONE;
}

int cardif_deinit(context *ctx)
{
  int *sock;

  sock = (int *)ctx->sockData;

  close((*sock));

  return XENONE;
}

int cardif_get_socket(context *ctx)
{
  int *sock;

  sock = (int *)ctx->sockData;

  return (*sock);
}

void build_rad_avp(uint8_t *packet, uint16_t *offset, uint8_t type, 
		   uint8_t len, uint8_t *data)
{
  struct radius_avp *radavp;

  radavp = (struct radius_avp *)&packet[(*offset)];

  radavp->attribute = type;
  radavp->length = len + sizeof(struct radius_avp);  

  memcpy(&packet[(*offset)+sizeof(struct radius_avp)], data, len);
  (*offset) += len + sizeof(struct radius_avp);
}

void build_rad_header(uint8_t *packet, uint16_t size)
{
  struct radius_pkt *pkt;
  int i;

  pkt = (struct radius_pkt *)packet;

  pkt->code = RADIUS_ACCESS_REQUEST;
  pkt->id = packetid;
  pkt->length = htons(size);
  
  for (i=0;i<16;i++)
    {
      pkt->authenticator[i] = random();
    }
  #warning Figure out the authenticator piece.
}

int cardif_sendframe(context *ctx)
{
  uint8_t *packet, blksiz;
  uint16_t offset = 0, eaplen, i, o;
  struct config_network *netdata;
  uint16_t blocks;
  int *sock;
  char authhmac[16];
  char *temp;

  debug_printf(DEBUG_NORMAL, "Preparing to send to RADIUS server.\n");

  if (ctx->send_size == 0)
    {
      debug_printf(DEBUG_NORMAL, "Nothing to send!\n");
      return -1;
    }

  packet = Malloc(1500);
  if (packet == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for packet!\n");
      return XEMALLOC;
    }

  netdata = config_get_network_config();

  offset = sizeof(struct radius_pkt);

  build_rad_avp(packet, &offset, RADIUS_AVP_USERNAME, 
		strlen(netdata->identity), netdata->identity);

  eaplen = eap_type_common_get_eap_length(&ctx->sendframe[OFFSET_TO_EAP]);

  debug_printf(DEBUG_NORMAL, "EAP packet is %d byte(s) long.\n", eaplen);

  // Now, add the EAP data in chunks.
  blocks = eaplen / (0xff - 2);

  if ((blocks * (0xff - 2)) != eaplen) blocks++;

  debug_printf(DEBUG_NORMAL, "There are %d blocks to send.\n", blocks);

  for (i=0; i < blocks; i++)
    {
      if (((i+1) * (0xff - 2)) > eaplen)
	{
	  blksiz = eaplen - (i * (0xff - 2));
	}
      else
	{
	  blksiz = (0xff - 2);
	}

      debug_printf(DEBUG_NORMAL, "This block is %d byte(s) long.\n", blksiz);

      build_rad_avp(packet, &offset, RADIUS_AVP_EAPMSG, blksiz,
		    &ctx->sendframe[OFFSET_TO_EAP + (i * (0xff - 2))]);
    }

  memset(&authhmac, 0x00, 16);

  build_rad_avp(packet, &offset, 80, 16, &authhmac);

  build_rad_header(packet, offset);

  printf("offset = %d\n", offset);
  temp = strdup(RAD_SECRET);
  o = offset;
  HMAC(EVP_md5(), temp, strlen(temp), packet, offset,
       authhmac, &i);

#warning Fix this correctly!
  offset = o;
  printf("offset = %d  i = %d\n", offset, i);

  memcpy(&packet[offset - 16], &authhmac, 16);
  FREE(temp);

  debug_printf(DEBUG_NORMAL, "Sending (%d) : \n", offset);
  debug_hex_dump(DEBUG_NORMAL, packet, offset);

  sock = (int *)ctx->sockData;
  
  if (sendto((*sock), packet, offset, 0, &dest, sizeof(dest)) != offset)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't send all of our packet?!\n");
    }

  FREE(packet);

  ctx->send_size = 0;

  return XENONE;
}

uint16_t verify_rad_hdr(uint8_t *packet, uint16_t size)
{
  struct radius_pkt *pkt;

  if (size < sizeof(struct radius_pkt))
    {
      debug_printf(DEBUG_NORMAL, "Packet too small to be a valid RADIUS packet!\n");
      return 0;
    }

  pkt = (struct radius_pkt *)packet;

  if ((pkt->code != RADIUS_ACCESS_CHALLENGE) && 
      (pkt->code != RADIUS_ACCESS_REJECT) &&
      (pkt->code != RADIUS_ACCESS_ACCEPT))
    {
      debug_printf(DEBUG_NORMAL, "Unknown RADIUS code! (%d)\n", pkt->code);
      return 0;
    }

  if (pkt->id != packetid)
    {
      debug_printf(DEBUG_NORMAL, "Invalid RADIUS packet id!  (Got %d should "
		   "be %d!)\n", pkt->id, packetid);
      return 0;
    }

  if (pkt->code == RADIUS_ACCESS_REJECT)
    {
      return 0xffff;
    }

  packetid++;

  return ntohs(pkt->length);
}

int cardif_getframe(context *ctx)
{
  uint8_t *packet;
  int size;
  int *sock;
  uint16_t radsiz, offset, eapptr;
  struct radius_avp *radavp;
  struct eapol_header *eapolhdr;

  packet = Malloc(1500);
  if (packet == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store RADIUS "
		   "packet!\n");
      return XEMALLOC;
    }

  sock = (int *)ctx->sockData;

#ifndef __CYGWIN__
  size = recvfrom((*sock), packet, 1500, MSG_DONTWAIT, NULL, 0);
#else
  size = recvfrom((*sock), packet, 1500, 0, NULL, 0);
#endif

  debug_printf(DEBUG_NORMAL, "Got a RADIUS packet of %d byte(s)\n", size);

⌨️ 快捷键说明

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