4.1.2 Pluggable Authentication Scenario with Consent Message Returned
The RDG client obtains the name of a RDG server by using an out-of-band mechanism. The RDG client also obtains the cookie required for authenticating the user on the server by an out-of-band mechanism. The RDG client establishes a binding handle (a binding handle is specified in [C706] section 2.1) to the RDG server at the well-known endpoint of 443 and 3388. The RDG client then calls the TsProxyCreateTunnel method to create and obtain the tunnel context handle. Note that at this point in time, the connection is unauthenticated. The RDG server then authenticates the user using the cookie that is passed in. As part of this call, the client sends current version capabilities to the server.
The rest of the call flow is identical to what is specified in section 4.1.1.
For example, the client calls the TsProxyCreateTunnel method on a server named "fourthcoffee.example.com". The cookie content "Test" is used for authenticating the user. The Consent Message "Accept" is returned.
Example for the TsProxyCreateTunnel method:
-
HRESULT = {to be filled in by server} TsProxyCreateTunnel( [in, ref] PTSG_PACKET TSGPacket; [out, ref] PTSG_PACKET* TSGPacketResponse = {to be filled in by server}; [out] PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext = {to be filled in by server, and saved as m_tunnelcontext by client}; [out] unsigned long* tunnelid = {to be filled in by server and saved as m_tunnelid by client}; );
Where TSG_PACKET is set as follows.
-
typedef struct _TSG_PACKET { unsigned long packetId = TSG_PACKET_TYPE_AUTH; TSG_PACKET_TYPE_UNION TSGPacket {= packetAuth}; } TSG_PACKET;
Where TSG_PACKET_AUTH is filled in as follows.
-
typedef struct _TSG_PACKET_AUTH { TSG_PACKET_VERSIONCAPS TSGVersionCaps; [range(0, 65536)]unsigned long cookieLen = 4; [size_is(cookieLen)]byte* cookie = "Test"; } TSG_PACKET_AUTH;
Where TSG_PACKET_VERSIONCAPS is filled in as follows.
-
typedef struct _TSG_PACKET_VERSIONCAPS { TSG_PACKET_HEADER TSGHeader { ComponentId = 0x5452; PacketId = TSG_PACKET_TYPE_VERSIONCAPS; } PTSG_PACKET_CAPABILITIES TSGCapTSGCaps { capabilityType = 1; TSGPacket.TSGCapNap = {1}; } unsigned long numCapabilities = 1; unsigned short majorVersion = 1; unsigned short minorVersion = 1; unsigned short quarantineCapabilities = 0; } TSG_PACKET_VERSIONCAPS;
The RDG server receives this method and returns the following.
-
HRESULT = S_OK TsProxyCreateTunnel( [in, ref] PTSG_PACKET TSGPacket = {unchanged}; [out, ref] PTSG_PACKET* TSGPacketResponse = = {filled in as shown below}; [out] PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext = pContextHandleObject; [out] unsigned long* tunnelId = 1; );
Where TSG_PACKET_RESPONSE is set as follows.
-
typedef struct _TSG_PACKET { unsigned long packetId = TSG_PACKET_TYPE_CAPS_RESPONSE; TSG_PACKET_TYPE_UNION TSGPacket {= packetCapsResponse}; } TSG_PACKET;
Where the TSG_PACKET_CAPS_RESPONSE is set as follows.
-
typedef struct _TSG_PACKET_CAPS_RESPONSE { TSG_PACKET_QUARENC_RESPONSE pktQuarEncResponse; TSG_PACKET_MSG_RESPONSE pktConsentMessage; } TSG_PACKET_CAPS_RESPONSE;
Where the TSG_PACKET_QUARENC_RESPONSE is set as follows.
-
typedef struct _TSG_PACKET_QUARENC_RESPONSE { unsigned long flags = 0; unsigned long certChainLen = 0; wchar_t* certChainData = ""; GUID nonce = CreateGuid(); PTSG_PACKET_VERSIONCAPS versionCaps { TSG_PACKET_HEADER TSGHeader { ComponentId = 0x5452; PacketId = TSG_PACKET_TYPE_VERSIONCAPS; } PTSG_PACKET_CAPABILITIES TSGCapTSGCaps { capabilityType = 1; TSGPacket.TSGCapNap = {1}; } unsigned long numCapabilities = 1; unsigned short majorVersion = 1; unsigned short minorVersion = 1; unsigned short quarantineCapabilities = 0; } } TSG_PACKET_QUARENC_RESPONSE;
Where the TSG_PACKET_MSG_RESPONSE is set as follows.
-
typedef struct _TSG_PACKET_MSG_RESPONSE { unsigned long msgID = 1; unsigned long msgType = TSG_ASYNC_MESSAGE_CONSENT_MESSAGE = 1; long isMsgPresent = 1; [switch_is(msgType)] TSG_PACKET_TYPE_MESSAGE_UNION messagePacket; } TSG_PACKET_MSG_RESPONSE;
Where the msgPacket is set as follows.
-
typedef [switch_type(unsigned long)] union { [case (TSG_ASYNC_MESSAGE_CONSENT_MESSAGE)] PTSG_PACKET_STRING_MESSAGE consentMessage; [case (TSG_ASYNC_MESSAGE_SERVICE_MESSAGE)] PTSG_PACKET_STRING_MESSAGE serviceMessage; [case (TSG_ASYNC_MESSAGE_REAUTH)] PTSG_PACKET_REAUTH_MESSAGE reauthMessage; } TSG_PACKET_TYPE_MESSAGE_UNION;
Where the consentMessage is set as follows.
-
typedef struct _TSG_PACKET_STRING_MESSAGE { long isDisplayMandatory = 1; long isConsentMandatory = 1; [range(0, 65536)] unsigned long msgBytes = 7; [size_is(msgBytes)] wchar_t* msgBuffer = "Accept"; } TSG_PACKET_STRING_MESSAGE;