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 2012 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 ((err = smb_ctx_alloc(&ctx)) != 0) 119 return (NT_STATUS_NO_MEMORY); 120 121 /* 122 * Set server, share, domain, user 123 * (in the ctx handle). 124 */ 125 (void) smb_ctx_setfullserver(ctx, server); 126 (void) smb_ctx_setshare(ctx, "IPC$", USE_IPC); 127 (void) smb_ctx_setdomain(ctx, domain, B_TRUE); 128 (void) smb_ctx_setuser(ctx, user, B_TRUE); 129 130 /* 131 * Set auth. info (hash) and type. 132 */ 133 if (user[0] == '\0') { 134 authflags = SMB_AT_ANON; 135 } else { 136 (void) smb_config_getnum(SMB_CI_LM_LEVEL, &lmcl); 137 if (lmcl <= 2) { 138 /* Send NTLM */ 139 authflags = SMB_AT_NTLM1; 140 } else { 141 /* Send NTLMv2 */ 142 authflags = SMB_AT_NTLM2; 143 } 144 smb_ipc_get_passwd(nthash, sizeof (nthash)); 145 (void) smb_ctx_setpwhash(ctx, nthash, NULL); 146 } 147 (void) smb_ctx_setauthflags(ctx, authflags); 148 149 /* 150 * Do lookup, connect, session setup, tree connect. 151 * Or find and reuse a session/tree, if one exists. 152 */ 153 if ((err = smb_ctx_resolve(ctx)) != 0) { 154 err = NT_STATUS_BAD_NETWORK_PATH; 155 goto errout; 156 } 157 if ((err = smb_ctx_get_ssn(ctx)) != 0) { 158 err = NT_STATUS_NETWORK_ACCESS_DENIED; 159 goto errout; 160 } 161 if ((err = smb_ctx_get_tree(ctx)) != 0) { 162 err = NT_STATUS_BAD_NETWORK_NAME; 163 goto errout; 164 } 165 166 /* Success! */ 167 *ctx_p = ctx; 168 return (0); 169 170 errout: 171 smb_ctx_free(ctx); 172 return (err); 173 } 174