/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
*/
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* SPNEGO back-end for NTLMSSP. See [MS-NLMP]
*/
#include <sys/byteorder.h>
#include <strings.h>
#include "smbd.h"
#include "smbd_authsvc.h"
#include <assert.h>
/* A shorter alias for a crazy long name from [MS-NLMP] */
#define NTLMSSP_NEGOTIATE_NTLM2 \
/* Need this in a header somewhere */
#ifdef _LITTLE_ENDIAN
/* little-endian values on little-endian */
#else /* (BYTE_ORDER == LITTLE_ENDIAN) */
/* little-endian values on big-endian (swap) */
#endif /* (BYTE_ORDER == LITTLE_ENDIAN) */
typedef struct ntlmssp_backend {
struct genhdr {
};
struct sec_buf {
};
struct nego_hdr {
/* workstation domain, name (place holders) */
};
struct auth_hdr {
/* Version struct (optional) */
/* MIC hash (optional) */
};
/* Allow turning these off for debugging, etc. */
int smbd_constant_challenge = 0;
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
static int smbd_ntlmssp_negotiate(authsvc_context_t *);
static int smbd_ntlmssp_authenticate(authsvc_context_t *);
/*
* Initialize this context for NTLMSSP, if possible.
*/
int
{
if (be == 0)
return (NT_STATUS_NO_MEMORY);
return (0);
}
void
{
}
/*
* Handle an auth message
*/
int
{
int rc;
return (NT_STATUS_INVALID_PARAMETER);
return (NT_STATUS_INVALID_PARAMETER);
return (NT_STATUS_INVALID_PARAMETER);
switch (mtype) {
break;
break;
default:
/* Sent by servers, not received. */
break;
}
return (rc);
}
#if (MAXHOSTNAMELEN < NETBIOS_NAME_SZ)
#error "MAXHOSTNAMELEN < NETBIOS_NAME_SZ"
#endif
/*
* Handle an NTLMSSP_MSGTYPE_NEGOTIATE message, and reply
* with an NTLMSSP_MSGTYPE_CHALLENGE message.
* See: [MS-NLMP] 2.2.1.1, 3.2.5.1.1
*/
static int
{
int secmode;
int mbflags;
int rc;
return (NT_STATUS_INVALID_PARAMETER);
/*
* Looks like we can ignore ws_dom, ws_name.
* Otherwise would parse those here.
*/
if (smbd_constant_challenge) {
sizeof (be->srv_challenge));
} else {
}
/*
* Compute srv_flags
*/
if (smbd_signing_enabled) {
}
/* LM Key is mutually exclusive with NTLM2 */
/* Get our "target name" */
if (secmode == SMB_SECMODE_DOMAIN) {
} else {
}
if (rc)
goto errout;
/*
* Build the NTLMSSP_MSGTYPE_CHALLENGE message.
*/
/*
* Fixed size parts
*/
"NTLMSSP", /* 0: signature (8c) */
NTLMSSP_MSGTYPE_CHALLENGE, /* 8: type (l) */
0, 0, 0, /* filled later: 12: target name (wwl) */
0, 0, /* 32: reserved (ll) */
0, 0, 0); /* filled later: 40: target info (wwl) */
if (rc < 0)
goto errout;
/*
* Variable length parts.
*
* Target name
*/
if (rc < 0)
goto errout;
/* overwrite target name offset+lengths */
/*
* Target info (AvPairList)
*
* numeric identifiers instead of names. There are many
* of these, but we put only the four expected by Windows:
* NetBIOS computer name
* NetBIOS domain name
* DNS computer name
* DNS domain name
* Note that "domain" above (even "DNS domain") refers to
* the AD domain of which we're a member, which may be
* _different_ from the configured DNS domain.
*
* Also note that in "workgroup" mode (not a domain member)
* all "domain" fields should be set to the same values as
* the "computer" fields ("bare" host name, not FQDN).
*/
/* NetBIOS Computer Name */
goto errout;
goto errout;
if (secmode != SMB_SECMODE_DOMAIN) {
/*
* Workgroup mode. Set all to hostname.
* tmp_name = netbios hostname from above.
*/
goto errout;
/*
* Want the bare computer name here (not FQDN).
*/
goto errout;
goto errout;
goto errout;
} else {
/*
* Domain mode. Use real host and domain values.
*/
/* NetBIOS Domain Name */
goto errout;
goto errout;
/* DNS Computer Name */
goto errout;
goto errout;
/* DNS Domain Name */
goto errout;
goto errout;
}
/* End marker */
goto errout;
/* overwrite target offset+lengths */
return (0);
return (NT_STATUS_INTERNAL_ERROR);
}
static int
{
int rc;
return (rc);
}
/*
* Handle an NTLMSSP_MSGTYPE_AUTHENTICATE message.
* See: [MS-NLMP] 2.2.1.3, 3.2.5.1.2
*/
static int
{
void *lm_resp;
void *nt_resp;
char *domain;
char *user;
char *wksta;
int mbflags;
/*
* Parse the NTLMSSP_MSGTYPE_AUTHENTICATE message.
*/
return (NT_STATUS_INVALID_PARAMETER);
goto errout;
goto errout;
goto errout;
goto errout;
goto errout;
goto errout;
goto errout;
goto errout;
goto errout;
}
/*
* If we're doing extended session security, the challenge
* this OWF was computed with is different. [MS-NLMP 3.3.1]
* It's: MD5(concat(ServerChallenge,ClientChallenge))
* where the ClientChallenge is in the LM resp. field.
*/
}
/*
* This (indirectly) calls smb_auth_validate() to
* check that the client gave us a valid hash.
*/
goto errout;
}
/*
* At this point, token->tkn_session_key is the
* "Session Base Key" [MS-NLMP] 3.2.5.1.2
* Compute the final session key. First need the
* "Key Exchange Key" [MS-NLMP] 3.4.5.1
*/
if (ntlm_v1x) {
} else {
/* KXKEY is the Session Base Key. */
}
/*
* If the client give us an encrypted session key,
* decrypt it (RC4) using the "key exchange key".
*/
/* RC4 args: result, key, data */
} else {
/* Final key is the KXKEY */
}
}
ctx->ctx_obodylen = 0;
return (0);
return (status);
}
static int
{
int rc;
mb, "wwl",
if (rc < 0)
return (rc);
return (SMB_MSGBUF_UNDERFLOW);
return (SMB_MSGBUF_UNDERFLOW);
return (rc);
return (0);
}
static int
{
int rc;
mb, "wwl",
if (rc < 0)
return (rc);
return (SMB_MSGBUF_UNDERFLOW);
return (SMB_MSGBUF_UNDERFLOW);
return (rc);
return (rc);
}