]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
samba-tool: Create DNS entries on member join
authorDavid Mulder <dmulder@suse.com>
Fri, 5 Nov 2021 20:43:18 +0000 (14:43 -0600)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 6 Dec 2021 22:08:31 +0000 (22:08 +0000)
The net ads join command already handles this,
and the call was missing from the python bindings
for samba-tool domain join member.

Signed-off-by: David Mulder <dmulder@suse.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/netcmd/domain.py
source3/utils/net_ads.c
source3/utils/net_ads_join_dns.c [new file with mode: 0644]
source3/utils/net_proto.h
source3/utils/py_net.c
source3/utils/wscript_build

index eb52557212e0d3ae77bfef92d9a7a9706f999bca..1bdc0ee535a7dc544899f30470b5b2e97019a497 100644 (file)
@@ -636,7 +636,10 @@ class cmd_domain_join(Command):
                     "Don't choose this unless you know what you're doing")
     ]
 
-    takes_options = []
+    takes_options = [
+        Option("--no-dns-updates", action="store_true",
+               help="Disable DNS updates")
+    ]
     takes_options.extend(common_join_options)
     takes_options.extend(common_provision_join_options)
 
@@ -652,7 +655,7 @@ class cmd_domain_join(Command):
             versionopts=None, server=None, site=None, targetdir=None,
             domain_critical_only=False, machinepass=None,
             use_ntvfs=False, experimental_s4_member=False, dns_backend=None,
-            quiet=False, verbose=False,
+            quiet=False, verbose=False, no_dns_updates=False,
             plaintext_secrets=False,
             backend_store=None, backend_store_size=None):
         lp = sambaopts.get_loadparm()
@@ -693,7 +696,8 @@ class cmd_domain_join(Command):
                 s3_net = s3_Net(creds, s3_lp, server=server)
                 (sid, domain_name) = s3_net.join_member(netbios_name,
                                                         machinepass=machinepass,
-                                                        debug=verbose)
+                                                        debug=verbose,
+                                                        noDnsUpdates=no_dns_updates)
 
             self.errf.write("Joined domain %s (%s)\n" % (domain_name, sid))
         elif role == "DC" and is_ad_dc_built():
index 6ab4a0096b1157c99a98c22213c147a7b7c10478..2a793139be0e8e24dee3cee6dc10a94e0171ada3 100644 (file)
@@ -591,12 +591,6 @@ static int net_ads_info(struct net_context *c, int argc, const char **argv)
        return 0;
 }
 
-static void use_in_memory_ccache(void) {
-       /* Use in-memory credentials cache so we do not interfere with
-        * existing credentials */
-       setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
-}
-
 static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain,
                                  uint32_t auth_flags, ADS_STRUCT **ads_ret)
 {
@@ -1502,209 +1496,6 @@ static WERROR check_ads_config( void )
        return WERR_OK;
 }
 
