资料出处:http://my.csdn.net/cclongying1989/code/detail/13010
#include "nids.h" //包含Libnids头文件
#include
#include //使用bzero()
#include "iostream"
#include "fstream"
#include "time.h"
#include "Base64.h" //用来Base64加密解密
using namespace std;
#pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"" ) // 设置入口地址
char ascii_string[10000]; //用于存放ASCII明文邮件内容的全局变量
char serverip[16]; //存放服务器IP
bool sendmail = false; //是否有邮件发送
//读取并分析获取的ASCII字符串内容
char* char_to_ascii(char ch)
{
//初始化
char* string;
ascii_string[0] = 0;
string = ascii_string;
if(isgraph(ch)) //判断该字符是否是除空格之外可打印的字符(ASCII码33-126之间的字符)
*string++ = ch;
else if(ch ==' ') //空格或其它字符
*string++ = ch;
else if(ch == 'n' || ch == 'r') //如果是回车换行
*string++ = ch;
else
*string++ = '.';
*string = 0;
return ascii_string;
}
//分析SMTP协议的回调函数
void smtp_protocol_callback(struct tcp_stream* smtp_connection, void** arg)
{
int i;
char content[65535];
char content_urgent[65535];
char content_temp[65535];
char content_gb[65535];
struct tuple4 ip_and_port = smtp_connection->addr;
//打开文件,准备随时写入,保证在return之前关闭文件
FILE *fp;
fp = fopen("maillog.txt", "a+"); //可读写打开文件
fseek(fp, 0L, 2); //跳到文件结尾
switch(smtp_connection->nids_state)
{
case NIDS_JUST_EST:
if(smtp_connection->addr.dest == 25) //SMTP客户端和SMTP服务器端建立连接
{
strcpy(serverip, inet_ntoa(*((struct in_addr *) &(ip_and_port.daddr)))); //记录邮件服务器的IP
smtp_connection->client.collect++; //SMTP客户端接收数据
smtp_connection->server.collect++; //SMTP服务器接收数据
smtp_connection->server.collect_urg++; //SMTP服务器接收紧急数据
smtp_connection->client.collect_urg++; //SMTP客户端接收紧急数据
fprintf(fp, "操作:t发送邮件.n");
}
fclose(fp);
return;
case NIDS_CLOSE: //SMTP客户端与SMTP服务器连接正常关闭
time_t datetime; //使用time.h中的结构体获取时间
struct tm *dt;
time(&datetime);
dt = localtime(&datetime);
if(sendmail)
{
fprintf(fp, "发送邮件成功!n服务器IP:t%sn", serverip);
sendmail = false;
}
else
{
fprintf(fp, "没有邮件可发送!n服务器IP:t%sn", serverip);
}
fprintf(fp, "操作时间:t%d.%d.%d %d:%d:%dn", (1900 + dt->tm_year), (1 + dt->tm_mon), dt->tm_mday, dt->tm_hour, dt->tm_min, dt->tm_sec);
fprintf(fp, "--------------------------n");
fclose(fp);
return;
case NIDS_RESET: //SMTP客户端与SMTP服务器连接被RST关闭
time_t datetimer; //使用time.h中的结构体获取时间
struct tm *dtr;
time(&datetimer);
dtr = localtime(&datetimer);
fprintf(fp, "发送邮件失败!n服务器IP:t%sn", serverip);
fprintf(fp, "操作时间:t%d.%d.%d %d:%d:%dn", (1900 + dtr->tm_year), (1 + dtr->tm_mon), dtr->tm_mday, dtr->tm_hour, dtr->tm_min, dtr->tm_sec);
fprintf(fp, "--------------------------n");
fclose(fp);
sendmail = false; //被RESET时也要把该变量置为false
return;
case NIDS_DATA: //SMTP接收到新的数据
{
char status_code[4];
struct half_stream* hlf;
if(smtp_connection->server.count_new_urg) //SMTP服务器接收到新的紧急数据
{
fclose(fp);
return;
}
if(smtp_connection->client.count_new_urg) //SMTP客户端接收到新的紧急数据
{
fclose(fp);
return;
}
if(smtp_connection->client.count_new) //SMTP客户端接收到新的数据
{
/* hlf = &smtp_connection->client;
memcpy(content, hlf->data, hlf->count_new);
content[hlf->count_new] = '';
if(strstr(strncpy(status_code, content, 3), "221")) //连接终止
fprintf(fp, "连接终止");
if(strstr(strncpy(status_code, content, 3), "250")) //操作成功
fprintf(fp, "操作成功");
if(strstr(strncpy(status_code, content, 3), "220")) //服务器就绪
fprintf(fp, "服务器就绪");
if(strstr(strncpy(status_code, content, 3), "354")) //开始邮件输入
fprintf(fp, "开始邮件输入");
if(strstr(strncpy(status_code, content, 3), "334")) //服务器响应验证
fprintf(fp, "服务器响应验证");
if(strstr(strncpy(status_code, content, 3), "235")) //认证成功可以发邮件
fprintf(fp, "认证成功可以发送");
for(i = 0; i < hlf->count_new; i++)
{
fprintf(fp, "%s", char_to_ascii(content[i]));
}
fprintf(fp, "n");
*/
fclose(fp);
return;
}
if(smtp_connection->server.count_new) //SMTP服务器接收到新的数据
{
hlf = &smtp_connection->server;
memcpy(content, hlf->data, hlf->count_new);
content[hlf->count_new] = '';
/* if(strstr(content, "EHLO"))
fprintf(fp, "HELLO命令n");
if(strstr(content, "QUIT"))
fprintf(fp, "退出连接n");
if(strstr(content, "DATA"))
fprintf(fp, "开始传输数据n");
if(strstr(content, "AUTH"))
fprintf(fp, "请求认证n");
if(strstr(content, "LOGIN"))
fprintf(fp, "认证机制为LOGINn");
if(strstr(content, "n."))
fprintf(fp, "数据传输结束n");
*/
/* if(strstr(content, "MAIL FROM"))
{
fprintf(fp, "发送方:"); //"MAIL FROM: "占11字符,i从11开始
for(i = 11; i < hlf->count_new; i++)
{
fprintf(fp, "%s", char_to_ascii(content[i]));
}
}
if(strstr(content, "RCPT TO"))
{
fprintf(fp, "接收方:"); //"RCPT TO: "占9字符,i从9开始
for(i = 9; i < hlf->count_new; i++)
{
fprintf(fp, "%s", char_to_ascii(content[i]));
}
}*/
if(strstr(content, "DATA")) //判断是否有可发邮件
{
sendmail = true; //在连接关闭的时候要把该变量置为false
}
//在DATA中提取需要信息
if(hlf->count_new > 0)
{
//提取From
char *pfrom;
pfrom = strstr(content, "From: ");
if(pfrom) //如果找到了From:
{
/*是否是汉字GB2312编码,如果是则分离出=?gb2312?B?到?=之间的字符
*发件人是这样的格式"=?gb2312?B?0cfD9w==?= "
*不仅要提取出汉字,还要把后边的邮件地址输出
*/
strcpy(content_temp, pfrom);
fprintf(fp, "发件人:t");
if(content_temp[6] == 61) //如果"From: "后是"="
{
//strcpy(content_temp, pGB2312);
char gbstring[1000];
i = 17; //只捕获=?gb2312?B?后边的字符
int j = 0; //用来记录循环次数,即截取的字符串长度
while(!(content_temp[i] == 63 && content_temp[i+1] == 61))
{
gbstring[j] = content_temp[i];
i++;
j++;
}
gbstring[j] = '';
unsigned long len;
string InBase = gbstring;
unsigned char OutBase[1000];//存放解密后字符串
if(CBase64::Decode(InBase, OutBase, &len))
{
for(int k=0; k之间的地址,ASSCII码"<"为60,">"为62
j = i;
j+= 2; //跳到"<"位置
while(!(content_temp[j-1] == 62))
{
fprintf(fp, "%s", char_to_ascii(content_temp[j]));
j++;
}
}
else
{
//strcpy(content_temp, pfrom);
i = 6; //"From: "后边开始输出
while(!(content_temp[i-1]==62 && content_temp[i]==13 && content_temp[i+1]==10))
{
fprintf(fp, "%s", char_to_ascii(content_temp[i]));
i++;
}
}//end if pGB2312
fprintf(fp, "n");
}//end if pfrom
pfrom=NULL;
free(pfrom); //释放指针
//提取To
char *pto;
pto = strstr(content, "To: ");
if(pto)
{
strcpy(content_temp, pto);
fprintf(fp, "收件人:t");
if(content_temp[4] == 61) //如果"To: "后是"="
{
char gbstring[1000];
i = 15; //只捕获=?gb2312?B?后边的字符
int j = 0; //用来记录循环次数,即截取的字符串长度
while(!(content_temp[i] == 63 && content_temp[i+1] == 61))
{
gbstring[j] = content_temp[i];
i++;
j++;
}
gbstring[j] = '';
unsigned long len;
string InBase = gbstring;
unsigned char OutBase[1000];//存放解密后字符串
if(CBase64::Decode(InBase, OutBase, &len))
{
for(int k=0; k之间的地址,ASSCII码"<"为60,">"为62,","为44
j = i;
j+= 2; //跳到"<"位置
//while(!(content_temp[j-1] == 62))
while(!(content_temp[j-1]==62 && content_temp[j]==13 && content_temp[j+1]==10))
{
fprintf(fp, "%s", char_to_ascii(content_temp[j]));
j++;
}
}
else
{
i = 4; //"To: "后边开始输出
while(!(content_temp[i-1]==62 && content_temp[i]==13 && content_temp[i+1]==10))
{
fprintf(fp, "%s", char_to_ascii(content_temp[i]));
i++;
}
}//end if pGB2312
fprintf(fp, "n");
}//end if pto
pto=NULL;
free(pto);
//提取Cc
char *pCc;
pCc = strstr(content, "Cc: ");
if(pCc)
{
strcpy(content_temp, pCc);
fprintf(fp, "抄送人:t");
if(content_temp[4] == 61) //如果"Cc: "后是"="
{
char gbstring[1000];
i = 15; //只捕获=?gb2312?B?后边的字符
int j = 0; //用来记录循环次数,即截取的字符串长度
while(!(content_temp[i] == 63 && content_temp[i+1] == 61))
{
gbstring[j] = content_temp[i];
i++;
j++;
}
gbstring[j] = '';
unsigned long len;
string InBase = gbstring;
unsigned char OutBase[1000];//存放解密后字符串
if(CBase64::Decode(InBase, OutBase, &len))
{
for(int k=0; k之间的地址,ASSCII码"<"为60,">"为62
j = i;
j+= 2; //跳到"<"位置
while(!(content_temp[j-1]==62 && content_temp[j]==13 && content_temp[j+1]==10))
{
fprintf(fp, "%s", char_to_ascii(content_temp[j]));
j++;
}
}
else
{
i = 4; //"Cc: "后边开始输出
while(!(content_temp[i-1]==62 && content_temp[i]==13 && content_temp[i+1]==10))
{
fprintf(fp, "%s", char_to_ascii(content_temp[i]));
i++;
}
}//end if pGB2312
fprintf(fp, "n");
}//end if pCc
pCc=NULL;
free(pCc);
//提取Subject
char *psub;
psub = strstr(content, "Subject: ");
if(psub)
{
strcpy(content_temp, psub);
//是否是汉字GB2312编码,如果是则分离出=?gb2312?B?到?=之间的字符
fprintf(fp, "主题:t");
if(content_temp[9] == 61) //如果"Subject: "后是"="
{
char gbstring[1000];
i = 20; //只捕获=?gb2312?B?后边的字符
int j = 0; //用来记录循环次数,即截取的字符串长度
while(!(content_temp[i] == 63 && content_temp[i+1] == 61))
{
gbstring[j] = content_temp[i];
i++;
j++;
}
gbstring[j] = '';
unsigned long len;
string InBase = gbstring;
unsigned char OutBase[1000];//存放解密后字符串
if(CBase64::Decode(InBase, OutBase, &len))
{
for(int k=0; k