#include "stdafx.h"
#include "SmtpProxyMT.h"
CSmtpProxyMT::CSmtpProxyMT()
{
AcceptFlag=false;
}
CSmtpProxyMT::~CSmtpProxyMT()
{
}
int CSmtpProxyMT::StartProxy(char *server, int port, int localport)
{
if(AcceptFlag)
return ERR_RUNNING;
strcpy(m_SSmtp.SmtpServer,server);
m_SSmtp.SmtpPort=port;
m_SSmtp.LocalPort=localport;
AcceptFlag=true;
StartProxyThread(this);
return 0;
}
void CSmtpProxyMT::StartProxyThread(CSmtpProxyMT* m_pCSmtpProxyMT)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;
_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpProxyThread,
(void*)m_pCSmtpProxyMT,0,(unsigned int*)&threadid);
}
DWORD CSmtpProxyMT::SmtpProxyThread(DWORD arg)
{
CSmtpProxyMT* m_pCSmtpProxyMT=static_cast<CSmtpProxyMT*>((void*)arg);
return m_pCSmtpProxyMT->SmtpProxyThreadMain();
}
DWORD CSmtpProxyMT::SmtpProxyThreadMain()
{
WSADATA wsaData;
sockaddr_in local;
int wsaret=WSAStartup(0x101,&wsaData);
if(wsaret!=0)
{
return ERR_WSAFAIL;
}
local.sin_family=AF_INET;
local.sin_addr.s_addr=INADDR_ANY;
local.sin_port=htons((u_short)this->m_SSmtp.LocalPort);
SmtpServerSocket=socket(AF_INET,SOCK_STREAM,0);
if(SmtpServerSocket==INVALID_SOCKET)
{
return ERR_INVALIDSOCKET;
}
if(bind(SmtpServerSocket,(sockaddr*)&local,sizeof(local))!=0)
{
return ERR_BIND;
}
if(listen(SmtpServerSocket,10)!=0)
{
return ERR_LISTEN;
}
SOCKET SmtpClientSocket;
sockaddr_in from;
int fromlen=sizeof(from);
while(AcceptFlag)
{
char temp[250];
SmtpClientSocket=accept(SmtpServerSocket,
(struct sockaddr*)&from,&fromlen);
if(!AcceptFlag)
break;
sprintf(temp,"%s",inet_ntoa(from.sin_addr));
this->m_SSmtp.LocalSocket=SmtpClientSocket;
this->m_SSmtp.pCSmtpProxyMT=this;
SSmtp *pSSmtp = new SSmtp;
m_SSmtp.CopyStruct(pSSmtp);
StartClientThread(pSSmtp);
}
closesocket(SmtpServerSocket);
WSACleanup();
return 0;
}
void CSmtpProxyMT::SSmtp::CopyStruct(SSmtp *pSSmtp)
{
strcpy(pSSmtp->ClientIP,ClientIP);
pSSmtp->LocalPort=LocalPort;
pSSmtp->LocalSocket=LocalSocket;
pSSmtp->SmtpPort=SmtpPort;
strcpy(pSSmtp->SmtpServer,SmtpServer);
pSSmtp->pCSmtpProxyMT=pCSmtpProxyMT;
}
void CSmtpProxyMT::StartClientThread(SSmtp *pSSmtp)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;
_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpClientThread,
(void*)pSSmtp,0,(unsigned int*)&threadid);
}
DWORD CSmtpProxyMT::SmtpClientThread(DWORD arg)
{
SSmtp* pSSmtp=static_cast<SSmtp*>((void*)arg);
SOCKET conn;
struct hostent *hp;
unsigned int addr;
struct sockaddr_in smtp_server;
conn=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(inet_addr((char far*)pSSmtp->SmtpServer)==INADDR_NONE)
{
hp=gethostbyname(pSSmtp->SmtpServer);
}
else
{
addr=inet_addr(pSSmtp->SmtpServer);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
closesocket(pSSmtp->LocalSocket);
delete pSSmtp;
return ERR_HOST;
}
smtp_server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
smtp_server.sin_family=AF_INET;
smtp_server.sin_port=htons(pSSmtp->SmtpPort);
if(connect(conn,(struct sockaddr*)&smtp_server,sizeof(smtp_server)))
{
closesocket(conn);
closesocket(pSSmtp->LocalSocket);
delete pSSmtp;
return ERR_CONNECT;
}
socket_pair *fromClient=new socket_pair;
socket_pair *fromServer=new socket_pair;
fromClient->src=fromServer->dest=pSSmtp->LocalSocket;
fromClient->dest=fromServer->src=conn;
fromClient->IsClient=true;
fromServer->IsClient=false;
fromServer->pCSmtpProxyMT=fromClient->pCSmtpProxyMT=pSSmtp->pCSmtpProxyMT;
StartDataThread(fromClient);
StartDataThread(fromServer);
delete pSSmtp;
return 0;
}
void CSmtpProxyMT::StartDataThread(socket_pair *pspair)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;
_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpDataThread,
(void*)pspair,0,(unsigned int*)&threadid);
}
DWORD CSmtpProxyMT::SmtpDataThread(DWORD arg)
{
socket_pair* pspair=static_cast<socket_pair*>((void*)arg);
char *buff=new char[10240+5120];
int n;
int data_stage=0;
BOOL ExistsBoundary=false;
char *boundary=new char[512];
BOOL alternate=false;
BOOL mixed=false;
while((n=recv(pspair->src,buff,10240,0))>0)
{
if(pspair->IsClient)
{
buff[n]=0;
if(data_stage==3)
{
char *tmpbuff=new char[10240+5120];
strcpy(tmpbuff,buff);
if(strstr(MakeUpper(tmpbuff),"MAIL FROM:")!=NULL)
{
data_stage=0;
ExistsBoundary=false;
alternate=false;
mixed=false;
}
delete tmpbuff;
}
if(data_stage==0)
if(IsDataCommand(buff))
data_stage=1;
if(data_stage==1)
{
if(!alternate)
{
if(strstr(buff,"Content-Type: multipart/alternative")!=NULL)
alternate=true;
}
if(!mixed)
{
if(strstr(buff,"Content-Type: multipart/mixed")!=NULL)
mixed=true;
}
if(!ExistsBoundary)
ExistsBoundary=FoundBoundary(boundary,buff);
if(ExistsBoundary)
{
if(alternate && !mixed)
{
char boundary1[512+64];
strcpy(boundary1,"\r\n--");
strcat(boundary1,boundary);
int i1=strlen(buff);
AddToEnd(buff, boundary1,pspair->pCSmtpProxyMT->ProxySignature);
n+=(strlen(buff)-i1);
}
else
{
char boundary1[512+64];
strcpy(boundary1,"\r\n--");
strcat(boundary1,boundary);
strcat(boundary1,"--\r\n");
char *p1;
char *p2;
char *buff2=new char[10240+5120];
char *buff3=new char[10240+5120];
strcpy(buff2,buff);
strcpy(buff3,buff);
if((p1=strstr(buff2,boundary1))!=NULL)
{
char sig[2048+512+512+128];
strcpy(sig,"\r\n--");
strcat(sig,boundary);
strcat(sig,"\r\n");
strcat(sig,"Content-Type: text/plain;\r\n\r\n");
strcat(sig,pspair->pCSmtpProxyMT->ProxySignature);
strcat(sig,"\r\n--");
strcat(sig,boundary);
strcat(sig,"\r\n\r\n");
p2=strstr(buff3,boundary1);
*p1=0;
strcat(buff2,sig);
strcat(buff2,p2);
n+=(strlen(buff2)-strlen(buff));
strcpy(buff,buff2);
}
delete buff2;
delete buff3;
}
}
if(IsEndOfData(buff))
data_stage=2;
}
if(data_stage==2)
{
if(!ExistsBoundary)
{
n+=InsertTextSignature(buff,pspair->pCSmtpProxyMT->ProxySignature);
}
data_stage=3;
}
}
send(pspair->dest,buff,n,0);
}
shutdown(pspair->src,SD_BOTH);
closesocket(pspair->src);
shutdown(pspair->dest,SD_BOTH);
closesocket(pspair->dest);
delete boundary;
delete buff;
delete pspair;
return 0;
}
BOOL CSmtpProxyMT::IsDataCommand(char *str)
{
char *str1=new char[10240+5120];
BOOL rv;
strcpy(str1,str);
if(strcmp(MakeUpper(str1),"DATA\r\n")==0)
rv= true;
else
rv= false;
delete str1;
return rv;
}
char* CSmtpProxyMT::MakeUpper(char* str)
{
char* tmp=str;
while(*tmp)
{
if(islower(*tmp))
*tmp=_toupper(*tmp);
tmp++;
}
return str;
}
BOOL CSmtpProxyMT::IsEndOfData(char *str)
{
if(strstr(str,"\r\n.\r\n")!=NULL)
return true;
else
return false;
}
BOOL CSmtpProxyMT::FoundBoundary(char *boundary, char *buff)
{
char *buff1=new char[10240+5120];
strcpy(buff1,buff);
char *tmp=strstr(buff1,"boundary=\"");
if(tmp==NULL)
{
delete buff1;
return false;
}
tmp+=10;
char *tmp1=strstr(tmp,"\"\r\n");
if(tmp1==NULL)
{
delete buff1;
return false;
}
*tmp1=0;
strcpy(boundary,tmp);
delete buff1;
return true;
}
int CSmtpProxyMT::InsertTextSignature(char *buff, char* sig)
{
char *tmp=strstr(buff,"\r\n.\r\n");
*tmp=0;
strcat(buff,sig);
strcat(buff,"\r\n.\r\n");
return strlen(sig);
}
BOOL CSmtpProxyMT::SetSignature(char *sig)
{
if(strlen(sig)>2047)
return false;
strcpy(ProxySignature,sig);
return true;
}
void CSmtpProxyMT::AddToEnd(char *buff, char *b, char* sig)
{
char *newbuff1=new char[10240+5120];
char *newbuff2=new char[10240+5120];
strcpy(newbuff1,buff);
char *p1;
int skip=1;
for(int i=0;i<=1;i++)
{
p1=newbuff1;
for(int j=0;j<skip;j++)
{
p1=strstr(p1,b);
if(p1==NULL)
{
delete newbuff1;
delete newbuff2;
return;
}
p1++;
}
p1=strstr(p1,b);
if(p1==NULL)
{
delete newbuff1;
delete newbuff2;
return;
}
strcpy(newbuff2,p1);
*p1=0;
strcat(newbuff1,sig);
strcat(newbuff1,newbuff2);
skip++;
}
strcpy(buff,newbuff1);
delete newbuff1;
delete newbuff2;
}
int CSmtpProxyMT::StopProxy()
{
if(!AcceptFlag)
return ERR_STOPPED;
AcceptFlag=false;
closesocket(SmtpServerSocket);
return OK_SUCCESS;
}