-/*******************************************************************
- Send a DNS update request
-*******************************************************************/
-
-#if defined(HAVE_KRB5)
-#include "../lib/addns/dns.h"
-
-static NTSTATUS net_update_dns_internal(struct net_context *c,
-                                       TALLOC_CTX *ctx, ADS_STRUCT *ads,
-                                       const char *machine_name,
-                                       const struct sockaddr_storage *addrs,
-                                       int num_addrs, bool remove_host)
-{
-       struct dns_rr_ns *nameservers = NULL;
-       size_t ns_count = 0, i;
-       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-       DNS_ERROR dns_err;
-       fstring dns_server;
-       const char *dnsdomain = NULL;
-       char *root_domain = NULL;
-
-       if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
-               d_printf(_("No DNS domain configured for %s. "
-                          "Unable to perform DNS Update.\n"), machine_name);
-               status = NT_STATUS_INVALID_PARAMETER;
-               goto done;
-       }
-       dnsdomain++;
-
-       status = ads_dns_lookup_ns(ctx,
-                                  dnsdomain,
-                                  &nameservers,
-                                  &ns_count);
-       if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
-               /* Child domains often do not have NS records.  Look
-                  for the NS record for the forest root domain
-                  (rootDomainNamingContext in therootDSE) */
-
-               const char *rootname_attrs[] =  { "rootDomainNamingContext", NULL };
-               LDAPMessage *msg = NULL;
-               char *root_dn;
-               ADS_STATUS ads_status;
-
-               if ( !ads->ldap.ld ) {
-                       ads_status = ads_connect( ads );
-                       if ( !ADS_ERR_OK(ads_status) ) {
-                               DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
-                               goto done;
-                       }
-               }
-
-               ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
-                                      "(objectclass=*)", rootname_attrs, &msg);
-               if (!ADS_ERR_OK(ads_status)) {
-                       goto done;
-               }
-
-               root_dn = ads_pull_string(ads, ctx, msg,  "rootDomainNamingContext");
-               if ( !root_dn ) {
-                       ads_msgfree( ads, msg );
-                       goto done;
-               }
-
-               root_domain = ads_build_domain( root_dn );
-
-               /* cleanup */
-               ads_msgfree( ads, msg );
-
-               /* try again for NS servers */
-
-               status = ads_dns_lookup_ns(ctx,
-                                          root_domain,
-                                          &nameservers,
-                                          &ns_count);
-
-               if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
-                       DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
-                        "realm\n", ads->config.realm));
-                       if (ns_count == 0) {
-                               status = NT_STATUS_UNSUCCESSFUL;
-                       }
-                       goto done;
-               }
-
-               dnsdomain = root_domain;
-
-       }
-
-       for (i=0; i < ns_count; i++) {
-
-               uint32_t flags = DNS_UPDATE_SIGNED |
-                                DNS_UPDATE_UNSIGNED |
-                                DNS_UPDATE_UNSIGNED_SUFFICIENT |
-                                DNS_UPDATE_PROBE |
-                                DNS_UPDATE_PROBE_SUFFICIENT;
-
-               if (c->opt_force) {
-                       flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
-                       flags &= ~DNS_UPDATE_UNSIGNED_SUFFICIENT;
-               }
-
-               /*
-                *  Do not return after PROBE completion if this function
-                *  is called for DNS removal.
-                */
-               if (remove_host) {
-                       flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
-               }
-
-               status = NT_STATUS_UNSUCCESSFUL;
-
-               /* Now perform the dns update - we'll try non-secure and if we fail,
-                  we'll follow it up with a secure update */
-
-               fstrcpy( dns_server, nameservers[i].hostname );
-
-               dns_err = DoDNSUpdate(dns_server,
-                                     dnsdomain,
-                                     machine_name,
-                                     addrs,
-                                     num_addrs,
-                                     flags,
-                                     remove_host);
-               if (ERR_DNS_IS_OK(dns_err)) {
-                       status = NT_STATUS_OK;
-                       goto done;
-               }
-
-               if (ERR_DNS_EQUAL(dns_err, ERROR_DNS_INVALID_NAME_SERVER) ||
-                   ERR_DNS_EQUAL(dns_err, ERROR_DNS_CONNECTION_FAILED) ||
-                   ERR_DNS_EQUAL(dns_err, ERROR_DNS_SOCKET_ERROR)) {
-                       DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
-                               dns_errstr(dns_err)));
-                       continue;
-               }
-
-               d_printf(_("DNS Update for %s failed: %s\n"),
-                       machine_name, dns_errstr(dns_err));
-               status = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-done:
-
-       SAFE_FREE( root_domain );
-
-       return status;
-}
-
-static NTSTATUS net_update_dns_ext(struct net_context *c,
-                                  TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
-                                  const char *hostname,
-                                  struct sockaddr_storage *iplist,
-                                  int num_addrs, bool remove_host)
-{
-       struct sockaddr_storage *iplist_alloc = NULL;
-       fstring machine_name;
-       NTSTATUS status;
-
-       if (hostname) {
-               fstrcpy(machine_name, hostname);
-       } else {
-               name_to_fqdn( machine_name, lp_netbios_name() );
-       }
-       if (!strlower_m( machine_name )) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       /*
-        * If remove_host is true, then remove all IP addresses associated with
-        * this hostname from the AD server.
-        */
-       if (!remove_host && (num_addrs == 0 || iplist == NULL)) {
-               /*
-                * Get our ip address
-                * (not the 127.0.0.x address but a real ip address)
-                */
-               num_addrs = get_my_ip_address(&iplist_alloc);
-               if ( num_addrs <= 0 ) {
-                       DEBUG(4, ("net_update_dns_ext: Failed to find my "
-                                 "non-loopback IP addresses!\n"));
-                       return NT_STATUS_INVALID_PARAMETER;
-               }
-               iplist = iplist_alloc;
-       }
-
-       status = net_update_dns_internal(c, mem_ctx, ads, machine_name,
-                                        iplist, num_addrs, remove_host);
-
-       SAFE_FREE(iplist_alloc);
-       return status;
-}
-
-static NTSTATUS net_update_dns(struct net_context *c, TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
-{
-       NTSTATUS status;
-
-       status = net_update_dns_ext(c, mem_ctx, ads, hostname, NULL, 0, false);
-       return status;
-}
-#endif
-
-
 /*******************************************************************
  ********************************************************************/
 
@@ -1739,94 +1530,6 @@ static int net_ads_join_usage(struct net_context *c, int argc, const char **argv
 }
 
 
-static void _net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
-{
-#if defined(HAVE_KRB5)
-       ADS_STRUCT *ads_dns = NULL;
-       int ret;
-       NTSTATUS status;
-
-       /*
-        * In a clustered environment, don't do dynamic dns updates:
-        * Registering the set of ip addresses that are assigned to
-        * the interfaces of the node that performs the join does usually
-        * not have the desired effect, since the local interfaces do not
-        * carry the complete set of the cluster's public IP addresses.
-        * And it can also contain internal addresses that should not
-        * be visible to the outside at all.
-        * In order to do dns updates in a clustererd setup, use
-        * net ads dns register.
-        */
-       if (lp_clustering()) {
-               d_fprintf(stderr, _("Not doing automatic DNS update in a "
-                                   "clustered setup.\n"));
-               return;
-       }
-
-       if (!r->out.domain_is_ad) {
-               return;
-       }
-
-       /*
-        * We enter this block with user creds.
-        * kinit with the machine password to do dns update.
-        */
-
-       ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name, ADS_SASL_PLAIN);
-
-       if (ads_dns == NULL) {
-               d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
-               goto done;
-       }
-
-       use_in_memory_ccache();
-
-       ret = asprintf(&ads_dns->auth.user_name, "%s$", lp_netbios_name());
-       if (ret == -1) {
-               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
-               goto done;
-       }
-
-       ads_dns->auth.password = secrets_fetch_machine_password(
-               r->out.netbios_domain_name, NULL, NULL);
-       if (ads_dns->auth.password == NULL) {
-               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
-               goto done;
-       }
-
-       ads_dns->auth.realm = SMB_STRDUP(r->out.dns_domain_name);
-       if (ads_dns->auth.realm == NULL) {
-               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
-               goto done;
-       }
-
-       if (!strupper_m(ads_dns->auth.realm)) {
-               d_fprintf(stderr, _("strupper_m %s failed\n"), ads_dns->auth.realm);
-               goto done;
-       }
-
-       ret = ads_kinit_password(ads_dns);
-       if (ret != 0) {
-               d_fprintf(stderr,
-                         _("DNS update failed: kinit failed: %s\n"),
-                         error_message(ret));
-               goto done;
-       }
-
-       status = net_update_dns(c, ctx, ads_dns, NULL);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf( stderr, _("DNS update failed: %s\n"),
-                         nt_errstr(status));
-       }
-
-done:
-       ads_destroy(&ads_dns);
-#endif
-
-       return;
-}
-
-
 int net_ads_join(struct net_context *c, int argc, const char **argv)
 {
        TALLOC_CTX *ctx = NULL;
@@ -2007,7 +1710,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
         * operation as succeeded if we came this far.
         */
        if (!c->opt_no_dns_updates) {
-               _net_ads_join_dns_updates(c, ctx, r);
+               net_ads_join_dns_updates(c, ctx, r);
        }
 
        TALLOC_FREE(r);
diff --git a/source3/utils/net_ads_join_dns.c b/source3/utils/net_ads_join_dns.c
new file mode 100644 (file)
index 0000000..995fd5e
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+   Samba Unix/Linux SMB client library
+   net ads dns internal functions
+   Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+   Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
+   Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
+   Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "utils/net.h"
+#include "../lib/addns/dnsquery.h"
+#include "secrets.h"
+#include "krb5_env.h"
+#include "utils/net_dns.h"
+#include "lib/util/string_wrappers.h"
+
+#ifdef HAVE_ADS
+
+/*******************************************************************
+ Send a DNS update request
+*******************************************************************/
+
+#if defined(HAVE_KRB5)
+#include "../lib/addns/dns.h"
+
+void use_in_memory_ccache(void) {
+       /* Use in-memory credentials cache so we do not interfere with
+        * existing credentials */
+       setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
+}
+
+static NTSTATUS net_update_dns_internal(struct net_context *c,
+                                       TALLOC_CTX *ctx, ADS_STRUCT *ads,
+                                       const char *machine_name,
+                                       const struct sockaddr_storage *addrs,
+                                       int num_addrs, bool remove_host)
+{
+       struct dns_rr_ns *nameservers = NULL;
+       size_t ns_count = 0, i;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       DNS_ERROR dns_err;
+       fstring dns_server;
+       const char *dnsdomain = NULL;
+       char *root_domain = NULL;
+
+       if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
+               d_printf(_("No DNS domain configured for %s. "
+                          "Unable to perform DNS Update.\n"), machine_name);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+       dnsdomain++;
+
+       status = ads_dns_lookup_ns(ctx,
+                                  dnsdomain,
+                                  &nameservers,
+                                  &ns_count);
+       if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
+               /* Child domains often do not have NS records.  Look
+                  for the NS record for the forest root domain
+                  (rootDomainNamingContext in therootDSE) */
+
+               const char *rootname_attrs[] =  { "rootDomainNamingContext", NULL };
+               LDAPMessage *msg = NULL;
+               char *root_dn;
+               ADS_STATUS ads_status;
+
+               if ( !ads->ldap.ld ) {
+                       ads_status = ads_connect( ads );
+                       if ( !ADS_ERR_OK(ads_status) ) {
+                               DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
+                               goto done;
+                       }
+               }
+
+               ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
+                                      "(objectclass=*)", rootname_attrs, &msg);
+               if (!ADS_ERR_OK(ads_status)) {
+                       goto done;
+               }
+
+               root_dn = ads_pull_string(ads, ctx, msg,  "rootDomainNamingContext");
+               if ( !root_dn ) {
+                       ads_msgfree( ads, msg );
+                       goto done;
+               }
+
+               root_domain = ads_build_domain( root_dn );
+
+               /* cleanup */
+               ads_msgfree( ads, msg );
+
+               /* try again for NS servers */
+
+               status = ads_dns_lookup_ns(ctx,
+                                          root_domain,
+                                          &nameservers,
+                                          &ns_count);
+
+               if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
+                       DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
+                        "realm\n", ads->config.realm));
+                       if (ns_count == 0) {
+                               status = NT_STATUS_UNSUCCESSFUL;
+                       }
+                       goto done;
+               }
+
+               dnsdomain = root_domain;
+
+       }
+
+       for (i=0; i < ns_count; i++) {
+
+               uint32_t flags = DNS_UPDATE_SIGNED |
+                                DNS_UPDATE_UNSIGNED |
+                                DNS_UPDATE_UNSIGNED_SUFFICIENT |
+                                DNS_UPDATE_PROBE |
+                                DNS_UPDATE_PROBE_SUFFICIENT;
+
+               if (c->opt_force) {
+                       flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
+                       flags &= ~DNS_UPDATE_UNSIGNED_SUFFICIENT;
+               }
+
+               /*
+                *  Do not return after PROBE completion if this function
+                *  is called for DNS removal.
+                */
+               if (remove_host) {
+                       flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
+               }
+
+               status = NT_STATUS_UNSUCCESSFUL;
+
+               /* Now perform the dns update - we'll try non-secure and if we fail,
+                  we'll follow it up with a secure update */
+
+               fstrcpy( dns_server, nameservers[i].hostname );
+
+               dns_err = DoDNSUpdate(dns_server,
+                                     dnsdomain,
+                                     machine_name,
+                                     addrs,
+                                     num_addrs,
+                                     flags,
+                                     remove_host);
+               if (ERR_DNS_IS_OK(dns_err)) {
+                       status = NT_STATUS_OK;
+                       goto done;
+               }
+
+               if (ERR_DNS_EQUAL(dns_err, ERROR_DNS_INVALID_NAME_SERVER) ||
+                   ERR_DNS_EQUAL(dns_err, ERROR_DNS_CONNECTION_FAILED) ||
+                   ERR_DNS_EQUAL(dns_err, ERROR_DNS_SOCKET_ERROR)) {
+                       DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
+                               dns_errstr(dns_err)));
+                       continue;
+               }
+
+               d_printf(_("DNS Update for %s failed: %s\n"),
+                       machine_name, dns_errstr(dns_err));
+               status = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+done:
+
+       SAFE_FREE( root_domain );
+
+       return status;
+}
+
+NTSTATUS net_update_dns_ext(struct net_context *c,
+                           TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
+                           const char *hostname,
+                           struct sockaddr_storage *iplist,
+                           int num_addrs, bool remove_host)
+{
+       struct sockaddr_storage *iplist_alloc = NULL;
+       fstring machine_name;
+       NTSTATUS status;
+
+       if (hostname) {
+               fstrcpy(machine_name, hostname);
+       } else {
+               name_to_fqdn( machine_name, lp_netbios_name() );
+       }
+       if (!strlower_m( machine_name )) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /*
+        * If remove_host is true, then remove all IP addresses associated with
+        * this hostname from the AD server.
+        */
+       if (!remove_host && (num_addrs == 0 || iplist == NULL)) {
+               /*
+                * Get our ip address
+                * (not the 127.0.0.x address but a real ip address)
+                */
+               num_addrs = get_my_ip_address(&iplist_alloc);
+               if ( num_addrs <= 0 ) {
+                       DEBUG(4, ("net_update_dns_ext: Failed to find my "
+                                 "non-loopback IP addresses!\n"));
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               iplist = iplist_alloc;
+       }
+
+       status = net_update_dns_internal(c, mem_ctx, ads, machine_name,
+                                        iplist, num_addrs, remove_host);
+
+       SAFE_FREE(iplist_alloc);
+       return status;
+}
+
+static NTSTATUS net_update_dns(struct net_context *c, TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
+{
+       NTSTATUS status;
+
+       status = net_update_dns_ext(c, mem_ctx, ads, hostname, NULL, 0, false);
+       return status;
+}
+#endif
+
+void net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
+{
+#if defined(HAVE_KRB5)
+       ADS_STRUCT *ads_dns = NULL;
+       int ret;
+       NTSTATUS status;
+
+       /*
+        * In a clustered environment, don't do dynamic dns updates:
+        * Registering the set of ip addresses that are assigned to
+        * the interfaces of the node that performs the join does usually
+        * not have the desired effect, since the local interfaces do not
+        * carry the complete set of the cluster's public IP addresses.
+        * And it can also contain internal addresses that should not
+        * be visible to the outside at all.
+        * In order to do dns updates in a clustererd setup, use
+        * net ads dns register.
+        */
+       if (lp_clustering()) {
+               d_fprintf(stderr, _("Not doing automatic DNS update in a "
+                                   "clustered setup.\n"));
+               return;
+       }
+
+       if (!r->out.domain_is_ad) {
+               return;
+       }
+
+       /*
+        * We enter this block with user creds.
+        * kinit with the machine password to do dns update.
+        */
+
+       ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name, ADS_SASL_PLAIN);
+
+       if (ads_dns == NULL) {
+               d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
+               goto done;
+       }
+
+       use_in_memory_ccache();
+
+       ret = asprintf(&ads_dns->auth.user_name, "%s$", lp_netbios_name());
+       if (ret == -1) {
+               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
+               goto done;
+       }
+
+       ads_dns->auth.password = secrets_fetch_machine_password(
+               r->out.netbios_domain_name, NULL, NULL);
+       if (ads_dns->auth.password == NULL) {
+               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
+               goto done;
+       }
+
+       ads_dns->auth.realm = SMB_STRDUP(r->out.dns_domain_name);
+       if (ads_dns->auth.realm == NULL) {
+               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
+               goto done;
+       }
+
+       if (!strupper_m(ads_dns->auth.realm)) {
+               d_fprintf(stderr, _("strupper_m %s failed\n"), ads_dns->auth.realm);
+               goto done;
+       }
+
+       ret = ads_kinit_password(ads_dns);
+       if (ret != 0) {
+               d_fprintf(stderr,
+                         _("DNS update failed: kinit failed: %s\n"),
+                         error_message(ret));
+               goto done;
+       }
+
+       status = net_update_dns(c, ctx, ads_dns, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf( stderr, _("DNS update failed: %s\n"),
+                         nt_errstr(status));
+       }
+
+done:
+       ads_destroy(&ads_dns);
+#endif
+
+       return;
+}
+
+#endif  /* HAVE_ADS */
index eea7cc9426f08e86301fba1859cdeaf9aca63419..b6ff639a0941a497a6b6c97796abe0ecae9a23da 100644 (file)
@@ -23,7 +23,9 @@
 #ifndef _NET_PROTO_H_
 #define _NET_PROTO_H_
 
+#include "ads.h"
 #include "libads/ads_status.h"
+#include "librpc/gen_ndr/libnet_join.h"
 
 /* The following definitions come from utils/net.c  */
 
@@ -46,6 +48,15 @@ int net_ads_kerberos(struct net_context *c, int argc, const char **argv);
 int net_ads_setspn(struct net_context *c, int argc, const char **argv);
 int net_ads(struct net_context *c, int argc, const char **argv);
 
+/* The following definitions come from utils/net_ads_join_dns.c  */
+void use_in_memory_ccache(void);
+NTSTATUS net_update_dns_ext(struct net_context *c,
+                           TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
+                           const char *hostname,
+                           struct sockaddr_storage *iplist,
+                           int num_addrs, bool remove_host);
+void net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r);
+
 /* The following definitions come from utils/net_ads_gpo.c  */
 
 int net_ads_gpo(struct net_context *c, int argc, const char **argv);
