<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/


#include "condor_common.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "condor_ver_info.h"
#include "condor_version.h"
#include "condor_environ.h"

#include "authentication.h"
#include "condor_string.h"
#include "condor_attributes.h"
#include "condor_adtypes.h"
#include "my_hostname.h"
#include "internet.h"
#include "HashTable.h"
#include "KeyCache.h"
#include "condor_daemon_core.h"
#include "condor_ipverify.h"
#include "condor_secman.h"
#include "classad_merge.h"
#include "daemon.h"
#include "subsystem_info.h"
#include "setenv.h"
#include "ipv6_hostname.h"

extern bool global_dc_get_cookie(int &len, unsigned char* &data);

// special security session "hint" used to specify that a new
// security session should be used
char const *USE_TMP_SEC_SESSION = "USE_TMP_SEC_SESSION";

void SecMan::key_printf(int debug_levels, KeyInfo *k) {
	if (param_boolean("SEC_DEBUG_PRINT_KEYS", false)) {
		if (k) {
			char hexout[260];  // holds (at least) a 128 byte key.
			const unsigned char* dataptr = k->getKeyData();
			int   length  =  k->getKeyLength();

			for (int i = 0; (i < length) && (i < 24); i++) {
				sprintf (&hexout[i*2], "%02x", *dataptr++);
			}

			dprintf (debug_levels, "KEYPRINTF: [%i] %s\n", length, hexout);
		} else {
			dprintf (debug_levels, "KEYPRINTF: [NULL]\n");
		}
	}
}



const char SecMan::sec_feat_act_rev[][10] = {
	"UNDEFINED",
	"INVALID",
	"FAIL",
	"YES",
	"NO"
};


const char SecMan::sec_req_rev[][10] = {
	"UNDEFINED",
	"INVALID",
	"NEVER",
	"OPTIONAL",
	"PREFERRED",
	"REQUIRED"
};

KeyCache SecMan::m_default_session_cache;
std::map<std::string,KeyCache*> *SecMan::m_tagged_session_cache = NULL;
std::string SecMan::m_tag;
KeyCache *SecMan::session_cache = &SecMan::m_default_session_cache;
std::string SecMan::m_pool_password;
HashTable<MyString,MyString> SecMan::command_map(209, MyStringHash, updateDuplicateKeys);
HashTable<MyString,classy_counted_ptr<SecManStartCommand> > SecMan::tcp_auth_in_progress(256, MyStringHash, rejectDuplicateKeys);
int SecMan::sec_man_ref_count = 0;
char* SecMan::_my_unique_id = 0;
char* SecMan::_my_parent_unique_id = 0;
bool SecMan::_should_check_env_for_unique_id = true;
IpVerify *SecMan::m_ipverify = NULL;

void
SecMan::setTag(const std::string &tag) {
        m_tag = tag;
	if (tag.size() == 0) {
		session_cache = &m_default_session_cache;
		return;
	}
	if (m_tagged_session_cache == NULL) {
		m_tagged_session_cache = new std::map<std::string, KeyCache*>();
	}
	std::map<std::string, KeyCache*>::const_iterator iter = m_tagged_session_cache->find(tag);
	KeyCache *tmp = NULL;
	if (iter == m_tagged_session_cache->end()) {
		tmp = new KeyCache();
		m_tagged_session_cache->insert(std::make_pair(tag, tmp));
	} else {
		tmp = iter->second;
	}
	session_cache = tmp;
}

SecMan::sec_req
SecMan::sec_alpha_to_sec_req(char *b) {
	if (!b || !*b) {  
		// ... that is the question :)
		return SEC_REQ_INVALID;
	}

	switch (toupper(b[0])) {
		case 'R':  // required
		case 'Y':  // yes
		case 'T':  // true
			return SEC_REQ_REQUIRED;
		case 'P':  // preferred
			return SEC_REQ_PREFERRED;
		case 'O':  // optional
			return SEC_REQ_OPTIONAL;
		case 'F':  // false
		case 'N':  // never
			return SEC_REQ_NEVER;
	}

	return SEC_REQ_INVALID;
}


SecMan::sec_feat_act
SecMan::sec_lookup_feat_act( const ClassAd &ad, const char* pname ) {

	char* res = NULL;
	ad.LookupString(pname, &res);

	if (res) {
		char buf[2];
		strncpy (buf, res, 1);
		buf[1] = 0;
		free (res);

		return sec_alpha_to_sec_feat_act(buf);
	}

	return SEC_FEAT_ACT_UNDEFINED;

}

