2 Samba Unix/Linux SMB client library
3 net ads dns internal functions
4 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5 Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
6 Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7 Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "utils/net.h"
25 #include "../lib/addns/dnsquery.h"
28 #include "utils/net_dns.h"
29 #include "lib/util/string_wrappers.h"
33 /*******************************************************************
34 Send a DNS update request
35 *******************************************************************/
37 #if defined(HAVE_KRB5)
38 #include "../lib/addns/dns.h"
40 void use_in_memory_ccache(void) {
41 /* Use in-memory credentials cache so we do not interfere with
42 * existing credentials */
43 setenv(KRB5_ENV_CCNAME
, "MEMORY:net_ads", 1);
46 static NTSTATUS
net_update_dns_internal(struct net_context
*c
,
47 TALLOC_CTX
*ctx
, ADS_STRUCT
*ads
,
48 const char *machine_name
,
49 const struct sockaddr_storage
*addrs
,
50 int num_addrs
, bool remove_host
)
52 struct dns_rr_ns
*nameservers
= NULL
;
53 size_t ns_count
= 0, i
;
54 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
57 const char *dnsdomain
= NULL
;
58 char *root_domain
= NULL
;
61 if (c
->opt_dns_ttl
> 0) {
62 ttl
= MIN(c
->opt_dns_ttl
, UINT32_MAX
);
65 if ( (dnsdomain
= strchr_m( machine_name
, '.')) == NULL
) {
66 d_printf(_("No DNS domain configured for %s. "
67 "Unable to perform DNS Update.\n"), machine_name
);
68 status
= NT_STATUS_INVALID_PARAMETER
;
73 status
= ads_dns_lookup_ns(ctx
,
77 if ( !NT_STATUS_IS_OK(status
) || (ns_count
== 0)) {
78 /* Child domains often do not have NS records. Look
79 for the NS record for the forest root domain
80 (rootDomainNamingContext in therootDSE) */
82 const char *rootname_attrs
[] = { "rootDomainNamingContext", NULL
};
83 LDAPMessage
*msg
= NULL
;
85 ADS_STATUS ads_status
;
87 if ( !ads
->ldap
.ld
) {
88 ads_status
= ads_connect( ads
);
89 if ( !ADS_ERR_OK(ads_status
) ) {
90 DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
95 ads_status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
,
96 "(objectclass=*)", rootname_attrs
, &msg
);
97 if (!ADS_ERR_OK(ads_status
)) {
101 root_dn
= ads_pull_string(ads
, ctx
, msg
, "rootDomainNamingContext");
103 ads_msgfree( ads
, msg
);
107 root_domain
= ads_build_domain( root_dn
);
110 ads_msgfree( ads
, msg
);
112 /* try again for NS servers */
114 status
= ads_dns_lookup_ns(ctx
,
119 if ( !NT_STATUS_IS_OK(status
) || (ns_count
== 0)) {
120 DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
121 "realm\n", ads
->config
.realm
));
123 status
= NT_STATUS_UNSUCCESSFUL
;
128 dnsdomain
= root_domain
;
132 for (i
=0; i
< ns_count
; i
++) {
134 uint32_t flags
= DNS_UPDATE_SIGNED
|
135 DNS_UPDATE_UNSIGNED
|
136 DNS_UPDATE_UNSIGNED_SUFFICIENT
|
138 DNS_UPDATE_PROBE_SUFFICIENT
;
141 flags
&= ~DNS_UPDATE_PROBE_SUFFICIENT
;
142 flags
&= ~DNS_UPDATE_UNSIGNED_SUFFICIENT
;
146 * Do not return after PROBE completion if this function
147 * is called for DNS removal.
150 flags
&= ~DNS_UPDATE_PROBE_SUFFICIENT
;
153 status
= NT_STATUS_UNSUCCESSFUL
;
155 /* Now perform the dns update - we'll try non-secure and if we fail,
156 we'll follow it up with a secure update */
158 fstrcpy( dns_server
, nameservers
[i
].hostname
);
160 dns_err
= DoDNSUpdate(dns_server
,
168 if (ERR_DNS_IS_OK(dns_err
)) {
169 status
= NT_STATUS_OK
;
173 if (ERR_DNS_EQUAL(dns_err
, ERROR_DNS_INVALID_NAME_SERVER
) ||
174 ERR_DNS_EQUAL(dns_err
, ERROR_DNS_CONNECTION_FAILED
) ||
175 ERR_DNS_EQUAL(dns_err
, ERROR_DNS_SOCKET_ERROR
)) {
176 DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
177 dns_errstr(dns_err
)));
181 d_printf(_("DNS Update for %s failed: %s\n"),
182 machine_name
, dns_errstr(dns_err
));
183 status
= NT_STATUS_UNSUCCESSFUL
;
189 SAFE_FREE( root_domain
);
194 NTSTATUS
net_update_dns_ext(struct net_context
*c
,
195 TALLOC_CTX
*mem_ctx
, ADS_STRUCT
*ads
,
196 const char *hostname
,
197 struct sockaddr_storage
*iplist
,
198 int num_addrs
, bool remove_host
)
200 struct sockaddr_storage
*iplist_alloc
= NULL
;
201 fstring machine_name
;
205 fstrcpy(machine_name
, hostname
);
207 name_to_fqdn( machine_name
, lp_netbios_name() );
209 if (!strlower_m( machine_name
)) {
210 return NT_STATUS_INVALID_PARAMETER
;
214 * If remove_host is true, then remove all IP addresses associated with
215 * this hostname from the AD server.
217 if (!remove_host
&& (num_addrs
== 0 || iplist
== NULL
)) {
220 * (not the 127.0.0.x address but a real ip address)
222 num_addrs
= get_my_ip_address(&iplist_alloc
);
223 if ( num_addrs
<= 0 ) {
224 DEBUG(4, ("net_update_dns_ext: Failed to find my "
225 "non-loopback IP addresses!\n"));
226 return NT_STATUS_INVALID_PARAMETER
;
228 iplist
= iplist_alloc
;
231 status
= net_update_dns_internal(c
, mem_ctx
, ads
, machine_name
,
232 iplist
, num_addrs
, remove_host
);
234 SAFE_FREE(iplist_alloc
);
238 static NTSTATUS
net_update_dns(struct net_context
*c
, TALLOC_CTX
*mem_ctx
, ADS_STRUCT
*ads
, const char *hostname
)
242 status
= net_update_dns_ext(c
, mem_ctx
, ads
, hostname
, NULL
, 0, false);
247 void net_ads_join_dns_updates(struct net_context
*c
, TALLOC_CTX
*ctx
, struct libnet_JoinCtx
*r
)
249 #if defined(HAVE_KRB5)
250 ADS_STRUCT
*ads_dns
= NULL
;
253 char *machine_password
= NULL
;
256 * In a clustered environment, don't do dynamic dns updates:
257 * Registering the set of ip addresses that are assigned to
258 * the interfaces of the node that performs the join does usually
259 * not have the desired effect, since the local interfaces do not
260 * carry the complete set of the cluster's public IP addresses.
261 * And it can also contain internal addresses that should not
262 * be visible to the outside at all.
263 * In order to do dns updates in a clustererd setup, use
264 * net ads dns register.
266 if (lp_clustering()) {
267 d_fprintf(stderr
, _("Not doing automatic DNS update in a "
268 "clustered setup.\n"));
272 if (!r
->out
.domain_is_ad
) {
277 * We enter this block with user creds.
278 * kinit with the machine password to do dns update.
281 ads_dns
= ads_init(ctx
,
286 if (ads_dns
== NULL
) {
287 d_fprintf(stderr
, _("DNS update failed: out of memory!\n"));
291 use_in_memory_ccache();
293 ads_dns
->auth
.user_name
= talloc_asprintf(ads_dns
,
296 if (ads_dns
->auth
.user_name
== NULL
) {
297 d_fprintf(stderr
, _("DNS update failed: out of memory\n"));
301 machine_password
= secrets_fetch_machine_password(
302 r
->out
.netbios_domain_name
, NULL
, NULL
);
303 if (machine_password
!= NULL
) {
304 ads_dns
->auth
.password
= talloc_strdup(ads_dns
,
306 SAFE_FREE(machine_password
);
307 if (ads_dns
->auth
.password
== NULL
) {
309 _("DNS update failed: out of memory\n"));
314 ads_dns
->auth
.realm
= talloc_asprintf_strupper_m(ads_dns
, "%s", r
->out
.dns_domain_name
);
315 if (ads_dns
->auth
.realm
== NULL
) {
316 d_fprintf(stderr
, _("talloc_asprintf_strupper_m %s failed\n"),
317 ads_dns
->auth
.realm
);
321 ret
= ads_kinit_password(ads_dns
);
324 _("DNS update failed: kinit failed: %s\n"),
329 status
= net_update_dns(c
, ctx
, ads_dns
, NULL
);
330 if (!NT_STATUS_IS_OK(status
)) {
331 d_fprintf( stderr
, _("DNS update failed: %s\n"),
336 TALLOC_FREE(ads_dns
);
342 #endif /* HAVE_ADS */