| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| |
| /* |
| * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. |
| * Copyright 2017 Nexenta Systems, Inc. All rights reserved. |
| */ |
| |
| /* |
| * There used to be a "redirector" library, which has been replaced, |
| * leaving only the "glue" functions in this file that adapt this |
| * library to the interface provided by libsmbfs. |
| */ |
| |
| #include <errno.h> |
| #include <string.h> |
| #include <strings.h> |
| #include <unistd.h> |
| #include <priv.h> |
| |
| #include <netsmb/smbfs_api.h> |
| #include <smbsrv/libsmb.h> |
| #include <smbsrv/libmlsvc.h> |
| #include <libsmbrdr.h> |
| #include <mlsvc.h> |
| |
| #include <assert.h> |
| |
| void |
| smbrdr_initialize(void) |
| { |
| (void) smb_lib_init(); |
| } |
| |
| /* |
| * mlsvc_disconnect |
| * |
| * Disconnects the session with given server. |
| * The new conection manager is smart enough |
| * so that we don't need this to do anything. |
| */ |
| /* ARGSUSED */ |
| void |
| smbrdr_disconnect(const char *server) |
| { |
| } |
| |
| |
| /* |
| * smbrdr_logon |
| * |
| * I'm not sure this really needs to do anything, but for now |
| * let's go ahead and authenticate here so this can return a |
| * status reflecting the outcome of authentication. |
| * |
| * If this successfully builds an smb_ctx, it just frees it. |
| * The driver retains sessions for a little while after the |
| * last reference goes away, so the session created here will |
| * usually still exist when the next call to smbrdr_ctx_new |
| * asks for this server+user (immediately after this returns), |
| * and only one session setup will go over the wire. |
| */ |
| int |
| smbrdr_logon(char *srv, char *dom, char *user) |
| { |
| struct smb_ctx *ctx; |
| int err; |
| |
| err = smbrdr_ctx_new(&ctx, srv, dom, user); |
| if (err == 0) |
| smb_ctx_free(ctx); |
| return (err); |
| } |
| |
| void |
| smbrdr_ctx_free(struct smb_ctx *ctx) |
| { |
| smb_ctx_free(ctx); |
| } |
| |
| /* |
| * Setup a new SMB client context. |
| * |
| * Get the SMB server's configuration stuff and |
| * store it in the new client context object. |
| */ |
| int |
| smbrdr_ctx_new(struct smb_ctx **ctx_p, char *server, |
| char *domain, char *user) |
| { |
| struct smb_ctx *ctx = NULL; |
| uchar_t nthash[SMBAUTH_HASH_SZ]; |
| int64_t lmcl; |
| int authflags, err; |
| |
| assert(server != NULL); |
| assert(domain != NULL); |
| assert(user != NULL); |
| |
| if (server[0] == '\0') |
| return (NT_STATUS_INTERNAL_ERROR); |
| |
| if ((err = smb_ctx_alloc(&ctx)) != 0) |
| return (NT_STATUS_NO_MEMORY); |
| |
| /* |
| * Set server, share, domain, user |
| * (in the ctx handle). |
| */ |
| (void) smb_ctx_setfullserver(ctx, server); |
| (void) smb_ctx_setshare(ctx, "IPC$", USE_IPC); |
| (void) smb_ctx_setdomain(ctx, domain, B_TRUE); |
| (void) smb_ctx_setuser(ctx, user, B_TRUE); |
| |
| /* |
| * Set auth. info (hash) and type. |
| */ |
| if (user[0] == '\0') { |
| authflags = SMB_AT_ANON; |
| } else { |
| (void) smb_config_getnum(SMB_CI_LM_LEVEL, &lmcl); |
| if (lmcl <= 2) { |
| /* Send NTLM */ |
| authflags = SMB_AT_NTLM1; |
| } else { |
| /* Send NTLMv2 */ |
| authflags = SMB_AT_NTLM2; |
| } |
| smb_ipc_get_passwd(nthash, sizeof (nthash)); |
| (void) smb_ctx_setpwhash(ctx, nthash, NULL); |
| } |
| (void) smb_ctx_setauthflags(ctx, authflags); |
| |
| /* |
| * Do lookup, connect, session setup, tree connect. |
| * Or find and reuse a session/tree, if one exists. |
| */ |
| if ((err = smb_ctx_resolve(ctx)) != 0) { |
| err = NT_STATUS_BAD_NETWORK_PATH; |
| goto errout; |
| } |
| if ((err = smb_ctx_get_ssn(ctx)) != 0) { |
| switch (err) { |
| case EAUTH: |
| err = NT_STATUS_NETWORK_ACCESS_DENIED; |
| break; |
| default: |
| err = NT_STATUS_BAD_NETWORK_PATH; |
| break; |
| } |
| goto errout; |
| } |
| if ((err = smb_ctx_get_tree(ctx)) != 0) { |
| err = NT_STATUS_BAD_NETWORK_NAME; |
| goto errout; |
| } |
| |
| /* Success! */ |
| *ctx_p = ctx; |
| return (0); |
| |
| errout: |
| smb_ctx_free(ctx); |
| return (err); |
| } |