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
;
60 if ( (dnsdomain
= strchr_m( machine_name
, '.')) == NULL
) {
61 d_printf(_("No DNS domain configured for %s. "
62 "Unable to perform DNS Update.\n"), machine_name
);
63 status
= NT_STATUS_INVALID_PARAMETER
;
68 status
= ads_dns_lookup_ns(ctx
,
72 if ( !NT_STATUS_IS_OK(status
) || (ns_count
== 0)) {
73 /* Child domains often do not have NS records. Look
74 for the NS record for the forest root domain
75 (rootDomainNamingContext in therootDSE) */
77 const char *rootname_attrs
[] = { "rootDomainNamingContext", NULL
};
78 LDAPMessage
*msg
= NULL
;
80 ADS_STATUS ads_status
;
82 if ( !ads
->ldap
.ld
) {
83 ads_status
= ads_connect( ads
);
84 if ( !ADS_ERR_OK(ads_status
) ) {
85 DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
90 ads_status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
,
91 "(objectclass=*)", rootname_attrs
, &msg
);
92 if (!ADS_ERR_OK(ads_status
)) {
96 root_dn
= ads_pull_string(ads
, ctx
, msg
, "rootDomainNamingContext");
98 ads_msgfree( ads
, msg
);
102 root_domain
= ads_build_domain( root_dn
);
105 ads_msgfree( ads
, msg
);
107 /* try again for NS servers */
109 status
= ads_dns_lookup_ns(ctx
,
114 if ( !NT_STATUS_IS_OK(status
) || (ns_count
== 0)) {
115 DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
116 "realm\n", ads
->config
.realm
));
118 status
= NT_STATUS_UNSUCCESSFUL
;
123 dnsdomain
= root_domain
;
127 for (i
=0; i
< ns_count
; i
++) {
129 uint32_t flags
= DNS_UPDATE_SIGNED
|
130 DNS_UPDATE_UNSIGNED
|
131 DNS_UPDATE_UNSIGNED_SUFFICIENT
|
133 DNS_UPDATE_PROBE_SUFFICIENT
;
136 flags
&= ~DNS_UPDATE_PROBE_SUFFICIENT
;
137 flags
&= ~DNS_UPDATE_UNSIGNED_SUFFICIENT
;
141 * Do not return after PROBE completion if this function
142 * is called for DNS removal.
145 flags
&= ~DNS_UPDATE_PROBE_SUFFICIENT
;
148 status
= NT_STATUS_UNSUCCESSFUL
;
150 /* Now perform the dns update - we'll try non-secure and if we fail,
151 we'll follow it up with a secure update */
153 fstrcpy( dns_server
, nameservers
[i
].hostname
);
155 dns_err
= DoDNSUpdate(dns_server
,
162 if (ERR_DNS_IS_OK(dns_err
)) {
163 status
= NT_STATUS_OK
;
167 if (ERR_DNS_EQUAL(dns_err
, ERROR_DNS_INVALID_NAME_SERVER
) ||
168 ERR_DNS_EQUAL(dns_err
, ERROR_DNS_CONNECTION_FAILED
) ||
169 ERR_DNS_EQUAL(dns_err
, ERROR_DNS_SOCKET_ERROR
)) {
170 DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
171 dns_errstr(dns_err
)));
175 d_printf(_("DNS Update for %s failed: %s\n"),
176 machine_name
, dns_errstr(dns_err
));
177 status
= NT_STATUS_UNSUCCESSFUL
;
183 SAFE_FREE( root_domain
);
188 NTSTATUS
net_update_dns_ext(struct net_context
*c
,
189 TALLOC_CTX
*mem_ctx
, ADS_STRUCT
*ads
,
190 const char *hostname
,
191 struct sockaddr_storage
*iplist
,
192 int num_addrs
, bool remove_host
)
194 struct sockaddr_storage
*iplist_alloc
= NULL
;
195 fstring machine_name
;
199 fstrcpy(machine_name
, hostname
);
201 name_to_fqdn( machine_name
, lp_netbios_name() );
203 if (!strlower_m( machine_name
)) {
204 return NT_STATUS_INVALID_PARAMETER
;
208 * If remove_host is true, then remove all IP addresses associated with
209 * this hostname from the AD server.
211 if (!remove_host
&& (num_addrs
== 0 || iplist
== NULL
)) {
214 * (not the 127.0.0.x address but a real ip address)
216 num_addrs
= get_my_ip_address(&iplist_alloc
);
217 if ( num_addrs
<= 0 ) {
218 DEBUG(4, ("net_update_dns_ext: Failed to find my "
219 "non-loopback IP addresses!\n"));
220 return NT_STATUS_INVALID_PARAMETER
;
222 iplist
= iplist_alloc
;
225 status
= net_update_dns_internal(c
, mem_ctx
, ads
, machine_name
,
226 iplist
, num_addrs
, remove_host
);
228 SAFE_FREE(iplist_alloc
);
232 static NTSTATUS
net_update_dns(struct net_context
*c
, TALLOC_CTX
*mem_ctx
, ADS_STRUCT
*ads
, const char *hostname
)
236 status
= net_update_dns_ext(c
, mem_ctx
, ads
, hostname
, NULL
, 0, false);
241 void net_ads_join_dns_updates(struct net_context
*c
, TALLOC_CTX
*ctx
, struct libnet_JoinCtx
*r
)
243 #if defined(HAVE_KRB5)
244 ADS_STRUCT
*ads_dns
= NULL
;
247 char *machine_password
= NULL
;
250 * In a clustered environment, don't do dynamic dns updates:
251 * Registering the set of ip addresses that are assigned to
252 * the interfaces of the node that performs the join does usually
253 * not have the desired effect, since the local interfaces do not
254 * carry the complete set of the cluster's public IP addresses.
255 * And it can also contain internal addresses that should not
256 * be visible to the outside at all.
257 * In order to do dns updates in a clustererd setup, use
258 * net ads dns register.
260 if (lp_clustering()) {
261 d_fprintf(stderr
, _("Not doing automatic DNS update in a "
262 "clustered setup.\n"));
266 if (!r
->out
.domain_is_ad
) {
271 * We enter this block with user creds.
272 * kinit with the machine password to do dns update.
275 ads_dns
= ads_init(ctx
,
280 if (ads_dns
== NULL
) {
281 d_fprintf(stderr
, _("DNS update failed: out of memory!\n"));
285 use_in_memory_ccache();
287 ads_dns
->auth
.user_name
= talloc_asprintf(ads_dns
,
290 if (ads_dns
->auth
.user_name
== NULL
) {
291 d_fprintf(stderr
, _("DNS update failed: out of memory\n"));
295 machine_password
= secrets_fetch_machine_password(
296 r
->out
.netbios_domain_name
, NULL
, NULL
);
297 if (machine_password
!= NULL
) {
298 ads_dns
->auth
.password
= talloc_strdup(ads_dns
,
300 SAFE_FREE(machine_password
);
301 if (ads_dns
->auth
.password
== NULL
) {
303 _("DNS update failed: out of memory\n"));
308 ads_dns
->auth
.realm
= talloc_asprintf_strupper_m(ads_dns
, "%s", r
->out
.dns_domain_name
);
309 if (ads_dns
->auth
.realm
== NULL
) {
310 d_fprintf(stderr
, _("talloc_asprintf_strupper_m %s failed\n"),
311 ads_dns
->auth
.realm
);
315 ret
= ads_kinit_password(ads_dns
);
318 _("DNS update failed: kinit failed: %s\n"),
323 status
= net_update_dns(c
, ctx
, ads_dns
, NULL
);
324 if (!NT_STATUS_IS_OK(status
)) {
325 d_fprintf( stderr
, _("DNS update failed: %s\n"),
330 TALLOC_FREE(ads_dns
);
336 #endif /* HAVE_ADS */