int Condor_Auth_X509::nameGssToLocal(const char * GSSClientname) { //this might need to change with SSLK5 stuff //just extract username from /CN=<username>@<domain,etc> OM_uint32 major_status; char *tmp_user = NULL; char local_user[USER_NAME_MAX]; // windows gsi does not currently include this function. we use it on // unix, but implement our own on windows for now. #ifdef WIN32 major_status = condor_gss_assist_gridmap(GSSClientname, &tmp_user); #else // Switched the unix map function to _map_and_authorize, which allows access // to the Globus callout infrastructure. char condor_str[] = "condor"; major_status = globus_gss_assist_map_and_authorize( context_handle, condor_str, // Requested service name NULL, // Requested user name; NULL for non-specified local_user, USER_NAME_MAX-1); // Leave one space at end of buffer, just-in-case // Defensive programming: to protect against buffer overruns in the // unknown globus mapping module, make sure we are at least nul-term'd local_user[USER_NAME_MAX-1] = '\0'; #endif if (tmp_user) { strcpy( local_user, tmp_user ); free(tmp_user); tmp_user = NULL; } if ( major_status != GSS_S_COMPLETE) { setRemoteUser("gsi"); setRemoteDomain( UNMAPPED_DOMAIN ); return 0; } MyString user; MyString domain; Authentication::split_canonical_name( local_user, user, domain ); setRemoteUser (user.Value()); setRemoteDomain(domain.Value()); setAuthenticatedName(GSSClientname); return 1; }
int Condor_Auth_Anonymous :: authenticate(const char * /* remoteHost */, CondorError* /* errstack */, bool /*non_blocking*/) { int retval = 0; // very simple for right now, server just set the remote user to // be anonymous directly if ( mySock_->isClient() ) { mySock_->decode(); mySock_->code( retval ); mySock_->end_of_message(); } else { //server side setRemoteUser( STR_ANONYMOUS ); setAuthenticatedName( STR_ANONYMOUS ); mySock_->encode(); retval = 1; mySock_->code( retval ); mySock_->end_of_message(); } return retval; }
int Condor_Auth_Claim :: authenticate(const char * /* remoteHost */, CondorError* /* errstack */, bool /*non_blocking*/) { const char * pszFunction = "Condor_Auth_Claim :: authenticate"; int retval = 0; int fail = 0; if ( mySock_->isClient() ) { MyString myUser; bool error_getting_name = false; // get our user name in condor priv // (which is what we want to use for daemons. for // tools and daemons not started as root, this will // just give us the username that we were invoked // as, which is also what we want) priv_state priv = set_condor_priv(); char* tmpOwner = NULL; char* tmpSwitchUser = param("SEC_CLAIMTOBE_USER"); if(tmpSwitchUser) { tmpOwner = tmpSwitchUser; dprintf(D_ALWAYS, "SEC_CLAIMTOBE_USER to %s!\n", tmpSwitchUser); } else { tmpOwner = my_username(); } // remove temptation to use this variable to see if we were // specifying the claim to be user tmpSwitchUser = NULL; set_priv(priv); if ( !tmpOwner ) { //send 0 if (!mySock_->code( retval )) { dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); return fail; } error_getting_name = true; } else { myUser = tmpOwner; free(tmpOwner); // check SEC_CLAIMTOBE_INCLUDE_DOMAIN. this knob exists (and defaults // to false) to provide backwards compatibility. it will be removed // completely in the development (6.9) series if (param_boolean("SEC_CLAIMTOBE_INCLUDE_DOMAIN", false)) { char* tmpDomain = param("UID_DOMAIN"); if ( !tmpDomain ) { //send 0 if (!mySock_->code( retval )) { dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); return fail; } error_getting_name = true; } else { myUser += "@"; myUser += tmpDomain; free(tmpDomain); } } } if (!error_getting_name) { //send 1 and then our username mySock_->encode(); retval = 1; char* tmpUser = strdup(myUser.Value()); ASSERT(tmpUser); if (!mySock_->code( retval ) || !mySock_->code( tmpUser )) { free(tmpUser); dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); return fail; } //setRemoteUser(tmpUser); // <-- IS THIS NEEDED???? free(tmpUser); if (!mySock_->end_of_message()) { dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); return fail; } mySock_->decode(); if (!mySock_->code( retval )) { dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); return fail; } } } else { //server side mySock_->decode(); if (!mySock_->code( retval )) { dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); return fail; } //if 1, receive user and send back ok if( retval == 1 ) { char* tmpUser = NULL; if (!mySock_->code( tmpUser ) || !mySock_->end_of_message()) { dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); if (tmpUser != NULL) { free(tmpUser); } return fail; } if( tmpUser ) { MyString myUser = tmpUser; // check SEC_CLAIMTOBE_INCLUDE_DOMAIN. this knob exists (and defaults // to false) to provide backwards compatibility. it will be removed // completely in the development (6.9) series if (param_boolean("SEC_CLAIMTOBE_INCLUDE_DOMAIN", false)) { // look for an '@' char in the name we received. // if present (newer clients), set the domain using // the given component. if not present (older clients), // use UID_DOMAIN from our config char* tmpDomain = NULL; char* at = strchr(tmpUser, '@'); if ( at ) { *at = '\0'; if (*(at + 1) != '\0') { tmpDomain = strdup(at + 1); } } if (!tmpDomain) { tmpDomain = param("UID_DOMAIN"); } ASSERT(tmpDomain); setRemoteDomain(tmpDomain); myUser.formatstr("%s@%s", tmpUser, tmpDomain); free(tmpDomain); } setRemoteUser(tmpUser); setAuthenticatedName(myUser.Value()); free(tmpUser); retval = 1; } else { // tmpUser is NULL; failure retval = 0; } mySock_->encode(); if (!mySock_->code( retval )) { dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); return fail; } } } if (!mySock_->end_of_message()) { dprintf(D_SECURITY, "Protocol failure at %s, %d!\n", pszFunction, __LINE__); return fail; } return retval; }
int Condor_Auth_X509::authenticate_server_gss(CondorError* errstack) { char * GSSClientname; int status = 0; OM_uint32 major_status = 0; OM_uint32 minor_status = 0; priv_state priv; priv = set_root_priv(); major_status = globus_gss_assist_accept_sec_context(&minor_status, &context_handle, credential_handle, &GSSClientname, &ret_flags, NULL, /* don't need user_to_user */ &token_status, NULL, /* don't delegate credential */ relisock_gsi_get, (void *) mySock_, relisock_gsi_put, (void *) mySock_ ); set_priv(priv); if ( (major_status != GSS_S_COMPLETE)) { if (major_status == 655360) { errstack->pushf("GSI", GSI_ERR_AUTHENTICATION_FAILED, "COMMON Failed to authenticate (%u:%u)", (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" ); } else { // store the raw subject name for later mapping setAuthenticatedName(GSSClientname); setRemoteUser("gsi"); setRemoteDomain( UNMAPPED_DOMAIN ); 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); } } // XXX FIXME ZKM // i am making failure to be mapped a non-fatal error at this point. status = 1; mySock_->encode(); if (!mySock_->code(status) || !mySock_->end_of_message()) { errstack->push("GSI", GSI_ERR_COMMUNICATIONS_ERROR, "Failed to authenticate with client. Unable to send status"); dprintf(D_SECURITY, "Unable to send final confirmation\n"); status = 0; } if (status != 0) { // Now, see if client likes me or not mySock_->decode(); if (!mySock_->code(status) || !mySock_->end_of_message()) { errstack->push("GSI", GSI_ERR_COMMUNICATIONS_ERROR, "Failed to authenticate with client. Unable to receive status"); dprintf(D_SECURITY, "Unable to receive client confirmation.\n"); status = 0; } else { if (status == 0) { errstack->push("GSI", GSI_ERR_COMMUNICATIONS_ERROR, "Failed to authenticate with client. Client does not trust our certificate. " "You may want to check the GSI_DAEMON_NAME in the condor_config"); dprintf(D_SECURITY, "Client rejected my certificate. Please check the GSI_DAEMON_NAME parameter in Condor's config file.\n"); } } } if (GSSClientname) { free(GSSClientname); } } return (status == 0) ? FALSE : TRUE; }
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::nameGssToLocal(const char * GSSClientname) { //this might need to change with SSLK5 stuff //just extract username from /CN=<username>@<domain,etc> OM_uint32 major_status = GSS_S_COMPLETE; char *tmp_user = NULL; char local_user[USER_NAME_MAX]; // windows gsi does not currently include this function. we use it on // unix, but implement our own on windows for now. #ifdef WIN32 major_status = condor_gss_assist_gridmap(GSSClientname, &tmp_user); #else // Switched the unix map function to _map_and_authorize, which allows access // to the Globus callout infrastructure. if (m_mapping == NULL) { // Size of hash table is purposely initialized small to prevent this // from hogging memory. This will, of course, grow at large sites. m_mapping = new GlobusMappingTable(53, hashFuncString, updateDuplicateKeys); } const char *auth_name_to_map; const char *fqan = getFQAN(); if (fqan && fqan[0]) { auth_name_to_map = fqan; } else { auth_name_to_map = GSSClientname; } globus_mapping_entry_ptr value; time_t now = 0; time_t gsi_cache_expiry = param_integer("GSS_ASSIST_GRIDMAP_CACHE_EXPIRATION", 0); if (gsi_cache_expiry && (m_mapping->lookup(auth_name_to_map, value) == 0)) { now = time(NULL); if (now < value->expiry_time) { dprintf(D_SECURITY, "Using Globus mapping result from the cache.\n"); if (value->name.size()) { tmp_user = strdup(value->name.c_str()); } else { major_status = GSS_S_FAILURE; } } } if ((tmp_user == NULL) && (major_status == GSS_S_COMPLETE)) { char condor_str[] = "condor"; major_status = globus_gss_assist_map_and_authorize( context_handle, condor_str, // Requested service name NULL, // Requested user name; NULL for non-specified local_user, USER_NAME_MAX-1); // Leave one space at end of buffer, just-in-case // Defensive programming: to protect against buffer overruns in the // unknown globus mapping module, make sure we are at least nul-term'd local_user[USER_NAME_MAX-1] = '\0'; // More defensive programming: There is a bug in LCMAPS, (which is possibly // called by a globus callout) that sometimes returns with the euid set to // root (!?!). As a safeguard, We check for that here and return to the // condor euid. This is done "outside" of the condor priv stack since this // is essentially undoing a side effect of the library call, not // intentionally changing priv state. if (geteuid() == 0) { dprintf(D_ALWAYS, "WARNING: globus returned with euid 0\n"); // attempt to undo if (seteuid(get_condor_uid())) { // complain loudly, but continue dprintf(D_ALWAYS, "ERROR: something has gone terribly wrong: errno %i\n", errno); } } if (now == 0) { now = time(NULL); } value.reset(new globus_mapping_entry_t); value->expiry_time = now + gsi_cache_expiry; // The special name of "" indicates failed mapping. if (major_status == GSS_S_COMPLETE) { value->name = local_user; } m_mapping->insert(auth_name_to_map, value); } #endif if (tmp_user) { strcpy( local_user, tmp_user ); free(tmp_user); tmp_user = NULL; } if ( major_status != GSS_S_COMPLETE) { setRemoteUser("gsi"); setRemoteDomain( UNMAPPED_DOMAIN ); return 0; } MyString user; MyString domain; Authentication::split_canonical_name( local_user, user, domain ); setRemoteUser (user.Value()); setRemoteDomain(domain.Value()); setAuthenticatedName(GSSClientname); return 1; }
Condor_Auth_X509::CondorAuthX509Retval Condor_Auth_X509::authenticate_server_gss(CondorError* errstack, bool non_blocking) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 minor_status = 0; OM_uint32 time_req; gss_buffer_desc output_token_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t output_token = &output_token_desc; gss_buffer_desc input_token_desc; gss_buffer_t input_token; if ( !m_globusActivated ) { errstack->push("GSI", GSI_ERR_AUTHENTICATION_FAILED, "Failed to load Globus libraries."); return Fail; } m_state = GSSAuth; do { if (non_blocking && !mySock_->readReady()) { dprintf(D_NETWORK, "Returning to DC as read would block.\n"); return WouldBlock; } input_token_desc.length = 0; input_token_desc.value = NULL; input_token = &input_token_desc; if ((token_status = relisock_gsi_get( mySock_, &input_token->value, &input_token->length)) != 0) { major_status = GSS_S_DEFECTIVE_TOKEN | GSS_S_CALL_INACCESSIBLE_READ; break; } dprintf(D_NETWORK, "gss_assist_accept_sec_context(1):inlen:%lu\n", static_cast<unsigned long>(input_token->length)); major_status = (*gss_accept_sec_context_ptr)( &minor_status, &context_handle, credential_handle, input_token, GSS_C_NO_CHANNEL_BINDINGS, &m_client_name, NULL, output_token, &ret_flags, &time_req, NULL); dprintf(D_NETWORK, "gss_assist_accept_sec_context(2)" "maj:%8.8x:min:%8.8x:ret:%8.8x " "outlen:%lu:context:%p\n", (unsigned int) major_status, (unsigned int) minor_status, (unsigned int) ret_flags, output_token->length, context_handle); if (output_token->length != 0) { if ((token_status = relisock_gsi_put( mySock_, output_token->value, output_token->length)) != 0) { major_status = GSS_S_DEFECTIVE_TOKEN | GSS_S_CALL_INACCESSIBLE_WRITE; } (*gss_release_buffer_ptr)(&minor_status, output_token); } if (GSS_ERROR(major_status)) { if (context_handle != GSS_C_NO_CONTEXT) { (*gss_delete_sec_context_ptr)(&minor_status, &context_handle, GSS_C_NO_BUFFER); } break; } if (input_token->length >0) { free(input_token->value); input_token->length = 0; } } while (major_status & GSS_S_CONTINUE_NEEDED); if (input_token->length >0) { free(input_token->value); input_token->length = 0; } m_status = 0; if ( (major_status != GSS_S_COMPLETE)) { if (major_status == 655360) { errstack->pushf("GSI", GSI_ERR_AUTHENTICATION_FAILED, "COMMON Failed to authenticate (%u:%u)", (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" ); } else { gss_buffer_desc tmp_buffer_desc = GSS_C_EMPTY_BUFFER; gss_buffer_t tmp_buffer = &tmp_buffer_desc; char * gss_name = NULL; major_status = (*gss_display_name_ptr)(&minor_status, m_client_name, tmp_buffer, NULL); if (major_status == GSS_S_COMPLETE) { gss_name = (char *)malloc(tmp_buffer->length+1); if (gss_name) { memcpy(gss_name, tmp_buffer->value, tmp_buffer->length); gss_name[tmp_buffer->length] = '\0'; } else { errstack->pushf("GSI", GSI_ERR_AUTHENTICATION_FAILED, "Unable to allocate buffer"); major_status = GSS_S_FAILURE; } } else { errstack->pushf("GSI", GSI_ERR_AUTHENTICATION_FAILED, "Unable to determine remote client name. Globus is reporting error (%u:%u)", (unsigned)major_status, (unsigned)minor_status); } (*gss_release_buffer_ptr)(&minor_status, tmp_buffer); // store the raw subject name for later mapping if (gss_name) { setAuthenticatedName(gss_name); free(gss_name); } setRemoteUser("gsi"); setRemoteDomain( UNMAPPED_DOMAIN ); 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); } } // XXX FIXME ZKM // i am making failure to be mapped a non-fatal error at this point. m_status = (major_status == GSS_S_COMPLETE); mySock_->encode(); if (!mySock_->code(m_status) || !mySock_->end_of_message()) { errstack->push("GSI", GSI_ERR_COMMUNICATIONS_ERROR, "Failed to authenticate with client. Unable to send status"); dprintf(D_SECURITY, "Unable to send final confirmation\n"); m_status = 0; } } m_state = GetClientPost; return (m_status == 0) ? Fail : Continue; }
int Condor_Auth_SSPI::sspi_server_auth(CredHandle& cred,CtxtHandle& srvCtx) { int rc; SecPkgInfo *secPackInfo; int it_worked = FALSE; // assume failure dprintf(D_FULLDEBUG, "sspi_server_auth() entered\n" ); rc = (pf->QuerySecurityPackageInfo)( "NTLM", &secPackInfo ); TimeStamp useBefore; rc = (pf->AcquireCredentialsHandle)( NULL, "NTLM", SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &cred, &useBefore ); // input and output buffers SecBufferDesc obd, ibd; SecBuffer ob, ib; DWORD ctxAttr; bool haveContext = false; while ( 1 ) { // prepare to get the server's response ibd.ulVersion = SECBUFFER_VERSION; ibd.cBuffers = 1; ibd.pBuffers = &ib; // just one buffer ib.BufferType = SECBUFFER_TOKEN; // preping a token here // receive the client's POD ib.pvBuffer = NULL; mySock_->decode(); if ( !mySock_->code(ib.cbBuffer) || !mySock_->end_of_message() || !(ib.pvBuffer = LocalAlloc( 0, ib.cbBuffer )) || !mySock_->get_bytes((char *) ib.pvBuffer, ib.cbBuffer) || !mySock_->end_of_message() ) { dprintf(D_ALWAYS, "ERROR sspi_server_auth() failed to received client POD\n"); if ( ib.pvBuffer ) { LocalFree( ib.pvBuffer ); ib.pvBuffer = NULL; } (pf->FreeContextBuffer)( secPackInfo ); return 0; } // by now we have an input buffer obd.ulVersion = SECBUFFER_VERSION; obd.cBuffers = 1; obd.pBuffers = &ob; // just one buffer ob.BufferType = SECBUFFER_TOKEN; // preping a token here ob.cbBuffer = secPackInfo->cbMaxToken; ob.pvBuffer = LocalAlloc( 0, ob.cbBuffer ); rc = (pf->AcceptSecurityContext)( &cred, haveContext? &srvCtx: NULL, &ibd, 0, SECURITY_NATIVE_DREP, &srvCtx, &obd, &ctxAttr, &useBefore ); if ( ib.pvBuffer != NULL ) { LocalFree( ib.pvBuffer ); ib.pvBuffer = NULL; } if ( rc == SEC_I_COMPLETE_AND_CONTINUE || rc == SEC_I_COMPLETE_NEEDED ) { if ( pf->CompleteAuthToken != NULL ) // only if implemented (pf->CompleteAuthToken)( &srvCtx, &obd ); if ( rc == SEC_I_COMPLETE_NEEDED ) rc = SEC_E_OK; else if ( rc == SEC_I_COMPLETE_AND_CONTINUE ) rc = SEC_I_CONTINUE_NEEDED; } // send the output buffer off to the server if ( ob.cbBuffer != 0 ) { mySock_->encode(); if ( !mySock_->code(ob.cbBuffer) || !mySock_->end_of_message() || !mySock_->put_bytes( (const char *) ob.pvBuffer, ob.cbBuffer ) || !mySock_->end_of_message() ) { dprintf(D_ALWAYS, "ERROR sspi_server_auth() failed to send output blob\n"); LocalFree( ob.pvBuffer ); ob.pvBuffer = NULL; (pf->FreeContextBuffer)( secPackInfo ); return 0; } } LocalFree( ob.pvBuffer ); ob.pvBuffer = NULL; if ( rc != SEC_I_CONTINUE_NEEDED ) break; haveContext = true; // loop back for another round dprintf(D_FULLDEBUG,"sspi_server_auth() looping\n"); } // we arrive here as soon as InitializeSecurityContext() // returns != SEC_I_CONTINUE_NEEDED. if ( rc != SEC_E_OK ) { dprintf( D_ALWAYS,"sspi_server_auth(): Oops! ASC() returned %d!\n", rc ); } // now we try to use the context to Impersonate and thereby get the login rc = (pf->ImpersonateSecurityContext)( &srvCtx ); char buf[256]; char *dom = NULL; DWORD bufsiz = sizeof buf; if ( rc != SEC_E_OK ) { dprintf( D_ALWAYS, "sspi_server_auth(): Failed to impersonate (returns %d)!\n", rc ); } else { // PLEASE READ: We're now running in the context of the // client we're impersonating. This means dprintf()'ing is // OFF LIMITS until we RevertSecurityContext(), since the // dprintf() will likely fail because the client // probably will not have write access to the log file. GetUserName( buf, &bufsiz ); dom = my_domainname(); // revert as soon as possible. (pf->RevertSecurityContext)( &srvCtx ); // Ok, safe to dprintf() now... it_worked = TRUE; setRemoteUser(buf); setRemoteDomain(dom); // set authenticated name used for mapping MyString auth_name; auth_name = buf; if(dom) { auth_name += "@"; auth_name += dom; } setAuthenticatedName(auth_name.Value()); dprintf( D_FULLDEBUG, "sspi_server_auth(): user name is: \"%s\"\n", buf ); if (dom) { dprintf( D_FULLDEBUG, "sspi_server_auth(): domain name is: \"%s\"\n", dom); free(dom); } } (pf->FreeContextBuffer)( secPackInfo ); dprintf( D_FULLDEBUG,"sspi_server_auth() exiting\n" ); // return success (1) or failure (0) return it_worked; }
int Condor_Auth_Kerberos :: map_kerberos_name(krb5_principal * princ_to_map) { krb5_error_code code; char * client = NULL; //------------------------------------------ // Decode the client name //------------------------------------------ if ((code = krb5_unparse_name(krb_context_, *princ_to_map, &client))){ dprintf(D_ALWAYS, "%s\n", error_message(code)); return FALSE; } else { dprintf( D_SECURITY, "KERBEROS: krb5_unparse_name: %s\n", client ); char * user = 0; char * at_sign = strchr(client, '@'); // first, see if the principal up to the @ sign is the same as // STR_KERBEROS_SERVER_PRINCIPAL char * server_princ = param(STR_KERBEROS_SERVER_PRINCIPAL); if (server_princ) { dprintf ( D_SECURITY, "KERBEROS: param server princ: %s\n", server_princ ); if (strcmp(client, server_princ) == 0) { user = param(STR_KERBEROS_SERVER_USER); if (user) { dprintf ( D_SECURITY, "KERBEROS: mapped to user: %s\n", user ); } } } if (!user) { dprintf ( D_SECURITY, "KERBEROS: no user yet determined, will grab up to slash\n" ); char * tmp; if ((tmp = strchr( client, '/')) == NULL) { tmp = at_sign; } int user_len = tmp - client; user = (char*) malloc( user_len + 1 ); ASSERT( user ); strncpy ( user, client, user_len ); user[user_len] = '\0'; dprintf ( D_SECURITY, "KERBEROS: picked user: %s\n", user ); } char * service = 0; service = param(STR_KERBEROS_SERVER_SERVICE); if (!service) { service = strdup(STR_DEFAULT_CONDOR_SERVICE); } // hack for now - map the "host" user to the condor user if ((strcmp(user, service) == 0)) { free(user); user = param(STR_KERBEROS_SERVER_USER); if (!user) { user = strdup(STR_DEFAULT_CONDOR_USER); } dprintf ( D_SECURITY, "KERBEROS: remapping '%s' to '%s'\n", service, user ); } setRemoteUser(user); setAuthenticatedName(client); free(user); user = 0; free(service); service = 0; free(server_princ); if (!map_domain_name(at_sign+1)) { return FALSE; } dprintf(D_SECURITY, "Client is %s@%s\n", getRemoteUser(), getRemoteDomain()); } return TRUE; }