s3-libads: Pass down the salt principal in smb_krb5_kt_add_entry()
authorAndreas Schneider <asn@samba.org>
Mon, 29 Feb 2016 15:21:56 +0000 (16:21 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 10 Mar 2016 05:52:25 +0000 (06:52 +0100)
This is a preparation to move smb_krb5_kt_add_entry() to krb5_wrap.

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
lib/krb5_wrap/krb5_samba.h
source3/libads/kerberos.c
source3/libads/kerberos_keytab.c
source3/libads/kerberos_proto.h
source3/libnet/libnet_keytab.c
source3/librpc/crypto/gse_krb5.c

index cef9144a17e8bd3049932ba0bd3efdc45b0f9f07..5dcce04a3042cbe37852b2162e5130c1101f2095 100644 (file)
@@ -144,12 +144,6 @@ void krb5_free_unparsed_name(krb5_context ctx, char *val);
 
 /* Samba wrapper functions for krb5 functionality. */
 bool setup_kaddr( krb5_address *pkaddr, struct sockaddr_storage *paddr);
-int create_kerberos_key_from_string(krb5_context context,
-                                   krb5_principal host_princ,
-                                   krb5_data *password,
-                                   krb5_keyblock *key,
-                                   krb5_enctype enctype,
-                                   bool no_salt);
 
 krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);
 bool get_krb5_smb_session_key(TALLOC_CTX *mem_ctx,
index 4774a9fc726e009fe4c40928143a7977df63ddf1..53407fa1b5488599bd2ac4c46b4eb2eb6dc50e24 100644 (file)
@@ -467,47 +467,36 @@ char* kerberos_secrets_fetch_des_salt( void )
  to look for the older tdb keys.  Caller must free if return is not null.
  ************************************************************************/
 
-static
-krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
-                                                       krb5_principal host_princ,
-                                                       int enctype)
+char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
+                                              const char *host_princ_s,
+                                              int enctype)
 {
-       char *unparsed_name = NULL, *salt_princ_s = NULL;
-       krb5_principal ret_princ = NULL;
-
+       char *salt_princ_s;
        /* lookup new key first */
 
-       if ( (salt_princ_s = kerberos_secrets_fetch_des_salt()) == NULL ) {
+       salt_princ_s = kerberos_secrets_fetch_des_salt();
+       if (salt_princ_s == NULL) {
 
                /* look under the old key.  If this fails, just use the standard key */
-
-               if (smb_krb5_unparse_name(talloc_tos(), context, host_princ, &unparsed_name) != 0) {
-                       return (krb5_principal)NULL;
-               }
-               if ((salt_princ_s = kerberos_secrets_fetch_salting_principal(unparsed_name, enctype)) == NULL) {
+               salt_princ_s = kerberos_secrets_fetch_salting_principal(host_princ_s,
+                                                                       enctype);
+               if (salt_princ_s == NULL) {
                        /* fall back to host/machine.realm@REALM */
                        salt_princ_s = kerberos_standard_des_salt();
                }
        }
 
-       if (smb_krb5_parse_name(context, salt_princ_s, &ret_princ) != 0) {
-               ret_princ = NULL;
-       }
-
-       TALLOC_FREE(unparsed_name);
-       SAFE_FREE(salt_princ_s);
-
-       return ret_princ;
+       return salt_princ_s;
 }
 
 int create_kerberos_key_from_string(krb5_context context,
                                        krb5_principal host_princ,
+                                       krb5_principal salt_princ,
                                        krb5_data *password,
                                        krb5_keyblock *key,
                                        krb5_enctype enctype,
                                        bool no_salt)
 {
-       krb5_principal salt_princ = NULL;
        int ret;
        /*
         * Check if we've determined that the KDC is salting keys for this
@@ -524,16 +513,12 @@ int create_kerberos_key_from_string(krb5_context context,
                KRB5_KEY_TYPE(key) = enctype;
                return 0;
        }
-       salt_princ = kerberos_fetch_salt_princ_for_host_princ(context, host_princ, enctype);
        ret = smb_krb5_create_key_from_string(context,
                                              salt_princ ? salt_princ : host_princ,
                                              NULL,
                                              password,
                                              enctype,
                                              key);
-       if (salt_princ) {
-               krb5_free_principal(context, salt_princ);
-       }
        return ret;
 }
 
index 309e614b4f022b7af2aa2834a36796fdb959855b..d3d69fcf298e472d2a3046ce9cad2d0eb39279f1 100644 (file)
@@ -187,7 +187,8 @@ static int smb_krb5_kt_add_entry(krb5_context context,
                                 krb5_keytab keytab,
                                 krb5_kvno kvno,
                                 const char *princ_s,
-                                krb5_enctype *enctypes,
+                                const char *salt_principal,
+                                krb5_enctype enctype,
                                 krb5_data password,
                                 bool no_salt,
                                 bool keep_old_entries)
@@ -195,7 +196,9 @@ static int smb_krb5_kt_add_entry(krb5_context context,
        krb5_error_code ret;
        krb5_keytab_entry kt_entry;
        krb5_principal princ = NULL;
-       int i;
+       krb5_keyblock *keyp;
+       krb5_principal salt_princ = NULL;
+       int rc;
 
        ZERO_STRUCT(kt_entry);
 
@@ -218,31 +221,40 @@ static int smb_krb5_kt_add_entry(krb5_context context,
         * not equal to the current kvno-1. */
 
        /* Now add keytab entries for all encryption types */
-       for (i = 0; enctypes[i]; i++) {
-               krb5_keyblock *keyp;
+       ret = smb_krb5_parse_name(context, salt_principal, &salt_princ);
+       if (ret) {
+               DBG_WARNING("krb5_parse_name(%s) failed (%s)\n",
+                           salt_principal, error_message(ret));
+               goto out;
+       }
 
-               keyp = KRB5_KT_KEY(&kt_entry);
+       keyp = KRB5_KT_KEY(&kt_entry);
 
-               if (create_kerberos_key_from_string(context, princ,
-                                                   &password, keyp,
-                                                   enctypes[i], no_salt)) {
-                       continue;
-               }
+       rc = create_kerberos_key_from_string(context,
+                                            princ,
+                                            salt_princ,
+                                            &password,
+                                            keyp,
+                                            enctype,
+                                            no_salt);
+       krb5_free_principal(context, salt_princ);
+       if (rc != 0) {
+               goto out;
+       }
 
-               kt_entry.principal = princ;
-               kt_entry.vno       = kvno;
+       kt_entry.principal = princ;
+       kt_entry.vno       = kvno;
 
-               DEBUG(3, (__location__ ": adding keytab entry for (%s) with "
-                         "encryption type (%d) and version (%d)\n",
-                         princ_s, enctypes[i], kt_entry.vno));
-               ret = krb5_kt_add_entry(context, keytab, &kt_entry);
-               krb5_free_keyblock_contents(context, keyp);
-               ZERO_STRUCT(kt_entry);
-               if (ret) {
-                       DEBUG(1, (__location__ ": adding entry to keytab "
-                                 "failed (%s)\n", error_message(ret)));
-                       goto out;
-               }
+       DEBUG(3, (__location__ ": adding keytab entry for (%s) with "
+                 "encryption type (%d) and version (%d)\n",
+                 princ_s, enctype, kt_entry.vno));
+       ret = krb5_kt_add_entry(context, keytab, &kt_entry);
+       krb5_free_keyblock_contents(context, keyp);
+       ZERO_STRUCT(kt_entry);
+       if (ret) {
+               DEBUG(1, (__location__ ": adding entry to keytab "
+                         "failed (%s)\n", error_message(ret)));
+               goto out;
        }
 
 out:
@@ -280,11 +292,13 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc)
        };
        char *princ_s = NULL;
        char *short_princ_s = NULL;
+       char *salt_princ_s = NULL;
        char *password_s = NULL;
        char *my_fqdn;
        TALLOC_CTX *tmpctx = NULL;
        char *machine_name;
        ADS_STATUS aderr;
+       int i;
 
        initialize_krb5_error_table();
        ret = krb5_init_context(&context);
@@ -407,25 +421,46 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc)
                goto out;
        }
 
