/* * ExceptionProc */ BOOL CALLBACK ExceptionProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { WORD cmd; ExceptDlgInfo *info; ProcNode *procinfo; WORD tmp; address addr; info = FaultGetExceptDlgInfo( hwnd ); switch( msg ) { case WM_INITDIALOG: /* make sure this dialog always comes up on top of everything else */ SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE ); SetWindowPos( hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE ); centerDialog( hwnd ); info = MemAlloc( sizeof( ExceptDlgInfo ) ); info->dbinfo = (DEBUG_EVENT *)lparam; info->rc = 0; info->action = 0; SetWindowLong( hwnd, DWL_USER, (DWORD)info ); info->procinfo = FindProcess( info->dbinfo->dwProcessId ); info->threadinfo = FindThread( info->procinfo, info->dbinfo->dwThreadId ); info->module = ModuleFromAddr( info->procinfo, info->dbinfo->u.Exception.ExceptionRecord.ExceptionAddress ); if( info->threadinfo != NULL ) { AllocMadRegisters( &(info->regs) ); LoadMADRegisters( info->regs, info->threadinfo->threadhdl ); GetCurrAddr( &( info->init_ip ), info->regs ); } if( info->module == NULL ) { info->got_dbginfo = FALSE; } else { if( !LoadDbgInfo( info->module ) ) { info->got_dbginfo = FALSE; } else { info->got_dbginfo = TRUE; } } if( LogData.autolog ) { //Just create the log and exit tmp = ConfigData.exception_action; CheckDlgButton( hwnd, INT_TERMINATE, BST_CHECKED ); SendMessage( hwnd, WM_COMMAND, MAKELONG( INT_ACT_AND_LOG, BN_CLICKED ), (LPARAM)GetDlgItem( hwnd, INT_ACT_AND_LOG ) ); ConfigData.exception_action = tmp; } else { fillExceptionDlg( hwnd, info ); } setProcessHdl( info->procinfo->prochdl ); break; case WM_COMMAND: cmd = LOWORD( wparam ); switch( cmd ) { case INT_ACT_AND_LOG: MakeLog( info ); /* fall through */ case INT_ACT: if( IsDlgButtonChecked( hwnd, INT_TERMINATE ) ) { ConfigData.exception_action = INT_TERMINATE; // hp = OpenProcess( PROCESS_TERMINATE, FALSE, // info->dbinfo->dwProcessId ); procinfo = FindProcess( info->dbinfo->dwProcessId ); if( procinfo == NULL ) { RCMessageBox( hwnd, STR_CANT_TERMINATE_APP, AppName, MB_OK | MB_ICONEXCLAMATION ); } else { TerminateProcess( procinfo->prochdl, -1 ); // CloseHandle( hp ); info->rc = DBG_CONTINUE; info->action = INT_TERMINATE; SendMessage( hwnd, WM_CLOSE, 0, 0L ); } } else if( IsDlgButtonChecked( hwnd, INT_CHAIN_TO_NEXT ) ) { ConfigData.exception_action = INT_CHAIN_TO_NEXT; info->rc = DBG_EXCEPTION_NOT_HANDLED; info->action = INT_CHAIN_TO_NEXT; SendMessage( hwnd, WM_CLOSE, 0, 0L ); } else if( IsDlgButtonChecked( hwnd, INT_RESTART ) ) { ConfigData.exception_action = INT_RESTART; info->rc = DBG_CONTINUE; info->action = INT_RESTART; SendMessage( hwnd, WM_CLOSE, 0, 0L ); } break; case INT_REGISTERS: SetDisasmInfo( info->procinfo->prochdl, info->module ); StatShowSymbols = TRUE; if ( DoStatDialog( hwnd ) == 1 ){ StoreMADRegisters( info->regs, info->threadinfo->threadhdl ); GetCurrAddr(&addr,info->regs); SetIp( hwnd, &addr ); } LoadMADRegisters( info->regs, info->threadinfo->threadhdl ); break; case INT_LOG_OPTIONS: SetLogOptions( hwnd ); break; } break; case WM_CLOSE: if( info->rc == 0 ) { SendMessage( hwnd, WM_COMMAND, INT_ACT, 0L ); } else { if( info->got_dbginfo ) { UnloadDbgInfo( info->module ); } EndDialog( hwnd, info->rc ); } break; case WM_DESTROY: DeAllocMadRegisters( info->regs ); MemFree( info ); break; default: return( FALSE ); break; } return( TRUE ); }
int main( int argc, char *argv[] ) { char *fn = "main()"; char f_randfile[ PATH_MAX ]; int listensd; /* socket descriptor we'll bind to */ int clientsd; /* incoming socket descriptor */ int addrlen; struct sockaddr_in srvaddr; struct sockaddr_in cliaddr; pthread_t ThreadId; /* thread id of each incoming conn */ pthread_t RecycleThread; /* used just for the recycle thread */ pthread_attr_t attr; /* generic thread attribute struct */ int rc, i, fd; unsigned int ui; pid_t pid; /* used just for a fork call */ struct linger lingerstruct; /* for the socket reuse stuff */ int flag; /* for the socket reuse stuff */ ICC_Struct *ICC_tptr; extern char *optarg; extern int optind; char ConfigFile[ MAXPATHLEN ]; /* path to our config file */ #ifdef HAVE_LIBWRAP struct request_info r; /* request struct for libwrap */ #endif flag = 1; ConfigFile[0] = '\0'; /* * Ignore signals we don't want to die from but we don't care enough * about to catch. */ signal( SIGPIPE, SIG_IGN ); signal( SIGHUP, SIG_IGN ); while (( i = getopt( argc, argv, "f:h" ) ) != EOF ) { switch( i ) { case 'f': /* user specified a config filename */ strncpy( ConfigFile, optarg, sizeof ConfigFile -1 ); ConfigFile[ sizeof ConfigFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using configuration file '%s'", fn, ConfigFile ); break; case 'h': Usage(); exit( 0 ); case '?': Usage(); exit( 1 ); } } /* * Make sure we know which config file to use and then set our config * options. */ if ( ! ConfigFile[0] ) { strncpy( ConfigFile, DEFAULT_CONFIG_FILE, sizeof ConfigFile -1 ); ConfigFile[ sizeof ConfigFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using default configuration file '%s'.", fn, ConfigFile ); } SetConfigOptions( ConfigFile ); SetLogOptions(); /* * Just for logging purposes, are we doing SELECT caching or not? */ if ( PC_Struct.enable_select_cache ) syslog( LOG_INFO, "%s: SELECT caching is enabled", fn ); else syslog( LOG_INFO, "%s: SELECT caching is disabled", fn ); #ifdef HAVE_LIBWRAP /* * Set our tcpd service name */ if (service = strrchr(argv[0], '/')) service++; else service = argv[0]; #endif /* * Initialize some stuff. */ rc = pthread_mutex_init(&mp, NULL); if ( rc ) { syslog(LOG_ERR, "%s: pthread_mutex_init() returned error [%d] initializing main mutex. Exiting.", fn, rc ); exit( 1 ); } rc = pthread_mutex_init(&trace, NULL); if ( rc ) { syslog(LOG_ERR, "%s: pthread_mutex_init() returned error [%d] initializing trace mutex. Exiting.", fn, rc ); exit( 1 ); } TraceUser[0] = '\0'; syslog( LOG_INFO, "%s: Allocating %d IMAP connection structures.", fn, PC_Struct.cache_size ); ICC_free = (ICC_Struct *)malloc( ( sizeof ( ICC_Struct ) ) * PC_Struct.cache_size ); if ( ! ICC_free ) { syslog(LOG_ERR, "%s: malloc() failed to allocate [%d] IMAPConnectionContext structures: %s", fn, PC_Struct.cache_size, strerror( errno ) ); exit( 1 ); } memset( ICC_free, 0, sizeof ( ICC_Struct ) * PC_Struct.cache_size ); ICC_tptr = ICC_free; /* * Bug fixed by Gary Mills <*****@*****.**>. I was pre-incrementing * ICC_tptr and then assigning. I guess gcc evaluates the expression * incorrectly, since I never had a problem with this. Gary had the * problem with cc, so it's fixed here. */ for ( ui = 0; ui < PC_Struct.cache_size - 1; ui++ ) { ICC_tptr->next = ICC_tptr + 1; ICC_tptr++; } memset( ICC_HashTable, 0, sizeof ICC_HashTable ); ServerInit(); /* detach from our parent if necessary */ if (! (getppid() == 1) && ( ! PC_Struct.foreground_mode ) ) { syslog( LOG_INFO, "%s: Configured to run in background mode.", fn ); if ( (pid = fork()) < 0) { syslog(LOG_ERR, "%s: initial call to fork() failed: %s", fn, strerror(errno)); exit( 1 ); } else if ( pid > 0) { exit( 0 ); } if (setsid() == -1) { syslog(LOG_WARNING, "%s: setsid() failed: %s", fn, strerror(errno)); } if ( (pid = fork()) < 0) { syslog(LOG_ERR, "%s: secondary call to fork() failed: %s", fn, strerror(errno)); exit( 1 ); } else if ( pid > 0) { exit( 0 ); } } else { syslog( LOG_INFO, "%s: Configured to run in foreground mode.", fn ); } SetBannerAndCapability(); if ( PC_Struct.login_disabled || PC_Struct.force_tls ) { syslog( LOG_INFO, "%s: Enabling STARTTLS.", fn ); #if HAVE_LIBSSL if ( PC_Struct.support_starttls ) { /* Initialize SSL_CTX */ SSL_library_init(); /* Need to seed PRNG, too! */ if ( RAND_egd( ( RAND_file_name( f_randfile, sizeof( f_randfile ) ) == f_randfile ) ? f_randfile : "/.rnd" ) ) { /* Not an EGD, so read and write it. */ if ( RAND_load_file( f_randfile, -1 ) ) RAND_write_file( f_randfile ); } SSL_load_error_strings(); tls_ctx = SSL_CTX_new( TLSv1_client_method() ); if ( tls_ctx == NULL ) { syslog(LOG_ERR, "%s: Failed to create new SSL_CTX. Exiting.", fn); exit( 1 ); } /* Work around all known bugs */ SSL_CTX_set_options( tls_ctx, SSL_OP_ALL ); if ( ! SSL_CTX_load_verify_locations( tls_ctx, PC_Struct.tls_ca_file, PC_Struct.tls_ca_path ) || ! SSL_CTX_set_default_verify_paths( tls_ctx ) ) { syslog(LOG_ERR, "%s: Failed to load CA data. Exiting.", fn); exit( 1 ); } if ( ! set_cert_stuff( tls_ctx, PC_Struct.tls_cert_file, PC_Struct.tls_key_file ) ) { syslog(LOG_ERR, "%s: Failed to load cert/key data. Exiting.", fn); exit( 1 ); } SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_NONE, verify_callback); } else #endif /* HAVE_LIBSSL */ { /* We're screwed! We won't be able to login without SASL */ syslog(LOG_ERR, "%s: IMAP server has LOGINDISABLED and we can't do STARTTLS. Exiting.", fn); exit( 1 ); } } memset( (char *) &srvaddr, 0, sizeof srvaddr ); srvaddr.sin_family = PF_INET; if ( !PC_Struct.listen_addr ) { srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); } else { srvaddr.sin_addr.s_addr = inet_addr( PC_Struct.listen_addr ); if ( srvaddr.sin_addr.s_addr == -1 ) { syslog( LOG_ERR, "%s: bad bind address: '%s' specified in config file. Exiting.", fn, PC_Struct.listen_addr ); exit( 1 ); } } syslog(LOG_INFO, "%s: Binding to tcp %s:%d", fn, PC_Struct.listen_addr ? PC_Struct.listen_addr : "*", PC_Struct.listen_port ); srvaddr.sin_port = htons(PC_Struct.listen_port); listensd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if ( listensd == -1 ) { syslog(LOG_ERR, "%s: socket() failed: %s", fn, strerror(errno)); exit( 1 ); } setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag)); lingerstruct.l_onoff = 1; lingerstruct.l_linger = 5; setsockopt(listensd, SOL_SOCKET, SO_LINGER, (void *)&lingerstruct, sizeof(lingerstruct)); if ( PC_Struct.send_tcp_keepalives ) { lingerstruct.l_onoff = 1; syslog( LOG_INFO, "%s: Enabling SO_KEEPALIVE.", fn ); setsockopt( listensd, SOL_SOCKET, SO_KEEPALIVE, (void *)&lingerstruct.l_onoff, sizeof lingerstruct.l_onoff ); } if ( bind(listensd, (struct sockaddr *)&srvaddr, sizeof( srvaddr ) ) < 0 ) { syslog(LOG_ERR, "%s: bind() failed: %s", fn, strerror(errno) ); exit( 1 ); } /* * Create and mmap() our stat file while we're still root. Since it's * configurable, we want to make sure we do this as root so there's the * greatest possibility that we'll have permission to write where we * need to. */ syslog( LOG_INFO, "%s: Using global statistics file '%s'", fn, PC_Struct.stat_filename ); fd = open( PC_Struct.stat_filename, O_RDWR | O_CREAT, S_IREAD | S_IWRITE ); if ( fd == -1 ) { syslog(LOG_ERR, "%s: open() failed for '%s': %s -- Exiting.", fn, PC_Struct.stat_filename, strerror( errno ) ); exit( 1 ); } if ( ( ftruncate( fd, sizeof( IMAPCounter_Struct ) ) ) == -1 ) { syslog(LOG_ERR, "%s: ftruncate() failed: %s -- Exiting.", fn, strerror( errno ) ); exit( 1 ); } IMAPCount = ( IMAPCounter_Struct *)mmap( 0, sizeof( IMAPCounter_Struct ), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if ( IMAPCount == MAP_FAILED ) { syslog(LOG_ERR, "%s: mmap() failed: %s -- Exiting.", fn, strerror( errno ) ); exit( 1 ); } memset( IMAPCount, 0, sizeof( IMAPCounter_Struct ) ); IMAPCount->StartTime = time( 0 ); IMAPCount->CountTime = time( 0 ); if ( BecomeNonRoot() ) exit( 1 ); /* some misc thread setup */ rc = pthread_attr_init( &attr ); if ( rc ) { syslog(LOG_ERR, "%s: pthread_attr_init() failed: [%d]\n", fn, rc); exit( 1 ); } rc = pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); if ( rc ) { syslog(LOG_ERR, "%s: pthread_attr_setdetachstate() failed: [%d]\n", fn, rc); exit( 1 ); } /* launch a recycle thread before we loop */ pthread_create( &RecycleThread, &attr, (void *)ICC_Recycle_Loop, NULL ); syslog(LOG_INFO, "%s: Launched ICC recycle thread with id %d", fn, RecycleThread ); /* * Now start listening and accepting connections. */ if ( listen(listensd, MAX_CONN_BACKLOG) < 0) { syslog( LOG_ERR, "%s: listen() failed: %s -- Exiting", fn, strerror(errno)); exit( 1 ); } syslog( LOG_INFO, "%s: Normal server startup.", fn ); /* * Main server loop */ for ( ;; ) { /* * Bug fixed by Gary Mills <*****@*****.**>. I forgot * to initialize addrlen. */ addrlen = sizeof cliaddr; clientsd = accept( listensd, (struct sockaddr *)&cliaddr, &addrlen ); if ( clientsd == -1 ) { syslog(LOG_WARNING, "%s: accept() failed: %s -- retrying", fn, strerror(errno)); sleep( 1 ); continue; } #ifdef HAVE_LIBWRAP request_init(&r, RQ_DAEMON, service, 0); request_set(&r, RQ_FILE, clientsd, 0); sock_host(&r); if (!hosts_access(&r)) { shutdown(clientsd, SHUT_RDWR); close(clientsd); syslog(deny_severity, "refused connection from %s", eval_client(&r)); continue; } #endif IMAPCount->TotalClientConnectionsAccepted++; IMAPCount->CurrentClientConnections++; if ( IMAPCount->CurrentClientConnections > IMAPCount->PeakClientConnections ) IMAPCount->PeakClientConnections = IMAPCount->CurrentClientConnections; pthread_create( &ThreadId, &attr, (void *)HandleRequest, (void *)clientsd ); } }
/* * WindowProc - main window message handler */ LONG CALLBACK MainWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { WORD cmd; about_info ai; HMENU mh; CommunicationBuffer *dbginfo; switch ( msg ) { case WM_CREATE: setupSystemMenu( hwnd ); MainLBox = CreateListBox( hwnd ); mh = GetMenu( hwnd ); if( ConfigData.auto_attatch ) { CheckMenuItem( mh, MENU_AUTO_ATTATCH, MF_BYCOMMAND | MF_CHECKED ); } if( ConfigData.continue_exception ) { CheckMenuItem( mh, MENU_EXCEPTION_CONTINUE, MF_BYCOMMAND | MF_CHECKED ); } LBPrintf( MainLBox, STR_DRNT_STARTED, AppName ); break; case WM_SIZE: MoveListBox( MainLBox, 0, 0, LOWORD( lparam ), HIWORD( lparam ) ); ClearAlert(); break; case WM_SYSCOMMAND: switch( wparam ) { case MENU_LOG_CURRENT_STATE: case MENU_LOG_OPTIONS: case MENU_TASK_CTL: SendMessage( hwnd, WM_COMMAND, wparam, 0 ); break; default: return( DefWindowProc( hwnd, msg, wparam, lparam ) ); } break; case WM_COMMAND: cmd = LOWORD( wparam ); switch( cmd ) { case LISTBOX_1: break; case MENU_EXCEPTION_CONTINUE: ConfigData.continue_exception = !ConfigData.continue_exception; mh = GetMenu( hwnd ); if( ConfigData.continue_exception ) { CheckMenuItem( mh, MENU_EXCEPTION_CONTINUE, MF_BYCOMMAND | MF_CHECKED ); } else { CheckMenuItem( mh, MENU_EXCEPTION_CONTINUE, MF_BYCOMMAND | MF_UNCHECKED ); } break; case MENU_LOG_VIEW: ViewLog(); break; case MENU_NEW_TASK: CallProcCtl( MENU_NEW_TASK, NULL, NULL ); break; case MENU_AUTO_ATTATCH: ConfigData.auto_attatch = ! ConfigData.auto_attatch; mh = GetMenu( hwnd ); if( ConfigData.auto_attatch ) { CheckMenuItem( mh, MENU_AUTO_ATTATCH, MF_BYCOMMAND | MF_CHECKED ); } else { CheckMenuItem( mh, MENU_AUTO_ATTATCH, MF_BYCOMMAND | MF_UNCHECKED ); } break; case MENU_SHOW_DIP_STATUS: ShowDIPStatus( hwnd ); break; case MENU_CLEAR: ClearListBox( MainLBox ); break; case MENU_SAVE_AS: SaveListBox( SLB_SAVE_AS, SaveExtra, "", AppName, hwnd, GetListBoxHwnd( MainLBox ) ); break; case MENU_SAVE: SaveListBox( SLB_SAVE_TMP, SaveExtra, ".\\drwat.txt", AppName, hwnd, GetListBoxHwnd( MainLBox ) ); break; case MENU_FONT: if( ChooseMonoFont( hwnd ) ) { SetListBoxFont( MainLBox ); } break; case MENU_MARK: ProcessMark( hwnd, Instance, MarkPrint ); break; case MENU_ABOUT: ai.owner = hwnd; ai.inst = Instance; ai.name = AllocRCString( STR_ABOUT_NAME ); ai.version = AllocRCString( STR_ABOUT_VERSION ); ai.first_cr_year = "1993"; ai.title = AllocRCString( STR_ABOUT_TITLE ); DoAbout( &ai ); FreeRCString( ai.name ); FreeRCString( ai.version ); FreeRCString( ai.title ); break; case MENU_HELP_CONTENTS: if( !WHtmlHelp( hwnd, DR_CHM_FILE, HELP_CONTENTS, 0 ) ) { WWinHelp( hwnd, DR_HELP_FILE, HELP_CONTENTS, 0 ); } break; case MENU_HELP_SRCH: if( !WHtmlHelp( hwnd, DR_CHM_FILE, HELP_PARTIALKEY, (HELP_DATA)"" ) ) { WWinHelp( hwnd, DR_HELP_FILE, HELP_PARTIALKEY, (HELP_DATA)"" ); } break; case MENU_HELP_ON_HELP: WWinHelp( hwnd, HELP_HELP_FILE, HELP_HELPONHELP, 0 ); break; case MENU_TASK_CTL: DisplayProcList(); break; case MENU_LOG_CURRENT_STATE: MakeLog( NULL ); break; case MENU_ERASE_LOG_FILE: EraseLog(); break; case MENU_LOG_OPTIONS: SetLogOptions( hwnd ); break; case MENU_EXIT: SendMessage( hwnd, WM_CLOSE, 0, 0L ); break; default: MessageBox( hwnd, "This function is not yet available", AppName, MB_OK ); break; } break; case DR_DEBUG_EVENT: dbginfo = (CommunicationBuffer *)lparam; dbginfo->action = DebugEventHandler( &dbginfo->dbginfo ); break; case WM_COPYDATA: { COPYDATASTRUCT *copydata; copydata = (COPYDATASTRUCT *)lparam; ProcessCommandLine( copydata->lpData ); } break; case WM_CLOSE: if( QueryEnd( hwnd ) ) { SendMessage( hwnd, WM_DESTROY, 0, 0L ); } break; case WM_DESTROY: FiniListBox( MainLBox ); PutProfileInfo(); DestroyMonoFonts(); WWinHelp( hwnd, DR_HELP_FILE, HELP_QUIT, 0 ); PostQuitMessage( 0 ); break; default: return( DefWindowProc( hwnd, msg, wparam, lparam ) ); } return( 0L ); } /* WindowProc */
int main( int argc, char *argv[] ) { const char *fn = "main()"; char f_randfile[ PATH_MAX ]; int listensd; /* socket descriptor we'll bind to */ int clientsd; /* incoming socket descriptor */ int sockaddrlen; struct sockaddr_storage srvaddr; struct sockaddr_storage cliaddr; pthread_t ThreadId; /* thread id of each incoming conn */ pthread_t RecycleThread; /* used just for the recycle thread */ pthread_attr_t attr; /* generic thread attribute struct */ int rc, i, fd; unsigned int ui; struct linger lingerstruct; /* for the socket reuse stuff */ int flag; /* for the socket reuse stuff */ ICC_Struct *ICC_tptr; extern char *optarg; extern int optind; char ConfigFile[ MAXPATHLEN ]; /* path to our config file */ char PidFile[ MAXPATHLEN ]; /* path to our pidfile */ #ifdef HAVE_LIBWRAP struct request_info r; /* request struct for libwrap */ #endif struct addrinfo aihints, *ai; int gaierrnum; flag = 1; ConfigFile[0] = '\0'; strncpy( PidFile, DEFAULT_PID_FILE, sizeof PidFile -1 ); /* * Ignore signals we don't want to die from but we don't care enough * about to catch. */ signal( SIGPIPE, SIG_IGN ); signal( SIGHUP, SIG_IGN ); while (( i = getopt( argc, argv, "f:p:h" ) ) != EOF ) { switch( i ) { case 'f': /* user specified a config filename */ strncpy( ConfigFile, optarg, sizeof ConfigFile -1 ); ConfigFile[ sizeof ConfigFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using configuration file '%s'", fn, ConfigFile ); break; case 'p': /* user specified a pidfile */ strncpy( PidFile, optarg, sizeof PidFile -1 ); PidFile[ sizeof PidFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using pidfile '%s'", fn, PidFile ); break; case 'h': Usage(); exit( 0 ); case '?': Usage(); exit( 1 ); } } /* * Make sure we know which config file to use and then set our config * options. */ if ( ! ConfigFile[0] ) { strncpy( ConfigFile, DEFAULT_CONFIG_FILE, sizeof ConfigFile -1 ); ConfigFile[ sizeof ConfigFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using default configuration file '%s'.", fn, ConfigFile ); } SetDefaultConfigValues(&PC_Struct); SetConfigOptions( ConfigFile ); SetLogOptions(); /* * Just for logging purposes, are we doing SELECT caching or not? */ if ( PC_Struct.enable_select_cache ) syslog( LOG_INFO, "%s: SELECT caching is enabled", fn ); else syslog( LOG_INFO, "%s: SELECT caching is disabled", fn ); /* * Just for logging purposes, are the admin commands enabled or not? */ if ( PC_Struct.enable_admin_commands ) syslog( LOG_INFO, "%s: Internal admin commands are enabled", fn ); else syslog( LOG_INFO, "%s: Internal admin commands are disabled", fn ); #ifdef HAVE_LIBWRAP /* * Set our tcpd service name */ if (service = strrchr(argv[0], '/')) service++; else service = argv[0]; #endif /* * Initialize some stuff. */ rc = pthread_mutex_init(&mp, NULL); if ( rc ) { syslog(LOG_ERR, "%s: pthread_mutex_init() returned error [%d] initializing main mutex. Exiting.", fn, rc ); exit( 1 ); } rc = pthread_mutex_init(&trace, NULL); if ( rc ) { syslog(LOG_ERR, "%s: pthread_mutex_init() returned error [%d] initializing trace mutex. Exiting.", fn, rc ); exit( 1 ); } TraceUser[0] = '\0'; syslog( LOG_INFO, "%s: Allocating %d IMAP connection structures.", fn, PC_Struct.cache_size ); ICC_free = (ICC_Struct *)malloc( ( sizeof ( ICC_Struct ) ) * PC_Struct.cache_size ); if ( ! ICC_free ) { syslog(LOG_ERR, "%s: malloc() failed to allocate [%d] IMAPConnectionContext structures: %s", fn, PC_Struct.cache_size, strerror( errno ) ); exit( 1 ); } memset( ICC_free, 0, sizeof ( ICC_Struct ) * PC_Struct.cache_size ); ICC_tptr = ICC_free; /* * Bug fixed by Gary Mills <*****@*****.**>. I was pre-incrementing * ICC_tptr and then assigning. I guess gcc evaluates the expression * incorrectly, since I never had a problem with this. Gary had the * problem with cc, so it's fixed here. */ for ( ui = 0; ui < PC_Struct.cache_size - 1; ui++ ) { ICC_tptr->next = ICC_tptr + 1; ICC_tptr++; } memset( ICC_HashTable, 0, sizeof ICC_HashTable ); #if HAVE_LIBSSL /* Initialize SSL_CTX */ syslog( LOG_INFO, "%s: Enabling openssl library.", fn ); SSL_library_init(); /* Set up OpenSSL thread protection */ ssl_thread_setup(fn); /* Need to seed PRNG, too! */ if ( RAND_egd( ( RAND_file_name( f_randfile, sizeof( f_randfile ) ) == f_randfile ) ? f_randfile : "/.rnd" ) ) { /* Not an EGD, so read and write it. */ if ( RAND_load_file( f_randfile, -1 ) ) RAND_write_file( f_randfile ); } SSL_load_error_strings(); tls_ctx = SSL_CTX_new( TLSv1_client_method() ); if ( tls_ctx == NULL ) { syslog(LOG_ERR, "%s: Failed to create new SSL_CTX. Exiting.", fn); exit( 1 ); } /* Work around all known bugs */ SSL_CTX_set_options( tls_ctx, SSL_OP_ALL ); if ( PC_Struct.tls_ca_file != NULL || PC_Struct.tls_ca_path != NULL ) { rc = SSL_CTX_load_verify_locations( tls_ctx, PC_Struct.tls_ca_file, PC_Struct.tls_ca_path ); } else { rc = SSL_CTX_set_default_verify_paths( tls_ctx ); } if ( rc == 0 ) { syslog(LOG_ERR, "%s: Failed to load CA data. Exiting.", fn); exit( 1 ); } if ( ! set_cert_stuff( tls_ctx, PC_Struct.tls_cert_file, PC_Struct.tls_key_file ) ) { syslog(LOG_ERR, "%s: Failed to load cert/key data. Exiting.", fn); exit( 1 ); } SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_NONE, verify_callback); #endif /* HAVE_LIBSSL */ ServerInit(); /* Daemonize() would go here */ SetBannerAndCapability(); /* * We don't need to check PC_Struct.support_starttls since we * probably have refetched the capability list after a STARTTLS * if we did one; it won't ever be supported at this point. * * It also makes no difference to check PC_Struct.force_tls now * because we've either done a STARTTLS or we haven't - all that * matters is if we got LOGINDISABLED or not. * * Note that all these things *ARE* tested when checking the * server capabilities (in fact, the following check is probably * a duplicate). */ if ( PC_Struct.login_disabled ) { /* We're screwed! We can't login */ syslog(LOG_ERR, "%s: IMAP server has LOGINDISABLED. Exiting.", fn); exit( 1 ); } memset( &aihints, 0, sizeof aihints ); aihints.ai_family = AF_UNSPEC; aihints.ai_socktype = SOCK_STREAM; aihints.ai_flags = AI_PASSIVE; if ( ( gaierrnum = getaddrinfo( PC_Struct.listen_addr, PC_Struct.listen_port, &aihints, &ai ) ) ) { syslog( LOG_ERR, "%s: bad bind address: '%s' specified in config file. Exiting.", fn, PC_Struct.listen_addr ); exit( 1 ); } syslog( LOG_INFO, "%s: Binding to tcp %s:%s", fn, PC_Struct.listen_addr ? PC_Struct.listen_addr : "*", PC_Struct.listen_port ); for ( ; ai != NULL; ai = ai->ai_next ) { listensd = socket( ai->ai_family, ai->ai_socktype, ai->ai_protocol ); if ( listensd == -1 ) { syslog(LOG_WARNING, "%s: socket() failed: %s", fn, strerror(errno)); continue; } setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag)); lingerstruct.l_onoff = 1; lingerstruct.l_linger = 5; setsockopt(listensd, SOL_SOCKET, SO_LINGER, (void *)&lingerstruct, sizeof(lingerstruct)); if ( PC_Struct.send_tcp_keepalives ) { lingerstruct.l_onoff = 1; syslog( LOG_INFO, "%s: Enabling SO_KEEPALIVE.", fn ); setsockopt( listensd, SOL_SOCKET, SO_KEEPALIVE, (void *)&lingerstruct.l_onoff, sizeof lingerstruct.l_onoff ); } memcpy( &srvaddr, ai->ai_addr, ai->ai_addrlen ); if ( bind( listensd, (struct sockaddr *)&srvaddr, ai->ai_addrlen ) < 0 ) { syslog(LOG_WARNING, "%s: bind() failed: %s", fn, strerror(errno) ); continue; } else break; } if ( ai == NULL ) { syslog( LOG_ERR, "%s: no useable addresses to bind to", fn ); exit( EXIT_FAILURE); } /* * Create and mmap() our stat file while we're still root. Since it's * configurable, we want to make sure we do this as root so there's the * greatest possibility that we'll have permission to write where we * need to. */ syslog( LOG_INFO, "%s: Using global statistics file '%s'", fn, PC_Struct.stat_filename ); fd = open( PC_Struct.stat_filename, O_RDWR | O_CREAT, S_IREAD | S_IWRITE ); if ( fd == -1 ) { syslog(LOG_ERR, "%s: open() failed for '%s': %s -- Exiting.", fn, PC_Struct.stat_filename, strerror( errno ) ); exit( 1 ); } if ( ( ftruncate( fd, sizeof( IMAPCounter_Struct ) ) ) == -1 ) { syslog(LOG_ERR, "%s: ftruncate() failed: %s -- Exiting.", fn, strerror( errno ) ); exit( 1 ); } IMAPCount = ( IMAPCounter_Struct *)mmap( 0, sizeof( IMAPCounter_Struct ), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if ( IMAPCount == MAP_FAILED ) { syslog(LOG_ERR, "%s: mmap() failed: %s -- Exiting.", fn, strerror( errno ) ); exit( 1 ); } memset( IMAPCount, 0, sizeof( IMAPCounter_Struct ) ); IMAPCount->StartTime = time( 0 ); IMAPCount->CountTime = time( 0 ); /* * Daemonize as late as possible, so that connection failures can be caught * and startup aborted before dettaching from parent */ Daemonize( PidFile ); if ( BecomeNonRoot() ) exit( 1 ); /* some misc thread setup */ rc = pthread_attr_init( &attr ); if ( rc ) { syslog(LOG_ERR, "%s: pthread_attr_init() failed: [%d]\n", fn, rc); exit( 1 ); } rc = pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); if ( rc ) { syslog(LOG_ERR, "%s: pthread_attr_setdetachstate() failed: [%d]\n", fn, rc); exit( 1 ); } /* launch a recycle thread before we loop */ pthread_create( &RecycleThread, &attr, (void *)ICC_Recycle_Loop, NULL ); syslog(LOG_INFO, "%s: Launched ICC recycle thread with id %d", fn, (int)RecycleThread ); /* * Now start listening and accepting connections. */ if ( listen(listensd, MAX_CONN_BACKLOG) < 0) { syslog( LOG_ERR, "%s: listen() failed: %s -- Exiting", fn, strerror(errno)); exit( 1 ); } syslog( LOG_INFO, "%s: squirrelmail-imap_proxy version %s normal server startup.", fn, IMAP_PROXY_VERSION ); /* * Main server loop */ for ( ;; ) { /* * Bug fixed by Gary Mills <*****@*****.**>. I forgot * to initialize sockaddrlen. */ sockaddrlen = sizeof cliaddr; clientsd = accept( listensd, (struct sockaddr *)&cliaddr, &sockaddrlen ); if ( clientsd == -1 ) { syslog(LOG_WARNING, "%s: accept() failed: %s -- retrying", fn, strerror(errno)); sleep( 1 ); continue; } #ifdef HAVE_LIBWRAP request_init(&r, RQ_DAEMON, service, 0); request_set(&r, RQ_FILE, clientsd, 0); sock_host(&r); if (!hosts_access(&r)) { shutdown(clientsd, SHUT_RDWR); close(clientsd); syslog(deny_severity, "refused connection from %s", eval_client(&r)); continue; } #endif IMAPCount->TotalClientConnectionsAccepted++; IMAPCount->CurrentClientConnections++; if ( IMAPCount->CurrentClientConnections > IMAPCount->PeakClientConnections ) IMAPCount->PeakClientConnections = IMAPCount->CurrentClientConnections; rc = pthread_create( &ThreadId, &attr, (void *)HandleRequest, (void *)clientsd ); if (rc != 0) { syslog(LOG_ERR, "%s: pthread_create() returned error [%d] for HandleRequest.", fn, rc ); close(clientsd); } } }