Exemplo n.º 1
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   P r i n t K e y r i n g P r o p e r t i e s                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  PrintKeyringProperties() prints properties associated with each key in the
%  keyring.
%
%  The format of the PrintKeyringProperties method is:
%
%      WizardBooleanType PrintKeyringProperties(const char *path,
%        BlobInfo *keyring_blob,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o path: the keyring path.
%
%    o blob_ibfo: list the key properties to this blob.
%
%    o exception: Return any errors or warnings in this structure.
%
*/
WizardExport WizardBooleanType PrintKeyringProperties(const char *path,
  BlobInfo *keyring_blob,ExceptionInfo *exception)
{
  char
    *canonical_path,
    *hex,
    *keyring_rdf,
    message[WizardPathExtent];

  const struct stat
    *properties;

  FileInfo
    *file_info;

  KeyringInfo
    keyring_info;

  ssize_t
    count;

  StringInfo
    *filetype,
    *id,
    *key,
    *magick,
    *nonce,
    *target;

  size_t
    length;

  WizardSizeType
    timestamp;

  WizardStatusType
    status;

  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
  WizardAssert(KeymapDomain,exception != (ExceptionInfo *) NULL);
  file_info=AcquireFileInfo(path,KeyringFilename,ReadFileMode,exception);
  if (file_info == (FileInfo *) NULL)
    return(WizardTrue);
  keyring_rdf=AcquireString("  <keyring:Keyring rdf:about=\"");
  canonical_path=CanonicalXMLContent(GetFilePath(file_info),WizardFalse);
  (void) ConcatenateString(&keyring_rdf,canonical_path);
  (void) ConcatenateString(&keyring_rdf,"\">\n");
  properties=GetFileProperties(file_info);
  (void) ConcatenateString(&keyring_rdf,"    <keyring:modify-date>");
  (void) FormatWizardTime(properties->st_mtime,WizardPathExtent,message);
  (void) ConcatenateString(&keyring_rdf,message);
  (void) ConcatenateString(&keyring_rdf,"</keyring:modify-date>\n");
  (void) ConcatenateString(&keyring_rdf,"    <keyring:create-date>");
  (void) FormatWizardTime(properties->st_mtime,WizardPathExtent,message);
  (void) ConcatenateString(&keyring_rdf,message);
  (void) ConcatenateString(&keyring_rdf,"</keyring:create-date>\n");
  (void) ConcatenateString(&keyring_rdf,"    <keyring:timestamp>");
  (void) FormatWizardTime(time((time_t *) NULL),WizardPathExtent,message);
  (void) ConcatenateString(&keyring_rdf,message);
  (void) ConcatenateString(&keyring_rdf,"</keyring:timestamp>\n");
  (void) ConcatenateString(&keyring_rdf,"  </keyring:Keyring>\n");
  length=strlen(keyring_rdf);
  count=WriteBlob(keyring_blob,length,(unsigned char *) keyring_rdf);
  keyring_rdf=DestroyString(keyring_rdf);
  if (count != (ssize_t) length)
    ThrowFileException(exception,FileError,GetFilePath(file_info));
  magick=GetWizardMagick(WizardMagick,sizeof(WizardMagick));
  target=CloneStringInfo(magick);
  status=ReadFileChunk(file_info,GetStringInfoDatum(target),
    GetStringInfoLength(target));
  if ((status == WizardFalse) || (CompareStringInfo(target,magick) != 0))
    {
      file_info=DestroyFileInfo(file_info,exception);
      (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
        "corrupt key ring file `%s'",GetFilePath(file_info));
      return(WizardFalse);
    }
  magick=DestroyStringInfo(magick);
  target=DestroyStringInfo(target);
  filetype=GetWizardMagick((unsigned char *) KeyringFiletype,
    strlen(KeyringFiletype));
  target=CloneStringInfo(filetype);
  status&=ReadFileChunk(file_info,GetStringInfoDatum(target),
    GetStringInfoLength(target));
  if ((status == WizardFalse) || (CompareStringInfo(target,filetype) != 0))
    {
      file_info=DestroyFileInfo(file_info,exception);
      (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
        "corrupt key ring file `%s'",GetFilePath(file_info));
      return(WizardFalse);
    }
  filetype=DestroyStringInfo(filetype);
  target=DestroyStringInfo(target);
  length=0;
  (void) ResetWizardMemory(&keyring_info,0,sizeof(keyring_info));
  while (ReadFile32Bits(file_info,&keyring_info.signature) != 0)
  {
    if (keyring_info.signature != WizardSignature)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
    status&=ReadFile32Bits(file_info,&length);
    status&=ReadFile16Bits(file_info,&keyring_info.protocol_major);
    status&=ReadFile16Bits(file_info,&keyring_info.protocol_minor);
    if ((keyring_info.protocol_major == 1) &&
        (keyring_info.protocol_minor == 0))
      timestamp=(time_t) length;
    else
      status&=ReadFile64Bits(file_info,&timestamp);
    keyring_info.timestamp=(time_t) timestamp;
    status&=ReadFile32Bits(file_info,&length);
    if (status == WizardFalse)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
    id=AcquireStringInfo(length);
    status&=ReadFileChunk(file_info,GetStringInfoDatum(id),
      GetStringInfoLength(id));
    status&=ReadFile32Bits(file_info,&length);
    if (status == WizardFalse)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
    key=AcquireStringInfo(length);
    status&=ReadFileChunk(file_info,GetStringInfoDatum(key),
      GetStringInfoLength(key));
    status&=ReadFile32Bits(file_info,&length);
    if (status == WizardFalse)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
    nonce=AcquireStringInfo(length);
    status&=ReadFileChunk(file_info,GetStringInfoDatum(nonce),
      GetStringInfoLength(nonce));
    keyring_rdf=AcquireString("  <keyring:Key rdf:about=\"");
    hex=StringInfoToHexString(id);
    (void) ConcatenateString(&keyring_rdf,hex);
    hex=DestroyString(hex);
    (void) ConcatenateString(&keyring_rdf,"\">\n");
    (void) ConcatenateString(&keyring_rdf,"    <keyring:memberOf "
      "rdf:resource=\"");
    (void) ConcatenateString(&keyring_rdf,canonical_path);
    (void) ConcatenateString(&keyring_rdf,"\"/>\n");
    (void) ConcatenateString(&keyring_rdf,"    <keyring:nonce>");
    hex=StringInfoToHexString(nonce);
    (void) ConcatenateString(&keyring_rdf,hex);
    hex=DestroyString(hex);
    (void) ConcatenateString(&keyring_rdf,"</keyring:nonce>\n");
    (void) ConcatenateString(&keyring_rdf,"    <keyring:timestamp>");
    (void) FormatWizardTime(keyring_info.timestamp,WizardPathExtent,message);
    (void) ConcatenateString(&keyring_rdf,message);
    (void) ConcatenateString(&keyring_rdf,"</keyring:timestamp>\n");
    (void) ConcatenateString(&keyring_rdf,"    <keyring:protocol>");
    (void) FormatLocaleString(message,WizardPathExtent,"%u.%u",
      keyring_info.protocol_major,(unsigned int) keyring_info.protocol_minor);
    (void) ConcatenateString(&keyring_rdf,message);
    (void) ConcatenateString(&keyring_rdf,"</keyring:protocol>\n");
    (void) ConcatenateString(&keyring_rdf,"  </keyring:Key>\n");
    length=strlen(keyring_rdf);
    count=WriteBlob(keyring_blob,length,(unsigned char *) keyring_rdf);
    keyring_rdf=DestroyString(keyring_rdf);
    if (count != (ssize_t) length)
      ThrowFileException(exception,FileError,GetFilePath(file_info));
    nonce=DestroyStringInfo(nonce);
    key=DestroyStringInfo(key);
    id=DestroyStringInfo(id);
    if (status == WizardFalse)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
  }
  canonical_path=DestroyString(canonical_path);
  file_info=DestroyFileInfo(file_info,exception);
  return(WizardTrue);
}
Exemplo n.º 2
0
REQUEST_NOTIFICATION_STATUS
CMyHttpModule::OnSendResponse(
    IN IHttpContext * pHttpContext,
    IN ISendResponseProvider * pResponseProvider
)
{
	REQUEST_STORED_CONTEXT *rsc = NULL;

	rsc = (REQUEST_STORED_CONTEXT *)pHttpContext->GetModuleContextContainer()->GetModuleContext(g_pModuleContext);

	EnterCriticalSection(&m_csLock);

	// here we must check if response body processing is enabled
	//
	if(rsc == NULL || rsc->m_pRequestRec == NULL || rsc->m_pResponseBuffer != NULL || !modsecIsResponseBodyAccessEnabled(rsc->m_pRequestRec))
	{
		goto Exit;
	}

    HRESULT hr = S_OK;
	IHttpResponse *pHttpResponse = NULL;
    HTTP_RESPONSE *pRawHttpResponse = NULL;
    HTTP_BYTE_RANGE *pFileByteRange = NULL;
    HTTP_DATA_CHUNK *pSourceDataChunk = NULL;
    LARGE_INTEGER  lFileSize;
    REQUEST_NOTIFICATION_STATUS ret = RQ_NOTIFICATION_CONTINUE;
	ULONGLONG ulTotalLength = 0;
	DWORD c;
	request_rec *r = rsc->m_pRequestRec;

	pHttpResponse = pHttpContext->GetResponse();
	pRawHttpResponse = pHttpResponse->GetRawHttpResponse();

	// here we must add handling of chunked response
	// apparently IIS 7 calls this handler once per chunk
	// see: http://stackoverflow.com/questions/4385249/how-to-buffer-and-process-chunked-data-before-sending-headers-in-iis7-native-mod

	if(pRawHttpResponse->EntityChunkCount == 0)
		goto Exit;

	// here we must transfer response headers
	//
	USHORT ctcch = 0;
	char *ct = (char *)pHttpResponse->GetHeader(HttpHeaderContentType, &ctcch);
	char *ctz = ZeroTerminate(ct, ctcch, r->pool);

	// assume HTML if content type not set
	// without this output filter would not buffer response and processing would hang
	//
	if(ctz[0] == 0)
		ctz = "text/html";

	r->content_type = ctz;

#define _TRANSHEADER(id,str) if(pRawHttpResponse->Headers.KnownHeaders[id].pRawValue != NULL) \
	{\
		apr_table_setn(r->headers_out, str, \
			ZeroTerminate(pRawHttpResponse->Headers.KnownHeaders[id].pRawValue, pRawHttpResponse->Headers.KnownHeaders[id].RawValueLength, r->pool)); \
	}

    _TRANSHEADER(HttpHeaderCacheControl, "Cache-Control");
    _TRANSHEADER(HttpHeaderConnection, "Connection");
    _TRANSHEADER(HttpHeaderDate, "Date");
    _TRANSHEADER(HttpHeaderKeepAlive, "Keep-Alive");             
    _TRANSHEADER(HttpHeaderPragma, "Pragma");                
    _TRANSHEADER(HttpHeaderTrailer, "Trailer");               
    _TRANSHEADER(HttpHeaderTransferEncoding, "Transfer-Encoding");      
    _TRANSHEADER(HttpHeaderUpgrade, "Upgrade");               
    _TRANSHEADER(HttpHeaderVia, "Via");                   
    _TRANSHEADER(HttpHeaderWarning, "Warning");               
    _TRANSHEADER(HttpHeaderAllow, "Allow");                 
    _TRANSHEADER(HttpHeaderContentLength, "Content-Length");         
    _TRANSHEADER(HttpHeaderContentType, "Content-Type");           
    _TRANSHEADER(HttpHeaderContentEncoding, "Content-Encoding");       
    _TRANSHEADER(HttpHeaderContentLanguage, "Content-Language");       
    _TRANSHEADER(HttpHeaderContentLocation, "Content-Location");       
    _TRANSHEADER(HttpHeaderContentMd5, "Content-Md5");            
    _TRANSHEADER(HttpHeaderContentRange, "Content-Range");          
    _TRANSHEADER(HttpHeaderExpires, "Expires");               
    _TRANSHEADER(HttpHeaderLastModified, "Last-Modified");          
	_TRANSHEADER(HttpHeaderAcceptRanges, "Accept-Ranges");
    _TRANSHEADER(HttpHeaderAge, "Age");                   
    _TRANSHEADER(HttpHeaderEtag, "Etag");                  
    _TRANSHEADER(HttpHeaderLocation, "Location");              
    _TRANSHEADER(HttpHeaderProxyAuthenticate, "Proxy-Authenticate");     
    _TRANSHEADER(HttpHeaderRetryAfter, "Retry-After");            
    _TRANSHEADER(HttpHeaderServer, "Server");                
    _TRANSHEADER(HttpHeaderSetCookie, "Set-Cookie");             
    _TRANSHEADER(HttpHeaderVary, "Vary");                  
    _TRANSHEADER(HttpHeaderWwwAuthenticate, "Www-Authenticate");

#undef	_TRANSHEADER

	for(int i = 0; i < pRawHttpResponse->Headers.UnknownHeaderCount; i++)
	{
		apr_table_setn(r->headers_out, 
			ZeroTerminate(pRawHttpResponse->Headers.pUnknownHeaders[i].pName, pRawHttpResponse->Headers.pUnknownHeaders[i].NameLength, r->pool), 
			ZeroTerminate(pRawHttpResponse->Headers.pUnknownHeaders[i].pRawValue, pRawHttpResponse->Headers.pUnknownHeaders[i].RawValueLength, r->pool));
	}

	r->content_encoding = apr_table_get(r->headers_out, "Content-Encoding");
	//r->content_type = apr_table_get(r->headers_out, "Content-Type");		-- already set above

	const char *lng = apr_table_get(r->headers_out, "Content-Languages");

	if(lng != NULL)
	{
		r->content_languages = apr_array_make(r->pool, 1, sizeof(const char *));

		*(const char **)apr_array_push(r->content_languages) = lng;
	}

	// Disable kernel caching for this response
	// Probably we don't have to do it for ModSecurity

    //pHttpContext->GetResponse()->DisableKernelCache(
    //        IISCacheEvents::HTTPSYS_CACHEABLE::HANDLER_HTTPSYS_UNFRIENDLY);

    for(c = 0; c < pRawHttpResponse->EntityChunkCount; c++ )
    {
        pSourceDataChunk = &pRawHttpResponse->pEntityChunks[ c ];

        switch( pSourceDataChunk->DataChunkType )
        {
            case HttpDataChunkFromMemory:
                ulTotalLength += pSourceDataChunk->FromMemory.BufferLength;
                break;
            case HttpDataChunkFromFileHandle:
                pFileByteRange = &pSourceDataChunk->FromFileHandle.ByteRange;
                //
                // File chunks may contain by ranges with unspecified length 
                // (HTTP_BYTE_RANGE_TO_EOF).  In order to send parts of such a chunk, 
                // its necessary to know when the chunk is finished, and
                // we need to move to the next chunk.
                //              
                if ( pFileByteRange->Length.QuadPart == HTTP_BYTE_RANGE_TO_EOF)
                {
                    if ( GetFileType( pSourceDataChunk->FromFileHandle.FileHandle ) == 
                                    FILE_TYPE_DISK )
                    {
                        if ( !GetFileSizeEx( pSourceDataChunk->FromFileHandle.FileHandle,
                                             &lFileSize ) )
                        {
                            DWORD dwError = GetLastError();
                            hr = HRESULT_FROM_WIN32(dwError);
                            goto Finished;
                        }

                        // put the resolved file length in the chunk, replacing 
                        // HTTP_BYTE_RANGE_TO_EOF
                        pFileByteRange->Length.QuadPart = 
                              lFileSize.QuadPart - pFileByteRange->StartingOffset.QuadPart;
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
                        goto Finished;                        
                    }
                }  

                ulTotalLength += pFileByteRange->Length.QuadPart;
                break;
            default:
                // TBD: consider implementing HttpDataChunkFromFragmentCache, 
                // and HttpDataChunkFromFragmentCacheEx
                hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
                goto Finished;                        
        }
    }

	rsc->m_pResponseBuffer = (char *)apr_palloc(rsc->m_pRequestRec->pool, ulTotalLength);

	ulTotalLength = 0;

    for(c = 0; c < pRawHttpResponse->EntityChunkCount; c++ )
    {
        pSourceDataChunk = &pRawHttpResponse->pEntityChunks[ c ];

        switch( pSourceDataChunk->DataChunkType )
        {
            case HttpDataChunkFromMemory:
				memcpy(rsc->m_pResponseBuffer + ulTotalLength, pSourceDataChunk->FromMemory.pBuffer, pSourceDataChunk->FromMemory.BufferLength);
                ulTotalLength += pSourceDataChunk->FromMemory.BufferLength;
                break;
            case HttpDataChunkFromFileHandle:
                pFileByteRange = &pSourceDataChunk->FromFileHandle.ByteRange;

				if(ReadFileChunk(pSourceDataChunk, rsc->m_pResponseBuffer + ulTotalLength) != S_OK)
				{
			        DWORD dwErr = GetLastError();

					hr = HRESULT_FROM_WIN32(dwErr);
	                goto Finished;
				}

                ulTotalLength += pFileByteRange->Length.QuadPart;
                break;
            default:
                // TBD: consider implementing HttpDataChunkFromFragmentCache, 
                // and HttpDataChunkFromFragmentCacheEx
                hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
                goto Finished;                        
        }
    }

	rsc->m_pResponseLength = ulTotalLength;

	//
    // If there's no content-length set, we need to set it to avoid chunked transfer mode
    // We can only do it if there is it's the only response to be sent.
    //

    DWORD dwFlags = pResponseProvider->GetFlags();

	if (pResponseProvider->GetHeadersBeingSent() && 
         (dwFlags & HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0 &&
         pHttpContext->GetResponse()->GetHeader(HttpHeaderContentLength) == NULL)    
    {
        CHAR szLength[21]; //Max length for a 64 bit int is 20

         ZeroMemory(szLength, sizeof(szLength));

         hr = StringCchPrintfA(
                    szLength, 
                    sizeof(szLength) / sizeof(CHAR) - 1, "%d", 
                    ulTotalLength);

        if(FAILED(hr))
        {
            goto Finished;      
        }

         hr = pHttpContext->GetResponse()->SetHeader(
                    HttpHeaderContentLength, 
                    szLength, 
                    (USHORT)strlen(szLength),
                    TRUE);

        if(FAILED(hr))
        {
            goto Finished;      
        }
    }

Finished:

	int status = modsecProcessResponse(rsc->m_pRequestRec);

	// the logic here is temporary, needs clarification
	//
	if(status != 0 && status != -1)
	{
		pHttpContext->GetResponse()->Clear();
		pHttpContext->GetResponse()->SetStatus(status, "ModSecurity Action");
		pHttpContext->SetRequestHandled();

		rsc->FinishRequest();

		LeaveCriticalSection(&m_csLock);
		
		return RQ_NOTIFICATION_FINISH_REQUEST;
	}
Exit:
	// temporary hack, in reality OnSendRequest theoretically could possibly come before OnEndRequest
	//
	if(rsc != NULL)
		rsc->FinishRequest();

	LeaveCriticalSection(&m_csLock);
		
	return RQ_NOTIFICATION_CONTINUE;
}
Exemplo n.º 3
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   E x p o r t K e y r i n g K e y                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ExportKeyringKey() exports a key from the keyring.
%
%  The format of the ExportKeyringKey method is:
%
%      WizardBooleanType ExportKeyringKey(KeyringInfo *keyring_info,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o keyring_info: The ring info.
%
%    o exception: Return any errors or warnings in this structure.
%
*/
WizardExport WizardBooleanType ExportKeyringKey(KeyringInfo *keyring_info,
  ExceptionInfo *exception)
{
  FileInfo
    *file_info;

  WizardStatusType
    status;

  StringInfo
    *filetype,
    *id,
    *key,
    *magick,
    *nonce,
    *target;

  size_t
    length,
    signature;

  WizardSizeType
    timestamp;

  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
  WizardAssert(KeymapDomain,keyring_info != (KeyringInfo *) NULL);
  WizardAssert(KeymapDomain,keyring_info->signature == WizardSignature);
  WizardAssert(KeymapDomain,exception != (ExceptionInfo *) NULL);
  file_info=AcquireFileInfo(keyring_info->path,KeyringFilename,ReadFileMode,
    exception);
  if (file_info == (FileInfo *) NULL)
    return(WizardFalse);
  magick=GetWizardMagick(WizardMagick,sizeof(WizardMagick));
  target=CloneStringInfo(magick);
  status=ReadFileChunk(file_info,GetStringInfoDatum(target),
    GetStringInfoLength(target));
  if ((status == WizardFalse) || (CompareStringInfo(target,magick) != 0))
    {
      file_info=DestroyFileInfo(file_info,exception);
      (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
        "corrupt key ring file `%s'",GetFilePath(file_info));
      return(WizardFalse);
    }
  magick=DestroyStringInfo(magick);
  target=DestroyStringInfo(target);
  filetype=GetWizardMagick((unsigned char *) KeyringFiletype,
    strlen(KeyringFiletype));
  target=CloneStringInfo(filetype);
  status&=ReadFileChunk(file_info,GetStringInfoDatum(target),
    GetStringInfoLength(target));
  if ((status == WizardFalse) || (CompareStringInfo(target,filetype) != 0))
    {
      file_info=DestroyFileInfo(file_info,exception);
      (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
        "corrupt key ring file `%s'",GetFilePath(file_info));
      return(WizardFalse);
    }
  filetype=DestroyStringInfo(filetype);
  target=DestroyStringInfo(target);
  signature=0;
  length=0;
  while (ReadFile32Bits(file_info,&signature) != 0)
  {
    if (signature != WizardSignature)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
    keyring_info->signature=signature;
    status&=ReadFile32Bits(file_info,&length);
    status&=ReadFile16Bits(file_info,&keyring_info->protocol_major);
    status&=ReadFile16Bits(file_info,&keyring_info->protocol_minor);
    if ((keyring_info->protocol_major == 1) &&
        (keyring_info->protocol_minor == 0))
      timestamp=(time_t) length;
    else
      status&=ReadFile64Bits(file_info,&timestamp);
    keyring_info->timestamp=(time_t) timestamp;
    status&=ReadFile32Bits(file_info,&length);
    if (status == WizardFalse)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
    id=AcquireStringInfo(length);
    status&=ReadFileChunk(file_info,GetStringInfoDatum(id),
      GetStringInfoLength(id));
    status&=ReadFile32Bits(file_info,&length);
    if (status == WizardFalse)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
    key=AcquireStringInfo(length);
    status&=ReadFileChunk(file_info,GetStringInfoDatum(key),
      GetStringInfoLength(key));
    status&=ReadFile32Bits(file_info,&length);
    if (status == WizardFalse)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
    nonce=AcquireStringInfo(length);
    status&=ReadFileChunk(file_info,GetStringInfoDatum(nonce),
      GetStringInfoLength(nonce));
    if (CompareStringInfo(keyring_info->id,id) == 0)
      {
        SetKeyringKey(keyring_info,key);
        SetKeyringNonce(keyring_info,nonce);
        nonce=DestroyStringInfo(nonce);
        key=DestroyStringInfo(key);
        id=DestroyStringInfo(id);
        file_info=DestroyFileInfo(file_info,exception);
        return(WizardTrue);
      }
    nonce=DestroyStringInfo(nonce);
    key=DestroyStringInfo(key);
    id=DestroyStringInfo(id);
    if (status == WizardFalse)
      {
        file_info=DestroyFileInfo(file_info,exception);
        (void) ThrowWizardException(exception,GetWizardModule(),KeyringError,
          "corrupt key ring file `%s'",GetFilePath(file_info));
        return(WizardFalse);
      }
  }
  file_info=DestroyFileInfo(file_info,exception);
  return(WizardFalse);
}