00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <string>
00037 #include <stdlib.h>
00038 #ifdef _WIN32
00039 # include <conio.h>
00040 # include <process.h>
00041 # include <io.h>
00042 # define _WINSOCKAPI_
00043 # include <windows.h>
00044 #else
00045 # include <signal.h>
00046 # include <unistd.h>
00047 #endif
00048 #include <sys/stat.h>
00049
00050 #include <time.h>
00051 #include <map>
00052 #include <list>
00053 #include <string.h>
00054 #include <time.h>
00055
00056 #include "log.h"
00057 #include "sock.h"
00058 #include "irc.h"
00059 #include "logic.h"
00060 #include "dcc.h"
00061 #include "botnet.h"
00062 #include "conf.h"
00063 #include "stats.h"
00064 #include "identd.h"
00065 #include "ssl.h"
00066 #include "win_sock.h"
00067 #include "exec.h"
00068 #include "filesys.h"
00069
00070 #include "match.h"
00071
00072 #include "params.h"
00073
00074 #pragma hdrstop
00075
00076
00077
00078
00079
00080 #define BOT_DIE 0
00081
00082
00083
00084
00085 #define BOT_ERROR 1
00086
00087
00088
00089
00090 #define BOT_RESTART 2
00091
00092 using namespace std;
00093
00094 extern bool dcc_want_to_restart;
00095 extern bool dcc_want_to_die;
00096 extern bool dcc_want_to_upgrade;
00097 extern string dcc_who_is_killing;
00098 extern s_socket* dcc_killing_user_socket;
00099 extern string dcc_killing_user_eol;
00100 extern s_socket irc_socket;
00101 extern s_ssl_conf ssl_conf;
00102 extern void dcc_send_msg(s_socket& socket, string msg, int& ec);
00103 extern void dcc_broadcast(string msg);
00104 extern void dcc_flush_all();
00105 extern void dcc_close_all();
00106 extern void dcc_close_servers();
00107
00108 bool copy_me_to_upper_dir=false;
00109 string binary_name;
00110 string this_instance_binary;
00111 bool spawned_by_service=false;
00112
00113 #ifndef _WIN32
00114 #ifndef HAVE_LTOA
00115 extern char *ltoa(long value, char *buffer, int radix);
00116 #endif
00117 #endif
00118
00119 extern void sock_send_cache();
00120
00121
00122
00123
00124
00125
00126
00127
00128 void handler_sigpipe(int sig)
00129 {
00130 log_debug("SIGPIPE handler: Broken pipe");
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140 void handler_sigterm(int sig)
00141 {
00142 dcc_want_to_die=true;
00143 dcc_who_is_killing="root";
00144 logic_partyline_backup("root");
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154 void handler_sighup(int sig)
00155 {
00156 dcc_want_to_die=true;
00157 dcc_who_is_killing="root";
00158 logic_partyline_backup("root");
00159 }
00160
00161 #ifdef _WIN32
00162
00163
00164
00165
00166
00167
00168
00169
00170 BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
00171 {
00172 switch(dwCtrlType) {
00173 case CTRL_C_EVENT:
00174 case CTRL_BREAK_EVENT:
00175 case CTRL_SHUTDOWN_EVENT:
00176 dcc_want_to_die=true;
00177 dcc_who_is_killing="root";
00178 logic_partyline_backup("root");
00179 return true;
00180 case CTRL_LOGOFF_EVENT:
00181 return false;
00182 }
00183 return false;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 bool ProcessMessage()
00194 {
00195 tagMSG* m=new tagMSG;
00196 if(PeekMessage(m,0,0,0,PM_REMOVE)) {
00197 TranslateMessage(m);
00198 DispatchMessage(m);
00199 delete m;
00200 return true;
00201 }
00202 delete m;
00203 return false;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212 void ProcessMessages()
00213 {
00214 while(ProcessMessage())
00215 ;
00216 }
00217 #endif
00218
00219
00220
00221
00222
00223
00224
00225
00226 void sleep(int ms)
00227 {
00228 #ifdef _WIN32
00229 ProcessMessages();
00230 sock_send_cache();
00231 if(ms) {
00232 if(ms<1000) {
00233 long ms_remain=ms;
00234 while(ms_remain>0) {
00235 ProcessMessages();
00236 sock_send_cache();
00237 int s=ms_remain>50?50:ms_remain;
00238 Sleep(s);
00239 ms_remain-=s;
00240 ProcessMessages();
00241 sock_send_cache();
00242 }
00243 } else {
00244 time_t now=time(NULL);
00245 for(;;) {
00246 Sleep(1);
00247 ProcessMessages();
00248 dcc_loop();
00249 sock_send_cache();
00250 if(now+ms/1000<time(NULL))
00251 break;
00252 }
00253 }
00254 }
00255 ProcessMessages();
00256 #else
00257 sock_send_cache();
00258 if(ms) {
00259 if(ms<1000) {
00260 long ms_remain=ms;
00261 while(ms_remain>0) {
00262 sock_send_cache();
00263 int s=ms_remain>50?50:ms_remain;
00264 timeval tv;
00265 tv.tv_sec=0;
00266 tv.tv_usec=ms*1000;
00267 select(1,NULL,NULL,NULL,&tv);
00268 ms_remain-=s;
00269 sock_send_cache();
00270 }
00271 } else {
00272 time_t now=time(NULL);
00273 for(;;) {
00274 timeval tv;
00275 tv.tv_sec=0;
00276 tv.tv_usec=1*1000;
00277 select(1,NULL,NULL,NULL,&tv);
00278 dcc_loop();
00279 sock_send_cache();
00280 if(now+ms/1000<time(NULL))
00281 break;
00282 }
00283 }
00284 }
00285 #endif
00286 }
00287
00288 #ifdef _WIN32
00289 # define FILE_SLASH "\\"
00290 #else
00291 # define FILE_SLASH "/"
00292 #endif
00293
00294
00295
00296
00297
00298
00299
00300 void disp_license()
00301 {
00302 char lic[]="VooDoo cIRCle version " VERSION "\nCopyright (C) 2004 by "
00303 "Marian VooDooMan Meravy (vdmfun@hotmail.com)\n\n"
00304 "VooDoo cIRCle comes with ABSOLUTELY NO WARRANTY; for details "
00305 "see\n`license.html'. This is free software, and you are welcome "
00306 "to redistribute\nit under certain conditions; see the license for details.\n\n"
00307 "This product includes software developed by the OpenSSL Project "
00308 "for use in the\nOpenSSL Toolkit. (http://www.openssl.org/)\n"
00309 "This product includes cryptographic software written by Eric Young\n"
00310 "(eay@cryptsoft.com). This product includes software written by\nTim "
00311 "Hudson (tjh@cryptsoft.com).\n\n\0";
00312 printf(lic);
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322 string write_kill_log()
00323 {
00324 string s;
00325 if(dcc_want_to_die)
00326 s="Die by ";
00327 else if(dcc_want_to_restart)
00328 s="Restart by ";
00329 else if(dcc_want_to_upgrade)
00330 s="Upgrade by ";
00331 s+=dcc_who_is_killing;
00332 irc_quit(s.c_str());
00333 if(!dcc_want_to_upgrade)
00334 s=(string)"*** "+s;
00335 else
00336 s=(string)"*** [previous instance] "+s;
00337 log_bot(s.c_str());
00338 return s;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347 void closeall(int fd)
00348 {
00349 #ifndef _WIN32
00350 int fdlimit=sysconf(_SC_OPEN_MAX);
00351
00352 while(fd<fdlimit)
00353 close(fd++);
00354 #endif
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 int daemon(bool nochdir, bool noclose, bool stdout_new_pid)
00371 {
00372 #ifndef _WIN32
00373 switch(fork()) {
00374 case 0: break;
00375 case -1: return -1;
00376 default:
00377 sleep(1000);
00378 _exit(BOT_DIE);
00379 }
00380
00381 if(setsid()<0)
00382 return -1;
00383
00384
00385
00386
00387 switch(fork()) {
00388 case 0: break;
00389 case -1: return -1;
00390 default:
00391 sleep(1000);
00392 _exit(BOT_DIE);
00393 }
00394
00395 if(!nochdir)
00396 chdir("/");
00397
00398 if(stdout_new_pid)
00399 printf("Background process PID is %d\n\n",getpid());
00400
00401 if(!noclose) {
00402 closeall(0);
00403 open("/dev/null",O_RDWR);
00404 dup(0); dup(0);
00405 }
00406
00407 #endif
00408 return 0;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 int main(int argc, char* argv[])
00424 {
00425 this_instance_binary=argv[0];
00426 binary_name=argv[0];
00427 #ifndef _WIN32
00428 bool b_interactive=false;
00429 #endif
00430 for(int i1=1; i1<argc; i1++) {
00431 if(!strcmp("--hush",argv[i1])) {
00432 #ifndef _WIN32
00433 closeall(0);
00434 open("/dev/null",O_RDWR);
00435 dup(0); dup(0);
00436 #endif
00437 continue;
00438 }
00439 if(!strcmp("-h",argv[i1]) ||
00440 !strcmp("--help",argv[i1])) {
00441 usage:
00442 disp_license();
00443 printf("%s%s%s\n\n","USAGE: ",argv[0]," [options]");
00444 printf("Options: -h, --help : this message\n");
00445 printf(" -v, --version : prints out version only\n");
00446 printf(" -i, --interactive : run in interactive mode\n");
00447 printf(" (default on win32)\n");
00448 printf(" -d, --daemon : run in background, exit immediately\n");
00449 printf(" (default on non-win32, unused in win32)\n");
00450 printf("\n");
00451 return BOT_DIE;
00452 }
00453 if(!strcmp("-i",argv[i1]) ||
00454 !strcmp("--interactive",argv[i1])) {
00455 #ifndef _WIN32
00456 b_interactive=true;
00457 #endif
00458 continue;
00459 }
00460 if(!strcmp("-v",argv[i1]) ||
00461 !strcmp("--version",argv[i1])) {
00462 printf("%s\n",VERSION);
00463 return BOT_DIE;
00464 }
00465 if(!strcmp("-d",argv[i1]) ||
00466 !strcmp("--daemon",argv[i1])) {
00467 #ifndef _WIN32
00468 b_interactive=false;
00469 #endif
00470 continue;
00471 }
00472 if(!strncmp("--upgrade=",argv[i1],strlen("--upgrade="))) {
00473 copy_me_to_upper_dir=true;
00474 string tmp=argv[i1];
00475 if(tmp.find("=",0)!=string::npos)
00476 tmp.erase(0,tmp.find("=",0)+1);
00477 binary_name=tmp;
00478 continue;
00479 }
00480 if(!strcmp("--service",argv[i1])) {
00481 spawned_by_service=true;
00482 #ifndef _WIN32
00483 spawned_by_service=false;
00484 #endif
00485 continue;
00486 }
00487 goto usage;
00488 }
00489 disp_license();
00490 #ifndef _WIN32
00491 if(!b_interactive)
00492 daemon(true,false,true);
00493 signal(SIGPIPE,handler_sigpipe);
00494 signal(SIGTERM,handler_sigterm);
00495 signal(SIGHUP,handler_sighup);
00496 #endif
00497
00498 srand((unsigned)time(NULL));
00499
00500 if(conf_init()) {
00501 printf("Cannot open file \"conf.txt\"!\n");
00502 return BOT_ERROR;
00503 }
00504
00505 if(!log_init()) {
00506 printf("Another instance is running! Exiting with code 0.\n");
00507 return 0;
00508 }
00509
00510 stats_init();
00511
00512 sock_startup();
00513
00514 if(conf_ssl_init()) {
00515 printf("Cannot open file \"ssl.txt\"!\n");
00516 return BOT_ERROR;
00517 }
00518 {
00519 char err_str[1024];
00520 if(ssl_init(err_str,(char*)ssl_conf.accept_ca_certs.c_str())) {
00521 char tmp[2048];
00522 sprintf(tmp,"%s %s","OpenSSL error:",err_str);
00523 log_bot(tmp);
00524 printf("%s\n",tmp);
00525 return BOT_ERROR;
00526 }
00527 }
00528
00529 int errorline=1;
00530 const char* reason=NULL;
00531 if(logic_load_conf("logic.txt",errorline,reason)) {
00532 char msg[1024];
00533 sprintf(msg,"%s%d","Error in \"logic.txt\" on line #",errorline);
00534 if(reason) {
00535 char m[1024];
00536 sprintf(m," - %s%s","Reason: ",reason);
00537 strcat(msg,m);
00538 }
00539 printf("%s\n",msg);
00540 log_bot(msg);
00541 log_done(BOT_ERROR,"");
00542 return BOT_ERROR;
00543 }
00544
00545 {
00546 FILE* f=fopen("logs" FILE_SLASH "irc_bot.pid","w");
00547 if(f) {
00548 fprintf(f,"%d\n",getpid());
00549 fclose(f);
00550 }
00551
00552 unlink("logs" FILE_SLASH "irc_bot.action");
00553 }
00554
00555 #ifdef _WIN32
00556 SetConsoleCtrlHandler(HandlerRoutine,true);
00557 #endif
00558
00559 {
00560 string proc="_sys_startup($pid)";
00561 map<string,string> vars;
00562 list<string> parms;
00563 char ch[64];
00564 ch[0]=0;
00565 ltoa(getpid(),ch,10);
00566 parms.push_back(ch);
00567 switch(logic_call_proc_ex2(proc.c_str(),vars,parms,false)) {
00568 case LOGIC_SOCKET_ERROR:
00569 case LOGIC_RESTART:
00570 dcc_want_to_restart=true;
00571 dcc_who_is_killing="self";
00572 logic_partyline_backup("self");
00573 break;
00574 case LOGIC_NO_SERVER:
00575 dcc_want_to_die=true;
00576 dcc_who_is_killing="self";
00577 logic_partyline_backup("self");
00578 break;
00579 default:
00580 break;
00581 }
00582 if(dcc_want_to_die || dcc_want_to_restart) {
00583 string log=write_kill_log();
00584 dcc_broadcast(log);
00585 dcc_flush_all();
00586 irc_disconnect();
00587 }
00588 }
00589
00590 again:
00591 bool error=false;
00592 while(!dcc_want_to_die && !dcc_want_to_restart) {
00593 if(irc_loop_process_input())
00594 break;
00595 logic_loop();
00596
00597 logic_loop_identd();
00598
00599 error=irc_loop_putserv();
00600 if(error)
00601 break;
00602
00603 botnet_loop();
00604
00605 {
00606 FILE* f=fopen("logs" FILE_SLASH "irc_bot.action","r");
00607 if(f) {
00608 char tmp[1024];
00609 tmp[0]=0;
00610 fgets(tmp,1024-16,f);
00611 if(!strcmp(tmp,"die\n") || !strcmp(tmp,"die\r\n") || !strcmp(tmp,"die\r")) {
00612 dcc_want_to_die=true;
00613 dcc_who_is_killing="root";
00614 fclose(f);
00615 f=NULL;
00616 unlink("logs" FILE_SLASH "irc_bot.action");
00617 logic_partyline_backup("root");
00618 }
00619 if(!strcmp(tmp,"restart\n") || !strcmp(tmp,"restart\r\n") || !strcmp(tmp,"restart\r")) {
00620 dcc_want_to_restart=true;
00621 dcc_who_is_killing="root";
00622 fclose(f);
00623 f=NULL;
00624 unlink("logs" FILE_SLASH "irc_bot.action");
00625 logic_partyline_backup("root");
00626 }
00627 if(f)
00628 fclose(f);
00629 f=NULL;
00630 }
00631 }
00632
00633 {
00634 extern list<char*> msgs_from_server;
00635 if(msgs_from_server.empty())
00636 sleep(50);
00637 else
00638 sleep(1);
00639 }
00640 static time_t last_copy_attemp=0;
00641 static bool copy_attemp_successful=false;
00642 if(!copy_attemp_successful && copy_me_to_upper_dir && last_copy_attemp+10<time(NULL)) {
00643 last_copy_attemp=time(NULL);
00644 FILE* f1=fopen(this_instance_binary.c_str(),"rb");
00645 if(f1) {
00646 FILE* f2=fopen(binary_name.c_str(),"wb");
00647 if(f2) {
00648 char tmp[1024];
00649 while(!feof(f1)) {
00650 fread(tmp,1,sizeof(tmp),f1);
00651 fwrite(tmp,1,sizeof(tmp),f2);
00652 }
00653 fclose(f2);
00654 #ifndef _WIN32
00655 chmod(binary_name.c_str(),S_IRWXU);
00656 #endif
00657 copy_attemp_successful=true;
00658 }
00659 fclose(f1);
00660 }
00661 }
00662 #ifdef _WIN32
00663 ProcessMessages();
00664 #endif
00665 }
00666
00667 if(dcc_want_to_die || dcc_want_to_restart) {
00668 string log=write_kill_log();
00669 dcc_broadcast(log);
00670
00671 if(dcc_want_to_die)
00672 logic_on_internal_event("@die@",dcc_who_is_killing,"","","",PRIVATE_EVENT_SEVERITY_CODE_INFORMATIONAL,"","");
00673 if(dcc_want_to_restart)
00674 logic_on_internal_event("@restart@",dcc_who_is_killing,"","","",PRIVATE_EVENT_SEVERITY_CODE_INFORMATIONAL,"","");
00675
00676 dcc_flush_all();
00677 irc_disconnect();
00678 }
00679
00680 if(!dcc_want_to_restart && !dcc_want_to_die) {
00681 logic_exec_from_work();
00682 goto again;
00683 }
00684
00685 if(dcc_want_to_restart) {
00686 dcc_close_servers();
00687 filesys_flush();
00688 dcc_flush_all();
00689
00690 int ec=0;
00691
00692 if(!spawned_by_service) {
00693 string tmp=binary_name;
00694 s_exec_handle* h=exec_async_exec2(tmp.c_str(),"--hush",NULL);
00695
00696 int exit_code;
00697 string disp_log, disp_dcc;
00698 if(h->error) {
00699 exit_code=BOT_RESTART;
00700
00701 disp_log=disp_dcc="RESTART: Error spawning new instance. Something should run it.";
00702 disp_dcc+=dcc_killing_user_eol;
00703
00704 log_bot(disp_log.c_str());
00705
00706 logic_on_internal_event("@restart_error@",dcc_who_is_killing,"","","",PRIVATE_EVENT_SEVERITY_CODE_FATAL_ERROR,disp_log,"");
00707
00708 if(dcc_killing_user_socket)
00709 dcc_send_msg(*dcc_killing_user_socket,disp_dcc,ec);
00710 } else
00711 exit_code=BOT_DIE;
00712
00713 string log=log_done(exit_code,dcc_killing_user_eol);
00714 ec=0;
00715 if(dcc_killing_user_socket)
00716 dcc_send_msg(*dcc_killing_user_socket,log,ec);
00717 sock_send_cache();
00718 if(dcc_killing_user_socket)
00719 sock_flush_later(*dcc_killing_user_socket);
00720
00721 if(!disp_log.empty() || !disp_dcc.empty()) {
00722 log_bot(disp_log.c_str());
00723 if(dcc_killing_user_socket)
00724 dcc_send_msg(*dcc_killing_user_socket,disp_dcc,ec);
00725 }
00726
00727 dcc_flush_all();
00728 sleep(1000);
00729 dcc_close_all();
00730 sleep(1000);
00731 sock_shutdown();
00732
00733 return exit_code;
00734 }
00735
00736
00737 string log=log_done(BOT_RESTART,dcc_killing_user_eol);
00738 ec=0;
00739 if(dcc_killing_user_socket)
00740 dcc_send_msg(*dcc_killing_user_socket,log,ec);
00741 sock_send_cache();
00742 if(dcc_killing_user_socket)
00743 sock_flush_later(*dcc_killing_user_socket);
00744
00745 dcc_flush_all();
00746 sleep(1000);
00747 dcc_close_all();
00748 sleep(1000);
00749 sock_shutdown();
00750
00751 return BOT_RESTART;
00752 }
00753
00754 string log=log_done(BOT_DIE,dcc_killing_user_eol);
00755 int ec=0;
00756 if(dcc_killing_user_socket)
00757 dcc_send_msg(*dcc_killing_user_socket,log,ec);
00758 sock_send_cache();
00759 if(dcc_killing_user_socket)
00760 sock_flush_later(*dcc_killing_user_socket);
00761
00762 filesys_flush();
00763
00764 dcc_flush_all();
00765 sleep(1000);
00766 dcc_close_all();
00767 sleep(1000);
00768 sock_shutdown();
00769 return BOT_DIE;
00770 }
00771