smb_smb.c revision 9c9af2590af49bb395bc8d2eace0f2d4ea16d165
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copyright (c) 2000-2001 Boris Popov
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * All rights reserved.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Redistribution and use in source and binary forms, with or without
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * modification, are permitted provided that the following conditions
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * are met:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 1. Redistributions of source code must retain the above copyright
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * notice, this list of conditions and the following disclaimer.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 2. Redistributions in binary form must reproduce the above copyright
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * notice, this list of conditions and the following disclaimer in the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * documentation and/or other materials provided with the distribution.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 3. All advertising materials mentioning features or use of this software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * must display the following acknowledgement:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This product includes software developed by Boris Popov.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 4. Neither the name of the author nor the names of any co-contributors
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * may be used to endorse or promote products derived from this software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * without specific prior written permission.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SUCH DAMAGE.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * $Id: smb_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Use is subject to license terms.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * various SMB requests. Most of the routines merely packs data into mbufs.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/param.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/systm.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/kmem.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/proc.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/lock.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/socket.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/uio.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/random.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/note.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/cmn_err.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef APPLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/smb_apple.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/utfconv.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_osdep.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_conn.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_rq.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_subr.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_tran.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Largest size to use with LARGE_READ/LARGE_WRITE.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Specs say up to 64k data bytes, but Windows traffic
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * uses 60k... no doubt for some good reason.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (Probably to keep 4k block alignment.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX: Move to smb.h maybe?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define SMB_MAX_LARGE_RW_SIZE (60*1024)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Default timeout values, all in seconds.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Make these tunable (only via mdb for now).
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_notice = 15;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_default = 30; /* was SMB_DEFRQTIMO */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_open = 45;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_read = 45;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_write = 60; /* was SMBWRTTIMO */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint smb_timo_append = 90;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross/*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Debug/test feature to disable NTMLv2.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Set this to zero to skip NTLMv2
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rossint nsmb_enable_ntlmv2 = 1;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int smb_smb_read(struct smb_share *ssp, u_int16_t fid,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int smb_smb_write(struct smb_share *ssp, u_int16_t fid,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rossstatic int smb_smb_readx(struct smb_share *ssp, u_int16_t fid,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rossstatic int smb_smb_writex(struct smb_share *ssp, u_int16_t fid,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstruct smb_dialect {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int d_id;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *d_name;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow};
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_unichar smb_unieol = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic struct smb_dialect smb_dialects[] = {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_CORE, "PC NETWORK PROGRAM 1.0"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_LANMAN1_0, "LANMAN1.0"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_LANMAN2_0, "LM1.2X002"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_LANMAN2_1, "LANMAN2.1"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {SMB_DIALECT_NTLM0_12, "NT LM 0.12"},
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {-1, NULL}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow};
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define SMB_DIALECT_MAX \
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (sizeof (smb_dialects) / sizeof (struct smb_dialect) - 2)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Number of seconds between 1970 and 1601 year
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowconst u_int64_t DIFF1970TO1601 = 11644473600ULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_time_local2server(struct timespec *tsp, int tzoff, long *seconds)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX - what if we connected to the server when it was in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * daylight savings/summer time and we've subsequently switched
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * to standard time, or vice versa, so that the time zone
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * offset we got from the server is now wrong?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *seconds = tsp->tv_sec - tzoff * 60;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* - tz.tz_minuteswest * 60 - (wall_cmos_clock ? adjkerntz : 0) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX - what if we connected to the server when it was in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * daylight savings/summer time and we've subsequently switched
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * to standard time, or vice versa, so that the time zone
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * offset we got from the server is now wrong?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tsp->tv_sec = seconds + tzoff * 60;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* + tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tsp->tv_nsec = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Time from server comes as UTC, so no need to use tz
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_time_NT2local(u_int64_t nsec, int tzoff, struct timespec *tsp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_time_local2NT(struct timespec *tsp, int tzoff, u_int64_t *nsec)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow long seconds;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_time_local2server(tsp, 0, &seconds);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *nsec = (((u_int64_t)(seconds) & ~1) + DIFF1970TO1601) *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (u_int64_t)10000000;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#if defined(NOICONVSUPPORT) || defined(lint)
4bff34e37def8a90f9194d81bc345c52ba20086athurlowextern int iconv_open(const char *to, const char *from, void **handle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlowextern int iconv_close(void *handle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_dialect *dp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_sopt *sp = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int8_t wc, stime[8], sblen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t dindex, tw, tw1, swlen, bc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int unicode = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *servercs;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow void *servercshandle = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow void *localcshandle = NULL;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross int negotiated_signing = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t toklen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * We set various flags below to keep track of
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * interesting things we learn from negotiation.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Clear all the flags except these two, which
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * are operational rather than protocol info.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_flags &= (SMBV_GONE | SMBV_RECONNECTING);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Now vc_hflags and vc_hflags2. Careful with this:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Leave SMB_FLAGS2_UNICODE off so mb_put_dstring
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * marshalls the dialect strings in plain ascii.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * We'll turn that on below, if appropriate.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Note: These flags are marshalled into the request
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * when we call smb_rq_alloc, so changing them after
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * this point does not affect THIS request.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_hflags = SMB_FLAGS_CASELESS;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_hflags2 = (SMB_FLAGS2_ERR_STATUS |
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMB_FLAGS2_KNOWS_LONG_NAMES);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* User-level may ask for extended security. */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_vopt & SMBVOPT_EXT_SEC)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_hflags2 |= SMB_FLAGS2_EXT_SEC;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* Also clear any old key (for reconnect) */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_mackey != NULL) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_mackey = NULL;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_mackeylen = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_seqno = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp = &vcp->vc_sopt;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow bzero(sp, sizeof (struct smb_sopt));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow for (dp = smb_dialects; dp->d_id != -1; dp++) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, SMB_DT_DIALECT);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, dp->d_name, SMB_CS_NONE);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This request should not wait for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * connection state changes, etc.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_INTERNAL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uint16le(mdp, &dindex);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dindex > SMB_DIALECT_MAX) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBERROR(
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "Don't know how to talk with server %s (%d)\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_srvname, dindex);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow dp = smb_dialects + dindex;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dindex < SMB_DIALECT_MAX) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBERROR(
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "Server %s negotiated old dialect (%s)\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_srvname, dp->d_name);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_proto = dp->d_id;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("Dialect %s (%d, %d)\n", dp->d_name, dindex, wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dp->d_id >= SMB_DIALECT_NTLM0_12) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 17)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &sp->sv_sm);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &sp->sv_maxmux);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &sp->sv_maxvcs);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_maxtx);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_maxraw);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_skey);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_caps);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_mem(mdp, (char *)stime, 8, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, (u_int16_t *)&sp->sv_tz);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &sblen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_uint16le(mdp, &bc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* BEGIN CSTYLED */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Will we do SMB signing? Or block the connection?
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * The table below describes this logic. References:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * [Windows Server Protocols: MS-SMB, sec. 3.2.4.2.3]
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * http://msdn.microsoft.com/en-us/library/cc212511.aspx
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * http://msdn.microsoft.com/en-us/library/cc212929.aspx
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Srv/Cli | Required | Enabled | If Required | Disabled
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * ------------+----------+------------+-------------+-----------
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Required | Signed | Signed | Signed | Blocked [1]
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * ------------+----------+------------+-------------+-----------
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Enabled | Signed | Signed | Not Signed | Not Signed
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * ------------+----------+------------+-------------+-----------
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * If Required | Signed | Not Signed | Not Signed | Not Signed
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * ------------+----------+------------+-------------+-----------
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Disabled | Blocked | Not Signed | Not Signed | Not Signed
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * [1] Like Windows 2003 and later, we don't really implement
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * the "Disabled" setting. Instead we implement "If Required",
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * so we always sign if the server requires signing.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* END CSTYLED */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (sp->sv_sm & SMB_SM_SIGS_REQUIRE) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Server requires signing.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross negotiated_signing = 1;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } else if (sp->sv_sm & SMB_SM_SIGS) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Server enables signing (client's option).
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * If enabled locally, do signing.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_vopt & SMBVOPT_SIGNING_ENABLED)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross negotiated_signing = 1;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* else not signing. */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } else {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Server does not support signing.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * If we "require" it, bail now.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBERROR("Client requires signing "
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross "but server has it disabled.\n");
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = EBADRPC;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("Security signatures: %d\n",
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross negotiated_signing);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (negotiated_signing) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMB_VC_LOCK(vcp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_flags |= SMBV_WILL_SIGN;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMB_VC_UNLOCK(vcp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sp->sv_caps & SMB_CAP_UNICODE) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags |= SMBV_UNICODE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow unicode = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!(sp->sv_caps & SMB_CAP_STATUS32)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * They don't do NT error codes.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If we send requests with
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SMB_FLAGS2_ERR_STATUS set in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Flags2, Windows 98, at least,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * appears to send replies with that
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * bit set even though it sends back
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * DOS error codes. (They probably
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * just use the request header as
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * a template for the reply header,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * and don't bother clearing that bit.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Therefore, we clear that bit in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * our vc_hflags2 field.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 &= ~SMB_FLAGS2_ERR_STATUS;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dp->d_id == SMB_DIALECT_NTLM0_12 &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_maxtx < 4096 &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (sp->sv_caps & SMB_CAP_NT_SMBS) == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags |= SMBV_WIN95;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("Win95 detected\n");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 3 cases here:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 1) Extended security.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Read bc bytes below for security blob.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note that we DON'T put the Caps flag in outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * outtoklen = bc
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 2) No extended security, have challenge data and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * possibly a domain name (which might be zero
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * bytes long, meaning "missing").
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copy challenge stuff to vcp->vc_ch (sblen bytes),
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * then copy Cap flags and domain name (bc-sblen
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * bytes) to outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * outtoklen = bc-sblen+4, where the 4 is for the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Caps flag.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 3) No extended security, no challenge data, just
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * possibly a domain name.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copy Capsflags and domain name (bc) to outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * outtoklen = bc+4, where 4 is for the Caps flag
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Sanity check: make sure the challenge length
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * isn't bigger than the byte count.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sblen > bc) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow toklen = bc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (sblen && sblen <= SMB_MAXCHALLENGELEN &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_sm & SMB_SM_ENCRYPT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (char *)vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sblen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_chlen = sblen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow toklen -= sblen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags |= SMBV_ENCRYPT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * For servers that don't support unicode
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * there are 2 things we could do:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 1) Pass the server Caps flags up to the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * user level so the logic up there will
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * know whether the domain name is unicode
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (this is what I did).
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 2) Try to convert the non-unicode string
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * to unicode. This doubles the length of
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the outtok buffer and would be guessing that
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the string was single-byte ascii, and that
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * might be wrong. Why ask for trouble?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Warning: NetApp may omit the GUID */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!(sp->sv_caps & SMB_CAP_EXT_SECURITY)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No extended security.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Stick domain name, if present,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * and caps in outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow toklen = toklen + 4; /* space for Caps flags */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtoklen = toklen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtok = kmem_alloc(toklen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* first store server capability bits */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(vcp->vc_outtok ==
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (caddr_t)(((u_int32_t *)vcp->vc_outtok)));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *(u_int32_t *)(vcp->vc_outtok) = sp->sv_caps;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Then store the domain name if present;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * be sure to subtract 4 from the length
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * for the Caps flag.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (toklen > 4) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtok+4, toklen-4,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Extended security.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Stick the rest of the buffer in outtok.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtoklen = toklen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_outtok = kmem_alloc(toklen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp, vcp->vc_outtok, toklen,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 &= ~(SMB_FLAGS2_EXT_SEC|SMB_FLAGS2_DFS|
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_FLAGS2_ERR_STATUS|SMB_FLAGS2_UNICODE);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dp->d_id > SMB_DIALECT_CORE) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &tw);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_sm = (uchar_t)tw;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &tw);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_maxtx = tw;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &sp->sv_maxmux);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &sp->sv_maxvcs);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &tw); /* rawmode */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint32le(mdp, &sp->sv_skey);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc == 13) { /* >= LANMAN1 */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16(mdp, &tw); /* time */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16(mdp, &tw1); /* date */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, (u_int16_t *)&sp->sv_tz);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &swlen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (swlen > SMB_MAXCHALLENGELEN)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16(mdp, NULL); /* mbz */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (md_get_uint16le(mdp, &bc) != 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (bc < swlen)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (swlen && (sp->sv_sm & SMB_SM_ENCRYPT)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = md_get_mem(mdp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (char *)vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow swlen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_chlen = swlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_flags |= SMBV_ENCRYPT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else { /* an old CORE protocol */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 &= ~SMB_FLAGS2_KNOWS_LONG_NAMES;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sp->sv_maxmux = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uint32_t x;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Maximum outstanding requests.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_maxmux < 1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_maxmux = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Max VCs between server and client.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We only use one.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_maxvcs = sp->sv_maxvcs;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_maxvcs < 1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_maxvcs = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Maximum transfer size.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Sanity checks:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Spec. says lower limit is 1024. OK.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Let's be conservative about an upper limit here.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Win2k uses 16644 (and others) so 32k should be a
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * reasonable sanity limit for this value.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note that this limit does NOT affect READX/WRITEX
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * with CAP_LARGE_xxx, which we nearly always use.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_txmax = sp->sv_maxtx;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_txmax < 1024)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_txmax = 1024;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_txmax > 0x8000)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_txmax = 0x8000;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Max read/write sizes, WITHOUT overhead.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This is just the payload size, so we must
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * leave room for the SMB headers, etc.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * This is just the vc_txmax value, but
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * reduced and rounded down. Tricky bit:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Servers typically give us a value that's
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * some nice "round" number, i.e 0x4000 plus
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * some overhead, i.e. Win2k: 16644==0x4104
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Subtract for the SMB header (32) and the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SMB command word and byte vectors (34?),
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * then round down to a 512 byte multiple.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow x = (vcp->vc_txmax - 68) & 0xFE00;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_rxmax = x;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_wxmax = x;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("TZ = %d\n", sp->sv_tz);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("CAPS = %x\n", sp->sv_caps);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("maxmux = %d\n", vcp->vc_maxmux);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("maxvcs = %d\n", vcp->vc_maxvcs);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("txmax = %d\n", vcp->vc_txmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("rxmax = %d\n", vcp->vc_rxmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("wxmax = %d\n", vcp->vc_wxmax);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If the server supports Unicode, set up to use Unicode
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * when talking to them. Othewise, use code page 437.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (unicode)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow servercs = "ucs-2";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * todo: if we can't determine the server's encoding, we
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * need to try a best-guess here.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow servercs = "cp437";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#if defined(NOICONVSUPPORT) || defined(lint)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * REVISIT
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = iconv_open(servercs, "utf-8", &servercshandle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error != 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = iconv_open("utf-8", servercs, &localcshandle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error != 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow iconv_close(servercshandle);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_toserver)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow iconv_close(vcp->vc_toserver);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_tolocal)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow iconv_close(vcp->vc_tolocal);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_toserver = servercshandle;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_tolocal = localcshandle;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (unicode)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_hflags2 |= SMB_FLAGS2_UNICODE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowbad:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic void
4bff34e37def8a90f9194d81bc345c52ba20086athurlowget_ascii_password(struct smb_vc *vcp, int upper, char *pbuf)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *pw = smb_vc_getpass(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (upper)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_toupper(pw, pbuf, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow strncpy(pbuf, pw, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf[SMB_MAXPASSWORDLEN] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef APPLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic void
4bff34e37def8a90f9194d81bc345c52ba20086athurlowget_unicode_password(struct smb_vc *vcp, char *pbuf)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow strncpy(pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf[SMB_MAXPASSWORDLEN] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic uchar_t *
4bff34e37def8a90f9194d81bc345c52ba20086athurlowadd_name_to_blob(uchar_t *blobnames, struct smb_vc *vcp, const uchar_t *name,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t namelen, int nametype, int uppercase)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct ntlmv2_namehdr namehdr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *namebuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t *uninamebuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t uninamelen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (name != NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamebuf = kmem_alloc(2 * namelen, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (uppercase) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namebuf = kmem_alloc(namelen + 1, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_toupper((const char *)name, namebuf, namelen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namebuf[namelen] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamelen = smb_strtouni(uninamebuf, namebuf, namelen,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow UCONV_IGNORE_NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(namebuf, namelen + 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamelen = smb_strtouni(uninamebuf, (char *)name,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namelen, UCONV_IGNORE_NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamelen = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uninamebuf = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namehdr.type = htoles(nametype);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow namehdr.len = htoles(uninamelen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow bcopy(&namehdr, blobnames, sizeof (namehdr));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames += sizeof (namehdr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (uninamebuf != NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow bcopy(uninamebuf, blobnames, uninamelen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames += uninamelen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(uninamebuf, namelen * 2);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (blobnames);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic uchar_t *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rossmake_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross size_t *bloblen, size_t *blob_allocsz)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t *blob;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t blobsize;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t domainlen, srvlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct ntlmv2_blobhdr *blobhdr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct timespec now;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int64_t timestamp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t *blobnames;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ptrdiff_t diff;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX - the information at
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * http://davenport.sourceforge.net/ntlm.html#theNtlmv2Response
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * says that the "target information" comes from the Type 2 message,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * but, as we're not doing NTLMSSP, we don't have that.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Should we use the names from the NegProt response? Can we trust
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the NegProt response? (I've seen captures where the primary
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * domain name has an extra byte in front of it.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * For now, we don't trust it - we use vcp->vc_domain and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * vcp->vc_srvname, instead. We upper-case them and convert
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * them to Unicode, as that's what's supposed to be in the blob.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow domainlen = strlen(vcp->vc_domain);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow srvlen = strlen(vcp->vc_srvname);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobsize = sizeof (struct ntlmv2_blobhdr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow + 3*sizeof (struct ntlmv2_namehdr) + 4 + 2*domainlen + 2*srvlen;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *blob_allocsz = blobsize;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross blobhdr = kmem_zalloc(blobsize, KM_SLEEP);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross blob = (uchar_t *)blobhdr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobhdr->header = htolel(0x00000101);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow gethrestime(&now);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_time_local2NT(&now, 0, &timestamp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobhdr->timestamp = htoleq(timestamp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobhdr->client_nonce = client_nonce;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames = blob + sizeof (struct ntlmv2_blobhdr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames = add_name_to_blob(blobnames, vcp, (uchar_t *)vcp->vc_domain,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow domainlen, NAMETYPE_DOMAIN_NB, 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames = add_name_to_blob(blobnames, vcp, (uchar_t *)vcp->vc_srvname,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow srvlen, NAMETYPE_MACHINE_NB, 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow blobnames = add_name_to_blob(blobnames, vcp, NULL, 0, NAMETYPE_EOL, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow diff = (intptr_t)blobnames - (intptr_t)blob;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(diff == (ptrdiff_t)((size_t)diff));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *bloblen = (size_t)diff;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (blob);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * When not doing Kerberos, we can try, in order:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * NTLMv2
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * NTLM (and maybe LM)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * if the server supports encrypted passwords, or
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * plain-text with the ASCII password not upper-cased
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * plain-text with the ASCII password upper-cased
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * if it doesn't.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rosstypedef enum {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ClearUC, /* Cleartext p/w, upper case */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ClearMC, /* Cleartext p/w, mixed case */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross NTLMv1,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross NTLMv2,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ExtSec, /* Extended Security (Kerberos) */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross NullSes /* Null session (keep last) */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross} authtype_t;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int minauth;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_uniptr unipp = NULL, ntencpass = NULL;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross char *pp = NULL, *up = NULL, *ucup = NULL;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross char *ucdp = vcp->vc_domain; /* already upper case */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *encpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross size_t plen = 0, plen_alloc = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross size_t uniplen = 0, uniplen_alloc = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross size_t ucup_sl = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross authtype_t authtype;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross size_t ntlmv2_bloblen, ntlmv2_blob_allocsz;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t *ntlmv2_blob;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int64_t client_nonce;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int32_t caps;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t bl; /* BLOB length */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross u_int16_t bc; /* byte count */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow u_int16_t action;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross u_int16_t rpflags2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int declinedguest = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uchar_t v2hash[16];
4bff34e37def8a90f9194d81bc345c52ba20086athurlow static const char NativeOS[] = "Solaris";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow static const char LanMan[] = "NETSMB";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Most of the "capability" bits we offer should be copied
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * from those offered by the server, with a mask applied.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This is the mask of capabilies copied from the server.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Some others get special handling below.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow static const uint32_t caps_mask =
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_UNICODE |
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_LARGE_FILES |
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_CAP_NT_SMBS |
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMB_CAP_STATUS32;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow caps = vcp->vc_sopt.sv_caps & caps_mask;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow minauth = vcp->vc_vopt & SMBVOPT_MINAUTH;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * This function tries authentication types in a
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * sequence going stronger to weaker, until it
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * succeeds or runs into "minauth" and fails.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Extended security is a special case because
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * fall-back requires a return to user-level and
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * a new connection, new SMB negotiate, etc.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Null session is also special - no fall-back.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Otherwise if the server supports encryption,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * try NTLMv2, then NTLM, etc.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_intok)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross authtype = ExtSec;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross else if (vcp->vc_username[0] == '\0')
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross authtype = NullSes;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross else if ((vcp->vc_sopt.sv_sm & SMB_SM_USER) == 0) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* Share-level security. */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross authtype = NullSes;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } else {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* Have SMB_SM_USER. Encryption? */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (nsmb_enable_ntlmv2)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross authtype = NTLMv2;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross else
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross authtype = NTLMv1;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } else {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * This is normally disallowed
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * by the minauth check below.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross authtype = ClearMC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * If server does not support encryption,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * disable unicode too. (Spec. for this?)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if ((vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) == 0) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_flags & SMBV_UNICODE) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_toserver = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlowagain:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("authtype = %d\n", authtype);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Now disallow auth. types that fall below
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * the minimum strength configured.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * We hold no kmem here.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross switch (minauth) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case SMBVOPT_MINAUTH_NONE:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case SMBVOPT_MINAUTH_LM:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case SMBVOPT_MINAUTH_NTLM:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (authtype < NTLMv1) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto ssn_exit;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case SMBVOPT_MINAUTH_NTLMV2:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (authtype < NTLMv2) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = EAUTH;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto ssn_exit;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case SMBVOPT_MINAUTH_KERBEROS:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (authtype < ExtSec) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = EAUTH;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto ssn_exit;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross default:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("bad minauth 0x%x\n", minauth);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = EAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto ssn_exit;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * See comment in smb_iod_sendrq()
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * about vc_smbuid initialization.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_smbuid = SMB_UID_UNKNOWN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Within this switch, we may allocate either or both:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * encpass, ntencpass (len: plen_alloc, uniplen_alloc)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * and will free these below (see the label "bad")
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross switch (authtype) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case ExtSec:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * With extended security, the whole blob is
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * passed in from user-level (vc_intok)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ASSERT(vcp->vc_intok != NULL);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross caps |= SMB_CAP_EXT_SECURITY;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* XXX Need Session Key */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_intoklen > 65536 ||
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross !(vcp->vc_hflags2 & SMB_FLAGS2_EXT_SEC) ||
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* We hold no kmem here. */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = EINVAL;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto ssn_exit;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_smbuid = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case NullSes:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow unipp = &smb_unieol;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uniplen = sizeof (smb_unieol);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case NTLMv2:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Compute the LMv2 and NTLMv2 responses,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * derived from the challenge, the user name,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * the domain/workgroup into which we're
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * logging, and the Unicode password.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Construct the client nonce by getting
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * a bunch of random data.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (void) random_get_pseudo_bytes((void *)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross &client_nonce, sizeof (client_nonce));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Convert the user name to upper-case, as
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * that's what's used when computing LMv2
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * and NTLMv2 responses.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ucup_sl = strlen(vcp->vc_username);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ucup = kmem_alloc(ucup_sl + 1, KM_SLEEP);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_toupper((const char *)vcp->vc_username,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ucup, ucup_sl);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ucup[ucup_sl] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Compute the NTLMv2 hash, which is
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * derived from the NTLMv1 hash and
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * the upper-case user + domain.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_ntlmv2hash(vcp->vc_nthash,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ucup, ucdp, v2hash);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Compute the LMv2 response, derived from
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * the v2hash, the server challenge, and
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * the client nonce (random bits).
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Note: kmem_alloc encpass (plen)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_ntlmv2response(v2hash,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_challenge,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (uchar_t *)&client_nonce, 8,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (uchar_t **)&encpass, &plen);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross plen_alloc = plen;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross pp = encpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Construct the blob.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Note: kmem_alloc ntlmv2_blob
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ntlmv2_blob = make_ntlmv2_blob(vcp,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross client_nonce, &ntlmv2_bloblen,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross &ntlmv2_blob_allocsz);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Compute the NTLMv2 response, derived
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * from the server challenge, the
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * user name, the domain/workgroup
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * into which we're logging, the
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * blob, and the v2 hash.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Note: kmem_alloc ntencpass (uniplen)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_ntlmv2response(v2hash,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_challenge,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ntlmv2_blob, ntlmv2_bloblen,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (uchar_t **)&ntencpass, &uniplen);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uniplen_alloc = uniplen;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross unipp = ntencpass;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * If we negotiated signing, compute the MAC key
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * and start signing messages, but only on the
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * first non-null session login.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if ((vcp->vc_flags & SMBV_WILL_SIGN) &&
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross !(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_calcv2mackey(vcp, v2hash,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (uchar_t *)ntencpass, uniplen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross kmem_free(ucup, ucup_sl + 1);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross kmem_free(ntlmv2_blob, ntlmv2_blob_allocsz);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case NTLMv1:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Compute the LM response, derived
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * from the challenge and the ASCII
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * password. (If minauth allows it.)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross plen_alloc = plen = 24;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross encpass = kmem_zalloc(plen, KM_SLEEP);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (minauth < SMBVOPT_MINAUTH_NTLM) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_lmresponse(vcp->vc_lmhash,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_challenge,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (uchar_t *)encpass);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross pp = encpass;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Compute the NTLM response, derived from
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * the challenge and the NT hash.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uniplen_alloc = uniplen = 24;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ntencpass = kmem_alloc(uniplen, KM_SLEEP);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_lmresponse(vcp->vc_nthash,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_challenge,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (uchar_t *)ntencpass);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross unipp = ntencpass;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * If we negotiated signing, compute the MAC key
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * and start signing messages, but only on the
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * first non-null session login.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if ((vcp->vc_flags & SMBV_WILL_SIGN) &&
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross !(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_calcmackey(vcp, vcp->vc_nthash,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (uchar_t *)ntencpass, uniplen);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case ClearMC:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case ClearUC:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * We try w/o uppercasing first so Samba mixed case
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * passwords work. If that fails, we come back and
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * try uppercasing to satisfy OS/2 and Windows for
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Workgroups.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross plen_alloc = plen = SMB_MAXPASSWORDLEN + 1;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross encpass = kmem_zalloc(plen, KM_SLEEP);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross get_ascii_password(vcp, (authtype == ClearUC), encpass);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross plen = strlen(encpass) + 1;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross pp = encpass;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uniplen_alloc = uniplen = plen * 2;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ntencpass = kmem_alloc(uniplen, KM_SLEEP);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (void) smb_strtouni(ntencpass, smb_vc_getpass(vcp), 0, 0);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross plen--;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * The uniplen is zeroed because Samba cannot deal
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * with this 2nd cleartext password. This Samba
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * "bug" is actually a workaround for problems in
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Microsoft clients.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uniplen = 0; /* -= 2 */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross unipp = ntencpass;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross default:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ASSERT(0);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = EAUTH;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto ssn_exit;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } /* switch authtype */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross scred, &rqp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (error)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto bad;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Build the request.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow up = vcp->vc_username;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If userid is null we are attempting anonymous browse login
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * so passwords must be zero length.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (*up == '\0') {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = uniplen = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxtx);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxmux);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, vcp->vc_number);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, vcp->vc_sopt.sv_skey);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((SMB_DIALECT(vcp)) < SMB_DIALECT_NTLM0_12) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, plen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, pp, plen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* user */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, ucdp, SMB_CS_NONE); /* domain */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_intok) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, vcp->vc_intoklen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, 0); /* reserved */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, caps); /* my caps */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, vcp->vc_intok, vcp->vc_intoklen,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow MB_MSYSTEM); /* security blob */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, plen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, uniplen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, 0); /* reserved */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, caps); /* my caps */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, pp, plen, MB_MSYSTEM); /* password */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)unipp, uniplen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* user */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, ucdp, SMB_CS_NONE); /* dom */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, NativeOS, SMB_CS_NONE); /* OS */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, vcp, LanMan, SMB_CS_NONE); /* LAN Mgr */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This request should not wait for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * connection state changes, etc.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_INTERNAL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, SMBSSNSETUPTIMO);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rqp->sr_errclass == ERRDOS &&
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rqp->sr_serror == ERRnoaccess)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAUTH;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!(rqp->sr_errclass == ERRDOS &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_serror == ERRmoredata))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Parse the reply
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rpflags2 = rqp->sr_rpflags2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_smbuid = rqp->sr_rpuid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = md_get_uint8(mdp, &wc);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (error)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto bad;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = EBADRPC;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_intok) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (wc != 4)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto bad;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } else if (wc != 3)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto bad;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint8(mdp, NULL); /* secondary cmd */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint8(mdp, NULL); /* mbz */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, NULL); /* andxoffset */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &action); /* action */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_intok)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &bl); /* ext security */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &bc); /* byte count */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_intok) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_outtoklen = bl;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_outtok = kmem_alloc(bl, KM_SLEEP);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = md_get_mem(mdp, vcp->vc_outtok, bl, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross goto bad;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Server OS, LANMGR, & Domain follow here.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * XXX: Should store these strings (later).
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Windows systems do not suport CAP_LARGE_...
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * when signing is enabled, so adjust sv_caps.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Match first 8 characters of server's OS
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * with the UCS-2LE string: "Windows "
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (bc > 16) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross static const char WindowsU[16] =
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross "W\0i\0n\0d\0o\0w\0s\0 ";
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross char osbuf[16];
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* align(2) */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (((uintptr_t)mdp->md_pos) & 1)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint8(mdp, NULL);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross bzero(osbuf, sizeof (osbuf));
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_mem(mdp, osbuf, sizeof (osbuf), MB_MSYSTEM);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (0 == bcmp(WindowsU, osbuf, sizeof (osbuf))) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("Server is Windows\n");
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_flags & SMBV_WILL_SIGN) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("disable CAP_LARGE_(r/w)\n");
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_sopt.sv_caps &=
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ~(SMB_CAP_LARGE_READX
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross | SMB_CAP_LARGE_WRITEX);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* success! */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlowbad:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * When authentication fails and we're (possibly) doing
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * fall-back to another method, we have to reset things.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (error && vcp->vc_mackey) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_hflags2 &= ~SMB_FLAGS2_SECURITY_SIGNATURE;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_mackey = NULL;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_mackeylen = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross vcp->vc_seqno = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rqp) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_rq_done(rqp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rqp = NULL;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (encpass) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross kmem_free(encpass, plen_alloc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow encpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (ntencpass) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross kmem_free(ntencpass, uniplen_alloc);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ntencpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Shall we try again with another auth type?
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Note: We hold no kmem here.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross switch (authtype) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case NullSes:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case ExtSec:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* Error or not, we're done. (no fallback) */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case NTLMv2:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We're doing user-level authentication (so we are actually
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * sending authentication stuff over the wire), and we're
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * not doing extended security, and the stuff we tried
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * failed (or we we're trying to login a real user but
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * got granted guest access instead.)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * See radar 4134676. This check works around the way a
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * certain old server grants limited Guest access when we
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * try NTLMv2, but works fine with NTLM. The fingerprint
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * we are looking for is DOS error codes and no-Unicode.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Note XP grants Guest access but uses Unicode and
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * NT error codes.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (error == 0 && (action & SMB_ACT_GUEST) &&
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross !(rpflags2 & SMB_FLAGS2_ERR_STATUS) &&
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross !(rpflags2 & SMB_FLAGS2_UNICODE)) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* force fallback */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow declinedguest = 1;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = EAUTH;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* FALLTHROUGH */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case NTLMv1:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case ClearMC:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (error) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross authtype = authtype - 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto again;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross case ClearUC:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross default:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* no more fallbacks */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowssn_exit:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error && declinedguest)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBERROR("we declined ntlmv2 guest access. errno will be %d\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_ssnclose(struct smb_vc *vcp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_smbuid == SMB_UID_UNKNOWN)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Run this with a relatively short timeout.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We don't really care about the result,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * as we're just trying to play nice and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * "say goodbye" before we hangup.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX: Add SMBLOGOFFTIMO somewhere?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, 5);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic char smb_any_share[] = "?????";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic char *
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_share_typename(int stype)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *pp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (stype) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case STYPE_DISKTREE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "A:";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case STYPE_PRINTQ:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = smb_any_share; /* can't use LPT: here... */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case STYPE_DEVICE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "COMM";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case STYPE_IPC:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "IPC";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow default:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = smb_any_share;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (pp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq rq, *rqp = &rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *pp, *pbuf, *encpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *pw;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t hash[SMB_PWH_MAX];
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error, plen, caseopt;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int upper = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowagain:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp = SSTOVC(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Make this a "VC-level" request, so it will have
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * rqp->sr_share == NULL, and smb_iod_sendrq()
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * will send it with TID = SMB_TID_UNKNOWN
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This also serves to bypass the wait for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * share state changes, which this call is
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * trying to carry out.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No longer need to set ssp->ss_tid
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * here, but it's harmless enough.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_tid = SMB_TID_UNKNOWN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_CONNECT_ANDX,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow caseopt = SMB_CS_NONE;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_sopt.sv_sm & SMB_SM_USER) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = "";
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow encpass = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf = kmem_alloc(SMB_MAXPASSWORDLEN + 1, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow encpass = kmem_alloc(24, KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pw = smb_share_getpass(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We try w/o uppercasing first so Samba mixed case
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * passwords work. If that fails we come back and try
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * uppercasing to satisfy OS/2 and Windows for Workgroups.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (upper++) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_toupper(pw, pbuf, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_oldlm_hash(pw, hash);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow strncpy(pbuf, pw, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_ntlmv1hash(pw, hash);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pbuf[SMB_MAXPASSWORDLEN] = '\0';
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef NOICONVSUPPORT
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We need to convert here to the server codeset.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Initially we will send the same stuff and see what happens
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * witout the conversion. REVISIT.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow iconv_convstr(vcp->vc_toserver, pbuf, pbuf, SMB_MAXPASSWORDLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = 24;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_lmresponse(hash,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_challenge,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uchar_t *)encpass);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = encpass;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow plen = strlen(pbuf) + 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = pbuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0); /* Flags */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, plen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = mb_put_mem(mbp, pp, plen, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("error %d from mb_put_mem for pp\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dmem(mbp, vcp, "\\\\", 2, caseopt, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = vcp->vc_srvname;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_put_dmem(mbp, vcp, pp, strlen(pp), caseopt, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("error %d from smb_put_dmem for srvname\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dmem(mbp, vcp, "\\", 1, caseopt, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = ssp->ss_name;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_put_dstring(mbp, vcp, pp, caseopt);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("error %d from smb_put_dstring for ss_name\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* The type name is always ASCII */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pp = smb_share_typename(ssp->ss_type);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = mb_put_mem(mbp, pp, strlen(pp) + 1, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("error %d from mb_put_mem for ss_type\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Don't want to risk missing a successful
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * tree connect response.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_NOINTR_RECV;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto bad;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Success! */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_SS_LOCK(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_tid = rqp->sr_rptid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_vcgenid = vcp->vc_genid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_flags |= SMBS_CONNECTED;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_SS_UNLOCK(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowbad:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (encpass)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(encpass, 24);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (pbuf)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(pbuf, SMB_MAXPASSWORDLEN + 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error && upper == 1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto again;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ssp->ss_tid == SMB_TID_UNKNOWN)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Build this as a "VC-level" request, so it will
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * avoid testing the _GONE flag on the share,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * which has already been set at this point.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Add the share pointer "by hand" below, so
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * smb_iod_sendrq will plug in the TID.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp = SSTOVC(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_DISCONNECT, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_share = ssp; /* by hand */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef lint
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Run this with a relatively short timeout. (5 sec.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We don't really care about the result here, but we
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * do need to make sure we send this out, or we could
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * "leak" active tree IDs on interrupt or timeout.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The NOINTR_SEND flag makes this request immune to
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * interrupt or timeout until the send is done.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_NOINTR_SEND;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, 5);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ssp->ss_tid = SMB_TID_UNKNOWN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross/*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Common function for read/write with UIO.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Called by netsmb smb_usr_rw,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * smbfs_readvnode, smbfs_writevnode
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rossint
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rosssmb_rwuio(struct smb_share *ssp, uint16_t fid, uio_rw_t rw,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uio_t *uiop, smb_cred_t *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = SSTOVC(ssp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ssize_t save_resid;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t len, rlen, maxlen;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross int error = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross int (*iofun)(struct smb_share *, uint16_t, uint32_t *,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uio_t *, smb_cred_t *, int);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Determine which function to use,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * and the transfer size per call.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (SMB_DIALECT(vcp) >= SMB_DIALECT_NTLM0_12) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Using NT LM 0.12, so readx, writex.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Make sure we can represent the offset.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0 &&
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross return (EFBIG);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rw == UIO_READ) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross iofun = smb_smb_readx;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross maxlen = SMB_MAX_LARGE_RW_SIZE;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross else
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross maxlen = vcp->vc_rxmax;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } else { /* UIO_WRITE */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross iofun = smb_smb_writex;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross maxlen = SMB_MAX_LARGE_RW_SIZE;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross else
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross maxlen = vcp->vc_wxmax;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } else {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Using the old SMB_READ and SMB_WRITE so
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * we're limited to 32-bit offsets, etc.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * XXX: Someday, punt the old dialects.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if ((uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross return (EFBIG);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rw == UIO_READ) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross iofun = smb_smb_read;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross maxlen = vcp->vc_rxmax;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross } else { /* UIO_WRITE */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross iofun = smb_smb_write;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross maxlen = vcp->vc_wxmax;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross save_resid = uiop->uio_resid;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross while (uiop->uio_resid > 0) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* Lint: uio_resid may be 64-bits */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rlen = len = (uint32_t)min(maxlen, uiop->uio_resid);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("rw=%d, off %lld, len %d\n",
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rw, uiop->uio_loffset, len);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = (*iofun)(ssp, fid, &rlen, uiop, scred, timo);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Note: the iofun called uio_update, so
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * not doing that here as one might expect.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Quit the loop either on error, or if we
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * transferred less then requested.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (error || (rlen < len))
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross timo = 0; /* only first I/O should wait */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (error && (save_resid != uiop->uio_resid)) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Stopped on an error after having
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * successfully transferred data.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Suppress this error.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("error %d suppressed\n", error);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = 0;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross return (error);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross}
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rossstatic int
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rosssmb_smb_readx(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uio_t *uiop, smb_cred_t *scred, int timo)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t offlo, offhi, rlen;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint16_t lenhi, lenlo, off, doff;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross lenhi = (uint16_t)(*lenp >> 16);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross lenlo = (uint16_t)*lenp;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross offhi = (uint32_t)(uiop->uio_loffset >> 32);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross offlo = (uint32_t)uiop->uio_loffset;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff); /* no secondary command */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0); /* MBZ */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0); /* offset to secondary */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint32le(mbp, offlo); /* offset (low part) */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, lenlo); /* MaxCount */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, 1); /* MinCount */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* (only indicates blocking) */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint32le(mbp, lenhi); /* MaxCountHigh */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, lenlo); /* Remaining ("obsolete") */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint32le(mbp, offhi); /* offset (high part) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (timo == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = smb_timo_read;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 12) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL); /* data compaction mode */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &lenlo); /* data len ret. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, &doff); /* data offset */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &lenhi);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rlen = (lenhi << 16) | lenlo;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint16le(mdp, NULL); /* ByteCount */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Does the data offset indicate padding?
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Add up the gets above, we have:
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (doff > off) /* pad byte(s)? */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rlen == 0) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *lenp = rlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* paranoid */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rlen > *lenp) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("bad server! rlen %d, len %d\n",
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rlen, *lenp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rlen = *lenp;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = md_get_uio(mdp, uiop, rlen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *lenp = rlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rosssmb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uio_t *uiop, smb_cred_t *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t offlo, offhi, rlen;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint16_t lenhi, lenlo;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross lenhi = (uint16_t)(*lenp >> 16);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross lenlo = (uint16_t)*lenp;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross offhi = (uint32_t)(uiop->uio_loffset >> 32);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross offlo = (uint32_t)uiop->uio_loffset;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0xff); /* no secondary command */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, 0); /* MBZ */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0); /* offset to secondary */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint32le(mbp, offlo); /* offset (low part) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, 0); /* MBZ (timeout) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0); /* !write-thru */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 0);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, lenhi);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, lenlo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 64); /* data offset from header start */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint32le(mbp, offhi); /* offset (high part) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint8(mbp, 0); /* pad byte */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = mb_put_uio(mbp, uiop, *lenp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (timo == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = smb_timo_write;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 6) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint8(mdp, NULL); /* andx cmd */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint8(mdp, NULL); /* reserved */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, NULL); /* andx offset */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &lenlo); /* data len ret. */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, NULL); /* remaining */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &lenhi);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rlen = (lenhi << 16) | lenlo;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *lenp = rlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rosssmb_smb_read(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uio_t *uiop, smb_cred_t *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross int error;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t off32;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint16_t bc, cnt, dlen, rcnt, todo;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ASSERT(uiop->uio_loffset <= UINT32_MAX);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross off32 = (uint32_t)uiop->uio_loffset;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ASSERT(*lenp <= UINT16_MAX);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross cnt = (uint16_t)*lenp;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* This next is an "estimate" of planned reads. */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, cnt);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint32le(mbp, off32);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, todo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (timo == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = smb_timo_read;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 5) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &rcnt); /* ret. count */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); /* res. */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &bc); /* byte count */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint8(mdp, NULL); /* buffer format */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &dlen); /* data len */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (dlen < rcnt) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("oops: dlen=%d rcnt=%d\n",
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (int)dlen, (int)rcnt);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rcnt = dlen;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rcnt == 0) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *lenp = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* paranoid */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rcnt > cnt) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross SMBSDEBUG("bad server! rcnt %d, cnt %d\n",
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross (int)rcnt, (int)cnt);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross rcnt = cnt;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = md_get_uio(mdp, uiop, (int)rcnt);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *lenp = (int)rcnt;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rosssmb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uio_t *uiop, smb_cred_t *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mdchain *mdp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint32_t off32;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint16_t cnt, rcnt, todo;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross uint8_t wc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ASSERT(uiop->uio_loffset <= UINT32_MAX);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross off32 = (uint32_t)uiop->uio_loffset;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross ASSERT(*lenp <= UINT16_MAX);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross cnt = (uint16_t)*lenp;
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /* This next is an "estimate" of planned writes. */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, cnt);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint32le(mbp, off32);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, todo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, SMB_DT_DATA);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross mb_put_uint16le(mbp, cnt);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross error = mb_put_uio(mbp, uiop, *lenp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (timo == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = smb_timo_write;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getreply(rqp, &mdp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_get_uint8(mdp, &wc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (wc != 1) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADRPC;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross md_get_uint16le(mdp, &rcnt);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross *lenp = rcnt;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic u_int32_t smbechoes = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mbp = &rqp->sr_rq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint16le(mbp, 1); /* echo count */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note: the IOD calls this, so
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * this request must not wait for
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * connection state changes, etc.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_INTERNAL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple_timed(rqp, timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef APPLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_smb_checkdir(struct smb_share *ssp, void *dnp, char *name,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int nmlen, struct smb_cred *scred)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct mbchain *mbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CHECK_DIRECTORY, scred, &rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_getrequest(rqp, &mbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_wend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bstart(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mb_put_uint8(mbp, SMB_DT_ASCII);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * All we need to do is marshall the path: "\\"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (the root of the share) into this request.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We essentially in-line smbfs_fullpath() here,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * except no mb_put_padbyte (already aligned).
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_put_dstring(mbp, SSTOVC(ssp), "\\", SMB_CS_NONE);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_bend(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_rq_simple(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_rq_done(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif /* APPLE */