int Condor_Auth_Kerberos :: authenticate(const char * /* remoteHost */, CondorError* /* errstack */, bool /*non_blocking*/) { int status = 0; if ( mySock_->isClient() ) { // we are the client. // initialize everything if needed. if (init_kerberos_context() && init_server_info()) { if (isDaemon() || get_mySubSystem()->isDaemon() ) { status = init_daemon(); } else { status = init_user(); } } else { status = FALSE; } int message = (status == TRUE? KERBEROS_PROCEED : KERBEROS_ABORT); mySock_->encode(); if (!mySock_->code(message) || !mySock_->end_of_message()) { status = FALSE; } else { if (message == KERBEROS_PROCEED) { // We are ready to go status = authenticate_client_kerberos(); } else { status = FALSE; } } } else { // we are the server. int ready; mySock_->decode(); if (!mySock_->code(ready) || !mySock_->end_of_message()) { status = FALSE; } else { if (ready == KERBEROS_PROCEED) { dprintf(D_SECURITY,"About to authenticate client using Kerberos\n" ); // initialize everything if needed. if (init_kerberos_context() && init_server_info()) { status = authenticate_server_kerberos(); } else { status = FALSE; } } } } return( status ); }
/* * listener_spawn is responsible for creating a Listener class * and launching the listener. It is provided as a means for * the C thread subsystem to launch the listener C++ object. */ void listener_spawn( thread_Settings *thread ) { Listener *theListener = NULL; // start up a listener theListener = new Listener( thread ); #ifndef WIN32 // handling of daemon mode in non-win32 builds if ( isDaemon( thread ) ) { theListener->runAsDaemon("iperf",LOG_DAEMON); } #endif // Start listening theListener->Run(); DELETE_PTR( theListener ); }
/* ------------------------------------------------------------------- * main() * Entry point into Iperf * * sets up signal handlers * initialize global locks and conditions * parses settings from environment and command line * starts up server or client thread * waits for all threads to complete * ------------------------------------------------------------------- */ int main( int argc, char **argv ) { #ifdef WIN32 // Start winsock WSADATA wsaData; int rc; #endif // Set SIGTERM and SIGINT to call our user interrupt function my_signal( SIGTERM, Sig_Interupt ); my_signal( SIGINT, Sig_Interupt ); #ifndef WIN32 // SIGALRM=14, _NSIG=3... my_signal( SIGALRM, Sig_Interupt ); #endif #ifndef WIN32 // Ignore broken pipes signal(SIGPIPE,SIG_IGN); #endif #ifdef WIN32 // Start winsock rc = WSAStartup( 0x202, &wsaData ); WARN_errno( rc == SOCKET_ERROR, "WSAStartup" ); if (rc == SOCKET_ERROR) return 0; // Tell windows we want to handle our own signals SetConsoleCtrlHandler( sig_dispatcher, true ); #endif // Initialize global mutexes and conditions Condition_Initialize ( &ReportCond ); Condition_Initialize ( &ReportDoneCond ); Mutex_Initialize( &groupCond ); Mutex_Initialize( &clients_mutex ); // Initialize the thread subsystem thread_init( ); // Initialize the interrupt handling thread to 0 sThread = thread_zeroid(); // perform any cleanup when quitting Iperf atexit( cleanup ); // Allocate the "global" settings thread_Settings* ext_gSettings = new thread_Settings; // Initialize settings to defaults Settings_Initialize( ext_gSettings ); // read settings from environment variables Settings_ParseEnvironment( ext_gSettings ); // read settings from command-line parameters Settings_ParseCommandLine( argc, argv, ext_gSettings ); // Check for either having specified client or server if ( ext_gSettings->mThreadMode == kMode_Client || ext_gSettings->mThreadMode == kMode_Listener ) { #ifdef WIN32 // Start the server as a daemon // Daemon mode for non-windows in handled // in the listener_spawn function if ( isDaemon( ext_gSettings ) ) { CmdInstallService(argc, argv); return 0; } // Remove the Windows service if requested if ( isRemoveService( ext_gSettings ) ) { // remove the service if ( CmdRemoveService() ) { fprintf(stderr, "IPerf Service is removed.\n"); return 0; } } #endif // initialize client(s) if ( ext_gSettings->mThreadMode == kMode_Client ) { client_init( ext_gSettings ); } #ifdef HAVE_THREAD // start up the reporter and client(s) or listener { thread_Settings *into = NULL; // Create the settings structure for the reporter thread Settings_Copy( ext_gSettings, &into ); into->mThreadMode = kMode_Reporter; // Have the reporter launch the client or listener into->runNow = ext_gSettings; // Start all the threads that are ready to go thread_start( into ); } #else // No need to make a reporter thread because we don't have threads thread_start( ext_gSettings ); #endif } else { // neither server nor client mode was specified // print usage and exit #ifdef WIN32 // In Win32 we also attempt to start a previously defined service // Starting in 2.0 to restart a previously defined service // you must call iperf with "iperf -D" or using the environment variable SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, { NULL, NULL} }; // Only attempt to start the service if "-D" was specified if ( !isDaemon(ext_gSettings) || // starting the service by SCM, there is no arguments will be passed in. // the arguments will pass into Service_Main entry. !StartServiceCtrlDispatcher(dispatchTable) ) // If the service failed to start then print usage #endif fprintf( stderr, usage_short, argv[0], argv[0] ); return 0; } // wait for other (client, server) threads to complete thread_joinall(); // all done! return 0; } // end main
/* ------------------------------------------------------------------- * main() * Entry point into Iperf * * sets up signal handlers * initialize global locks and conditions * parses settings from environment and command line * starts up server or client thread * waits for all threads to complete * ------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" #endif /* __cplusplus */ int IPERF_MAIN( int argc, char **argv ) { #ifdef NO_EXIT should_exit = 0; #endif /* NO_EXIT */ #ifdef IPERF_DEBUG debug_init(); #endif /* IPERF_DEBUG */ #ifndef NO_INTERRUPTS #ifdef WIN32 setsigalrmfunc(call_sigalrm); #endif /* WIN32 */ // Set SIGTERM and SIGINT to call our user interrupt function my_signal( SIGTERM, Sig_Interupt ); my_signal( SIGINT, Sig_Interupt ); my_signal( SIGALRM, Sig_Interupt ); #ifndef WIN32 // Ignore broken pipes signal(SIGPIPE,SIG_IGN); #else // Start winsock WORD wVersionRequested; WSADATA wsaData; // Using MAKEWORD macro, Winsock version request 2.2 wVersionRequested = MAKEWORD(2, 2); int rc = WSAStartup( wVersionRequested, &wsaData ); WARN_errno( rc == SOCKET_ERROR, ( "WSAStartup failed.\n" ) ); if (rc != 0) { fprintf(stderr, "The Winsock DLL was not found!\n"); return 1; } /* * Confirm that the WinSock DLL supports 2.2. Note that if the DLL supports * versions greater than 2.2 in addition to 2.2, it will still return 2.2 in * wVersion since that is the version we requested. */ if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) { /* Tell the user that we could not find a usable WinSock DLL. */ fprintf(stderr, "The DLL does not support the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion)); WSACleanup(); return 1; } // Tell windows we want to handle our own signals SetConsoleCtrlHandler( sig_dispatcher, true ); #endif /* WIN32 */ #endif /* NO_INTERRUPTS */ // Initialize global mutexes and conditions IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Initializing report condition.\n" ) ); Condition_Initialize ( &ReportCond ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Initializing report done condition.\n" ) ); Condition_Initialize ( &ReportDoneCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Initializing group condition mutex.\n" ) ); Mutex_Initialize( &groupCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Initializing clients mutex.\n" ) ); Mutex_Initialize( &clients_mutex ); // Initialize the thread subsystem IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Initializing the thread subsystem.\n" ) ); thread_init( ); // Initialize the interrupt handling thread to 0 sThread = thread_zeroid(); #ifndef NO_EXIT // perform any cleanup when quitting Iperf atexit( cleanup ); #endif /* NO_EXIT */ // Allocate the "global" settings thread_Settings *ext_gSettings = (thread_Settings*) malloc( sizeof( thread_Settings ) ); FAIL( ext_gSettings == NULL, ( "Unable to allocate memory for thread_Settings ext_gSettings.\n" ), NULL ); IPERF_DEBUGF( MEMALLOC_DEBUG, IPERF_MEMALLOC_MSG( ext_gSettings, sizeof( thread_Settings ) ) ); // Initialize settings to defaults Settings_Initialize( ext_gSettings ); #ifndef NO_ENVIRONMENT // read settings from environment variables Settings_ParseEnvironment( ext_gSettings ); #endif /* NO_ENVIORNMENT */ // read settings from command-line parameters Settings_ParseCommandLine( argc, argv, ext_gSettings ); #ifdef NO_EXIT if (should_exit) { IPERF_DEBUGF( MEMFREE_DEBUG | IPERF_DBG_TRACE, IPERF_MEMFREE_MSG( ext_gSettings ) ); FREE_PTR( ext_gSettings ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Destroying report condition.\n" ) ); Condition_Destroy( &ReportCond ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Destroying report done condition.\n" ) ); Condition_Destroy( &ReportDoneCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Destroying group condition mutex.\n" ) ); Mutex_Destroy( &groupCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Destroying clients mutex.\n" ) ); Mutex_Destroy( &clients_mutex ); return 0; } #endif /* NO_EXIT */ // Check for either having specified client or server if ( ext_gSettings->mThreadMode == kMode_Client || ext_gSettings->mThreadMode == kMode_Listener ) { #ifdef WIN32 #ifndef NO_DAEMON // Start the server as a daemon // Daemon mode for non-windows in handled // in the listener_spawn function if ( isDaemon( ext_gSettings ) ) { CmdInstallService(argc, argv); return 0; } #endif /* NO_DAEMON */ #ifndef NO_SERVICE // Remove the Windows service if requested if ( isRemoveService( ext_gSettings ) ) { // remove the service if ( CmdRemoveService() ) { fprintf(stderr, "IPerf Service is removed.\n"); return 0; } } #endif /* NO_SERVICE */ #endif /* WIN32 */ // initialize client(s) if ( ext_gSettings->mThreadMode == kMode_Client ) { IPERF_DEBUGF( CLIENT_DEBUG | LISTENER_DEBUG | IPERF_DBG_TRACE, ( "Initializing client(s)...\n" ) ); client_init( ext_gSettings ); } #ifdef HAVE_THREAD // start up the reporter and client(s) or listener thread_Settings *into = NULL; // Create the settings structure for the reporter thread IPERF_DEBUGF( CLIENT_DEBUG | LISTENER_DEBUG | REPORTER_DEBUG | IPERF_DBG_TRACE, ( "Creating the settings structure for the reporter thread.\n" ) ); Settings_Copy( ext_gSettings, &into ); into->mThreadMode = kMode_Reporter; // Have the reporter launch the client or listener IPERF_DEBUGF( CLIENT_DEBUG | LISTENER_DEBUG | IPERF_DBG_TRACE, ( "Setting the reporter to launch the client or listener before launching itself.\n" ) ); into->runNow = ext_gSettings; // Start all the threads that are ready to go IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Starting all the threads...\n" ) ); thread_start( into ); #else // No need to make a reporter thread because we don't have threads IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Starting iperf in a single thread...\n" ) ); thread_start( ext_gSettings ); #endif /* HAVE_THREAD */ } else { // neither server nor client mode was specified // print usage and exit #ifdef WIN32 // In Win32 we also attempt to start a previously defined service // Starting in 2.0 to restart a previously defined service // you must call iperf with "iperf -D" or using the environment variable SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT((char *) SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, { NULL, NULL} }; #ifndef NO_DAEMON // Only attempt to start the service if "-D" was specified if ( !isDaemon(ext_gSettings) || // starting the service by SCM, there is no arguments will be passed in. // the arguments will pass into Service_Main entry. !StartServiceCtrlDispatcher(dispatchTable) ) // If the service failed to start then print usage #endif /* NO_DAEMON */ #endif /* WIN32 */ fprintf( stderr, usage_short, argv[0], argv[0] ); return 0; } // wait for other (client, server) threads to complete // IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Waiting for other (client, server) threads to complete...\n" ) ); // thread_joinall(); #ifdef NO_EXIT /* We can't run the atexit function */ #ifdef WIN32 // Shutdown Winsock WSACleanup(); #endif /* WIN32 */ // clean up the list of clients Iperf_destroy ( &clients ); // shutdown the thread subsystem IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Deinitializing the thread subsystem.\n" ) ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Destroying report condition.\n" ) ); Condition_Destroy( &ReportCond ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Destroying report done condition.\n" ) ); Condition_Destroy( &ReportDoneCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Destroying group condition mutex.\n" ) ); Mutex_Destroy( &groupCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Destroying clients mutex.\n" ) ); Mutex_Destroy( &clients_mutex ); #ifdef IPERF_DEBUG debug_init(); #endif /* IPERF_DEBUG */ #endif /* NO_EXIT */ // all done! IPERF_DEBUGF( IPERF_DBG_TRACE | IPERF_DBG_STATE, ( "Done!\n" ) ); return 0; } // end main
int Condor_Auth_X509::authenticate_client_gss(CondorError* errstack) { OM_uint32 major_status = 0; OM_uint32 minor_status = 0; int status = 0; priv_state priv = PRIV_UNKNOWN; if (isDaemon()) { priv = set_root_priv(); } char target_str[] = "GSI-NO-TARGET"; major_status = globus_gss_assist_init_sec_context(&minor_status, credential_handle, &context_handle, target_str, GSS_C_MUTUAL_FLAG, &ret_flags, &token_status, relisock_gsi_get, (void *) mySock_, relisock_gsi_put, (void *) mySock_ ); if (isDaemon()) { set_priv(priv); } if (major_status != GSS_S_COMPLETE) { if (major_status == 655360 && minor_status == 6) { errstack->pushf("GSI", GSI_ERR_AUTHENTICATION_FAILED, "Failed to authenticate. Globus is reporting error (%u:%u). " "This indicates that it was unable to find the issuer " "certificate for your credential", (unsigned)major_status, (unsigned)minor_status); } else if (major_status == 655360 && minor_status == 9) { errstack->pushf("GSI", GSI_ERR_AUTHENTICATION_FAILED, "Failed to authenticate. Globus is reporting error (%u:%u). " "This indicates that it was unable to verify the server's " "credential", (unsigned)major_status, (unsigned)minor_status); } else if (major_status == 655360 && minor_status == 11) { errstack->pushf("GSI", GSI_ERR_AUTHENTICATION_FAILED, "Failed to authenticate. Globus is reporting error (%u:%u). " "This indicates that it was unable verify the server's " "credentials because a signing policy file was not found or " "could not be read.", (unsigned)major_status, (unsigned)minor_status); } else { errstack->pushf("GSI", GSI_ERR_AUTHENTICATION_FAILED, "Failed to authenticate. Globus is reporting error (%u:%u)", (unsigned)major_status, (unsigned)minor_status); } print_log(major_status,minor_status,token_status, "Condor GSI authentication failure"); // Following four lines of code is added to temporarily // resolve a bug (I belive so) in Globus's GSI code. // basically, if client calls init_sec_context with // mutual authentication and it returns with a mismatched // target principal, init_sec_context will return without // sending the server any token. The sever, therefore, // hangs on waiting for the token (or until the timeout // occurs). This code will force the server to break out // the loop. status = 0; mySock_->encode(); mySock_->code(status); mySock_->end_of_message(); } else { // Now, wait for final signal mySock_->decode(); if (!mySock_->code(status) || !mySock_->end_of_message()) { errstack->push("GSI", GSI_ERR_COMMUNICATIONS_ERROR, "Failed to authenticate with server. Unable to receive server status"); dprintf(D_SECURITY, "Unable to receive final confirmation for GSI Authentication!\n"); } if (status == 0) { errstack->push("GSI", GSI_ERR_AUTHENTICATION_FAILED, "Failed to get authorization from server. Either the server " "does not trust your certificate, or you are not in the server's " "authorization file (grid-mapfile)"); dprintf(D_SECURITY, "Server is unable to authorize my user name. Check the GRIDMAP file on the server side.\n"); goto clear; } char * server = get_server_info(); // store the raw subject name for later mapping setAuthenticatedName(server); // Default to user name "gsi@unmapped". // Later on, if configured, we will invoke the callout in nameGssToLocal. setRemoteUser("gsi"); setRemoteDomain( UNMAPPED_DOMAIN ); // extract and store VOMS attributes if (param_boolean("USE_VOMS_ATTRIBUTES", true)) { // get the voms attributes from the peer globus_gsi_cred_handle_t peer_cred = context_handle->peer_cred_handle->cred_handle; char * voms_fqan = NULL; int voms_err = extract_VOMS_info(peer_cred, 1, NULL, NULL, &voms_fqan); if (!voms_err) { setFQAN(voms_fqan); free(voms_fqan); } else { // complain! dprintf(D_SECURITY, "ZKM: VOMS FQAN not present (error %i), ignoring.\n", voms_err); } } std::string fqh = get_full_hostname(mySock_->peer_addr()); StringList * daemonNames = getDaemonList("GSI_DAEMON_NAME",fqh.c_str()); // Now, let's see if the name is in the list, I am not using // anycase here, so if the host name and what we are looking for // are in different cases, then we will run into problems. if( daemonNames ) { status = daemonNames->contains_withwildcard(server) == TRUE? 1 : 0; if( !status ) { errstack->pushf("GSI", GSI_ERR_UNAUTHORIZED_SERVER, "Failed to authenticate because the subject '%s' is not currently trusted by you. " "If it should be, add it to GSI_DAEMON_NAME or undefine GSI_DAEMON_NAME.", server); dprintf(D_SECURITY, "GSI_DAEMON_NAME is defined and the server %s is not specified in the GSI_DAEMON_NAME parameter\n", server); } } else { status = CheckServerName(fqh.c_str(),mySock_->peer_ip_str(),mySock_,errstack); } if (status) { dprintf(D_SECURITY, "valid GSS connection established to %s\n", server); } mySock_->encode(); if (!mySock_->code(status) || !mySock_->end_of_message()) { errstack->push("GSI", GSI_ERR_COMMUNICATIONS_ERROR, "Failed to authenticate with server. Unable to send status"); dprintf(D_SECURITY, "Unable to mutually authenticate with server!\n"); status = 0; } delete [] server; delete daemonNames; } clear: return (status == 0) ? FALSE : TRUE; }
int Condor_Auth_X509::authenticate_self_gss(CondorError* errstack) { OM_uint32 major_status; OM_uint32 minor_status; char comment[1024]; if ( credential_handle != GSS_C_NO_CREDENTIAL ) { // user already auth'd dprintf( D_FULLDEBUG, "This process has a valid certificate & key\n" ); return TRUE; } // ensure all env vars are in place, acquire cred will fail otherwise //use gss-assist to verify user (not connection) //this method will prompt for password if private key is encrypted! int time = mySock_->timeout(60 * 5); //allow user 5 min to type passwd priv_state priv = PRIV_UNKNOWN; //if ((!mySock_->isClient() && { if (isDaemon()) { priv = set_root_priv(); } major_status = globus_gss_assist_acquire_cred(&minor_status, GSS_C_BOTH, &credential_handle); if (major_status != GSS_S_COMPLETE) { major_status = globus_gss_assist_acquire_cred(&minor_status, GSS_C_BOTH, &credential_handle); } //if (!mySock_->isClient() || isDaemon()) { if (isDaemon()) { set_priv(priv); } mySock_->timeout(time); //put it back to what it was before if (major_status != GSS_S_COMPLETE) { if (major_status == 851968 && minor_status == 20) { errstack->pushf("GSI", GSI_ERR_NO_VALID_PROXY, "Failed to authenticate. Globus is reporting error (%u:%u). " "This indicates that you do not have a valid user proxy. " "Run grid-proxy-init.", (unsigned)major_status, (unsigned)minor_status); } else if (major_status == 851968 && minor_status == 12) { errstack->pushf("GSI", GSI_ERR_NO_VALID_PROXY, "Failed to authenticate. Globus is reporting error (%u:%u). " "This indicates that your user proxy has expired. " "Run grid-proxy-init.", (unsigned)major_status, (unsigned)minor_status); } else { errstack->pushf("GSI", GSI_ERR_ACQUIRING_SELF_CREDINTIAL_FAILED, "Failed to authenticate. Globus is reporting error (%u:%u). There is probably a problem with your credentials. (Did you run grid-proxy-init?)", (unsigned)major_status, (unsigned)minor_status); } sprintf(comment,"authenticate_self_gss: acquiring self credentials failed. Please check your Condor configuration file if this is a server process. Or the user environment variable if this is a user process. \n"); print_log( major_status,minor_status,0,comment); credential_handle = GSS_C_NO_CREDENTIAL; return FALSE; } dprintf( D_FULLDEBUG, "This process has a valid certificate & key\n" ); return TRUE; }