/*
   3APA3A simpliest proxy server
   (c) 2002-2003 by ZARAZA <3APA3A@security.nnov.ru>

   please read License Agreement

   $Id: pop3p.c,v 1.3 2003/11/21 12:17:16 vlad Exp $
*/

#include "proxy.h"
#ifndef PORT
#define PORT 110
#endif

#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }

#define SERVICE S_POP3P

#define child pop3pchild

void * child(void * data) {
#define param ((struct clientparam*)data)
 int i=0, res;
 unsigned char buf[320];
 unsigned char *sb, *se, *sp, *pusername=NULL, *request=NULL;
 unsigned short port = 0;

 if(send(param->clisock, "+OK Proxy\r\n", 11, 0)!=11) {RETURN (611);}
 i = sockgetline(param->clisock, buf, sizeof(buf) - 1, '\n', timeouts[STRING_S]);
 if(i<10) {RETURN(612);}
 
 buf[i] = 0;
 if (strncasecmp((char *)buf, "USER ", 5)){RETURN (613);}
 if ((sb=(unsigned char *)strchr((char *)buf+5, '@')) == NULL) {RETURN(614);}
 sb += 1;
 while ((se=(unsigned char *)strchr((char *)sb, '@')))sb=se+1;
 if ((se=(unsigned char *)strchr((char *)sb, '\r')) == NULL || sb==se) {RETURN (615);}
 *se = 0;
 if ( (sp = (unsigned char *)strchr((char *)sb, ':')) ) *sp = 0;
 port = 110;
 request = (unsigned char *)strdup((char *)buf + 5);
 *(sb-1) = 0;
 pusername = buf+5;
 if(sp){
	port = atoi((char *)sp+1);
	*sp = ':';
 }
 if(param->hostname)free(param->hostname);
 param->hostname = sb;
 param->sins.sin_port = htons(port);
 param->operation = CONNECT;
 if((sb = strchr(pusername, ':'))){
	*sb = 0;
	if((se = strchr(sb + 1, ':'))){
		*se = 0;
		if(*(sb+1)) param->password = (unsigned char *)strdup(sb+1);
		if(*pusername) param->username = (unsigned char *)strdup(pusername);
		pusername = se+1;
	}
	else {
		if(*(sb+1)) param->username = (unsigned char *)strdup(sb+1);
		pusername = sb+1;
	}
 }
 pusername = (unsigned char *)strdup(pusername);
 res = (*param->authfunc)(param);
 param->hostname = NULL;
 if(res) {RETURN(res);}
 i = sockgetline(param->remsock, buf, sizeof(buf) - 1, '\n', timeouts[STRING_L]);
 param->statssrv+=i;
 if( i < 3 ) {RETURN(621);}
 buf[i] = 0;
 if(strncasecmp((char *)buf, "+OK", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(622);}
 if( send(param->remsock, "USER ", 5, 0)!= 5 || 
	send(param->remsock, pusername, strlen((char *)pusername), 0) <= 0 ||
	send(param->remsock, "\r\n", 2, 0)!=2)
		{RETURN(623);}
 param->statscli += (strlen((char *)pusername) + 7);
 RETURN (sockmap(param, 180));
CLEANRET:

 (*param->logfunc)(param, request);
 if(param->clisock != INVALID_SOCKET) {
	if (param->res > 611 && param->res <700) send(param->clisock, "-ERR\r\n", 6,0);
	shutdown(param->clisock, SHUT_RDWR);
	close(param->clisock);
 }
 if(request)free(request);
 if(pusername)free(pusername);
 freeparam(param);
 return (NULL);
}

#ifdef WITHMAIN
#include "proxymain.c"
#endif
