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:
parent
05c09e8cfa
commit
5e31e8f15b
@ -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():
|
||||
|
@ -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);
|
||||
|
328
source3/utils/net_ads_join_dns.c
Normal file
328
source3/utils/net_ads_join_dns.c
Normal 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 */
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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'
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user