| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- /*
- 3APA3A simpliest proxy server
- (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
- please read License Agreement
- */
- #include "proxy.h"
- #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
- char ehlo[] = "250-Proxy\r\n"
- "250-AUTH PLAIN LOGIN\r\n"
- "250-8BITMIME\r\n"
- "250 DSN\r\n";
- int readreply (struct clientparam* param) {
- unsigned char * buf;
- int res, i, bufsize = 640;
- if(!(buf = myalloc(bufsize))) return 0;
- do {
- i = sockgetlinebuf(param, SERVER, buf, bufsize-1, '\n', conf.timeouts[STRING_L]);
- if(i < 1) break;
- #ifndef WITHMAIN
- res = handlehdrfilterssrv(param, &buf, &bufsize, 0, &i);
- if(res != PASS) {
- myfree(buf);
- return -1;
- }
- #endif
- socksend(param->clisock, buf, i, conf.timeouts[STRING_S]);
- } while (i > 3 && buf[3] == '-');
- if(i < 3) {
- myfree(buf);
- return 0;
- }
- buf[i] = 0;
- res = atoi((char *)buf);
- myfree(buf);
- return res;
- }
- int readcommand (struct clientparam* param) {
- unsigned char * buf;
- int res, i, bufsize = 320;
- int ret = 1;
- if(!(buf = myalloc(bufsize))) return 0;
- i = sockgetlinebuf(param, CLIENT, buf, bufsize-1, '\n', conf.timeouts[STRING_L]);
- if(i < 4) return 0;
- #ifndef WITHMAIN
- if(!strncasecmp((char *)buf, "MAIL", 4) || !strncasecmp((char *)buf, "RCPT", 4) || !strncasecmp((char *)buf, "STARTTLS", 8) || !strncasecmp((char *)buf, "TURN", 4)){
- res = handlehdrfilterscli(param, &buf, &bufsize, 0, &i);
- if(res != PASS) {
- myfree(buf);
- if(res == HANDLED) return 2;
- return -1;
- }
- }
- #endif
- socksend(param->remsock, buf, i, conf.timeouts[STRING_S]);
- myfree(buf);
- if(!strncasecmp((char *)buf, "STARTTLS", 8) || !strncasecmp((char *)buf, "TURN", 4)){
- ret = 22;
- }
- return ret;
- }
- int readdata (struct clientparam* param) {
- unsigned char * buf;
- int res, i, bufsize = 4096;
- if(!(buf = myalloc(bufsize))) return 0;
- while ((i = sockgetlinebuf(param, CLIENT, buf, bufsize-1, '\n', conf.timeouts[STRING_L])) > 0 && !(i==3 && buf[0] == '.')){
- #ifndef WITHMAIN
- res = handledatfltcli(param, &buf, &bufsize, 0, &i);
- if(res != PASS) {
- myfree(buf);
- if(res == HANDLED) return 1;
- return -1;
- }
- #endif
- socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, buf, i, conf.timeouts[STRING_S]);
- }
- if(i < 1) {
- myfree(buf);
- return 0;
- }
- socksend(param->remsock, buf, i, conf.timeouts[STRING_S]);
- myfree(buf);
- return 1;
- }
- void * smtppchild(struct clientparam* param) {
- int i=0, res;
- unsigned char buf[320];
- unsigned char username[256];
- char * command = NULL;
- int login = 0;
- if(socksend(param->clisock, (unsigned char *)"220 Proxy\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (611);}
- i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
- while(i > 4 && (strncasecmp((char *)buf, "AUTH PLAIN", 10) || !(login = 2)) && (strncasecmp((char *)buf, "AUTH LOGIN", 10) || !(login = 1))){
- if(!strncasecmp((char *)buf, "QUIT", 4)){
- socksend(param->clisock, (unsigned char *)"221 Proxy\r\n", 11,conf.timeouts[STRING_S]);
- RETURN(0);
- }
- else if(!strncasecmp((char *)buf, "HELO ", 5)){
- socksend(param->clisock, (unsigned char *)"250 Proxy\r\n", 11,conf.timeouts[STRING_S]);
- }
- else if(!strncasecmp((char *)buf, "EHLO ", 5)){
- socksend(param->clisock, (unsigned char *)ehlo, sizeof(ehlo) - 1,conf.timeouts[STRING_S]);
- }
- else if(!param->hostname) socksend(param->clisock, (unsigned char *)"571 need AUTH first\r\n", 22, conf.timeouts[STRING_S]);
- else {
- login = -1;
- buf[i] = 0;
- command = mystrdup((char *)buf);
- break;
- }
- i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
- }
- if(!login) {RETURN(662);}
- if(login == 1){
- socksend(param->clisock, (unsigned char *)"334 VXNlcm5hbWU6\r\n", 18,conf.timeouts[STRING_S]);
- i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
- if(i < 3) {RETURN(663);}
- buf[i-2] = 0;
- i = de64(buf,username,255);
- if(i < 1) {RETURN(664);}
- username[i] = 0;
- parseconnusername((char *)username, param, 0, 25);
- socksend(param->clisock, (unsigned char *)"334 UGFzc3dvcmQ6\r\n", 18,conf.timeouts[STRING_S]);
- i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
- if(i < 2) {RETURN(665);}
- buf[i-2] = 0;
- i = de64(buf,username,255);
- if(i < 0) {RETURN(666);}
- username[i] = 0;
- if(param->extpassword) myfree(param->extpassword);
- param->extpassword = (unsigned char *)mystrdup((char *)username);
- }
- else if(login == 2){
- if(i > 13) {
- buf[i-2] = 0;
- i = de64(buf+11,username,255);
- }
- else {
- socksend(param->clisock, (unsigned char *)"334\r\n", 5,conf.timeouts[STRING_S]);
- i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
- if(i < 3) {RETURN(667);}
- buf[i-2] = 0;
- i = de64(buf,username,255);
- }
- if(i < 3 || *username) {RETURN(668);}
- username[i] = 0;
- parseconnusername((char *)username+1, param, 0, 25);
- res = (int)strlen((char *)username+1) + 2;
- if(res < i){
- if(param->extpassword) myfree(param->extpassword);
- param->extpassword = (unsigned char *)mystrdup((char *)username + res);
- }
- }
- #ifndef WITHMAIN
- {
- int action, reqbufsize, reqsize;
- reqbufsize = reqsize = (int)strlen((char *)param->hostname) + 1;
- action = handlereqfilters(param, ¶m->hostname, &reqbufsize, 0, &reqsize);
- if(action == HANDLED){
- RETURN(0);
- }
- if(action != PASS) RETURN(617);
- }
- #endif
- param->operation = CONNECT;
- res = (*param->srv->authfunc)(param);
- if(res) {RETURN(res);}
- do {
- i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
- } while (i > 3 && buf[3] == '-');
- if( i < 3 ) {RETURN(671);}
- buf[i] = 0;
- if(strncasecmp((char *)buf, "220", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(672);}
- i = sprintf((char *)buf, "EHLO [");
- i += myinet_ntop(*SAFAMILY(¶m->sinsl), SAADDR(¶m->sinsl), (char *)buf+strlen((char *)buf), 64);
- i += sprintf((char *)buf+strlen((char *)buf), "]\r\n");
- if(socksend(param->remsock, buf, i, conf.timeouts[STRING_S])!= i) {RETURN(673);}
- param->statscli64+=i;
- param->nwrites++;
- login = 0;
- do {
- i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
- if(i < 1) break;
- buf[i] = 0;
- if(strstr((char *)buf, "LOGIN")) login |= 1;
- if(strstr((char *)buf, "PLAIN")) login |= 2;
- } while (i > 3 && buf[3] == '-');
- if(i<3) {RETURN(672);}
- if(!command || (param->extusername && param->extpassword)){
- if(!param->extusername || !*param->extusername || !param->extpassword || !*param->extpassword || !login){
- socksend(param->clisock, (unsigned char *)"235 auth required\r\n", 19,conf.timeouts[STRING_S]);
- }
- if ((login & 1)) {
- socksend(param->remsock, (unsigned char *)"AUTH LOGIN\r\n", 12, conf.timeouts[STRING_S]);
- param->statscli64+=12;
- param->nwrites++;
- i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
- if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(680);}
- en64(param->extusername, buf, (int)strlen((char *)param->extusername));
- socksend(param->remsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
- socksend(param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]);
- param->statscli64+=(i+2);
- param->nwrites+=2;
- i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
- if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(681);}
- en64(param->extpassword, buf, (int)strlen((char *)param->extpassword));
- socksend(param->remsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
- socksend(param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]);
- param->statscli64+=(i+2);
- param->nwrites+=2;
- }
- else if((login & 2)){
- socksend(param->remsock, (unsigned char *)"AUTH PLAIN\r\n", 12, conf.timeouts[STRING_S]);
- param->statscli64+=(12);
- param->nwrites++;
- i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
- if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(682);}
- *username = 0;
- i = (int)strlen((char *)param->extusername) + 1;
- memcpy(username+1, param->extusername, i);
- i++;
- res = (int)strlen((char *)param->extpassword);
- memcpy(username + i, param->extpassword, res);
- i+=res;
- en64(username, buf, i);
- i = (int)strlen((char *)buf);
- socksend(param->remsock, buf, i, conf.timeouts[STRING_S]);
- socksend(param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]);
- param->statscli64+=(i+2);
- param->nwrites+=2;
- }
- if(command) {
- i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
- }
- res = 1;
- }
- if(command) {
- res = 1;
- #ifndef WITHMAIN
- if(!strncasecmp(command, "MAIL", 4) || !strncasecmp(command, "RCPT", 4) || !strncasecmp(command, "STARTTLS", 8) || !strncasecmp(command, "TURN", 4)){
- res = (int)strlen(command);
- command[res] = 0;
- res = handlehdrfilterscli(param, (unsigned char **)&command, &res, 0, &res);
- if(res != PASS) {
- if(res == HANDLED) res = 2;
- else RETURN(677);
- }
- else if(!strncasecmp(command, "STARTTLS", 8) || !strncasecmp(command, "TURN", 4))
- res = 22;
- }
- #endif
- i = (int)strlen(command);
- if(res != 2) socksend(param->remsock, (unsigned char *)command, i, conf.timeouts[STRING_S]);
- }
- #ifndef WITHMAIN
- if(param->nhdrfilterscli || param->nhdrfilterssrv || param->ndatfilterscli || param->ndatfilterssrv){
- do {
- if(res == 22) RETURN (mapsocket(param, 180));
- if(res != 2 && (res = readreply(param)) <= 0) break;
- if(res == 221) RETURN(0);
- if(res == 354) res = readdata(param);
- else res = readcommand(param);
- } while(res > 0);
- if(res == 22)
- if(res >= 0) RETURN(0);
- RETURN(676);
- }
- else
- #endif
-
- RETURN (mapsocket(param, 180));
- CLEANRET:
- if(param->hostname&¶m->extusername) {
- sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(¶m->sinsr)==25?0:':',ntohs(*SAPORT(¶m->sinsr)));
- (*param->srv->logfunc)(param, buf);
- }
- else (*param->srv->logfunc)(param, NULL);
- if(param->clisock != INVALID_SOCKET) {
- if ((param->res > 0 && param->res < 100) || (param->res > 661 && param->res <700)) socksend(param->clisock, (unsigned char *)"571 \r\n", 6,conf.timeouts[STRING_S]);
- }
- if(command) myfree(command);
- freeparam(param);
- return (NULL);
- }
- #ifdef WITHMAIN
- struct proxydef childdef = {
- smtppchild,
- 25,
- 0,
- S_SMTPP,
- " -hdefault_host[:port] - use this host and port as default if no host specified\n"
- };
- #include "proxymain.c"
- #endif
|