[Fedora-directory-commits] windowsautoenroll/proxy MSG00001.bin, NONE, 1.1 RedHatCSProxy.idl, NONE, 1.1 RedHatCSProxy_h.h, NONE, 1.1 RedHatCSProxy_i.c, NONE, 1.1 RedHatCSProxy_p.c, NONE, 1.1 RedHatCertSvrProxy.rc, NONE, 1.1 b64.c, NONE, 1.1 b64.h, NONE, 1.1 cert.ico, NONE, 1.1 csproxy.h, NONE, 1.1 dlldata.c, NONE, 1.1 messages.RES, NONE, 1.1 messages.aps, NONE, 1.1 messages.h, NONE, 1.1 messages.mc, NONE, 1.1 messages.rc, NONE, 1.1 p32.ico, NONE, 1.1 proxy.vcproj, NONE, 1.1 registry.cpp, NONE, 1.1 resource.h, NONE, 1.1 service.cpp, NONE, 1.1 stdafx.cpp, NONE, 1.1 stdafx.h, NONE, 1.1 util.cpp, NONE, 1.1 proxy.cpp, 1.1.1.1, 1.2 submit.cpp, 1.1.1.1, 1.2

Steven W Parkinson (sparkins) fedora-directory-commits at redhat.com
Tue Mar 13 01:36:12 UTC 2007


Author: sparkins

Update of /cvs/dirsec/windowsautoenroll/proxy
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv24806/proxy

Modified Files:
	proxy.cpp submit.cpp 
Added Files:
	MSG00001.bin RedHatCSProxy.idl RedHatCSProxy_h.h 
	RedHatCSProxy_i.c RedHatCSProxy_p.c RedHatCertSvrProxy.rc 
	b64.c b64.h cert.ico csproxy.h dlldata.c messages.RES 
	messages.aps messages.h messages.mc messages.rc p32.ico 
	proxy.vcproj registry.cpp resource.h service.cpp stdafx.cpp 
	stdafx.h util.cpp 
Log Message:
0.9.1: new since last release:
running as a service, CA failover, support for ICertRequestD2 (IFDEFed),
using C++ strings instead of char[], support for additional domain controllers
in a forest, decoding PKCS#10 request to find Cert template name, installer,
new base 64 decoder, profile mapper



--- NEW FILE MSG00001.bin ---



--- NEW FILE RedHatCSProxy.idl ---
/** BEGIN COPYRIGHT BLOCK
 * END COPYRIGHT BLOCK */

import "oaidl.idl";
import "ocidl.idl";

// The contents of this file was written by Red Hat Corp, based on information
// in certreqd.h, which is shipped in the MSDN SDK

//  RH CS Proxy file ------------------------------------------------------------------------

// This file will be processed by the MIDL tool to produce the type library
// and marshalling code.

import "wtypes.idl"; 
//import "certif.idl";


// This comes from certbase.idl, but has no corresponding include file
typedef struct _CERTTRANSBLOB
{
	unsigned long               cb;
	[size_is(cb), unique] BYTE *pb;
} CERTTRANSBLOB;


//+--------------------------------------------------------------------------
// ICertRequestD class -- local COM interface, local implementation
//+--------------------------------------------------------------------------


[
	object,
	uuid(d99e6e70-fc88-11d0-b498-00a0c90312f3),
	dual,
	helpstring("Red Hat ICertRequestD Interface"),
	pointer_default(unique)
]

interface ICertRequestD: IUnknown
{
	import "oaidl.idl";


	HRESULT Request(
		[in] DWORD dwFlags,
		[unique][string][in] const wchar_t * pwszAuthority,
		[ref][out][in]       DWORD *         pdwRequestId,
		[out]                DWORD *         pdwDisposition,
		[unique][string][in] const wchar_t * pwszAttributes,
		[ref][in]            const CERTTRANSBLOB *pctbRequest,
		[ref][out]           CERTTRANSBLOB * pctbCertChain,
		[ref][out]           CERTTRANSBLOB * pctbEncodedCert,
		[ref][out]           CERTTRANSBLOB * pctbDispositionMessage);

	HRESULT GetCACert( 
		[in]                 DWORD           fchain,
		[unique][string][in] const wchar_t * pwszAuthority,
		[ref][out]           CERTTRANSBLOB * pctbOut );

	HRESULT  Ping( 
		[unique][string][in] const wchar_t * pwszAuthority);

};


[
	object,
	uuid(5422fd3a-d4b8-4cef-a12e-e87d4ca22e90),
	dual,
	helpstring("Red Hat ICertRequestD2 Interface"),
	pointer_default(unique)
]

interface ICertRequestD2: ICertRequestD
{
	import "oaidl.idl";

	HRESULT Request2(
		[unique][string][in] const wchar_t * pwszAuthority,
		[in]                 DWORD           dwFlags,
		[unique][string][in] const wchar_t * pwszSerialNumber,
		[ref][out][in]       DWORD *         pdwRequestId,
		[out]                DWORD *         pdwDisposition,
		[unique][string][in] const wchar_t * pwszAttributes,
		[ref][in]            const CERTTRANSBLOB *pctbRequest,
		[ref][out]           CERTTRANSBLOB * pctbFullResponse,
		[ref][out]           CERTTRANSBLOB * pctbEncodedCert,
		[ref][out]           CERTTRANSBLOB * pctbDispositionMessage
		);


	HRESULT GetCAProperty(
		 [unique][string][in]  const wchar_t *pwszAuthority,
         [in]                  LONG           PropId,
         [in]                  LONG           PropIndex,
         [in]                  LONG           PropType,
         [ref][out]            CERTTRANSBLOB *pctbPropertyValue 
		 );


	HRESULT GetCAPropertyInfo(
		 [unique][string][in]    const wchar_t *pwszAuthority,
         [out]                   LONG          *pcProperty,
         [ref][out]              CERTTRANSBLOB *pctbPropInfo
		 );

			
	HRESULT  Ping2( 
		[unique][string][in] const wchar_t * pwszAuthority);


};



[
	uuid(96946675-8068-403f-889C-F406D57FE8A2),
	helpstring("Red Hat Type Library"),
	version(1.0)
]
library redhattypelib
{
	[
		uuid(d99e6e74-fc88-11d0-b498-00a0c90312f3),
		helpstring("Red Hat CCertRequestD Class"),
	]
	coclass CCertRequestD
	{
		[default] interface ICertRequestD;

	}
}




--- NEW FILE RedHatCSProxy_h.h ---


/* this ALWAYS GENERATED file contains the definitions for the interfaces */


 /* File created by MIDL compiler version 6.00.0361 */
/* at Wed Feb 07 16:18:20 2007
 */
/* Compiler settings for .\RedHatCSProxy.idl:
    Oicf, W1, Zp8, env=Win32 (32b run)
    protocol : dce , ms_ext, c_ext, robust
    error checks: allocation ref bounds_check enum stub_data 
    VC __declspec() decoration level: 
         __declspec(uuid()), __declspec(selectany), __declspec(novtable)
         DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING(  )

#pragma warning( disable: 4049 )  /* more than 64k source lines */


/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif

#include "rpc.h"
#include "rpcndr.h"

#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__

#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/

#ifndef __RedHatCSProxy_h_h__
#define __RedHatCSProxy_h_h__

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

/* Forward Declarations */ 

#ifndef __ICertRequestD_FWD_DEFINED__
#define __ICertRequestD_FWD_DEFINED__
typedef interface ICertRequestD ICertRequestD;
#endif 	/* __ICertRequestD_FWD_DEFINED__ */


#ifndef __ICertRequestD2_FWD_DEFINED__
#define __ICertRequestD2_FWD_DEFINED__
typedef interface ICertRequestD2 ICertRequestD2;
#endif 	/* __ICertRequestD2_FWD_DEFINED__ */


#ifndef __CCertRequestD_FWD_DEFINED__
#define __CCertRequestD_FWD_DEFINED__

#ifdef __cplusplus
typedef class CCertRequestD CCertRequestD;
#else
typedef struct CCertRequestD CCertRequestD;
#endif /* __cplusplus */

#endif 	/* __CCertRequestD_FWD_DEFINED__ */


/* header files for imported files */
#include "oaidl.h"
#include "ocidl.h"

#ifdef __cplusplus
extern "C"{
#endif 

void * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void * ); 

/* interface __MIDL_itf_RedHatCSProxy_0000 */
/* [local] */ 

typedef struct _CERTTRANSBLOB
    {
    unsigned long cb;
    /* [unique][size_is] */ BYTE *pb;
    } 	CERTTRANSBLOB;



extern RPC_IF_HANDLE __MIDL_itf_RedHatCSProxy_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_RedHatCSProxy_0000_v0_0_s_ifspec;

#ifndef __ICertRequestD_INTERFACE_DEFINED__
#define __ICertRequestD_INTERFACE_DEFINED__

/* interface ICertRequestD */
/* [unique][helpstring][dual][uuid][object] */ 


EXTERN_C const IID IID_ICertRequestD;

#if defined(__cplusplus) && !defined(CINTERFACE)
    
    MIDL_INTERFACE("d99e6e70-fc88-11d0-b498-00a0c90312f3")
    ICertRequestD : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE Request( 
            /* [in] */ DWORD dwFlags,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [in][out][ref] */ DWORD *pdwRequestId,
            /* [out] */ DWORD *pdwDisposition,
            /* [in][string][unique] */ const wchar_t *pwszAttributes,
            /* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
            /* [out][ref] */ CERTTRANSBLOB *pctbCertChain,
            /* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
            /* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetCACert( 
            /* [in] */ DWORD fchain,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [out][ref] */ CERTTRANSBLOB *pctbOut) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE Ping( 
            /* [in][string][unique] */ const wchar_t *pwszAuthority) = 0;
        
    };
    
#else 	/* C style interface */

    typedef struct ICertRequestDVtbl
    {
        BEGIN_INTERFACE
        
        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
            ICertRequestD * This,
            /* [in] */ REFIID riid,
            /* [iid_is][out] */ void **ppvObject);
        
        ULONG ( STDMETHODCALLTYPE *AddRef )( 
            ICertRequestD * This);
        
        ULONG ( STDMETHODCALLTYPE *Release )( 
            ICertRequestD * This);
        
        HRESULT ( STDMETHODCALLTYPE *Request )( 
            ICertRequestD * This,
            /* [in] */ DWORD dwFlags,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [in][out][ref] */ DWORD *pdwRequestId,
            /* [out] */ DWORD *pdwDisposition,
            /* [in][string][unique] */ const wchar_t *pwszAttributes,
            /* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
            /* [out][ref] */ CERTTRANSBLOB *pctbCertChain,
            /* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
            /* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage);
        
        HRESULT ( STDMETHODCALLTYPE *GetCACert )( 
            ICertRequestD * This,
            /* [in] */ DWORD fchain,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [out][ref] */ CERTTRANSBLOB *pctbOut);
        
        HRESULT ( STDMETHODCALLTYPE *Ping )( 
            ICertRequestD * This,
            /* [in][string][unique] */ const wchar_t *pwszAuthority);
        
        END_INTERFACE
    } ICertRequestDVtbl;

    interface ICertRequestD
    {
        CONST_VTBL struct ICertRequestDVtbl *lpVtbl;
    };

    

#ifdef COBJMACROS


#define ICertRequestD_QueryInterface(This,riid,ppvObject)	\
    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)

#define ICertRequestD_AddRef(This)	\
    (This)->lpVtbl -> AddRef(This)

#define ICertRequestD_Release(This)	\
    (This)->lpVtbl -> Release(This)


#define ICertRequestD_Request(This,dwFlags,pwszAuthority,pdwRequestId,pdwDisposition,pwszAttributes,pctbRequest,pctbCertChain,pctbEncodedCert,pctbDispositionMessage)	\
    (This)->lpVtbl -> Request(This,dwFlags,pwszAuthority,pdwRequestId,pdwDisposition,pwszAttributes,pctbRequest,pctbCertChain,pctbEncodedCert,pctbDispositionMessage)

#define ICertRequestD_GetCACert(This,fchain,pwszAuthority,pctbOut)	\
    (This)->lpVtbl -> GetCACert(This,fchain,pwszAuthority,pctbOut)

#define ICertRequestD_Ping(This,pwszAuthority)	\
    (This)->lpVtbl -> Ping(This,pwszAuthority)

#endif /* COBJMACROS */


#endif 	/* C style interface */



HRESULT STDMETHODCALLTYPE ICertRequestD_Request_Proxy( 
    ICertRequestD * This,
    /* [in] */ DWORD dwFlags,
    /* [in][string][unique] */ const wchar_t *pwszAuthority,
    /* [in][out][ref] */ DWORD *pdwRequestId,
    /* [out] */ DWORD *pdwDisposition,
    /* [in][string][unique] */ const wchar_t *pwszAttributes,
    /* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
    /* [out][ref] */ CERTTRANSBLOB *pctbCertChain,
    /* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
    /* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage);


void __RPC_STUB ICertRequestD_Request_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);


HRESULT STDMETHODCALLTYPE ICertRequestD_GetCACert_Proxy( 
    ICertRequestD * This,
    /* [in] */ DWORD fchain,
    /* [in][string][unique] */ const wchar_t *pwszAuthority,
    /* [out][ref] */ CERTTRANSBLOB *pctbOut);


void __RPC_STUB ICertRequestD_GetCACert_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);


HRESULT STDMETHODCALLTYPE ICertRequestD_Ping_Proxy( 
    ICertRequestD * This,
    /* [in][string][unique] */ const wchar_t *pwszAuthority);


void __RPC_STUB ICertRequestD_Ping_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);



#endif 	/* __ICertRequestD_INTERFACE_DEFINED__ */


#ifndef __ICertRequestD2_INTERFACE_DEFINED__
#define __ICertRequestD2_INTERFACE_DEFINED__

/* interface ICertRequestD2 */
/* [unique][helpstring][dual][uuid][object] */ 


EXTERN_C const IID IID_ICertRequestD2;

#if defined(__cplusplus) && !defined(CINTERFACE)
    
    MIDL_INTERFACE("5422fd3a-d4b8-4cef-a12e-e87d4ca22e90")
    ICertRequestD2 : public ICertRequestD
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE Request2( 
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [in] */ DWORD dwFlags,
            /* [in][string][unique] */ const wchar_t *pwszSerialNumber,
            /* [in][out][ref] */ DWORD *pdwRequestId,
            /* [out] */ DWORD *pdwDisposition,
            /* [in][string][unique] */ const wchar_t *pwszAttributes,
            /* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
            /* [out][ref] */ CERTTRANSBLOB *pctbFullResponse,
            /* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
            /* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetCAProperty( 
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [in] */ LONG PropId,
            /* [in] */ LONG PropIndex,
            /* [in] */ LONG PropType,
            /* [out][ref] */ CERTTRANSBLOB *pctbPropertyValue) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetCAPropertyInfo( 
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [out] */ LONG *pcProperty,
            /* [out][ref] */ CERTTRANSBLOB *pctbPropInfo) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE Ping2( 
            /* [in][string][unique] */ const wchar_t *pwszAuthority) = 0;
        
    };
    
#else 	/* C style interface */

    typedef struct ICertRequestD2Vtbl
    {
        BEGIN_INTERFACE
        
        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
            ICertRequestD2 * This,
            /* [in] */ REFIID riid,
            /* [iid_is][out] */ void **ppvObject);
        
        ULONG ( STDMETHODCALLTYPE *AddRef )( 
            ICertRequestD2 * This);
        
        ULONG ( STDMETHODCALLTYPE *Release )( 
            ICertRequestD2 * This);
        
        HRESULT ( STDMETHODCALLTYPE *Request )( 
            ICertRequestD2 * This,
            /* [in] */ DWORD dwFlags,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [in][out][ref] */ DWORD *pdwRequestId,
            /* [out] */ DWORD *pdwDisposition,
            /* [in][string][unique] */ const wchar_t *pwszAttributes,
            /* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
            /* [out][ref] */ CERTTRANSBLOB *pctbCertChain,
            /* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
            /* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage);
        
        HRESULT ( STDMETHODCALLTYPE *GetCACert )( 
            ICertRequestD2 * This,
            /* [in] */ DWORD fchain,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [out][ref] */ CERTTRANSBLOB *pctbOut);
        
        HRESULT ( STDMETHODCALLTYPE *Ping )( 
            ICertRequestD2 * This,
            /* [in][string][unique] */ const wchar_t *pwszAuthority);
        
        HRESULT ( STDMETHODCALLTYPE *Request2 )( 
            ICertRequestD2 * This,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [in] */ DWORD dwFlags,
            /* [in][string][unique] */ const wchar_t *pwszSerialNumber,
            /* [in][out][ref] */ DWORD *pdwRequestId,
            /* [out] */ DWORD *pdwDisposition,
            /* [in][string][unique] */ const wchar_t *pwszAttributes,
            /* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
            /* [out][ref] */ CERTTRANSBLOB *pctbFullResponse,
            /* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
            /* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage);
        
        HRESULT ( STDMETHODCALLTYPE *GetCAProperty )( 
            ICertRequestD2 * This,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [in] */ LONG PropId,
            /* [in] */ LONG PropIndex,
            /* [in] */ LONG PropType,
            /* [out][ref] */ CERTTRANSBLOB *pctbPropertyValue);
        
        HRESULT ( STDMETHODCALLTYPE *GetCAPropertyInfo )( 
            ICertRequestD2 * This,
            /* [in][string][unique] */ const wchar_t *pwszAuthority,
            /* [out] */ LONG *pcProperty,
            /* [out][ref] */ CERTTRANSBLOB *pctbPropInfo);
        
        HRESULT ( STDMETHODCALLTYPE *Ping2 )( 
            ICertRequestD2 * This,
            /* [in][string][unique] */ const wchar_t *pwszAuthority);
        
        END_INTERFACE
    } ICertRequestD2Vtbl;

    interface ICertRequestD2
    {
        CONST_VTBL struct ICertRequestD2Vtbl *lpVtbl;
    };

    

#ifdef COBJMACROS


#define ICertRequestD2_QueryInterface(This,riid,ppvObject)	\
    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)

#define ICertRequestD2_AddRef(This)	\
    (This)->lpVtbl -> AddRef(This)

#define ICertRequestD2_Release(This)	\
    (This)->lpVtbl -> Release(This)


#define ICertRequestD2_Request(This,dwFlags,pwszAuthority,pdwRequestId,pdwDisposition,pwszAttributes,pctbRequest,pctbCertChain,pctbEncodedCert,pctbDispositionMessage)	\
    (This)->lpVtbl -> Request(This,dwFlags,pwszAuthority,pdwRequestId,pdwDisposition,pwszAttributes,pctbRequest,pctbCertChain,pctbEncodedCert,pctbDispositionMessage)

#define ICertRequestD2_GetCACert(This,fchain,pwszAuthority,pctbOut)	\
    (This)->lpVtbl -> GetCACert(This,fchain,pwszAuthority,pctbOut)

#define ICertRequestD2_Ping(This,pwszAuthority)	\
    (This)->lpVtbl -> Ping(This,pwszAuthority)


#define ICertRequestD2_Request2(This,pwszAuthority,dwFlags,pwszSerialNumber,pdwRequestId,pdwDisposition,pwszAttributes,pctbRequest,pctbFullResponse,pctbEncodedCert,pctbDispositionMessage)	\
    (This)->lpVtbl -> Request2(This,pwszAuthority,dwFlags,pwszSerialNumber,pdwRequestId,pdwDisposition,pwszAttributes,pctbRequest,pctbFullResponse,pctbEncodedCert,pctbDispositionMessage)

#define ICertRequestD2_GetCAProperty(This,pwszAuthority,PropId,PropIndex,PropType,pctbPropertyValue)	\
    (This)->lpVtbl -> GetCAProperty(This,pwszAuthority,PropId,PropIndex,PropType,pctbPropertyValue)

#define ICertRequestD2_GetCAPropertyInfo(This,pwszAuthority,pcProperty,pctbPropInfo)	\
    (This)->lpVtbl -> GetCAPropertyInfo(This,pwszAuthority,pcProperty,pctbPropInfo)

#define ICertRequestD2_Ping2(This,pwszAuthority)	\
    (This)->lpVtbl -> Ping2(This,pwszAuthority)

#endif /* COBJMACROS */


#endif 	/* C style interface */



HRESULT STDMETHODCALLTYPE ICertRequestD2_Request2_Proxy( 
    ICertRequestD2 * This,
    /* [in][string][unique] */ const wchar_t *pwszAuthority,
    /* [in] */ DWORD dwFlags,
    /* [in][string][unique] */ const wchar_t *pwszSerialNumber,
    /* [in][out][ref] */ DWORD *pdwRequestId,
    /* [out] */ DWORD *pdwDisposition,
    /* [in][string][unique] */ const wchar_t *pwszAttributes,
    /* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
    /* [out][ref] */ CERTTRANSBLOB *pctbFullResponse,
    /* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
    /* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage);


void __RPC_STUB ICertRequestD2_Request2_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);


HRESULT STDMETHODCALLTYPE ICertRequestD2_GetCAProperty_Proxy( 
    ICertRequestD2 * This,
    /* [in][string][unique] */ const wchar_t *pwszAuthority,
    /* [in] */ LONG PropId,
    /* [in] */ LONG PropIndex,
    /* [in] */ LONG PropType,
    /* [out][ref] */ CERTTRANSBLOB *pctbPropertyValue);


void __RPC_STUB ICertRequestD2_GetCAProperty_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);


HRESULT STDMETHODCALLTYPE ICertRequestD2_GetCAPropertyInfo_Proxy( 
    ICertRequestD2 * This,
    /* [in][string][unique] */ const wchar_t *pwszAuthority,
    /* [out] */ LONG *pcProperty,
    /* [out][ref] */ CERTTRANSBLOB *pctbPropInfo);


void __RPC_STUB ICertRequestD2_GetCAPropertyInfo_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);


HRESULT STDMETHODCALLTYPE ICertRequestD2_Ping2_Proxy( 
    ICertRequestD2 * This,
    /* [in][string][unique] */ const wchar_t *pwszAuthority);


void __RPC_STUB ICertRequestD2_Ping2_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);



#endif 	/* __ICertRequestD2_INTERFACE_DEFINED__ */



#ifndef __redhattypelib_LIBRARY_DEFINED__
#define __redhattypelib_LIBRARY_DEFINED__

/* library redhattypelib */
/* [version][helpstring][uuid] */ 


EXTERN_C const IID LIBID_redhattypelib;

EXTERN_C const CLSID CLSID_CCertRequestD;

#ifdef __cplusplus

class DECLSPEC_UUID("d99e6e74-fc88-11d0-b498-00a0c90312f3")
CCertRequestD;
#endif
#endif /* __redhattypelib_LIBRARY_DEFINED__ */

/* Additional Prototypes for ALL interfaces */

/* end of Additional Prototypes */

#ifdef __cplusplus
}
#endif

#endif




--- NEW FILE RedHatCSProxy_i.c ---


/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */

/* link this file in with the server and any clients */


 /* File created by MIDL compiler version 6.00.0361 */
/* at Wed Feb 07 16:18:20 2007
 */
/* Compiler settings for .\RedHatCSProxy.idl:
    Oicf, W1, Zp8, env=Win32 (32b run)
    protocol : dce , ms_ext, c_ext, robust
    error checks: allocation ref bounds_check enum stub_data 
    VC __declspec() decoration level: 
         __declspec(uuid()), __declspec(selectany), __declspec(novtable)
         DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING(  )

#if !defined(_M_IA64) && !defined(_M_AMD64)


#pragma warning( disable: 4049 )  /* more than 64k source lines */


