r18534: Fix grammar
[Samba.git] / source / libaddns / dnsupdate.c
blob124b627707cb7f04c956820ab2d08c1482edea22
1 /*
2 Public Interface file for Linux DNS client library implementation
4 Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
5 Copyright (C) 2006 Gerald Carter <jerry@samba.org>
7 ** NOTE! The following LGPL license applies to the libaddns
8 ** library. This does NOT imply that all of Samba is released
9 ** under the LGPL
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 02110-1301 USA
27 #include "dns.h"
29 /********************************************************************
30 ********************************************************************/
32 static int32 DNSSendUpdate1( HANDLE hDNSServer, const char *szDomainName,
33 char *szHost, struct in_addr *iplist,
34 int num_ips,
35 DNS_UPDATE_RESPONSE * *ppDNSUpdateResponse )
37 int32 dwError = 0;
38 DNS_UPDATE_REQUEST *pDNSUpdateRequest = NULL;
39 DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL;
40 DNS_ZONE_RECORD *pDNSZoneRecord = NULL;
41 DNS_RR_RECORD *pDNSPRRecord = NULL;
42 int i;
44 dwError = DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest );
45 BAIL_ON_ERROR( dwError );
47 dwError = DNSCreateZoneRecord( szDomainName, &pDNSZoneRecord );
48 BAIL_ON_ERROR( dwError );
50 dwError =
51 DNSUpdateAddZoneSection( pDNSUpdateRequest, pDNSZoneRecord );
52 BAIL_ON_ERROR( dwError );
54 /* Add the CNAME not in user record */
56 pDNSPRRecord = NULL;
57 dwError =
58 DNSCreateNameNotInUseRecord( szHost, QTYPE_CNAME,
59 &pDNSPRRecord );
60 BAIL_ON_ERROR( dwError );
62 dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord );
63 BAIL_ON_ERROR( dwError );
65 /* Add a Prerequisite for each IP address to see if everything is already setup */
67 for ( i = 0; i < num_ips; i++ ) {
68 DNS_RR_RECORD *pDNSPrereq = NULL;
70 dwError =
71 DNSCreateNameInUseRecord( szHost, QTYPE_A, &iplist[i],
72 &pDNSPrereq );
73 BAIL_ON_ERROR( dwError );
75 dwError =
76 DNSUpdateAddPRSection( pDNSUpdateRequest,
77 pDNSPrereq );
78 BAIL_ON_ERROR( dwError );
81 dwError =
82 DNSUpdateSendUpdateRequest2( hDNSServer, pDNSUpdateRequest );
83 BAIL_ON_ERROR( dwError );
85 dwError =
86 DNSUpdateReceiveUpdateResponse( hDNSServer,
87 &pDNSUpdateResponse );
88 BAIL_ON_ERROR( dwError );
90 *ppDNSUpdateResponse = pDNSUpdateResponse;
92 return dwError;
94 error:
96 if ( pDNSZoneRecord ) {
97 DNSFreeZoneRecord( pDNSZoneRecord );
100 if ( pDNSUpdateRequest ) {
101 DNSUpdateFreeRequest( pDNSUpdateRequest );
104 *ppDNSUpdateResponse = NULL;
105 return dwError;
108 /********************************************************************
109 ********************************************************************/
111 static int32 DNSSendUpdate2( HANDLE hDNSServer, const char *szDomainName,
112 char *szHost, struct in_addr *iplist,
113 int num_ips,
114 DNS_UPDATE_RESPONSE * *ppDNSUpdateResponse )
116 int32 dwError = 0;
117 DNS_UPDATE_REQUEST *pDNSUpdateRequest = NULL;
118 DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL;
119 DNS_ZONE_RECORD *pDNSZoneRecord = NULL;
120 DNS_RR_RECORD *pDNSPRRecord = NULL;
121 int i;
123 dwError = DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest );
124 BAIL_ON_ERROR( dwError );
126 dwError = DNSCreateZoneRecord( szDomainName, &pDNSZoneRecord );
127 BAIL_ON_ERROR( dwError );
129 dwError =
130 DNSUpdateAddZoneSection( pDNSUpdateRequest, pDNSZoneRecord );
131 BAIL_ON_ERROR( dwError );
133 /* Add the CNAME not in user record */
135 pDNSPRRecord = NULL;
136 dwError =
137 DNSCreateNameNotInUseRecord( szHost, QTYPE_CNAME,
138 &pDNSPRRecord );
139 BAIL_ON_ERROR( dwError );
141 dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord );
142 BAIL_ON_ERROR( dwError );
144 /* Add the IN not in user record */
146 pDNSPRRecord = NULL;
147 dwError =
148 DNSCreateNameNotInUseRecord( szHost, QTYPE_A, &pDNSPRRecord );
149 BAIL_ON_ERROR( dwError );
151 dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord );
152 BAIL_ON_ERROR( dwError );
155 for ( i = 0; i < num_ips; i++ ) {
156 DNS_RR_RECORD *pDNSRRAddRecord = NULL;
158 dwError =
159 DNSCreateARecord( szHost, DNS_CLASS_IN, QTYPE_A,
160 ntohl( iplist[i].s_addr ),
161 &pDNSRRAddRecord );
162 BAIL_ON_ERROR( dwError );
164 dwError =
165 DNSUpdateAddUpdateSection( pDNSUpdateRequest,
166 pDNSRRAddRecord );
167 BAIL_ON_ERROR( dwError );
170 dwError =
171 DNSUpdateSendUpdateRequest2( hDNSServer, pDNSUpdateRequest );
172 BAIL_ON_ERROR( dwError );
174 dwError =
175 DNSUpdateReceiveUpdateResponse( hDNSServer,
176 &pDNSUpdateResponse );
177 BAIL_ON_ERROR( dwError );
179 *ppDNSUpdateResponse = pDNSUpdateResponse;
181 return dwError;
183 error:
185 if ( pDNSZoneRecord ) {
186 DNSFreeZoneRecord( pDNSZoneRecord );
189 if ( pDNSUpdateRequest ) {
190 DNSUpdateFreeRequest( pDNSUpdateRequest );
193 *ppDNSUpdateResponse = NULL;
194 return dwError;
197 /********************************************************************
198 ********************************************************************/
200 static int32 DNSSendUpdate3( HANDLE hDNSServer, const char *szDomainName,
201 char *szHost, struct in_addr *iplist,
202 int num_ips,
203 DNS_UPDATE_RESPONSE * *ppDNSUpdateResponse )
205 int32 dwError = 0;
206 DNS_UPDATE_REQUEST *pDNSUpdateRequest = NULL;
207 DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL;
208 DNS_ZONE_RECORD *pDNSZoneRecord = NULL;
209 DNS_RR_RECORD *pDNSPRRecord = NULL;
210 int i;
211 DNS_RR_RECORD *pDNSRRAddRecord = NULL;
213 dwError = DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest );
214 BAIL_ON_ERROR( dwError );
216 dwError = DNSCreateZoneRecord( szDomainName, &pDNSZoneRecord );
217 BAIL_ON_ERROR( dwError );
219 dwError =
220 DNSUpdateAddZoneSection( pDNSUpdateRequest, pDNSZoneRecord );
221 BAIL_ON_ERROR( dwError );
223 /* Add the CNAME not in user record */
225 dwError =
226 DNSCreateNameNotInUseRecord( szHost, QTYPE_CNAME,
227 &pDNSPRRecord );
228 BAIL_ON_ERROR( dwError );
230 dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord );
231 BAIL_ON_ERROR( dwError );
233 /* Delete any existing A records */
235 dwError =
236 DNSCreateARecord( szHost, DNS_CLASS_ANY, QTYPE_A, 0,
237 &pDNSRRAddRecord );
238 BAIL_ON_ERROR( dwError );
240 dwError =
241 DNSUpdateAddUpdateSection( pDNSUpdateRequest,
242 pDNSRRAddRecord );
243 BAIL_ON_ERROR( dwError );
246 for ( i = 0; i < num_ips; i++ ) {
248 dwError =
249 DNSCreateARecord( szHost, DNS_CLASS_IN, QTYPE_A,
250 ntohl( iplist[i].s_addr ),
251 &pDNSRRAddRecord );
252 BAIL_ON_ERROR( dwError );
254 dwError =
255 DNSUpdateAddUpdateSection( pDNSUpdateRequest,
256 pDNSRRAddRecord );
257 BAIL_ON_ERROR( dwError );
260 dwError =
261 DNSUpdateSendUpdateRequest2( hDNSServer, pDNSUpdateRequest );
262 BAIL_ON_ERROR( dwError );
264 dwError =
265 DNSUpdateReceiveUpdateResponse( hDNSServer,
266 &pDNSUpdateResponse );
267 BAIL_ON_ERROR( dwError );
269 *ppDNSUpdateResponse = pDNSUpdateResponse;
271 return dwError;
273 error:
275 if ( pDNSZoneRecord ) {
276 DNSFreeZoneRecord( pDNSZoneRecord );
279 if ( pDNSUpdateRequest ) {
280 DNSUpdateFreeRequest( pDNSUpdateRequest );
283 *ppDNSUpdateResponse = NULL;
285 return dwError;
288 /********************************************************************
289 ********************************************************************/
291 int32 DNSSendUpdate( HANDLE hDNSServer, const char *szDomainName, char *szHost,
292 struct in_addr * iplist, int num_ips,
293 DNS_UPDATE_RESPONSE * *ppDNSUpdateResponse )
295 int32 dwError = 0;
296 int32 dwResponseCode = 0;
297 DNS_UPDATE_RESPONSE *response = NULL;
299 dwError = DNSSendUpdate1( hDNSServer, szDomainName, szHost,
300 iplist, num_ips, &response );
301 BAIL_ON_ERROR( dwError );
303 dwError = DNSUpdateGetResponseCode( response, &dwResponseCode );
304 BAIL_ON_ERROR( dwError );
306 if ( ( dwResponseCode == DNS_NO_ERROR )
307 || ( dwResponseCode == DNS_REFUSED ) ) {
308 *ppDNSUpdateResponse = response;
309 return dwError;
312 response = NULL;
314 dwError = DNSSendUpdate2( hDNSServer, szDomainName, szHost,
315 iplist, num_ips, &response );
316 BAIL_ON_ERROR( dwError );
318 dwError = DNSUpdateGetResponseCode( response, &dwResponseCode );
319 BAIL_ON_ERROR( dwError );
321 if ( ( dwResponseCode == DNS_NO_ERROR )
322 || ( dwResponseCode == DNS_REFUSED ) ) {
323 *ppDNSUpdateResponse = response;
324 return dwError;
327 response = NULL;
329 dwError = DNSSendUpdate3( hDNSServer, szDomainName, szHost,
330 iplist, num_ips, &response );
332 error:
333 *ppDNSUpdateResponse = response;
335 return dwError;
338 /********************************************************************
339 ********************************************************************/
340 #ifdef HAVE_GSSAPI_SUPPORT
341 int32 DNSSendSecureUpdate( HANDLE hDNSServer,
342 gss_ctx_id_t * pGSSContext,
343 char *pszKeyName,
344 char *szDomainName,
345 char *szHost,
346 int32 dwIP, DNS_UPDATE_RESPONSE ** ppDNSUpdateResponse )
348 int32 dwError = 0;
349 DNS_UPDATE_REQUEST *pDNSUpdateRequest = NULL;
350 DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL;
351 DNS_ZONE_RECORD *pDNSZoneRecord = NULL;
352 DNS_RR_RECORD *pDNSPRRecord = NULL;
353 DNS_RR_RECORD *pDNSARecord = NULL;
356 dwError = DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest );
357 BAIL_ON_ERROR( dwError );
359 dwError = DNSCreateZoneRecord( szDomainName, &pDNSZoneRecord );
360 BAIL_ON_ERROR( dwError );
362 dwError = DNSUpdateAddZoneSection( pDNSUpdateRequest,
363 pDNSZoneRecord );
364 BAIL_ON_ERROR( dwError );
366 dwError = DNSCreateNameInUseRecord( szDomainName,
367 QTYPE_A, NULL, &pDNSPRRecord );
368 BAIL_ON_ERROR( dwError );
370 dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord );
371 BAIL_ON_ERROR( dwError );
373 dwError = DNSCreateDeleteRecord( szHost,
374 DNS_CLASS_ANY,
375 QTYPE_A, &pDNSARecord );
376 BAIL_ON_ERROR( dwError );
378 dwError = DNSUpdateAddUpdateSection( pDNSUpdateRequest, pDNSARecord );
379 BAIL_ON_ERROR( dwError );
381 dwError = DNSCreateARecord( szHost,
382 DNS_CLASS_IN,
383 QTYPE_A, dwIP, &pDNSARecord );
384 BAIL_ON_ERROR( dwError );
386 dwError = DNSUpdateAddUpdateSection( pDNSUpdateRequest, pDNSARecord );
387 BAIL_ON_ERROR( dwError );
389 /* Now Sign the Record */
391 dwError = DNSUpdateGenerateSignature( pGSSContext,
392 pDNSUpdateRequest, pszKeyName );
393 BAIL_ON_ERROR( dwError );
396 dwError =
397 DNSUpdateSendUpdateRequest2( hDNSServer, pDNSUpdateRequest );
398 BAIL_ON_ERROR( dwError );
400 dwError =
401 DNSUpdateReceiveUpdateResponse( hDNSServer,
402 &pDNSUpdateResponse );
403 BAIL_ON_ERROR( dwError );
405 *ppDNSUpdateResponse = pDNSUpdateResponse;
407 return dwError;
409 error:
411 if ( pDNSZoneRecord ) {
412 DNSFreeZoneRecord( pDNSZoneRecord );
415 if ( pDNSUpdateRequest ) {
416 DNSUpdateFreeRequest( pDNSUpdateRequest );
419 *ppDNSUpdateResponse = NULL;
421 return dwError;
425 /*********************************************************************
426 *********************************************************************/
428 int32 DNSUpdateGenerateSignature( gss_ctx_id_t * pGSSContext,
429 DNS_UPDATE_REQUEST * pDNSUpdateRequest,
430 char *pszKeyName )
432 int32 dwError = 0;
433 int32 dwMinorStatus = 0;
434 uint8 *pMessageBuffer = NULL;
435 int32 dwMessageSize = 0;
436 int32 dwMaxSignatureSize = 0;
437 uint8 *pSignature = NULL;
438 int32 dwTimeSigned = 0;
439 int16 wFudge = 0;
440 gss_buffer_desc MsgDesc, MicDesc;
441 DNS_RR_RECORD *pDNSTSIGRecord = NULL;
443 dwError = DNSBuildMessageBuffer( pDNSUpdateRequest,
444 pszKeyName,
445 &dwTimeSigned,
446 &wFudge,
447 &pMessageBuffer, &dwMessageSize );
448 BAIL_ON_ERROR( dwError );
450 dwError = DNSBuildSignatureBuffer( dwMaxSignatureSize, &pSignature );
451 BAIL_ON_ERROR( dwError );
453 MsgDesc.value = pMessageBuffer;
454 MsgDesc.length = dwMessageSize;
456 MicDesc.value = NULL;
457 MicDesc.length = 0;
459 dwError = gss_get_mic( ( OM_uint32 * ) & dwMinorStatus,
460 *pGSSContext, 0, &MsgDesc, &MicDesc );
461 display_status( "gss_init_context", dwError, dwMinorStatus );
462 BAIL_ON_ERROR( dwError );
464 dwError = DNSCreateTSIGRecord( pszKeyName,
465 dwTimeSigned,
466 wFudge,
467 pDNSUpdateRequest->wIdentification,
468 (uint8 *)MicDesc.value,
469 MicDesc.length, &pDNSTSIGRecord );
470 BAIL_ON_ERROR( dwError );
472 dwError = DNSUpdateAddAdditionalSection( pDNSUpdateRequest,
473 pDNSTSIGRecord );
474 BAIL_ON_ERROR( dwError );
477 error:
479 if ( pMessageBuffer ) {
480 DNSFreeMemory( pMessageBuffer );
482 return dwError;
484 if ( pSignature ) {
485 DNSFreeMemory( pSignature );
488 return dwError;
490 #endif /* HAVE_GSSAPI_SUPPORT */
492 /*********************************************************************
493 *********************************************************************/
495 int32 DNSBuildSignatureBuffer( int32 dwMaxSignatureSize, uint8 ** ppSignature )
497 int32 dwError = 0;
498 uint8 *pSignature = NULL;
500 dwError = DNSAllocateMemory( dwMaxSignatureSize,
501 ( void * ) &pSignature );
502 BAIL_ON_ERROR( dwError );
504 *ppSignature = pSignature;
506 return dwError;
508 error:
509 *ppSignature = NULL;
510 return dwError;
513 /*********************************************************************
514 *********************************************************************/
516 int32 DNSBuildMessageBuffer( DNS_UPDATE_REQUEST * pDNSUpdateRequest,
517 char *szKeyName,
518 int32 * pdwTimeSigned,
519 int16 * pwFudge,
520 uint8 ** ppMessageBuffer, int32 * pdwMessageSize )
522 int32 dwError = 0;
523 uint8 *pSrcBuffer = NULL;
524 int32 dwReqMsgSize = 0;
525 int32 dwAlgorithmLen = 0;
526 int32 dwNameLen = 0;
527 uint8 *pMessageBuffer = NULL;
528 int32 dwMessageSize = 0;
529 uint8 *pOffset = NULL;
530 int16 wnError, wError = 0;
531 int16 wnFudge = 0;
532 int16 wFudge = DNS_TEN_HOURS_IN_SECS;
533 int16 wnOtherLen = 0, wOtherLen = 0;
534 int32 dwBytesCopied = 0;
535 int16 wnClass = 0, wClass = DNS_CLASS_ANY;
536 int32 dwnTTL = 0, dwTTL = 0;
537 int32 dwnTimeSigned, dwTimeSigned = 0;
538 HANDLE hSendBuffer = ( HANDLE ) NULL;
539 DNS_DOMAIN_NAME *pDomainName = NULL;
540 DNS_DOMAIN_NAME *pAlgorithmName = NULL;
541 int16 wTimePrefix = 0;
542 int16 wnTimePrefix = 0;
543 char szTsig[9];
545 dwError = DNSDomainNameFromString( szKeyName, &pDomainName );
546 BAIL_ON_ERROR( dwError );
548 dwError = DNSGetDomainNameLength( pDomainName, &dwNameLen );
549 BAIL_ON_ERROR( dwError );
551 strncpy( szTsig, "gss-tsig", sizeof( szTsig ) );
552 dwError = DNSDomainNameFromString( szTsig, &pAlgorithmName );
553 BAIL_ON_ERROR( dwError );
555 dwError = DNSGetDomainNameLength( pAlgorithmName, &dwAlgorithmLen );
556 BAIL_ON_ERROR( dwError );
558 dwError =
559 DNSUpdateBuildRequestMessage( pDNSUpdateRequest,
560 &hSendBuffer );
561 BAIL_ON_ERROR( dwError );
563 dwReqMsgSize = DNSGetSendBufferContextSize( hSendBuffer );
564 dwMessageSize += dwReqMsgSize;
565 dwMessageSize += dwNameLen;
566 dwMessageSize += sizeof( int16 ); /* class */
567 dwMessageSize += sizeof( int32 ); /* TTL */
568 dwMessageSize += dwAlgorithmLen;
569 dwMessageSize += ( sizeof( int16 ) + sizeof( int32 ) ); /* Time Signed */
570 dwMessageSize += sizeof( int16 ); /* Fudge */
571 dwMessageSize += sizeof( int16 ); /* wError */
572 dwMessageSize += sizeof( int16 ); /* Other Len */
573 dwMessageSize += wOtherLen;
575 dwError =
576 DNSAllocateMemory( dwMessageSize,
577 ( void * ) &pMessageBuffer );
578 BAIL_ON_ERROR( dwError );
580 pOffset = pMessageBuffer;
581 pSrcBuffer = DNSGetSendBufferContextBuffer( hSendBuffer );
582 memcpy( pOffset, pSrcBuffer, dwReqMsgSize );
583 pOffset += dwReqMsgSize;
585 dwError =
586 DNSCopyDomainName( pOffset, pAlgorithmName, &dwBytesCopied );
587 BAIL_ON_ERROR( dwError );
588 pOffset += dwBytesCopied;
590 wnClass = htons( wClass );
591 memcpy( pOffset, &wnClass, sizeof( int16 ) );
592 pOffset += sizeof( int16 );
594 dwnTTL = htonl( dwTTL );
595 memcpy( pOffset, &dwnTTL, sizeof( int32 ) );
596 pOffset += sizeof( int32 );
599 wnTimePrefix = htons( wTimePrefix );
600 memcpy( pOffset, &wnTimePrefix, sizeof( int16 ) );
601 pOffset += sizeof( int16 );
604 time_t t;
605 time(&t);
606 dwTimeSigned = t;
608 dwnTimeSigned = htonl( dwTimeSigned );
609 memcpy( pOffset, &dwnTimeSigned, sizeof( int32 ) );
610 pOffset += sizeof( int32 );
612 wnFudge = htons( wFudge );
613 memcpy( pOffset, &wnFudge, sizeof( int16 ) );
614 pOffset += sizeof( int16 );
616 wnError = htons( wError );
617 memcpy( pOffset, &wnError, sizeof( int16 ) );
618 pOffset += sizeof( int16 );
620 wnOtherLen = htons( wOtherLen );
621 memcpy( pOffset, &wnOtherLen, sizeof( int16 ) );
622 pOffset += sizeof( int16 );
624 *ppMessageBuffer = pMessageBuffer;
625 *pdwMessageSize = dwMessageSize;
627 *pdwTimeSigned = dwTimeSigned;
628 *pwFudge = wFudge;
630 return dwError;
632 error:
634 if ( pMessageBuffer ) {
635 DNSFreeMemory( pMessageBuffer );
638 *ppMessageBuffer = NULL;
639 *pdwMessageSize = 0;
640 *pdwTimeSigned = dwTimeSigned;
641 *pwFudge = wFudge;
642 return dwError;