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
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
29 /********************************************************************
30 ********************************************************************/
32 static int32
DNSSendUpdate1( HANDLE hDNSServer
, const char *szDomainName
,
33 char *szHost
, struct in_addr
*iplist
,
35 DNS_UPDATE_RESPONSE
* *ppDNSUpdateResponse
)
38 DNS_UPDATE_REQUEST
*pDNSUpdateRequest
= NULL
;
39 DNS_UPDATE_RESPONSE
*pDNSUpdateResponse
= NULL
;
40 DNS_ZONE_RECORD
*pDNSZoneRecord
= NULL
;
41 DNS_RR_RECORD
*pDNSPRRecord
= NULL
;
44 dwError
= DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest
);
45 BAIL_ON_ERROR( dwError
);
47 dwError
= DNSCreateZoneRecord( szDomainName
, &pDNSZoneRecord
);
48 BAIL_ON_ERROR( dwError
);
51 DNSUpdateAddZoneSection( pDNSUpdateRequest
, pDNSZoneRecord
);
52 BAIL_ON_ERROR( dwError
);
54 /* Add the CNAME not in user record */
58 DNSCreateNameNotInUseRecord( szHost
, QTYPE_CNAME
,
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
;
71 DNSCreateNameInUseRecord( szHost
, QTYPE_A
, &iplist
[i
],
73 BAIL_ON_ERROR( dwError
);
76 DNSUpdateAddPRSection( pDNSUpdateRequest
,
78 BAIL_ON_ERROR( dwError
);
82 DNSUpdateSendUpdateRequest2( hDNSServer
, pDNSUpdateRequest
);
83 BAIL_ON_ERROR( dwError
);
86 DNSUpdateReceiveUpdateResponse( hDNSServer
,
87 &pDNSUpdateResponse
);
88 BAIL_ON_ERROR( dwError
);
90 *ppDNSUpdateResponse
= pDNSUpdateResponse
;
96 if ( pDNSZoneRecord
) {
97 DNSFreeZoneRecord( pDNSZoneRecord
);
100 if ( pDNSUpdateRequest
) {
101 DNSUpdateFreeRequest( pDNSUpdateRequest
);
104 *ppDNSUpdateResponse
= NULL
;
108 /********************************************************************
109 ********************************************************************/
111 static int32
DNSSendUpdate2( HANDLE hDNSServer
, const char *szDomainName
,
112 char *szHost
, struct in_addr
*iplist
,
114 DNS_UPDATE_RESPONSE
* *ppDNSUpdateResponse
)
117 DNS_UPDATE_REQUEST
*pDNSUpdateRequest
= NULL
;
118 DNS_UPDATE_RESPONSE
*pDNSUpdateResponse
= NULL
;
119 DNS_ZONE_RECORD
*pDNSZoneRecord
= NULL
;
120 DNS_RR_RECORD
*pDNSPRRecord
= NULL
;
123 dwError
= DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest
);
124 BAIL_ON_ERROR( dwError
);
126 dwError
= DNSCreateZoneRecord( szDomainName
, &pDNSZoneRecord
);
127 BAIL_ON_ERROR( dwError
);
130 DNSUpdateAddZoneSection( pDNSUpdateRequest
, pDNSZoneRecord
);
131 BAIL_ON_ERROR( dwError
);
133 /* Add the CNAME not in user record */
137 DNSCreateNameNotInUseRecord( szHost
, QTYPE_CNAME
,
139 BAIL_ON_ERROR( dwError
);
141 dwError
= DNSUpdateAddPRSection( pDNSUpdateRequest
, pDNSPRRecord
);
142 BAIL_ON_ERROR( dwError
);
144 /* Add the IN not in user record */
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
;
159 DNSCreateARecord( szHost
, DNS_CLASS_IN
, QTYPE_A
,
160 ntohl( iplist
[i
].s_addr
),
162 BAIL_ON_ERROR( dwError
);
165 DNSUpdateAddUpdateSection( pDNSUpdateRequest
,
167 BAIL_ON_ERROR( dwError
);
171 DNSUpdateSendUpdateRequest2( hDNSServer
, pDNSUpdateRequest
);
172 BAIL_ON_ERROR( dwError
);
175 DNSUpdateReceiveUpdateResponse( hDNSServer
,
176 &pDNSUpdateResponse
);
177 BAIL_ON_ERROR( dwError
);
179 *ppDNSUpdateResponse
= pDNSUpdateResponse
;
185 if ( pDNSZoneRecord
) {
186 DNSFreeZoneRecord( pDNSZoneRecord
);
189 if ( pDNSUpdateRequest
) {
190 DNSUpdateFreeRequest( pDNSUpdateRequest
);
193 *ppDNSUpdateResponse
= NULL
;
197 /********************************************************************
198 ********************************************************************/
200 static int32
DNSSendUpdate3( HANDLE hDNSServer
, const char *szDomainName
,
201 char *szHost
, struct in_addr
*iplist
,
203 DNS_UPDATE_RESPONSE
* *ppDNSUpdateResponse
)
206 DNS_UPDATE_REQUEST
*pDNSUpdateRequest
= NULL
;
207 DNS_UPDATE_RESPONSE
*pDNSUpdateResponse
= NULL
;
208 DNS_ZONE_RECORD
*pDNSZoneRecord
= NULL
;
209 DNS_RR_RECORD
*pDNSPRRecord
= NULL
;
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
);
220 DNSUpdateAddZoneSection( pDNSUpdateRequest
, pDNSZoneRecord
);
221 BAIL_ON_ERROR( dwError
);
223 /* Add the CNAME not in user record */
226 DNSCreateNameNotInUseRecord( szHost
, QTYPE_CNAME
,
228 BAIL_ON_ERROR( dwError
);
230 dwError
= DNSUpdateAddPRSection( pDNSUpdateRequest
, pDNSPRRecord
);
231 BAIL_ON_ERROR( dwError
);
233 /* Delete any existing A records */
236 DNSCreateARecord( szHost
, DNS_CLASS_ANY
, QTYPE_A
, 0,
238 BAIL_ON_ERROR( dwError
);
241 DNSUpdateAddUpdateSection( pDNSUpdateRequest
,
243 BAIL_ON_ERROR( dwError
);
246 for ( i
= 0; i
< num_ips
; i
++ ) {
249 DNSCreateARecord( szHost
, DNS_CLASS_IN
, QTYPE_A
,
250 ntohl( iplist
[i
].s_addr
),
252 BAIL_ON_ERROR( dwError
);
255 DNSUpdateAddUpdateSection( pDNSUpdateRequest
,
257 BAIL_ON_ERROR( dwError
);
261 DNSUpdateSendUpdateRequest2( hDNSServer
, pDNSUpdateRequest
);
262 BAIL_ON_ERROR( dwError
);
265 DNSUpdateReceiveUpdateResponse( hDNSServer
,
266 &pDNSUpdateResponse
);
267 BAIL_ON_ERROR( dwError
);
269 *ppDNSUpdateResponse
= pDNSUpdateResponse
;
275 if ( pDNSZoneRecord
) {
276 DNSFreeZoneRecord( pDNSZoneRecord
);
279 if ( pDNSUpdateRequest
) {
280 DNSUpdateFreeRequest( pDNSUpdateRequest
);
283 *ppDNSUpdateResponse
= NULL
;
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
)
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
;
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
;
329 dwError
= DNSSendUpdate3( hDNSServer
, szDomainName
, szHost
,
330 iplist
, num_ips
, &response
);
333 *ppDNSUpdateResponse
= response
;
338 /********************************************************************
339 ********************************************************************/
340 #ifdef HAVE_GSSAPI_SUPPORT
341 int32
DNSSendSecureUpdate( HANDLE hDNSServer
,
342 gss_ctx_id_t
* pGSSContext
,
346 int32 dwIP
, DNS_UPDATE_RESPONSE
** ppDNSUpdateResponse
)
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
,
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
,
375 QTYPE_A
, &pDNSARecord
);
376 BAIL_ON_ERROR( dwError
);
378 dwError
= DNSUpdateAddUpdateSection( pDNSUpdateRequest
, pDNSARecord
);
379 BAIL_ON_ERROR( dwError
);
381 dwError
= DNSCreateARecord( szHost
,
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
);
397 DNSUpdateSendUpdateRequest2( hDNSServer
, pDNSUpdateRequest
);
398 BAIL_ON_ERROR( dwError
);
401 DNSUpdateReceiveUpdateResponse( hDNSServer
,
402 &pDNSUpdateResponse
);
403 BAIL_ON_ERROR( dwError
);
405 *ppDNSUpdateResponse
= pDNSUpdateResponse
;
411 if ( pDNSZoneRecord
) {
412 DNSFreeZoneRecord( pDNSZoneRecord
);
415 if ( pDNSUpdateRequest
) {
416 DNSUpdateFreeRequest( pDNSUpdateRequest
);
419 *ppDNSUpdateResponse
= NULL
;
425 /*********************************************************************
426 *********************************************************************/
428 int32
DNSUpdateGenerateSignature( gss_ctx_id_t
* pGSSContext
,
429 DNS_UPDATE_REQUEST
* pDNSUpdateRequest
,
433 int32 dwMinorStatus
= 0;
434 uint8
*pMessageBuffer
= NULL
;
435 int32 dwMessageSize
= 0;
436 int32 dwMaxSignatureSize
= 0;
437 uint8
*pSignature
= NULL
;
438 int32 dwTimeSigned
= 0;
440 gss_buffer_desc MsgDesc
, MicDesc
;
441 DNS_RR_RECORD
*pDNSTSIGRecord
= NULL
;
443 dwError
= DNSBuildMessageBuffer( pDNSUpdateRequest
,
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
;
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
,
467 pDNSUpdateRequest
->wIdentification
,
468 (uint8
*)MicDesc
.value
,
469 MicDesc
.length
, &pDNSTSIGRecord
);
470 BAIL_ON_ERROR( dwError
);
472 dwError
= DNSUpdateAddAdditionalSection( pDNSUpdateRequest
,
474 BAIL_ON_ERROR( dwError
);
479 if ( pMessageBuffer
) {
480 DNSFreeMemory( pMessageBuffer
);
485 DNSFreeMemory( pSignature
);
490 #endif /* HAVE_GSSAPI_SUPPORT */
492 /*********************************************************************
493 *********************************************************************/
495 int32
DNSBuildSignatureBuffer( int32 dwMaxSignatureSize
, uint8
** ppSignature
)
498 uint8
*pSignature
= NULL
;
500 dwError
= DNSAllocateMemory( dwMaxSignatureSize
,
501 ( void * ) &pSignature
);
502 BAIL_ON_ERROR( dwError
);
504 *ppSignature
= pSignature
;
513 /*********************************************************************
514 *********************************************************************/
516 int32
DNSBuildMessageBuffer( DNS_UPDATE_REQUEST
* pDNSUpdateRequest
,
518 int32
* pdwTimeSigned
,
520 uint8
** ppMessageBuffer
, int32
* pdwMessageSize
)
523 uint8
*pSrcBuffer
= NULL
;
524 int32 dwReqMsgSize
= 0;
525 int32 dwAlgorithmLen
= 0;
527 uint8
*pMessageBuffer
= NULL
;
528 int32 dwMessageSize
= 0;
529 uint8
*pOffset
= NULL
;
530 int16 wnError
, wError
= 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;
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
);
559 DNSUpdateBuildRequestMessage( pDNSUpdateRequest
,
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
;
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
;
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
);
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
;
634 if ( pMessageBuffer
) {
635 DNSFreeMemory( pMessageBuffer
);
638 *ppMessageBuffer
= NULL
;
640 *pdwTimeSigned
= dwTimeSigned
;