Jeff Horwitz <[EMAIL PROTECTED]> writes: > Hi Russ--
> Once I stopped using Krb5 at the day job, I haven't kept up much with > interface changes. If you can send a patch, I will be more than happy > to apply it and make another release. I finally got around to working on this. This patch: * Adds get_init_creds_password and get_init_creds_keytab interfaces that follow the upstream interface and return an Authen::Krb5::Creds object rather than storing the new credentials directly into a ticket cache. * Adds a destructor for Authen::Krb5::Creds objects now that we're returning them to the user. * Adds a store_cred() method to Authen::Krb5::Ccache so that the caller can do something useful with the returned credentials. * Reimplements get_in_tkt_with_password and get_in_tkt_with_keytab in terms of get_init_creds_{password,keytab}, krb5_cc_initialize, and krb5_cc_store_cred. * Updates the documentation accordingly. Tested against MIT Kerberos 1.6.1, but these interfaces have been consistent for quite some time and shouldn't change with older versions of Kerberos. Let me know if you have any concerns or issues with the patch; I'm happy to adjust it as desired. -- Russ Allbery ([EMAIL PROTECTED]) <http://www.eyrie.org/~eagle/>
Index: Krb5.xs =================================================================== --- Krb5.xs (revision 5109) +++ Krb5.xs (working copy) @@ -6,6 +6,7 @@ #include "XSUB.h" #include <krb5.h> #include <com_err.h> +#include <errno.h> #include "krb5_constants.c" #ifdef __cplusplus @@ -310,6 +311,68 @@ OUTPUT: RETVAL +Authen::Krb5::Creds +krb5_get_init_creds_password(client, password, service = NULL) + Authen::Krb5::Principal client + char *password + char *service + + PREINIT: + krb5_get_init_creds_opt opt; + + CODE: + if (service != NULL && service[0] == '\0') service = NULL; + RETVAL = calloc(1, sizeof(krb5_creds)); + if (RETVAL == NULL) { + err = errno; + XSRETURN_UNDEF; + } + krb5_get_init_creds_opt_init(&opt); + + err = krb5_get_init_creds_password(context, RETVAL, client, password, + NULL, NULL, 0, service, &opt); + if (err) { + free(RETVAL); + XSRETURN_UNDEF; + } + can_free((SV *)RETVAL); + + OUTPUT: + RETVAL + +Authen::Krb5::Creds +krb5_get_init_creds_keytab(client, keytab, service = NULL) + Authen::Krb5::Principal client + Authen::Krb5::Keytab keytab + char *service + + PREINIT: + krb5_get_init_creds_opt opt; + + CODE: + if (service != NULL && service[0] == '\0') service = NULL; + RETVAL = calloc(1, sizeof(krb5_creds)); + if (RETVAL == NULL) { + err = errno; + XSRETURN_UNDEF; + } + krb5_get_init_creds_opt_init(&opt); + + err = krb5_get_init_creds_keytab(context, RETVAL, client, keytab, 0, + service, &opt); + if (err) { + free(RETVAL); + XSRETURN_UNDEF; + } + can_free((SV *)RETVAL); + + OUTPUT: + RETVAL + + + # These are legacy interfaces which are deprecated in the current MIT + # Kerberos. Reimplement them in terms of the new get_init_creds + # interfaces rather than call the deprecated functions. void krb5_get_in_tkt_with_password(client, server, password, cc) Authen::Krb5::Principal client @@ -319,49 +382,69 @@ PREINIT: krb5_creds cr; - krb5_timestamp now; - krb5_deltat lifetime = 0; + krb5_get_init_creds_opt opt; + char *service; CODE: memset((char *)&cr,0,sizeof(krb5_creds)); - krb5_timeofday(context, &now); - cr.client = client; - cr.server = server; - cr.times.starttime = now; - cr.times.endtime = now + KRB5_DEFAULT_LIFE; - cr.times.renew_till = 0; + krb5_get_init_creds_opt_init(&opt); + err = krb5_unparse_name(context, server, &service); + if (err) XSRETURN_UNDEF; - err = krb5_get_in_tkt_with_password(context, 0, 0, NULL, NULL, - password, cc, &cr, 0); + err = krb5_get_in_tkt_with_password(context, &cr, client, password, + NULL, NULL, 0, service, &opt); + free(service); + if (err) XSRETURN_UNDEF; - if (err) XSRETURN_UNDEF; + err = krb5_cc_initialize(context, cc, client); + if (err) { + krb5_free_cred_contents(context, &cr); + XSRETURN_UNDEF; + } + err = krb5_cc_store_cred(context, cc, &cr); + if (err) { + krb5_free_cred_contents(context, &cr); + XSRETURN_UNDEF; + } + krb5_free_cred_contents(context, &cr); + XSRETURN_YES; void krb5_get_in_tkt_with_keytab(client, server, keytab, cc) Authen::Krb5::Principal client Authen::Krb5::Principal server - Authen::Krb5::Keytab keytab + Authen::Krb5::Keytab keytab Authen::Krb5::Ccache cc PREINIT: krb5_creds cr; - krb5_timestamp now; - krb5_deltat lifetime = 0; + krb5_get_init_creds_opt opt; + char *service; CODE: - memset((char *)&cr,0,sizeof(krb5_creds)); - krb5_timeofday(context, &now); - cr.client = client; - cr.server = server; - cr.times.starttime = now; - cr.times.endtime = now + KRB5_DEFAULT_LIFE; - cr.times.renew_till = 0; + memset(&cr,0,sizeof(krb5_creds)); + krb5_get_init_creds_opt_init(&opt); + err = krb5_unparse_name(context, server, &service); + if (err) XSRETURN_UNDEF; - err = krb5_get_in_tkt_with_keytab(context, 0, 0, NULL, NULL, - keytab, cc, &cr, 0); + err = krb5_get_init_creds_keytab(context, &cr, client, keytab, 0, + service, &opt); + free(service); + if (err) XSRETURN_UNDEF; - if (err) XSRETURN_UNDEF; + err = krb5_cc_initialize(context, cc, client); + if (err) { + krb5_free_cred_contents(context, &cr); + XSRETURN_UNDEF; + } + err = krb5_cc_store_cred(context, cc, &cr); + if (err) { + krb5_free_cred_contents(context, &cr); + XSRETURN_UNDEF; + } + krb5_free_cred_contents(context, &cr); + XSRETURN_YES; SV * @@ -602,6 +685,16 @@ XSRETURN_YES; } +void +store_cred(cc, creds) + Authen::Krb5::Ccache cc + Authen::Krb5::Creds creds + + CODE: + err = krb5_cc_store_cred(context, cc, creds); + if (err) XSRETURN_UNDEF; + XSRETURN_YES; + const char * get_name(cc) Authen::Krb5::Ccache cc @@ -1177,3 +1270,16 @@ OUTPUT: RETVAL + +MODULE = Authen::Krb5 PACKAGE = Authen::Krb5::Creds + +void +DESTROY(creds) + Authen::Krb5::Creds creds + + CODE: + if (creds && should_free((SV *)creds)) { + krb5_free_cred_contents(context, creds); + free(creds); + freed((SV *)creds); + } Index: Krb5.pm =================================================================== --- Krb5.pm (revision 5109) +++ Krb5.pm (working copy) @@ -188,22 +188,49 @@ I<kvno> and I<enctype>) and returns the key in the form of an Authen::Krb5::Keyblock object. +=item get_init_creds_password(client, password[, service]) + +Attempt to get an initial ticket for the client. 'client' is a principal +object for which you want an initial ticket. 'password' is the password for +the client. 'service', if given, is the string representation (not a +principal object) for the ticket to acquire. If not given, it defaults to +krbtgt/[EMAIL PROTECTED] for the local realm. Returns an Authen::Krb5::Creds +object or undef on failure. + +=item get_init_creds_keytab(client, keytab[, service]) + +Attempt to get an inintial ticket for the client using a keytab. 'client' +is a principal object for which you want an initial ticket. 'keytab' is a +keytab object created with kt_resolve. 'service', if given, is the string +representation (not a principal object) for the ticket to acquire. If not +given, it defaults to krbtgt/[EMAIL PROTECTED] for the local realm. Returns an +Authen::Krb5::Creds object or undef on failure. + =item get_in_tkt_with_password(client,server,password,cc) Attempt to get an initial ticket for the client. 'client' is a principal object for which you want an initial ticket. 'server' is a principal object -for the service (usually krbtgt/[EMAIL PROTECTED]). 'password' is the password for -the client, and 'cc' is a Authen::Krb5::Ccache object representing the current -credentials cache. Returns a Kerberos error code. +for the service (usually krbtgt/[EMAIL PROTECTED]). 'password' is the password +for the client, and 'cc' is a Authen::Krb5::Ccache object representing the +current credentials cache. Returns a Kerberos error code. +Although this interface is deprecated in the Kerberos C libraries, it's +supported in the Perl module. In this module, it's implemented in terms of +krb5_get_init_creds_password, krb5_cc_initialize, and krb5_cc_store_cred. + =item get_in_tkt_with_keytab(client,server,keytab,cc) Obtain an initial ticket for the client using a keytab. 'client' is a -principal object for which you want an initial ticket. 'server' is a principal -object for the service (usually krbtgt/[EMAIL PROTECTED]). 'keytab' is a keytab -object createed with kt_resolve. 'cc' is a Authen::Krb5::Ccache object -representing the current credentials cache. Returns a Kerberos error code. +principal object for which you want an initial ticket. 'server' is a +principal object for the service (usually krbtgt/[EMAIL PROTECTED]). 'keytab' is +a keytab object createed with kt_resolve. 'cc' is a Authen::Krb5::Ccache +object representing the current credentials cache. Returns a Kerberos error +code. +Although this interface is deprecated in the Kerberos C libraries, it's +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 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 @@ -322,6 +349,12 @@ Creates/refreshes a credentials cache for the primary principal 'p'. If the cache already exists, its contents are destroyed. +=item o store_cred(creds) + +Stores the given credentials, which should be an Authen::Krb5::Creds object +as returned from get_init_creds_password() or get_init_creds_keytab(), in +the cache. + =item o get_name Returns the name of the credentials cache.