diff --git a/src/authradius.c b/src/authradius.c index bc41fe5..f0d73cb 100644 --- a/src/authradius.c +++ b/src/authradius.c @@ -281,7 +281,7 @@ void random_vector(uint8_t *vector, struct clientparam *param) 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; + random_vector_pool[i] += myrand() & 0xff; } did_random = 1; diff --git a/src/common.c b/src/common.c index 38159d7..c0ab945 100644 --- a/src/common.c +++ b/src/common.c @@ -13,7 +13,25 @@ char * copyright = COPYRIGHT; -int randomizer = 1; +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +# define MYRAND_ARC4RANDOM 1 +#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 36))) +# define MYRAND_ARC4RANDOM 1 +#elif defined(__linux__) +# define MYRAND_GETRANDOM 1 +# include +#elif defined(_WIN32) +# if defined(__WATCOMC__) +# define MYRAND_CRYPTGENRANDOM 1 +# include +# else +# define MYRAND_BCRYPTGENRANDOM 1 +# include +# pragma comment(lib, "bcrypt.lib") +# endif +#else +# define MYRAND_FALLBACK 1 +#endif @@ -188,18 +206,31 @@ int numservers=0; char* NULLADDR="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -int myrand(void * entropy, int len){ - int i; - uint16_t init; - - init = randomizer; - for(i=0; i < len/2; i++){ - init ^= ((uint16_t *)entropy)[i]; +uint32_t myrand(void){ +#if defined(MYRAND_ARC4RANDOM) + return arc4random(); +#elif defined(MYRAND_GETRANDOM) + uint32_t r = 0; + ssize_t n; + do { + n = getrandom(&r, sizeof(r), 0); + } while(n < 0 && errno == EINTR); + return r; +#elif defined(MYRAND_BCRYPTGENRANDOM) + uint32_t r = 0; + BCryptGenRandom(NULL, (PUCHAR)&r, sizeof(r), BCRYPT_USE_SYSTEM_PREFERRED_RNG); + return r; +#elif defined(MYRAND_CRYPTGENRANDOM) + uint32_t r = 0; + HCRYPTPROV prov; + if(CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT|CRYPT_SILENT)){ + CryptGenRandom(prov, sizeof(r), (BYTE *)&r); + CryptReleaseContext(prov, 0); } - srand(rand()+init); - randomizer = rand(); - return rand(); - + return r; +#else + return ((uint32_t)rand() << 16) ^ (uint32_t)rand(); +#endif } #ifndef WITH_POLL diff --git a/src/conf.c b/src/conf.c index 1427419..67a0a49 100644 --- a/src/conf.c +++ b/src/conf.c @@ -108,6 +108,14 @@ int getrotate(char c){ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t) { struct tm *ts; + static const char * const rot_fmt[] = { + [NONE] = "%s", + [ANNUALLY] = "%s.%04d", + [MONTHLY] = "%s.%04d.%02d", + [DAILY] = "%s.%04d.%02d.%02d", + [HOURLY] = "%s.%04d.%02d.%02d-%02d", + [MINUTELY] = "%s.%04d.%02d.%02d-%02d.%02d", + }; ts = localtime(&t); if(strlen((char *)name) >= 4096){ @@ -117,32 +125,13 @@ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsign if(strchr((char *)name, '%')){ dobuf2(NULL, buf, NULL, NULL, ts, (char *)name); } - else switch(lt){ - case NONE: - sprintf((char *)buf, "%s", name); - break; - case ANNUALLY: - sprintf((char *)buf, "%s.%04d", name, ts->tm_year+1900); - break; - case MONTHLY: - sprintf((char *)buf, "%s.%04d.%02d", name, ts->tm_year+1900, ts->tm_mon+1); - break; - case WEEKLY: - t = t - (ts->tm_wday * (60*60*24)); - ts = localtime(&t); - sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday); - break; - case DAILY: - sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday); - break; - case HOURLY: - sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour); - break; - case MINUTELY: - sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min); - break; - default: - break; + else if(lt == WEEKLY){ + t = t - (ts->tm_wday * (60*60*24)); + ts = localtime(&t); + sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday); + } + else if((unsigned)lt < sizeof(rot_fmt)/sizeof(rot_fmt[0]) && rot_fmt[lt]){ + sprintf((char *)buf, rot_fmt[lt], name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min); } if(ext){ strcat((char *)buf, "."); diff --git a/src/ftp.c b/src/ftp.c index b2bd75b..a2c71a2 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -7,6 +7,18 @@ #include "proxy.h" +/* + * Read one FTP server response, skipping continuation lines (lines whose + * 4th character is '-' per RFC 959). Returns the line length on success, + * 0/<0 on socket error/timeout. The final line's text is left in buf. + */ +static int ftpreadresponse(struct clientparam *param, char *buf, int buflen) { + int i; + while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, buflen - 1, '\n', + conf.timeouts[STRING_L])) > 0 + && (i < 3 || !isnumber(*buf) || buf[3] == '-')) {} + return i; +} int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) { char tbuf[256]; @@ -20,8 +32,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) { if(innbuf)*innbuf = 0; if(len < 140) return 707; - while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ - } + i = ftpreadresponse(param, buf, len); if(i < 3) return 706; buf[i] = 0; if(atoi(buf)/100 != 2) { @@ -34,8 +45,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) { } param->statscli64 += (int)strlen(buf); param->nwrites++; - while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ - } + i = ftpreadresponse(param, buf, len); if(i < 3) return 704; buf[i] = 0; res = atoi(buf)/100; @@ -99,8 +109,7 @@ int ftpres(struct clientparam *param, unsigned char * buf, int l){ int i; if (l < 16) return 755; - while((i = sockgetlinebuf(param, SERVER, buf, l - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ - } + i = ftpreadresponse(param, (char *)buf, l); buf[i] = 0; if(i < 3) return 751; if(buf[0] != '2' && buf[0] != '1') return 750; @@ -115,8 +124,7 @@ int ftpsyst(struct clientparam *param, unsigned char *buf, unsigned len){ } param->statscli64 += 6; param->nwrites++; - while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ - } + i = ftpreadresponse(param, (char *)buf, len); if(i < 7) return 722; buf[3] = 0; if(atoi((char *)buf)/100 != 2) return 723; @@ -134,8 +142,7 @@ int ftppwd(struct clientparam *param, unsigned char *buf, unsigned len){ } param->statscli64 += 5; param->nwrites++; - while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ - } + i = ftpreadresponse(param, (char *)buf, len); if(i < 7) return 732; buf[3] = 0; if(atoi((char *)buf)/100 != 2) return 733; @@ -159,8 +166,7 @@ int ftptype(struct clientparam *param, unsigned char* f_type){ } param->statscli64 += (int)strlen(buf); param->nwrites++; - while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ - } + i = ftpreadresponse(param, buf, sizeof(buf)); if(i < 3) return 742; if(buf[0] != '2') return 740; return 0; @@ -181,8 +187,7 @@ SOCKET ftpdata(struct clientparam *param){ } param->statscli64 += 6; param->nwrites++; - while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ - } + i = ftpreadresponse(param, buf, sizeof(buf)); if(i < 7) return INVALID_SOCKET; if(buf[0] != '2') return INVALID_SOCKET; buf[i-2] = 0; @@ -195,7 +200,7 @@ SOCKET ftpdata(struct clientparam *param){ rem = param->remsock; param->remsock = INVALID_SOCKET; param->req = param->sinsr; - *SAPORT(¶m->req) = *SAPORT(¶m->sinsr) = htons((uint16_t)((b5<<8)^b6)); + *SAPORT(¶m->req) = *SAPORT(¶m->sinsr) = htons((uint16_t)(((b5 & 0xff)<<8) | (b6 & 0xff))); *SAPORT(¶m->sinsl) = 0; i = param->operation; param->operation = FTP_DATA; @@ -233,8 +238,7 @@ SOCKET ftpcommand(struct clientparam *param, unsigned char * command, unsigned c } param->statscli64 += (int)strlen(buf); param->nwrites++; - while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ - } + i = ftpreadresponse(param, buf, sizeof(buf)); if(i < 3) { param->srv->so._closesocket(param->sostate, s); return INVALID_SOCKET; diff --git a/src/hash.c b/src/hash.c index 6d3e97d..b56bb9c 100644 --- a/src/hash.c +++ b/src/hash.c @@ -85,7 +85,7 @@ int inithashtable(struct hashtable *ht, unsigned tablesize, unsigned poolsize, u ht->poolsize = poolsize; ht->tablesize = tablesize; ht->growlimit = growlimit; - ht->entropy = myrand(ht, sizeof(struct hashtable)); + ht->entropy = myrand(); memset(ht->ihashtable, 0, ht->tablesize * sizeof(uint32_t)); memset(ht->hashvalues, 0, ht->poolsize * (sizeof(struct hashentry) + ht->recsize - 4)); diff --git a/src/proxy.c b/src/proxy.c index 1fc5729..17854d7 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -135,6 +135,27 @@ char * proxy_stringtable[] = { #define BUFSIZE (LINESIZE*2) #define FTPBUFSIZE 1536 +#define PST_COUNT (sizeof(proxy_stringtable)/sizeof(proxy_stringtable[0]) - 1) +static int proxy_stringtable_len[PST_COUNT]; + +static int pst_len(int idx){ + int len = proxy_stringtable_len[idx]; + if(!len) { + len = (int)strlen(proxy_stringtable[idx]); + proxy_stringtable_len[idx] = len; + } + return len; +} + +static int send_st(struct clientparam *param, int idx){ + return socksend(param, param->clisock, (unsigned char *)proxy_stringtable[idx], pst_len(idx), conf.timeouts[STRING_S]); +} + +static void freeptr(void *p){ + void **pp = (void **)p; + if(*pp) { free(*pp); *pp = NULL; } +} + static void logurl(struct clientparam * param, char * buf, char * req, int ftp){ char *sb; char *se; @@ -347,16 +368,28 @@ for(;;){ if(!isconnect){ if(se==sg)*se-- = ' '; *se = '/'; - memmove(ss, se, i - (se - sb) + 1); + memmove(ss, se, i - (se - buf) + 1); } } reqlen = i = (int)strlen((char *)buf); - if(!strncasecmp((char *)buf, "CONNECT", 7))param->operation = HTTP_CONNECT; - else if(!strncasecmp((char *)buf, "GET", 3))param->operation = (ftp)?FTP_GET:HTTP_GET; - else if(!strncasecmp((char *)buf, "PUT", 3))param->operation = (ftp)?FTP_PUT:HTTP_PUT; - else if(!strncasecmp((char *)buf, "POST", 4)||!strncasecmp((char *)buf, "BITS_POST", 9))param->operation = HTTP_POST; - else if(!strncasecmp((char *)buf, "HEAD", 4))param->operation = HTTP_HEAD; - else param->operation = HTTP_OTHER; + { + static const struct { const char *m; int mlen; int op_http, op_ftp; } methods[] = { + {"CONNECT", 7, HTTP_CONNECT, HTTP_CONNECT}, + {"GET", 3, HTTP_GET, FTP_GET}, + {"PUT", 3, HTTP_PUT, FTP_PUT}, + {"POST", 4, HTTP_POST, HTTP_POST}, + {"BITS_POST", 9, HTTP_POST, HTTP_POST}, + {"HEAD", 4, HTTP_HEAD, HTTP_HEAD}, + }; + int k; + param->operation = HTTP_OTHER; + for(k = 0; k < (int)(sizeof(methods)/sizeof(methods[0])); k++){ + if(!strncasecmp((char *)buf, methods[k].m, methods[k].mlen)){ + param->operation = ftp ? methods[k].op_ftp : methods[k].op_http; + break; + } + } + } do { buf[inbuf+i]=0; /*printf("Got: %s\n", buf+inbuf);*/ @@ -403,7 +436,7 @@ for(;;){ } if( i > 11 && !strncasecmp((char *)(buf+inbuf), "Expect: 100", 11)){ keepalive = 1; - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[17], (int)strlen(proxy_stringtable[17]), conf.timeouts[STRING_S]); + send_st(param, 17); continue; } if(param->transparent && i > 6 && !strncasecmp((char *)buf + inbuf, "Host:", 5)){ @@ -516,7 +549,7 @@ for(;;){ #endif if(isconnect && param->redirtype != R_HTTP) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[8], (int)strlen(proxy_stringtable[8]), conf.timeouts[STRING_S]); + send_st(param, 8); } @@ -593,7 +626,7 @@ for(;;){ res = ftptype(param, (unsigned char *)"I"); if(res)RETURN(res); ftpbase[--i] = 0; - ftps = ftpcommand(param, param->operation == FTP_PUT? (unsigned char *)"PUT" : (unsigned char *)"RETR", ftpbase); + ftps = ftpcommand(param, param->operation == FTP_PUT? (unsigned char *)"STOR" : (unsigned char *)"RETR", ftpbase); } else { if(inftpbuf){ @@ -607,7 +640,7 @@ for(;;){ } if(ftps == INVALID_SOCKET){RETURN(780);} if(!mode){ - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[8], (int)strlen(proxy_stringtable[8]), conf.timeouts[STRING_S]); + send_st(param, 8); s = param->remsock; param->remsock = ftps; if((param->operation == FTP_PUT) && (contentlength64 > 0)) param->waitclient64 = contentlength64; @@ -753,7 +786,7 @@ for(;;){ if((bufsize - inbuf) < LINESIZE){ if (bufsize > 20000){ if(!headsent++){ - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[9], (int)strlen(proxy_stringtable[9]), conf.timeouts[STRING_S]); + send_st(param, 9); } if((unsigned)socksend(param, param->clisock, buf, inbuf, conf.timeouts[STRING_S]) != inbuf){ RETURN(781); @@ -797,16 +830,10 @@ for(;;){ if(isconnect && param->redirtype != R_HTTP) { if(param->redirectfunc) { - if(req)free(req); - if(buf)free(buf); + freeptr(&req); freeptr(&buf); freeptr(&ftpbase); return (*param->redirectfunc)(param); } param->res = mapsocket(param, conf.timeouts[CONNECTION_L]); - if(param->redirectfunc) { - if(req)free(req); - if(buf)free(buf); - return (*param->redirectfunc)(param); - } RETURN(param->res); } @@ -828,44 +855,46 @@ for(;;){ param->nwrites++; } inbuf = 0; + { + int hlen = (int)strlen((char *)buf); #ifndef ANONYMOUS if(!anonymous){ - int len = strlen((char *)buf); - len += sprintf((char*)buf + len, "Forwarded: for="); - if(*SAFAMILY(¶m->sincr) == AF_INET6) len += sprintf((char*)buf + len, "\"["); - len += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), (char *)buf + len, 128); - if(*SAFAMILY(¶m->sincr) == AF_INET6) len += sprintf((char*)buf + len, "]:%d\";by=", (int)ntohs(*SAPORT(¶m->sincr))); - else len += sprintf((char*)buf + len, ":%d;by=", (int)ntohs(*SAPORT(¶m->sincr))); - gethostname((char *)(buf + len), 256); - sprintf((char*)buf+strlen((char *)buf), ":%d\r\n", (int)ntohs(*SAPORT(¶m->sincl))); + hlen += sprintf((char*)buf + hlen, "Forwarded: for="); + if(*SAFAMILY(¶m->sincr) == AF_INET6) hlen += sprintf((char*)buf + hlen, "\"["); + hlen += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), (char *)buf + hlen, 128); + if(*SAFAMILY(¶m->sincr) == AF_INET6) hlen += sprintf((char*)buf + hlen, "]:%d\";by=", (int)ntohs(*SAPORT(¶m->sincr))); + else hlen += sprintf((char*)buf + hlen, ":%d;by=", (int)ntohs(*SAPORT(¶m->sincr))); + gethostname((char *)(buf + hlen), 256); + hlen += (int)strlen((char *)(buf + hlen)); + hlen += sprintf((char*)buf + hlen, ":%d\r\n", (int)ntohs(*SAPORT(¶m->sincl))); } else if(anonymous>1){ - sprintf((char*)buf+strlen((char *)buf), "Via: 1.1 "); - gethostname((char *)(buf+strlen((char *)buf)), 256); - sprintf((char*)buf+strlen((char *)buf), ":%d (%s %s)\r\nX-Forwarded-For: ", (int)ntohs(*SAPORT(¶m->srv->intsa)), conf.stringtable?conf.stringtable[2]:(unsigned char *)"", conf.stringtable?conf.stringtable[3]:(unsigned char *)""); - if(anonymous != 2)myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), (char *)buf + strlen((char *)buf), 128); + hlen += sprintf((char*)buf + hlen, "Via: 1.1 "); + gethostname((char *)(buf + hlen), 256); + hlen += (int)strlen((char *)(buf + hlen)); + hlen += sprintf((char*)buf + hlen, ":%d (%s %s)\r\nX-Forwarded-For: ", (int)ntohs(*SAPORT(¶m->srv->intsa)), conf.stringtable?conf.stringtable[2]:(unsigned char *)"", conf.stringtable?conf.stringtable[3]:(unsigned char *)""); + if(anonymous != 2)hlen += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), (char *)buf + hlen, 128); else { - unsigned long tmp; - - tmp = ((unsigned long)myrand(param, sizeof(struct clientparam))<<16)^(unsigned long)rand(); - myinet_ntop(AF_INET, &tmp, (char *)buf + strlen((char *)buf), 64); + uint32_t tmp = myrand(); + hlen += myinet_ntop(AF_INET, &tmp, (char *)buf + hlen, 64); } - sprintf((char*)buf+strlen((char *)buf), "\r\n"); + hlen += sprintf((char*)buf + hlen, "\r\n"); } #endif if(keepalive <= 1) { - sprintf((char*)buf+strlen((char *)buf), "Connection: %s\r\n", keepalive? "keep-alive":"close"); + hlen += sprintf((char*)buf + hlen, "Connection: %s\r\n", keepalive? "keep-alive":"close"); } if(param->extusername){ - sprintf((char*)buf + strlen((char *)buf), "%s: Basic ", (redirect)?"Proxy-Authorization":"Authorization"); + hlen += sprintf((char*)buf + hlen, "%s: Basic ", (redirect)?"Proxy-Authorization":"Authorization"); sprintf((char*)username, "%.128s:%.128s", param->extusername, param->extpassword?param->extpassword:(unsigned char*)""); - en64(username, buf+strlen((char *)buf), (int)strlen((char *)username)); - sprintf((char*)buf + strlen((char *)buf), "\r\n"); + hlen = (int)(en64(username, buf + hlen, (int)strlen((char *)username)) - buf); + hlen += sprintf((char*)buf + hlen, "\r\n"); } - sprintf((char*)buf+strlen((char *)buf), "\r\n"); - if ((res = socksend(param, param->remsock, buf+reqlen, (int)strlen((char *)buf+reqlen), conf.timeouts[STRING_S])) != (int)strlen((char *)buf+reqlen)) { + hlen += sprintf((char*)buf + hlen, "\r\n"); + if ((res = socksend(param, param->remsock, buf+reqlen, hlen - reqlen, conf.timeouts[STRING_S])) != hlen - reqlen) { RETURN(518); } + } #ifdef TCP_CORK { int opt = 0; @@ -1004,16 +1033,17 @@ for(;;){ #else #endif if(!isconnect || param->operation){ - if(authenticate && !param->transparent) sprintf((char*)buf+strlen((char *)buf), + int hlen = (int)strlen((char *)buf); + if(authenticate && !param->transparent) hlen += sprintf((char*)buf + hlen, "Proxy-support: Session-Based-Authentication\r\n" "Connection: Proxy-support\r\n" ); if(!param->srv->transparent && res>=200){ - if(ckeepalive <= 1) sprintf((char*)buf+strlen((char *)buf), "Connection: %s\r\n", + if(ckeepalive <= 1) hlen += sprintf((char*)buf + hlen, "Connection: %s\r\n", (hascontent && ckeepalive)?"keep-alive":"close"); } - sprintf((char*)buf + strlen((char *)buf), "\r\n"); - if((socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S])) != (int)strlen((char *)buf)) { + hlen += sprintf((char*)buf + hlen, "\r\n"); + if(socksend(param, param->clisock, buf, hlen, conf.timeouts[STRING_S]) != hlen) { RETURN(521); } } @@ -1084,51 +1114,32 @@ REQUESTEND: CLEANRET: if(param->res != 555 && param->res && param->clisock != INVALID_SOCKET && (param->res < 90 || param->res >=800 || param->res == 100 ||(param->res > 500 && param->res< 800))) { - if((param->res>=509 && param->res < 517) || param->res > 900) { + int stidx = -1; + int r = param->res; + + if((r >= 509 && r < 517) || r > 900) { if(buf) while( (i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, '\n', conf.timeouts[STRING_S])) > 2); } - if(param->res == 10) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[2], (int)strlen(proxy_stringtable[2]), conf.timeouts[STRING_S]); + if(r == 10) stidx = 2; + else if(r == 700 || r == 701) stidx = 16; + else if(r == 100 || (r > 10 && r < 20) || (r > 701 && r <= 705)) stidx = 1; + else if(r >= 20 && r < 30) stidx = 6; + else if(r >= 30 && r < 80) stidx = 5; + else if(r == 1 || (!param->srv->needuser && r < 10)) stidx = 11; + else if(r < 10) stidx = 7; + else if(r == 999) stidx = 4; + else if(r == 519) stidx = 3; + else if(r == 517) stidx = 15; + else if(r == 780) stidx = 10; + else if(r >= 511 && r <= 516) stidx = 0; + + if(stidx >= 0) { + send_st(param, stidx); + if(r == 700 || r == 701) socksend(param, param->clisock, (unsigned char *)ftpbuf, inftpbuf, conf.timeouts[STRING_S]); } - else if (param->res == 700 || param->res == 701){ - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[16], (int)strlen(proxy_stringtable[16]), conf.timeouts[STRING_S]); - socksend(param, param->clisock, (unsigned char *)ftpbuf, inftpbuf, conf.timeouts[STRING_S]); - } - else if(param->res == 100 || (param->res >10 && param->res < 20) || (param->res >701 && param->res <= 705)) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[1], (int)strlen(proxy_stringtable[1]), conf.timeouts[STRING_S]); - } - else if(param->res >=20 && param->res < 30) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[6], (int)strlen(proxy_stringtable[6]), conf.timeouts[STRING_S]); - } - else if(param->res >=30 && param->res < 80) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[5], (int)strlen(proxy_stringtable[5]), conf.timeouts[STRING_S]); - } - else if(param->res == 1 || (!param->srv->needuser && param->res < 10)) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[11], (int)strlen(proxy_stringtable[11]), conf.timeouts[STRING_S]); - } - else if(param->res < 10) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[7], (int)strlen(proxy_stringtable[7]), conf.timeouts[STRING_S]); - } - else if(param->res == 999) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[4], (int)strlen(proxy_stringtable[4]), conf.timeouts[STRING_S]); - } - else if(param->res == 519) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[3], (int)strlen(proxy_stringtable[3]), conf.timeouts[STRING_S]); - } - else if(param->res == 517) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[15], (int)strlen(proxy_stringtable[15]), conf.timeouts[STRING_S]); - } - else if(param->res == 780) { - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[10], (int)strlen(proxy_stringtable[10]), conf.timeouts[STRING_S]); - } - else if(param->res >= 511 && param->res<=516){ - socksend(param, param->clisock, (unsigned char *)proxy_stringtable[0], (int)strlen(proxy_stringtable[0]), conf.timeouts[STRING_S]); - } - } + } logurl(param, (char *)buf, (char *)req, ftp); - if(req)free(req); - if(buf)free(buf); - if(ftpbase)free(ftpbase); + freeptr(&req); freeptr(&buf); freeptr(&ftpbase); freeparam(param); return (NULL); } diff --git a/src/proxy.h b/src/proxy.h index 2afbaa9..e72fb25 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -317,7 +317,7 @@ int readconfig(FILE * fp); int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to); -int myrand(void * entropy, int len); +uint32_t myrand(void); uint32_t murmurhash3(const void *key, int len, uint32_t seed); extern char *copyright; diff --git a/src/redirect.c b/src/redirect.c index a18b9ee..0d8929b 100644 --- a/src/redirect.c +++ b/src/redirect.c @@ -274,14 +274,14 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ return 100; } - r2 = (myrand(param, sizeof(struct clientparam))%1000); + r2 = (myrand()%1000); for(cur = acentry->chains; cur; cur=cur->next){ if(((weight = weight - cur->weight) > r2)|| done) { if(weight <= 0) { weight += 1000; done = 0; - r2 = (myrand(param, sizeof(struct clientparam))%1000); + r2 = (myrand()%1000); } continue; } @@ -290,7 +290,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ if(weight <= 0) { weight += 1000; done = 0; - r2 = (myrand(param, sizeof(struct clientparam))%1000); + r2 = (myrand()%1000); } if(!connected){ if(cur->type == R_EXTIP){ @@ -302,12 +302,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ int i; for(i = 0; i < 8; i++){ - if(i==4)myrand(¶m->sincr, sizeof(param->sincr)); - else if(i==6) myrand(¶m->req, sizeof(param->req)); - - if(i*16 >= cur->cidr) ((uint16_t *)SAADDR(¶m->sinsl))[i] |= rand(); + if(i*16 >= cur->cidr) ((uint16_t *)SAADDR(¶m->sinsl))[i] |= (uint16_t)myrand(); else if ((i+1)*16 > cur->cidr){ - c = rand(); + c = (uint16_t)myrand(); c >>= (cur->cidr - (i*16)); c |= ntohs(((uint16_t *)SAADDR(¶m->sinsl))[i]); ((uint16_t *)SAADDR(¶m->sinsl))[i] = htons(c); diff --git a/src/resolve.c b/src/resolve.c index d7f6f19..3d4eacc 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -70,7 +70,7 @@ uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_ } len = (int)strlen((char *)name); - serial = myrand(name,len); + serial = myrand(); *(unsigned short*)buf = serial; /* query id */ buf[2] = 1; /* recursive */ buf[3] = 0; diff --git a/src/socks.c b/src/socks.c index 8452407..61b656b 100644 --- a/src/socks.c +++ b/src/socks.c @@ -9,6 +9,12 @@ #include "proxy.h" #ifdef __linux__ #include + +static int switch_ns(struct srvparam *srv, int target_fd) { + if(target_fd < 0) return 0; + if(srv->saved_nsfd >= 0 && setns(srv->saved_nsfd, CLONE_NEWNET)) return -1; + return setns(target_fd, CLONE_NEWNET); +} #endif #define RETURN(xxx) { param->res = xxx; goto CLEANRET; } @@ -75,14 +81,14 @@ void * sockschild(struct clientparam* param) { RETURN(412); } if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} - if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);}; + if (i && (res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != (int)i) {RETURN(441);} buf[i] = 0; if(!param->username) { param->username = (unsigned char *)strdup((char *)buf); if(!param->username){RETURN(21);} } if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);} - if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);}; + if (i && (res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != (int)i) {RETURN(441);} buf[i] = 0; if(!param->password) { param->password = (unsigned char *)strdup((char *)buf); @@ -198,33 +204,28 @@ void * sockschild(struct clientparam* param) { case 2: case 3: -#ifndef NOIPV6 +#ifndef NOIPV6 param->sinsl = *SAFAMILY(¶m->req)==AF_INET6? param->srv->extsa6 : param->srv->extsa; #else param->sinsl = param->srv->extsa; #endif -#ifdef __linux__ - if(command == 3 && param->srv->o_nsfd >= 0) { - if(param->srv->saved_nsfd >= 0 && setns(param->srv->saved_nsfd, CLONE_NEWNET)) {RETURN(11);} - if(setns(param->srv->o_nsfd, CLONE_NEWNET)) {RETURN(11);} - } -#endif - if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} param->operation = command == 2?BIND:UDPASSOC; + if(command == 2){ + if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);} #ifdef REUSE - if (command == 2){ - int opt; - + { + int opt; #ifdef SO_REUSEADDR - opt = 1; - param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)); + opt = 1; + param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)); #endif #ifdef SO_REUSEPORT - opt = 1; - param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int)); + opt = 1; + param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int)); #endif - } + } #endif + } break; default: @@ -249,6 +250,13 @@ void * sockschild(struct clientparam* param) { } #endif + if(command == 3) { +#ifdef __linux__ + if(switch_ns(param->srv, param->srv->o_nsfd)) {RETURN(11);} +#endif + if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} + } + if(command > 1) { if(param->srv->so._bind(param->sostate, param->remsock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->sinsl))) { *SAPORT(¶m->sinsl) = 0; @@ -263,10 +271,7 @@ fflush(stderr); if(command == 3) { param->ctrlsock = param->clisock; #ifdef __linux__ - if(param->srv->i_nsfd >= 0) { - if(param->srv->saved_nsfd >= 0 && setns(param->srv->saved_nsfd, CLONE_NEWNET)) {RETURN(11);} - if(setns(param->srv->i_nsfd, CLONE_NEWNET)) {RETURN(11);} - } + if(switch_ns(param->srv, param->srv->i_nsfd)) {RETURN(11);} #endif param->clisock = param->srv->so._socket(param->sostate, SASOCK(¶m->sincr), SOCK_DGRAM, IPPROTO_UDP); if(param->clisock == INVALID_SOCKET) {RETURN(11);} diff --git a/src/udpsockmap.c b/src/udpsockmap.c index 5e8e30a..2aeb749 100644 --- a/src/udpsockmap.c +++ b/src/udpsockmap.c @@ -201,11 +201,13 @@ int udpsockmap(struct clientparam *param, int timeo) sendlen = len + hdrsize; } else if (nhops >= 2) { int off = 0, k; + int bad = 0; for (k = 1; k < nhops; k++) { int next = socks5_udp_skip_hdr(param->srvbuf + off, len - off); - if (next < 0) break; + if (next < 0) { bad = 1; break; } off += next; } + if (bad) continue; sendoff = off; sendlen = len - off; }