1 /*
2    Samba Unix/Linux Dynamic DNS Update
3    net ads commands
4 
5    Copyright (C) Krishna Ganugapati (krishnag@centeris.com)         2006
6    Copyright (C) Gerald Carter                                      2006
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "includes.h"
23 #include "utils/net.h"
24 #include "../lib/addns/dns.h"
25 #include "utils/net_dns.h"
26 
27 #if defined(WITH_DNS_UPDATES)
28 
29 /*********************************************************************
30 *********************************************************************/
31 
DoDNSUpdate(char * pszServerName,const char * pszDomainName,const char * pszHostName,const struct sockaddr_storage * sslist,size_t num_addrs,uint32_t flags,bool remove_host)32 DNS_ERROR DoDNSUpdate(char *pszServerName,
33 		      const char *pszDomainName, const char *pszHostName,
34 		      const struct sockaddr_storage *sslist, size_t num_addrs,
35 		      uint32_t flags, bool remove_host)
36 {
37 	DNS_ERROR err;
38 	struct dns_connection *conn;
39 	TALLOC_CTX *mem_ctx;
40 	OM_uint32 minor;
41 	struct dns_update_request *req, *resp;
42 
43 	DEBUG(10,("DoDNSUpdate called with flags: 0x%08x\n", flags));
44 
45 	if (!(flags & DNS_UPDATE_SIGNED) &&
46 	    !(flags & DNS_UPDATE_UNSIGNED) &&
47 	    !(flags & DNS_UPDATE_PROBE)) {
48 		return ERROR_DNS_INVALID_PARAMETER;
49 	}
50 
51 	if ( !remove_host && ((num_addrs <= 0) || !sslist) ) {
52 		return ERROR_DNS_INVALID_PARAMETER;
53 	}
54 
55 	if (!(mem_ctx = talloc_init("DoDNSUpdate"))) {
56 		return ERROR_DNS_NO_MEMORY;
57 	}
58 
59 	err = dns_open_connection( pszServerName, DNS_TCP, mem_ctx, &conn );
60 	if (!ERR_DNS_IS_OK(err)) {
61 		goto error;
62 	}
63 
64 	if (flags & DNS_UPDATE_PROBE) {
65 
66 		/*
67 		 * Probe if everything's fine
68 		 */
69 
70 		err = dns_create_probe(mem_ctx, pszDomainName, pszHostName,
71 				       num_addrs, sslist, &req);
72 		if (!ERR_DNS_IS_OK(err)) goto error;
73 
74 		err = dns_update_transaction(mem_ctx, conn, req, &resp);
75 
76 		if (!ERR_DNS_IS_OK(err)) {
77 			DEBUG(3,("DoDNSUpdate: failed to probe DNS\n"));
78 			goto error;
79 		}
80 
81 		if ((dns_response_code(resp->flags) == DNS_NO_ERROR) &&
82 		    (flags & DNS_UPDATE_PROBE_SUFFICIENT)) {
83 			TALLOC_FREE(mem_ctx);
84 			return ERROR_DNS_SUCCESS;
85 		}
86 	}
87 
88 	if (flags & DNS_UPDATE_UNSIGNED) {
89 
90 		/*
91 		 * First try without signing
92 		 */
93 
94 		err = dns_create_update_request(mem_ctx, pszDomainName, pszHostName,
95 						sslist, num_addrs, &req);
96 		if (!ERR_DNS_IS_OK(err)) goto error;
97 
98 		err = dns_update_transaction(mem_ctx, conn, req, &resp);
99 		if (!ERR_DNS_IS_OK(err)) {
100 			DEBUG(3,("DoDNSUpdate: unsigned update failed\n"));
101 			goto error;
102 		}
103 
104 		if ((dns_response_code(resp->flags) == DNS_NO_ERROR) &&
105 		    (flags & DNS_UPDATE_UNSIGNED_SUFFICIENT)) {
106 			TALLOC_FREE(mem_ctx);
107 			return ERROR_DNS_SUCCESS;
108 		}
109 	}
110 
111 	/*
112 	 * Okay, we have to try with signing
113 	 */
114 	if (flags & DNS_UPDATE_SIGNED) {
115 		gss_ctx_id_t gss_context;
116 		char *keyname;
117 
118 		err = dns_create_update_request(mem_ctx, pszDomainName, pszHostName,
119 						sslist, num_addrs, &req);
120 		if (!ERR_DNS_IS_OK(err)) goto error;
121 
122 		if (!(keyname = dns_generate_keyname( mem_ctx ))) {
123 			err = ERROR_DNS_NO_MEMORY;
124 			goto error;
125 		}
126 
127 		err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
128 					     keyname, &gss_context, DNS_SRV_ANY );
129 
130 		/* retry using the Windows 2000 DNS hack */
131 		if (!ERR_DNS_IS_OK(err)) {
132 			err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
133 						     keyname, &gss_context,
134 						     DNS_SRV_WIN2000 );
135 		}
136 
137 		if (!ERR_DNS_IS_OK(err))
138 			goto error;
139 
140 		err = dns_sign_update(req, gss_context, keyname,
141 				      "gss.microsoft.com", time(NULL), 3600);
142 
143 		gss_delete_sec_context(&minor, &gss_context, GSS_C_NO_BUFFER);
144 
145 		if (!ERR_DNS_IS_OK(err)) goto error;
146 
147 		err = dns_update_transaction(mem_ctx, conn, req, &resp);
148 		if (!ERR_DNS_IS_OK(err)) goto error;
149 
150 		err = (dns_response_code(resp->flags) == DNS_NO_ERROR) ?
151 			ERROR_DNS_SUCCESS : ERROR_DNS_UPDATE_FAILED;
152 
153 		if (!ERR_DNS_IS_OK(err)) {
154 			DEBUG(3,("DoDNSUpdate: signed update failed\n"));
155 		}
156 	}
157 
158 
159 error:
160 	TALLOC_FREE(mem_ctx);
161 	return err;
162 }
163 
164 /*********************************************************************
165 *********************************************************************/
166 
get_my_ip_address(struct sockaddr_storage ** pp_ss)167 int get_my_ip_address( struct sockaddr_storage **pp_ss )
168 
169 {
170 	int i, n;
171 	struct sockaddr_storage *list = NULL;
172 	int count = 0;
173 
174 	/* Honor the configured list of interfaces to register */
175 
176 	load_interfaces();
177 	n = iface_count();
178 
179 	if (n <= 0) {
180 		return -1;
181 	}
182 
183 	if ( (list = SMB_MALLOC_ARRAY( struct sockaddr_storage, n )) == NULL ) {
184 		return -1;
185 	}
186 
187 	for ( i=0; i<n; i++ ) {
188 		const struct sockaddr_storage *nic_sa_storage = NULL;
189 
190 		if ((nic_sa_storage = iface_n_sockaddr_storage(i)) == NULL)
191 			continue;
192 
193 		/* Don't register loopback addresses */
194 		if (is_loopback_addr((const struct sockaddr *)nic_sa_storage)) {
195 			continue;
196 		}
197 
198 		/* Don't register link-local addresses */
199 		if (is_linklocal_addr(nic_sa_storage)) {
200 			continue;
201 		}
202 
203 		memcpy(&list[count++], nic_sa_storage, sizeof(struct sockaddr_storage));
204 	}
205 	*pp_ss = list;
206 
207 	return count;
208 }
209 
do_gethostbyname(const char * server,const char * host)210 DNS_ERROR do_gethostbyname(const char *server, const char *host)
211 {
212 	struct dns_connection *conn = NULL;
213 	struct dns_request *req, *resp;
214 	DNS_ERROR err;
215 	int ans = 0;
216 
217 	err = dns_open_connection(server, DNS_UDP, NULL, &conn);
218 	if (!ERR_DNS_IS_OK(err)) {
219 		goto error;
220 	}
221 
222 	err = dns_create_query(conn, host, QTYPE_A, DNS_CLASS_IN, &req);
223 	if (!ERR_DNS_IS_OK(err)) {
224 		goto error;
225 	}
226 
227 	err = dns_transaction(conn, conn, req, &resp);
228 	if (!ERR_DNS_IS_OK(err)) {
229 		goto error;
230 	}
231 
232 	if (resp->num_answers == 0) {
233 		printf("%s", "No answers!\n");
234 		goto error;
235 	}
236 
237 	for (ans = 0; ans < resp->num_answers; ans++) {
238 		struct in_addr resp_ip;
239 
240 		if (ans > 0)
241 			printf("%s", " ");
242 
243 		resp_ip.s_addr = *((uint32_t *)resp->answers[ans]->data);
244 		printf("%s", inet_ntoa(resp_ip));
245 	}
246 
247 	printf("%s", "\n");
248 
249  error:
250 	TALLOC_FREE(conn);
251 	return err;
252 }
253 
254 #endif	/* defined(WITH_DNS_UPDATES) */
255