libcli/auth: Move more kerberos wrapping in common
authorAndrew Bartlett <abartlet@samba.org>
Wed, 20 Apr 2011 02:03:48 +0000 (12:03 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 20 Apr 2011 02:31:07 +0000 (04:31 +0200)
These functions are required to get the krb5 PAC parsing and
verfication in common.

Andrew Bartlett

libcli/auth/krb5_wrap.c
libcli/auth/krb5_wrap.h
source3/libsmb/clikrb5.c

index 0a466fdd4ea31a323805e66eaa5fdb60547953ed..c69e3946c67d775809c04c29bb36c9a534bf085a 100644 (file)
@@ -3,7 +3,7 @@
    simple kerberos5 routines for active directory
    Copyright (C) Andrew Tridgell 2001
    Copyright (C) Luke Howard 2002-2003
-   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2011
    Copyright (C) Guenther Deschner 2005-2009
 
    This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
 #ifdef HAVE_KRB5
 
 #include "libcli/auth/krb5_wrap.h"
+#include "librpc/gen_ndr/krb5pac.h"
 
 #if defined(HAVE_KRB5_PRINCIPAL2SALT) && defined(HAVE_KRB5_USE_ENCTYPE) && defined(HAVE_KRB5_STRING_TO_KEY) && defined(HAVE_KRB5_ENCRYPT_BLOCK)
 int create_kerberos_key_from_string_direct(krb5_context context,
@@ -102,6 +103,210 @@ int create_kerberos_key_from_string_direct(krb5_context context,
 #endif
 }
 
+/**************************************************************
+ Wrappers around kerberos string functions that convert from
+ utf8 -> unix charset and vica versa.
+**************************************************************/
+
+/**************************************************************
+ krb5_parse_name that takes a UNIX charset.
+**************************************************************/
+
+ krb5_error_code smb_krb5_parse_name(krb5_context context,
+                               const char *name, /* in unix charset */
+                               krb5_principal *principal)
+{
+       krb5_error_code ret;
+       char *utf8_name;
+       size_t converted_size;
+
+       if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) {
+               return ENOMEM;
+       }
+
+       ret = krb5_parse_name(context, utf8_name, principal);
+       TALLOC_FREE(utf8_name);
+       return ret;
+}
+
+#if !defined(HAVE_KRB5_FREE_UNPARSED_NAME)
+static void krb5_free_unparsed_name(krb5_context context, char *val)
+{
+       SAFE_FREE(val);
+}
+#endif
+
+/**************************************************************
+ krb5_parse_name that returns a UNIX charset name. Must
+ be freed with talloc_free() call.
+**************************************************************/
+
+krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx,
+                                     krb5_context context,
+                                     krb5_const_principal principal,
+                                     char **unix_name)
+{
+       krb5_error_code ret;
+       char *utf8_name;
+       size_t converted_size;
+
+       *unix_name = NULL;
+       ret = krb5_unparse_name(context, principal, &utf8_name);
+       if (ret) {
+               return ret;
+       }
+
+       if (!pull_utf8_talloc(mem_ctx, unix_name, utf8_name, &converted_size)) {
+               krb5_free_unparsed_name(context, utf8_name);
+               return ENOMEM;
+       }
+       krb5_free_unparsed_name(context, utf8_name);
+       return 0;
+}
+
+ krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, 
+                                           const char *name, 
+                                           krb5_principal *principal)
+{
+#ifdef HAVE_KRB5_PARSE_NAME_NOREALM
+       return smb_krb5_parse_name_norealm_conv(context, name, principal);
+#endif
+
+       /* we are cheating here because parse_name will in fact set the realm.
+        * We don't care as the only caller of smb_krb5_parse_name_norealm
+        * ignores the realm anyway when calling
+        * smb_krb5_principal_compare_any_realm later - Guenther */
+
+       return smb_krb5_parse_name(context, name, principal);
+}
+
+ bool smb_krb5_principal_compare_any_realm(krb5_context context, 
+                                         krb5_const_principal princ1, 
+                                         krb5_const_principal princ2)
+{
+#ifdef HAVE_KRB5_PRINCIPAL_COMPARE_ANY_REALM
+
+       return krb5_principal_compare_any_realm(context, princ1, princ2);
+
+/* krb5_princ_size is a macro in MIT */
+#elif defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size)
+
+       int i, len1, len2;
+       const krb5_data *p1, *p2;
+
+       len1 = krb5_princ_size(context, princ1);
+       len2 = krb5_princ_size(context, princ2);
+
+       if (len1 != len2)
+               return False;
+
+       for (i = 0; i < len1; i++) {
+
+               p1 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ1), i);
+               p2 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ2), i);
+
+               if (p1->length != p2->length || memcmp(p1->data, p2->data, p1->length))
+                       return False;
+       }
+
+       return True;
+#else
+#error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION
+#endif
+}
+
+ void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum,
+                                    struct PAC_SIGNATURE_DATA *sig)
+{
+#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM
+       cksum->cksumtype        = (krb5_cksumtype)sig->type;
+       cksum->checksum.length  = sig->signature.length;
+       cksum->checksum.data    = sig->signature.data;
+#else
+       cksum->checksum_type    = (krb5_cksumtype)sig->type;
+       cksum->length           = sig->signature.length;
+       cksum->contents         = sig->signature.data;
+#endif
+}
+
+ krb5_error_code smb_krb5_verify_checksum(krb5_context context,
+                                         const krb5_keyblock *keyblock,
+                                        krb5_keyusage usage,
+                                        krb5_checksum *cksum,
+                                        uint8_t *data,
+                                        size_t length)
+{
+       krb5_error_code ret;
+
+       /* verify the checksum */
+
+       /* welcome to the wonderful world of samba's kerberos abstraction layer:
+        * 
+        * function                     heimdal 0.6.1rc3        heimdal 0.7     MIT krb 1.4.2
+        * -----------------------------------------------------------------------------
+        * krb5_c_verify_checksum       -                       works           works
+        * krb5_verify_checksum         works (6 args)          works (6 args)  broken (7 args) 
+        */
+
+#if defined(HAVE_KRB5_C_VERIFY_CHECKSUM)
+       {
+               krb5_boolean checksum_valid = false;
+               krb5_data input;
+
+               input.data = (char *)data;
+               input.length = length;
+
+               ret = krb5_c_verify_checksum(context, 
+                                            keyblock, 
+                                            usage,
+                                            &input, 
+                                            cksum,
+                                            &checksum_valid);
+               if (ret) {
+                       DEBUG(3,("smb_krb5_verify_checksum: krb5_c_verify_checksum() failed: %s\n", 
+                               error_message(ret)));
+                       return ret;
+               }
+
+               if (!checksum_valid)
+                       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+       }
+
+#elif KRB5_VERIFY_CHECKSUM_ARGS == 6 && defined(HAVE_KRB5_CRYPTO_INIT) && defined(HAVE_KRB5_CRYPTO) && defined(HAVE_KRB5_CRYPTO_DESTROY)
+
+       /* Warning: MIT's krb5_verify_checksum cannot be used as it will use a key
+        * without enctype and it ignores any key_usage types - Guenther */
+
+       {
+
+               krb5_crypto crypto;
+               ret = krb5_crypto_init(context,
+                                      keyblock,
+                                      0,
+                                      &crypto);
+               if (ret) {
+                       DEBUG(0,("smb_krb5_verify_checksum: krb5_crypto_init() failed: %s\n", 
+                               error_message(ret)));
+                       return ret;
+               }
+
+               ret = krb5_verify_checksum(context,
+                                          crypto,
+                                          usage,
+                                          data,
+                                          length,
+                                          cksum);
+
+               krb5_crypto_destroy(context, crypto);
+       }
+
+#else
+#error UNKNOWN_KRB5_VERIFY_CHECKSUM_FUNCTION
+#endif
+
+       return ret;
+}
+
  char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx)
 {
        char *ret;
index e608efe58c97b905cb5fb73de717c9a50b0c669a..3cdcedc97119928968679fa44fb8097e2235bc2c 100644 (file)
@@ -21,6 +21,8 @@
 */
 
 #include "system/kerberos.h"
+struct PAC_SIGNATURE_DATA;
+struct PAC_DATA;
 
 int create_kerberos_key_from_string_direct(krb5_context context,
                                                  krb5_principal host_princ,
@@ -30,3 +32,25 @@ int create_kerberos_key_from_string_direct(krb5_context context,
 void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
 krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
 char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);
+
+ krb5_error_code smb_krb5_parse_name(krb5_context context,
+                               const char *name, /* in unix charset */
+                                    krb5_principal *principal);
+krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx,
+                                     krb5_context context,
+                                     krb5_const_principal principal,
+                                     char **unix_name);
+ krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, 
+                                           const char *name, 
+                                            krb5_principal *principal);
+ bool smb_krb5_principal_compare_any_realm(krb5_context context, 
+                                         krb5_const_principal princ1, 
+                                          krb5_const_principal princ2);
+ void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum,
+                                    struct PAC_SIGNATURE_DATA *sig);
+ krb5_error_code smb_krb5_verify_checksum(krb5_context context,
+                                         const krb5_keyblock *keyblock,
+                                        krb5_keyusage usage,
+                                        krb5_checksum *cksum,
+                                        uint8_t *data,
+                                         size_t length);
index b341ff4be6c1642712635d355dbba2135bb99272..a872d2df61e0d619abc5a86003a26e277b8069ac 100644 (file)
@@ -50,84 +50,6 @@ krb5_error_code krb5_auth_con_set_req_cksumtype(
        krb5_cksumtype     cksumtype);
 #endif
 