SecMan::sec_feat_act
SecMan::sec_alpha_to_sec_feat_act(char *b) {
	if (!b || !*b) {  
		// ... that is the question :)
		return SEC_FEAT_ACT_INVALID;
	}

	switch (toupper(b[0])) {
		case 'F':  // enact
			return SEC_FEAT_ACT_FAIL;
		case 'Y':  // yes
			return SEC_FEAT_ACT_YES;
		case 'N':  // no
			return SEC_FEAT_ACT_NO;
	}

	return SEC_FEAT_ACT_INVALID;
}


/*
SecMan::sec_act
SecMan::sec_alpha_to_sec_act(char *b) {
	if (!b || !*b) {  
		// ... that is the question :)
		return SEC_ACT_INVALID;
	}

	switch (toupper(b[0])) {
		case 'A':  // ask
			return SEC_REQ_ASK;
		case 'E':  // enact
			return SEC_ENACT;
		case 'U':  // usekey
			return SEC_USEKEY;
		case 'N':  // none
			return SEC_NONE;
	}

	return SEC_INVALID;
}
*/

/*
SecMan::sec_act
SecMan::sec_lookup_act( const ClassAd &ad, const char* pname ) {

	char* res = NULL;
	ad.LookupString(pname, &res);

	if (res) {
		char buf[2];
		strncpy (buf, res, 1);
		buf[1] = 0;
		free (res);

		return sec_alpha_to_sec_act(buf);
	}

	return SEC_UNDEFINED;
}
*/


SecMan::sec_req
SecMan::sec_lookup_req( const ClassAd &ad, const char* pname ) {

	char* res = NULL;
	ad.LookupString(pname, &res);

	if (res) {
		char buf[2];
		strncpy (buf, res, 1);
		buf[1] = 0;
		free (res);

		return sec_alpha_to_sec_req(buf);
	}

	return SEC_REQ_UNDEFINED;
}

SecMan::sec_feat_act
SecMan::sec_req_to_feat_act (sec_req r) {
	if ( (r == SEC_REQ_REQUIRED) || (r == SEC_REQ_PREFERRED) ) {
		return SEC_FEAT_ACT_YES;
	} else {
		return SEC_FEAT_ACT_NO;
	}
}


bool
SecMan::sec_is_negotiable (sec_req r) {
	if ( (r == SEC_REQ_REQUIRED) || (r == SEC_REQ_NEVER) ) {
		return false;
	} else {
		return true;
	}
}


SecMan::sec_req
SecMan::sec_req_param( const char* fmt, DCpermission auth_level, sec_req def ) {
	char *config_value = getSecSetting( fmt, auth_level );

	if (config_value) {
		char buf[2];
		strncpy (buf, config_value, 1);
		buf[1] = 0;
		free (config_value);

		sec_req res = sec_alpha_to_sec_req(buf);

		if (res == SEC_REQ_UNDEFINED || res == SEC_REQ_INVALID) {
			MyString param_name;
			char *value = getSecSetting( fmt, auth_level, &param_name );
			if( res == SEC_REQ_INVALID ) {
				EXCEPT( "SECMAN: %s=%s is invalid!",
				        param_name.Value(), value ? value : "(null)" );
			}
			if( IsDebugVerbose(D_SECURITY) ) {
				dprintf (D_SECURITY,
				         "SECMAN: %s is undefined; using %s.\n",
				         param_name.Value(), SecMan::sec_req_rev[def]);
			}
			free(value);

			return def;
		}

		return res;
	}

	return def;
}

void SecMan::getAuthenticationMethods( DCpermission perm, MyString *result ) {
	ASSERT( result );

	char * p = getSecSetting ("SEC_%s_AUTHENTICATION_METHODS", perm);

	if (p) {
		*result = p;
		free (p);
	} else {
		*result = SecMan::getDefaultAuthenticationMethods();
	}
}

bool
SecMan::getIntSecSetting( int &result, const char* fmt, DCpermissionHierarchy const &auth_level, MyString *param_name /* = NULL */, char const *check_subsystem /* = NULL */ )
{
	return getSecSetting_implementation(&result,NULL,fmt,auth_level,param_name,check_subsystem);
}

