Merge branch 'master' of ssh://moonshot.suchdamage.org:822/srv/git/moonshot
[mech_eap.orig] / util_reauth.c
index 0a8373d..8b853cb 100644 (file)
@@ -70,14 +70,11 @@ getAcceptorKey(krb5_context krbContext,
     krb5_error_code code;
     krb5_keytab keytab = NULL;
     krb5_keytab_entry ktent = { 0 };
-#ifdef HAVE_HEIMDAL_VERSION
-    krb5_kt_cursor cursor = { 0 };
-#else
-    krb5_kt_cursor cursor = NULL;
-#endif
+    krb5_kt_cursor cursor;
 
     *princ = NULL;
     memset(key, 0, sizeof(*key));
+    memset(&cursor, 0, sizeof(cursor));
 
     code = krb5_kt_default(krbContext, &keytab);
     if (code != 0)
@@ -100,40 +97,24 @@ getAcceptorKey(krb5_context krbContext,
 
         while ((code = krb5_kt_next_entry(krbContext, keytab,
                                           &ktent, &cursor)) == 0) {
-#ifdef HAVE_HEIMDAL_VERSION
-            if (ktent.keyblock.keytype == ctx->encryptionType)
-                break;
-            else
-                krb5_kt_free_entry(krbContext, &ktent);
-#else
-            if (ktent.key.enctype == ctx->encryptionType)
+            if (KRB_KEY_TYPE(KRB_KT_ENT_KEYBLOCK(&ktent)) == ctx->encryptionType)
                 break;
             else
-                krb5_free_keytab_entry_contents(krbContext, &ktent);
-#endif
+                KRB_KT_ENT_FREE(krbContext, &ktent);
         }
     }
 
     if (code == 0) {
         *princ = ktent.principal;
-#ifdef HAVE_HEIMDAL_VERSION
-        *key = ktent.keyblock;
-#else
-        *key = ktent.key;
-#endif
+        *key = *KRB_KT_ENT_KEYBLOCK(&ktent);
     }
 
 cleanup:
     if (cred == GSS_C_NO_CREDENTIAL || cred->name == GSS_C_NO_NAME)
         krb5_kt_end_seq_get(krbContext, keytab, &cursor);
     krb5_kt_close(krbContext, keytab);
-
     if (code != 0)
-#ifdef HAVE_HEIMDAL_VERSION
-        krb5_kt_free_entry(krbContext, &ktent);
-#else
-        krb5_free_keytab_entry_contents(krbContext, &ktent);
-#endif
+        KRB_KT_ENT_FREE(krbContext, &ktent);
 
     return code;
 }
