Bus authentication on Windows v2.0

LRN lrn1986 at gmail.com
Mon Jun 6 13:43:03 UTC 2016


On 06.06.2016 14:46, Simon McVittie wrote:
> On 03/06/16 20:30, LRN wrote:
>> I think i can make SSPI-based authentication work. However, i'm unsure 
>> how
>> to frame the data exchange between two processes.
>> If implemented with no explicit leaning toward D-bus, it would have to
>> exchange auth data in-band (in place of the single NUL byte, which on 
>> *nix
>> is accompanied by ancillary auth data; Windows does not allow ancillary
>> data for streaming TCP sockets).
> 
> If there is already a SASL mechanism for SSPI, please use it. If not,
> you're welcome to invent a DBUS_SSPI SASL mechanism with whatever
> in-band data exchange you need.
> 

The way i understand this is that SASL is a framework, and that any
authentication mechanism that fits into this framework is a SASL mechanism
(i think D-bus source code refers to such mechanisms as "SASL profiles").

SSPI seems to be roughly the same thing as SASL. SSPI provides a set of
generic functions, which both the client and the server call to initialize
the authentication state, then to generate opaque data buffers that they
exchange until authentication either succeeds or fails. If it succeeds,
SSPI can then be used to sign or encrypt further data. SSPI does have any
specs on how the data buffers are exchanged - as long as both parties have
an agreed-upon method of passing buffers to each other, SSPI will work just
fine.
This is how SSPI works in practice (NTLM is being used):

SERVER: calls AcquireCredentialsHandle() to get its own credentials (or
someone else's credentials, if name/password are provided or if SERVER is
root).
CLIENT: calls AcquireCredentialsHandle() to get its own credentials (or
someone else's credentials, if name/password are provided or if CLIENT is root)
CLIENT: calls InitializeSecurityContext(), giving it nothing;
InitializeSecurityContext() says "keep authenticating" and generates 55
bytes of opaque data
CLIENT: sends 55 bytes of opaque data to SERVER
SERVER: receives 55 bytes of opaque data from the CLIENT
SERVER: calls AcceptSecurityContext(), giving it 55 bytes of opaque data;
AcceptSecurityContext() says "keep authenticating" and generates 148 bytes
of opaque data
SERVER: sends 148 bytes of opaque data to CLIENT
CLIENT: receives 148 bytes of opaque data from SERVER
CLIENT: calls InitializeSecurityContext(), giving it 148 bytes of opaque
data; InitializeSecurityContext() says "authentication succeeded" and
generates 88 bytes of opaque data
CLIENT: sends 88 bytes of opaque data to SERVER
SERVER: receives 88 bytes of opaque data from CLIENT
SERVER: calls AcceptSecurityContext(), giving it 88 bytes of opaque data;
AcceptSecurityContext() says "authentication succeeded" and generates 0
bytes of opaque data
CLIENT is now authenticated (SERVER is also authenticated, if SSP supported
server authentication)

An SSPI mechanism is called "SSP". There can be any number of SSPs
available (for example, a cryptographic dongle might provide an SSP), but
most people seem to use MS SSPs that are guaranteed to be present - NTLM,
Kerberos, Negotiate and Digest. There's also CredSSP, which, AFAIU, uses
certificates.

All SSPI calls (starting from AcquireCredentialsHandle()) take SSP name (a
string) as an argument. Therefore, both parties must either use a
pre-agganged SSP, or agree upon an SSP before they start authenticating.

Once authentication succeeds, both parties can use the security context
object (which gets created during the exchange) to do stuff or query
information from it.

I'm a bit unsure what kind of information can be queried from a security
context that is created during Digest or CredSSP exchanges. I also don't
know what kind of credentials Digest SSP uses (AcquireCredentialsHandle()
accepts username, domain and password, but i don't know how it uses them).
Digest SSP lean heavily towards HTTP, i'm not sure how they apply to D-bus.

I'm more interested in NTLM and Kerberos SSPs. They use Windows access
token objects as credentials (when doing NTLM authentication, the client
calling AcquireCredentialsHandle() gives it NULL for most arguments, as all
necessary authentication data is taken from its currently-used access
token), and once security context object is created, server is able to
query an access token object from it. Access tokens are the ultimate
authentication objects in NT - one can query user SID from them (user SID
uniquely identifies a user), for example, and (if the client allowed it)
use them to impersonate the client (to either act in client's name, or ask
the system whether the client has access to a particular system object).

As a convenience, "Negotiate" SSP results in either NTLM or Kerberos SSP
being used under the hood, depending on whether Kerberos is supported or
not. This way client and server can use more secure Kerberos auth, if it's
available, and fall back on NTLM, if it's not. In practice this requires
some forethought, as Kerberos is rather picky (one needs to, for example,
supply a "principal" name to AcquireCredentialsHandle(); NTLM doesn't
really care about that). Kerberos supports mutual authentication (server
must have valid credentials), NTLM does not (and is thus considered
insecure when used over the network, as malicious 3rd party can steal real
NTLM traffic and use it to authenticate to some other server).

Here's how this could work with D-Bus:

C: AUTH
S: REJECTED SSPI_KERBEROS SSPI_NTLM EXTERNAL ANONYMOUS DBUS_COOKIE_SHA1
<C figures out that it supports SSPI_NTLM>
<C calls:
AcquireCredentialsHandleW (NULL, L"NTLM", SECPKG_CRED_OUTBOUND, 0, 0, 0, 0,
&cred_object, &lifetime)
>
<C calls:
InitializeSecurityContextW (&cred_object, 0, 0, ISC_REQ_IDENTIFY, 0,
SECURITY_NATIVE_DREP, 0, &sec_context, &output_buffer, &attributes, &lifetime)
>
<C optionally (depends on what InitializeSecurtyContextW() returns) calls:
CompleteAuthToken (&sec_context, &output_buffer)
>
C: AUTH SSPI_NTLM <U hex-encoded bytes from output_buffer>
<S calls:
AcquireCredentialsHandleW (NULL, L"NTLM", SECPKG_CRED_INBOUND, 0, 0, 0, 0,
&cred_object, &lifetime)
>
<S calls:
AcceptSecurityContext (&cred_object, 0, &input_buffer, 0,
SECURITY_NATIVE_DREP, &sec_context, &output_buffer, &attributes, &lifetime)
>
<S optionally (depends on what AcceptSecurtyContext() returns) calls:
CompleteAuthToken (&sec_context, &output_buffer)
>
S: DATA <Y hex-encoded bytes from output_buffer>
<C calls:
InitializeSecurityContextW (&cred_object, &sec_context, 0,
ISC_REQ_IDENTIFY, 0, SECURITY_NATIVE_DREP, &input_buffer, &sec_context,
&output_buffer, &attributes, &lifetime)
>
<C optionally (depends on what InitializeSecurtyContextW() returns) calls:
CompleteAuthToken (&sec_context, &output_buffer)
>
<if output_buffer is not empty:>
C: DATA <W hex-encoded bytes from output_buffer>
<S calls:
AcceptSecurityContext (&cred_object, &sec_context, &input_buffer, 0,
SECURITY_NATIVE_DREP, &sec_context, &output_buffer, &attributes, &lifetime)
>
<S optionally (depends on what AcceptSecurtyContext() returns) calls:
CompleteAuthToken (&sec_context, &output_buffer)
>
<if output_buffer is not empty:>
C: DATA <Z hex-encoded bytes from output_buffer>
...
S: OK 1234deadbeef
C: BEGIN

On the server side the exchange ends when the value returned by
AcceptSecurityContext() does not have SEC_I_CONTINUE_NEEDED or
SEC_I_COMPLETE_AND_CONTINUE bits set (server still needs to send any
output_buffer back to the client, if it's not empty; for NTLM, it is empty
though).

On the client side the exchange ends when the value returned by
InitializeSecurityContextW() does not have SEC_I_CONTINUE_NEEDED or
SEC_I_COMPLETE_AND_CONTINUE bits set (client still needs to send any
output_buffer back to the server, if it's not empty; for NTLM, it is not
empty).

For D-bus this means the following:
* If the bits (see above) are not set, you're done.
* If you're done, don't accept DATA anymore (whether it should be just
discarded or it should be treated as protocol error, i'm not sure).
* If there's a non-empty ouptut buffer, send it as DATA
* If there's an empty output buffer, and you're server, send OK and proceed.
* If there's an empty output buffer, and you're client, wait for OK (i guess?)

-- 
O< ascii ribbon - stop html email! - www.asciiribbon.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/dbus/attachments/20160606/4fdf21d5/attachment.sig>


More information about the dbus mailing list