Skip Menu |

This queue is for tickets about the Krb5 CPAN distribution.

Report information
The Basics
Id: 89446
Status: new
Priority: 0/
Queue: Krb5

People
Owner: Nobody in particular
Requestors: jaroslaw.polok [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: (no value)



Subject: [PATCH]: Add support for Kerberos 'Services 4 User' protocol extensions to the module
Hello, Attached patch implements 'Services 4 User' Kerberos protocol extension functions: http://k5wiki.kerberos.org/wiki/Projects/Services4User - S4U2Self - protocol transition. - S4U2Proxy - constrained delegation. These extensions are implemented starting with MIT krb5 1.8, I've tested attached patch on Red Hat Enterprise Linux 6.4 - krb5 1.10, perl-Authen-Krb5 1.9. Could you consider adding this functionality to the Authen::Krb5 module ? Best Regards Jarek
Subject: Krb5-1.9-S4U.patch
This patch adds 'Services for User' (S4U) Kerberos protocol extensions implementation (MIT Krb5 >= 1.10): http://k5wiki.kerberos.org/wiki/Projects/Services4User Both S4U2Self (protocol transition) and S4U2Proxy (constrained delegation) extensions are implemented. Implementation tested with: Red Hat Enterprise Linux 6.4 (krb5 1.10), perl-Authen-Krb5 1.9 (plus this patch), Microsoft Active Directory 2008. 13.10.2013 Jaroslaw.Polok@gmail.com diff -Naur Krb5-1.9/Changes Krb5-1.9-S4U/Changes --- Krb5-1.9/Changes 2010-01-04 02:31:03.000000000 +0100 +++ Krb5-1.9-S4U/Changes 2013-10-13 13:37:46.835596507 +0200 @@ -1,5 +1,10 @@ Revision history for Perl extension Krb5. +1.X Add get_credentials_for_user(), get_credentials_for_proxy() + S4U2Self/S4U2Proxy implementation (MIT Krb5 >= 1.10) + http://k5wiki.kerberos.org/wiki/Projects/Services4User + (jaroslaw.polok@gmail.com) + 1.9 Add Authen::Krb5::Creds object (tom.jones@oucs.ox.ac.uk) 1.8 Fix broken get_in_tkt_with_password implementation (rra@debian.org) diff -Naur Krb5-1.9/Krb5.pm Krb5-1.9-S4U/Krb5.pm --- Krb5-1.9/Krb5.pm 2010-01-04 02:38:58.000000000 +0100 +++ Krb5-1.9-S4U/Krb5.pm 2013-10-14 09:35:25.813871166 +0200 @@ -231,6 +231,30 @@ supported in the Perl module. In this module, it's implemented in terms of krb5_get_init_creds_keytab, krb5_cc_initialize, and krb5_cc_store_cred. +=item get_credentials_for_user(client, server, cc) + +Obtain credentials for user using S4U2Self protocol extension (protocol +transition) 'client' is a principal object for which you want credentials. +'server' is a principal which can acquire credentials for 'client'. +'cc' is a Authen::Krb5::Ccache object representing the current +credentials cache. Returns a Kerberos error code. + +This interface implements S4U2Self protocol extension described at: +http://k5wiki.kerberos.org/wiki/Projects/Services4User#API + += item get_credentials_for_proxy(client, server, proxy, cc, keytab) + +Obtain credentials for user using S4U2Proxy protocol extension +(constrained delegation). 'client' is a principal object for which +you want credentials. 'server' is a principal which can acquire +credentials for 'client' for principal object 'proxy'. +'cc' is a Authen::Krb5::Ccache object representing the current +credentials cache. 'keytab' is a keytab object containing valid +keys for 'server'. Returns a Kerberos error code. + +This interface implements S4U2Proxy protocol extension described at: +http://k5wiki.kerberos.org/wiki/Projects/Services4User#API + =item mk_req(auth_context,ap_req_options,service,hostname,in,cc) Obtains a ticket for a specified service and returns a KRB_AP_REQ message diff -Naur Krb5-1.9/Krb5.xs Krb5-1.9-S4U/Krb5.xs --- Krb5-1.9/Krb5.xs 2010-01-04 02:29:19.000000000 +0100 +++ Krb5-1.9-S4U/Krb5.xs 2013-10-14 09:34:07.741554748 +0200 @@ -52,6 +52,8 @@ */ krb5_error_code krb5_free_krbhst(krb5_context, char * const *); krb5_error_code krb5_get_krbhst(krb5_context, const krb5_data *, char ***); +krb5_error_code krb5_get_credentials_for_user(krb5_context, krb5_flags, krb5_ccache, krb5_creds *,krb5_data *, krb5_creds **); +krb5_error_code krb5_get_credentials_for_proxy(krb5_context, krb5_flags, krb5_ccache, krb5_creds *,krb5_ticket *, krb5_creds **); /* * The following three routines implement a "safehouse" for nested Kerberos @@ -331,6 +333,167 @@ OUTPUT: RETVAL + +Authen::Krb5::Creds +krb5_get_credentials_for_user(principal_for_user, principal, cc) + Authen::Krb5::Principal principal_for_user + Authen::Krb5::Principal principal + Authen::Krb5::Ccache cc + + PREINIT: + krb5_creds creds; + + CODE: + memset(&creds, 0, sizeof(creds)); + creds.client = principal_for_user; + creds.server = principal; + creds.keyblock.enctype = 0; + + RETVAL = calloc(1, sizeof(krb5_creds)); + if (RETVAL == NULL) { + err = errno; + XSRETURN_UNDEF; + } + + err = krb5_get_credentials_for_user(context, KRB5_GC_NO_STORE, cc, &creds, NULL, &RETVAL); + if (err) { + free(RETVAL); + XSRETURN_UNDEF; + } + can_free((SV *)RETVAL); + + OUTPUT: + RETVAL + + +Authen::Krb5::Creds +krb5_get_credentials_for_proxy(principal_for_user, principal, principal_for_proxy, cc, keytab) + Authen::Krb5::Principal principal_for_user + Authen::Krb5::Principal principal + Authen::Krb5::Principal principal_for_proxy + Authen::Krb5::Ccache cc + Authen::Krb5::Keytab keytab + + PREINIT: + krb5_creds creds; + krb5_ticket *ticket=NULL; + krb5_creds *creds_out; + + char keytab_out_name[20]; + krb5_keytab keytab_out; + krb5_kt_cursor kt_cursor; + krb5_keytab_entry kt_entry; + + CODE: + +# NOTE: this part of code should not be necessary, unfortunately in MIT krb5 +# krb5_server_decrypt_ticket_keytab() takes into account first(?) +# principal found in a keytab and fails if that one does not +# match (for keytabs containing multiple principals), so we make a +# temporary keytab containg only entries we want as a workaround + + sprintf(keytab_out_name,"MEMORY:Krb5_%06d",getpid()); + + err = krb5_kt_resolve(context,keytab_out_name,&keytab_out); + if (err) { + XSRETURN_UNDEF; + } + + err = krb5_kt_start_seq_get(context,keytab,&kt_cursor); + if (err) { + XSRETURN_UNDEF; + } + + while(krb5_kt_next_entry(context,keytab,&kt_entry,&kt_cursor) == 0) { + if(krb5_principal_compare(context,kt_entry.principal,principal)) { + err=krb5_kt_add_entry(context,keytab_out,&kt_entry); + if (err) { + XSRETURN_UNDEF; + } + } + } + + if (err) { + XSRETURN_UNDEF; + } + + err = krb5_kt_end_seq_get(context,keytab,&kt_cursor); + if (err) { + XSRETURN_UNDEF; + } + +# +# NOTE: end of workaround +# + memset(&creds, 0, sizeof(creds)); + creds.client = principal_for_user; + creds.server = principal; + creds.keyblock.enctype = 0; + + creds_out = calloc(1, sizeof(krb5_creds)); + if (creds_out == NULL) { + err = errno; + XSRETURN_UNDEF; + } + + err = krb5_get_credentials_for_user(context, KRB5_GC_NO_STORE, cc, &creds, NULL, &creds_out); + if (err) { + free(creds_out); + XSRETURN_UNDEF; + } + + ticket = calloc(1, sizeof(krb5_ticket)); + if (ticket == NULL) { + err = errno; + free(creds_out); + XSRETURN_UNDEF; + } + + err = krb5_decode_ticket(&creds_out->ticket, &ticket); + if (err) { + free(creds_out); + free(ticket); + XSRETURN_UNDEF; + } + +# +# NOTE: temporary keytab_out used instead of input one (keytab) +# + err = krb5_server_decrypt_ticket_keytab(context, keytab_out, ticket); + if (err) { + free(creds_out); + free(keytab_out_name); + free(ticket); + XSRETURN_UNDEF; + } + + RETVAL = calloc(1, sizeof(krb5_creds)); + if (RETVAL == NULL) { + err = errno; + free(creds_out); + free(ticket); + XSRETURN_UNDEF; + } + + free(creds_out); + memset(&creds, 0, sizeof(creds)); + creds.client = ticket->enc_part2->client; + creds.server = principal_for_proxy; + creds.keyblock.enctype = 0; + + err= krb5_get_credentials_for_proxy(context, KRB5_GC_NO_STORE , cc, &creds, ticket, &RETVAL); + if (err) { + free(RETVAL); + free(ticket); + XSRETURN_UNDEF; + } + + free(ticket); + can_free((SV *)RETVAL); + + OUTPUT: + RETVAL + Authen::Krb5::Creds krb5_get_init_creds_password(client, password, service = NULL) Authen::Krb5::Principal client diff -Naur Krb5-1.9/sample_S4U Krb5-1.9-S4U/sample_S4U --- Krb5-1.9/sample_S4U 1970-01-01 01:00:00.000000000 +0100 +++ Krb5-1.9-S4U/sample_S4U 2013-10-14 09:40:40.794157904 +0200 @@ -0,0 +1,37 @@ +#!/usr/local/in/perl -w +# +# Just basic usage, no error checking .. etc.. +# to make it work you must use existing principals ! + +use Authen::Krb5; + +Authen::Krb5::init_context(); +Authen::Krb5::init_ets(); + +$krb5ccache = Authen::Krb5::cc_resolve('/tmp/test.ccache'); + +$krb5keytab = Authen::Krb5::kt_resolve('/etc/test.keytab'); + +$krb5princ = Authen::Krb5::parse_name('SERVICE1/hostname.host.domain'); +$krb5ccache->initialize($krb5princ); +$krb5creds = Authen::Krb5::get_init_creds_keytab($krb5princ,$krb5keytab); +$krb5ccache->store_cred($krb5creds); + +$krb5princ_for_user = Authen::Krb5::parse_name('joeuser'); + +# S4U2Self +$krb5creds_for_user= Authen::Krb5::get_credentials_for_user($krb5princ_for_user, $krb5princ, $krb5ccache); + +$krb5ccache->store_cred($krb5creds_for_user); + +# S4U2Proxy +$krb5princ_proxy = Authen::Krb5::parse_name('SERVICE2/hostname2.host.domain'); +$krb5creds_for_user_proxy = Authen::Krb5::get_credentials_for_proxy($krb5princ_for_user,$krb5princ,$krb5princ_proxy,$krb5ccache,$krb5keytab); + +$krb5ccache->store_cred($krb5creds_for_user_proxy); + + + + + +