1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * There used to be a "redirector" library, which has been replaced,
  29  * leaving only the "glue" functions in this file that adapt this
  30  * library to the interface provided by libsmbfs.
  31  */
  32 
  33 #include <errno.h>
  34 #include <string.h>
  35 #include <strings.h>
  36 #include <unistd.h>
  37 #include <priv.h>
  38 
  39 #include <netsmb/smbfs_api.h>
  40 #include <smbsrv/libsmb.h>
  41 #include <smbsrv/libmlsvc.h>
  42 #include <libsmbrdr.h>
  43 #include <mlsvc.h>
  44 
  45 #include <assert.h>
  46 
  47 void
  48 smbrdr_initialize(void)
  49 {
  50         (void) smb_lib_init();
  51 }
  52 
  53 /*
  54  * mlsvc_disconnect
  55  *
  56  * Disconnects the session with given server.
  57  * The new conection manager is smart enough
  58  * so that we don't need this to do anything.
  59  */
  60 /* ARGSUSED */
  61 void
  62 smbrdr_disconnect(const char *server)
  63 {
  64 }
  65 
  66 
  67 /*
  68  * smbrdr_logon
  69  *
  70  * I'm not sure this really needs to do anything, but for now
  71  * let's go ahead and authenticate here so this can return a
  72  * status reflecting the outcome of authentication.
  73  *
  74  * If this successfully builds an smb_ctx, it just frees it.
  75  * The driver retains sessions for a little while after the
  76  * last reference goes away, so the session created here will
  77  * usually still exist when the next call to smbrdr_ctx_new
  78  * asks for this server+user (immediately after this returns),
  79  * and only one session setup will go over the wire.
  80  */
  81 int
  82 smbrdr_logon(char *srv, char *dom, char *user)
  83 {
  84         struct smb_ctx *ctx;
  85         int err;
  86 
  87         err = smbrdr_ctx_new(&ctx, srv, dom, user);
  88         if (err == 0)
  89                 smb_ctx_free(ctx);
  90         return (err);
  91 }
  92 
  93 void
  94 smbrdr_ctx_free(struct smb_ctx *ctx)
  95 {
  96         smb_ctx_free(ctx);
  97 }
  98 
  99 /*
 100  * Setup a new SMB client context.
 101  *
 102  * Get the SMB server's configuration stuff and
 103  * store it in the new client context object.
 104  */
 105 int
 106 smbrdr_ctx_new(struct smb_ctx **ctx_p, char *server,
 107         char *domain, char *user)
 108 {
 109         struct smb_ctx *ctx = NULL;
 110         uchar_t nthash[SMBAUTH_HASH_SZ];
 111         int64_t lmcl;
 112         int authflags, err;
 113 
 114         assert(server != NULL);
 115         assert(domain != NULL);
 116         assert(user != NULL);
 117 
 118         if (server[0] == '\0')
 119                 return (NT_STATUS_INTERNAL_ERROR);
 120 
 121         if ((err = smb_ctx_alloc(&ctx)) != 0)
 122                 return (NT_STATUS_NO_MEMORY);
 123 
 124         /*
 125          * Set server, share, domain, user
 126          * (in the ctx handle).
 127          */
 128         (void) smb_ctx_setfullserver(ctx, server);
 129         (void) smb_ctx_setshare(ctx, "IPC$", USE_IPC);
 130         (void) smb_ctx_setdomain(ctx, domain, B_TRUE);
 131         (void) smb_ctx_setuser(ctx, user, B_TRUE);
 132 
 133         /*
 134          * Set auth. info (hash) and type.
 135          */
 136         if (user[0] == '\0') {
 137                 authflags = SMB_AT_ANON;
 138         } else {
 139                 (void) smb_config_getnum(SMB_CI_LM_LEVEL, &lmcl);
 140                 if (lmcl <= 2) {
 141                         /* Send NTLM */
 142                         authflags = SMB_AT_NTLM1;
 143                 } else {
 144                         /* Send NTLMv2 */
 145                         authflags = SMB_AT_NTLM2;
 146                 }
 147                 smb_ipc_get_passwd(nthash, sizeof (nthash));
 148                 (void) smb_ctx_setpwhash(ctx, nthash, NULL);
 149         }
 150         (void) smb_ctx_setauthflags(ctx, authflags);
 151 
 152         /*
 153          * Do lookup, connect, session setup, tree connect.
 154          * Or find and reuse a session/tree, if one exists.
 155          */
 156         if ((err = smb_ctx_resolve(ctx)) != 0) {
 157                 err = NT_STATUS_BAD_NETWORK_PATH;
 158                 goto errout;
 159         }
 160         if ((err = smb_ctx_get_ssn(ctx)) != 0) {
 161                 err = NT_STATUS_NETWORK_ACCESS_DENIED;
 162                 goto errout;
 163         }
 164         if ((err = smb_ctx_get_tree(ctx)) != 0) {
 165                 err = NT_STATUS_BAD_NETWORK_NAME;
 166                 goto errout;
 167         }
 168 
 169         /* Success! */
 170         *ctx_p = ctx;
 171         return (0);
 172 
 173 errout:
 174         smb_ctx_free(ctx);
 175         return (err);
 176 }