-/**************************************************************
- Wrappers around kerberos string functions that convert from
- utf8 -> unix charset and vica versa.
-**************************************************************/
-
-/**************************************************************
- krb5_parse_name that takes a UNIX charset.
-**************************************************************/
-
- krb5_error_code smb_krb5_parse_name(krb5_context context,
-                               const char *name, /* in unix charset */
-                               krb5_principal *principal)
-{
-       krb5_error_code ret;
-       char *utf8_name;
-       size_t converted_size;
-
-       if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) {
-               return ENOMEM;
-       }
-
-       ret = krb5_parse_name(context, utf8_name, principal);
-       TALLOC_FREE(utf8_name);
-       return ret;
-}
-
-#ifdef HAVE_KRB5_PARSE_NAME_NOREALM
-/**************************************************************
- krb5_parse_name_norealm that takes a UNIX charset.
-**************************************************************/
-
-static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
-                               const char *name, /* in unix charset */
-                               krb5_principal *principal)
-{
-       krb5_error_code ret;
-       char *utf8_name;
-       size_t converted_size;
-
-       *principal = NULL;
-       if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) {
-               return ENOMEM;
-       }
-
-       ret = krb5_parse_name_norealm(context, utf8_name, principal);
-       TALLOC_FREE(utf8_name);
-       return ret;
-}
-#endif
-
-/**************************************************************
- krb5_parse_name that returns a UNIX charset name. Must
- be freed with talloc_free() call.
-**************************************************************/
-
-krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx,
-                                     krb5_context context,
-                                     krb5_const_principal principal,
-                                     char **unix_name)
-{
-       krb5_error_code ret;
-       char *utf8_name;
-       size_t converted_size;
-
-       *unix_name = NULL;
-       ret = krb5_unparse_name(context, principal, &utf8_name);
-       if (ret) {
-               return ret;
-       }
-
-       if (!pull_utf8_talloc(mem_ctx, unix_name, utf8_name, &converted_size)) {
-               krb5_free_unparsed_name(context, utf8_name);
-               return ENOMEM;
-       }
-       krb5_free_unparsed_name(context, utf8_name);
-       return 0;
-}
-
 #ifndef HAVE_KRB5_SET_REAL_TIME
 /*
  * This function is not in the Heimdal mainline.
@@ -530,13 +452,6 @@ bool unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_
 
 #endif /* HAVE_KRB5_LOCATE_KDC */
 
