Exemple #1
0
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);
	}
}
Exemple #2
0
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;
}
Exemple #3
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;
	}
}