s3-libnet_join: add support for libnet_DomainOfflineJoin
authorGünther Deschner <gd@samba.org>
Mon, 15 Feb 2021 19:57:56 +0000 (20:57 +0100)
committerGünther Deschner <gd@samba.org>
Wed, 14 Jul 2021 16:49:30 +0000 (16:49 +0000)
libnet_DomainOfflineJoin will consume the provided offline domain join
blob and lay out libnet_Join information to properly store join metadata
in the local database.

Guenther

Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
source3/libnet/libnet_join.c

index 553ab05b32c3c32c88f8ecd00155dcc48781c6c8..ce837e730e22b627a268901fdbebfd2b17f32a35 100644 (file)
@@ -45,6 +45,8 @@
 #include "auth/credentials/credentials.h"
 #include "krb5_env.h"
 #include "libsmb/dsgetdcname.h"
+#include "rpc_client/util_netlogon.h"
+#include "libnet/libnet_join_offline.h"
 
 /****************************************************************
 ****************************************************************/
@@ -936,6 +938,14 @@ static ADS_STATUS libnet_join_post_processing_ads_modify(TALLOC_CTX *mem_ctx,
        ADS_STATUS status;
        bool need_etype_update = false;
 
+       if (r->in.request_offline_join) {
+               /*
+                * When in the "request offline join" path we can no longer
+                * modify the AD account as we are operating w/o network - gd
+                */
+               return ADS_SUCCESS;
+       }
+
        if (!r->in.ads) {
                status = libnet_join_connect_ads_user(mem_ctx, r);
                if (!ADS_ERR_OK(status)) {
@@ -2271,6 +2281,14 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx,
                return WERR_INVALID_PARAMETER;
        }
 
+       if (r->in.request_offline_join) {
+               /*
+                * When in the "request offline join" path we do not have admin
+                * credentials available so we can skip the next steps - gd
+                */
+               return WERR_OK;
+       }
+
        if (!r->in.admin_domain) {
                char *admin_domain = NULL;
                char *admin_account = NULL;
@@ -2806,6 +2824,74 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
 /****************************************************************
 ****************************************************************/
 
+static WERROR libnet_DomainOfflineJoin(TALLOC_CTX *mem_ctx,
+                                      struct libnet_JoinCtx *r)
+{
+       NTSTATUS status;
+       WERROR werr;
+       struct ODJ_WIN7BLOB win7blob;
+       const char *dc_name;
+
+       if (!r->in.request_offline_join) {
+               return WERR_NERR_DEFAULTJOINREQUIRED;
+       }
+
+       if (r->in.odj_provision_data == NULL) {
+               return WERR_INVALID_PARAMETER;
+       }
+
+       werr = libnet_odj_find_win7blob(r->in.odj_provision_data, &win7blob);
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
+       }
+
+       r->out.netbios_domain_name = talloc_strdup(mem_ctx,
+                       win7blob.DnsDomainInfo.Name.string);
+       W_ERROR_HAVE_NO_MEMORY(r->out.netbios_domain_name);
+
+       r->out.dns_domain_name = talloc_strdup(mem_ctx,
+                       win7blob.DnsDomainInfo.DnsDomainName.string);
+       W_ERROR_HAVE_NO_MEMORY(r->out.dns_domain_name);
+
+       r->out.forest_name = talloc_strdup(mem_ctx,
+                       win7blob.DnsDomainInfo.DnsForestName.string);
+       W_ERROR_HAVE_NO_MEMORY(r->out.forest_name);
+
+       r->out.domain_guid = win7blob.DnsDomainInfo.DomainGuid;
+       r->out.domain_sid = dom_sid_dup(mem_ctx,
+                       win7blob.DnsDomainInfo.Sid);
+       W_ERROR_HAVE_NO_MEMORY(r->out.domain_sid);
+
+       dc_name = strip_hostname(win7blob.DcInfo.dc_address);
+       if (dc_name == NULL) {
+               return WERR_DOMAIN_CONTROLLER_NOT_FOUND;
+       }
+       r->in.dc_name = talloc_strdup(mem_ctx, dc_name);
+       W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
+
+       r->out.domain_is_ad = true;
+
+       /* we cannot use talloc_steal but have to deep copy the struct here */
+       status = copy_netr_DsRGetDCNameInfo(mem_ctx, &win7blob.DcInfo,
+                                           &r->out.dcinfo);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ntstatus_to_werror(status);
+       }
+
+       return WERR_OK;
+#if 0
+       /* the following fields are currently not filled in */
+
+       const char * dn;
+       uint32_t set_encryption_types;
+       const char * krb5_salt;
+       uint32_t account_rid;
+#endif
+}
+
+/****************************************************************
+****************************************************************/
+
 static WERROR libnet_join_rollback(TALLOC_CTX *mem_ctx,
                                   struct libnet_JoinCtx *r)
 {
@@ -2853,7 +2939,11 @@ WERROR libnet_Join(TALLOC_CTX *mem_ctx,
        }
 
        if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
-               werr = libnet_DomainJoin(mem_ctx, r);
+               if (r->in.request_offline_join) {
+                       werr = libnet_DomainOfflineJoin(mem_ctx, r);
+               } else {
+                       werr = libnet_DomainJoin(mem_ctx, r);
+               }
                if (!W_ERROR_IS_OK(werr)) {
                        goto done;
                }
@@ -2872,6 +2962,14 @@ WERROR libnet_Join(TALLOC_CTX *mem_ctx,
        }
 
        if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
+               if (r->in.request_offline_join) {
+                       /*
+                        * When we are serving an offline domain join request we
+                        * have no network so we are done here - gd.
+                        */
+                       goto done;
+               }
+
                werr = libnet_join_post_verify(mem_ctx, r);
                if (!W_ERROR_IS_OK(werr)) {
                        libnet_join_rollback(mem_ctx, r);