@@ -144,22 +125,24 @@ freezeAttrContext(OM_uint32 *minor,
                   krb5_const_principal acceptorPrinc,
                   krb5_keyblock *session,
 #ifdef HAVE_HEIMDAL_VERSION
-                  krb5_authdata *authdata
+                  krb5_authdata *kdcIssuedAuthData
 #else
-                  krb5_authdata ***authdata
+                  krb5_authdata ***kdcIssuedAuthData
 #endif
                   )
 {
     OM_uint32 major, tmpMinor;
     krb5_error_code code;
+    krb5_context krbContext;
     gss_buffer_desc attrBuf = GSS_C_EMPTY_BUFFER;
 #ifdef HAVE_HEIMDAL_VERSION
-    AuthorizationData authDataBuf, *authData = &authDataBuf;
+    krb5_authdata authDataBuf, *authData = &authDataBuf;
     AuthorizationDataElement authDatum = { 0 };
 #else
     krb5_authdata *authData[2], authDatum = { 0 };
 #endif
-    krb5_context krbContext;
+
+    memset(kdcIssuedAuthData, 0, sizeof(*kdcIssuedAuthData));
 
     GSSEAP_KRB_INIT(&krbContext);
 
@@ -181,7 +164,7 @@ freezeAttrContext(OM_uint32 *minor,
 #endif
 
     code = krbMakeAuthDataKdcIssued(krbContext, session, acceptorPrinc,
-                                    authData, authdata);
+                                    authData, kdcIssuedAuthData);
     if (code != 0) {
         major = GSS_S_FAILURE;
         *minor = code;
@@ -213,13 +196,15 @@ gssEapMakeReauthCreds(OM_uint32 *minor,
     EncTicketPart enc_part;
     AuthorizationData authData = { 0 };
     krb5_crypto krbCrypto = NULL;
-    unsigned char *buf = NULL;
-    size_t buf_size, len;
+    krb5_data ticketData = { 0 };
+    krb5_data encPartData = { 0 };
+    size_t len;
 #else
     krb5_ticket ticket;
     krb5_enc_tkt_part enc_part;
+    krb5_data *ticketData = NULL;
 #endif
-    krb5_data *ticketData = NULL, *credsData = NULL;
+    krb5_data credsData = { 0 };
     krb5_creds creds = { 0 };
     krb5_auth_context authContext = NULL;
 
@@ -249,12 +234,12 @@ gssEapMakeReauthCreds(OM_uint32 *minor,
      * Generate a random session key to place in the ticket and
      * sign the "KDC-Issued" authorization data element.
      */
-    code = krb5_c_make_random_key(krbContext, ctx->encryptionType,
-                                  &session);
+#ifdef HAVE_HEIMDAL_VERSION
+    code = krb5_generate_random_keyblock(krbContext, ctx->encryptionType,
+                                         &session);
     if (code != 0)
         goto cleanup;
 
-#ifdef HAVE_HEIMDAL_VERSION
     enc_part.flags.initial = 1;
     enc_part.key = session;
     enc_part.crealm = ctx->initiatorName->krbPrincipal->realm;
@@ -271,7 +256,8 @@ gssEapMakeReauthCreds(OM_uint32 *minor,
     if (GSS_ERROR(major))
         goto cleanup;
 
-    ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, &enc_part, &len, code);
+    ASN1_MALLOC_ENCODE(EncTicketPart, encPartData.data, encPartData.length,
+                       &enc_part, &len, code);
     if (code != 0)
         goto cleanup;
 
@@ -282,20 +268,23 @@ gssEapMakeReauthCreds(OM_uint32 *minor,
     code = krb5_encrypt_EncryptedData(krbContext,
                                       krbCrypto,
                                       KRB5_KU_TICKET,
-                                      buf,
-                                      len,
+                                      encPartData.data,
+                                      encPartData.length,
                                       0,
                                       &ticket.enc_part);
     if (code != 0)
         goto cleanup;
 
-    GSSEAP_FREE(buf);
-    buf = NULL;
-
-    ASN1_MALLOC_ENCODE(Ticket, buf, buf_size, &ticket, &len, code);
+    ASN1_MALLOC_ENCODE(Ticket, ticketData.data, ticketData.length,
+                       &ticket, &len, code);
     if (code != 0)
         goto cleanup;
 #else
+    code = krb5_c_make_random_key(krbContext, ctx->encryptionType,
+                                  &session);
+    if (code != 0)
+        goto cleanup;
+
     enc_part.flags = TKT_FLG_INITIAL;
     enc_part.session = &session;
     enc_part.client = ctx->initiatorName->krbPrincipal;
@@ -331,7 +320,7 @@ gssEapMakeReauthCreds(OM_uint32 *minor,
     creds.times.endtime = enc_part.endtime;
     creds.times.renew_till = 0;
     creds.flags.b = enc_part.flags;
-    creds.ticket = *ticketData;
+    creds.ticket = ticketData;
     creds.authdata = authData;
 #else
     creds.keyblock = session;
@@ -354,32 +343,30 @@ gssEapMakeReauthCreds(OM_uint32 *minor,
     if (code != 0)
         goto cleanup;
 
-    code = krb5_mk_1cred(krbContext, authContext, &creds, &credsData, NULL);
+    code = krbMakeCred(krbContext, authContext, &creds, &credsData);
     if (code != 0)
         goto cleanup;
 
-    krbDataToGssBuffer(credsData, credBuf);
+    krbDataToGssBuffer(&credsData, credBuf);
 
 cleanup:
 #ifdef HAVE_HEIMDAL_VERSION
     if (krbCrypto != NULL)
         krb5_crypto_destroy(krbContext, krbCrypto);
-    if (buf != NULL)
-        GSSEAP_FREE(buf);
     free_AuthorizationData(&authData);
     free_EncryptedData(&ticket.enc_part);
+    krb5_data_free(&ticketData);
+    krb5_data_free(&encPartData);
 #else
     krb5_free_authdata(krbContext, enc_part.authorization_data);
     if (ticket.enc_part.ciphertext.data != NULL)
         GSSEAP_FREE(ticket.enc_part.ciphertext.data);
+    krb5_free_data(krbContext, ticketData);
 #endif
     krb5_free_keyblock_contents(krbContext, &session);
     krb5_free_principal(krbContext, server);
     krb5_free_keyblock_contents(krbContext, &acceptorKey);
-    krb5_free_data(krbContext, ticketData);
     krb5_auth_con_free(krbContext, authContext);
-    if (credsData != NULL)
-        GSSEAP_FREE(credsData);
 
     if (major == GSS_S_COMPLETE) {
         *minor = code;
@@ -643,9 +630,11 @@ cleanup:
     return major;
 }
 
+#ifndef HAVE_HEIMDAL_VERSION
 static gss_buffer_desc radiusAvpKrbAttr = {
     sizeof("urn:authdata-radius-avp") - 1, "urn:authdata-radius-avp"
 };
+#endif
 
 /*
  * Unfortunately extracting an AD-KDCIssued authorization data element
@@ -665,15 +654,46 @@ static gss_buffer_desc radiusAvpKrbAttr = {
  */
 static OM_uint32
 defrostAttrContext(OM_uint32 *minor,
+                   gss_ctx_id_t glueContext,
                    gss_name_t glueName,
                    gss_name_t mechName)
 {
     OM_uint32 major, tmpMinor;
+#ifdef HAVE_HEIMDAL_VERSION
+    gss_OID_desc oid = { 0 };
+    gss_buffer_set_t authData = GSS_C_NO_BUFFER_SET;
+#else
     gss_buffer_desc authData = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc authDataDisplay = GSS_C_EMPTY_BUFFER;
     int more = -1;
     int authenticated, complete;
+#endif
+
+#ifdef HAVE_HEIMDAL_VERSION
+    major = composeOid(minor,
+                       GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements,
+                       GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length,
+                       KRB5_AUTHDATA_RADIUS_AVP, &oid);
+    if (GSS_ERROR(major))
+        return major;
+
+    /* XXX we are assuming that this verifies AD-KDCIssued signature */
+    major = gssInquireSecContextByOid(minor, glueContext,
+                                      &oid, &authData);
+    if (major == GSS_S_COMPLETE) {
+        if (authData == GSS_C_NO_BUFFER_SET || authData->count != 1)
+            major = GSS_S_FAILURE;
+        else
+            major = gssEapImportAttrContext(minor, authData->elements, mechName);
+    } else if (major == GSS_S_FAILURE && *minor == ENOENT) {
+        /* This is the equivalent of GSS_S_UNAVAILABLE for MIT attr APIs */
+        *minor = 0;
+        major = GSS_S_COMPLETE;
+    }
 
+    gss_release_buffer_set(&tmpMinor, &authData);
+    GSSEAP_FREE(oid.elements);
+#else
     major = gssGetNameAttribute(minor, glueName, &radiusAvpKrbAttr,
                                 &authenticated, &complete,
                                 &authData, &authDataDisplay, &more);
@@ -688,6 +708,7 @@ defrostAttrContext(OM_uint32 *minor,
 
     gss_release_buffer(&tmpMinor, &authData);
     gss_release_buffer(&tmpMinor, &authDataDisplay);
+#endif /* HAVE_HEIMDAL_VERSION */
 
     return major;
 }
@@ -698,6 +719,7 @@ defrostAttrContext(OM_uint32 *minor,
  */
 OM_uint32
 gssEapGlueToMechName(OM_uint32 *minor,
+                     gss_ctx_id_t glueContext,
                      gss_name_t glueName,
                      gss_name_t *pMechName)
 {
@@ -715,7 +737,7 @@ gssEapGlueToMechName(OM_uint32 *minor,
     if (GSS_ERROR(major))
         goto cleanup;
 
-    major = defrostAttrContext(minor, glueName, *pMechName);
+    major = defrostAttrContext(minor, glueContext, glueName, *pMechName);
     if (GSS_ERROR(major))
         goto cleanup;
 
@@ -984,7 +1006,9 @@ gssEapReauthInitialize(OM_uint32 *minor)
     NEXT_SYMBOL(gssDisplayNameNext,            "gss_display_name");
     NEXT_SYMBOL(gssImportNameNext,             "gss_import_name");
     NEXT_SYMBOL(gssStoreCredNext,              "gss_store_cred");
+#ifndef HAVE_HEIMDAL_VERSION
     NEXT_SYMBOL(gssGetNameAttributeNext,       "gss_get_name_attribute");
+#endif
 
     return major;
 }