diff options
Diffstat (limited to 'source3/libaddns')
-rw-r--r-- | source3/libaddns/addns.h | 32 | ||||
-rw-r--r-- | source3/libaddns/dns.h | 521 | ||||
-rw-r--r-- | source3/libaddns/dnserr.h | 74 | ||||
-rw-r--r-- | source3/libaddns/dnsgss.c | 550 | ||||
-rw-r--r-- | source3/libaddns/dnsrecord.c | 548 | ||||
-rw-r--r-- | source3/libaddns/dnsrequest.c | 478 | ||||
-rw-r--r-- | source3/libaddns/dnsresponse.c | 589 | ||||
-rw-r--r-- | source3/libaddns/dnssign.c | 52 | ||||
-rw-r--r-- | source3/libaddns/dnssock.c | 766 | ||||
-rw-r--r-- | source3/libaddns/dnsupdate.c | 644 | ||||
-rw-r--r-- | source3/libaddns/dnsuprequest.c | 428 | ||||
-rw-r--r-- | source3/libaddns/dnsupresp.c | 397 | ||||
-rw-r--r-- | source3/libaddns/dnsutils.c | 596 |
13 files changed, 5675 insertions, 0 deletions
diff --git a/source3/libaddns/addns.h b/source3/libaddns/addns.h new file mode 100644 index 0000000000..d7774537fe --- /dev/null +++ b/source3/libaddns/addns.h @@ -0,0 +1,32 @@ +/* + Public Interface file for Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#ifndef _ADDNS_H +#define _ADDNS_H + + +#endif /* _ADDNS_H */ + diff --git a/source3/libaddns/dns.h b/source3/libaddns/dns.h new file mode 100644 index 0000000000..ec61dff23b --- /dev/null +++ b/source3/libaddns/dns.h @@ -0,0 +1,521 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#ifndef _DNS_H +#define _DNS_H + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <time.h> +#include <string.h> +#include <errno.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <uuid/uuid.h> +#include <krb5.h> + +#if HAVE_GSSAPI_H +#include <gssapi.h> +#elif HAVE_GSSAPI_GSSAPI_H +#include <gssapi/gssapi.h> +#elif HAVE_GSSAPI_GSSAPI_GENERIC_H +#include <gssapi/gssapi_generic.h> +#endif + +#include <talloc.h> + +#define TALLOC(ctx, size) talloc_named_const(ctx, size, __location__) +#define TALLOC_P(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) +#define TALLOC_MEMDUP(ctx, ptr, size) _talloc_memdup(ctx, ptr, size, __location__) +#define TALLOC_ZERO(ctx, size) _talloc_zero(ctx, size, __location__) +#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +#define TALLOC_REALLOC(ctx, ptr, count) _talloc_realloc(ctx, ptr, count, __location__) +#define TALLOC_REALLOC_ARRAY(ctx, ptr, type, count) (type *)_talloc_realloc_array(ctx, ptr, sizeof(type), count, #type) +#define TALLOC_FREE(ctx) do { if ((ctx) != NULL) {talloc_free(ctx); ctx=NULL;} } while(0) + +/******************************************************************* + Type definitions for int16, int32, uint16 and uint32. Needed + for Samba coding style +*******************************************************************/ + +#ifndef uint8 +# define uint8 unsigned char +#endif + +#if !defined(int16) && !defined(HAVE_INT16_FROM_RPC_RPC_H) +# if (SIZEOF_SHORT == 4) +# define int16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; +# else /* SIZEOF_SHORT != 4 */ +# define int16 short +# endif /* SIZEOF_SHORT != 4 */ + /* needed to work around compile issue on HP-UX 11.x */ +# define _INT16 1 +#endif + +/* + * Note we duplicate the size tests in the unsigned + * case as int16 may be a typedef from rpc/rpc.h + */ + +#if !defined(uint16) && !defined(HAVE_UINT16_FROM_RPC_RPC_H) +# if (SIZEOF_SHORT == 4) +# define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; +# else /* SIZEOF_SHORT != 4 */ +# define uint16 unsigned short +# endif /* SIZEOF_SHORT != 4 */ +#endif + +#if !defined(int32) && !defined(HAVE_INT32_FROM_RPC_RPC_H) +# if (SIZEOF_INT == 4) +# define int32 int +# elif (SIZEOF_LONG == 4) +# define int32 long +# elif (SIZEOF_SHORT == 4) +# define int32 short +# else + /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */ +# define int32 int +# endif + /* needed to work around compile issue on HP-UX 11.x */ +# define _INT32 1 +#endif + +/* + * Note we duplicate the size tests in the unsigned + * case as int32 may be a typedef from rpc/rpc.h + */ + +#if !defined(uint32) && !defined(HAVE_UINT32_FROM_RPC_RPC_H) +# if (SIZEOF_INT == 4) +# define uint32 unsigned int +# elif (SIZEOF_LONG == 4) +# define uint32 unsigned long +# elif (SIZEOF_SHORT == 4) +# define uint32 unsigned short +# else + /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */ +# define uint32 unsigned +# endif +#endif + +/* + * check for 8 byte long long + */ + +#if !defined(uint64) +# if (SIZEOF_LONG == 8) +# define uint64 unsigned long +# elif (SIZEOF_LONG_LONG == 8) +# define uint64 unsigned long long +# endif /* don't lie. If we don't have it, then don't use it */ +#endif + +#include "dnserr.h" + + +#define DNS_TCP 1 +#define DNS_UDP 2 + +#define DNS_OPCODE_UPDATE 1 + +#define BAIL_ON_ERROR(x) \ + if ((x)){ \ + goto error; \ + } + +#define BAIL_ON_DNS_ERROR(x) \ + if ( !ERR_DNS_IS_OK((x)) ) { \ + goto error; \ + } + +#define BAIL_ON_SEC_ERROR(dwMajorStatus) \ + if ((dwMajorStatus!= GSS_S_COMPLETE)\ + && (dwMajorStatus != GSS_S_CONTINUE_NEEDED)) {\ + goto sec_error; \ + } + +/* DNS Class Types */ + +#define DNS_CLASS_IN 1 +#define DNS_CLASS_ANY 255 +#define DNS_CLASS_NONE 254 + +/* DNS RR Types */ + +#define DNS_RR_A 1 + +#define DNS_TCP_PORT 53 +#define DNS_UDP_PORT 53 + +#define QTYPE_A 1 +#define QTYPE_NS 2 +#define QTYPE_MD 3 +#define QTYPE_CNAME 5 +#define QTYPE_SOA 6 +#define QTYPE_ANY 255 +#define QTYPE_TKEY 249 +#define QTYPE_TSIG 250 + +/* +MF 4 a mail forwarder (Obsolete - use MX) +CNAME 5 the canonical name for an alias +SOA 6 marks the start of a zone of authority +MB 7 a mailbox domain name (EXPERIMENTAL) +MG 8 a mail group member (EXPERIMENTAL) +MR 9 a mail rename domain name (EXPERIMENTAL) +NULL 10 a null RR (EXPERIMENTAL) +WKS 11 a well known service description +PTR 12 a domain name pointer +HINFO 13 host information +MINFO 14 mailbox or mail list information +MX 15 mail exchange +TXT 16 text strings +*/ + +#define QR_QUERY 0x0000 +#define QR_RESPONSE 0x0001 + +#define OPCODE_QUERY 0x00 +#define OPCODE_IQUERY 0x01 +#define OPCODE_STATUS 0x02 + +#define AA 1 + +#define RECURSION_DESIRED 0x01 + +#define RCODE_NOERROR 0 +#define RCODE_FORMATERROR 1 +#define RCODE_SERVER_FAILURE 2 +#define RCODE_NAME_ERROR 3 +#define RCODE_NOTIMPLEMENTED 4 +#define RCODE_REFUSED 5 + +#define SENDBUFFER_SIZE 65536 +#define RECVBUFFER_SIZE 65536 + +#define DNS_ONE_DAY_IN_SECS 86400 +#define DNS_TEN_HOURS_IN_SECS 36000 + +#define SOCKET_ERROR -1 +#define INVALID_SOCKET -1 + +#define DNS_NO_ERROR 0 +#define DNS_FORMAT_ERROR 1 +#define DNS_SERVER_FAILURE 2 +#define DNS_NAME_ERROR 3 +#define DNS_NOT_IMPLEMENTED 4 +#define DNS_REFUSED 5 + +typedef long HANDLE; +typedef gss_ctx_id_t CtxtHandle, *PCtxtHandle; + +#ifndef _BOOL +typedef int BOOL; + +#define _BOOL /* So we don't typedef BOOL again */ +#endif + + +typedef struct dns_domain_label { + struct dns_domain_label *pNext; + char *pszLabel; + int32 dwLength; +} DNS_DOMAIN_LABEL; + +typedef struct { + DNS_DOMAIN_LABEL *pLabelList; +} DNS_DOMAIN_NAME; + +typedef struct { + DNS_DOMAIN_NAME *pDomainName; + int16 wQueryType; + int16 wQueryClass; +} DNS_QUESTION_RECORD; + + +typedef struct { + DNS_DOMAIN_NAME *pDomainName; + int16 wZoneType; + int16 wZoneClass; +} DNS_ZONE_RECORD; + + +typedef struct { + DNS_DOMAIN_NAME *pDomainName; + int16 wType; + int16 wClass; + int32 dwTTL; + int16 wRDataSize; + uint8 *pRData; +} DNS_RR_HEADER; + + +typedef struct { + uint8 *pDefData; +} DNS_DEF_RDATA; + +typedef struct { + int16 wAlgorithmOffset; + int16 wInceptionOffset; + int16 wExpirationOffset; + int16 wModeOffset; + int16 wErrorOffset; + int16 wKeySizeOffset; + int16 wKeyDataOffset; + int16 wOtherSizeOffset; + int16 wOtherDataOffset; +} DNS_TKEY_OFFSETS; + +typedef struct { + int16 wAlgorithmOffset; + int16 wTimeSignedOffset; + int16 wFudgeOffset; + int16 wMacSizeOffset; + int16 wMacDataOffset; + int16 wOriginalMessageIdOffset; + int16 wErrorOffset; + int16 wOtherSizeOffset; + int16 wOtherDataOffset; +} DNS_TSIG_OFFSETS; + + +typedef struct { + DNS_RR_HEADER RRHeader; + union { + DNS_TKEY_OFFSETS TKey; + DNS_TSIG_OFFSETS TSig; + } Offsets; + uint8 *pRData; +} DNS_RR_RECORD; + + +typedef struct { + int16 wIdentification; + int16 wParameter; + int16 wQuestions; + int16 wAnswers; + int16 wAuthoritys; + int16 wAdditionals; + DNS_QUESTION_RECORD **ppQuestionRRSet; + DNS_RR_RECORD **ppAnswerRRSet; + DNS_RR_RECORD **ppAuthorityRRSet; + DNS_RR_RECORD **ppAdditionalRRSet; +} DNS_REQUEST; + + +typedef struct { + int16 wIdentification; + int16 wParameter; + int16 wZones; + int16 wPRs; + int16 wUpdates; + int16 wAdditionals; + DNS_ZONE_RECORD **ppZoneRRSet; + DNS_RR_RECORD **ppPRRRSet; + DNS_RR_RECORD **ppUpdateRRSet; + DNS_RR_RECORD **ppAdditionalRRSet; +} DNS_UPDATE_REQUEST; + + +typedef struct { + int16 wIdentification; + int16 wParameter; + int16 wQuestions; + int16 wAnswers; + int16 wAuthoritys; + int16 wAdditionals; + DNS_QUESTION_RECORD **ppQuestionRRSet; + DNS_RR_RECORD **ppAnswerRRSet; + DNS_RR_RECORD **ppAuthorityRRSet; + DNS_RR_RECORD **ppAdditionalRRSet; + uint8 *pDNSOutBuffer; + int32 dwNumBytes; +} DNS_RESPONSE; + +typedef struct { + int16 wIdentification; + int16 wParameter; + int16 wZones; + int16 wPRs; + int16 wUpdates; + int16 wAdditionals; + DNS_ZONE_RECORD **ppZoneRRSet; + DNS_RR_RECORD **ppPRRRSet; + DNS_RR_RECORD **ppUpdateRRSet; + DNS_RR_RECORD **ppAdditionalRRSet; + uint8 *pDNSOutBuffer; + int32 dwNumBytes; +} DNS_UPDATE_RESPONSE; + +typedef struct { + int32 hType; + int s; + struct sockaddr RecvAddr; +} DNS_CONNECTION_CONTEXT; + +typedef struct { + uint8 *pSendBuffer; + int32 dwBufferSize; + int32 dwBytesWritten; + int32 dwBufferOffset; +} DNS_SENDBUFFER_CONTEXT; + +typedef struct { + uint8 *pRecvBuffer; + int32 dwBufferSize; + int32 dwBytesRecvd; + int32 dwBytesRead; +} DNS_RECEIVEBUFFER_CONTEXT; + +/* from dnsutils.c */ + +int32 DNSGenerateIdentifier( int16 * pwIdentifer ); +int32 DNSGetDomainNameLength( DNS_DOMAIN_NAME * pDomainName, int32 * pdwLength ); +int32 DNSCopyDomainName( uint8 * pBuffer, DNS_DOMAIN_NAME * pDomainName, int32 * pdwCopied ); +int32 DNSAllocateString( char *pszInputString, char **ppszOutputString ); +int32 DNSGenerateKeyName( char **pszKeyName ); +int32 DNSMakeRRHeader( DNS_RR_HEADER * pDNSRR, char *szOwnerName, int16 wType, int32 dwTTL ); +int32 DNSDomainNameFromString( char *pszDomainName, DNS_DOMAIN_NAME ** ppDomainName ); +int32 DNSAppendLabel( DNS_DOMAIN_LABEL * pLabelList, DNS_DOMAIN_LABEL * pLabel, DNS_DOMAIN_LABEL ** ppNewLabelList ); +int32 DNSGenerateKeyName( char **ppszKeyName ); +void DNSRecordGenerateOffsets( DNS_RR_RECORD * pDNSRecord ); +int32 MapDNSResponseCodes( int16 wResponseCode ); +int32 GetLastError( void ); +int32 WSAGetLastError( void ); +int32 DNSAllocateMemory(int32 dwSize, void * * ppMemory); +int32 DNSReallocMemory(void * pMemory, void * * ppNewMemory, int32 dwSize); +void DNSFreeMemory( void * pMemory ); +int32 DNSAllocateString(char *pszInputString, char **ppszOutputString); +void DNSFreeString(char * pszString); +void DNSFreeDomainName(DNS_DOMAIN_NAME *pDomainName); + +/* from dnsrecord.c */ + +int32 DNSCreateDeleteRecord( char *szHost, int16 wClass, int16 wType, DNS_RR_RECORD ** ppDNSRecord ); +int32 DNSCreateARecord( char *szHost, int16 wClass, int16 wType, int32 dwIP, DNS_RR_RECORD ** ppDNSRecord ); +int32 DNSCreateTKeyRecord( char *szKeyName, uint8 * pKeyData, int16 dwKeyLen, DNS_RR_RECORD ** ppDNSRecord ); +int32 DNSCreateTSIGRecord( char *szKeyName, int32 dwTimeSigned, int16 wFudge, int16 wOriginalID, uint8 * pMac, int16 wMacSize, DNS_RR_RECORD ** ppDNSRecord ); +int32 DNSCreateQuestionRecord( char *pszQName, int16 wQType, int16 wQClass, DNS_QUESTION_RECORD ** ppDNSQuestionRecord ); +int32 DNSAddQuestionSection( DNS_REQUEST * pDNSRequest, DNS_QUESTION_RECORD * pDNSQuestion ); +int32 DNSAddAdditionalSection( DNS_REQUEST * pDNSRequest, DNS_RR_RECORD * pDNSRecord ); +int32 DNSAddAnswerSection( DNS_REQUEST * pDNSRequest, DNS_RR_RECORD * pDNSRecord ); +int32 DNSAddAuthoritySection( DNS_REQUEST * pDNSRequest, DNS_RR_RECORD * pDNSRecord ); +int32 DNSCreateZoneRecord( char *pszZName, DNS_ZONE_RECORD ** ppDNSZoneRecord ); +int32 DNSFreeZoneRecord( DNS_ZONE_RECORD * pDNSZoneRecord ); +int32 DNSCreateNameInUseRecord( char *pszName, int32 qtype, struct in_addr *addr, DNS_RR_RECORD ** ppDNSRRRecord ); +int32 DNSCreateNameNotInUseRecord( char *pszName, int32 qtype, DNS_RR_RECORD ** ppDNSRRRecord ); + +/* from dnsresponse.c */ + +int32 DNSStdReceiveStdResponse( HANDLE hDNSHandle, DNS_RESPONSE ** ppDNSResponse ); +int32 DNSUnmarshallDomainName( HANDLE hRecvBuffer, DNS_DOMAIN_NAME ** ppDomainName ); +int32 DNSUnmarshallRRHeader( HANDLE hRecvBuffer, DNS_RR_HEADER * pRRHeader ); +int32 DNSUnmarshallRData( HANDLE hRecvBuffer, int32 dwSize, uint8 ** ppRData, int32 * pdwRead ); +int32 DNSUpdateGetResponseCode( DNS_UPDATE_RESPONSE * pDNSUpdateResponse, int32 * pdwResponseCode ); + +/* from dnsrequest.c */ + +int32 DNSStdSendMarshallSection( HANDLE hSendBuffer, DNS_RR_RECORD ** ppDNSAnswerRRRecords, int16 wAnswers ); +int32 DNSMarshallDomainName( HANDLE hSendBuffer, DNS_DOMAIN_NAME * pDomainName ); +int32 DNSMarshallRRHeader( HANDLE hSendBuffer, DNS_RR_RECORD * pDNSRecord ); +int32 DNSMarshallRData( HANDLE hSendBuffer, DNS_RR_RECORD * pDNSRecord ); +int32 DNSWriteDomainName( HANDLE hDNSHandle, DNS_DOMAIN_NAME * pDomainName ); +void DNSFreeRequest( DNS_REQUEST * pDNSRequest ); +int32 DNSStdAddQuestionSection( DNS_REQUEST * pDNSRequest, DNS_QUESTION_RECORD * pDNSQuestion ); +int32 DNSStdAddAdditionalSection( DNS_REQUEST * pDNSRequest, DNS_RR_RECORD * pDNSRecord ); +int32 DNSStdCreateStdRequest( DNS_REQUEST ** ppDNSRequest ); +int32 DNSStdSendStdRequest2( HANDLE hDNSServer, DNS_REQUEST * pDNSRequest ); + +/* from dnsuprequest.c */ + +int32 DNSUpdateSendUpdateRequest2( HANDLE hSendBuffer, DNS_UPDATE_REQUEST * pDNSRequest ); +int32 DNSUpdateBuildRequestMessage( DNS_UPDATE_REQUEST * pDNSRequest, HANDLE * phSendBuffer ); +void DNSUpdateFreeRequest( DNS_UPDATE_REQUEST * pDNSRequest ); +int32 DNSWriteDomainName( HANDLE hDNSHandle, DNS_DOMAIN_NAME * pDomainName ); +void DNSUpdateFreeRequest( DNS_UPDATE_REQUEST * pDNSRequest ); +int32 DNSUpdateAddZoneSection( DNS_UPDATE_REQUEST * pDNSRequest, DNS_ZONE_RECORD * pDNSZone ); +int32 DNSUpdateAddAdditionalSection( DNS_UPDATE_REQUEST * pDNSRequest, DNS_RR_RECORD * pDNSRecord ); +int32 DNSUpdateAddPRSection( DNS_UPDATE_REQUEST * pDNSRequest, DNS_RR_RECORD * pDNSRecord ); +int32 DNSUpdateAddUpdateSection( DNS_UPDATE_REQUEST * pDNSRequest, DNS_RR_RECORD * pDNSRecord ); +int32 DNSUpdateCreateUpdateRequest( DNS_UPDATE_REQUEST ** ppDNSRequest ); + +/* from dnssock.c */ + +DNS_ERROR DNSOpen( char *nameserver, int32 dwType, HANDLE * phDNSServer ); +int32 DNSReceiveBufferContext( HANDLE hDNSHandle, HANDLE hDNSRecvBuffer, int32 * pdwBytesRead ); +int32 DNSCreateSendBuffer( HANDLE * phDNSSendBuffer ); +int32 DNSMarshallBuffer( HANDLE hDNSSendBuffer, uint8 * pDNSSendBuffer, int32 dwBufferSize, int32 * pdwBytesWritten );; +int32 DNSSendBufferContext( HANDLE hDNSServer, HANDLE hSendBuffer, int32 * pdwBytesSent ); +int32 DNSCreateReceiveBuffer( HANDLE * phDNSRecvBuffer ); +int32 DNSUnmarshallBuffer( HANDLE hDNSRecvBuffer, uint8 * pDNSRecvBuffer, int32 dwBufferSize, int32 * pdwBytesRead ); +int32 DNSUnmarshallDomainNameAtOffset( HANDLE hRecvBuffer, int16 wOffset, DNS_DOMAIN_NAME ** ppDomainName ); +int32 DNSReceiveBufferMoveBackIndex( HANDLE hRecvBuffer, int16 wOffset ); +void DNSFreeSendBufferContext( HANDLE hSendBuffer ); +int32 DNSGetSendBufferContextSize( HANDLE hSendBuffer ); +uint8 *DNSGetSendBufferContextBuffer( HANDLE hSendBuffer ); + +/* from linux/dnsgss.c */ + +int32 DNSVerifyResponseMessage_GSSSuccess( PCtxtHandle pGSSContext, DNS_RR_RECORD * pClientTKeyRecord, DNS_RESPONSE * pDNSResponse ); +int32 DNSVerifyResponseMessage_GSSContinue( PCtxtHandle pGSSContext, DNS_RR_RECORD * pClientTKeyRecord, DNS_RESPONSE * pDNSResponse, uint8 ** ppServerKeyData, int16 * pwServerKeyDataSize ); +int32 DNSResponseGetRCode( DNS_RESPONSE * pDNSResponse, int16 * pwRCode ); +int32 DNSResponseGetTSIGRecord( DNS_RESPONSE * pDNSResponse, DNS_RR_RECORD ** ppTSIGRecord ); +int32 DNSCompareTKeyRecord( DNS_RR_RECORD * pClientTKeyRecord, DNS_RR_RECORD * pTKeyRecord ); +int32 DNSBuildTKeyQueryRequest( char *szKeyName, uint8 * pKeyData, int32 dwKeyLen, DNS_REQUEST ** ppDNSRequest ); +int32 DNSResponseGetTKeyRecord( DNS_RESPONSE * pDNSResponse, DNS_RR_RECORD ** ppTKeyRecord ); +int32 DNSGetTKeyData( DNS_RR_RECORD * pTKeyRecord, uint8 ** ppKeyData, int16 * pwKeyDataSize ); +int32 DNSNegotiateSecureContext( HANDLE hDNSServer, char *szDomain, char *szServerName, char *szKeyName, PCtxtHandle pGSSContext ); +void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat ); +int32 DNSNegotiateContextAndSecureUpdate( HANDLE hDNSServer, char *szServiceName, char *szDomainName, char *szHost, int32 dwIPAddress ); + +/* from linux/dnsupdate.c */ + +int32 DNSSendUpdate( HANDLE hDNSServer, char *szDomainName, char *szHost, struct in_addr *iplist, int num_addrs, DNS_UPDATE_RESPONSE ** ppDNSUpdateResponse ); +int32 DNSSendSecureUpdate( HANDLE hDNSServer, PCtxtHandle pGSSContext, char *pszKeyName, char *szDomainName, char *szHost, int32 dwIP, DNS_UPDATE_RESPONSE ** ppDNSUpdateResponse ); +int32 DNSUpdateGenerateSignature( PCtxtHandle pGSSContext, DNS_UPDATE_REQUEST * pDNSUpdateRequest, char *pszKeyName ); +int32 DNSBuildSignatureBuffer( int32 dwMaxSignatureSize, uint8 ** ppSignature ); +int32 DNSBuildMessageBuffer( DNS_UPDATE_REQUEST * pDNSUpdateRequest, char *szKeyName, int32 * pdwTimeSigned, int16 * pwFudge, uint8 ** ppMessageBuffer, int32 * pdwMessageSize ); +int32 DNSClose( HANDLE hDNSUpdate ); + +/* from dnsupresp.c */ + +int32 DNSUpdateReceiveUpdateResponse( HANDLE hDNSHandle, DNS_UPDATE_RESPONSE ** ppDNSResponse ); + +/* from dnssign.c */ + +int32 DNSGenerateHash( CtxtHandle * gss_context, uint8 * pRequestBuffer, uint8 ** ppMAC, int32 * pdwMacLen ); +int32 BuildHashInputBuffer( DNS_REQUEST * pDNSRequest, int32 dwLength, uint8 ** ppHashInputBuffer, int32 * pdwHashInputBufferLen ); +int32 DNSStdValidateAndGetTSIGRecord( CtxtHandle * gss_context, DNS_RESPONSE * pDNSResponse, DNS_RR_RECORD ** ppDNSTSIGRecord ); + +#endif /* _DNS_H */ diff --git a/source3/libaddns/dnserr.h b/source3/libaddns/dnserr.h new file mode 100644 index 0000000000..eee1303c00 --- /dev/null +++ b/source3/libaddns/dnserr.h @@ -0,0 +1,74 @@ +/* + Error codes for Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#ifndef _DNSERR_H +#define _DNSERR_H + + +/* The Splint code analysis tool (http://www.splint.org.) doesn't + like immediate structures. */ + +#ifdef _SPLINT_ +#undef HAVE_IMMEDIATE_STRUCTURES +#endif + +/* Setup the DNS_ERROR typedef. Technique takes from nt_status.h */ + +#if defined(HAVE_IMMEDIATE_STRUCTURES) +typedef struct {uint32 v;} DNS_ERROR; +#define ERROR_DNS(x) ((DNS_ERROR) { x }) +#define ERROR_DNS_V(x) ((x).v) +#else +typedef uint32 DNS_ERROR; +#define ERROR_DNS(x) (x) +#define ERROR_DNS_V(x) (x) +#endif + +#define ERR_DNS_IS_OK(x) (ERROR_DNS_V(x) == 0) +#define ERR_DNS_EQUAL(x,y) (ERROR_DNS_V(x) == ERROR_DNS_V(y)) + +/************************************************* + * Define the error codes here + *************************************************/ + +#define ERROR_DNS_SUCCESS ERROR_DNS(0) +#define ERROR_DNS_RECORD_NOT_FOUND ERROR_DNS(1) +#define ERROR_DNS_BAD_RESPONSE ERROR_DNS(2) +#define ERROR_DNS_INVALID_PARAMETER ERROR_DNS(3) +#define ERROR_DNS_NO_MEMORY ERROR_DNS(4) +#define ERROR_DNS_INVALID_NAME_SERVER ERROR_DNS(5) +#define ERROR_DNS_CONNECTION_FAILED ERROR_DNS(6) + + +#define ERROR_BAD_RESPONSE 1 +#define ERROR_RECORD_NOT_FOUND 2 +#define ERROR_OUTOFMEMORY 8 +#if !defined(ERROR_INVALID_PARAMETER) +#define ERROR_INVALID_PARAMETER 87 +#endif + +#endif /* _DNSERR_H */ + diff --git a/source3/libaddns/dnsgss.c b/source3/libaddns/dnsgss.c new file mode 100644 index 0000000000..d710604b01 --- /dev/null +++ b/source3/libaddns/dnsgss.c @@ -0,0 +1,550 @@ +/* + Public Interface file for Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" +#include <ctype.h> + + +/********************************************************************* +*********************************************************************/ + +static int strupr( char *szDomainName ) +{ + if ( !szDomainName ) { + return ( 0 ); + } + while ( *szDomainName != '\0' ) { + *szDomainName = toupper( *szDomainName ); + szDomainName++; + } + return ( 0 ); +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSBuildTKeyQueryRequest( char *szKeyName, + uint8 * pKeyData, + int32 dwKeyLen, DNS_REQUEST ** ppDNSRequest ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pDNSTKeyRecord = NULL; + DNS_REQUEST *pDNSRequest = NULL; + DNS_QUESTION_RECORD *pDNSQuestionRecord = NULL; + + dwError = DNSStdCreateStdRequest( &pDNSRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateQuestionRecord( szKeyName, + QTYPE_TKEY, + DNS_CLASS_IN, + &pDNSQuestionRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSStdAddQuestionSection( pDNSRequest, pDNSQuestionRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateTKeyRecord( szKeyName, + pKeyData, + ( int16 ) dwKeyLen, &pDNSTKeyRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSStdAddAdditionalSection( pDNSRequest, pDNSTKeyRecord ); + BAIL_ON_ERROR( dwError ); + + *ppDNSRequest = pDNSRequest; + + return dwError; + + error: + + *ppDNSRequest = NULL; + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSVerifyResponseMessage_GSSSuccess( PCtxtHandle pGSSContext, + DNS_RR_RECORD * pClientTKeyRecord, + DNS_RESPONSE * pDNSResponse ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pTKeyRecord = NULL; + DNS_RR_RECORD *pTSIGRecord = NULL; + int16 wRCode = 0; + + dwError = DNSResponseGetRCode( pDNSResponse, &wRCode ); + BAIL_ON_ERROR( dwError ); + + if ( wRCode != 0 ) { + dwError = ERROR_BAD_RESPONSE; + BAIL_ON_ERROR( dwError ); + + } + + dwError = DNSResponseGetTKeyRecord( pDNSResponse, &pTKeyRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCompareTKeyRecord( pClientTKeyRecord, pTKeyRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSResponseGetTSIGRecord( pDNSResponse, &pTSIGRecord ); + BAIL_ON_ERROR( dwError ); + +/* + dwMajorStatus = GSS_VerifyMIC( + pDNSResponse->pDNSResponseBuffer, + pDNSResponse->dwNumBytes, + pDNSRRRecord->RData.TSIGRData.pMAC, + pDNSRRRecord->RData.TSIGRData.wMaxSize + ) + BAIL_ON_ERROR(dwMajorStatus);*/ + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSVerifyResponseMessage_GSSContinue( PCtxtHandle pGSSContext, + DNS_RR_RECORD * pClientTKeyRecord, + DNS_RESPONSE * pDNSResponse, + uint8 ** ppServerKeyData, + int16 * pwServerKeyDataSize ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pTKeyRecord = NULL; + int16 wRCode = 0; + uint8 *pServerKeyData = NULL; + int16 wServerKeyDataSize = 0; + + + dwError = DNSResponseGetRCode( pDNSResponse, &wRCode ); + BAIL_ON_ERROR( dwError ); + if ( wRCode != 0 ) { + dwError = ERROR_BAD_RESPONSE; + BAIL_ON_ERROR( dwError ); + + } + + dwError = DNSResponseGetTKeyRecord( pDNSResponse, &pTKeyRecord ); + BAIL_ON_ERROR( dwError ); + + + dwError = DNSCompareTKeyRecord( pClientTKeyRecord, pTKeyRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSGetTKeyData( pTKeyRecord, + &pServerKeyData, &wServerKeyDataSize ); + BAIL_ON_ERROR( dwError ); + + *ppServerKeyData = pServerKeyData; + *pwServerKeyDataSize = wServerKeyDataSize; + + return dwError; + + error: + + *ppServerKeyData = NULL; + *pwServerKeyDataSize = 0; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSResponseGetRCode( DNS_RESPONSE * pDNSResponse, int16 * pwRCode ) +{ + int32 dwError = 0; + int16 wnParameter = 0; + uint8 uChar = 0; + + wnParameter = htons( pDNSResponse->wParameter ); + + /* Byte 0 is the most significate byte + Bit 12, 13, 14, 15 or Bit 4, 5, 6, 7 represent the RCode */ + + memcpy( &uChar, ( uint8 * ) & wnParameter + 1, 1 ); + uChar >>= 4; + *pwRCode = ( int16 ) uChar; + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSResponseGetTKeyRecord( DNS_RESPONSE * pDNSResponse, + DNS_RR_RECORD ** ppTKeyRecord ) +{ + int32 dwError = 0; + int16 wAnswers = 0; + DNS_RR_RECORD *pDNSRecord = NULL; + int32 i = 0; + + + wAnswers = pDNSResponse->wAnswers; + if ( !wAnswers ) { + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR( dwError ); + } + + for ( i = 0; i < wAnswers; i++ ) { + pDNSRecord = *( pDNSResponse->ppAnswerRRSet + i ); + if ( pDNSRecord->RRHeader.wType == QTYPE_TKEY ) { + *ppTKeyRecord = pDNSRecord; + return dwError; + } + } + dwError = ERROR_RECORD_NOT_FOUND; + + error: + *ppTKeyRecord = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSResponseGetTSIGRecord( DNS_RESPONSE * pDNSResponse, + DNS_RR_RECORD ** ppTSIGRecord ) +{ + int32 dwError = 0; + int16 wAdditionals = 0; + DNS_RR_RECORD *pDNSRecord = NULL; + + int32 i = 0; + + wAdditionals = pDNSResponse->wAdditionals; + if ( !wAdditionals ) { + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR( dwError ); + } + + for ( i = 0; i < wAdditionals; i++ ) { + pDNSRecord = *( pDNSResponse->ppAdditionalRRSet + i ); + if ( pDNSRecord->RRHeader.wType == QTYPE_TSIG ) { + *ppTSIGRecord = pDNSRecord; + return dwError; + } + } + dwError = ERROR_RECORD_NOT_FOUND; + + error: + *ppTSIGRecord = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCompareTKeyRecord( DNS_RR_RECORD * pClientTKeyRecord, + DNS_RR_RECORD * pTKeyRecord ) +{ + int32 dwError = 0; + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSNegotiateContextAndSecureUpdate( HANDLE hDNSServer, + char *szServiceName, + char *szDomainName, + char *szHost, int32 dwIPAddress ) +{ + int32 dwError = 0; + char *pszKeyName = NULL; + CtxtHandle ContextHandle = 0; + CtxtHandle *pContextHandle = &ContextHandle; + + dwError = DNSGenerateKeyName( &pszKeyName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSNegotiateSecureContext( hDNSServer, szDomainName, szHost, + pszKeyName, pContextHandle ); + BAIL_ON_ERROR( dwError ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSGetTKeyData( DNS_RR_RECORD * pTKeyRecord, + uint8 ** ppKeyData, int16 * pwKeyDataSize ) +{ + int32 dwError = 0; + int16 wKeyDataSize = 0; + int16 wnKeyDataSize = 0; + int32 dwKeyDataSizeOffset = 0; + int32 dwKeyDataOffset = 0; + uint8 *pKeyData = NULL; + + DNSRecordGenerateOffsets( pTKeyRecord ); + dwKeyDataSizeOffset = pTKeyRecord->Offsets.TKey.wKeySizeOffset; + dwKeyDataOffset = pTKeyRecord->Offsets.TKey.wKeyDataOffset; + memcpy( &wnKeyDataSize, pTKeyRecord->pRData + dwKeyDataSizeOffset, + sizeof( int16 ) ); + wKeyDataSize = ntohs( wnKeyDataSize ); + + dwError = DNSAllocateMemory( wKeyDataSize, ( void ** ) &pKeyData ); + BAIL_ON_ERROR( dwError ); + + memcpy( pKeyData, pTKeyRecord->pRData + dwKeyDataOffset, + wKeyDataSize ); + + *ppKeyData = pKeyData; + *pwKeyDataSize = wKeyDataSize; + + return dwError; + + + error: + + *ppKeyData = NULL; + *pwKeyDataSize = 0; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSNegotiateSecureContext( HANDLE hDNSServer, + char *szDomain, + char *szServerName, + char *szKeyName, PCtxtHandle pGSSContext ) +{ + int32 dwError = 0; + int32 dwMajorStatus = 0; + char szUpperCaseDomain[256]; + char szTargetName[256]; + DNS_ERROR dns_status; + + gss_buffer_desc input_name; + gss_buffer_desc input_desc, output_desc; + DNS_REQUEST *pDNSRequest = NULL; + DNS_RESPONSE *pDNSResponse = NULL; + DNS_RR_RECORD *pClientTKeyRecord = NULL; + HANDLE hDNSTcpServer = ( HANDLE ) NULL; + + uint8 *pServerKeyData = NULL; + int16 wServerKeyDataSize = 0; + + OM_uint32 ret_flags = 0; + + int32 dwMinorStatus = 0; + gss_name_t targ_name; + gss_cred_id_t creds; + + krb5_principal host_principal; + krb5_context ctx = NULL; + + gss_OID_desc nt_host_oid_desc = + { 10, ( char * ) ( ( void * ) "\052\206\110\206\367\022\001\002\002\002" ) }; + gss_OID_desc krb5_oid_desc = + { 9, ( char * ) ( ( void * ) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" ) }; + + input_desc.value = NULL; + input_desc.length = 0; + + dns_status = DNSOpen( szServerName, DNS_TCP, &hDNSTcpServer ); + BAIL_ON_DNS_ERROR( dns_status ); + + + memset( szUpperCaseDomain, 0, sizeof( szUpperCaseDomain ) ); + memcpy( szUpperCaseDomain, szDomain, strlen( szDomain ) ); + strupr( szUpperCaseDomain ); + + dwMajorStatus = gss_acquire_cred( ( OM_uint32 * ) & dwMinorStatus, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_INITIATE, + &creds, NULL, NULL ); + BAIL_ON_SEC_ERROR( dwMajorStatus ); + printf( "After gss_acquire_cred %d\n", dwMajorStatus ); + + sprintf( szTargetName, "dns/%s@%s", szServerName, szUpperCaseDomain ); + printf( "%s\n", szTargetName ); + + krb5_init_context( &ctx ); + krb5_parse_name( ctx, szTargetName, &host_principal ); + krb5_free_context( ctx ); + + input_name.value = &host_principal; + input_name.length = sizeof( host_principal ); + + dwMajorStatus = gss_import_name( ( OM_uint32 * ) & dwMinorStatus, + &input_name, + &nt_host_oid_desc, &targ_name ); + printf( "After gss_import_name %d\n", dwMajorStatus ); + BAIL_ON_SEC_ERROR( dwMajorStatus ); + printf( "After gss_import_name %d\n", dwMajorStatus ); + + memset( pGSSContext, 0, sizeof( CtxtHandle ) ); + *pGSSContext = GSS_C_NO_CONTEXT; + + do { + + dwMajorStatus = gss_init_sec_context( ( OM_uint32 * ) & + dwMinorStatus, creds, + pGSSContext, targ_name, + &krb5_oid_desc, + GSS_C_REPLAY_FLAG | + GSS_C_MUTUAL_FLAG | + GSS_C_SEQUENCE_FLAG | + GSS_C_CONF_FLAG | + GSS_C_INTEG_FLAG | + GSS_C_DELEG_FLAG, 0, + NULL, &input_desc, NULL, + &output_desc, + &ret_flags, NULL ); + display_status( "gss_init_context", dwMajorStatus, + dwMinorStatus ); + BAIL_ON_SEC_ERROR( dwMajorStatus ); + printf( "After gss_init_sec_context %d\n", dwMajorStatus ); + + switch ( dwMajorStatus ) { + + case GSS_S_COMPLETE: + if ( output_desc.length != 0 ) { + + dwError = DNSBuildTKeyQueryRequest( szKeyName, + output_desc. + value, + output_desc. + length, + &pDNSRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSStdSendStdRequest2( hDNSTcpServer, + pDNSRequest ); + BAIL_ON_ERROR( dwError ); + + + dwError = + DNSStdReceiveStdResponse + ( hDNSTcpServer, &pDNSResponse ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSVerifyResponseMessage_GSSSuccess + ( pGSSContext, pClientTKeyRecord, + pDNSResponse ); + BAIL_ON_ERROR( dwError ); + } + break; + + + case GSS_S_CONTINUE_NEEDED: + if ( output_desc.length != 0 ) { + + dwError = DNSBuildTKeyQueryRequest( szKeyName, + output_desc. + value, + output_desc. + length, + &pDNSRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSStdSendStdRequest2( hDNSTcpServer, + pDNSRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSStdReceiveStdResponse + ( hDNSTcpServer, &pDNSResponse ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSVerifyResponseMessage_GSSContinue + ( pGSSContext, pClientTKeyRecord, + pDNSResponse, &pServerKeyData, + &wServerKeyDataSize ); + BAIL_ON_ERROR( dwError ); + + input_desc.value = pServerKeyData; + input_desc.length = wServerKeyDataSize; + } + break; + + default: + BAIL_ON_ERROR( dwError ); + } + + } while ( dwMajorStatus == GSS_S_CONTINUE_NEEDED ); + + /* If we arrive here, we have a valid security context */ + + sec_error: + error: + + return dwError; + +} + +/********************************************************************* +*********************************************************************/ + +static void display_status_1( const char *m, OM_uint32 code, int type ) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while ( 1 ) { + maj_stat = gss_display_status( &min_stat, code, + type, GSS_C_NULL_OID, + &msg_ctx, &msg ); + fprintf( stdout, "GSS-API error %s: %s\n", m, + ( char * ) msg.value ); + ( void ) gss_release_buffer( &min_stat, &msg ); + + if ( !msg_ctx ) + break; + } +} + +/********************************************************************* +*********************************************************************/ + +void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat ) +{ + display_status_1( msg, maj_stat, GSS_C_GSS_CODE ); + display_status_1( msg, min_stat, GSS_C_MECH_CODE ); +} diff --git a/source3/libaddns/dnsrecord.c b/source3/libaddns/dnsrecord.c new file mode 100644 index 0000000000..704d747ee9 --- /dev/null +++ b/source3/libaddns/dnsrecord.c @@ -0,0 +1,548 @@ +/* + Linux DNS client library implementation + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + +/********************************************************************* +*********************************************************************/ + +int32 DNSCreateDeleteRecord( char *szHost, int16 wClass, + int16 wType, DNS_RR_RECORD ** ppDNSRecord ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + + dwError = DNSDomainNameFromString( szHost, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + pDNSRRRecord->RRHeader.dwTTL = 0; + pDNSRRRecord->RRHeader.wClass = wClass; + pDNSRRRecord->RRHeader.wType = wType; + pDNSRRRecord->RRHeader.pDomainName = pDomainName; + pDNSRRRecord->RRHeader.wRDataSize = 0; + + *ppDNSRecord = pDNSRRRecord; + + return dwError; + error: + + if ( pDomainName ) { + DNSFreeDomainName( pDomainName ); + } + if ( pDNSRRRecord ) { + DNSFreeMemory( pDNSRRRecord ); + } + + *ppDNSRecord = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCreateARecord( char *szHost, int16 wClass, + int16 wType, int32 dwIP, DNS_RR_RECORD ** ppDNSRecord ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + uint8 *pRData = NULL; + int32 dwnIP = 0; + + dwError = DNSDomainNameFromString( szHost, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + pDNSRRRecord->RRHeader.wType = wType; + pDNSRRRecord->RRHeader.pDomainName = pDomainName; + + pDNSRRRecord->RRHeader.wClass = wClass; + pDNSRRRecord->RRHeader.wRDataSize = 0; + pDNSRRRecord->RRHeader.dwTTL = 0; + + if ( wClass != DNS_CLASS_ANY ) { + pDNSRRRecord->RRHeader.dwTTL = DNS_ONE_DAY_IN_SECS; + pDNSRRRecord->RRHeader.wRDataSize = sizeof( int32 ); + dwError = + DNSAllocateMemory( sizeof( int32 ), + ( void ** ) &pRData ); + dwnIP = htonl( dwIP ); + memcpy( pRData, &dwnIP, sizeof( int32 ) ); + pDNSRRRecord->pRData = pRData; + } + + *ppDNSRecord = pDNSRRRecord; + + return dwError; + error: + + if ( pDomainName ) { + DNSFreeDomainName( pDomainName ); + } + if ( pDNSRRRecord ) { + DNSFreeMemory( pDNSRRRecord ); + } + + if ( pDNSRRRecord ) { + DNSFreeMemory( pRData ); + } + *ppDNSRecord = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCreateTKeyRecord( char *szKeyName, uint8 * pKeyData, + int16 wKeySize, DNS_RR_RECORD ** ppDNSRecord ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pDNSRecord = NULL; + DNS_DOMAIN_NAME *pAlgorithmName = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + time_t t; + + int32 dwRDataSize = 0; + int32 dwnInception, dwInception = 0; + int32 dwnExpiration, dwExpiration = 0; + int16 wnMode, wMode = 0; + int16 wnError, wError = 0; + int16 wnKeySize = 0; + int16 wnOtherSize, wOtherSize = 0; + + int32 dwAlgorithmLen = 0; + int32 dwCopied = 0; + int32 dwOffset = 0; + + uint8 *pRData = NULL; + + char szTemp[20]; + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSDomainNameFromString( szKeyName, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + strncpy( szTemp, "gss.microsoft.com", sizeof( szTemp ) ); + dwError = DNSDomainNameFromString( szTemp, &pAlgorithmName ); + BAIL_ON_ERROR( dwError ); + + pDNSRecord->RRHeader.dwTTL = 0; + pDNSRecord->RRHeader.pDomainName = pDomainName; + pDNSRecord->RRHeader.wClass = DNS_CLASS_ANY; + pDNSRecord->RRHeader.wType = QTYPE_TKEY; + + time( &t ); + dwExpiration = ( int32 ) t + DNS_ONE_DAY_IN_SECS; + dwInception = ( int32 ) t; + wError = 0; + wMode = 3; + + dwError = DNSGetDomainNameLength( pAlgorithmName, &dwAlgorithmLen ); + BAIL_ON_ERROR( dwError ); + + dwRDataSize = dwAlgorithmLen + + sizeof( dwExpiration ) + sizeof( dwInception ) + + sizeof( wError ) + sizeof( wMode ) + +sizeof( wError ) + + sizeof( wKeySize ) + wKeySize + sizeof( wOtherSize ) + + wOtherSize; + + dwError = DNSAllocateMemory( dwRDataSize, ( void ** ) &pRData ); + BAIL_ON_ERROR( dwError ); + + dwnInception = htonl( dwInception ); + dwnExpiration = htonl( dwExpiration ); + wnMode = htons( wMode ); + wnError = htons( wError ); + wnKeySize = htons( wKeySize ); + wnOtherSize = htons( wOtherSize ); + + dwError = DNSCopyDomainName( pRData, pAlgorithmName, &dwCopied ); + BAIL_ON_ERROR( dwError ); + dwOffset += dwCopied; + + memcpy( pRData + dwOffset, &dwnInception, sizeof( int32 ) ); + dwOffset += sizeof( int32 ); + + memcpy( pRData + dwOffset, &dwnExpiration, sizeof( int32 ) ); + dwOffset += sizeof( int32 ); + + memcpy( pRData + dwOffset, &wnMode, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + memcpy( pRData + dwOffset, &wnError, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + memcpy( pRData + dwOffset, &wnKeySize, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + memcpy( pRData + dwOffset, pKeyData, wKeySize ); + dwOffset += wKeySize; + + memcpy( pRData + dwOffset, &wnOtherSize, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + pDNSRecord->RRHeader.wRDataSize = ( int16 ) dwRDataSize; + + pDNSRecord->pRData = pRData; + *ppDNSRecord = pDNSRecord; + + return dwError; + + error: + + + if ( pDNSRecord ) { + DNSFreeMemory( pDNSRecord ); + } + + if ( pDomainName ) { + DNSFreeDomainName( pDomainName ); + } + + if ( pAlgorithmName ) { + DNSFreeDomainName( pAlgorithmName ); + } + + *ppDNSRecord = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCreateTSIGRecord( char *szKeyName, int32 dwTimeSigned, + int16 wFudge, int16 wOriginalID, uint8 * pMac, + int16 wMacSize, DNS_RR_RECORD ** ppDNSRecord ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pDNSRecord = NULL; + DNS_DOMAIN_NAME *pAlgorithmName = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + time_t t; + + int32 dwRDataSize = 0; + + int16 wnFudge = 0; + int16 wnError = 0, wError = 0; + int16 wnMacSize = 0; + int16 wnOriginalID = 0; + int16 wnOtherLen = 0, wOtherLen = 0; + + int32 dwAlgorithmLen = 0; + int32 dwCopied = 0; + int32 dwOffset = 0; + + uint8 *pRData = NULL; + + int32 dwnTimeSigned = 0; + int16 wnTimePrefix = 0; + int16 wTimePrefix = 0; + + char szTemp[20]; + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSDomainNameFromString( szKeyName, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + strncpy( szTemp, "gss.microsoft.com", sizeof( szTemp ) ); + dwError = DNSDomainNameFromString( szTemp, &pAlgorithmName ); + BAIL_ON_ERROR( dwError ); + + pDNSRecord->RRHeader.dwTTL = 0; + pDNSRecord->RRHeader.pDomainName = pDomainName; + pDNSRecord->RRHeader.wClass = DNS_CLASS_ANY; + pDNSRecord->RRHeader.wType = QTYPE_TSIG; + + /* This needs to be a 48bit value - 6 octets. */ + + time( &t ); + + dwError = DNSGetDomainNameLength( pAlgorithmName, &dwAlgorithmLen ); + BAIL_ON_ERROR( dwError ); + + dwRDataSize = dwAlgorithmLen + 6 + sizeof( wFudge ) + sizeof( wMacSize ) + + wMacSize + sizeof( wOriginalID ) + sizeof( wError ) + + sizeof( wOtherLen ); + + dwError = DNSAllocateMemory( dwRDataSize, ( void ** ) &pRData ); + BAIL_ON_ERROR( dwError ); + + /* Convert t to 48 bit network order */ + + wnTimePrefix = htons( wTimePrefix ); + dwnTimeSigned = htonl( dwTimeSigned ); + wnFudge = htons( wFudge ); + wnMacSize = htons( wMacSize ); + wnOriginalID = htons( wOriginalID ); + wnError = htons( wError ); + wnOtherLen = htons( wOtherLen ); + + dwError = DNSCopyDomainName( pRData, pAlgorithmName, &dwCopied ); + BAIL_ON_ERROR( dwError ); + dwOffset += dwCopied; + + memcpy( pRData + dwOffset, &wnTimePrefix, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + memcpy( pRData + dwOffset, &dwnTimeSigned, sizeof( int32 ) ); + dwOffset += sizeof( int32 ); + + memcpy( pRData + dwOffset, &wnFudge, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + + memcpy( pRData + dwOffset, &wnMacSize, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + memcpy( pRData + dwOffset, pMac, wMacSize ); + dwOffset += wMacSize; + + memcpy( pRData + dwOffset, &wnOriginalID, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + memcpy( pRData + dwOffset, &wnError, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + memcpy( pRData + dwOffset, &wnOtherLen, sizeof( int16 ) ); + dwOffset += sizeof( int16 ); + + pDNSRecord->RRHeader.wRDataSize = ( int16 ) dwRDataSize; + + pDNSRecord->pRData = pRData; + *ppDNSRecord = pDNSRecord; + + return dwError; + + error: + + + if ( pDNSRecord ) { + DNSFreeMemory( pDNSRecord ); + } + + if ( pDomainName ) { + DNSFreeDomainName( pDomainName ); + } + + if ( pAlgorithmName ) { + DNSFreeDomainName( pAlgorithmName ); + } + + *ppDNSRecord = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCreateQuestionRecord( char *pszQName, int16 wQType, + int16 wQClass, + DNS_QUESTION_RECORD ** ppDNSQuestionRecord ) +{ + int32 dwError = 0; + DNS_QUESTION_RECORD *pDNSQuestionRecord = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + + dwError = DNSDomainNameFromString( pszQName, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_QUESTION_RECORD ), + ( void ** ) &pDNSQuestionRecord ); + BAIL_ON_ERROR( dwError ); + + pDNSQuestionRecord->pDomainName = pDomainName; + pDNSQuestionRecord->wQueryClass = wQClass; + pDNSQuestionRecord->wQueryType = wQType; + + *ppDNSQuestionRecord = pDNSQuestionRecord; + + return dwError; + error: + + if ( pDomainName ) { + DNSFreeDomainName( pDomainName ); + } + if ( pDNSQuestionRecord ) { + DNSFreeMemory( pDNSQuestionRecord ); + } + *ppDNSQuestionRecord = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCreateZoneRecord( char *pszZName, DNS_ZONE_RECORD ** ppDNSZoneRecord ) +{ + int32 dwError = 0; + DNS_ZONE_RECORD *pDNSZoneRecord = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + + dwError = DNSDomainNameFromString( pszZName, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_ZONE_RECORD ), + ( void ** ) &pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + pDNSZoneRecord->pDomainName = pDomainName; + pDNSZoneRecord->wZoneClass = DNS_CLASS_IN; + pDNSZoneRecord->wZoneType = QTYPE_SOA; + + *ppDNSZoneRecord = pDNSZoneRecord; + + return dwError; + error: + + if ( pDomainName ) { + DNSFreeDomainName( pDomainName ); + } + if ( pDNSZoneRecord ) { + DNSFreeMemory( pDNSZoneRecord ); + } + *ppDNSZoneRecord = NULL; + return dwError; +} + +int32 DNSFreeZoneRecord( DNS_ZONE_RECORD * pDNSZoneRecord ) +{ + int32 dwError = 0; + + return dwError; + +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCreateNameInUseRecord( char *pszName, int32 qtype, + struct in_addr * ip, + DNS_RR_RECORD * *ppDNSRRRecord ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + + dwError = DNSDomainNameFromString( pszName, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + pDNSRRRecord->RRHeader.pDomainName = pDomainName; + pDNSRRRecord->RRHeader.dwTTL = 0; + pDNSRRRecord->RRHeader.wType = qtype; + + if ( !ip ) { + pDNSRRRecord->RRHeader.wClass = DNS_CLASS_ANY; + pDNSRRRecord->RRHeader.wRDataSize = 0; + } else { + pDNSRRRecord->RRHeader.wClass = DNS_CLASS_IN; + pDNSRRRecord->RRHeader.wRDataSize = 4; + dwError = + DNSAllocateMemory( 4, + ( void ** ) &pDNSRRRecord-> + pRData ); + BAIL_ON_ERROR( dwError ); + memcpy( pDNSRRRecord->pRData, &ip->s_addr, 4 ); + } + + *ppDNSRRRecord = pDNSRRRecord; + + return dwError; + error: + + if ( pDomainName ) { + DNSFreeDomainName( pDomainName ); + } + if ( pDNSRRRecord ) { + DNSFreeMemory( pDNSRRRecord ); + } + *ppDNSRRRecord = NULL; + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCreateNameNotInUseRecord( char *pszName, int32 qtype, + DNS_RR_RECORD * *ppDNSRRRecord ) +{ + int32 dwError = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + + dwError = DNSDomainNameFromString( pszName, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + pDNSRRRecord->RRHeader.pDomainName = pDomainName; + pDNSRRRecord->RRHeader.wClass = DNS_CLASS_NONE; + pDNSRRRecord->RRHeader.wType = qtype; + pDNSRRRecord->RRHeader.dwTTL = 0; + pDNSRRRecord->RRHeader.wRDataSize = 0; + + *ppDNSRRRecord = pDNSRRRecord; + + return dwError; + error: + + if ( pDomainName ) { + DNSFreeDomainName( pDomainName ); + } + if ( pDNSRRRecord ) { + DNSFreeMemory( pDNSRRRecord ); + } + *ppDNSRRRecord = NULL; + return dwError; + +} + diff --git a/source3/libaddns/dnsrequest.c b/source3/libaddns/dnsrequest.c new file mode 100644 index 0000000000..3dd402981f --- /dev/null +++ b/source3/libaddns/dnsrequest.c @@ -0,0 +1,478 @@ +/* + Linux DNS client library implementation + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdMarshallQuestionSection( HANDLE hSendBuffer, + DNS_QUESTION_RECORD ** ppDNSQuestionRecords, + int16 wQuestions ) +{ + int32 dwError = 0; + int32 i = 0; + int32 dwRead = 0; + DNS_QUESTION_RECORD *pDNSQuestionRecord = NULL; + int16 wnQueryType = 0; + int16 wnQueryClass = 0; + + for ( i = 0; i < wQuestions; i++ ) { + + pDNSQuestionRecord = *( ppDNSQuestionRecords + i ); + dwError = + DNSMarshallDomainName( hSendBuffer, + pDNSQuestionRecord-> + pDomainName ); + BAIL_ON_ERROR( dwError ); + + wnQueryType = htons( pDNSQuestionRecord->wQueryType ); + dwError = + DNSMarshallBuffer( hSendBuffer, + ( uint8 * ) & wnQueryType, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + + wnQueryClass = htons( pDNSQuestionRecord->wQueryClass ); + dwError = + DNSMarshallBuffer( hSendBuffer, + ( uint8 * ) & wnQueryClass, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + + pDNSQuestionRecord++; + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdMarshallAnswerSection( HANDLE hSendBuffer, + DNS_RR_RECORD ** ppDNSAnswerRRRecords, + int16 wAnswers ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSAnswerRRRecord = NULL; + + + for ( i = 0; i < wAnswers; i++ ) { + + pDNSAnswerRRRecord = *( ppDNSAnswerRRRecords + i ); + + dwError = + DNSMarshallRRHeader( hSendBuffer, + pDNSAnswerRRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSMarshallRData( hSendBuffer, pDNSAnswerRRRecord ); + BAIL_ON_ERROR( dwError ); + + pDNSAnswerRRRecord++; + + } + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdMarshallAuthoritySection( HANDLE hSendBuffer, + DNS_RR_RECORD ** ppDNSAuthorityRRRecords, + int16 wAuthoritys ) +{ + int32 dwError = 0; + int32 i = 0; + + DNS_RR_RECORD *pDNSAuthorityRRRecord = NULL; + + for ( i = 0; i < wAuthoritys; i++ ) { + + pDNSAuthorityRRRecord = *( ppDNSAuthorityRRRecords + i ); + + dwError = + DNSMarshallRRHeader( hSendBuffer, + pDNSAuthorityRRRecord ); + + dwError = DNSMarshallRData( hSendBuffer, + pDNSAuthorityRRRecord ); + BAIL_ON_ERROR( dwError ); + + } + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdMarshallAdditionalSection( HANDLE hSendBuffer, + DNS_RR_RECORD ** ppDNSAdditionalsRRRecords, + int16 wAdditionals ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSAdditionalRRRecord = NULL; + + for ( i = 0; i < wAdditionals; i++ ) { + + pDNSAdditionalRRRecord = *( ppDNSAdditionalsRRRecords + i ); + + dwError = + DNSMarshallRRHeader( hSendBuffer, + pDNSAdditionalRRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSMarshallRData( hSendBuffer, + pDNSAdditionalRRRecord ); + BAIL_ON_ERROR( dwError ); + + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSBuildRequestMessage( DNS_REQUEST * pDNSRequest, HANDLE * phSendBuffer ) +{ + int32 dwError = 0; + char DNSMessageHeader[12]; + int16 wnIdentification = 0; + int16 wnParameter = 0; + int16 wnQuestions = 0; + int16 wnAnswers = 0; + int16 wnAuthoritys = 0; + int16 wnAdditionals = 0; + int32 dwRead = 0; + HANDLE hSendBuffer = ( HANDLE ) NULL; + + dwError = DNSCreateSendBuffer( &hSendBuffer ); + BAIL_ON_ERROR( dwError ); + + wnIdentification = htons( pDNSRequest->wIdentification ); + memcpy( DNSMessageHeader, ( char * ) &wnIdentification, 2 ); + + wnParameter = htons( pDNSRequest->wParameter ); + memcpy( DNSMessageHeader + 2, ( char * ) &wnParameter, 2 ); + + wnQuestions = htons( pDNSRequest->wQuestions ); + memcpy( DNSMessageHeader + 4, ( char * ) &wnQuestions, 2 ); + + wnAnswers = htons( pDNSRequest->wAnswers ); + memcpy( DNSMessageHeader + 6, ( char * ) &wnAnswers, 2 ); + + wnAuthoritys = htons( pDNSRequest->wAuthoritys ); + memcpy( DNSMessageHeader + 8, ( char * ) &wnAuthoritys, 2 ); + + wnAdditionals = htons( pDNSRequest->wAdditionals ); + memcpy( DNSMessageHeader + 10, ( char * ) &wnAdditionals, 2 ); + + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) DNSMessageHeader, + 12, &dwRead ); + BAIL_ON_ERROR( dwError ); + + if ( pDNSRequest->wQuestions ) { + dwError = + DNSStdMarshallQuestionSection( hSendBuffer, + pDNSRequest-> + ppQuestionRRSet, + pDNSRequest-> + wQuestions ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wAnswers ) { + dwError = + DNSStdMarshallAnswerSection( hSendBuffer, + pDNSRequest-> + ppAnswerRRSet, + pDNSRequest->wAnswers ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wAuthoritys ) { + dwError = + DNSStdMarshallAuthoritySection( hSendBuffer, + pDNSRequest-> + ppAuthorityRRSet, + pDNSRequest-> + wAuthoritys ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wAdditionals ) { + dwError = + DNSStdMarshallAdditionalSection( hSendBuffer, + pDNSRequest-> + ppAdditionalRRSet, + pDNSRequest-> + wAdditionals ); + BAIL_ON_ERROR( dwError ); + } +#if 0 + DNSDumpSendBufferContext( hSendBuffer ); +#endif + *phSendBuffer = hSendBuffer; + + return dwError; + + error: + + if ( hSendBuffer ) { + DNSFreeSendBufferContext( hSendBuffer ); + } + + *phSendBuffer = ( HANDLE ) NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdSendStdRequest2( HANDLE hDNSServer, DNS_REQUEST * pDNSRequest ) +{ + int32 dwError = 0; + int32 dwBytesSent = 0; + HANDLE hSendBuffer = ( HANDLE ) NULL; + + dwError = DNSBuildRequestMessage( pDNSRequest, &hSendBuffer ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSSendBufferContext( hDNSServer, hSendBuffer, &dwBytesSent ); + BAIL_ON_ERROR( dwError ); + + error: + + if ( hSendBuffer ) { + DNSFreeSendBufferContext( hSendBuffer ); + } + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSMarshallDomainName( HANDLE hSendBuffer, DNS_DOMAIN_NAME * pDomainName ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pTemp = NULL; + int32 dwLen = 0; + int32 dwSent = 0; + char uEndChar = 0; + + pTemp = pDomainName->pLabelList; + while ( pTemp ) { + dwLen = ( int32 ) strlen( pTemp->pszLabel ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & dwLen, + sizeof( char ), &dwSent ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSMarshallBuffer( hSendBuffer, + ( uint8 * ) pTemp->pszLabel, dwLen, + &dwSent ); + BAIL_ON_ERROR( dwError ); + pTemp = pTemp->pNext; + } + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & uEndChar, + sizeof( char ), &dwSent ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSMarshallRRHeader( HANDLE hSendBuffer, DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwError = 0; + int32 dwRead = 0; + int16 wnType = 0; + int16 wnClass = 0; + int16 wnRDataSize = 0; + int32 dwnTTL = 0; + + dwError = + DNSMarshallDomainName( hSendBuffer, + pDNSRecord->RRHeader.pDomainName ); + BAIL_ON_ERROR( dwError ); + + wnType = htons( pDNSRecord->RRHeader.wType ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & wnType, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + wnClass = htons( pDNSRecord->RRHeader.wClass ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & wnClass, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwnTTL = htonl( pDNSRecord->RRHeader.dwTTL ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & dwnTTL, + sizeof( int32 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + wnRDataSize = htons( pDNSRecord->RRHeader.wRDataSize ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & wnRDataSize, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSMarshallRData( HANDLE hSendBuffer, DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwError = 0; + int32 dwWritten = 0; + + dwError = + DNSMarshallBuffer( hSendBuffer, pDNSRecord->pRData, + pDNSRecord->RRHeader.wRDataSize, + &dwWritten ); + BAIL_ON_ERROR( dwError ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdAddQuestionSection( DNS_REQUEST * pDNSRequest, + DNS_QUESTION_RECORD * pDNSQuestion ) +{ + int32 dwNumQuestions = 0; + int32 dwError = 0; + + dwNumQuestions = pDNSRequest->wQuestions; + + dwError = DNSReallocMemory( ( uint8 * ) pDNSRequest->ppQuestionRRSet, + ( void ** ) &pDNSRequest->ppQuestionRRSet, + ( dwNumQuestions + + 1 ) * sizeof( DNS_QUESTION_RECORD * ) + ); + BAIL_ON_ERROR( dwError ); + + *( pDNSRequest->ppQuestionRRSet + dwNumQuestions ) = pDNSQuestion; + + pDNSRequest->wQuestions += 1; + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdAddAdditionalSection( DNS_REQUEST * pDNSRequest, + DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwNumAdditionals = 0; + int32 dwError = 0; + + dwNumAdditionals = pDNSRequest->wAdditionals; + dwError = DNSReallocMemory( pDNSRequest->ppAdditionalRRSet, + ( void ** ) &pDNSRequest-> + ppAdditionalRRSet, + ( dwNumAdditionals + + 1 ) * sizeof( DNS_RR_RECORD * ) ); + BAIL_ON_ERROR( dwError ); + + *( pDNSRequest->ppAdditionalRRSet + dwNumAdditionals ) = pDNSRecord; + + pDNSRequest->wAdditionals += 1; + + error: + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdCreateStdRequest( DNS_REQUEST ** ppDNSRequest ) +{ + int32 dwError = 0; + DNS_REQUEST *pDNSRequest = NULL; + +#if 0 + int16 wRecursionDesired = RECURSION_DESIRED; + int16 wParameter = QR_QUERY; + int16 wOpcode = OPCODE_QUERY; +#endif + dwError = + DNSAllocateMemory( sizeof( DNS_REQUEST ), + ( void ** ) &pDNSRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSGenerateIdentifier( &pDNSRequest->wIdentification ); + BAIL_ON_ERROR( dwError ); + +/* + wOpcode <<= 1; + wRecursionDesired <<= 7; + wParameter |= wOpcode; + wParameter |= wRecursionDesired; +*/ + pDNSRequest->wParameter = 0x00; + + *ppDNSRequest = pDNSRequest; + + return dwError; + + error: + + *ppDNSRequest = NULL; + return dwError; +} diff --git a/source3/libaddns/dnsresponse.c b/source3/libaddns/dnsresponse.c new file mode 100644 index 0000000000..65a8853049 --- /dev/null +++ b/source3/libaddns/dnsresponse.c @@ -0,0 +1,589 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdAllocateResponse( DNS_RESPONSE ** ppDNSResponse ) +{ + int32 dwError = 0; + DNS_RESPONSE *pDNSResponse = NULL; + + dwError = + DNSAllocateMemory( sizeof( DNS_RESPONSE ), + ( void ** ) &pDNSResponse ); + BAIL_ON_ERROR( dwError ); + + *ppDNSResponse = pDNSResponse; + + return dwError; + + error: + + *ppDNSResponse = NULL; + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdUnmarshallQuestionSection( HANDLE hReceiveBuffer, + int16 wQuestions, + DNS_QUESTION_RECORD * + **pppDNSQuestionRecords ) +{ + int32 dwError = 0; + int32 i = 0; + int32 dwRead = 0; + DNS_QUESTION_RECORD *pDNSQuestionRecord = NULL; + DNS_QUESTION_RECORD **ppDNSQuestionRecords = NULL; + int16 wnQueryClass = 0; + int16 wnQueryType = 0; + + + dwError = + DNSAllocateMemory( wQuestions * + sizeof( DNS_QUESTION_RECORD * ), + ( void ** ) &ppDNSQuestionRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wQuestions; i++ ) { + + dwError = + DNSAllocateMemory( sizeof( DNS_QUESTION_RECORD ), + ( void ** ) &pDNSQuestionRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallDomainName( hReceiveBuffer, + &pDNSQuestionRecord-> + pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallBuffer( hReceiveBuffer, + ( uint8 * ) & wnQueryType, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + pDNSQuestionRecord->wQueryType = ntohs( wnQueryType ); + + dwError = + DNSUnmarshallBuffer( hReceiveBuffer, + ( uint8 * ) & wnQueryClass, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + pDNSQuestionRecord->wQueryClass = ntohs( wnQueryClass ); + + *( ppDNSQuestionRecords + i ) = pDNSQuestionRecord; + } + + *pppDNSQuestionRecords = ppDNSQuestionRecords; + return dwError; + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdUnmarshallAnswerSection( HANDLE hReceiveBuffer, + int16 wAnswers, + DNS_RR_RECORD * **pppDNSAnswerRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSAnswerRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wAnswers * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSAnswerRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wAnswers; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRData; + + *( ppDNSAnswerRRRecords + i ) = pDNSRRRecord; + } + + *pppDNSAnswerRRRecords = ppDNSAnswerRRRecords; + + return dwError; + + error: + + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdUnmarshallAuthoritySection( HANDLE hReceiveBuffer, + int16 wAuthoritys, + DNS_RR_RECORD * **pppDNSAuthorityRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSAuthorityRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wAuthoritys * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSAuthorityRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wAuthoritys; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRData; + + *( ppDNSAuthorityRRRecords + i ) = pDNSRRRecord; + } + + *pppDNSAuthorityRRRecords = ppDNSAuthorityRRRecords; + + return dwError; + + error: + + return dwError; + +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdUnmarshallAdditionalSection( HANDLE hReceiveBuffer, + int16 wAdditionals, + DNS_RR_RECORD * + **pppDNSAdditionalsRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSAdditionalRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wAdditionals * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSAdditionalRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wAdditionals; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRData; + + + *( ppDNSAdditionalRRRecords + i ) = pDNSRRRecord; + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdReceiveStdResponse( HANDLE hDNSHandle, DNS_RESPONSE ** ppDNSResponse ) +{ + DNS_RESPONSE *pDNSResponse = NULL; + int32 dwError = 0; + int16 wnIdentification, wIdentification = 0; + int16 wnParameter, wParameter = 0; + int16 wnQuestions, wQuestions = 0; + int16 wnAnswers, wAnswers = 0; + int16 wnAdditionals, wAdditionals = 0; + int16 wnAuthoritys, wAuthoritys = 0; + int32 dwRead = 0; + DNS_RR_RECORD **ppDNSAnswerRecords = NULL; + DNS_RR_RECORD **ppDNSAdditionalRecords = NULL; + DNS_RR_RECORD **ppDNSAuthorityRecords = NULL; + DNS_QUESTION_RECORD **ppDNSQuestionRecords = NULL; + HANDLE hRecvBuffer = ( HANDLE ) NULL; + + dwError = DNSCreateReceiveBuffer( &hRecvBuffer ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSReceiveBufferContext( hDNSHandle, hRecvBuffer, &dwRead ); + BAIL_ON_ERROR( dwError ); + +#if 0 + dwError = DNSDumpRecvBufferContext( hRecvBuffer ); + BAIL_ON_ERROR( dwError ); +#endif + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, + ( uint8 * ) & wnIdentification, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wIdentification = ntohs( wnIdentification ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnParameter, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wParameter = ntohs( wnParameter ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnQuestions, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wQuestions = ntohs( wnQuestions ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnAnswers, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wAnswers = ntohs( wnAnswers ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnAuthoritys, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wAuthoritys = ntohs( wnAuthoritys ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnAdditionals, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wAdditionals = ntohs( wnAdditionals ); + + + if ( wQuestions ) { + dwError = + DNSStdUnmarshallQuestionSection( hRecvBuffer, + wQuestions, + &ppDNSQuestionRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wAnswers ) { + dwError = + DNSStdUnmarshallAnswerSection( hRecvBuffer, wAnswers, + &ppDNSAnswerRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wAuthoritys ) { + dwError = + DNSStdUnmarshallAuthoritySection( hRecvBuffer, + wAuthoritys, + &ppDNSAuthorityRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wAdditionals ) { + dwError = + DNSStdUnmarshallAdditionalSection( hRecvBuffer, + wAdditionals, + &ppDNSAdditionalRecords ); + BAIL_ON_ERROR( dwError ); + } + + dwError = DNSStdAllocateResponse( &pDNSResponse ); + BAIL_ON_ERROR( dwError ); + + pDNSResponse->wIdentification = wIdentification; + pDNSResponse->wParameter = wParameter; + pDNSResponse->wQuestions = wQuestions; + pDNSResponse->wAnswers = wAnswers; + pDNSResponse->wAuthoritys = wAuthoritys; + pDNSResponse->wAdditionals = wAdditionals; + + pDNSResponse->ppQuestionRRSet = ppDNSQuestionRecords; + pDNSResponse->ppAnswerRRSet = ppDNSAnswerRecords; + pDNSResponse->ppAuthorityRRSet = ppDNSAuthorityRecords; + pDNSResponse->ppAdditionalRRSet = ppDNSAdditionalRecords; + + *ppDNSResponse = pDNSResponse; + + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUnmarshallDomainName( HANDLE hRecvBuffer, DNS_DOMAIN_NAME ** ppDomainName ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pLabel = NULL; + DNS_DOMAIN_LABEL *pLabelList = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + char *pszLabel = NULL; + char szLabel[65]; + uint8 uLen = 0; + int32 dwRead = 0; + uint8 uLen1, uLen2 = 0; + int16 wnOffset, wOffset = 0; + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, &uLen1, sizeof( char ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + if ( uLen1 & 0xC0 ) { + + uLen1 |= 0x3F; + dwError = + DNSUnmarshallBuffer( hRecvBuffer, &uLen2, + sizeof( char ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + memcpy( ( uint8 * ) & wnOffset, &uLen1, sizeof( char ) ); + memcpy( ( uint8 * ) & wnOffset + 1, &uLen2, sizeof( char ) ); + wOffset = ntohs( wnOffset ); + + dwError = + DNSUnmarshallDomainNameAtOffset( hRecvBuffer, wOffset, + &pDomainName ); + BAIL_ON_ERROR( dwError ); + *ppDomainName = pDomainName; + + return dwError; + + } else { + + dwError = DNSReceiveBufferMoveBackIndex( hRecvBuffer, 1 ); + BAIL_ON_ERROR( dwError ); + + while ( 1 ) { + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, &uLen, + sizeof( char ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + if ( uLen == 0 ) { + break; + } + + memset( szLabel, 0, 65 ); + dwError = + DNSUnmarshallBuffer( hRecvBuffer, + ( uint8 * ) szLabel, + uLen, &dwRead ); + + dwError = DNSAllocateString( szLabel, &pszLabel ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_LABEL ), + ( void ** ) &pLabel ); + BAIL_ON_ERROR( dwError ); + + pLabel->pszLabel = pszLabel; + dwError = + DNSAppendLabel( pLabelList, pLabel, + &pLabelList ); + BAIL_ON_ERROR( dwError ); + } + + } + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_NAME ), + ( void ** ) &pDomainName ); + BAIL_ON_ERROR( dwError ); + pDomainName->pLabelList = pLabelList; + + *ppDomainName = pDomainName; + + return dwError; + + error: + + *ppDomainName = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUnmarshallRRHeader( HANDLE hRecvBuffer, DNS_RR_HEADER * pRRHeader ) +{ + int32 dwError = 0; + int32 dwRead = 0; + int16 wnType = 0; + int16 wnClass = 0; + int16 wnRDataSize = 0; + int32 dwnTTL = 0; + + dwError = + DNSUnmarshallDomainName( hRecvBuffer, + &pRRHeader->pDomainName ); + BAIL_ON_ERROR( dwError ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnType, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + pRRHeader->wType = ntohs( wnType ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnClass, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + pRRHeader->wClass = ntohs( wnClass ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & dwnTTL, + sizeof( int32 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + pRRHeader->dwTTL = ntohl( dwnTTL ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnRDataSize, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + pRRHeader->wRDataSize = htons( wnRDataSize ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUnmarshallRData( HANDLE hRecvBuffer, + int32 dwSize, uint8 ** ppRData, int32 * pdwRead ) +{ + int32 dwError = 0; + uint8 *pMemory = NULL; + + dwError = DNSAllocateMemory( dwSize, ( void ** ) &pMemory ); + BAIL_ON_ERROR( dwError ); + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) pMemory, dwSize, + pdwRead ); + BAIL_ON_ERROR( dwError ); + + *ppRData = pMemory; + + return dwError; + + error: + + if ( pMemory ) { + DNSFreeMemory( pMemory ); + } + + *ppRData = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateGetResponseCode( DNS_UPDATE_RESPONSE * pDNSUpdateResponse, + int32 * pdwResponseCode ) +{ + int32 dwError = 0; + + *pdwResponseCode = + MapDNSResponseCodes( pDNSUpdateResponse->wParameter ); + + return dwError; +} + diff --git a/source3/libaddns/dnssign.c b/source3/libaddns/dnssign.c new file mode 100644 index 0000000000..b7989c6b1d --- /dev/null +++ b/source3/libaddns/dnssign.c @@ -0,0 +1,52 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdValidateAndGetTSIGRecord( CtxtHandle * gss_context, + DNS_RESPONSE * pDNSResponse, + DNS_RR_RECORD ** ppDNSTSIGRecord ) +{ + int32 dwError = 0; + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateValidateAndGetTSIGRecord( CtxtHandle * gss_context, + DNS_UPDATE_RESPONSE * pDNSUpdateResponse, + DNS_RR_RECORD ** ppDNSTSIGRecord ) +{ + int32 dwError = 0; + + return dwError; +} diff --git a/source3/libaddns/dnssock.c b/source3/libaddns/dnssock.c new file mode 100644 index 0000000000..0af30cc1be --- /dev/null +++ b/source3/libaddns/dnssock.c @@ -0,0 +1,766 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + +/******************************************************************** +********************************************************************/ + +static DNS_ERROR DNSTCPOpen( char *nameserver, HANDLE * phDNSServer ) +{ + DNS_ERROR dwError = ERROR_DNS_INVALID_PARAMETER; + int sockServer; + unsigned long ulAddress; + struct hostent *pHost; + struct sockaddr_in s_in; + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + + if ( (pDNSContext = TALLOC_P( NULL, DNS_CONNECTION_CONTEXT )) == NULL ) { + return ERROR_DNS_NO_MEMORY; + } + + if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) { + if ( (pHost = gethostbyname( nameserver )) == NULL ) { + dwError = ERROR_DNS_INVALID_NAME_SERVER; + BAIL_ON_DNS_ERROR( dwError ); + } + memcpy( &ulAddress, pHost->h_addr, pHost->h_length ); + } + + if ( (sockServer = socket( PF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET ) { + dwError = ERROR_DNS_NO_MEMORY; + BAIL_ON_DNS_ERROR( dwError ); + } + + s_in.sin_family = AF_INET; + s_in.sin_addr.s_addr = ulAddress; + s_in.sin_port = htons( DNS_TCP_PORT ); + + if ( (connect( sockServer, &s_in, sizeof( s_in ))) == SOCKET_ERROR ) { + dwError = ERROR_DNS_CONNECTION_FAILED; + BAIL_ON_DNS_ERROR( dwError ); + } + + pDNSContext->s = sockServer; + pDNSContext->hType = DNS_TCP; + + *phDNSServer = ( HANDLE ) pDNSContext; + + dwError = ERROR_DNS_SUCCESS; + + return dwError; + +error: + TALLOC_FREE( pDNSContext ); + *phDNSServer = ( HANDLE ) NULL; + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static DNS_ERROR DNSUDPOpen( char *nameserver, HANDLE * phDNSServer ) +{ + DNS_ERROR dwError = ERROR_DNS_INVALID_PARAMETER; + int SendSocket; + unsigned long ulAddress; + struct hostent *pHost; + struct sockaddr_in RecvAddr; + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + + if ( (pDNSContext = TALLOC_P( NULL, DNS_CONNECTION_CONTEXT )) == NULL ) { + return ERROR_DNS_NO_MEMORY; + } + + if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) { + if ( (pHost = gethostbyname( nameserver )) == NULL ) { + dwError = ERROR_DNS_INVALID_NAME_SERVER; + BAIL_ON_DNS_ERROR( dwError ); + } + memcpy( &ulAddress, pHost->h_addr, pHost->h_length ); + } + + /* Create a socket for sending data */ + + SendSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + + /* Set up the RecvAddr structure with the IP address of + the receiver (in this example case "123.456.789.1") + and the specified port number. */ + + RecvAddr.sin_family = AF_INET; + RecvAddr.sin_port = htons( DNS_UDP_PORT ); + RecvAddr.sin_addr.s_addr = ulAddress; + + pDNSContext->s = SendSocket; + pDNSContext->hType = DNS_UDP; + memcpy( &pDNSContext->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) ); + + *phDNSServer = ( HANDLE ) pDNSContext; + + dwError = ERROR_DNS_SUCCESS; + + return dwError; + +error: + TALLOC_FREE( pDNSContext ); + *phDNSServer = ( HANDLE ) NULL; + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +DNS_ERROR DNSOpen( char *nameserver, int32 dwType, HANDLE * phDNSServer ) +{ + switch ( dwType ) { + case DNS_TCP: + return DNSTCPOpen( nameserver, phDNSServer ); + case DNS_UDP: + return DNSUDPOpen( nameserver, phDNSServer ); + } + + return ERROR_DNS_INVALID_PARAMETER; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSSendTCPRequest( HANDLE hDNSHandle, + uint8 * pDNSSendBuffer, + int32 dwBufferSize, int32 * pdwBytesSent ) +{ + int32 dwError = 0; + int32 dwBytesSent = 0; + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + + + pDNSContext = ( DNS_CONNECTION_CONTEXT * ) hDNSHandle; + + dwBytesSent = send( pDNSContext->s, pDNSSendBuffer, dwBufferSize, 0 ); + if ( dwBytesSent == SOCKET_ERROR ) { + dwError = WSAGetLastError( ); + BAIL_ON_ERROR( dwError ); + } + + *pdwBytesSent = dwBytesSent; + + return dwError; + + error: + *pdwBytesSent = 0; + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSSendUDPRequest( HANDLE hDNSHandle, + uint8 * pDNSSendBuffer, + int32 dwBufferSize, int32 * pdwBytesSent ) +{ + int32 dwError = 0; + int32 dwBytesSent = 0; + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + + pDNSContext = ( DNS_CONNECTION_CONTEXT * ) hDNSHandle; + + dwBytesSent = sendto( pDNSContext->s, + pDNSSendBuffer, + dwBufferSize, + 0, + ( struct sockaddr * ) & pDNSContext->RecvAddr, + sizeof( pDNSContext->RecvAddr ) + ); + if ( dwBytesSent == SOCKET_ERROR ) { + dwError = WSAGetLastError( ); + BAIL_ON_ERROR( dwError ); + } else { + *pdwBytesSent = dwBytesSent; + } + + return dwError; + + error: + *pdwBytesSent = 0; + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSSelect( HANDLE hDNSHandle ) +{ + int32 dwError = 0; + fd_set rfds; + struct timeval tv; + int32 dwNumSockets = 0; + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + + pDNSContext = ( DNS_CONNECTION_CONTEXT * ) hDNSHandle; + FD_ZERO( &rfds ); + FD_SET( pDNSContext->s, &rfds ); + + tv.tv_sec = 10; + tv.tv_usec = 0; + dwNumSockets = select( pDNSContext->s + 1, &rfds, NULL, NULL, &tv ); + if ( dwNumSockets == SOCKET_ERROR ) { + dwError = WSAGetLastError( ); + BAIL_ON_ERROR( dwError ); + } + + if ( !dwNumSockets ) { +#ifndef WIN32 + dwError = ETIMEDOUT; +#elif + dwError = WSAETIMEDOUT; +#endif + } + + error: + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSTCPReceiveBufferContext( HANDLE hDNSHandle, + HANDLE hDNSRecvBuffer, int32 * pdwBytesRead ) +{ + int32 dwError = 0; + int32 dwRead = 0; + int16 wBytesToRead = 0; + int16 wnBytesToRead = 0; + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + DNS_RECEIVEBUFFER_CONTEXT *pDNSRecvContext = NULL; + + pDNSContext = ( DNS_CONNECTION_CONTEXT * ) hDNSHandle; + pDNSRecvContext = ( DNS_RECEIVEBUFFER_CONTEXT * ) hDNSRecvBuffer; + + dwError = DNSSelect( hDNSHandle ); + BAIL_ON_ERROR( dwError ); + + dwRead = recv( pDNSContext->s, ( char * ) &wnBytesToRead, + sizeof( int16 ), 0 ); + if ( dwRead == SOCKET_ERROR ) { + dwError = WSAGetLastError( ); + BAIL_ON_ERROR( dwError ); + } + + wBytesToRead = ntohs( wnBytesToRead ); + + dwError = DNSSelect( hDNSHandle ); + BAIL_ON_ERROR( dwError ); + + dwRead = recv( pDNSContext->s, + ( char * ) pDNSRecvContext->pRecvBuffer, wBytesToRead, + 0 ); + if ( dwRead == SOCKET_ERROR ) { + dwError = WSAGetLastError( ); + BAIL_ON_ERROR( dwError ); + } + + pDNSRecvContext->dwBytesRecvd = dwRead; + + *pdwBytesRead = ( int32 ) dwRead; + + return dwError; + + error: + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSUDPReceiveBufferContext( HANDLE hDNSHandle, + HANDLE hDNSRecvBuffer, int32 * pdwBytesRead ) +{ + int32 dwError = 0; + int32 dwRead = 0; + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + DNS_RECEIVEBUFFER_CONTEXT *pDNSRecvContext = NULL; + + pDNSContext = ( DNS_CONNECTION_CONTEXT * ) hDNSHandle; + pDNSRecvContext = ( DNS_RECEIVEBUFFER_CONTEXT * ) hDNSRecvBuffer; + + dwError = DNSSelect( hDNSHandle ); + BAIL_ON_ERROR( dwError ); + + dwRead = recv( pDNSContext->s, + ( char * ) pDNSRecvContext->pRecvBuffer, 512, 0 ); + if ( dwRead == SOCKET_ERROR ) { + dwError = WSAGetLastError( ); + BAIL_ON_ERROR( dwError ); + } + + pDNSRecvContext->dwBytesRecvd = dwRead; + + *pdwBytesRead = ( int32 ) dwRead; + + error: + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSReceiveBufferContext( HANDLE hDNSHandle, + HANDLE hDNSRecvBuffer, int32 * pdwBytesRead ) +{ + int32 dwError = 0; + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + + pDNSContext = ( DNS_CONNECTION_CONTEXT * ) hDNSHandle; + + switch ( pDNSContext->hType ) { + case DNS_TCP: + dwError = + DNSTCPReceiveBufferContext( hDNSHandle, + hDNSRecvBuffer, + pdwBytesRead ); + break; + case DNS_UDP: + dwError = + DNSUDPReceiveBufferContext( hDNSHandle, + hDNSRecvBuffer, + pdwBytesRead ); + break; + } + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSCreateSendBuffer( HANDLE * phDNSSendBuffer ) +{ + int32 dwError = 0; + DNS_SENDBUFFER_CONTEXT *pDNSContext = NULL; + uint8 *pSendBuffer = NULL; + + dwError = DNSAllocateMemory( sizeof( DNS_SENDBUFFER_CONTEXT ), + ( void ** ) &pDNSContext ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( SENDBUFFER_SIZE, + ( void ** ) &pSendBuffer ); + BAIL_ON_ERROR( dwError ); + + pDNSContext->pSendBuffer = pSendBuffer; + pDNSContext->dwBufferSize = SENDBUFFER_SIZE; + + /* We will offset into the buffer by 2 bytes + If we are doing a TCP write; we will fill in these + two bytes and send + 2 bytes + If we are doing a UDP write; we will start our send + +2 bytes and only send dwWritten; */ + + pDNSContext->dwBufferOffset += 2; + + *phDNSSendBuffer = ( HANDLE ) pDNSContext; + + return dwError; + + error: + + if ( pSendBuffer ) { + DNSFreeMemory( pSendBuffer ); + } + if ( pDNSContext ) { + DNSFreeMemory( pDNSContext ); + } + *phDNSSendBuffer = ( HANDLE ) NULL; + + return dwError; +} + + +/******************************************************************** +********************************************************************/ + +int32 DNSMarshallBuffer( HANDLE hDNSSendBuffer, + uint8 * pDNSSendBuffer, + int32 dwBufferSize, int32 * pdwBytesWritten ) +{ + int32 dwError = 0; + uint8 *pTemp = NULL; + DNS_SENDBUFFER_CONTEXT *pDNSContext = NULL; + +/* BugBug - we need to check for amount of space remaining in the +SendBuffer Context - if its insufficent, we want to realloc the +Buffer and copy the context; Right now the assumption is we have a big +enough buffer */ + + pDNSContext = ( DNS_SENDBUFFER_CONTEXT * ) hDNSSendBuffer; + + pTemp = pDNSContext->pSendBuffer + pDNSContext->dwBufferOffset; + + memcpy( pTemp, pDNSSendBuffer, dwBufferSize ); + + pDNSContext->dwBytesWritten += dwBufferSize; + pDNSContext->dwBufferOffset += dwBufferSize; + + *pdwBytesWritten = dwBufferSize; + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSTCPSendBufferContext( HANDLE hDNSServer, + HANDLE hSendBuffer, int32 * pdwBytesSent ) +{ + DNS_SENDBUFFER_CONTEXT *pSendBufferContext = NULL; + int32 dwError = 0; + int16 wBytesWritten = 0; + int16 wnBytesWritten = 0; + + pSendBufferContext = ( DNS_SENDBUFFER_CONTEXT * ) hSendBuffer; + + wBytesWritten = ( int16 ) pSendBufferContext->dwBytesWritten; + wnBytesWritten = htons( wBytesWritten ); + + memcpy( pSendBufferContext->pSendBuffer, &wnBytesWritten, + sizeof( int16 ) ); + + dwError = DNSSendTCPRequest( hDNSServer, + pSendBufferContext->pSendBuffer, + pSendBufferContext->dwBytesWritten + 2, + pdwBytesSent ); + BAIL_ON_ERROR( dwError ); + + error: + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSUDPSendBufferContext( HANDLE hDNSServer, + HANDLE hSendBuffer, int32 * pdwBytesSent ) +{ + DNS_SENDBUFFER_CONTEXT *pSendBufferContext = NULL; + int32 dwError = 0; + + pSendBufferContext = ( DNS_SENDBUFFER_CONTEXT * ) hSendBuffer; + + /* Now remember to send 2 bytes ahead of pSendBuffer; because + we ignore the 2 bytes size field. */ + + dwError = DNSSendUDPRequest( hDNSServer, + pSendBufferContext->pSendBuffer + 2, + pSendBufferContext->dwBytesWritten, + pdwBytesSent ); + BAIL_ON_ERROR( dwError ); + + error: + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSSendBufferContext( HANDLE hDNSServer, + HANDLE hSendBuffer, int32 * pdwBytesSent ) +{ + DNS_CONNECTION_CONTEXT *pDNSContext = NULL; + int32 dwError = 0; + + pDNSContext = ( DNS_CONNECTION_CONTEXT * ) hDNSServer; + + switch ( pDNSContext->hType ) { + case DNS_TCP: + dwError = DNSTCPSendBufferContext( hDNSServer, + hSendBuffer, + pdwBytesSent ); + BAIL_ON_ERROR( dwError ); + break; + + case DNS_UDP: + dwError = DNSUDPSendBufferContext( hDNSServer, + hSendBuffer, + pdwBytesSent ); + BAIL_ON_ERROR( dwError ); + break; + } + error: + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSDumpSendBufferContext( HANDLE hSendBuffer ) +{ + DNS_SENDBUFFER_CONTEXT *pSendBufferContext = NULL; + int32 dwError = 0; + int32 dwCurLine = 0; + int32 i = 0; + + pSendBufferContext = ( DNS_SENDBUFFER_CONTEXT * ) hSendBuffer; + printf( "\n" ); + printf( "Buffer Size is: %d\n", pSendBufferContext->dwBytesWritten ); + while ( i < pSendBufferContext->dwBytesWritten ) { + if ( ( i / 16 ) > dwCurLine ) { + printf( "\n" ); + dwCurLine++; + } + if ( ( i % 8 ) == 0 ) { + printf( " " ); + } + printf( "%.2x ", pSendBufferContext->pSendBuffer[i] ); + i++; + } + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSDumpRecvBufferContext( HANDLE hRecvBuffer ) +{ + DNS_RECEIVEBUFFER_CONTEXT *pRecvBufferContext = NULL; + int32 dwError = 0; + int32 dwCurLine = 0; + int32 i = 0; + + pRecvBufferContext = ( DNS_RECEIVEBUFFER_CONTEXT * ) hRecvBuffer; + + printf( "\n" ); + printf( "Buffer Size is: %d\n", pRecvBufferContext->dwBytesRecvd ); + + while ( i < pRecvBufferContext->dwBytesRecvd ) { + if ( ( i / 16 ) > dwCurLine ) { + printf( "\n" ); + dwCurLine++; + } + if ( ( i % 8 ) == 0 ) { + printf( " " ); + } + printf( "%.2x ", pRecvBufferContext->pRecvBuffer[i] ); + i++; + } + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSCreateReceiveBuffer( HANDLE * phDNSRecvBuffer ) +{ + int32 dwError = 0; + DNS_RECEIVEBUFFER_CONTEXT *pDNSContext = NULL; + uint8 *pRecvBuffer = NULL; + + dwError = DNSAllocateMemory( sizeof( DNS_RECEIVEBUFFER_CONTEXT ), + ( void ** ) &pDNSContext ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( RECVBUFFER_SIZE, + ( void ** ) &pRecvBuffer ); + BAIL_ON_ERROR( dwError ); + + pDNSContext->pRecvBuffer = pRecvBuffer; + pDNSContext->dwBufferSize = RECVBUFFER_SIZE; + + *phDNSRecvBuffer = ( HANDLE ) pDNSContext; + + return dwError; + + error: + + if ( pRecvBuffer ) { + DNSFreeMemory( pRecvBuffer ); + } + if ( pDNSContext ) { + DNSFreeMemory( pDNSContext ); + } + *phDNSRecvBuffer = ( HANDLE ) NULL; + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSUnmarshallBuffer( HANDLE hDNSRecvBuffer, + uint8 * pDNSRecvBuffer, + int32 dwBufferSize, int32 * pdwBytesRead ) +{ + int32 dwError = 0; + uint8 *pTemp = NULL; + DNS_RECEIVEBUFFER_CONTEXT *pDNSContext = NULL; + +/* BugBug - we need to check for amount of space remaining in the +SendBuffer Context - if its insufficent, we want to realloc the +Buffer and copy the context; Right now the assumption is we have a big +enough buffer */ + + pDNSContext = ( DNS_RECEIVEBUFFER_CONTEXT * ) hDNSRecvBuffer; + + pTemp = pDNSContext->pRecvBuffer + pDNSContext->dwBytesRead; + + memcpy( pDNSRecvBuffer, pTemp, dwBufferSize ); + + pDNSContext->dwBytesRead += dwBufferSize; + + *pdwBytesRead = dwBufferSize; + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSUnmarshallDomainNameAtOffset( HANDLE hRecvBuffer, + int16 wOffset, + DNS_DOMAIN_NAME ** ppDomainName ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pLabel = NULL; + DNS_DOMAIN_LABEL *pLabelList = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + char *pszLabel = NULL; + char szLabel[65]; + uint8 uLen = 0; + int32 dwCurrent = 0; + DNS_RECEIVEBUFFER_CONTEXT *pRecvContext = NULL; + + pRecvContext = ( DNS_RECEIVEBUFFER_CONTEXT * ) hRecvBuffer; + dwCurrent = wOffset; + + while ( 1 ) { + + memcpy( &uLen, pRecvContext->pRecvBuffer + dwCurrent, + sizeof( char ) ); + dwCurrent++; + + if ( uLen == 0 ) { + break; + } + + memset( szLabel, 0, 65 ); + memcpy( szLabel, pRecvContext->pRecvBuffer + dwCurrent, + uLen ); + dwCurrent += uLen; + + dwError = DNSAllocateString( szLabel, &pszLabel ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_LABEL ), + ( void ** ) &pLabel ); + BAIL_ON_ERROR( dwError ); + + pLabel->pszLabel = pszLabel; + dwError = DNSAppendLabel( pLabelList, pLabel, &pLabelList ); + BAIL_ON_ERROR( dwError ); + } + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_NAME ), + ( void ** ) &pDomainName ); + BAIL_ON_ERROR( dwError ); + pDomainName->pLabelList = pLabelList; + + *ppDomainName = pDomainName; + + return dwError; + + error: + + *ppDomainName = NULL; + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSReceiveBufferMoveBackIndex( HANDLE hRecvBuffer, int16 wOffset ) +{ + int32 dwError = 0; + DNS_RECEIVEBUFFER_CONTEXT *pDNSContext = NULL; + + pDNSContext = ( DNS_RECEIVEBUFFER_CONTEXT * ) hRecvBuffer; + pDNSContext->dwBytesRead -= wOffset; + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +void DNSFreeSendBufferContext( HANDLE hSendBuffer ) +{ + DNS_SENDBUFFER_CONTEXT *pSendBufferContext = NULL; + + pSendBufferContext = ( DNS_SENDBUFFER_CONTEXT * ) hSendBuffer; + + if ( pSendBufferContext->pSendBuffer ) { + DNSFreeMemory( pSendBufferContext->pSendBuffer ); + } + if ( pSendBufferContext ) { + DNSFreeMemory( pSendBufferContext ); + } +} + +/******************************************************************** +********************************************************************/ + +int32 DNSGetSendBufferContextSize( HANDLE hSendBuffer ) +{ + DNS_SENDBUFFER_CONTEXT *pSendBufferContext = NULL; + + pSendBufferContext = ( DNS_SENDBUFFER_CONTEXT * ) hSendBuffer; + + return ( pSendBufferContext->dwBytesWritten ); + +} + +/******************************************************************** +********************************************************************/ + +uint8 *DNSGetSendBufferContextBuffer( HANDLE hSendBuffer ) +{ + DNS_SENDBUFFER_CONTEXT *pSendBufferContext = NULL; + + pSendBufferContext = ( DNS_SENDBUFFER_CONTEXT * ) hSendBuffer; + + return ( pSendBufferContext->pSendBuffer ); +} + diff --git a/source3/libaddns/dnsupdate.c b/source3/libaddns/dnsupdate.c new file mode 100644 index 0000000000..8cf497a653 --- /dev/null +++ b/source3/libaddns/dnsupdate.c @@ -0,0 +1,644 @@ +/* + Public Interface file for Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + +/******************************************************************** +********************************************************************/ + +static int32 DNSSendUpdate1( HANDLE hDNSServer, char *szDomainName, + char *szHost, struct in_addr *iplist, + int num_ips, + DNS_UPDATE_RESPONSE * *ppDNSUpdateResponse ) +{ + int32 dwError = 0; + DNS_UPDATE_REQUEST *pDNSUpdateRequest = NULL; + DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL; + DNS_ZONE_RECORD *pDNSZoneRecord = NULL; + DNS_RR_RECORD *pDNSPRRecord = NULL; + int i; + + dwError = DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateZoneRecord( szDomainName, &pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateAddZoneSection( pDNSUpdateRequest, pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + /* Add the CNAME not in user record */ + + pDNSPRRecord = NULL; + dwError = + DNSCreateNameNotInUseRecord( szHost, QTYPE_CNAME, + &pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + /* Add a Prerequisite for each IP address to see if everything is already setup */ + + for ( i = 0; i < num_ips; i++ ) { + DNS_RR_RECORD *pDNSPrereq = NULL; + + dwError = + DNSCreateNameInUseRecord( szHost, QTYPE_A, &iplist[i], + &pDNSPrereq ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateAddPRSection( pDNSUpdateRequest, + pDNSPrereq ); + BAIL_ON_ERROR( dwError ); + } + + dwError = + DNSUpdateSendUpdateRequest2( hDNSServer, pDNSUpdateRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateReceiveUpdateResponse( hDNSServer, + &pDNSUpdateResponse ); + BAIL_ON_ERROR( dwError ); + + *ppDNSUpdateResponse = pDNSUpdateResponse; + + return dwError; + + error: + + if ( pDNSZoneRecord ) { + DNSFreeZoneRecord( pDNSZoneRecord ); + } + + if ( pDNSUpdateRequest ) { + DNSUpdateFreeRequest( pDNSUpdateRequest ); + } + + *ppDNSUpdateResponse = NULL; + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSSendUpdate2( HANDLE hDNSServer, char *szDomainName, + char *szHost, struct in_addr *iplist, + int num_ips, + DNS_UPDATE_RESPONSE * *ppDNSUpdateResponse ) +{ + int32 dwError = 0; + DNS_UPDATE_REQUEST *pDNSUpdateRequest = NULL; + DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL; + DNS_ZONE_RECORD *pDNSZoneRecord = NULL; + DNS_RR_RECORD *pDNSPRRecord = NULL; + int i; + + dwError = DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateZoneRecord( szDomainName, &pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateAddZoneSection( pDNSUpdateRequest, pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + /* Add the CNAME not in user record */ + + pDNSPRRecord = NULL; + dwError = + DNSCreateNameNotInUseRecord( szHost, QTYPE_CNAME, + &pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + /* Add the IN not in user record */ + + pDNSPRRecord = NULL; + dwError = + DNSCreateNameNotInUseRecord( szHost, QTYPE_A, &pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + + for ( i = 0; i < num_ips; i++ ) { + DNS_RR_RECORD *pDNSRRAddRecord = NULL; + + dwError = + DNSCreateARecord( szHost, DNS_CLASS_IN, QTYPE_A, + ntohl( iplist[i].s_addr ), + &pDNSRRAddRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateAddUpdateSection( pDNSUpdateRequest, + pDNSRRAddRecord ); + BAIL_ON_ERROR( dwError ); + } + + dwError = + DNSUpdateSendUpdateRequest2( hDNSServer, pDNSUpdateRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateReceiveUpdateResponse( hDNSServer, + &pDNSUpdateResponse ); + BAIL_ON_ERROR( dwError ); + + *ppDNSUpdateResponse = pDNSUpdateResponse; + + return dwError; + + error: + + if ( pDNSZoneRecord ) { + DNSFreeZoneRecord( pDNSZoneRecord ); + } + + if ( pDNSUpdateRequest ) { + DNSUpdateFreeRequest( pDNSUpdateRequest ); + } + + *ppDNSUpdateResponse = NULL; + return dwError; +} + +/******************************************************************** +********************************************************************/ + +static int32 DNSSendUpdate3( HANDLE hDNSServer, char *szDomainName, + char *szHost, struct in_addr *iplist, + int num_ips, + DNS_UPDATE_RESPONSE * *ppDNSUpdateResponse ) +{ + int32 dwError = 0; + DNS_UPDATE_REQUEST *pDNSUpdateRequest = NULL; + DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL; + DNS_ZONE_RECORD *pDNSZoneRecord = NULL; + DNS_RR_RECORD *pDNSPRRecord = NULL; + int i; + DNS_RR_RECORD *pDNSRRAddRecord = NULL; + + dwError = DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateZoneRecord( szDomainName, &pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateAddZoneSection( pDNSUpdateRequest, pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + /* Add the CNAME not in user record */ + + dwError = + DNSCreateNameNotInUseRecord( szHost, QTYPE_CNAME, + &pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + /* Delete any existing A records */ + + dwError = + DNSCreateARecord( szHost, DNS_CLASS_ANY, QTYPE_A, 0, + &pDNSRRAddRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateAddUpdateSection( pDNSUpdateRequest, + pDNSRRAddRecord ); + BAIL_ON_ERROR( dwError ); + + + for ( i = 0; i < num_ips; i++ ) { + + dwError = + DNSCreateARecord( szHost, DNS_CLASS_IN, QTYPE_A, + ntohl( iplist[i].s_addr ), + &pDNSRRAddRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateAddUpdateSection( pDNSUpdateRequest, + pDNSRRAddRecord ); + BAIL_ON_ERROR( dwError ); + } + + dwError = + DNSUpdateSendUpdateRequest2( hDNSServer, pDNSUpdateRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateReceiveUpdateResponse( hDNSServer, + &pDNSUpdateResponse ); + BAIL_ON_ERROR( dwError ); + + *ppDNSUpdateResponse = pDNSUpdateResponse; + + return dwError; + + error: + + if ( pDNSZoneRecord ) { + DNSFreeZoneRecord( pDNSZoneRecord ); + } + + if ( pDNSUpdateRequest ) { + DNSUpdateFreeRequest( pDNSUpdateRequest ); + } + + *ppDNSUpdateResponse = NULL; + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSSendUpdate( HANDLE hDNSServer, char *szDomainName, char *szHost, + struct in_addr * iplist, int num_ips, + DNS_UPDATE_RESPONSE * *ppDNSUpdateResponse ) +{ + int32 dwError = 0; + int32 dwResponseCode = 0; + DNS_UPDATE_RESPONSE *response = NULL; + + dwError = DNSSendUpdate1( hDNSServer, szDomainName, szHost, + iplist, num_ips, &response ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateGetResponseCode( response, &dwResponseCode ); + BAIL_ON_ERROR( dwError ); + + if ( ( dwResponseCode == DNS_NO_ERROR ) + || ( dwResponseCode == DNS_REFUSED ) ) { + *ppDNSUpdateResponse = response; + return dwError; + } + + response = NULL; + + dwError = DNSSendUpdate2( hDNSServer, szDomainName, szHost, + iplist, num_ips, &response ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateGetResponseCode( response, &dwResponseCode ); + BAIL_ON_ERROR( dwError ); + + if ( ( dwResponseCode == DNS_NO_ERROR ) + || ( dwResponseCode == DNS_REFUSED ) ) { + *ppDNSUpdateResponse = response; + return dwError; + } + + response = NULL; + + dwError = DNSSendUpdate3( hDNSServer, szDomainName, szHost, + iplist, num_ips, &response ); + + error: + *ppDNSUpdateResponse = response; + + return dwError; +} + +/******************************************************************** +********************************************************************/ + +int32 DNSSendSecureUpdate( HANDLE hDNSServer, + PCtxtHandle pGSSContext, + char *pszKeyName, + char *szDomainName, + char *szHost, + int32 dwIP, DNS_UPDATE_RESPONSE ** ppDNSUpdateResponse ) +{ + int32 dwError = 0; + DNS_UPDATE_REQUEST *pDNSUpdateRequest = NULL; + DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL; + DNS_ZONE_RECORD *pDNSZoneRecord = NULL; + DNS_RR_RECORD *pDNSPRRecord = NULL; + DNS_RR_RECORD *pDNSARecord = NULL; + + + dwError = DNSUpdateCreateUpdateRequest( &pDNSUpdateRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateZoneRecord( szDomainName, &pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddZoneSection( pDNSUpdateRequest, + pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateNameInUseRecord( szDomainName, + QTYPE_A, NULL, &pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddPRSection( pDNSUpdateRequest, pDNSPRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateDeleteRecord( szHost, + DNS_CLASS_ANY, + QTYPE_A, &pDNSARecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddUpdateSection( pDNSUpdateRequest, pDNSARecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateARecord( szHost, + DNS_CLASS_IN, + QTYPE_A, dwIP, &pDNSARecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddUpdateSection( pDNSUpdateRequest, pDNSARecord ); + BAIL_ON_ERROR( dwError ); + + /* Now Sign the Record */ + + dwError = DNSUpdateGenerateSignature( pGSSContext, + pDNSUpdateRequest, pszKeyName ); + BAIL_ON_ERROR( dwError ); + + + dwError = + DNSUpdateSendUpdateRequest2( hDNSServer, pDNSUpdateRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateReceiveUpdateResponse( hDNSServer, + &pDNSUpdateResponse ); + BAIL_ON_ERROR( dwError ); + + *ppDNSUpdateResponse = pDNSUpdateResponse; + + return dwError; + + error: + + if ( pDNSZoneRecord ) { + DNSFreeZoneRecord( pDNSZoneRecord ); + } + + if ( pDNSUpdateRequest ) { + DNSUpdateFreeRequest( pDNSUpdateRequest ); + } + + *ppDNSUpdateResponse = NULL; + + return dwError; +} + + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateGenerateSignature( PCtxtHandle pGSSContext, + DNS_UPDATE_REQUEST * pDNSUpdateRequest, + char *pszKeyName ) +{ + int32 dwError = 0; + int32 dwMinorStatus = 0; + HANDLE hSendBuffer = ( HANDLE ) NULL; + uint8 *pMessageBuffer = NULL; + int32 dwMessageSize = 0; + int32 dwMaxSignatureSize = 0; + uint8 *pSignature = NULL; + int32 dwTimeSigned = 0; + int16 wFudge = 0; + gss_buffer_desc MsgDesc, MicDesc; + DNS_RR_RECORD *pDNSTSIGRecord = NULL; + + dwError = DNSBuildMessageBuffer( pDNSUpdateRequest, + pszKeyName, + &dwTimeSigned, + &wFudge, + &pMessageBuffer, &dwMessageSize ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSBuildSignatureBuffer( dwMaxSignatureSize, &pSignature ); + BAIL_ON_ERROR( dwError ); + + MsgDesc.value = pMessageBuffer; + MsgDesc.length = dwMessageSize; + + MicDesc.value = NULL; + MicDesc.length = 0; + + dwError = gss_get_mic( ( OM_uint32 * ) & dwMinorStatus, + *pGSSContext, 0, &MsgDesc, &MicDesc ); + display_status( "gss_init_context", dwError, dwMinorStatus ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSCreateTSIGRecord( pszKeyName, + dwTimeSigned, + wFudge, + pDNSUpdateRequest->wIdentification, + MicDesc.value, + MicDesc.length, &pDNSTSIGRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSUpdateAddAdditionalSection( pDNSUpdateRequest, + pDNSTSIGRecord ); + BAIL_ON_ERROR( dwError ); + + + error: + + if ( hSendBuffer ) { + DNSFreeSendBufferContext( hSendBuffer ); + } + + if ( pMessageBuffer ) { + DNSFreeMemory( pMessageBuffer ); + } + return dwError; + + if ( pSignature ) { + DNSFreeMemory( pSignature ); + } + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSBuildSignatureBuffer( int32 dwMaxSignatureSize, uint8 ** ppSignature ) +{ + int32 dwError = 0; + uint8 *pSignature = NULL; + + dwError = DNSAllocateMemory( dwMaxSignatureSize, + ( void ** ) &pSignature ); + BAIL_ON_ERROR( dwError ); + + *ppSignature = pSignature; + + return dwError; + + error: + *ppSignature = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSBuildMessageBuffer( DNS_UPDATE_REQUEST * pDNSUpdateRequest, + char *szKeyName, + int32 * pdwTimeSigned, + int16 * pwFudge, + uint8 ** ppMessageBuffer, int32 * pdwMessageSize ) +{ + int32 dwError = 0; + uint8 *pSrcBuffer = NULL; + int32 dwReqMsgSize = 0; + int32 dwAlgorithmLen = 0; + int32 dwNameLen = 0; + uint8 *pMessageBuffer = NULL; + int32 dwMessageSize = 0; + uint8 *pOffset = NULL; + int16 wnError, wError = 0; + int16 wnFudge = 0; + int16 wFudge = DNS_TEN_HOURS_IN_SECS; + int16 wnOtherLen = 0, wOtherLen = 0; + int32 dwBytesCopied = 0; + int16 wnClass = 0, wClass = DNS_CLASS_ANY; + int32 dwnTTL = 0, dwTTL = 0; + int32 dwnTimeSigned, dwTimeSigned = 0; + HANDLE hSendBuffer = ( HANDLE ) NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + DNS_DOMAIN_NAME *pAlgorithmName = NULL; + int16 wTimePrefix = 0; + int16 wnTimePrefix = 0; + char szTsig[9]; + + dwError = DNSDomainNameFromString( szKeyName, &pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSGetDomainNameLength( pDomainName, &dwNameLen ); + BAIL_ON_ERROR( dwError ); + + strncpy( szTsig, "gss-tsig", sizeof( szTsig ) ); + dwError = DNSDomainNameFromString( szTsig, &pAlgorithmName ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSGetDomainNameLength( pAlgorithmName, &dwAlgorithmLen ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUpdateBuildRequestMessage( pDNSUpdateRequest, + &hSendBuffer ); + BAIL_ON_ERROR( dwError ); + + dwReqMsgSize = DNSGetSendBufferContextSize( hSendBuffer ); + dwMessageSize += dwReqMsgSize; + dwMessageSize += dwNameLen; + dwMessageSize += sizeof( int16 ); /* class */ + dwMessageSize += sizeof( int32 ); /* TTL */ + dwMessageSize += dwAlgorithmLen; + dwMessageSize += ( sizeof( int16 ) + sizeof( int32 ) ); /* Time Signed */ + dwMessageSize += sizeof( int16 ); /* Fudge */ + dwMessageSize += sizeof( int16 ); /* wError */ + dwMessageSize += sizeof( int16 ); /* Other Len */ + dwMessageSize += wOtherLen; + + dwError = + DNSAllocateMemory( dwMessageSize, + ( void ** ) &pMessageBuffer ); + BAIL_ON_ERROR( dwError ); + + pOffset = pMessageBuffer; + pSrcBuffer = DNSGetSendBufferContextBuffer( hSendBuffer ); + memcpy( pOffset, pSrcBuffer, dwReqMsgSize ); + pOffset += dwReqMsgSize; + + dwError = + DNSCopyDomainName( pOffset, pAlgorithmName, &dwBytesCopied ); + BAIL_ON_ERROR( dwError ); + pOffset += dwBytesCopied; + + wnClass = htons( wClass ); + memcpy( pOffset, &wnClass, sizeof( int16 ) ); + pOffset += sizeof( int16 ); + + dwnTTL = htonl( dwTTL ); + memcpy( pOffset, &dwnTTL, sizeof( int32 ) ); + pOffset += sizeof( int32 ); + + + wnTimePrefix = htons( wTimePrefix ); + memcpy( pOffset, &wnTimePrefix, sizeof( int16 ) ); + pOffset += sizeof( int16 ); + + time( (time_t*)&dwTimeSigned ); + dwnTimeSigned = htonl( dwTimeSigned ); + memcpy( pOffset, &dwnTimeSigned, sizeof( int32 ) ); + pOffset += sizeof( int32 ); + + wnFudge = htons( wFudge ); + memcpy( pOffset, &wnFudge, sizeof( int16 ) ); + pOffset += sizeof( int16 ); + + wnError = htons( wError ); + memcpy( pOffset, &wnError, sizeof( int16 ) ); + pOffset += sizeof( int16 ); + + wnOtherLen = htons( wOtherLen ); + memcpy( pOffset, &wnOtherLen, sizeof( int16 ) ); + pOffset += sizeof( int16 ); + + *ppMessageBuffer = pMessageBuffer; + *pdwMessageSize = dwMessageSize; + + *pdwTimeSigned = dwTimeSigned; + *pwFudge = wFudge; + + return dwError; + + error: + + if ( pMessageBuffer ) { + DNSFreeMemory( pMessageBuffer ); + } + + *ppMessageBuffer = NULL; + *pdwMessageSize = 0; + *pdwTimeSigned = dwTimeSigned; + *pwFudge = wFudge; + return dwError; + +} diff --git a/source3/libaddns/dnsuprequest.c b/source3/libaddns/dnsuprequest.c new file mode 100644 index 0000000000..d8188d5f58 --- /dev/null +++ b/source3/libaddns/dnsuprequest.c @@ -0,0 +1,428 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateMarshallZoneSection( HANDLE hSendBuffer, + DNS_ZONE_RECORD ** ppDNSZoneRecords, + int16 wZones ) +{ + int32 dwError = 0; + int32 i = 0; + int32 dwRead = 0; + DNS_ZONE_RECORD *pDNSZoneRecord = NULL; + int16 wnZoneType = 0; + int16 wnZoneClass = 0; + + for ( i = 0; i < wZones; i++ ) { + + pDNSZoneRecord = *( ppDNSZoneRecords + i ); + dwError = + DNSMarshallDomainName( hSendBuffer, + pDNSZoneRecord->pDomainName ); + BAIL_ON_ERROR( dwError ); + + wnZoneType = htons( pDNSZoneRecord->wZoneType ); + dwError = + DNSMarshallBuffer( hSendBuffer, + ( uint8 * ) & wnZoneType, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + + wnZoneClass = htons( pDNSZoneRecord->wZoneClass ); + dwError = + DNSMarshallBuffer( hSendBuffer, + ( uint8 * ) & wnZoneClass, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + + pDNSZoneRecord++; + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateMarshallPRSection( HANDLE hSendBuffer, + DNS_RR_RECORD ** ppDNSPRRRRecords, int16 wPRs ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSPRRRRecord = NULL; + + + for ( i = 0; i < wPRs; i++ ) { + + pDNSPRRRRecord = *( ppDNSPRRRRecords + i ); + + dwError = DNSMarshallRRHeader( hSendBuffer, pDNSPRRRRecord ); + BAIL_ON_ERROR( dwError ); + + if ( pDNSPRRRRecord->RRHeader.wRDataSize ) { + dwError = + DNSMarshallRData( hSendBuffer, + pDNSPRRRRecord ); + BAIL_ON_ERROR( dwError ); + } + } + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateMarshallUpdateSection( HANDLE hSendBuffer, + DNS_RR_RECORD ** ppDNSUpdateRRRecords, + int16 wZones ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSUpdateRRRecord = NULL; + + for ( i = 0; i < wZones; i++ ) { + + pDNSUpdateRRRecord = *( ppDNSUpdateRRRecords + i ); + + dwError = + DNSMarshallRRHeader( hSendBuffer, + pDNSUpdateRRRecord ); + + if ( pDNSUpdateRRRecord->RRHeader.wRDataSize ) { + dwError = DNSMarshallRData( hSendBuffer, + pDNSUpdateRRRecord ); + BAIL_ON_ERROR( dwError ); + } + + } + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateMarshallAdditionalSection( HANDLE hSendBuffer, + DNS_RR_RECORD ** + ppDNSAdditionalsRRRecords, + int16 wAdditionals ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSAdditionalRRRecord = NULL; + + for ( i = 0; i < wAdditionals; i++ ) { + + pDNSAdditionalRRRecord = *( ppDNSAdditionalsRRRecords + i ); + + dwError = + DNSMarshallRRHeader( hSendBuffer, + pDNSAdditionalRRRecord ); + BAIL_ON_ERROR( dwError ); + + if ( pDNSAdditionalRRRecord->RRHeader.wRDataSize ) { + dwError = DNSMarshallRData( hSendBuffer, + pDNSAdditionalRRRecord ); + BAIL_ON_ERROR( dwError ); + } + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateSendUpdateRequest2( HANDLE hDNSServer, + DNS_UPDATE_REQUEST * pDNSRequest ) +{ + int32 dwError = 0; + int32 dwBytesSent = 0; + HANDLE hSendBuffer = ( HANDLE ) NULL; + + dwError = DNSUpdateBuildRequestMessage( pDNSRequest, &hSendBuffer ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSSendBufferContext( hDNSServer, hSendBuffer, &dwBytesSent ); + BAIL_ON_ERROR( dwError ); + + error: + + if ( hSendBuffer ) { + DNSFreeSendBufferContext( hSendBuffer ); + } + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateBuildRequestMessage( DNS_UPDATE_REQUEST * pDNSRequest, + HANDLE * phSendBuffer ) +{ + int32 dwError = 0; + char DNSMessageHeader[12]; + int16 wnIdentification = 0; + int16 wnParameter = 0; + int16 wnZones = 0; + int16 wnPRs = 0; + int16 wnUpdates = 0; + int16 wnAdditionals = 0; + int32 dwRead = 0; + HANDLE hSendBuffer = ( HANDLE ) NULL; + + dwError = DNSCreateSendBuffer( &hSendBuffer ); + BAIL_ON_ERROR( dwError ); + + wnIdentification = htons( pDNSRequest->wIdentification ); + memcpy( DNSMessageHeader, ( char * ) &wnIdentification, 2 ); + + wnParameter = htons( pDNSRequest->wParameter ); + memcpy( DNSMessageHeader + 2, ( char * ) &wnParameter, 2 ); + + wnZones = htons( pDNSRequest->wZones ); + memcpy( DNSMessageHeader + 4, ( char * ) &wnZones, 2 ); + + wnPRs = htons( pDNSRequest->wPRs ); + memcpy( DNSMessageHeader + 6, ( char * ) &wnPRs, 2 ); + + wnUpdates = htons( pDNSRequest->wUpdates ); + memcpy( DNSMessageHeader + 8, ( char * ) &wnUpdates, 2 ); + + wnAdditionals = htons( pDNSRequest->wAdditionals ); + memcpy( DNSMessageHeader + 10, ( char * ) &wnAdditionals, 2 ); + + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) DNSMessageHeader, + 12, &dwRead ); + BAIL_ON_ERROR( dwError ); + + if ( pDNSRequest->wZones ) { + dwError = + DNSUpdateMarshallZoneSection( hSendBuffer, + pDNSRequest-> + ppZoneRRSet, + pDNSRequest->wZones ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wPRs ) { + dwError = + DNSUpdateMarshallPRSection( hSendBuffer, + pDNSRequest->ppPRRRSet, + pDNSRequest->wPRs ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wUpdates ) { + dwError = + DNSUpdateMarshallUpdateSection( hSendBuffer, + pDNSRequest-> + ppUpdateRRSet, + pDNSRequest-> + wUpdates ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wAdditionals ) { + dwError = + DNSUpdateMarshallAdditionalSection( hSendBuffer, + pDNSRequest-> + ppAdditionalRRSet, + pDNSRequest-> + wAdditionals ); + BAIL_ON_ERROR( dwError ); + } +#if 0 + DNSDumpSendBufferContext( hSendBuffer ); +#endif + + *phSendBuffer = hSendBuffer; + + return dwError; + + error: + + if ( hSendBuffer ) { + DNSFreeSendBufferContext( hSendBuffer ); + } + + *phSendBuffer = ( HANDLE ) NULL; + return dwError; +} + + +/********************************************************************* +*********************************************************************/ + +void DNSUpdateFreeRequest( DNS_UPDATE_REQUEST * pDNSRequest ) +{ + return; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateAddZoneSection( DNS_UPDATE_REQUEST * pDNSRequest, + DNS_ZONE_RECORD * pDNSZone ) +{ + int32 dwNumZones = 0; + int32 dwError = 0; + + dwNumZones = pDNSRequest->wZones; + + dwError = DNSReallocMemory( ( uint8 * ) pDNSRequest->ppZoneRRSet, + ( void ** ) &pDNSRequest->ppZoneRRSet, + ( dwNumZones + + 1 ) * sizeof( DNS_ZONE_RECORD * ) + ); + BAIL_ON_ERROR( dwError ); + + *( pDNSRequest->ppZoneRRSet + dwNumZones ) = pDNSZone; + + pDNSRequest->wZones += 1; + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateAddAdditionalSection( DNS_UPDATE_REQUEST * pDNSRequest, + DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwNumAdditionals = 0; + int32 dwError = 0; + + dwNumAdditionals = pDNSRequest->wAdditionals; + dwError = DNSReallocMemory( pDNSRequest->ppAdditionalRRSet, + ( void ** ) &pDNSRequest-> + ppAdditionalRRSet, + ( dwNumAdditionals + + 1 ) * sizeof( DNS_RR_RECORD * ) ); + BAIL_ON_ERROR( dwError ); + + *( pDNSRequest->ppAdditionalRRSet + dwNumAdditionals ) = pDNSRecord; + + pDNSRequest->wAdditionals += 1; + + error: + return dwError; +} + +int32 DNSUpdateAddPRSection( DNS_UPDATE_REQUEST * pDNSRequest, + DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwNumPRs = 0; + int32 dwError = 0; + + dwNumPRs = pDNSRequest->wPRs; + dwError = DNSReallocMemory( pDNSRequest->ppPRRRSet, + ( void ** ) &pDNSRequest->ppPRRRSet, + ( dwNumPRs + + 1 ) * sizeof( DNS_RR_RECORD * ) ); + BAIL_ON_ERROR( dwError ); + + *( pDNSRequest->ppPRRRSet + dwNumPRs ) = pDNSRecord; + + pDNSRequest->wPRs += 1; + + error: + return dwError; +} + + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateAddUpdateSection( DNS_UPDATE_REQUEST * pDNSRequest, + DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwError = 0; + int16 wNumUpdates = 0; + + wNumUpdates = pDNSRequest->wUpdates; + dwError = DNSReallocMemory( pDNSRequest->ppUpdateRRSet, + ( void ** ) &pDNSRequest->ppUpdateRRSet, + ( wNumUpdates + + 1 ) * sizeof( DNS_RR_RECORD * ) ); + BAIL_ON_ERROR( dwError ); + + *( pDNSRequest->ppUpdateRRSet + wNumUpdates ) = pDNSRecord; + + pDNSRequest->wUpdates += 1; + + error: + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateCreateUpdateRequest( DNS_UPDATE_REQUEST ** ppDNSRequest ) +{ + int32 dwError = 0; + DNS_UPDATE_REQUEST *pDNSRequest = NULL; + + dwError = + DNSAllocateMemory( sizeof( DNS_UPDATE_REQUEST ), + ( void ** ) &pDNSRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSGenerateIdentifier( &pDNSRequest->wIdentification ); + BAIL_ON_ERROR( dwError ); + + pDNSRequest->wParameter = 0x2800; + + *ppDNSRequest = pDNSRequest; + + return dwError; + + error: + + if ( pDNSRequest ) { + DNSUpdateFreeRequest( pDNSRequest ); + } + *ppDNSRequest = NULL; + return dwError; +} diff --git a/source3/libaddns/dnsupresp.c b/source3/libaddns/dnsupresp.c new file mode 100644 index 0000000000..c5f7642acd --- /dev/null +++ b/source3/libaddns/dnsupresp.c @@ -0,0 +1,397 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateAllocateResponse( DNS_UPDATE_RESPONSE ** ppDNSResponse ) +{ + int32 dwError = 0; + DNS_UPDATE_RESPONSE *pDNSResponse = NULL; + + dwError = + DNSAllocateMemory( sizeof( DNS_UPDATE_RESPONSE ), + ( void ** ) &pDNSResponse ); + BAIL_ON_ERROR( dwError ); + + *ppDNSResponse = pDNSResponse; + + return dwError; + + error: + + *ppDNSResponse = NULL; + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateUnmarshallAdditionalSection( HANDLE hReceiveBuffer, + int16 wAdditionals, + DNS_RR_RECORD * + **pppDNSAdditionalsRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSAdditionalRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wAdditionals * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSAdditionalRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wAdditionals; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRRData; + + *( ppDNSAdditionalRRRecords + i ) = pDNSRRRecord; + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateUnmarshallPRSection( HANDLE hReceiveBuffer, + int16 wPRs, + DNS_RR_RECORD * **pppDNSPRRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSPRRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wPRs * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSPRRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wPRs; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRRData; + + *( ppDNSPRRRRecords + i ) = pDNSRRRecord; + } + + *pppDNSPRRRRecords = ppDNSPRRRRecords; + + return dwError; + + error: + + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateUnmarshallUpdateSection( HANDLE hReceiveBuffer, + int16 wUpdates, + DNS_RR_RECORD * **pppDNSUpdateRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSUpdateRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wUpdates * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSUpdateRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wUpdates; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRRData; + + *( ppDNSUpdateRRRecords + i ) = pDNSRRRecord; + } + + *pppDNSUpdateRRRecords = ppDNSUpdateRRRecords; + + return dwError; + + error: + + return dwError; + +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSUpdateUnmarshallZoneSection( HANDLE hReceiveBuffer, + int16 wZones, + DNS_ZONE_RECORD * **pppDNSZoneRecords ) +{ + int32 dwError = 0; + int32 i = 0; + int32 dwRead = 0; + DNS_ZONE_RECORD *pDNSZoneRecord = NULL; + DNS_ZONE_RECORD **ppDNSZoneRecords = NULL; + int16 wnZoneClass = 0; + int16 wnZoneType = 0; + + + dwError = DNSAllocateMemory( wZones * sizeof( DNS_ZONE_RECORD * ), + ( void ** ) &ppDNSZoneRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wZones; i++ ) { + + dwError = + DNSAllocateMemory( sizeof( DNS_ZONE_RECORD ), + ( void ** ) &pDNSZoneRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallDomainName( hReceiveBuffer, + &pDNSZoneRecord-> + pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallBuffer( hReceiveBuffer, + ( uint8 * ) & wnZoneType, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + pDNSZoneRecord->wZoneType = ntohs( wnZoneType ); + + dwError = + DNSUnmarshallBuffer( hReceiveBuffer, + ( uint8 * ) & wnZoneClass, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + pDNSZoneRecord->wZoneClass = ntohs( wnZoneClass ); + + *( ppDNSZoneRecords + i ) = pDNSZoneRecord; + } + + *pppDNSZoneRecords = ppDNSZoneRecords; + return dwError; + + error: + + return dwError; +} + + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateReceiveUpdateResponse( HANDLE hDNSHandle, + DNS_UPDATE_RESPONSE ** ppDNSResponse ) +{ + DNS_UPDATE_RESPONSE *pDNSResponse = NULL; + int32 dwError = 0; + int16 wnIdentification, wIdentification = 0; + int16 wnParameter, wParameter = 0; + int16 wnZones, wZones = 0; + int16 wnPRs, wPRs = 0; + int16 wnAdditionals, wAdditionals = 0; + int16 wnUpdates, wUpdates = 0; + int32 dwRead = 0; + DNS_RR_RECORD **ppDNSPRRecords = NULL; + DNS_RR_RECORD **ppDNSAdditionalRecords = NULL; + DNS_RR_RECORD **ppDNSUpdateRecords = NULL; + DNS_ZONE_RECORD **ppDNSZoneRecords = NULL; + HANDLE hRecvBuffer = ( HANDLE ) NULL; + + dwError = DNSCreateReceiveBuffer( &hRecvBuffer ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSReceiveBufferContext( hDNSHandle, hRecvBuffer, &dwRead ); + BAIL_ON_ERROR( dwError ); + +#if 0 + dwError = DNSDumpRecvBufferContext( hRecvBuffer ); + BAIL_ON_ERROR( dwError ); +#endif + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, + ( uint8 * ) & wnIdentification, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wIdentification = ntohs( wnIdentification ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnParameter, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wParameter = ntohs( wnParameter ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnZones, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wZones = ntohs( wnZones ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnPRs, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wPRs = ntohs( wnPRs ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnUpdates, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wUpdates = ntohs( wnUpdates ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnAdditionals, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wAdditionals = ntohs( wnAdditionals ); + + + if ( wZones ) { + dwError = + DNSUpdateUnmarshallZoneSection( hRecvBuffer, wZones, + &ppDNSZoneRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wPRs ) { + dwError = + DNSUpdateUnmarshallPRSection( hRecvBuffer, wPRs, + &ppDNSPRRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wUpdates ) { + dwError = + DNSUpdateUnmarshallUpdateSection( hRecvBuffer, + wUpdates, + &ppDNSUpdateRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wAdditionals ) { + dwError = + DNSUpdateUnmarshallAdditionalSection( hRecvBuffer, + wAdditionals, + &ppDNSAdditionalRecords ); + BAIL_ON_ERROR( dwError ); + } + + dwError = DNSUpdateAllocateResponse( &pDNSResponse ); + BAIL_ON_ERROR( dwError ); + + pDNSResponse->wIdentification = wIdentification; + pDNSResponse->wParameter = wParameter; + pDNSResponse->wZones = wZones; + pDNSResponse->wPRs = wPRs; + pDNSResponse->wUpdates = wUpdates; + pDNSResponse->wAdditionals = wAdditionals; + + pDNSResponse->ppZoneRRSet = ppDNSZoneRecords; + pDNSResponse->ppPRRRSet = ppDNSPRRecords; + pDNSResponse->ppUpdateRRSet = ppDNSUpdateRecords; + pDNSResponse->ppAdditionalRRSet = ppDNSAdditionalRecords; + + *ppDNSResponse = pDNSResponse; + + + error: + + return dwError; +} + diff --git a/source3/libaddns/dnsutils.c b/source3/libaddns/dnsutils.c new file mode 100644 index 0000000000..6071d35d53 --- /dev/null +++ b/source3/libaddns/dnsutils.c @@ -0,0 +1,596 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" +#include <ctype.h> + +#define TRUE 1 +#define FALSE 0 + +#define STATE_BEGIN 0 +#define STATE_LABEL 1 +#define STATE_FINISH 2 + +#define TOKEN_LABEL 1 +#define TOKEN_SEPARATOR 2 +#define TOKEN_EOS 3 + +/********************************************************************* +*********************************************************************/ + +static int32 getToken( char *pszString, char *pszToken, int32 * pdwToken, + int32 * pdwPosition ) +{ + int32 dwError = 0; + char c = 0; + int32 dwToken = 0; + int32 i = 0; + int32 dwState = 0; + int32 dwPosition = 0; + + dwPosition = *pdwPosition; + dwState = STATE_BEGIN; + while ( dwState != STATE_FINISH ) { + c = pszString[dwPosition]; + if ( c == '\0' ) { + if ( dwState == STATE_LABEL ) { + dwToken = TOKEN_LABEL; + dwState = STATE_FINISH; + continue; + } else if ( dwState == STATE_BEGIN ) { + dwToken = TOKEN_EOS; + dwState = STATE_FINISH; + continue; + } + } else if ( isalnum( c ) || c == '-' ) { + pszToken[i++] = c; + dwPosition++; + dwState = STATE_LABEL; + continue; + } else if ( c == '.' ) { + if ( dwState == STATE_LABEL ) { + dwToken = TOKEN_LABEL; + dwState = STATE_FINISH; + continue; + } else if ( dwState == STATE_BEGIN ) { + dwToken = TOKEN_SEPARATOR; + dwPosition++; + dwState = STATE_FINISH; + continue; + } + } else { + if ( dwState == STATE_LABEL ) { + dwToken = TOKEN_LABEL; + dwState = STATE_FINISH; + } else if ( dwState == 0 ) { + dwError = ERROR_INVALID_PARAMETER; + dwState = STATE_FINISH; + } + } + } + *pdwPosition = dwPosition; + *pdwToken = dwToken; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSMakeLabel( char *szLabel, DNS_DOMAIN_LABEL ** ppLabel ) +{ + DNS_DOMAIN_LABEL *pLabel = NULL; + char *pszLabel = NULL; + int32 dwError = 0; + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_LABEL ), + ( void ** ) &pLabel ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSAllocateString( szLabel, &pszLabel ); + BAIL_ON_ERROR( dwError ); + + pLabel->pszLabel = pszLabel; + pLabel->dwLength = ( int32 ) strlen( pszLabel ); + *ppLabel = pLabel; + return dwError; + + error: + + if ( pLabel ) { + DNSFreeMemory( pLabel ); + } + *ppLabel = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static void DNSFreeLabel( DNS_DOMAIN_LABEL * pLabel ) +{ + if ( pLabel ) { + DNSFreeMemory( pLabel ); + } + return; +} + +/********************************************************************* +*********************************************************************/ + +void DNSFreeLabelList(DNS_DOMAIN_LABEL *pLabelList) +{ + DNS_DOMAIN_LABEL *pTemp = NULL; + while(pLabelList) { + pTemp = pLabelList; + pLabelList = pLabelList->pNext; + DNSFreeLabel(pTemp); + } + + return; +} + +/********************************************************************* +*********************************************************************/ + +void DNSFreeDomainName(DNS_DOMAIN_NAME *pDomainName) +{ + DNSFreeLabelList(pDomainName->pLabelList); + DNSFreeMemory(pDomainName); + + return; +} + +/********************************************************************* +*********************************************************************/ + +static int32 LabelList( char *pszString, int32 * pdwPosition, DNS_DOMAIN_LABEL ** ppList ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pList = NULL; + DNS_DOMAIN_LABEL *pLabel = NULL; + int32 dwToken = 0; + char szToken[64]; + + memset( szToken, 0, 64 ); + dwError = getToken( pszString, szToken, &dwToken, pdwPosition ); + BAIL_ON_ERROR( dwError ); + if ( dwToken != TOKEN_LABEL ) { + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR( dwError ); + } + + dwError = DNSMakeLabel( szToken, &pLabel ); + BAIL_ON_ERROR( dwError ); + + memset( szToken, 0, 64 ); + dwError = getToken( pszString, szToken, &dwToken, pdwPosition ); + BAIL_ON_ERROR( dwError ); + if ( dwToken == TOKEN_EOS ) { + *ppList = pLabel; + return dwError; + } else if ( dwToken == TOKEN_SEPARATOR ) { + dwError = LabelList( pszString, pdwPosition, &pList ); + BAIL_ON_ERROR( dwError ); + + pLabel->pNext = pList; + *ppList = pLabel; + } + + return dwError; + + error: + if ( pLabel ) { + DNSFreeLabel( pLabel ); + } + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSGetDomainNameOffset( uint8 * pBuffer ) +{ + uint8 uLen = 0; + uint8 uLen1; + int32 dwOffset = 0; + + uLen1 = *pBuffer; + if ( uLen1 & 0xC0 ) { + dwOffset += 2; + + } else { + + while ( 1 ) { + + uLen = *pBuffer; + pBuffer++; + dwOffset++; + if ( uLen == 0 ) { + break; + } + dwOffset += uLen; + pBuffer += uLen; + } + } + return ( dwOffset ); +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSGenerateIdentifier( int16 * pwIdentifier ) +{ + int32 dwError = 0; + + *pwIdentifier = random( ); + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSGetDomainNameLength( DNS_DOMAIN_NAME * pDomainName, int32 * pdwLength ) +{ + int32 dwError = 0; + int32 dwLength = 0; + DNS_DOMAIN_LABEL *pDomainLabel = NULL; + + if ( !pDomainName ) { + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR( dwError ); + } + pDomainLabel = pDomainName->pLabelList; + + while ( pDomainLabel ) { + dwLength += pDomainLabel->dwLength; + dwLength += 1; + pDomainLabel = pDomainLabel->pNext; + } + dwLength += 1; + *pdwLength = dwLength; + + return dwError; + error: + + *pdwLength = 0; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCopyDomainName( uint8 * pBuffer, + DNS_DOMAIN_NAME * pDomainName, int32 * pdwCopied ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pDomainLabel = NULL; + uint8 uChar = 0; + int32 dwCopied = 0; + + if ( !pDomainName ) { + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR( dwError ); + } + + pDomainLabel = pDomainName->pLabelList; + while ( pDomainLabel ) { + uChar = ( uint8 ) pDomainLabel->dwLength; + memcpy( pBuffer + dwCopied, &uChar, sizeof( uint8 ) ); + dwCopied += sizeof( uint8 ); + memcpy( pBuffer + dwCopied, pDomainLabel->pszLabel, + pDomainLabel->dwLength ); + dwCopied += pDomainLabel->dwLength; + pDomainLabel = pDomainLabel->pNext; + } + uChar = 0; + memcpy( pBuffer + dwCopied, &uChar, sizeof( uint8 ) ); + dwCopied += sizeof( uint8 ); + + *pdwCopied = dwCopied; + return dwError; + + error: + *pdwCopied = 0; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSGenerateKeyName( char **ppszKeyName ) +{ + int32 dwError = 0; + char *pszKeyName = NULL; + char szTemp[256]; + char szBuffer[256]; + unsigned char uuid[16]; + + memset( szTemp, 0, 256 ); + memset( szBuffer, 0, 256 ); + memset( uuid, 0, 16 ); + + uuid_generate( uuid ); + + uuid_unparse( uuid, szBuffer ); + + strcpy( szTemp, szBuffer ); + dwError = DNSAllocateString( szTemp, &pszKeyName ); + BAIL_ON_ERROR( dwError ); + + *ppszKeyName = pszKeyName; + + return dwError; + + error: + + *ppszKeyName = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSDomainNameFromString( char *pszDomainName, + DNS_DOMAIN_NAME ** ppDomainName ) +{ + int32 dwError = 0; + int32 dwPosition = 0; + DNS_DOMAIN_NAME *pDomainName = NULL; + DNS_DOMAIN_LABEL *pLabelList = NULL; + + if ( !pszDomainName || !*pszDomainName ) { + dwError = ERROR_INVALID_PARAMETER; + return dwError; + } + + dwError = LabelList( pszDomainName, &dwPosition, &pLabelList ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_NAME ), + ( void ** ) &pDomainName ); + BAIL_ON_ERROR( dwError ); + + pDomainName->pLabelList = pLabelList; + + *ppDomainName = pDomainName; + + return dwError; + + error: + + if ( pLabelList ) { + DNSFreeLabelList( pLabelList ); + } + *ppDomainName = NULL; + + return dwError; +} + + +/********************************************************************* +*********************************************************************/ + +int32 DNSAppendLabel( DNS_DOMAIN_LABEL * pLabelList, + DNS_DOMAIN_LABEL * pLabel, + DNS_DOMAIN_LABEL ** ppNewLabelList ) +{ + DNS_DOMAIN_LABEL **ppLabelList = NULL; + int32 dwError = 0; + + if ( pLabelList == NULL ) { + *ppNewLabelList = pLabel; + return dwError; + } + + ppLabelList = &pLabelList; + + while ( ( *ppLabelList )->pNext ) { + ppLabelList = &( ( *ppLabelList )->pNext ); + } + + ( *ppLabelList )->pNext = pLabel; + *ppNewLabelList = pLabelList; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 GetLastError( ) +{ + return ( errno ); +} + +/********************************************************************* +*********************************************************************/ + +int32 WSAGetLastError( void ) +{ + return ( errno ); +} + +/********************************************************************* +*********************************************************************/ + +void DNSRecordGenerateOffsets( DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwOffset = 0; + uint8 *pRData = NULL; + int16 wKeySize, wnKeySize = 0; + + pRData = pDNSRecord->pRData; + switch ( pDNSRecord->RRHeader.wType ) { + case QTYPE_TKEY: + pDNSRecord->Offsets.TKey.wAlgorithmOffset = + ( int16 ) dwOffset; + dwOffset += DNSGetDomainNameOffset( pRData ); + pDNSRecord->Offsets.TKey.wInceptionOffset = + ( int16 ) dwOffset; + dwOffset += sizeof( int32 ); + pDNSRecord->Offsets.TKey.wExpirationOffset = + ( int16 ) dwOffset; + dwOffset += sizeof( int32 ); + pDNSRecord->Offsets.TKey.wModeOffset = ( int16 ) dwOffset; + dwOffset += sizeof( int16 ); + pDNSRecord->Offsets.TKey.wErrorOffset = ( int16 ) dwOffset; + dwOffset += sizeof( int16 ); + pDNSRecord->Offsets.TKey.wKeySizeOffset = ( int16 ) dwOffset; + dwOffset += sizeof( int16 ); + pDNSRecord->Offsets.TKey.wKeyDataOffset = ( int16 ) dwOffset; + + memcpy( &wnKeySize, + pRData + pDNSRecord->Offsets.TKey.wKeySizeOffset, + sizeof( int16 ) ); + wKeySize = ntohs( wnKeySize ); + + dwOffset += wKeySize; + pDNSRecord->Offsets.TKey.wOtherSizeOffset = + ( int16 ) dwOffset; + dwOffset += sizeof( int16 ); + pDNSRecord->Offsets.TKey.wOtherDataOffset = + ( int16 ) dwOffset; + break; + + case QTYPE_TSIG: + break; + } + return; +} + +/********************************************************************* +*********************************************************************/ + +int32 MapDNSResponseCodes( int16 wResponseCode ) +{ + int16 wnResponseCode = 0; + uint8 *pByte = NULL; + + wnResponseCode = htons( wResponseCode ); + pByte = ( uint8 * ) & wnResponseCode; + +#if 0 + printf( "Byte 0 - %.2x\n", pByte[0] ); + printf( "Byte 1 - %.2x\n", pByte[1] ); +#endif + /* Bit 3, 2, 1, 0 of Byte 2 represent the RCode */ + + return ( ( int32 ) pByte[1] ); +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSAllocateMemory(int32 dwSize, void * * ppMemory) +{ + + int32 dwError = 0; + void * pMemory = NULL; + + pMemory = malloc(dwSize); + if (!pMemory){ + dwError = ERROR_OUTOFMEMORY; + *ppMemory = NULL; + }else { + memset(pMemory,0, dwSize); + *ppMemory = pMemory; + } + return (dwError); +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSReallocMemory(void * pMemory, void * * ppNewMemory, int32 dwSize) +{ + int32 dwError = 0; + void * pNewMemory = NULL; + + if (pMemory == NULL) { + pNewMemory = malloc(dwSize); + memset(pNewMemory, 0, dwSize); + }else { + pNewMemory = realloc(pMemory, dwSize); + } + if (!pNewMemory){ + dwError = ERROR_OUTOFMEMORY; + *ppNewMemory = NULL; + }else { + *ppNewMemory = pNewMemory; + } + + return(dwError); +} + +/********************************************************************* +*********************************************************************/ + +void DNSFreeMemory( void * pMemory ) +{ + free(pMemory); + return; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSAllocateString(char *pszInputString, char **ppszOutputString) +{ + int32 dwError = 0; + int32 dwLen = 0; + char * pszOutputString = NULL; + + if (!pszInputString || !*pszInputString){ + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR(dwError); + } + dwLen = (int32)strlen(pszInputString); + dwError = DNSAllocateMemory(dwLen+1, (void * *)&pszOutputString); + BAIL_ON_ERROR(dwError); + + strcpy(pszOutputString, pszInputString); + + *ppszOutputString = pszOutputString; + + return(dwError); +error: + *ppszOutputString = pszOutputString; + return(dwError); +} + +/********************************************************************* +*********************************************************************/ + +void DNSFreeString(char * pszString) +{ + return; +} + + + |