У меня есть служба kerberos, на которую я могу попросить билет с помощью kinit и knvo. Я вижу в wireshark, что sname установлен в KRB5_NT_PRINCIPAL. Я пытаюсь сгенерировать заявку с помощью API MIT C, но не могу найти службу. Я заметил в WireShark, что разница в имени. С кодом c он отправляет sname-type как «KRB5_NT_SRV_HST» и завершается ошибкой. Я попытался установить тип service_principal на KRB5_NT_PRINCIPAL, но он все еще не работает. Запросы не выполняются в функции krb5_mk_req, которая является сообщением TGS-REQ. Вот мой код:
#include <stdio.h>
#include <krb5.h>
#include <com_err.h>
#include <string.h>
#include <unistd.h>
#define TKT_LIFETIME 30
#define NO_REPLAYCACHE
static void syslog_err(const char* tag, long code, const char*format, va_list args){
printf("%s: %s in %s\n", tag, error_message(code), format);
}
#define check_code(err, tag)\
if(err){\
void (*proc)(const char*, long, const char*, va_list);\
proc=set_com_err_hook(syslog_err);\
com_err("ERROR: ",(err),(tag));\
(void)set_com_err_hook(proc);\
goto cleanup;\
}
int main() {
const char *username="foo@BAR";
const char *password="foobar";
//const char *host="foobar";
const char kt_pathname[256] = "/etc/krb5.keytab";
char service[256]="krbtgt";
char host[256]="BAR";
krb5_error_code err;
krb5_error_code err_t;
krb5_context context;
krb5_auth_context auth_context = NULL;
krb5_creds credentials;
krb5_principal user_principal,
service_principal;
krb5_verify_init_creds_opt vic_options;
krb5_keytab keytab=NULL;
krb5_ccache ccache;
//char ccache_name[L_tmpnam + 8];
char ccache_name[19]="/tmp/krb5cc_XXXXXX";
krb5_get_init_creds_opt * gic_options;
#ifndef NO_REPLAYCACHE
krb5_verify_init_creds_opt vic_options;
#endif
krb5_data apreq_pkt;
char myhostname[256],sprinc[256];
int have_user_principal =0,
have_service_principal=0,
have_keytab=0,
have_credentials=0,
success=-1,
ccache_retval;
apreq_pkt.data=NULL;
err = krb5_init_context(&context);
check_code(err, "failed to init krb5 context");
ccache_retval = mkstemp(&ccache_name[12]);
if (ccache_retval == -1) printf("Error: failed to create a cache file");
err = krb5_cc_resolve(context,ccache_name,&ccache);
check_code(err, "fill a ccache file");
err = krb5_parse_name(context, username, &user_principal);
check_code(err, "parse principal name");
have_user_principal=1;
err = krb5_cc_initialize(context,ccache,user_principal);
check_code(err, "initialize cc cache");
(void) memset( (char*)&credentials, 0, sizeof(credentials));
krb5_get_init_creds_opt_alloc(context, &gic_options); // Allocate a new initial credential options structure
krb5_get_init_creds_opt_set_tkt_life(gic_options, TKT_LIFETIME); // Set the ticket lifetime in initial credential options
err = krb5_get_init_creds_password(context, &credentials, user_principal,password,0,0,0,NULL,gic_options); //Get initial credentials using a password
check_code(err, "get initial credentials")
// at this point, we have a ticket (stored in credentials)
err = krb5_cc_store_cred(context, ccache, &credentials); // Store credentials in a credential cache
err_t=err;
check_code(err, "store credentials");
if(err_t) have_credentials=1;
err = krb5_sname_to_principal(context,host,service,KRB5_NT_SRV_HST,&service_principal); //Generate a full principal name from a service name KRB5_NT_UNKNOWN
check_code(err, "sname_to_principal");
service_principal->type=KRB5_NT_PRINCIPAL;
have_service_principal=1;
err = krb5_kt_resolve(context,kt_pathname,&keytab); //Get a handle for a key table
check_code(err, "kt_resolve");
have_keytab=1;
#ifndef NO_REPLAYCACHE
krb5_verify_init_creds_opt_init(&vic_options); //Initialize a credential verification options structure
krb5_verify_init_creds_opt_set_ap_req_nofail(&vic_options,1); //Set whether credential verification is required
err = krb5_verify_init_creds(context, &credentials, service_principal, keytab,0,&vic_options); //Verify initial credentials against a keytab
check_code(err,"verify init credentials");
#else
err = krb5_mk_req(context,&auth_context,0,service,host,NULL,ccache,&apreq_pkt);
check_code(err, "apreq_pkt request");
if(auth_context){
krb5_auth_con_free(context,auth_context); //Free a krb5_auth_context structure.
auth_context=NULL;
}
err = krb5_auth_con_init(context,&auth_context); //Create and initialize an authentication context
check_code(err, "auth init");
err = krb5_auth_con_setflags(context,auth_context,~KRB5_AUTH_CONTEXT_DO_TIME); //Set a flags field in a krb5_auth_context structure
check_code(err, "auth set flags");
err = krb5_rd_req(context,&auth_context,&apreq_pkt,service_principal,keytab,NULL,NULL); // This function parses, decrypts and verifies a AP-REQ message
check_code(err, "decrypt & verify AP-REQ message");
if(auth_context){
krb5_auth_con_free(context,auth_context); //Free a krb5_auth_context structure.
auth_context=NULL;
}
#endif
err = krb5_cc_destroy(context,ccache);
if (err!=0)
printf("[*] Failed to destroy kerberos context \n");
else
success=1;
*/
cleanup:
if(apreq_pkt.data)
krb5_free_data_contents(context,&apreq_pkt); // Free the contents of a krb5_data structure and zero the data field
if(have_keytab){
krb5_kt_close(context,keytab);
if (err!=0)
printf("[*] Failed to destroy the keytab \n"); //Close a key table handle
}
krb5_cc_destroy(context,ccache);
if(have_user_principal)
krb5_free_principal(context,user_principal);
if(have_service_principal)
krb5_free_principal(context,service_principal);
if(have_credentials)
krb5_free_cred_contents(context,&credentials);
if(context)
krb5_free_context(context);
return 0;
}
файлы krb5.conf как на клиенте, так и на сервере:
KDC & Client krb5.conf:
[libdefaults]
encryption & properties
.
.
.
default_realm = TEST1.EXAMPLE.COM
[domain_realms]
.test1.example.com = TEST1.EXAMPLE.COM
test1.example.com = TEST1.EXAMPLE.COM
[logging]
files configurations
.
.
.
[realms]
TEST1.EXAMPLE.COM = {
kdc = TEST1.EXAMPLE.COM:88
default_domain = TEST1.EXAMPLE.COM
admin_server=TEST1.EXAMPLE.COM
}
, где TEST1.EXAMPLE.COM - их область (клиент и сервер & сервер приложений). IP-адрес каждого компьютера отображается в файле / etc / hosts, то есть: 192.168.xx
Спасибо!