index 1d9b1d783c6924ba1e1fff6ca538d5337ba84fb5..3142f83bc7f7adc1aaed241ce17556d6426a6b2b 100644 (file)
@@ -64,19 +64,23 @@ static WERROR check_ads_config(struct loadparm_context *lp_ctx)
 static PyObject *py_net_join_member(py_net_Object *self, PyObject *args, PyObject *kwargs)
 {
        struct libnet_JoinCtx *r = NULL;
+       struct net_context *c;
        WERROR werr;
        PyObject *result;
        TALLOC_CTX *mem_ctx;
+       uint8_t no_dns_updates;
        bool modify_config = lp_config_backend_is_registry();
        const char *kwnames[] = { "dnshostname", "createupn", "createcomputer",
                                  "osName", "osVer", "osServicePack",
-                                 "machinepass", "debug", NULL };
+                                 "machinepass", "debug", "noDnsUpdates", NULL };
 
        mem_ctx = talloc_new(self->mem_ctx);
        if (mem_ctx == NULL) {
                PyErr_NoMemory();
                return NULL;
        }
+       c = talloc_zero(mem_ctx, struct net_context);
+       c->msg_ctx = mem_ctx;
 
        werr = libnet_init_JoinCtx(mem_ctx, &r);
        if (!W_ERROR_IS_OK(werr)) {
@@ -84,7 +88,7 @@ static PyObject *py_net_join_member(py_net_Object *self, PyObject *args, PyObjec
                return NULL;
        }
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|sssssssp:Join",
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssssspp:Join",
                                         discard_const_p(char *, kwnames),
                                         &r->in.dnshostname,
                                         &r->in.upn,
@@ -93,7 +97,8 @@ static PyObject *py_net_join_member(py_net_Object *self, PyObject *args, PyObjec
                                         &r->in.os_version,
                                         &r->in.os_servicepack,
                                         &r->in.machine_password,
-                                        &r->in.debug)) {
+                                        &r->in.debug,
+                                        &no_dns_updates)) {
                talloc_free(mem_ctx);
                PyErr_FromString(_("Invalid arguments\n"));
                return NULL;
@@ -121,6 +126,9 @@ static PyObject *py_net_join_member(py_net_Object *self, PyObject *args, PyObjec
                                  WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
                                  WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
        r->in.msg_ctx           = cmdline_messaging_context(get_dyn_CONFIGFILE());
+       c->opt_user_name = r->in.admin_account;
+       c->opt_password = r->in.admin_password;
+       c->opt_kerberos = r->in.use_kerberos;
 
        werr = libnet_Join(mem_ctx, r);
        if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND)) {
@@ -150,6 +158,16 @@ static PyObject *py_net_join_member(py_net_Object *self, PyObject *args, PyObjec
                         r->out.netbios_domain_name, get_dyn_CONFIGFILE());
        }
 
