Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16824 SMB client connection setup rework
NEX-17232 SMB client reconnect failures
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (improve debug)
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)
re #11128 nsmb_close locking and teardown deadlock
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
+++ new/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
1 1 /*
2 2 * Copyright (c) 2000-2001 Boris Popov
3 3 * All rights reserved.
4 4 *
5 5 * Redistribution and use in source and binary forms, with or without
6 6 * modification, are permitted provided that the following conditions
7 7 * are met:
8 8 * 1. Redistributions of source code must retain the above copyright
9 9 * notice, this list of conditions and the following disclaimer.
10 10 * 2. Redistributions in binary form must reproduce the above copyright
11 11 * notice, this list of conditions and the following disclaimer in the
12 12 * documentation and/or other materials provided with the distribution.
13 13 * 3. All advertising materials mentioning features or use of this software
14 14 * must display the following acknowledgement:
15 15 * This product includes software developed by Boris Popov.
16 16 * 4. Neither the name of the author nor the names of any co-contributors
17 17 * may be used to endorse or promote products derived from this software
18 18 * without specific prior written permission.
19 19 *
20 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
26 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 30 * SUCH DAMAGE.
31 31 *
32 32 * $Id: smb_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $
33 33 */
34 34
35 35 /*
36 - * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
36 + * Portions Copyright (C) 2001 - 2014 Apple Inc. All rights reserved.
37 37 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
38 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
38 39 */
39 40
40 41 /*
41 42 * various SMB requests. Most of the routines merely packs data into mbufs.
42 43 */
43 44 #include <sys/param.h>
44 45 #include <sys/systm.h>
45 46 #include <sys/kmem.h>
46 47 #include <sys/proc.h>
47 48 #include <sys/lock.h>
48 49 #include <sys/socket.h>
49 50 #include <sys/uio.h>
50 51 #include <sys/random.h>
51 52 #include <sys/note.h>
53 +#include <sys/errno.h>
52 54 #include <sys/cmn_err.h>
53 55
54 56 #include <netsmb/smb_osdep.h>
55 57
56 58 #include <netsmb/smb.h>
57 59 #include <netsmb/smb_conn.h>
58 60 #include <netsmb/smb_rq.h>
59 61 #include <netsmb/smb_subr.h>
60 62 #include <netsmb/smb_tran.h>
61 63
62 64 #define STYPE_LEN 8 /* share type strings */
63 65
64 -/*
65 - * Largest size to use with LARGE_READ/LARGE_WRITE.
66 - * Specs say up to 64k data bytes, but Windows traffic
67 - * uses 60k... no doubt for some good reason.
68 - * (Probably to keep 4k block alignment.)
69 - * XXX: Move to smb.h maybe?
70 - */
71 -#define SMB_MAX_LARGE_RW_SIZE (60*1024)
66 +struct smb_dialect {
67 + int d_id;
68 + const char *d_name;
69 +};
72 70
71 +static struct smb_dialect smb_dialects[3] = {
72 + {SMB_DIALECT_NTLM0_12, "NT LANMAN 1.0"},
73 + {SMB_DIALECT_NTLM0_12, "NT LM 0.12"},
74 +#define NDIALECT_SMB1 2
75 + {SMB_DIALECT_SMB2_FF, "SMB 2.???"},
76 +#define NDIALECT_SMB2 3
77 +};
78 +
79 +static const uint32_t smb_clnt_caps_mask =
80 + SMB_CAP_UNICODE |
81 + SMB_CAP_LARGE_FILES |
82 + SMB_CAP_NT_SMBS |
83 + SMB_CAP_STATUS32 |
84 + SMB_CAP_EXT_SECURITY;
85 +
73 86 /*
74 87 * Default timeout values, all in seconds.
75 88 * Make these tunable (only via mdb for now).
76 89 */
77 90 int smb_timo_notice = 15;
78 91 int smb_timo_default = 30; /* was SMB_DEFRQTIMO */
92 +int smb_timo_logon = 45;
79 93 int smb_timo_open = 45;
80 94 int smb_timo_read = 45;
81 95 int smb_timo_write = 60; /* was SMBWRTTIMO */
82 96 int smb_timo_append = 90;
83 97
84 -static int smb_smb_read(struct smb_share *ssp, uint16_t fid,
85 - uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
86 -static int smb_smb_write(struct smb_share *ssp, uint16_t fid,
87 - uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
98 +int
99 +smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
100 +{
101 + smb_sopt_t *sv = &vcp->vc_sopt;
102 + smbioc_ssn_work_t *wk = &vcp->vc_work;
103 + struct smb_rq *rqp = NULL;
104 + struct mbchain *mbp = NULL;
105 + struct mdchain *mdp = NULL;
106 + struct smb_dialect *dp;
107 + int err, sblen, tlen;
108 + uint8_t wc, eklen;
109 + uint16_t dindex, bc;
110 + uint16_t ndialects;
111 + boolean_t will_sign = B_FALSE;
88 112
89 -static int smb_smb_readx(struct smb_share *ssp, uint16_t fid,
90 - uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
91 -static int smb_smb_writex(struct smb_share *ssp, uint16_t fid,
92 - uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
113 + /*
114 + * Initialize: vc_hflags and vc_hflags2.
115 + * Note: vcp->vc_hflags* are copied into the
116 + * (per request) rqp->rq_hflags* by smb_rq_init.
117 + *
118 + * Like Windows, set FLAGS2_UNICODE in our first request,
119 + * even though technically we don't yet know whether the
120 + * server supports Unicode. Will clear this flag below
121 + * if we find out it doesn't. Need to do this because
122 + * some servers reject all non-Unicode requests.
123 + */
124 + vcp->vc_hflags =
125 + SMB_FLAGS_CASELESS |
126 + SMB_FLAGS_CANONICAL_PATHNAMES;
127 + vcp->vc_hflags2 =
128 + SMB_FLAGS2_KNOWS_LONG_NAMES |
129 + SMB_FLAGS2_KNOWS_EAS |
130 + SMB_FLAGS2_IS_LONG_NAME |
131 + SMB_FLAGS2_EXT_SEC |
132 + SMB_FLAGS2_ERR_STATUS |
133 + SMB_FLAGS2_UNICODE;
93 134
135 + /*
136 + * The initial UID needs to be zero,
137 + */
138 + vcp->vc_smbuid = 0;
139 +
140 + /*
141 + * (Re)init negotiated values
142 + */
143 + bzero(sv, sizeof (*sv));
144 + sv->sv_maxmux = 1;
145 + sv->sv_maxvcs = 1;
146 + sv->sv_maxtx = 1024;
147 +
148 + /*
149 + * Should we offer the magic SMB2 dialect?
150 + */
151 + if (vcp->vc_ssn.ssn_maxver >= SMB2_DIALECT_BASE)
152 + ndialects = NDIALECT_SMB2;
153 + else
154 + ndialects = NDIALECT_SMB1;
155 +
156 + err = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp);
157 + if (err)
158 + return (err);
159 +
160 + /*
161 + * Build the SMB request.
162 + */
163 + smb_rq_getrequest(rqp, &mbp);
164 + smb_rq_wstart(rqp);
165 + smb_rq_wend(rqp);
166 + smb_rq_bstart(rqp);
167 + for (dindex = 0; dindex < ndialects; dindex++) {
168 + dp = &smb_dialects[dindex];
169 + mb_put_uint8(mbp, SMB_DT_DIALECT);
170 + tlen = strlen(dp->d_name) + 1;
171 + mb_put_mem(mbp, dp->d_name, tlen, MB_MSYSTEM);
172 + }
173 + smb_rq_bend(rqp);
174 +
175 + /*
176 + * Do the OTW call.
177 + */
178 + err = smb_rq_internal(rqp, smb_timo_default);
179 + /*
180 + * If it's an SMB1-to-SMB2 negotiate response,
181 + * call the special handler and then skip the
182 + * whole rest of this function.
183 + */
184 + if (err == EPROTO) {
185 + err = smb2_parse_smb1nego_resp(rqp);
186 + smb_rq_done(rqp);
187 + return (err);
188 + }
189 + if (err) {
190 + SMBSDEBUG("smb_rq_internal, err %d", err);
191 + goto errout;
192 + }
193 + /* Should only get status success. */
194 + if (rqp->sr_error != NT_STATUS_SUCCESS) {
195 + err = ENOTSUP;
196 + goto errout;
197 + }
198 +
199 + /*
200 + * Decode the response
201 + *
202 + * Comments to right show names as described in
203 + * The Microsoft SMB Protocol spec. [MS-SMB]
204 + * section 2.2.3
205 + */
206 + smb_rq_getreply(rqp, &mdp);
207 + (void) md_get_uint8(mdp, &wc);
208 + err = md_get_uint16le(mdp, &dindex);
209 + if (err != 0)
210 + goto errout;
211 + if (dindex >= ndialects) {
212 + SMBERROR("Invalid dialect index from server: %s\n",
213 + vcp->vc_srvname);
214 + err = EBADRPC;
215 + goto errout;
216 + }
217 + dp = smb_dialects + dindex;
218 + sv->sv_proto = dp->d_id;
219 + SMBSDEBUG("Dialect %s", dp->d_name);
220 + if (dp->d_id < SMB_DIALECT_NTLM0_12) {
221 + SMBSDEBUG("old dialect %s", dp->d_name);
222 + goto errout;
223 + }
224 + if (wc != 17) {
225 + SMBSDEBUG("bad wc %d", (int)wc);
226 + goto errout;
227 + }
228 + md_get_uint8(mdp, &sv->sv_sm); /* SecurityMode */
229 + md_get_uint16le(mdp, &sv->sv_maxmux); /* MaxMpxCount */
230 + md_get_uint16le(mdp, &sv->sv_maxvcs); /* MaxCountVCs */
231 + md_get_uint32le(mdp, &sv->sv_maxtx); /* MaxBufferSize */
232 + md_get_uint32le(mdp, &sv->sv_maxraw); /* MaxRawSize */
233 + md_get_uint32le(mdp, &sv->sv_skey); /* SessionKey */
234 + md_get_uint32le(mdp, &sv->sv_caps); /* Capabilities */
235 + md_get_mem(mdp, NULL, 8, MB_MSYSTEM); /* SystemTime(s) */
236 + md_get_uint16le(mdp, (uint16_t *)&sv->sv_tz);
237 + md_get_uint8(mdp, &eklen); /* EncryptionKeyLength */
238 + err = md_get_uint16le(mdp, &bc); /* ByteCount */
239 + if (err)
240 + goto errout;
241 +
242 + /* BEGIN CSTYLED */
243 + /*
244 + * Will we do SMB signing? Or block the connection?
245 + * The table below describes this logic. References:
246 + * [Windows Server Protocols: MS-SMB, sec. 3.2.4.2.3]
247 + * http://msdn.microsoft.com/en-us/library/cc212511.aspx
248 + * http://msdn.microsoft.com/en-us/library/cc212929.aspx
249 + *
250 + * Srv/Cli | Required | Enabled | If Required | Disabled
251 + * ------------+----------+------------+-------------+-----------
252 + * Required | Signed | Signed | Signed | Blocked [1]
253 + * ------------+----------+------------+-------------+-----------
254 + * Enabled | Signed | Signed | Not Signed | Not Signed
255 + * ------------+----------+------------+-------------+-----------
256 + * If Required | Signed | Not Signed | Not Signed | Not Signed
257 + * ------------+----------+------------+-------------+-----------
258 + * Disabled | Blocked | Not Signed | Not Signed | Not Signed
259 + *
260 + * [1] Like Windows 2003 and later, we don't really implement
261 + * the "Disabled" setting. Instead we implement "If Required",
262 + * so we always sign if the server requires signing.
263 + */
264 + /* END CSTYLED */
265 +
266 + if (sv->sv_sm & SMB_SM_SIGS_REQUIRE) {
267 + /*
268 + * Server requires signing. We will sign,
269 + * even if local setting is "disabled".
270 + */
271 + will_sign = B_TRUE;
272 + } else if (sv->sv_sm & SMB_SM_SIGS) {
273 + /*
274 + * Server enables signing (client's option).
275 + * If enabled locally, do signing.
276 + */
277 + if (vcp->vc_vopt & SMBVOPT_SIGNING_ENABLED)
278 + will_sign = B_TRUE;
279 + /* else not signing. */
280 + } else {
281 + /*
282 + * Server does not support signing.
283 + * If we "require" it, bail now.
284 + */
285 + if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
286 + SMBERROR("Client requires signing "
287 + "but server has it disabled.");
288 + err = EBADRPC;
289 + goto errout;
290 + }
291 + }
292 +
293 + /*
294 + * Anonymous sessions can't sign.
295 + */
296 + if (vcp->vc_vopt & SMBVOPT_ANONYMOUS) {
297 + will_sign = B_FALSE;
298 + }
299 +
300 + SMBSDEBUG("Security signatures: %d", (int)will_sign);
301 + if (will_sign) {
302 + vcp->vc_flags |= SMBV_SIGNING;
303 + vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
304 +
305 + /*
306 + * MS-SMB 2.2.4.5 says that when SMB signing is enabled,
307 + * we should NOT use "large read/write" even though the
308 + * server might offer those capabilities.
309 + */
310 + sv->sv_caps &= ~(SMB_CAP_LARGE_READX | SMB_CAP_LARGE_WRITEX);
311 + }
312 +
313 + /* See comment above re. FLAGS2_UNICODE */
314 + if ((sv->sv_caps & SMB_CAP_UNICODE) != 0)
315 + vcp->vc_flags |= SMBV_UNICODE;
316 + else
317 + vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE;
318 +
319 + if ((sv->sv_caps & SMB_CAP_STATUS32) == 0) {
320 + /* They don't do NT error codes. */
321 + vcp->vc_hflags2 &= ~SMB_FLAGS2_ERR_STATUS;
322 + }
323 +
324 + /*
325 + * Warn if they don't support SMB_CAP_NT_SMBS
326 + * (We'll try to use NtCreate anyway)
327 + */
328 + if ((sv->sv_caps & SMB_CAP_NT_SMBS) == 0) {
329 + cmn_err(CE_NOTE, "%s does not support SMB_CAP_NT_SMBS",
330 + vcp->vc_srvname);
331 + }
332 +
333 + /*
334 + * The rest of the message varies depending on
335 + * whether we've negotiated "extended security".
336 + *
337 + * With extended security, we have:
338 + * Server_GUID (length 16)
339 + * Security_BLOB
340 + * Otherwise we have:
341 + * EncryptionKey (length is eklen)
342 + * PrimaryDomain
343 + */
344 + if (sv->sv_caps & SMB_CAP_EXT_SECURITY) {
345 + SMBSDEBUG("Ext.Security: yes");
346 +
347 + /*
348 + * Skip the server GUID.
349 + */
350 + err = md_get_mem(mdp, NULL, SMB_GUIDLEN, MB_MSYSTEM);
351 + if (err)
352 + goto errout;
353 + /*
354 + * Remainder is the security blob.
355 + * Note: eklen "must be ignored" [MS-SMB]
356 + */
357 + sblen = (int)bc - SMB_GUIDLEN;
358 + if (sblen < 0)
359 + goto errout;
360 + /* Security blob (hint) is next */
361 + } else {
362 + SMBSDEBUG("Ext.Security: no");
363 + err = ENOTSUP;
364 + goto errout;
365 + }
366 +
367 + /*
368 + * Copy the security blob out to user space.
369 + * Buffer addr,size in vc_auth_rbuf,rlen
370 + */
371 + if (wk->wk_u_auth_rlen < sblen) {
372 + SMBSDEBUG("vc_auth_rbuf too small");
373 + /* Give caller required size. */
374 + wk->wk_u_auth_rlen = sblen;
375 + err = EMSGSIZE;
376 + goto errout;
377 + }
378 + wk->wk_u_auth_rlen = sblen;
379 + err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr, sblen, MB_MUSER);
380 + if (err)
381 + goto errout;
382 +
383 + /*
384 + * A few sanity checks on what we received,
385 + * becuse we will send these in ssnsetup.
386 + *
387 + * Maximum outstanding requests (we care),
388 + * and Max. VCs (we only use one). Also,
389 + * MaxBufferSize lower limit per spec.
390 + */
391 + if (sv->sv_maxmux < 1)
392 + sv->sv_maxmux = 1;
393 + if (sv->sv_maxvcs < 1)
394 + sv->sv_maxvcs = 1;
395 + if (sv->sv_maxtx < 1024)
396 + sv->sv_maxtx = 1024;
397 +
398 + /*
399 + * Maximum transfer size.
400 + * Sanity checks:
401 + *
402 + * Let's be conservative about an upper limit here.
403 + * Win2k uses 16644 (and others) so 32k should be a
404 + * reasonable sanity limit for this value.
405 + *
406 + * Note that this limit does NOT affect READX/WRITEX
407 + * with CAP_LARGE_..., which we nearly always use.
408 + */
409 + vcp->vc_txmax = sv->sv_maxtx;
410 + if (vcp->vc_txmax > 0x8000)
411 + vcp->vc_txmax = 0x8000;
412 +
413 + /*
414 + * Max read/write sizes, WITHOUT overhead.
415 + * This is just the payload size, so we must
416 + * leave room for the SMB headers, etc.
417 + * This is just the ct_txmax value, but
418 + * reduced and rounded down. Tricky bit:
419 + *
420 + * Servers typically give us a value that's
421 + * some nice "round" number, i.e 0x4000 plus
422 + * some overhead, i.e. Win2k: 16644==0x4104
423 + * Subtract for the SMB header (32) and the
424 + * SMB command word and byte vectors (34?),
425 + * then round down to a 512 byte multiple.
426 + */
427 + tlen = vcp->vc_txmax - 68;
428 + tlen &= 0xFE00;
429 +
430 + vcp->vc_rwmax = tlen;
431 + vcp->vc_rxmax = tlen;
432 + vcp->vc_wxmax = tlen;
433 +
434 + /*
435 + * Most of the "capability" bits we offer in session setup
436 + * are just copied from those offered by the server.
437 + */
438 + sv->sv_caps &= smb_clnt_caps_mask;
439 +
440 + smb_rq_done(rqp);
441 + return (0);
442 +
443 +errout:
444 + smb_rq_done(rqp);
445 + if (err == 0)
446 + err = EBADRPC;
447 + return (err);
448 +}
449 +
450 +static const char NativeOS[] = "illumos";
451 +static const char LanMan[] = "NETSMB";
452 +
453 +int
454 +smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
455 +{
456 + smb_sopt_t *sv = &vcp->vc_sopt;
457 + smbioc_ssn_work_t *wk = &vcp->vc_work;
458 + struct smb_rq *rqp = NULL;
459 + struct mbchain *mbp = NULL;
460 + struct mdchain *mdp = NULL;
461 + char *sb;
462 + int err, ret;
463 + uint32_t caps;
464 + uint16_t action, bc, sblen;
465 + uint8_t wc;
466 +
467 + caps = sv->sv_caps;
468 + sb = wk->wk_u_auth_wbuf.lp_ptr;
469 + sblen = (uint16_t)wk->wk_u_auth_wlen;
470 +
471 + err = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX,
472 + scred, &rqp);
473 + if (err != 0) {
474 + ret = err;
475 + goto out;
476 + }
477 +
478 + /*
479 + * Build the SMB Session Setup request.
480 + * Always extended security form.
481 + */
482 + mbp = &rqp->sr_rq;
483 + smb_rq_wstart(rqp);
484 + mb_put_uint16le(mbp, 0xff); /* 0: AndXCommand */
485 + mb_put_uint16le(mbp, 0); /* 1: AndXOffset */
486 + mb_put_uint16le(mbp, sv->sv_maxtx); /* 2: MaxBufferSize */
487 + mb_put_uint16le(mbp, sv->sv_maxmux); /* 3: MaxMpxCount */
488 + mb_put_uint16le(mbp, 1); /* 4: VcNumber */
489 + mb_put_uint32le(mbp, sv->sv_skey); /* 5,6: Session Key */
490 + mb_put_uint16le(mbp, sblen); /* 7: Sec. Blob Len */
491 + mb_put_uint32le(mbp, 0); /* 8,9: reserved */
492 + mb_put_uint32le(mbp, caps); /* 10,11: Capabilities */
493 + smb_rq_wend(rqp); /* 12: Byte Count */
494 + smb_rq_bstart(rqp);
495 + err = mb_put_mem(mbp, sb, sblen, MB_MUSER);
496 + if (err != 0) {
497 + ret = err;
498 + goto out;
499 + }
500 + (void) smb_put_dstring(mbp, vcp, NativeOS, SMB_CS_NONE);
501 + (void) smb_put_dstring(mbp, vcp, LanMan, SMB_CS_NONE);
502 + smb_rq_bend(rqp);
503 +
504 + /*
505 + * Run the request. The return value here should be the
506 + * return from this function, unless we fail decoding.
507 + * Note: NT_STATUS_MORE_PROCESSING_REQUIRED is OK, and
508 + * the caller expects EINPROGRESS for that case.
509 + */
510 + ret = smb_rq_internal(rqp, smb_timo_logon);
511 + if (ret != 0)
512 + goto out;
513 + switch (rqp->sr_error) {
514 + case NT_STATUS_SUCCESS:
515 + break;
516 + case NT_STATUS_MORE_PROCESSING_REQUIRED:
517 + /* Keep going, but return... */
518 + ret = EINPROGRESS;
519 + break;
520 + default:
521 + ret = EAUTH;
522 + goto out;
523 + }
524 +
525 + if (vcp->vc_smbuid == 0)
526 + vcp->vc_smbuid = rqp->sr_rpuid;
527 +
528 + /*
529 + * Parse the reply
530 + */
531 + smb_rq_getreply(rqp, &mdp);
532 +
533 + err = md_get_uint8(mdp, &wc);
534 + if (err != 0)
535 + wc = 0;
536 + if (wc != 4) {
537 + ret = EBADRPC;
538 + goto out;
539 + }
540 + md_get_uint16le(mdp, NULL); /* secondary cmd */
541 + md_get_uint16le(mdp, NULL); /* andxoffset */
542 + md_get_uint16le(mdp, &action); /* action XXX */
543 + md_get_uint16le(mdp, &sblen); /* sec. blob len */
544 + md_get_uint16le(mdp, &bc); /* byte count */
545 + /*
546 + * Get the security blob, after
547 + * sanity-checking the length.
548 + */
549 + if (sblen == 0 || sblen > bc) {
550 + ret = EBADRPC;
551 + goto out;
552 + }
553 + if (sblen > wk->wk_u_auth_rlen) {
554 + ret = EBADRPC;
555 + goto out;
556 + }
557 + sb = wk->wk_u_auth_rbuf.lp_ptr;
558 + err = md_get_mem(mdp, sb, sblen, MB_MUSER);
559 + if (err) {
560 + ret = EBADRPC;
561 + goto out;
562 + }
563 +
564 + /*
565 + * Native OS, LANMGR, & Domain follow here.
566 + * We don't need them and don't parse them.
567 + */
568 +
569 +out:
570 + if (err != 0 && err != EINPROGRESS) {
571 + /* UID no longer valid. */
572 + vcp->vc_smbuid = 0;
573 + }
574 + if (rqp)
575 + smb_rq_done(rqp);
576 +
577 + return (ret);
578 +}
579 +
580 +int
581 +smb_smb_logoff(struct smb_vc *vcp, struct smb_cred *scred)
582 +{
583 + struct smb_rq *rqp;
584 + struct mbchain *mbp;
585 + int error;
586 +
587 + if (vcp->vc_smbuid == SMB_UID_UNKNOWN)
588 + return (0);
589 +
590 + error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp);
591 + if (error)
592 + return (error);
593 + mbp = &rqp->sr_rq;
594 + smb_rq_wstart(rqp);
595 + mb_put_uint8(mbp, 0xff);
596 + mb_put_uint8(mbp, 0);
597 + mb_put_uint16le(mbp, 0);
598 + smb_rq_wend(rqp);
599 + smb_rq_bstart(rqp);
600 + smb_rq_bend(rqp);
601 +
602 + /*
603 + * Run this with a relatively short timeout. (5 sec.)
604 + * We don't really care about the result here.
605 + * Also, don't reconnect for this, of course!
606 + */
607 + rqp->sr_flags |= SMBR_NORECONNECT;
608 + error = smb_rq_internal(rqp, 5);
609 + smb_rq_done(rqp);
610 + return (error);
611 +}
612 +
94 613 /*
95 614 * Get the string representation of a share "use" type,
96 615 * as needed for the "service" in tree connect.
97 616 */
98 617 static const char *
99 618 smb_share_typename(uint32_t stype)
100 619 {
101 620 const char *p;
102 621
103 622 switch (stype) {
104 623 case STYPE_DISKTREE:
105 624 p = "A:";
106 625 break;
107 626 case STYPE_PRINTQ:
108 627 p = "LPT1:";
109 628 break;
110 629 case STYPE_DEVICE:
111 630 p = "COMM";
112 631 break;
113 632 case STYPE_IPC:
114 633 p = "IPC";
115 634 break;
116 635 case STYPE_UNKNOWN:
117 636 default:
118 637 p = "?????";
119 638 break;
120 639 }
121 640 return (p);
122 641 }
123 642
124 643 /*
125 644 * Parse a share type name (inverse of above)
126 645 */
127 646 static uint32_t
128 647 smb_share_parsetype(char *name)
129 648 {
130 649 int stype;
131 650
132 651 switch (*name) {
133 652 case 'A': /* A: */
134 653 stype = STYPE_DISKTREE;
135 654 break;
136 655 case 'C': /* COMM */
137 656 stype = STYPE_DEVICE;
138 657 break;
139 658 case 'I': /* IPC */
140 659 stype = STYPE_IPC;
141 660 break;
142 661 case 'L': /* LPT: */
143 662 stype = STYPE_PRINTQ;
144 663 break;
145 664 default:
146 665 stype = STYPE_UNKNOWN;
147 666 break;
148 667 }
149 668 return (stype);
150 669 }
151 670
152 671 int
153 672 smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
154 673 {
155 674 struct smb_vc *vcp;
156 675 struct smb_rq *rqp = NULL;
157 676 struct mbchain *mbp;
158 677 struct mdchain *mdp;
159 678 const char *tname;
160 679 char *pbuf, *unc_name = NULL;
161 680 int error, tlen, plen, unc_len;
162 681 uint16_t bcnt, options;
163 682 uint8_t wc;
164 683 char stype_str[STYPE_LEN];
165 684
166 685 vcp = SSTOVC(ssp);
167 686
168 687 /*
169 688 * Make this a "VC-level" request, so it will have
170 689 * rqp->sr_share == NULL, and smb_iod_sendrq()
171 690 * will send it with TID = SMB_TID_UNKNOWN
172 691 *
173 692 * This also serves to bypass the wait for
174 693 * share state changes, which this call is
175 694 * trying to carry out.
176 695 */
177 696 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_CONNECT_ANDX,
178 697 scred, &rqp);
179 698 if (error)
180 699 return (error);
181 700
182 701 /*
183 702 * Build the UNC name, i.e. "//server/share"
184 703 * but with backslashes of course.
185 704 * size math: three slashes, one null.
186 705 */
187 706 unc_len = 4 + strlen(vcp->vc_srvname) + strlen(ssp->ss_name);
188 707 unc_name = kmem_alloc(unc_len, KM_SLEEP);
189 708 (void) snprintf(unc_name, unc_len, "\\\\%s\\%s",
190 709 vcp->vc_srvname, ssp->ss_name);
191 710 SMBSDEBUG("unc_name: \"%s\"", unc_name);
192 711
193 712
194 713 /*
195 714 * Share-level password (pre-computed in user-space)
196 715 * MS-SMB 2.2.6 says this should be null terminated,
197 716 * and the pw length includes the null.
198 717 */
199 718 pbuf = ssp->ss_pass;
200 719 plen = strlen(pbuf) + 1;
201 720
202 721 /*
203 722 * Build the request.
204 723 */
205 724 mbp = &rqp->sr_rq;
206 725 smb_rq_wstart(rqp);
207 726 mb_put_uint8(mbp, 0xff);
208 727 mb_put_uint8(mbp, 0);
209 728 mb_put_uint16le(mbp, 0);
210 729 mb_put_uint16le(mbp, 0); /* Flags */
211 730 mb_put_uint16le(mbp, plen);
212 731 smb_rq_wend(rqp);
213 732 smb_rq_bstart(rqp);
214 733
215 734 /* Tree connect password, if any */
216 735 error = mb_put_mem(mbp, pbuf, plen, MB_MSYSTEM);
217 736 if (error)
218 737 goto out;
219 738
220 739 /* UNC resource name */
221 740 error = smb_put_dstring(mbp, vcp, unc_name, SMB_CS_NONE);
222 741 if (error)
223 742 goto out;
224 743
225 744 /*
226 745 * Put the type string (always ASCII),
227 746 * including the null.
228 747 */
229 748 tname = smb_share_typename(ssp->ss_use);
230 749 tlen = strlen(tname) + 1;
231 750 error = mb_put_mem(mbp, tname, tlen, MB_MSYSTEM);
232 751 if (error)
233 752 goto out;
234 753
235 754 smb_rq_bend(rqp);
236 755
237 756 /*
238 757 * Run the request.
239 758 *
240 759 * Using NOINTR_RECV because we don't want to risk
241 760 * missing a successful tree connect response,
242 761 * which would "leak" Tree IDs.
243 762 */
244 763 rqp->sr_flags |= SMBR_NOINTR_RECV;
245 764 error = smb_rq_simple(rqp);
246 765 SMBSDEBUG("%d\n", error);
247 766 if (error) {
248 767 /*
249 768 * If we get the server name wrong, i.e. due to
250 769 * mis-configured name services, this will be
251 770 * NT_STATUS_DUPLICATE_NAME. Log this error.
252 771 */
253 772 SMBERROR("(%s) failed, status=0x%x",
254 773 unc_name, rqp->sr_error);
255 774 goto out;
256 775 }
257 776
258 777 /*
259 778 * Parse the TCON response
260 779 */
261 780 smb_rq_getreply(rqp, &mdp);
262 781 md_get_uint8(mdp, &wc);
263 782 if (wc != 3 && wc != 7) {
264 783 error = EBADRPC;
265 784 goto out;
266 785 }
267 786 md_get_uint16le(mdp, NULL); /* AndX cmd */
268 787 md_get_uint16le(mdp, NULL); /* AndX off */
269 788 md_get_uint16le(mdp, &options); /* option bits (DFS, search) */
270 789 if (wc == 7) {
271 790 md_get_uint32le(mdp, NULL); /* MaximalShareAccessRights */
272 791 md_get_uint32le(mdp, NULL); /* GuestMaximalShareAcc... */
273 792 }
274 793 error = md_get_uint16le(mdp, &bcnt); /* byte count */
275 794 if (error)
276 795 goto out;
277 796
278 797 /*
279 798 * Get the returned share type string, i.e. "IPC" or whatever.
280 799 * (See smb_share_typename, smb_share_parsetype). If we get
281 800 * an error reading the type, just say STYPE_UNKNOWN.
282 801 */
283 802 tlen = STYPE_LEN;
284 803 bzero(stype_str, tlen--);
285 804 if (tlen > bcnt)
286 805 tlen = bcnt;
287 806 md_get_mem(mdp, stype_str, tlen, MB_MSYSTEM);
288 807 stype_str[tlen] = '\0';
289 808 ssp->ss_type = smb_share_parsetype(stype_str);
290 809
291 810 /* Success! */
292 811 SMB_SS_LOCK(ssp);
293 812 ssp->ss_tid = rqp->sr_rptid;
294 813 ssp->ss_vcgenid = vcp->vc_genid;
295 814 ssp->ss_options = options;
296 815 ssp->ss_flags |= SMBS_CONNECTED;
297 816 SMB_SS_UNLOCK(ssp);
298 817
299 818 out:
300 819 if (unc_name)
301 820 kmem_free(unc_name, unc_len);
302 821 smb_rq_done(rqp);
303 822 return (error);
304 823 }
305 824
306 825 int
307 826 smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred)
308 827 {
309 828 struct smb_vc *vcp;
310 829 struct smb_rq *rqp;
311 830 int error;
312 831
313 832 if (ssp->ss_tid == SMB_TID_UNKNOWN)
314 833 return (0);
315 834
316 835 /*
317 836 * Build this as a "VC-level" request, so it will
318 837 * avoid testing the _GONE flag on the share,
319 838 * which has already been set at this point.
320 839 * Add the share pointer "by hand" below, so
321 840 * smb_iod_sendrq will plug in the TID.
322 841 */
323 842 vcp = SSTOVC(ssp);
324 843 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_DISCONNECT, scred, &rqp);
325 844 if (error)
326 845 return (error);
327 846 rqp->sr_share = ssp; /* by hand */
328 847
329 848 smb_rq_wstart(rqp);
330 849 smb_rq_wend(rqp);
331 850 smb_rq_bstart(rqp);
332 851 smb_rq_bend(rqp);
333 852
334 853 /*
335 854 * Run this with a relatively short timeout. (5 sec.)
336 855 * We don't really care about the result here, but we
337 856 * do need to make sure we send this out, or we could
338 857 * "leak" active tree IDs on interrupt or timeout.
339 858 * The NOINTR_SEND flag makes this request immune to
340 859 * interrupt or timeout until the send is done.
341 860 * Also, don't reconnect for this, of course!
342 861 */
343 862 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
344 863 error = smb_rq_simple_timed(rqp, 5);
|
↓ open down ↓ |
241 lines elided |
↑ open up ↑ |
345 864 SMBSDEBUG("%d\n", error);
346 865 smb_rq_done(rqp);
347 866 ssp->ss_tid = SMB_TID_UNKNOWN;
348 867 return (error);
349 868 }
350 869
351 870 /*
352 871 * Modern create/open of file or directory.
353 872 */
354 873 int
355 -smb_smb_ntcreate(
874 +smb1_smb_ntcreate(
356 875 struct smb_share *ssp,
357 876 struct mbchain *name_mb,
358 877 uint32_t cr_flags, /* create flags */
359 878 uint32_t req_acc, /* requested access */
360 879 uint32_t efa, /* ext. file attrs (DOS attr +) */
361 880 uint32_t share_acc,
362 881 uint32_t open_disp, /* open disposition */
363 882 uint32_t createopt, /* NTCREATEX_OPTIONS_ */
364 883 uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */
365 884 struct smb_cred *scrp,
366 885 uint16_t *fidp, /* returned FID */
367 886 uint32_t *cr_act_p, /* optional create action */
368 887 struct smbfattr *fap) /* optional attributes */
369 888 {
370 889 struct smb_rq rq, *rqp = &rq;
371 890 struct smb_vc *vcp = SSTOVC(ssp);
372 891 struct mbchain *mbp;
373 892 struct mdchain *mdp;
374 893 struct smbfattr fa;
375 894 uint64_t llongint;
376 895 uint32_t longint, createact;
377 896 uint16_t fid;
378 897 uint8_t wc;
379 898 int error;
380 899
381 900 bzero(&fa, sizeof (fa));
382 901 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp);
383 902 if (error)
384 903 return (error);
385 904 smb_rq_getrequest(rqp, &mbp);
386 905
387 906 /* Word parameters */
388 907 smb_rq_wstart(rqp);
389 908 mb_put_uint8(mbp, 0xff); /* secondary command */
390 909 mb_put_uint8(mbp, 0); /* MBZ */
391 910 mb_put_uint16le(mbp, 0); /* offset to next command (none) */
392 911 mb_put_uint8(mbp, 0); /* MBZ */
393 912 mb_put_uint16le(mbp, name_mb->mb_count);
394 913 mb_put_uint32le(mbp, cr_flags); /* NTCREATEX_FLAGS_* */
395 914 mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */
396 915 mb_put_uint32le(mbp, req_acc);
397 916 mb_put_uint64le(mbp, 0); /* "initial allocation size" */
398 917 mb_put_uint32le(mbp, efa);
399 918 mb_put_uint32le(mbp, share_acc);
400 919 mb_put_uint32le(mbp, open_disp);
401 920 mb_put_uint32le(mbp, createopt);
402 921 mb_put_uint32le(mbp, impersonate);
403 922 mb_put_uint8(mbp, 0); /* security flags (?) */
404 923 smb_rq_wend(rqp);
405 924
406 925 /*
407 926 * Byte parameters: Just the path name, aligned.
408 927 * Note: mb_put_mbuf consumes mb_top, so clear it.
409 928 */
410 929 smb_rq_bstart(rqp);
411 930 if (SMB_UNICODE_STRINGS(vcp))
412 931 mb_put_padbyte(mbp);
413 932 mb_put_mbuf(mbp, name_mb->mb_top);
414 933 bzero(name_mb, sizeof (*name_mb));
415 934 smb_rq_bend(rqp);
416 935
417 936 /*
418 937 * Don't want to risk missing a successful
419 938 * open response, or we could "leak" FIDs.
420 939 */
421 940 rqp->sr_flags |= SMBR_NOINTR_RECV;
422 941 error = smb_rq_simple_timed(rqp, smb_timo_open);
423 942 if (error)
424 943 goto done;
425 944 smb_rq_getreply(rqp, &mdp);
426 945 /*
427 946 * spec says 26 for word count, but 34 words are defined
428 947 * and observed from win2000
429 948 */
430 949 error = md_get_uint8(mdp, &wc);
431 950 if (error)
432 951 goto done;
433 952 if (wc != 26 && wc < 34) {
434 953 error = EBADRPC;
435 954 goto done;
436 955 }
437 956 md_get_uint8(mdp, NULL); /* secondary cmd */
438 957 md_get_uint8(mdp, NULL); /* mbz */
439 958 md_get_uint16le(mdp, NULL); /* andxoffset */
440 959 md_get_uint8(mdp, NULL); /* oplock lvl granted */
441 960 md_get_uint16le(mdp, &fid); /* file ID */
442 961 md_get_uint32le(mdp, &createact); /* create_action */
443 962
444 963 md_get_uint64le(mdp, &llongint); /* creation time */
445 964 smb_time_NT2local(llongint, &fa.fa_createtime);
446 965 md_get_uint64le(mdp, &llongint); /* access time */
447 966 smb_time_NT2local(llongint, &fa.fa_atime);
448 967 md_get_uint64le(mdp, &llongint); /* write time */
449 968 smb_time_NT2local(llongint, &fa.fa_mtime);
450 969 md_get_uint64le(mdp, &llongint); /* change time */
451 970 smb_time_NT2local(llongint, &fa.fa_ctime);
452 971
453 972 md_get_uint32le(mdp, &longint); /* attributes */
454 973 fa.fa_attr = longint;
455 974 md_get_uint64le(mdp, &llongint); /* allocation size */
456 975 fa.fa_allocsz = llongint;
457 976 md_get_uint64le(mdp, &llongint); /* EOF position */
458 977 fa.fa_size = llongint;
459 978
460 979 error = md_get_uint16le(mdp, NULL); /* file type */
461 980 /* other stuff we don't care about */
462 981
463 982 done:
464 983 smb_rq_done(rqp);
465 984 if (error)
466 985 return (error);
467 986
|
↓ open down ↓ |
102 lines elided |
↑ open up ↑ |
468 987 *fidp = fid;
469 988 if (cr_act_p)
470 989 *cr_act_p = createact;
471 990 if (fap)
472 991 *fap = fa; /* struct copy */
473 992
474 993 return (0);
475 994 }
476 995
477 996 int
478 -smb_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
997 +smb1_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
479 998 struct smb_cred *scrp)
480 999 {
481 1000 struct smb_rq rq, *rqp = &rq;
482 1001 struct mbchain *mbp;
483 1002 long time;
484 1003 int error;
485 1004
486 1005 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
487 1006 if (error)
488 1007 return (error);
489 1008 smb_rq_getrequest(rqp, &mbp);
490 1009 smb_rq_wstart(rqp);
491 1010 mb_put_uint16le(mbp, fid);
492 1011 if (mtime) {
493 1012 int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
494 1013 smb_time_local2server(mtime, sv_tz, &time);
495 1014 } else {
496 1015 time = 0;
497 1016 }
498 1017 mb_put_uint32le(mbp, time);
499 1018 smb_rq_wend(rqp);
500 1019 smb_rq_bstart(rqp);
501 1020 smb_rq_bend(rqp);
502 1021
503 1022 /* Make sure we send, but only if already connected */
504 1023 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
505 1024 error = smb_rq_simple(rqp);
506 1025 smb_rq_done(rqp);
507 1026 return (error);
508 1027 }
509 1028
510 1029 int
511 1030 smb_smb_open_prjob(
512 1031 struct smb_share *ssp,
513 1032 char *title,
514 1033 uint16_t setuplen,
515 1034 uint16_t mode,
516 1035 struct smb_cred *scrp,
517 1036 uint16_t *fidp)
518 1037 {
519 1038 struct smb_rq rq, *rqp = &rq;
520 1039 struct smb_vc *vcp = SSTOVC(ssp);
521 1040 struct mbchain *mbp;
522 1041 struct mdchain *mdp;
523 1042 uint16_t fid;
524 1043 uint8_t wc;
525 1044 int error;
526 1045
527 1046 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN_PRINT_FILE, scrp);
528 1047 if (error)
529 1048 return (error);
530 1049 smb_rq_getrequest(rqp, &mbp);
531 1050
532 1051 /* Word parameters */
533 1052 smb_rq_wstart(rqp);
534 1053 mb_put_uint16le(mbp, setuplen);
535 1054 mb_put_uint16le(mbp, mode);
536 1055 smb_rq_wend(rqp);
537 1056
538 1057 /*
539 1058 * Byte parameters: Just the title
540 1059 */
541 1060 smb_rq_bstart(rqp);
542 1061 mb_put_uint8(mbp, SMB_DT_ASCII);
543 1062 error = smb_put_dstring(mbp, vcp, title, SMB_CS_NONE);
544 1063 smb_rq_bend(rqp);
545 1064 if (error)
546 1065 goto done;
547 1066
548 1067 /*
549 1068 * Don't want to risk missing a successful
550 1069 * open response, or we could "leak" FIDs.
551 1070 */
552 1071 rqp->sr_flags |= SMBR_NOINTR_RECV;
553 1072 error = smb_rq_simple_timed(rqp, smb_timo_open);
554 1073 if (error)
555 1074 goto done;
556 1075
557 1076 smb_rq_getreply(rqp, &mdp);
558 1077 error = md_get_uint8(mdp, &wc);
559 1078 if (error || wc < 1) {
560 1079 error = EBADRPC;
561 1080 goto done;
562 1081 }
563 1082 error = md_get_uint16le(mdp, &fid);
564 1083
565 1084 done:
566 1085 smb_rq_done(rqp);
567 1086 if (error)
568 1087 return (error);
569 1088
570 1089 *fidp = fid;
571 1090 return (0);
572 1091 }
573 1092
574 1093 /*
575 1094 * Like smb_smb_close, but for print shares.
576 1095 */
577 1096 int
578 1097 smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid,
579 1098 struct smb_cred *scrp)
580 1099 {
581 1100 struct smb_rq rq, *rqp = &rq;
582 1101 struct mbchain *mbp;
583 1102 int error;
584 1103
585 1104 error = smb_rq_init(rqp, SSTOCP(ssp),
586 1105 SMB_COM_CLOSE_PRINT_FILE, scrp);
587 1106 if (error)
588 1107 return (error);
589 1108 smb_rq_getrequest(rqp, &mbp);
590 1109 smb_rq_wstart(rqp);
591 1110 mb_put_uint16le(mbp, fid);
592 1111 smb_rq_wend(rqp);
|
↓ open down ↓ |
104 lines elided |
↑ open up ↑ |
593 1112 smb_rq_bstart(rqp);
594 1113 smb_rq_bend(rqp);
595 1114
596 1115 /* Make sure we send but only if already connected */
597 1116 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
598 1117 error = smb_rq_simple(rqp);
599 1118 smb_rq_done(rqp);
600 1119 return (error);
601 1120 }
602 1121
603 -/*
604 - * Common function for read/write with UIO.
605 - * Called by netsmb smb_usr_rw,
606 - * smbfs_readvnode, smbfs_writevnode
607 - */
608 1122 int
609 -smb_rwuio(struct smb_share *ssp, uint16_t fid, uio_rw_t rw,
1123 +smb_smb_readx(smb_fh_t *fhp, uint32_t *lenp,
610 1124 uio_t *uiop, smb_cred_t *scred, int timo)
611 1125 {
612 - struct smb_vc *vcp = SSTOVC(ssp);
613 - ssize_t save_resid;
614 - uint32_t len, rlen, maxlen;
615 - int error = 0;
616 - int (*iofun)(struct smb_share *, uint16_t, uint32_t *,
617 - uio_t *, smb_cred_t *, int);
618 -
619 - /*
620 - * Determine which function to use,
621 - * and the transfer size per call.
622 - */
623 - if (SMB_DIALECT(vcp) >= SMB_DIALECT_NTLM0_12) {
624 - /*
625 - * Using NT LM 0.12, so readx, writex.
626 - * Make sure we can represent the offset.
627 - */
628 - if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0 &&
629 - (uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
630 - return (EFBIG);
631 -
632 - if (rw == UIO_READ) {
633 - iofun = smb_smb_readx;
634 - if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX)
635 - maxlen = SMB_MAX_LARGE_RW_SIZE;
636 - else
637 - maxlen = vcp->vc_rxmax;
638 - } else { /* UIO_WRITE */
639 - iofun = smb_smb_writex;
640 - if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)
641 - maxlen = SMB_MAX_LARGE_RW_SIZE;
642 - else
643 - maxlen = vcp->vc_wxmax;
644 - }
645 - } else {
646 - /*
647 - * Using the old SMB_READ and SMB_WRITE so
648 - * we're limited to 32-bit offsets, etc.
649 - * XXX: Someday, punt the old dialects.
650 - */
651 - if ((uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
652 - return (EFBIG);
653 -
654 - if (rw == UIO_READ) {
655 - iofun = smb_smb_read;
656 - maxlen = vcp->vc_rxmax;
657 - } else { /* UIO_WRITE */
658 - iofun = smb_smb_write;
659 - maxlen = vcp->vc_wxmax;
660 - }
661 - }
662 -
663 - save_resid = uiop->uio_resid;
664 - while (uiop->uio_resid > 0) {
665 - /* Lint: uio_resid may be 64-bits */
666 - rlen = len = (uint32_t)min(maxlen, uiop->uio_resid);
667 - error = (*iofun)(ssp, fid, &rlen, uiop, scred, timo);
668 -
669 - /*
670 - * Note: the iofun called uio_update, so
671 - * not doing that here as one might expect.
672 - *
673 - * Quit the loop either on error, or if we
674 - * transferred less then requested.
675 - */
676 - if (error || (rlen < len))
677 - break;
678 -
679 - timo = 0; /* only first I/O should wait */
680 - }
681 - if (error && (save_resid != uiop->uio_resid)) {
682 - /*
683 - * Stopped on an error after having
684 - * successfully transferred data.
685 - * Suppress this error.
686 - */
687 - SMBSDEBUG("error %d suppressed\n", error);
688 - error = 0;
689 - }
690 -
691 - return (error);
692 -}
693 -
694 -static int
695 -smb_smb_readx(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
696 - uio_t *uiop, smb_cred_t *scred, int timo)
697 -{
1126 + struct smb_share *ssp = FHTOSS(fhp);
698 1127 struct smb_rq *rqp;
699 1128 struct mbchain *mbp;
700 1129 struct mdchain *mdp;
701 1130 int error;
702 1131 uint32_t offlo, offhi, rlen;
703 1132 uint16_t lenhi, lenlo, off, doff;
704 1133 uint8_t wc;
705 1134
706 1135 lenhi = (uint16_t)(*lenp >> 16);
707 1136 lenlo = (uint16_t)*lenp;
708 1137 offhi = (uint32_t)(uiop->uio_loffset >> 32);
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
709 1138 offlo = (uint32_t)uiop->uio_loffset;
710 1139
711 1140 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
712 1141 if (error)
713 1142 return (error);
714 1143 smb_rq_getrequest(rqp, &mbp);
715 1144 smb_rq_wstart(rqp);
716 1145 mb_put_uint8(mbp, 0xff); /* no secondary command */
717 1146 mb_put_uint8(mbp, 0); /* MBZ */
718 1147 mb_put_uint16le(mbp, 0); /* offset to secondary */
719 - mb_put_uint16le(mbp, fid);
1148 + mb_put_uint16le(mbp, fhp->fh_fid1);
720 1149 mb_put_uint32le(mbp, offlo); /* offset (low part) */
721 1150 mb_put_uint16le(mbp, lenlo); /* MaxCount */
722 1151 mb_put_uint16le(mbp, 1); /* MinCount */
723 1152 /* (only indicates blocking) */
724 1153 mb_put_uint32le(mbp, lenhi); /* MaxCountHigh */
725 1154 mb_put_uint16le(mbp, lenlo); /* Remaining ("obsolete") */
726 1155 mb_put_uint32le(mbp, offhi); /* offset (high part) */
727 1156 smb_rq_wend(rqp);
728 1157 smb_rq_bstart(rqp);
729 1158 smb_rq_bend(rqp);
730 1159
731 1160 if (timo == 0)
732 1161 timo = smb_timo_read;
733 1162 error = smb_rq_simple_timed(rqp, timo);
734 1163 if (error)
735 1164 goto out;
736 1165
737 1166 smb_rq_getreply(rqp, &mdp);
738 1167 error = md_get_uint8(mdp, &wc);
739 1168 if (error)
740 1169 goto out;
741 1170 if (wc != 12) {
742 1171 error = EBADRPC;
743 1172 goto out;
744 1173 }
745 1174 md_get_uint8(mdp, NULL);
746 1175 md_get_uint8(mdp, NULL);
747 1176 md_get_uint16le(mdp, NULL);
748 1177 md_get_uint16le(mdp, NULL);
749 1178 md_get_uint16le(mdp, NULL); /* data compaction mode */
750 1179 md_get_uint16le(mdp, NULL);
751 1180 md_get_uint16le(mdp, &lenlo); /* data len ret. */
752 1181 md_get_uint16le(mdp, &doff); /* data offset */
753 1182 md_get_uint16le(mdp, &lenhi);
754 1183 rlen = (lenhi << 16) | lenlo;
755 1184 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
756 1185 error = md_get_uint16le(mdp, NULL); /* ByteCount */
757 1186 if (error)
758 1187 goto out;
759 1188 /*
760 1189 * Does the data offset indicate padding?
761 1190 * The current offset is a constant, found
762 1191 * by counting the md_get_ calls above.
763 1192 */
764 1193 off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */
765 1194 if (doff > off) /* pad byte(s)? */
766 1195 md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM);
767 1196 if (rlen == 0) {
768 1197 *lenp = rlen;
769 1198 goto out;
770 1199 }
771 1200 /* paranoid */
772 1201 if (rlen > *lenp) {
773 1202 SMBSDEBUG("bad server! rlen %d, len %d\n",
774 1203 rlen, *lenp);
775 1204 rlen = *lenp;
776 1205 }
777 1206 error = md_get_uio(mdp, uiop, rlen);
778 1207 if (error)
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
779 1208 goto out;
780 1209
781 1210 /* Success */
782 1211 *lenp = rlen;
783 1212
784 1213 out:
785 1214 smb_rq_done(rqp);
786 1215 return (error);
787 1216 }
788 1217
789 -static int
790 -smb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
1218 +int
1219 +smb_smb_writex(smb_fh_t *fhp, uint32_t *lenp,
791 1220 uio_t *uiop, smb_cred_t *scred, int timo)
792 1221 {
1222 + struct smb_share *ssp = FHTOSS(fhp);
793 1223 struct smb_rq *rqp;
794 1224 struct mbchain *mbp;
795 1225 struct mdchain *mdp;
796 1226 int error;
797 1227 uint32_t offlo, offhi, rlen;
798 1228 uint16_t lenhi, lenlo;
799 1229 uint8_t wc;
800 1230
801 1231 lenhi = (uint16_t)(*lenp >> 16);
802 1232 lenlo = (uint16_t)*lenp;
803 1233 offhi = (uint32_t)(uiop->uio_loffset >> 32);
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
804 1234 offlo = (uint32_t)uiop->uio_loffset;
805 1235
806 1236 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
807 1237 if (error)
808 1238 return (error);
809 1239 smb_rq_getrequest(rqp, &mbp);
810 1240 smb_rq_wstart(rqp);
811 1241 mb_put_uint8(mbp, 0xff); /* no secondary command */
812 1242 mb_put_uint8(mbp, 0); /* MBZ */
813 1243 mb_put_uint16le(mbp, 0); /* offset to secondary */
814 - mb_put_uint16le(mbp, fid);
1244 + mb_put_uint16le(mbp, fhp->fh_fid1);
815 1245 mb_put_uint32le(mbp, offlo); /* offset (low part) */
816 1246 mb_put_uint32le(mbp, 0); /* MBZ (timeout) */
817 1247 mb_put_uint16le(mbp, 0); /* !write-thru */
818 1248 mb_put_uint16le(mbp, 0);
819 1249 mb_put_uint16le(mbp, lenhi);
820 1250 mb_put_uint16le(mbp, lenlo);
821 1251 mb_put_uint16le(mbp, 64); /* data offset from header start */
822 1252 mb_put_uint32le(mbp, offhi); /* offset (high part) */
823 1253 smb_rq_wend(rqp);
824 1254 smb_rq_bstart(rqp);
825 1255
826 1256 mb_put_uint8(mbp, 0); /* pad byte */
827 1257 error = mb_put_uio(mbp, uiop, *lenp);
828 1258 if (error)
829 1259 goto out;
830 1260 smb_rq_bend(rqp);
831 1261 if (timo == 0)
832 1262 timo = smb_timo_write;
833 1263 error = smb_rq_simple_timed(rqp, timo);
834 1264 if (error)
835 1265 goto out;
836 1266 smb_rq_getreply(rqp, &mdp);
837 1267 error = md_get_uint8(mdp, &wc);
838 1268 if (error)
839 1269 goto out;
840 1270 if (wc != 6) {
841 1271 error = EBADRPC;
842 1272 goto out;
843 1273 }
844 1274 md_get_uint8(mdp, NULL); /* andx cmd */
845 1275 md_get_uint8(mdp, NULL); /* reserved */
846 1276 md_get_uint16le(mdp, NULL); /* andx offset */
847 1277 md_get_uint16le(mdp, &lenlo); /* data len ret. */
848 1278 md_get_uint16le(mdp, NULL); /* remaining */
849 1279 error = md_get_uint16le(mdp, &lenhi);
850 1280 if (error)
851 1281 goto out;
|
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
852 1282
853 1283 /* Success */
854 1284 rlen = (lenhi << 16) | lenlo;
855 1285 *lenp = rlen;
856 1286
857 1287 out:
858 1288 smb_rq_done(rqp);
859 1289 return (error);
860 1290 }
861 1291
862 -static int
863 -smb_smb_read(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
864 - uio_t *uiop, smb_cred_t *scred, int timo)
865 -{
866 - struct smb_rq *rqp;
867 - struct mbchain *mbp;
868 - struct mdchain *mdp;
869 - int error;
870 - uint32_t off32;
871 - uint16_t bc, cnt, dlen, rcnt, todo;
872 - uint8_t wc;
873 1292
874 - ASSERT(uiop->uio_loffset <= UINT32_MAX);
875 - off32 = (uint32_t)uiop->uio_loffset;
876 - ASSERT(*lenp <= UINT16_MAX);
877 - cnt = (uint16_t)*lenp;
878 - /* This next is an "estimate" of planned reads. */
879 - todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
880 -
881 - error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp);
882 - if (error)
883 - return (error);
884 - smb_rq_getrequest(rqp, &mbp);
885 - smb_rq_wstart(rqp);
886 - mb_put_uint16le(mbp, fid);
887 - mb_put_uint16le(mbp, cnt);
888 - mb_put_uint32le(mbp, off32);
889 - mb_put_uint16le(mbp, todo);
890 - smb_rq_wend(rqp);
891 - smb_rq_bstart(rqp);
892 - smb_rq_bend(rqp);
893 -
894 - if (timo == 0)
895 - timo = smb_timo_read;
896 - error = smb_rq_simple_timed(rqp, timo);
897 - if (error)
898 - goto out;
899 - smb_rq_getreply(rqp, &mdp);
900 - error = md_get_uint8(mdp, &wc);
901 - if (error)
902 - goto out;
903 - if (wc != 5) {
904 - error = EBADRPC;
905 - goto out;
906 - }
907 - md_get_uint16le(mdp, &rcnt); /* ret. count */
908 - md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); /* res. */
909 - md_get_uint16le(mdp, &bc); /* byte count */
910 - md_get_uint8(mdp, NULL); /* buffer format */
911 - error = md_get_uint16le(mdp, &dlen); /* data len */
912 - if (error)
913 - goto out;
914 - if (dlen < rcnt) {
915 - SMBSDEBUG("oops: dlen=%d rcnt=%d\n",
916 - (int)dlen, (int)rcnt);
917 - rcnt = dlen;
918 - }
919 - if (rcnt == 0) {
920 - *lenp = 0;
921 - goto out;
922 - }
923 - /* paranoid */
924 - if (rcnt > cnt) {
925 - SMBSDEBUG("bad server! rcnt %d, cnt %d\n",
926 - (int)rcnt, (int)cnt);
927 - rcnt = cnt;
928 - }
929 - error = md_get_uio(mdp, uiop, (int)rcnt);
930 - if (error)
931 - goto out;
932 -
933 - /* success */
934 - *lenp = (int)rcnt;
935 -
936 -out:
937 - smb_rq_done(rqp);
938 - return (error);
939 -}
940 -
941 -static int
942 -smb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
943 - uio_t *uiop, smb_cred_t *scred, int timo)
944 -{
945 - struct smb_rq *rqp;
946 - struct mbchain *mbp;
947 - struct mdchain *mdp;
948 - int error;
949 - uint32_t off32;
950 - uint16_t cnt, rcnt, todo;
951 - uint8_t wc;
952 -
953 - ASSERT(uiop->uio_loffset <= UINT32_MAX);
954 - off32 = (uint32_t)uiop->uio_loffset;
955 - ASSERT(*lenp <= UINT16_MAX);
956 - cnt = (uint16_t)*lenp;
957 - /* This next is an "estimate" of planned writes. */
958 - todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
959 -
960 - error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
961 - if (error)
962 - return (error);
963 - smb_rq_getrequest(rqp, &mbp);
964 - smb_rq_wstart(rqp);
965 - mb_put_uint16le(mbp, fid);
966 - mb_put_uint16le(mbp, cnt);
967 - mb_put_uint32le(mbp, off32);
968 - mb_put_uint16le(mbp, todo);
969 - smb_rq_wend(rqp);
970 - smb_rq_bstart(rqp);
971 - mb_put_uint8(mbp, SMB_DT_DATA);
972 - mb_put_uint16le(mbp, cnt);
973 -
974 - error = mb_put_uio(mbp, uiop, *lenp);
975 - if (error)
976 - goto out;
977 - smb_rq_bend(rqp);
978 - if (timo == 0)
979 - timo = smb_timo_write;
980 - error = smb_rq_simple_timed(rqp, timo);
981 - if (error)
982 - goto out;
983 - smb_rq_getreply(rqp, &mdp);
984 - error = md_get_uint8(mdp, &wc);
985 - if (error)
986 - goto out;
987 - if (wc != 1) {
988 - error = EBADRPC;
989 - goto out;
990 - }
991 - error = md_get_uint16le(mdp, &rcnt);
992 - if (error)
993 - goto out;
994 - *lenp = rcnt;
995 -
996 -out:
997 - smb_rq_done(rqp);
998 - return (error);
999 -}
1000 -
1001 -
1002 1293 static u_int32_t smbechoes = 0;
1003 1294
1295 +/*
1296 + * Note: the IOD calls this, so this request must not wait for
1297 + * connection state changes, etc. (uses smb_rq_internal)
1298 + */
1004 1299 int
1005 1300 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo)
1006 1301 {
1007 1302 struct smb_rq *rqp;
1008 1303 struct mbchain *mbp;
1009 1304 int error;
1010 1305
1011 1306 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp);
1012 1307 if (error)
1013 1308 return (error);
1014 1309 mbp = &rqp->sr_rq;
1015 1310 smb_rq_wstart(rqp);
1016 1311 mb_put_uint16le(mbp, 1); /* echo count */
1017 1312 smb_rq_wend(rqp);
1018 1313 smb_rq_bstart(rqp);
1019 1314 mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes));
1020 1315 smb_rq_bend(rqp);
1021 - /*
1022 - * Note: the IOD calls this, so
1023 - * this request must not wait for
1024 - * connection state changes, etc.
1025 - */
1026 1316 rqp->sr_flags |= SMBR_NORECONNECT;
1027 - error = smb_rq_simple_timed(rqp, timo);
1317 + error = smb_rq_internal(rqp, timo);
1028 1318 SMBSDEBUG("%d\n", error);
1029 1319 smb_rq_done(rqp);
1030 1320 return (error);
1031 1321 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX