Line data Source code
1 : /*
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)
8 :
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.
13 :
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.
18 :
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/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "utils/net.h"
25 : #include "../lib/addns/dnsquery.h"
26 : #include "passdb.h"
27 : #include "utils/net_dns.h"
28 : #include "lib/util/string_wrappers.h"
29 :
30 : #ifdef HAVE_ADS
31 :
32 : /*******************************************************************
33 : Send a DNS update request
34 : *******************************************************************/
35 :
36 : #if defined(HAVE_KRB5)
37 : #include "../lib/addns/dns.h"
38 :
39 68 : static NTSTATUS net_update_dns_internal(struct net_context *c,
40 : TALLOC_CTX *ctx,
41 : ADS_STRUCT *ads,
42 : struct cli_credentials *creds,
43 : const char *machine_name,
44 : const struct sockaddr_storage *addrs,
45 : int num_addrs, bool remove_host)
46 : {
47 68 : struct dns_rr_ns *nameservers = NULL;
48 68 : size_t ns_count = 0, i;
49 68 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
50 0 : DNS_ERROR dns_err;
51 0 : fstring dns_server;
52 68 : const char *dnsdomain = NULL;
53 68 : char *root_domain = NULL;
54 68 : uint32_t ttl = 3600;
55 :
56 68 : if (c->opt_dns_ttl > 0) {
57 2 : ttl = MIN(c->opt_dns_ttl, UINT32_MAX);
58 : }
59 :
60 68 : if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
61 0 : d_printf(_("No DNS domain configured for %s. "
62 : "Unable to perform DNS Update.\n"), machine_name);
63 0 : status = NT_STATUS_INVALID_PARAMETER;
64 0 : goto done;
65 : }
66 68 : dnsdomain++;
67 :
68 68 : status = ads_dns_lookup_ns(ctx,
69 : dnsdomain,
70 : &nameservers,
71 : &ns_count);
72 68 : 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) */
76 :
77 20 : const char *rootname_attrs[] = { "rootDomainNamingContext", NULL };
78 20 : LDAPMessage *msg = NULL;
79 0 : char *root_dn;
80 0 : ADS_STATUS ads_status;
81 :
82 20 : if ( !ads->ldap.ld ) {
83 0 : ads_status = ads_connect_creds(ads, creds);
84 0 : if ( !ADS_ERR_OK(ads_status) ) {
85 0 : DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
86 0 : status = ads_ntstatus(ads_status);
87 0 : goto done;
88 : }
89 : }
90 :
91 20 : ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
92 : "(objectclass=*)", rootname_attrs, &msg);
93 20 : if (!ADS_ERR_OK(ads_status)) {
94 0 : status = ads_ntstatus(ads_status);
95 0 : goto done;
96 : }
97 :
98 20 : root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
99 20 : if ( !root_dn ) {
100 0 : ads_msgfree( ads, msg );
101 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
102 0 : goto done;
103 : }
104 :
105 20 : root_domain = ads_build_domain( root_dn );
106 :
107 : /* cleanup */
108 20 : ads_msgfree( ads, msg );
109 :
110 : /* try again for NS servers */
111 :
112 20 : status = ads_dns_lookup_ns(ctx,
113 : root_domain,
114 : &nameservers,
115 : &ns_count);
116 :
117 20 : if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
118 0 : DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
119 : "realm\n", ads->config.realm));
120 0 : if (ns_count == 0) {
121 0 : status = NT_STATUS_UNSUCCESSFUL;
122 : }
123 0 : goto done;
124 : }
125 :
126 20 : dnsdomain = root_domain;
127 :
128 : }
129 :
130 68 : for (i=0; i < ns_count; i++) {
131 :
132 68 : uint32_t flags = DNS_UPDATE_SIGNED |
133 : DNS_UPDATE_UNSIGNED |
134 : DNS_UPDATE_UNSIGNED_SUFFICIENT |
135 : DNS_UPDATE_PROBE |
136 : DNS_UPDATE_PROBE_SUFFICIENT;
137 :
138 68 : if (c->opt_force) {
139 2 : flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
140 2 : flags &= ~DNS_UPDATE_UNSIGNED_SUFFICIENT;
141 : }
142 :
143 : /*
144 : * Do not return after PROBE completion if this function
145 : * is called for DNS removal.
146 : */
147 68 : if (remove_host) {
148 8 : flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
149 : }
150 :
151 68 : status = NT_STATUS_UNSUCCESSFUL;
152 :
153 : /* Now perform the dns update - we'll try non-secure and if we fail,
154 : we'll follow it up with a secure update */
155 :
156 68 : fstrcpy( dns_server, nameservers[i].hostname );
157 :
158 68 : dns_err = DoDNSUpdate(dns_server,
159 : dnsdomain,
160 : machine_name,
161 : creds,
162 : addrs,
163 : num_addrs,
164 : flags,
165 : ttl,
166 : remove_host);
167 68 : if (ERR_DNS_IS_OK(dns_err)) {
168 45 : status = NT_STATUS_OK;
169 45 : goto done;
170 : }
171 :
172 23 : if (ERR_DNS_EQUAL(dns_err, ERROR_DNS_INVALID_NAME_SERVER) ||
173 23 : ERR_DNS_EQUAL(dns_err, ERROR_DNS_CONNECTION_FAILED) ||
174 23 : ERR_DNS_EQUAL(dns_err, ERROR_DNS_SOCKET_ERROR)) {
175 0 : DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
176 : dns_errstr(dns_err)));
177 0 : continue;
178 : }
179 :
180 23 : d_printf(_("DNS Update for %s failed: %s\n"),
181 : machine_name, dns_errstr(dns_err));
182 23 : status = NT_STATUS_UNSUCCESSFUL;
183 23 : goto done;
184 : }
185 :
186 0 : done:
187 :
188 68 : SAFE_FREE( root_domain );
189 :
190 68 : return status;
191 : }
192 :
193 68 : NTSTATUS net_update_dns_ext(struct net_context *c,
194 : TALLOC_CTX *mem_ctx,
195 : ADS_STRUCT *ads,
196 : struct cli_credentials *creds,
197 : const char *hostname,
198 : struct sockaddr_storage *iplist,
199 : int num_addrs, bool remove_host)
200 : {
201 68 : struct sockaddr_storage *iplist_alloc = NULL;
202 0 : fstring machine_name;
203 0 : NTSTATUS status;
204 :
205 68 : if (hostname) {
206 20 : fstrcpy(machine_name, hostname);
207 : } else {
208 48 : const char *dns_hostname = lp_dns_hostname();
209 48 : if (dns_hostname == NULL) {
210 0 : return NT_STATUS_NO_MEMORY;
211 : }
212 48 : fstrcpy(machine_name, lp_dns_hostname());
213 : }
214 68 : if (!strlower_m( machine_name )) {
215 0 : return NT_STATUS_INVALID_PARAMETER;
216 : }
217 :
218 : /*
219 : * If remove_host is true, then remove all IP addresses associated with
220 : * this hostname from the AD server.
221 : */
222 68 : if (!remove_host && (num_addrs == 0 || iplist == NULL)) {
223 : /*
224 : * Get our ip address
225 : * (not the 127.0.0.x address but a real ip address)
226 : */
227 48 : num_addrs = get_my_ip_address(&iplist_alloc);
228 48 : if ( num_addrs <= 0 ) {
229 0 : DEBUG(4, ("net_update_dns_ext: Failed to find my "
230 : "non-loopback IP addresses!\n"));
231 0 : return NT_STATUS_INVALID_PARAMETER;
232 : }
233 48 : iplist = iplist_alloc;
234 : }
235 :
236 68 : status = net_update_dns_internal(c,
237 : mem_ctx,
238 : ads,
239 : creds,
240 : machine_name,
241 : iplist,
242 : num_addrs,
243 : remove_host);
244 :
245 68 : SAFE_FREE(iplist_alloc);
246 68 : return status;
247 : }
248 :
249 : #endif
250 :
251 48 : void net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
252 : {
253 : #if defined(HAVE_KRB5)
254 48 : ADS_STRUCT *ads_dns = NULL;
255 48 : struct cli_credentials *creds = NULL;
256 0 : NTSTATUS status;
257 :
258 : /*
259 : * In a clustered environment, don't do dynamic dns updates:
260 : * Registering the set of ip addresses that are assigned to
261 : * the interfaces of the node that performs the join does usually
262 : * not have the desired effect, since the local interfaces do not
263 : * carry the complete set of the cluster's public IP addresses.
264 : * And it can also contain internal addresses that should not
265 : * be visible to the outside at all.
266 : * In order to do dns updates in a clustererd setup, use
267 : * net ads dns register.
268 : */
269 48 : if (lp_clustering()) {
270 0 : d_fprintf(stderr, _("Not doing automatic DNS update in a "
271 : "clustered setup.\n"));
272 0 : return;
273 : }
274 :
275 48 : if (!r->out.domain_is_ad) {
276 0 : return;
277 : }
278 :
279 : /*
280 : * We enter this block with user creds.
281 : * kinit with the machine password to do dns update.
282 : */
283 :
284 48 : ads_dns = ads_init(ctx,
285 : lp_realm(),
286 : lp_workgroup(),
287 : r->in.dc_name,
288 : ADS_SASL_PLAIN);
289 48 : if (ads_dns == NULL) {
290 0 : d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
291 0 : goto done;
292 : }
293 :
294 48 : status = pdb_get_trust_credentials(ads_dns->server.workgroup,
295 : ads_dns->server.realm,
296 : ads_dns,
297 : &creds);
298 48 : if (!NT_STATUS_IS_OK(status)) {
299 0 : d_fprintf(stderr, "pdb_get_trust_credentials() failed: %s\n",
300 : nt_errstr(status));
301 0 : goto done;
302 : }
303 :
304 48 : status = net_update_dns_ext(c,
305 : ads_dns,
306 : ads_dns,
307 : creds,
308 : NULL,
309 : NULL,
310 : 0,
311 : false);
312 48 : if (!NT_STATUS_IS_OK(status)) {
313 21 : d_fprintf( stderr, _("DNS update failed: %s\n"),
314 : nt_errstr(status));
315 : }
316 :
317 27 : done:
318 48 : TALLOC_FREE(ads_dns);
319 : #endif
320 :
321 48 : return;
322 : }
323 :
324 : #endif /* HAVE_ADS */
|