1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

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 <dmulder@suse.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
David Mulder 2021-11-05 14:43:18 -06:00 committed by Andrew Bartlett
parent 05c09e8cfa
commit 5e31e8f15b
6 changed files with 373 additions and 306 deletions

View 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():

View 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);

View File

@ -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 */

View 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);

View 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);

View 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'
)