12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * This file and its contents are supplied under the terms of the
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * You may only use this file in accordance with the terms of version
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * 1.0 of the CDDL.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * A full copy of the text of the CDDL should have accompanied this
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * source. A copy of the CDDL is also available via the Internet at
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * http://www.illumos.org/license/CDDL.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * SPNEGO back-end for NTLMSSP. See [MS-NLMP]
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <sys/types.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <sys/byteorder.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <strings.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include "smbd.h"
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include "smbd_authsvc.h"
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include "netsmb/ntlmssp.h"
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <assert.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/* A shorter alias for a crazy long name from [MS-NLMP] */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#define NTLMSSP_NEGOTIATE_NTLM2 \
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/* Need this in a header somewhere */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#ifdef _LITTLE_ENDIAN
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/* little-endian values on little-endian */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#define htolel(x) ((uint32_t)(x))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#define letohl(x) ((uint32_t)(x))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#else /* (BYTE_ORDER == LITTLE_ENDIAN) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/* little-endian values on big-endian (swap) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#define letohl(x) BSWAP_32(x)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#define htolel(x) BSWAP_32(x)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#endif /* (BYTE_ORDER == LITTLE_ENDIAN) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rosstypedef struct ntlmssp_backend {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t expect_type;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t clnt_flags;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t srv_flags;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char srv_challenge[8];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross} ntlmssp_backend_t;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstruct genhdr {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char h_id[8]; /* "NTLMSSP" */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t h_type;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross};
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstruct sec_buf {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint16_t sb_length;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint16_t sb_maxlen;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t sb_offset;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross};
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstruct nego_hdr {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char h_id[8];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t h_type;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t h_flags;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* workstation domain, name (place holders) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint16_t ws_dom[4];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint16_t ws_name[4];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross};
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstruct auth_hdr {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char h_id[8];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t h_type;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct sec_buf h_lm_resp;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct sec_buf h_nt_resp;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct sec_buf h_domain;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct sec_buf h_user;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct sec_buf h_wksta;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct sec_buf h_essn_key; /* encrypted session key */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t h_flags;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Version struct (optional) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* MIC hash (optional) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross};
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/* Allow turning these off for debugging, etc. */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossint smbd_signing_enabled = 1;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossint smbd_constant_challenge = 0;
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic uint8_t constant_chal[8] = {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int smbd_ntlmssp_negotiate(authsvc_context_t *);
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int smbd_ntlmssp_authenticate(authsvc_context_t *);
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int encode_avpair_str(smb_msgbuf_t *, uint16_t, char *);
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int decode_secbuf_bin(smb_msgbuf_t *, struct sec_buf *, void **);
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int decode_secbuf_str(smb_msgbuf_t *, struct sec_buf *, char **);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Initialize this context for NTLMSSP, if possible.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossint
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmbd_ntlmssp_init(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ntlmssp_backend_t *be;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be = malloc(sizeof (*be));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be == 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_NO_MEMORY);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bzero(be, sizeof (*be));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->expect_type = NTLMSSP_MSGTYPE_NEGOTIATE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_backend = be;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossvoid
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmbd_ntlmssp_fini(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross free(ctx->ctx_backend);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Handle an auth message
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossint
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmbd_ntlmssp_work(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct genhdr *ihdr = ctx->ctx_ibodybuf;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ntlmssp_backend_t *be = ctx->ctx_backend;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t mtype;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int rc;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (ctx->ctx_ibodylen < sizeof (*ihdr))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_INVALID_PARAMETER);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (bcmp(ihdr->h_id, "NTLMSSP", 8))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_INVALID_PARAMETER);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mtype = letohl(ihdr->h_type);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (mtype != be->expect_type)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_INVALID_PARAMETER);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross switch (mtype) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross case NTLMSSP_MSGTYPE_NEGOTIATE:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_orawtype = LSA_MTYPE_ES_CONT;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smbd_ntlmssp_negotiate(ctx);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross break;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross case NTLMSSP_MSGTYPE_AUTHENTICATE:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_orawtype = LSA_MTYPE_ES_DONE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smbd_ntlmssp_authenticate(ctx);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross break;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross default:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross case NTLMSSP_MSGTYPE_CHALLENGE:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Sent by servers, not received. */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = NT_STATUS_INVALID_PARAMETER;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross break;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (rc);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#if (MAXHOSTNAMELEN < NETBIOS_NAME_SZ)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#error "MAXHOSTNAMELEN < NETBIOS_NAME_SZ"
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#endif
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Handle an NTLMSSP_MSGTYPE_NEGOTIATE message, and reply
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * with an NTLMSSP_MSGTYPE_CHALLENGE message.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * See: [MS-NLMP] 2.2.1.1, 3.2.5.1.1
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmbd_ntlmssp_negotiate(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char tmp_name[MAXHOSTNAMELEN];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ntlmssp_backend_t *be = ctx->ctx_backend;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct nego_hdr *ihdr = ctx->ctx_ibodybuf;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_msgbuf_t mb;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint8_t *save_scan;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int secmode;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int mbflags;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int rc;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross size_t var_start, var_end;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint16_t var_size;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (ctx->ctx_ibodylen < sizeof (*ihdr))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_INVALID_PARAMETER);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->clnt_flags = letohl(ihdr->h_flags);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Looks like we can ignore ws_dom, ws_name.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Otherwise would parse those here.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross secmode = smb_config_get_secmode();
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smbd_constant_challenge) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) memcpy(be->srv_challenge, constant_chal,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sizeof (be->srv_challenge));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross } else {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross randomize(be->srv_challenge, sizeof (be->srv_challenge));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Compute srv_flags
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags =
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_REQUEST_TARGET |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_NTLM |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_TARGET_INFO;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags |= be->clnt_flags & (
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_NTLM2 |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_128 |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_KEY_EXCH |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_56);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smbd_signing_enabled) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags |= be->clnt_flags & (
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_SIGN |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_SEAL |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_NEGOTIATE_ALWAYS_SIGN);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->clnt_flags & NTLMSSP_NEGOTIATE_UNICODE)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags |= NTLMSSP_NEGOTIATE_UNICODE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross else if (be->clnt_flags & NTLMSSP_NEGOTIATE_OEM)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags |= NTLMSSP_NEGOTIATE_OEM;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* LM Key is mutually exclusive with NTLM2 */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if ((be->srv_flags & NTLMSSP_NEGOTIATE_NTLM2) == 0 &&
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (be->clnt_flags & NTLMSSP_NEGOTIATE_LM_KEY) != 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Get our "target name" */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (secmode == SMB_SECMODE_DOMAIN) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_getdomainname(tmp_name, NETBIOS_NAME_SZ);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross } else {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags |= NTLMSSP_TARGET_TYPE_SERVER;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_getnetbiosname(tmp_name, NETBIOS_NAME_SZ);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (rc)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Build the NTLMSSP_MSGTYPE_CHALLENGE message.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbflags = SMB_MSGBUF_NOTERM;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->srv_flags & NTLMSSP_NEGOTIATE_UNICODE)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbflags |= SMB_MSGBUF_UNICODE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_msgbuf_init(&mb, ctx->ctx_obodybuf, ctx->ctx_obodylen, mbflags);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Fixed size parts
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_msgbuf_encode(
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &mb, "8clwwll8cllwwl", /* offset, name (fmt) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross "NTLMSSP", /* 0: signature (8c) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NTLMSSP_MSGTYPE_CHALLENGE, /* 8: type (l) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 0, 0, 0, /* filled later: 12: target name (wwl) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_flags, /* 20: flags (l) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_challenge, /* 24: (8c) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 0, 0, /* 32: reserved (ll) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 0, 0, 0); /* filled later: 40: target info (wwl) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#define TARGET_NAME_OFFSET 12
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#define TARGET_INFO_OFFSET 40
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (rc < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Variable length parts.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Target name
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross var_start = smb_msgbuf_used(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_msgbuf_encode(&mb, "u", tmp_name);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross var_end = smb_msgbuf_used(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross var_size = (uint16_t)(var_end - var_start);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (rc < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* overwrite target name offset+lengths */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross save_scan = mb.scan;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mb.scan = mb.base + TARGET_NAME_OFFSET;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) smb_msgbuf_encode(&mb, "wwl", var_size, var_size, var_start);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mb.scan = save_scan;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Target info (AvPairList)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * These AV pairs are like our name/value pairs, but have
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * numeric identifiers instead of names. There are many
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * of these, but we put only the four expected by Windows:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * NetBIOS computer name
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * NetBIOS domain name
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * DNS computer name
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * DNS domain name
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Note that "domain" above (even "DNS domain") refers to
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * the AD domain of which we're a member, which may be
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * _different_ from the configured DNS domain.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Also note that in "workgroup" mode (not a domain member)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * all "domain" fields should be set to the same values as
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * the "computer" fields ("bare" host name, not FQDN).
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross var_start = smb_msgbuf_used(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* NetBIOS Computer Name */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_getnetbiosname(tmp_name, NETBIOS_NAME_SZ))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (encode_avpair_str(&mb, MsvAvNbComputerName, tmp_name) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (secmode != SMB_SECMODE_DOMAIN) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Workgroup mode. Set all to hostname.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * tmp_name = netbios hostname from above.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (encode_avpair_str(&mb, MsvAvNbDomainName, tmp_name) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Want the bare computer name here (not FQDN).
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_gethostname(tmp_name, MAXHOSTNAMELEN, SMB_CASE_LOWER))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (encode_avpair_str(&mb, MsvAvDnsComputerName, tmp_name) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (encode_avpair_str(&mb, MsvAvDnsDomainName, tmp_name) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross } else {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Domain mode. Use real host and domain values.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* NetBIOS Domain Name */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_getdomainname(tmp_name, NETBIOS_NAME_SZ))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (encode_avpair_str(&mb, MsvAvNbDomainName, tmp_name) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* DNS Computer Name */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_getfqhostname(tmp_name, MAXHOSTNAMELEN))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (encode_avpair_str(&mb, MsvAvDnsComputerName, tmp_name) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* DNS Domain Name */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_getfqdomainname(tmp_name, MAXHOSTNAMELEN))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (encode_avpair_str(&mb, MsvAvDnsDomainName, tmp_name) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* End marker */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_msgbuf_encode(&mb, "ww", MsvAvEOL, 0) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross var_end = smb_msgbuf_used(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross var_size = (uint16_t)(var_end - var_start);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* overwrite target offset+lengths */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross save_scan = mb.scan;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mb.scan = mb.base + TARGET_INFO_OFFSET;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) smb_msgbuf_encode(&mb, "wwl", var_size, var_size, var_start);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mb.scan = save_scan;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_obodylen = smb_msgbuf_used(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_msgbuf_term(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->expect_type = NTLMSSP_MSGTYPE_AUTHENTICATE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rosserrout:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_msgbuf_term(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_INTERNAL_ERROR);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int
12b65585e720714b31036daaa2b30eb76014048eGordon Rossencode_avpair_str(smb_msgbuf_t *mb, uint16_t AvId, char *name)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int rc;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint16_t len;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross len = smb_wcequiv_strlen(name);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_msgbuf_encode(mb, "wwU", AvId, len, name);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (rc);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Handle an NTLMSSP_MSGTYPE_AUTHENTICATE message.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * See: [MS-NLMP] 2.2.1.3, 3.2.5.1.2
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmbd_ntlmssp_authenticate(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct auth_hdr hdr;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_msgbuf_t mb;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_logon_t user_info;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_token_t *token = NULL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ntlmssp_backend_t *be = ctx->ctx_backend;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross void *lm_resp;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross void *nt_resp;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char *domain;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char *user;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char *wksta;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross void *essn_key; /* encrypted session key (optional) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int mbflags;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint_t status = NT_STATUS_INTERNAL_ERROR;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char combined_challenge[SMBAUTH_CHAL_SZ];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross unsigned char kxkey[SMBAUTH_HASH_SZ];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross boolean_t ntlm_v1x = B_FALSE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bzero(&user_info, sizeof (user_info));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Parse the NTLMSSP_MSGTYPE_AUTHENTICATE message.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (ctx->ctx_ibodylen < sizeof (hdr))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_INVALID_PARAMETER);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbflags = SMB_MSGBUF_NOTERM;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->srv_flags & NTLMSSP_NEGOTIATE_UNICODE)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbflags |= SMB_MSGBUF_UNICODE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_msgbuf_init(&mb, ctx->ctx_ibodybuf, ctx->ctx_ibodylen, mbflags);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bzero(&hdr, sizeof (hdr));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_msgbuf_decode(&mb, "12.") < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (decode_secbuf_bin(&mb, &hdr.h_lm_resp, &lm_resp) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (decode_secbuf_bin(&mb, &hdr.h_nt_resp, &nt_resp) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (decode_secbuf_str(&mb, &hdr.h_domain, &domain) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (decode_secbuf_str(&mb, &hdr.h_user, &user) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (decode_secbuf_str(&mb, &hdr.h_wksta, &wksta) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (decode_secbuf_bin(&mb, &hdr.h_essn_key, &essn_key) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_msgbuf_decode(&mb, "l", &be->clnt_flags) < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->clnt_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (hdr.h_essn_key.sb_length < 16 || essn_key == NULL)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_level = NETR_NETWORK_LOGON;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_flags = 0;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_ntlm_flags = be->clnt_flags;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_username = (user) ? user : "";
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_domain = (domain) ? domain : "";
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_workstation = (wksta) ? wksta : "";
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_clnt_ipaddr =
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_clinfo.lci_clnt_ipaddr;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_local_port = 445;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_challenge_key.len = SMBAUTH_CHAL_SZ;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_challenge_key.val = (uint8_t *)be->srv_challenge;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_nt_password.len = hdr.h_nt_resp.sb_length;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_nt_password.val = nt_resp;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_lm_password.len = hdr.h_lm_resp.sb_length;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_lm_password.val = lm_resp;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_native_os = ctx->ctx_clinfo.lci_native_os;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_native_lm = ctx->ctx_clinfo.lci_native_lm;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * If we're doing extended session security, the challenge
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * this OWF was computed with is different. [MS-NLMP 3.3.1]
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * It's: MD5(concat(ServerChallenge,ClientChallenge))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * where the ClientChallenge is in the LM resp. field.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (user_info.lg_nt_password.len == SMBAUTH_LM_RESP_SZ &&
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_lm_password.len >= SMBAUTH_CHAL_SZ &&
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (be->clnt_flags & NTLMSSP_NEGOTIATE_NTLM2) != 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_auth_ntlm2_mkchallenge(combined_challenge,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_challenge, lm_resp);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_challenge_key.val =
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (uint8_t *)combined_challenge;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross user_info.lg_lm_password.len = 0;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ntlm_v1x = B_TRUE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * This (indirectly) calls smb_auth_validate() to
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * check that the client gave us a valid hash.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross token = smbd_user_auth_logon(&user_info);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (token == NULL) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross status = NT_STATUS_ACCESS_DENIED;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto errout;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (token->tkn_ssnkey.val != NULL &&
12b65585e720714b31036daaa2b30eb76014048eGordon Ross token->tkn_ssnkey.len == SMBAUTH_HASH_SZ) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * At this point, token->tkn_session_key is the
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * "Session Base Key" [MS-NLMP] 3.2.5.1.2
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Compute the final session key. First need the
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * "Key Exchange Key" [MS-NLMP] 3.4.5.1
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (ntlm_v1x) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_auth_ntlm2_kxkey(kxkey,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->srv_challenge, lm_resp,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross token->tkn_ssnkey.val);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross } else {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* KXKEY is the Session Base Key. */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) memcpy(kxkey, token->tkn_ssnkey.val,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross SMBAUTH_HASH_SZ);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * If the client give us an encrypted session key,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * decrypt it (RC4) using the "key exchange key".
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->clnt_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* RC4 args: result, key, data */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) smb_auth_RC4(token->tkn_ssnkey.val,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross SMBAUTH_HASH_SZ, kxkey, SMBAUTH_HASH_SZ,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross essn_key, hdr.h_essn_key.sb_length);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross } else {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Final key is the KXKEY */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) memcpy(token->tkn_ssnkey.val, kxkey,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross SMBAUTH_HASH_SZ);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_token = token;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_obodylen = 0;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_msgbuf_term(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rosserrout:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_msgbuf_term(&mb);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (status);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int
12b65585e720714b31036daaa2b30eb76014048eGordon Rossdecode_secbuf_bin(smb_msgbuf_t *mb, struct sec_buf *sb, void **binp)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int rc;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *binp = NULL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_msgbuf_decode(
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mb, "wwl",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &sb->sb_length,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &sb->sb_maxlen,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &sb->sb_offset);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (rc < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (rc);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (sb->sb_offset > mb->max)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (SMB_MSGBUF_UNDERFLOW);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (sb->sb_length > (mb->max - sb->sb_offset))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (SMB_MSGBUF_UNDERFLOW);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (sb->sb_length == 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (rc);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *binp = mb->base + sb->sb_offset;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int
12b65585e720714b31036daaa2b30eb76014048eGordon Rossdecode_secbuf_str(smb_msgbuf_t *mb, struct sec_buf *sb, char **cpp)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint8_t *save_scan;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int rc;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *cpp = NULL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_msgbuf_decode(
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mb, "wwl",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &sb->sb_length,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &sb->sb_maxlen,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &sb->sb_offset);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (rc < 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (rc);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (sb->sb_offset > mb->max)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (SMB_MSGBUF_UNDERFLOW);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (sb->sb_length > (mb->max - sb->sb_offset))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (SMB_MSGBUF_UNDERFLOW);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (sb->sb_length == 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (rc);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross save_scan = mb->scan;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mb->scan = mb->base + sb->sb_offset;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_msgbuf_decode(mb, "#u", (int)sb->sb_length, cpp);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mb->scan = save_scan;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (rc);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}