[1/4] rpcrt4: Add support for session cookies.

Hans Leidekker hans at codeweavers.com
Wed Aug 28 02:49:34 CDT 2013


---
 dlls/rpcrt4/rpc_assoc.c     |    4 ++--
 dlls/rpcrt4/rpc_assoc.h     |    4 +++-
 dlls/rpcrt4/rpc_binding.c   |   27 +++++++++++++++++++++--
 dlls/rpcrt4/rpc_binding.h   |    6 +++++-
 dlls/rpcrt4/rpc_transport.c |   50 +++++++++++++++++++++++++++++++++++--------
 5 files changed, 76 insertions(+), 15 deletions(-)

diff --git a/dlls/rpcrt4/rpc_assoc.c b/dlls/rpcrt4/rpc_assoc.c
index 8cf2947..2bbd821 100644
--- a/dlls/rpcrt4/rpc_assoc.c
+++ b/dlls/rpcrt4/rpc_assoc.c
@@ -389,7 +389,7 @@ static RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc,
 RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
                                         const RPC_SYNTAX_IDENTIFIER *InterfaceId,
                                         const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo,
-                                        RpcQualityOfService *QOS, RpcConnection **Connection)
+                                        RpcQualityOfService *QOS, LPCWSTR CookieAuth, RpcConnection **Connection)
 {
     RpcConnection *NewConnection;
     RPC_STATUS status;
@@ -402,7 +402,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
     status = RPCRT4_CreateConnection(&NewConnection, FALSE /* is this a server connection? */,
         assoc->Protseq, assoc->NetworkAddr,
         assoc->Endpoint, assoc->NetworkOptions,
-        AuthInfo, QOS);
+        AuthInfo, QOS, CookieAuth);
     if (status != RPC_S_OK)
         return status;
 
diff --git a/dlls/rpcrt4/rpc_assoc.h b/dlls/rpcrt4/rpc_assoc.h
index f8df62d..3d9b612 100644
--- a/dlls/rpcrt4/rpc_assoc.h
+++ b/dlls/rpcrt4/rpc_assoc.h
@@ -47,7 +47,9 @@ typedef struct _RpcAssoc
 } RpcAssoc;
 
 RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc) DECLSPEC_HIDDEN;
-RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection) DECLSPEC_HIDDEN;
+RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId,
+    const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS,
+    LPCWSTR CookieAuth, RpcConnection **Connection) DECLSPEC_HIDDEN;
 void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) DECLSPEC_HIDDEN;
 ULONG RpcAssoc_Release(RpcAssoc *assoc) DECLSPEC_HIDDEN;
 RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, ULONG assoc_gid, RpcAssoc **assoc_out) DECLSPEC_HIDDEN;
diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c
index 5b49643..a6cfb6a 100644
--- a/dlls/rpcrt4/rpc_binding.c
+++ b/dlls/rpcrt4/rpc_binding.c
@@ -263,6 +263,7 @@ RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
   RPCRT4_strfree(Binding->NetworkAddr);
   RPCRT4_strfree(Binding->Protseq);
   HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
+  HeapFree(GetProcessHeap(), 0, Binding->CookieAuth);
   if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
   if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
   HeapFree(GetProcessHeap(), 0, Binding);
@@ -277,7 +278,7 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
 
   if (!Binding->server) {
      return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId,
-         TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection);
+         TransferSyntax, Binding->AuthInfo, Binding->QOS, Binding->CookieAuth, Connection);
   } else {
     /* we already have a connection with acceptable binding, so use it */
     if (Binding->FromConn) {
@@ -1002,6 +1003,7 @@ RPC_STATUS RPC_ENTRY RpcBindingCopy(
   DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
   DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
   DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
+  DestBinding->CookieAuth = RPCRT4_strdupW(SrcBinding->CookieAuth);
   if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
   DestBinding->Assoc = SrcBinding->Assoc;
 
@@ -1923,6 +1925,27 @@ RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, UL
  */
 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue)
 {
-    FIXME("(%p, %d, %ld): stub\n", BindingHandle, Option, OptionValue);
+    TRACE("(%p, %d, %ld)\n", BindingHandle, Option, OptionValue);
+
+    switch (Option)
+    {
+    case RPC_C_OPT_COOKIE_AUTH:
+    {
+        RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR *cookie = (RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR *)OptionValue;
+        RpcBinding *binding = BindingHandle;
+        int len = MultiByteToWideChar(CP_ACP, 0, cookie->Buffer, cookie->BufferSize, NULL, 0);
+        WCHAR *str;
+
+        if (!(str = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)))) return ERROR_OUTOFMEMORY;
+        MultiByteToWideChar(CP_ACP, 0, cookie->Buffer, cookie->BufferSize, str, len);
+        str[len] = 0;
+        HeapFree(GetProcessHeap(), 0, binding->CookieAuth);
+        binding->CookieAuth = str;
+        break;
+    }
+    default:
+        FIXME("option %u not supported\n", Option);
+        break;
+    }
     return RPC_S_OK;
 }
diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h
index 21c962d..7b8eaf3 100644
--- a/dlls/rpcrt4/rpc_binding.h
+++ b/dlls/rpcrt4/rpc_binding.h
@@ -78,6 +78,7 @@ typedef struct _RpcConnection
   ULONG encryption_auth_len;
   ULONG signature_auth_len;
   RpcQualityOfService *QOS;
+  LPWSTR CookieAuth;
 
   /* client-only */
   struct list conn_pool_entry;
