From: David Mulder Date: Fri, 5 Nov 2021 20:43:18 +0000 (-0600) Subject: samba-tool: Create DNS entries on member join X-Git-Tag: tdb-1.4.6~456 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e31e8f15bf0dea1de4f09d270f6bed1a71fb875;p=thirdparty%2Fsamba.git samba-tool: Create DNS entries on member join 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 Reviewed-by: Andrew Bartlett --- diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py index eb52557212e..1bdc0ee535a 100644 --- a/python/samba/netcmd/domain.py +++ b/python/samba/netcmd/domain.py @@ -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(): diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 6ab4a0096b1..2a793139be0 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -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 index 00000000000..995fd5e7cca --- /dev/null +++ b/source3/utils/net_ads_join_dns.c @@ -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 . +*/ + +#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 */ diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h index eea7cc9426f..b6ff639a094 100644 --- a/source3/utils/net_proto.h +++ b/source3/utils/net_proto.h @@ -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); diff --git a/source3/utils/py_net.c b/source3/utils/py_net.c index 1d9b1d783c6..3142f83bc7f 100644 --- a/source3/utils/py_net.c +++ b/source3/utils/py_net.c @@ -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); diff --git a/source3/utils/wscript_build b/source3/utils/wscript_build index 2ccab010752..48ce876db27 100644 --- a/source3/utils/wscript_build +++ b/source3/utils/wscript_build @@ -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' )