ntlmssp.c revision 427a21b56415a2c5048627d491e6e8da8d953bf1
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
* NT Lan Manager Security Support Provider (NTLMSSP)
*
* Based on information from the "Davenport NTLM" page:
*/
#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <netdb.h>
#include <libintl.h>
#include <xti.h>
#include <assert.h>
#include <sys/byteorder.h>
#include "private.h"
#include "charsets.h"
#include "spnego.h"
#include "derparse.h"
#include "ssp.h"
#include "ntlm.h"
#include "ntlmssp.h"
typedef struct ntlmssp_state {
char *ss_target_name;
struct mbuf *ss_target_info;
/*
* So called "security buffer".
* A lot like an RPC string.
*/
struct sec_buf {
};
#define ID_SZ 8
/*
* Get a "security buffer" (header part)
*/
static int
{
int err;
return (err);
}
/*
* Get a "security buffer" (data part), where
* the data is delivered as an mbuf.
*/
static int
{
int err;
/*
* Setup tmp_mb to point to the start of the header.
* This is a dup ref - do NOT free it.
*/
/* Skip data up to the offset. */
if (err)
return (err);
/* Get the data (as an mbuf). */
return (err);
}
/*
* Put a "security buffer" (header part)
*/
static int
{
int err;
return (err);
}
/*
* Put a "security buffer" (data part), where
* the data is an mbuf. Note: consumes m.
*/
static int
{
return (err);
}
/*
* Put a "security buffer" (data part), where
* the data is a string (OEM or unicode).
*
* The string is NOT null terminated.
*/
static int
const char *s, int unicode)
{
/*
* Put the string into a temp. mbuf,
* then chop off the null terminator
* before appending to caller's mbp.
*/
if (err)
return (err);
if (err)
return (err);
return (EFAULT);
/*
* Note: tmp_mb.mb_top is consumed,
* so do NOT free it (no mb_done)
*/
return (err);
}
/*
* Build a Type 1 message
*
* This message has a header section containing offsets to
* data later in the message. We use the common trick of
* building it in two parts and then concatenatening.
*/
int
{
struct type1hdr {
} hdr;
int err;
return (err);
/*
* Initialize the negotiation flags, and
* save what we sent. For reference:
* [MS-NLMP] spec. (also ntlmssp.h)
*/
else
}
/*
* Put the client domain, client name strings.
* These are always in OEM format, upper-case.
*/
goto out;
}
if (err)
goto out;
if (err)
goto out;
/*
* Marshal the header (in LE order)
* then concatenate the 2nd part.
*/
out:
return (err);
}
/*
* Parse a Type 2 message
*/
int
{
struct type2hdr {
struct sec_buf h_target_name;
} hdr;
struct mbuf *m;
goto out;
}
/*
* Save the mbdata pointers before we consume anything.
* Careful to NOT free this (would be dup. free)
* We use this below to find data based on offsets
* from the start of the header.
*/
/* Parse the fixed size header stuff. */
goto out;
}
/*
* Save flags, challenge for later.
*/
/*
* Now find out if the optional parts are there.
*/
}
/*
* Get the target name string. First get a copy of
* security buffer header; then parse the string.
*/
if (err)
goto out;
/*
* Get the target info blob, if present.
*/
&ssp_st->ss_target_info);
}
out:
return (err);
}
/*
* Build a Type 3 message
*
* This message has a header section containing offsets to
* data later in the message. We use the common trick of
* building it in two parts and then concatenatening.
*/
int
{
struct type3hdr {
} hdr;
/*
* Fill in the NTLMSSP header, etc.
*/
goto out;
/*
* Put the LMv2,NTLMv2 responses, or
* possibly LM, NTLM (v1) responses.
*/
/* Build the NTLMv2 "target info" blob. */
if (err)
goto out;
} else {
}
if (err)
goto out;
if (err)
goto out;
if (err)
goto out;
/*
* Put the "target" (domain), user, workstation
*/
if (err)
goto out;
if (err)
goto out;
if (err)
goto out;
/*
* Put the "Random Session Key". We don't set
* NTLMSSP_NEGOTIATE_KEY_EXCH, so it's empty.
* (In-line mb_put_sb_data here.)
*/
/*
* Marshal the header (in LE order)
* then concatenate the 2nd part.
*/
out:
return (err);
}
/*
* ntlmssp_final
*
* Called after successful authentication.
* Setup the MAC key for signing.
*/
int
{
int err = 0;
/*
* MAC_key is just the session key, but
* Only on the first successful auth.
*/
ctx->ct_mackeylen = 0;
goto out;
}
/*
* Apparently, the server used seq. no. zero
* for our previous message, so next is two.
*/
}
out:
return (err);
}
/*
* ntlmssp_next_token
*
* See ssp.c: ssp_ctx_next_token
*/
int
{
int err;
/* final call on successful auth. */
goto out;
}
/* Will build an ouptut token. */
if (err)
goto out;
/*
* When called with in_mb == NULL, it means
* this is the first call for this session,
* so put a Type 1 (initialize) token.
*/
goto out;
}
/*
* This is not the first call, so
* parse the response token we received.
* It should be a Type 2 (challenge).
* Then put a Type 3 (authenticate)
*/
if (err)
goto out;
out:
if (err)
return (err);
}
/*
* ntlmssp_ctx_destroy
*
* Destroy mechanism-specific data.
*/
void
{
}
}
/*
* ntlmssp_init_clnt
*
* Initialize a new NTLMSSP client context.
*/
int
{
(SMB_AT_NTLM2 | SMB_AT_NTLM1)) == 0) {
DPRINT("No NTLM authflags");
return (ENOTSUP);
}
return (ENOMEM);
return (0);
}