📄 cardif_radius.c
字号:
/*******************************************************************
* 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 + -