Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

"kinit" program doesn't add to cache?

I’ve tried to implement the kinit command by code.

After struggling a bit I can run it successfully using krb5 on Linux Rocky 8.5.

My problem is that after running my program without any error, I can’t see anything when running klist,
While when running the kinit -kt test.keytab username@DOMAIN I can see the Kerberos ticket when running klist.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I’m Just wondering what I’ve been missing.
I want it to run with the default cache exactly as the above kinit does.

#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,ret)<<std::endl;
                    }
                }
                else
                {
                    std::cerr<<"krb5_kt_resolve:"<<krb5_get_error_message(context,ret)<<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,ret)<<std::endl;
                }
            }
        }
        else
        {
            std::cerr<<"krb5_parse_name:"<<krb5_get_error_message(context,ret)<<std::endl;
        }
    }
    else
    {
        // Handle error
        std::cerr<<"krb5_init_context:"<<krb5_get_error_message(context,ret)<<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,ret)<<std::endl;
                }
            }
            else
            {
                std::cerr<<"krb5_cc_initialize:"<<krb5_get_error_message(context,ret)<<std::endl;
            }
        }
        else
        {
            std::cerr<<"krb5_cc_default:"<<krb5_get_error_message(context,ret)<<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;
} 

>Solution :

You’re calling krb5_cc_destroy() at the end. As the documentation says, it works like kdestroy:

This function destroys any existing contents of cache and closes the handle to it.

To close the handle without destroying contents, use krb5_cc_close().

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading