rpcrt4: Implemented NTLM authentication for rpcrt4 connections.

oldstable
Mike McCormack 2006-05-15 23:04:25 +09:00 committed by Alexandre Julliard
parent f20cfdfa84
commit 336e67e2d1
4 changed files with 193 additions and 9 deletions

View File

@ -5,7 +5,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = rpcrt4.dll
IMPORTLIB = librpcrt4.$(IMPLIBEXT)
IMPORTS = iphlpapi advapi32 kernel32 ntdll
IMPORTS = secur32 iphlpapi advapi32 kernel32 ntdll
EXTRALIBS = -luuid
C_SRCS = \

View File

@ -981,9 +981,45 @@ RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, unsigned char *ServerPrinc
RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
RPC_SECURITY_QOS *SecurityQos )
{
FIXME("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
return RPC_S_OK;
RpcBinding* bind = (RpcBinding*)Binding;
RPC_STATUS r;
TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
if (!AuthIdentity)
return RPC_S_INVALID_AUTH_IDENTITY;
if (AuthnLevel != RPC_C_AUTHN_LEVEL_CONNECT)
{
FIXME("unsupported AuthnLevel %lu\n", AuthnLevel);
return RPC_S_UNKNOWN_AUTHN_LEVEL;
}
if (AuthnSvc != RPC_C_AUTHN_WINNT)
{
FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
return RPC_S_UNKNOWN_AUTHN_SERVICE;
}
if (AuthzSvr)
{
FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
return RPC_S_UNKNOWN_AUTHZ_SERVICE;
}
if (SecurityQos)
FIXME("SecurityQos ignored\n");
r = AcquireCredentialsHandleA(NULL, "NTLM", SECPKG_CRED_OUTBOUND, NULL,
AuthIdentity, NULL, NULL, &bind->cred, &bind->exp);
if (r == ERROR_SUCCESS)
{
bind->AuthnSvc = AuthnSvc;
bind->AuthnLevel = AuthnLevel;
}
TRACE("AcquireCredentialsHandleA returned %08lx\n", r);
return r;
}
/***********************************************************************

View File

@ -22,6 +22,7 @@
#define __WINE_RPC_BINDING_H
#include "wine/rpcss_shared.h"
#include "security.h"
struct protseq_ops;
@ -36,6 +37,11 @@ typedef struct _RpcConnection
USHORT MaxTransmissionSize;
/* The active interface bound to server. */
RPC_SYNTAX_IDENTIFIER ActiveInterface;
/* authentication */
CtxtHandle ctx;
TimeStamp exp;
ULONG attr;
} RpcConnection;
struct protseq_ops {
@ -62,6 +68,12 @@ typedef struct _RpcBinding
RPC_BLOCKING_FN BlockingFn;
ULONG ServerTid;
RpcConnection* FromConn;
/* authentication */
unsigned long AuthnLevel;
unsigned long AuthnSvc;
CredHandle cred;
TimeStamp exp;
} RpcBinding;
LPSTR RPCRT4_strndupA(LPCSTR src, INT len);

View File

