2 Samba Unix/Linux Dynamic DNS Update
5 Copyright (C) Krishna Ganugapati (krishnag@centeris.com) 2006
6 Copyright (C) Gerald Carter 2006
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.
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.
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/>.
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"
29 #if defined(HAVE_KRB5)
31 /*********************************************************************
32 *********************************************************************/
34 static DNS_ERROR
DoDNSUpdateNegotiateGensec(const char *pszServerName
,
35 const char *pszDomainName
,
37 enum dns_ServerType srv_type
,
38 struct cli_credentials
*creds
,
40 struct gensec_security
**_gensec
)
42 TALLOC_CTX
*frame
= talloc_stackframe();
43 struct auth_generic_state
*ans
= NULL
;
47 status
= auth_generic_client_prepare(mem_ctx
, &ans
);
48 if (!NT_STATUS_IS_OK(status
)) {
49 err
= ERROR_DNS_GSS_ERROR
;
52 talloc_steal(frame
, ans
);
54 status
= auth_generic_set_creds(ans
, creds
);
55 if (!NT_STATUS_IS_OK(status
)) {
56 err
= ERROR_DNS_GSS_ERROR
;
60 status
= gensec_set_target_service(ans
->gensec_security
,
62 if (!NT_STATUS_IS_OK(status
)) {
63 err
= ERROR_DNS_GSS_ERROR
;
67 status
= gensec_set_target_hostname(ans
->gensec_security
,
69 if (!NT_STATUS_IS_OK(status
)) {
70 err
= ERROR_DNS_GSS_ERROR
;
74 gensec_want_feature(ans
->gensec_security
, GENSEC_FEATURE_SIGN
);
76 status
= auth_generic_client_start(ans
, GENSEC_OID_KERBEROS5
);
77 if (!NT_STATUS_IS_OK(status
)) {
78 err
= ERROR_DNS_GSS_ERROR
;
82 err
= dns_negotiate_sec_ctx(pszServerName
,
86 if (!ERR_DNS_IS_OK(err
)) {
90 *_gensec
= talloc_move(mem_ctx
, &ans
->gensec_security
);
97 DNS_ERROR
DoDNSUpdate(char *pszServerName
,
98 const char *pszDomainName
,
99 const char *pszHostName
,
100 struct cli_credentials
*creds
,
101 const struct sockaddr_storage
*sslist
,
108 struct dns_connection
*conn
;
110 struct dns_update_request
*req
, *resp
;
112 DEBUG(10,("DoDNSUpdate called with flags: 0x%08x\n", flags
));
114 if (!(flags
& DNS_UPDATE_SIGNED
) &&
115 !(flags
& DNS_UPDATE_UNSIGNED
) &&
116 !(flags
& DNS_UPDATE_PROBE
)) {
117 return ERROR_DNS_INVALID_PARAMETER
;
120 if ( !remove_host
&& ((num_addrs
<= 0) || !sslist
) ) {
121 return ERROR_DNS_INVALID_PARAMETER
;
124 if (!(mem_ctx
= talloc_init("DoDNSUpdate"))) {
125 return ERROR_DNS_NO_MEMORY
;
128 err
= dns_open_connection( pszServerName
, DNS_TCP
, mem_ctx
, &conn
);
129 if (!ERR_DNS_IS_OK(err
)) {
133 if (flags
& DNS_UPDATE_PROBE
) {
136 * Probe if everything's fine
139 err
= dns_create_probe(mem_ctx
, pszDomainName
, pszHostName
,
140 num_addrs
, sslist
, &req
);
141 if (!ERR_DNS_IS_OK(err
)) goto error
;
143 err
= dns_update_transaction(mem_ctx
, conn
, req
, &resp
);
145 if (!ERR_DNS_IS_OK(err
)) {
146 DEBUG(3,("DoDNSUpdate: failed to probe DNS\n"));
150 if ((dns_response_code(resp
->flags
) == DNS_NO_ERROR
) &&
151 (flags
& DNS_UPDATE_PROBE_SUFFICIENT
)) {
152 TALLOC_FREE(mem_ctx
);
153 return ERROR_DNS_SUCCESS
;
157 if (flags
& DNS_UPDATE_UNSIGNED
) {
160 * First try without signing
163 err
= dns_create_update_request(mem_ctx
,
170 if (!ERR_DNS_IS_OK(err
)) goto error
;
172 err
= dns_update_transaction(mem_ctx
, conn
, req
, &resp
);
173 if (!ERR_DNS_IS_OK(err
)) {
174 DEBUG(3,("DoDNSUpdate: unsigned update failed\n"));
178 if ((dns_response_code(resp
->flags
) == DNS_NO_ERROR
) &&
179 (flags
& DNS_UPDATE_UNSIGNED_SUFFICIENT
)) {
180 TALLOC_FREE(mem_ctx
);
181 return ERROR_DNS_SUCCESS
;
186 * Okay, we have to try with signing
188 if (flags
& DNS_UPDATE_SIGNED
) {
189 struct gensec_security
*gensec
= NULL
;
190 char *keyname
= NULL
;
192 err
= dns_create_update_request(mem_ctx
,
199 if (!ERR_DNS_IS_OK(err
)) goto error
;
201 if (!(keyname
= dns_generate_keyname( mem_ctx
))) {
202 err
= ERROR_DNS_NO_MEMORY
;
206 err
= DoDNSUpdateNegotiateGensec(pszServerName
,
214 /* retry using the Windows 2000 DNS hack */
215 if (!ERR_DNS_IS_OK(err
)) {
216 err
= DoDNSUpdateNegotiateGensec(pszServerName
,
225 if (!ERR_DNS_IS_OK(err
))
228 err
= dns_sign_update(req
, gensec
, keyname
,
229 "gss.microsoft.com", time(NULL
), 3600);
231 if (!ERR_DNS_IS_OK(err
)) goto error
;
233 err
= dns_update_transaction(mem_ctx
, conn
, req
, &resp
);
234 if (!ERR_DNS_IS_OK(err
)) goto error
;
236 err
= (dns_response_code(resp
->flags
) == DNS_NO_ERROR
) ?
237 ERROR_DNS_SUCCESS
: ERROR_DNS_UPDATE_FAILED
;
239 if (!ERR_DNS_IS_OK(err
)) {
240 DEBUG(3,("DoDNSUpdate: signed update failed\n"));
246 TALLOC_FREE(mem_ctx
);
250 /*********************************************************************
251 *********************************************************************/
253 int get_my_ip_address( struct sockaddr_storage
**pp_ss
)
257 struct sockaddr_storage
*list
= NULL
;
260 /* Honor the configured list of interfaces to register */
269 if ( (list
= SMB_MALLOC_ARRAY( struct sockaddr_storage
, n
)) == NULL
) {
273 for ( i
=0; i
<n
; i
++ ) {
274 const struct sockaddr_storage
*nic_sa_storage
= NULL
;
276 if ((nic_sa_storage
= iface_n_sockaddr_storage(i
)) == NULL
)
279 /* Don't register loopback addresses */
280 if (is_loopback_addr((const struct sockaddr
*)nic_sa_storage
)) {
284 /* Don't register link-local addresses */
285 if (is_linklocal_addr(nic_sa_storage
)) {
289 memcpy(&list
[count
++], nic_sa_storage
, sizeof(struct sockaddr_storage
));
296 #endif /* defined(HAVE_KRB5) */