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