char* 
SecMan::getSecSetting( const char* fmt, DCpermissionHierarchy const &auth_level, MyString *param_name /* = NULL */, char const *check_subsystem /* = NULL */ )
{
	char *result = NULL;
	getSecSetting_implementation(NULL,&result,fmt,auth_level,param_name,check_subsystem);
	return result;
}

bool
SecMan::getSecSetting_implementation( int *int_result,char **str_result, const char* fmt, DCpermissionHierarchy const &auth_level, MyString *param_name, char const *check_subsystem )
{
	DCpermission const *perms = auth_level.getConfigPerms();
	bool found;

		// Now march through the list of config settings to look for.  The
		// last one in the list will be DEFAULT_PERM, which we only use
		// if nothing else is found first.

	for( ; *perms != LAST_PERM; perms++ ) {
		MyString buf;
		if( check_subsystem ) {
				// First see if there is a specific config entry for the
				// specified condor subsystem.
			buf.formatstr( fmt, PermString(*perms) );
			buf.formatstr_cat("_%s",check_subsystem);
			if( int_result ) {
				found = param_integer( buf.Value(), *int_result, false, 0, false, 0, 0 );
			}
			else {
				*str_result = param( buf.Value() );
				found = *str_result;
			}
			if( found ) {
				if( param_name ) {
						// Caller wants to know the param name.
					param_name->append_to_list(buf);
				}
				return true;
			}
		}

		buf.formatstr( fmt, PermString(*perms) );
		if( int_result ) {
			found = param_integer( buf.Value(), *int_result, false, 0, false, 0, 0 );
		}
		else {
			*str_result = param( buf.Value() );
			found = *str_result;
		}
		if( found ) {
			if( param_name ) {
					// Caller wants to know the param name.
				param_name->append_to_list(buf);
			}
			return true;
		}
	}

	return false;
}



// params() for a bunch of stuff and sets up a class ad describing our security
// preferences/requirements.  returns true if the security policy is valid, and
// false otherwise.

// there are many ways to end up with and 'invalid' security policy.  here are a
// couple:
//
// 6.3-style negotiation is disabled and one of AUTH, ENC, or INTEG were required.
//
// either ENC or INTEG are supposed to happen but AUTH is NEVER (can't exchange
// private key if we don't authenticate)

