void initialize_uids(void) { #if defined(WIN32) #include "my_username.h" char *name = NULL; char *domain = NULL; name = my_username(); domain = my_domainname(); caller_name = name; job_user_name = name; if ( !init_user_ids(name, domain ) ) { // shouldn't happen - we always can get our own token vmprintf(D_ALWAYS, "Could not initialize user_priv with our own token!\n"); } vmprintf(D_ALWAYS, "Initialize Uids: caller=%s@%s, job user=%s@%s\n", caller_name.Value(), domain, job_user_name.Value(), domain); if( name ) { free(name); } if( domain ) { free(domain); } return; #else // init_user_ids was called in main_pre_dc_init() vmprintf(D_ALWAYS, "Initial UID/GUID=%d/%d, EUID/EGUID=%d/%d, " "Condor UID/GID=%d,%d\n", (int)getuid(), (int)getuid(), (int)geteuid(), (int)getegid(), (int)get_condor_uid(), (int)get_condor_gid()); vmprintf(D_ALWAYS, "Initialize Uids: caller=%s, job user=%s\n", caller_name.Value(), job_user_name.Value()); return; #endif }
Qmgr_connection * ConnectQ(const char *qmgr_location, int timeout, bool read_only, CondorError* errstack, const char *effective_owner, const char* schedd_version_str ) { int rval, ok; int cmd = read_only ? QMGMT_READ_CMD : QMGMT_WRITE_CMD; // do we already have a connection active? if( qmgmt_sock ) { // yes; reject new connection (we can only handle one at a time) return( NULL ); } // set up the error handling so it will clean up automatically on // return. also allow them to specify their own stack. CondorError our_errstack; CondorError* errstack_select = &our_errstack; if (errstack) { errstack_select = errstack; } // no connection active as of now; create a new one Daemon d( DT_SCHEDD, qmgr_location ); if( ! d.locate() ) { ok = FALSE; if( qmgr_location ) { dprintf( D_ALWAYS, "Can't find address of queue manager %s\n", qmgr_location ); } else { dprintf( D_ALWAYS, "Can't find address of local queue manager\n" ); } } else { // QMGMT_WRITE_CMD didn't exist before 7.5.0, so use QMGMT_READ_CMD // when talking to older schedds if( cmd == QMGMT_WRITE_CMD ) { if( !schedd_version_str ) schedd_version_str = d.version(); if( !schedd_version_str ) { // Some day when we don't care about compatibility with // things from before 7.5.0, we could stop defaulting // to QMGMT_READ_CMD here. cmd = QMGMT_READ_CMD; } else { CondorVersionInfo ver_info(schedd_version_str); if( !ver_info.built_since_version(7,5,0) ) { cmd = QMGMT_READ_CMD; } } } qmgmt_sock = (ReliSock*) d.startCommand( cmd, Stream::reli_sock, timeout, errstack_select); ok = qmgmt_sock != NULL; if( !ok && !errstack) { dprintf(D_ALWAYS, "Can't connect to queue manager: %s\n", errstack_select->getFullText().c_str() ); } } if( !ok ) { if( qmgmt_sock ) delete qmgmt_sock; qmgmt_sock = NULL; return 0; } // If security negotiation is turned off and we are using WRITE_CMD, // then we must force authentication now, before trying to initialize // the connection, because this command is registered with // force_authentication=true on the server side. if( cmd == QMGMT_WRITE_CMD && !qmgmt_sock->triedAuthentication()) { if( !SecMan::authenticate_sock(qmgmt_sock, CLIENT_PERM, errstack_select ) ) { delete qmgmt_sock; qmgmt_sock = NULL; if (!errstack) { dprintf( D_ALWAYS, "Authentication Error: %s\n", errstack_select->getFullText().c_str() ); } return 0; } } // This could be a problem char *username = my_username(); char *domain = my_domainname(); if ( !username ) { dprintf(D_FULLDEBUG,"Failure getting my_username()\n"); delete qmgmt_sock; qmgmt_sock = NULL; if (domain) free(domain); return( 0 ); } /* Get the schedd to handle Q ops. */ /* Get rid of all the code below */ if (read_only || !qmgmt_sock->triedAuthentication()) { if ( read_only ) { rval = InitializeReadOnlyConnection( username ); } else { rval = InitializeConnection( username, domain ); } if (username) { free(username); username = NULL; } if (domain) { free(domain); domain = NULL; } if (rval < 0) { delete qmgmt_sock; qmgmt_sock = NULL; return 0; } if ( !read_only ) { if (!SecMan::authenticate_sock(qmgmt_sock, CLIENT_PERM, errstack_select)) { delete qmgmt_sock; qmgmt_sock = NULL; if (!errstack) { dprintf( D_ALWAYS, "Authentication Error: %s\n", errstack_select->getFullText().c_str() ); } return 0; } } } if (username) free(username); if (domain) free(domain); if( effective_owner && *effective_owner ) { if( QmgmtSetEffectiveOwner( effective_owner ) != 0 ) { if( errstack ) { errstack->pushf( "Qmgmt",SCHEDD_ERR_SET_EFFECTIVE_OWNER_FAILED, "SetEffectiveOwner(%s) failed with errno=%d: %s.", effective_owner, errno, strerror(errno) ); } else { dprintf( D_ALWAYS, "SetEffectiveOwner(%s) failed with errno=%d: %s.\n", effective_owner, errno, strerror(errno) ); } delete qmgmt_sock; qmgmt_sock = NULL; return 0; } } return &connection; }
bool JobInfoCommunicator::initUserPrivWindows( void ) { // Win32 // taken origionally from OsProc::StartJob. Here we create the // user and initialize user_priv. // By default, assume execute login may be shared by other processes. setExecuteAccountIsDedicated( NULL ); // we support running the job as other users if the user // is specifed in the config file, and the account's password // is properly stored in our credential stash. char *name = NULL; char *domain = NULL; bool init_priv_succeeded = true; bool run_as_owner = allowRunAsOwner( false, false ); // TODO.. // Currently vmgahp for VMware VM universe can't run as user on Windows. // It seems like a bug of VMware. VMware command line tool such as "vmrun" // requires Administrator privilege. // So here we set name and domain with my_username and my_domainname // -jaeyoung 06/15/07 if( job_universe == CONDOR_UNIVERSE_VM ) { #if 0 // If "VM_UNIV_NOBODY_USER" is defined in Condor configuration file, // wee will use it. char *vm_jobs_as = param("VM_UNIV_NOBODY_USER"); if (vm_jobs_as) { getDomainAndName(vm_jobs_as, domain, name); /* * name and domain are now just pointers into vm_jobs_as * buffer. copy these values into their own buffer so we * deallocate below. */ if ( name ) { name = strdup(name); } if ( domain ) { domain = strdup(domain); } free(vm_jobs_as); } #endif MyString vm_type; job_ad->LookupString(ATTR_JOB_VM_TYPE, vm_type); if( strcasecmp(vm_type.Value(), CONDOR_VM_UNIVERSE_VMWARE) == MATCH ) { name = my_username(); domain = my_domainname(); } } if( !name ) { if ( run_as_owner ) { job_ad->LookupString(ATTR_OWNER,&name); job_ad->LookupString(ATTR_NT_DOMAIN,&domain); } } if ( !name ) { char slot_user[255]; MyString slotName = ""; slotName = Starter->getMySlotName(); slotName.upper_case(); sprintf(slot_user, "%s_USER", slotName); char *run_jobs_as = param(slot_user); if (run_jobs_as) { getDomainAndName(run_jobs_as, domain, name); /* * name and domain are now just pointers into run_jobs_as * buffer. copy these values into their own buffer so we * deallocate below. */ if ( name ) { name = strdup(name); } if ( domain ) { domain = strdup(domain); } free(run_jobs_as); } } if ( name ) { if (!init_user_ids(name, domain)) { dprintf(D_ALWAYS, "Could not initialize user_priv as \"%s\\%s\".\n" "\tMake sure this account's password is securely stored " "with condor_store_cred.\n", domain, name ); init_priv_succeeded = false; } else { MyString login_name; joinDomainAndName(name, domain, login_name); if( checkDedicatedExecuteAccounts( login_name.Value() ) ) { setExecuteAccountIsDedicated( login_name.Value() ); } } } else if ( !can_switch_ids() ) { char *u = my_username(); char *d = my_domainname(); if ( !init_user_ids(u, d) ) { // shouldn't happen - we always can get our own token dprintf(D_ALWAYS, "Could not initialize user_priv with our own token!\n"); init_priv_succeeded = false; } free(u); free(d); } else if( init_user_ids("nobody", ".") ) { // just init a new nobody user; dynuser handles the rest. // the "." means Local Machine to LogonUser setExecuteAccountIsDedicated( get_user_loginname() ); } else { dprintf( D_ALWAYS, "ERROR: Could not initialize user_priv " "as \"nobody\"\n" ); init_priv_succeeded = false; } if ( name ) free(name); if ( domain ) free(domain); user_priv_is_initialized = init_priv_succeeded; return init_priv_succeeded; }
int init_user_ids(const char username[], const char domain[]) { int retval = 0; if (!username || !domain) { dprintf(D_ALWAYS, "WARNING: init_user_ids() called with" " NULL arguments!\n"); return 0; } // we have to be very careful calling dprintf in this function, because dprintf // will try and _set_priv to root and then back to what it was. so we need to // make sure that our global variables are always in a state where that doesn't // except. // TJ:2010: Can't do this here, UserIdsInited must never be true // while CurrUserHandle is NULL or dprintf will EXCEPT. // UserIdsInited = true; // see if we already have a user handle for the requested user. // if so, just return 1. // TODO: cache multiple user handles to save time. dprintf(D_FULLDEBUG, "init_user_ids: want user '%s@%s', " "current is '%s@%s'\n", username, domain, UserLoginName, UserDomainName); if ( CurrUserHandle = cached_tokens.getToken(username, domain)) { UserIdsInited = true; // do this before we call dprintf // when we uninit_user_ids we can end up CurrUserHandle in the cache // but UserLoginName and UserDomainName not set, if that happens // we need to set them here. if ( ! UserLoginName) UserLoginName = strdup(username); if ( ! UserDomainName) UserDomainName = strdup(domain); dprintf(D_FULLDEBUG, "init_user_ids: Already have handle for %s@%s," " so returning.\n", username, domain); return 1; } else { char* myusr = my_username(); char* mydom = my_domainname(); // we cleared CurrUserHandle, so we aren't inited. UserIdsInited = false; // see if our calling thread matches the user and domain // we want a token for. This happens if we're submit for example. if ( strcmp( myusr, username ) == 0 && strcasecmp( mydom, domain ) == 0 ) { // domain is case insensitive dprintf(D_FULLDEBUG, "init_user_ids: Calling thread has token " "we want, so returning.\n"); CurrUserHandle = my_usertoken(); if (CurrUserHandle) { UserIdsInited = true; } else { dprintf(D_FULLDEBUG, "init_user_ids: handle is null!\n"); } if (UserLoginName) { free(UserLoginName); UserLoginName = NULL; } if (UserDomainName) { free(UserDomainName); UserDomainName = NULL; } // these are strdup'ed, so we can just stash their pointers UserLoginName = myusr; UserDomainName = mydom; // don't forget to drop it in the cache too cached_tokens.storeToken(UserLoginName, UserDomainName, CurrUserHandle); return 1; } } // at this point UserIdsInited should be false. ASSERT( ! UserIdsInited); // anything beyond this requires user switching if (!can_switch_ids()) { dprintf(D_ALWAYS, "init_user_ids: failed because user switching is disabled\n"); return 0; } if ( strcmp(username,"nobody") != 0 ) { // here we call routines to deal with passwords. Hopefully we're // running as LocalSystem here, otherwise we can't get at the // password stash. lsa_mgr lsaMan; char pw[255]; char user[255]; char dom[255]; wchar_t w_fullname[255]; wchar_t *w_pw; bool got_password = false; bool got_password_from_credd = false; // these should probably be snprintfs swprintf(w_fullname, L"%S@%S", username, domain); sprintf(user, "%s", username); sprintf(dom, "%s", domain); // make sure we're SYSTEM when we do this w_pw = lsaMan.query(w_fullname); if ( w_pw ) { // copy password into a char buffer sprintf(pw, "%S", w_pw); // we don't need the wide char pw anymore, so clean it up SecureZeroMemory(w_pw, wcslen(w_pw)*sizeof(wchar_t)); delete[](w_pw); w_pw = NULL; // now that we got a password, see if it is good. retval = LogonUser( user, // user name dom, // domain or server - local for now pw, // password LOGON32_LOGON_INTERACTIVE, // type of logon operation. // LOGON_BATCH doesn't seem to work right here. LOGON32_PROVIDER_DEFAULT, // logon provider &CurrUserHandle // receive tokens handle ); if ( !retval ) { dprintf(D_FULLDEBUG,"Locally stored credential for %s@%s is stale\n", user,dom); // Set handle to NULL to make certain we recall LogonUser again below CurrUserHandle = NULL; } else { got_password = true; // so we don't bother going to a credd } } // if we don't have the password from our local stash, try to fetch // it from a credd. this tiny function is in a separate file so // that we don't pull in all of daemon core when we link to the utils library. char *credd_host = param("CREDD_HOST"); if (credd_host && got_password==false) { #if 1 got_password = get_password_from_credd( credd_host, username, domain, pw, sizeof(pw)); got_password_from_credd = got_password; #else dprintf(D_FULLDEBUG, "trying to fetch password from credd: %s\n", credd_host); Daemon credd(DT_CREDD); Sock * credd_sock = credd.startCommand(CREDD_GET_PASSWD,Stream::reli_sock,10); if ( credd_sock ) { credd_sock->put((char*)username); // send user credd_sock->put((char*)domain); // send domain credd_sock->end_of_message(); credd_sock->decode(); pw[0] = '\0'; int my_stupid_sizeof_int_for_damn_cedar = sizeof(pw); char *my_buffer = pw; if ( credd_sock->code(my_buffer,my_stupid_sizeof_int_for_damn_cedar) && pw[0] ) { got_password = true; got_password_from_credd = true; } else { dprintf(D_FULLDEBUG, "credd (%s) did not have info for %s@%s\n", credd_host, username,domain); } delete credd_sock; credd_sock = NULL; } else { dprintf(D_FULLDEBUG,"Failed to contact credd %s: %s\n", credd_host,credd.error() ? credd.error() : ""); } #endif } if (credd_host) free(credd_host); if ( ! got_password ) { dprintf(D_ALWAYS, "ERROR: Could not locate valid credential for user " "'%s@%s'\n", username, domain); return 0; } else { dprintf(D_FULLDEBUG, "Found credential for user '%s'\n", username); // If we have not yet called LogonUser, then CurrUserHandle is NULL, // and we need to call it here. if ( CurrUserHandle == NULL ) { retval = LogonUser( user, // user name dom, // domain or server - local for now pw, // password LOGON32_LOGON_INTERACTIVE, // type of logon operation. // LOGON_BATCH doesn't seem to work right here. LOGON32_PROVIDER_DEFAULT, // logon provider &CurrUserHandle // receive tokens handle ); } else { // we already have a good user handle from calling LogonUser to check to // see if our stashed credential was stale or not, so set retval to success retval = 1; // LogonUser returns nonzero value on success } dprintf(D_FULLDEBUG, "LogonUser completed.\n"); if (UserLoginName) { free(UserLoginName); UserDomainName = NULL; } if (UserDomainName) { free(UserDomainName); UserDomainName = NULL; } UserLoginName = strdup(username); UserDomainName = strdup(domain); if ( !retval ) { dprintf(D_ALWAYS, "init_user_ids: LogonUser failed with NT Status %ld\n", GetLastError()); retval = 0; // return of 0 means FAILURE } else { // stash the new token in our cache cached_tokens.storeToken(UserLoginName, UserDomainName, CurrUserHandle); UserIdsInited = true; // if we got the password from the credd, and the admin wants passwords stashed // locally on this machine, then do it. if ( got_password_from_credd && param_boolean("CREDD_CACHE_LOCALLY",false) ) { cache_credd_locally(username, domain, pw); } retval = 1; // return of 1 means SUCCESS } // clear pw from memory SecureZeroMemory(pw, 255); return retval; } } else { /// // Here's where we use a nobody account // dprintf(D_FULLDEBUG, "Using dynamic user account.\n"); myDynuser->reset(); // at this point, we know we want a user nobody, so // generate a dynamic user and stash the handle if ( !myDynuser->init_user() ) { // This is indicative of a serious problem. EXCEPT("Failed to create a user nobody"); } if (UserLoginName) { free(UserLoginName); UserDomainName = NULL; } if (UserDomainName) { free(UserDomainName); UserDomainName = NULL; } UserLoginName = strdup( myDynuser->get_accountname() ); UserDomainName = strdup( "." ); // we created a new user, now just stash the token CurrUserHandle = myDynuser->get_token(); // drop the handle in our cache too cached_tokens.storeToken(UserLoginName, UserDomainName, CurrUserHandle); UserIdsInited = true; return 1; } }
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 main(int argc, char *argv[]) { MyString my_full_name; const char *full_name; char* pw = NULL; struct StoreCredOptions options; int result = FAILURE_ABORTED; bool pool_password_arg = false; bool pool_password_delete = false; Daemon *daemon = NULL; char *credd_host; MyName = condor_basename(argv[0]); // load up configuration file myDistro->Init( argc, argv ); config(); if (!parseCommandLine(&options, argc, argv)) { goto cleanup; } // if -h was given, just print usage if (options.help || (options.mode == 0)) { usage(); goto cleanup; } #if !defined(WIN32) // if the -f argument was given, we just want to prompt for a password // and write it to a file (in our weirdo XORed format) // if (options.password_file != NULL) { if (options.pw[0] == '\0') { pw = get_password(); printf("\n"); } else { pw = strnewp(options.pw); SecureZeroMemory(options.pw, MAX_PASSWORD_LENGTH + 1); } result = write_password_file(options.password_file, pw); SecureZeroMemory(pw, strlen(pw)); if (result != SUCCESS) { fprintf(stderr, "error writing password file: %s\n", options.password_file); } goto cleanup; } #endif // determine the username to use if ( strcmp(options.username, "") == 0 ) { // default to current user and domain char* my_name = my_username(); char* my_domain = my_domainname(); my_full_name.formatstr("%s@%s", my_name, my_domain); if ( my_name) { free(my_name); } if ( my_domain) { free(my_domain); } my_name = my_domain = NULL; } else if (strcmp(options.username, POOL_PASSWORD_USERNAME) == 0) { #if !defined(WIN32) // we don't support querying the pool password on UNIX // (since it is not possible to do so through the // STORE_POOL_CRED command) if (options.mode == QUERY_MODE) { fprintf(stderr, "Querying the pool password is not supported.\n"); goto cleanup; } #endif // append the correct domain name if we're using the pool pass // we first try POOL_PASSWORD_DOMAIN, then UID_DOMAIN pool_password_arg = true; char *domain; if ((domain = param("SEC_PASSWORD_DOMAIN")) == NULL) { if ((domain = param("UID_DOMAIN")) == NULL) { fprintf(stderr, "ERROR: could not domain for pool password\n"); goto cleanup; } } my_full_name.formatstr(POOL_PASSWORD_USERNAME "@%s", domain); free(domain); } else { // username was specified on the command line my_full_name += options.username; } full_name = my_full_name.Value(); printf("Account: %s\n\n", full_name); // determine where to direct our command daemon = NULL; credd_host = NULL; if (options.daemonname != NULL) { if (pool_password_arg && (options.mode != QUERY_MODE)) { // daemon named on command line; go to master for pool password //printf("sending command to master: %s\n", options.daemonname); daemon = new Daemon(DT_MASTER, options.daemonname); } else { // daemon named on command line; go to schedd for user password //printf("sending command to schedd: %s\n", options.daemonname); daemon = new Daemon(DT_SCHEDD, options.daemonname); } } else if (!pool_password_arg && ((credd_host = param("CREDD_HOST")) != NULL)) { // no daemon given, use credd for user passwords if CREDD_HOST is defined // (otherwise, we use the local schedd) //printf("sending command to CREDD: %s\n", credd_host); daemon = new Daemon(DT_CREDD); } else { //printf("sending command to local daemon\n"); } // flag the case where we're deleting the pool password if (pool_password_arg && (options.mode == DELETE_MODE)) { pool_password_delete = true; } switch (options.mode) { case ADD_MODE: case DELETE_MODE: if (!pool_password_delete) { if ( strcmp(options.pw, "") == 0 ) { // get password from the user. pw = get_password(); printf("\n\n"); } else { // got the passwd from the command line. pw = strnewp(options.pw); SecureZeroMemory(options.pw, MAX_PASSWORD_LENGTH); } } if ( pw || pool_password_delete) { result = store_cred(full_name, pw, options.mode, daemon); if ((result == FAILURE_NOT_SECURE) && goAheadAnyways()) { // if user is ok with it, send the password in the clear result = store_cred(full_name, pw, options.mode, daemon, true); } if (pw) { SecureZeroMemory(pw, strlen(pw)); delete[] pw; } } break; case QUERY_MODE: result = queryCredential(full_name, daemon); break; #if defined(WIN32) case CONFIG_MODE: return interactive(); break; #endif default: fprintf(stderr, "Internal error\n"); goto cleanup; } // output result of operation switch (result) { case SUCCESS: if (options.mode == QUERY_MODE) { printf("A credential is stored and is valid.\n"); } else { printf("Operation succeeded.\n"); } break; case FAILURE: printf("Operation failed.\n"); if (pool_password_arg && (options.mode != QUERY_MODE)) { printf(" Make sure you have CONFIG access to the target Master.\n"); } else { printf(" Make sure your ALLOW_WRITE setting includes this host.\n"); } break; case FAILURE_BAD_PASSWORD: if (options.mode == QUERY_MODE) { printf("A credential is stored, but it is invalid. " "Run 'condor_store_cred add' again.\n"); } else { printf("Operation failed: bad password.\n"); } break; case FAILURE_NOT_FOUND: if (options.mode == QUERY_MODE) { printf("No credential is stored.\n"); } else { printf("Operation failed: username not found.\n"); } break; case FAILURE_NOT_SECURE: case FAILURE_ABORTED: printf("Operation aborted.\n"); break; case FAILURE_NOT_SUPPORTED: printf("Operation failed.\n" " The target daemon is not running as SYSTEM.\n"); break; default: fprintf(stderr, "Operation failed: unknown error code\n"); } cleanup: if (options.daemonname) { delete[] options.daemonname; } if (daemon) { delete daemon; } if ( result == SUCCESS ) { return 0; } else { return 1; } }