GithubHelp home page GithubHelp logo

gssapi / gss-ntlmssp Goto Github PK

View Code? Open in Web Editor NEW
30.0 8.0 26.0 438 KB

A complete implementation of the MS-NLMP documents as a GSSAPI mechanism

License: ISC License

Makefile 1.28% M4 1.89% C 96.46% Shell 0.37%

gss-ntlmssp's Introduction

Build GSSNTLMSSP

GSS-NTLMSSP

This is a mechglue plugin for the GSSAPI library that implements NTLM authentication.

So far it has been built and tested only with the libgssapi implementation that comes with MIT Kerberos (Versions 1.11 and above)

Project Information

The project is currently hosted on github

Project related information (releases, hot to contribute, coding style, etc.. is available in the wiki

Acknowlegments

Protocol Documentation:

This project has been made much simpler thanks to the work done by the Samba Team first in Samba and Microsoft later by releasing documents such as MS-NLMP.

OID Space:

The Samba Project kindly donated this OID space: 1.3.6.1.4.1.7165.655.1.x

gss-ntlmssp's People

Contributors

feoone avatar karelchanivecky avatar norwayfun avatar oersen avatar omajid avatar sashan avatar simmon-nplob avatar simo5 avatar stefanb2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gss-ntlmssp's Issues

Crypto routine failure with UTF-16 surrogate pair in password

When trying to get a credential for a password that contains a UTF-16 surrogate pair char like ๐„ž it fails with

Major (851968): Unspecified GSS failure...nor (1314127875): Crypto routine failure

This seems to be a problem with the libunistring library when trying to convert UTF-8 bytes to the UCS-2LE encoding. I have no idea if this can be fixed or whether we should really care but technically I can create a username and password in Windows with these characters in the value and authenticate with them using NTLM.

To replicate this problem run

import gssapi

ntlm = gssapi.OID.from_int_seq('1.3.6.1.4.1.311.2.2.10')

username = b"User\xF0\x9D\x84\x9E".decode('utf-8')  # ๐„ž in UTF-8
password = b"Pass\xF0\x9D\x84\x9E"
username = gssapi.Name(username, name_type=gssapi.NameType.user)
cred = gssapi.raw.acquire_cred_with_password(username, password, usage='initiate', mechs=[ntlm])

It seems like this step and the same for NTOWFv1 is where the problem occurs but I don't fully understand how libunistring really works to see if there is a workaround or whether this should be raised there.

Even if we get past this and don't use these types of chars for the password, the code also fails when generating or parsing an authenticate message with a username like this. I haven't looked into the code to see what this may be but I would guess it's a similar situation with the password.

If you wish to try and fix this I'm happy to supply a way to set up a local user with a char that becomes a surrogate pair on Windows as I've tested this out with a Python NTLM implementation I have.

Segfault for ntlm_seal when no confidentiality or integrity is negotiated

If trying to wrap data when neither the sign or seal negotiate flags were negotiated then gss_wrap will seg fault. The same scenario through SSPI has the EncryptMessage function return SEC_E_UNSUPPORTED_FUNCTION and I would expect a similar result here and not a fatal error.

To reproduce run the following

import gssapi
import os
import tempfile

ntlm = gssapi.OID.from_int_seq('1.3.6.1.4.1.311.2.2.10')

with tempfile.NamedTemporaryFile() as temp_fd:
    with open(temp_fd.name, mode='wb') as fd:
        fd.write(b"DOMAIN:USER:PASS")

    os.environ['NTLM_USER_FILE'] = temp_fd.name

    c_cred = gssapi.Credentials(name=gssapi.Name(base='DOMAIN\\USER', name_type=gssapi.NameType.user), usage='initiate', mechs=[ntlm])
    s_cred = gssapi.Credentials(usage='accept', mechs=[ntlm])

    spn = gssapi.Name(base='http@test', name_type=gssapi.NameType.hostbased_service)
    c = gssapi.SecurityContext(creds=c_cred, usage='initiate', name=spn, mech=ntlm, flags=gssapi.RequirementFlag.mutual_authentication)
    s = gssapi.SecurityContext(creds=s_cred, usage='accept')

    c.step(s.step(c.step()))

    c.wrap(b"data", True)

When stepping through the code the seg fault seems to happen in

ret = RC4_UPDATE(h->seal_handle, message, output);
as the seal_handle has not been generated due to sign/seal not being set.

Sorry for the massive influx of questions/problems here, just trying to report what I can see when doing tests.

gss_accept_sec_context fails on 2nd call unless user credentials are cached in winbind cache

I'm troubleshooting gssntlmssp issue: new user cannot authenticate because his credentials are not known for winbind cache.
According to the source code, gssntlm_accept_sec_context -> gssntlm_acquire_cred -> gssntlm_acquire_cred_from -> external_get_creds -> winbind_get_creds -> wbcCredentialCache is probably the relevant trace for this problem and winbind reports "could not find credentials for user" error for this. The issue is avoided only when the user credentials are already in winbind cache (can be done by 'wbinfo -K'), but this is not the general case.
Please advise if I do something wrong and some initial preparation is needed (but should be the same for all users in directory, not per-user action).

My linux 'cntos-volodymyr' machine is joined to domain and it is capable to do proper kerberos authentication (keytab file has records of host service for machine account), winbind is running and 'ntlm_auth' utility from samba works perfectly. To easily reproduce the issue with gssntlmssp, I run gss client/server utilities provided by MIT Kerberos library.

Client-side call:
$ gss-client -mech '{1.3.6.1.4.1.311.2.2.10}' -user volodymyr -pass 'password' cntos-volodymyr host HELLO_MSG

Server-side call (with gss troubleshooting):
$ ltrace gss-server host 2>&1 | grep gss
gss_accept_sec_context(0x7ffd373b2abc, 0x7ffd373b2ad8, 0x55dec98a7ea0, 0x7ffd373b2b20) = 1
gss_release_buffer(0x7ffd373b2ab8, 0x7ffd373b2b10, 184, 0) = 0
gss_accept_sec_context(0x7ffd373b2abc, 0x7ffd373b2ad8, 0x55dec98a7ea0, 0x7ffd373b2b20) = 0xd0000
gss_display_status(0x7ffd373b2998, 0xd0000, 1, 0) = 0
gss_release_buffer(0x7ffd373b2998, 0x7ffd373b29a0, 0x7f8fa9efca00, 0x7fffff9d) = 0
gss_display_status(0x7ffd373b29c8, 0x4e540016, 2, 0) = 0
gss_release_buffer(0x7ffd373b29c8, 0x7ffd373b29d0, 0x7f8fa9efca00, 0x7fffffc9) = 0

Winbind log:
process_request_written: [53057:unknown request]: delivered response to client
process_request_send: process_request: request fn NTLMAUTH
[53057]: perform NTLM auth on behalf of user VAST-SMB-DEV\volodymyr
winbindd_dual_ccache_ntlm_auth: could not find credentials for user VAST-SMB-DEV\volodymyr
process_request_written: [53057:unknown request]: delivered response to client

Migration to Weblate

this is a follow-up of: https://pagure.io/gssntlmssp/issue/15

I migrated your project, you have a first PR here: #38
you can keep it open as long as you wish, Weblate will reuse it and squash commits per author to limit the number of commits

Weblate will update all po files each time you change the pot file.
Weblate will update your LINGUAS file to keep your like easier.

please connect to https://translate.fedoraproject.org/ so I can make you admin

kind advice:

  • please rewrite your readme in Pagure so we don't loose time (yes, you wrote you migrated to github, but I missed it, other will loose time too)
  • if you choose not to forward issues to github, please close all Pagure issues, at least we would be informed of the transfer
  • as a translator, have no idea what your project does, having example on where it is used would help me

Implement gss_set_cred_option()

Although libkrb5 should be able to handle a mechanism w/o this function implemented, it seem that, at least in some version, lack of the function causes a series of events that will end up with libkrb5 trying to dereference a gssntlmssp context as a union context and crashes.

Implementing, even an empty function would prevent the issue.

.Net 6 Ubuntu jammy 22.04 base image upgrade. GSSAPI NTLM error

Hi,

We are planning to upgrade our .Net core MVC application from .Net 6 to .Net 8 version. It is written in C#. To prepare for that upgrade we first upgraded from ubuntu 20.04 to ubuntu 22.04. We target ubuntu 22.04 version jammy tag with amd64 architecture.

This is our base image in the Docker file and the following line updates our package list.

FROM artifactory.xyz.com/dockerhub-microsoft/dotnet/aspnet:6.0-jammy-amd64 AS base

&& apt-get update && apt-get install -y --no-install-recommends curl gss-ntlmssp tzdata \

When our application tries to authenticate and open SSRS reports we get "GSSAPI operation failed with error - Unspecified GSS failure. Minor code may provide more information (Crypto routine failure)"

We were previously using focal base image in 20.04 version and was able to render SSRS reports. Did something change with gss-ntlmssp package in 22.04 version? I was reading some other posts where it says this issue is related to incompatibilities between OpenSSL 3.0 and the older cryptographic algorithms involved in NTLM authentication. Any thoughts on how to fix this issue? Appreciate your kind response.

Not possible to obtain access token (PAC) for authenticated context, unsupported operation

We need to obtain detailed security information about authenticated user via GSSAPI.
As the part of NETLOGON_VALIDATION_SAM_INFO4 structure (response to NETLOGON_NETWORK_INFO from DC, part of processing AUTHENTICATE_MESSAGE from client by server, see [MS-APDS], "4.1 NTLM Pass-Through Authentication" for example) all the details of authenticated user are delivered to server. We need this from server side (after a call to gss_accept_sec_context) to identify the user (userSID, SIDs of all groups, etc).
It seems like gssntlmssp library doesn't have this option yet ("The operation or option is not
available or unsupported" is returned for gss_get_name_attribute for example). Can we add it as a new feature?

Possible ways to inquire this information from the context via GSSAPI are:

  • gss_get_name_attribute with "urn:mspac:" name (also can get sub-parts, like "urn:mspac:logon-info")

  • gss_inquire_sec_context_by_oid with EXTRACT_PAC_AUTHZ_DATA_FROM_SEC_CONTEXT_OID

See gssapi_pac.c code of samba for usage example: https://github.com/encukou/samba/blob/master/auth/kerberos/gssapi_pac.c
Also opencifs LsaMapSecurityGetPacInfoFromGssContext here: https://github.com/BeyondTrust/pbis-open/blob/master/lsass/interop/lwmapsecurity/lwmapsecurity-lsass.c

Doesn't work with OpenSSL 3 on Alpine 3.18

Hi. I faced the problem that if I'll build the package for Alpine 3.18, it won't work. Here is a Dockerfile I'm using for that:

FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine3.18
RUN apk add --no-cache git curl
RUN apk add --no-cache make m4 autoconf automake gcc g++ krb5-dev openssl-dev gettext-dev  
RUN apk add --no-cache libtool libxml2 libxslt libunistring-dev zlib-dev samba-dev

RUN git clone https://github.com/gssapi/gss-ntlmssp
WORKDIR gss-ntlmssp
RUN autoreconf -f -i
RUN ./configure --without-manpages --disable-nls
RUN make install

The build is working, but when I'm using gssntlmssp.so library, I'm receiving 403 errors during authentication requests. Previously and on our older images it was working perfectly fine with the same authentication endpoint.
I've got to know that when OpenSSL 3 became default package in Alpine 3.18, then it stopped working. Reference:
https://stackoverflow.com/questions/76185769/gssapi-operation-failed-with-error-an-unsupported-mechanism-was-requested-for
https://bugs.launchpad.net/ubuntu/+source/gss-ntlmssp/+bug/1995915

Maybe someone has a solution for that?
Thanks in advance!

ntlm_auth != ibgssapi + gss-ntlmssp + winbind?

So we have ubuntu clients that use sssd to authenticate with the AD.
Also we have websites that require ntlm_auth to do SSO.
As far as I am able to tell ntlm_auth is part of samba.
Am i correct in the assumption that i can't use winbind and the library libgssapi + gss-ntlmssp + firefox to do SSO with these websites?

Lack of NTLMSSP_NEGOTIATE_VERSION and offset calculation

The code seems to assume that the MIC offset is shifted down 8 bytes if NTLMSSP_NEGOTIATE_VERSION flag is not present. That doesn't seem to be in line with the Microsoft specification which always lists it as present, just being set to zero bytes. This discrepancy causes the MIC to be placed at a wrong offset and thus inadverently fail the integrity check.

I discovered it when comparing the macOS, Windows and this implementation. The MIC generation was explicitly enabled for the test through the private SPNEGO inquiry (https://github.com/dotnet/runtime/pull/65627/files#diff-c67e0117ce4bb818f2a2cc2c01ea9b2058c1a63b846af571ed2d59a2db9d33ffR411)

Problem working versus CIFS from kernel 5.17

Hi,

In Linux kernel 5.17 the client started to use Version in the Negotiate message -
`commit 52d005337b2c94ab37273d9ad8382d4fb051defd
Author: Steve French [email protected]
Date: Wed Jan 19 22:00:29 2022 -0600

smb3: send NTLMSSP version information

For improved debugging it can be helpful to send version information
as other clients do during NTLMSSP negotiation. See protocol document
MS-NLMP section 2.2.1.1

Set the major and minor versions based on the kernel version, and the
BuildNumber based on the internal cifs.ko module version number,
and following the recommendation in the protocol documentation
(MS-NLMP section 2.2.10) we set the NTLMRevisionCurrent field to 15.

Reviewed-by: Shyam Prasad N <[email protected]>
Signed-off-by: Steve French <[email protected]>

`

This commit is causing the VERSION flag to be set also in the AUTH message but the client is not sending Version in the auth message so we are doing wrong parsing and failing the login because the first header is written in offset 64 while we are expecting it in offset 72 (because we add the version size).
Checking the kernel code I see the logic decides about the offset in the payload only based on the offset mentioned in the first header and not basing it on the struct size, thoughts about changing it to have the same logic?

UNTRUSTED_SPN_SOURCE should not be set

(Continuing from jborean93/smbprotocol#169)

Windows servers have a security policy Microsoft network server: Server SPN target name validation level, which (if enabled) will check the SPN sent in MSV_AV_TARGET_NAME and will reject authentication if it thinks you're authenticating to an unrecognized SPN. (I assume this is meant to prevent NTLM relay attacks, though it also adds checks to Kerberos SPNs as well.)

Latest gss-ntlmssp Git now sends the SPN in the correct format, but still gets rejected by Windows servers with this policy enabled. The biggest difference I can see between gss-ntlmssp and working clients (Win10, Samba, pyspnego) is that gss-ntlmssp now sets the UNTRUSTED_SPN_SOURCE flag in MSV_AV_FLAGS, which none of the other clients do, and if I understand the NTLM spec right this flag tells the server to pretend the SPN field was empty (which the newly added checks then reject as unrecognized).

gssntlmssp library crashes on anonymous user authentication (usr_name == NULL)

We are using gssntlmssp in SMB2 server for NTLM authentication (as a plugin for GSSAPI library called for SESSION_SETUP verb). We have this problem in gssntlmssp during null session penetration test (using anonymous session - i.e. empty user with empty password):
net use \\rnd-volodymyr2\root "" /user:

The problem is due to bug of anonymous access validation:
src/gss_sec_ctx.c:838

        if (((usr_name == NULL) || (usr_name[0] == '\0')) &&
            (nt_chal_resp.length == 0) &&
            (((lm_chal_resp.length == 1) && (lm_chal_resp.data[0] == '\0')) ||
             (lm_chal_resp.length == 0))) {
            /* Anonymous auth */
            /* FIXME: not supported for now */
            set_GSSERR(ERR_NOTSUPPORTED);
            goto done;

        } else {
         ...
         ulen = strlen(usr_name);

Compound condition requires all sub-conditions to be met:
empty user_name AND zero NT challenge len AND zero LM challenge len
So if only user_name is empty but challenges are not zero - we go to full processing.
During full processing we don't check user_name for NULL anymore and fails on NULL pointer de-reference.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fe739ffb700 (LWP 726)]
gssntlm_accept_sec_context (minor_status=0x7fe739fb8574, context_handle=0x7fe70c000a40, acceptor_cred_handle=<optimized out>, input_token=0x7fe71c001110, input_chan_bindings=0x0, src_name=0x7fe739fb8218, 
    mech_type=0x7fe739fb8228, output_token=0x7fe739fb83b0, ret_flags=0x7fe739fb8204, time_rec=0x7fe739fb857c, delegated_cred_handle=0x0) at src/gss_sec_ctx.c:866
866	            ulen = strlen(usr_name);
(gdb) bt
#0  gssntlm_accept_sec_context (minor_status=0x7fe739fb8574, context_handle=0x7fe70c000a40, acceptor_cred_handle=<optimized out>, input_token=0x7fe71c001110, input_chan_bindings=0x0, src_name=0x7fe739fb8218, 
    mech_type=0x7fe739fb8228, output_token=0x7fe739fb83b0, ret_flags=0x7fe739fb8204, time_rec=0x7fe739fb857c, delegated_cred_handle=0x0) at src/gss_sec_ctx.c:866
#1  0x00007fecb46b06d6 in gss_accept_sec_context () from /lib64/libgssapi_krb5.so.2
#2  0x00007fecb46dde73 in spnego_gss_accept_sec_context () from /lib64/libgssapi_krb5.so.2
#3  0x00007fecb46b06d6 in gss_accept_sec_context () from /lib64/libgssapi_krb5.so.2
#4  0x00007feca3b0b1e7 in Proto::GssApi::accept_security_context(unsigned short, unsigned char*, Proto::GssapiSecurityContext*, Proto::GssapiBuffer*) (this=0x7feca99eeab0 <Smb2::SmbProto::_gss_api>, 
    req_security_buffer_length=535, req_security_buffer=<optimized out>, context=0x7fe9f1e2c148, output_token=0x7fe517cefe18) at src/proto/common/gss_api.cpp:269
#5  0x00007feca3e24f70 in Smb2::accept_security_context_async_worker(void*) (args=0x7fe517cefda0) at src/proto/smb2/smb2_session.cpp:957
...
(gdb) p usr_name
$1 = 0x0
(gdb) p nt_chal_resp.length
$2 = 316
(gdb) p lm_chal_resp.length
$3 = 24

Proposed fix is to change validation to this:

if (empty user_name OR zero NT challenge len OR zero LM challenge len) {
  set_GSSERR(ERR_NOTSUPPORTED);
} else {
 ...

Patch file is below:

diff --git a/src/gss_sec_ctx.c b/src/gss_sec_ctx.c
index 2989f1a..f1a433c 100644
--- a/src/gss_sec_ctx.c
+++ b/src/gss_sec_ctx.c
@@ -835,8 +835,8 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
 goto done;
 }
 
- if (((usr_name == NULL) || (usr_name[0] == '\0')) &&
- (nt_chal_resp.length == 0) &&
+ if (((usr_name == NULL) || (usr_name[0] == '\0')) ||
+ (nt_chal_resp.length == 0) ||
 (((lm_chal_resp.length == 1) && (lm_chal_resp.data[0] == '\0')) ||
 (lm_chal_resp.length == 0))) {
 /* Anonymous auth */

GSS_C_INQ_SSPI_SESSION_KEY - Feature not supported

Hi

I'm trying to call gss_inquire_sec_context_by_oid with GSS_C_INQ_SSPI_SESSION_KEY to a negotiated NTLM context but it is erroring out with Major (1048576): The operation or option is not available or unsupported, Minor (1314127893): Feature not supported. I'm looking at the code for gssntlm_inquire_sec_context_by_oid and the only time ERR_NOTSUPPORTED is returned if if the OID does not match any of the listed OIDs that are in the if statements. The actual gssntlm_sspi_session_key can return ERR_NOTAVAIL but that doesn't seem to be the case based on the error reported in my call.

I can reproduce this issue against a proper domain setup but a simple reproducer for this issue is

import gssapi
import os
import tempfile

from gssapi.raw import acquire_cred_with_password, inquire_sec_context_by_oid


NTLM = gssapi.OID.from_int_seq('1.3.6.1.4.1.311.2.2.10')
GSS_C_INQ_SSPI_SESSION_KEY = gssapi.OID.from_int_seq("1.2.840.113554.1.2.2.5.5")

with tempfile.NamedTemporaryFile() as ntlm_file:
    with open(ntlm_file.name, mode='wb') as fd:
        fd.write(b"domain:username:password")

    os.environ['NTLM_USER_FILE'] = ntlm_file.name

    c = gssapi.SecurityContext(
        creds=acquire_cred_with_password(gssapi.Name(base='username', name_type=gssapi.NameType.user),
                                   b'password', usage='initiate', mechs=[NTLM]).creds,
        usage='initiate',
        name=gssapi.Name('host@domain', name_type=gssapi.NameType.hostbased_service),
        mech=NTLM,
    )
    s = gssapi.SecurityContext(
        creds=acquire_cred_with_password(gssapi.Name(base='username', name_type=gssapi.NameType.hostbased_service),
                                   b'password', usage='accept', mechs=[NTLM]).creds,
        usage='accept')

    in_token = None
    while not c.complete:
        out_token = c.step(in_token)
        in_token = s.step(out_token)

    # Verifies wrapping is actually working which would mean there is a session key available
    c_enc_msg = c.wrap(b"Hello world", encrypt=True).message
    s_dec_msg = s.unwrap(c_enc_msg).message
    s_enc_msg = s.wrap(s_dec_msg, encrypt=True).message
    c_dec_msg = c.unwrap(s_enc_msg).message
    assert c_dec_msg == b"Hello world"

    # Both fail with the GSSError I shared above
    c_session_key = inquire_sec_context_by_oid(c, GSS_C_INQ_SSPI_SESSION_KEY)[0]
    s_session_key = inquire_sec_context_by_oid(s, GSS_C_INQ_SSPI_SESSION_KEY)[0]

I've double checked that the OID I'm using matches up with what is documented for GSS_C_INQ_SSPI_SESSION_KEY in MIT krb5 and this same code works fine for a Kerberos negotiated context.

On a side note manually parsing the NTLM 3 msg with the known password I am able to generate the session key myself but because NTLMSSP_NEGOTIATE_KEY_EXCH is not a negotiated flag it isn't sending the encrypted session key across the wire. Is this by choice as the docs indicate that this "SHOULD" be used under the V entry for the flags

V (1 bit): If set, requests an explicit key exchange. This capability SHOULD be used because it improves security for message integrity or confidentiality. See sections 3.2.5.1.2, 3.2.5.2.1, and 3.2.5.2.2 for details. An alternate name for this field is NTLMSSP_NEGOTIATE_KEY_EXCH.

Has this been omitted on purpose due to the age of RC4 encryption that it used here or is there another reason?

(ansible-py37) jborean:~/dev/pyspnego$ bin/pyspnego-parse --password password --token TlRMTVNTUAADAAAAAAAAAEAAAADCAMIAQAAAAAAAAAAAAAAAEAAQAAIBAAAaABoAEgEAABAAEAAsAQAAFYKKoAgDDMe4rJ/5XPH/v/d/Kw0BAQAAAAAAAOC3ZQP5GdYBHdWOyE5G9/YAAAAAAQAaAEoAQgBPAFIARQBBAE4ALQBMAEkATgBVAFgAAgAWAFcATwBSAEsAUwBUAEEAVABJAE8ATgADABoAagBiAG8AcgBlAGEAbgAtAGwAaQBuAHUAeAAGAAQAAAAAAAcACADgt2UD+RnWAQkADABkAG8AbQBhAGkAbgAKABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdQBzAGUAcgBuAGEAbQBlAEoAQgBPAFIARQBBAE4ALQBMAEkATgBVAFgAAAAAAAAAAAAAAAAAAAAAAA==
{
    "MessageType": "NtlmAuthenticate (3)",
    "Signature": "NTLMSSP\u0000",
    "Data": {
        "NegotiateFlagsRaw": 2693431829,
        "NegotiateFlags": [
            "NTLMSSP_NEGOTIATE_56 (2147483648)",
            "NTLMSSP_NEGOTIATE_128 (536870912)",
            "NTLMSSP_NEGOTIATE_TARGET_INFO (8388608)",
            "NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY (524288)",
            "NTLMSSP_TARGET_TYPE_SERVER (131072)",
            "NTLMSSP_NEGOTIATE_ALWAYS_SIGN (32768)",
            "NTLMSSP_NEGOTIATE_NTLM (512)",
            "NTLMSSP_NEGOTIATE_SIGN (16)",
            "NTLMSSP_REQUEST_TARGET (4)",
            "NTLMSSP_NEGOTIATE_UNICODE (1)"
        ],
        "LmChallengeResponse": null,
        "NtChallengeResponse": {
            "ResponseType": "NTLMv2",
            "NTProofStr": [
                "08030CC7B8AC9FF95CF1FFBFF77F2B0D"
            ],
            "ClientChallenge": {
                "RespType": 1,
                "HiRespType": 1,
                "Reserved1": 0,
                "Reserved2": 0,
                "TimeStamp": "2020-04-24T05:27:14.855728",
                "ChallengeFromClient": "1DD58EC84E46F7F6",
                "Reserved3": 0,
                "AvPairs": [
                    {
                        "AvId": "MSV_AV_NB_COMPUTER_NAME (1)",
                        "Value": "JBOREAN-LINUX"
                    },
                    {
                        "AvId": "MSV_AV_NB_DOMAIN_NAME (2)",
                        "Value": "WORKSTATION"
                    },
                    {
                        "AvId": "MSV_AV_DNS_COMPUTER_NAME (3)",
                        "Value": "jborean-linux"
                    },
                    {
                        "AvId": "MSV_AV_FLAGS (6)",
                        "Value": []
                    },
                    {
                        "AvId": "MSV_AV_TIMESTAMP (7)",
                        "Value": "2020-04-24T05:27:14.855728"
                    },
                    {
                        "AvId": "MSV_AV_TARGET_NAME (9)",
                        "Value": "domain"
                    },
                    {
                        "AvId": "MSV_AV_CHANNEL_BINDINGS (10)",
                        "Value": "00000000000000000000000000000000"
                    },
                    {
                        "AvId": "MSV_AV_EOL (0)",
                        "Value": null
                    }
                ],
                "Reserved4": 0
            }
        },
        "DomainName": null,
        "UserName": "username",
        "Workstation": "JBOREAN-LINUX",
        "EncryptedRandomSessionKey": null,
        "Version": null,
        "MIC": "5CF1FFBFF77F2B0D0101000000000000",
        "SessionKey": "D4271F9C44E73E7C2D89A69C73198304"
    },
    "RawData": "4E544C4D53535000030000000000000040000000C200C20040000000000000000000000010001000020100001A001A0012010000100010002C01000015828AA008030CC7B8AC9FF95CF1FFBFF77F2B0D0101000000000000E0B76503F919D6011DD58EC84E46F7F60000000001001A004A0042004F005200450041004E002D004C0049004E00550058000200160057004F0052004B00530054004100540049004F004E0003001A006A0062006F007200650061006E002D006C0069006E0075007800060004000000000007000800E0B76503F919D60109000C0064006F006D00610069006E000A00100000000000000000000000000000000000000000000000000075007300650072006E0061006D0065004A0042004F005200450041004E002D004C0049004E005500580000000000000000000000000000000000"
}

Autoconf warnings when building.

I'm building gss-ntlmssp from this repo in a docker container using the image python:3.11.2-alpine3.17 as a base
but i'm getting some errors while configuring and building the package.

Hosts used to build the docker image:
linux/amd64 Rocky Linux 8.6
linux/amd64 Ubuntu 22:04

I am running the following commands.

git clone https://github.com/gssapi/gss-ntlmssp /tmp/gss-ntlmssp 
cd /tmp/gss-ntlmssp 
git reset --hard 646c7fc5b961eade381fb7e4378074d4fd453321 
autoreconf -f -i 
./configure --without-manpages --disable-nls 
make && make install 

The package is building just fine but is it okay to ignore the following errors?

aclocal: warning: couldn't open directory 'm4': No such file or directory
libtoolize: putting auxiliary files in '.'.
libtoolize: copying file './ltmain.sh'
libtoolize: putting macros in 'm4'.
libtoolize: copying file 'm4/libtool.m4'
libtoolize: copying file 'm4/ltoptions.m4'
libtoolize: copying file 'm4/ltsugar.m4'
libtoolize: copying file 'm4/ltversion.m4'
libtoolize: copying file 'm4/lt~obsolete.m4'
libtoolize: Consider adding 'AC_CONFIG_MACRO_DIRS([m4])' to configure.ac,
libtoolize: and rerunning libtoolize and aclocal.
configure.ac:31: warning: The macro `ac_cv_prog_gcc' is obsolete.
configure.ac:31: You should run autoupdate.
./lib/autoconf/c.m4:440: ac_cv_prog_gcc is expanded from...
aclocal.m4:182: AM_CONDITIONAL is expanded from...
configure.ac:31: the top level
configure.ac:34: warning: The macro `AC_CONFIG_HEADER' is obsolete.
configure.ac:34: You should run autoupdate.
./lib/autoconf/status.m4:719: AC_CONFIG_HEADER is expanded from...
configure.ac:34: the top level
configure.ac:39: warning: The macro `AC_HELP_STRING' is obsolete.
configure.ac:39: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
./lib/autoconf/general.m4:1553: AC_ARG_WITH is expanded from...
build_macros.m4:1: BUILD_WITH_SHARED_BUILD_DIR is expanded from...
configure.ac:39: the top level
external/platform.m4:1: warning: The macro `AC_HELP_STRING' is obsolete.
external/platform.m4:1: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
./lib/autoconf/general.m4:1553: AC_ARG_WITH is expanded from...
external/platform.m4:1: the top level
configure.ac:51: warning: The macro `AC_HELP_STRING' is obsolete.
configure.ac:51: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
./lib/autoconf/general.m4:1553: AC_ARG_WITH is expanded from...
conf_macros.m4:1: WITH_DISTRO_VERSION is expanded from...
configure.ac:51: the top level
configure.ac:52: warning: The macro `AC_HELP_STRING' is obsolete.
configure.ac:52: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
./lib/autoconf/general.m4:1553: AC_ARG_WITH is expanded from...
conf_macros.m4:42: WITH_TEST_DIR is expanded from...
configure.ac:52: the top level
configure.ac:53: warning: The macro `AC_HELP_STRING' is obsolete.
configure.ac:53: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
./lib/autoconf/general.m4:1553: AC_ARG_WITH is expanded from...
conf_macros.m4:12: WITH_MANPAGES is expanded from...
configure.ac:53: the top level
configure.ac:54: warning: The macro `AC_HELP_STRING' is obsolete.
configure.ac:54: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
./lib/autoconf/general.m4:1553: AC_ARG_WITH is expanded from...
conf_macros.m4:28: WITH_XML_CATALOG is expanded from...
configure.ac:54: the top level
configure.ac:55: warning: The macro `AC_HELP_STRING' is obsolete.
configure.ac:55: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
./lib/autoconf/general.m4:1553: AC_ARG_WITH is expanded from...
conf_macros.m4:72: WITH_WBCLIENT is expanded from...
configure.ac:55: the top level
configure.ac:56: warning: The macro `AC_HELP_STRING' is obsolete.
configure.ac:56: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
./lib/autoconf/general.m4:1553: AC_ARG_WITH is expanded from...
conf_macros.m4:89: WITH_WINBIND_TLS_CONTEXT is expanded from...
configure.ac:56: the top level
configure.ac:104: warning: The macro `AC_LANG_C' is obsolete.
configure.ac:104: You should run autoupdate.
./lib/autoconf/c.m4:72: AC_LANG_C is expanded from...
external/ax_check_zlib.m4:68: AX_CHECK_ZLIB is expanded from...
configure.ac:104: the top level
configure.ac:113: warning: The macro `AC_ERROR' is obsolete.
configure.ac:113: You should run autoupdate.
./lib/autoconf/oldnames.m4:34: AC_ERROR is expanded from...
configure.ac:113: the top level
configure.ac:116: warning: The macro `AC_ERROR' is obsolete.
configure.ac:116: You should run autoupdate.
./lib/autoconf/oldnames.m4:34: AC_ERROR is expanded

Send MIC by Default

Currently gss-ntlmssp only adds the MIC to the authentication message if the caller has also called gss_inquire_sec_context_by_oid(ctx, spnego_req_mechlistMIC_oid). This sets an internal flag that tells gss-ntlmssp that the caller knows enough about the library and SPNEGO to include the mechListMIC in the wrapper token. I believe that the default should have gss-ntlmssp always add the MIC regardless of this being called first. At this point in time I feel like any users of gss-ntlmssp will know how to reset the crypto state for the mechListMIC or even use the inquiry to determine if the MIC was set (server is new enough) rather than having to call it twice to enable the MIC as well.

I know this is a complex setup so happy to look into it further if needed.

LMOWFv1 with passwords > 14 chars

The MS-NLMP docs define the LMOWFv1 function as

 Define LMOWFv1(Passwd, User, UserDom) as
        ConcatenationOf( DES( UpperCase( Passwd)[0..6],"KGS!@#$%"),
                  DES( UpperCase( Passwd)[7..13],"KGS!@#$%")) 

It also states that

Password of the user. If the password is longer than 14 characters, the LMOWF v1 cannot be computed. For LMOWF v1, if the password is shorter than 14 characters, it is padded by appending zeroes.

While this is correct for LM hash authentication, this hash is still computed even if NTv1 hashes are used stopping longer passwords being used for NTv1. The check here will block the initiator from acquiring a credential even if they want to use just NTv1 and not LMv1 authentication.

Multi-threaded libwbclient API should be supported

We use gssntlmssp library with support of winbind external server from multi-threaded application.
We see sporadic unexpected authentication failures during stress-test (when few requests are done in parallel) while everything is ok for non-parallel flow. Root-cause of the problem is unexpected interleaved data received by winbind, in this case request is dropped. We are getting an error for wbcAuthenticateUserEx call:

wbc_status = wbcAuthenticateUserEx(&wbc_params, &wbc_info, &wbc_err);

For details of this call from gssntlmssp library, see winbind_srv_auth function here:
https://github.com/gssapi/gss-ntlmssp/blob/main/src/winbind.c

From winbind side:

[2021/01/06 08:29:19.646294, 10, pid=256853, effective(0, 0), real(0, 0), class=winbind] ../source3/winbindd/winbindd.c:763(process_request_send)
  process_request_send: process_request: request fn NTLMAUTH
...
[2021/01/06 08:29:19.646523,  0, pid=256853, effective(0, 0), real(0, 0), class=winbind] ../source3/winbindd/winbindd.c:1005(winbind_client_activity)
  winbind_client_activity[256138:PAM_AUTH_CRAP]:unexpected data from client - removing client
[2021/01/06 08:29:19.646616,  1, pid=256853, effective(0, 0), real(0, 0), class=winbind] ../source3/winbindd/winbindd_dual.c:337(wb_child_request_cleanup)
  wb_child_request_cleanup: keep orphaned subreq[0x55564bdc1b00]

We have got this feedback from Samba developers (Volker Lendecke):
... one guess would be that the code using the gss-ntlmssp library is
multi-threaded. While the gss-ntlmssp library possibly is thread-safe
in general, its use of libwbclient is definitely not. Directly using
wbcAuthenticateUserEx() and other needs to be protected by a mutex, or
alternatively the library must create a wbcContext using wbcCtxCreate
in thread-local storage and then call wbcCtxAuthenticateUserEx(). The
wbcCtx*() calls are designed to be callable in a multi-threaded
environment, the wbcAuthenticateUserEx call is definitely not.

We need to have an option for using multi-threaded API of libwbclient from gssntlmssp.
One can use some compile-time option to specify the intended API or optionally we can just refactor the code to always use MT-safe calls.

gssntlmssp has few other winbind client calls - wbcInterfaceDetails and wbcCredentialCache - see src/winbind.c of gssntlmssp.
We haven't seen such races with them yet, but probably that's due very short time of request handling (local requests, no need to talk with DC). Probably all libwbclient calls should use the same approach.

Question: What 'Feature not available' error means?

Hello,

I am trying to solve this issue, in short, we have ASP.NET server hosted on CentOS 7 and we would like to use Windows authentication, but we are getting the following error

2021-06-21 07:51:55.4321|ERROR|Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler|An exception occurred while processing the authentication request. Interop+NetSecurityNative+GssApiException: GSSAPI operation failed with error - Unspecified GSS failure. Minor code may provide more information (Feature not available).

What exactly this error means?
Thank you very much.

Using gss-ntlmssp from Java

I have a problem, maybe you can help me.
I am using the gss-ntlmssp GSS plugin from Java on Linux by setting the system property "-Dsun.security.jgss.native=true".

I am testing HTTP proxy authorization with Negotiate (Kerberos), NTLM and Basic. I have set up a test system with multiple docker containers, one with a Samba DC, one with a Squid proxy and one development container with which I test the authorization.

The test setup seems to be ok, I can succesfully do:

[CORP\user1@develop1 proxytest]$ curl -v --proxy-negotiate -u: -x squidserver.corp.example.com:3128 https://<destination>
[CORP\user1@develop1 proxytest]$ curl -v --proxy-ntlm --proxy-user CORP\\user1 -u: -x squidserver.corp.example.com:3128 https://<destination>

Though I must admit challenge/response authorization with wbinfo is only successful if I run it as root, not as CORP\user1 (maybe that's the problem?):

[CORP\user1@develop1 proxytest]$ wbinfo -a CORP\\user1
Enter CORP\user1's password:
plaintext password authentication succeeded
Enter CORP\user1's password:
challenge/response password authentication failed
Could not authenticate user CORP\user1 with challenge/response

In my Java program I create a GSS context with the NTLMSSP Oid and create a token with:

		Oid ntlmOid = new Oid("1.3.6.1.4.1.311.2.2.10");
		Oid oid = ntlmOid;
		String service = "[email protected]";
		GSSName serverName = manager.createName(service, GSSName.NT_HOSTBASED_SERVICE);
		GSSContext context = manager.createContext(serverName,
				oid,
				null,
				GSSContext.DEFAULT_LIFETIME);

This is successful, and I can create a token which I send Base64 encoded to Squid:

		byte[] token = new byte[0];
		token = context.initSecContext(token, 0, token.length);
		String encodedToken = Base64.getEncoder().encodeToString(token);

The Proxy-authenticate line I send to Squid looks like this:

Proxy-Authorization: NTLM TlRMTVNTUAABAAAAN4II4gAAAAAAAAAAAAAAAAAAAAAGAgAAAAAADw==

Then I get back the following token from Squid:

Proxy-Authenticate: NTLM TlRMTVNTUAACAAAACAAIADgAAAA1goniYTUVUwP3TmIAAAAAAAAAAJYAlgBAAAAABgEAAAAAAA9DAE8AUgBQAAIACABDAE8AUgBQAAEAFgBTAFEAVQBJAEQAUwBFAFIAVgBFAFIABAAgAGMAbwByAHAALgBlAHgAYQBtAHAAbABlAC4AYwBvAG0AAwA4AHMAcQB1AGkAZABzAGUAcgB2AGUAcgAuAGMAbwByAHAALgBlAHgAYQBtAHAAbABlAC4AYwBvAG0ABwAIAHAs/DxdjdkBAAAAAA==

But if I Base64 decode this token and feed it into the GSSContext I get an exception:

...
byte[] tokenBin = Base64.getDecoder().decode(token64);
byte[] token2 = context.initSecContext(tokenBin, 0, tokenBin.length);

Exception:

Exception in thread "main" GSSException: Defective token detected (Mechanism level: Failed to decode data)
        at java.security.jgss/sun.security.jgss.wrapper.GSSLibStub.initContext(Native Method)
        at java.security.jgss/sun.security.jgss.wrapper.NativeGSSContext.initSecContext(NativeGSSContext.java:277)
        at java.security.jgss/sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:266)
        at java.security.jgss/sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:196)
        at proxytest.HttpClient.main(HttpClient.java:136)

The gss-ntlmssp Log looks like this:

[CORP\user1@develop1 proxytest]$ cat gssntlm.log
[1684837520] ALLOK: gssntlm_import_name_by_mech() @ src/gss_names.c:355 [0:0]
[1684837520] ALLOK: gssntlm_acquire_cred_from() @ src/gss_creds.c:501 [0:0]
[1684837520] ALLOK: gssntlm_import_name_by_mech() @ src/gss_names.c:355 [0:0]
[1684837520] ALLOK: gssntlm_init_sec_context() @ src/gss_sec_ctx.c:246 [1:0]
[1684837520] ALLOK: gssntlm_release_name() @ src/gss_names.c:633 [0:0]
[1684837520] ALLOK: gssntlm_release_name() @ src/gss_names.c:633 [0:0]
[1684837520] ALLOK: gssntlm_import_name_by_mech() @ src/gss_names.c:355 [0:0]
[1684837520] ALLOK: gssntlm_acquire_cred_from() @ src/gss_creds.c:501 [0:0]
[1684837520] ERROR: gssntlm_init_sec_context() @ src/gss_sec_ctx.c:293 [589824:1314127873]
[1684837520] ALLOK: gssntlm_delete_sec_context() @ src/gss_sec_ctx.c:483 [0:0]
[1684837520] ALLOK: gssntlm_release_name() @ src/gss_names.c:633 [0:0]
[1684837520] ALLOK: gssntlm_release_name() @ src/gss_names.c:633 [0:0]
[1684837520] ALLOK: gssntlm_display_status() @ src/gss_err.c:139 [0:0]

Any idea what I am doing wrong ? Isn't base64 decoding the token I get and feeding it into gss-ntlmssp enough, do I have to do something else ? Btw., if I use the Kerberos Oid, and do a Proxy-Authenticate: Negotiate instead of NTLM, my test program works, so I think principally the Java GSSAPI is working.

signature without integrity does not match SSPI

When a security context does not having signing/integrity negotiated but NTLMSSP_NEGOTIATE_ALWAYS_SIGN is set SSPI will generate a signature of \x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00. This library generates a signature of \x00 * 16. I can't find this mentioned anywhere in MS-NLMP but the Davenport NTLM docs does mention this under "Dummy" Signing

This is used if the SSPI context was initialized without specifying support for message integrity. If the "Negotiate Always Sign" NTLM flag is established, calls to MakeSignature will succeed, returning the constant "signature":

0x01000000000000000000000000000000

Here are the various permutations I've tried:

Flags SSPI GSSAPI
0ยน N/Aยฒ N/Aยฒ
ALWAYS_SIGN 01000000000000000000000000000000 00000000000000000000000000000000
ALWAYS_SIGN, SIGN 010000007D9A8B2A8D70259900000000 01000000AE0D7D7DF4AF985800000000
ALWAYS_SIGN, SEAL N/Aยณ 00000000000000000000000000000000
ALWAYS_SIGN, SEAL, SIGN 0100000080363D8599F6A5D200000000 01000000B64F49F73A83493600000000

ยน - 0 means neither ALWAYS_SIGN, SIGN, or SEAL is set.
ยฒ - SSPI and GSSAPI always sets NTLMSSP_NEGOTIATE_ALWAYS_SIGN so I cannot test this there.
ยณ - Setting SEAL will always set SIGN for SSPI.

Just as an FYI, the seq number part of the dummy signature does not increment when signing a 2nd message using SSPI.

Credentials with dot ('.') in domain name are parsed improperly by get_enterprise_name

We use gssntlmssp for SMB server authentication with external user (both client and server are joined to AD, winbind is running).
When SMB user is using FQDN as domain name (with dots), gssntlmssp tries to authenticate wrong user and winbind fails the authentication.

Use-case:
Windows user is trying to map SMB drive manually via cmd.exe with custom '/user' parameter where domain is represented as FQDN:

net use x: \server_ip\share_name /user:my.domain.fqdn\username

We have the following problematic flow:
gssntlm_accept_sec_context -> gssntlm_import_name -> gssntlm_import_name_by_mech -> get_enterprise_name

On the level of gssntlm_accept_sec_context we have useratdom='[email protected]' and it is parsed by get_enterprise_name as whole username because it contains dots in domain name. I.e. gssntlmssp parses it
as domain=NULL and username='[email protected]'.
Expected behaviour is to parse it as domain='my.domain.fqdn' and username='username'.

Note - using FQDN as domain name is required in cases when short domain name is not unique in AD forest, for example
we have 'sales.us.mycompany.com' and 'sales.europe.mycompany.com'; in this case short domain name 'sales' is not unique and cannot be used.

In the code I see following commit related to this bug (see below). When the change is reverted, the issue is fixed.
I think that we need to handle "email address as username" use-case in other more safe way (check only for \@ in username, don't rely on dots in domain name) because dots in domain name is not "unlikely" but the required flow.

$ git show -p 12cfa317
commit 12cfa317b8cdee94d0c4a6daf30dec56cd8d8fe2
Author: Simo Sorce <[email protected]>
Date:   Tue Jan 6 14:24:58 2015 -0500

    Names with a . in the domain are enteprise names
    
    This allows people to put in an email address as the source name and
    have i treated automatically as an enterprise name as well.
    
    Although technically NetBIOS names can have dots it is unlikely and the
    user@domain form is generally undestood to be used with UPNs and email
    like addresses which use the DNS Domain Name.
    
    The fallback case for NetBIOS domain names with a dot is to configure the
    client to use the DOMAIN\user name form instead.

diff --git a/src/gss_names.c b/src/gss_names.c
index e76a3e8..1a35ed2 100644
--- a/src/gss_names.c
+++ b/src/gss_names.c
@@ -96,11 +96,18 @@ static uint32_t get_enterprise_name(uint32_t *minor_status,
     buf[len] = '\0';
 
     e = strstr(buf, "\\@");
+    if (e) {
+        /* remove escape */
+        memmove(e, e + 1, len - (e - buf));
+    } else {
+        /* check if domain part contains dot */
+        e = strchr(buf, '@');
+        if (e) {
+            e = strchr(e, '.');
+        }
+    }
     if (!e) return GSSERRS(0, GSS_S_UNAVAILABLE);
 
-    /* remove escape */
-    memmove(e, e + 1, len - (e - buf));
-
     *username = strdup(buf);
     if (NULL == *username) {
         set_GSSERR(ENOMEM);

gss_wrap/gss_unwrap should work on connection without NEGOTIATE_SEAL

Let's start with a bit of a background.

RFC 2222 originally specified the GSSAPI SASL mechanism for authentication. It didn't specifically tie the mechanism to Kerberos unlike the later RFC 4752 revision. As a last step of the authentication exchange the server sends a token with supported protection schemes and maximum token size to the client. This is encoded with GSS_Wrap API with conf_flag == 0. The client decodes it with GSS_Unwrap, chooses the preferred protection for rest of communication, and then encodes the reply with GSS_Wrap and sends it back to server.

Microsoft Exchange implements this mechanism for authentication to SMTP, IMAP and POP3 services. It works with Negotiate, Kerberos and NTLM protocols. The NTLM one is particularly tricky because the semantics for GSS_Warp/GSS_Unwrap are not fully covered by the specifications. So I went ahead, set up an Exchange server with Windows AD and tested what is really sent on the wire.


In case NEGOTIATE_SEAL is negotiated in the initial authentication the gss-ntlmssp library is already interoperable. The conf_flag is ignored (not a surprise since NTLM doesn't have a way to transmit the flag on the wire like Kerberos does), sealing and signing is applied.

In case NEGOTIATE_SEAL is NOT negotiated and NEGOTIATE_SIGN+NEGOTIATE_KEY_EXHANGE were negotiated the tokens should still be sealed with the computed key and signed. gss-ntlmssp currently doesn't implement that.

I didn't check the behavior for other flag combinations yet. I am not particularly interested in them because anything without MIC calculation downgrades the security beyond a point where latest Windows versions may reject it.


Notably, I would expect the GSS_Wrap behavior to align with the behavior of the EncryptMessage (NTLM) API on Windows with the data buffer not having the SECBUFFER_READONLY flag and the conf_flag flag matching the SECQOP_WRAP_NO_ENCRYPT flag. That means always sealing the data (at least for NTLM2 w/ key exchange) and ignoring the conf_flag flag.

Confusingly, the NegotiateStream specification is also defined in terms of GSS_Wrap/GSS_Unwrap methods. Unlike the SMTP authentication it behaves differently on NTLM where it sends the messages as <signature token><unsealed message> if NEGOTIATE_SEAL was not specified. This difference is caused by a special NTLM code path in the NegotiateStream code that passes the SECBUFFER_READONLY flag to the EncryptMessage/DecryptMessage methods. The equivalent GSSAPI transformation is to call gss_get_mic to produce the <signature token> and use gss_verify_mic to verify it. This cannot be expressed with GSS_Wrap/GSS_Unwrap directly.

GSS_C_MA_AUTH_INIT_ANON

If you support GSS_C_ANON_FLAG, you should list GSS_C_MA_AUTH_INIT_ANON as a supported mechanism attribute. Future versions of Heimdal may exclude mechanisms from negotiation that do not support this attribute, if the initiator requested GSS_C_ANON_FLAG.

LmCompatibilityLevel 0 LM_KEY Wrapping

I was playing around with different NTLM versions and found that when LmCompatibilityLevel is 0 through the LM_COMPAT_LEVEL env var this mech fails to wrap the data properly when talking to a MS NTLM endpoint.

gss-ntlmssp is currently set up to set the NTLMSSP_NEGOTIATE_LM_KEY flag at this LM level and it seems like the KXKEY or maybe the SEALKEY method in MS-NLMP isn't documented properly as none of the implementations I've read or worked on handle this in a way that works in the real world.

The authentication process works, when you go to wrap the data on the client and then unwrap it on the MS server, the MS server fails saying the message or signature has been altered. If I was to compile the code and have it not set the LM_KEY flag the wrapping and unwrapping work just fine for the 0 LM compat level so my guess is there's something wrong with the MS docs.

Because this is woefully outdated and no one in their right mind should be using this compat level I'm all good if you just close this. Just thought I would let you know.

gssntlm_acquire_cred_from fails with ENOENT for external credentials if NTLM_USER_FILE is unset

Using the latest code from github, I'm runing gss-server + gss-client utilities with gssntlmssp plugin installed.
My computer is joined to AD (has 'host' service keys in krb5.keytab file), it has winbind running and I use AD (external) credentials to run the simple test:

$ gss-server host

$ gss-client -mech '{1.3.6.1.4.1.311.2.2.10}' -user 'AD_DOMAIN\test_user' -pass 'password' localhost host HELLO

I'm getting this unexpected error from server-side:

starting...
GSS-API error accepting context: Unspecified GSS failure.  Minor code may provide more information
GSS-API error accepting context: No such file or directory

After debugging I found the root-cause:
[1600941819] ERROR: gssntlm_acquire_cred_from() @ src/gss_creds.c:445 [851968:2]

#0  gssntlm_acquire_cred_from (minor_status=minor_status@entry=0x7fffffffd9ec, desired_name=0x555555762e60, time_req=time_req@entry=4294967295, desired_mechs=desired_mechs@entry=0x0, 
    cred_usage=cred_usage@entry=1, cred_store=0x0, output_cred_handle=output_cred_handle@entry=0x7fffffffda38, actual_mechs=actual_mechs@entry=0x0, time_rec=time_rec@entry=0x0)
    at src/gss_creds.c:397
#1  0x00007ffff5bc383c in gssntlm_accept_sec_context (minor_status=0x7fffffffe11c, context_handle=0x55555575a090, acceptor_cred_handle=<optimized out>, input_token=<optimized out>, 
    input_chan_bindings=0x0, src_name=0x7fffffffe008, mech_type=0x7fffffffe018, output_token=0x7fffffffe170, ret_flags=0x7fffffffdff4, time_rec=0x0, delegated_cred_handle=0x0)
    at src/gss_sec_ctx.c:890
#2  0x00007ffff7b9d6d6 in gss_accept_sec_context () from /lib64/libgssapi_krb5.so.2

The bug is inside gssntlm_acquire_cred_from() function in this section of code:

    if (cred_usage == GSS_C_INITIATE) {
        if (name != NULL && name->type != GSSNTLM_NAME_USER) {
            set_GSSERRS(ERR_NOUSRNAME, GSS_S_BAD_NAMETYPE);
            goto done;
        }

        if (cred_store != GSS_C_NO_CRED_STORE) {
            retmin = get_creds_from_store(name, cred, cred_store);
        } else {
            char *filename;

            filename = get_user_file_envvar();
            if (!filename) {
                set_GSSERRS(ENOENT, GSS_S_CRED_UNAVAIL);
                goto done;
            }
            retmin = get_user_file_creds(filename, name, cred);
            if (retmin) {
                retmin = external_get_creds(name, cred);
            }

            free(filename);
        }

The problem is that external_get_creds() is even NOT TRIED if get_user_file_envvar() returned NULL and ENOENT is returned immediately without winbind calls.
I.e. if local users file environment variable NTLM_USER_FILE is not set then external credentials are skipped.
Expected behaviour is to use external users regardless of NTLM_USER_FILE variable (it should be optional).

I think that this bug have been done recently into this commit:

Date:   Mon Jul 20 15:45:45 2020 -0400

    Add ability to pass keyfile via cred store

Why does MIC calculation depend on srv_time

This is in reference to: https://github.com/simo5/gss-ntlmssp/blob/e498737a96e8832a2cb9141ab1fe51e129185a48/src/ntlm.c#L821.
Could you please explain why this is done like this: Why MIC calculation depends on srv_time?

The reason I ask is that I am seeing an authentication failure while trying to connect and the most striking difference I see between a successful and unsuccessful authentication is MIC.

Below is the packet trace of the successful and unsuccessful authentication attempts:
Archive.zip

Service name from SPN is incorrectly dropped

The SPN named imported using GSS_C_NT_HOSTBASED_SERVICE drops the service name (

gss-ntlmssp/src/gss_names.c

Lines 297 to 300 in 9b6493b

retmaj = string_split(&retmin, '@',
input_name_buffer->value,
input_name_buffer->length,
NULL, &name->data.server.name);
). That's not in line with other NTLM implementations, including Windows, which preserve it. The other implementations simply convert the SERVICE@HOST format into SERVICE/HOST format which is the included in full in the AVID structure (MsvAvTargetName).

gss-ntlmssp can crash while processing authentication

This is originally discussed here: dotnet/runtime#83540
It looks like recent regression and I can provide core dumps if needed.
So far it manifested for us on RedHat 7 but it may not be limited to thais

[toweinfu@toweinfu-rh7 System.Net.Mail.Functional.Tests]$ rpm -qi  gssntlmssp
Name        : gssntlmssp
Version     : 1.2.0
Release     : 1.el7
Architecture: x86_64
Install Date: Thu 09 Mar 2023 06:29:25 PM UTC
Group       : System Environment/Libraries
Size        : 137341
License     : LGPLv3+
Signature   : RSA/SHA256, Tue 21 Feb 2023 04:30:30 PM UTC, Key ID 6a2faea2352c64e5
Source RPM  : gssntlmssp-1.2.0-1.el7.src.rpm
Build Date  : Tue 21 Feb 2023 02:14:11 PM UTC
Build Host  : buildhw-x86-12.iad2.fedoraproject.org
Relocations : (not relocatable)
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : https://fedorahosted.org/gss-ntlmssp
Bug URL     : https://bugz.fedoraproject.org/gssntlmssp
Summary     : GSSAPI NTLMSSP Mechanism
Description :
A GSSAPI Mechanism that implements NTLMSSP
(lldb) r
Process 2230 launched: '../../correlation-payload/dotnet' (x86_64)
  Discovering: System.Net.Mail.Functional.Tests (method display = ClassAndMethod, method display options = None)
  Discovered:  System.Net.Mail.Functional.Tests (found 155 of 156 test cases)
  Starting:    System.Net.Mail.Functional.Tests (parallel test collections = on, max threads = 2)
Process 2230 stopped
* thread #11: tid = 2256, 0x00007fff74e9331f gssntlmssp.so`ntlm_decode_u16l_str_hdr(str_hdr=0x00007fbeb001266c, buffer=0x00007fbeb0009ba0, payload_offs=56, str=0x00007fbecabfbd40, ctx=0x0000000000000000) + 111 at ntlm.c:328, name = '.NET Long Runni', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
    frame #0: 0x00007fff74e9331f gssntlmssp.so`ntlm_decode_u16l_str_hdr(str_hdr=0x00007fbeb001266c, buffer=0x00007fbeb0009ba0, payload_offs=56, str=0x00007fbecabfbd40, ctx=0x0000000000000000) + 111 at ntlm.c:328
   325 	        safefree(out);
   326 	    } else {
   327 	        /* make sure to terminate output string */
-> 328 	        out[outlen] = '\0';
   329 	    }
   330
   331 	    *str = out;
(lldb) bt
* thread #11: tid = 2256, 0x00007fff74e9331f gssntlmssp.so`ntlm_decode_u16l_str_hdr(str_hdr=0x00007fbeb001266c, buffer=0x00007fbeb0009ba0, payload_offs=56, str=0x00007fbecabfbd40, ctx=0x0000000000000000) + 111 at ntlm.c:328, name = '.NET Long Runni', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
  * frame #0: 0x00007fff74e9331f gssntlmssp.so`ntlm_decode_u16l_str_hdr(str_hdr=0x00007fbeb001266c, buffer=0x00007fbeb0009ba0, payload_offs=56, str=0x00007fbecabfbd40, ctx=0x0000000000000000) + 111 at ntlm.c:328
    frame #1: 0x00007fff74e94b2a gssntlmssp.so`ntlm_decode_chal_msg(ctx=<unavailable>, buffer=0x00007fbeb0009ba0, _flags=0x00007fbecabfbdd4, target_name=0x00007fbecabfbe08, challenge=0x00007fbecabfbe10, target_info=0x00007fbecabfbe20) + 186 at ntlm.c:1125
    frame #2: 0x00007fff74e9b394 gssntlmssp.so`gssntlm_init_sec_context(minor_status=0x00007fbecabfcb00, claimant_cred_handle=0x00007fbeb0012c30, context_handle=<unavailable>, target_name=<unavailable>, mech_type=<unavailable>, req_flags=<unavailable>, time_req=0, input_chan_bindings=0x0000000000000000, input_token=0x00007fbeb0009900, actual_mech_type=0x00007fbeb0013100, output_token=0x00007fbecabfc120, ret_flags=0x00007fbeb00130f0, time_rec=0x0000000000000000) + 2436 at gss_sec_ctx.c:290
    frame #3: 0x00007fff76297ecb libgssapi_krb5.so.2`gss_init_sec_context + 555
    frame #4: 0x00007fff762be6ef libgssapi_krb5.so.2`___lldb_unnamed_symbol372$$libgssapi_krb5.so.2 + 239
    frame #5: 0x00007fff762c046a libgssapi_krb5.so.2`___lldb_unnamed_symbol374$$libgssapi_krb5.so.2 + 1178
    frame #6: 0x00007fff76297ecb libgssapi_krb5.so.2`gss_init_sec_context + 555
    frame #7: 0x00007fffeeefacd7 libSystem.Net.Security.Native.so`NetSecurityNative_InitSecContextEx(minorStatus=0x00007fbecabfcb00, claimantCredHandle=0x00007fbeb00127e0, contextHandle=0x00007fbecabfc760, packageType=0, cbt=0x0000000000000000, cb

and note dotnet/runtime#83540 (comment)

Likely introduced by this security fix: c753000

When str_len is 0, the code takes goto done here, all ret, out and outlen are 0 and the code crashes here

NTLM fails on Ubuntu 22.04 with OpenSSL 3.0

It seems like OpenSSL 3.0 (at least on Ubuntu) retired md4.

# openssl md4
Error setting digest
4037123E367F0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:../crypto/evp/evp_fetch.c:349:Global default library context, Algorithm (MD4 : 88), Properties ()
4037123E367F0000:error:03000086:digital envelope routines:evp_md_init_internal:initialization error:../crypto/evp/digest.c:237:

authentication fails with unknown GSS error: dotnet/runtime#67353
Perhaps gss-ntlm should have fall-back implementation instead of depending on OpenSSL.

gssntlm_acquire_cred_from crashes due SIGSEGV when desired_name=NULL

Running samba winbind with gssntlmssp of the latest development version installed (got sources from github + compiled). Immediately after start I get this crash:

Program received signal SIGSEGV, Segmentation fault.
get_creds_from_store (name=name@entry=0x0, cred=cred@entry=0x5555558a6a40, cred_store=cred_store@entry=0x7fffffffd260) at src/gss_creds.c:239
239	src/gss_creds.c: No such file or directory.
(gdb) bt
#0  get_creds_from_store (name=name@entry=0x0, cred=cred@entry=0x5555558a6a40, cred_store=cred_store@entry=0x7fffffffd260) at src/gss_creds.c:239
#1  0x00007fffddb9a487 in gssntlm_acquire_cred_from (minor_status=0x7fffffffce34, desired_name=0x0, time_req=<optimized out>, desired_mechs=<optimized out>, cred_usage=<optimized out>, 
    cred_store=0x7fffffffd260, output_cred_handle=0x7fffffffcd60, actual_mechs=0x0, time_rec=0x0) at src/gss_creds.c:435
#2  0x00007fffede7d160 in gss_add_cred_from () from /lib64/libgssapi_krb5.so.2
#3  0x00007fffede7d7a9 in gss_acquire_cred_from () from /lib64/libgssapi_krb5.so.2
#4  0x00007fffedea622b in get_available_mechs () from /lib64/libgssapi_krb5.so.2
#5  0x00007fffedea643d in spnego_gss_acquire_cred_from () from /lib64/libgssapi_krb5.so.2
#6  0x00007fffede7d160 in gss_add_cred_from () from /lib64/libgssapi_krb5.so.2
#7  0x00007fffede7d7a9 in gss_acquire_cred_from () from /lib64/libgssapi_krb5.so.2
#8  0x00007ffff504fc7f in smb_gss_krb5_import_cred () from /usr/lib64/samba/libkrb5samba-samba4.so
#9  0x00007ffff10b7edf in gensec_gse_client_start () from /usr/lib64/samba/libgse-samba4.so
#10 0x00007ffff18fb91b in gensec_start_mech () from /usr/lib64/samba/libgensec-samba4.so
#11 0x00007ffff18fc71c in gensec_start_mech_by_ops () from /usr/lib64/samba/libgensec-samba4.so
#12 0x00007ffff18eb58d in gensec_spnego_client_negTokenInit_step () from /usr/lib64/samba/libgensec-samba4.so
#13 0x00007ffff18ebb4b in gensec_spnego_client_negTokenInit_start () from /usr/lib64/samba/libgensec-samba4.so
#14 0x00007ffff18ecc61 in gensec_spnego_update_send () from /usr/lib64/samba/libgensec-samba4.so
#15 0x00007ffff18fa940 in gensec_update_send () from /usr/lib64/samba/libgensec-samba4.so
#16 0x00007ffff3015835 in cli_session_setup_gensec_local_next () from /usr/lib64/samba/liblibsmb-samba4.so
#17 0x00007ffff3017287 in cli_session_setup_creds_send () from /usr/lib64/samba/liblibsmb-samba4.so
#18 0x00007ffff30179dd in cli_session_setup_creds () from /usr/lib64/samba/liblibsmb-samba4.so
#19 0x0000555555599727 in init_dc_connection_network ()
#20 0x00007ffff27a4ea4 in messaging_dispatch_classic () from /lib64/libsmbconf.so.0
#21 0x00007ffff27a5f51 in messaging_recv_cb () from /lib64/libsmbconf.so.0
#22 0x00007fffeecff5ba in msg_dgm_ref_recv () from /usr/lib64/samba/libmessages-dgm-samba4.so
#23 0x00007fffeecfd706 in messaging_dgm_read_handler () from /usr/lib64/samba/libmessages-dgm-samba4.so
#24 0x00007ffff5469153 in tevent_common_invoke_fd_handler () from /usr/lib64/samba/libtevent.so.0
#25 0x00007ffff546f587 in epoll_event_loop_once () from /usr/lib64/samba/libtevent.so.0
#26 0x00007ffff546d6a7 in std_event_loop_once () from /usr/lib64/samba/libtevent.so.0
#27 0x00007ffff546889d in _tevent_loop_once () from /usr/lib64/samba/libtevent.so.0
#28 0x000055555557b15c in main ()

As far as I see from backtrace and source code, the problem happens because Kerberos library calls gssntlm_acquire_cred_from with desired_name=NULL and library tries to de-reference it without proper check for NULL.

# 2
status = mech->gss_acquire_cred(minor_status, internal_name, time_req,
                    &target_mechs, cred_usage, &cred, NULL,
                    time_recp);

# 1
 if (cred_usage == GSS_C_INITIATE) {
        if (name != NULL && name->type != GSSNTLM_NAME_USER) {
            set_GSSERRS(ERR_NOUSRNAME, GSS_S_BAD_NAMETYPE);
            goto done;
        }

        if (cred_store != GSS_C_NO_CRED_STORE) {
            retmin = get_creds_from_store(name, cred, cred_store);
        } else {

# 0

static int get_creds_from_store(struct gssntlm_name *name,
                                struct gssntlm_cred *cred,
                                gss_const_key_value_set_t cred_store)
{
    uint32_t i;
    int ret;

    /* special case to let server creds carry a keyfile */
    if (name->type == GSSNTLM_NAME_SERVER) {

Debug-log for gssntlmssp cannot be collected for process with nonempty permitted capability set

We use gssntlmssp from SMB server (NTLM authentication) and we need to enable logging feature for gssntlmssp.
Logging is already supported here in some basic way via GSSNTLMSSP_DEBUG environment variable.
However in the code 'secure_getenv' function is used to fetch it:

void gssntlm_debug_init(void)
{
...
    env = secure_getenv("GSSNTLMSSP_DEBUG");

From 'man secure_getenv':

The  GNU-specific secure_getenv() function is just like getenv() except that it returns NULL in cases where "secure execution" is required.
...
*  the process has a nonempty permitted capability set

Alas, in SMB server we need to listen SMB port 445 (lower port < 1024) so cap_net_bind_service is specially set for this.
Bottom line - our process can't enable logging in any way because secure_getenv always returns NULL. We need some optional way to enable logging.

how to build it for alpine 3.1

hi , is there any set of instruction we can follow to include it in alpine image

RUN apk add gss-ntlmssp is not working

pls advise

Default channel bindings cause auth failure

I've found that when no channel bindings are specified, gss-ntlmssp sets MSV_AV_CHANNEL_BINDINGS to be 00000000000000000000000000000000. This causes issues on SSPI when it is set to process the channel bindings token. Typically most MS services that deal with channel bindings have 3 settings

  • Ignore - Do not validate the channel bindings if present
  • Accept - Validate the bindings but don't fail if not present
  • Required - Require and validate the bindings

I've found that when using gss-ntlmssp against an IIS site that is set to either accept or require channel bindings in it's auth configuration, it will fail when processing the Authentication token.

While this doesn't cover the actual Windows setup, you can use the following script to test authentication against an IIS site that is configured to "accept" channel bindings

import base64
import gssapi
import ssl
import urllib3

from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes


def get_channel_bindings(server):
    cert_pem = ssl.get_server_certificate((server, 443))
    b_cert = ssl.PEM_cert_to_DER_cert(cert_pem)
    cert = x509.load_der_x509_certificate(b_cert, default_backend())

    hash_algorithm = cert.signature_hash_algorithm

    if hash_algorithm.name in ['md5', 'sha1']:
        digest = hashes.Hash(hashes.SHA256(), default_backend())
    else:
        digest = hashes.Hash(hash_algorithm, default_backend())

    digest.update(b_cert)
    b_cert_hash = digest.finalize()

    b_app_data = b"tls-server-end-point:" + b_cert_hash

    return gssapi.raw.ChannelBindings(application_data=b_app_data)


server = '192.168.56.6'
url = 'https://%s/' % server

# It's a pain to get the underlying socket of a request in Python so we just manually get the cert ourselves
channel_bindings = get_channel_bindings(server)
channel_bindings = None

warnings.simplefilter('ignore', category=urllib3.exceptions.InsecureRequestWarning)
http = urllib3.PoolManager(cert_reqs='CERT_NONE')

ntlm = gssapi.OID.from_int_seq('1.3.6.1.4.1.311.2.2.10')

username = gssapi.Name('vagrant', name_type=gssapi.NameType.user)
cred = gssapi.raw.acquire_cred_with_password(username, b'vagrant', usage='initiate', mechs=[ntlm]).creds
c = gssapi.SecurityContext(name=gssapi.Name('http@test', name_type=gssapi.NameType.hostbased_service),
                           creds=cred, mech=ntlm, usage='initiate', channel_bindings=channel_bindings)

out_token = base64.b64encode(c.step()).decode()
print("NTLM Negotiate: %s" % out_token)

resp = http.request('GET', url, headers={
    'Authorization': 'Negotiate %s' % out_token,
})

in_token = resp.headers['WWW-Authenticate'].split(' ')[1]
print("NTLM Challenge: %s" % in_token)

out_token = base64.b64encode(c.step(base64.b64decode(in_token))).decode()
print("NTLM Authenticate: %s" % out_token)

resp = http.request('GET', url, headers={
    'Authorization': 'Negotiate %s' % out_token,
})

if resp.status == 401:
    raise Exception("Authentication failed")

If you were to comment out channel_bindings = None then the authentication works just fine but when not setting the bindings the authentication fails. Here is the NTLM authentication token that was sent in this exchange

MessageType: NtlmAuthenticate (3)
Signature: "NTLMSSP\0"
Data:
  LmChallengeResponseFields:
    Len: 0
    MaxLen: 0
    BufferOffset: 72
  NtChallengeResponseFields:
    Len: 240
    MaxLen: 240
    BufferOffset: 72
  DomainNameFields:
    Len: 0
    MaxLen: 0
    BufferOffset: 0
  UserNameFields:
    Len: 14
    MaxLen: 14
    BufferOffset: 312
  WorkstationFields:
    Len: 26
    MaxLen: 26
    BufferOffset: 326
  EncryptedRandomSessionKeyFields:
    Len: 16
    MaxLen: 16
    BufferOffset: 352
  NegotiateFlags:
    raw: 3800728085
    flags:
    - NTLMSSP_NEGOTIATE_56 (2147483648)
    - NTLMSSP_NEGOTIATE_KEY_EXCH (1073741824)
    - NTLMSSP_NEGOTIATE_128 (536870912)
    - NTLMSSP_NEGOTIATE_VERSION (33554432)
    - NTLMSSP_NEGOTIATE_TARGET_INFO (8388608)
    - NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY (524288)
    - NTLMSSP_TARGET_TYPE_SERVER (131072)
    - NTLMSSP_NEGOTIATE_ALWAYS_SIGN (32768)
    - NTLMSSP_NEGOTIATE_NTLM (512)
    - NTLMSSP_NEGOTIATE_SIGN (16)
    - NTLMSSP_REQUEST_TARGET (4)
    - NTLMSSP_NEGOTIATE_UNICODE (1)
  Version:
    Major: 6
    Minor: 2
    Build: 0
    Reserved: '000000'
    NTLMRevision: 15
  MIC:
  Payload:
    LmChallengeResponse:
    NtChallengeResponse:
      ResponseType: NTLMv2
      NTProofStr: 55F53974A37F645DC6EAE24F616DCE99
      ClientChallenge:
        RespType: 1
        HiRespType: 1
        Reserved1: 0
        Reserved2: 0
        TimeStamp: '2020-06-06T04:21:11.7360608Z'
        ChallengeFromClient: F108B844B11ED8BD
        Reserved3: 0
        AvPairs:
        - AvId: MSV_AV_NB_COMPUTER_NAME (1)
          Value: WIN-OA4NAHNUCHT
        - AvId: MSV_AV_NB_DOMAIN_NAME (2)
          Value: WIN-OA4NAHNUCHT
        - AvId: MSV_AV_DNS_COMPUTER_NAME (3)
          Value: WIN-OA4NAHNUCHT
        - AvId: MSV_AV_DNS_DOMAIN_NAME (4)
          Value: WIN-OA4NAHNUCHT
        - AvId: MSV_AV_FLAGS (6)
          Value:
            raw: 0
            flags: []
        - AvId: MSV_AV_TIMESTAMP (7)
          Value: '2020-06-06T04:21:11.7360608Z'
        - AvId: MSV_AV_TARGET_NAME (9)
          Value: test
        - AvId: MSV_AV_CHANNEL_BINDINGS (10)
          Value: '00000000000000000000000000000000'
        - AvId: MSV_AV_EOL (0)
          Value:
        Reserved4: 0
    DomainName:
    UserName: vagrant
    Workstation: JBOREAN-LINUX
    EncryptedRandomSessionKey: F0B7AE8F117C4B596E4DA88D35500A05
  SessionKey: Failed to derive
RawData: 4E544C4D53535000030000000000000048000000F000F0004800000000000000000000000E000E00380100001A001A0046010000100010006001000015828AE2060200000000000F55F53974A37F645DC6EAE24F616DCE990101000000000000E0E5F4E8B93BD601F108B844B11ED8BD0000000001001E00570049004E002D004F00410034004E00410048004E00550043004800540002001E00570049004E002D004F00410034004E00410048004E00550043004800540003001E00570049004E002D004F00410034004E00410048004E00550043004800540004001E00570049004E002D004F00410034004E00410048004E005500430048005400060004000000000007000800E0E5F4E8B93BD6010900080074006500730074000A001000000000000000000000000000000000000000000000000000760061006700720061006E0074004A0042004F005200450041004E002D004C0049004E0055005800F0B7AE8F117C4B596E4DA88D35500A05

The MS-NLMP docs for this behaviour are somewhat vague but it states the checks occur when

If the AUTHENTICATE_MESSAGE contains a nonzero MsvAvChannelBindings AV_PAIR

I originally understood a nonzero pair meaning the value isn't 00000000000000000000000000000000 but it seems to be when the value isn't set at all.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.