+       /*
+        * We try doing the dns update (if it was compiled in
+        * and if it was not disabled on the command line).
+        * If the dns update fails, we still consider the join
+        * operation as succeeded if we came this far.
+        */
+       if (!no_dns_updates) {
+               net_ads_join_dns_updates(c, mem_ctx, r);
+       }
+
        result = Py_BuildValue("ss", dom_sid_string(mem_ctx, r->out.domain_sid),
                               r->out.dns_domain_name);
 
index 2ccab0107525383be45ff20f2f87c1497d90807d..48ce876db27acbf9596191d959637309a1b6b730 100644 (file)
@@ -7,6 +7,9 @@ bld.SAMBA3_SUBSYSTEM('PASSWD_UTIL',
 bld.SAMBA3_SUBSYSTEM('CONN_TDB',
                      source='conn_tdb.c')
 
+bld.SAMBA3_SUBSYSTEM('DNS_UTIL',
+                     source='net_dns.c net_ads_join_dns.c')
+
 bld.SAMBA3_BINARY('profiles',
                  source='profiles.c',
                  deps='''
@@ -211,7 +214,6 @@ bld.SAMBA3_BINARY('net',
                  net_util.c
                  net_rpc_sh_acct.c
                  net_rpc_audit.c
-                 net_dns.c
                  net_ads_gpo.c
                  net_conf.c
                  net_conf_util.c
@@ -281,6 +283,7 @@ bld.SAMBA3_BINARY('net',
                  jansson
                  common_auth
                  ADOUBLE
+                 DNS_UTIL
                  ''')
 
 bld.SAMBA3_BINARY('mvxattr',
@@ -339,6 +342,6 @@ pytalloc_util = bld.pyembed_libname('pytalloc-util')
 pyrpc_util = bld.pyembed_libname('pyrpc_util')
 bld.SAMBA3_PYTHON('python_net_s3',
         source='py_net.c',
-        deps='LIBNET cmdline_contexts %s %s' % (pytalloc_util, pyrpc_util),
+        deps='LIBNET DNS_UTIL cmdline_contexts %s %s' % (pytalloc_util, pyrpc_util),
         realname='samba/net_s3.so'
         )