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 2017 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
47void
48smbrdr_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 */
61void
62smbrdr_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 */
81int
82smbrdr_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
93void
94smbrdr_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 */
105int
106smbrdr_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		switch (err) {
162		case EAUTH:
163			err = NT_STATUS_NETWORK_ACCESS_DENIED;
164			break;
165		default:
166			err = NT_STATUS_BAD_NETWORK_PATH;
167			break;
168		}
169		goto errout;
170	}
171	if ((err = smb_ctx_get_tree(ctx)) != 0) {
172		err = NT_STATUS_BAD_NETWORK_NAME;
173		goto errout;
174	}
175
176	/* Success! */
177	*ctx_p = ctx;
178	return (0);
179
180errout:
181	smb_ctx_free(ctx);
182	return (err);
183}
184