void MachAttributes::credd_test() { // Attempt to perform a NOP on our CREDD_HOST. This will test // our ability to authenticate with DAEMON-level auth, and thus // fetch passwords. If we succeed, we'll advertise the CREDD_HOST char *credd_host = param("CREDD_HOST"); if (credd_host == NULL) { if (m_local_credd != NULL) { free(m_local_credd); m_local_credd = NULL; } return; } if (m_local_credd != NULL) { if (strcmp(m_local_credd, credd_host) == 0) { free(credd_host); return; } else { free(m_local_credd); m_local_credd = NULL; m_last_credd_test = 0; } } time_t now = time(NULL); double thresh = (double)param_integer("CREDD_TEST_INTERVAL", 300); if (difftime(now, m_last_credd_test) > thresh) { Daemon credd(DT_CREDD); if (credd.locate()) { Sock *sock = credd.startCommand(CREDD_NOP, Stream::reli_sock, 20); if (sock != NULL) { sock->decode(); if (sock->end_of_message()) { m_local_credd = credd_host; } } } m_last_credd_test = now; } if (credd_host != m_local_credd) { free(credd_host); } }
int main(int argc, char **argv) { char * server_address = NULL; char ** ptr; const char * myName; // find our name myName = strrchr( argv[0], DIR_DELIM_CHAR ); if( !myName ) { myName = argv[0]; } else { myName++; } // read config file myDistro->Init (argc, argv); config (); for (ptr=argv+1,argc--; argc > 0; argc--,ptr++) { if ( ptr[0][0] == '-' ) { switch ( ptr[0][1] ) { case 'h': usage(myName); exit(0); break; case 'd': // dprintf to console Termlog = 1; dprintf_config ("TOOL", get_param_functions()); break; case 'n': if( !(--argc) || !(*(++ptr)) ) { fprintf( stderr, "%s: -n requires another argument\n", myName ); exit(1); } server_address = strdup (*ptr); break; case 'v': version(); // this function calls exit(0) break; default: fprintf( stderr, "%s: Unknown option %s\n", myName, *ptr); usage(myName); exit(1); } } //fi } //rof CondorError errorstack; int number = 0; SimpleList <Credential*> result; DCCredd credd(server_address); // resolve server address if ( ! credd.locate() ) { fprintf (stderr, "%s\n", credd.error() ); return 1; } if (!credd.listCredentials (result, number, errorstack)) { fprintf (stderr, "Unable to retrieve credentials (%s)\n", errorstack.getFullText(true)); return 1; } if (number > 0) { Credential * cred; result.Rewind(); printf ("Name\tType\n-----\t-----\n"); while (result.Next (cred)) { printf ("%s\t%s\n", cred->GetName(), cred->GetTypeString()); } printf ("\nTotal %d\n", number); } else if (number == 0) { printf ("No credentials currently stored on this server\n"); } else { fprintf (stderr, "ERROR\n"); return 1; } return 0; }
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; } }