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