/* 3APA3A simplest proxy server (c) 2002-2026 by Vladimir Dubrovin please read License Agreement */ #include "proxy.h" #include "libs/blake2.h" void initbandlims(struct clientparam *param); int alwaysauth(struct clientparam * param){ int res; struct trafcount * tc; int countout = 0; if(conf.connlimiter && !param->connlim && startconnlims(param)) return 10; res = doconnect(param); if(!res){ if(conf.bandlimfunc && (conf.bandlimiter||conf.bandlimiterout)){ _3proxy_mutex_lock(&bandlim_mutex); initbandlims(param); _3proxy_mutex_unlock(&bandlim_mutex); } if(conf.trafcountfunc && conf.trafcounter) { _3proxy_mutex_lock(&tc_mutex); for(tc = conf.trafcounter; tc; tc = tc->next) { if(tc->disabled) continue; if(ACLmatches(tc->ace, param)){ if(tc->ace->action == NOCOUNTIN) { countout = 1; break; } if(tc->ace->action == NOCOUNTALL) break; if(tc->ace->action != COUNTIN) { countout = 1; if(tc->ace->action != COUNTALL) continue; } if(tc->traflim64 <= tc->traf64) { _3proxy_mutex_unlock(&tc_mutex); return 10; } param->trafcountfunc = conf.trafcountfunc; param->maxtrafin64 = tc->traflim64 - tc->traf64; } } if(countout)for(tc = conf.trafcounter; tc; tc = tc->next) { if(tc->disabled) continue; if(ACLmatches(tc->ace, param)){ if(tc->ace->action == NOCOUNTOUT || tc->ace->action == NOCOUNTALL) break; if(tc->ace->action != COUNTOUT && tc->ace->action != COUNTALL) { continue; } if(tc->traflim64 <= tc->traf64) { _3proxy_mutex_unlock(&tc_mutex); return 10; } param->trafcountfunc = conf.trafcountfunc; param->maxtrafout64 = tc->traflim64 - tc->traf64; } } _3proxy_mutex_unlock(&tc_mutex); } } return res; } int cacheauth(struct clientparam * param){ struct authcache ac; uint32_t ttl; unsigned type = param->srv->authcachetype; if( ((type & 2) && !param->username) || ((type & 4) && !param->password) || ( (type & 1) && *SAFAMILY(¶m->sincr) != AF_INET #ifndef NOIPv6 && *SAFAMILY(¶m->sincr) != AF_INET6 #endif ) || (!hashresolv(&auth_table, param, &ac, &ttl))) { return 4; } if((type & 1) &&(type & 8) && (ac.sincr_family != *SAFAMILY(¶m->sincr) || memcmp(ac.sincr_addr, SAADDR(¶m->sincr), SAADDRLEN(¶m->sincr)) )) { return 10; } if(!(type&2) && *ac.username){ if(param->username) free(param->username); param->username = (unsigned char *)strdup((char *)ac.username); } if((type & 32)){ memset(¶m->sinsl, 0, sizeof(param->sinsl)); *(SAFAMILY(¶m->sinsl)) = ac.sinsl_family; memcpy(SAADDR(¶m->sinsl), ac.sinsl_addr, SAADDRLEN(¶m->sinsl)); } return 0; } int doauth(struct clientparam * param){ int res = 0; struct auth *authfuncs; char * tmp; int ret = 0; for(authfuncs=param->srv->authfuncs; authfuncs; authfuncs=authfuncs->next){ res = authfuncs->authenticate?(*authfuncs->authenticate)(param):0; if(!res) { if(authfuncs->authorize && (res = (*authfuncs->authorize)(param))) return res; if(param->srv->authcachetype && authfuncs->authenticate && authfuncs->authenticate != cacheauth && param->username && (!(param->srv->authcachetype&4) || (!param->pwtype && param->password))){ struct authcache ac={.username=""}; if(param->username) { strncpy((char *)ac.username, (char *)param->username, 64); ac.username[63] = 0; } if(*SAFAMILY(¶m->sincr) == AF_INET #ifndef NOIPv6 || *SAFAMILY(¶m->sincr) == AF_INET6 #endif ) { ac.sincr_family = *SAFAMILY(¶m->sincr); memcpy(ac.sincr_addr, SAADDR(¶m->sincr), SAADDRLEN(¶m->sincr)); } if(*SAFAMILY(¶m->sinsl) == AF_INET #ifndef NOIPv6 || *SAFAMILY(¶m->sinsl) == AF_INET6 #endif ) { ac.sinsl_family = *SAFAMILY(¶m->sinsl); memcpy(ac.sinsl_addr, SAADDR(¶m->sinsl), SAADDRLEN(¶m->sinsl)); } hashadd(&auth_table, param, &ac, conf.time + param->srv->authcachetime); } break; } if(res > ret) ret = res; if(ret > 9) return ret; } if(!res){ ret = alwaysauth(param); if (param->afterauthfilters){ FILTER_ACTION action; action = handleafterauthflt(param); if(action != PASS) return 19; } } return ret; } int ipauth(struct clientparam * param){ int res; unsigned char *username; username = param->username; param->username = NULL; res = checkACL(param); param->username = username; return res; } int userauth(struct clientparam * param){ return (param->username)? 0:4; } int dnsauth(struct clientparam * param){ char buf[128]; char addr[16]; char dig[]="0123456789abcdef"; unsigned u; int i; if(*SAFAMILY(¶m->sincr)!=AF_INET){ char *s = buf; for(i=15; i>=0; i--){ unsigned char c=((unsigned char *)SAADDR(¶m->sincr))[i]; *s++ = dig[(c&0xf)]; *s++ = '.'; *s++ = dig[(c>>4)]; *s++ = '.'; } sprintf(s, "ip6.arpa"); } else { u = ntohl(*(uint32_t *)SAADDR(¶m->sincr)); sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", ((u&0x000000FF)), ((u&0x0000FF00)>>8), ((u&0x00FF0000)>>16), ((u&0xFF000000)>>24)); } if(!udpresolve(*SAFAMILY(¶m->sincr), (unsigned char *)buf, (unsigned char *)addr, NULL, param, 1)) { return 3; } if(memcmp(SAADDR(¶m->sincr), addr, SAADDRLEN(¶m->sincr))) { return 3; } return param->username? 0:3; } int strongauth(struct clientparam * param){ static char dummy; unsigned char buf[256]; char pass[256] = {0}; if (!param->username) return 4; if (!param->pwtype && param->password) { if (pwl_table.ihashtable && hashresolv(&pwl_table, param->username, pass, NULL)) { switch(pass[0]){ case CL: { int pwlen = strlen((char *)param->password); if(pwlen > 255) pwlen = 255; if((unsigned)pwlen < pwl_table.recsize) { if(!strncmp(pass + 1, (char *)param->password, pwl_table.recsize - 1)) return 0; } else { blake2b_state S; unsigned hashsz; hashsz = pwl_table.recsize - 1 < 64 ? pwl_table.recsize - 1 : 64; memset(buf, 0, pwl_table.recsize - 1); blake2b_init(&S, hashsz); blake2b_update(&S, param->password, pwlen + 1); blake2b_final(&S, buf, hashsz); if(!memcmp(pass + 1, buf, pwl_table.recsize - 1)) return 0; } return 6; } case CR: if (mycrypt(param->password, (unsigned char *)pass + 1, buf) && !strcmp(pass + 1, (char *)buf)) return 0; else return 7; #ifdef WITH_SSL case NT: if(ntpwdhash(buf, param->password, 1) && !strcmp(pass + 1, (char *)buf)) return 0; else return 8; #endif default: break; } } } return 5; } int radauth(struct clientparam * param); struct auth authfuncs[] = { {authfuncs+1, NULL, NULL, ""}, {authfuncs+2, ipauth, NULL, "iponly"}, {authfuncs+3, userauth, checkACL, "useronly"}, {authfuncs+4, dnsauth, checkACL, "dnsname"}, {authfuncs+5, strongauth, checkACL, "strong"}, {authfuncs+6, cacheauth, checkACL, "cache"}, {authfuncs+7, cacheauth, NULL, "cacheacl"}, #ifndef NORADIUS #define AUTHOFFSET 1 {authfuncs+8, radauth, checkACL, "radius"}, #else #define AUTHOFFSET 0 #endif {authfuncs+8+AUTHOFFSET, NULL, NULL, "none"}, {NULL, NULL, NULL, ""} };