Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netsmb/smb_usr.c
39476 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2000-2001 Boris Popov
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#include <sys/param.h>
30
#include <sys/malloc.h>
31
#include <sys/kernel.h>
32
#include <sys/systm.h>
33
#include <sys/conf.h>
34
#include <sys/proc.h>
35
#include <sys/fcntl.h>
36
#include <sys/socket.h>
37
#include <sys/socketvar.h>
38
#include <sys/sysctl.h>
39
#include <sys/mbuf.h>
40
41
#include <sys/iconv.h>
42
43
#include <netsmb/smb.h>
44
#include <netsmb/smb_conn.h>
45
#include <netsmb/smb_rq.h>
46
#include <netsmb/smb_subr.h>
47
#include <netsmb/smb_dev.h>
48
49
/*
50
* helpers for nsmb device. Can be moved to the smb_dev.c file.
51
*/
52
static void smb_usr_vcspec_free(struct smb_vcspec *spec);
53
54
static int
55
smb_usr_vc2spec(struct smbioc_ossn *dp, struct smb_vcspec *spec)
56
{
57
int flags = 0;
58
59
bzero(spec, sizeof(*spec));
60
61
#ifdef NETSMB_NO_ANON_USER
62
if (dp->ioc_user[0] == 0)
63
return EINVAL;
64
#endif
65
66
if (dp->ioc_server == NULL)
67
return EINVAL;
68
if (dp->ioc_localcs[0] == 0) {
69
SMBERROR("no local charset ?\n");
70
return EINVAL;
71
}
72
73
spec->sap = smb_memdupin(dp->ioc_server, dp->ioc_svlen);
74
if (spec->sap == NULL)
75
return ENOMEM;
76
if (dp->ioc_local) {
77
spec->lap = smb_memdupin(dp->ioc_local, dp->ioc_lolen);
78
if (spec->lap == NULL) {
79
smb_usr_vcspec_free(spec);
80
return ENOMEM;
81
}
82
}
83
spec->srvname = dp->ioc_srvname;
84
spec->pass = dp->ioc_password;
85
spec->domain = dp->ioc_workgroup;
86
spec->username = dp->ioc_user;
87
spec->mode = dp->ioc_mode;
88
spec->rights = dp->ioc_rights;
89
spec->owner = dp->ioc_owner;
90
spec->group = dp->ioc_group;
91
spec->localcs = dp->ioc_localcs;
92
spec->servercs = dp->ioc_servercs;
93
if (dp->ioc_opt & SMBVOPT_PRIVATE)
94
flags |= SMBV_PRIVATE;
95
if (dp->ioc_opt & SMBVOPT_SINGLESHARE)
96
flags |= SMBV_PRIVATE | SMBV_SINGLESHARE;
97
spec->flags = flags;
98
return 0;
99
}
100
101
static void
102
smb_usr_vcspec_free(struct smb_vcspec *spec)
103
{
104
if (spec->sap)
105
smb_memfree(spec->sap);
106
if (spec->lap)
107
smb_memfree(spec->lap);
108
}
109
110
static int
111
smb_usr_share2spec(struct smbioc_oshare *dp, struct smb_sharespec *spec)
112
{
113
bzero(spec, sizeof(*spec));
114
spec->mode = dp->ioc_mode;
115
spec->rights = dp->ioc_rights;
116
spec->owner = dp->ioc_owner;
117
spec->group = dp->ioc_group;
118
spec->name = dp->ioc_share;
119
spec->stype = dp->ioc_stype;
120
spec->pass = dp->ioc_password;
121
return 0;
122
}
123
124
int
125
smb_usr_lookup(struct smbioc_lookup *dp, struct smb_cred *scred,
126
struct smb_vc **vcpp, struct smb_share **sspp)
127
{
128
struct smb_vc *vcp = NULL;
129
struct smb_vcspec vspec; /* XXX */
130
struct smb_sharespec sspec, *sspecp = NULL; /* XXX */
131
int error;
132
133
if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE)
134
return EINVAL;
135
error = smb_usr_vc2spec(&dp->ioc_ssn, &vspec);
136
if (error)
137
return error;
138
if (dp->ioc_flags & SMBLK_CREATE)
139
vspec.flags |= SMBV_CREATE;
140
141
if (dp->ioc_level >= SMBL_SHARE) {
142
error = smb_usr_share2spec(&dp->ioc_sh, &sspec);
143
if (error)
144
goto out;
145
sspecp = &sspec;
146
}
147
error = smb_sm_lookup(&vspec, sspecp, scred, &vcp);
148
if (error == 0) {
149
*vcpp = vcp;
150
*sspp = vspec.ssp;
151
}
152
out:
153
smb_usr_vcspec_free(&vspec);
154
return error;
155
}
156
157
/*
158
* Connect to the resource specified by smbioc_ossn structure.
159
* It may either find an existing connection or try to establish a new one.
160
* If no errors occurred smb_vc returned locked and referenced.
161
*/
162
int
163
smb_usr_opensession(struct smbioc_ossn *dp, struct smb_cred *scred,
164
struct smb_vc **vcpp)
165
{
166
struct smb_vc *vcp = NULL;
167
struct smb_vcspec vspec;
168
int error;
169
170
error = smb_usr_vc2spec(dp, &vspec);
171
if (error)
172
return error;
173
if (dp->ioc_opt & SMBVOPT_CREATE)
174
vspec.flags |= SMBV_CREATE;
175
176
error = smb_sm_lookup(&vspec, NULL, scred, &vcp);
177
smb_usr_vcspec_free(&vspec);
178
return error;
179
}
180
181
int
182
smb_usr_openshare(struct smb_vc *vcp, struct smbioc_oshare *dp,
183
struct smb_cred *scred, struct smb_share **sspp)
184
{
185
struct smb_share *ssp;
186
struct smb_sharespec shspec;
187
int error;
188
189
error = smb_usr_share2spec(dp, &shspec);
190
if (error)
191
return error;
192
error = smb_vc_lookupshare(vcp, &shspec, scred, &ssp);
193
if (error == 0) {
194
*sspp = ssp;
195
return 0;
196
}
197
if ((dp->ioc_opt & SMBSOPT_CREATE) == 0)
198
return error;
199
error = smb_share_create(vcp, &shspec, scred, &ssp);
200
if (error)
201
return error;
202
error = smb_smb_treeconnect(ssp, scred);
203
if (error) {
204
smb_share_put(ssp, scred);
205
} else
206
*sspp = ssp;
207
return error;
208
}
209
210
int
211
smb_usr_simplerequest(struct smb_share *ssp, struct smbioc_rq *dp,
212
struct smb_cred *scred)
213
{
214
struct smb_rq *rqp;
215
struct mbchain *mbp;
216
struct mdchain *mdp;
217
u_int8_t wc;
218
u_int16_t bc;
219
int error;
220
221
switch (dp->ioc_cmd) {
222
case SMB_COM_TRANSACTION2:
223
case SMB_COM_TRANSACTION2_SECONDARY:
224
case SMB_COM_CLOSE_AND_TREE_DISC:
225
case SMB_COM_TREE_CONNECT:
226
case SMB_COM_TREE_DISCONNECT:
227
case SMB_COM_NEGOTIATE:
228
case SMB_COM_SESSION_SETUP_ANDX:
229
case SMB_COM_LOGOFF_ANDX:
230
case SMB_COM_TREE_CONNECT_ANDX:
231
return EPERM;
232
}
233
rqp = malloc(sizeof(struct smb_rq), M_SMBTEMP, M_WAITOK);
234
error = smb_rq_init(rqp, SSTOCP(ssp), dp->ioc_cmd, scred);
235
if (error) {
236
free(rqp, M_SMBTEMP);
237
return error;
238
}
239
mbp = &rqp->sr_rq;
240
smb_rq_wstart(rqp);
241
error = mb_put_mem(mbp, dp->ioc_twords, dp->ioc_twc * 2, MB_MUSER);
242
if (error)
243
goto bad;
244
smb_rq_wend(rqp);
245
smb_rq_bstart(rqp);
246
error = mb_put_mem(mbp, dp->ioc_tbytes, dp->ioc_tbc, MB_MUSER);
247
if (error)
248
goto bad;
249
smb_rq_bend(rqp);
250
error = smb_rq_simple(rqp);
251
if (error)
252
goto bad;
253
mdp = &rqp->sr_rp;
254
md_get_uint8(mdp, &wc);
255
dp->ioc_rwc = wc;
256
wc *= 2;
257
if (wc > dp->ioc_rpbufsz) {
258
error = EBADRPC;
259
goto bad;
260
}
261
error = md_get_mem(mdp, dp->ioc_rpbuf, wc, MB_MUSER);
262
if (error)
263
goto bad;
264
md_get_uint16le(mdp, &bc);
265
if ((wc + bc) > dp->ioc_rpbufsz) {
266
error = EBADRPC;
267
goto bad;
268
}
269
dp->ioc_rbc = bc;
270
error = md_get_mem(mdp, dp->ioc_rpbuf + wc, bc, MB_MUSER);
271
bad:
272
dp->ioc_errclass = rqp->sr_errclass;
273
dp->ioc_serror = rqp->sr_serror;
274
dp->ioc_error = rqp->sr_error;
275
smb_rq_done(rqp);
276
free(rqp, M_SMBTEMP);
277
return error;
278
279
}
280
281
static int
282
smb_cpdatain(struct mbchain *mbp, int len, caddr_t data)
283
{
284
int error;
285
286
if (len == 0)
287
return 0;
288
error = mb_init(mbp);
289
if (error)
290
return error;
291
return mb_put_mem(mbp, data, len, MB_MUSER);
292
}
293
294
int
295
smb_usr_t2request(struct smb_share *ssp, struct smbioc_t2rq *dp,
296
struct smb_cred *scred)
297
{
298
struct smb_t2rq *t2p;
299
struct mdchain *mdp;
300
int error, len;
301
302
if (dp->ioc_setupcnt > 3)
303
return EINVAL;
304
t2p = malloc(sizeof(struct smb_t2rq), M_SMBTEMP, M_WAITOK);
305
error = smb_t2_init(t2p, SSTOCP(ssp), dp->ioc_setup[0], scred);
306
if (error) {
307
free(t2p, M_SMBTEMP);
308
return error;
309
}
310
len = t2p->t2_setupcount = dp->ioc_setupcnt;
311
if (len > 1)
312
t2p->t2_setupdata = dp->ioc_setup;
313
if (dp->ioc_name) {
314
t2p->t_name = smb_strdupin(dp->ioc_name, 128);
315
if (t2p->t_name == NULL) {
316
error = ENOMEM;
317
goto bad;
318
}
319
}
320
t2p->t2_maxscount = 0;
321
t2p->t2_maxpcount = dp->ioc_rparamcnt;
322
t2p->t2_maxdcount = dp->ioc_rdatacnt;
323
error = smb_cpdatain(&t2p->t2_tparam, dp->ioc_tparamcnt, dp->ioc_tparam);
324
if (error)
325
goto bad;
326
error = smb_cpdatain(&t2p->t2_tdata, dp->ioc_tdatacnt, dp->ioc_tdata);
327
if (error)
328
goto bad;
329
error = smb_t2_request(t2p);
330
if (error)
331
goto bad;
332
mdp = &t2p->t2_rparam;
333
if (mdp->md_top) {
334
len = m_fixhdr(mdp->md_top);
335
if (len > dp->ioc_rparamcnt) {
336
error = EMSGSIZE;
337
goto bad;
338
}
339
dp->ioc_rparamcnt = len;
340
error = md_get_mem(mdp, dp->ioc_rparam, len, MB_MUSER);
341
if (error)
342
goto bad;
343
} else
344
dp->ioc_rparamcnt = 0;
345
mdp = &t2p->t2_rdata;
346
if (mdp->md_top) {
347
len = m_fixhdr(mdp->md_top);
348
if (len > dp->ioc_rdatacnt) {
349
error = EMSGSIZE;
350
goto bad;
351
}
352
dp->ioc_rdatacnt = len;
353
error = md_get_mem(mdp, dp->ioc_rdata, len, MB_MUSER);
354
} else
355
dp->ioc_rdatacnt = 0;
356
bad:
357
if (t2p->t_name)
358
smb_strfree(t2p->t_name);
359
smb_t2_done(t2p);
360
free(t2p, M_SMBTEMP);
361
return error;
362
}
363
364