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