diff --git a/src/3proxy.c b/src/3proxy.c index 9b8e848..6942795 100644 --- a/src/3proxy.c +++ b/src/3proxy.c @@ -141,8 +141,10 @@ int timechanged (time_t oldtime, time_t newtime, ROTATION lt){ struct tm tmold; struct tm *tm; tm = localtime(&oldtime); + if(!tm) return 0; tmold = *tm; tm = localtime(&newtime); + if(!tm) return 0; switch(lt){ case MINUTELY: if(tm->tm_min != tmold.tm_min)return 1; @@ -214,17 +216,17 @@ void dumpcounters(struct trafcount *tlin, int counterd){ cheader.updated = conf.time; - lseek(counterd, 0, SEEK_SET); - if(write(counterd, &cheader, sizeof(struct counter_header))){} + if(lseek(counterd, 0, SEEK_SET) >= 0 && write(counterd, &cheader, sizeof(struct counter_header))){} for(tl=tlin; tl; tl = tl->next){ if(tl->number){ - lseek(counterd, + if(lseek(counterd, sizeof(struct counter_header) + (tl->number - 1) * sizeof(struct counter_record), - SEEK_SET); - crecord.traf64 = tl->traf64; - crecord.cleared = tl->cleared; - crecord.updated = tl->updated; - if(write(counterd, &crecord, sizeof(struct counter_record))){} + SEEK_SET) >= 0){ + crecord.traf64 = tl->traf64; + crecord.cleared = tl->cleared; + crecord.updated = tl->updated; + if(write(counterd, &crecord, sizeof(struct counter_record))){} + } } if(tl->type!=NEVER && timechanged(tl->cleared, conf.time, tl->type)){ tl->cleared = conf.time; @@ -267,9 +269,11 @@ void cyclestep(void){ } if(timechanged(basetime, conf.time, DAILY)) { tm = localtime(&conf.time); - wday = (1 << tm->tm_wday); - tm->tm_hour = tm->tm_min = tm->tm_sec = 0; - basetime = mktime(tm); + if(tm){ + wday = (1 << tm->tm_wday); + tm->tm_hour = tm->tm_min = tm->tm_sec = 0; + basetime = mktime(tm); + } } if(conf.logname) { if(timechanged(conf.logtime, conf.time, conf.logtype)) { @@ -530,7 +534,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int conf.version++; if(res) RETURN(res); - if(!writable)fclose(fp); + if(!writable){fclose(fp); fp = NULL;} #ifdef _WIN32 @@ -561,6 +565,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int CLEARRETURN: + if(fp && fp != stdin) {fclose(fp); fp = NULL;} return 0; } diff --git a/src/auth.c b/src/auth.c index 97585a2..28ae07c 100644 --- a/src/auth.c +++ b/src/auth.c @@ -118,7 +118,10 @@ int doauth(struct clientparam * param){ if(conf.authcachetype && authfuncs->authenticate && authfuncs->authenticate != cacheauth && param->username && (!(conf.authcachetype&4) || (!param->pwtype && param->password))){ struct authcache ac={.username=""}; - if(param->username) strncpy((char *)ac.username, (char *)param->username, 64); + 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 @@ -252,3 +255,4 @@ struct auth authfuncs[] = { {authfuncs+8+AUTHOFFSET, NULL, NULL, "none"}, {NULL, NULL, NULL, ""} }; + diff --git a/src/common.c b/src/common.c index 99fdd5f..cb1b88d 100644 --- a/src/common.c +++ b/src/common.c @@ -22,10 +22,15 @@ int randomizer = 1; void daemonize(void){ - if(fork() > 0) { + pid_t pid = fork(); + if(pid > 0) { usleep(SLEEPTIME); _exit(0); } + if(pid < 0) { + perror("fork()"); + return; + } setsid(); } @@ -244,6 +249,7 @@ int FD_ZERO(&writefd); FD_ZERO(&oobfd); for(i=0; i= FD_SETSIZE) continue; if((fds[i].events&POLLIN))FD_SET(fds[i].fd, &readfd); if((fds[i].events&POLLOUT))FD_SET(fds[i].fd, &writefd); if((fds[i].events&POLLPRI))FD_SET(fds[i].fd, &oobfd); @@ -252,6 +258,7 @@ int } if((num = select(((int)(maxfd))+1, &readfd, &writefd, &oobfd, &tv)) < 1) return num; for(i=0; i= FD_SETSIZE) continue; if(FD_ISSET(fds[i].fd, &readfd)) fds[i].revents |= POLLIN; if(FD_ISSET(fds[i].fd, &writefd)) fds[i].revents |= POLLOUT; if(FD_ISSET(fds[i].fd, &oobfd)) fds[i].revents |= POLLPRI; diff --git a/src/conf.c b/src/conf.c index 2ddf645..8c1ac66 100644 --- a/src/conf.c +++ b/src/conf.c @@ -582,7 +582,7 @@ static int h_maxconn(int argc, unsigned char **argv){ static int h_backlog(int argc, unsigned char **argv){ conf.backlog = atoi((char *)argv[1]); - if(conf.maxchild < 0) { + if(conf.backlog < 0) { return(1); } return 0; @@ -778,6 +778,7 @@ static int h_parent(int argc, unsigned char **argv){ chains->weight = (unsigned)atoi((char *)argv[1]); if(chains->weight == 0 || chains->weight >1000) { fprintf(stderr, "Chaining error: bad chain weight %u line %d\n", chains->weight, linenum); + myfree(chains); return(3); } for(i = 0; redirs[i].name ; i++){ @@ -793,6 +794,7 @@ static int h_parent(int argc, unsigned char **argv){ } if(!redirs[i].name) { fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]); + myfree(chains); return(4); } #ifdef WITH_UN @@ -803,12 +805,18 @@ static int h_parent(int argc, unsigned char **argv){ #endif cidr = strchr((char *)argv[3], '/'); if(cidr) *cidr = 0; - if(!getip46(46, argv[3], (struct sockaddr *)&chains->addr)) return (5); + if(!getip46(46, argv[3], (struct sockaddr *)&chains->addr)) { + myfree(chains); + return (5); + } #ifdef WITH_UN } #endif chains->exthost = (unsigned char *)mystrdup((char *)argv[3]); - if(!chains->exthost) return 21; + if(!chains->exthost) { + myfree(chains); + return 21; + } if(cidr){ *cidr = '/'; chains->cidr = atoi(cidr + 1); @@ -1221,7 +1229,10 @@ static int h_ace(int argc, unsigned char **argv){ } memset(acl->chains, 0, sizeof(struct chain)); acl->chains->type = R_HTTP; - if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) return 5; + if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) { + freeacl(acl); + return 5; + } *SAPORT(&acl->chains->addr) = htons((uint16_t)atoi((char *)argv[2])); acl->chains->weight = 1000; case ALLOW: @@ -1405,7 +1416,7 @@ static int h_radius(int argc, unsigned char **argv){ s++; } if( !getip46(46, argv[nradservers + 2], (struct sockaddr *)&radiuslist[nradservers].authaddr)) return 1; - if( s && !getip46(46, (unsigned char *)s+1, (struct sockaddr *)&radiuslist[nradservers].localaddr)) return 2; + if( s && !getip46(46, (unsigned char *)s, (struct sockaddr *)&radiuslist[nradservers].localaddr)) return 2; if(!*SAPORT(&radiuslist[nradservers].authaddr))*SAPORT(&radiuslist[nradservers].authaddr) = htons(1812); port = ntohs(*SAPORT(&radiuslist[nradservers].authaddr)); radiuslist[nradservers].logaddr = radiuslist[nradservers].authaddr; @@ -1709,8 +1720,8 @@ int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned cha *str = 0; space = 1; if(incbegin){ - argc--; - if((fd = open((char *)incbegin+1, O_RDONLY)) <= 0){ + if(argc) argc--; + if((fd = open((char *)incbegin+1, O_RDONLY)) < 0){ fprintf(stderr, "Failed to open %s\n", incbegin+1); return -1; } @@ -1723,7 +1734,7 @@ int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned cha } } len = 0; - if(argm[argc]!=(incbegin+1)) { + if(argc > 0 && argm[argc]!=(incbegin+1)) { len = (int)strlen((char *)argm[argc]); memmove(buf+*inbuf, argm[argc], len); } diff --git a/src/limiter.c b/src/limiter.c index 7bc67a2..02ae5cf 100644 --- a/src/limiter.c +++ b/src/limiter.c @@ -42,6 +42,15 @@ int startconnlims (struct clientparam *param){ ce->basetime = conf.time; } } + if(ret) { + struct connlim * cee; + for(cee = conf.connlimiter; cee != ce; cee = cee->next) { + if(ACLmatches(cee->ace, param) && !cee->period && cee->rating) { + cee->rating--; + } + } + param->connlim = 0; + } pthread_mutex_unlock(&connlim_mutex); return ret; } diff --git a/src/proxy.c b/src/proxy.c index 4ab4909..2448f1a 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -337,7 +337,10 @@ for(;;){ if(su) { su = (unsigned char *)mystrdup((char *)sb); decodeurl(su, 0); - if(parseconnusername((char *)su, (struct clientparam *)param, 1, (uint16_t)((ftp)?21:80))) RETURN (100); + if(parseconnusername((char *)su, (struct clientparam *)param, 1, (uint16_t)((ftp)?21:80))) { + myfree(su); + RETURN (100); + } myfree(su); } else if(parsehostname((char *)sb, (struct clientparam *)param, (uint16_t)((ftp)? 21:80))) RETURN(100); @@ -1077,11 +1080,13 @@ 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) while( (i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, '\n', conf.timeouts[STRING_S])) > 2); + if((param->res>=509 && param->res < 517) || param->res > 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]); } - else if (res == 700 || res == 701){ + 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]); } diff --git a/src/proxymain.c b/src/proxymain.c index 0aa4e67..04d5839 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -101,7 +101,7 @@ void * threadfunc (void *p) { if(token){ sscanf(token,"%hu%hu", &u1, &u2); if(u1) *SAPORT(¶m->sincr) = htons(u1); - if(u2) *SAPORT(¶m->sincl) = htons(u1); + if(u2) *SAPORT(¶m->sincl) = htons(u2); } } } @@ -730,6 +730,12 @@ int MODULEMAINFUNC (int argc, char** argv){ sleeptime = (sleeptime<<1); if(!sleeptime) { srv.so._closesocket(srv.so.state, sock); + if(cbc_string) myfree(cbc_string); + if(cbl_string) myfree(cbl_string); + if(srv.ibindtodevice) myfree(srv.ibindtodevice); + if(srv.obindtodevice) myfree(srv.obindtodevice); + if(srv.logtarget) myfree(srv.logtarget); + if(srv.logformat) myfree(srv.logformat); return -3; } } @@ -737,6 +743,13 @@ int MODULEMAINFUNC (int argc, char** argv){ if(srv.so._listen (srv.so.state, sock, srv.backlog?srv.backlog : 1+(srv.maxchild>>3))==-1) { sprintf((char *)buf, "listen(): %s", strerror(errno)); if(!srv.silent)dolog(&defparam, buf); + srv.so._closesocket(srv.so.state, sock); + if(cbc_string) myfree(cbc_string); + if(cbl_string) myfree(cbl_string); + if(srv.ibindtodevice) myfree(srv.ibindtodevice); + if(srv.obindtodevice) myfree(srv.obindtodevice); + if(srv.logtarget) myfree(srv.logtarget); + if(srv.logformat) myfree(srv.logformat); return -4; } } @@ -752,6 +765,12 @@ int MODULEMAINFUNC (int argc, char** argv){ parsehost(srv.family, cbl_string, (struct sockaddr *)&cbsa); if((srv.cbsock=srv.so._socket(srv.so.state, SASOCK(&cbsa), SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) { dolog(&defparam, (unsigned char *)"Failed to allocate connect back socket"); + if(cbc_string) myfree(cbc_string); + if(cbl_string) myfree(cbl_string); + if(srv.ibindtodevice) myfree(srv.ibindtodevice); + if(srv.obindtodevice) myfree(srv.obindtodevice); + if(srv.logtarget) myfree(srv.logtarget); + if(srv.logformat) myfree(srv.logformat); return -6; } opt = 1; @@ -765,10 +784,24 @@ int MODULEMAINFUNC (int argc, char** argv){ if(srv.so._bind(srv.so.state, srv.cbsock, (struct sockaddr*)&cbsa, SASIZE(&cbsa))==-1) { dolog(&defparam, (unsigned char *)"Failed to bind connect back socket"); + srv.so._closesocket(srv.so.state, srv.cbsock); + if(cbc_string) myfree(cbc_string); + if(cbl_string) myfree(cbl_string); + if(srv.ibindtodevice) myfree(srv.ibindtodevice); + if(srv.obindtodevice) myfree(srv.obindtodevice); + if(srv.logtarget) myfree(srv.logtarget); + if(srv.logformat) myfree(srv.logformat); return -7; } if(srv.so._listen(srv.so.state, srv.cbsock, 1 + (srv.maxchild>>4))==-1) { dolog(&defparam, (unsigned char *)"Failed to listen connect back socket"); + srv.so._closesocket(srv.so.state, srv.cbsock); + if(cbc_string) myfree(cbc_string); + if(cbl_string) myfree(cbl_string); + if(srv.ibindtodevice) myfree(srv.ibindtodevice); + if(srv.obindtodevice) myfree(srv.obindtodevice); + if(srv.logtarget) myfree(srv.logtarget); + if(srv.logformat) myfree(srv.logformat); return -8; } } @@ -891,6 +924,7 @@ int MODULEMAINFUNC (int argc, char** argv){ if(srv.so._getsockname(srv.so.state, new_sock, (struct sockaddr *)&defparam.sincl, &size)){ sprintf((char *)buf, "getsockname(): %s", strerror(errno)); if(!srv.silent)dolog(&defparam, buf); + srv.so._closesocket(srv.so.state, new_sock); continue; } #ifdef WITH_UN @@ -993,20 +1027,27 @@ int MODULEMAINFUNC (int argc, char** argv){ if(!srv.silent)dolog(&defparam, buf); error = 1; } + pthread_mutex_unlock(&srv.counter_mutex); + if(error) freeparam(newparam); #else error = pthread_create(&thread, &pa, threadfunc, (void *)newparam); - srv.childcount++; if(error){ sprintf((char *)buf, "pthread_create(): %s", strerror(error)); if(!srv.silent)dolog(&defparam, buf); + if(newparam->prev) newparam->prev->next = newparam->next; + else srv.child = newparam->next; + if(newparam->next) newparam->next->prev = newparam->prev; + pthread_mutex_unlock(&srv.counter_mutex); + newparam->srv = NULL; + freeparam(newparam); } else { + srv.childcount++; newparam->threadid = (uint64_t)thread; + pthread_mutex_unlock(&srv.counter_mutex); } #endif - pthread_mutex_unlock(&srv.counter_mutex); - if(error) freeparam(newparam); memset(&defparam.sincl, 0, sizeof(defparam.sincl)); memset(&defparam.sincr, 0, sizeof(defparam.sincr)); @@ -1166,21 +1207,23 @@ void freeparam(struct clientparam * param) { } if(param->clibuf) myfree(param->clibuf); if(param->srvbuf) myfree(param->srvbuf); - if(param->ctrlsocksrv != INVALID_SOCKET && param->ctrlsocksrv != param->remsock) { - param->srv->so._shutdown(param->sostate, param->ctrlsocksrv, SHUT_RDWR); - param->srv->so._closesocket(param->sostate, param->ctrlsocksrv); - } - if(param->ctrlsock != INVALID_SOCKET && param->ctrlsock != param->clisock) { - param->srv->so._shutdown(param->sostate, param->ctrlsock, SHUT_RDWR); - param->srv->so._closesocket(param->sostate, param->ctrlsock); - } - if(param->remsock != INVALID_SOCKET) { - param->srv->so._shutdown(param->sostate, param->remsock, SHUT_RDWR); - param->srv->so._closesocket(param->sostate, param->remsock); - } - if(param->clisock != INVALID_SOCKET) { - param->srv->so._shutdown(param->sostate, param->clisock, SHUT_RDWR); - param->srv->so._closesocket(param->sostate, param->clisock); + if(param->srv) { + if(param->ctrlsocksrv != INVALID_SOCKET && param->ctrlsocksrv != param->remsock) { + param->srv->so._shutdown(param->sostate, param->ctrlsocksrv, SHUT_RDWR); + param->srv->so._closesocket(param->sostate, param->ctrlsocksrv); + } + if(param->ctrlsock != INVALID_SOCKET && param->ctrlsock != param->clisock) { + param->srv->so._shutdown(param->sostate, param->ctrlsock, SHUT_RDWR); + param->srv->so._closesocket(param->sostate, param->ctrlsock); + } + if(param->remsock != INVALID_SOCKET) { + param->srv->so._shutdown(param->sostate, param->remsock, SHUT_RDWR); + param->srv->so._closesocket(param->sostate, param->remsock); + } + if(param->clisock != INVALID_SOCKET) { + param->srv->so._shutdown(param->sostate, param->clisock, SHUT_RDWR); + param->srv->so._closesocket(param->sostate, param->clisock); + } } if(param->datfilterssrv) myfree(param->datfilterssrv); #ifndef STDMAIN diff --git a/src/redirect.c b/src/redirect.c index 6fdafe5..d7a4cd2 100644 --- a/src/redirect.c +++ b/src/redirect.c @@ -138,7 +138,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc if(socksend(param, param->remsock, buf, 3, conf.timeouts[CHAIN_TO]) != 3){ return 51; } - param->statssrv64+=len; + param->statssrv64+=3; param->nwrites++; if(sockgetlinebuf(param, SERVER, buf, 2, EOF, conf.timeouts[CHAIN_TO]) != 2){ return 52; @@ -334,9 +334,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ int len; len = sprintf(buf, "PROXY %s ", *SAFAMILY(¶m->sincr) == AF_INET6 ? "TCP6" : "TCP4"); - len += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), buf+len, sizeof(param->sincr)); + len += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), buf+len, sizeof(buf) - len); buf[len++] = ' '; - len += myinet_ntop(*SAFAMILY(¶m->sincl), SAADDR(¶m->sincl), buf+len, sizeof(param->sincl)); + len += myinet_ntop(*SAFAMILY(¶m->sincl), SAADDR(¶m->sincl), buf+len, sizeof(buf) - len); len += sprintf(buf + len, " %hu %hu\r\n", ntohs(*SAPORT(¶m->sincr)), ntohs(*SAPORT(¶m->sincl)) diff --git a/src/sockmap.c b/src/sockmap.c index b61182c..9e59618 100644 --- a/src/sockmap.c +++ b/src/sockmap.c @@ -57,7 +57,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){ int fdsc = 0; int sleeptime = 0; FILTER_ACTION action; - int res; + int res = 0; SASIZETYPE sasize; int needaction = 0; int graceclinum=0, gracesrvnum=0, graceclitraf=0, gracesrvtraf=0; diff --git a/src/socks.c b/src/socks.c index f194a56..bd4b32a 100644 --- a/src/socks.c +++ b/src/socks.c @@ -98,7 +98,7 @@ void * sockschild(struct clientparam* param) { buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} buf[1] = (unsigned char) res; - port = *(uint16_t*)buf; + memcpy(&port, buf, 2); c = 1; } @@ -158,16 +158,16 @@ void * sockschild(struct clientparam* param) { buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} buf[1] = (unsigned char) res; - port = *(uint16_t*)buf; + memcpy(&port, buf, 2); } else { - sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); + if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]) < 0) {RETURN(441);} buf[127] = 0; if(param->srv->needuser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf); if(!memcmp(SAADDR(¶m->req), "\0\0\0", 3)){ param->service = S_SOCKS45; - sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); + if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]) < 0) {RETURN(441);} buf[127] = 0; if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); @@ -314,8 +314,13 @@ fflush(stderr); else{ buf[0] = 0; buf[1] = 90 + !!(repcode); - memcpy(buf+2, SAPORT(&sin), 2); - memcpy(buf+4, SAADDR(&sin), 4); + if(*SAFAMILY(&sin) == AF_INET){ + memcpy(buf+2, SAPORT(&sin), 2); + memcpy(buf+4, SAADDR(&sin), 4); + } else { + memset(buf+2, 0, 6); + param->res = 997; + } socksend(param, param->clisock, buf, 8, conf.timeouts[STRING_S]); } @@ -336,8 +341,9 @@ fflush(stderr); switch(command) { case 1: if(param->redirectfunc){ + void *ret = (*param->redirectfunc)(param); if(buf)myfree(buf); - return (*param->redirectfunc)(param); + return ret; } param->res = mapsocket(param, conf.timeouts[CONNECTION_L]); break; @@ -370,7 +376,10 @@ fflush(stderr); unsigned long ul=1; ioctlsocket(param->remsock, FIONBIO, &ul); #else - fcntl(param->remsock,F_SETFL,O_NONBLOCK | fcntl(param->remsock,F_GETFL)); + { + int flags = fcntl(param->remsock, F_GETFL); + if(flags != -1) fcntl(param->remsock, F_SETFL, O_NONBLOCK | flags); + } #endif }