#ifdef __cplusplus
extern "C"{
#endif 


#include <rpc.h>
#include <rpcndr.h>

#ifdef _MIDL_USE_GUIDDEF_

#ifndef INITGUID
#define INITGUID
#include <guiddef.h>
#undef INITGUID
#else
#include <guiddef.h>
#endif

#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
        DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)

#else // !_MIDL_USE_GUIDDEF_

#ifndef __IID_DEFINED__
#define __IID_DEFINED__

typedef struct _IID
{
    unsigned long x;
    unsigned short s1;
    unsigned short s2;
    unsigned char  c[8];
} IID;

#endif // __IID_DEFINED__

#ifndef CLSID_DEFINED
#define CLSID_DEFINED
typedef IID CLSID;
#endif // CLSID_DEFINED

#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
        const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}

#endif !_MIDL_USE_GUIDDEF_

MIDL_DEFINE_GUID(IID, IID_ICertRequestD,0xd99e6e70,0xfc88,0x11d0,0xb4,0x98,0x00,0xa0,0xc9,0x03,0x12,0xf3);


MIDL_DEFINE_GUID(IID, IID_ICertRequestD2,0x5422fd3a,0xd4b8,0x4cef,0xa1,0x2e,0xe8,0x7d,0x4c,0xa2,0x2e,0x90);


MIDL_DEFINE_GUID(IID, LIBID_redhattypelib,0x96946675,0x8068,0x403f,0x88,0x9C,0xF4,0x06,0xD5,0x7F,0xE8,0xA2);


MIDL_DEFINE_GUID(CLSID, CLSID_CCertRequestD,0xd99e6e74,0xfc88,0x11d0,0xb4,0x98,0x00,0xa0,0xc9,0x03,0x12,0xf3);

#undef MIDL_DEFINE_GUID

#ifdef __cplusplus
}
#endif



#endif /* !defined(_M_IA64) && !defined(_M_AMD64)*/



--- NEW FILE RedHatCSProxy_p.c ---


/* this ALWAYS GENERATED file contains the proxy stub code */


 /* File created by MIDL compiler version 6.00.0361 */
/* at Wed Feb 07 16:18:20 2007
 */
/* Compiler settings for .\RedHatCSProxy.idl:
    Oicf, W1, Zp8, env=Win32 (32b run)
    protocol : dce , ms_ext, c_ext, robust
    error checks: allocation ref bounds_check enum stub_data 
    VC __declspec() decoration level: 
         __declspec(uuid()), __declspec(selectany), __declspec(novtable)
         DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING(  )

#if !defined(_M_IA64) && !defined(_M_AMD64)


#pragma warning( disable: 4049 )  /* more than 64k source lines */
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */
#pragma warning( disable: 4211 )  /* redefine extent to static */
#pragma warning( disable: 4232 )  /* dllimport identity*/
#define USE_STUBLESS_PROXY


/* verify that the <rpcproxy.h> version is high enough to compile this file*/
#ifndef __REDQ_RPCPROXY_H_VERSION__
#define __REQUIRED_RPCPROXY_H_VERSION__ 475
#endif


#include "rpcproxy.h"
#ifndef __RPCPROXY_H_VERSION__
#error this stub requires an updated version of <rpcproxy.h>
#endif // __RPCPROXY_H_VERSION__


#include "RedHatCSProxy_h.h"

#define TYPE_FORMAT_STRING_SIZE   55                                
#define PROC_FORMAT_STRING_SIZE   403                               
#define TRANSMIT_AS_TABLE_SIZE    0            
#define WIRE_MARSHAL_TABLE_SIZE   0            

typedef struct _MIDL_TYPE_FORMAT_STRING
    {
    short          Pad;
    unsigned char  Format[ TYPE_FORMAT_STRING_SIZE ];
    } MIDL_TYPE_FORMAT_STRING;

typedef struct _MIDL_PROC_FORMAT_STRING
    {
    short          Pad;
    unsigned char  Format[ PROC_FORMAT_STRING_SIZE ];
    } MIDL_PROC_FORMAT_STRING;


static RPC_SYNTAX_IDENTIFIER  _RpcTransferSyntax = 
{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}};


extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;
extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;


extern const MIDL_STUB_DESC Object_StubDesc;


extern const MIDL_SERVER_INFO ICertRequestD_ServerInfo;
extern const MIDL_STUBLESS_PROXY_INFO ICertRequestD_ProxyInfo;


extern const MIDL_STUB_DESC Object_StubDesc;


extern const MIDL_SERVER_INFO ICertRequestD2_ServerInfo;
extern const MIDL_STUBLESS_PROXY_INFO ICertRequestD2_ProxyInfo;



#if !defined(__RPC_WIN32__)
#error  Invalid build platform for this stub.
#endif

#if !(TARGET_IS_NT50_OR_LATER)
#error You need a Windows 2000 or later to run this stub because it uses these features:
#error   /robust command line switch.
#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.
#error This app will die there with the RPC_X_WRONG_STUB_VERSION error.
#endif


static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
    {
        0,
        {

	/* Procedure Request */

			0x33,		/* FC_AUTO_HANDLE */
			0x6c,		/* Old Flags:  object, Oi2 */
/*  2 */	NdrFcLong( 0x0 ),	/* 0 */
/*  6 */	NdrFcShort( 0x3 ),	/* 3 */
/*  8 */	NdrFcShort( 0x2c ),	/* x86 Stack size/offset = 44 */
/* 10 */	NdrFcShort( 0x24 ),	/* 36 */
/* 12 */	NdrFcShort( 0x40 ),	/* 64 */
/* 14 */	0x47,		/* Oi2 Flags:  srv must size, clt must size, has return, has ext, */
			0xa,		/* 10 */
/* 16 */	0x8,		/* 8 */
			0x7,		/* Ext Flags:  new corr desc, clt corr check, srv corr check, */
/* 18 */	NdrFcShort( 0x3 ),	/* 3 */
/* 20 */	NdrFcShort( 0x1 ),	/* 1 */
/* 22 */	NdrFcShort( 0x0 ),	/* 0 */

	/* Parameter dwFlags */

/* 24 */	NdrFcShort( 0x48 ),	/* Flags:  in, base type, */
/* 26 */	NdrFcShort( 0x4 ),	/* x86 Stack size/offset = 4 */
/* 28 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pwszAuthority */

/* 30 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 32 */	NdrFcShort( 0x8 ),	/* x86 Stack size/offset = 8 */
/* 34 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Parameter pdwRequestId */

/* 36 */	NdrFcShort( 0x158 ),	/* Flags:  in, out, base type, simple ref, */
/* 38 */	NdrFcShort( 0xc ),	/* x86 Stack size/offset = 12 */
/* 40 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pdwDisposition */

/* 42 */	NdrFcShort( 0x2150 ),	/* Flags:  out, base type, simple ref, srv alloc size=8 */
/* 44 */	NdrFcShort( 0x10 ),	/* x86 Stack size/offset = 16 */
/* 46 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pwszAttributes */

/* 48 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 50 */	NdrFcShort( 0x14 ),	/* x86 Stack size/offset = 20 */
/* 52 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Parameter pctbRequest */

/* 54 */	NdrFcShort( 0x10b ),	/* Flags:  must size, must free, in, simple ref, */
/* 56 */	NdrFcShort( 0x18 ),	/* x86 Stack size/offset = 24 */
/* 58 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Parameter pctbCertChain */

/* 60 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 62 */	NdrFcShort( 0x1c ),	/* x86 Stack size/offset = 28 */
/* 64 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Parameter pctbEncodedCert */

/* 66 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 68 */	NdrFcShort( 0x20 ),	/* x86 Stack size/offset = 32 */
/* 70 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Parameter pctbDispositionMessage */

/* 72 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 74 */	NdrFcShort( 0x24 ),	/* x86 Stack size/offset = 36 */
/* 76 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Return value */

/* 78 */	NdrFcShort( 0x70 ),	/* Flags:  out, return, base type, */
/* 80 */	NdrFcShort( 0x28 ),	/* x86 Stack size/offset = 40 */
/* 82 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Procedure GetCACert */

/* 84 */	0x33,		/* FC_AUTO_HANDLE */
			0x6c,		/* Old Flags:  object, Oi2 */
/* 86 */	NdrFcLong( 0x0 ),	/* 0 */
/* 90 */	NdrFcShort( 0x4 ),	/* 4 */
/* 92 */	NdrFcShort( 0x14 ),	/* x86 Stack size/offset = 20 */
/* 94 */	NdrFcShort( 0x8 ),	/* 8 */
/* 96 */	NdrFcShort( 0x8 ),	/* 8 */
/* 98 */	0x47,		/* Oi2 Flags:  srv must size, clt must size, has return, has ext, */
			0x4,		/* 4 */
/* 100 */	0x8,		/* 8 */
			0x3,		/* Ext Flags:  new corr desc, clt corr check, */
/* 102 */	NdrFcShort( 0x1 ),	/* 1 */
/* 104 */	NdrFcShort( 0x0 ),	/* 0 */
/* 106 */	NdrFcShort( 0x0 ),	/* 0 */

	/* Parameter fchain */

/* 108 */	NdrFcShort( 0x48 ),	/* Flags:  in, base type, */
/* 110 */	NdrFcShort( 0x4 ),	/* x86 Stack size/offset = 4 */
/* 112 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pwszAuthority */

/* 114 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 116 */	NdrFcShort( 0x8 ),	/* x86 Stack size/offset = 8 */
/* 118 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Parameter pctbOut */

/* 120 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 122 */	NdrFcShort( 0xc ),	/* x86 Stack size/offset = 12 */
/* 124 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Return value */

/* 126 */	NdrFcShort( 0x70 ),	/* Flags:  out, return, base type, */
/* 128 */	NdrFcShort( 0x10 ),	/* x86 Stack size/offset = 16 */
/* 130 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Procedure Ping */

/* 132 */	0x33,		/* FC_AUTO_HANDLE */
			0x6c,		/* Old Flags:  object, Oi2 */
/* 134 */	NdrFcLong( 0x0 ),	/* 0 */
/* 138 */	NdrFcShort( 0x5 ),	/* 5 */
/* 140 */	NdrFcShort( 0xc ),	/* x86 Stack size/offset = 12 */
/* 142 */	NdrFcShort( 0x0 ),	/* 0 */
/* 144 */	NdrFcShort( 0x8 ),	/* 8 */
/* 146 */	0x46,		/* Oi2 Flags:  clt must size, has return, has ext, */
			0x2,		/* 2 */
/* 148 */	0x8,		/* 8 */
			0x1,		/* Ext Flags:  new corr desc, */
/* 150 */	NdrFcShort( 0x0 ),	/* 0 */
/* 152 */	NdrFcShort( 0x0 ),	/* 0 */
/* 154 */	NdrFcShort( 0x0 ),	/* 0 */

	/* Parameter pwszAuthority */

/* 156 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 158 */	NdrFcShort( 0x4 ),	/* x86 Stack size/offset = 4 */
/* 160 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Return value */

/* 162 */	NdrFcShort( 0x70 ),	/* Flags:  out, return, base type, */
/* 164 */	NdrFcShort( 0x8 ),	/* x86 Stack size/offset = 8 */
/* 166 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Procedure Request2 */

/* 168 */	0x33,		/* FC_AUTO_HANDLE */
			0x6c,		/* Old Flags:  object, Oi2 */
/* 170 */	NdrFcLong( 0x0 ),	/* 0 */
/* 174 */	NdrFcShort( 0x6 ),	/* 6 */
/* 176 */	NdrFcShort( 0x30 ),	/* x86 Stack size/offset = 48 */
/* 178 */	NdrFcShort( 0x24 ),	/* 36 */
/* 180 */	NdrFcShort( 0x40 ),	/* 64 */
/* 182 */	0x47,		/* Oi2 Flags:  srv must size, clt must size, has return, has ext, */
			0xb,		/* 11 */
/* 184 */	0x8,		/* 8 */
			0x7,		/* Ext Flags:  new corr desc, clt corr check, srv corr check, */
/* 186 */	NdrFcShort( 0x3 ),	/* 3 */
/* 188 */	NdrFcShort( 0x1 ),	/* 1 */
/* 190 */	NdrFcShort( 0x0 ),	/* 0 */

	/* Parameter pwszAuthority */

/* 192 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 194 */	NdrFcShort( 0x4 ),	/* x86 Stack size/offset = 4 */
/* 196 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Parameter dwFlags */

/* 198 */	NdrFcShort( 0x48 ),	/* Flags:  in, base type, */
/* 200 */	NdrFcShort( 0x8 ),	/* x86 Stack size/offset = 8 */
/* 202 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pwszSerialNumber */

/* 204 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 206 */	NdrFcShort( 0xc ),	/* x86 Stack size/offset = 12 */
/* 208 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Parameter pdwRequestId */

/* 210 */	NdrFcShort( 0x158 ),	/* Flags:  in, out, base type, simple ref, */
/* 212 */	NdrFcShort( 0x10 ),	/* x86 Stack size/offset = 16 */
/* 214 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pdwDisposition */

/* 216 */	NdrFcShort( 0x2150 ),	/* Flags:  out, base type, simple ref, srv alloc size=8 */
/* 218 */	NdrFcShort( 0x14 ),	/* x86 Stack size/offset = 20 */
/* 220 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pwszAttributes */

/* 222 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 224 */	NdrFcShort( 0x18 ),	/* x86 Stack size/offset = 24 */
/* 226 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Parameter pctbRequest */

/* 228 */	NdrFcShort( 0x10b ),	/* Flags:  must size, must free, in, simple ref, */
/* 230 */	NdrFcShort( 0x1c ),	/* x86 Stack size/offset = 28 */
/* 232 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Parameter pctbFullResponse */

/* 234 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 236 */	NdrFcShort( 0x20 ),	/* x86 Stack size/offset = 32 */
/* 238 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Parameter pctbEncodedCert */

/* 240 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 242 */	NdrFcShort( 0x24 ),	/* x86 Stack size/offset = 36 */
/* 244 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Parameter pctbDispositionMessage */

/* 246 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 248 */	NdrFcShort( 0x28 ),	/* x86 Stack size/offset = 40 */
/* 250 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Return value */

/* 252 */	NdrFcShort( 0x70 ),	/* Flags:  out, return, base type, */
/* 254 */	NdrFcShort( 0x2c ),	/* x86 Stack size/offset = 44 */
/* 256 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Procedure GetCAProperty */

/* 258 */	0x33,		/* FC_AUTO_HANDLE */
			0x6c,		/* Old Flags:  object, Oi2 */
/* 260 */	NdrFcLong( 0x0 ),	/* 0 */
/* 264 */	NdrFcShort( 0x7 ),	/* 7 */
/* 266 */	NdrFcShort( 0x1c ),	/* x86 Stack size/offset = 28 */
/* 268 */	NdrFcShort( 0x18 ),	/* 24 */
/* 270 */	NdrFcShort( 0x8 ),	/* 8 */
/* 272 */	0x47,		/* Oi2 Flags:  srv must size, clt must size, has return, has ext, */
			0x6,		/* 6 */
/* 274 */	0x8,		/* 8 */
			0x3,		/* Ext Flags:  new corr desc, clt corr check, */
/* 276 */	NdrFcShort( 0x1 ),	/* 1 */
/* 278 */	NdrFcShort( 0x0 ),	/* 0 */
/* 280 */	NdrFcShort( 0x0 ),	/* 0 */

	/* Parameter pwszAuthority */

/* 282 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 284 */	NdrFcShort( 0x4 ),	/* x86 Stack size/offset = 4 */
/* 286 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Parameter PropId */

/* 288 */	NdrFcShort( 0x48 ),	/* Flags:  in, base type, */
/* 290 */	NdrFcShort( 0x8 ),	/* x86 Stack size/offset = 8 */
/* 292 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter PropIndex */

/* 294 */	NdrFcShort( 0x48 ),	/* Flags:  in, base type, */
/* 296 */	NdrFcShort( 0xc ),	/* x86 Stack size/offset = 12 */
/* 298 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter PropType */

/* 300 */	NdrFcShort( 0x48 ),	/* Flags:  in, base type, */
/* 302 */	NdrFcShort( 0x10 ),	/* x86 Stack size/offset = 16 */
/* 304 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pctbPropertyValue */

/* 306 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 308 */	NdrFcShort( 0x14 ),	/* x86 Stack size/offset = 20 */
/* 310 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Return value */

/* 312 */	NdrFcShort( 0x70 ),	/* Flags:  out, return, base type, */
/* 314 */	NdrFcShort( 0x18 ),	/* x86 Stack size/offset = 24 */
/* 316 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Procedure GetCAPropertyInfo */

/* 318 */	0x33,		/* FC_AUTO_HANDLE */
			0x6c,		/* Old Flags:  object, Oi2 */
/* 320 */	NdrFcLong( 0x0 ),	/* 0 */
/* 324 */	NdrFcShort( 0x8 ),	/* 8 */
/* 326 */	NdrFcShort( 0x14 ),	/* x86 Stack size/offset = 20 */
/* 328 */	NdrFcShort( 0x0 ),	/* 0 */
/* 330 */	NdrFcShort( 0x24 ),	/* 36 */
/* 332 */	0x47,		/* Oi2 Flags:  srv must size, clt must size, has return, has ext, */
			0x4,		/* 4 */
/* 334 */	0x8,		/* 8 */
			0x3,		/* Ext Flags:  new corr desc, clt corr check, */
/* 336 */	NdrFcShort( 0x1 ),	/* 1 */
/* 338 */	NdrFcShort( 0x0 ),	/* 0 */
/* 340 */	NdrFcShort( 0x0 ),	/* 0 */

	/* Parameter pwszAuthority */

/* 342 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 344 */	NdrFcShort( 0x4 ),	/* x86 Stack size/offset = 4 */
/* 346 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Parameter pcProperty */

/* 348 */	NdrFcShort( 0x2150 ),	/* Flags:  out, base type, simple ref, srv alloc size=8 */
/* 350 */	NdrFcShort( 0x8 ),	/* x86 Stack size/offset = 8 */
/* 352 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Parameter pctbPropInfo */

/* 354 */	NdrFcShort( 0x2113 ),	/* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
/* 356 */	NdrFcShort( 0xc ),	/* x86 Stack size/offset = 12 */
/* 358 */	NdrFcShort( 0x1e ),	/* Type Offset=30 */

	/* Return value */

/* 360 */	NdrFcShort( 0x70 ),	/* Flags:  out, return, base type, */
/* 362 */	NdrFcShort( 0x10 ),	/* x86 Stack size/offset = 16 */
/* 364 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

	/* Procedure Ping2 */

/* 366 */	0x33,		/* FC_AUTO_HANDLE */
			0x6c,		/* Old Flags:  object, Oi2 */
/* 368 */	NdrFcLong( 0x0 ),	/* 0 */
/* 372 */	NdrFcShort( 0x9 ),	/* 9 */
/* 374 */	NdrFcShort( 0xc ),	/* x86 Stack size/offset = 12 */
/* 376 */	NdrFcShort( 0x0 ),	/* 0 */
/* 378 */	NdrFcShort( 0x8 ),	/* 8 */
/* 380 */	0x46,		/* Oi2 Flags:  clt must size, has return, has ext, */
			0x2,		/* 2 */
/* 382 */	0x8,		/* 8 */
			0x1,		/* Ext Flags:  new corr desc, */
/* 384 */	NdrFcShort( 0x0 ),	/* 0 */
/* 386 */	NdrFcShort( 0x0 ),	/* 0 */
/* 388 */	NdrFcShort( 0x0 ),	/* 0 */

	/* Parameter pwszAuthority */

/* 390 */	NdrFcShort( 0xb ),	/* Flags:  must size, must free, in, */
/* 392 */	NdrFcShort( 0x4 ),	/* x86 Stack size/offset = 4 */
/* 394 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */

	/* Return value */

/* 396 */	NdrFcShort( 0x70 ),	/* Flags:  out, return, base type, */
/* 398 */	NdrFcShort( 0x8 ),	/* x86 Stack size/offset = 8 */
/* 400 */	0x8,		/* FC_LONG */
			0x0,		/* 0 */

			0x0
        }
    };

static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
    {
        0,
        {
			NdrFcShort( 0x0 ),	/* 0 */
/*  2 */	
			0x12, 0x8,	/* FC_UP [simple_pointer] */
/*  4 */	
			0x25,		/* FC_C_WSTRING */
			0x5c,		/* FC_PAD */
/*  6 */	
			0x11, 0x8,	/* FC_RP [simple_pointer] */
/*  8 */	0x8,		/* FC_LONG */
			0x5c,		/* FC_PAD */
/* 10 */	
			0x11, 0xc,	/* FC_RP [alloced_on_stack] [simple_pointer] */
/* 12 */	0x8,		/* FC_LONG */
			0x5c,		/* FC_PAD */
/* 14 */	
			0x11, 0x0,	/* FC_RP */
/* 16 */	NdrFcShort( 0xe ),	/* Offset= 14 (30) */
/* 18 */	
			0x1b,		/* FC_CARRAY */
			0x0,		/* 0 */
/* 20 */	NdrFcShort( 0x1 ),	/* 1 */
/* 22 */	0x19,		/* Corr desc:  field pointer, FC_ULONG */
			0x0,		/*  */
/* 24 */	NdrFcShort( 0x0 ),	/* 0 */
/* 26 */	NdrFcShort( 0x1 ),	/* Corr flags:  early, */
/* 28 */	0x1,		/* FC_BYTE */
			0x5b,		/* FC_END */
/* 30 */	
			0x16,		/* FC_PSTRUCT */
			0x3,		/* 3 */
/* 32 */	NdrFcShort( 0x8 ),	/* 8 */
/* 34 */	
			0x4b,		/* FC_PP */
			0x5c,		/* FC_PAD */
/* 36 */	
			0x46,		/* FC_NO_REPEAT */
			0x5c,		/* FC_PAD */
/* 38 */	NdrFcShort( 0x4 ),	/* 4 */
/* 40 */	NdrFcShort( 0x4 ),	/* 4 */
/* 42 */	0x12, 0x0,	/* FC_UP */
/* 44 */	NdrFcShort( 0xffe6 ),	/* Offset= -26 (18) */
/* 46 */	
			0x5b,		/* FC_END */

			0x8,		/* FC_LONG */
/* 48 */	0x8,		/* FC_LONG */
			0x5b,		/* FC_END */
/* 50 */	
			0x11, 0x4,	/* FC_RP [alloced_on_stack] */
/* 52 */	NdrFcShort( 0xffea ),	/* Offset= -22 (30) */

			0x0
        }
    };


/* Standard interface: __MIDL_itf_RedHatCSProxy_0000, ver. 0.0,
   GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */


/* Object interface: IUnknown, ver. 0.0,
   GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */


/* Object interface: ICertRequestD, ver. 0.0,
   GUID={0xd99e6e70,0xfc88,0x11d0,{0xb4,0x98,0x00,0xa0,0xc9,0x03,0x12,0xf3}} */

#pragma code_seg(".orpc")
static const unsigned short ICertRequestD_FormatStringOffsetTable[] =
    {
    0,
    84,
    132
    };

static const MIDL_STUBLESS_PROXY_INFO ICertRequestD_ProxyInfo =
    {
    &Object_StubDesc,
    __MIDL_ProcFormatString.Format,
    &ICertRequestD_FormatStringOffsetTable[-3],
    0,
    0,
    0
    };


