mirror of
https://github.com/3proxy/3proxy.git
synced 2025-02-23 02:25:40 +08:00
radauth.c: implements RADIUS authentication for 3proxy
This commit is contained in:
parent
f709255d62
commit
5cb3947c45
268
src/authradius.c
268
src/authradius.c
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <proxy.h>
|
#include "proxy.h"
|
||||||
#include "libs/md5.h"
|
#include "libs/md5.h"
|
||||||
|
|
||||||
#define AUTH_VECTOR_LEN 16
|
#define AUTH_VECTOR_LEN 16
|
||||||
@ -95,6 +95,10 @@
|
|||||||
#define PW_NAS_PORT_ID_STRING 87
|
#define PW_NAS_PORT_ID_STRING 87
|
||||||
#define PW_FRAMED_POOL 89
|
#define PW_FRAMED_POOL 89
|
||||||
|
|
||||||
|
#define PW_NAS_IPV6_ADDRESS 95
|
||||||
|
#define PW_LOGIN_IPV6_HOST 98
|
||||||
|
#define PW_FRAMED_IPV6_ADDRESS 168
|
||||||
|
|
||||||
#define PW_FALL_THROUGH 500
|
#define PW_FALL_THROUGH 500
|
||||||
#define PW_ADD_PORT_TO_IP_ADDRESS 501
|
#define PW_ADD_PORT_TO_IP_ADDRESS 501
|
||||||
#define PW_EXEC_PROGRAM 502
|
#define PW_EXEC_PROGRAM 502
|
||||||
@ -154,6 +158,17 @@
|
|||||||
#define PW_STATUS_ACCOUNTING_ON 7
|
#define PW_STATUS_ACCOUNTING_ON 7
|
||||||
#define PW_STATUS_ACCOUNTING_OFF 8
|
#define PW_STATUS_ACCOUNTING_OFF 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef NOIPV6
|
||||||
|
struct sockaddr_in radiuslist[MAXRADIUS];
|
||||||
|
#else
|
||||||
|
struct sockaddr_in6 radiuslist[MAXRADIUS];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int nradservers = 0;
|
||||||
|
char * radiussecret = NULL;
|
||||||
|
|
||||||
void md5_calc(unsigned char *output, unsigned char *input,
|
void md5_calc(unsigned char *output, unsigned char *input,
|
||||||
unsigned int inputlen);
|
unsigned int inputlen);
|
||||||
|
|
||||||
@ -274,10 +289,11 @@ void random_vector(uint8_t *vector)
|
|||||||
static int did_random = 0;
|
static int did_random = 0;
|
||||||
static int counter = 0;
|
static int counter = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&rad_mutex);
|
||||||
if (!did_random) {
|
if (!did_random) {
|
||||||
|
|
||||||
for (i = 0; i < (int)sizeof(random_vector_pool); i++) {
|
for (i = 0; i < (int)sizeof(random_vector_pool); i++) {
|
||||||
random_vector_pool[i] += myrand((void *) random_vector_pool+i, 1); & 0xff;
|
random_vector_pool[i] += myrand((void *) random_vector_pool+i, 1) & 0xff;
|
||||||
}
|
}
|
||||||
did_random = 1;
|
did_random = 1;
|
||||||
|
|
||||||
@ -288,7 +304,6 @@ void random_vector(uint8_t *vector)
|
|||||||
* and put the resulting information through MD5,
|
* and put the resulting information through MD5,
|
||||||
* so it's all mashed together.
|
* so it's all mashed together.
|
||||||
*/
|
*/
|
||||||
pthread_mutex_lock(&rad_mutex);
|
|
||||||
counter++;
|
counter++;
|
||||||
random_vector_pool[AUTH_VECTOR_LEN] += (counter & 0xff);
|
random_vector_pool[AUTH_VECTOR_LEN] += (counter & 0xff);
|
||||||
md5_calc((u_char *) random_vector_pool,
|
md5_calc((u_char *) random_vector_pool,
|
||||||
@ -337,50 +352,42 @@ typedef struct radius_packet_t {
|
|||||||
char buf[256];
|
char buf[256];
|
||||||
extern int ntry;
|
extern int ntry;
|
||||||
|
|
||||||
|
#define RETURN(xxx) { res = xxx; goto CLEANRET; }
|
||||||
|
|
||||||
|
|
||||||
int radauth(struct clientparam * param){
|
int radauth(struct clientparam * param){
|
||||||
{
|
|
||||||
int port = 0;
|
|
||||||
int loop;
|
int loop;
|
||||||
int id;
|
int id;
|
||||||
int res=0;
|
int res = 4;
|
||||||
SOCKET sockfd;
|
SOCKET sockfd = -1;
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
int total_length;
|
int total_length;
|
||||||
int len;
|
int len;
|
||||||
unsigned dst_ipaddr;
|
|
||||||
#ifdef NOIPV6
|
#ifdef NOIPV6
|
||||||
struct sockaddr_in saremote;
|
struct sockaddr_in saremote;
|
||||||
#else
|
#else
|
||||||
struct sockaddr_in6 saremote;
|
struct sockaddr_in6 saremote;
|
||||||
#endif
|
#endif
|
||||||
struct sockaddr *sa;
|
struct pollfd fds[1];
|
||||||
struct timeval tv;
|
|
||||||
fd_set rdfdesc;
|
|
||||||
char vector[AUTH_VECTOR_LEN];
|
char vector[AUTH_VECTOR_LEN];
|
||||||
radius_packet_t packet, rpacket;
|
radius_packet_t packet, rpacket;
|
||||||
int salen;
|
SASIZETYPE salen;
|
||||||
int data_len;
|
int data_len;
|
||||||
uint8_t *vendor_len;
|
uint8_t *vendor_len;
|
||||||
int count=0;
|
int count=0;
|
||||||
uint8_t *attr;
|
uint8_t *attr;
|
||||||
int haveerror;
|
|
||||||
int loginservice;
|
|
||||||
long vendor=0;
|
long vendor=0;
|
||||||
int vendorlen=0;
|
int vendorlen=0;
|
||||||
int mailservice=0;
|
|
||||||
|
|
||||||
|
if(!radiussecret || !nradservers) return 4;
|
||||||
|
|
||||||
memset(&packet, 0, sizeof(packet));
|
memset(&packet, 0, sizeof(packet));
|
||||||
|
|
||||||
random_vector(packet.vector);
|
random_vector(packet.vector);
|
||||||
|
|
||||||
id = (((int)getpid() + ntry) & 0xff);
|
id = (((int)getpid() + ntry) & 0xff);
|
||||||
*errorstring = NULL;
|
|
||||||
port = getport("radius");
|
|
||||||
if (port == 0) port = PW_AUTH_UDP_PORT;
|
|
||||||
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
||||||
perror("radclient: socket: ");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet.code = PW_AUTHENTICATION_REQUEST;
|
packet.code = PW_AUTHENTICATION_REQUEST;
|
||||||
packet.id=id;
|
packet.id=id;
|
||||||
@ -399,116 +406,132 @@ int radauth(struct clientparam * param){
|
|||||||
ptr+=4;
|
ptr+=4;
|
||||||
total_length+=6;
|
total_length+=6;
|
||||||
|
|
||||||
/* NAS-Port */
|
|
||||||
|
|
||||||
*ptr++ = PW_NAS_PORT_ID;
|
|
||||||
*ptr++ = 6;
|
|
||||||
(*(uint32_t *)ptr)=htonl((unsigned int)p->server_port);
|
|
||||||
ptr+=4;
|
|
||||||
total_length+=6;
|
|
||||||
|
|
||||||
/* NAS-Port-Type */
|
/* NAS-Port-Type */
|
||||||
|
|
||||||
*ptr++ = PW_NAS_PORT_TYPE;
|
*ptr++ = PW_NAS_PORT_TYPE;
|
||||||
*ptr++ = 6;
|
*ptr++ = 6;
|
||||||
(*(uint32_t *)ptr)=htonl(PW_NAS_PORT_VIRTUAL);
|
(*(uint32_t *)ptr)=htonl(PW_NAS_PORT_VIRTUAL);
|
||||||
ptr+=4;
|
ptr+=4;
|
||||||
total_length+=6;
|
total_length+=6;
|
||||||
|
|
||||||
/* NAS-IP-Address */
|
/* NAS-Port */
|
||||||
|
*ptr++ = PW_NAS_PORT_ID;
|
||||||
*ptr++ = PW_NAS_IP_ADDRESS;
|
|
||||||
*ptr++ = 6;
|
*ptr++ = 6;
|
||||||
(*(uint32_t *)ptr)=p->server_ip;
|
(*(uint32_t *)ptr)=htonl(*SAPORT(¶m->srv->intsa));
|
||||||
|
|
||||||
ptr+=4;
|
ptr+=4;
|
||||||
total_length+=6;
|
total_length+=6;
|
||||||
|
|
||||||
|
|
||||||
|
if(*SAFAMILY(¶m->sincl) == AF_INET6){
|
||||||
|
/* NAS-IPv6-Address */
|
||||||
|
*ptr++ = PW_NAS_IPV6_ADDRESS;
|
||||||
|
*ptr++ = 18;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* NAS-IP-Address */
|
||||||
|
*ptr++ = PW_NAS_IP_ADDRESS;
|
||||||
|
*ptr++ = 6;
|
||||||
|
}
|
||||||
|
len = SAADDRLEN(¶m->sincl);
|
||||||
|
memcpy(ptr, SAADDR(¶m->sincl), len);
|
||||||
|
ptr += len;
|
||||||
|
total_length += len;
|
||||||
|
|
||||||
|
/* NAS-Port */
|
||||||
|
*ptr++ = PW_LOGIN_TCP_PORT;
|
||||||
|
*ptr++ = 6;
|
||||||
|
(*(uint32_t *)ptr)=htonl(*SAPORT(¶m->req));
|
||||||
|
ptr+=4;
|
||||||
|
total_length+=6;
|
||||||
|
|
||||||
|
|
||||||
|
if(*SAFAMILY(¶m->req) == AF_INET6){
|
||||||
|
/* NAS-IPv6-Address */
|
||||||
|
*ptr++ = PW_LOGIN_IPV6_HOST;
|
||||||
|
*ptr++ = 18;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* NAS-IP-Address */
|
||||||
|
*ptr++ = PW_LOGIN_IP_HOST;
|
||||||
|
*ptr++ = 6;
|
||||||
|
}
|
||||||
|
len = SAADDRLEN(¶m->req);
|
||||||
|
memcpy(ptr, SAADDR(¶m->req), len);
|
||||||
|
ptr += len;
|
||||||
|
total_length += len;
|
||||||
|
|
||||||
|
|
||||||
/* Username */
|
/* Username */
|
||||||
len = strlen(p->user);
|
if(param->username){
|
||||||
if(len>128)len=128;
|
len = strlen(param->username);
|
||||||
*ptr++ = PW_USER_NAME;
|
if(len>128)len=128;
|
||||||
*ptr++ = len + 2;
|
*ptr++ = PW_USER_NAME;
|
||||||
memcpy(ptr, p->user, len);
|
*ptr++ = len + 2;
|
||||||
ptr+=len;
|
memcpy(ptr, param->username, len);
|
||||||
total_length += (len+2);
|
ptr+=len;
|
||||||
|
total_length += (len+2);
|
||||||
|
}
|
||||||
|
|
||||||
len = strlen(password);
|
if(param->password){
|
||||||
if(len > 128) len = 128;
|
len = strlen(param->password);
|
||||||
*ptr++ = PW_PASSWORD;
|
if(len > 128) len = 128;
|
||||||
ptr++;
|
*ptr++ = PW_PASSWORD;
|
||||||
memcpy(ptr, password, len);
|
ptr++;
|
||||||
rad_pwencode(ptr,
|
memcpy(ptr, param->password, len);
|
||||||
|
rad_pwencode(ptr,
|
||||||
&len,
|
&len,
|
||||||
p->radiussecret,
|
radiussecret,
|
||||||
(char *)packet.vector);
|
(char *)packet.vector);
|
||||||
*(ptr-1) = len + 2;
|
*(ptr-1) = len + 2;
|
||||||
ptr+=len;
|
ptr+=len;
|
||||||
total_length+= (len+2);
|
total_length+= (len+2);
|
||||||
|
}
|
||||||
|
|
||||||
total_length+=(4+AUTH_VECTOR_LEN);
|
total_length+=(4+AUTH_VECTOR_LEN);
|
||||||
packet.length = htons(total_length);
|
packet.length = htons(total_length);
|
||||||
memcpy(vector, packet.vector, AUTH_VECTOR_LEN);
|
memcpy(vector, packet.vector, AUTH_VECTOR_LEN);
|
||||||
|
|
||||||
for (loop = 0; p->radiuslist[loop] && loop < MAXRADIUS; loop++) {
|
for (loop = 0; loop < nradservers && loop < MAXRADIUS; loop++) {
|
||||||
*errorstring = 0;
|
|
||||||
haveerror = 0;
|
|
||||||
loginservice = 0;
|
|
||||||
packet.id++;
|
|
||||||
dst_ipaddr = ip_getaddr(p->radiuslist[loop]);
|
|
||||||
|
|
||||||
sa = (struct sockaddr_in *) &saremote;
|
saremote = radiuslist[loop];
|
||||||
memset ((char *) sa, '\0', sizeof (saremote));
|
#idef NOIPV6
|
||||||
sa->sin_family = AF_INET;
|
if(SAFAMILY(&saremote)!= AF_INET)continue;
|
||||||
sa->sin_addr.s_addr = dst_ipaddr;
|
#else
|
||||||
/*
|
if(SAFAMILY(&saremote)!= AF_INET && SAFAMILY(&saremote)!= AF_INET6)continue;
|
||||||
sa->sin_port = htons(port);
|
#endif
|
||||||
*/
|
packet.id++;
|
||||||
sa->sin_port = htons(1812);
|
if(sockfd >= 0) so._closesocket(sockfd);
|
||||||
res = sendto(sockfd, &packet, ntohs(packet.length), 0,
|
if ((sockfd = so._socket(SASOCK(saremote), SOCK_DGRAM, 0)) < 0) {
|
||||||
(struct sockaddr *)&saremote, sizeof(struct sockaddr_in));
|
return 4;
|
||||||
if(res != ntohs(packet.length)){
|
}
|
||||||
res = 1;
|
|
||||||
|
len = so._sendto(sockfd, &packet, ntohs(packet.length), 0,
|
||||||
|
(struct sockaddr *)&saremote, sizeof(saremote);
|
||||||
|
if(len != ntohs(packet.length)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* And wait for reply, timing out as necessary */
|
/* And wait for reply, timing out as necessary */
|
||||||
FD_ZERO(&rdfdesc);
|
|
||||||
FD_SET(sockfd, &rdfdesc);
|
|
||||||
|
|
||||||
tv.tv_sec = (int)timeout;
|
memset(fds, 0, sizeof(fds));
|
||||||
tv.tv_usec = 1000000 * (timeout - (int)timeout);
|
fds[0].fd = sockfd;
|
||||||
|
fds[0].events = POLLIN;
|
||||||
|
if(so._poll(fds, 1, conf.timeouts[SINGLEBYTE_L]*1000) <= 0) continue;
|
||||||
|
|
||||||
/* Something's wrong if we don't get exactly one fd. */
|
salen = sizeof(saremote);
|
||||||
if (select(sockfd + 1, &rdfdesc, NULL, NULL, &tv) != 1) {
|
|
||||||
res = 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&saremote, 0, sizeof(saremote));
|
|
||||||
salen = sizeof(struct sockaddr_in);
|
|
||||||
|
|
||||||
data_len = recvfrom(sockfd, &rpacket, sizeof(packet)-strlen(p->radiussecret),
|
data_len = so._recvfrom(sockfd, &rpacket, sizeof(packet)-16,
|
||||||
0, (struct sockaddr *)&saremote, &salen);
|
0, (struct sockaddr *)&saremote, &salen);
|
||||||
|
|
||||||
if (data_len < 0) {
|
|
||||||
res = 3;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_len < 20) {
|
if (data_len < 20) {
|
||||||
res = 4;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rpacket.code != PW_AUTHENTICATION_ACK &&
|
if( rpacket.code != PW_AUTHENTICATION_ACK &&
|
||||||
rpacket.code != PW_AUTHENTICATION_REJECT ){
|
rpacket.code != PW_AUTHENTICATION_REJECT ){
|
||||||
res = 5;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calc_replydigest((char *)&rpacket, packet.vector, p->radiussecret,
|
if (calc_replydigest((char *)&rpacket, packet.vector, radiussecret,
|
||||||
data_len) ){
|
data_len) ){
|
||||||
res = 5;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,7 +542,6 @@ int radauth(struct clientparam * param){
|
|||||||
*/
|
*/
|
||||||
total_length = ntohs(rpacket.length);
|
total_length = ntohs(rpacket.length);
|
||||||
if (data_len != total_length) {
|
if (data_len != total_length) {
|
||||||
res = 6;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +581,7 @@ int radauth(struct clientparam * param){
|
|||||||
* Sanity check the attributes for length.
|
* Sanity check the attributes for length.
|
||||||
*/
|
*/
|
||||||
if(!vendor && attr[0] == PW_VENDOR_SPECIFIC) {
|
if(!vendor && attr[0] == PW_VENDOR_SPECIFIC) {
|
||||||
if (attr[1] < 6 || count < 6) return 9;
|
if (attr[1] < 6 || count < 6) RETURN(4);
|
||||||
vendorlen = attr[1]-6;
|
vendorlen = attr[1]-6;
|
||||||
vendor = htonl(*((int*)(attr +2)));
|
vendor = htonl(*((int*)(attr +2)));
|
||||||
count -= 6;
|
count -= 6;
|
||||||
@ -570,9 +592,8 @@ int radauth(struct clientparam * param){
|
|||||||
if (!vendor && attr[0] == PW_REPLY_MESSAGE) {
|
if (!vendor && attr[0] == PW_REPLY_MESSAGE) {
|
||||||
memcpy(buf, attr+2, attr[1]-2);
|
memcpy(buf, attr+2, attr[1]-2);
|
||||||
buf[attr[1]-2]=0;
|
buf[attr[1]-2]=0;
|
||||||
haveerror = 1;
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
else if (vendor == SANDY && attr[0] == SANDY_MAIL_MAILBOX) {
|
else if (vendor == SANDY && attr[0] == SANDY_MAIL_MAILBOX) {
|
||||||
memcpy (p->drop_name, attr + 2, attr[1] - 2);
|
memcpy (p->drop_name, attr + 2, attr[1] - 2);
|
||||||
}
|
}
|
||||||
@ -582,18 +603,17 @@ int radauth(struct clientparam * param){
|
|||||||
else if (vendor == SANDY && attr[0] == SANDY_MAIL_SERVICE) {
|
else if (vendor == SANDY && attr[0] == SANDY_MAIL_SERVICE) {
|
||||||
mailservice = ntohl(*(int *)(attr+2)) ;
|
mailservice = ntohl(*(int *)(attr+2)) ;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
count -= attr[1]; /* grab the attribute length */
|
count -= attr[1]; /* grab the attribute length */
|
||||||
if(vendorlen) {
|
if(vendorlen) {
|
||||||
vendorlen -= attr[1];
|
vendorlen -= attr[1];
|
||||||
if (!vendorlen) vendor = 0;
|
if (!vendorlen) vendor = 0;
|
||||||
else if (vendorlen < 0) return 10;
|
else if (vendorlen < 0) RETURN(4);
|
||||||
}
|
}
|
||||||
attr += attr[1];
|
attr += attr[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count !=0 || vendorlen!=0) {
|
if (count !=0 || vendorlen!=0) {
|
||||||
res = 20;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -602,53 +622,13 @@ int radauth(struct clientparam * param){
|
|||||||
* If not, we complain, and throw the packet away.
|
* If not, we complain, and throw the packet away.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(haveerror){
|
|
||||||
*errorstring=buf;
|
|
||||||
}
|
|
||||||
if(rpacket.code != PW_AUTHENTICATION_ACK){
|
if(rpacket.code != PW_AUTHENTICATION_ACK){
|
||||||
res = 0;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(mailservice != 3){
|
RETURN(0);
|
||||||
*errorstring = "This account is not valid for mailbox access, check your settings";
|
|
||||||
return 130;
|
|
||||||
}
|
|
||||||
p->auth = at;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return 100+res;
|
CLEANRET:
|
||||||
|
if(sockfd >= 0) so._closesocket(sockfd);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_MAIN
|
|
||||||
|
|
||||||
extern int librad_debug;
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char*argv[]){
|
|
||||||
|
|
||||||
char *radiuslist[] = {"195.122.226.5", NULL};
|
|
||||||
int dodeletes;
|
|
||||||
char * errorstring;
|
|
||||||
int result;
|
|
||||||
/*
|
|
||||||
librad_debug = 1;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(argc!=3)return 1;
|
|
||||||
|
|
||||||
result = radius_pass(PLAIN, argv[1], argv[2], NULL, radiuslist, "test", &dodeletes, &errorstring);
|
|
||||||
|
|
||||||
printf("Login: %s/%d, Dodeletes: %s, Errorstring: %s\n",
|
|
||||||
(result)?"FAILED":"SUCCEED",
|
|
||||||
result,
|
|
||||||
(dodeletes)?"YES":"NO",
|
|
||||||
(errorstring)?errorstring:"NONE"
|
|
||||||
);
|
|
||||||
fflush(stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -140,6 +140,7 @@ void daemonize(void);
|
|||||||
|
|
||||||
#include "structures.h"
|
#include "structures.h"
|
||||||
|
|
||||||
|
#define MAXRADIUS 5
|
||||||
|
|
||||||
extern RESOLVFUNC resolvfunc;
|
extern RESOLVFUNC resolvfunc;
|
||||||
|
|
||||||
@ -326,6 +327,14 @@ extern struct commands commandhandlers[];
|
|||||||
#define mapsocket(a,b) sockmap(a,b)
|
#define mapsocket(a,b) sockmap(a,b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NOIPV6
|
||||||
|
extern struct sockaddr_in radiuslist[MAXRADIUS];
|
||||||
|
#else
|
||||||
|
extern struct sockaddr_in6 radiuslist[MAXRADIUS];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int nradservers = 0;
|
||||||
|
extern char * radiussecret = NULL;
|
||||||
|
|
||||||
#ifdef _WINCE
|
#ifdef _WINCE
|
||||||
char * CEToUnicode (const char *str);
|
char * CEToUnicode (const char *str);
|
||||||
|
Loading…
Reference in New Issue
Block a user