-       /* add the fqdn principal to the keytab */
-       ret = smb_krb5_kt_add_entry(context, keytab, kvno,
-                                   princ_s, enctypes, password,
-                                   false, false);
-       if (ret) {
-               DEBUG(1, (__location__ ": Failed to add entry to keytab\n"));
-               goto out;
-       }
-
-       /* add the short principal name if we have one */
-       if (short_princ_s) {
-               ret = smb_krb5_kt_add_entry(context, keytab, kvno,
-                                           short_princ_s, enctypes, password,
-                                           false, false);
+       for (i = 0; enctypes[i]; i++) {
+               salt_princ_s = kerberos_fetch_salt_princ_for_host_princ(context,
+                                                                       princ_s,
+                                                                       enctypes[i]);
+
+               /* add the fqdn principal to the keytab */
+               ret = smb_krb5_kt_add_entry(context,
+                                           keytab,
+                                           kvno,
+                                           princ_s,
+                                           salt_princ_s,
+                                           enctypes[i],
+                                           password,
+                                           false,
+                                           false);
                if (ret) {
-                       DEBUG(1, (__location__
-                                 ": Failed to add short entry to keytab\n"));
+                       DEBUG(1, (__location__ ": Failed to add entry to keytab\n"));
+                       SAFE_FREE(salt_princ_s);
                        goto out;
                }
+
+               /* add the short principal name if we have one */
+               if (short_princ_s) {
+                       ret = smb_krb5_kt_add_entry(context,
+                                                   keytab,
+                                                   kvno,
+                                                   short_princ_s,
+                                                   salt_princ_s,
+                                                   enctypes[i],
+                                                   password,
+                                                   false,
+                                                   false);
+                       if (ret) {
+                               DEBUG(1, (__location__
+                                         ": Failed to add short entry to keytab\n"));
+                               SAFE_FREE(salt_princ_s);
+                               goto out;
+                       }
+               }
+               SAFE_FREE(salt_princ_s);
        }
 
 out:
index 8a6e00de7967708c60a9ba7e809e09adc27a54ee..7c566729a11c374f3e066f431a11e492668a1a2a 100644 (file)
@@ -58,6 +58,9 @@ int kerberos_kinit_password_ext(const char *principal,
 int ads_kdestroy(const char *cc_name);
 char* kerberos_standard_des_salt( void );
 bool kerberos_secrets_store_des_salt( const char* salt );
+char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
+                                              const char *host_princ_s,
+                                              int enctype);
 
 bool kerberos_secrets_store_salting_principal(const char *service,
                                              int enctype,
@@ -99,6 +102,7 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
 #ifdef HAVE_KRB5
 int create_kerberos_key_from_string(krb5_context context,
                                        krb5_principal host_princ,
+                                       krb5_principal salt_princ,
                                        krb5_data *password,
                                        krb5_keyblock *key,
                                        krb5_enctype enctype,
index 6349c2291f7371d232a76e3efc5620930e73879c..9df1cb8093ec51168a550d544a4c6fd66f35b56c 100644 (file)
@@ -214,6 +214,8 @@ static krb5_error_code libnet_keytab_add_entry(krb5_context context,
        krb5_keyblock *keyp;
        krb5_keytab_entry kt_entry;
        krb5_error_code ret;
+       krb5_principal salt_princ = NULL;
+       char *salt_princ_s;
 
        /* remove duplicates first ... */
        ret = libnet_keytab_remove_entries(context, keytab, princ_s, kvno,
@@ -236,9 +238,30 @@ static krb5_error_code libnet_keytab_add_entry(krb5_context context,
 
        keyp = KRB5_KT_KEY(&kt_entry);
 
-       if (create_kerberos_key_from_string(context, kt_entry.principal,
-                                           &password, keyp, enctype, true))
-       {
+       salt_princ_s = kerberos_fetch_salt_princ_for_host_princ(context,
+                                                               princ_s,
+                                                               enctype);
+       if (salt_princ_s == NULL) {
+               ret = KRB5KRB_ERR_GENERIC;
+               goto done;
+       }
+
+       ret = krb5_parse_name(context, salt_princ_s, &salt_princ);
+       SAFE_FREE(salt_princ_s);
+       if (ret != 0) {
+               ret = KRB5KRB_ERR_GENERIC;
+               goto done;
+       }
+
+       ret = create_kerberos_key_from_string(context,
+                                             kt_entry.principal,
+                                             salt_princ,
+                                             &password,
+                                             keyp,
+                                             enctype,
+                                             true);
+       krb5_free_principal(context, salt_princ);
+       if (ret != 0) {
                ret = KRB5KRB_ERR_GENERIC;
                goto done;
        }
index 3597329a613f126abc0241b6cee8eaff5296120a..b213e83f3b8ddbc8f6218c26876f0a246f23a998 100644 (file)
@@ -22,6 +22,7 @@
 #include "secrets.h"
 #include "gse_krb5.h"
 #include "lib/param/loadparm.h"
+#include "libads/kerberos_proto.h"
 
 #ifdef HAVE_KRB5
 
@@ -131,15 +132,44 @@ static krb5_error_code fill_keytab_from_password(krb5_context krbctx,
 
        for (i = 0; enctypes[i]; i++) {
                krb5_keyblock *key = NULL;
+               krb5_principal salt_princ = NULL;
+               char *salt_princ_s;
+               char *princ_s;
+               int rc;
 
                if (!(key = SMB_MALLOC_P(krb5_keyblock))) {
                        ret = ENOMEM;
                        goto out;
                }
 
-               if (create_kerberos_key_from_string(krbctx, princ,
-                                                   password, key,
-                                                   enctypes[i], false)) {
+               ret = krb5_unparse_name(krbctx, princ, &princ_s);
+               if (ret != 0) {
+                       continue;
+               }
+
+               salt_princ_s = kerberos_fetch_salt_princ_for_host_princ(krbctx,
+                                                                       princ_s,
+                                                                       enctypes[i]);
+               SAFE_FREE(princ_s);
+               if (salt_princ_s == NULL) {
+                       continue;
+               }
+
+               ret = krb5_parse_name(krbctx, salt_princ_s, &salt_princ);
+               SAFE_FREE(salt_princ_s);
+               if (ret != 0) {
+                       continue;
+               }
+
+               rc = create_kerberos_key_from_string(krbctx,
+                                                    princ,
+                                                    salt_princ,
+                                                    password,
+                                                    key,
+                                                    enctypes[i],
+                                                    false);
+               krb5_free_principal(krbctx, salt_princ);
+               if (rc != 0) {
                        DEBUG(10, ("Failed to create key for enctype %d "
                                   "(error: %s)\n",
                                   enctypes[i], error_message(ret)));