-#if !defined(HAVE_KRB5_FREE_UNPARSED_NAME)
- void krb5_free_unparsed_name(krb5_context context, char *val)
-{
-       SAFE_FREE(val);
-}
-#endif
-
  void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype)
 {
 #if defined(HAVE_KRB5_KEYBLOCK_IN_CREDS)
@@ -1010,98 +925,6 @@ done:
 }
 #endif
 
- void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum,
-                                    struct PAC_SIGNATURE_DATA *sig)
-{
-#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM
-       cksum->cksumtype        = (krb5_cksumtype)sig->type;
-       cksum->checksum.length  = sig->signature.length;
-       cksum->checksum.data    = sig->signature.data;
-#else
-       cksum->checksum_type    = (krb5_cksumtype)sig->type;
-       cksum->length           = sig->signature.length;
-       cksum->contents         = sig->signature.data;
-#endif
-}
-
- krb5_error_code smb_krb5_verify_checksum(krb5_context context,
-                                         const krb5_keyblock *keyblock,
-                                        krb5_keyusage usage,
-                                        krb5_checksum *cksum,
-                                        uint8 *data,
-                                        size_t length)
-{
-       krb5_error_code ret;
-
-       /* verify the checksum */
-
-       /* welcome to the wonderful world of samba's kerberos abstraction layer:
-        * 
-        * function                     heimdal 0.6.1rc3        heimdal 0.7     MIT krb 1.4.2
-        * -----------------------------------------------------------------------------
-        * krb5_c_verify_checksum       -                       works           works
-        * krb5_verify_checksum         works (6 args)          works (6 args)  broken (7 args) 
-        */
-
-#if defined(HAVE_KRB5_C_VERIFY_CHECKSUM)
-       {
-               krb5_boolean checksum_valid = False;
-               krb5_data input;
-
-               input.data = (char *)data;
-               input.length = length;
-
-               ret = krb5_c_verify_checksum(context, 
-                                            keyblock, 
-                                            usage,
-                                            &input, 
-                                            cksum,
-                                            &checksum_valid);
-               if (ret) {
-                       DEBUG(3,("smb_krb5_verify_checksum: krb5_c_verify_checksum() failed: %s\n", 
-                               error_message(ret)));
-                       return ret;
-               }
-
-               if (!checksum_valid)
-                       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-       }
-
-#elif KRB5_VERIFY_CHECKSUM_ARGS == 6 && defined(HAVE_KRB5_CRYPTO_INIT) && defined(HAVE_KRB5_CRYPTO) && defined(HAVE_KRB5_CRYPTO_DESTROY)
-
-       /* Warning: MIT's krb5_verify_checksum cannot be used as it will use a key
-        * without enctype and it ignores any key_usage types - Guenther */
-
-       {
-
-               krb5_crypto crypto;
-               ret = krb5_crypto_init(context,
-                                      keyblock,
-                                      0,
-                                      &crypto);
-               if (ret) {
-                       DEBUG(0,("smb_krb5_verify_checksum: krb5_crypto_init() failed: %s\n", 
-                               error_message(ret)));
-                       return ret;
-               }
-
-               ret = krb5_verify_checksum(context,
-                                          crypto,
-                                          usage,
-                                          data,
-                                          length,
-                                          cksum);
-
-               krb5_crypto_destroy(context, crypto);
-       }
-
-#else
-#error UNKNOWN_KRB5_VERIFY_CHECKSUM_FUNCTION
-#endif
-
-       return ret;
-}
-
  time_t get_authtime_from_tkt(krb5_ticket *tkt)
 {
 #if defined(HAVE_KRB5_TKT_ENC_PART2)
@@ -1276,57 +1099,6 @@ out:
        return ret;
 }
 
- krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, 
-                                           const char *name, 
-                                           krb5_principal *principal)
-{
-#ifdef HAVE_KRB5_PARSE_NAME_NOREALM
-       return smb_krb5_parse_name_norealm_conv(context, name, principal);
-#endif
-
-       /* we are cheating here because parse_name will in fact set the realm.
-        * We don't care as the only caller of smb_krb5_parse_name_norealm
-        * ignores the realm anyway when calling
-        * smb_krb5_principal_compare_any_realm later - Guenther */
-
-       return smb_krb5_parse_name(context, name, principal);
-}
-
- bool smb_krb5_principal_compare_any_realm(krb5_context context, 
-                                         krb5_const_principal princ1, 
-                                         krb5_const_principal princ2)
-{
-#ifdef HAVE_KRB5_PRINCIPAL_COMPARE_ANY_REALM
-
-       return krb5_principal_compare_any_realm(context, princ1, princ2);
-
-/* krb5_princ_size is a macro in MIT */
-#elif defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size)
-
-       int i, len1, len2;
-       const krb5_data *p1, *p2;
-
-       len1 = krb5_princ_size(context, princ1);
-       len2 = krb5_princ_size(context, princ2);
-
-       if (len1 != len2)
-               return False;
-
-       for (i = 0; i < len1; i++) {
-
-               p1 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ1), i);
-               p2 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ2), i);
-
-               if (p1->length != p2->length || memcmp(p1->data, p2->data, p1->length))
-                       return False;
-       }
-
-       return True;
-#else
-#error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION
-#endif
-}
-
  krb5_error_code smb_krb5_renew_ticket(const char *ccache_string,      /* FILE:/tmp/krb5cc_0 */
                                       const char *client_string,       /* gd@BER.SUSE.DE */
                                       const char *service_string,      /* krbtgt/BER.SUSE.DE@BER.SUSE.DE */