/* FILE $Id: mainfunc.h 6 2005-11-24 00:02:59Z ggw $ PURPOSE AUTHOR (C) 2001-2004 Gary Wallis. GPL License applies. See LICENSE in distribution. TODO 4269261797 */ #define ACCESS_SOURCE_WEBCONSOLE 1 #define ACCESS_SOURCE_POPPER 2 #define ACCESS_SOURCE_RADIUSD 3 #define ACCESS_SOURCE_NUKESPAM_MISSES 4 #define ACCESS_SOURCE_NUKESPAM_NSENT 5 #define ACCESS_SOURCE_NUKESPAM_RESERVED 6 #define ACCESS_SOURCE_DUL 7 #ifdef NUKESPAM //NukeSpam vars static unsigned uLogTime=0; static char cQID[16]={""}; static char cRcpt[100]={""}; static unsigned uType=0; static unsigned uRejectsType=0; static unsigned uCount=0; static char cSender[100]={""}; static unsigned uNrcpts=0; static unsigned uSize=0; static char cRelayIP[16]={""}; static unsigned uExpireTime=0; static unsigned uFirstTime=0; static unsigned uLastTime=0; static unsigned uFirstCount=0; static unsigned uLastCount=0; static char cRejectTag[100]={""}; //NukeSpam work in progress void NukeSpamLoad(void); void strmyncpy(char *target, char *source, int n); int GetuLogTime(char *cYear, char *query); int GetcQID(char *query); int GetcRelayIP(char *query); int LoadLogFile(FILE *fp); int GetLastuLogTime(unsigned *uLastLogTime); int InsertUpdateMarker(void); int InsertInTotMailLog(void); int RemoveExpiredRows(unsigned uLastTime); void CreatetMailLog(void); time_t TimeToUnixTime(char *cTime); time_t DateToUnixTime(char *cDate); int Process(void); int ExtractSenderInfoAndUpdate(char *cQID,int count); int InsertUpdate_tScoreBoard(void); void Update_tScoreBoard(char *rowid); void Insert_tScoreBoard(void); int tAccessBlock(char *cSender); int Block(void); int InsertUpdate_tRejects(char *cKey); void Update_tRejects(char *cRejectTag); void Insert_tRejects(void); int CreatetRejects(void); void NukeSpamStats(void); #endif static char cTableList[32][32]={"tUser","tDomain","tVUT","tVUTEntries","tDUL","tAccess","tLocal","tAlias","tServer","tUsage","tConfiguration","tJob","tJobStatus","tStatus","tHDQuota","tTrafficQuota","tMailFilter","tClient","tAuthorize",""}; char cInitTableList[32][32]={"tJobStatus","tStatus","tServer","tHDQuota","tTrafficQuota","tMailFilter","tConfiguration",""}; void ExtMainShell(int argc, char *argv[]); void Initialize(char *cPasswd); void Backup(char *cPasswd); void Restore(char *cPasswd, char *cTableName); void RestoreAll(char *cPasswd); void mySQLRootConnect(char *cPasswd); #ifdef RADIUSIMPORT void mysqlRadiusConnect(char *cServer,char *cLogin,char *cPasswd); #endif //Extern mail.c int ProcessJobQueue(unsigned uDebug, char *cServer); int ProcessESMTPJobQueue(unsigned uDebug, char *cServer); void ProcessExtJobQueue(char *cServer); #ifdef RADIUSIMPORT void mysqlRadiusImport(); #endif void CleanLocalAccess(void);//mail.c void CleanDoneOkJobQueue(void);//mail.c void FixLocalUIDs(unsigned uMode);//mail.c void UpgradeSchema(char *cPasswd); void GetConfiguration(const char *cName, char *cValue, unsigned uHtml); void TextConnectDb(void); void MigrateUsers(unsigned uDryRun, unsigned uHelp); MYSQL mysql2; int ExtMainCommands(pentry entries[], int x) { if(!strcmp(function,"MainTools")) { //ProjectFunctionProcess() } return(0); } void ExtMainContent(void) { printf("
"); printf(""); printf(""); printf(""); }//void ExtMainContent(void) void ExtMainShell(int argc, char *argv[]) { if(argc==3 && !strcmp(argv[1],"Initialize")) Initialize(argv[2]); #ifdef NUKESPAM else if(argc==2 && !strcmp(argv[1],"NukeSpamLoad")) NukeSpamLoad(); #endif else if(argc==3 && !strcmp(argv[1],"ProcessJobQueue")) ProcessJobQueue(0,argv[2]); else if(argc==3 && !strcmp(argv[1],"ProcessESMTPJobQueue")) ProcessESMTPJobQueue(0,argv[2]); else if(argc==3 && !strcmp(argv[1],"JobQueue")) ProcessJobQueue(0,argv[2]); else if(argc==3 && !strcmp(argv[1],"ProcessExtJobQueue")) { TextConnectDb(); ProcessExtJobQueue(argv[2]); mysql_close(&mysql); exit(0); } else if(argc==3 && !strcmp(argv[1],"JobQueueDebug")) ProcessJobQueue(1,argv[2]); else if(argc==3 && !strcmp(argv[1],"ESMTPJobQueueDebug")) ProcessESMTPJobQueue(1,argv[2]); else if(argc==3 && !strcmp(argv[1],"RestoreAll")) RestoreAll(argv[2]); else if(argc==2 && !strcmp(argv[1],"CleanLocalAccess")) CleanLocalAccess(); else if(argc==2 && !strcmp(argv[1],"CleanDoneOkJobQueue")) CleanDoneOkJobQueue(); else if(argc==2 && !strcmp(argv[1],"FixLocalUIDs")) FixLocalUIDs(0); else if(argc==2 && !strcmp(argv[1],"UpgradeSchema")) UpgradeSchema(""); else if(argc==3 && !strcmp(argv[1],"UpgradeSchema")) UpgradeSchema(argv[2]); else if(argc==2 && !strcmp(argv[1],"MigrateUsersHelp")) MigrateUsers(0,1); else if(argc==2 && !strcmp(argv[1],"MigrateUsersDryRun")) MigrateUsers(1,0); else if(argc==2 && !strcmp(argv[1],"MigrateUsers")) MigrateUsers(0,0); #ifdef NUKESPAM else if(argc==2 && !strcmp(argv[1],"NukeSpamStats")) NukeSpamStats(); else if(argc==2 && !strcmp(argv[1],"NukeSpamSetup")) { TextConnectDb(); CreatetMailLog(); CreatetRejects(); mysql_close(&mysql); exit(0); } #endif else if(argc==3 && !strcmp(argv[1],"FixLocalUIDs") && !strcmp(argv[2],"Repair")) FixLocalUIDs(1); else if(argc==3 && !strcmp(argv[1],"FixLocalUIDs") && !strcmp(argv[2],"Report-All")) FixLocalUIDs(2); else if(argc==3 && !strcmp(argv[1],"FixLocalUIDs") && !strcmp(argv[2],"Report-Non-Active")) FixLocalUIDs(3); else if(argc==3 && !strcmp(argv[1],"FixLocalUIDs") && !strcmp(argv[2],"Repair-Non-Active")) FixLocalUIDs(13); else if(argc==3 && !strcmp(argv[1],"Backup")) Backup(argv[2]); else if(argc==4 && !strcmp(argv[1],"Restore")) Restore(argv[2],argv[3]); #ifdef RADIUSIMPORT else if(argc==5 && !strcmp(argv[1],"mysqlRadiusImport")) { mysqlRadiusConnect(argv[2],argv[3],argv[4]); mysqlRadiusImport(); mysql_close(&mysql); exit(0); } #endif else { printf("\n%s Menu %s\n\nDatabase Ops:\n",argv[0],RELEASE); printf("\tInitialize|Backup|RestoreAll \n"); printf("\tRestore \n"); #ifdef RADIUSIMPORT printf("\tmysqlRadiusImport \n"); #endif printf("\nCrontab Ops:\n"); printf("\tProcessJobQueue \n"); printf("\tProcessESMTPJobQueue \n"); printf("\tProcessExtJobQueue \n"); printf("\tCleanLocalAccess\n"); printf("\nSpecial Admin Ops:\n"); printf("\tFixLocalUIDs [Repair|Report-All|Report-Non-Active|Repair-Non-Active]\n"); printf("\tJobQueueDebug \n"); printf("\tESMTPJobQueueDebug \n"); printf("\tCleanDoneOkJobQueue\n"); printf("\tUpgradeSchema []\n"); printf("\tMigrateUsersHelp\n"); printf("\tMigrateUsersDryRun\n"); printf("\tMigrateUsers\n"); #ifdef NUKESPAM printf("\tNukeSpamLoad\n"); printf("\tNukeSpamSetup\n"); printf("\tNukeSpamStats (html output!)\n"); #endif printf("\n"); } mysql_close(&mysql); exit(0); }//void ExtMainShell(int argc, char *argv[]) //ProjectFunctionStubs() void RestoreAll(char *cPasswd) { char cISMROOT[256]={""}; if(getenv("ISMROOT")!=NULL) { strncpy(cISMROOT,getenv("ISMROOT"),255); cHost[255]=0; } if(!cISMROOT[0]) { printf("You must set ISMROOT env var first. Ex. export ISMROOT/home/ism-3.0\n"); exit(1); } printf("Restoring mysqlSendmail data from .txt file in %s/mysqlSendmail/data...\n\n",cISMROOT); //connect as root to master db mySQLRootConnect(cPasswd); sprintf(query,"USE %s",DBNAME); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } for(i=0;cTableList[i][0];i++) { sprintf(query,"load data infile '%s/mysqlSendmail/data/%s.txt' replace into table %s",cISMROOT,cTableList[i],cTableList[i]); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } printf("%s\n",cTableList[i]); } printf("\nDone\n"); }//void RestoreAll(char *cPasswd) void Restore(char *cPasswd, char *cTableName) { char cISMROOT[256]={""}; if(getenv("ISMROOT")!=NULL) { strncpy(cISMROOT,getenv("ISMROOT"),255); cHost[255]=0; } if(!cISMROOT[0]) { printf("You must set ISMROOT env var first. Ex. export ISMROOT=/home/ism-3.0\n"); exit(1); } printf("Restoring mysqlSendmail data from .txt file in %s/mysqlSendmail/data...\n\n",cISMROOT); //connect as root to master db mySQLRootConnect(cPasswd); sprintf(query,"USE %s",DBNAME); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } sprintf(query,"load data infile '%s/mysqlSendmail/data/%s.txt' replace into table %s",cISMROOT,cTableName,cTableName); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } printf("%s\n\nDone\n",cTableName); }//void Restore(char *cPasswd, char *cTableName) void Backup(char *cPasswd) { char cISMROOT[256]={""}; if(getenv("ISMROOT")!=NULL) { strncpy(cISMROOT,getenv("ISMROOT"),255); cHost[255]=0; } if(!cISMROOT[0]) { printf("You must set ISMROOT env var first. Ex. export ISMROOT=/home/ism-3.0\n"); exit(1); } printf("Backing up mysqlSendmail data to .txt files in %s/mysqlSendmail/data...\n\n", cISMROOT); //connect as root to master db mySQLRootConnect(cPasswd); sprintf(query,"USE %s",DBNAME); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } for(i=0;cTableList[i][0];i++) { char cFileName[300]; sprintf(cFileName,"%s/mysqlSendmail/data/%s.txt" ,cISMROOT,cTableList[i]); unlink(cFileName); sprintf(query,"SELECT * INTO OUTFILE '%s' FROM %s",cFileName,cTableList[i]); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } printf("%s\n",cTableList[i]); } printf("\nDone.\n"); }//void Backup(char *cPasswd) void Initialize(char *cPasswd) { char cISMROOT[256]={""}; time_t clock; if(getenv("ISMROOT")!=NULL) { strncpy(cISMROOT,getenv("ISMROOT"),255); cHost[255]=0; } if(!cISMROOT[0]) { printf("You must set ISMROOT env var first. Ex. export ISMROOT=/home/ism-3.0\n"); exit(1); } printf("Creating db and setting permissions, installing data from %s/mysqlSendmail...\n\n",cISMROOT); //connect as root to master db mySQLRootConnect(cPasswd); //Create database sprintf(query,"CREATE DATABASE %s",DBNAME); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } //Grant localaccess privileges. sprintf(query,"GRANT ALL ON %s.* to %s@localhost identified by '%s'", DBNAME,DBLOGIN,DBPASSWD); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } //Change to mysqlbind db. Then initialize some tables with needed data sprintf(query,"USE %s",DBNAME); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } time(&clock); CreatetAuthorize(); //And 3 standard example users sprintf(query,"INSERT INTO tAuthorize SET cLabel='Root',uCertClient=1,cIpMask='0.0.0.0',uPerm=12,uOwner=1,uCreatedBy=1,uCreatedDate=%lu,cPasswd='..M0/uAvCFhis'",(long unsigned)clock); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } sprintf(query,"INSERT INTO tAuthorize SET cLabel='Jane Admin',uCertClient=2,cIpMask='0.0.0.0',uPerm=10,uOwner=2,uCreatedBy=1,uCreatedDate=%lu,cPasswd='..M0/uAvCFhis'",(long unsigned)clock); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } sprintf(query,"INSERT INTO tAuthorize SET cLabel='Joe Reseller',uCertClient=3,cIpMask='0.0.0.0',uPerm=8,uOwner=3,uCreatedBy=1,uCreatedDate=%lu,cPasswd='..M0/uAvCFhis'",(long unsigned)clock); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } CreatetClient(); sprintf(query,"INSERT INTO tClient SET cLabel='Root',uOwner=1,uCreatedBy=1,uCreatedDate=%lu",(long unsigned)clock); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } sprintf(query,"INSERT INTO tClient SET cLabel='Jane Admin',uOwner=1,uCreatedBy=1,uCreatedDate=%lu",(long unsigned)clock); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } sprintf(query,"INSERT INTO tClient SET cLabel='Joe Reseller',uOwner=1,uCreatedBy=1,uCreatedDate=%lu",(long unsigned)clock); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } //Create tables and install default data //CreatetJob(); CreatetUser(); CreatetDomain(); CreatetVUT(); CreatetVUTEntries(); CreatetDUL(); CreatetAccess(); CreatetLocal(); CreatetAlias(); CreatetServer(); CreatetUsage(); CreatetConfiguration(); CreatetJob(); CreatetJobStatus(); CreatetStatus(); CreatetHDQuota(); CreatetTrafficQuota(); CreatetMailFilter(); for(i=0;cInitTableList[i][0];i++) { sprintf(query,"load data infile '%s/mysqlSendmail/data/%s.txt' replace into table %s",cISMROOT,cInitTableList[i],cInitTableList[i]); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } } printf("Done\n"); }//void Initialize(void) void mySQLRootConnect(char *cPasswd) { char cMySQLRootPwd[256]={""}; char *cUseThisPasswd=NULL; if(cPasswd==NULL || !cPasswd[0]) { ConnectDb();//using local.h compiled in info GetConfiguration("cMySQLRootPwd",cMySQLRootPwd,0); mysql_close(&mysql); if(cMySQLRootPwd[0]) cUseThisPasswd=cMySQLRootPwd; } else { if(cPasswd[0]) cUseThisPasswd=cPasswd; } mysql_init(&mysql); if (!mysql_real_connect(&mysql,DBIP,"root",cUseThisPasswd,"mysql",DBPORT,DBSOCKET,0)) { if(mysql_errno(&mysql)) fprintf(stderr,"%s\n",mysql_error(&mysql)); fprintf(stderr,"Database server unavailable\n"); exit(1); } }//void mySQLRootConnect(char *cPasswd) #ifdef RADIUSIMPORT //This is a major hack...TODO void mysqlRadiusConnect(char *cServer,char *cLogin,char *cPasswd) { mysql_init(&mysql2); if(!mysql_real_connect(&mysql2,cServer,cLogin,cPasswd,"mysqlradius",DBPORT,DBSOCKET,0)) { fprintf(stderr,"%s database server unavailable\n",cServer); exit(1); } }//void mysqlRadiusConnect(); #endif #ifdef NUKESPAM void CreatetScoreBoard(void) { sprintf(query,"CREATE TEMPORARY TABLE tScoreBoard ( uRow int unsigned PRIMARY KEY AUTO_INCREMENT, cSender varchar(100) NOT NULL DEFAULT '', cRelayIP char(16) NOT NULL DEFAULT '', uCount int unsigned NOT NULL DEFAULT 0, uFirstTime int unsigned NOT NULL DEFAULT 0, uLastTime int unsigned NOT NULL DEFAULT 0, uExpireTime int unsigned NOT NULL DEFAULT 0, uType int unsigned NOT NULL DEFAULT 0, cQID varchar(16) NOT NULL DEFAULT '', KEY (cQID), KEY (cRelayIP), KEY (uType), KEY (cSender))"); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } }//void CreatetScoreBoard(void) /* void DroptScoreBoard(void) { mysql_query(&mysql,"DROP TABLE tScoreBoard"); }//void DroptScoreBoard(void) */ void NukeSpamLoad(void) { ConnectDb(); if(!LoadLogFile(stdin)) { //If temporary table not needed //DroptScoreBoard(); CreatetScoreBoard(); if(Process()) { fprintf(stderr,"Process() Error\n"); exit(1); } if(Block()) { fprintf(stderr, "Block() Error\n"); exit(1); } exit(0); } else { fprintf(stderr,"Could not load logfile correctly.\n"); exit(1); } }//void NukeSpamLoad(void) int LoadLogFile(FILE *fp) { char *cp=NULL,*cp2=NULL; int error=0; int errors=0; char cYear[8]; unsigned uLastLogTime=0; unsigned uLastTime=0;//Hold last uLogTime for 1000 marker time_t clock; if(!fp) return(1); //Example mail log line //Mar 6 07:50:31 mercury sendmail[19757]: h23JnGQn027273: to=, delay=2+19:45:24, xdelay=00:00:00, mailer=esmtp, pri=22982437, relay=tateandbaker.com. [209.8.161.115], dsn=4.0.0, stat=Deferred: Connection refused by tateandbaker.com. time(&clock); strftime(cYear,5,"%Y",localtime(&clock)); if(GetLastuLogTime(&uLastLogTime)) { //Create a new emtpy one anyway. Do not return unless this //also fails //return(1); uType=1000;//See unsigned GetLastuLogTime(void); uLogTime=0; strcpy(cRcpt,"Last log line marker"); if(InsertUpdateMarker()) { fprintf(stderr,"NukeSpam: InsertUpdateMarker() Error3\n"); return(1); } uLastLogTime=0; } //debug only //printf("GetLastuLogTime() %u\n",uLastLogTime); while(fgets(query,4095,fp)) { //safety first query[4095]=0; if(!strstr(query,"sendmail")) continue; //Very Debug only //printf("\n%s",query); //uType=1; if(strstr(query,"... User unknown")) { //debug only //printf("%s",query); //uLogTime error+=GetuLogTime(cYear,query); //Only add new records if(uLastLogTime>=uLogTime) continue; //cQID error+=GetcQID(query); //cRcpt if((cp=(strchr(query,'<')))) { if((cp2=(strchr(cp+1,'>')))) { *cp2=0; //debug only strmyncpy(cRcpt,cp+1,99); //Debug only //printf("cRcpt=%s\n",cRcpt); *cp2='>'; } } else { error++; fprintf(stderr,"Left angle bracket error: %s",query); } uType=1;//User unknown }//... Unknown user uType=1; //uType=2 Ignores from=root or others sent from command line //or similar else if((cp=strstr(query,": from=<"))) { char *cp3; //uLogTime error+=GetuLogTime(cYear,query); //Only add new records if(uLastLogTime>=uLogTime) continue; //cQID error+=GetcQID(query); //cRelayIP error+=GetcRelayIP(query); //nRcpts if((cp2=(strstr(cp+9,"nrcpts=")))) { if((cp3=(strchr(cp2+7,',')))) { *cp3=0; uNrcpts=0; sscanf(cp2+7,"%u",&uNrcpts); //printf("uNrcpts=%u\n",uNrcpts); *cp3=','; } } else { error++; printf("nrcpts= error: %s",query); } //nSize if((cp2=(strstr(cp+9,"size=")))) { if((cp3=(strchr(cp2+5,',')))) { *cp3=0; uSize=0; sscanf(cp2+5,"%u",&uSize); //printf("uSize=%u\n",uSize); *cp3=','; } } else { printf("size= error: %s",query); error++; } //cSender if((cp2=(strchr(cp+8,'>')))) { *cp2=0; strmyncpy(cSender,cp+8,99); //Debug only //printf("cSender=%s\n",cSender); *cp2='>'; //Handle strange nested cases like //<"Mabinti"> //in tscoreboard.c we nick any other level '<' //and also escape double quotes if((cp2=(strchr(cSender,'<')))) { char temp[100]; strmyncpy(temp,cp2+1,99); strcpy(cSender,temp); //Debug only //printf("cSender=%s\n",cSender); } } else { fprintf(stderr,"Right angle bracket error: %s",query); error++; } uType=2;//From }//uType=2 //Check http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2821 //uType=100 550 rejects //uType=101 553 mail-abuse.org type rejects. Check sendmail.cf file //uType=102 554 Our rejects //uType=103 xxx catch all else if((cp=strstr(query,", reject="))) { register int i; //uLogTime error+=GetuLogTime(cYear,query); //Only add new records if(uLastLogTime>=uLogTime) continue; //cQID //may not have cQID GetcQID(query); //cRelayIP //may not have cRelayIP GetcRelayIP(query); //Get rejection notice text if(strcmp(cQID,"NOQUEUE")) { if((cp2=(strstr(cp+11,"... ")))) { strmyncpy(cSender,cp2+4,99); //cut off \n cSender[strlen(cSender)-1]=0; } } else { //cQID exists strmyncpy(cSender,cp+13,99); //cut off \n if(cSender[(i=strlen(cSender)-1)]=='\n') cSender[i]=0; } //Last ditch case if(!cSender[0]) { strmyncpy(cSender,cp+12,99); //cut off \n if(cSender[(i=strlen(cSender)-1)]=='\n') cSender[i]=0; } //Never seen this but... if(!cSender[0]) strcpy(cSender,"No reject text"); sscanf(cp+9,"%u ",&uRejectsType); if(uRejectsType==550) uType=100; else if(uRejectsType==553) uType=101; else if(uRejectsType==554) uType=102; else if(1) uType=103; if(InsertUpdate_tRejects(cSender)) fprintf(stderr,"LoadLogFile(). InsertUpdate_tRejects() error"); }//uType=100,101,102 and 103 //Type 200: Local mail delivered else if((cp=strstr(query,", mailer=local, stat=Sent"))) { //uLogTime error+=GetuLogTime(cYear,query); //Only add new records if(uLastLogTime>=uLogTime) continue; //cQID error+=GetcQID(query); //cRcpt if((cp=(strchr(query,'<')))) { if((cp2=(strchr(cp+1,'>')))) { *cp2=0; strmyncpy(cRcpt,cp+1,99); *cp2='>'; } } else if((cp=(strstr(query,"to=")))) { if((cp2=(strchr(cp+3,',')))) { *cp2=0; strmyncpy(cRcpt,cp+3,99); *cp2=','; } } else if(1) { fprintf(stderr,"Local mail deliver error: %s",query); error++; } uType=200; } //uType=200 //Type 201: Relayed/Remote mail delivered else if((cp=strstr(query,", relay=")) && (strstr(query,", stat=Sent"))) { //uLogTime error+=GetuLogTime(cYear,query); //Only add new records if(uLastLogTime>=uLogTime) continue; //cQID error+=GetcQID(query); //cRelayIP error+=GetcRelayIP(query); //cRcpt if((cp=(strchr(query,'<')))) { if((cp2=(strchr(cp+1,'>')))) { *cp2=0; strmyncpy(cRcpt,cp+1,99); *cp2='>'; } } else if((cp=(strstr(query,"to=")))) { if((cp2=(strchr(cp+3,',')))) { *cp2=0; strmyncpy(cRcpt,cp+3,99); *cp2=','; } } else if(1) { fprintf(stderr,"Remote mail deliver error: %s",query); error++; } uType=201; }//uType=201 if(!error) { if(uType) { //uMailLog primary key if(InsertInTotMailLog()) { fprintf(stderr,"NukeSpam: InsertInTotMailLog() Error2\n"); return(1); } //Debug only //printf("uLastTime=%u,uLogTime=%u,cQID=%s,cRcpt=%s,uType=%u,cSender=%s,uNrcpts=%u,uSize=%u,cRelayIP=%s\n",uLastTime,uLogTime,cQID,cRcpt,uType,cSender,uNrcpts,uSize,cRelayIP); uLastTime=uLogTime; uLogTime=0; cQID[0]=0; cRcpt[0]=0; uType=0; cSender[0]=0; uNrcpts=0; uSize=0; cRelayIP[0]=0; } } else { //Maybe the error was not about the date. What is this? uLastTime=uLogTime; fprintf(stderr, "NukeSpam: LoadLogFile() error %d\n%s\n" ,error,query); error=0; errors++; } } //Add a last log line record if(uLastTime>0) { uType=1000;//See unsigned GetLastuLogTime(void); uLogTime=uLastTime; strcpy(cRcpt,"Last log line marker"); if(InsertUpdateMarker()) { fprintf(stderr,"NukeSpam: InsertUpdateMarker() Error3\n"); errors++; } } fclose(fp); if(uLastTime>0) { if(RemoveExpiredRows(uLastTime)) { fprintf(stderr,"NukeSpam: RemoveExpiredRows() error\n"); return(1); } } if(errors) return(1); return(0); }//int LoadLogFile(FILE *fp) int GetcRelayIP(char *query) { char *cp,*cp2,*cp3; //cRelayIP if((cp=(strstr(query,"relay=")))) { if((cp2=(strchr(cp+6,'[')))) { if((cp3=(strchr(cp2+1,']')))) { unsigned uPos; *cp3=0; strmyncpy(cRelayIP,cp2+1,15); if(cRelayIP[(uPos=strlen(cRelayIP)-1)]=='\'') cRelayIP[uPos]=0; //Debug only //printf("cRelayIP=%s\n",cRelayIP); *cp3=']'; } else return(1); } else return(1); } else { fprintf(stderr,"GetcRelayIP() error\n"); return(1); } return(0); }//int GetcRelayIP(char *query) int GetcQID(char *query) { char *cp,*cp2; //cQID if((cp=(strstr(query,"]:")))) { if((cp2=(strchr(cp+3,':')))) { *cp2=0; strmyncpy(cQID,cp+3,15); //Debug only //printf("cQID=%s\n",cQID); *cp2=':'; } } else { fprintf(stderr,"GetcQID() error\n"); return(1); } return(0); }//int GetcQID(char *query) int GetuLogTime(char *cYear, char *query) { time_t uTime; char cTime[16]; char cDate[32]; //char cUnixDate[44]; char cMonth[4]; unsigned uDay=0; //Example mail log line start //Mar 6 07:50:31 //uLogTime strmyncpy(cMonth,query,3); query[6]=0; sscanf(query+4,"%u",&uDay); query[6]=' '; strmyncpy(cTime,query+7,8); sprintf(cDate,"%2.2d-%s-%s",uDay,cMonth,cYear); uTime=TimeToUnixTime(cTime); uTime+=DateToUnixTime(cDate); //GMT Adjust how to automate this? //uTime-=(10800);//-3 hours adj. ARG uTime-=(28800);//-8 hours adj. CA //Debug only //printf("ctime:%s cDate:%s cTime:%s \n",ctime((time_t *)&uTime),cDate,cTime); //Set global if(uTime>4269261796) { fprintf(stderr,"GetuLogTime() range error\n"); exit(1); } uLogTime=uTime; return(0); }//int GetuLogTime(char *cYear, char *query) void strmyncpy(char *target, char *source, int n) { register int i; for(i=0;i1) { //Error condition return(2); } return(0); }//int InsertUpdateMarker(void) int InsertInTotMailLog(void) { sprintf(query,"INSERT INTO tMailLog SET uLogTime=%u,cQID='%s',cRcpt='%s',uType=%u,cSender='%s',uNrcpts=%u,uSize=%u,cRelayIP='%s'", uLogTime, cQID, cRcpt, uType, cSender, uNrcpts, uSize, cRelayIP); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); return(1); } return(0); }//int InsertInTotMailLog(void) int RemoveExpiredRows(unsigned uLastTime) { if(uLastTime>3600) uLastTime-= 3600;//1Hr sprintf(query,"DELETE FROM tMailLog WHERE uLogTime<%u",uLastTime); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); return(1); } return(0); }//int RemoveExpiredRows(unsigned uLastTime) void CreatetMailLog(void) { mysql_query(&mysql,"DROP TABLE tMailLog"); sprintf(query,"CREATE TABLE tMailLog ( uMailLog int unsigned PRIMARY KEY AUTO_INCREMENT, uLogTime int unsigned NOT NULL DEFAULT 0, cQID varchar(16) NOT NULL DEFAULT '', KEY (cQID), cRcpt varchar(100) NOT NULL DEFAULT '', uType int unsigned NOT NULL DEFAULT 0, KEY (uType), cSender varchar(100) NOT NULL DEFAULT '', KEY (cSender), uNrcpts int unsigned NOT NULL DEFAULT 0, uSize int unsigned NOT NULL DEFAULT 0, cRelayIP varchar(16) NOT NULL DEFAULT '', KEY (cRelayIP) )"); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } //Start table with 0 marker uLogTime=0; if(InsertUpdateMarker()) exit(1); }//void CreatetMailLog(void) char *strptime(const char *s, const char *format, struct tm *tm); time_t DateToUnixTime(char *cDate) { struct tm locTime; time_t res; bzero(&locTime, sizeof(struct tm)); strptime(cDate,"%d-%b-%Y", &locTime); locTime.tm_sec = 0; locTime.tm_min = 0; locTime.tm_hour = 0; res = mktime(&locTime); return(res); } time_t TimeToUnixTime(char *cTime) { struct tm locTime; time_t res; bzero(&locTime, sizeof(struct tm)); strptime(cTime,"%H:%M:%S", &locTime); locTime.tm_year = 70; locTime.tm_mon = 0; locTime.tm_mday = 1; res = mktime(&locTime); return(res); } //Algo description: // Sort "User unknown" log entries by cQID, Count how many. Dont confuse // nrcpts with misses. Save nrcpts in tScoreBoard anyway // On each new unique cQID. Find the corresponding from relay entry. // There should only be one. If there are more than one, use only the // first. // With info from that entry and the cQID create/update a tScoreBoard row // based on the cSender (from). // Updating is harder since we want to do more things like: // (Why update? Because senders dont send all emails at once (bcc etc.) // and some even change their IP continuosly (spoofed? header rewrite?)) // 1-. Use the most relevant cQID. One that was actually used to deliver // email to someone. (So we can read the email and check to see if it is // spam. See ISP privacy policy!) // 2-. Update the uCount: Increment the current one. // 3-. Update the uNrcpts using uExpireTime col for now. int Process(void) { MYSQL_RES *res; register int i=0; //First process: Mail guesser, or outdated user info attack signature sprintf(query,"SELECT cQID,cRcpt FROM tMailLog WHERE uType=1 ORDER BY cQID,uMailLog"); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); return(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i>0) { MYSQL_ROW field; char cLastQID[18]={"New"}; int count=1;//count how many same cQID of misses while((field=mysql_fetch_row(res))) { //Debug only //printf("%s %s (%s)\n",field[0],field[1],cLastQID); //New cQID if(strcmp(cLastQID,field[0])) { //Debug only //printf("%s %d\n", field[0],count); strcpy(cLastQID,field[0]); ExtractSenderInfoAndUpdate(field[0],count); count=1; } else { count++; } }//End of while() //Handle last group of same cQID's case if(count>1) ExtractSenderInfoAndUpdate(cLastQID,count); } else { //Debug only //printf("Did not find any 'User unknown' events\n"); } return(0); }//int Process(void) int ExtractSenderInfoAndUpdate(char *cQID,int count) { MYSQL_RES *res; register int i; sprintf(query,"SELECT uLogTime,cQID,cSender,cRelayIP,uNrcpts FROM tMailLog WHERE uType=2 AND cQID='%s' ORDER BY cQID", cQID); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i>0) { MYSQL_ROW field; while((field=mysql_fetch_row(res))) { //Debug only //printf("%s %s %s\n",field[1],field[2],field[3]); sscanf(field[4],"%u",&uNrcpts); if(uNrcpts>0) strcpy(cQID,field[1]); else cQID[0]=0; uExpireTime=uNrcpts; strcpy(cSender,field[2]); strcpy(cRelayIP,field[3]); uCount=count; sscanf(field[0],"%u",&uFirstTime); uType=1; //Spammer many misses signature if(InsertUpdate_tScoreBoard()) return(1); } //Debug only //printf("\n"); } return(0); }//int ExtractSenderInfoAndUpdate(char *cQID,int count) int InsertUpdate_tScoreBoard(void) { MYSQL_RES *res; register int i; char cSenderLocal[202]; strcpy(cSenderLocal,TextAreaSave(cSender)); //Signature 1 only uType=1 sprintf(query,"SELECT uRow,uCount,uFirstTime,cQID,uExpireTime FROM tScoreBoard WHERE uType=1 AND cSender='%s'", cSenderLocal); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i>0) { MYSQL_ROW field; unsigned uPrevCount=0; while((field=mysql_fetch_row(res))) { sscanf(field[1],"%u",&uPrevCount); uCount+=uPrevCount; uLastTime=uFirstTime; sscanf(field[2],"%u",&uFirstTime); //using uExpireTime for uNrcpts storage //Dont update if not empty. See uNrcpts above if(field[3][0]) strcpy(cQID,field[3]); //debug only //printf("Update %d\n",uCount); Update_tScoreBoard(field[0]); } } else if(i==0) { //debug only //printf("Insert\n"); uLastTime=uFirstTime; Insert_tScoreBoard(); } return(0); }//int InsertUpdate_tScoreBoard(void) void Insert_tScoreBoard(void) { //insert query sprintf(query,"INSERT INTO tScoreBoard VALUES (0,'%s','%s',%u,%u,%u,%u,%u,'%s' )", TextAreaSave(cSender) ,cRelayIP ,uCount ,uFirstTime ,uLastTime ,uExpireTime ,uType ,cQID ); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } }//void Insert_tScoreBoard(void) void Update_tScoreBoard(char *rowid) { //update query sprintf(query,"UPDATE tScoreBoard SET cSender='%s',cRelayIP='%s',uCount=%u,uFirstTime=%u,uLastTime=%u,uExpireTime=%u,uType=%u,cQID='%s' WHERE uRow=%s", TextAreaSave(cSender) ,cRelayIP ,uCount ,uFirstTime ,uLastTime ,uExpireTime ,uType ,cQID ,rowid); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } }//void Update_tScoreBoard(char *rowid) int Block(void) { MYSQL_RES *res; register int i; sprintf(query,"SELECT cSender,uCount,uExpireTime,uFirstTime,uLastTime,cRelayIP FROM tScoreBoard WHERE uCount>10 OR ( uCount>3 AND uExpireTime>1 )"); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i>0) { MYSQL_ROW field; while((field=mysql_fetch_row(res))) { //If empty sender most likely a dumb but //guaranteed spammer //use IP. Next version check against mysqlSendmail.tDUL //Better to use relay info if possible if(cRelayIP[0]) { strcpy(cSender,field[5]); } else { if(field[0][0]) strcpy(cSender,field[0]); else strcpy(cSender,field[5]); } switch(tAccessBlock(cSender)) { case 1: return(1); break; case 2: //Debug only //printf("%s is already in tAccess\n",cSender); break; default: printf("Blocked %s for %s misses\n",cSender,field[1]); } } } return(0); }//int Block(void) int tAccessBlock(char *cSender) { MYSQL_RES *res; time_t uTime,uExpireTime; time(&uTime); uExpireTime= 3600*72 + uTime;//Release in 72 hours from now. //This specific match has to be discussed. ClassC entries? Priority block? Or whatever //was set via popper,radiusd,tDul or webconsole sprintf(query,"SELECT uAccess FROM tAccess WHERE cDomainIP='%s'",TextAreaSave(cSender)); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i==0 && cSender[0]) { sprintf(query,"INSERT INTO tAccess SET cDomainIP='%s',cRelayAttr='ERROR:\"554 You have been identified as a possible spam source.\"',uServer=1,uExpireDate=%lu,uSource=%u,uOwner=1,uCreatedBy=1,uCreatedDate=%lu",TextAreaSave(cSender),uExpireTime,ACCESS_SOURCE_NUKESPAM_MISSES,uTime); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } return(0); } return(2); }//int tAccessBlock(char *cSender) int CreatetRejects(void) { mysql_query(&mysql,"DROP TABLE tRejects"); sprintf(query,"CREATE TABLE tRejects ( uRejects int unsigned PRIMARY KEY AUTO_INCREMENT, uRejectsType int unsigned NOT NULL DEFAULT 0, cRejectTag varchar(100) NOT NULL DEFAULT '', uCount int unsigned NOT NULL DEFAULT 0, uFirstCount int unsigned NOT NULL DEFAULT 0, uLastCount int unsigned NOT NULL DEFAULT 0, KEY (uRejectsType), KEY (cRejectTag) )"); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } return(0); }//CreatetRejects() void Insert_tRejects(void) { //insert query sprintf(query,"INSERT INTO tRejects SET uRejectsType=%u,cRejectTag='%s',uCount=%u,uFirstCount=%u,uLastCount=%u",uRejectsType,cRejectTag ,uCount ,uFirstCount ,uLastCount); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } }//void Insert_tRejects(void) void Update_tRejects(char *cRejectTag) { //update query sprintf(query,"UPDATE tRejects SET uCount=%u,uFirstCount=%u,uLastCount=%u WHERE cRejectTag='%s'",uCount ,uFirstCount ,uLastCount ,cRejectTag); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } }//void Update_tRejects(void) int InsertUpdate_tRejects(char *cKey) { register int i; time_t clock; MYSQL_RES *res; MYSQL_ROW field; time(&clock); uLastCount=clock; strmyncpy(cRejectTag,TextAreaSave(cKey),99); sprintf(query,"SELECT uRejects,uCount,uFirstCount,uLastCount FROM tRejects WHERE cRejectTag='%s'",cRejectTag); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i>0) { field=mysql_fetch_row(res); sscanf(field[1],"%u",&uCount); uCount++; sscanf(field[2],"%u",&uFirstCount); Update_tRejects(cRejectTag); } else { uCount=1; uFirstCount=clock; Insert_tRejects(); } mysql_free_result(res); return(0); }//int InsertUpdate_tRejects(char *cKey) void NukeSpamStats(void) { MYSQL_RES *res; MYSQL_ROW field; register int i; TextConnectDb(); printf("NukeSpamStats()