@ -173,6 +173,22 @@ RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation,
return header;
}
RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation)
{
RpcPktHdr *header;
header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(header->common) + 12);
if (header == NULL)
return NULL;
RPCRT4_BuildCommonHeader(header, PKT_AUTH3, DataRepresentation);
header->common.frag_len = 0x14;
header->common.auth_len = 0;
return header;
}
RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation,
unsigned char RpcVersion,
unsigned char RpcVersionMinor)
@ -279,13 +295,12 @@ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header,
memcpy(pkt + hdr_size, buffer_pos, Header->common.frag_len - hdr_size - alen);
/* add the authorization info */
if (AuthLength)
if (Connection->Used && AuthLength)
{
auth_hdr = &pkt[Header->common.frag_len - alen];
/* FIXME: is this per fragment or per message? */
auth_hdr[0] = RPC_C_AUTHN_WINNT;
auth_hdr[1] = RPC_C_AUTHN_LEVEL_CONNECT;
auth_hdr[0] = Connection->Used->AuthnSvc;
auth_hdr[1] = Connection->Used->AuthnLevel;
auth_hdr[2] = 0x00; /* FIXME: add padding */
auth_hdr[3] = 0x00;
@ -310,6 +325,87 @@ write:
return RPC_S_OK;
}
/***********************************************************************
* RPCRT4_AuthNegotiate (internal)
*/
static void RPCRT4_AuthNegotiate(RpcConnection *conn, SecBuffer *out)
{
SECURITY_STATUS r;
SecBufferDesc out_desc;
unsigned char *buffer;
RpcBinding *bind = conn->Used;
buffer = HeapAlloc(GetProcessHeap(), 0, 0x100);
out->BufferType = SECBUFFER_TOKEN;
out->cbBuffer = 0x100;
out->pvBuffer = buffer;
out_desc.ulVersion = 0;
out_desc.cBuffers = 1;
out_desc.pBuffers = out;
conn->attr = 0;
conn->ctx.dwLower = 0;
conn->ctx.dwUpper = 0;
r = InitializeSecurityContextA(&bind->cred, NULL, NULL,
ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | ISC_REQ_MUTUAL_AUTH |
ISC_REQ_DELEGATE, 0, SECURITY_NETWORK_DREP,
NULL, 0, &conn->ctx, &out_desc, &conn->attr, &bind->exp);
TRACE("r = %08lx cbBuffer = %ld attr = %08lx\n", r, out->cbBuffer, conn->attr);
}
/***********************************************************************
* RPCRT4_AuthorizeBinding (internal)
*/
static RPC_STATUS RPCRT_AuthorizeConnection(RpcConnection* conn,
BYTE *challenge, ULONG count)
{
SecBufferDesc inp_desc, out_desc;
SecBuffer inp, out;
SECURITY_STATUS r;
unsigned char buffer[0x100];
RpcPktHdr *resp_hdr;
RPC_STATUS status;
TRACE("challenge %s, %ld bytes\n", challenge, count);
out.BufferType = SECBUFFER_TOKEN;
out.cbBuffer = sizeof buffer;
out.pvBuffer = buffer;
out_desc.ulVersion = 0;
out_desc.cBuffers = 1;
out_desc.pBuffers = &out;
inp.BufferType = SECBUFFER_TOKEN;
inp.pvBuffer = challenge;
inp.cbBuffer = count;
inp_desc.cBuffers = 1;
inp_desc.pBuffers = &inp;
inp_desc.ulVersion = 0;
r = InitializeSecurityContextA(&conn->Used->cred, &conn->ctx, NULL,
ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | ISC_REQ_MUTUAL_AUTH |
ISC_REQ_DELEGATE, 0, SECURITY_NETWORK_DREP,
&inp_desc, 0, &conn->ctx, &out_desc, &conn->attr, &conn->exp);
if (r)
return r;
resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION);
if (!resp_hdr)
return E_OUTOFMEMORY;
status = RPCRT4_SendAuth(conn, resp_hdr, NULL, 0, out.pvBuffer, out.cbBuffer);
RPCRT4_FreeHeader(resp_hdr);
return status;
}
/***********************************************************************
* RPCRT4_Send (internal)
*
@ -318,7 +414,37 @@ write:
RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header,
void *Buffer, unsigned int BufferLength)
{
return RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, NULL, 0);
RPC_STATUS r;
SecBuffer out;
/* if we've already authenticated, just send the context */
if (Connection->ctx.dwUpper || Connection->ctx.dwLower)
{
unsigned char buffer[0x10];
memset(buffer, 0, sizeof buffer);
buffer[0] = 1; /* version number lsb */
return RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, buffer, sizeof buffer);
}
if (Connection->Used == NULL ||
Connection->Used->AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT ||
Connection->Used->AuthnLevel == RPC_C_AUTHN_LEVEL_NONE)
{
return RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, NULL, 0);
}
out.BufferType = SECBUFFER_TOKEN;
out.cbBuffer = 0;
out.pvBuffer = NULL;
/* tack on a negotiate packet */
RPCRT4_AuthNegotiate(Connection, &out);
r = RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, out.pvBuffer, out.cbBuffer);
HeapFree(GetProcessHeap(), 0, out.pvBuffer);
return r;
}
/***********************************************************************
@ -439,6 +565,16 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
}
}
/* respond to authorization request */
if (common_hdr.ptype == PKT_BIND_ACK && common_hdr.auth_len > 8)
{
unsigned int offset;
offset = common_hdr.frag_len - hdr_length - common_hdr.auth_len;
RPCRT_AuthorizeConnection(Connection, (LPBYTE)pMsg->Buffer + offset,
common_hdr.auth_len);
}
/* success */
status = RPC_S_OK;