我尝试通过代码实现
kinit
命令。
经过一番努力,我可以在 Linux Rocky 8.5 上使用 krb5 成功运行它。
我的问题是,运行我的程序没有任何错误后,运行时我看不到任何东西
klist
,
当运行 kinit -kt test.keytab username@DOMAIN
时,我可以在运行 klist
时看到 Kerberos 票证。
我只是想知道我错过了什么。 我希望它与上面的
kinit
一样使用默认缓存运行。
#include <krb5.h>
#include <iostream>
#include <string>
#define RESULT_OK(X) ((X)==0)
int kinit(const std::string& username, const std::string& domain, const std::string& password, bool password_is_keytab)
{
krb5_context context=NULL;
krb5_principal principal=NULL;
krb5_creds creds;
krb5_keytab keytab=NULL;
// Init Kerberos context
krb5_error_code ret = krb5_init_context(&context);
if (RESULT_OK(ret))
{
// Parse the principal name, create principal
ret = krb5_parse_name(context, (username + "@" + domain).c_str(), &principal);
if(RESULT_OK(ret))
{
if(password_is_keytab)
{
ret = krb5_kt_resolve(context, password.c_str(), &keytab);
if(RESULT_OK(ret))
{
ret = krb5_get_init_creds_keytab(context, &creds, principal, keytab, 0, NULL, NULL);
if(RESULT_OK(ret))
{
//OK
}
else
{
std::cerr<<"krb5_get_init_creds_keytab:"<<krb5_get_error_message(context)<<std::endl;
}
}
else
{
std::cerr<<"krb5_kt_resolve:"<<krb5_get_error_message(context)<<std::endl;
}
}
else
{
ret = krb5_get_init_creds_password(context, &creds, principal, password.c_str(),NULL, NULL, 0, NULL, NULL);
if(RESULT_OK(ret))
{
//OK
}
else
{
std::cerr<<"krb5_get_init_creds_password:"<<krb5_get_error_message(context)<<std::endl;
}
}
}
else
{
std::cerr<<"krb5_parse_name:"<<krb5_get_error_message(context)<<std::endl;
}
}
else
{
// Handle error
std::cerr<<"krb5_init_context:"<<krb5_get_error_message(context)<<std::endl;
}
if(RESULT_OK(ret))
{
krb5_ccache cache = NULL;
ret = krb5_cc_default(context, &cache);
if(RESULT_OK(ret))
{
ret = krb5_cc_initialize(context, cache, principal);
if(RESULT_OK(ret))
{
ret = krb5_cc_store_cred(context, cache, &creds);
if(RESULT_OK(ret))
{
std::cout<<"kinit succeeded"<<std::endl;
}
else
{
std::cerr<<"krb5_cc_store_cred:"<<krb5_get_error_message(context)<<std::endl;
}
}
else
{
std::cerr<<"krb5_cc_initialize:"<<krb5_get_error_message(context)<<std::endl;
}
}
else
{
std::cerr<<"krb5_cc_default:"<<krb5_get_error_message(context)<<std::endl;
}
if(cache) krb5_cc_destroy(context, cache);
}
if(keytab) krb5_kt_close(context, keytab);
krb5_free_cred_contents(context, &creds);
if(principal) krb5_free_principal(context, principal);
if(context) krb5_free_context(context);
return ret;
}
int main()
{
std::string username = "username";
std::string domain = "DOMAIN";
std::string keytab = "/etc/keytab/test.keytab";
int res = kinit(username, domain, keytab, 1);
std::cout<<"res = "<<res<<std::endl;
return res;
}
您最后会打电话给
krb5_cc_destroy()
。正如文档所说,它的工作原理类似于 kdestroy
:
此函数销毁cache的任何现有内容并关闭它的句柄。
要关闭手柄而不破坏内容,请使用
krb5_cc_close()
。