[28272] in Kerberos
Re: [modauthkerb] Saving credential with KrbSaveCredentials
daemon@ATHENA.MIT.EDU (Mikkel Kruse Johnsen)
Wed Aug 15 20:28:26 2007
From: Mikkel Kruse Johnsen <mikkel@linet.dk>
To: achim@grolmsnet.de
In-Reply-To: <200708141930.49168.achim@grolmsnet.de>
Content-Type: multipart/mixed; boundary="=-RsY6BcWm50qepaHQRESa"
Date: Wed, 15 Aug 2007 09:02:16 +0200
Message-Id: <1187161336.3009.7.camel@tux.lib.cbs.dk>
Mime-Version: 1.0
Cc: modauthkerb-help@lists.sourceforge.net, kerberos <kerberos@mit.edu>
Reply-To: mikkel@linet.dk
Errors-To: kerberos-bounces@mit.edu
--=-RsY6BcWm50qepaHQRESa
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Hi All
I got it to work. It seems there is an error in the SPNEGO code on MIT
Kerberos. When compiling mod_auth_kerb to use it's internal SPNEGO code
everything works fine.
The error as I see it, is that autheticate works but saving the
credential fails.
...
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1553): [client
130.226.36.170] kerb_authenticate_user entered with user (NULL) and
auth_type Kerberos
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1553): [client
130.226.36.170] kerb_authenticate_user entered with user (NULL) and
auth_type Kerberos
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1206): [client
130.226.36.170] Acquiring creds for HTTP/sugi.cbs.dk@CBS.DK
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1364): [client
130.226.36.170] Verifying client data using KRB5 GSS-API
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1380): [client
130.226.36.170] Verification returned code 0 lifetime 79137
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1398): [client
130.226.36.170] GSS-API token of length 22 bytes will be sent back
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1447): [client
130.226.36.170] set cached name mkj.lib@CBS.DK for connection
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1456): [client
130.226.36.170] krb_save_credentials activated, GSS_C_DELEG_FLAG
available
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1105): [client
130.226.36.170] Lifetime of delegated credential is expired
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1120): [client
130.226.36.170] Display name (mkj.lib@CBS.DK)
[Tue Aug 14 15:21:32 2007] [debug] src/mod_auth_kerb.c(1132): [client
130.226.36.170] Cred Usage GSS_C_BOTH
[Tue Aug 14 15:21:32 2007] [error] [client 130.226.36.170] Cannot store
delegated credential (gss_krb5_copy_ccache: Invalid credential was
supplied (No error))
....
As you can see the credential is expired when using the SPNEGO in MIT
kerberos.
...
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1553): [client
130.226.36.170] kerb_authenticate_user entered with user (NULL) and
auth_type Kerberos
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1553): [client
130.226.36.170] kerb_authenticate_user entered with user (NULL) and
auth_type Kerberos
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1206): [client
130.226.36.170] Acquiring creds for HTTP/sugi.cbs.dk@CBS.DK
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1364): [client
130.226.36.170] Verifying client data using SPNEGO GSS-API
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1380): [client
130.226.36.170] Verification returned code 0 lifetime 27495
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1398): [client
130.226.36.170] GSS-API token of length 22 bytes will be sent back
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1447): [client
130.226.36.170] set cached name mkj.lib@CBS.DK for connection
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1456): [client
130.226.36.170] krb_save_credentials activated, GSS_C_DELEG_FLAG
available
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1108): [client
130.226.36.170] Lifetime of delegated credential is 27495
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1120): [client
130.226.36.170] Display name (mkj.lib@CBS.DK)
[Wed Aug 15 08:41:46 2007] [debug] src/mod_auth_kerb.c(1125): [client
130.226.36.170] Cred Usage GSS_C_INITIATE
....
But using the SPNEGO in mod_auth_kerb it is not.
So is this an error in MIT kerberos or is mod_auth_kerb using the SPNEGO
wrong ?
/Mikkel
On Tue, 2007-08-14 at 19:30 +0200, Achim Grolms wrote:
> On Friday 10 August 2007 21:02, Henry B. Hotz wrote:
>
> > > Is there anyone who has this working, saving the ticket from either
> > > Firefox/linux, Firefox/WinXP, IE7/WinXP ?
> >
> > Yes, I've had no problems with the two WinXP cases. Have done
> > Firefox both with native Windows SSPI and with KfW GSSAPI.
>
> That means your requests use the SPNEGO mechtype in every case?
>
> On your mod_auth_kerb side - what code does the SPNEGO processing,
> mod_auth_kerb itself or a SPNEGO-supporting Kerberosimplementation?
>
>
> Background of this question:
> I have asked Mikkel to run HTTP-Requests on the Firefoxmachine
> using Perl and LWP::Authen::Negotiate (from CPAN)
> because LWP::Authen::Negotiate can be easily modified.
>
> The strange thing is:
>
> If using GSSAPI-mechtype Kerberos5 everything works fine.
> If using GSSAPI-mechtype SPNEGO Mikkel gets the same results
> as if he uses his Firefox.
>
> Any ideas?
>
> Achim
> Received-SPF: pass (0: SPF record at ispgateway.de designates 80.67.18.14 as permitted sender)
>
> !DSPAM:46c1e6cb107062091219428!
>
Mikkel Kruse
Johnsen
Adm.Dir.
Linet
Ørholmgade 6 st tv
Copenhagen N 2200
Denmark
Work: +45 21287793
Mobile: +45
21287793
Email:
mikkel@linet.dk
IM:
mikkel@linet.dk
(MSN)
Professional
Profile
Healthcare
Network
Consultant
--=-RsY6BcWm50qepaHQRESa
Content-Disposition: attachment; filename=mod_auth_kerb-5.3-deleg.patch
Content-Type: text/x-patch; name=mod_auth_kerb-5.3-deleg.patch; charset=UTF-8
Content-Transfer-Encoding: 7bit
diff -r -u mod_auth_kerb-5.3.orig/src/mod_auth_kerb.c mod_auth_kerb-5.3/src/mod_auth_kerb.c
--- mod_auth_kerb-5.3.orig/src/mod_auth_kerb.c 2007-07-25 11:38:20.000000000 +0200
+++ mod_auth_kerb-5.3/src/mod_auth_kerb.c 2007-08-15 08:41:11.000000000 +0200
@@ -1060,6 +1060,13 @@
krb5_context context;
int ret = HTTP_INTERNAL_SERVER_ERROR;
+ gss_name_t name;
+ OM_uint32 lifetime;
+ gss_cred_usage_t cred_usage;
+ gss_OID_set mechanisms;
+
+ gss_buffer_desc output_name_buffer;
+
problem = krb5_init_context(&context);
if (problem) {
log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Cannot initialize krb5 context");
@@ -1080,6 +1087,57 @@
goto end;
}
+ // Start Credential Check
+ //
+ maj_stat = gss_inquire_cred (&min_stat, delegated_cred, &name, &lifetime, &cred_usage, &mechanisms);
+ if (maj_stat != GSS_S_COMPLETE) {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Inquire delegated credential (%s)",
+ get_gss_error(r->pool, maj_stat, min_stat, "gss_inquire_cred"));
+ goto end;
+ }
+
+ if (lifetime == GSS_C_INDEFINITE) {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Lifetime of delegated credential never expires");
+ } else {
+ if (lifetime == 0) {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Lifetime of delegated credential is expired");
+ } else {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Lifetime of delegated credential is %d", lifetime);
+ }
+ }
+
+ maj_stat = gss_display_name (&min_stat, name, &output_name_buffer, NULL);
+ if (maj_stat != GSS_S_COMPLETE) {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Display name (%s)",
+ get_gss_error(r->pool, maj_stat, min_stat, "gss_display_name"));
+ goto end;
+ } else {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Display name (%s)", (char *)output_name_buffer.value);
+ }
+
+ if (cred_usage == GSS_C_INITIATE) {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Cred Usage GSS_C_INITIATE");
+ } else {
+ if (cred_usage == GSS_C_ACCEPT) {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Cred Usage GSS_C_ACCEPT");
+ } else {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Cred Usage GSS_C_BOTH");
+ }
+ }
+
+ gss_release_oid_set(&min_stat, &mechanisms);
+ //
+ // End Credential Check
+
maj_stat = gss_krb5_copy_ccache(&min_stat, delegated_cred, ccache);
if (GSS_ERROR(maj_stat)) {
log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
@@ -1125,7 +1183,7 @@
token.length = strlen(buf) + 1;
major_status = gss_import_name(&minor_status, &token,
- (have_server_princ) ? GSS_KRB5_NT_PRINCIPAL_NAME : GSS_C_NT_HOSTBASED_SERVICE,
+ (have_server_princ) ? /*GSS_KRB5_NT_PRINCIPAL_NAME*/ (gss_OID)gss_nt_krb5_name : /*GSS_C_NT_HOSTBASED_SERVICE*/ (gss_OID)gss_nt_service_name,
&server_name);
memset(&token, 0, sizeof(token));
if (GSS_ERROR(major_status)) {
@@ -1163,6 +1221,7 @@
return 0;
}
+#ifndef GSSAPI_SUPPORTS_SPNEGO
static int
cmp_gss_type(gss_buffer_t token, gss_OID oid)
{
@@ -1189,6 +1248,7 @@
return memcmp(p, oid->elements, oid->length);
}
+#endif
#define NAMEKEY "mod_auth_kerb:client_name"
@@ -1198,7 +1258,13 @@
authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
const char *auth_line, char **negotiate_ret_value)
{
- OM_uint32 major_status, minor_status, minor_status2;
+ krb5_context ctx;
+ krb5_keytab keytab;
+ krb5_kt_cursor cursor;
+ krb5_keytab_entry entry;
+ int k5_errno;
+ char *principal = NULL;
+ OM_uint32 major_status, minor_status, minor_status2, major_status_accept;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
const char *auth_param = NULL;
@@ -1215,6 +1281,9 @@
spnego_oid.length = 6;
spnego_oid.elements = (void *)"\x2b\x06\x01\x05\x05\x02";
+ OM_uint32 acc_ret_flags;
+ OM_uint32 time_rec;
+
if (conf->krb_5_keytab) {
char *ktname;
/* we don't use the ap_* calls here, since the string passed to putenv()
@@ -1234,9 +1303,11 @@
#endif
}
+/*
ret = get_gss_creds(r, conf, &server_creds);
if (ret)
goto end;
+*/
/* ap_getword() shifts parameter */
auth_param = ap_getword_white(r->pool, &auth_line);
@@ -1264,54 +1335,81 @@
gss_accept_sec_context_spnego : gss_accept_sec_context;
#endif
- log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Verifying client data using %s",
+ /* We're going to try accepting the context with every different principal
+ available in our keytab if we can. Otherwise, we're going to fall back
+ on just doing this once with the specified principal name. If k5_errno
+ is zero, we're walking through the keytab; otherwise, we're not. */
+ k5_errno = krb5_init_context(&ctx);
+ if (k5_errno == 0 && conf->krb_5_keytab)
+ k5_errno = krb5_kt_resolve(ctx, conf->krb_5_keytab, &keytab);
+ else
+ k5_errno = krb5_kt_default(ctx, &keytab);
+ if (k5_errno == 0)
+ k5_errno = krb5_kt_start_seq_get(ctx, keytab, &cursor);
+
+ /* Here's the big loop in which we try to do the authentication. */
+ do {
+ if (k5_errno == 0)
+ k5_errno = krb5_kt_next_entry(ctx, keytab, &entry, &cursor);
+ if (k5_errno == 0)
+ k5_errno = krb5_unparse_name(ctx, entry.principal, &principal);
+ if (k5_errno == 0)
+ conf->krb_service_name = principal;
+
+ ret = get_gss_creds(r, conf, &server_creds);
+ if (ret)
+ goto end;
+
+ /* pridat: Read client Negotiate data of length XXX, prefix YYY */
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Verifying client data using %s",
(accept_sec_token == gss_accept_sec_context)
? "KRB5 GSS-API"
: "SPNEGO GSS-API");
- major_status = accept_sec_token(&minor_status,
- &context,
- server_creds,
- &input_token,
- GSS_C_NO_CHANNEL_BINDINGS,
- &client_name,
- NULL,
- &output_token,
- NULL,
- NULL,
- &delegated_cred);
- log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "Verification returned code %d", major_status);
- if (output_token.length) {
- char *token = NULL;
- size_t len;
+ major_status_accept = accept_sec_token(&minor_status,
+ &context,
+ server_creds,
+ &input_token,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &client_name,
+ NULL,
+ &output_token,
+ &acc_ret_flags,
+ &time_rec,
+ &delegated_cred);
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Verification returned code %d lifetime %d", major_status_accept, time_rec);
+ if (output_token.length) {
+ char *token = NULL;
+ size_t len;
- len = apr_base64_encode_len(output_token.length) + 1;
- token = apr_pcalloc(r->connection->pool, len + 1);
- if (token == NULL) {
- log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ len = apr_base64_encode_len(output_token.length) + 1;
+ token = apr_pcalloc(r->connection->pool, len + 1);
+ if (token == NULL) {
+ log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"ap_pcalloc() failed (not enough memory)");
- ret = HTTP_INTERNAL_SERVER_ERROR;
- gss_release_buffer(&minor_status2, &output_token);
- goto end;
- }
- apr_base64_encode(token, output_token.value, output_token.length);
- token[len] = '\0';
- *negotiate_ret_value = token;
- log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "GSS-API token of length %d bytes will be sent back",
- output_token.length);
- gss_release_buffer(&minor_status2, &output_token);
- set_kerb_auth_headers(r, conf, 0, 0, *negotiate_ret_value);
- }
+ ret = HTTP_INTERNAL_SERVER_ERROR;
+ gss_release_buffer(&minor_status2, &output_token);
+ goto end;
+ }
+ apr_base64_encode(token, output_token.value, output_token.length);
+ token[len] = '\0';
+ *negotiate_ret_value = token;
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "GSS-API token of length %d bytes will be sent back",
+ output_token.length);
+ gss_release_buffer(&minor_status2, &output_token);
+ set_kerb_auth_headers(r, conf, 0, 0, *negotiate_ret_value);
+ }
+ } while (k5_errno == 0 && GSS_ERROR(major_status_accept));
- if (GSS_ERROR(major_status)) {
+ if (GSS_ERROR(major_status_accept)) {
if (input_token.length > 7 && memcmp(input_token.value, "NTLMSSP", 7) == 0)
log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"Warning: received token seems to be NTLM, which isn't supported by the Kerberos module. Check your IE configuration.");
log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "%s", get_gss_error(r->pool, major_status, minor_status,
+ "%s", get_gss_error(r->pool, major_status_accept, minor_status,
"gss_accept_sec_context() failed"));
/* Don't offer the Negotiate method again if call to GSS layer failed */
*negotiate_ret_value = NULL;
@@ -1323,7 +1421,7 @@
/* This is a _Kerberos_ module so multiple authentication rounds aren't
* supported. If we wanted a generic GSS authentication we would have to do
* some magic with exporting context etc. */
- if (major_status & GSS_S_CONTINUE_NEEDED) {
+ if (major_status_accept & GSS_S_CONTINUE_NEEDED) {
ret = HTTP_UNAUTHORIZED;
goto end;
}
@@ -1351,8 +1449,30 @@
}
#endif
- if (conf->krb_save_credentials && delegated_cred != GSS_C_NO_CREDENTIAL)
- store_gss_creds(r, conf, (char *)output_token.value, delegated_cred);
+ if (major_status_accept == GSS_S_COMPLETE ) {
+ if (conf->krb_save_credentials) {
+ if (delegated_cred != GSS_C_NO_CREDENTIAL) {
+ if (acc_ret_flags & GSS_C_DELEG_FLAG) {
+ log_rerror( APLOG_MARK, APLOG_DEBUG, 0, r,
+ "krb_save_credentials activated, GSS_C_DELEG_FLAG available");
+
+ store_gss_creds(r, conf, (char *)output_token.value, delegated_cred);
+ }
+ else {
+ log_rerror( APLOG_MARK, APLOG_DEBUG, 0, r,
+ "krb_save_credentials activated, no GSS_C_DELEG_FLAG");
+ }
+ }
+ else {
+ log_rerror( APLOG_MARK, APLOG_DEBUG, 0, r,
+ "krb_save_credentials activated, no GSS_C_NO_CREDENTIAL");
+ }
+ }
+ }
+ else {
+ log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
+ "krb_save_credentials not activated, no GSS_S_COMPLETE");
+ }
gss_release_buffer(&minor_status, &output_token);
--=-RsY6BcWm50qepaHQRESa
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
________________________________________________
Kerberos mailing list Kerberos@mit.edu
https://mailman.mit.edu/mailman/listinfo/kerberos
--=-RsY6BcWm50qepaHQRESa--