| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- /*
- 3APA3A simpliest proxy server
- (c) 2000-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
- please read License Agreement
- */
- #ifndef NORADIUS
- #include "proxy.h"
- #include "libs/md5.h"
- #define AUTH_VECTOR_LEN 16
- #define MAX_STRING_LEN 254
- #define PW_AUTH_UDP_PORT 1645
- #define PW_TYPE_STRING 0
- #define PW_TYPE_INTEGER 1
- #define PW_TYPE_IPADDR 2
- #define PW_TYPE_DATE 3
- #define PW_TYPE_ABINARY 4
- #define PW_TYPE_OCTETS 5
- #define PW_AUTHENTICATION_REQUEST 1
- #define PW_AUTHENTICATION_ACK 2
- #define PW_AUTHENTICATION_REJECT 3
- #define PW_ACCOUNTING_REQUEST 4
- #define PW_ACCOUNTING_RESPONSE 5
- #define PW_ACCOUNTING_STATUS 6
- #define PW_PASSWORD_REQUEST 7
- #define PW_USER_NAME 1
- #define PW_PASSWORD 2
- #define PW_CHAP_PASSWORD 3
- #define PW_NAS_IP_ADDRESS 4
- #define PW_NAS_PORT_ID 5
- #define PW_SERVICE_TYPE 6
- #define PW_FRAMED_PROTOCOL 7
- #define PW_FRAMED_IP_ADDRESS 8
- #define PW_FRAMED_IP_NETMASK 9
- #define PW_FRAMED_ROUTING 10
- #define PW_FILTER_ID 11
- #define PW_FRAMED_MTU 12
- #define PW_FRAMED_COMPRESSION 13
- #define PW_LOGIN_IP_HOST 14
- #define PW_LOGIN_SERVICE 15
- #define PW_LOGIN_TCP_PORT 16
- #define PW_OLD_PASSWORD 17
- #define PW_REPLY_MESSAGE 18
- #define PW_CALLBACK_NUMBER 19
- #define PW_CALLBACK_ID 20
- #define PW_FRAMED_ROUTE 22
- #define PW_FRAMED_IPXNET 23
- #define PW_STATE 24
- #define PW_CLASS 25
- #define PW_VENDOR_SPECIFIC 26
- #define PW_SESSION_TIMEOUT 27
- #define PW_IDLE_TIMEOUT 28
- #define PW_CALLED_STATION_ID 30
- #define PW_CALLING_STATION_ID 31
- #define PW_NAS_IDENTIFIER 32
- #define PW_PROXY_STATE 33
- #define PW_ACCT_STATUS_TYPE 40
- #define PW_ACCT_DELAY_TIME 41
- #define PW_ACCT_INPUT_OCTETS 42
- #define PW_ACCT_OUTPUT_OCTETS 43
- #define PW_ACCT_SESSION_ID 44
- #define PW_ACCT_AUTHENTIC 45
- #define PW_ACCT_SESSION_TIME 46
- #define PW_ACCT_INPUT_PACKETS 47
- #define PW_ACCT_OUTPUT_PACKETS 48
- #define PW_ACCT_TERMINATE_CAUSE 49
- #define PW_EVENT_TIMESTAMP 55
- #define PW_CHAP_CHALLENGE 60
- #define PW_NAS_PORT_TYPE 61
- #define PW_PORT_LIMIT 62
- #define PW_ARAP_PASSWORD 70
- #define PW_ARAP_FEATURES 71
- #define PW_ARAP_ZONE_ACCESS 72
- #define PW_ARAP_SECURITY 73
- #define PW_ARAP_SECURITY_DATA 74
- #define PW_PASSWORD_RETRY 75
- #define PW_PROMPT 76
- #define PW_CONNECT_INFO 77
- #define PW_CONFIGURATION_TOKEN 78
- #define PW_EAP_MESSAGE 79
- #define PW_MESSAGE_AUTHENTICATOR 80
- #define PW_ARAP_CHALLENGE_RESPONSE 84
- #define PW_NAS_PORT_ID_STRING 87
- #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_ADD_PORT_TO_IP_ADDRESS 501
- #define PW_EXEC_PROGRAM 502
- #define PW_EXEC_PROGRAM_WAIT 503
- #define PW_AUTHTYPE 1000
- #define PW_PREFIX 1003
- #define PW_SUFFIX 1004
- #define PW_GROUP 1005
- #define PW_CRYPT_PASSWORD 1006
- #define PW_CONNECT_RATE 1007
- #define PW_ADD_PREFIX 1008
- #define PW_ADD_SUFFIX 1009
- #define PW_EXPIRATION 1010
- #define PW_USER_CATEGORY 1029
- #define PW_GROUP_NAME 1030
- #define PW_HUNTGROUP_NAME 1031
- #define PW_SIMULTANEOUS_USE 1034
- #define PW_STRIP_USER_NAME 1035
- #define PW_HINT 1040
- #define PAM_AUTH_ATTR 1041
- #define PW_LOGIN_TIME 1042
- #define PW_STRIPPED_USER_NAME 1043
- #define PW_CURRENT_TIME 1044
- #define PW_REALM 1045
- #define PW_NO_SUCH_ATTRIBUTE 1046
- #define PW_PACKET_TYPE 1047
- #define PW_PROXY_TO_REALM 1048
- #define PW_REPLICATE_TO_REALM 1049
- #define PW_ACCT_SESSION_START_TIME 1050
- #define PW_ACCT_UNIQUE_SESSION_ID 1051
- #define PW_CLIENT_IP_ADDRESS 1052
- #define LDAP_USERDN 1053
- #define PW_NS_MTA_MD5_PASSWORD 1054
- #define PW_SQL_USER_NAME 1055
- #define PW_LOGIN_USER 1
- #define PW_FRAMED_USER 2
- #define PW_CALLBACK_LOGIN_USER 3
- #define PW_CALLBACK_FRAMED_USER 4
- #define PW_OUTBOUND_USER 5
- #define PW_ADMINISTRATIVE_USER 6
- #define PW_NAS_PROMPT_USER 7
- #define PW_AUTHENTICATE_ONLY 8
- #define PW_CALLBACK_NAS_PROMPT 9
- #define PW_NAS_PORT_ASYNC 0
- #define PW_NAS_PORT_SYNC 1
- #define PW_NAS_PORT_ISDN 2
- #define PW_NAS_PORT_ISDN_V120 3
- #define PW_NAS_PORT_ISDN_V110 4
- #define PW_NAS_PORT_VIRTUAL 5
- #define PW_STATUS_START 1
- #define PW_STATUS_STOP 2
- #define PW_STATUS_ALIVE 3
- #define PW_STATUS_ACCOUNTING_ON 7
- #define PW_STATUS_ACCOUNTING_OFF 8
- struct radserver radiuslist[MAXRADIUS];
- static int ntry = 0;
- int nradservers = 0;
- char radiussecret[64]="";
- pthread_mutex_t rad_mutex;
- void md5_calc(unsigned char *output, unsigned char *input,
- unsigned int inputlen);
- char *strNcpy(char *dest, const char *src, int n)
- {
- if (n > 0)
- strncpy(dest, src, n);
- else
- n = 1;
- dest[n - 1] = 0;
- return dest;
- }
- void md5_calc(unsigned char *output, unsigned char *input,
- unsigned int inlen)
- {
- MD5_CTX context;
- MD5Init(&context);
- MD5Update(&context, input, inlen);
- MD5Final(output, &context);
- }
- 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;
- uint8_t calc_digest[AUTH_VECTOR_LEN];
- uint8_t calc_vector[AUTH_VECTOR_LEN];
- memcpy(calc_vector, packet + 4, AUTH_VECTOR_LEN);
- memcpy(packet + 4, original, AUTH_VECTOR_LEN);
- secretlen = strlen(secret);
- memcpy(packet + len, secret, secretlen);
- md5_calc(calc_digest, (u_char *)packet, len + secretlen);
- /*
- * Return 0 if OK, 2 if not OK.
- */
- return memcmp(calc_vector, calc_digest, AUTH_VECTOR_LEN) ? 2 : 0;
- }
- #define AUTH_PASS_LEN (16)
- int rad_pwencode(char *passwd, int *pwlen, const char *secret, const char *vector)
- {
- uint8_t buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 1];
- char digest[AUTH_VECTOR_LEN];
- int i, n, secretlen;
- int len;
- len = strlen(passwd);
- if (len > 128) len = 128;
- *pwlen = len;
- if (len % AUTH_PASS_LEN != 0) {
- n = AUTH_PASS_LEN - (len % AUTH_PASS_LEN);
- for (i = len; n > 0; n--, i++)
- passwd[i] = 0;
- len = *pwlen = i;
- }
- secretlen = strlen(secret);
- memcpy(buffer, secret, secretlen);
- memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
- md5_calc((u_char *)digest, buffer, secretlen + AUTH_VECTOR_LEN);
- for (i = 0; i < AUTH_PASS_LEN; i++)
- passwd[i] ^= digest[i];
- if (len <= AUTH_PASS_LEN) return 0;
- for (n = 0; n < 128 && n <= (len - AUTH_PASS_LEN); n += AUTH_PASS_LEN) {
- memcpy(buffer + secretlen, passwd + n, AUTH_PASS_LEN);
- md5_calc((u_char *)digest, buffer, secretlen + AUTH_PASS_LEN);
- for (i = 0; i < AUTH_PASS_LEN; i++)
- passwd[i + n + AUTH_PASS_LEN] ^= digest[i];
- }
- return 0;
- }
- void random_vector(uint8_t *vector, struct clientparam *param)
- {
- int i;
- static int did_random = 0;
- static int counter = 0;
- if (!did_random) {
- ntry = (int)basetime;
- for (i = 0; i < (int)sizeof(random_vector_pool); i++) {
- random_vector_pool[i] += myrand((void *) ¶m->msec_start, sizeof(param->msec_start)) & 0xff;
- }
- did_random = 1;
- }
- counter++;
- random_vector_pool[AUTH_VECTOR_LEN] += (counter & 0xff);
- md5_calc((u_char *) random_vector_pool,
- (u_char *) random_vector_pool,
- sizeof(random_vector_pool));
- md5_calc((u_char *) vector,
- (u_char *) random_vector_pool,
- sizeof(random_vector_pool));
- }
- static float timeout = 5;
- typedef struct radius_packet_t {
- uint8_t code;
- uint8_t id;
- uint16_t length;
- uint8_t vector[AUTH_VECTOR_LEN];
- uint8_t data[4096];
- } radius_packet_t;
-
- #define RETURN(xxx) { res = xxx; goto CLEANRET; }
- int radsend(struct clientparam * param, int auth){
- int loop;
- int id;
- int res = 4;
- SOCKET sockfd = -1;
- unsigned char *ptr;
- int total_length;
- int len;
- int op;
- #ifdef NOIPV6
- struct sockaddr_in saremote;
- #else
- struct sockaddr_in6 saremote;
- #endif
- struct pollfd fds[1];
- char vector[AUTH_VECTOR_LEN];
- radius_packet_t packet, rpacket;
- SASIZETYPE salen;
- int data_len;
- uint8_t *vendor_len;
- int count=0;
- uint8_t *attr;
- long vendor=0;
- int vendorlen=0;
- if(!radiussecret || !nradservers) {
- return 4;
- }
- memset(&packet, 0, sizeof(packet));
- pthread_mutex_lock(&rad_mutex);
- random_vector(packet.vector, param);
- id = ((ntry++) & 0xff);
- pthread_mutex_unlock(&rad_mutex);
- packet.code = PW_AUTHENTICATION_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++ = 6;
- (*(uint32_t *)ptr)=htonl(PW_AUTHENTICATE_ONLY);
- ptr+=4;
- total_length+=6;
- /* NAS-Port-Type */
- *ptr++ = PW_NAS_PORT_TYPE;
- *ptr++ = 6;
- (*(uint32_t *)ptr)=htonl(PW_NAS_PORT_VIRTUAL);
- ptr+=4;
- total_length+=6;
- /* NAS-Port */
- *ptr++ = PW_NAS_PORT_ID;
- *ptr++ = 6;
- (*(uint32_t *)ptr)=htonl((uint32_t)ntohs((*SAPORT(¶m->srv->intsa))));
- ptr+=4;
- 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 += (2+len);
- /* NAS-Identifier */
- if(conf.stringtable){
- *ptr++ = PW_NAS_IDENTIFIER;
- len = strlen(conf.stringtable[SERVICES+param->service]);
- *ptr++ = (2 + len);
- memcpy(ptr, conf.stringtable[SERVICES+param->service], len);
- ptr += len;
- total_length+=(len+2);
- }
- if(*SAFAMILY(¶m->sincr) == AF_INET6){
- /* Framed-IPv6-Address */
- *ptr++ = PW_FRAMED_IPV6_ADDRESS;
- *ptr++ = 18;
- }
- else {
- /* Framed-IP-Address */
- *ptr++ = PW_FRAMED_IP_ADDRESS;
- *ptr++ = 6;
- }
- len = SAADDRLEN(¶m->sincr);
- memcpy(ptr, SAADDR(¶m->sincr), len);
- ptr += len;
- total_length += (2+len);
- /* Called-Station-ID */
- if(param->hostname){
- *ptr++ = PW_CALLED_STATION_ID;
- len = strlen(param->hostname);
- *ptr++ = (2 + len);
- memcpy(ptr, param->hostname, len);
- ptr += len;
- total_length+=(len+2);
- }
- /* Login-Service */
- op = param->operation;
- for(len=0; op; len++)op>>=1;
- *ptr++ = PW_LOGIN_SERVICE;
- *ptr++ = 4;
- (*(uint16_t *)ptr)=htons((uint16_t)(len + 1000));
- ptr+=2;
- total_length+=4;
- /* Login-TCP-Port */
- *ptr++ = PW_LOGIN_TCP_PORT;
- *ptr++ = 4;
- (*(uint16_t *)ptr)=*SAPORT(¶m->req);
- ptr+=2;
- total_length+=4;
- if(*SAFAMILY(¶m->req) == AF_INET6){
- /* Login-IPv6-Host */
- *ptr++ = PW_LOGIN_IPV6_HOST;
- *ptr++ = 18;
- }
- else {
- /* Login-IP-Host */
- *ptr++ = PW_LOGIN_IP_HOST;
- *ptr++ = 6;
- }
- len = SAADDRLEN(¶m->req);
- memcpy(ptr, SAADDR(¶m->req), len);
- ptr += len;
- total_length += (2+len);
- /* Username */
- if(param->username){
- len = strlen(param->username);
- if(len>128)len=128;
- *ptr++ = PW_USER_NAME;
- *ptr++ = len + 2;
- memcpy(ptr, param->username, len);
- ptr+=len;
- total_length += (len+2);
- }
-
- if(param->password){
- len = strlen(param->password);
- if(len > 128) len = 128;
- *ptr++ = PW_PASSWORD;
- ptr++;
- memcpy(ptr, param->password, len);
- rad_pwencode(ptr,
- &len,
- radiussecret,
- (char *)packet.vector);
- *(ptr-1) = len + 2;
- ptr+=len;
- total_length+= (len+2);
- }
-
- total_length+=(4+AUTH_VECTOR_LEN);
- packet.length = htons(total_length);
- memcpy(vector, packet.vector, AUTH_VECTOR_LEN);
-
- for (loop = 0; loop < nradservers && loop < MAXRADIUS; loop++) {
- SOCKET remsock;
- saremote = auth?radiuslist[loop].authaddr : radiuslist[loop].logaddr;
- #ifdef NOIPV6
- if(*SAFAMILY(&saremote)!= AF_INET) {
- continue;
- }
- #else
- if(*SAFAMILY(&saremote)!= AF_INET && *SAFAMILY(&saremote)!= AF_INET6){
- 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)){
- continue;
- }
- memset(fds, 0, sizeof(fds));
- fds[0].fd = remsock;
- fds[0].events = POLLIN;
- if(so._poll(fds, 1, conf.timeouts[SINGLEBYTE_L]*1000) <= 0) {
- continue;
- }
- salen = sizeof(saremote);
-
- data_len = so._recvfrom(remsock, (char *)&rpacket, sizeof(packet)-16,
- 0, (struct sockaddr *)&saremote, &salen);
- if (data_len < 20) {
- continue;
- }
- if( rpacket.code != PW_AUTHENTICATION_ACK &&
- rpacket.code != PW_AUTHENTICATION_REJECT ){
- continue;
- }
- if (calc_replydigest((char *)&rpacket, packet.vector, radiussecret,
- data_len) ){
- continue;
- }
- total_length = ntohs(rpacket.length);
- if (data_len != total_length) {
- continue;
- }
- attr = rpacket.data;
- count = total_length - 20;
- vendor_len = 0;
- while (count >= 2) {
- if (!vendor && attr[0] == 0) {
- break;
- }
-
- if (attr[1] < 2) {
- break;
- }
- if(!vendor && attr[0] == PW_VENDOR_SPECIFIC) {
- if (attr[1] < 6 || count < 6) RETURN(4);
- vendorlen = attr[1]-6;
- vendor = htonl(*((int*)(attr +2)));
- count -= 6;
- attr += 6;
- continue;
- }
-
- if (!vendor && attr[0] == PW_FRAMED_IP_ADDRESS && attr[1] == 6) {
- *SAFAMILY(¶m->sinsl) = AF_INET;
- memcpy(SAADDR(¶m->sinsl), attr+2, 4);
- }
- else if (!vendor && attr[0] == PW_FRAMED_IPV6_ADDRESS && attr[1] == 18) {
- *SAFAMILY(¶m->sinsl) = AF_INET6;
- memcpy(SAADDR(¶m->sinsl), attr+2, 16);
- }
- else if (!vendor && attr[0] == PW_REPLY_MESSAGE && attr[1] >= 3 && isdigit(attr[2])) {
- res = 0;
- 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];
- if (!vendorlen) vendor = 0;
- else if (vendorlen < 0) RETURN(4);
- }
- attr += attr[1];
- }
- if (count !=0 || vendorlen!=0) {
- continue;
- }
- if(rpacket.code == PW_AUTHENTICATION_REJECT) RETURN (res);
- if(rpacket.code == PW_AUTHENTICATION_ACK) RETURN(0);
- res = 4;
- }
- CLEANRET:
- if(sockfd >= 0) so._closesocket(sockfd);
- return res;
- }
- int radauth(struct clientparam * param){
- return radsend(param, 1);
- }
- #endif
|