s3:utils: Fix auth callback with smburl
[samba.git] / source3 / utils / net_dns.c
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(HAVE_KRB5)
28
29 /*********************************************************************
30 *********************************************************************/
31
32 DNS_ERROR DoDNSUpdate(char *pszServerName,
33                       const char *pszDomainName,
34                       const char *pszHostName,
35                       const struct sockaddr_storage *sslist,
36                       size_t num_addrs,
37                       uint32_t flags,
38                       uint32_t ttl,
39                       bool remove_host)
40 {
41         DNS_ERROR err;
42         struct dns_connection *conn;
43         TALLOC_CTX *mem_ctx;
44         OM_uint32 minor;
45         struct dns_update_request *req, *resp;
46
47         DEBUG(10,("DoDNSUpdate called with flags: 0x%08x\n", flags));
48
49         if (!(flags & DNS_UPDATE_SIGNED) &&
50             !(flags & DNS_UPDATE_UNSIGNED) &&
51             !(flags & DNS_UPDATE_PROBE)) {
52                 return ERROR_DNS_INVALID_PARAMETER;
53         }
54
55         if ( !remove_host && ((num_addrs <= 0) || !sslist) ) {
56                 return ERROR_DNS_INVALID_PARAMETER;
57         }
58
59         if (!(mem_ctx = talloc_init("DoDNSUpdate"))) {
60                 return ERROR_DNS_NO_MEMORY;
61         }
62
63         err = dns_open_connection( pszServerName, DNS_TCP, mem_ctx, &conn );
64         if (!ERR_DNS_IS_OK(err)) {
65                 goto error;
66         }
67
68         if (flags & DNS_UPDATE_PROBE) {
69
70                 /*
71                  * Probe if everything's fine
72                  */
73
74                 err = dns_create_probe(mem_ctx, pszDomainName, pszHostName,
75                                        num_addrs, sslist, &req);
76                 if (!ERR_DNS_IS_OK(err)) goto error;
77
78                 err = dns_update_transaction(mem_ctx, conn, req, &resp);
79
80                 if (!ERR_DNS_IS_OK(err)) {
81                         DEBUG(3,("DoDNSUpdate: failed to probe DNS\n"));
82                         goto error;
83                 }
84
85                 if ((dns_response_code(resp->flags) == DNS_NO_ERROR) &&
86                     (flags & DNS_UPDATE_PROBE_SUFFICIENT)) {
87                         TALLOC_FREE(mem_ctx);
88                         return ERROR_DNS_SUCCESS;
89                 }
90         }
91
92         if (flags & DNS_UPDATE_UNSIGNED) {
93
94                 /*
95                  * First try without signing
96                  */
97
98                 err = dns_create_update_request(mem_ctx,
99                                                 pszDomainName,
100                                                 pszHostName,
101                                                 sslist,
102                                                 num_addrs,
103                                                 ttl,
104                                                 &req);
105                 if (!ERR_DNS_IS_OK(err)) goto error;
106
107                 err = dns_update_transaction(mem_ctx, conn, req, &resp);
108                 if (!ERR_DNS_IS_OK(err)) {
109                         DEBUG(3,("DoDNSUpdate: unsigned update failed\n"));
110                         goto error;
111                 }
112
113                 if ((dns_response_code(resp->flags) == DNS_NO_ERROR) &&
114                     (flags & DNS_UPDATE_UNSIGNED_SUFFICIENT)) {
115                         TALLOC_FREE(mem_ctx);
116                         return ERROR_DNS_SUCCESS;
117                 }
118         }
119
120         /*
121          * Okay, we have to try with signing
122          */
123         if (flags & DNS_UPDATE_SIGNED) {
124                 gss_ctx_id_t gss_context;
125                 char *keyname;
126
127                 err = dns_create_update_request(mem_ctx,
128                                                 pszDomainName,
129                                                 pszHostName,
130                                                 sslist,
131                                                 num_addrs,
132                                                 ttl,
133                                                 &req);
134                 if (!ERR_DNS_IS_OK(err)) goto error;
135
136                 if (!(keyname = dns_generate_keyname( mem_ctx ))) {
137                         err = ERROR_DNS_NO_MEMORY;
138                         goto error;
139                 }
140
141                 err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
142                                              keyname, &gss_context, DNS_SRV_ANY );
143
144                 /* retry using the Windows 2000 DNS hack */
145                 if (!ERR_DNS_IS_OK(err)) {
146                         err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
147                                                      keyname, &gss_context, 
148                                                      DNS_SRV_WIN2000 );
149                 }
150
151                 if (!ERR_DNS_IS_OK(err))
152                         goto error;
153
154                 err = dns_sign_update(req, gss_context, keyname,
155                                       "gss.microsoft.com", time(NULL), 3600);
156
157                 gss_delete_sec_context(&minor, &gss_context, GSS_C_NO_BUFFER);
158
159                 if (!ERR_DNS_IS_OK(err)) goto error;
160
161                 err = dns_update_transaction(mem_ctx, conn, req, &resp);
162                 if (!ERR_DNS_IS_OK(err)) goto error;
163
164                 err = (dns_response_code(resp->flags) == DNS_NO_ERROR) ?
165                         ERROR_DNS_SUCCESS : ERROR_DNS_UPDATE_FAILED;
166
167                 if (!ERR_DNS_IS_OK(err)) {
168                         DEBUG(3,("DoDNSUpdate: signed update failed\n"));
169                 }
170         }
171
172
173 error:
174         TALLOC_FREE(mem_ctx);
175         return err;
176 }
177
178 /*********************************************************************
179 *********************************************************************/
180
181 int get_my_ip_address( struct sockaddr_storage **pp_ss )
182
183 {
184         int i, n;
185         struct sockaddr_storage *list = NULL;
186         int count = 0;
187
188         /* Honor the configured list of interfaces to register */
189
190         load_interfaces();
191         n = iface_count();
192
193         if (n <= 0) {
194                 return -1;
195         }
196
197         if ( (list = SMB_MALLOC_ARRAY( struct sockaddr_storage, n )) == NULL ) {
198                 return -1;
199         }
200
201         for ( i=0; i<n; i++ ) {
202                 const struct sockaddr_storage *nic_sa_storage = NULL;
203
204                 if ((nic_sa_storage = iface_n_sockaddr_storage(i)) == NULL)
205                         continue;
206
207                 /* Don't register loopback addresses */
208                 if (is_loopback_addr((const struct sockaddr *)nic_sa_storage)) {
209                         continue;
210                 }
211
212                 /* Don't register link-local addresses */
213                 if (is_linklocal_addr(nic_sa_storage)) {
214                         continue;
215                 }
216
217                 memcpy(&list[count++], nic_sa_storage, sizeof(struct sockaddr_storage));
218         }
219         *pp_ss = list;
220
221         return count;
222 }
223
224 #endif  /* defined(HAVE_KRB5) */