613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * CDDL HEADER START
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The contents of this file are subject to the terms of the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Common Development and Distribution License (the "License").
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * You may not use this file except in compliance with the License.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * or http://www.opensolaris.org/os/licensing.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * See the License for the specific language governing permissions
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * and limitations under the License.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If applicable, add the following below this CDDL HEADER, with the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * CDDL HEADER END
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Use is subject to license terms.
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Functions to setup connections (TCP and/or NetBIOS)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This has the fall-back logic for IP6, IP4, NBT
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <errno.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <stdio.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <string.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <strings.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <stdlib.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <unistd.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netdb.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <libintl.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <xti.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <assert.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/types.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/time.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/byteorder.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/socket.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/fcntl.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netinet/in.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netinet/tcp.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <arpa/inet.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netsmb/smb.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netsmb/smb_lib.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netsmb/netbios.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netsmb/nb_lib.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netsmb/smb_dev.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include "charsets.h"
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include "private.h"
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * SMB messages are up to 64K.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Let's leave room for two.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic int smb_tcpsndbuf = 0x20000;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic int smb_tcprcvbuf = 0x20000;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic int smb_connect_timeout = 30; /* seconds */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint smb_recv_timeout = 30; /* seconds */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint conn_tcp6(struct smb_ctx *, const struct sockaddr *, int);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint conn_tcp4(struct smb_ctx *, const struct sockaddr *, int);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint conn_nbt(struct smb_ctx *, const struct sockaddr *, char *);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Internal set sockopt for int-sized options.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Borrowed from: libnsl/rpc/ti_opts.c
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_setopt_int(int fd, int level, int name, int val)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct t_optmgmt oreq, ores;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct t_opthdr oh;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int ival;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross } opts;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* opt header */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross opts.oh.len = sizeof (opts);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross opts.oh.level = level;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross opts.oh.name = name;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross opts.oh.status = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross opts.ival = val;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross oreq.flags = T_NEGOTIATE;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross oreq.opt.buf = (void *)&opts;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross oreq.opt.len = sizeof (opts);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ores.flags = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ores.opt.buf = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ores.opt.maxlen = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (t_optmgmt(fd, &oreq, &ores) < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("t_opgmgnt, t_errno = %d", t_errno);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (t_errno == TSYSERR)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (errno);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (EPROTO);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ores.flags != T_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("flags 0x%x, status 0x%x",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (int)ores.flags, (int)opts.oh.status);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (EPROTO);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_setopts(int fd)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Set various socket/TCP options.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Failures here are not fatal -
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * just log a complaint.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * We don't need these two:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * SO_RCVTIMEO, SO_SNDTIMEO
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_setopt_int(fd, SOL_SOCKET, SO_SNDBUF, smb_tcpsndbuf);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("set SO_SNDBUF, err %d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_setopt_int(fd, SOL_SOCKET, SO_RCVBUF, smb_tcprcvbuf);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("set SO_RCVBUF, err %d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_setopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, 1);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("set SO_KEEPALIVE, err %d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_setopt_int(fd, IPPROTO_TCP, TCP_NODELAY, 1);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("set TCP_NODELAY, err %d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Set the connect timeout (in milliseconds). */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_setopt_int(fd, IPPROTO_TCP,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross TCP_CONN_ABORT_THRESHOLD,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_connect_timeout * 1000);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("set connect timeout, err %d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossconn_tcp6(struct smb_ctx *ctx, const struct sockaddr *sa, int port)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct sockaddr_in6 sin6;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char *dev = "/dev/tcp6";
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char paddrbuf[INET6_ADDRSTRLEN];
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct t_call sndcall;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int fd, err;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (sa->sa_family != AF_INET6) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("bad af %d", sa->sa_family);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (EINVAL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(sa, &sin6, sizeof (sin6));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sin6.sin6_port = htons(port);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("tcp6: %s (%d)",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross inet_ntop(AF_INET6, &sin6.sin6_addr,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross paddrbuf, sizeof (paddrbuf)), port);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fd = t_open(dev, O_RDWR, NULL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fd < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Assume t_errno = TSYSERR */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = errno;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross perror(dev);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((err = smb_setopts(fd)) != 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto errout;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (t_bind(fd, NULL, NULL) < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("t_bind t_errno %d", t_errno);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (t_errno == TSYSERR)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = errno;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = EPROTO;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto errout;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.addr.maxlen = sizeof (sin6);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.addr.len = sizeof (sin6);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.addr.buf = (void *) &sin6;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.opt.len = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.udata.len = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (t_connect(fd, &sndcall, NULL) < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = get_xti_err(fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("connect, err %d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto errout;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("tcp6: connected, fd=%d", fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->ct_tran_fd = fd;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosserrout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is used for both SMB over TCP (port 445)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * and NetBIOS - see conn_nbt().
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossconn_tcp4(struct smb_ctx *ctx, const struct sockaddr *sa, int port)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct sockaddr_in sin;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char *dev = "/dev/tcp";
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char paddrbuf[INET_ADDRSTRLEN];
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct t_call sndcall;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int fd, err;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (sa->sa_family != AF_INET) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("bad af %d", sa->sa_family);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (EINVAL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(sa, &sin, sizeof (sin));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sin.sin_port = htons(port);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("tcp4: %s (%d)",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross inet_ntop(AF_INET, &sin.sin_addr,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross paddrbuf, sizeof (paddrbuf)), port);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fd = t_open(dev, O_RDWR, NULL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fd < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Assume t_errno = TSYSERR */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = errno;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross perror(dev);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((err = smb_setopts(fd)) != 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto errout;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (t_bind(fd, NULL, NULL) < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("t_bind t_errno %d", t_errno);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (t_errno == TSYSERR)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = errno;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = EPROTO;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto errout;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.addr.maxlen = sizeof (sin);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.addr.len = sizeof (sin);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.addr.buf = (void *) &sin;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.opt.len = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sndcall.udata.len = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (t_connect(fd, &sndcall, NULL) < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = get_xti_err(fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("connect, err %d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto errout;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("tcp4: connected, fd=%d", fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->ct_tran_fd = fd;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosserrout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Open a NetBIOS connection (session, port 139)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The optional name parameter, if passed, means
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * we found the sockaddr via NetBIOS name lookup,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * and can just use that for our session request.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Otherwise (if name is NULL), we're connecting
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * by IP address, and need to come up with the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * NetBIOS name by other means.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossconn_nbt(struct smb_ctx *ctx, const struct sockaddr *saarg, char *name)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct sockaddr_in sin;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct sockaddr *sa;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char server[NB_NAMELEN];
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char workgroup[NB_NAMELEN];
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err, nberr, port;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(saarg, &sin, sizeof (sin));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sa = (struct sockaddr *)&sin;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross switch (sin.sin_family) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case AF_NETBIOS: /* our fake AF */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sin.sin_family = AF_INET;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case AF_INET:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross default:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("bad af %d", sin.sin_family);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (EINVAL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross port = IPPORT_NETBIOS_SSN;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If we have a NetBIOS name, just use it.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is the path taken when we've done a
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * NetBIOS name lookup on this name to get
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the IP address in the passed sa. Otherwise,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * we're connecting by IP address, and need to
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * figure out what NetBIOS name to use.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (name) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross strlcpy(server, name, sizeof (server));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("given name: %s", server);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross } else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Try a NetBIOS node status query,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * which searches for a type=[20] name.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If that doesn't work, just use the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * (fake) "*SMBSERVER" name.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("try node status");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross server[0] = '\0';
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross nberr = nbns_getnodestatus(ctx->ct_nb,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross &sin.sin_addr, server, workgroup);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (nberr == 0 && server[0] != '\0') {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Found the name. Save for reconnect. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("found name: %s", server);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross strlcpy(ctx->ct_srvname, server,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sizeof (ctx->ct_srvname));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross } else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("getnodestatus, nberr %d", nberr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross strlcpy(server, "*SMBSERVER", sizeof (server));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Establish the TCP connection.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Careful to close it on errors.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((err = conn_tcp4(ctx, sa, port)) != 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("TCP connect: err=%d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Connected. Do NetBIOS session request. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = nb_ssn_request(ctx, server);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("ssn_rq, err %d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->ct_tran_fd != -1) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(ctx->ct_tran_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->ct_tran_fd = -1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Make a new connection, or reconnect.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_connect(smb_ctx_t *ctx)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct sockaddr *sa;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err, err2;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct mbdata blob;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross memset(&blob, 0, sizeof (blob));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->ct_srvname[0] == '\0') {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("sername not set!");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (EINVAL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("server: %s", ctx->ct_srvname);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (smb_debug)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross dump_ctx("smb_iod_connect", ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This may be a reconnect, so
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * cleanup if necessary.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->ct_tran_fd != -1) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(ctx->ct_tran_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->ct_tran_fd = -1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Get local machine name.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Full name - not a NetBIOS name.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->ct_locname == NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_getlocalname(&ctx->ct_locname);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_error(dgettext(TEXT_DOMAIN,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "can't get local name"), err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * We're called with each IP address
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * already copied into ct_srvaddr.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->ct_flags |= SMBCF_RESOLVED;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sa = &ctx->ct_srvaddr.sa;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross switch (sa->sa_family) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case AF_INET6:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = conn_tcp6(ctx, sa, IPPORT_SMB);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case AF_INET:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = conn_tcp4(ctx, sa, IPPORT_SMB);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If port 445 was not listening, try port 139.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Note: Not doing NetBIOS name lookup here.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * We already have the IP address.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross switch (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case ECONNRESET:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case ECONNREFUSED:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err2 = conn_nbt(ctx, sa, NULL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err2 == 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case AF_NETBIOS:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Like AF_INET, but use NetBIOS ssn. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = conn_nbt(ctx, sa, ctx->ct_srvname);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross default:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("skipped family %d", sa->sa_family);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = EPROTONOSUPPORT;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("connect, err=%d", err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * Do SMB Negotiate Protocol.
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross */
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross err = smb_negprot(ctx, &blob);
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross if (err)
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross goto out;
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Empty user name means an explicit request for
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * NULL session setup, which is a special case.
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * If negotiate determined that we want to do
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * SMB signing, we have to turn that off for a
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * NULL session. [MS-SMB 3.3.5.3].
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->ct_user[0] == '\0') {
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross /* Null user should have null domain too. */
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross ctx->ct_domain[0] = '\0';
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross ctx->ct_authflags = SMB_AT_ANON;
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross ctx->ct_clnt_caps &= ~SMB_CAP_EXT_SECURITY;
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross ctx->ct_vcflags &= ~SMBV_WILL_SIGN;
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross /*
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * Do SMB Session Setup (authenticate)
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross *
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * If the server negotiated extended security,
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * run the SPNEGO state machine, otherwise do
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * one of the old-style variants.
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross */
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) {
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross err = smb_ssnsetup_spnego(ctx, &blob);
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross } else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * Server did NOT negotiate extended security.
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * Try NTLMv2, NTLMv1, or ANON (if enabled).
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross if (ctx->ct_authflags & SMB_AT_NTLM2) {
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross err = smb_ssnsetup_ntlm2(ctx);
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross } else if (ctx->ct_authflags & SMB_AT_NTLM1) {
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross err = smb_ssnsetup_ntlm1(ctx);
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross } else if (ctx->ct_authflags & SMB_AT_ANON) {
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross err = smb_ssnsetup_null(ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross } else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * Don't return EAUTH, because a new
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross * password prompt will not help.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross DPRINT("No NTLM authflags");
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross err = ENOTSUP;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mb_done(&blob);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(ctx->ct_tran_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->ct_tran_fd = -1;
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross } else {
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross /* Tell library code we have a session. */
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross ctx->ct_flags |= SMBCF_SSNACTIVE;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("tran_fd = %d", ctx->ct_tran_fd);
85e6b6747d07050e01ec91acef2453655821f9abGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}