@@ -134,6 +135,7 @@ typedef struct _RpcBinding
   /* authentication */
   RpcAuthInfo *AuthInfo;
   RpcQualityOfService *QOS;
+  LPWSTR CookieAuth;
 } RpcBinding;
 
 LPSTR RPCRT4_strndupA(LPCSTR src, INT len) DECLSPEC_HIDDEN;
@@ -153,7 +155,9 @@ ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos) DECLSPEC_HIDDEN;
 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos) DECLSPEC_HIDDEN;
 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2) DECLSPEC_HIDDEN;
 
-RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) DECLSPEC_HIDDEN;
+RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq,
+    LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo,
+    RpcQualityOfService *QOS, LPCWSTR CookieAuth) DECLSPEC_HIDDEN;
 RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn ) DECLSPEC_HIDDEN;
 RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN;
 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection) DECLSPEC_HIDDEN;
diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c
index e7f10ab..00d03e4 100644
--- a/dlls/rpcrt4/rpc_transport.c
+++ b/dlls/rpcrt4/rpc_transport.c
@@ -284,7 +284,7 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq
   }
 
   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
-                              endpoint, NULL, NULL, NULL);
+                              endpoint, NULL, NULL, NULL, NULL);
   if (r != RPC_S_OK)
       return r;
 
@@ -342,7 +342,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protse
   }
 
   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
-                              endpoint, NULL, NULL, NULL);
+                              endpoint, NULL, NULL, NULL, NULL);
   if (r != RPC_S_OK)
     return r;
 
@@ -1363,7 +1363,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
 
         create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
                                                 protseq->Protseq, NULL,
-                                                service, NULL, NULL, NULL);
+                                                service, NULL, NULL, NULL, NULL);
         if (create_status != RPC_S_OK)
         {
             closesocket(sock);
@@ -2447,6 +2447,30 @@ static RPC_STATUS insert_authorization_header(HINTERNET request, RpcQualityOfSer
     return status;
 }
 
+static RPC_STATUS insert_cookie_header(HINTERNET request, const WCHAR *value)
+{
+    static const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '};
+    WCHAR *header, *ptr;
+    int len;
+    RPC_STATUS status = RPC_S_SERVER_UNAVAILABLE;
+
+    if (!value) return RPC_S_OK;
+
+    len = strlenW(value);
+    if ((header = HeapAlloc(GetProcessHeap(), 0, sizeof(cookieW) + (len + 3) * sizeof(WCHAR))))
+    {
+        memcpy(header, cookieW, sizeof(cookieW));
+        ptr = header + sizeof(cookieW) / sizeof(cookieW[0]);
+        memcpy(ptr, value, len * sizeof(WCHAR));
+        ptr[len++] = '\r';
+        ptr[len++] = '\n';
+        ptr[len] = 0;
+        if ((HttpAddRequestHeadersW(request, header, -1, HTTP_ADDREQ_FLAG_ADD_IF_NEW))) status = RPC_S_OK;
+        HeapFree(GetProcessHeap(), 0, header);
+    }
+    return status;
+}
+
 static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
 {
     RpcConnection_http *httpc = (RpcConnection_http *)Connection;
@@ -2511,6 +2535,10 @@ static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
     if (status != RPC_S_OK)
         return status;
 
+    status = insert_cookie_header(httpc->in_request, Connection->CookieAuth);
+    if (status != RPC_S_OK)
+        return status;
+
     httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, wszAcceptTypes,
                                           flags, (DWORD_PTR)httpc->async_data);
     HeapFree(GetProcessHeap(), 0, url);
@@ -2523,6 +2551,10 @@ static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
     if (status != RPC_S_OK)
         return status;
 
+    status = insert_cookie_header(httpc->out_request, Connection->CookieAuth);
+    if (status != RPC_S_OK)
+        return status;
+
     status = rpcrt4_http_prepare_in_pipe(httpc->in_request,
                                          httpc->async_data,
                                          httpc->cancel_event,
@@ -3001,7 +3033,7 @@ RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
 
 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
     LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
-    LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS)
+    LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS, LPCWSTR CookieAuth)
 {
   static LONG next_id;
   const struct connection_ops *ops;
@@ -3023,6 +3055,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
   NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
   NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
   NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
+  NewConnection->CookieAuth = RPCRT4_strdupW(CookieAuth);
   NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
   memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface));
   NewConnection->NextCallId = 1;
@@ -3051,11 +3084,9 @@ static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnecti
 {
   RPC_STATUS err;
 
-  err = RPCRT4_CreateConnection(Connection, OldConnection->server,
-                                rpcrt4_conn_get_name(OldConnection),
-                                OldConnection->NetworkAddr,
-                                OldConnection->Endpoint, NULL,
-                                OldConnection->AuthInfo, OldConnection->QOS);
+  err = RPCRT4_CreateConnection(Connection, OldConnection->server, rpcrt4_conn_get_name(OldConnection),
+                                OldConnection->NetworkAddr, OldConnection->Endpoint, NULL,
+                                OldConnection->AuthInfo, OldConnection->QOS, OldConnection->CookieAuth);
   if (err == RPC_S_OK)
     rpcrt4_conn_handoff(OldConnection, *Connection);
   return err;
@@ -3077,6 +3108,7 @@ RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection)
   RPCRT4_strfree(Connection->Endpoint);
   RPCRT4_strfree(Connection->NetworkAddr);
   HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
+  HeapFree(GetProcessHeap(), 0, Connection->CookieAuth);
   if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
   if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
 
-- 
1.7.10.4







More information about the wine-patches mailing list