1252 lines
41 KiB
C
1252 lines
41 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip4_ipradius.c,v $ $Revision: 1.18.16.3 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmip4/config/ipmip4_ipradius.c,v $
|
|
* $Author: jsheng $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifdef IPRADIUS
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipmip4_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_clib2.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_ipd.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_hash.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_sysctl.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_sysvar.h>
|
|
|
|
#include <ipradius.h>
|
|
|
|
#include <ipmip.h>
|
|
#include <private/ipmip_buffer.h>
|
|
#include <private/ipmip_cli.h>
|
|
|
|
#include "ipmip4.h"
|
|
|
|
#include <private/ipmip4_radius.h>
|
|
#include <private/ipmip4_context.h>
|
|
#include <private/ipmip4_sysext.h>
|
|
#include <private/ipmip4_pktbuf.h>
|
|
#include <private/ipmip4_util.h>
|
|
|
|
#if defined(IPMCRYPTO)
|
|
#include <ip/openssl/md5.h>
|
|
#else
|
|
#include <openssl/md5.h>
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
#define IPMIP4_IPRADIUS_BUFFER_SIZE 4096
|
|
#define IPMIP4_IPRADIUS_AUTH_SIZE 16
|
|
#ifdef IPCOM_SYSLOG_PRIORITY
|
|
#undef IPCOM_SYSLOG_PRIORITY
|
|
#endif
|
|
#define IPCOM_SYSLOG_PRIORITY IPMIP4_SYSTEM_PRIORITY
|
|
#ifdef IPCOM_SYSLOG_FACILITY
|
|
#undef IPCOM_SYSLOG_FACILITY
|
|
#endif
|
|
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
typedef struct Ipmip4_ipradius_server
|
|
{
|
|
Ipradius_server auth;
|
|
Ipradius_server acct;
|
|
|
|
struct Ip_sockaddr_in lcl;
|
|
Ip_fd fd;
|
|
Ip_u32 msgid;
|
|
} Ipmip4_ipradius_server_t;
|
|
|
|
typedef struct Ipmip4_radius_context
|
|
{
|
|
Ipmip4_ipradius_server_t radius;
|
|
Ipcom_mutex lock;
|
|
|
|
struct Ipmip4_context *ctx;
|
|
|
|
Ipmip4_msgext_uhdr_t *nai;
|
|
|
|
/* User password */
|
|
char *pwd;
|
|
Ip_size_t pwd_len;
|
|
|
|
/* The procs I need for this particular context */
|
|
struct Ipmip_proc *proc;
|
|
struct Ipmip_proc *tmo2_proc;
|
|
} Ipmip4_radius_context_t;
|
|
|
|
|
|
/* Data required to properly handle the callback */
|
|
typedef struct Ipmip4_ipradius_cookie
|
|
{
|
|
Ipmip4_radius_func_t func;
|
|
|
|
Ipmip4_radius_context_t *radius;
|
|
Ipmip4_pktbuf_t *pbuf;
|
|
void *arg;
|
|
} Ipmip4_ipradius_cookie_t;
|
|
|
|
|
|
/* Data required to properly handle the callback */
|
|
typedef struct Ipmip4_ipradius_acct_cookie
|
|
{
|
|
Ipmip4_radius_func_t func;
|
|
|
|
Ipmip4_radius_context_t *radius;
|
|
Ipmip4_pktbuf_t *pbuf;
|
|
void *arg;
|
|
int state;
|
|
} Ipmip4_ipradius_acct_cookie_t;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* A link symbol */
|
|
int ipmip4_ipradius_link_symbol;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_event_callback
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_err
|
|
ipmip4_radius_event_callback(int event,
|
|
Ipradius_request* request,
|
|
Ipradius_header* request_packet,
|
|
Ipradius_header* response_packet,
|
|
Ipradius_server* server)
|
|
{
|
|
Ipmip4_ipradius_cookie_t *cookie = request->cookie;
|
|
Ipmip_proc_t *proc;
|
|
|
|
/* Select an appropriate proc structure */
|
|
if (ipcom_getpid() == cookie->radius->proc->pid)
|
|
proc = cookie->radius->proc;
|
|
else
|
|
proc = cookie->radius->tmo2_proc;
|
|
|
|
IPMIP_UNUSED_PARAMETER(request);
|
|
IPMIP_UNUSED_PARAMETER(server);
|
|
|
|
switch(event)
|
|
{
|
|
case IPRADIUS_EVENT_ACCESS_ACCEPT:
|
|
(*cookie->func) (IPMIP4_RADIUS_ACCESS_REQUEST_SUCCESS, cookie->radius->ctx, proc, cookie->radius, cookie->pbuf, cookie->arg, request_packet, response_packet);
|
|
break;
|
|
case IPRADIUS_EVENT_ACCESS_REJECT:
|
|
case IPRADIUS_EVENT_ACCESS_CHALLENGE:
|
|
case IPRADIUS_EVENT_ACCESS_TIMEOUT:
|
|
case IPRADIUS_EVENT_ACCESS_CANCELLED:
|
|
(*cookie->func) (IPMIP4_RADIUS_ACCESS_REQUEST_FAILURE, cookie->radius->ctx, proc, cookie->radius, cookie->pbuf, cookie->arg, request_packet, response_packet);
|
|
break;
|
|
|
|
default:
|
|
IP_PANIC();
|
|
break;
|
|
}
|
|
|
|
ipcom_free(cookie);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_event_callback
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_err
|
|
ipmip4_radius_acct_callback(int event,
|
|
Ipradius_request* request,
|
|
Ipradius_header* request_packet,
|
|
Ipradius_header* response_packet,
|
|
Ipradius_server* server)
|
|
{
|
|
Ipmip4_ipradius_acct_cookie_t *cookie = request->cookie;
|
|
Ipmip_proc_t *proc;
|
|
Ip_u32 type;
|
|
|
|
/* Select an appropriate proc structure */
|
|
if (ipcom_getpid() == cookie->radius->proc->pid)
|
|
proc = cookie->radius->proc;
|
|
else
|
|
proc = cookie->radius->tmo2_proc;
|
|
|
|
IPMIP_UNUSED_PARAMETER(request);
|
|
IPMIP_UNUSED_PARAMETER(server);
|
|
switch(event)
|
|
{
|
|
case IPRADIUS_EVENT_ACCOUNTING_RESPONSE:
|
|
if (cookie->state == IPRADIUS_ACCT_Stop)
|
|
(*cookie->func) (IPMIP4_RADIUS_ACCOUNTING_STOP_RESPONSE, cookie->radius->ctx, proc, cookie->radius, IP_NULL, cookie->arg, request_packet, response_packet);
|
|
else
|
|
{
|
|
(*cookie->func) (IPMIP4_RADIUS_ACCOUNTING_START_RESPONSE, cookie->radius->ctx, proc, cookie->radius, cookie->pbuf, cookie->arg, request_packet, response_packet);
|
|
cookie->pbuf = IP_NULL;
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IPRADIUS_EVENT_ACCOUNTING_REQUEST:
|
|
if (ipradius_attr_get_u32(request_packet, IPRADIUS_ATTR_Acct_Status_Type, &type) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "UNABLE TO LOCATE ACCOUNTING TYPE");
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/**/
|
|
switch (type)
|
|
{
|
|
case IPRADIUS_ACCT_Start:
|
|
(*cookie->func) (IPMIP4_RADIUS_ACCOUNTING_START, cookie->radius->ctx, proc, cookie->radius, cookie->pbuf, cookie->arg, request_packet, response_packet);
|
|
cookie->state = IPRADIUS_ACCT_Start;
|
|
break;
|
|
case IPRADIUS_ACCT_Stop:
|
|
(*cookie->func) (IPMIP4_RADIUS_ACCOUNTING_STOP, cookie->radius->ctx, proc, cookie->radius, cookie->pbuf, cookie->arg, request_packet, response_packet);
|
|
cookie->state = IPRADIUS_ACCT_Stop;
|
|
cookie->pbuf = IP_NULL;
|
|
break;
|
|
default:
|
|
IPCOM_LOG1(ERR, "UNKNOWN ACCOUNTING TYPE %d", type);
|
|
break;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
|
|
case IPRADIUS_EVENT_ACCOUNTING_CANCELLED:
|
|
case IPRADIUS_EVENT_ACCOUNTING_TIMEOUT:
|
|
(*cookie->func) (IPMIP4_RADIUS_ACCOUNTING_FAILED, cookie->radius->ctx, proc, cookie->radius, cookie->pbuf, cookie->arg, request_packet, IP_NULL);
|
|
break;
|
|
|
|
default:
|
|
IP_PANIC();
|
|
break;
|
|
}
|
|
|
|
ipcom_free(cookie);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip4_radius_proc(Ipmip4_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip4_radius_context_t *radius)
|
|
{
|
|
char *radbuf = ipcom_malloc(IPMIP4_IPRADIUS_BUFFER_SIZE);
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
|
|
/*********** tick loop ***********/
|
|
for (; proc->quit != IP_TRUE;)
|
|
{
|
|
Ip_fd_set rset;
|
|
int ret;
|
|
struct Ip_timeval tv;
|
|
|
|
/* Clear it */
|
|
IP_FD_ZERO(&rset);
|
|
|
|
/* Add the client socket */
|
|
IP_FD_SET(radius->radius.fd, &rset);
|
|
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 200 * 1000;
|
|
ret = ipcom_socketselect(radius->radius.fd + 1, &rset, IP_NULL, IP_NULL, &tv);
|
|
/* Timeout */
|
|
if (ret == 0)
|
|
continue;
|
|
else if (ret < 0)
|
|
{
|
|
IPCOM_LOG2(WARNING, "radius context socketselect() failed : %s [%d]", ipcom_strerror(ipcom_errno), ipcom_errno);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
struct Ip_sockaddr_in sin4;
|
|
Ip_socklen_t sin4_len = sizeof(sin4);
|
|
|
|
/* Time to read */
|
|
ret = ipcom_recvfrom(radius->radius.fd, radbuf, IPMIP4_IPRADIUS_BUFFER_SIZE, 0, (struct Ip_sockaddr *)&sin4, &sin4_len);
|
|
if (ret <= 0)
|
|
{
|
|
IPCOM_LOG2(WARNING, "radius context recvfrom() failed : %s [%d]", ipcom_strerror(ipcom_errno), ipcom_errno);
|
|
}
|
|
else
|
|
{
|
|
ret = ipradius_read((Ipradius_header*)radbuf, ret, (struct Ip_sockaddr *)&sin4);
|
|
if (ret != IPCOM_SUCCESS)
|
|
IPCOM_LOG0(ERR, "radius - input parsing failed");
|
|
}
|
|
}
|
|
}
|
|
|
|
ipcom_free(radbuf);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_access_request_chap_auth
|
|
*===========================================================================
|
|
* Description: Add CHAP specific radius authentication VSE's based on the
|
|
* packet buffer.
|
|
* Parameters: ctx - Context
|
|
* proc - Current process
|
|
* radius - Radius context
|
|
* pbuf - Packet buffer
|
|
* msg - Radius access request buffer
|
|
* Returns: IP_TRUE on success
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmip4_radius_access_request_chap_auth(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip4_radius_context_t *radius,
|
|
Ipmip4_pktbuf_t *pbuf,
|
|
Ipmip4_radius_packet_t *omsg)
|
|
{
|
|
Ipmip4_ext_gen_auth_t *auth = (Ipmip4_ext_gen_auth_t *)pbuf->ext.mobile.mn_aaa;
|
|
Ip_size_t auth_size = IPMIP4_MSGEXT_LHDR_EXT_SIZE(pbuf->ext.mobile.mn_aaa);
|
|
Ipradius_header *msg = omsg;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(radius);
|
|
|
|
/* We're not interested in the SPI field; only the authenticator */
|
|
auth_size -= 4;
|
|
if (auth_size > 128)
|
|
{
|
|
ipmip_pktbuf_error(&pbuf->ipmip,
|
|
0,
|
|
"Authentication extension too large in RRQ; unable to handle");
|
|
return IP_FALSE;
|
|
}
|
|
else
|
|
{
|
|
Ip_u8 *ptr;
|
|
Ip_size_t size;
|
|
MD5_CTX md5;
|
|
Ip_u8 zero = 0;
|
|
|
|
/* Add the CHAP challenge */
|
|
MD5_Init(&md5);
|
|
|
|
ptr = IPMIP_BUFFER_PTR(&pbuf->ipmip.packet);
|
|
size = (Ip_size_t)((char *)pbuf->ext.mobile.mn_aaa - (char *)ptr) + IPMIP4_EXT_GENAUTHHDR_LENGTH;
|
|
|
|
MD5_Update(&md5, ptr, size);
|
|
MD5_Final((unsigned char *)proc->ntop.ntop_pbuf, &md5);
|
|
|
|
if (pbuf->ext.mobile.challenge == IP_NULL || IPMIP4_MSGEXT_SHDR_EXT_SIZE(pbuf->ext.mobile.challenge) == 0)
|
|
{
|
|
ptr = &zero;
|
|
size = 1;
|
|
}
|
|
else
|
|
{
|
|
/* Add the 237 low bytes of the challenge */
|
|
ptr = IPMIP4_MSGEXT_SHDR_EXT_DATA(pbuf->ext.mobile.challenge);
|
|
size = IPMIP4_MSGEXT_SHDR_EXT_SIZE(pbuf->ext.mobile.challenge);
|
|
}
|
|
|
|
if (size < 238)
|
|
ipcom_memcpy(&proc->ntop.ntop_pbuf[16], ptr, size);
|
|
else
|
|
{
|
|
Ip_size_t diff = size - 237;
|
|
|
|
size -= diff;
|
|
ipcom_memcpy(&proc->ntop.ntop_pbuf[16], ptr + diff, size);
|
|
}
|
|
|
|
/* Add the MD5 hash */
|
|
size += 16;
|
|
|
|
(void)ipradius_attr_add_array(msg,
|
|
IPRADIUS_ATTR_CHAP_Challenge,
|
|
(Ip_u8*)&proc->ntop.ntop_pbuf[0],
|
|
(Ip_u8)size);
|
|
|
|
proc->ntop.ntop_pbuf[0] = ptr[0];
|
|
ipcom_memcpy(&proc->ntop.ntop_pbuf[1], &auth->authenticator[0], auth_size);
|
|
|
|
/* Add the CHAP challenge */
|
|
(void)ipradius_attr_add_array(msg,
|
|
IPRADIUS_ATTR_CHAP_Password,
|
|
(Ip_u8*)proc->ntop.ntop_pbuf,
|
|
(Ip_u8)auth_size + 1);
|
|
return IP_TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip4_radius_dump_server(struct Ipmip_proc *proc,
|
|
Ipmip_cli_message_t *request,
|
|
Ipradius_server *server,
|
|
const char *vformat,
|
|
const char *pre)
|
|
{
|
|
ipmip_cli_config_printf(&request->message,
|
|
"%s.%s.address=%s",
|
|
vformat, pre, ipmip_ntop_inet(proc, server->server_addr.sin.sin_addr.s_addr));
|
|
|
|
ipmip_cli_config_printf(&request->message,
|
|
"%s.%s.secret=<hidden>",
|
|
vformat, pre);
|
|
|
|
ipmip_cli_config_printf(&request->message,
|
|
"%s.%s.port=%d",
|
|
vformat, pre, ip_ntohs(server->server_addr.sin.sin_port));
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_read_server
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmip4_radius_read_server(Ipradius_server *server,
|
|
const char *defbase,
|
|
const char *vformat,
|
|
const char *pre,
|
|
Ip_u16 defport,
|
|
int server_type)
|
|
{
|
|
char *secret = IP_NULL;
|
|
Ip_u32 srv;
|
|
Ip_bool success = IP_FALSE;
|
|
Ip_size_t sz;
|
|
|
|
if (vformat)
|
|
{
|
|
if (!ipmip_sysvar_inet(0, &srv, IP_NULL, "%s.%s.address", vformat, pre) && defbase)
|
|
(void)ipmip_sysvar_inet(0, &srv, IP_NULL, "%s.%s.address", defbase, pre);
|
|
}
|
|
else
|
|
(void)ipmip_sysvar_inet(0, &srv, IP_NULL, "%s.%s.address", defbase, pre);
|
|
|
|
if (srv == 0)
|
|
{
|
|
IPCOM_LOG1(ERR, "IPMIP4: Radius configuration; %s server address not specified.", pre);
|
|
goto done_out;
|
|
}
|
|
|
|
if (vformat)
|
|
secret = ipmip_sysvar("%s.%s.secret", vformat, pre);
|
|
if (secret == IP_NULL && defbase)
|
|
secret = ipmip_sysvar("%s.%s.secret", defbase, pre);
|
|
|
|
if (!secret)
|
|
{
|
|
IPCOM_LOG1(ERR, "IPMIP4: Radius configuration; %s secret not specified", pre);
|
|
goto done_out;
|
|
}
|
|
|
|
/* Setup the server */
|
|
server->server_addr.sin.sin_family = IP_AF_INET;
|
|
server->server_addr.sin.sin_addr.s_addr = srv;
|
|
|
|
if (defbase)
|
|
defport = ipmip_sysvar_ulong(defport, "%s.%s.port", defbase, pre);
|
|
|
|
if (vformat)
|
|
defport = ipmip_sysvar_ulong(defport, "%s.%s.port", vformat, pre);
|
|
server->server_addr.sin.sin_port = ipcom_htons(defport);
|
|
|
|
IPCOM_SA_LEN_SET(&server->server_addr.sin, sizeof(struct Ip_sockaddr_in));
|
|
|
|
sz = ipcom_strlen(secret);
|
|
sz = IP_MIN(sz, sizeof(server->shared_secret));
|
|
ipcom_strncpy((char *)server->shared_secret, (char *)secret, sz);
|
|
|
|
/* Force terminate string unconditionally */
|
|
server->shared_secret[IPRADIUS_MAX_SECRET_SIZE - 1] = '\0';
|
|
|
|
/**/
|
|
server->shared_secret_len = sz;
|
|
server->index = 0;
|
|
server->pollnum = 3;
|
|
server->pollsec = 3;
|
|
server->server_type = server_type;
|
|
server->conf[0] = (unsigned long)-1;
|
|
success = IP_TRUE;
|
|
|
|
done_out:
|
|
if (secret)
|
|
ipcom_free(secret);
|
|
return success;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_context_create
|
|
*===========================================================================
|
|
* Description: Create a radius context if so specified by the configuration
|
|
* parameters
|
|
* Parameters: ctx - MIPv4 context
|
|
* proc - Current process context
|
|
* func - Radius processing callback function
|
|
* format - Base configuration path
|
|
* Returns: A radius context if properly configured and enabled
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipmip4_radius_context_t *
|
|
ipmip4_radius_context_create(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
const char *defbase,
|
|
const char *format,
|
|
...)
|
|
{
|
|
char *vformat = IP_NULL;
|
|
Ipmip4_radius_context_t *radius = IP_NULL;
|
|
va_list ap;
|
|
|
|
if (format)
|
|
{
|
|
va_start(ap, format);
|
|
vformat = ipmip_util_vstrdup(format, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
if (!vformat && !defbase)
|
|
return IP_NULL;
|
|
|
|
radius = ipcom_calloc(1, sizeof(*radius));
|
|
if (!radius)
|
|
{
|
|
IPCOM_LOG0(ERR, "IPMIP4: Radius configuration; failed to allocate memory");
|
|
goto done_out;
|
|
}
|
|
|
|
(void)ipcom_mutex_create(&radius->lock);
|
|
|
|
/* Base parameters */
|
|
radius->ctx = ctx;
|
|
radius->radius.fd = IP_INVALID_SOCKET;
|
|
|
|
if (vformat)
|
|
radius->nai = (Ipmip4_msgext_uhdr_t *)ipmip4_sysext_nai_aaah("%s.nai", vformat);
|
|
if (defbase && radius->nai == IP_NULL)
|
|
radius->nai = (Ipmip4_msgext_uhdr_t *)ipmip4_sysext_nai_aaah("%s.nai", defbase);
|
|
|
|
if (vformat)
|
|
radius->pwd = ipmip_sysvar("%s.user_password", vformat);
|
|
if (defbase && radius->pwd == IP_NULL)
|
|
radius->pwd = ipmip_sysvar("%s.user_password", defbase);
|
|
if (radius->pwd)
|
|
radius->pwd_len = ipcom_strlen(radius->pwd);
|
|
|
|
ipmip4_radius_read_server(&radius->radius.auth, defbase, vformat, "access", 1812, IPRADIUS_ACCESS_SERVER);
|
|
ipmip4_radius_read_server(&radius->radius.acct, defbase, vformat, "accounting", 1813, IPRADIUS_ACCOUNTING_SERVER);
|
|
|
|
radius->radius.lcl.sin_family = IP_AF_INET;
|
|
|
|
if (vformat)
|
|
{
|
|
if (!ipmip_sysvar_inet(0, &radius->radius.lcl.sin_addr.s_addr, IP_NULL, "%s.local.address", vformat) && defbase)
|
|
(void)ipmip_sysvar_inet(0, &radius->radius.lcl.sin_addr.s_addr, IP_NULL, "%s.local.address", defbase);
|
|
|
|
}
|
|
else
|
|
{
|
|
(void)ipmip_sysvar_inet(0, &radius->radius.lcl.sin_addr.s_addr, IP_NULL, "%s.local.address", defbase);
|
|
}
|
|
|
|
radius->radius.lcl.sin_port = 0;
|
|
IPCOM_SA_LEN_SET(&radius->radius.lcl, sizeof(struct Ip_sockaddr_in));
|
|
|
|
/* Create the socket */
|
|
radius->radius.fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, IP_IPPROTO_UDP);
|
|
if (radius->radius.fd == IP_INVALID_SOCKET)
|
|
{
|
|
IPCOM_LOG1(ERR, "IPMIP4: Radius configuration; failed to allocate datagram socket = %x", ipcom_errno);
|
|
goto error_out;
|
|
}
|
|
|
|
if (ipcom_bind(radius->radius.fd, (struct Ip_sockaddr *)&radius->radius.lcl, sizeof(radius->radius.lcl)) < 0)
|
|
{
|
|
IPCOM_LOG1(ERR, "IPMIP4: Radius configuration; failed to bind datagram socket = %x", ipcom_errno);
|
|
goto error_out;
|
|
}
|
|
|
|
/* Add the server */
|
|
if (radius->radius.auth.server_type != 0)
|
|
ipradius_server_add(&radius->radius.auth);
|
|
if (radius->radius.acct.server_type != 0)
|
|
ipradius_server_add(&radius->radius.acct);
|
|
|
|
radius->tmo2_proc = ipmip_proc_alloc();
|
|
if (radius->tmo2_proc == IP_NULL)
|
|
goto error_out;
|
|
|
|
/* Need to start the radius process */
|
|
radius->proc = ipmip_proc_start(&ctx->ipmip, proc, "radius", (Ipmip_proc_func_t)ipmip4_radius_proc, radius);
|
|
if (radius->proc == IP_NULL)
|
|
goto error_out;
|
|
|
|
done_out:
|
|
ipcom_free(vformat);
|
|
return radius;
|
|
|
|
error_out:
|
|
ipcom_mutex_delete(&radius->lock);
|
|
if (radius->radius.fd != IP_INVALID_SOCKET)
|
|
ipcom_socketclose(radius->radius.fd);
|
|
if (radius->tmo2_proc)
|
|
ipmip_proc_destroy(radius->tmo2_proc);
|
|
ipcom_free(radius);
|
|
radius = IP_NULL;
|
|
goto done_out;
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip4_radius_context_dump(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip4_radius_context_t *radius,
|
|
Ipmip_cli_message_t *request,
|
|
const char *format,
|
|
...)
|
|
{
|
|
char *vformat = IP_NULL;
|
|
va_list ap;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
|
|
va_start(ap, format);
|
|
vformat = ipmip_util_vstrdup(format, ap);
|
|
va_end(ap);
|
|
|
|
if (radius->nai)
|
|
{
|
|
Ip_u8 *data = &((Ip_u8 *)radius->nai)[3];
|
|
ipmip_cli_config_printf(&request->message,
|
|
"%s.nai=%s",
|
|
vformat, data);
|
|
}
|
|
|
|
if (radius->pwd)
|
|
{
|
|
ipmip_cli_config_printf(&request->message,
|
|
"%s.user_password=<hidden>",
|
|
vformat);
|
|
}
|
|
|
|
ipmip_cli_config_printf(&request->message,
|
|
"%s.local.address=%s",
|
|
vformat, ipmip_ntop_inet(proc, radius->radius.lcl.sin_addr.s_addr));
|
|
|
|
ipmip4_radius_dump_server(proc, request, &radius->radius.auth, vformat, "access");
|
|
ipmip4_radius_dump_server(proc, request, &radius->radius.acct, vformat, "accounting");
|
|
|
|
ipcom_free(vformat);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_context_destroy
|
|
*===========================================================================
|
|
* Description: Stop and destroy a radius context
|
|
* Parameters: ctx - The context
|
|
* proc - Current process
|
|
* radius - Radius context.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip4_radius_context_destroy(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip4_radius_context_t *radius)
|
|
{
|
|
if (radius != IP_NULL)
|
|
{
|
|
/* Do stop the context */
|
|
ipmip_proc_stop(&ctx->ipmip, proc, radius->proc, IP_NULL, IP_NULL);
|
|
ipmip_proc_destroy(radius->tmo2_proc);
|
|
ipcom_mutex_delete(&radius->lock);
|
|
|
|
if (radius->radius.acct.server_type)
|
|
ipradius_server_remove(&radius->radius.acct);
|
|
if (radius->radius.auth.server_type)
|
|
ipradius_server_remove(&radius->radius.auth);
|
|
|
|
ipcom_socketclose(radius->radius.fd);
|
|
|
|
if (radius->pwd)
|
|
ipcom_free(radius->pwd);
|
|
if (radius->nai)
|
|
ipcom_free(radius->nai);
|
|
ipcom_free(radius);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_access_request
|
|
*===========================================================================
|
|
* Description: Create a radius access base message
|
|
* Parameters: ctx - Context
|
|
* proc - Current process
|
|
* radius - Radius context
|
|
* Returns: A message structure if successful
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipmip4_radius_packet_t*
|
|
ipmip4_radius_access_request_init(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip4_radius_context_t *radius)
|
|
{
|
|
Ipradius_header *msg = ipradius_access_request_pkt_malloc();
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (msg == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
ipcom_mutex_lock(radius->lock);
|
|
msg->id = ++radius->radius.msgid;
|
|
ipcom_mutex_unlock(radius->lock);
|
|
msg->code = IPRADIUS_CODE_Access_Request;
|
|
return (Ipmip4_radius_packet_t*)msg;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_access_request
|
|
*===========================================================================
|
|
* Description: Do an ordinary access request; no challenge provided
|
|
* Parameters: ctx - Context
|
|
* proc - Current process
|
|
* radius - Radius context
|
|
* func - Radius callback function
|
|
* nai - Identity of the requesting node
|
|
* pbuf - Current transaction
|
|
* Returns: IP_TRUE on successful request transmission.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip4_radius_access_request(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip4_radius_context_t *radius,
|
|
Ipmip4_radius_func_t func,
|
|
Ipmip4_radius_packet_t *omsg,
|
|
Ipmip4_pktbuf_t *pbuf,
|
|
void *arg,
|
|
int auth_type)
|
|
{
|
|
Ipradius_request request = {0};
|
|
Ip_u8 errattr = 0;
|
|
Ipmip4_ipradius_cookie_t *cookie;
|
|
Ipradius_header *msg = omsg;
|
|
|
|
if (radius->radius.auth.server_type == 0)
|
|
{
|
|
ipmip_pktbuf_error(&pbuf->ipmip,
|
|
0,
|
|
"RADIUS access server not properly configured");
|
|
ipmip4_radius_access_request_free(ctx, proc, radius, omsg);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
if (auth_type == IPMIP4_RADIUS_AUTH_CHAP)
|
|
{
|
|
if (!ipmip4_radius_access_request_chap_auth(ctx, proc, radius, pbuf, omsg))
|
|
{
|
|
ipmip4_radius_access_request_free(ctx, proc, radius, omsg);
|
|
return IP_FALSE;
|
|
}
|
|
}
|
|
|
|
if (auth_type == IPMIP4_RADIUS_AUTH_USER_PASSWORD)
|
|
{
|
|
if (radius->pwd == IP_NULL)
|
|
{
|
|
ipmip_pktbuf_error(&pbuf->ipmip,
|
|
0,
|
|
"RADIUS User-Password authentication requested, but no configured password");
|
|
ipmip4_radius_access_request_free(ctx, proc, radius, omsg);
|
|
return IP_FALSE;
|
|
}
|
|
}
|
|
|
|
cookie = ipcom_malloc(sizeof(*cookie));
|
|
if (!cookie)
|
|
{
|
|
ipradius_access_request_pkt_free(msg);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/* Store the cookie info */
|
|
cookie->func = func;
|
|
cookie->radius = radius;
|
|
cookie->pbuf = pbuf;
|
|
cookie->arg = arg;
|
|
|
|
ipcom_mutex_lock(radius->lock);
|
|
request.unique = msg->id;
|
|
ipcom_mutex_unlock(radius->lock);
|
|
msg->code = IPRADIUS_CODE_Access_Request;
|
|
/* */
|
|
if (auth_type == IPMIP4_RADIUS_AUTH_USER_PASSWORD)
|
|
{
|
|
request.pwd_type = IPRADIUS_PAP_Password;
|
|
request.pwd_len = IP_MIN(sizeof(request.pwd), radius->pwd_len);
|
|
ipcom_strncpy(request.pwd, radius->pwd, request.pwd_len);
|
|
}
|
|
else
|
|
request.pwd_type = IPRADIUS_No_Password;
|
|
request.fd = radius->radius.fd;
|
|
request.event_callback = ipmip4_radius_event_callback;
|
|
request.cookie = cookie;
|
|
|
|
request.num_servers = 1;
|
|
ipcom_memcpy(&request.serv_list[0].server_addr,
|
|
&radius->radius.auth.server_addr,
|
|
sizeof(union Ip_sockaddr_union));
|
|
request.serv_list[0].server_type = radius->radius.auth.server_type;
|
|
request.serv_list[0].pollnum = radius->radius.auth.pollnum;
|
|
request.serv_list[0].pollsec = radius->radius.auth.pollsec;
|
|
|
|
/* Store the radius context */
|
|
if (ipradius_access_request(msg, &request, &errattr) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "Ipradius access request failed");
|
|
ipcom_free(cookie);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_access_request_free
|
|
*===========================================================================
|
|
* Description: Free a radius access base message
|
|
* Parameters: ctx - Context
|
|
* proc - Current process
|
|
* radius - Radius context
|
|
* msg - Message
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip4_radius_access_request_free(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip4_radius_context *radius,
|
|
Ipmip4_radius_packet_t *msg)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(radius);
|
|
|
|
ipradius_access_request_pkt_free((Ipradius_header *)msg);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_accounting_start
|
|
*===========================================================================
|
|
* Description: Start radius accounting for the session
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* func - Callback function
|
|
* unique_id - Unique session ID
|
|
* pbuf - Packet buffer
|
|
* Returns: IP_TRUE on success.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip4_radius_accounting_start(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip4_radius_context *radius,
|
|
Ipmip4_radius_func_t func,
|
|
Ip_u32 unique_id,
|
|
Ipmip4_pktbuf_t *pbuf,
|
|
void *arg)
|
|
{
|
|
Ipradius_request request;
|
|
Ipmip4_ipradius_acct_cookie_t *cookie;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (radius->radius.acct.server_type == 0)
|
|
return IP_FALSE;
|
|
|
|
cookie = ipcom_malloc(sizeof(*cookie));
|
|
if (!cookie)
|
|
return IP_FALSE;
|
|
|
|
ipcom_memset(&request, 0, sizeof(request));
|
|
|
|
/**/
|
|
request.unique = unique_id;
|
|
request.pwd_type = 0;
|
|
|
|
request.pwd_len = 0;
|
|
request.chap_ident = 0;
|
|
|
|
/* Set RADIUS socket descriptor and event callback. */
|
|
request.fd = radius->radius.fd;
|
|
request.event_callback = ipmip4_radius_acct_callback;
|
|
|
|
request.num_servers = 1;
|
|
ipcom_memcpy(&request.serv_list[0].server_addr,
|
|
&radius->radius.acct.server_addr,
|
|
sizeof(union Ip_sockaddr_union));
|
|
request.serv_list[0].server_type = radius->radius.acct.server_type;
|
|
request.serv_list[0].pollnum = radius->radius.acct.pollnum;
|
|
request.serv_list[0].pollsec = radius->radius.acct.pollsec;
|
|
|
|
cookie->func = func;
|
|
cookie->radius = radius;
|
|
cookie->pbuf = pbuf;
|
|
cookie->arg = arg;
|
|
|
|
request.cookie = cookie;
|
|
|
|
/* Start the accounting. */
|
|
if (ipradius_accounting_session_start(&request, 0) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "Failed to start accounting");
|
|
ipcom_free(cookie);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_accounting_stop
|
|
*===========================================================================
|
|
* Description: Stop radius accounting for the session
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* unique_id - Unique session ID
|
|
* Returns: IP_TRUE on success.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip4_radius_accounting_stop(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip4_radius_context *radius,
|
|
Ip_u32 unique_id)
|
|
{
|
|
int ret = ipradius_accounting_session_stop(unique_id, 1);
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(radius);
|
|
|
|
return ret == IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_attr_add
|
|
*===========================================================================
|
|
* Description: Add a radius extension
|
|
* Parameters: ctx - Context
|
|
* proc - Current process
|
|
* radius - Radius context
|
|
* msg - Message
|
|
* type - Type of extension
|
|
* data - Payload
|
|
* size - Size of payload
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip4_radius_attr_add(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip4_radius_context *radius,
|
|
Ipmip4_radius_packet_t *msg,
|
|
Ip_u8 type,
|
|
void *data,
|
|
Ip_size_t size)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(radius);
|
|
|
|
(void)ipradius_attr_add_array((Ipradius_header *)msg, type, data, size);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_attr_vendor_add
|
|
*===========================================================================
|
|
* Description: Add a radius VSA
|
|
* Parameters: ctx - Context
|
|
* proc - Current process
|
|
* radius - Radius context
|
|
* msg - Message
|
|
* vendor - Vendor
|
|
* type - Vendor Type
|
|
* data - Payload
|
|
* size - Size of payload
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip4_radius_attr_vendor_add(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip4_radius_context *radius,
|
|
Ipmip4_radius_packet_t *msg,
|
|
Ip_u32 vendor,
|
|
Ip_u8 type,
|
|
void *data,
|
|
Ip_size_t size)
|
|
{
|
|
Ip_u8 *ptr;
|
|
|
|
if ((size + 6) > sizeof(proc->ntop.ntop_pbuf))
|
|
return;
|
|
|
|
/* Do create a VENDOR VSA RADIUS attribute */
|
|
ptr = (Ip_u8 *)proc->ntop.ntop_pbuf;
|
|
|
|
/* Set VENDOR */
|
|
IP_SET_HTONL(&ptr[0], vendor);
|
|
ptr[4] = type;
|
|
ptr[5] = size + 2;
|
|
/* Copy VSA data */
|
|
ipcom_memcpy(&ptr[6], data, size);
|
|
|
|
/* Add the VSA */
|
|
ipmip4_radius_attr_add(ctx, proc, radius, msg, IPMIP4_RADIUS_ATTR_Vendor_Specific, proc->ntop.ntop_pbuf, size + 6);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_attr_next
|
|
*===========================================================================
|
|
* Description: Get next radius extension
|
|
* Parameters: ctx - Context
|
|
* proc - Current process
|
|
* radius - Radius context
|
|
* msg - Message
|
|
* last - Last retrieved attribute or IP_NULL if first.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_u8 *
|
|
ipmip4_radius_attr_next(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip4_radius_context *radius,
|
|
Ipmip4_radius_packet_t *msg,
|
|
Ip_u8 *last)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(radius);
|
|
|
|
/* Get next attribute */
|
|
return ipradius_attr_get_next((Ipradius_header *)msg, last);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_aaah
|
|
*===========================================================================
|
|
* Description: Return the AAAH NAI for a radius context. The memory is dynamically
|
|
* allocated and must be freed by the caller.
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* radius - Radius AAAH NAI
|
|
* Returns: The AAAH NAI.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipmip4_msgext_uhdr_t *
|
|
ipmip4_radius_aaah(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip4_radius_context *radius)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (radius->nai)
|
|
return ipmip4_msgext_shdr_dup(radius->nai);
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_radius_decrypt_tunnel_password
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipmip4_radius_decrypt_tunnel_password(struct Ipmip4_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip4_radius_context *radius,
|
|
Ipmip4_radius_packet_t *request,
|
|
Ip_u8 *attr,
|
|
Ip_size_t attr_len,
|
|
Ipmip_buffer_t *buffer)
|
|
{
|
|
Ip_u8 *salt;
|
|
Ip_u8 *data;
|
|
MD5_CTX md5;
|
|
char *decrypt;
|
|
Ipradius_header *req = (Ipradius_header *)request;
|
|
int i = 0;
|
|
int j = 0;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
|
|
/* Add the CHAP challenge */
|
|
MD5_Init(&md5);
|
|
|
|
ipmip_buffer_init(buffer);
|
|
|
|
salt = &attr[0];
|
|
data = &attr[2];
|
|
attr_len -= 2;
|
|
|
|
(void)ipmip_buffer_reserve(buffer, attr_len);
|
|
decrypt = IPMIP_BUFFER_PTR(buffer);
|
|
ipmip_buffer_append(buffer, IP_NULL, attr_len);
|
|
|
|
MD5_Update(&md5, radius->radius.auth.shared_secret, radius->radius.auth.shared_secret_len);
|
|
MD5_Update(&md5, req->auth, 16);
|
|
MD5_Update(&md5, salt, 2);
|
|
MD5_Final((unsigned char *)proc->ntop.ntop_pbuf, &md5);
|
|
|
|
while (j < (int)attr_len)
|
|
{
|
|
for (i = 0; i < 16; i++, j++)
|
|
decrypt[j] = data[j] ^ proc->ntop.ntop_pbuf[i];
|
|
|
|
if (j < (int)attr_len)
|
|
{
|
|
MD5_Init(&md5);
|
|
MD5_Update(&md5, radius->radius.auth.shared_secret, radius->radius.auth.shared_secret_len);
|
|
MD5_Update(&md5, &data[j - 16], 16);
|
|
MD5_Final((unsigned char *)proc->ntop.ntop_pbuf, &md5);
|
|
}
|
|
}
|
|
|
|
decrypt = IPMIP_BUFFER_PTR(buffer);
|
|
|
|
i = decrypt[0];
|
|
if (i >= (int)attr_len)
|
|
{
|
|
ipmip_buffer_release(buffer);
|
|
return IP_NULL;
|
|
}
|
|
|
|
decrypt++;
|
|
decrypt[i] = '\0';
|
|
return decrypt;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
#else /* IPRADIUS */
|
|
int ipmip4_radius_empty_file = 0;
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|