]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
krb5_wrap: add smb_krb5_salt_principal()
authorStefan Metzmacher <metze@samba.org>
Wed, 17 May 2017 15:13:02 +0000 (17:13 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 13 Jul 2017 08:51:17 +0000 (10:51 +0200)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 5df46700cfb0a15fec2d366e12728cd497188741)

lib/krb5_wrap/krb5_samba.c
lib/krb5_wrap/krb5_samba.h

index 76e879591989a1e864e43df83b4a48cf66d3fb06..38547ec7be89b68c326cc8196241b332a8ac50b6 100644 (file)
@@ -324,6 +324,126 @@ int smb_krb5_get_pw_salt(krb5_context context,
 #error UNKNOWN_SALT_FUNCTIONS
 #endif
 
+/**
+ * @brief This constructs the salt principal used by active directory
+ *
+ * Most Kerberos encryption types require a salt in order to
+ * calculate the long term private key for user/computer object
+ * based on a password.
+ *
+ * The returned _salt_principal is a string in forms like this:
+ * - host/somehost.example.com@EXAMPLE.COM
+ * - SomeAccount@EXAMPLE.COM
+ * - SomePrincipal@EXAMPLE.COM
+ *
+ * This is not the form that's used as salt, it's just
+ * the human readable form.
+ *
+ * @param[in]  realm              The realm the user/computer is added too.
+ *
+ * @param[in]  sAMAccountName     The sAMAccountName attribute of the object.
+ *
+ * @param[in]  userPrincipalName  The userPrincipalName attribute of the object
+ *                                or NULL is not available.
+ *
+ * @param[in]  is_computer        The indication of the object includes
+ *                                objectClass=computer.
+ *
+ * @param[in]  mem_ctx            The TALLOC_CTX to allocate _salt_principal.
+ *
+ * @param[out]  _salt_principal   The resulting principal as string.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+int smb_krb5_salt_principal(const char *realm,
+                           const char *sAMAccountName,
+                           const char *userPrincipalName,
+                           bool is_computer,
+                           TALLOC_CTX *mem_ctx,
+                           char **_salt_principal)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       char *upper_realm = NULL;
+       const char *principal = NULL;
+       int principal_len = 0;
+
+       *_salt_principal = NULL;
+
+       if (sAMAccountName == NULL) {
+               TALLOC_FREE(frame);
+               return EINVAL;
+       }
+
+       if (realm == NULL) {
+               TALLOC_FREE(frame);
+               return EINVAL;
+       }
+
+       upper_realm = strupper_talloc(frame, realm);
+       if (upper_realm == NULL) {
+               TALLOC_FREE(frame);
+               return ENOMEM;
+       }
+
+       /* Many, many thanks to lukeh@padl.com for this
+        * algorithm, described in his Nov 10 2004 mail to
+        * samba-technical@lists.samba.org */
+
+       /*
+        * Determine a salting principal
+        */
+       if (is_computer) {
+               int computer_len = 0;
+               char *tmp = NULL;
+
+               computer_len = strlen(sAMAccountName);
+               if (sAMAccountName[computer_len-1] == '$') {
+                       computer_len -= 1;
+               }
+
+               tmp = talloc_asprintf(frame, "host/%*.*s.%s",
+                                     computer_len, computer_len,
+                                     sAMAccountName, realm);
+               if (tmp == NULL) {
+                       TALLOC_FREE(frame);
+                       return ENOMEM;
+               }
+
+               principal = strlower_talloc(frame, tmp);
+               TALLOC_FREE(tmp);
+               if (principal == NULL) {
+                       TALLOC_FREE(frame);
+                       return ENOMEM;
+               }
+               principal_len = strlen(principal);
+
+       } else if (userPrincipalName != NULL) {
+               char *p;
+
+               principal = userPrincipalName;
+               p = strchr(principal, '@');
+               if (p != NULL) {
+                       principal_len = PTR_DIFF(p, principal);
+               } else {
+                       principal_len = strlen(principal);
+               }
+       } else {
+               principal = sAMAccountName;
+               principal_len = strlen(principal);
+       }
+
+       *_salt_principal = talloc_asprintf(mem_ctx, "%*.*s@%s",
+                                          principal_len, principal_len,
+                                          principal, upper_realm);
+       if (*_salt_principal == NULL) {
+               TALLOC_FREE(frame);
+               return ENOMEM;
+       }
+
+       TALLOC_FREE(frame);
+       return 0;
+}
+
 #if defined(HAVE_KRB5_GET_PERMITTED_ENCTYPES)
  krb5_error_code get_kerberos_allowed_etypes(krb5_context context,
                                            krb5_enctype **enctypes)
index 2d0f51d4f0837f2ce5a7df7174e9f493b36f5deb..31974e07cb16dfa8ec40cd0707558862f32017e6 100644 (file)
@@ -362,6 +362,12 @@ krb5_error_code ms_suptypes_to_ietf_enctypes(TALLOC_CTX *mem_ctx,
 int smb_krb5_get_pw_salt(krb5_context context,
                         krb5_const_principal host_princ,
                         krb5_data *psalt);
+int smb_krb5_salt_principal(const char *realm,
+                           const char *sAMAccountName,
+                           const char *userPrincipalName,
+                           bool is_computer,
+                           TALLOC_CTX *mem_ctx,
+                           char **_salt_principal);
 
 int smb_krb5_create_key_from_string(krb5_context context,
                                    krb5_const_principal host_princ,