NukeSpamStats()

\n"); //Report table 1 sprintf(query,"SELECT uType,COUNT(*) FROM tMailLog WHERE uType>99 AND uType<200 GROUP BY uType"); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i) { printf("Rejects during last hour
"); printf("\n"); printf("\n"); while((field=mysql_fetch_row(res))) { printf("\n",field[1],field[0]); } printf("
NumberInternal Reject Codes: 100=550, 101=553, 102=554, 103=Other 5XX codes
%s %s
\n"); printf("
\n"); } mysql_free_result(res); //2nd part of report sprintf(query,"SELECT uRejectsType,SUM(uCount) FROM tRejects GROUP BY uRejectsType"); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i) { printf("Cummulative rejects
\n"); printf("\n"); printf("\n"); while((field=mysql_fetch_row(res))) { printf("\n",field[1],field[0]); } printf("
NumberReject Code
%s %s
\n"); printf("
\n"); } mysql_free_result(res); //3rd part of report sprintf(query,"SELECT FROM_UNIXTIME(MIN(uFirstCount)),FROM_UNIXTIME(MAX(uLastCount)) FROM tRejects"); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); i=mysql_num_rows(res); if(i) { printf("Historical Info
\n"); printf("\n"); printf("\n"); if((field=mysql_fetch_row(res))) { printf("\n",field[0]); printf("\n",field[1]); } printf("
PointDate Time
Since%s
Last%s
\n"); printf("
\n"); } mysql_free_result(res); printf("

