Description: Add support for ad_upn_realm
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 krb5-sync (3.2-1su1) stable-kdc; urgency=medium
 .
   * Update NEWS and README as well as bump the version number.
Author: Adam Henry Lewenberg <adamhl@stanford.edu>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: 2019-01-15

--- krb5-sync-3.2.orig/NEWS
+++ krb5-sync-3.2/NEWS
@@ -1,5 +1,11 @@
                       User-Visible krb5-sync Changes
 
+krb5-sync 3.2 (2017-09-07)
+
+    Add new configuration parameter ad_upn_realm to allow searching for
+    users using different domain suffiex than ad_realm. See README for
+    more details. (adamhl@stanford.edu)
+
 krb5-sync 3.1 (2015-08-18)
 
     In krb5-sync-backend silent mode, fix the ignore regex for missing
--- krb5-sync-3.2.orig/README
+++ krb5-sync-3.2/README
@@ -319,6 +319,26 @@ CONFIGURATION
       deactivate this plugin while still loading it by removing that part
       of the configuration.
 
+  ad_upn_realm
+
+      Specifies the realm to append to the username when doing a search
+      for the user using the userPrincipalName attribute in the Active
+      Directory. Normally, this is equal to ad_realm which is what
+      ad_upn_realm defaults to if not specified explicitly. But there are
+      situations where the domain appended to the user's name in the
+      userPrincipalName attribute does NOT equal ad_realm, so you specify
+      that here in those cases.
+
+      Example 1: if ad_realm is set to "WIN.EXAMPLE.COM" and ad_upn_realm
+      is not specified in krb5.conf, then ad_upn_realm will be set to
+      "WIN.EXAMPLE.COM" and krb5-sync will search for the user with
+      attribute userPrincipalName equal to "<user>@WIN.EXAMPLE.COM".
+
+      Example 2: if ad_realm is set to "WIN.EXAMPLE.COM" and ad_upn_realm
+      is set to "EXAMPLE.COM", then ad_upn_realm will be set to
+      "EXAMPLE.COM" and krb5-sync will search for the user with attribute
+      userPrincipalName equal to "<user>@EXAMPLE.COM".
+
   queue_dir
 
       Specifies where to queue changes that couldn't be made.  If password
--- krb5-sync-3.2.orig/plugin/ad.c
+++ krb5-sync-3.2/plugin/ad.c
@@ -133,7 +133,7 @@ fail:
  */
 static krb5_error_code
 get_ad_principal(kadm5_hook_modinfo *config, krb5_context ctx,
-                 krb5_const_principal principal, krb5_principal *ad_principal)
+                 krb5_const_principal principal, krb5_principal *ad_principal, bool use_ad_upn_realm)
 {
     krb5_error_code code;
     int ncomp;
@@ -155,9 +155,15 @@ get_ad_principal(kadm5_hook_modinfo *con
         instance = krb5_principal_get_comp_string(ctx, principal, 1);
         if (strcmp(instance, config->ad_base_instance) == 0) {
             base = krb5_principal_get_comp_string(ctx, principal, 0);
-            code = krb5_build_principal(ctx, ad_principal,
-                                        strlen(config->ad_realm),
-                                        config->ad_realm, base, (char *) 0);
+	    if (use_ad_upn_realm) {
+                code = krb5_build_principal(ctx, ad_principal,
+                                            strlen(config->ad_upn_realm),
+                                            config->ad_upn_realm, base, (char *) 0);
+	    } else {
+                code = krb5_build_principal(ctx, ad_principal,
+                                            strlen(config->ad_realm),
+                                            config->ad_realm, base, (char *) 0);
+	    }
             if (code != 0)
                 return code;
         }
@@ -168,7 +174,11 @@ get_ad_principal(kadm5_hook_modinfo *con
         code = krb5_copy_principal(ctx, principal, ad_principal);
         if (code != 0)
             return code;
-        krb5_principal_set_realm(ctx, *ad_principal, config->ad_realm);
+        if (use_ad_upn_realm) {
+            krb5_principal_set_realm(ctx, *ad_principal, config->ad_upn_realm);
+	} else {
+            krb5_principal_set_realm(ctx, *ad_principal, config->ad_realm);
+	}
     }
     return 0;
 }
@@ -199,8 +209,8 @@ sync_ad_chpass(kadm5_hook_modinfo *confi
     if (code != 0)
         return code;
 
-    /* Get the corresponding AD principal. */
-    code = get_ad_principal(config, ctx, principal, &ad_principal);
+    /* Get the corresponding AD principal. We set the use_ad_upn_realm to false for changing password.  */
+    code = get_ad_principal(config, ctx, principal, &ad_principal, false);
     if (code != 0)
         goto done;
 
@@ -326,8 +336,11 @@ sync_ad_status(kadm5_hook_modinfo *confi
      * Since all we know is the local principal, we have to convert that to
      * the AD principal and then query Active Directory via LDAP to get back
      * the CN for the user to construct the full DN.
+     *
+     * When doing a sync status we need to use the ad_upn_realm, so we set
+     * the use_ad_upn_realm parameter to "true".
      */
-    code = get_ad_principal(config, ctx, principal, &ad_principal);
+    code = get_ad_principal(config, ctx, principal, &ad_principal, true);
     if (code != 0)
         goto done;
     code = krb5_unparse_name(ctx, ad_principal, &target);
--- krb5-sync-3.2.orig/plugin/general.c
+++ krb5-sync-3.2/plugin/general.c
@@ -50,6 +50,7 @@ sync_init(krb5_context ctx, kadm5_hook_m
     sync_config_string(ctx, "ad_keytab", &config->ad_keytab);
     sync_config_string(ctx, "ad_principal", &config->ad_principal);
     sync_config_string(ctx, "ad_realm", &config->ad_realm);
+    sync_config_string(ctx, "ad_upn_realm", &config->ad_upn_realm);
     sync_config_string(ctx, "ad_admin_server", &config->ad_admin_server);
     sync_config_string(ctx, "ad_ldap_base", &config->ad_ldap_base);
 
@@ -73,6 +74,14 @@ sync_init(krb5_context ctx, kadm5_hook_m
     config->syslog = true;
     sync_config_boolean(ctx, "syslog", &config->syslog);
 
+    /*
+      If ad_upn_realm was not defined in the configuration file,
+      set it equal to ad_realm (which MUST always be defined).
+    */
+    if (!config->ad_upn_realm) {
+      sync_config_string(ctx, "ad_realm", &config->ad_upn_realm);
+    }
+
     /* Initialized.  Set data and return. */
     *result = config;
     return 0;
--- krb5-sync-3.2.orig/plugin/internal.h
+++ krb5-sync-3.2/plugin/internal.h
@@ -49,6 +49,7 @@ struct kadm5_hook_modinfo_st {
     char *ad_principal;
     bool ad_queue_only;
     char *ad_realm;
+    char *ad_upn_realm;
     char *queue_dir;
     bool syslog;
 };
