/* 3APA3A simplest proxy server (c) 2002-2026 by Vladimir Dubrovin please read License Agreement */ #include "proxy.h" #ifdef WITH_POP3P #define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #ifdef WITHMAIN #define NOSTARTTLS 1 #else #define NOSTARTTLS param->srv->nostarttls #endif void * pop3pchild(struct clientparam* param) { int i=0, res; unsigned char buf[320]; unsigned char *se; if(socksend(param, param->clisock, (unsigned char *)"+OK 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, "USER", 4)){ if(!strncasecmp((char *)buf, "QUIT", 4)){ socksend(param, param->clisock, (unsigned char *)"+OK\r\n", 5,conf.timeouts[STRING_S]); RETURN(0); } if(!strncasecmp((char *)buf, "CAPA", 4) && !NOSTARTTLS){ socksend(param, param->clisock, (unsigned char *)"+OK Capability list follows\r\nSTLS\r\n.\r\n", 38, conf.timeouts[STRING_S]); i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]); continue; } #ifndef WITHMAIN if(!strncasecmp((char *)buf, "STLS", 4) && !param->srv->nostarttls){ if(socksend(param, param->clisock, (unsigned char *)"+OK Begin TLS negotiation\r\n", 27, conf.timeouts[STRING_S])!=27) {RETURN(623);} param->clientstarttls = S_POP3P; if(!param->srv->targetport) param->srv->targetport = htons(110); return (void *)tlsprchild; } #endif socksend(param, param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]); i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]); } if(i<6) {RETURN(612);} buf[i] = 0; if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0; if (strncasecmp((char *)buf, "USER ", 5)){RETURN (614);} if(parseconnusername((char *)buf +5, param, 0, 110)){RETURN(615);} param->operation = CONNECT; res = (*param->srv->authfunc)(param); if(res) {RETURN(res);} i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]); if( i < 3 ) {RETURN(621);} buf[i] = 0; if(strncasecmp((char *)buf, "+OK", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(622);} if( socksend(param, param->remsock, (unsigned char *)"USER ", 5, conf.timeouts[STRING_S])!= 5 || socksend(param, param->remsock, param->extusername, (int)strlen((char *)param->extusername), conf.timeouts[STRING_S]) <= 0 || socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2) {RETURN(623);} param->statscli64 += (uint64_t)(strlen((char *)param->extusername) + 7); param->nwrites++; RETURN (mapsocket(param, 180)); CLEANRET: if(param->hostname&¶m->extusername) { sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==110)?0:':', ntohs(*SAPORT(¶m->sinsr))); dolog(param, buf); } else dolog(param, NULL); if(param->clisock != INVALID_SOCKET) { if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param, param->clisock, (unsigned char *)"-ERR\r\n", 6,conf.timeouts[STRING_S]); } return (NULL); } #ifdef WITHMAIN struct proxydef childdef = { pop3pchild, 110, 0, S_POP3P, " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n" }; #include "proxymain.c" #endif #else /* Built without this proxy of its own. The command and the redirect naming it are the STARTTLS proxy speaking that protocol, which negotiates the same way and passes the session on: what "tlspr -Xpop3" does, under the name a configuration already uses. */ void * pop3pchild(struct clientparam * param){ param->starttls = S_POP3P; return (void *)tlsprchild; } #endif