From 4a553de100ca9fa9068b91e430dbb3ed78ef7895 Mon Sep 17 00:00:00 2001 From: z3APA3A <3APA3A@3proxy.ru> Date: Tue, 19 Dec 2017 01:22:07 +0300 Subject: [PATCH] RADIUS accounting added (not optimized yet) --- src/authradius.c | 106 +++++++++++++++++++++++++++++++++++------------ src/conf.c | 12 +++++- src/datatypes.c | 1 + src/proxy.h | 4 ++ 4 files changed, 95 insertions(+), 28 deletions(-) diff --git a/src/authradius.c b/src/authradius.c index f8ab686..652a317 100644 --- a/src/authradius.c +++ b/src/authradius.c @@ -198,6 +198,9 @@ void md5_calc(unsigned char *output, unsigned char *input, static uint8_t random_vector_pool[AUTH_VECTOR_LEN*2]; + + + static int calc_replydigest(char *packet, char *original, const char *secret, int len) { int secretlen; @@ -295,7 +298,7 @@ typedef struct radius_packet_t { #define RETURN(xxx) { res = xxx; goto CLEANRET; } -int radsend(struct clientparam * param, int auth){ +int radsend(struct clientparam * param, int auth, int stop){ int loop; int id; @@ -320,6 +323,7 @@ int radsend(struct clientparam * param, int auth){ uint8_t *attr; long vendor=0; int vendorlen=0; + char buf[64]; if(!radiussecret || !nradservers) { @@ -328,28 +332,34 @@ int radsend(struct clientparam * param, int auth){ memset(&packet, 0, sizeof(packet)); + pthread_mutex_lock(&rad_mutex); - random_vector(packet.vector, param); + if(auth)random_vector(packet.vector, param); id = ((ntry++) & 0xff); pthread_mutex_unlock(&rad_mutex); - packet.code = PW_AUTHENTICATION_REQUEST; + packet.code = auth?PW_AUTHENTICATION_REQUEST:PW_ACCOUNTING_REQUEST; packet.id=id; ptr = packet.data; total_length = 0; - md5_calc(packet.vector, packet.vector, - sizeof(packet.vector)); - - /* Service Type */ - *ptr++ = PW_SERVICE_TYPE; + *ptr++ = auth?PW_SERVICE_TYPE:PW_ACCT_STATUS_TYPE; *ptr++ = 6; - (*(uint32_t *)ptr)=htonl(PW_AUTHENTICATE_ONLY); + (*(uint32_t *)ptr)=htonl(auth?PW_AUTHENTICATE_ONLY:stop?PW_STATUS_STOP:PW_STATUS_START); ptr+=4; total_length+=6; + /* Acct-Session-Id */ + sprintf(buf, "%u.%u.%u", (unsigned)param->time_start, (unsigned)param->msec_start, (unsigned)param->threadid); + len = strlen(buf); + *ptr++ = PW_ACCT_SESSION_ID; + *ptr++ = 2+len; + memcpy(ptr, buf, len); + ptr+=len; + total_length+=len+2; + /* NAS-Port-Type */ *ptr++ = PW_NAS_PORT_TYPE; *ptr++ = 6; @@ -459,7 +469,40 @@ int radsend(struct clientparam * param, int auth){ total_length += (len+2); } - if(param->password){ + if(stop){ + /* Acct-Input-Octets */ + *ptr++ = PW_ACCT_INPUT_OCTETS; + *ptr++ = 6; + (*(uint32_t *)ptr)=htonl((uint32_t)param->statssrv64); + ptr+=4; + total_length+=6; + /* Acct-Output-Octets */ + *ptr++ = PW_ACCT_OUTPUT_OCTETS; + *ptr++ = 6; + (*(uint32_t *)ptr)=htonl((uint32_t)param->statscli64); + ptr+=4; + total_length+=6; + /* Acct-Input-Packets */ + *ptr++ = PW_ACCT_INPUT_PACKETS; + *ptr++ = 6; + (*(uint32_t *)ptr)=htonl((uint32_t)param->nreads); + ptr+=4; + total_length+=6; + /* Acct-Output-Packets */ + *ptr++ = PW_ACCT_OUTPUT_PACKETS; + *ptr++ = 6; + (*(uint32_t *)ptr)=htonl((uint32_t)param->nwrites); + ptr+=4; + total_length+=6; + /* Acct-Session-Time */ + *ptr++ = PW_ACCT_SESSION_TIME; + *ptr++ = 6; + (*(uint32_t *)ptr)=htonl((uint32_t)(time(0) - param->time_start)); + ptr+=4; + total_length+=6; + } + + if(auth && param->password){ len = strlen(param->password); if(len > 128) len = 128; *ptr++ = PW_PASSWORD; @@ -473,9 +516,15 @@ int radsend(struct clientparam * param, int auth){ ptr+=len; total_length+= (len+2); } - + total_length+=(4+AUTH_VECTOR_LEN); packet.length = htons(total_length); + + if(!auth){ + len = strlen(radiussecret); + memcpy(ptr,radiussecret,len); + md5_calc(packet.vector, (u_char *)&packet, total_length + len); + } memcpy(vector, packet.vector, AUTH_VECTOR_LEN); for (loop = 0; loop < nradservers && loop < MAXRADIUS; loop++) { @@ -492,15 +541,19 @@ int radsend(struct clientparam * param, int auth){ continue; } #endif - packet.id++; + +/* if(auth) { +*/ if(sockfd >= 0) so._closesocket(sockfd); if ((sockfd = so._socket(SASOCK(&saremote), SOCK_DGRAM, 0)) < 0) { return 4; } remsock = sockfd; +/* } else remsock = radiuslist[loop].logsock; +*/ len = so._sendto(remsock, (char *)&packet, total_length, 0, (struct sockaddr *)&saremote, sizeof(saremote)); if(len != ntohs(packet.length)){ @@ -524,10 +577,13 @@ int radsend(struct clientparam * param, int auth){ continue; } - if( rpacket.code != PW_AUTHENTICATION_ACK && + if( auth && rpacket.code != PW_AUTHENTICATION_ACK && rpacket.code != PW_AUTHENTICATION_REJECT ){ continue; } + if( !auth && rpacket.code != PW_ACCOUNTING_RESPONSE){ + continue; + } if (calc_replydigest((char *)&rpacket, packet.vector, radiussecret, data_len) ){ @@ -539,6 +595,8 @@ int radsend(struct clientparam * param, int auth){ continue; } + if(!auth) RETURN(0); + attr = rpacket.data; count = total_length - 20; vendor_len = 0; @@ -575,18 +633,6 @@ int radsend(struct clientparam * param, int auth){ for(len = 2; len < attr[1] && isdigit(attr[len]); len++) res = (res * 10) + (attr[len] - '0'); } - -/* - else if (vendor == SANDY && attr[0] == SANDY_MAIL_MAILBOX) { - memcpy (p->drop_name, attr + 2, attr[1] - 2); - } - else if (vendor == SANDY && attr[0] == SANDY_MAIL_MBOXCONTROL) { - if (ntohl(*(int *)(attr+2)) & 1) p->dodeletes = 1; - } - else if (vendor == SANDY && attr[0] == SANDY_MAIL_SERVICE) { - mailservice = ntohl(*(int *)(attr+2)) ; - } -*/ count -= attr[1]; if(vendorlen) { vendorlen -= attr[1]; @@ -610,8 +656,16 @@ CLEANRET: } int radauth(struct clientparam * param){ - return radsend(param, 1); + /*radsend(param, 0, 0);*/ + return radsend(param, 1, 0); +} + +void logradius(struct clientparam * param, const unsigned char *s) { + radsend(param, 0, 1); + if(param->trafcountfunc)(*param->trafcountfunc)(param); + clearstat(param); } + #endif diff --git a/src/conf.c b/src/conf.c index 6794d37..75eda74 100644 --- a/src/conf.c +++ b/src/conf.c @@ -327,6 +327,9 @@ static int h_log(int argc, unsigned char ** argv){ conf.logfunc = logsql; } #endif + else if(!strcmp(argv[1],"radius")){ + conf.logfunc = logradius; + } else { FILE *fp; if(argc > 2) { @@ -1272,13 +1275,15 @@ static int h_delimchar(int argc, unsigned char **argv){ static int h_radius(int argc, unsigned char **argv){ + unsigned short port; + +/* int oldrad; #ifdef NOIPV6 struct sockaddr_in bindaddr; #else struct sockaddr_in6 bindaddr; #endif - unsigned short port; oldrad = nradservers; nradservers = 0; @@ -1286,6 +1291,7 @@ static int h_radius(int argc, unsigned char **argv){ if(radiuslist[oldrad].logsock >= 0) so._closesocket(radiuslist[oldrad].logsock); radiuslist[oldrad].logsock = -1; } +*/ memset(radiuslist, 0, sizeof(radiuslist)); if(strlen(argv[1]) > 63) argv[1][63] = 0; strcpy(radiussecret, argv[1]); @@ -1294,10 +1300,12 @@ static int h_radius(int argc, unsigned char **argv){ if(!*SAPORT(&radiuslist[nradservers].authaddr))*SAPORT(&radiuslist[nradservers].authaddr) = htons(1812); port = ntohs(*SAPORT(&radiuslist[nradservers].authaddr)); radiuslist[nradservers].logaddr = radiuslist[nradservers].authaddr; - *SAPORT(&radiuslist[nradservers].logaddr) = htons(port); + *SAPORT(&radiuslist[nradservers].logaddr) = htons(port+1); +/* bindaddr = conf.intsa; if ((radiuslist[nradservers].logsock = so._socket(SASOCK(&radiuslist[nradservers].logaddr), SOCK_DGRAM, 0)) < 0) return 2; if (so._bind(radiuslist[nradservers].logsock, (struct sockaddr *)&bindaddr, SASIZE(&bindaddr))) return 3; +*/ } return 0; } diff --git a/src/datatypes.c b/src/datatypes.c index 0a9780c..d7bcdd7 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -520,6 +520,7 @@ static void * ef_server_childcount(struct node * node){ static void * ef_server_log(struct node * node){ if(((struct srvparam *)node->value) -> logfunc == lognone) return "none"; + else if(((struct srvparam *)node->value) -> logfunc == logradius) return "radius"; else if(((struct srvparam *)node->value) -> logfunc == logstdout) return (((struct srvparam *)node->value) -> logtarget)?"file":"stdout"; #ifndef _WIN32 diff --git a/src/proxy.h b/src/proxy.h index 6d31f23..039de9b 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -177,6 +177,8 @@ extern FILE * stdlog; void logstdout(struct clientparam * param, const unsigned char *s); void logsyslog(struct clientparam * param, const unsigned char *s); void lognone(struct clientparam * param, const unsigned char *s); +void logradius(struct clientparam * param, const unsigned char *s); + #ifndef NOSQL void logsql(struct clientparam * param, const unsigned char *s); int init_sql(char * s); @@ -339,7 +341,9 @@ extern struct radserver { #else struct sockaddr_in6 authaddr, logaddr; #endif +/* SOCKET logsock; +*/ } radiuslist[MAXRADIUS]; extern char radiussecret[64];