void * adminchild(struct clientparam* param) { int i, res; char * buf; char username[256]; char *sb; char *req = NULL; struct printparam pp; int contentlen = 0; int isform = 0; pp.inbuf = 0; pp.cp = param; buf = myalloc(LINESIZE); if(!buf) {RETURN(555);} i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S]); if(i<5 || ((buf[0]!='G' || buf[1]!='E' || buf[2]!='T' || buf[3]!=' ' || buf[4]!='/') && (buf[0]!='P' || buf[1]!='O' || buf[2]!='S' || buf[3]!='T' || buf[4]!=' ' || buf[5]!='/'))) { RETURN(701); } buf[i] = 0; sb = strchr(buf+5, ' '); if(!sb){ RETURN(702); } *sb = 0; req = mystrdup(buf + ((*buf == 'P')? 6 : 5)); while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){ buf[i] = 0; if(i > 19 && (!strncasecmp(buf, "authorization", 13))){ sb = strchr(buf, ':'); if(!sb)continue; ++sb; while(isspace(*sb))sb++; if(!*sb || strncasecmp(sb, "basic", 5)){ continue; } sb+=5; while(isspace(*sb))sb++; i = de64((unsigned char *)sb, (unsigned char *)username, 255); if(i<=0)continue; username[i] = 0; sb = strchr((char *)username, ':'); if(sb){ *sb = 0; if(param->password)myfree(param->password); param->password = (unsigned char *)mystrdup(sb+1); } if(param->username) myfree(param->username); param->username = (unsigned char *)mystrdup(username); continue; } else if(i > 15 && (!strncasecmp(buf, "content-length:", 15))){ sb = buf + 15; while(isspace(*sb))sb++; contentlen = atoi(sb); } else if(i > 13 && (!strncasecmp(buf, "content-type:", 13))){ sb = buf + 13; while(isspace(*sb))sb++; if(!strncasecmp(sb, "x-www-form-urlencoded", 21)) isform = 1; } } param->operation = ADMIN; if(isform && contentlen) { printstr(&pp, "HTTP/1.0 100 Continue\r\n\r\n"); stdpr(&pp, NULL, 0); } res = (*param->srv->authfunc)(param); if(res && res != 10) { printstr(&pp, authreq); RETURN(res); } if(param->srv->singlepacket || param->redirected){ if(*req == 'C') req[1] = 0; else *req = 0; } sprintf(buf, ok, conf.stringtable?(char *)conf.stringtable[2]:"3proxy", conf.stringtable?(char *)conf.stringtable[2]:"3[APA3A] tiny proxy", conf.stringtable?(char *)conf.stringtable[3]:""); if(*req != 'S') printstr(&pp, buf); switch(*req){ case 'C': printstr(&pp, counters); { struct trafcount *cp; int num = 0; for(cp = conf.trafcounter; cp; cp = cp->next, num++){ int inbuf = 0; if(cp->ace && (param->srv->singlepacket || param->redirected)){ if(!ACLmatches(cp->ace, param))continue; } if(req[1] == 'S' && atoi(req+2) == num) cp->disabled=0; if(req[1] == 'D' && atoi(req+2) == num) cp->disabled=1; inbuf += sprintf(buf, "<tr>" "<td>%s</td><td><A HREF=\'/C%c%d\'>%s</A></td><td>", (cp->comment)?cp->comment:" ", (cp->disabled)?'S':'D', num, (cp->disabled)?"NO":"YES" ); if(!cp->ace || !cp->ace->users){ inbuf += sprintf(buf+inbuf, "<center>ANY</center>"); } else { inbuf += printuserlist(buf+inbuf, LINESIZE-800, cp->ace->users, ",<br />\r\n"); } inbuf += sprintf(buf+inbuf, "</td><td>"); if(!cp->ace || !cp->ace->src){ inbuf += sprintf(buf+inbuf, "<center>ANY</center>"); } else { inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->src, ",<br />\r\n"); } inbuf += sprintf(buf+inbuf, "</td><td>"); if(!cp->ace || !cp->ace->dst){ inbuf += sprintf(buf+inbuf, "<center>ANY</center>"); } else { inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->dst, ",<br />\r\n"); } inbuf += sprintf(buf+inbuf, "</td><td>"); if(!cp->ace || !cp->ace->ports){ inbuf += sprintf(buf+inbuf, "<center>ANY</center>"); } else { inbuf += printportlist(buf+inbuf, LINESIZE-128, cp->ace->ports, ",<br />\r\n"); } if(cp->type == NONE) { inbuf += sprintf(buf+inbuf, "</td><td colspan=\'6\' align=\'center\'>exclude from limitation</td></tr>\r\n" ); } else { inbuf += sprintf(buf+inbuf, "</td><td>%.3f</td>" "<td>MB%s</td>" "<td>%.3f MB</td>" "<td>%s</td>", (1024.0 * (float)cp->traflimgb) + (float)cp->traflim/1048576.0, rotations[cp->type], (1024.0 * (float)cp->trafgb) + (float)cp->traf/1048576.0, cp->cleared?ctime(&cp->cleared):"never" ); inbuf += sprintf(buf + inbuf, "<td>%s</td>" "<td>%i</td>" "</tr>\r\n", cp->updated?ctime(&cp->updated):"never", cp->number ); } printstr(&pp, buf); } } printstr(&pp, counterstail); break; case 'R': conf.needreload = 1; printstr(&pp, "<h3>Reload scheduled</h3>"); break; case 'S': { if(req[1] == 'X'){ printstr(&pp, style); break; } printstr(&pp, xml); printval(conf.services, TYPE_SERVER, 0, &pp); printstr(&pp, postxml); } break; case 'F': { FILE *fp; char buf[256]; fp = confopen(); if(!fp){ printstr(&pp, "<h3><font color=\"red\">Failed to open config file</font></h3>"); break; } printstr(&pp, "<h3>Please be careful editing config file remotely</h3>"); printstr(&pp, "<form method=\"POST\" action=\"/U\"><textarea cols=\"80\" rows=\"30\" name=\"conffile\">"); while(fgets(buf, 256, fp)){ printstr(&pp, buf); } if(!writable) fclose(fp); printstr(&pp, "</textarea><br><input type=\"Submit\"></form>"); break; } case 'U': { int l=0; int error = 0; if(!writable || fseek(writable, 0, 0)){ error = 1; } while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '+', conf.timeouts[STRING_S])) > 0){ if(i > (contentlen - l)) i = (contentlen - l); buf[i] = 0; if(!l){ if(strncasecmp(buf, "conffile=", 9)) error = 1; } if(!error){ decodeurl((unsigned char *)buf, 1); fprintf(writable, "%s", l? buf : buf + 9); } l += i; if(l >= contentlen) break; } if(writable && !error){ fflush(writable); #ifndef _WINCE ftruncate(fileno(writable), ftell(writable)); #endif } printstr(&pp, error? "<h3><font color=\"red\">Config file is not writable</font></h3>Make sure you have \"writable\" command in configuration file": "<h3>Configuration updated</h3>"); } break; default: printstr(&pp, (char *)conf.stringtable[WEBBANNERS]); break; } if(*req != 'S') printstr(&pp, tail); CLEANRET: printstr(&pp, NULL); if(buf) myfree(buf); (*param->srv->logfunc)(param, (unsigned char *)req); if(req)myfree(req); freeparam(param); return (NULL); }
void * proxychild(struct clientparam* param) { int res=0, i=0; unsigned char* buf = NULL, *newbuf; int inbuf; int bufsize; unsigned reqlen = 0; unsigned char *sb=NULL, *sg=NULL, *se=NULL, *sp=NULL, *req=NULL, *su=NULL, *ss = NULL; unsigned char *ftpbase=NULL; unsigned char username[1024]; int keepalive = 0; uint64_t contentlength64 = 0; int hascontent =0; int isconnect = 0; int redirect = 0; int prefix = 0, ckeepalive=0; int ftp = 0; int anonymous; int sleeptime = 0; int reqsize, reqbufsize; int authenticate; struct pollfd fds[2]; SOCKET ftps; char ftpbuf[FTPBUFSIZE]; int inftpbuf = 0; #ifndef WITHMAIN FILTER_ACTION action; #endif if(!(buf = myalloc(BUFSIZE))) {RETURN(21);} bufsize = BUFSIZE; anonymous = param->srv->singlepacket; for(;;){ memset(buf, 0, bufsize); inbuf = 0; if(keepalive && (param->cliinbuf == param->clioffset) && (param->remsock != INVALID_SOCKET)){ memset(fds, 0, sizeof(fds)); fds[0].fd = param->clisock; fds[0].events = POLLIN; fds[1].fd = param->remsock; fds[1].events = POLLIN; res = so._poll(fds, 2, conf.timeouts[STRING_S]*1000); if(res<=0) { RETURN(555); } if((fds[1].revents & (POLLIN|POLLHUP|POLLERR|POLLNVAL))) { if(param->transparent || (!param->redirected && param->redirtype == R_HTTP)) RETURN(555); ckeepalive = 0; so._shutdown(param->remsock, SHUT_RDWR); so._closesocket(param->remsock); param->remsock = INVALID_SOCKET; param->redirected = 0; param->redirtype = 0; } } i = sockgetlinebuf(param, CLIENT, buf, LINESIZE - 1, '\n', conf.timeouts[STRING_L]); if(i<=0) { RETURN((keepalive)?555:(i)?507:508); } if (i==2 && buf[0]=='\r' && buf[1]=='\n') continue; buf[i] = 0; if(req) { if(!param->transparent && !param->srv->transparent && param->redirtype != R_HTTP && (i<=prefix || strncasecmp((char *)buf, (char *)req, prefix))){ ckeepalive = 0; if(param->remsock != INVALID_SOCKET){ so._shutdown(param->remsock, SHUT_RDWR); so._closesocket(param->remsock); } param->remsock = INVALID_SOCKET; param->redirected = 0; param->redirtype = 0; } myfree(req); } req = (unsigned char *)mystrdup((char *)buf); if(!req){RETURN(510);} if(i<10) { RETURN(511); } if(buf[i-3] == '1') keepalive = 2; if((isconnect = !strncasecmp((char *)buf, "CONNECT", 7))) keepalive = 2; if ((sb=(unsigned char *)(unsigned char *)strchr((char *)buf, ' ')) == NULL) {RETURN(512);} ss = ++sb; if(!isconnect) { if (!strncasecmp((char *)sb, "http://", 7)) { sb += 7; } else if (!strncasecmp((char *)sb, "ftp://", 6)) { ftp = 1; sb += 6; } else if(*sb == '/') { param->transparent = 1; } else { RETURN (513); } } else { if ((se=(unsigned char *)(unsigned char *)strchr((char *)sb, ' ')) == NULL || sb==se) {RETURN (514);} *se = 0; } if(!param->transparent || isconnect) { if(!isconnect) { if ((se=(unsigned char *)(unsigned char *)strchr((char *)sb, '/')) == NULL || sb==se || !(sg=(unsigned char *)strchr((char *)sb, ' '))) {RETURN (515);} if(se > sg) se=sg; *se = 0; } prefix = (int)(se - buf); su = (unsigned char*)strrchr((char *)sb, '@'); if(su) { su = mystrdup(sb); decodeurl(su, 0); parseconnusername((char *)su, (struct clientparam *)param, 1, (unsigned short)((ftp)?21:80)); myfree(su); } else parsehostname((char *)sb, (struct clientparam *)param, (unsigned short)((ftp)? 21:80)); if(!isconnect){ if(se==sg)*se-- = ' '; *se = '/'; memmove(ss, se, i - (se - sb) + 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; do { buf[inbuf+i]=0; /*printf("Got: %s\n", buf+inbuf);*/ #ifndef WITHMAIN if(i > 25 && !param->srv->transparent && (!strncasecmp((char *)(buf+inbuf), "proxy-authorization", 19))){ sb = (unsigned char *)strchr((char *)(buf+inbuf), ':'); if(!sb)continue; ++sb; while(isspace(*sb))sb++; if(!*sb) continue; if(!strncasecmp((char *)sb, "basic", 5)){ sb+=5; while(isspace(*sb))sb++; i = de64(sb, username, 255); if(i<=0)continue; username[i] = 0; sb = (unsigned char *)strchr((char *)username, ':'); if(sb){ *sb = 0; if(param->password)myfree(param->password); param->password = (unsigned char *)mystrdup((char *)sb+1); param->pwtype = 0; } if(param->username)myfree(param->username); param->username = (unsigned char *)mystrdup((char *)username); continue; } #ifndef NOCRYPT if(param->srv->usentlm && !strncasecmp((char *)sb, "ntlm", 4)){ sb+=4; while(isspace(*sb))sb++; i = de64(sb, username, 1023); if(i<=16)continue; username[i] = 0; if(strncasecmp((char *)username, "NTLMSSP", 8)) continue; if(username[8] == 1) { while( (i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){ if(i> 15 && (!strncasecmp((char *)(buf), "content-length", 14))){ buf[i]=0; sscanf((char *)buf + 15, "%"PRINTF_INT64_MODIFIER"u", &contentlength64); } } while( contentlength64 > 0 && (i = sockgetlinebuf(param, CLIENT, buf, (BUFSIZE < contentlength64)? BUFSIZE - 1:(int)contentlength64, '\n', conf.timeouts[STRING_S])) > 0){ if ((uint64_t)i > contentlength64) break; contentlength64-=i; } contentlength64 = 0; if(param->password)myfree(param->password); param->password = myalloc(32); param->pwtype = 2; i = (int)strlen(proxy_stringtable[13]); memcpy(buf, proxy_stringtable[13], i); genchallenge(param, (char *)param->password, (char *)buf + i); memcpy(buf + strlen((char *)buf), "\r\n\r\n", 5); socksend(param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]); ckeepalive = keepalive = 1; goto REQUESTEND; } if(username[8] == 3 && param->pwtype == 2 && i>=80) { unsigned offset, len; len = username[20] + (((unsigned)username[21]) << 8); offset = username[24] + (((unsigned)username[25]) << 8); if(len != 24 || len + offset > (unsigned)i) continue; memcpy(param->password + 8, username + offset, 24); len = username[36] + (((unsigned)username[37]) << 8); offset = username[40] + (((unsigned)username[41]) << 8); if(len> 255 || len + offset > (unsigned)i) continue; if(param->username) myfree(param->username); unicode2text((char *)username+offset, (char *)username+offset, (len>>1)); param->username = (unsigned char *)mystrdup((char *)username+offset); } continue; } #endif }