in auth/kerberos/src/krb.cpp [108:244]
std::pair<int, std::string> fetch_gmsa_password_and_create_krb_ticket(
std::string domain_name, krb_ticket_info_t* krb_ticket, const std::string& krb_cc_name,
CF_logger& cf_logger )
{
std::vector<std::string> results;
std::string gmsa_account_name = "";
std::string distinguished_name = "";
if ( krb_ticket != NULL )
{
gmsa_account_name = krb_ticket->service_account_name;
distinguished_name = krb_ticket->distinguished_name;
}
if ( domain_name.empty() || gmsa_account_name.empty() )
{
std::string log_message =
"ERROR: " + std::string( __func__ ) + ": " + std::to_string( __LINE__ ) + " null args";
cf_logger.logger( LOG_ERR, log_message.c_str() );
std::string err_msg = std::string( "domain_name " + domain_name + " or gmsa_account_name " +
gmsa_account_name + " is empty" );
return std::make_pair( -1, err_msg );
}
std::pair<int, std::string> ldap_search_result;
std::string base_dn = "";
std::pair<int, std::string> base_dn_result = Util::get_base_dn( domain_name );
if ( base_dn_result.first == 0 && !base_dn_result.second.empty() )
{
base_dn = base_dn_result.second;
}
if ( distinguished_name.empty() && getenv( ENV_CF_GMSA_OU ) != NULL )
{
distinguished_name = std::string( getenv( ENV_CF_GMSA_OU ) );
}
std::vector<std::string> fqdn_list_result = Util::get_FQDN_list( domain_name );
for ( auto fqdn : fqdn_list_result )
{
if ( distinguished_name.empty() )
{
std::pair<int, std::string> distinguished_name_result =
Util::find_dn( gmsa_account_name, base_dn, fqdn );
if ( distinguished_name_result.first == 0 && !distinguished_name_result.second.empty() )
{
distinguished_name = distinguished_name_result.second;
}
std::string log_str = "Found dn = " + distinguished_name;
cf_logger.logger( LOG_INFO, log_str.c_str() );
}
krb_ticket->distinguished_name = distinguished_name;
// Then find the password
std::string search_string = std::string(
" -s sub '(objectClass=msDs-GroupManagedServiceAccount)' msDS-ManagedPassword" );
ldap_search_result =
Util::execute_ldapsearch( gmsa_account_name, distinguished_name, fqdn, search_string );
if ( ldap_search_result.first == 0 )
{
std::size_t pos = ldap_search_result.second.find( "msDS-ManagedPassword:" );
if ( pos != std::string::npos )
{
std::string log_str = ldap_search_result.second.substr( 0, pos );
log_str = "ldapsearch successful with FQDN = " + fqdn + ", cmd = " + log_str + "," +
"search_string = " + search_string;
std::cerr << log_str << std::endl;
cf_logger.logger( LOG_INFO, log_str.c_str() );
}
break;
}
else
{
std::string log_str = "ldapsearch failed with FQDN = " + fqdn + " " +
ldap_search_result.second.c_str() + " " + search_string;
std::cerr << log_str << std::endl;
cf_logger.logger( LOG_INFO, log_str.c_str() );
}
}
fqdn_list_result.clear();
if ( ldap_search_result.first != 0 ) // ldapsearch did not work in any FQDN
{
return std::make_pair( -1, std::string( "" ) );
}
std::pair<size_t, void*> password_found_result =
Util::find_password( ldap_search_result.second );
OPENSSL_cleanse( (void*)ldap_search_result.second.c_str(),
strlen( ldap_search_result.second.c_str() ) );
if ( password_found_result.first == 0 || password_found_result.second == nullptr )
{
std::string log_str = Util::getCurrentTime() + '\t' + "ERROR: Password not found";
std::cerr << log_str << std::endl;
cf_logger.logger( LOG_ERR, log_str.c_str() );
return std::make_pair( -1, log_str );
}
blob_t* blob = ( (blob_t*)password_found_result.second );
auto* blob_password = (uint8_t*)blob->current_password;
std::transform( domain_name.begin(), domain_name.end(), domain_name.begin(),
[]( unsigned char c ) { return std::toupper( c ); } );
std::string default_principal = "'" + gmsa_account_name + "$'" + "@" + domain_name;
/* Pipe password to the utf16 decoder and kinit */
std::string kinit_cmd = std::string("dotnet ") + std::string( install_path_for_decode_exe ) +
std::string( " | kinit " ) + std::string( " -c " ) + krb_cc_name +
" -V " + default_principal;
std::cerr << Util::getCurrentTime() << '\t' << "INFO:" << kinit_cmd << std::endl;
FILE* fp = popen( kinit_cmd.c_str(), "w" );
if ( fp == nullptr )
{
perror( "kinit failed" );
OPENSSL_cleanse( password_found_result.second, password_found_result.first );
OPENSSL_free( password_found_result.second );
std::string log_message = "ERROR: " + std::string( __func__ ) + " : " +
std::to_string( __LINE__ ) + " kinit failed";
cf_logger.logger( LOG_ERR, log_message.c_str() );
std::cerr << Util::getCurrentTime() << '\t' << "ERROR: kinit failed" << std::endl;
return std::make_pair( -1, std::string( "kinit failed" ) );
}
fwrite( blob_password, 1, GMSA_PASSWORD_SIZE, fp );
int error_code = pclose( fp );
// kinit output
std::string log_str = Util::getCurrentTime() + '\t' +
"INFO: kinit return value = " + std::to_string( error_code );
std::cerr << log_str << std::endl;
cf_logger.logger( LOG_ERR, log_str.c_str() );
OPENSSL_cleanse( password_found_result.second, password_found_result.first );
return std::make_pair( error_code, krb_cc_name );
}