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