summaryrefslogtreecommitdiff
path: root/source3/libaddns/dnsupdate.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libaddns/dnsupdate.c')
-rw-r--r--source3/libaddns/dnsupdate.c644
1 files changed, 644 insertions, 0 deletions
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;
+
+}