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) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <smbsrv/smb_kproto.h>
28 #include <smbsrv/smb_fsops.h>
29 #include <smbsrv/smb_share.h>
30 #include <smbsrv/string.h>
31 #include <smbsrv/nmpipes.h>
32 #include <smbsrv/mailslot.h>
33
34 /*
35 * count of bytes in server response packet
36 * except parameters and data. Note that setup
37 * word count is zero.
38 */
39 #define RESP_HEADER_LEN 24
40
41 /*
42 * We started by using common functions for transaction/transaction2
43 * and transaction_secondary/transaction2_secondary because they
44 * are respectively so similar. However, it turned out to be a bad
45 * idea because of quirky differences. Be sure if you modify one
46 * of these four functions to check and see if the modification should
47 * be applied to its peer.
48 */
49
50 static int smb_trans_ready(smb_xa_t *);
51 static smb_sdrc_t smb_trans_dispatch(smb_request_t *, smb_xa_t *);
52 static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *);
53
54 smb_sdrc_t
smb_pre_transaction(smb_request_t * sr)55 smb_pre_transaction(smb_request_t *sr)
56 {
57 DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr);
58 return (SDRC_SUCCESS);
59 }
60
61 void
smb_post_transaction(smb_request_t * sr)62 smb_post_transaction(smb_request_t *sr)
63 {
64 DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr);
65 }
66
67 smb_sdrc_t
smb_com_transaction(smb_request_t * sr)68 smb_com_transaction(smb_request_t *sr)
69 {
70 int rc;
71 unsigned char msrcnt, suwcnt;
72 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags;
73 uint16_t pscnt, psoff, dscnt, dsoff;
74 uint32_t timeo;
75 struct smb_xa *xa;
76 char *stn;
77 int ready;
78
79 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT,
80 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags,
81 &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt);
82
83 if (rc != 0)
84 return (SDRC_ERROR);
85
86 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
87 msrcnt, suwcnt);
88 if (xa == NULL) {
89 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
90 return (SDRC_ERROR);
91 }
92
93 /* Should be some alignment stuff here in SMB? */
94 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) {
95 rc = smbsr_decode_data(sr, "%.U", sr, &stn);
96 } else {
97 rc = smbsr_decode_data(sr, "%s", sr, &stn);
98 }
99 if (rc != 0) {
100 smb_xa_rele(sr->session, xa);
101 return (SDRC_ERROR);
102 }
103
104 xa->xa_pipe_name = smb_mem_strdup(stn);
105 xa->smb_flags = flags;
106 xa->smb_timeout = timeo;
107 xa->req_disp_param = pscnt;
108 xa->req_disp_data = dscnt;
109
110 if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
111 sr->smb_vwv.chain_offset, suwcnt * 2)) {
112 smb_xa_rele(sr->session, xa);
113 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
114 return (SDRC_ERROR);
115 }
116 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
117 smb_xa_rele(sr->session, xa);
118 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
119 return (SDRC_ERROR);
120 }
121 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
122 smb_xa_rele(sr->session, xa);
123 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
124 return (SDRC_ERROR);
125 }
126
127 ready = smb_trans_ready(xa);
128
129 if (smb_xa_open(xa)) {
130 smb_xa_rele(sr->session, xa);
131 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
132 return (SDRC_ERROR);
133 }
134 sr->r_xa = xa;
135
136 if (!ready) {
137 rc = smbsr_encode_empty_result(sr);
138 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
139 }
140
141 if (!smb_xa_complete(xa)) {
142 smb_xa_close(xa);
143 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
144 return (SDRC_ERROR);
145 }
146
147 return (smb_trans_dispatch(sr, xa));
148 }
149
150 smb_sdrc_t
smb_pre_transaction_secondary(smb_request_t * sr)151 smb_pre_transaction_secondary(smb_request_t *sr)
152 {
153 DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr);
154 return (SDRC_SUCCESS);
155 }
156
157 void
smb_post_transaction_secondary(smb_request_t * sr)158 smb_post_transaction_secondary(smb_request_t *sr)
159 {
160 DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr);
161 }
162
163 smb_sdrc_t
smb_com_transaction_secondary(smb_request_t * sr)164 smb_com_transaction_secondary(smb_request_t *sr)
165 {
166 uint16_t tpscnt, tdscnt, pscnt, psdisp;
167 uint16_t dscnt, dsoff, dsdisp, psoff;
168 smb_xa_t *xa;
169 int rc;
170
171 if ((xa = smbsr_lookup_xa(sr)) == 0) {
172 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
173 return (SDRC_ERROR);
174 }
175
176 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
177 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
178 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
179 ERRDOS, ERRnoaccess);
180 return (SDRC_ERROR);
181 }
182 }
183
184 if (xa->smb_com != SMB_COM_TRANSACTION) {
185 return (SDRC_DROP_VC);
186 }
187
188 rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt,
189 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp);
190
191 if (rc != 0)
192 return (SDRC_ERROR);
193
194 mutex_enter(&xa->xa_mutex);
195 if (xa->smb_tpscnt > tpscnt)
196 xa->smb_tpscnt = tpscnt;
197 if (xa->smb_tdscnt > tdscnt)
198 xa->smb_tdscnt = tdscnt;
199 xa->req_disp_param = psdisp + pscnt;
200 xa->req_disp_data = dsdisp + dscnt;
201
202 /*
203 * The words psdisp, dsdisp, tell us what displacement
204 * into the entire trans parameter and data buffers
205 * where we should put the params & data that are
206 * delivered by this request. [MS-CIFS] says all the
207 * parameters and data SHOULD be sent sequentially, so
208 * so we can normally reassemble by simply appending.
209 * However, the components MAY come out of order, so
210 * check and set the current offset. This is rare,
211 * and we might like to know when this happens, so
212 * fire some static dtrace probes when it does.
213 */
214 if (xa->req_param_mb.chain_offset != psdisp) {
215 DTRACE_PROBE2(trans_param_disp,
216 smb_xa_t *, xa, uint16_t, psdisp);
217 xa->req_param_mb.chain_offset = psdisp;
218 }
219 if (xa->req_data_mb.chain_offset != dsdisp) {
220 DTRACE_PROBE2(trans_data_disp,
221 smb_xa_t *, xa, uint16_t, dsdisp);
222 xa->req_data_mb.chain_offset = dsdisp;
223 }
224
225 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
226 mutex_exit(&xa->xa_mutex);
227 smb_xa_close(xa);
228 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
229 return (SDRC_ERROR);
230 }
231 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
232 mutex_exit(&xa->xa_mutex);
233 smb_xa_close(xa);
234 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
235 return (SDRC_ERROR);
236 }
237 mutex_exit(&xa->xa_mutex);
238
239 if (!smb_trans_ready(xa))
240 return (SDRC_NO_REPLY);
241
242 if (!smb_xa_complete(xa))
243 return (SDRC_NO_REPLY);
244
245 return (smb_trans_dispatch(sr, xa));
246 }
247
248 smb_sdrc_t
smb_pre_ioctl(smb_request_t * sr)249 smb_pre_ioctl(smb_request_t *sr)
250 {
251 DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr);
252 return (SDRC_SUCCESS);
253 }
254
255 void
smb_post_ioctl(smb_request_t * sr)256 smb_post_ioctl(smb_request_t *sr)
257 {
258 DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr);
259 }
260
261 smb_sdrc_t
smb_com_ioctl(smb_request_t * sr)262 smb_com_ioctl(smb_request_t *sr)
263 {
264 uint16_t fid, category, function, tpscnt, tdscnt, mprcnt;
265 uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff;
266 uint32_t timeout;
267 int rc;
268
269 rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function,
270 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt,
271 &pdoff, &dscnt, &dsoff);
272
273 if (rc != 0)
274 return (SDRC_ERROR);
275
276 return (SDRC_NOT_IMPLEMENTED);
277 }
278
279 smb_sdrc_t
smb_pre_transaction2(smb_request_t * sr)280 smb_pre_transaction2(smb_request_t *sr)
281 {
282 DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr);
283 return (SDRC_SUCCESS);
284 }
285
286 void
smb_post_transaction2(smb_request_t * sr)287 smb_post_transaction2(smb_request_t *sr)
288 {
289 DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr);
290 }
291
292 smb_sdrc_t
smb_com_transaction2(struct smb_request * sr)293 smb_com_transaction2(struct smb_request *sr)
294 {
295 unsigned char msrcnt, suwcnt;
296 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags;
297 uint16_t pscnt, psoff, dscnt, dsoff;
298 uint32_t timeo;
299 smb_xa_t *xa;
300 int ready;
301 int rc;
302
303 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt,
304 &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt,
305 &dsoff, &suwcnt);
306
307 if (rc != 0)
308 return (SDRC_ERROR);
309
310 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
311 msrcnt, suwcnt);
312 if (xa == 0) {
313 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
314 return (SDRC_ERROR);
315 }
316
317 xa->smb_flags = flags;
318 xa->smb_timeout = timeo;
319 xa->req_disp_param = pscnt;
320 xa->req_disp_data = dscnt;
321
322 if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
323 sr->smb_vwv.chain_offset, suwcnt*2)) {
324 smb_xa_rele(sr->session, xa);
325 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
326 return (SDRC_ERROR);
327 }
328 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
329 smb_xa_rele(sr->session, xa);
330 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
331 return (SDRC_ERROR);
332 }
333 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
334 smb_xa_rele(sr->session, xa);
335 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
336 return (SDRC_ERROR);
337 }
338
339 ready = smb_trans_ready(xa);
340
341 if (smb_xa_open(xa)) {
342 smb_xa_rele(sr->session, xa);
343 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
344 return (SDRC_ERROR);
345 }
346 sr->r_xa = xa;
347
348 if (!ready) {
349 rc = smbsr_encode_empty_result(sr);
350 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
351 }
352
353 if (!smb_xa_complete(xa)) {
354 smb_xa_close(xa);
355 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
356 return (SDRC_ERROR);
357 }
358
359 return (smb_trans2_dispatch(sr, xa));
360 }
361
362 smb_sdrc_t
smb_pre_transaction2_secondary(smb_request_t * sr)363 smb_pre_transaction2_secondary(smb_request_t *sr)
364 {
365 DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr);
366 return (SDRC_SUCCESS);
367 }
368
369 void
smb_post_transaction2_secondary(smb_request_t * sr)370 smb_post_transaction2_secondary(smb_request_t *sr)
371 {
372 DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr);
373 }
374
375 smb_sdrc_t
smb_com_transaction2_secondary(smb_request_t * sr)376 smb_com_transaction2_secondary(smb_request_t *sr)
377 {
378 uint16_t tpscnt, tdscnt, fid;
379 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
380 smb_xa_t *xa;
381 int rc;
382
383 if ((xa = smbsr_lookup_xa(sr)) == 0) {
384 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
385 return (SDRC_ERROR);
386 }
387
388 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
389 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
390 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
391 ERRDOS, ERRnoaccess);
392 return (SDRC_ERROR);
393 }
394 }
395
396 if (xa->smb_com != SMB_COM_TRANSACTION2) {
397 return (SDRC_DROP_VC);
398 }
399
400 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
401 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
402
403 if (rc != 0)
404 return (SDRC_ERROR);
405
406 mutex_enter(&xa->xa_mutex);
407 if (xa->smb_tpscnt > tpscnt)
408 xa->smb_tpscnt = tpscnt;
409 if (xa->smb_tdscnt > tdscnt)
410 xa->smb_tdscnt = tdscnt;
411 if (fid != 0xFFFF)
412 xa->xa_smb_fid = fid;
413 xa->req_disp_param = psdisp + pscnt;
414 xa->req_disp_data = dsdisp + dscnt;
415
416 /*
417 * See comment in smb_com_transaction_secondary
418 */
419 if (xa->req_param_mb.chain_offset != psdisp) {
420 DTRACE_PROBE2(trans_param_disp,
421 smb_xa_t *, xa, uint16_t, psdisp);
422 xa->req_param_mb.chain_offset = psdisp;
423 }
424 if (xa->req_data_mb.chain_offset != dsdisp) {
425 DTRACE_PROBE2(trans_data_disp,
426 smb_xa_t *, xa, uint16_t, dsdisp);
427 xa->req_data_mb.chain_offset = dsdisp;
428 }
429
430 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
431 mutex_exit(&xa->xa_mutex);
432 smb_xa_close(xa);
433 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
434 return (SDRC_ERROR);
435 }
436 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
437 mutex_exit(&xa->xa_mutex);
438 smb_xa_close(xa);
439 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
440 return (SDRC_ERROR);
441 }
442 mutex_exit(&xa->xa_mutex);
443
444 if (!smb_trans_ready(xa))
445 return (SDRC_NO_REPLY);
446
447 if (!smb_xa_complete(xa))
448 return (SDRC_NO_REPLY);
449
450 return (smb_trans2_dispatch(sr, xa));
451 }
452
453 static smb_sdrc_t
smb_nt_trans_dispatch(struct smb_request * sr,struct smb_xa * xa)454 smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
455 {
456 int rc;
457 int total_bytes, n_setup, n_param, n_data;
458 int param_off, param_pad, data_off, data_pad;
459
460 switch (xa->smb_func) {
461 case NT_TRANSACT_CREATE:
462 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0)
463 rc = smb_nt_transact_create(sr, xa);
464 smb_post_nt_transact_create(sr, xa);
465 break;
466 case NT_TRANSACT_NOTIFY_CHANGE:
467 rc = smb_nt_transact_notify_change(sr, xa);
468 break;
469 case NT_TRANSACT_QUERY_SECURITY_DESC:
470 rc = smb_nt_transact_query_security_info(sr, xa);
471 break;
472 case NT_TRANSACT_SET_SECURITY_DESC:
473 rc = smb_nt_transact_set_security_info(sr, xa);
474 break;
475 case NT_TRANSACT_IOCTL:
476 rc = smb_nt_transact_ioctl(sr, xa);
477 break;
478 case NT_TRANSACT_QUERY_QUOTA:
479 rc = smb_nt_transact_query_quota(sr, xa);
480 break;
481 case NT_TRANSACT_SET_QUOTA:
482 rc = smb_nt_transact_set_quota(sr, xa);
483 break;
484 case NT_TRANSACT_RENAME:
485 rc = smb_nt_transact_rename(sr, xa);
486 break;
487
488 default:
489 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
490 return (SDRC_ERROR);
491 }
492
493 switch (rc) {
494 case SDRC_SUCCESS:
495 break;
496
497 case SDRC_DROP_VC:
498 case SDRC_NO_REPLY:
499 case SDRC_ERROR:
500 case SDRC_SR_KEPT:
501 return (rc);
502
503 case SDRC_NOT_IMPLEMENTED:
504 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
505 return (SDRC_ERROR);
506
507 default:
508 break;
509 }
510
511 n_setup = MBC_LENGTH(&xa->rep_setup_mb);
512 n_param = MBC_LENGTH(&xa->rep_param_mb);
513 n_data = MBC_LENGTH(&xa->rep_data_mb);
514
515 if (xa->smb_msrcnt < n_setup ||
516 xa->smb_mprcnt < n_param ||
517 xa->smb_mdrcnt < n_data) {
518 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
519 return (SDRC_ERROR);
520 }
521
522 /* neato, blast it over there */
523
524 n_setup = (n_setup + 1) / 2; /* Conver to setup words */
525 param_pad = 1; /* must be one */
526 param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
527 data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */
528 data_off = param_off + n_param + data_pad; /* Param off from hdr */
529 total_bytes = param_pad + n_param + data_pad + n_data;
530
531 rc = smbsr_encode_result(sr, 18+n_setup, total_bytes,
532 "b3.llllllllbCw#.C#.C",
533 18 + n_setup, /* wct */
534 n_param, /* Total Parameter Bytes */
535 n_data, /* Total Data Bytes */
536 n_param, /* Total Parameter Bytes this buffer */
537 param_off, /* Param offset from header start */
538 0, /* Param displacement */
539 n_data, /* Total Data Bytes this buffer */
540 data_off, /* Data offset from header start */
541 0, /* Data displacement */
542 n_setup, /* suwcnt */
543 &xa->rep_setup_mb, /* setup[] */
544 total_bytes, /* Total data bytes */
545 param_pad,
546 &xa->rep_param_mb,
547 data_pad,
548 &xa->rep_data_mb);
549 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
550 }
551
552 smb_sdrc_t
smb_pre_nt_transact(smb_request_t * sr)553 smb_pre_nt_transact(smb_request_t *sr)
554 {
555 DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr);
556 return (SDRC_SUCCESS);
557 }
558
559 void
smb_post_nt_transact(smb_request_t * sr)560 smb_post_nt_transact(smb_request_t *sr)
561 {
562 DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr);
563 }
564
565 smb_sdrc_t
smb_com_nt_transact(struct smb_request * sr)566 smb_com_nt_transact(struct smb_request *sr)
567 {
568 uint16_t Function;
569 unsigned char MaxSetupCount, SetupCount;
570 uint32_t TotalParameterCount, TotalDataCount;
571 uint32_t MaxParameterCount, MaxDataCount, pscnt;
572 uint32_t psoff, dscnt, dsoff;
573 smb_xa_t *xa;
574 int ready;
575 int rc;
576
577 rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount,
578 &TotalParameterCount, &TotalDataCount, &MaxParameterCount,
579 &MaxDataCount, &pscnt, &psoff, &dscnt,
580 &dsoff, &SetupCount, &Function);
581
582 if (rc != 0)
583 return (SDRC_ERROR);
584
585 xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount,
586 MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount);
587 if (xa == 0) {
588 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
589 return (SDRC_ERROR);
590 }
591
592 xa->smb_flags = 0;
593 xa->smb_timeout = 0;
594 xa->smb_func = Function;
595 xa->req_disp_param = pscnt;
596 xa->req_disp_data = dscnt;
597
598 if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
599 sr->smb_vwv.chain_offset, SetupCount * 2)) {
600 smb_xa_rele(sr->session, xa);
601 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
602 return (SDRC_ERROR);
603 }
604 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
605 smb_xa_rele(sr->session, xa);
606 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
607 return (SDRC_ERROR);
608 }
609 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
610 smb_xa_rele(sr->session, xa);
611 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
612 return (SDRC_ERROR);
613 }
614
615 ready = smb_trans_ready(xa);
616
617 if (smb_xa_open(xa)) {
618 smb_xa_rele(sr->session, xa);
619 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
620 return (SDRC_ERROR);
621 }
622 sr->r_xa = xa;
623
624 if (!ready) {
625 rc = smbsr_encode_empty_result(sr);
626 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
627 }
628
629 if (!smb_xa_complete(xa)) {
630 smb_xa_close(xa);
631 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
632 return (SDRC_ERROR);
633 }
634
635 return (smb_nt_trans_dispatch(sr, xa));
636 }
637
638 smb_sdrc_t
smb_pre_nt_transact_secondary(smb_request_t * sr)639 smb_pre_nt_transact_secondary(smb_request_t *sr)
640 {
641 DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr);
642 return (SDRC_SUCCESS);
643 }
644
645 void
smb_post_nt_transact_secondary(smb_request_t * sr)646 smb_post_nt_transact_secondary(smb_request_t *sr)
647 {
648 DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr);
649 }
650
651 smb_sdrc_t
smb_com_nt_transact_secondary(struct smb_request * sr)652 smb_com_nt_transact_secondary(struct smb_request *sr)
653 {
654 uint16_t tpscnt, tdscnt, fid;
655 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
656 smb_xa_t *xa;
657 int rc;
658
659 if ((xa = smbsr_lookup_xa(sr)) == 0) {
660 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
661 return (SDRC_ERROR);
662 }
663
664 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
665 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
666 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
667 ERRDOS, ERRnoaccess);
668 return (SDRC_ERROR);
669 }
670 }
671
672 if (xa->smb_com != SMB_COM_TRANSACTION2) {
673 return (SDRC_DROP_VC);
674 }
675
676 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
677 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
678
679 if (rc != 0)
680 return (SDRC_ERROR);
681
682 mutex_enter(&xa->xa_mutex);
683 if (xa->smb_tpscnt > tpscnt)
684 xa->smb_tpscnt = tpscnt;
685 if (xa->smb_tdscnt > tdscnt)
686 xa->smb_tdscnt = tdscnt;
687 if (fid != 0xFFFF)
688 xa->xa_smb_fid = fid;
689 xa->req_disp_param = psdisp + pscnt;
690 xa->req_disp_data = dsdisp + dscnt;
691
692 /*
693 * See comment in smb_com_transaction_secondary
694 */
695 if (xa->req_param_mb.chain_offset != psdisp) {
696 DTRACE_PROBE2(trans_param_disp,
697 smb_xa_t *, xa, uint16_t, psdisp);
698 xa->req_param_mb.chain_offset = psdisp;
699 }
700 if (xa->req_data_mb.chain_offset != dsdisp) {
701 DTRACE_PROBE2(trans_data_disp,
702 smb_xa_t *, xa, uint16_t, dsdisp);
703 xa->req_data_mb.chain_offset = dsdisp;
704 }
705
706 if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
707 mutex_exit(&xa->xa_mutex);
708 smb_xa_close(xa);
709 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
710 return (SDRC_ERROR);
711 }
712 if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
713 mutex_exit(&xa->xa_mutex);
714 smb_xa_close(xa);
715 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
716 return (SDRC_ERROR);
717 }
718 mutex_exit(&xa->xa_mutex);
719
720 if (!smb_trans_ready(xa))
721 return (SDRC_NO_REPLY);
722
723 if (!smb_xa_complete(xa))
724 return (SDRC_NO_REPLY);
725
726 return (smb_nt_trans_dispatch(sr, xa));
727 }
728
729 static int
smb_trans_ready(smb_xa_t * xa)730 smb_trans_ready(smb_xa_t *xa)
731 {
732 int rc;
733
734 mutex_enter(&xa->xa_mutex);
735 rc = xa->req_disp_data >= xa->smb_tdscnt &&
736 xa->req_disp_param >= xa->smb_tpscnt;
737 mutex_exit(&xa->xa_mutex);
738
739 return (rc);
740 }
741
742 static void
smb_encode_SHARE_INFO_1(struct mbuf_chain * output,struct mbuf_chain * text,char * oem_name,uint16_t type,char * comment)743 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
744 char *oem_name, uint16_t type, char *comment)
745 {
746 (void) smb_mbc_encodef(output, "13c.wl", oem_name,
747 type, MBC_LENGTH(text));
748
749 (void) smb_mbc_encodef(text, "s", comment ? comment : "");
750 }
751
752 static void
smb_encode_SHARE_INFO_2(struct mbuf_chain * output,struct mbuf_chain * text,smb_request_t * sr,char * oem_name,uint16_t type,char * comment,uint16_t access,char * path,char * password)753 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
754 smb_request_t *sr, char *oem_name, uint16_t type,
755 char *comment, uint16_t access, char *path, char *password)
756 {
757 unsigned char pword[9];
758
759 bzero(pword, sizeof (pword));
760 (void) strncpy((char *)pword, password, sizeof (pword));
761 smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment);
762 (void) smb_mbc_encodef(output, "wwwl9c.",
763 access,
764 sr->sr_cfg->skc_maxconnections,
765 smb_server_get_session_count(sr->sr_server),
766 MBC_LENGTH(text),
767 pword);
768 (void) smb_mbc_encodef(text, "s", path);
769 }
770
771 int
smb_trans_net_share_enum(struct smb_request * sr,struct smb_xa * xa)772 smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
773 {
774 /*
775 * Number of data bytes that will
776 * be sent in the current response
777 */
778 uint16_t data_scnt;
779
780 /*
781 * Total number of data bytes that
782 * are sent till now. This is only
783 * used for calculating current data
784 * displacement
785 */
786 uint16_t tot_data_scnt;
787
788 /*
789 * Number of parameter bytes should
790 * be sent for the current response.
791 * It is 8 for the 1st response and
792 * 0 for others
793 */
794 uint16_t param_scnt;
795
796 /* number of setup and parameter bytes */
797 uint16_t n_setup, n_param;
798
799 /* data and parameter displacement */
800 uint16_t data_disp, param_disp;
801
802 /* parameter and data offset and pad */
803 int param_off, param_pad, data_off, data_pad;
804
805 /*
806 * total bytes of parameters and data
807 * in the packet, plus the pad bytes.
808 */
809 int tot_packet_bytes;
810
811 boolean_t first_resp;
812
813 char fmt[16];
814 struct mbuf_chain reply;
815
816 uint16_t level;
817 uint16_t pkt_bufsize;
818 smb_enumshare_info_t esi;
819 char *sent_buf;
820
821 ASSERT(sr->uid_user);
822
823 if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level,
824 &esi.es_bufsize) != 0)
825 return (SDRC_NOT_IMPLEMENTED);
826
827 if (level != 1) {
828 /*
829 * Only level 1 is valid for NetShareEnum
830 * None of the error codes in the spec are meaningful
831 * here. This error code is returned by Windows.
832 */
833 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
834 ERROR_INVALID_LEVEL, 0, 0, 0);
835 return (SDRC_SUCCESS);
836 }
837
838 esi.es_buf = smb_srm_zalloc(sr, esi.es_bufsize);
839 esi.es_posix_uid = crgetuid(sr->uid_user->u_cred);
840 smb_kshare_enum(sr->sr_server, &esi);
841
842 /* client buffer size is not big enough to hold any shares */
843 if (esi.es_nsent == 0) {
844 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
845 ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal);
846 return (SDRC_SUCCESS);
847 }
848
849 /*
850 * Initialize the reply mbuf chain. Note that we re-initialize
851 * this on each pass through the loop below.
852 */
853 MBC_SETUP(&reply, smb_maxbufsize);
854
855 /*
856 * The rep_setup_mb is already initialized in smb_trans_dispatch().
857 * Calling MBC_INIT() will initialized the structure and so the
858 * pointer to the mbuf chains will be lost. Therefore, we need
859 * to free the resources before calling MBC_INIT() again.
860 */
861 n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */
862 MBC_FLUSH(&xa->rep_setup_mb);
863
864 n_param = 8;
865 pkt_bufsize = sr->session->smb_msg_size -
866 (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
867
868 tot_data_scnt = 0;
869 sent_buf = esi.es_buf;
870 first_resp = B_TRUE;
871
872 while (tot_data_scnt < esi.es_datasize) {
873 data_scnt = esi.es_datasize - tot_data_scnt;
874 if (data_scnt > pkt_bufsize)
875 data_scnt = pkt_bufsize;
876 MBC_FLUSH(&xa->rep_data_mb);
877
878 (void) sprintf(fmt, "%dc", data_scnt);
879 (void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf);
880
881 sent_buf += data_scnt;
882 tot_data_scnt += data_scnt;
883
884 /* Only the 1st response packet contains parameters */
885 param_scnt = (first_resp) ? n_param : 0;
886 param_pad = 1; /* always one */
887 param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
888 param_disp = (first_resp) ? 0 : n_param;
889
890 MBC_FLUSH(&xa->rep_param_mb);
891
892 if (first_resp) {
893 first_resp = B_FALSE;
894 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
895 (esi.es_ntotal > esi.es_nsent)
896 ? ERROR_MORE_DATA : 0,
897 0, esi.es_nsent, esi.es_ntotal);
898 }
899
900 data_pad = (param_off + n_param) & 1; /* Pad to short */
901
902 /* data off from hdr start */
903 data_off = param_off + param_scnt + data_pad;
904 data_disp = tot_data_scnt - data_scnt;
905 tot_packet_bytes = param_pad + param_scnt + data_pad +
906 data_scnt;
907
908 MBC_FLUSH(&reply);
909 (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT,
910 sr->first_smb_com,
911 sr->smb_rcls,
912 sr->smb_reh,
913 sr->smb_err,
914 sr->smb_flg | SMB_FLAGS_REPLY,
915 sr->smb_flg2,
916 sr->smb_pid_high,
917 sr->smb_sig,
918 sr->smb_tid,
919 sr->smb_pid,
920 sr->smb_uid,
921 sr->smb_mid);
922
923 (void) smb_mbc_encodef(&reply,
924 "bww2.wwwwwwb.Cw#.C#.C",
925 10 + n_setup, /* wct */
926 n_param, /* Total Parameter Bytes */
927 esi.es_datasize, /* Total Data Bytes */
928 param_scnt, /* Total Parameter Bytes this buffer */
929 param_off, /* Param offset from header start */
930 param_disp, /* Param displacement */
931 data_scnt, /* Total Data Bytes this buffer */
932 data_off, /* Data offset from header start */
933 data_disp, /* Data displacement */
934 n_setup, /* suwcnt */
935 &xa->rep_setup_mb, /* setup[] */
936 tot_packet_bytes, /* Total data bytes */
937 param_pad,
938 &xa->rep_param_mb,
939 data_pad,
940 &xa->rep_data_mb);
941
942 if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
943 smb_sign_reply(sr, &reply);
944
945 (void) smb_session_send(sr->session, 0, &reply);
946
947 }
948
949 m_freem(reply.chain);
950
951 return (SDRC_NO_REPLY);
952 }
953
954 int
smb_trans_net_share_getinfo(smb_request_t * sr,struct smb_xa * xa)955 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa)
956 {
957 uint16_t level, max_bytes, access;
958 struct mbuf_chain str_mb;
959 char *share;
960 char *password;
961 smb_kshare_t *si;
962
963 if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
964 &share, &level, &max_bytes) != 0)
965 return (SDRC_NOT_IMPLEMENTED);
966
967 si = smb_kshare_lookup(sr->sr_server, share);
968 if ((si == NULL) || (si->shr_oemname == NULL)) {
969 (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
970 NERR_NetNameNotFound, 0, 0);
971 if (si)
972 smb_kshare_release(sr->sr_server, si);
973 return (SDRC_SUCCESS);
974 }
975
976 access = SHARE_ACCESS_ALL;
977 password = "";
978
979 MBC_INIT(&str_mb, max_bytes);
980
981 switch (level) {
982 case 0 :
983 (void) smb_mbc_encodef(&xa->rep_data_mb, "13c",
984 si->shr_oemname);
985 break;
986
987 case 1 :
988 smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
989 si->shr_oemname, si->shr_type, si->shr_cmnt);
990 break;
991
992 case 2 :
993 smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
994 si->shr_oemname, si->shr_type, si->shr_cmnt, access,
995 si->shr_path, password);
996 break;
997
998 default:
999 smb_kshare_release(sr->sr_server, si);
1000 (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1001 ERROR_INVALID_LEVEL, 0, 0);
1002 m_freem(str_mb.chain);
1003 return (SDRC_NOT_IMPLEMENTED);
1004 }
1005
1006 smb_kshare_release(sr->sr_server, si);
1007 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success,
1008 -MBC_LENGTH(&xa->rep_data_mb),
1009 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1010 (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1011 m_freem(str_mb.chain);
1012 return (SDRC_SUCCESS);
1013 }
1014
1015 int
smb_trans_net_workstation_getinfo(struct smb_request * sr,struct smb_xa * xa)1016 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa)
1017 {
1018 uint16_t level, max_bytes;
1019 struct mbuf_chain str_mb;
1020 char *domain;
1021 char *hostname;
1022
1023 if ((smb_mbc_decodef(&xa->req_param_mb, "ww",
1024 &level, &max_bytes) != 0) ||
1025 (level != 10)) {
1026 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
1027 NERR_BadTransactConfig, 0, 0, 0);
1028 return (SDRC_SUCCESS);
1029 }
1030
1031 domain = sr->sr_cfg->skc_nbdomain;
1032 hostname = sr->sr_cfg->skc_hostname;
1033
1034 MBC_INIT(&str_mb, max_bytes);
1035
1036 (void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */
1037
1038 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1039 (void) smb_mbc_encodef(&str_mb, "s", hostname);
1040 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1041 (void) smb_mbc_encodef(&str_mb, "s", "nobody");
1042 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1043 (void) smb_mbc_encodef(&str_mb, "s", domain);
1044 (void) smb_mbc_encodef(&xa->rep_data_mb, "bbl",
1045 (uint8_t)sr->sr_cfg->skc_version.sv_major,
1046 (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1047 MBC_LENGTH(&str_mb));
1048 (void) smb_mbc_encodef(&str_mb, "s", domain);
1049 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1050 (void) smb_mbc_encodef(&str_mb, "s", domain);
1051
1052 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0,
1053 -MBC_LENGTH(&xa->rep_data_mb),
1054 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1055 (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1056 m_freem(str_mb.chain);
1057 return (SDRC_SUCCESS);
1058 }
1059
1060 int
smb_trans_net_user_getinfo(struct smb_request * sr,struct smb_xa * xa)1061 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa)
1062 {
1063 uint16_t level, max_bytes;
1064 unsigned char *user;
1065 int rc;
1066
1067 rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
1068 &user,
1069 &level,
1070 &max_bytes);
1071
1072 if (rc != 0)
1073 return (SDRC_NOT_IMPLEMENTED);
1074
1075 (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1076 NERR_UserNotFound, 0, 0);
1077 return (SDRC_SUCCESS);
1078 }
1079
1080 smb_sdrc_t
smb_trans_net_server_getinfo(struct smb_request * sr,struct smb_xa * xa)1081 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa)
1082 {
1083 uint16_t level, buf_size;
1084 uint16_t avail_data, max_data;
1085 char server_name[16];
1086 struct mbuf_chain str_mb;
1087
1088 if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0)
1089 return (SDRC_ERROR);
1090
1091 max_data = MBC_MAXBYTES(&xa->rep_data_mb);
1092
1093 MBC_INIT(&str_mb, buf_size);
1094
1095 bzero(server_name, sizeof (server_name));
1096 (void) strncpy(server_name, sr->sr_cfg->skc_hostname,
1097 sizeof (server_name));
1098
1099 /* valid levels are 0 and 1 */
1100 switch (level) {
1101 case 0:
1102 (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name);
1103 break;
1104
1105 case 1:
1106 (void) smb_mbc_encodef(&str_mb, "s",
1107 sr->sr_cfg->skc_system_comment);
1108 (void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name,
1109 (uint8_t)sr->sr_cfg->skc_version.sv_major,
1110 (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1111 MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb));
1112 break;
1113
1114 default:
1115 (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1116 ERROR_INVALID_LEVEL, 0, 0);
1117 m_freem(str_mb.chain);
1118 return (SDRC_SUCCESS);
1119 }
1120
1121 avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb);
1122 (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1123 NERR_Success, max_data - avail_data, avail_data);
1124 (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1125 m_freem(str_mb.chain);
1126 return (SDRC_SUCCESS);
1127 }
1128
1129 /*
1130 * 6.4 The NetServerEnum2 RAP Service
1131 *
1132 * The NetServerEnum2 RAP service lists all computers of the specified type
1133 * or types that are visible in the specified domains. It may also
1134 * enumerate domains.
1135 *
1136 * The following definition uses the notation and terminology defined in
1137 * the CIFS Remote Administration Protocol specification, which is required
1138 * in order to make it well-defined. The definition is:
1139 *
1140 * uint16_t NetServerEnum2 (
1141 * uint16_t sLevel,
1142 * RCVBUF pbBuffer,
1143 * RCVBUFLEN cbBuffer,
1144 * ENTCOUNT pcEntriesRead,
1145 * uint16_t *pcTotalAvail,
1146 * uint32_t fServerType,
1147 * char *pszDomain,
1148 * );
1149 *
1150 * where:
1151 *
1152 * sLevel specifies the level of detail (0 or 1) requested.
1153 *
1154 * pbBuffer points to the buffer to receive the returned data. If the
1155 * function is successful, the buffer contains a sequence of
1156 * server_info_x structures, where x is 0 or 1, depending on the
1157 * level of detail requested.
1158 *
1159 * cbBuffer specifies the size, in bytes, of the buffer pointed to by
1160 * the pbBuffer parameter.
1161 *
1162 * pcEntriesRead points to a 16 bit variable that receives a count of
1163 * the number of servers enumerated in the buffer. This count is
1164 * valid only if NetServerEnum2 returns the NERR_Success or
1165 * ERROR_MORE_DATA values.
1166 *
1167 * pcTotal Avail points to a 16 bit variable that receives a count of
1168 * the total number of available entries. This count is valid only if
1169 * NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values.
1170 *
1171 * fServerType specifies the type or types of computers to enumerate.
1172 * Computers that match at least one of the specified types are
1173 * returned in the buffer. Possible values are defined in the request
1174 * parameters section.
1175 *
1176 * pszDomain points to a null-terminated string that contains the
1177 * name of the workgroup in which to enumerate computers of the
1178 * specified type or types. If the pszDomain parameter is a null
1179 * string or a null pointer, servers are enumerated for the current
1180 * domain of the computer.
1181 *
1182 * 6.4.1 Transaction Request Parameters section
1183 *
1184 * The Transaction request parameters section in this instance contains:
1185 * . The 16 bit function number for NetServerEnum2 which is 104.
1186 * . The parameter descriptor string which is "WrLehDz".
1187 * . The data descriptor string for the (returned) data which is "B16" for
1188 * level detail 0 or "B16BBDz" for level detail 1.
1189 * . The actual parameters as described by the parameter descriptor
1190 * string.
1191 *
1192 * The parameters are:
1193 * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in
1194 * the parameter descriptor string. This represents the level of detail
1195 * the server is expected to return
1196 * . A 16 bit integer that contains the size of the receive buffer.
1197 * . A 32 bit integer that represents the type of servers the function
1198 * should enumerate. The possible values may be any of the following or
1199 * a combination of the following:
1200 *
1201 * SV_TYPE_WORKSTATION 0x00000001 All workstations
1202 * SV_TYPE_SERVER 0x00000002 All servers
1203 * SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL
1204 * server
1205 * SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller
1206 * SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller
1207 * SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource
1208 * service
1209 * SV_TYPE_AFP 0x00000040 Apple File Protocol servers
1210 * SV_TYPE_NOVELL 0x00000080 Novell servers
1211 * SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member
1212 * SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue
1213 * SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service.
1214 * SV_TYPE_XENIX_SERVER 0x00000800 Xenix server
1215 * SV_TYPE_NT 0x00001000 NT server
1216 * SV_TYPE_WFW 0x00002000 Server running Windows for
1217 * Workgroups
1218 * SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server
1219 * SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser
1220 * service
1221 * SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server
1222 * SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server
1223 * SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server
1224 * SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked
1225 * "local"
1226 * SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszDomain
1227 * parameter must be NULL.
1228 *
1229 * . A null terminated ASCII string representing the pszDomain parameter
1230 * described above
1231 *
1232 * 6.4.2 Transaction Request Data section
1233 *
1234 * There is no data or auxiliary data to send as part of the request.
1235 *
1236 * 6.4.3 Transaction Response Parameters section
1237 *
1238 * The transaction response parameters section consists of:
1239 * . A 16 bit word indicating the return status. The possible values are:
1240 *
1241 * Code Value Description
1242 * NERR_Success 0 No errors encountered
1243 * ERROR_MORE_DATA 234 Additional data is available
1244 * NERR_ServerNotStarted 2114 The RAP service on the remote computer
1245 * is not running
1246 * NERR_BadTransactConfig 2141 The server is not configured for
1247 * transactions, IPC$ is not shared
1248 *
1249 * . A 16 bit "converter" word.
1250 * . A 16 bit number representing the number of entries returned.
1251 * . A 16 bit number representing the total number of available entries.
1252 * If the supplied buffer is large enough, this will equal the number of
1253 * entries returned.
1254 *
1255 * 6.4.4 Transaction Response Data section
1256 *
1257 * The return data section consists of a number of SERVER_INFO_1 structures.
1258 * The number of such structures present is determined by the third entry
1259 * (described above) in the return parameters section.
1260 *
1261 * At level detail 0, the Transaction response data section contains a
1262 * number of SERVER_INFO_0 data structure. The number of such structures is
1263 * equal to the 16 bit number returned by the server in the third parameter
1264 * in the Transaction response parameter section. The SERVER_INFO_0 data
1265 * structure is defined as:
1266 *
1267 * struct SERVER_INFO_0 {
1268 * char sv0_name[16];
1269 * };
1270 *
1271 * where:
1272 *
1273 * sv0_name is a null-terminated string that specifies the name of a
1274 * computer or domain .
1275 *
1276 * At level detail 1, the Transaction response data section contains a
1277 * number of SERVER_INFO_1 data structure. The number of such structures is
1278 * equal to the 16 bit number returned by the server in the third parameter
1279 * in the Transaction response parameter section. The SERVER_INFO_1 data
1280 * structure is defined as:
1281 *
1282 * struct SERVER_INFO_1 {
1283 * char sv1_name[16];
1284 * char sv1_version_major;
1285 * char sv1_version_minor;
1286 * uint32_t sv1_type;
1287 * char *sv1_comment_or_master_browser;
1288 * };
1289 *
1290 * sv1_name contains a null-terminated string that specifies the name
1291 * of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in
1292 * sv1_type.
1293 *
1294 * sv1_version_major whatever was specified in the HostAnnouncement
1295 * or DomainAnnouncement frame with which the entry was registered.
1296 *
1297 * sv1_version_minor whatever was specified in the HostAnnouncement
1298 * or DomainAnnouncement frame with which the entry was registered.
1299 *
1300 * sv1_type specifies the type of software the computer is running.
1301 * The member can be one or a combination of the values defined above
1302 * in the Transaction request parameters section for fServerType.
1303 *
1304 *
1305 * sv1_comment_or_master_browser points to a null-terminated string. If
1306 * the sv1_type indicates that the entry is for a domain, this
1307 * specifies the name of server running the domain master browser;
1308 * otherwise, it specifies a comment describing the server. The comment
1309 * can be a null string or the pointer may be a null pointer.
1310 *
1311 * In case there are multiple SERVER_INFO_1 data structures to
1312 * return, the server may put all these fixed length structures in
1313 * the return buffer, leave some space and then put all the variable
1314 * length data (the actual value of the sv1_comment strings) at the
1315 * end of the buffer.
1316 *
1317 * There is no auxiliary data to receive.
1318 */
1319
1320 int
smb_trans_net_server_enum2(struct smb_request * sr,struct smb_xa * xa)1321 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
1322 {
1323 uint16_t opcode, level, max_bytes;
1324 uint32_t server_type;
1325 unsigned char *domain;
1326 struct mbuf_chain str_mb;
1327 char *hostname, *s;
1328 smb_kmod_cfg_t *si;
1329
1330 if (smb_mbc_decodef(&xa->req_param_mb,
1331 "%wsswwls", sr, &opcode, &s, &s,
1332 &level, &max_bytes, &server_type, &domain) != 0)
1333 return (SDRC_NOT_IMPLEMENTED);
1334
1335 si = sr->sr_cfg;
1336
1337 if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) {
1338 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1339 return (SDRC_SUCCESS);
1340 }
1341
1342 if ((server_type & MY_SERVER_TYPE) == 0) {
1343 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1344 return (SDRC_SUCCESS);
1345 }
1346
1347 MBC_INIT(&str_mb, max_bytes);
1348
1349 hostname = si->skc_hostname;
1350
1351 (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname);
1352 if (level == 1) {
1353 (void) smb_mbc_encodef(&xa->rep_data_mb, "bbll",
1354 (uint8_t)sr->sr_cfg->skc_version.sv_major,
1355 (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1356 MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1357 (void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment);
1358 }
1359
1360 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0,
1361 -MBC_LENGTH(&xa->rep_data_mb), 1, 1);
1362 (void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain);
1363 return (SDRC_SUCCESS);
1364 }
1365
1366 static boolean_t
is_supported_mailslot(const char * mailslot)1367 is_supported_mailslot(const char *mailslot)
1368 {
1369 static char *mailslots[] = {
1370 PIPE_LANMAN,
1371 MAILSLOT_LANMAN,
1372 MAILSLOT_BROWSE,
1373 MAILSLOT_MSBROWSE
1374 };
1375
1376 int i;
1377
1378 for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i)
1379 if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0)
1380 return (B_TRUE);
1381
1382 return (B_FALSE);
1383 }
1384
1385 /*
1386 * smb_trans_nmpipe
1387 *
1388 * This is used for RPC bind and request transactions.
1389 *
1390 * If the data available from the pipe is larger than the maximum
1391 * data size requested by the client, return as much as requested.
1392 * The residual data remains in the pipe until the client comes back
1393 * with a read request or closes the pipe.
1394 *
1395 * When we read less than what's available, we MUST return the
1396 * status NT_STATUS_BUFFER_OVERFLOW (or ERRDOS/ERROR_MORE_DATA)
1397 */
1398 static smb_sdrc_t
smb_trans_nmpipe(smb_request_t * sr,smb_xa_t * xa)1399 smb_trans_nmpipe(smb_request_t *sr, smb_xa_t *xa)
1400 {
1401 smb_vdb_t vdb;
1402 struct mbuf *mb;
1403 int rc;
1404
1405 smbsr_lookup_file(sr);
1406 if (sr->fid_ofile == NULL) {
1407 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
1408 ERRDOS, ERRbadfid);
1409 return (SDRC_ERROR);
1410 }
1411
1412 rc = smb_mbc_decodef(&xa->req_data_mb, "#B",
1413 xa->smb_tdscnt, &vdb);
1414 if (rc != 0) {
1415 /* Not enough data sent. */
1416 smbsr_error(sr, 0, ERRSRV, ERRerror);
1417 return (SDRC_ERROR);
1418 }
1419
1420 rc = smb_opipe_write(sr, &vdb.vdb_uio);
1421 if (rc != 0) {
1422 smbsr_errno(sr, rc);
1423 return (SDRC_ERROR);
1424 }
1425
1426 vdb.vdb_tag = 0;
1427 vdb.vdb_uio.uio_iov = &vdb.vdb_iovec[0];
1428 vdb.vdb_uio.uio_iovcnt = MAX_IOVEC;
1429 vdb.vdb_uio.uio_segflg = UIO_SYSSPACE;
1430 vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
1431 vdb.vdb_uio.uio_loffset = (offset_t)0;
1432 vdb.vdb_uio.uio_resid = xa->smb_mdrcnt;
1433 mb = smb_mbuf_allocate(&vdb.vdb_uio);
1434
1435 rc = smb_opipe_read(sr, &vdb.vdb_uio);
1436 if (rc != 0) {
1437 m_freem(mb);
1438 smbsr_errno(sr, rc);
1439 return (SDRC_ERROR);
1440 }
1441
1442 smb_mbuf_trim(mb, xa->smb_mdrcnt - vdb.vdb_uio.uio_resid);
1443 MBC_ATTACH_MBUF(&xa->rep_data_mb, mb);
1444
1445 /*
1446 * If the output buffer holds a partial pipe message,
1447 * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
1448 * As we don't have message boundary markers, the best
1449 * we can do is return that status when we have ALL of:
1450 * Output buffer was < SMB_PIPE_MAX_MSGSIZE
1451 * We filled the output buffer (resid==0)
1452 * There's more data (ioctl FIONREAD)
1453 */
1454 if (xa->smb_mdrcnt < SMB_PIPE_MAX_MSGSIZE &&
1455 vdb.vdb_uio.uio_resid == 0) {
1456 int nread = 0;
1457 rc = smb_opipe_get_nread(sr, &nread);
1458 if (rc == 0 && nread != 0) {
1459 smbsr_status(sr, NT_STATUS_BUFFER_OVERFLOW,
1460 ERRDOS, ERROR_MORE_DATA);
1461 }
1462 }
1463
1464 return (SDRC_SUCCESS);
1465 }
1466
1467 static smb_sdrc_t
smb_trans_dispatch(smb_request_t * sr,smb_xa_t * xa)1468 smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa)
1469 {
1470 int rc, pos;
1471 int total_bytes, n_setup, n_param, n_data;
1472 int param_off, param_pad, data_off, data_pad;
1473 uint16_t opcode;
1474 uint16_t devstate;
1475 char *req_fmt;
1476 char *rep_fmt;
1477
1478 if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) {
1479 rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode,
1480 &sr->smb_fid);
1481 if (rc != 0)
1482 goto trans_err_not_supported;
1483 switch (opcode) {
1484 case TRANS_SET_NMPIPE_STATE:
1485 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w",
1486 &devstate)) != 0)
1487 goto trans_err_not_supported;
1488
1489 rc = SDRC_SUCCESS;
1490 break;
1491
1492 case TRANS_TRANSACT_NMPIPE:
1493 rc = smb_trans_nmpipe(sr, xa);
1494 break;
1495
1496 case TRANS_WAIT_NMPIPE:
1497 delay(SEC_TO_TICK(1));
1498 rc = SDRC_SUCCESS;
1499 break;
1500
1501 default:
1502 goto trans_err_not_supported;
1503 }
1504 } else {
1505 if (!is_supported_mailslot(xa->xa_pipe_name))
1506 goto trans_err_not_supported;
1507
1508 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr,
1509 &opcode, &req_fmt, &rep_fmt)) != 0)
1510 goto trans_err_not_supported;
1511
1512 switch (opcode) {
1513 case API_WshareEnum:
1514 rc = smb_trans_net_share_enum(sr, xa);
1515 break;
1516
1517 case API_WshareGetInfo:
1518 rc = smb_trans_net_share_getinfo(sr, xa);
1519 break;
1520
1521 case API_WserverGetInfo:
1522 rc = smb_trans_net_server_getinfo(sr, xa);
1523 break;
1524
1525 case API_WUserGetInfo:
1526 rc = smb_trans_net_user_getinfo(sr, xa);
1527 break;
1528
1529 case API_WWkstaGetInfo:
1530 rc = smb_trans_net_workstation_getinfo(sr, xa);
1531 break;
1532
1533 case API_NetServerEnum2:
1534 rc = smb_trans_net_server_enum2(sr, xa);
1535 break;
1536
1537 default:
1538 goto trans_err_not_supported;
1539 }
1540 }
1541
1542 switch (rc) {
1543 case SDRC_SUCCESS:
1544 break;
1545
1546 case SDRC_DROP_VC:
1547 case SDRC_NO_REPLY:
1548 case SDRC_ERROR:
1549 return (rc);
1550
1551 case SDRC_NOT_IMPLEMENTED:
1552 goto trans_err_not_supported;
1553
1554 default:
1555 break;
1556 }
1557
1558 n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1559 n_param = MBC_LENGTH(&xa->rep_param_mb);
1560 n_data = MBC_LENGTH(&xa->rep_data_mb);
1561
1562 if (xa->smb_msrcnt < n_setup ||
1563 xa->smb_mprcnt < n_param ||
1564 xa->smb_mdrcnt < n_data) {
1565 goto trans_err_too_small;
1566 }
1567
1568 /* neato, blast it over there */
1569
1570 n_setup = (n_setup + 1) / 2; /* Convert to setup words */
1571 param_pad = 1; /* always one */
1572 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1573 data_pad = (param_off + n_param) & 1; /* Pad to short */
1574 /* Param off from hdr start */
1575 data_off = param_off + n_param + data_pad;
1576 total_bytes = param_pad + n_param + data_pad + n_data;
1577
1578 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1579 "bww2.wwwwwwb.Cw#.C#.C",
1580 10 + n_setup, /* wct */
1581 n_param, /* Total Parameter Bytes */
1582 n_data, /* Total Data Bytes */
1583 n_param, /* Total Parameter Bytes this buffer */
1584 param_off, /* Param offset from header start */
1585 0, /* Param displacement */
1586 n_data, /* Total Data Bytes this buffer */
1587 data_off, /* Data offset from header start */
1588 0, /* Data displacement */
1589 n_setup, /* suwcnt */
1590 &xa->rep_setup_mb, /* setup[] */
1591 total_bytes, /* Total data bytes */
1592 param_pad,
1593 &xa->rep_param_mb,
1594 data_pad,
1595 &xa->rep_data_mb);
1596 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1597
1598 trans_err_too_small:
1599 rc = NERR_BufTooSmall;
1600 goto trans_err;
1601
1602 trans_err_not_supported:
1603 rc = ERROR_NOT_SUPPORTED;
1604 goto trans_err;
1605
1606 trans_err:
1607 pos = MBC_LENGTH(&sr->reply) + 23;
1608 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1609 10, /* wct */
1610 4, 0, /* tpscnt tdscnt */
1611 4, pos, 0, /* pscnt psoff psdisp */
1612 0, 0, 0, /* dscnt dsoff dsdisp */
1613 0, /* suwcnt */
1614 4, /* bcc */
1615 rc,
1616 0); /* converter word? */
1617 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1618 }
1619
1620 static smb_sdrc_t
smb_trans2_dispatch(smb_request_t * sr,smb_xa_t * xa)1621 smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa)
1622 {
1623 int rc, pos;
1624 int total_bytes, n_setup, n_param, n_data;
1625 int param_off, param_pad, data_off;
1626 uint16_t data_pad;
1627 uint16_t opcode;
1628 uint16_t nt_unknown_secret = 0x0100;
1629 char *fmt;
1630
1631 n_data = xa->smb_mdrcnt;
1632
1633 if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0)
1634 goto trans_err_not_supported;
1635
1636 /*
1637 * Save this for /proc to read later.
1638 */
1639 xa->smb_func = opcode;
1640
1641 /* for now, only respond to the */
1642 switch (opcode) {
1643 case TRANS2_OPEN2:
1644 rc = smb_com_trans2_open2(sr, xa);
1645 break;
1646
1647 case TRANS2_CREATE_DIRECTORY:
1648 rc = smb_com_trans2_create_directory(sr, xa);
1649 break;
1650
1651 case TRANS2_FIND_FIRST2:
1652 /*
1653 * Should have enough room to send the response
1654 * data back to client.
1655 */
1656 if (n_data == 0) {
1657 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1658 ERRDOS, ERROR_BAD_LENGTH);
1659 return (SDRC_ERROR);
1660 }
1661 rc = smb_com_trans2_find_first2(sr, xa);
1662 break;
1663
1664 case TRANS2_FIND_NEXT2:
1665 /*
1666 * Should have enough room to send the response
1667 * data back to client.
1668 */
1669 if (n_data == 0) {
1670 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1671 ERRDOS, ERROR_BAD_LENGTH);
1672 return (SDRC_ERROR);
1673 }
1674 rc = smb_com_trans2_find_next2(sr, xa);
1675 break;
1676
1677 case TRANS2_QUERY_FS_INFORMATION:
1678 /*
1679 * Should have enough room to send the response
1680 * data back to client.
1681 */
1682 if (n_data == 0) {
1683 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1684 ERRDOS, ERROR_BAD_LENGTH);
1685 return (SDRC_ERROR);
1686 }
1687 rc = smb_com_trans2_query_fs_information(sr, xa);
1688 break;
1689
1690 case TRANS2_SET_FS_INFORMATION:
1691 rc = smb_com_trans2_set_fs_information(sr, xa);
1692 break;
1693
1694 case TRANS2_QUERY_PATH_INFORMATION:
1695 /*
1696 * Should have enough room to send the response
1697 * data back to client.
1698 */
1699 if (n_data == 0) {
1700 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1701 ERRDOS, ERROR_BAD_LENGTH);
1702 return (SDRC_ERROR);
1703 }
1704 rc = smb_com_trans2_query_path_information(sr, xa);
1705 break;
1706
1707 case TRANS2_QUERY_FILE_INFORMATION:
1708 /*
1709 * Should have enough room to send the response
1710 * data back to client.
1711 */
1712 if (n_data == 0) {
1713 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1714 ERRDOS, ERROR_BAD_LENGTH);
1715 return (SDRC_ERROR);
1716 }
1717 rc = smb_com_trans2_query_file_information(sr, xa);
1718 break;
1719
1720 case TRANS2_SET_PATH_INFORMATION:
1721 rc = smb_com_trans2_set_path_information(sr, xa);
1722 break;
1723
1724 case TRANS2_SET_FILE_INFORMATION:
1725 rc = smb_com_trans2_set_file_information(sr, xa);
1726 break;
1727
1728 case TRANS2_GET_DFS_REFERRAL:
1729 rc = smb_com_trans2_get_dfs_referral(sr, xa);
1730 break;
1731
1732 default:
1733 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
1734 goto trans_err_not_supported;
1735 }
1736
1737 switch (rc) {
1738 case SDRC_SUCCESS:
1739 break;
1740
1741 case SDRC_DROP_VC:
1742 case SDRC_NO_REPLY:
1743 case SDRC_ERROR:
1744 return (rc);
1745
1746 case SDRC_NOT_IMPLEMENTED:
1747 goto trans_err_not_supported;
1748
1749 default:
1750 break;
1751 }
1752
1753 n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1754 n_param = MBC_LENGTH(&xa->rep_param_mb);
1755 n_data = MBC_LENGTH(&xa->rep_data_mb);
1756
1757 if (xa->smb_msrcnt < n_setup ||
1758 xa->smb_mprcnt < n_param ||
1759 xa->smb_mdrcnt < n_data) {
1760 goto trans_err_too_small;
1761 }
1762
1763 /* neato, blast it over there */
1764
1765 n_setup = (n_setup + 1) / 2; /* Conver to setup words */
1766 param_pad = 1; /* must be one */
1767 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1768
1769 /*
1770 * Including the nt_unknown_secret value persuades netmon to
1771 * display the correct data format for QueryPathInfo and
1772 * QueryFileInfo.
1773 */
1774 if (opcode == TRANS2_QUERY_FILE_INFORMATION ||
1775 opcode == TRANS2_QUERY_PATH_INFORMATION) {
1776 data_pad = sizeof (uint16_t);
1777 data_off = param_off + n_param + data_pad;
1778 fmt = "bww2.wwwwwwb.Cw#.CwC";
1779 nt_unknown_secret = 0x0100;
1780 }
1781 else
1782 {
1783 data_pad = (param_off + n_param) & 1; /* Pad to short */
1784 /* Param off from hdr start */
1785 data_off = param_off + n_param + data_pad;
1786 fmt = "bww2.wwwwwwb.Cw#.C#.C";
1787 nt_unknown_secret = data_pad;
1788 }
1789
1790 total_bytes = param_pad + n_param + data_pad + n_data;
1791
1792 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1793 fmt,
1794 10 + n_setup, /* wct */
1795 n_param, /* Total Parameter Bytes */
1796 n_data /* + data_pad */, /* Total Data Bytes */
1797 n_param, /* Total Parameter Bytes this buffer */
1798 param_off, /* Param offset from header start */
1799 0, /* Param displacement */
1800 n_data /* + data_pad */, /* Total Data Bytes this buffer */
1801 data_off, /* Data offset from header start */
1802 0, /* Data displacement */
1803 n_setup, /* suwcnt */
1804 &xa->rep_setup_mb, /* setup[] */
1805 total_bytes, /* Total data bytes */
1806 param_pad,
1807 &xa->rep_param_mb,
1808 nt_unknown_secret,
1809 &xa->rep_data_mb);
1810 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1811
1812 trans_err_too_small:
1813 rc = NERR_BufTooSmall;
1814 goto trans_err;
1815
1816 trans_err_not_supported:
1817 rc = ERROR_NOT_SUPPORTED;
1818 goto trans_err;
1819
1820 trans_err:
1821 pos = MBC_LENGTH(&sr->reply) + 23;
1822 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1823 10, /* wct */
1824 4, 0, /* tpscnt tdscnt */
1825 4, pos, 0, /* pscnt psoff psdisp */
1826 0, 0, 0, /* dscnt dsoff dsdisp */
1827 0, /* suwcnt */
1828 4, /* bcc */
1829 rc,
1830 0); /* converter word? */
1831 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1832 }
1833
1834 static uint32_t smb_xa_max_setup_count = 200;
1835 static uint32_t smb_xa_max_param_count = 32 * 1024;
1836 static uint32_t smb_xa_max_data_count = 64 * 1024;
1837
1838 smb_xa_t *
smb_xa_create(smb_session_t * session,smb_request_t * sr,uint32_t total_parameter_count,uint32_t total_data_count,uint32_t max_parameter_count,uint32_t max_data_count,uint32_t max_setup_count,uint32_t setup_word_count)1839 smb_xa_create(
1840 smb_session_t *session,
1841 smb_request_t *sr,
1842 uint32_t total_parameter_count,
1843 uint32_t total_data_count,
1844 uint32_t max_parameter_count,
1845 uint32_t max_data_count,
1846 uint32_t max_setup_count,
1847 uint32_t setup_word_count)
1848 {
1849 smb_xa_t *xa, *nxa;
1850 smb_llist_t *xlist;
1851
1852 /*
1853 * Sanity check what the client says it will send.
1854 * Caller handles NULL return as ERRnoroom.
1855 */
1856 if (setup_word_count > smb_xa_max_setup_count)
1857 return (NULL);
1858 if (total_parameter_count > smb_xa_max_param_count)
1859 return (NULL);
1860 if (total_data_count > smb_xa_max_data_count)
1861 return (NULL);
1862
1863 /*
1864 * Limit what the client asks us to allocate for
1865 * returned setup, params, data.
1866 */
1867 if (max_setup_count > smb_xa_max_setup_count)
1868 max_setup_count = smb_xa_max_setup_count;
1869 if (max_parameter_count > smb_xa_max_param_count)
1870 max_parameter_count = smb_xa_max_param_count;
1871 if (max_data_count > smb_xa_max_data_count)
1872 max_data_count = smb_xa_max_data_count;
1873
1874 xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP);
1875 xa->xa_refcnt = 1;
1876 xa->smb_com = sr->smb_com;
1877 xa->smb_flg = sr->smb_flg;
1878 xa->smb_flg2 = sr->smb_flg2;
1879 xa->smb_tid = sr->smb_tid;
1880 xa->smb_pid = sr->smb_pid;
1881 xa->smb_uid = sr->smb_uid;
1882 xa->xa_smb_mid = sr->smb_mid;
1883 xa->xa_smb_fid = 0xFFFF;
1884 xa->reply_seqnum = sr->reply_seqnum;
1885 xa->smb_tpscnt = total_parameter_count;
1886 xa->smb_tdscnt = total_data_count;
1887 xa->smb_mprcnt = max_parameter_count;
1888 xa->smb_mdrcnt = max_data_count;
1889 xa->smb_msrcnt = max_setup_count;
1890 xa->smb_suwcnt = setup_word_count;
1891 xa->xa_session = session;
1892 xa->xa_magic = SMB_XA_MAGIC;
1893
1894 /* request parts */
1895 xa->req_setup_mb.max_bytes = setup_word_count * 2;
1896 xa->req_param_mb.max_bytes = total_parameter_count;
1897 xa->req_data_mb.max_bytes = total_data_count;
1898
1899 /* reply parts */
1900 xa->rep_setup_mb.max_bytes = max_setup_count * 2;
1901 xa->rep_param_mb.max_bytes = max_parameter_count;
1902 xa->rep_data_mb.max_bytes = max_data_count;
1903
1904 /*
1905 * The new xa structure is checked against the current list to see
1906 * if it exists already.
1907 */
1908 xlist = &session->s_xa_list;
1909 smb_llist_enter(xlist, RW_WRITER);
1910 nxa = smb_llist_head(xlist);
1911 while (nxa) {
1912 ASSERT(nxa->xa_magic == SMB_XA_MAGIC);
1913 if (nxa->xa_smb_mid == xa->xa_smb_mid &&
1914 nxa->smb_pid == xa->smb_pid &&
1915 !SMB_XA_CLOSED(nxa) &&
1916 !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
1917 smb_llist_exit(xlist);
1918 kmem_free(xa, sizeof (smb_xa_t));
1919 return (NULL);
1920 }
1921 nxa = smb_llist_next(xlist, nxa);
1922 }
1923 smb_llist_insert_tail(xlist, xa);
1924 smb_llist_exit(xlist);
1925 return (xa);
1926 }
1927
1928 void
smb_xa_delete(smb_xa_t * xa)1929 smb_xa_delete(smb_xa_t *xa)
1930 {
1931 ASSERT(xa->xa_refcnt == 0);
1932 ASSERT(SMB_XA_CLOSED(xa));
1933
1934 if (xa->xa_pipe_name)
1935 smb_mem_free(xa->xa_pipe_name);
1936
1937 /* request parts */
1938 if (xa->req_setup_mb.chain != NULL)
1939 m_freem(xa->req_setup_mb.chain);
1940 if (xa->req_param_mb.chain != NULL)
1941 m_freem(xa->req_param_mb.chain);
1942 if (xa->req_data_mb.chain != NULL)
1943 m_freem(xa->req_data_mb.chain);
1944
1945 /* reply parts */
1946 if (xa->rep_setup_mb.chain != NULL)
1947 m_freem(xa->rep_setup_mb.chain);
1948 if (xa->rep_param_mb.chain != NULL)
1949 m_freem(xa->rep_param_mb.chain);
1950 if (xa->rep_data_mb.chain != NULL)
1951 m_freem(xa->rep_data_mb.chain);
1952
1953 xa->xa_magic = (uint32_t)~SMB_XA_MAGIC;
1954 kmem_free(xa, sizeof (smb_xa_t));
1955 }
1956
1957 smb_xa_t *
smb_xa_hold(smb_xa_t * xa)1958 smb_xa_hold(smb_xa_t *xa)
1959 {
1960 mutex_enter(&xa->xa_mutex);
1961 xa->xa_refcnt++;
1962 ASSERT(xa->xa_refcnt);
1963 mutex_exit(&xa->xa_mutex);
1964 return (xa);
1965 }
1966
1967 void
smb_xa_rele(smb_session_t * session,smb_xa_t * xa)1968 smb_xa_rele(smb_session_t *session, smb_xa_t *xa)
1969 {
1970 mutex_enter(&xa->xa_mutex);
1971 ASSERT(xa->xa_refcnt);
1972 xa->xa_refcnt--;
1973 if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) {
1974 mutex_exit(&xa->xa_mutex);
1975 smb_llist_enter(&session->s_xa_list, RW_WRITER);
1976 smb_llist_remove(&session->s_xa_list, xa);
1977 smb_llist_exit(&session->s_xa_list);
1978 smb_xa_delete(xa);
1979 return;
1980 }
1981 mutex_exit(&xa->xa_mutex);
1982 }
1983
1984 int
smb_xa_open(smb_xa_t * xa)1985 smb_xa_open(smb_xa_t *xa)
1986 {
1987 int rc;
1988
1989 mutex_enter(&xa->xa_mutex);
1990
1991 ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0);
1992
1993 if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) {
1994 xa->xa_flags |= SMB_XA_FLAG_OPEN;
1995 rc = 0;
1996 } else {
1997 rc = ERROR_INVALID_HANDLE;
1998 }
1999
2000 mutex_exit(&xa->xa_mutex);
2001
2002 return (rc);
2003 }
2004
2005 void
smb_xa_close(smb_xa_t * xa)2006 smb_xa_close(smb_xa_t *xa)
2007 {
2008 mutex_enter(&xa->xa_mutex);
2009 xa->xa_flags |= SMB_XA_FLAG_CLOSE;
2010 xa->xa_flags &= ~SMB_XA_FLAG_OPEN;
2011
2012 if (xa->xa_refcnt == 0) {
2013 mutex_exit(&xa->xa_mutex);
2014 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER);
2015 smb_llist_remove(&xa->xa_session->s_xa_list, xa);
2016 smb_llist_exit(&xa->xa_session->s_xa_list);
2017 smb_xa_delete(xa);
2018 return;
2019 }
2020
2021 mutex_exit(&xa->xa_mutex);
2022 }
2023
2024 int
smb_xa_complete(smb_xa_t * xa)2025 smb_xa_complete(smb_xa_t *xa)
2026 {
2027 int rc;
2028
2029 mutex_enter(&xa->xa_mutex);
2030 if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) {
2031 rc = 0; /* error ("not complete") */
2032 } else {
2033 rc = 1; /* Yes, "complete" */
2034 xa->xa_flags |= SMB_XA_FLAG_COMPLETE;
2035
2036 /*
2037 * During trans & trans-secondary processing,
2038 * we copied the request data into these.
2039 * Now we want to parse them, so we need to
2040 * move the "finger" back to the beginning.
2041 */
2042 xa->req_setup_mb.chain_offset = 0;
2043 xa->req_param_mb.chain_offset = 0;
2044 xa->req_data_mb.chain_offset = 0;
2045 }
2046
2047 mutex_exit(&xa->xa_mutex);
2048 return (rc);
2049 }
2050
2051 smb_xa_t *
smb_xa_find(smb_session_t * session,uint16_t pid,uint16_t mid)2052 smb_xa_find(
2053 smb_session_t *session,
2054 uint16_t pid,
2055 uint16_t mid)
2056 {
2057 smb_xa_t *xa;
2058 smb_llist_t *xlist;
2059
2060 xlist = &session->s_xa_list;
2061 smb_llist_enter(xlist, RW_READER);
2062 xa = smb_llist_head(xlist);
2063 while (xa) {
2064 mutex_enter(&xa->xa_mutex);
2065 if (xa->xa_smb_mid == mid &&
2066 xa->smb_pid == pid &&
2067 !SMB_XA_CLOSED(xa) &&
2068 !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2069 xa->xa_refcnt++;
2070 ASSERT(xa->xa_refcnt);
2071 mutex_exit(&xa->xa_mutex);
2072 break;
2073 }
2074 mutex_exit(&xa->xa_mutex);
2075 xa = smb_llist_next(xlist, xa);
2076 }
2077 smb_llist_exit(xlist);
2078 return (xa);
2079 }
2080