$Id: mainfunc.h 6 2005-11-24 00:02:59Z ggw $\n"); exit(0); }//void Stats(void) #endif //if defined NUKESPAM void UpgradeSchema(char *cPasswd) { mySQLRootConnect(cPasswd); sprintf(query,"USE %s",DBNAME); mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } printf("\nUpgradeSchema() if needed\n"); printf("\ttUser\n"); sprintf(query,"ALTER TABLE tUser CHANGE COLUMN cPasswd cPasswd VARCHAR(64) NOT NULL DEFAULT ''"); mysql_query(&mysql,qstr); if(mysql_errno(&mysql)) fprintf(stderr,"%s\n",mysql_error(&mysql)); }//void UpgradeSchema(char *cPasswd) int NewUser(unsigned uUser); void MigrateUsers(unsigned uDryRun, unsigned uHelp) { MYSQL_RES *res; MYSQL_ROW field; uid_t uUID=999999; char cMbox[256]={"var/mail/%s"}; char cImapMail[256]={"INBOX.*"}; time_t luClock; printf("\nMigrateUsers %s ($Rev: 21 $)\n",RELEASESHORT); uUID=getuid(); if(uUID) { printf("\nOnly root can run this command\n"); exit(1); } if(uHelp) { printf("\nHelp\n"); printf("1-. mysqldump remote host mysqlsendmail data and pipe into mysql.\n"); printf("2-. rsync mail and user dirs imap mail folders into a /migration dir\n"); printf("\tEx. /migration/home//INBOX.* and /migration/var/mail/\n"); exit(0); } else if(uDryRun) { printf("\nDryRun: Nothing will be actually done but complete process will be dumped to stdout.\n"); } printf("\nMigrateUsers Start\n\n"); //Connect to local mySQL TextConnectDb(); printf("Add or update tUsers from tUser\n"); time(&luClock); GetConfiguration("cMbox",cMbox,0); GetConfiguration("cImapMail",cImapMail,0); sprintf(query,"SELECT cLogin,uUser FROM tUser WHERE uStatus=1 OR uStatus=8");//Active or Modified mysql_query(&mysql,query); if(mysql_errno(&mysql)) { fprintf(stderr,"%s\n",mysql_error(&mysql)); exit(1); } res=mysql_store_result(&mysql); while((field=mysql_fetch_row(res))) { unsigned uUser=0; struct passwd *structPassInfo; sscanf(field[1],"%u",&uUser); printf("%s/%u add\n",field[0],uUser); if(!(structPassInfo=getpwnam(field[0]))) { printf("%s add",field[0]); if(!uDryRun) NewUser(uUser); else printf(" dry-run"); printf("\n"); } else { if(uDryRun) printf("%s dry-run for existing user\n",field[0]); } #ifdef MIGRATION_DIR //install mailbox char cMboxFmtd[256]; //this is very implementation dependent and should //come from tConfiguration. Examples: //char cMbox[256]="var/mail/%s"; //char cMbox[256]="~%s/.maildir"; sprintf(cMboxFmtd,cMbox,field[0]); sprintf(query,"cp /migration/%s /%s",cMboxFmtd,cMboxFmtd); if(!uDryRun) { if(!system(query)) { sprintf(query,"chown %s /%s; chgrp mail /%s", field[0],cMboxFmtd,cMboxFmtd); if(!system(query)) { sprintf(query,"chmod 600 /%s",cMboxFmtd); system(query); } } } else { printf("DryRun: %s\n",query); } //this also is very implementation dependent and should //come from tConfiguration //copy over users INBOX.* or mail imap dirs if they exist //this depends on the type of imapd used on the remote server //char cImapMail[256]="mail"; //char cImapMail[256]="INBOX.*"; //This maybe needed someday: sprintf(cMboxFmtd,cImapMail,field[0]); sprintf(query,"cp -rp /migration/home/%s/%s ~%s/",field[0],cImapMail,field[0]); if(!uDryRun) { if(!system(query)) { sprintf(query,"chown -R %s ~%s/%s",field[0],field[0],cImapMail); system(query); } } else { printf("DryRun: %s\n",query); } #endif } mysql_free_result(res); printf("\nMigrateUsers Done\n"); mysql_close(&mysql); exit(0); }//void MigrateUsers(const char *cRemoteMySQLConnectString, unsigned uDryRun, unsigned uHelp) //sedall patch1 //sedall patch2