static const MIDL_SERVER_INFO ICertRequestD_ServerInfo = 
    {
    &Object_StubDesc,
    0,
    __MIDL_ProcFormatString.Format,
    &ICertRequestD_FormatStringOffsetTable[-3],
    0,
    0,
    0,
    0};
CINTERFACE_PROXY_VTABLE(6) _ICertRequestDProxyVtbl = 
{
    &ICertRequestD_ProxyInfo,
    &IID_ICertRequestD,
    IUnknown_QueryInterface_Proxy,
    IUnknown_AddRef_Proxy,
    IUnknown_Release_Proxy ,
    (void *) (INT_PTR) -1 /* ICertRequestD::Request */ ,
    (void *) (INT_PTR) -1 /* ICertRequestD::GetCACert */ ,
    (void *) (INT_PTR) -1 /* ICertRequestD::Ping */
};

const CInterfaceStubVtbl _ICertRequestDStubVtbl =
{
    &IID_ICertRequestD,
    &ICertRequestD_ServerInfo,
    6,
    0, /* pure interpreted */
    CStdStubBuffer_METHODS
};


/* Object interface: ICertRequestD2, ver. 0.0,
   GUID={0x5422fd3a,0xd4b8,0x4cef,{0xa1,0x2e,0xe8,0x7d,0x4c,0xa2,0x2e,0x90}} */

#pragma code_seg(".orpc")
static const unsigned short ICertRequestD2_FormatStringOffsetTable[] =
    {
    0,
    84,
    132,
    168,
    258,
    318,
    366
    };

static const MIDL_STUBLESS_PROXY_INFO ICertRequestD2_ProxyInfo =
    {
    &Object_StubDesc,
    __MIDL_ProcFormatString.Format,
    &ICertRequestD2_FormatStringOffsetTable[-3],
    0,
    0,
    0
    };


static const MIDL_SERVER_INFO ICertRequestD2_ServerInfo = 
    {
    &Object_StubDesc,
    0,
    __MIDL_ProcFormatString.Format,
    &ICertRequestD2_FormatStringOffsetTable[-3],
    0,
    0,
    0,
    0};
CINTERFACE_PROXY_VTABLE(10) _ICertRequestD2ProxyVtbl = 
{
    &ICertRequestD2_ProxyInfo,
    &IID_ICertRequestD2,
    IUnknown_QueryInterface_Proxy,
    IUnknown_AddRef_Proxy,
    IUnknown_Release_Proxy ,
    (void *) (INT_PTR) -1 /* ICertRequestD::Request */ ,
    (void *) (INT_PTR) -1 /* ICertRequestD::GetCACert */ ,
    (void *) (INT_PTR) -1 /* ICertRequestD::Ping */ ,
    (void *) (INT_PTR) -1 /* ICertRequestD2::Request2 */ ,
    (void *) (INT_PTR) -1 /* ICertRequestD2::GetCAProperty */ ,
    (void *) (INT_PTR) -1 /* ICertRequestD2::GetCAPropertyInfo */ ,
    (void *) (INT_PTR) -1 /* ICertRequestD2::Ping2 */
};

const CInterfaceStubVtbl _ICertRequestD2StubVtbl =
{
    &IID_ICertRequestD2,
    &ICertRequestD2_ServerInfo,
    10,
    0, /* pure interpreted */
    CStdStubBuffer_METHODS
};

static const MIDL_STUB_DESC Object_StubDesc = 
    {
    0,
    NdrOleAllocate,
    NdrOleFree,
    0,
    0,
    0,
    0,
    0,
    __MIDL_TypeFormatString.Format,
    1, /* -error bounds_check flag */
    0x50002, /* Ndr library version */
    0,
    0x6000169, /* MIDL Version 6.0.361 */
    0,
    0,
    0,  /* notify & notify_flag routine table */
    0x1, /* MIDL flag */
    0, /* cs routines */
    0,   /* proxy/server info */
    0   /* Reserved5 */
    };

const CInterfaceProxyVtbl * _RedHatCSProxy_ProxyVtblList[] = 
{
    ( CInterfaceProxyVtbl *) &_ICertRequestD2ProxyVtbl,
    ( CInterfaceProxyVtbl *) &_ICertRequestDProxyVtbl,
    0
};

const CInterfaceStubVtbl * _RedHatCSProxy_StubVtblList[] = 
{
    ( CInterfaceStubVtbl *) &_ICertRequestD2StubVtbl,
    ( CInterfaceStubVtbl *) &_ICertRequestDStubVtbl,
    0
};

PCInterfaceName const _RedHatCSProxy_InterfaceNamesList[] = 
{
    "ICertRequestD2",
    "ICertRequestD",
    0
};


#define _RedHatCSProxy_CHECK_IID(n)	IID_GENERIC_CHECK_IID( _RedHatCSProxy, pIID, n)

int __stdcall _RedHatCSProxy_IID_Lookup( const IID * pIID, int * pIndex )
{
    IID_BS_LOOKUP_SETUP

    IID_BS_LOOKUP_INITIAL_TEST( _RedHatCSProxy, 2, 1 )
    IID_BS_LOOKUP_RETURN_RESULT( _RedHatCSProxy, 2, *pIndex )
    
}

const ExtendedProxyFileInfo RedHatCSProxy_ProxyFileInfo = 
{
    (PCInterfaceProxyVtblList *) & _RedHatCSProxy_ProxyVtblList,
    (PCInterfaceStubVtblList *) & _RedHatCSProxy_StubVtblList,
    (const PCInterfaceName * ) & _RedHatCSProxy_InterfaceNamesList,
    0, // no delegation
    & _RedHatCSProxy_IID_Lookup, 
    2,
    2,
    0, /* table of [async_uuid] interfaces */
    0, /* Filler1 */
    0, /* Filler2 */
    0  /* Filler3 */
};
#if _MSC_VER >= 1200
#pragma warning(pop)
#endif


#endif /* !defined(_M_IA64) && !defined(_M_AMD64)*/



--- NEW FILE RedHatCertSvrProxy.rc ---
// Microsoft Visual C++ generated resource script.
//
#include "resource1.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource1.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\0"
END

1 TEXTINCLUDE 
BEGIN
    "resource1.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////




--- NEW FILE b64.c ---
/*
 * Copyright (C), 2000-2006 by the monit project group.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */


#include <windows.h> 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "b64.h"

/* Private prototypes */
static int is_base64(char c);
static char encode(unsigned char u);
static unsigned char decode(char c);


/**
 *  Implementation of base64 encoding/decoding. 
 *
 *  @author Jan-Henrik Haukeland, <hauk at tildeslash.com>
 *
 */



/* ------------------------------------------------------------------ Public */



/**
 * Base64 encode and return size data in 'src'. The caller must free the
 * returned string.
 * @param size The size of the data in src
 * @param src The data to be base64 encode
 * @return encoded string otherwise NULL
 */
char *encode_base64(int size, unsigned char *src) {

  int i;
  char *out, *p;

  if(!src)
    return NULL;

  if(!size)
    size= (int)strlen((char *)src);
    
  out= calloc(sizeof(char), size*4/3+4);

  p= out;
    
  for(i=0; i<size; i+=3) {
      
    unsigned char b1=0, b2=0, b3=0, b4=0, b5=0, b6=0, b7=0;
      
    b1 = src[i];
      
    if(i+1<size)
      b2 = src[i+1];
      
    if(i+2<size)
      b3 = src[i+2];
      
    b4= b1>>2;
    b5= ((b1&0x3)<<4)|(b2>>4);
    b6= ((b2&0xf)<<2)|(b3>>6);
    b7= b3&0x3f;
      
    *p++= encode(b4);
    *p++= encode(b5);
      
    if(i+1<size) {
      *p++= encode(b6);
    } else {
      *p++= '=';
    }
      
    if(i+2<size) {
      *p++= encode(b7);
    } else {
      *p++= '=';
    }

  }

  return out;

}


/**
 * Decode the base64 encoded string 'src' into the memory pointed to by
 * 'dest'. The dest buffer is <b>not</b> NUL terminated.
 * @param dest Pointer to memory for holding the decoded string.
 * Must be large enough to recieve the decoded string.
 * @param src A base64 encoded string.
 * @return TRUE (the length of the decoded string) if decode
 * succeeded otherwise FALSE.
 */
int decode_base64(unsigned char *dest, const char *src) {

  if(src && *src) {
  
    unsigned char *p= dest;
    int k, l= (int)strlen(src)+1;
    unsigned char *buf= calloc(sizeof(unsigned char), l);

    
    /* Ignore non base64 chars as per the POSIX standard */
    for(k=0, l=0; src[k]; k++) {
      
      if(is_base64(src[k])) {
	
	buf[l++]= src[k];
	
      }
      
    } 
    
    for(k=0; k<l; k+=4) {
      
      char c1='A', c2='A', c3='A', c4='A';
      unsigned char b1=0, b2=0, b3=0, b4=0;
      
      c1= buf[k];
      
      if(k+1<l) {
	
	c2= buf[k+1];
	
      }
      
      if(k+2<l) {
	
	c3= buf[k+2];
	
      }
      
      if(k+3<l) {
	
	c4= buf[k+3];
	
      }
      
      b1= decode(c1);
      b2= decode(c2);
      b3= decode(c3);
      b4= decode(c4);
      
      *p++=((b1<<2)|(b2>>4) );
      
      if(c3 != '=') {
	
	*p++=(((b2&0xf)<<4)|(b3>>2) );
	
      }
      
      if(c4 != '=') {
	
	*p++=(((b3&0x3)<<6)|b4 );
	
      }
      
    }
    
    free(buf);
    
    return (int) (p-dest);

  }

  return 0;
  
}


/* ----------------------------------------------------------------- Private */


/**
 * Base64 encode one byte
 */
static char encode(unsigned char u) {

  if(u < 26)  return 'A'+u;
  if(u < 52)  return 'a'+(u-26);
  if(u < 62)  return '0'+(u-52);
  if(u == 62) return '+';
  
  return '/';

}


/**
 * Decode a base64 character
 */
static unsigned char decode(char c) {
  
  if(c >= 'A' && c <= 'Z') return(c - 'A');
  if(c >= 'a' && c <= 'z') return(c - 'a' + 26);
  if(c >= '0' && c <= '9') return(c - '0' + 52);
  if(c == '+')             return 62;
  
  return 63;
  
}


/**
 * Return TRUE if 'c' is a valid base64 character, otherwise FALSE
 */
static int is_base64(char c) {

  if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
     (c >= '0' && c <= '9') || (c == '+')             ||
     (c == '/')             || (c == '=')) {
    
    return TRUE;
    
  }
  
  return FALSE;

}





--- NEW FILE b64.h ---
/*
 * Copyright (C), 2000-2006 by the monit project group.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */


#ifndef BASE64_H
#define BASE64_H


int   decode_base64(unsigned char *dest, const char *src);
char *encode_base64(int size, unsigned char *src);

#endif



--- NEW FILE cert.ico ---


--- NEW FILE csproxy.h ---

#ifndef CSPROXY_H
#define CSPROXY_H

#include <map>
#include <string>
#include <vector>

#include "RedHatCSProxy_h.h"

using std::map;
using std::string;
using std::vector;

#define AEPERR 0x8CA50000

class requestinfo {
public:
	char *PKCS10Request;
	string *windowsCertTemplateName;
	map<string,string> attrs;      // attributes parsed from the request
	map<string,string> httpvars;   // the name/value pairs we're going to send to the CA
	DWORD disposition;

	requestinfo() 
		: PKCS10Request(NULL),
		  windowsCertTemplateName(NULL),
		  disposition(0) {};

	~requestinfo() {
		if (windowsCertTemplateName != NULL) { delete windowsCertTemplateName; }
	}

	void parseRequest(const CERTTRANSBLOB *);
	void parseAttributes(const wchar_t *pwszAttributes);
	void determineCertificateTemplate();
	void populateRequestForTemplate(string &);

};




class cainfo {
public:
	char *host;
	DWORD port;
	DWORD catype;
	FILETIME last_success;    // The time that we last communicated with the CA
	FILETIME last_failure;    // The time that we last failed to communicate with the CA

	  // XXX fixme
	bool canService(string *templatename) { return true; }

	// retry_not_before
};

//typedef map<string,string> atrmap;

class profile {
public:
	string rhcsprofilename;
};

#define BUFSIZE 8192

class configvars {
public:
	vector <cainfo *> all_cas;
	map<string,profile> profilemap;
	BYTE certhash[BUFSIZE];
	DWORD  certhash_size;
	BYTE cacert[BUFSIZE];
	DWORD  cacert_size;
	DWORD  icertrequestd2;
	DWORD  retryinterval;
};

// this 'context' class is to tie together information about a single
// certificate request, as it gets passed to a CA.
class context {
public:
	context(configvars *vars) :
		securitystatus(0),	status(0),
		fatalerror(0),	config(vars)  {};

	configvars* config;
	requestinfo *request;
	vector<cainfo *> cas;
	cainfo* selectedca;

	// a 'stack' of errors caused during enrollment to the selected CA
	vector<string> errors; 
	int fatalerror;

	DWORD status;
	DWORD securitystatus;

	vector<cainfo*> makeCandidateCAList();
	vector<cainfo*> findRespondingCAs(vector<cainfo*> candidates);

/*
 * context     - input  - dumping ground
 * certrequest - input  - certificate request to submit to CA
 * cert        - output - the certificate (base-64 ascii) is written here
 * certchain   - output - the certificate chain (base-64 ascii) is written here
 * requestinfo - input  - 
 * vars        - input  - configuration parameters
 */
LONG submitRequestToCA(	string &cert,  string &certchain);

LONG extractCertFromResponse(string &respX, string &cert_out,
							 string &p7_out);

};


/* The 'registry' class encapsulates reading/writing of the
   config variables from the registry
 */
class registry {
private:
	configvars *v;
	// This events gets triggered when the registry changes
	HANDLE event;
	HKEY config;
public:
	registry();
	bool        changed();
	void        update();
	void        setupnotification();
	configvars* getvars();
};


#define    CATYPE_UNKNOWN        0
#define    CATYPE_NETSCAPE_61    1
#define    CATYPE_REDHAT_71      2
#define    CATYPE_REDHAT_72      3
#define    CATYPE_REDHAT_73      4


// debug message type (masked with LogLevel registry setting
#define LOG_REQ        0x0001
#define LOG_CERT       0x0002
#define LOG_GENERAL    0x0004
#define LOG_D_COM      0x0010
#define LOG_D_CONFIG   0x0020
#define LOG_D_CA       0x0040
#define LOG_D_FUNC     0x0080
#define LOG_D_DETAIL   0x0100
		
				  
extern void getlogconfig();
extern void debug(const char* pFormat,...);
extern void debugt(unsigned int type, const char* pFormat,...);


extern "C" HRESULT getConfig(HKEY, configvars *vars);
extern "C" LONG getguid(LPCWSTR dchostname, GUID *guid);
extern "C" void decodeToBlob( const char *src, CERTTRANSBLOB *blob);

extern void exemain(int argc, char **argv);
extern int svcmain(int argc, char **argv);
extern bool service_running();

#endif

--- NEW FILE dlldata.c ---
/*********************************************************
   DllData file -- generated by MIDL compiler 

        DO NOT ALTER THIS FILE

   This file is regenerated by MIDL on every IDL file compile.

   To completely reconstruct this file, delete it and rerun MIDL
   on all the IDL files in this DLL, specifying this file for the
   /dlldata command line option

*********************************************************/


#include <rpcproxy.h>

#ifdef __cplusplus
extern "C"   {
#endif

EXTERN_PROXY_FILE( RedHatCSProxy )


PROXYFILE_LIST_START
/* Start of list */
  REFERENCE_PROXY_FILE( RedHatCSProxy ),
/* End of list */
PROXYFILE_LIST_END


DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )

#ifdef __cplusplus
}  /*extern "C" */
#endif

/* end of generated dlldata file */


--- NEW FILE messages.RES ---



--- NEW FILE messages.aps ---



--- NEW FILE messages.h ---
//
//  Values are 32 bit values layed out as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +---+-+-+-----------------------+-------------------------------+
//  |Sev|C|R|     Facility          |               Code            |
//  +---+-+-+-----------------------+-------------------------------+
//
//  where
//
//      Sev - is the severity code
//
//          00 - Success
//          01 - Informational
//          10 - Warning
//          11 - Error
//
//      C - is the Customer code flag
//
//      R - is a reserved bit
//
//      Facility - is the facility code
//
//      Code - is the facility's status code
//
//
// Define the facility codes
//


//
// Define the severity codes
//


//
// MessageId: MSG_RHCSPROXY_DEBUG
//
// MessageText:
//
//  %1.
//
#define MSG_RHCSPROXY_DEBUG              ((DWORD)0x40000064L)



--- NEW FILE messages.mc ---
MessageIdTypedef=DWORD

MessageId=100
Severity=Informational
Facility=Application
SymbolicName=MSG_RHCSPROXY_DEBUG
Language=English
%1.
.


--- NEW FILE messages.rc ---
LANGUAGE 0x9,0x1
1 11 MSG00001.bin


--- NEW FILE p32.ico ---



TkËî(äôÒùù“ñò3éôÂÓ&§ºç®ã™ÜwΆÓ$4êêêøôñÖ´ŸîàØþþþûùøòçáåÐÃÚ»¨Î¥ŒÑª’ÝÁ°Ü¿­ùõóõíèpwwBÎÛÏï2åôÖùø’ñò3éô«º#{Œ¿ç®ã ß€Ò‹×'7îîîé×ÌͤŠýûûþþþÕ°£Ò«œôëèòèäúöôòèáåÐÃØ·£Ó®—Êž‚\ZROáéÏïNçóÏ÷ö‘ññ1Öà%$—³®ã¡ß„ԏÙ*;òòòøóðÔ°šýüûþþþ¾…pÑ©šÀˆs¶w_ÝÀµé×Ðþþþþþþûø÷òçádjeOáéÏïkêòÃõó‘ðñ-·¿
øøøñëæÕ´ ùøøõõõÈÈȯ¯¯ŸŸŸ£££¹¹¹ÐÐÐâââôôôýýýýýýnvv5¢Å:ÏÞ¼¼¼ŒŒŒ)))|¤§¢òø£óøžóø§Ëη··222/22&'








