Line data Source code
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 : #include "auth/gensec/gensec.h"
27 : #include "auth_generic.h"
28 :
29 : #if defined(HAVE_KRB5)
30 :
31 : /*********************************************************************
32 : *********************************************************************/
33 :
34 65 : static DNS_ERROR DoDNSUpdateNegotiateGensec(const char *pszServerName,
35 : const char *pszDomainName,
36 : const char *keyname,
37 : enum dns_ServerType srv_type,
38 : struct cli_credentials *creds,
39 : TALLOC_CTX *mem_ctx,
40 : struct gensec_security **_gensec)
41 : {
42 65 : TALLOC_CTX *frame = talloc_stackframe();
43 65 : struct auth_generic_state *ans = NULL;
44 0 : NTSTATUS status;
45 0 : DNS_ERROR err;
46 :
47 65 : status = auth_generic_client_prepare(mem_ctx, &ans);
48 65 : if (!NT_STATUS_IS_OK(status)) {
49 0 : err = ERROR_DNS_GSS_ERROR;
50 0 : goto error;
51 : }
52 65 : talloc_steal(frame, ans);
53 :
54 65 : status = auth_generic_set_creds(ans, creds);
55 65 : if (!NT_STATUS_IS_OK(status)) {
56 0 : err = ERROR_DNS_GSS_ERROR;
57 0 : goto error;
58 : }
59 :
60 65 : status = gensec_set_target_service(ans->gensec_security,
61 : "dns");
62 65 : if (!NT_STATUS_IS_OK(status)) {
63 0 : err = ERROR_DNS_GSS_ERROR;
64 0 : goto error;
65 : }
66 :
67 65 : status = gensec_set_target_hostname(ans->gensec_security,
68 : pszServerName);
69 65 : if (!NT_STATUS_IS_OK(status)) {
70 0 : err = ERROR_DNS_GSS_ERROR;
71 0 : goto error;
72 : }
73 :
74 65 : gensec_want_feature(ans->gensec_security, GENSEC_FEATURE_SIGN);
75 :
76 65 : status = auth_generic_client_start(ans, GENSEC_OID_KERBEROS5);
77 65 : if (!NT_STATUS_IS_OK(status)) {
78 0 : err = ERROR_DNS_GSS_ERROR;
79 0 : goto error;
80 : }
81 :
82 65 : err = dns_negotiate_sec_ctx(pszServerName,
83 : keyname,
84 65 : ans->gensec_security,
85 : srv_type);
86 65 : if (!ERR_DNS_IS_OK(err)) {
87 0 : goto error;
88 : }
89 :
90 65 : *_gensec = talloc_move(mem_ctx, &ans->gensec_security);
91 65 : error:
92 65 : TALLOC_FREE(frame);
93 :
94 65 : return err;
95 : }
96 :
97 68 : DNS_ERROR DoDNSUpdate(char *pszServerName,
98 : const char *pszDomainName,
99 : const char *pszHostName,
100 : struct cli_credentials *creds,
101 : const struct sockaddr_storage *sslist,
102 : size_t num_addrs,
103 : uint32_t flags,
104 : uint32_t ttl,
105 : bool remove_host)
106 : {
107 0 : DNS_ERROR err;
108 0 : struct dns_connection *conn;
109 0 : TALLOC_CTX *mem_ctx;
110 0 : struct dns_update_request *req, *resp;
111 :
112 68 : DEBUG(10,("DoDNSUpdate called with flags: 0x%08x\n", flags));
113 :
114 68 : if (!(flags & DNS_UPDATE_SIGNED) &&
115 0 : !(flags & DNS_UPDATE_UNSIGNED) &&
116 0 : !(flags & DNS_UPDATE_PROBE)) {
117 0 : return ERROR_DNS_INVALID_PARAMETER;
118 : }
119 :
120 68 : if ( !remove_host && ((num_addrs <= 0) || !sslist) ) {
121 0 : return ERROR_DNS_INVALID_PARAMETER;
122 : }
123 :
124 68 : if (!(mem_ctx = talloc_init("DoDNSUpdate"))) {
125 0 : return ERROR_DNS_NO_MEMORY;
126 : }
127 :
128 68 : err = dns_open_connection( pszServerName, DNS_TCP, mem_ctx, &conn );
129 68 : if (!ERR_DNS_IS_OK(err)) {
130 0 : goto error;
131 : }
132 :
133 68 : if (flags & DNS_UPDATE_PROBE) {
134 :
135 : /*
136 : * Probe if everything's fine
137 : */
138 :
139 68 : err = dns_create_probe(mem_ctx, pszDomainName, pszHostName,
140 : num_addrs, sslist, &req);
141 68 : if (!ERR_DNS_IS_OK(err)) goto error;
142 :
143 65 : err = dns_update_transaction(mem_ctx, conn, req, &resp);
144 :
145 65 : if (!ERR_DNS_IS_OK(err)) {
146 0 : DEBUG(3,("DoDNSUpdate: failed to probe DNS\n"));
147 0 : goto error;
148 : }
149 :
150 65 : if ((dns_response_code(resp->flags) == DNS_NO_ERROR) &&
151 0 : (flags & DNS_UPDATE_PROBE_SUFFICIENT)) {
152 0 : TALLOC_FREE(mem_ctx);
153 0 : return ERROR_DNS_SUCCESS;
154 : }
155 : }
156 :
157 65 : if (flags & DNS_UPDATE_UNSIGNED) {
158 :
159 : /*
160 : * First try without signing
161 : */
162 :
163 65 : err = dns_create_update_request(mem_ctx,
164 : pszDomainName,
165 : pszHostName,
166 : sslist,
167 : num_addrs,
168 : ttl,
169 : &req);
170 65 : if (!ERR_DNS_IS_OK(err)) goto error;
171 :
172 65 : err = dns_update_transaction(mem_ctx, conn, req, &resp);
173 65 : if (!ERR_DNS_IS_OK(err)) {
174 0 : DEBUG(3,("DoDNSUpdate: unsigned update failed\n"));
175 0 : goto error;
176 : }
177 :
178 65 : if ((dns_response_code(resp->flags) == DNS_NO_ERROR) &&
179 0 : (flags & DNS_UPDATE_UNSIGNED_SUFFICIENT)) {
180 0 : TALLOC_FREE(mem_ctx);
181 0 : return ERROR_DNS_SUCCESS;
182 : }
183 : }
184 :
185 : /*
186 : * Okay, we have to try with signing
187 : */
188 65 : if (flags & DNS_UPDATE_SIGNED) {
189 65 : struct gensec_security *gensec = NULL;
190 65 : char *keyname = NULL;
191 :
192 65 : err = dns_create_update_request(mem_ctx,
193 : pszDomainName,
194 : pszHostName,
195 : sslist,
196 : num_addrs,
197 : ttl,
198 : &req);
199 65 : if (!ERR_DNS_IS_OK(err)) goto error;
200 :
201 65 : if (!(keyname = dns_generate_keyname( mem_ctx ))) {
202 0 : err = ERROR_DNS_NO_MEMORY;
203 0 : goto error;
204 : }
205 :
206 65 : err = DoDNSUpdateNegotiateGensec(pszServerName,
207 : pszDomainName,
208 : keyname,
209 : DNS_SRV_ANY,
210 : creds,
211 : mem_ctx,
212 : &gensec);
213 :
214 : /* retry using the Windows 2000 DNS hack */
215 65 : if (!ERR_DNS_IS_OK(err)) {
216 0 : err = DoDNSUpdateNegotiateGensec(pszServerName,
217 : pszDomainName,
218 : keyname,
219 : DNS_SRV_WIN2000,
220 : creds,
221 : mem_ctx,
222 : &gensec);
223 : }
224 :
225 65 : if (!ERR_DNS_IS_OK(err))
226 0 : goto error;
227 :
228 65 : err = dns_sign_update(req, gensec, keyname,
229 : "gss.microsoft.com", time(NULL), 3600);
230 :
231 65 : if (!ERR_DNS_IS_OK(err)) goto error;
232 :
233 65 : err = dns_update_transaction(mem_ctx, conn, req, &resp);
234 65 : if (!ERR_DNS_IS_OK(err)) goto error;
235 :
236 97 : err = (dns_response_code(resp->flags) == DNS_NO_ERROR) ?
237 32 : ERROR_DNS_SUCCESS : ERROR_DNS_UPDATE_FAILED;
238 :
239 65 : if (!ERR_DNS_IS_OK(err)) {
240 20 : DEBUG(3,("DoDNSUpdate: signed update failed\n"));
241 : }
242 : }
243 :
244 :
245 0 : error:
246 68 : TALLOC_FREE(mem_ctx);
247 68 : return err;
248 : }
249 :
250 : /*********************************************************************
251 : *********************************************************************/
252 :
253 48 : int get_my_ip_address( struct sockaddr_storage **pp_ss )
254 :
255 : {
256 0 : int i, n;
257 48 : struct sockaddr_storage *list = NULL;
258 48 : int count = 0;
259 :
260 : /* Honor the configured list of interfaces to register */
261 :
262 48 : load_interfaces();
263 48 : n = iface_count();
264 :
265 48 : if (n <= 0) {
266 0 : return -1;
267 : }
268 :
269 48 : if ( (list = SMB_MALLOC_ARRAY( struct sockaddr_storage, n )) == NULL ) {
270 0 : return -1;
271 : }
272 :
273 274 : for ( i=0; i<n; i++ ) {
274 226 : const struct sockaddr_storage *nic_sa_storage = NULL;
275 :
276 226 : if ((nic_sa_storage = iface_n_sockaddr_storage(i)) == NULL)
277 0 : continue;
278 :
279 : /* Don't register loopback addresses */
280 226 : if (is_loopback_addr((const struct sockaddr *)nic_sa_storage)) {
281 0 : continue;
282 : }
283 :
284 : /* Don't register link-local addresses */
285 226 : if (is_linklocal_addr(nic_sa_storage)) {
286 0 : continue;
287 : }
288 :
289 226 : memcpy(&list[count++], nic_sa_storage, sizeof(struct sockaddr_storage));
290 : }
291 48 : *pp_ss = list;
292 :
293 48 : return count;
294 : }
295 :
296 : #endif /* defined(HAVE_KRB5) */
|