bool
SecMan::FillInSecurityPolicyAd( DCpermission auth_level, ClassAd* ad, 
								bool raw_protocol,
								bool use_tmp_sec_session,
								bool force_authentication )
{
	if( ! ad ) {
		EXCEPT( "SecMan::FillInSecurityPolicyAd called with NULL ad!" );
	}

	// get values from config file, trying each auth level in the
	// list in turn.  The final level in the list will be "DEFAULT".
	// if that fails, the default value (OPTIONAL) is used.

	sec_req sec_authentication = force_authentication ? SEC_REQ_REQUIRED :
		sec_req_param("SEC_%s_AUTHENTICATION", auth_level, SEC_REQ_OPTIONAL);

	sec_req sec_encryption = sec_req_param(
		"SEC_%s_ENCRYPTION", auth_level, SEC_REQ_OPTIONAL);

	sec_req sec_integrity = sec_req_param(
		 "SEC_%s_INTEGRITY", auth_level, SEC_REQ_OPTIONAL);


	// regarding SEC_NEGOTIATE values:
	// REQUIRED- outgoing will always negotiate, and incoming must
	//           be negotiated as well.
	// PREFERRED- outgoing will try to negotiate but fall back to
	//            6.2 method if necessary.  incoming will allow
	//            negotiated & unnegotiated commands.
	// OPTIONAL- outgoing will be 6.2 style.  incoming will allow
	//           negotiated and unnegotiated commands.
	// NEVER- everything will be 6.2 style

	// as of 6.5.0, the default is PREFERRED

	sec_req sec_negotiation = sec_req_param ("SEC_%s_NEGOTIATION", auth_level, SEC_REQ_PREFERRED);

	if( raw_protocol ) {
		sec_negotiation = SEC_REQ_NEVER;
		sec_authentication = SEC_REQ_NEVER;
		sec_encryption = SEC_REQ_NEVER;
		sec_integrity = SEC_REQ_NEVER;
	}


	if (!ReconcileSecurityDependency (sec_authentication, sec_encryption) ||
		!ReconcileSecurityDependency (sec_authentication, sec_integrity) ||
	    !ReconcileSecurityDependency (sec_negotiation, sec_authentication) ||
	    !ReconcileSecurityDependency (sec_negotiation, sec_encryption) ||
		!ReconcileSecurityDependency (sec_negotiation, sec_integrity)) {

		// houston, we have a problem.  
		dprintf (D_SECURITY, "SECMAN: failure! can't resolve security policy:\n");
		dprintf (D_SECURITY, "SECMAN:   SEC_NEGOTIATION=\"%s\"\n",
				SecMan::sec_req_rev[sec_negotiation]);
		dprintf (D_SECURITY, "SECMAN:   SEC_AUTHENTICATION=\"%s\"\n",
				SecMan::sec_req_rev[sec_authentication]);
		dprintf (D_SECURITY, "SECMAN:   SEC_ENCRYPTION=\"%s\"\n", 
				SecMan::sec_req_rev[sec_encryption]);
		dprintf (D_SECURITY, "SECMAN:   SEC_INTEGRITY=\"%s\"\n", 
				SecMan::sec_req_rev[sec_integrity]);
		return false;
	}

	// for those of you reading this code, a 'paramer'
	// is a thing that param()s.
	char *paramer;

	// auth methods
	paramer = SecMan::getSecSetting ("SEC_%s_AUTHENTICATION_METHODS", auth_level);
	if (paramer == NULL) {
		paramer = strdup(SecMan::getDefaultAuthenticationMethods().Value());
	}

	if (paramer) {
		ad->Assign (ATTR_SEC_AUTHENTICATION_METHODS, paramer);
		free(paramer);
		paramer = NULL;
	} else {
		if( sec_authentication == SEC_REQ_REQUIRED ) {
			dprintf( D_SECURITY, "SECMAN: no auth methods, "
					 "but a feature was required! failing...\n" );
			return false;
		} else {<commit_msg>Add CLAIMTOBE to the list of default methods for CLIENT and READ.  #6125<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/


#include "condor_common.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "condor_ver_info.h"
#include "condor_version.h"
#include "condor_environ.h"

#include "authentication.h"
#include "condor_string.h"
#include "condor_attributes.h"
#include "condor_adtypes.h"
#include "my_hostname.h"
#include "internet.h"
#include "HashTable.h"
#include "KeyCache.h"
#include "condor_daemon_core.h"
#include "condor_ipverify.h"
#include "condor_secman.h"
#include "classad_merge.h"
#include "daemon.h"
#include "subsystem_info.h"
#include "setenv.h"
#include "ipv6_hostname.h"

extern bool global_dc_get_cookie(int &len, unsigned char* &data);

// special security session "hint" used to specify that a new
// security session should be used
char const *USE_TMP_SEC_SESSION = "USE_TMP_SEC_SESSION";

void SecMan::key_printf(int debug_levels, KeyInfo *k) {
	if (param_boolean("SEC_DEBUG_PRINT_KEYS", false)) {
		if (k) {
			char hexout[260];  // holds (at least) a 128 byte key.
			const unsigned char* dataptr = k->getKeyData();
			int   length  =  k->getKeyLength();

			for (int i = 0; (i < length) && (i < 24); i++) {
				sprintf (&hexout[i*2], "%02x", *dataptr++);
			}

			dprintf (debug_levels, "KEYPRINTF: [%i] %s\n", length, hexout);
		} else {
			dprintf (debug_levels, "KEYPRINTF: [NULL]\n");
		}
	}
}



const char SecMan::sec_feat_act_rev[][10] = {
	"UNDEFINED",
	"INVALID",
	"FAIL",
	"YES",
	"NO"
};


const char SecMan::sec_req_rev[][10] = {
	"UNDEFINED",
	"INVALID",
	"NEVER",
	"OPTIONAL",
	"PREFERRED",
	"REQUIRED"
};

KeyCache SecMan::m_default_session_cache;
std::map<std::string,KeyCache*> *SecMan::m_tagged_session_cache = NULL;
std::string SecMan::m_tag;
KeyCache *SecMan::session_cache = &SecMan::m_default_session_cache;
std::string SecMan::m_pool_password;
HashTable<MyString,MyString> SecMan::command_map(209, MyStringHash, updateDuplicateKeys);
HashTable<MyString,classy_counted_ptr<SecManStartCommand> > SecMan::tcp_auth_in_progress(256, MyStringHash, rejectDuplicateKeys);
int SecMan::sec_man_ref_count = 0;
char* SecMan::_my_unique_id = 0;
char* SecMan::_my_parent_unique_id = 0;
bool SecMan::_should_check_env_for_unique_id = true;
IpVerify *SecMan::m_ipverify = NULL;

void
SecMan::setTag(const std::string &tag) {
        m_tag = tag;
	if (tag.size() == 0) {
		session_cache = &m_default_session_cache;
		return;
	}
	if (m_tagged_session_cache == NULL) {
		m_tagged_session_cache = new std::map<std::string, KeyCache*>();
	}
	std::map<std::string, KeyCache*>::const_iterator iter = m_tagged_session_cache->find(tag);
	KeyCache *tmp = NULL;
	if (iter == m_tagged_session_cache->end()) {
		tmp = new KeyCache();
		m_tagged_session_cache->insert(std::make_pair(tag, tmp));
	} else {
		tmp = iter->second;
	}
	session_cache = tmp;
}

SecMan::sec_req
SecMan::sec_alpha_to_sec_req(char *b) {
	if (!b || !*b) {  
		// ... that is the question :)
		return SEC_REQ_INVALID;
	}

	switch (toupper(b[0])) {
		case 'R':  // required
		case 'Y':  // yes
		case 'T':  // true
			return SEC_REQ_REQUIRED;
		case 'P':  // preferred
			return SEC_REQ_PREFERRED;
		case 'O':  // optional
			return SEC_REQ_OPTIONAL;
		case 'F':  // false
		case 'N':  // never
			return SEC_REQ_NEVER;
	}

	return SEC_REQ_INVALID;
}


SecMan::sec_feat_act
SecMan::sec_lookup_feat_act( const ClassAd &ad, const char* pname ) {

	char* res = NULL;
	ad.LookupString(pname, &res);

	if (res) {
		char buf[2];
		strncpy (buf, res, 1);
		buf[1] = 0;
		free (res);

		return sec_alpha_to_sec_feat_act(buf);
	}

	return SEC_FEAT_ACT_UNDEFINED;

}

SecMan::sec_feat_act
SecMan::sec_alpha_to_sec_feat_act(char *b) {
	if (!b || !*b) {  
		// ... that is the question :)
		return SEC_FEAT_ACT_INVALID;
	}

	switch (toupper(b[0])) {
		case 'F':  // enact
			return SEC_FEAT_ACT_FAIL;
		case 'Y':  // yes
			return SEC_FEAT_ACT_YES;
		case 'N':  // no
			return SEC_FEAT_ACT_NO;
	}

	return SEC_FEAT_ACT_INVALID;
}


/*
SecMan::sec_act
SecMan::sec_alpha_to_sec_act(char *b) {
	if (!b || !*b) {  
		// ... that is the question :)
		return SEC_ACT_INVALID;
	}

	switch (toupper(b[0])) {
		case 'A':  // ask
			return SEC_REQ_ASK;
		case 'E':  // enact
			return SEC_ENACT;
		case 'U':  // usekey
			return SEC_USEKEY;
		case 'N':  // none
			return SEC_NONE;
	}

	return SEC_INVALID;
}
*/

/*
SecMan::sec_act
SecMan::sec_lookup_act( const ClassAd &ad, const char* pname ) {

	char* res = NULL;
	ad.LookupString(pname, &res);

	if (res) {
		char buf[2];
		strncpy (buf, res, 1);
		buf[1] = 0;
		free (res);

		return sec_alpha_to_sec_act(buf);
	}

	return SEC_UNDEFINED;
}
*/


SecMan::sec_req
SecMan::sec_lookup_req( const ClassAd &ad, const char* pname ) {

	char* res = NULL;
	ad.LookupString(pname, &res);

	if (res) {
		char buf[2];
		strncpy (buf, res, 1);
		buf[1] = 0;
		free (res);

		return sec_alpha_to_sec_req(buf);
	}

	return SEC_REQ_UNDEFINED;
}

SecMan::sec_feat_act
SecMan::sec_req_to_feat_act (sec_req r) {
	if ( (r == SEC_REQ_REQUIRED) || (r == SEC_REQ_PREFERRED) ) {
		return SEC_FEAT_ACT_YES;
	} else {
		return SEC_FEAT_ACT_NO;
	}
}


bool
SecMan::sec_is_negotiable (sec_req r) {
	if ( (r == SEC_REQ_REQUIRED) || (r == SEC_REQ_NEVER) ) {
		return false;
	} else {
		return true;
	}
}


SecMan::sec_req
SecMan::sec_req_param( const char* fmt, DCpermission auth_level, sec_req def ) {
	char *config_value = getSecSetting( fmt, auth_level );

	if (config_value) {
		char buf[2];
		strncpy (buf, config_value, 1);
		buf[1] = 0;
		free (config_value);

		sec_req res = sec_alpha_to_sec_req(buf);

		if (res == SEC_REQ_UNDEFINED || res == SEC_REQ_INVALID) {
			MyString param_name;
			char *value = getSecSetting( fmt, auth_level, &param_name );
			if( res == SEC_REQ_INVALID ) {
				EXCEPT( "SECMAN: %s=%s is invalid!",
				        param_name.Value(), value ? value : "(null)" );
			}
			if( IsDebugVerbose(D_SECURITY) ) {
				dprintf (D_SECURITY,
				         "SECMAN: %s is undefined; using %s.\n",
				         param_name.Value(), SecMan::sec_req_rev[def]);
			}
			free(value);

			return def;
		}

		return res;
	}

	return def;
}

void SecMan::getAuthenticationMethods( DCpermission perm, MyString *result ) {
	ASSERT( result );

	char * p = getSecSetting ("SEC_%s_AUTHENTICATION_METHODS", perm);

	if (p) {
		*result = p;
		free (p);
	} else {
		*result = SecMan::getDefaultAuthenticationMethods();
	}
}

bool
SecMan::getIntSecSetting( int &result, const char* fmt, DCpermissionHierarchy const &auth_level, MyString *param_name /* = NULL */, char const *check_subsystem /* = NULL */ )
{
	return getSecSetting_implementation(&result,NULL,fmt,auth_level,param_name,check_subsystem);
}

char* 
SecMan::getSecSetting( const char* fmt, DCpermissionHierarchy const &auth_level, MyString *param_name /* = NULL */, char const *check_subsystem /* = NULL */ )
{
	char *result = NULL;
	getSecSetting_implementation(NULL,&result,fmt,auth_level,param_name,check_subsystem);
	return result;
}

bool
SecMan::getSecSetting_implementation( int *int_result,char **str_result, const char* fmt, DCpermissionHierarchy const &auth_level, MyString *param_name, char const *check_subsystem )
{
	DCpermission const *perms = auth_level.getConfigPerms();
	bool found;

		// Now march through the list of config settings to look for.  The
		// last one in the list will be DEFAULT_PERM, which we only use
		// if nothing else is found first.

	for( ; *perms != LAST_PERM; perms++ ) {
		MyString buf;
		if( check_subsystem ) {
				// First see if there is a specific config entry for the
				// specified condor subsystem.
			buf.formatstr( fmt, PermString(*perms) );
			buf.formatstr_cat("_%s",check_subsystem);
			if( int_result ) {
				found = param_integer( buf.Value(), *int_result, false, 0, false, 0, 0 );
			}
			else {
				*str_result = param( buf.Value() );
				found = *str_result;
			}
			if( found ) {
				if( param_name ) {
						// Caller wants to know the param name.
					param_name->append_to_list(buf);
				}
				return true;
			}
		}

		buf.formatstr( fmt, PermString(*perms) );
		if( int_result ) {
			found = param_integer( buf.Value(), *int_result, false, 0, false, 0, 0 );
		}
		else {
			*str_result = param( buf.Value() );
			found = *str_result;
		}
		if( found ) {
			if( param_name ) {
					// Caller wants to know the param name.
				param_name->append_to_list(buf);
			}
			return true;
		}
	}

	return false;
}



// params() for a bunch of stuff and sets up a class ad describing our security
// preferences/requirements.  returns true if the security policy is valid, and
// false otherwise.

// there are many ways to end up with and 'invalid' security policy.  here are a
// couple:
//
// 6.3-style negotiation is disabled and one of AUTH, ENC, or INTEG were required.
//
// either ENC or INTEG are supposed to happen but AUTH is NEVER (can't exchange
// private key if we don't authenticate)

bool
SecMan::FillInSecurityPolicyAd( DCpermission auth_level, ClassAd* ad, 
								bool raw_protocol,
								bool use_tmp_sec_session,
								bool force_authentication )
{
	if( ! ad ) {
		EXCEPT( "SecMan::FillInSecurityPolicyAd called with NULL ad!" );
	}

	// get values from config file, trying each auth level in the
	// list in turn.  The final level in the list will be "DEFAULT".
	// if that fails, the default value (OPTIONAL) is used.

	sec_req sec_authentication = force_authentication ? SEC_REQ_REQUIRED :
		sec_req_param("SEC_%s_AUTHENTICATION", auth_level, SEC_REQ_OPTIONAL);

	sec_req sec_encryption = sec_req_param(
		"SEC_%s_ENCRYPTION", auth_level, SEC_REQ_OPTIONAL);

	sec_req sec_integrity = sec_req_param(
		 "SEC_%s_INTEGRITY", auth_level, SEC_REQ_OPTIONAL);


	// regarding SEC_NEGOTIATE values:
	// REQUIRED- outgoing will always negotiate, and incoming must
	//           be negotiated as well.
	// PREFERRED- outgoing will try to negotiate but fall back to
	//            6.2 method if necessary.  incoming will allow
	//            negotiated & unnegotiated commands.
	// OPTIONAL- outgoing will be 6.2 style.  incoming will allow
	//           negotiated and unnegotiated commands.
	// NEVER- everything will be 6.2 style

	// as of 6.5.0, the default is PREFERRED

	sec_req sec_negotiation = sec_req_param ("SEC_%s_NEGOTIATION", auth_level, SEC_REQ_PREFERRED);

	if( raw_protocol ) {
		sec_negotiation = SEC_REQ_NEVER;
		sec_authentication = SEC_REQ_NEVER;
		sec_encryption = SEC_REQ_NEVER;
		sec_integrity = SEC_REQ_NEVER;
	}


	if (!ReconcileSecurityDependency (sec_authentication, sec_encryption) ||
		!ReconcileSecurityDependency (sec_authentication, sec_integrity) ||
	    !ReconcileSecurityDependency (sec_negotiation, sec_authentication) ||
	    !ReconcileSecurityDependency (sec_negotiation, sec_encryption) ||
		!ReconcileSecurityDependency (sec_negotiation, sec_integrity)) {

		// houston, we have a problem.  
		dprintf (D_SECURITY, "SECMAN: failure! can't resolve security policy:\n");
		dprintf (D_SECURITY, "SECMAN:   SEC_NEGOTIATION=\"%s\"\n",
				SecMan::sec_req_rev[sec_negotiation]);
		dprintf (D_SECURITY, "SECMAN:   SEC_AUTHENTICATION=\"%s\"\n",
				SecMan::sec_req_rev[sec_authentication]);
		dprintf (D_SECURITY, "SECMAN:   SEC_ENCRYPTION=\"%s\"\n", 
				SecMan::sec_req_rev[sec_encryption]);
		dprintf (D_SECURITY, "SECMAN:   SEC_INTEGRITY=\"%s\"\n", 
				SecMan::sec_req_rev[sec_integrity]);
		return false;
	}

	// for those of you reading this code, a 'paramer'
	// is a thing that param()s.
	char *paramer;

	// auth methods
	paramer = SecMan::getSecSetting ("SEC_%s_AUTHENTICATION_METHODS", auth_level);
	if (paramer == NULL) {
		MyString methods = SecMan::getDefaultAuthenticationMethods();
		if(auth_level == READ) {
			methods += ",CLAIMTOBE";
			dprintf(D_SECURITY, "SECMAN: default READ methods: %s\n", methods.Value());
		} else if (auth_level == CLIENT_PERM) {
			methods += ",CLAIMTOBE";
			dprintf(D_SECURITY, "SECMAN:: default CLIENT methods: %s\n", methods.Value());
		}
		paramer = strdup(methods.Value());
	}

	if (paramer) {
		ad->Assign (ATTR_SEC_AUTHENTICATION_METHODS, paramer);
		free(paramer);
		paramer = NULL;
	} else {
		if( sec_authentication == SEC_REQ_REQUIRED ) {
			dprintf( D_SECURITY, "SECMAN: no auth methods, "
					 "but a feature was required! failing...\n" );
			return false;
		} else {
{'fraction_non_alphanumeric': 0.13837087581902066, 'fraction_numerical': 0.005970612181599659, 'mean_word_length': 4.054673721340388, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4915737', 'n_tokens_mistral': 10165, 'n_tokens_neox': 9315, 'n_words': 2319}