***[[[–––ÊÊÊêêêìììéäáêçåÜȻֺ©Ôµ¢ÊŸ„Ò°›Ù¾­âÓÊëåâðððêäßÓ±›çÝÖòòò:::

--- NEW FILE proxy.vcproj ---
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="7.10"
	Name="proxy"
	ProjectGUID="{BCE7AE2E-C0C2-4B5A-B05C-02DF16CC9F70}"
	Keyword="Win32Proj">
	<Platforms>
		<Platform
			Name="Win32"/>
	</Platforms>
	<Configurations>
		<Configuration
			Name="Debug|Win32"
			OutputDirectory="Debug"
			IntermediateDirectory="Debug"
			ConfigurationType="1"
			CharacterSet="2">
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="D:\i386\microsoft_platform_sdk_2003_r2\Include"
				PreprocessorDefinitions="_WIN32_WINNT=0x500;WIN32;REGISTER_PROXY_DLL"
				MinimalRebuild="TRUE"
				BasicRuntimeChecks="3"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				Detect64BitPortabilityProblems="TRUE"
				DebugInformationFormat="4"/>
			<Tool
				Name="VCCustomBuildTool"
				Description="Creating messages.dll"
				CommandLine="link /noentry /out:$(IntDir)\messages.dll /DLL messages.res
"
				Outputs="$(IntDir)\messages.dll"/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="rpcndr.lib rpcrt4.lib certidl.lib winhttp.lib crypt32.lib adsiid.lib activeds.lib"
				OutputFile="$(OutDir)/rhcsproxy.exe"
				LinkIncremental="2"
				GenerateDebugInformation="TRUE"
				ProgramDatabaseFile="$(OutDir)/proxy.pdb"
				SubSystem="1"
				TargetMachine="1"/>
			<Tool
				Name="VCMIDLTool"/>
			<Tool
				Name="VCPostBuildEventTool"/>
			<Tool
				Name="VCPreBuildEventTool"/>
			<Tool
				Name="VCPreLinkEventTool"/>
			<Tool
				Name="VCResourceCompilerTool"/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"/>
			<Tool
				Name="VCXMLDataGeneratorTool"/>
			<Tool
				Name="VCWebDeploymentTool"/>
			<Tool
				Name="VCManagedWrapperGeneratorTool"/>
			<Tool
				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
		</Configuration>
		<Configuration
			Name="Release|Win32"
			OutputDirectory="Release"
			IntermediateDirectory="Release"
			ConfigurationType="1"
			CharacterSet="2">
			<Tool
				Name="VCCLCompilerTool"
				AdditionalIncludeDirectories="D:\i386\microsoft_platform_sdk_2003_r2\Include"
				PreprocessorDefinitions="_WIN32_WINNT=0x500;WIN32;REGISTER_PROXY_DLL"
				MinimalRebuild="TRUE"
				RuntimeLibrary="0"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				Detect64BitPortabilityProblems="TRUE"
				DebugInformationFormat="3"/>
			<Tool
				Name="VCCustomBuildTool"
				Description="Creating messages.dll"
				CommandLine="link /noentry /out:$(IntDir)\messages.dll /DLL messages.res
"
				Outputs="$(IntDir)\messages.dll"/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="rpcndr.lib rpcrt4.lib certidl.lib winhttp.lib crypt32.lib adsiid.lib activeds.lib"
				OutputFile="$(OutDir)/rhcsproxy.exe"
				LinkIncremental="1"
				AdditionalLibraryDirectories="D:\i386\microsoft_platform_sdk_2003_r2\lib"
				GenerateDebugInformation="TRUE"
				SubSystem="1"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				TargetMachine="1"/>
			<Tool
				Name="VCMIDLTool"/>
			<Tool
				Name="VCPostBuildEventTool"/>
			<Tool
				Name="VCPreBuildEventTool"/>
			<Tool
				Name="VCPreLinkEventTool"/>
			<Tool
				Name="VCResourceCompilerTool"/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"/>
			<Tool
				Name="VCXMLDataGeneratorTool"/>
			<Tool
				Name="VCWebDeploymentTool"/>
			<Tool
				Name="VCManagedWrapperGeneratorTool"/>
			<Tool
				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
			<File
				RelativePath=".\b64.c">
			</File>
			<File
				RelativePath=".\dlldata.c">
			</File>
			<File
				RelativePath=".\proxy.cpp">
			</File>
			<File
				RelativePath=".\RedHatCSProxy_i.c">
			</File>
			<File
				RelativePath=".\RedHatCSProxy_p.c">
			</File>
			<File
				RelativePath=".\registry.cpp">
			</File>
			<File
				RelativePath=".\service.cpp">
			</File>
			<File
				RelativePath=".\stdafx.cpp">
			</File>
			<File
				RelativePath=".\submit.cpp">
			</File>
			<File
				RelativePath=".\util.cpp">
			</File>
		</Filter>
		<Filter
			Name="Header Files"
			Filter="h;hpp;hxx;hm;inl;inc;xsd"
			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
			<File
				RelativePath=".\b64.h">
			</File>
			<File
				RelativePath=".\csproxy.h">
			</File>
			<File
				RelativePath=".\messages.h">
			</File>
			<File
				RelativePath=".\nvpair.h">
			</File>
			<File
				RelativePath=".\RedHatCSProxy_h.h">
			</File>
			<File
				RelativePath=".\resource.h">
			</File>
			<File
				RelativePath=".\stdafx.h">
			</File>
		</Filter>
		<Filter
			Name="Resource Files"
			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
		</Filter>
	</Files>
	<Globals>
	</Globals>
</VisualStudioProject>


--- NEW FILE registry.cpp ---
#define _WIN32_DCOM
#include <windows.h> 
#include <winhttp.h>

#include <atlconv.h>
#include "csproxy.h"

#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>





registry::registry()
{
	v = NULL;
	config = NULL;
	// Create an event to be used to notify when the registry changes
    event = CreateEvent(NULL, TRUE, FALSE, NULL);
	
	HRESULT r;
	r = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
					  TEXT("SOFTWARE\\Red Hat\\RHCSProxy\\Config"),
					  0,
					  KEY_READ| KEY_NOTIFY,
					  &config );
	if (! FAILED(r)) {
		update();
	}
}

bool registry::changed()
{
	if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0) return true;
	else return false;
}

void registry::update()
{
	if (v != NULL) {
		delete v;
	}
	v = new configvars();
	getConfig(config,v);
	setupnotification();
	
}

void registry::setupnotification()
{
	// Set up registry change notification.
	RegNotifyChangeKeyValue(config, TRUE, 
		REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
		event, TRUE);
}

configvars * registry::getvars()
{
	if (changed()) {
		debug("Registry changed. Re-reading configuration");
		update();
		getlogconfig();
	}
	return v;
}





HRESULT getRegistryString(HKEY key, char*name, char**value)
{
	HRESULT r;
	DWORD size=0;

	/* first time calling - size is zero, so windows will fill in
	 * the right size, then we allocate the buffer and call again
	 */
	r = RegQueryValueEx(key, name, NULL,NULL, (LPBYTE)value, &size );
	if (FAILED(r)) return r;
	*value = (char*)malloc(size);
	r = RegQueryValueEx(key, name, NULL,NULL, (LPBYTE)*value, &size );
	return r;
}

HRESULT getRegistryDWORD(HKEY key, char *name,DWORD *value)
{
	HRESULT r;
	char *value_string;
	r = getRegistryString(key,name,&value_string);
	if (FAILED(r)) return r;
	*value = atoi(value_string);
	free(value_string);
	return ERROR_SUCCESS;
}

void freeConfig(configvars **vars)
{
	delete *vars;
	*vars = NULL;
}



/* getConfig()  will read configuration information from the registry.
 * You will not usually write data into the registry by hand. Use the
 * UI to set up the registry as appropriate.
 *
 * The registry info is rooted at: HKEY\Local Machine\SOFTWARE\Red Hat\RHCSProxy\Config
 */
 // returns 0 on success
HRESULT getConfig(HKEY config, configvars *v)
{
	HRESULT r;
	debugt(LOG_D_FUNC,"getConfig");

	DWORD buffer_size = BUFSIZE;
	v->certhash_size = buffer_size;
	v->cacert_size   = buffer_size;

	char *hostname=NULL;
	INTERNET_PORT portnum = INTERNET_DEFAULT_HTTPS_PORT;
	DWORD catype = CATYPE_UNKNOWN;
	
	CHAR     achKey[MAX_PATH]; 
	DWORD    achKeySize = MAX_PATH;
    CHAR     achClass[MAX_PATH] = "";  // buffer for class name 
    DWORD    cchClassName = MAX_PATH;  // size of class string 
    DWORD    cSubKeys;                 // number of subkeys 
    DWORD    cbMaxSubKey;              // longest subkey size 
    DWORD    cchMaxClass;              // longest class string 
    DWORD    cValues;              // number of values for key 
    DWORD    cchMaxValue;          // longest value name 
    DWORD    cbMaxValueData;       // longest value data 
    DWORD    cbSecurityDescriptor; // size of security descriptor 
    FILETIME ftLastWriteTime;      // last write time 
 
    DWORD i; 
    DWORD retCode; 
 
#define MAX_VALUE_NAME 1024 
    DWORD cchValue = MAX_VALUE_NAME; 


	// get the subkey for 'CertificateAuthorities'
	HKEY certificateauthorities;
	r = RegOpenKeyEx(config, TEXT("CertificateAuthorities"),
			0,KEY_READ, &certificateauthorities );
	if (FAILED(r)) return -2;


	/* This function queries for the number of subkeys in the
	 * "certificate authorities" key.
	 */
	RegQueryInfoKey(certificateauthorities,        // key handle 
        achClass,                // buffer for class name 
        &cchClassName,           // size of class string 
        NULL,                    // reserved 
        &cSubKeys,               // number of subkeys 
        &cbMaxSubKey,            // longest subkey size 
        &cchMaxClass,            // longest class string 
        &cValues,                // number of values for this key 
        &cchMaxValue,            // longest value name 
        &cbMaxValueData,         // longest value data 
        &cbSecurityDescriptor,   // security descriptor 
        &ftLastWriteTime);       // last write time 


	/* Loop through each of the certificate authorities in the
	 * registry. Each time through the loop, achKey will be set to
	 * "1", "2", etc....
	 */
	for (i = 0, retCode = ERROR_SUCCESS; 
            retCode == ERROR_SUCCESS; i++) 
    { 
		achKeySize = MAX_PATH;
        retCode = RegEnumKeyEx(certificateauthorities, 
                     i, 
                     achKey, 
                     &achKeySize, 
                     NULL, 
                     NULL, 
                     NULL, 
                     &ftLastWriteTime);

        if (retCode == (DWORD)ERROR_SUCCESS) 
        {
			HKEY cainfokey;
			r = RegOpenKeyEx(certificateauthorities, achKey, 0, KEY_READ, &cainfokey );
			if (FAILED(r)) return -3;

			cainfo *ca = new cainfo();
			r = getRegistryString(cainfokey, "hostname", &ca->host);
			if (FAILED(r))  return -4;
			debugt(LOG_D_CONFIG,"reading ca hostname: %s",ca->host);

			r = getRegistryDWORD(cainfokey, "port", &ca->port);
			if (FAILED(r))  return -4;
			debugt(LOG_D_CONFIG,"reading ca port: %d",ca->port);

			r = getRegistryDWORD(cainfokey, "catype", &ca->catype);
			if (FAILED(r))  return -4;
			debugt(LOG_D_CONFIG,"reading ca type: %d",ca->catype);

			FILETIME long_ago = { 0, 0};
			ca->last_failure = long_ago;
			GetSystemTimeAsFileTime(&ca->last_success);

			v->all_cas.push_back(ca);

			RegCloseKey(cainfokey);

			break;  // just take the first one for now
        }
		
	}
	RegCloseKey(certificateauthorities);


// Get the Profile Mappings
		// get the subkey for 'ProfileMap'
	cchValue = MAX_VALUE_NAME; 

	HKEY profilemap;
	r = RegOpenKeyEx(config, TEXT("ProfileMap"),
			0,KEY_READ, &profilemap );
	if (FAILED(r)) return -2;


	/* This function queries for the number of subkeys in the
	 * "certificate authorities" key.
	 */
	RegQueryInfoKey(profilemap,        // key handle 
        achClass,                // buffer for class name 
        &cchClassName,           // size of class string 
        NULL,                    // reserved 
        &cSubKeys,               // number of subkeys 
        &cbMaxSubKey,            // longest subkey size 
        &cchMaxClass,            // longest class string 
        &cValues,                // number of values for this key 
        &cchMaxValue,            // longest value name 
        &cbMaxValueData,         // longest value data 
        &cbSecurityDescriptor,   // security descriptor 
        &ftLastWriteTime);       // last write time 


	/* Loop through each of the certificate authorities in the
	 * registry. Each time through the loop, achKey will be set to
	 * "1", "2", etc....
	 */
	
	for (i = 0, retCode = ERROR_SUCCESS; 
            retCode == ERROR_SUCCESS; i++) 
    { 
		achKeySize = MAX_PATH;
        retCode = RegEnumKeyEx(profilemap, 
                     i, 
                     achKey, 
                     &achKeySize, 
                     NULL, 
                     NULL, 
                     NULL, 
                     &ftLastWriteTime);

        if (retCode == (DWORD)ERROR_SUCCESS) 
        {
			HKEY mykey;
			r = RegOpenKeyEx(profilemap, achKey, 0, KEY_READ, &mykey );
			if (FAILED(r)) return -3;

			char *p;
			r = getRegistryString(mykey, "CAProfileName", &p);
			if (FAILED(r))  return -4;
			debugt(LOG_D_CONFIG,"reading profile name: %s",p);

			profile pr;
			pr.rhcsprofilename = p;
			v->profilemap[string(achKey)] = pr;
			free(p);
			RegCloseKey(mykey);
        }
		
	}
	RegCloseKey(profilemap);

// End of profile Mappings




// HASH OF AUTH CERTIFICATE
	r = RegQueryValueEx(
				config,
				"AuthenticationCertificate",
				NULL,
				NULL,
				(LPBYTE)v->certhash,
				&v->certhash_size );

	debugt(LOG_D_CONFIG,"reg query result (for AuthenticationCertificate) = %d",r);
	if (v->certhash_size >= 4) {
		debugt(LOG_D_CONFIG,
			  "Using Authentication Certificate (hash=0x%02x%02x%02x%02x...)",
			  v->certhash[0],
			  v->certhash[1],
			  v->certhash[2],
			  v->certhash[3]);
	} else {
		debugt(LOG_GENERAL,"Error: Authentication Certificate in Registry is too short");	
	}
		

	if (FAILED(r))  return -6;


// CA CERTIFICATE
	r = RegQueryValueEx(
				config,
				"CACertificate",
				NULL,
				NULL,
				(LPBYTE)v->cacert,
				&v->cacert_size );


	if (FAILED(r)) {
		return -7;
	}
	
	debugt(LOG_D_CONFIG,"cacert: 0:%x 1:%x 2:%x, length=%d",
		v->cacert[0], v->cacert[1], v->cacert[2],
		v->cacert_size);


// Whether or not to do ICertRequestD2 (this code is incomplete)
	v->icertrequestd2 = 0;
	size_t p_size = sizeof(DWORD);

	// Whether to register the ICertRequestD2 interface with DCOM.
	r = getRegistryDWORD(config, "ICertRequestD2", (LPDWORD)&v->icertrequestd2);
	// Interval until we retry a CA which had failed
	r = getRegistryDWORD(config, "RetryInterval", (LPDWORD)&v->retryinterval);


	return 0;
}


--- NEW FILE resource.h ---
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by testserver.rc
//

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40002
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif


--- NEW FILE service.cpp ---
/** BEGIN COPYRIGHT BLOCK
 * END COPYRIGHT BLOCK */


#include <windows.h> 

#include "csproxy.h"

#define UNICODE




SERVICE_STATUS			serviceStatus1;
SERVICE_STATUS_HANDLE	serviceStatus1Handle;

HANDLE killevent;

bool running;
bool service_running()
{
	return running;
}



void WINAPI serviceCtrlHandler(DWORD FwdControl)
{
	debug("ServiceCtrlHandler begin %d",FwdControl);
	switch (FwdControl) {
		case SERVICE_CONTROL_PAUSE:
			debug("ServiceCtrlHandler recvd pause");
			serviceStatus1.dwCurrentState = SERVICE_PAUSED;
			break;
		case SERVICE_CONTROL_CONTINUE:
			debug("ServiceCtrlHandler recvd continue");
			break;
		case SERVICE_CONTROL_STOP:
			debug("ServiceCtrlHandler recvd stop");
			serviceStatus1.dwWin32ExitCode = 0;
			serviceStatus1.dwCurrentState = SERVICE_STOPPED;
			serviceStatus1.dwCheckPoint = 0;
			serviceStatus1.dwWaitHint = 0;
			running = false;
			if (!SetServiceStatus(serviceStatus1Handle,&serviceStatus1)) {
				debug("ServiceCtrlHandler stop: error setting status");
			}
			break;
		case SERVICE_CONTROL_INTERROGATE:
			debug("ServiceCtrlHandler recvd interrogate");
			if (!SetServiceStatus(serviceStatus1Handle,&serviceStatus1)) {
				debug("ServiceCtrlHandler interrogate: error setting status");
			}
			break;
		default:
			debug("ServiceCtrlHandler recvd %d",FwdControl);
	}
	debug("ServiceCtrlHandler returning %d",FwdControl);
}

DWORD WINAPI serviceInit(DWORD argc, LPTSTR *argv, DWORD *errorcode)
{
	debug("serviceInit");
	exemain(0,NULL);
	*errorcode = 0;
	debug("serviceInit returning");
	return 0;
}



void WINAPI ServiceMain1(DWORD argc, LPTSTR *argv)
{
	debug("ServiceMain1: argc = %d",argc);
	
	DWORD status;
	DWORD errorcode;


	// 1. - register service to get handle
	
	serviceStatus1Handle = RegisterServiceCtrlHandler(
				(LPCSTR)L"Red Hat Certificate Server Proxy", 
				serviceCtrlHandler
				);
	if (serviceStatus1Handle == (SERVICE_STATUS_HANDLE)0) {
		OutputDebugString((LPCSTR)L"ServiceMain1 - failed to register ctrl handler\n");
		debug("ServiceMain1: failed to register ctrl handler");
	}

	killevent = CreateEvent(0, TRUE, FALSE, 0);

	// 2. set status to 'pending'

	serviceStatus1.dwServiceType = SERVICE_WIN32;
	serviceStatus1.dwCurrentState = SERVICE_START_PENDING;
	serviceStatus1.dwControlsAccepted = SERVICE_ACCEPT_STOP;
	serviceStatus1.dwWin32ExitCode = 0;
	serviceStatus1.dwServiceSpecificExitCode = 0;
	serviceStatus1.dwCheckPoint = 0;
	serviceStatus1.dwWaitHint = 0;

	debug("ServiceMain1: setservicestatus=startpending");
	SetServiceStatus(serviceStatus1Handle, &serviceStatus1);


	// 4. if error, set status to stopped, exit
	/*
	if (status != NO_ERROR) {
		serviceStatus1.dwCurrentState = SERVICE_STOPPED;
		serviceStatus1.dwCheckPoint = 0;
		serviceStatus1.dwWaitHint = 0;
		serviceStatus1.dwWin32ExitCode = status;
		serviceStatus1.dwServiceSpecificExitCode = errorcode;
		SetServiceStatus(serviceStatus1Handle, &serviceStatus1);
		return;
	} */
	
	serviceStatus1.dwCurrentState = SERVICE_RUNNING;
	serviceStatus1.dwCheckPoint = 0;
	serviceStatus1.dwWaitHint = 0;
	serviceStatus1.dwWin32ExitCode = 0;
	serviceStatus1.dwServiceSpecificExitCode = 0;
	debug("ServiceMain1: setservicestatus=running");
	SetServiceStatus(serviceStatus1Handle, &serviceStatus1);

	// 3. call initialization
	debug("ServiceMain1: calling serviceInit");
	running = true;
	status = serviceInit(argc,argv, &errorcode);

	debug("ServiceMain1 - returning");
	return;
	
}



int svcmain(int argc, char **argv)
{
	DWORD pid = GetCurrentProcessId();

	
	SERVICE_TABLE_ENTRY servicedispatchtable[] = 
	{
		{ (LPSTR)L"redhatcertsvrservice1", ServiceMain1 },
		{ NULL, NULL }
	};


	debug("svcmain: calling StartServiceCtrlDispatcher");
	if (!StartServiceCtrlDispatcher(servicedispatchtable)) {
		debug("could not start service dispatcher");
	}
	debug("svcmain: back in svcmain");

	//debug("svcmain: sleeping forever");
	//while(1) { Sleep(1000); }
	debug("svcmain: reutrning");
	return 0;
}






--- NEW FILE stdafx.cpp ---
// stdafx.cpp : source file that includes just the standard includes
// testserver.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file


--- NEW FILE stdafx.h ---
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once


#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

// TODO: reference additional headers your program requires here


--- NEW FILE util.cpp ---
/* printcertnames() will print out, to the console, a list of all certificate names
   which are available in the MY certificate store, so you can figure out which to use
   for client-auth. This isn't useful any more, since:
      1) There is a UI to do this
	  2) The selection is based on a hash of the certificate, not its name
	  */
#if 0
void printcertnames()
{
    USES_CONVERSION;
	HCERTSTORE hMyStore = CertOpenSystemStore( 0, TEXT("MY") );
	if (hMyStore) {
		PCCERT_CONTEXT pCertContext, previous=NULL,test=NULL;

		CERT_ENHKEY_USAGE enky;
		enky.cUsageIdentifier = 1;
		char *x = szOID_PKIX_KP_CLIENT_AUTH;
		enky.rgpszUsageIdentifier = &x;
		printf("A list of valid certificates in the MY store follows:\n");
		do {
			pCertContext = 
					CertFindCertificateInStore( hMyStore,
						X509_ASN_ENCODING,
						0,
						//CERT_FIND_ANY,
						CERT_FIND_ENHKEY_USAGE,
						&enky,
						previous );
			if (pCertContext != NULL) {
				DWORD dwpara = CERT_X500_NAME_STR;
				char name[MAX_PATH];
				DWORD name_size=MAX_PATH;
				CertGetNameString(
					pCertContext,
					CERT_NAME_RDN_TYPE,
					0,
					&dwpara,
					(LPSTR)&name,
					name_size );
				printf("%s\n",name);
				BYTE buf[1024];
				CERT_BLOB *cn = (CERT_BLOB *)&buf;
				DWORD bufsize=1024;

				CertStrToName(
					X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
					name,
					CERT_OID_NAME_STR,
					NULL,
					buf,
					&bufsize,
					NULL);

				test = CertFindCertificateInStore( hMyStore,
						X509_ASN_ENCODING |PKCS_7_ASN_ENCODING,
						0,
						//CERT_FIND_ANY,
						CERT_FIND_SUBJECT_NAME,
						cn,
						NULL);
				//printf("tried to find cert by subject = %lx\n",(void*)test);

				

			}
			previous = pCertContext;

		} while (pCertContext != NULL);
	}

}
#endif

Index: proxy.cpp
===================================================================
RCS file: /cvs/dirsec/windowsautoenroll/proxy/proxy.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- proxy.cpp	29 Jul 2006 00:42:44 -0000	1.1.1.1
+++ proxy.cpp	13 Mar 2007 01:36:10 -0000	1.2
@@ -1,520 +1,1304 @@
-/** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- * 
- * This Program 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 General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- * 
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception. 
- * 
- * 
- * Copyright (C) 2006 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK */
-
-
-#define _WIN32_DCOM
-#define _WIN32_WINNT 0x500
-
-#include <windows.h> 
-#include <stdlib.h>
-#include <comdef.h>
-#include <objbase.h>
-#include <assert.h>
-#include <stdarg.h>
-#include <certcli.h>
-#include "messages.h"
-
-
-#include "stdafx.h"
-
-//*******************************************************************
-//* Required macros
-//*******************************************************************
-#define UNICODE         // UNICODE
-
-//*******************************************************************
-//* Includes
-//*******************************************************************
-
-#include <stdio.h>
-
-#include <initguid.h>
-#include "RedHatCSProxy_h.h"    // Get CLSID and IID definitions
-
-
-extern LONG submitRequestToCA(char *certrequest, char **cert);
-
-/* XXX - we are not currently shipping the code required to
-   implement these functions, so the linker will fail.
- */
-extern "C" {
-	extern size_t b64_decode(char const *src, size_t srcLen, void *dest, size_t destSize);
-	extern size_t b64_encode(void const *src, size_t srcSize, char *dest, size_t destLen);
-};
-
-
-
-
-
-FILE *fp=NULL;
-
-void debug(LPCTSTR pFormat,...)
-{
-
-	TCHAR chmsg[1024];
-	HANDLE es;
-	LPTSTR lpszStrings[1];
-	va_list pa;
-	va_start(pa,pFormat);
-	vsprintf(chmsg, pFormat, pa);
-	va_end(pa);
-
-	lpszStrings[0] = chmsg;
-
-	es = RegisterEventSource(NULL, "RHCSProxy");
-	if (es != NULL) {
-		ReportEvent(es, EVENTLOG_INFORMATION_TYPE,
-			CAT_1,MSG_RHCSPROXY_DEBUG, NULL, 1, 0,
-			(LPCTSTR*) &lpszStrings[0],
-			NULL);
-		
-		DeregisterEventSource(es);
-	}
-	puts(chmsg);
-	if(fp == NULL) {
-		fp = fopen("C:\\serverlogs\\serverlog.txt","a+");
-	}
-	if (fp != NULL) {
-		fprintf(fp,"%s\n",chmsg);
-		fflush(fp);
-	}
-}
-
-
-//*******************************************************************
-//*  CoHello component object implementation. 
-//*******************************************************************
-
-
-class CCertRequestD : public ICertRequestD {
-public:
-	// constructors/destructors
-	CCertRequestD() : m_lRefCount(0) 
-	{ 
-	}
-
-	~CCertRequestD() 
-	{ 
-	}
-
-public: 
-	// IUnknown Methods
-	STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
-	{
-		if (riid==IID_IUnknown||riid==IID_ICertRequestD) {
-			*ppv= (ICertRequestD *)(this);
-		} else {
-			*ppv=NULL; return E_NOINTERFACE ;
-		}
-
-		AddRef();
-		return S_OK;
-	}
-
-	STDMETHODIMP_(ULONG) AddRef(void)
-	{
-		return ++m_lRefCount;
-	}
-
-	STDMETHODIMP_(ULONG) Release(void)
-	{
-		long lCount = m_lRefCount-1;
-		if (lCount == 0) {
-			delete this; 
-		} 
-		return lCount; 
-	}
-	/*
-	// IDispatch methods
-	STDMETHODIMP GetTypeInfoCount(UINT FAR* pctinfo)
-	{
-	if (pctinfo == NULL) {
-	return E_INVALIDARG;
-	}
-	*pctinfo = 1;
-	return NOERROR;
-	} 
-
-	STDMETHODIMP GetTypeInfo(
-	UINT iTInfo,
-	LCID lcid,
-	ITypeInfo FAR* FAR* ppTInfo)
-	{
-	if (ppTInfo == NULL)
-	return E_INVALIDARG;
-	*ppTInfo = NULL;
-
-	if(iTInfo != 0)
-	return DISP_E_BADINDEX;
-
-	m_ptinfo->AddRef();      // AddRef and return pointer to cached
-	// typeinfo for this object.
-	*ppTInfo = m_ptinfo;
-
-	return NOERROR;
-	}
-
-
-	STDMETHODIMP GetIDsOfNames(
-	REFIID riid,
-	OLECHAR FAR* FAR* rgszNames,
-	UINT cNames,
-	LCID lcid,
-	DISPID FAR* rgDispId)
-	{
-	return DispGetIDsOfNames(m_ptinfo, rgszNames, cNames, rgDispId);
-	}
-
-	STDMETHODIMP Invoke(
-	DISPID dispidMember,
-	REFIID riid,
-	LCID lcid,
-	WORD wFlags,
-	DISPPARAMS FAR* pdispparams,
-	VARIANT FAR* pvarResult,
-	EXCEPINFO FAR* pexcepinfo,
-	UINT FAR* puArgErr)
-	{
-	return DispInvoke(
-	this, m_ptinfo,
-	dispidMember, wFlags, pdispparams,
-	pvarResult, pexcepinfo, puArgErr); 
-	}
-	*/
-
-
-	STDMETHODIMP Request( 
-		/* [in] */ DWORD dwFlags,
-		/* [in][string][unique] */ const wchar_t *pwszAuthority,
-		/* [in][out][ref] */ DWORD *pdwRequestId,
-		/* [out] */ DWORD *pdwDisposition,
-		/* [in][string][unique] */ const wchar_t *pwszAttributes,
-		/* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
-		/* [out][ref] */ CERTTRANSBLOB *pctbCertChain,
-		/* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
-		/* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage)
-	{
-		debug("Request");
-		debug("---- Request(flags=%hx, authority=%ws, requestid=%hd, attributes=%ws,"
-			" request[0..6]=%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-			dwFlags, pwszAuthority, pdwRequestId, pwszAttributes,
-			pctbRequest->pb[0],
-			pctbRequest->pb[1],
-			pctbRequest->pb[2],
-			pctbRequest->pb[3],
-			pctbRequest->pb[4],
-			pctbRequest->pb[5],
-			pctbRequest->pb[6]
-			);
-		IServerSecurity *iss = NULL;
-		HRESULT r;
-		//r = CoGetCallContext(IID_IServerSecurity, (void**)&iss);
-
-		DWORD authsvc;
-		DWORD authzsvc;
-		OLECHAR *svrprincname;
-		DWORD authlevel;
-		DWORD implevel= -1;
-		
-		RPC_AUTHZ_HANDLE privs;
-		SEC_WINNT_AUTH_IDENTITY *privs_identity = (SEC_WINNT_AUTH_IDENTITY*)&privs;
-		DWORD caps = EOAC_MAKE_FULLSIC;
-		
-		debug("About to call CoQueryClientBlanket");
-		r = CoQueryClientBlanket(&authsvc, &authzsvc, &svrprincname,
-								&authlevel, NULL, &privs, &caps);
-		debug("CoQueryClientBlanket returned %d",r);
-
-		debug("privs converted");
-		/*
-		char username[200];
-		debug("User length: %lx",privs_identity->UserLength);
-
-		for (unsigned int i=0; i< privs_identity->UserLength; i++) {
-		//for (unsigned int i=0; i< 40; i++) {
-			username[i] = (char) privs_identity->User[i];
-		//	sprintf(username+i*3,"%02x:",((char*)privs_identity)[i]);
-		}
-		*/
-		wchar_t* username = (wchar_t*)privs;
-			
-	
-		
-		DWORD secinfoflags = privs_identity->Flags;
-		debug("Request: secinfoflags gotten");
-		debug("Request:  Client Blanket: (authsvc=%hx(%s), authzsvc=%hx(%s), ",
-						  authsvc, authsvc==RPC_C_AUTHN_WINNT? "WINNT SSP":"?" ,
-			  authzsvc, authzsvc==RPC_C_AUTHZ_NONE? "AUTHZ_NONE":"?");
-		debug("Request:   svrprincname=%ws, ", svrprincname);
-
-		debug("Request:   authlevel=%hd(%s)",authlevel, authlevel==RPC_C_AUTHN_LEVEL_PKT_PRIVACY? "PKT_PRIVACY":"?");
-		debug("Request:   secinfoflags=%hd",secinfoflags);
-		debug("Request:   privs.username=%ws",username);
-		debug("Request:   caps=%hx",caps);
-
-
-		if (SUCCEEDED(r)) {
-	
-			char *b64req=NULL;
-			size_t b64size = b64_encode(pctbRequest->pb, pctbRequest->cb, NULL, 0);
-			b64req = (char*)malloc(b64size+1);
-			b64_encode(pctbRequest->pb, pctbRequest->cb, b64req, b64size);
-			b64req[b64size] = 0;
-			//debug("Request:   b64encoded cert request=%s",b64req);
-        
-			char *cert=NULL;
-			r = submitRequestToCA(b64req, &cert);
-			//debug("Request:   submit returned %lx",r);
-
-			if (r == 0) {
-				BYTE *cbin=NULL;
-				size_t binsize = b64_decode(cert, strlen(cert), NULL, 0);
-				BYTE* bincert = (BYTE*)malloc(binsize);
-				binsize = b64_decode(cert, strlen(cert), bincert, binsize);
-				pctbEncodedCert->pb = bincert;
-				pctbEncodedCert->cb = binsize;
-				*pdwDisposition = CR_DISP_ISSUED;
-			} else {
-				*pdwDisposition = CR_DISP_DENIED;
-			}
-		}
-
-		return S_OK;
-	}
-
-	STDMETHODIMP  GetCACert( 
-		/* [in] */ DWORD fchain,
-		/* [in][string][unique] */ const wchar_t *pwszAuthority,
-		/* [out][ref] */ CERTTRANSBLOB *pctbOut) 
-	{
-		debug("---- GetCACert(%ws)",pwszAuthority);
-		CERTTRANSBLOB *x = new CERTTRANSBLOB();
-		x->cb = 5;
-		x->pb = (BYTE*)malloc(5);
-		x->pb[0] = 1;
-		x->pb[1] = 2;
-		x->pb[2] = 3;
-		x->pb[3] = 4;
-		x->pb[4] = 8;
-		*pctbOut  = *x;
-		return S_OK;
-	}
-
-	STDMETHODIMP Ping( 
-		/* [in][string][unique] */ const wchar_t *pwszAuthority)
-	{
-		debug("---- Ping(%ws)",pwszAuthority);
-		return S_OK;
-	}
-
-
-
-
-	
-private:
-	LONG m_lRefCount;
-};
-
-
-
-
-// This implementation doesn't 'do' refcounting!
-class CCertRequestDFactory : public IClassFactory 
-{
-public:
-	// IUnknown Methods
-	STDMETHODIMP QueryInterface (REFIID riid, void** ppv)
-	{
-
-		if (riid==IID_IUnknown||riid==IID_IClassFactory) {
-			*ppv= static_cast<IClassFactory *>(this);
-		} else {
-			*ppv=NULL; return E_NOINTERFACE ;
-		}
-
-		return S_OK;
-	}
-
-	STDMETHODIMP_(ULONG) AddRef(void)
-	{ 
-		return 1; 
-	}
-
-	STDMETHODIMP_(ULONG) Release(void) 
-	{ 
-		return 1; 
-	}
-
-	// IClassFactory Methods
-	STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv)
-	{
-		HRESULT r;
-		debug("Class factory creating instance of CCertRequestD");
-		CCertRequestD *pCertRequestD = new CCertRequestD;
-		debug("created new CCertrequestd object");
-		r = pCertRequestD->QueryInterface(riid, ppv);
-		debug("queryinterface on new object is 0x%lx",r);
-		return r;
-	}
-
-	STDMETHODIMP LockServer(BOOL fLock)
-	{
-		return S_OK;        
-	}   
-};
-
-// This code does not seem to be necessary.
-HRESULT RegisterInterfaceMarshaler()
-{
-	HRESULT r;
-    debug("in registerInterface Marshaler");
-	DWORD dwCookie=0;
-	IUnknown *pUnk=0;
-
-	r = ::DllGetClassObject(IID_ICertRequestD, IID_IUnknown, (void**)&pUnk);
-	if (FAILED(r)) {
-		debug("failed to get Class Object");
-		return r;
-	}
-
-
-	r = ::CoRegisterClassObject(IID_ICertRequestD, pUnk,
-		CLSCTX_REMOTE_SERVER,
-		REGCLS_MULTIPLEUSE, &dwCookie);
-	if (FAILED(r)) {
-		debug("failed to register Class Object");
-		return r;
-	}
-
-	::CoRegisterPSClsid(IID_ICertRequestD, IID_ICertRequestD);
-	if (FAILED(r)) {
-		debug("failed to Register PS Clsidt");
-		return r;
-	}
-	debug("Registered Interface Marshaller");
-	
-
-	return S_OK;
-}
-
-//*******************************************************************
-//* The factory that can create CertRequestD objects is a globally defined.
-//*******************************************************************
-CCertRequestDFactory g_CertRequestDClassFactory;
-
-//*******************************************************************
-//* The server component's main() routine.
-//*******************************************************************
-void exemain(int argc, char **argv)
-{
-
-
-	debug("testserver started");
-	HRESULT r;
-	r = CoInitializeEx(NULL, COINIT_MULTITHREADED);
-	if (FAILED(r)) {
-		debug("CoInitializeEx failed (%lx)",r);
-		goto end;
-	}
-
-	/*
-	r = RegisterInterfaceMarshaler();
-	if (FAILED(r)) {
-		debug("Register InterfaceMarshaler failed (%lx)",r);
-		goto end;
-	}
-	*/
-
-
-	DWORD dwCookie=0;
-
-	r = CoRegisterClassObject(CLSID_CCertRequestD, 
-		&g_CertRequestDClassFactory,
-		CLSCTX_SERVER | CLSCTX_REMOTE_SERVER, 
-		REGCLS_MULTIPLEUSE, 
-		&dwCookie);
-
-	if (FAILED(r)) {
-		debug("CoRegisterClassObject failed (%lx)",r);
-		goto end;
-	}
-	debug("Successfully registered class object for CCertRequestD");
-
-	/*
-	debug("testing cocreateinstanceex");
-	ICertRequestD *icrd=NULL;
-
-	COSERVERINFO si;
-	si.dwReserved1 = 0;
-	si.dwReserved2 = 0;
-	si.pAuthInfo = NULL;
-	si.pwszName = L"sparkinswindows.sparkins.sfbay.redhat.com";
-
-	MULTI_QI mi;
-	mi.pIID = &IID_ICertRequestD;
-	mi.pItf = NULL;
-	mi.hr = 0;
-
-
-	r = CoCreateInstanceEx(
-		CLSID_CCertRequestD,
-		NULL,
-		CLSCTX_ALL,
-		&si,
-		1,
-		&mi
-		);
-
-
-	if (!FAILED(r)) {
-		ICertRequestD *rq = (ICertRequestD *) mi.pItf;
-		rq->Ping(L"hello");
-		debug("instance created in-process successfully");
-	}
-	*/
-
-	debug("Waiting for requests");
-
-	// For demonstration, this component will live forever.
-	//Sleep(INFINITE);
-end:
-	;
-
-}
-
-
-
+/** BEGIN COPYRIGHT BLOCK
+ * END COPYRIGHT BLOCK */
+
+
+#define _WIN32_DCOM
+#define _WIN32_WINNT 0x500
+
+
+
+#include <windows.h> 
+#include <atlconv.h>
+#include <stdlib.h>
+#include <comdef.h>
+#include <objbase.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <certcli.h>
+#include <certsrv.h>
+
+#include <exception>
+#include <ActiveDS.h>
+#include <Iads.h>
+#include <adsiid.h>
+
+#include "messages.h"
+#include "stdafx.h"
+
+//*******************************************************************
+//* Required macros
+//*******************************************************************
+#define UNICODE         // UNICODE
+
+//*******************************************************************
+//* Includes
+//*******************************************************************
+
+#include <stdio.h>
+
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+using namespace std;
+
+#include <initguid.h>
+#include "RedHatCSProxy_h.h"    // Get CLSID and IID definitions
+
+#include "csproxy.h"
+
+
+unsigned int g_logoptions;
+
+
+extern "C" {
+#include "b64.h"
+};
+
+void debug_lower(TCHAR *chmsg);
+string guidtostr(GUID *guid);
+
+
+
+
+
+//*******************************************************************
+//*  CCertRequestD component object implementation. 
+//*******************************************************************
+
+
+class CCertRequestD : public ICertRequestD2 {
+
+private:
+	LONG m_lRefCount;
+	registry *reg;
+	
+public:
+	// constructors/destructors
+	CCertRequestD(registry *r) : m_lRefCount(0) 
+	{ 
+		reg = r;
+	}
+
+	~CCertRequestD() 
+	{ 
+	}
+
+	// IUnknown Methods
+	STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
+	{
+		configvars *vars = reg->getvars();
+		GUID guid = riid;
+		//wchar_t guidstr[128];
+		//guidtostr(&guid, guidstr);
+		//debugt(LOG_D_COM,"queryinterface: %ws",guidstr);
+		
+		if (riid==IID_IUnknown) {
+			debugt(LOG_D_COM,"returning IUnknown");
+			*ppv = static_cast<IUnknown*> ((ICertRequestD*)this);
+		} else if (riid==IID_ICertRequestD) {
+			debugt(LOG_D_COM,"returning ICertRequestD");
+			*ppv= (ICertRequestD *) this;
+		} else if (riid==IID_ICertRequestD2 && vars->icertrequestd2) {
+			debugt(LOG_D_COM,"returning ICertRequestD2");
+			try {
+				*ppv= (ICertRequestD2 *) this;
+			} catch (exception e) {
+				debugt(LOG_D_COM,"got exception during cast to ICertRequestD2: message %s",e.what());
+				*ppv=NULL; return E_NOINTERFACE ;
+			}
+		} else {
+			*ppv=NULL; return E_NOINTERFACE ;
+		}
+		
+		AddRef();
+		return S_OK;
+	}
+
+	STDMETHODIMP_(ULONG) AddRef(void)
+	{
+		return ++m_lRefCount;
+	}
+
+	STDMETHODIMP_(ULONG) Release(void)
+	{
+		long lCount = m_lRefCount-1;
+		if (lCount == 0) {
+			delete this; 
+		} 
+		return lCount; 
+	}
+
+	STDMETHODIMP Request( 
+		/* [in] */ DWORD dwFlags,
+		/* [in][string][unique] */ const wchar_t *pwszAuthority,
+		/* [in][out][ref] */ DWORD *pdwRequestId,
+		/* [out] */ DWORD *pdwDisposition,
+		/* [in][string][unique] */ const wchar_t *pwszAttributes,
+		/* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
+		/* [out][ref] */ CERTTRANSBLOB *pctbCertChain,
+		/* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
+		/* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage)
+	{
+		debugt(LOG_D_FUNC,"Request()");
+		return Request2(
+			pwszAuthority,
+			dwFlags,
+			L"",
+			pdwRequestId,
+			pdwDisposition,
+			pwszAttributes,
+			pctbRequest,
+			pctbCertChain, // FULL Response / Cert Chain
+			pctbEncodedCert,
+			pctbDispositionMessage
+			);
+	}
+	 
+	STDMETHODIMP Request2( 
+        /* [in][string][unique] */ const wchar_t *pwszAuthority,
+        /* [in] */ DWORD dwFlags,
+        /* [in][string][unique] */ const wchar_t *pwszSerialNumber,
+        /* [in][out][ref] */ DWORD *pdwRequestId,
+        /* [out] */ DWORD *pdwDisposition,
+        /* [in][string][unique] */ const wchar_t *pwszAttributes,
+        /* [in][ref] */ const CERTTRANSBLOB *pctbRequest,
+        /* [out][ref] */ CERTTRANSBLOB *pctbFullResponse,
+        /* [out][ref] */ CERTTRANSBLOB *pctbEncodedCert,
+        /* [out][ref] */ CERTTRANSBLOB *pctbDispositionMessage)
+
+	{
+		//_asm int 3;
+
+
+
+		debugt(LOG_D_FUNC,"Request2()");
+		if (pctbRequest->cb >7) {
+			debugt(LOG_D_DETAIL,"---- Request2(flags=%hx, authority=%ws, requestid=%hd, attributes=%ws,"
+				" serial=%ws request[0..6]=%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+				dwFlags, pwszAuthority, pdwRequestId, pwszAttributes,
+				pwszSerialNumber,
+				pctbRequest->pb[0],	pctbRequest->pb[1],
+				pctbRequest->pb[2],	pctbRequest->pb[3],
+				pctbRequest->pb[4],	pctbRequest->pb[5],
+				pctbRequest->pb[6]
+				);
+		}
+		IServerSecurity *iss = NULL;
+		HRESULT r;
+
+
+// This code is used to extract security info from the
+// COM context.
+
+		DWORD authsvc;
+		DWORD authzsvc;
+		OLECHAR *svrprincname;
+		DWORD authlevel;
+		DWORD implevel= -1;
+
+		RPC_AUTHZ_HANDLE privs;
+		SEC_WINNT_AUTH_IDENTITY *privs_identity = (SEC_WINNT_AUTH_IDENTITY*)&privs;
+		DWORD caps = EOAC_MAKE_FULLSIC;
+		
+		debugt(LOG_D_COM,"About to call CoQueryClientBlanket");
+		r = CoQueryClientBlanket(&authsvc,  &authzsvc, &svrprincname,
+								&authlevel, NULL, &privs, &caps);
+		debugt(LOG_D_COM,"CoQueryClientBlanket returned %d",r);
+
+		wchar_t* username = (wchar_t*)privs;
+			
+		DWORD secinfoflags = privs_identity->Flags;
+		debugt(LOG_D_COM,"Request:  Client Blanket:"
+			"(authsvc=%hx(%s), authzsvc=%hx(%s), ",
+			 authsvc,
+			 authsvc==RPC_C_AUTHN_WINNT? "WINNT SSP":"?" ,
+			 authzsvc,
+			 authzsvc==RPC_C_AUTHZ_NONE? "AUTHZ_NONE":"?");
+
+		debugt(LOG_D_COM,"Request:   "
+			"svrprincname=%ws, authlevel=%hd(%s) "
+			"secinfoflags=%hd privs.username=%ws caps=%hx",
+			svrprincname,
+			authlevel,
+			authlevel==RPC_C_AUTHN_LEVEL_PKT_PRIVACY? "PKT_PRIVACY":"?",
+			secinfoflags,
+			username,
+			caps );
+
+		configvars *vars = reg->getvars();
+
+		requestinfo req;
+		/* Pull apart PKCS#10, putting pieces into request object */
+		req.parseRequest(pctbRequest);
+
+		/* Pull apart attribute strings into request object */
+		req.parseAttributes(pwszAttributes);
+
+		/* Figure out which type of cert the requestor wants */
+		req.determineCertificateTemplate();
+
+		context cx(vars);
+		cx.request = &req;
+
+		/* if a profile map exists, convert the windows cert template
+		 * name to a CS profile name.
+		 */
+		string csprofile = *(req.windowsCertTemplateName);
+		if (cx.config->profilemap.find(csprofile) != cx.config->profilemap.end()) {
+			csprofile = cx.config->profilemap[csprofile].rhcsprofilename;
+		}
+		// Copies pieces of the of the request into http name/value pairs
+		req.populateRequestForTemplate(csprofile);
+
+
+		
+		vector<cainfo*> candidatecas = cx.makeCandidateCAList();
+		if (candidatecas.size() == 0)  {
+			// uh-oh : no ca can service this type of request
+		}		
+
+		vector<cainfo*> respondingcas = cx.findRespondingCAs(candidatecas);
+		if (respondingcas.size() == 0)  {
+			// uh-oh : all the CA's are down, and we haven't waited long enough to
+			// retry
+		}		
+
+
+		*pdwDisposition = CR_DISP_ERROR;
+
+		string cert, certchain;
+
+		for (unsigned int j=0; j<respondingcas.size(); j++) {
+			cx.selectedca = respondingcas[j];
+			debug("Request:   submitting to CA");
+			r = cx.submitRequestToCA(cert, certchain);
+			debug("submitRequestToCA returned %lx",r);
+
+			if (r == 0) {
+				GetSystemTimeAsFileTime(&cx.selectedca->last_success);
+			} else {
+				GetSystemTimeAsFileTime(&cx.selectedca->last_failure);
+			}
+
+			size_t errors_size = cx.errors.size();
+			if (errors_size>0) {
+				string e = cx.errors[0];
+				if (errors_size > 1) {
+					for (unsigned int k=1; k < errors_size; k++) {
+						e = " >> "+ cx.errors[k];
+					}
+				}
+				
+				debugt(LOG_GENERAL, "%s error was encountered while "
+					"submitting the certificate request to CA "
+					"%s:%d. \nFull error details: %s",
+					cx.fatalerror ? "A fatal" : "A nonfatal",
+					cx.selectedca->host, cx.selectedca->port,
+					e.c_str());
+			}
+
+			/* If we got a certificate, break */
+			if (r == 0) { break; }
+
+			/* Fatal error: We communicated with the CA. The CA
+			 *      processed our HTTP request, and returned a
+			 *      response which positively indicated that the
+			 *      certificate request failed. We do not try to
+			 *      post requests to other CA's in the list.
+			 *
+			 * Nonfatal: We could not make a connection to the CA, 
+			 *      or, the HTTP response was not '200'. In this case,
+			 *      we continue to try other CA's in the list.
+			 *
+			 * If the certificate request is waiting for approval
+			 * (in pending state), then this is not a fatal error
+			 * but we don't handle this case well
+			 */
+
+			if (cx.fatalerror) {
+				break;
+			}
+		}
+
+		if (r == 0) {  // success
+
+			decodeToBlob(cert.c_str(), pctbEncodedCert);
+			//debug("dumping certificate... %s", cert.c_str());
+			//debugbuffer(pctbEncodedCert->pb,pctbEncodedCert->cb);
+
+			decodeToBlob(certchain.c_str(), pctbFullResponse);
+			//debug("dumping cert chain... %s", certchain.c_str());
+			//debugbuffer(pctbFullResponse->pb,pctbFullResponse->cb);
+
+			// XXX need to get disposition from req->
+			*pdwDisposition = CR_DISP_ISSUED;
+		} else {
+			debugt(LOG_CERT,"A certificate was not issued. Failure code %lx",r);
+			*pdwDisposition = CR_DISP_ERROR;
+
+#if 0
+			/* Here, I want to include the error message from 
+			 * cx.errors, and stuff it into the disposition message.
+			 * My hope was that this would get displayed to the
+			 * enrolling application, but that is not the case,
+			 * so maybe I'm doing something wrong here.
+			 */
+			if (pctbDispositionMessage != NULL) {
+
+
+				USES_CONVERSION;
+				char* sMultibyte = "hello";
+				BSTR sUnicode;
+
+				sUnicode = SysAllocString(A2W(sMultibyte));   
+
+				pctbDispositionMessage->pb = (BYTE*)sUnicode;
+				pctbDispositionMessage->cb = sizeof(BSTR);
+			}
+#endif
+
+		}
+
+		return S_OK;
+	}
+
+
+	STDMETHODIMP GetCAPropertyInfo( 
+            /* [in][string][unique] */ const wchar_t *pwszAuthority,
+            /* [out] */ LONG *pcProperty,
+            /* [out][ref] */ CERTTRANSBLOB *pctbPropInfo)
+	{
+		debugt(LOG_D_FUNC,"GetCAPropertyInfo");
+		//debugt(LOG_D_DETAIL,"property: %d",pcProperty);
+		return S_OK;
+	}
+
+    STDMETHODIMP GetCAProperty( 
+        /* [in][string][unique] */ const wchar_t *pwszAuthority,
+        /* [in] */ LONG PropId,
+        /* [in] */ LONG PropIndex,
+        /* [in] */ LONG PropType,
+        /* [out][ref] */ CERTTRANSBLOB *pctbPropertyValue)
+	{
+		debugt(LOG_D_FUNC,"GetCAProperty: authority=%ws, PropId = %d, PropIndex =%d, PropType = %d",
+			pwszAuthority, PropId, PropIndex, PropType);
+		pctbPropertyValue->cb = 0;
+		pctbPropertyValue->pb = NULL;
+		return S_OK;
+	}
+
+	/* GetCACert is not usually called during enrollment, but is called
+	 * during some query operations initiated with the certutil.exe command
+	 */
+	STDMETHODIMP  GetCACert( 
+		/* [in] */ DWORD fchain,
+		/* [in][string][unique] */ const wchar_t *pwszAuthority,
+		/* [out][ref] */ CERTTRANSBLOB *pctbOut) 
+	{
+		BYTE storage[8192];
+		BYTE *b = storage;
+		unsigned short *msg = NULL;
+		int s=0;
+
+		char *c = (char*) &fchain;
+		
+		debug("---- GetCACert(%d=%x[%c%c%c%c],%ws)",fchain,fchain,c[3],c[2],c[1],c[0],pwszAuthority);
+		if (pctbOut != NULL) {
+			debug("---- GetCACert(certtransblob: cb = %d, pb=%lx",pctbOut->cb, pctbOut->pb);
+		} else {
+				debug("---- GetCACert(certtransblob=NULL)");
+		}
+
+		unsigned long fchain_upper = fchain & 0xFFFF0000;
+		unsigned long fchain_lower = fchain & 0x0000FFFF;
+
+		// some values of 'fchain' have their name in the first two bytes, and
+		// and index in the lower two bytes.
+		// if the first two bytes do indicate one of these types, we will
+		// mask off those lower two bytes so that we can switch() on it.
+		if (fchain_upper == 0x65780000 ||  // ex
+			fchain_upper == 0x63740000 ||  // ct
+			fchain_upper == 0xe3740000 ||  // pi-t!
+			fchain_upper == 0xe3f40000 ||  // pi-?!
+			fchain_upper == 0x736c0000 ||  // pi-?!
+			0) {
+			fchain = fchain_upper;
+		}
+		
+		switch (fchain) {
+			case 0x6E616D65:  // name
+				debug(" parsing 'name'");
+				b[0] = 'r'; b[1] = 0; b[2] = 'h'; b[3] = 0;
+				b[4] = 'c'; b[5] = 0; b[6] = '3'; b[7] = 0;
+				s = 8;
+				msg = L"Red Hat Certificate System Proxy";
+				break;
+			case 0x696E666F:  // info
+				debug(" parsing 'info'");
+
+				CAINFO c;
+				c.cbSize = sizeof(CAINFO);   // not sure about this one?
+				c.CAType = ENUM_ENTERPRISE_ROOTCA;
+				c.cCASignatureCerts = 0;
+				c.cCAExchangeCerts = 0;
+				c.cExitModules = 0;
+				c.lPropIdMax = 0;
+				c.lRoleSeparationEnabled = 0;
+				c.cKRACertCount = 0;
+				c.cKRACertUsedCount = 0;
+				c.fAdvancedServer = 0;
+
+				b = (BYTE*) &c;
+				s = sizeof(CAINFO);
+		
+				break;
+			case 0x74797065:  // type
+				debug(" parsing 'type'");
+				b[0] = 0; b[1] = 0; b[2] = 0; b[3] = 0;  // ENUM_ENTERPRISE_ROOTCA=0;
+				s = 4;
+				break;
+			case 0x70726f64:  // prod
+				debug(" parsing 'prod'");
+				b[0] = 'r'; b[1] = 0; b[2] = 'h'; b[3] = 0;
+				b[4] = 'c'; b[5] = 0; b[6] = '4'; b[7] = 0;
+				s = 8;
+				msg = L"Red Hat Certificate System Proxy";
+				break;
+			case 0x73740000:  // st(atus)
+				b[0] = 1;   // return 'unavailable'
+				b[1] = 1;   // return 'unavailable'
+				b[2] = 1;   // return 'unavailable'
+				b[3] = 1;   // return 'unavailable'
+				b[4] = 1;   // return 'unavailable'
+				s=5;
+				/* this returns an array of bytes , with each byte
+				   representing the status of one certificate, as follows:
+				 0 -- Incomplete
+				 1 -- Unavailable
+				 2 -- Revoked
+				 3 -- Valid
+				 4 -- Expired
+				 5 -- Under Submission
+				 >=6  Unknown
+				 */
+				break;
+			case 0x736C0000:  // sl (crl)
+				b[0] = 1;   // return 'unavailable'
+				s=0;
+				break;
+			case 0x65780000:  // ex (exit?)
+				msg = L"Red Hat Certificate System Proxy";
+				break;
+			case 0x63740000:  // ct
+				b[0] = 1;
+				s=1;
+				break;
+			case 0xe3740000:  // pi-t
+				b[0] = 1;
+				s=1;
+				break;
+			case 0xe3f40000:  // pi-?
+				b[0] = 1;
+				s=1;
+				break;
+			case 0x66696c65:   // file
+				msg = L"no-file-present";
+				break;
+			case 0x706f6c69:   // poli
+				msg = L"xxxx";
+				break;
+			case 0x73616e69:   // sani(tized name)
+				msg = L"Red Hat Certificate System Proxy";
+				break;
+			case 0x73686172:   // shar (shared file name)
+				msg = L"no-shared-file-present";
+				break;
+			case 0x70617265:   // pare (parent ca)
+				b[0] = 0;
+				s=0;
+				msg = L"Parent";
+				break;
+			default:
+				return -1;
+				b[0] = 0;
+				s=0;
+				break;
+		}
+
+		/*
+		x->cb = this->vars->cacert_size;
+		x->pb = (BYTE*)malloc(this->vars->cacert_size);
+		memcpy(x->pb,this->vars->cacert,this->vars->cacert_size);
+		*/
+
+		if (msg != NULL) {
+			pctbOut->pb = (BYTE*)wcsdup((wchar_t *)msg);
+			pctbOut->cb = (DWORD) wcslen((wchar_t *)msg) * 2;
+		} else {
+			if (s==0) {
+				pctbOut->pb = NULL;
+				pctbOut->cb = 0;
+			} else {
+				pctbOut->pb = (BYTE*)malloc(s);
+				memcpy(pctbOut->pb,b,s);
+				pctbOut->cb = s;
+			}
+		}
+
+		return S_OK;
+	}
+
+
+	// Ping is effectively unimplemented
+	STDMETHODIMP Ping( 
+		/* [in][string][unique] */ const wchar_t *pwszAuthority)
+	{
+		debugt(LOG_D_FUNC,"Ping");
+		debugt(LOG_D_DETAIL,"Ping - Authority = %ws",pwszAuthority);
+		return S_OK;
+	}
+
+	STDMETHODIMP Ping2( 
+		/* [in][string][unique] */ const wchar_t *pwszAuthority)
+	{
+		debugt(LOG_D_FUNC,"Ping2");
+		debugt(LOG_D_DETAIL,"Ping2 - Authority = %ws",pwszAuthority);
+		return Ping(pwszAuthority);
+	}
+
+
+
+
+	
+
+};
+
+
+
+
+// This implementation doesn't 'do' refcounting!
+class CCertRequestDFactory : public IClassFactory 
+{
+	registry *reg;
+public:
+	CCertRequestDFactory()
+	{
+		reg = new registry();
+		reg->update();
+	}
+	// IUnknown Methods
+	STDMETHODIMP QueryInterface (REFIID riid, void** ppv)
+	{
+
+		if (riid==IID_IUnknown) {
+			*ppv = (IUnknown*)this;
+		} else if (riid==IID_IClassFactory) {
+			*ppv= static_cast<IClassFactory *>(this);
+		} else {
+			*ppv=NULL;
+			return E_NOINTERFACE;
+		}
+
+		return S_OK;
+	}
+
+	STDMETHODIMP_(ULONG) AddRef(void)
+	{ 
+		return 1; 
+	}
+
+	STDMETHODIMP_(ULONG) Release(void) 
+	{ 
+		return 1; 
+	}
+
+
+
+	// IClassFactory Methods
+	STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv)
+	{
+		HRESULT r;
+		
+		debugt(LOG_D_COM,"Class factory creating instance of CCertRequestD");
+		
+		
+		CCertRequestD *pCertRequestD = new CCertRequestD(reg);
+		debugt(LOG_D_COM,"created new CCertrequestd object");
+		r = pCertRequestD->QueryInterface(riid, ppv);
+		
+		return r;
+	}
+
+	STDMETHODIMP LockServer(BOOL fLock)
+	{
+		return S_OK;        
+	}   
+
+private:
+	configvars *vars;
+};
+
+// This code does not seem to be necessary.
+HRESULT RegisterInterfaceMarshaler()
+{
+	HRESULT r;
+    debugt(LOG_D_COM,"in registerInterface Marshaler");
+	DWORD dwCookie=0;
+	IUnknown *pUnk=0;
+
+	r = ::DllGetClassObject(IID_ICertRequestD, IID_IUnknown, (void**)&pUnk);
+	if (FAILED(r)) {
+		debugt(LOG_D_COM,"failed to get Class Object");
+		return r;
+	}
+
+
+	r = ::CoRegisterClassObject(IID_ICertRequestD, pUnk,
+		CLSCTX_REMOTE_SERVER,
+		REGCLS_MULTIPLEUSE, &dwCookie);
+	if (FAILED(r)) {
+		debugt(LOG_D_COM,"failed to register Class Object");
+		return r;
+	}
+
+	::CoRegisterPSClsid(IID_ICertRequestD, IID_ICertRequestD);
+	if (FAILED(r)) {
+		debugt(LOG_D_COM,"failed to Register PS Clsidt");
+		return r;
+	}
+	debugt(LOG_D_COM,"Registered Interface Marshaller");
+	
+
+	return S_OK;
+}
+
+//*******************************************************************
+//* The factory that can create CertRequestD objects is a globally defined.
+//*******************************************************************
+CCertRequestDFactory *g_CertRequestDClassFactory;
+
+void getlogconfig()
+{
+	HRESULT r;
+
+	// read log flags
+	HKEY config;
+	r = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+			TEXT("SOFTWARE\\Red Hat\\RHCSProxy\\Config"),
+			0, //options
+			KEY_READ,
+			&config );
+	if (FAILED(r)) return;
+
+	
+	char buf[256];
+	DWORD size = 256;
+	r = RegQueryValueEx(
+			config,
+			"LogOptions",
+			NULL,
+			NULL,
+			(LPBYTE)buf,
+			&size );
+	if (FAILED(r)) {
+		g_logoptions = LOG_REQ |LOG_CERT;
+	} else {
+		g_logoptions = atoi(buf);
+	}
+}
+
+
+EXTERN_C const IID IID_ICertRequestD;
+
+//*******************************************************************
+//* The server component's main() routine.
+//*******************************************************************
+void exemain(int argc, char **argv)
+{
+	HRESULT r;
+
+	debugt(LOG_D_COM,"Certificate System proxy started");
+	
+	r = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+	if (FAILED(r)) {
+		debug("CoInitializeEx failed (%lx)",r);
+		goto end;
+	}
+
+	CLSID guid;
+	r = CLSIDFromString(L"{D99E6E74-FC88-11D0-B498-00A0C90312F3}",&guid);
+
+	r = CoInitializeSecurity((PSECURITY_DESCRIPTOR)&guid, // access permissions
+		-1,    // count of auth services (-1 -> let dcom choose)
+		NULL,  // auth services
+		NULL,  // reserved
+		RPC_C_AUTHN_LEVEL_CONNECT,
+		RPC_C_IMP_LEVEL_IDENTIFY,
+		NULL,      // pAuthList
+		EOAC_APPID, // capabilities
+		NULL);     // reserved
+
+	if (FAILED(r)) {
+		debug("CoInitializeSecurity failed (%lx)",r);
+		goto end;
+	}
+
+	g_CertRequestDClassFactory = new CCertRequestDFactory();
+
+	DWORD dwCookie=0;
+
+	r = CoRegisterClassObject(CLSID_CCertRequestD, 
+		g_CertRequestDClassFactory,
+		CLSCTX_SERVER | CLSCTX_REMOTE_SERVER, 
+		REGCLS_MULTIPLEUSE, 
+		&dwCookie);
+
+	if (FAILED(r)) {
+		debugt(LOG_D_COM,"CoRegisterClassObject failed (%lx)",r);
+		goto end;
+	}
+	debugt(LOG_D_COM,"Successfully registered class object for CCertRequestD");
+
+	debugt(LOG_D_COM,"Waiting for requests");
+
+	while (service_running()) {
+		Sleep(1000);
+	}
+	debugt(LOG_D_COM,"Saw stop signal");
+end:
+	;
+
+}
+
+
+LONG getguid(LPCWSTR dchostname, GUID *guid)
+{
+
+	HRESULT hr = S_OK; // COM result variable
+	ADS_SEARCH_COLUMN col;  // COL for iterations
+	LPWSTR szUsername = NULL; // Username
+	LPWSTR szPassword = NULL; // Password
+	LONG r=0;
+	ADS_SEARCH_HANDLE hSearch;
+
+	// Interface Pointers.
+	IDirectorySearch     *pDSSearch    =NULL;
+ 
+	// Initialize COM.
+	hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+	if (FAILED(hr)) {
+		debug("CoInitializeEx failed (%lx)",hr);
+		goto loser;
+	}
+
+	
+
+	IADs *rootdse = NULL;
+	//IADsPropertyList *rootdse_props = NULL;
+	// Add code to securely retrieve the username and password or
+	// leave both as NULL to use the default security context.
+ 
+	// Open a connection with server.
+	hr = ADsOpenObject(L"LDAP://rootDSE", 
+		szUsername,
+		szPassword,
+		ADS_SECURE_AUTHENTICATION,
+		IID_IADs,
+		(void **)&rootdse);
+	if (FAILED(hr)) { r = 10; goto loser; }
+
+//	if (FAILED(hr)) { r = 12; goto loser; }
+	// XXX Leaks
+	BSTR dnname = SysAllocString(L"defaultNamingContext");
+	VARIANT v;
+	hr = rootdse->Get(dnname,&v);
+	if (FAILED(hr)) { r = 11; goto loser; }
+
+
+	
+
+	if (dnname == NULL) { r = 4; goto loser; }
+			
+
+	size_t i = wcslen(v.bstrVal);
+		// XXX leaks
+	wchar_t *dc_base_url = (wchar_t *)malloc( (sizeof wchar_t)*(i+20));
+	wcscpy(dc_base_url,L"LDAP://");
+	wcscat(dc_base_url,v.bstrVal);
+	hr = ADsOpenObject(dc_base_url, szUsername,szPassword,
+			ADS_SECURE_AUTHENTICATION,
+			IID_IDirectorySearch,
+			(void **)&pDSSearch);
+	LPWSTR attrs[1];
+	attrs[0] = L"objectGUID";
+	size_t hostnamelen = wcslen(dchostname);
+	// XXX Leaks
+	wchar_t *filter = (wchar_t *)malloc( (sizeof wchar_t)*(hostnamelen+20));
+	wcscpy(filter,L"dNSHostName=");
+	wcscat(filter,dchostname);
+	hr = pDSSearch->ExecuteSearch(filter,attrs, 1, &hSearch);
+
+	if (FAILED(hr)) { r = 1; goto loser; }
+	
+	hr = pDSSearch->GetNextRow(hSearch);
+	if (hr == S_ADS_NOMORE_ROWS) { r = 13; goto loser; }
+	if (FAILED(hr)) { r = 2; goto loser; }
+					
+
+	// column leaked
+	hr = pDSSearch->GetColumn(hSearch, attrs[0], &col);
+	if (FAILED(hr)) { r = 3; goto loser; }
+
+	switch (col.dwADsType)
+	{									
+	case ADSTYPE_OCTET_STRING:
+		if (guid != NULL) {
+			memcpy( (LPBYTE)guid,
+				    col.pADsValues[0].OctetString.lpValue,
+				    col.pADsValues[0].OctetString.dwLength);
+				}
+			break;
+		default:
+			printf("Unexpected ADsType: %d\n", col.dwADsType);
+			r = 8;
+			goto loser;
+			break;
+	}
+	r = S_OK;
+loser:
+	if (r != S_OK) {
+		printf("error code %lx at %d\n",hr,r);
+	}
+	if (pDSSearch != NULL)  pDSSearch->CloseSearchHandle(hSearch);
+	return r;
+}
+
+
+
+/* Attributes is a string consisting of a series of lines, with each
+ * line consisting of a string of the form:
+ *  name:value
+ *
+ * This functions breaks up the attributes string and 
+ * puts it the name/values into an map in req->attrs
+ */
+void requestinfo::parseAttributes(const wchar_t *pwszAttributes)
+{
+	debugt(LOG_D_FUNC,"parseAttributes");
+	USES_CONVERSION;
+	istringstream stream(W2A(pwszAttributes));
+	string line;
+
+
+	while (stream >> line) {
+		size_t colon = line.find(':');
+
+		string name  = line.substr(0,colon);
+		string value = line.substr(colon+1);
+		this->attrs[name] = value;
+	}
+
+debugt(LOG_D_FUNC,"parseAttributes (returning)");
+}
+
+
+/*
+ * base-64 decodes the string in 'src', and puts the binary
+ * in an allocated buffer inside of blob. This function allocates
+ * the buffer
+ */
+void decodeToBlob(const char *src, CERTTRANSBLOB *blob)
+{
+	debugt(LOG_D_FUNC,"decodeToBlob");
+	if (src != NULL) {
+		// Decode b64 into a binary
+		// Allocates a little too much, by basing the size on
+		// the b64 string instead of the binary, but its big enough
+		// XXX - need to free this
+		unsigned char *dest = (unsigned char*)calloc(strlen(src),1);
+		size_t size = decode_base64((unsigned char*)dest,src);
+
+		if (size) {
+			blob->pb = dest;
+			blob->cb = (DWORD)size;
+		} 
+	}
+	debugt(LOG_D_FUNC,"decodeToBlob (returning)");
+}
+
+	/*
+	 * This function pulls apart the P10 plob, and populates the
+	 * requestinfo structure with useful information from the request
+	 * See http://technet2.microsoft.com/WindowsServer/en/library/d78843f2-f739-4d1f-84ca-f6337f5685d81033.mspx?mfr=true
+	 * for an example request (although it doesn't seem to be exactly
+	 * what the client sends - my test showed that the DC doesn't put a
+	 * SubjectAltName extension in the request, which means I have to
+	 * figure out the DC GUID through other means. sigh.
+	 */
+void requestinfo::parseRequest(const CERTTRANSBLOB *p10)
+{
+	CERT_REQUEST_INFO *b;
+	DWORD b_size = 0;
+
+	debugt(LOG_D_FUNC,"parseRequest");
+
+	this->PKCS10Request = encode_base64(p10->cb, p10->pb);
+
+	// Pull apart the PKCS#10 cert request.
+	if (! CryptDecodeObjectEx(
+		X509_ASN_ENCODING,
+		X509_CERT_REQUEST_TO_BE_SIGNED,
+		p10->pb,
+		p10->cb,
+		CRYPT_DECODE_ALLOC_FLAG,
+		NULL,   // para
+		&b,
+		&b_size
+		) )
+	{
+		debugt(LOG_D_DETAIL,"failed to parse PKCS#10 - error: %lx:",GetLastError());
+		return;
+	}
+
+	/* For each attribute: */
+	for (unsigned int i=0;i <b->cAttribute; i++) {
+		CRYPT_ATTRIBUTE *a = &b->rgAttribute[i];
+
+/*
+		if (debugt(LOG_D_DETAIL,"A Comparing OID #%d: '%s' == '%s'",
+			i,szOID_OS_VERSION, a->pszObjId),
+			strcmp(szOID_OS_VERSION,a->pszObjId) == 0) {
+			// os version
+			continue;
+		}
+		if (debugt(LOG_D_DETAIL,"B Comparing OID #%d: '%s' == '%s'",
+			i,szOID_REQUEST_CLIENT_INFO, a->pszObjId),
+			strcmp(szOID_REQUEST_CLIENT_INFO,a->pszObjId) == 0) {
+			// client info
+			continue;
+		}
+		*/
+		debugt(LOG_D_DETAIL,"C Comparing OID #%d: '%s' == '%s' (latter was provided in certificate request)",
+			i,szOID_RSA_certExtensions, a->pszObjId);
+		if (strcmp(szOID_RSA_certExtensions,a->pszObjId) == 0) {
+			// requested extensions
+			for (DWORD k=0; k < a->cValue; k++) {
+				CRYPT_ATTR_BLOB *p = &a->rgValue[k];
+				CERT_EXTENSIONS ex;
+				CERT_EXTENSIONS *e = &ex;
+				DWORD e_size = sizeof(CERT_EXTENSIONS);
+				if (!CryptDecodeObjectEx(X509_ASN_ENCODING,
+						X509_EXTENSIONS,
+						p->pbData,
+						p->cbData,
+						CRYPT_DECODE_ALLOC_FLAG,
+						NULL,
+						&e,
+						&e_size
+						) ) {
+							continue;
+						}
+				
+
+				for (unsigned int j=0;j<e->cExtension; j++) {
+					CERT_EXTENSION *c = &e->rgExtension[j];
+					if (strcmp(szOID_ENROLL_CERTTYPE_EXTENSION,
+						c->pszObjId) == 0) {
+							debug("cert type: %02x %02x %02x %02x", 
+								c->Value.pbData[0],
+								c->Value.pbData[1],
+								c->Value.pbData[2],
+								c->Value.pbData[3] );
+
+							// XXX need to convert from unicode to ascii
+							char *d = (char*)c->Value.pbData;
+							if (d[0] == 0x1e) {   // BMPSTRING
+								int length = d[1]/2;  // only half the space is needed as
+													  // we convert UNICODE->ASCII
+								string *s = new string();
+								for (int m=0;m<length;m++) {
+									s->append(1,d[2 + m*2 +1]);
+								}
+								this->windowsCertTemplateName = s;
+							}
+					}
+				}
+			}
+			continue;
+		}
+	}
+	debugt(LOG_D_FUNC,"parseRequest (returning)");
+}
+
+
+/* returns how much 'newer' newer is, in seconds */
+unsigned int filetimedeltaseconds(FILETIME older, FILETIME newer)
+{
+	ULONGLONG o, n, diff;
+	o = older.dwHighDateTime << (8*sizeof(older.dwHighDateTime));
+	o |= older.dwLowDateTime;
+	n = newer.dwHighDateTime << (8*sizeof(newer.dwHighDateTime));
+	n |= newer.dwLowDateTime;
+	
+	diff = n-o;
+
+	// diff is in 100ns intervals.
+	// * 10 intervals per us
+	// * 1000 us per ms
+	// * 1000 ms per s
+	ULONGLONG seconds = diff / ( 10 * 1000 * 1000 );
+	unsigned int s = (int) seconds;
+
+	return s;
+}
+
+/* Returns a list of CAs in the order that they should be tried.
+ */
+vector<cainfo*> context::findRespondingCAs(vector<cainfo*> candidates)
+{
+	debugt(LOG_D_FUNC,"findRespondingCAs");
+	vector<cainfo*> cas;
+
+	FILETIME now;
+
+	GetSystemTimeAsFileTime(&now);
+
+	for (unsigned int i=0;i <candidates.size(); i++) {
+// If the last failure was long ago, its okay to try it again
+		if ( filetimedeltaseconds(candidates[i]->last_failure, now) 
+			   > config->retryinterval )
+		{
+			cas.push_back(config->all_cas[i]);
+		}
+	}
+	debugt(LOG_D_FUNC,"findRespondingCAs (returning)");
+	return cas;
+
+}
+
+vector<cainfo*> context::makeCandidateCAList()
+{
+	debugt(LOG_D_FUNC,"makeCandidateCAList");
+	// make a list of all the CAs which can service the request
+	vector<cainfo*> cas;
+	for (unsigned int i=0;i <config->all_cas.size(); i++) {
+		if ( config->all_cas[i]->canService(request->windowsCertTemplateName))
+		{
+			cas.push_back(config->all_cas[i]);
+		}
+	}
+	debugt(LOG_D_FUNC,"makeCandidateCAList (returning)");
+	return cas;
+}
+
+/*
+ * There seems to be two ways for the enrollee to indicate
+ * what certificate type it wants. Either it can set this
+ * CertificateTemplate attribute in the request (as does
+ * IIS), or failing that, it can include the Certificate
+ * Template extension in the PKCS#10 request
+ */
+
+void requestinfo::determineCertificateTemplate()
+{
+	debugt(LOG_D_FUNC,"determineCertificateTemplate");
+	//req->httpvars["CertificateTemplate"] = *(this->windowsCertTemplateName);
+
+	if (windowsCertTemplateName == NULL) {
+		// IIS doesn't put it's cert template inside the PKCS#10 request, it sets it
+		// in this attribute:
+		windowsCertTemplateName = new string(attrs["CertificateTemplate"]);
+	}
+	if (*windowsCertTemplateName == "WebServer") {
+		// hopefully, IIS puts the CN requested into the PKCS#10.
+	}
+	if (*windowsCertTemplateName == "DomainController") {
+		USES_CONVERSION;
+
+		GUID gu;
+		const char *ccm = attrs["ccm"].c_str();
+		const wchar_t *ccmw = A2W(ccm);
+
+		HRESULT r = getguid(ccmw,&gu);
+		if (FAILED(r)) {
+			disposition = CR_DISP_ERROR;
+			goto loser;
+		}
+		string guidstr = guidtostr(&gu);
+		attrs["GUID"] = guidstr;
+	} 
+
+
+loser:
+	debugt(LOG_D_FUNC,"determineCertificateTemplate (returning)");
+	return;
+}
+
+
+void requestinfo::populateRequestForTemplate(string &csprofile)
+{
+	debugt(LOG_D_FUNC,"populateRequestForTemplate");
+	/* copy all attributes into HTTP vars */
+	map<string,string> copy(this->attrs.begin(), this->attrs.end());
+	this->httpvars = copy;
+
+	this->httpvars["cert_request_type"] = "pkcs10";
+	this->httpvars["cert_request"]      = this->PKCS10Request;
+	const char *s = this->httpvars["cert_request"].c_str();
+	this->httpvars["requestor_phone"]   = "unknown";
+	this->httpvars["profileId"]         = csprofile;
+	debugt(LOG_D_FUNC,"populateRequestForTemplate (returning)");
+}
+
+
+
+
+void  main(int argc, char **argv) 
+{
+	
+	int i;
+	int interactive=1;  // FORCE for now!
+	int test=0;
+	int configtest=0;
+	int dogetguid=0;
+	int service=0;
+
+	getlogconfig();
+
+	 debug("argc = %d",argc);
+	 for (i=0;i<argc;i++) {
+		 debug("argc[%d]= %s",i,argv[i]);
+		 if (!strcmp("-i",argv[i])) { interactive = 1; }
+		 if (!strcmp("-t",argv[i])) { debug("setting test=1"); test = 1; }
+		 if (!strcmp("-c",argv[i])) { debug("setting configtest=1"); configtest = 1; }
+		 if (!strcmp("-g",argv[i])) { debug("setting dogetguid=1"); dogetguid = 1; }
+		 if (!strcmp("-s",argv[i])) { debug("setting service=1"); service = 1; interactive =0; }
+	 }
+	 if (test) {
+		 debug("running test\n");
+		 //testmain();
+	 } else if (configtest) {
+		 debug("running configtest\n");
+//		 submitRequestToCA((char *)NULL,(char**)NULL,(char**)NULL,(nvpair*)NULL, NULL);
+	 } else if (dogetguid) {
+		 debug("getting guid\n");
+		 GUID g;
+		 getguid(L"sparkinswindows.sparkins.sfbay.redhat.com",&g);
+		 debug("guid= %lx\n",g.Data1);
+	 }  else if (service) {
+		 debug("running as a service\n");
+		svcmain(argc,argv);
+	 }  else if (interactive ) {
+		 debug("running interactive\n");
+		 exemain(0,NULL);
+		 Sleep(INFINITE);
+	 }
+	 
+	 debug("main - returning");
+	 return;
+}
+
+
+int should_log(unsigned int type)
+{
+	return (type & g_logoptions);
+}
+
+void debugbuffer2(BYTE *buf, int length, int offset)
+{
+	char c[512];
+	for (int i=0;i<length; i++) {
+		sprintf(c+i*3,"%02x ",buf[i+offset]);
+	}
+	debugt(LOG_D_DETAIL,"%s",c);
+}
+
+void debugbuffer(BYTE *buf, int length)
+{
+	debugt(LOG_D_DETAIL, "Dumping buf. Size = %d", length);
+	if (length >2048) length = 2048;
+
+
+	int partsize=64;
+	for (int i=0; i<length; i+= partsize) {
+		int count = length-i;
+		if (count > partsize) count=partsize;
+		debugt(LOG_D_DETAIL, "Dumping buffer. Size = %d, Offset=%d",
+			length, i);
+		debugbuffer2(buf, count, i);
+	}
+
+
+}
+
+void debug(const char* pFormat,...)
+{
+	int type = LOG_D_DETAIL;
+	if (should_log(type)) {
+		TCHAR chmsg[10240];
+		va_list pa;
+		va_start(pa,pFormat);
+		vsprintf(chmsg, pFormat, pa);
+		va_end(pa);
+		debug_lower(chmsg);
+	}
+}
+
+void debugt(unsigned int type, const char * pFormat,...)
+{
+	if (should_log(type)) {
+		TCHAR chmsg[10240];
+		va_list pa;
+		va_start(pa,pFormat);
+		vsprintf(chmsg, pFormat, pa);
+		va_end(pa);
+		debug_lower(chmsg);
+	}
+}
+
+void debug_lower(TCHAR *chmsg)
+{
+	LPTSTR lpszStrings[1];
+	HANDLE es;
+
+	TCHAR msg[10240];
+	/* don't print thread ID unless we're logging detail messages */
+	if (should_log(LOG_D_DETAIL)) {
+		sprintf(msg,"thread=%x %s",GetCurrentThreadId(),chmsg);
+	} else {
+		sprintf(msg,"%s",chmsg);
+	}
+	lpszStrings[0] = msg;
+
+	es = RegisterEventSource(NULL, "RHCSProxy");
+
+	if (es != NULL) {
+		ReportEvent(es,                 //event source
+			EVENTLOG_INFORMATION_TYPE,  //event type
+			0,                          // category
+			MSG_RHCSPROXY_DEBUG,        // message id
+			NULL,                       // SID - security identifier
+			1,                          // number of strings supplied
+			0,                          // length of binary data
+			(LPCTSTR*) &lpszStrings[0],  // strings
+			NULL);                       // binary data
+		printf("%s\n",msg);
+		DeregisterEventSource(es);
+	}
+	
+}
+
+string guidtostr(GUID *guid) {
+  char str[40];
+
+  sprintf(str, "%08lX%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
+	guid->Data1, guid->Data2, guid->Data3,
+	guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+	guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
+
+  return string(str);
+}
+


Index: submit.cpp
===================================================================
RCS file: /cvs/dirsec/windowsautoenroll/proxy/submit.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- submit.cpp	29 Jul 2006 00:42:44 -0000	1.1.1.1
+++ submit.cpp	13 Mar 2007 01:36:10 -0000	1.2
@@ -1,663 +1,591 @@
-/** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- * 
- * This Program 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 General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- * 
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception. 
- * 
- * 
- * Copyright (C) 2006 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK */
-
-#define _WIN32_DCOM
-
-
-#include <windows.h> 
-#include <winhttp.h>
-#include <WinCrypt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <comdef.h>
-#include <objbase.h>
-#include <assert.h>
-
-#include <ctype.h>
-
-#include <certcli.h>
-#include <certsrv.h>
-
-#include <atlconv.h>
-
-extern void debug(LPCTSTR pFormat,...);
-
-
-int add_char(char *p, char c)
-{
-	int i=1;
-	char *h = "0123456789abcdef";
-	if ( isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
-		*p = c;
-	} else {
-		*p++ = '%';
-		*p++ = h[((c & 0xf0) >> 4)];
-		*p++ = h[c & 0x0f];
-		i=3;
-	}
-	return i;
-}
-
-char *make_nv(char *name, char*value)
-{
-	//alloc mem for worst case, everything needs to be encoded, plus =, plus terminating 0
-	char *p = NULL;
-	char *r;
-	r = (char*)malloc(strlen(name)*3 + strlen(value)*3 +1 +1);  
-	p=r;
-	while (1) {
-		if (*name) {
-			p += add_char(p,*name);
-			name++;
-			if (*name == 0) {
-				*p = '=';
-				p++;
-			}
-		} else {
-			if (*value) {
-				p += add_char(p,*value);
-				value++;
-			} else {
-				break;
-			}
-		}
-
-	}
-	*p = 0;
-	return r;
-}
-
-
-char *buildRequestString(char *certrequest)
-{
-	char *p[10];
-	int c=0;
-	int i=0, s=0;
-
-	if (certrequest == NULL) { return NULL; }
-
-	p[c++] = make_nv("cert_request_type", "pkcs10");
-	
-	p[c++] = make_nv("cert_request",      certrequest);
-	p[c++] = make_nv("requestor_phone",   "650 650 6500");
-	p[c++] = make_nv("profileId",         "caAgentServerCert");
-	p[c]   = NULL;
-
-	for (i=0; i<c; i++) {  s += strlen(p[i]); }
-	
-	char *r = (char*)malloc(s+ c + 1);
-
-	r[0] = 0;
-	for (i=0;i<c;i++) {
-		strcat(r,p[i]);
-		free(p[i]);
-		if (p[i+1] != NULL) { 
-			strcat(r, "&");
-		}
-	}
-
-	return r;
-}
-
-
-
-void printcertnames()
-{
-    USES_CONVERSION;
-	HCERTSTORE hMyStore = CertOpenSystemStore( 0, TEXT("MY") );
-	if (hMyStore) {
-		PCCERT_CONTEXT pCertContext, previous=NULL,test=NULL;
-
-		CERT_ENHKEY_USAGE enky;
-		enky.cUsageIdentifier = 1;
-		char *x = szOID_PKIX_KP_CLIENT_AUTH;
-		enky.rgpszUsageIdentifier = &x;
-		printf("A list of valid certificates in the MY store follows:\n");
-		do {
-			pCertContext = 
-					CertFindCertificateInStore( hMyStore,
-						X509_ASN_ENCODING,
-						0,
-						//CERT_FIND_ANY,
-						CERT_FIND_ENHKEY_USAGE,
-						&enky,
-						previous );
-			if (pCertContext != NULL) {
-				DWORD dwpara = CERT_X500_NAME_STR;
-				char name[MAX_PATH];
-				DWORD name_size=MAX_PATH;
-				CertGetNameString(
-					pCertContext,
-					CERT_NAME_RDN_TYPE,
-					0,
-					&dwpara,
-					(LPSTR)&name,
-					name_size );
-				printf("%s\n",name);
-				BYTE buf[1024];
-				CERT_BLOB *cn = (CERT_BLOB *)&buf;
-				DWORD bufsize=1024;
-
-				CertStrToName(
-					X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
-					name,
-					CERT_OID_NAME_STR,
-					NULL,
-					buf,
-					&bufsize,
-					NULL);
-
-				test = CertFindCertificateInStore( hMyStore,
-						X509_ASN_ENCODING |PKCS_7_ASN_ENCODING,
-						0,
-						//CERT_FIND_ANY,
-						CERT_FIND_SUBJECT_NAME,
-						cn,
-						NULL);
-				printf("tried to find cert by subject = %lx\n",(void*)test);
-
-				
-
-			}
-			previous = pCertContext;
-
-		} while (pCertContext != NULL);
-	}
-
-}
-
-
-
-void Callback (
-  HINTERNET hInternet,
-  DWORD_PTR dwContext,
-  DWORD dwInternetStatus,
-  LPVOID lpvStatusInformation,
-  DWORD dwStatusInformationLength )
-{
-
-	if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) {
-		DWORD status = * ((DWORD*)lpvStatusInformation);
-		printf("security status = %d\n", status);
-	}
-	return;
-
-}
-
-// return 0 on success
-HRESULT getConfig(char **a_host, int *a_port, char **a_certname)
-{
-	char hostname[MAX_PATH];
-	DWORD hostname_size = MAX_PATH;
-	char port[16];
-	DWORD port_size = 16;
-	char clientcertname[MAX_PATH];
-	DWORD clientcertname_size = MAX_PATH;
-
-	INTERNET_PORT portnum = INTERNET_DEFAULT_HTTPS_PORT;
-	HKEY config;
-
-	HRESULT r;
-
-	r = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-			TEXT("SOFTWARE\\Red Hat\\RHCSProxy\\Config"),
-			0, //options
-			KEY_READ,
-			&config );
-	if (FAILED(r)) return -1;
-
-	HKEY certificateauthorities;
-	 r = RegOpenKeyEx(config,
-			TEXT("CertificateAuthorities"),
-			0, //options
-			KEY_READ,
-			&certificateauthorities );
-	if (FAILED(r)) return -2;
-	
-	CHAR     achKey[MAX_PATH]; 
-	DWORD    achKeySize = MAX_PATH;
-    CHAR     achClass[MAX_PATH] = "";  // buffer for class name 
-    DWORD    cchClassName = MAX_PATH;  // size of class string 
-    DWORD    cSubKeys;                 // number of subkeys 
-    DWORD    cbMaxSubKey;              // longest subkey size 
-    DWORD    cchMaxClass;              // longest class string 
-    DWORD    cValues;              // number of values for key 
-    DWORD    cchMaxValue;          // longest value name 
-    DWORD    cbMaxValueData;       // longest value data 
-    DWORD    cbSecurityDescriptor; // size of security descriptor 
-    FILETIME ftLastWriteTime;      // last write time 
- 
-    DWORD i; 
-    DWORD retCode; 
- 
-#define MAX_VALUE_NAME 1024 
-    DWORD cchValue = MAX_VALUE_NAME; 
-	
-	RegQueryInfoKey(certificateauthorities,        // key handle 
-        achClass,                // buffer for class name 
-        &cchClassName,           // size of class string 
-        NULL,                    // reserved 
-        &cSubKeys,               // number of subkeys 
-        &cbMaxSubKey,            // longest subkey size 
-        &cchMaxClass,            // longest class string 
-        &cValues,                // number of values for this key 
-        &cchMaxValue,            // longest value name 
-        &cbMaxValueData,         // longest value data 
-        &cbSecurityDescriptor,   // security descriptor 
-        &ftLastWriteTime);       // last write time 
-
-
-	for (i = 0, retCode = ERROR_SUCCESS; 
-            retCode == ERROR_SUCCESS; i++) 
-    { 
-		achKeySize = MAX_PATH;
-        retCode = RegEnumKeyEx(certificateauthorities, 
-                     i, 
-                     achKey, 
-                     &achKeySize, 
-                     NULL, 
-                     NULL, 
-                     NULL, 
-                     &ftLastWriteTime);
-
-        if (retCode == (DWORD)ERROR_SUCCESS) 
-        {
-			HKEY cainfo;
-			r = RegOpenKeyEx(certificateauthorities,
-				achKey,
-				0, //options
-				KEY_READ,
-				&cainfo );
-			if (FAILED(r)) return -3;
-
-
-			r = RegQueryValueEx(
-				cainfo,
-				"hostname",
-				NULL,
-				NULL,
-				(LPBYTE)&hostname,
-				&hostname_size );
-
-			if (FAILED(r))  return -4;
-
-			r = RegQueryValueEx(
-				cainfo,
-				"port",
-				NULL,
-				NULL,
-				(LPBYTE)&port,
-				&port_size );
-			portnum = (INTERNET_PORT)atoi(port);
-
-			if (FAILED(r))  return -5;
-
-			RegCloseKey(cainfo);
-
-
-			break;  // just take the first one for now
-        }
-		
-	}
-	RegCloseKey(certificateauthorities);
-
-	r = RegQueryValueEx(
-				config,
-				"AuthenticationCertificate",
-				NULL,
-				NULL,
-				(LPBYTE)&clientcertname,
-				&clientcertname_size );
-
-	if (FAILED(r))  return -6;
-	
-	*a_certname = strdup(clientcertname);
-	*a_host     = strdup(hostname);
-	*a_port     = portnum;
-
-	return 0;
-
-}
-
-
-LONG setClientCertificate(HINTERNET hRequest, char *clientcertname)
-{
-	LONG r=0;
-	HCERTSTORE hMyStore = CertOpenSystemStore( 0, TEXT("MY") );
-	if (hMyStore) {
-		PCCERT_CONTEXT pCertContext =
-			CertFindCertificateInStore( hMyStore, 
-											X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
-											0,
-											CERT_FIND_SUBJECT_STR_A,
-											clientcertname,
-											NULL );
-		if (pCertContext == NULL) {
-			debug("submit: could not find certificate with name %s. Name should be a substring of Certificate Subject Name. E.g. If CN=Red Hat Agent, the value for name could be 'Red Hat' (But not CN=Red Hat)", clientcertname);
-			r = -1;
-			goto loser;
-		}
-
-		WinHttpSetOption(	hRequest,
-						WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
-						(LPVOID) pCertContext,
-						sizeof(CERT_CONTEXT) );
-
-		// WinHttpSetOption will dup the cert, we can free it here.
-		CertFreeCertificateContext( pCertContext );
-	} else {
-		r = -2;
-		goto loser;		
-	}
-loser:
-	return r;
-}
-
-
-LONG readHTTPResponse(HINTERNET hRequest, char **buffer)
-{
-	LONG r=0;
-	int index = 0;
-	int dwDownloaded=0;
-	int dwSize =0;
-	int buffersize = 128000;
-	char *response = (char*)malloc(buffersize);
-	response[0] = 0;
-	
-	do 
-       {
-        // Check for available data.
-		if (!WinHttpQueryDataAvailable( hRequest, (LPDWORD) &dwSize)) {
-			r = -1;
-            goto loser;
-		}
-
-		if (index + dwSize > buffersize) {
-			printf("CA returned too much data.\n");
-			r = -2;
-			goto loser;
-		}
-        if (!WinHttpReadData( hRequest, (LPVOID)&response[index], dwSize, (LPDWORD)&dwDownloaded)) {
-			printf("Error %u in WinHttpReadData.\n", GetLastError());
-			r = -3;
-			goto loser;
-		}
-		else {
-			index += dwDownloaded;
-			response[index] = 0;
-		}
-
-	   } while (dwSize>0);
-
-loser:
-	   if (r) {
-		   free(response);
-		   *buffer = NULL;
-	   } else {
-		   *buffer = response;
-	   }
-	return r;
-}
-
-// modifies 'response'
-// fills in 'cert' with a pointer to the cert returned from the CA
-LONG extractCertFromResponse(char *response, char**c)
-{
-	LONG r=0;
-	char *cert = NULL;
-
-	*c = NULL;
-	printf("Response from CA: %s\n",response);
-	char *beginmarker = "-----BEGIN CERTIFICATE-----";
-	char *begincert = strstr(response,beginmarker);
-	if (begincert == NULL) {
-		r = -1;
-		goto loser;
-	}
-	begincert += strlen(beginmarker);
-	char *endcert   = strstr(begincert,"-----END CERTIFICATE-----");
-	if (endcert == NULL) {
-		r = -2;
-		goto loser;
-	}
-	*endcert =0;
-	cert = begincert;
-	int s,d;
-		
-	for (s=0,d=0; begincert[s]; ) {
-		if (begincert[s] == '\\') {
-			if (begincert[s+1] == 0) { break; }  // malformed input - backslash at end of str
-			s+=2;                                // skip over slash and escaped char
-			continue;
-		}
-		cert[d] = begincert[s];
-		d++;
-		s++;
-	}
-	cert[d] = 0;
-	*c = strdup(cert);
-loser:
-	return r;
-}
-
-// returns 0 on success
-LONG submitRequestToCA(char *certrequest, char **cert)
-
-{
-	LONG r=0;
-
-	char *hostname = NULL;
-	int port = 0;
-	char *clientcertname = NULL;
-	char *response=NULL;
-
-	debug("submit: begin");
-	
-	if (getConfig(&hostname, &port, &clientcertname)) {
-		return r | 0x8C01000;
-	}
-	debug("submit: after getConfig... %s, %d, %s", hostname, port, clientcertname);
-
-	BOOL  bResults = FALSE;
-    HINTERNET hSession = NULL,
-              hConnect = NULL,
-              hRequest = NULL;
-	
-
-	// Find the hostname for the CA by looking in the registry
-
-	USES_CONVERSION;
-
-    // Use WinHttpOpen to obtain a session handle.
-	// We just use the o/s defined proxy settings
-    hSession = WinHttpOpen(  L"Red Hat CS AutoEnrollment Proxy/0.1",  //User Agent
-                             WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
-                             WINHTTP_NO_PROXY_NAME, 
-                             WINHTTP_NO_PROXY_BYPASS, 
-							 0);   // 0= synchronous
-
-    // Specify an HTTP server.
-	if (hSession == NULL) {
-		r = -4;
-		goto loser;
-	}
-	debug("submit: after WinHttpOpen");
-// Install the status callback function.
-	
-    WINHTTP_STATUS_CALLBACK isCallback = WinHttpSetStatusCallback( hSession,
-                                (WINHTTP_STATUS_CALLBACK)Callback,
-//                                WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS |WINHTTP_CALLBACK_FLAG_SECURE_FAILURE,
-                                WINHTTP_CALLBACK_FLAG_SECURE_FAILURE,
-								NULL);
-	
-
-	hConnect = WinHttpConnect( hSession, A2W(hostname),
-                                   port, 0);
-
-    // Create an HTTP Request handle.
-	if (hConnect == NULL) {
-		 r = -5;
-		 goto loser;
-	}
-	debug("submit: after WinHttpConnect");
-
-    hRequest = WinHttpOpenRequest( hConnect, L"POST", L"/ca/ee/ca/profileSubmitSSLClient", 
-                                       NULL, WINHTTP_NO_REFERER, 
-                                       WINHTTP_DEFAULT_ACCEPT_TYPES,
-									   WINHTTP_FLAG_SECURE
-									   );
-
-	// Set SSL Client Certificate to use
-	if (hRequest == NULL)  {
-		r = -6;
-		goto loser;
-	}
-	debug("submit: after WinHttpOpenRequest");
-
-	r = setClientCertificate(hRequest, clientcertname);
-	debug("submit: setClientCertificate returned %lx",r);
-	if (FAILED(r)) { 
-		r |= 0x8C05000;
-		goto loser;
-	}
-	debug("submit: after setClientCertificate");
-
-	char *req = buildRequestString(certrequest);
-	if (req == NULL) {
-		r = -9;
-		goto loser;
-	}
-	debug("submit: after buildRequestString (req length = %d)", strlen(req));
-
-    // Send a Request.
-	if (hRequest) {
-        bResults = WinHttpSendRequest( hRequest, 
-			L"Content-Type: application/x-www-form-urlencoded", -1,
-                                       req, strlen(req), 
-                                       strlen(req), 0);
-		if (!bResults) {
-			r = -7;
-			goto loser;
-		}
-		bResults = WinHttpReceiveResponse(hRequest, NULL);
-		if (!bResults) {
-			r = -8;
-			goto loser;
-		}
-
-	}
-
-
-
-	if (r = readHTTPResponse(hRequest,&response )) {
-		r |= 0x8C03000;
-		goto loser;
-	}
-
-	char *c=NULL;
-	if (response != NULL) {
-		if (r = extractCertFromResponse(response, &c)) {
-			r |= 0x8C04000;
-			goto loser;
-		} else {
-			*cert = c;
-			//printf("returned certificate: %s\n",c);
-		}
-
-	}
-
-	
-
-
-    // Close any open handles.
-loser:
-	if (r) {
-		if ((r & 0x8C000000) == 0x8C000000) {
-			// r was set in one of the subroutines
-		} else {
-			r |= 0x8C02000;   // r was -1, -2, -3, etc...
-		}
-
-		debug("submit: returning r=%lx\n",r);
-
-		if (response) { free(response); }
-		if (cert)     { free(cert); }
-
-		if (hRequest) WinHttpCloseHandle(hRequest);
-	    if (hConnect) WinHttpCloseHandle(hConnect);
-	    if (hSession) WinHttpCloseHandle(hSession);
-
-	}
-	
-	return r;
-}
-
-void test_submit()
-{
-	char *c=NULL;
-	char *req = "-----BEGIN NEW CERTIFICATE REQUEST-----MIIDLzCCApgCAQAwHzEdMBsGA1UEAxMUYmFieXJ1dGguZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKTWQ0muj0iH6oM+ZvYN9mRfgg3I48GR0IOfX78JfLw6eg7BmWS/NFe0x03X7ts5lbDLhYusmavMBlryJ7v6/aZZp9RuEMlb7SV7m3zZGSZBrKZEQhC8ibfsRf31jXKJJkiuYR8XDl+7Txrlu68DSTM3+SoZKEyMG2cQOBHTqW/3AgMBAAGgggHOMBoGCisGAQQBgjcNAgMxDBYKNS4yLjM3OTAuMjBQBgkqhkiG9w0BCQ4xQzBBMB0GA1UdDgQWBBRxbsYJogSaIeyJRok4+lf12vdGLjATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwXgYJKwYBBAGCNxUUMVEwTwIBAQwpc3BhcmtpbnN3aW5kb3dzLnNwYXJraW5zLnNmYmF5LnJlZGhhdC5jb20MFlNQQVJLSU5TXEFkbWluaXN0cmF0b3IMB2NlcnRyZXEwgf0GCisGAQQBgjcNAgIxge4wgesCAQEeWgBNAGkAYwByAG8AcwBvAGYAdAAgAFIAUwBBACAAUwBDAGgAYQBuAG4AZQBsACAAQwByAHkAcAB0AG8AZwByAGEAcABoAGkAYwAgAFAAcgBvAHYAaQBkAGUAcgOBiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA0GCSqGSIb3DQEBBQUAA4GBAIk/LJXtwbQ7JfK!
 7bEqGcx95VL5d74TadVwuORfLLn8kX4bcfIXuMu7beh1ay4RD3vD43i65OA6vTQ9qr6BMQU9tXvbT8gBWRZ0bntNlm53IeEm7Iwc925Fr39A1SYMU6isUauCF9BjPwNaz3uswUjynqd+/BVp8rDLdTzjW35k3-----END NEW CERTIFICATE REQUEST-----";
-	LONG r=0;
-
-	r = submitRequestToCA(req, &c);
-	printf("submit returned error: %lx\n", r);
-}
-
-
-
-#ifdef SUBMIT_MAIN
-
-int APIENTRY WinMain(HINSTANCE i, HINSTANCE p, LPSTR cmdline, int cmdshow)
-{
-
-  test_submit();
-
-  return 0;
-}
-
-void main()
-{
-
-	 test_submit();
-}
-
-#endif
-
-
-
-
-
+/** BEGIN COPYRIGHT BLOCK
+ * END COPYRIGHT BLOCK */
+
+#define _WIN32_DCOM
+
+
+#include <windows.h> 
+#include <winhttp.h>
+#include <WinCrypt.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <comdef.h>
+#include <objbase.h>
+#include <assert.h>
+
+#include <ctype.h>
+
+#include <certcli.h>
+#include <certsrv.h>
+
+#include <atlconv.h>
+#include "csproxy.h"
+
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+using namespace std;
+
+
+
+string urlencode(string s)
+{
+	string r;
+	string h = "0123456789abcdef";
+	const char *before_encoding = s.c_str();
+	for (unsigned int i=0;i<s.length(); i++) {
+		char c = s[i];
+		if ( isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
+			r += c;
+		} else {
+			r += "%" + 	h.substr(((c & 0xf0) >> 4),1) + h.substr(c & 0x0f,1);
+		}
+	}
+	const char *after_encoding = r.c_str();
+	return r;
+}
+
+/*
+ * build a string, given a set of name/value pairs
+ * The caller is responsible for returning the returned string
+ */
+string buildRequestString(requestinfo *r)
+{
+	string s;
+	map<string,string> &httpvars = r->httpvars;
+	for (map<string,string>::iterator i = httpvars.begin();
+		i!= httpvars.end(); ++i) {
+
+			s += urlencode(i->first) + "=" + urlencode(i->second) + "&";
+		}
+	return s;
+}
+
+
+
+
+/* This callback is called when an error is encountered during
+ * the HTTP transaction.
+ * TODO: expand the security status variable to meaningful english
+ */
+
+void Callback (
+  HINTERNET hInternet,
+  DWORD_PTR dwContext,
+  DWORD dwInternetStatus,
+  LPVOID lpvStatusInformation,
+  DWORD dwStatusInformationLength )
+{
+
+	debugt(LOG_D_DETAIL,"callback status type = %lx\n", dwInternetStatus);
+
+	if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) {
+		DWORD status = * ((DWORD*)lpvStatusInformation);
+
+		// Retrieve the application-specific context pointer
+		context *ctx;
+		DWORD ctx_size=sizeof(ctx);
+		WinHttpQueryOption(hInternet, WINHTTP_OPTION_CONTEXT_VALUE,
+			&ctx, &ctx_size );
+
+		string error = "";
+		if (status & 0x01) error += "Certificate Revocation Check Failed. ";
+		if (status & 0x02) error +=	"Invalid Certificate. ";
+		if (status & 0x04) error += "Certificate Revoked. ";
+		if (status & 0x08) error += "Invalid CA. ";
+		if (status & 0x10) error += "Certificate CN (Common Name) invalid. ";
+		if (status & 0x20) error += "Certificate Date Invalid. ";
+		if (status & 0x40) error += "Wrong usage (key usage, extended key usage) for certificate. ";
+
+		char *hostname = "UNKNOWN";
+		DWORD port = 0;
+		if (ctx != NULL) {
+			cainfo *ca = ctx->selectedca;
+			if (ca != NULL) {
+				hostname = ctx->selectedca->host;
+				port = ctx->selectedca->port;
+				ctx->status = 1;
+				ctx->securitystatus = status;
+			}
+		}
+
+		debugt(LOG_D_DETAIL,"Cannot create SSL connection to CA: %s:%d. "
+				"The analysis of the server certificate (and chain) reports: %lx (%s)."
+				"Note: Due to some as yet unidentified issue, this thread will crash, and "
+				"failover will not happen for this request.\n",
+				hostname, port, status, error.c_str());
+	}
+	return;
+
+}
+
+
+
+/*
+ * Set the client certificate to use for this SSL socket.
+ */
+LONG setClientCertificate(HINTERNET hRequest, BYTE *clientcerthash, DWORD clientcerthash_size)
+{
+	debugt(LOG_D_FUNC,"setClientCertificate");
+	LONG r=0;
+	/*
+
+When running as a service, I would prefer for the service to be able to access its
+own certificate/key profile, but it doesn't seem to be able to do that by accessing
+the 'MY' store. 
+
+	BOOL WINAPI CertEnumSystemStore(
+		DWORD dwFlags,
+		void* pvSystemStoreLocationPara,
+		void* pvArg,
+		PFN_CERT_ENUM_SYSTEM_STORE pfnEnum
+		);
+
+Parameters
+dwFlags 
+[in] Specifies the location of the system store. The following flag values are defined. 
+CERT_SYSTEM_STORE_CURRENT_USER 
+CERT_SYSTEM_STORE_CURRENT_SERVICE 
+*/
+
+
+
+	HCERTSTORE hMyStore = CertOpenSystemStore( 0, TEXT("MY") );
+	if (hMyStore) {
+		CERT_ID c;
+		c.dwIdChoice = CERT_ID_SHA1_HASH;
+		c.HashId.cbData = clientcerthash_size;
+		c.HashId.pbData = clientcerthash;
+		PCCERT_CONTEXT pCertContext =
+			CertFindCertificateInStore( hMyStore, 
+											X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+											0,
+											CERT_FIND_CERT_ID,
+											&c,
+											NULL );
+		if (pCertContext == NULL) {
+			debug("submit: could not find certificate with supplied hash.");
+			r = -1;
+			goto loser;
+		}
+
+		WinHttpSetOption(	hRequest,
+						WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
+						(LPVOID) pCertContext,
+						sizeof(CERT_CONTEXT) );
+
+		// WinHttpSetOption will dup the cert, we can free it here.
+		CertFreeCertificateContext( pCertContext );
+	} else {
+		r = -2;
+		goto loser;		
+	}
+loser:
+	return r;
+}
+
+/* Read the response from the socket, and stuff it into a buffer
+ * The buffer is allocated by this function and it's the responsibility
+ * of the caller to free it.
+ */
+LONG readHTTPResponse(HINTERNET hRequest, string &s)
+{
+	debugt(LOG_D_FUNC,"readHTTPResponse");
+	LONG r=0;
+	int index = 0;
+	int dwDownloaded=0;
+	int dwSize =0;
+	int buffersize = 100000;
+	char *response = (char*)malloc(buffersize);
+	response[0] = 0;
+	
+	do 
+       {
+        // Check for available data.
+		if (!WinHttpQueryDataAvailable( hRequest, (LPDWORD) &dwSize)) {
+			r = -1;
+            goto loser;
+		}
+		debugt(LOG_D_DETAIL,"readHttpresponse2");
+		if (index + dwSize > buffersize) {
+			debugt(LOG_D_DETAIL,"CA returned too much data.");
+			r = -2;
+			goto loser;
+		}
+		debugt(LOG_D_DETAIL,"readHttpresponse3");
+        if (!WinHttpReadData( hRequest, (LPVOID)&response[index], dwSize, (LPDWORD)&dwDownloaded)) {
+			debugt(LOG_D_DETAIL,"Error %u in WinHttpReadData.\n", GetLastError());
+			r = -3;
+			goto loser;
+		}
+		else {
+			index += dwDownloaded;
+			response[index] = 0;
+		}
+	   } while (dwSize>0);
+
+loser:
+	   if (r) {
+		   s = "";
+		   debugt(LOG_D_DETAIL,"readHttpresponse: returned empty string");
+	   } else {
+		   s = response;
+		   debugt(LOG_D_DETAIL,"readHttpresponse: returned string len:%d",strlen(response));
+	   }
+   free(response);
+		   
+	return r;
+}
+
+
+/* Get one line of data at a time
+ * This function will modify not only the content of the char array
+ * pointed to by *start, by replacing newlines with NULs, but also
+ * modify *start itself, making it advance to the position after the
+ * newline. This function can then be called once more to get the next
+ * line.
+ * Returns a pointer to a NUL terminated string - one line at a time.
+ * This function doesn't allocate any extra buffer, so the caller
+ * should not free the pointer it returns.
+ */
+ 
+
+char *readline(char **start)
+{
+	if (**start == 0) {
+		return NULL;
+	}
+	char *r = *start;
+	int i=0;
+	for (i=0;; i++) {
+		if ((*start)[i] == 0) {     // this is the case where response terminates with
+			*start = (*start) + i;  // no newline.  the next pass will return a null
+			break;
+		}
+		if ((*start)[i] == '\n' ) {
+			(*start)[i] = 0;           
+			*start = (*start) + i +1;  // skip over null
+			break;
+		}
+	}
+	return r;
+}
+
+
+/* 
+ * The interesting part of the response from the CA is a series
+ * of var x = "YYYY"; statements.
+ * This function returns the 'YYYY' part.
+ */
+string getvalue(string s)
+{
+	size_t beginquote = s.find("\"");
+	size_t endquote = s.find("\"",beginquote+1);
+	return s.substr(beginquote+1,endquote-beginquote-1);
+}
+
+/*
+ * Remove the PEM headers so that just the base-64 cert is inside
+ */
+void removePEM(string &s)
+{
+	string BEGINMARKER("-----BEGIN CERTIFICATE-----");
+	string ENDMARKER("-----END CERTIFICATE-----");
+
+	size_t end_of_beginmarker = BEGINMARKER.length();
+	size_t start_of_endmarker = s.find(ENDMARKER);
+
+	if (start_of_endmarker == string.npos) start_of_endmarker = 0;
+
+	s = s.substr(end_of_beginmarker, start_of_endmarker-end_of_beginmarker);
+
+}
+
+/*
+ * Remove any newlines  (which are represented as \r or \n)
+ */
+
+void removenewlines(string &s)
+{
+	string r;
+	int escaping=0;
+
+	size_t j = s.length();
+	for (size_t i=0; i<j; i++) {
+		char c = s[i];
+		if (escaping) {
+			escaping = 0;
+			continue;
+		}
+		if (c == '\\') {
+			escaping = 1;
+			continue;
+		}
+		r.push_back(c);
+	}
+	s = r;
+}
+
+
+// modifies 'response'
+// fills in 'cert' with a pointer to the cert returned from the CA
+LONG context::extractCertFromResponse(string &respX, 
+							 string &cert_out,
+							 string &p7_out)
+{
+	debugt(LOG_D_FUNC,"extractCertFromResponse");
+	LONG r=0;
+
+#define MODE_READING_NONE  0
+#define MODE_READING_CERT  1
+#define MODE_READING_PKCS7 2
+	int count=0;
+
+	string resp(respX);
+	istringstream stream(resp);
+	string line;
+
+	int mode=MODE_READING_NONE;    
+
+	while (getline(stream,line) ) {
+		if (count++ < 45) {
+			debugt(LOG_D_DETAIL,"line %d: %s",count,line.c_str());
+		}
+		if (line.find("outputList.outputVal=\"") != string.npos) {
+			
+			if (mode == MODE_READING_CERT) {
+				debugt(LOG_D_DETAIL,"reading value for CERT");
+				mode = MODE_READING_NONE;
+				string s = getvalue(line);
+				debug("value for certificate = %s",s.c_str());
+				removePEM(s);
+				removenewlines(s);
+				cert_out = s;
+			}
+			if (mode == MODE_READING_PKCS7) {
+				debugt(LOG_D_DETAIL,"reading value for CERTCHAIN");
+				mode = MODE_READING_NONE;
+				string s = getvalue(line);
+				removenewlines(s);
+				p7_out = s;
+				
+			}
+		}
+		
+		if (line.find("outputList.outputId=\"b64_cert\"") != string.npos) {
+			debugt(LOG_D_DETAIL,"saw cert in response");
+			mode = MODE_READING_CERT;
+		}
+		if (line.find("outputList.outputId=\"pkcs7\"") != string.npos) {
+			debugt(LOG_D_DETAIL,"saw certchain in response");
+			mode = MODE_READING_PKCS7;
+		}
+		if (line.find("</script>") != string.npos) {
+			goto loser;
+		}
+		if (line.find("errorReason") != string.npos) {
+			string s = getvalue(line);
+			debugt(LOG_D_DETAIL,"errorReason checking: error value = %s", s.c_str());
+			if (s != "") {
+				debugt(LOG_D_DETAIL,"CA %s:%d returned the following error: %s",
+					selectedca->host, selectedca->port, s.c_str()
+					);
+				errors.push_back( string("CA reported: ") + s );
+				if (s == "Authentication Error") {
+					fatalerror = 1;
+				}
+				r=1;
+				goto loser;
+			}
+		}
+	}
+loser:
+	return r;
+}
+
+// returns 0 on success
+LONG context::submitRequestToCA(string &cert, string& certchain)
+{
+	LONG r=0;
+	string req;
+	
+	char *c=NULL;
+	char *cchain=NULL;
+	
+	debugt(LOG_D_FUNC,"submitRequestToCA");
+	
+	BOOL  bResults = FALSE;
+    HINTERNET hSession = NULL,
+              hConnect = NULL,
+              hRequest = NULL;
+
+	USES_CONVERSION;
+
+    // Use WinHttpOpen to obtain a session handle.
+	// We just use the o/s defined proxy settings
+    hSession = WinHttpOpen(  L"Red Hat CS Auto Enrollment Proxy/0.9.1",  //User Agent
+                             WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
+                             WINHTTP_NO_PROXY_NAME, 
+                             WINHTTP_NO_PROXY_BYPASS, 
+							 0);   // 0= synchronous
+
+    // Specify an HTTP server.
+	if (hSession == NULL) {
+		r = 4;
+		goto loser;
+	}
+	debugt(LOG_D_DETAIL,"submit: after WinHttpOpen");
+    
+	hConnect = WinHttpConnect( hSession, A2W(selectedca->host),
+								(INTERNET_PORT)selectedca->port, 0);
+
+    // Create an HTTP Request handle.
+	if (hConnect == NULL) {
+		 r = 5;
+		 goto loser;
+	}
+	debug("submit: after WinHttpConnect");
+
+	
+	wchar_t *url = L"/ca/profileSubmitSSLClient";
+	
+	if ( (selectedca->catype == CATYPE_REDHAT_72) ||
+		 (selectedca->catype == CATYPE_REDHAT_73)     ) {
+		url = L"/ca/ee/ca/profileSubmitSSLClient";
+	}
+	
+
+    hRequest = WinHttpOpenRequest( hConnect, L"POST", url, 
+                                       NULL, WINHTTP_NO_REFERER, 
+                                       WINHTTP_DEFAULT_ACCEPT_TYPES,
+									   WINHTTP_FLAG_SECURE
+									   );
+
+	// Set SSL Client Certificate to use
+	if (hRequest == NULL)  {
+		r = 6;
+		goto loser;
+	}
+	debug("submit: after WinHttpOpenRequest");
+
+	r = setClientCertificate(hRequest, config->certhash, config->certhash_size);
+	debug("submit: setClientCertificate returned %lx",r);
+	if (FAILED(r)) { 
+		r = (r &0xffff) | 0x8C050000;
+		goto loser;
+	}
+	debug("submit: after setClientCertificate");
+
+	req = buildRequestString(request);
+	if (req.length() == 0) {
+		r = 7;
+		goto loser;
+	}
+	debug("submit: after buildRequestString (req length = %d)", req.length());
+
+	//WinHttpSetOption(hSession, WINHTTP_OPTION_CONTEXT_VALUE, ctx, sizeof(ctx) );
+	
+	
+	WINHTTP_STATUS_CALLBACK isCallback = WinHttpSetStatusCallback( hRequest,
+                                (WINHTTP_STATUS_CALLBACK)Callback,
+                                WINHTTP_CALLBACK_FLAG_SECURE_FAILURE,
+								NULL);
+								
+
+    // Send a Request.
+	if (hRequest) {
+		const char *req_c = req.c_str();
+
+        bResults = WinHttpSendRequest(
+			hRequest,               //   HINTERNET hRequest,
+			L"Content-Type: application/x-www-form-urlencoded\r\n",
+			-1,                     //    DWORD dwHeadersLength,
+			(void*)req_c,           //    LPVOID lpOptional (HTTP POST data)
+			(DWORD)strlen(req_c),   //  DWORD dwOptionalLength,
+            (DWORD)strlen(req_c),   //  DWORD dwTotalLength,
+			0);  // context pointer
+
+		if (!bResults) {
+			r = GetLastError();
+			r = (r &0xffff) | 0x8C060000;
+			goto loser;
+		}
+		bResults = WinHttpReceiveResponse(hRequest, NULL);
+		if (!bResults) {
+			r = GetLastError();
+			r = 9;
+			goto loser;
+		}
+	}
+
+	{
+		string response="";
+
+		if (r = readHTTPResponse(hRequest, response )) {
+			r = (r &0xffff) | 0x8C030000;
+			goto loser;
+		}
+		debug("readHTTPResponse returned %d",r);
+
+		if (response.length() > 100) { 
+			char *end=NULL;
+			if (r = extractCertFromResponse(response, cert, certchain)) {
+				debug("extractCertFromResponse returned %d",r);
+				r = (r &0xffff) | 0x8C040000;
+				goto loser;
+			}
+		}
+	}
+
+    // Close any open handles.
+loser:
+	if (r) {
+		if ((r & 0xFF000000) == 0x8C000000) {
+			// r was set in one of the subroutines
+			debug("submit: r was set in subr: r=%lx",r);
+		} else {
+			debug("submit: r: r=%d",r);
+			
+			r = (r &0xffff) | 0x8C020000;   // r was -1, -2, -3, etc...
+		}
+
+		debug("submit: returning r=%lx",r);
+
+	}
+
+	debug("submit: 1");
+
+	if (hRequest) WinHttpCloseHandle(hRequest);
+
+	if (hConnect) WinHttpCloseHandle(hConnect);
+
+	if (hSession) WinHttpCloseHandle(hSession);
+	
+	debug("submit: returning\n");
+	return r;
+}
+
+void test_submit()
+{
+	char *c=NULL;
+	char *req = "-----BEGIN NEW CERTIFICATE REQUEST-----MIIDLzCCApgCAQAwHzEdMBsGA1UEAxMUYmFieXJ1dGguZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKTWQ0muj0iH6oM+ZvYN9mRfgg3I48GR0IOfX78JfLw6eg7BmWS/NFe0x03X7ts5lbDLhYusmavMBlryJ7v6/aZZp9RuEMlb7SV7m3zZGSZBrKZEQhC8ibfsRf31jXKJJkiuYR8XDl+7Txrlu68DSTM3+SoZKEyMG2cQOBHTqW/3AgMBAAGgggHOMBoGCisGAQQBgjcNAgMxDBYKNS4yLjM3OTAuMjBQBgkqhkiG9w0BCQ4xQzBBMB0GA1UdDgQWBBRxbsYJogSaIeyJRok4+lf12vdGLjATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwXgYJKwYBBAGCNxUUMVEwTwIBAQwpc3BhcmtpbnN3aW5kb3dzLnNwYXJraW5zLnNmYmF5LnJlZGhhdC5jb20MFlNQQVJLSU5TXEFkbWluaXN0cmF0b3IMB2NlcnRyZXEwgf0GCisGAQQBgjcNAgIxge4wgesCAQEeWgBNAGkAYwByAG8AcwBvAGYAdAAgAFIAUwBBACAAUwBDAGgAYQBuAG4AZQBsACAAQwByAHkAcAB0AG8AZwByAGEAcABoAGkAYwAgAFAAcgBvAHYAaQBkAGUAcgOBiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA0GCSqGSIb3DQEBBQUAA4GBAIk/LJXtwbQ7JfK!
 7bEqGcx95VL5d74TadVwuORfLLn8kX4bcfIXuMu7beh1ay4RD3vD43i65OA6vTQ9qr6BMQU9tXvbT8gBWRZ0bntNlm53IeEm7Iwc925Fr39A1SYMU6isUauCF9BjPwNaz3uswUjynqd+/BVp8rDLdTzjW35k3-----END NEW CERTIFICATE REQUEST-----";
+	LONG r=0;
+
+//	r = submitRequestToCA(req, &c, NULL,NULL,NULL);   // this will break - must pass in vars as 4th arg
+	printf("submit returned error: %lx\n", r);
+}
+
+
+
+void testmain()
+{
+
+	 test_submit();
+}
+
+
+




More information about the Fedora-directory-commits mailing list