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 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 /*
29 * SMB mbuf marshaling encode/decode.
30 */
31
32 #include <smbsrv/smb_kproto.h>
33
34
35 #define MALLOC_QUANTUM 80
36
37 #define DECODE_NO_ERROR 0
38 #define DECODE_NO_MORE_DATA 1
39 #define DECODE_ALLOCATION_ERROR 2
40 #define DECODE_CONVERSION_ERROR 3
41
42 static int mbc_marshal_cstou8(char *, char *, size_t, char *, size_t);
43 static int mbc_marshal_make_room(mbuf_chain_t *, int32_t);
44 static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t);
45 static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t);
46 static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t);
47 static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t);
48 static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t);
49 static int mbc_marshal_put_ascii_string(mbuf_chain_t *, char *, int);
50 static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int);
51 static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *);
52 static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m);
53 static int mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc);
54 static uint8_t mbc_marshal_fetch_byte(mbuf_chain_t *mbc);
55 static int mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data);
56 static int mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data);
57 static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data);
58 static uint64_t qswap(uint64_t ll);
59 static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data);
60 static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data);
61 static int mbc_marshal_get_ascii_string(smb_request_t *, mbuf_chain_t *,
62 uint8_t **ascii, int);
63 static int mbc_marshal_get_unicode_string(smb_request_t *, mbuf_chain_t *,
64 uint8_t **, int);
65 static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **);
66 static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *);
67 static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *);
68 static int mbc_marshal_get_skip(mbuf_chain_t *, uint_t);
69
70 /*
71 * smb_mbc_vdecodef
72 *
73 * This function reads the contents of the mbc chain passed in under the list
74 * of arguments passed in.
75 *
76 * The format string provides a description of the parameters passed in as well
77 * as an action to be taken by smb_mbc_vdecodef().
78 *
79 * % Pointer to an SMB request structure (smb_request_t *). There
80 * should be only one of these in the string.
81 *
82 * C Pointer to an mbuf chain. Copy to that mbuf chain the number of
83 * bytes specified (number preceding C).
84 *
85 * m Pointer to an mbuf. Copy to that mbuf the number of bytes
86 * specified (number preceding m).
87 *
88 * M Read the 32 bit value at the current location of the mbuf chain
89 * and check if it matches the signature of an SMB1 request (SMBx).
90 *
91 * N Read the 32 bit value at the current location of the mbuf chain
92 * and check if it matches the signature of an SMB2 request (SMBx).
93 *
94 * b Pointer to a buffer. Copy to that buffer the number of bytes
95 * specified (number preceding b).
96 *
97 * c Same as 'b'.
98 *
99 * w Pointer to a word (16bit value). Copy the next 16bit value into
100 * that location.
101 *
102 * l Pointer to a long (32bit value). Copy the next 32bit value into
103 * that location.
104 *
105 * q Pointer to a quad (64bit value). Copy the next 64bit value into
106 * that location.
107 *
108 * Q Same as above with a call to qswap().
109 *
110 * B Pointer to a vardata_block structure. That structure is used to
111 * retrieve data from the mbuf chain (an iovec type structure is
112 * embedded in a vardata_block).
113 *
114 * D Pointer to a vardata_block structure. That structure is used to
115 * retrieve data from the mbuf chain, however, two fields of the
116 * vardata_block structure (tag and len) are first initialized
117 * using the mbuf chain itself.
118 *
119 * V Same as 'D'.
120 *
121 * L
122 *
123 * A
124 *
125 * P Same as 'A'
126 *
127 * S Same as 'A'
128 *
129 * u Pointer to a string pointer. Allocate memory and retrieve the
130 * string at the current location in the mbuf chain. Store the
131 * address to the buffer allocated at the address specified by
132 * the pointer. In addition if an sr was passed and it indicates
133 * that the string is an unicode string, convert it.
134 *
135 * s Same as 'u' without convertion.
136 *
137 * U Same as 'u'. The string to retrieve is unicode.
138 *
139 * y Pointer to a 32bit value. Read the dos time at the current mbuf
140 * chain location, convert it to unix time and store it at the
141 * location indicated by the pointer.
142 *
143 * Y Same as 'y' bt the dos time coded in the mbuf chain is inverted.
144 *
145 * . Skip the number of bytes indicated by the number preceding '.'.
146 *
147 * , Same as '.' but take in account it is an unicode string.
148 */
149 int
smb_mbc_vdecodef(mbuf_chain_t * mbc,const char * fmt,va_list ap)150 smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
151 {
152 uint8_t c;
153 uint8_t cval;
154 uint8_t *cvalp;
155 uint8_t **cvalpp;
156 uint16_t wval;
157 uint16_t *wvalp;
158 uint32_t *lvalp;
159 uint64_t *llvalp;
160 smb_vdb_t *vdp;
161 smb_request_t *sr = NULL;
162 uint32_t lval;
163 int unicode = 0;
164 int repc;
165 boolean_t repc_specified;
166
167 while ((c = *fmt++) != 0) {
168 repc_specified = B_FALSE;
169 repc = 1;
170
171 if ('0' <= c && c <= '9') {
172 repc = 0;
173 do {
174 repc = repc * 10 + c - '0';
175 c = *fmt++;
176 } while ('0' <= c && c <= '9');
177 repc_specified = B_TRUE;
178 } else if (c == '#') {
179 repc = va_arg(ap, int);
180 c = *fmt++;
181 repc_specified = B_TRUE;
182 }
183
184 switch (c) {
185 case '%':
186 sr = va_arg(ap, struct smb_request *);
187 if (sr->session->dialect >= SMB_VERS_2_BASE) {
188 unicode = 1;
189 break;
190 }
191 unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE;
192 break;
193
194 case 'C': /* Mbuf_chain */
195 if (mbc_marshal_get_mbuf_chain(mbc, repc,
196 va_arg(ap, mbuf_chain_t *)) != 0)
197 return (-1);
198 break;
199
200 case 'm': /* struct_mbuf */
201 if (mbc_marshal_get_mbufs(mbc, repc,
202 va_arg(ap, mbuf_t **)) != 0)
203 return (-1);
204 break;
205
206 case 'M':
207 if (mbc_marshal_get_long(mbc, &lval) != 0)
208 return (-1);
209 if (lval != 0x424D53FF) /* 0xFF S M B */
210 return (-1);
211 break;
212
213 case 'N':
214 if (mbc_marshal_get_long(mbc, &lval) != 0)
215 return (-1);
216 if (lval != 0x424D53FE) /* 0xFE S M B */
217 return (-1);
218 break;
219
220 case 'b':
221 case 'c':
222 cvalp = va_arg(ap, uint8_t *);
223 if (MBC_ROOM_FOR(mbc, repc) == 0)
224 /* Data will never be available */
225 return (-1);
226
227 while (repc-- > 0)
228 *cvalp++ = mbc_marshal_fetch_byte(mbc);
229 break;
230
231 case 'w':
232 wvalp = va_arg(ap, uint16_t *);
233 while (repc-- > 0)
234 if (mbc_marshal_get_short(mbc, wvalp++) != 0)
235 return (-1);
236 break;
237
238 case 'l':
239 lvalp = va_arg(ap, uint32_t *);
240 while (repc-- > 0)
241 if (mbc_marshal_get_long(mbc, lvalp++) != 0)
242 return (-1);
243 break;
244
245 case 'q':
246 llvalp = va_arg(ap, uint64_t *);
247 while (repc-- > 0)
248 if (mbc_marshal_get_long_long(
249 mbc, llvalp++) != 0)
250 return (-1);
251 break;
252
253 case 'Q':
254 llvalp = va_arg(ap, uint64_t *);
255 while (repc-- > 0)
256 if (mbc_marshal_get_odd_long_long(
257 mbc, llvalp++) != 0)
258 return (-1);
259 break;
260
261 case 'B':
262 vdp = va_arg(ap, struct vardata_block *);
263 vdp->vdb_tag = 0;
264 vdp->vdb_len = repc;
265 vdp->vdb_uio.uio_iov = &vdp->vdb_iovec[0];
266 vdp->vdb_uio.uio_iovcnt = MAX_IOVEC;
267 vdp->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
268 vdp->vdb_uio.uio_resid = repc;
269 if (mbc_marshal_get_uio(mbc, &vdp->vdb_uio) != 0)
270 return (-1);
271 break;
272
273 case 'D':
274 case 'V':
275 vdp = va_arg(ap, struct vardata_block *);
276 if (mbc_marshal_get_char(mbc, &vdp->vdb_tag) != 0)
277 return (-1);
278 if (mbc_marshal_get_short(mbc, &wval) != 0)
279 return (-1);
280 vdp->vdb_len = (uint32_t)wval;
281 vdp->vdb_uio.uio_iov = &vdp->vdb_iovec[0];
282 vdp->vdb_uio.uio_iovcnt = MAX_IOVEC;
283 vdp->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
284 vdp->vdb_uio.uio_resid = vdp->vdb_len;
285 if (vdp->vdb_len != 0) {
286 if (mbc_marshal_get_uio(mbc,
287 &vdp->vdb_uio) != 0)
288 return (-1);
289 }
290 break;
291
292 case 'L':
293 if (mbc_marshal_get_char(mbc, &cval) != 0)
294 return (-1);
295 if (cval != 2)
296 return (-1);
297 goto ascii_conversion;
298
299 case 'A':
300 case 'S':
301 if (mbc_marshal_get_char(mbc, &cval) != 0)
302 return (-1);
303 if (((c == 'A' || c == 'S') && cval != 4) ||
304 (c == 'L' && cval != 2))
305 return (-1);
306 /* FALLTHROUGH */
307
308 case 'u': /* Convert from unicode if flags are set */
309 if (unicode)
310 goto unicode_translation;
311 /* FALLTHROUGH */
312
313 case 's':
314 ascii_conversion:
315 ASSERT(sr != NULL);
316 cvalpp = va_arg(ap, uint8_t **);
317 if (!repc_specified)
318 repc = 0;
319 if (mbc_marshal_get_ascii_string(sr,
320 mbc, cvalpp, repc) != 0)
321 return (-1);
322 break;
323
324 case 'U': /* Convert from unicode */
325 unicode_translation:
326 ASSERT(sr != 0);
327 cvalpp = va_arg(ap, uint8_t **);
328 if (!repc_specified)
329 repc = 0;
330 if (mbc->chain_offset & 1)
331 mbc->chain_offset++;
332 if (mbc_marshal_get_unicode_string(sr,
333 mbc, cvalpp, repc) != 0)
334 return (-1);
335 break;
336
337 case 'Y': /* dos time to unix time tt/dd */
338 lvalp = va_arg(ap, uint32_t *);
339 while (repc-- > 0) {
340 short d, t;
341
342 if (mbc_marshal_get_short(mbc,
343 (uint16_t *)&t) != 0)
344 return (-1);
345 if (mbc_marshal_get_short(mbc,
346 (uint16_t *)&d) != 0)
347 return (-1);
348 *lvalp++ = smb_time_dos_to_unix(d, t);
349 }
350 break;
351
352 case 'y': /* dos time to unix time dd/tt */
353 lvalp = va_arg(ap, uint32_t *);
354 while (repc-- > 0) {
355 short d, t;
356
357 if (mbc_marshal_get_short(mbc,
358 (uint16_t *)&d) != 0)
359 return (-1);
360 if (mbc_marshal_get_short(mbc,
361 (uint16_t *)&t) != 0)
362 return (-1);
363 *lvalp++ = smb_time_dos_to_unix(d, t);
364 }
365 break;
366
367 case ',':
368 if (unicode)
369 repc *= 2;
370 /* FALLTHROUGH */
371
372 case '.':
373 if (mbc_marshal_get_skip(mbc, repc) != 0)
374 return (-1);
375 break;
376
377 default:
378 ASSERT(0);
379 return (-1);
380 }
381 }
382 return (0);
383 }
384
385 /*
386 * smb_mbc_decodef
387 *
388 * This function reads the contents of the mbc chain passed in under the
389 * control of the format fmt.
390 *
391 * (for a description of the format string see smb_mbc_vencodef()).
392 */
393 int
smb_mbc_decodef(mbuf_chain_t * mbc,const char * fmt,...)394 smb_mbc_decodef(mbuf_chain_t *mbc, const char *fmt, ...)
395 {
396 int xx;
397 va_list ap;
398
399 va_start(ap, fmt);
400 xx = smb_mbc_vdecodef(mbc, fmt, ap);
401 va_end(ap);
402 return (xx);
403 }
404
405 /*
406 * smb_mbc_peek
407 *
408 * This function reads the contents of the mbc passed in at the specified offset
409 * under the control of the format fmt. The offset of the chain passed in is not
410 * modified.
411 *
412 * (for a description of the format string see smb_mbc_vdecodef()).
413 */
414 int
smb_mbc_peek(mbuf_chain_t * mbc,int offset,const char * fmt,...)415 smb_mbc_peek(mbuf_chain_t *mbc, int offset, const char *fmt, ...)
416 {
417 mbuf_chain_t tmp;
418 va_list ap;
419 int xx;
420
421 va_start(ap, fmt);
422
423 (void) MBC_SHADOW_CHAIN(&tmp, mbc, offset, mbc->max_bytes - offset);
424 xx = smb_mbc_vdecodef(&tmp, fmt, ap);
425 va_end(ap);
426 return (xx);
427 }
428
429 /*
430 * smb_mbc_vencodef
431 *
432 * This function builds a stream of bytes in the mbc chain passed in under the
433 * control of the list of arguments passed in.
434 *
435 * The format string provides a description of the parameters passed in as well
436 * as an action to be taken by smb_mbc_vencodef().
437 *
438 * \b Restore the mbuf chain offset to its initial value.
439 *
440 * % Pointer to an SMB request structure (smb_request_t *). There
441 * should be only one of these in the string. If an sr in present
442 * it will be used to determine if unicode conversion should be
443 * applied to the strings.
444 *
445 * C Pointer to an mbuf chain. Copy that mbuf chain into the
446 * destination mbuf chain.
447 *
448 * D Pointer to a vardata_block structure. Copy the data described
449 * by that structure into the mbuf chain. The tag field is hard
450 * coded to '1'.
451 *
452 * M Write the SMB1 request signature ('SMBX') into the mbuf chain.
453 *
454 * N Write the SMB2 request signature ('SMBX') into the mbuf chain.
455 *
456 * T Pointer to a timestruc_t. Convert the content of the structure
457 * into NT time and store the result of the conversion in the
458 * mbuf chain.
459 *
460 * V Same as 'D' but the tag field is hard coded to '5'.
461 *
462 * b Byte. Store the byte or the nymber of bytes specified into the
463 * the mbuf chain. A format string like this "2b" would require 2
464 * bytes to be passed in.
465 *
466 * m Pointer to an mbuf. Copy the contents of the mbuf into the mbuf
467 * chain.
468 *
469 * c Pointer to a buffer. Copy the buffer into the mbuf chain. The
470 * size of the buffer is indicated by the number preceding 'c'.
471 *
472 * w Word (16bit value). Store the word or the number of words
473 * specified into the the mbuf chain. A format string like this
474 * "2w" would require 2 words to be passed in.
475 *
476 * l Long (32bit value). Store the long or the number of longs
477 * specified into the the mbuf chain. A format string like this
478 * "2l" would require 2 longs to be passed in.
479 *
480 * q Quad (64bit value). Store the quad or the number of quads
481 * specified into the the mbuf chain. A format string like this
482 * "2q" would require 2 quads to be passed in.
483 *
484 * L Pointer to a string. Store the string passed in into the mbuf
485 * chain preceded with a tag value of '2'.
486 *
487 * S Pointer to a string. Store the string passed in into the mbuf
488 * chain preceded with a tag value of '4'. Applied a unicode
489 * conversion is appropriate.
490 *
491 * A Same as 'S'
492 *
493 * P Pointer to a string. Store the string passed in into the mbuf
494 * chain preceded with a tag value of '5'. Applied a unicode
495 * conversion is appropriate.
496 *
497 * u Pointer to a string. Store the string passed in into the mbuf
498 * chain. Applied a unicode conversion is appropriate.
499 *
500 * s Pointer to a string. Store the string passed in into the mbuf
501 * chain.
502 *
503 * Y Date/Time. Store the Date/Time or the number of Date/Time(s)
504 * specified into the the mbuf chain. A format string like this
505 * "2Y" would require 2 Date/Time values. The Date/Time is
506 * converted to DOS before storing.
507 *
508 * y Same as 'Y'. The order of Date and Time is reversed.
509 *
510 * , Character. Store the character or number of character specified
511 * into the mbuf chain. A format string like this "2c" would
512 * require 2 characters to be passed in. A unicode conversion is
513 * applied if appropriate.
514 *
515 * . Same as '`' without unicode conversion.
516 *
517 * U Align the offset of the mbuf chain on a 16bit boundary.
518 */
519 int
smb_mbc_vencodef(mbuf_chain_t * mbc,const char * fmt,va_list ap)520 smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
521 {
522 uint8_t *cvalp;
523 timestruc_t *tvp;
524 smb_vdb_t *vdp;
525 smb_request_t *sr = NULL;
526 uint64_t llval;
527 int64_t nt_time;
528 uint32_t lval;
529 uint_t tag;
530 int unicode = 0;
531 int repc;
532 boolean_t repc_specified;
533 uint16_t wval;
534 uint8_t cval;
535 uint8_t c;
536
537 while ((c = *fmt++) != 0) {
538 repc_specified = B_FALSE;
539 repc = 1;
540
541 if ('0' <= c && c <= '9') {
542 repc = 0;
543 do {
544 repc = repc * 10 + c - '0';
545 c = *fmt++;
546 } while ('0' <= c && c <= '9');
547 repc_specified = B_TRUE;
548 } else if (c == '#') {
549 repc = va_arg(ap, int);
550 c = *fmt++;
551 repc_specified = B_TRUE;
552
553 }
554
555 switch (c) {
556 case '%':
557 sr = va_arg(ap, struct smb_request *);
558 if (sr->session->dialect >= SMB_VERS_2_BASE) {
559 unicode = 1;
560 break;
561 }
562 unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE;
563 break;
564
565 case 'C': /* Mbuf_chain */
566 if (mbc_marshal_put_mbuf_chain(mbc,
567 va_arg(ap, mbuf_chain_t *)) != 0)
568 return (DECODE_NO_MORE_DATA);
569 break;
570
571 case 'D':
572 vdp = va_arg(ap, struct vardata_block *);
573
574 if (mbc_marshal_put_char(mbc, 1) != 0)
575 return (DECODE_NO_MORE_DATA);
576 if (mbc_marshal_put_short(mbc, vdp->vdb_len) != 0)
577 return (DECODE_NO_MORE_DATA);
578 if (mbc_marshal_put_uio(mbc, &vdp->vdb_uio) != 0)
579 return (DECODE_NO_MORE_DATA);
580 break;
581
582 case 'M':
583 /* 0xFF S M B */
584 if (mbc_marshal_put_long(mbc, 0x424D53FF))
585 return (DECODE_NO_MORE_DATA);
586 break;
587
588 case 'N':
589 /* 0xFE S M B */
590 if (mbc_marshal_put_long(mbc, 0x424D53FE))
591 return (DECODE_NO_MORE_DATA);
592 break;
593
594 case 'T':
595 tvp = va_arg(ap, timestruc_t *);
596 nt_time = smb_time_unix_to_nt(tvp);
597 if (mbc_marshal_put_long_long(mbc, nt_time) != 0)
598 return (DECODE_NO_MORE_DATA);
599 break;
600
601 case 'V':
602 vdp = va_arg(ap, struct vardata_block *);
603
604 if (mbc_marshal_put_char(mbc, 5) != 0)
605 return (DECODE_NO_MORE_DATA);
606 if (mbc_marshal_put_short(mbc, vdp->vdb_len) != 0)
607 return (DECODE_NO_MORE_DATA);
608 if (mbc_marshal_put_uio(mbc, &vdp->vdb_uio) != 0)
609 return (DECODE_NO_MORE_DATA);
610 break;
611
612 case 'b':
613 while (repc-- > 0) {
614 cval = va_arg(ap, int);
615 if (mbc_marshal_put_char(mbc, cval) != 0)
616 return (DECODE_NO_MORE_DATA);
617 }
618 break;
619
620 case 'm': /* struct_mbuf */
621 if (mbc_marshal_put_mbufs(mbc,
622 va_arg(ap, mbuf_t *)) != 0)
623 return (DECODE_NO_MORE_DATA);
624 break;
625
626 case 'c':
627 cvalp = va_arg(ap, uint8_t *);
628 while (repc-- > 0) {
629 if (mbc_marshal_put_char(mbc,
630 *cvalp++) != 0)
631 return (DECODE_NO_MORE_DATA);
632 }
633 break;
634
635 case 'w':
636 while (repc-- > 0) {
637 wval = va_arg(ap, int);
638 if (mbc_marshal_put_short(mbc, wval) != 0)
639 return (DECODE_NO_MORE_DATA);
640 }
641 break;
642
643 case 'l':
644 while (repc-- > 0) {
645 lval = va_arg(ap, uint32_t);
646 if (mbc_marshal_put_long(mbc, lval) != 0)
647 return (DECODE_NO_MORE_DATA);
648 }
649 break;
650
651 case 'q':
652 while (repc-- > 0) {
653 llval = va_arg(ap, uint64_t);
654 if (mbc_marshal_put_long_long(mbc, llval) != 0)
655 return (DECODE_NO_MORE_DATA);
656 }
657 break;
658
659
660 case 'L':
661 tag = 2;
662 goto ascii_conversion;
663
664 case 'S':
665 case 'A':
666 tag = 4;
667 goto tagged_str;
668
669 case 'P':
670 tag = 3;
671 goto tagged_str;
672
673 tagged_str:
674 if (mbc_marshal_put_char(mbc, tag) != 0)
675 return (DECODE_NO_MORE_DATA);
676 /* FALLTHROUGH */
677
678 case 'u': /* Convert from unicode if flags are set */
679 if (unicode)
680 goto unicode_translation;
681 /* FALLTHROUGH */
682
683 case 's': /* ASCII/multibyte string */
684 ascii_conversion: cvalp = va_arg(ap, uint8_t *);
685 if (!repc_specified)
686 repc = 0;
687 if (mbc_marshal_put_ascii_string(mbc,
688 (char *)cvalp, repc) != 0)
689 return (DECODE_NO_MORE_DATA);
690 break;
691
692 case 'Y': /* int32_t, encode dos date/time */
693 while (repc-- > 0) {
694 uint16_t d, t;
695
696 lval = va_arg(ap, uint32_t);
697 smb_time_unix_to_dos(lval,
698 (short *)&d, (short *)&t);
699 if (mbc_marshal_put_short(mbc, t) != 0)
700 return (DECODE_NO_MORE_DATA);
701 if (mbc_marshal_put_short(mbc, d) != 0)
702 return (DECODE_NO_MORE_DATA);
703 }
704 break;
705
706 case 'y': /* int32_t, encode dos date/time */
707 while (repc-- > 0) {
708 uint16_t d, t;
709
710 lval = va_arg(ap, uint32_t);
711 smb_time_unix_to_dos(lval,
712 (short *)&d, (short *)&t);
713 if (mbc_marshal_put_short(mbc, d) != 0)
714 return (DECODE_NO_MORE_DATA);
715 if (mbc_marshal_put_short(mbc, t) != 0)
716 return (DECODE_NO_MORE_DATA);
717 }
718 break;
719
720 case ',':
721 if (unicode)
722 repc *= 2;
723 /* FALLTHROUGH */
724
725 case '.':
726 while (repc-- > 0)
727 if (mbc_marshal_put_char(mbc, 0) != 0)
728 return (DECODE_NO_MORE_DATA);
729 break;
730
731 case 'U': /* Convert to unicode, align to word boundary */
732 unicode_translation:
733 if (mbc->chain_offset & 1)
734 mbc->chain_offset++;
735 cvalp = va_arg(ap, uint8_t *);
736 if (!repc_specified)
737 repc = 0;
738 if (mbc_marshal_put_unicode_string(mbc,
739 (char *)cvalp, repc) != 0)
740 return (DECODE_NO_MORE_DATA);
741 break;
742
743 default:
744 ASSERT(0);
745 return (-1);
746 }
747 }
748 return (0);
749 }
750
751 /*
752 * smb_mbc_encodef
753 *
754 * This function builds a stream of bytes in the mbc chain passed in under the
755 * control of the format fmt.
756 *
757 * (for a description of the format string see smb_mbc_vencodef()).
758 */
759 int
smb_mbc_encodef(mbuf_chain_t * mbc,const char * fmt,...)760 smb_mbc_encodef(mbuf_chain_t *mbc, const char *fmt, ...)
761 {
762 int rc;
763 va_list ap;
764
765 va_start(ap, fmt);
766 rc = smb_mbc_vencodef(mbc, fmt, ap);
767 va_end(ap);
768 return (rc);
769 }
770
771 /*
772 * smb_mbc_poke
773 *
774 * This function writes a stream of bytes in the mbc passed in at the specified
775 * offset under the control of the format fmt. The offset of the chain passed in
776 * is not modified.
777 *
778 * (for a description of the format string see smb_mbc_vencodef()).
779 */
780 int
smb_mbc_poke(mbuf_chain_t * mbc,int offset,const char * fmt,...)781 smb_mbc_poke(mbuf_chain_t *mbc, int offset, const char *fmt, ...)
782 {
783 int len, rc;
784 mbuf_chain_t tmp;
785 va_list ap;
786
787 if ((len = mbc->max_bytes - offset) < 0)
788 return (DECODE_NO_MORE_DATA);
789 rc = MBC_SHADOW_CHAIN(&tmp, mbc, offset, len);
790 if (rc)
791 return (DECODE_NO_MORE_DATA);
792
793 va_start(ap, fmt);
794 rc = smb_mbc_vencodef(&tmp, fmt, ap);
795 va_end(ap);
796
797 return (rc);
798 }
799
800 /*
801 * Copy data from the src mbuf chain to the dst mbuf chain,
802 * at the given offset in the src and current offset in dst,
803 * for copy_len bytes. Does NOT update src->chain_offset.
804 */
805 int
smb_mbc_copy(mbuf_chain_t * dst_mbc,const mbuf_chain_t * src_mbc,int copy_offset,int copy_len)806 smb_mbc_copy(mbuf_chain_t *dst_mbc, const mbuf_chain_t *src_mbc,
807 int copy_offset, int copy_len)
808 {
809 mbuf_t *src_m;
810 int offset, len;
811 int rc;
812
813 if (copy_len <= 0)
814 return (0);
815 if (copy_offset < 0)
816 return (EINVAL);
817 if ((copy_offset + copy_len) > src_mbc->max_bytes)
818 return (EMSGSIZE);
819
820 /*
821 * Advance to the src mbuf where we start copying.
822 */
823 offset = copy_offset;
824 src_m = src_mbc->chain;
825 while (src_m && offset >= src_m->m_len) {
826 offset -= src_m->m_len;
827 src_m = src_m->m_next;
828 }
829 if (src_m == NULL)
830 return (EFAULT);
831
832 /*
833 * Copy the first part, which may start somewhere past
834 * the beginning of the current mbuf.
835 */
836 len = src_m->m_len - offset;
837 if (len > copy_len)
838 len = copy_len;
839 rc = smb_mbc_put_mem(dst_mbc, src_m->m_data + offset, len);
840 if (rc != 0)
841 return (rc);
842 copy_len -= len;
843
844 /*
845 * Copy remaining mbufs...
846 */
847 while (copy_len > 0) {
848 src_m = src_m->m_next;
849 if (src_m == NULL)
850 break;
851 len = src_m->m_len;
852 if (len > copy_len)
853 len = copy_len;
854 rc = smb_mbc_put_mem(dst_mbc, src_m->m_data, len);
855 copy_len -= len;
856 }
857
858 return (0);
859 }
860
861 /*
862 * Copy data from the passed memory buffer into the mbuf chain
863 * at the current offset.
864 */
865 int
smb_mbc_put_mem(mbuf_chain_t * mbc,void * vmem,int mem_len)866 smb_mbc_put_mem(mbuf_chain_t *mbc, void *vmem, int mem_len)
867 {
868 caddr_t mem = vmem;
869 mbuf_t *m;
870 int32_t offset, tlen;
871 int rc;
872
873 if (mem_len <= 0)
874 return (0);
875
876 if ((rc = mbc_marshal_make_room(mbc, mem_len)) != 0)
877 return (rc);
878
879 /*
880 * Advance to the dst mbuf where we start copying.
881 * Allocations were done by _make_room().
882 */
883 offset = mbc->chain_offset;
884 m = mbc->chain;
885 while (offset >= m->m_len) {
886 ASSERT(m->m_len > 0);
887 offset -= m->m_len;
888 m = m->m_next;
889 }
890
891 /*
892 * Copy the first part, which may start somewhere past
893 * the beginning of the current mbuf.
894 */
895 tlen = m->m_len - offset;
896 if (tlen > mem_len)
897 tlen = mem_len;
898 bcopy(mem, m->m_data + offset, tlen);
899 mbc->chain_offset += tlen;
900 mem += tlen;
901 mem_len -= tlen;
902
903 /*
904 * Copy remaining mem into mbufs. These all start
905 * at the beginning of each mbuf, and the last may
906 * end somewhere short of m_len.
907 */
908 while (mem_len > 0) {
909 m = m->m_next;
910 tlen = m->m_len;
911 if (tlen > mem_len)
912 tlen = mem_len;
913 bcopy(mem, m->m_data, tlen);
914 mbc->chain_offset += tlen;
915 mem += tlen;
916 mem_len -= tlen;
917 }
918
919 return (0);
920 }
921
922 /*
923 * Put data into mbuf chain allocating as needed.
924 * Adds room to end of mbuf chain if needed.
925 */
926 static int
mbc_marshal_make_room(mbuf_chain_t * mbc,int32_t bytes_needed)927 mbc_marshal_make_room(mbuf_chain_t *mbc, int32_t bytes_needed)
928 {
929 mbuf_t *m;
930 mbuf_t *l;
931 int32_t bytes_available;
932
933 bytes_needed += mbc->chain_offset;
934 if (bytes_needed > mbc->max_bytes)
935 return (EMSGSIZE);
936
937 if ((m = mbc->chain) == 0) {
938 MGET(m, M_WAIT, MT_DATA);
939 m->m_len = 0;
940 MCLGET(m, M_WAIT);
941 mbc->chain = m;
942 /* xxxx */
943 /* ^ */
944 }
945
946 /* ---- ----- --xx ---xxx */
947 /* ^ */
948
949 l = 0;
950 while ((m != 0) && (bytes_needed >= m->m_len)) {
951 l = m;
952 bytes_needed -= m->m_len;
953 m = m->m_next;
954 }
955
956 if ((bytes_needed == 0) || (m != 0)) {
957 /* We have enough room already */
958 return (0);
959 }
960
961 /* ---- ----- --xx ---xxx */
962 /* ^ */
963 /* Back up to start of last mbuf */
964 m = l;
965 bytes_needed += m->m_len;
966
967 /* ---- ----- --xx ---xxx */
968 /* ^ */
969
970 bytes_available = (m->m_flags & M_EXT) ?
971 m->m_ext.ext_size : MLEN;
972
973 /* ---- ----- --xx ---xxx */
974 /* ^ */
975 while ((bytes_needed != 0) && (bytes_needed > bytes_available)) {
976 m->m_len = bytes_available;
977 bytes_needed -= m->m_len;
978 /* ---- ----- --xx ------ */
979 /* ^ */
980
981 MGET(m->m_next, M_WAIT, MT_DATA);
982 m = m->m_next;
983 m->m_len = 0;
984 MCLGET(m, M_WAIT);
985
986 ASSERT((m->m_flags & M_EXT) != 0);
987 bytes_available = m->m_ext.ext_size;
988
989 /* ---- ----- --xx ------ xxxx */
990 /* ^ */
991 }
992
993 /* ---- ----- --xx ------ xxxx */
994 /* ^ */
995 /* Expand last tail as needed */
996 if (m->m_len <= bytes_needed) {
997 m->m_len = bytes_needed;
998 /* ---- ----- --xx ------ --xx */
999 /* ^ */
1000 }
1001
1002 return (0);
1003 }
1004
1005 static void
mbc_marshal_store_byte(mbuf_chain_t * mbc,uint8_t data)1006 mbc_marshal_store_byte(mbuf_chain_t *mbc, uint8_t data)
1007 {
1008 mbuf_t *m = mbc->chain;
1009 int32_t cur_offset = mbc->chain_offset;
1010
1011 /*
1012 * Scan forward looking for the last data currently in chain.
1013 */
1014 while (cur_offset >= m->m_len) {
1015 cur_offset -= m->m_len;
1016 m = m->m_next;
1017 }
1018 ((char *)m->m_data)[cur_offset] = data;
1019 mbc->chain_offset++;
1020 }
1021
1022 static int
mbc_marshal_put_char(mbuf_chain_t * mbc,uint8_t data)1023 mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t data)
1024 {
1025 if (mbc_marshal_make_room(mbc, sizeof (char)) != 0)
1026 return (DECODE_NO_MORE_DATA);
1027 mbc_marshal_store_byte(mbc, data);
1028 return (0);
1029 }
1030
1031 static int
mbc_marshal_put_short(mbuf_chain_t * mbc,uint16_t data)1032 mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t data)
1033 {
1034 if (mbc_marshal_make_room(mbc, sizeof (short)))
1035 return (DECODE_NO_MORE_DATA);
1036 mbc_marshal_store_byte(mbc, data);
1037 mbc_marshal_store_byte(mbc, data >> 8);
1038 return (0);
1039 }
1040
1041 static int
mbc_marshal_put_long(mbuf_chain_t * mbc,uint32_t data)1042 mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t data)
1043 {
1044 if (mbc_marshal_make_room(mbc, sizeof (int32_t)))
1045 return (DECODE_NO_MORE_DATA);
1046 mbc_marshal_store_byte(mbc, data);
1047 mbc_marshal_store_byte(mbc, data >> 8);
1048 mbc_marshal_store_byte(mbc, data >> 16);
1049 mbc_marshal_store_byte(mbc, data >> 24);
1050 return (0);
1051 }
1052
1053 static int
mbc_marshal_put_long_long(mbuf_chain_t * mbc,uint64_t data)1054 mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t data)
1055 {
1056 if (mbc_marshal_make_room(mbc, sizeof (int64_t)))
1057 return (DECODE_NO_MORE_DATA);
1058
1059 mbc_marshal_store_byte(mbc, data);
1060 mbc_marshal_store_byte(mbc, data >> 8);
1061 mbc_marshal_store_byte(mbc, data >> 16);
1062 mbc_marshal_store_byte(mbc, data >> 24);
1063 mbc_marshal_store_byte(mbc, data >> 32);
1064 mbc_marshal_store_byte(mbc, data >> 40);
1065 mbc_marshal_store_byte(mbc, data >> 48);
1066 mbc_marshal_store_byte(mbc, data >> 56);
1067 return (0);
1068 }
1069
1070 /*
1071 * When need to convert from UTF-8 (internal format) to a single
1072 * byte string (external format ) when marshalling a string.
1073 */
1074 static int
mbc_marshal_put_ascii_string(mbuf_chain_t * mbc,char * mbs,int repc)1075 mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc)
1076 {
1077 smb_wchar_t wide_char;
1078 int nbytes;
1079 int length;
1080
1081 if ((length = smb_sbequiv_strlen(mbs)) == -1)
1082 return (DECODE_NO_MORE_DATA);
1083
1084 length += sizeof (char);
1085
1086 if ((repc > 0) && (repc < length))
1087 length = repc;
1088 if (mbc_marshal_make_room(mbc, length))
1089 return (DECODE_NO_MORE_DATA);
1090
1091 while (*mbs) {
1092 /*
1093 * We should restore oem chars here.
1094 */
1095 nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX);
1096 if (nbytes == -1)
1097 return (DECODE_NO_MORE_DATA);
1098
1099 mbc_marshal_store_byte(mbc, (uint8_t)wide_char);
1100
1101 if (wide_char & 0xFF00)
1102 mbc_marshal_store_byte(mbc, wide_char >> 8);
1103
1104 mbs += nbytes;
1105 }
1106
1107 mbc_marshal_store_byte(mbc, 0);
1108 return (0);
1109 }
1110
1111 static int
mbc_marshal_put_unicode_string(mbuf_chain_t * mbc,char * ascii,int repc)1112 mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc)
1113 {
1114 smb_wchar_t wchar;
1115 int consumed;
1116 int length;
1117
1118 if ((length = smb_wcequiv_strlen(ascii)) == -1)
1119 return (DECODE_NO_MORE_DATA);
1120
1121 length += sizeof (smb_wchar_t);
1122
1123 if ((repc > 0) && (repc < length))
1124 length = repc;
1125
1126 if (mbc_marshal_make_room(mbc, length))
1127 return (DECODE_NO_MORE_DATA);
1128 while (length > 0) {
1129 consumed = smb_mbtowc(&wchar, ascii, MTS_MB_CHAR_MAX);
1130 if (consumed == -1)
1131 break; /* Invalid sequence */
1132 /*
1133 * Note that consumed will be 0 when the null terminator
1134 * is encountered and ascii will not be advanced beyond
1135 * that point. Length will continue to be decremented so
1136 * we won't get stuck here.
1137 */
1138 ascii += consumed;
1139 mbc_marshal_store_byte(mbc, wchar);
1140 mbc_marshal_store_byte(mbc, wchar >> 8);
1141 length -= sizeof (smb_wchar_t);
1142 }
1143 return (0);
1144 }
1145
1146 static int /*ARGSUSED*/
uiorefnoop(caddr_t p,int size,int adj)1147 uiorefnoop(caddr_t p, int size, int adj)
1148 {
1149 return (0);
1150 }
1151
1152 static int
mbc_marshal_put_uio(mbuf_chain_t * mbc,struct uio * uio)1153 mbc_marshal_put_uio(mbuf_chain_t *mbc, struct uio *uio)
1154 {
1155 mbuf_t **t;
1156 mbuf_t *m = NULL;
1157 struct iovec *iov = uio->uio_iov;
1158 int32_t i, iov_cnt = uio->uio_iovcnt;
1159
1160 iov = uio->uio_iov;
1161 t = &mbc->chain;
1162 for (i = 0; i < iov_cnt; i++) {
1163 MGET(m, M_WAIT, MT_DATA);
1164 m->m_ext.ext_buf = iov->iov_base;
1165 m->m_ext.ext_ref = uiorefnoop;
1166 m->m_data = m->m_ext.ext_buf;
1167 m->m_flags |= M_EXT;
1168 m->m_len = m->m_ext.ext_size = iov->iov_len;
1169 mbc->max_bytes += m->m_len;
1170 m->m_next = 0;
1171 *t = m;
1172 t = &m->m_next;
1173 iov++;
1174 }
1175 return (0);
1176 }
1177
1178 static int
mbc_marshal_put_mbufs(mbuf_chain_t * mbc,mbuf_t * m)1179 mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m)
1180 {
1181 mbuf_t *mt;
1182 mbuf_t **t;
1183 int bytes;
1184
1185 if (m != NULL) {
1186 mt = m;
1187 bytes = mt->m_len;
1188 while (mt->m_next != 0) {
1189 mt = mt->m_next;
1190 bytes += mt->m_len;
1191 }
1192 if (bytes != 0) {
1193 t = &mbc->chain;
1194 while (*t != 0) {
1195 bytes += (*t)->m_len;
1196 t = &(*t)->m_next;
1197 }
1198 *t = m;
1199 mbc->chain_offset = bytes;
1200 } else {
1201 m_freem(m);
1202 }
1203 }
1204 return (0);
1205 }
1206
1207 static int
mbc_marshal_put_mbuf_chain(mbuf_chain_t * mbc,mbuf_chain_t * nmbc)1208 mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc)
1209 {
1210 if (nmbc->chain != 0) {
1211 if (mbc_marshal_put_mbufs(mbc, nmbc->chain))
1212 return (DECODE_NO_MORE_DATA);
1213 MBC_SETUP(nmbc, nmbc->max_bytes);
1214 }
1215 return (0);
1216 }
1217
1218 static uint8_t
mbc_marshal_fetch_byte(mbuf_chain_t * mbc)1219 mbc_marshal_fetch_byte(mbuf_chain_t *mbc)
1220 {
1221 uint8_t data;
1222 mbuf_t *m = mbc->chain;
1223 int32_t offset = mbc->chain_offset;
1224
1225 while (offset >= m->m_len) {
1226 offset -= m->m_len;
1227 m = m->m_next;
1228 }
1229 data = ((uint8_t *)m->m_data)[offset];
1230 mbc->chain_offset++;
1231 return (data);
1232 }
1233
1234 static int
mbc_marshal_get_char(mbuf_chain_t * mbc,uint8_t * data)1235 mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data)
1236 {
1237 if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
1238 /* Data will never be available */
1239 return (DECODE_NO_MORE_DATA);
1240 }
1241 *data = mbc_marshal_fetch_byte(mbc);
1242 return (0);
1243 }
1244
1245 static int
mbc_marshal_get_short(mbuf_chain_t * mbc,uint16_t * data)1246 mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data)
1247 {
1248 uint16_t tmp;
1249 mbuf_t *m = mbc->chain;
1250 int32_t offset = mbc->chain_offset;
1251
1252 if (MBC_ROOM_FOR(mbc, sizeof (short)) == 0) {
1253 /* Data will never be available */
1254 return (DECODE_NO_MORE_DATA);
1255 }
1256
1257 while (offset >= m->m_len) {
1258 offset -= m->m_len;
1259 m = m->m_next;
1260 }
1261 if ((m->m_len - offset) >= sizeof (short)) {
1262 *data = LE_IN16(m->m_data + offset);
1263 mbc->chain_offset += sizeof (short);
1264 } else {
1265 tmp = (uint16_t)mbc_marshal_fetch_byte(mbc);
1266 tmp |= ((uint16_t)mbc_marshal_fetch_byte(mbc)) << 8;
1267 *data = tmp;
1268 }
1269 return (0);
1270 }
1271
1272 static int
mbc_marshal_get_long(mbuf_chain_t * mbc,uint32_t * data)1273 mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data)
1274 {
1275 uint32_t tmp;
1276 mbuf_t *m = mbc->chain;
1277 int32_t offset = mbc->chain_offset;
1278
1279 if (MBC_ROOM_FOR(mbc, sizeof (int32_t)) == 0) {
1280 /* Data will never be available */
1281 return (DECODE_NO_MORE_DATA);
1282 }
1283 while (offset >= m->m_len) {
1284 offset -= m->m_len;
1285 m = m->m_next;
1286 }
1287 if ((m->m_len - offset) >= sizeof (int32_t)) {
1288 *data = LE_IN32(m->m_data + offset);
1289 mbc->chain_offset += sizeof (int32_t);
1290 } else {
1291 tmp = (uint32_t)mbc_marshal_fetch_byte(mbc);
1292 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 8;
1293 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 16;
1294 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 24;
1295 *data = tmp;
1296 }
1297 return (0);
1298 }
1299
1300 static uint64_t
qswap(uint64_t ll)1301 qswap(uint64_t ll)
1302 {
1303 uint64_t v;
1304
1305 v = ll >> 32;
1306 v |= ll << 32;
1307
1308 return (v);
1309 }
1310
1311 static int
mbc_marshal_get_odd_long_long(mbuf_chain_t * mbc,uint64_t * data)1312 mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data)
1313 {
1314 uint64_t tmp;
1315 mbuf_t *m = mbc->chain;
1316 int32_t offset = mbc->chain_offset;
1317
1318 if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) {
1319 /* Data will never be available */
1320 return (DECODE_NO_MORE_DATA);
1321 }
1322 while (offset >= m->m_len) {
1323 offset -= m->m_len;
1324 m = m->m_next;
1325 }
1326
1327 if ((m->m_len - offset) >= sizeof (int64_t)) {
1328 *data = qswap(LE_IN64(m->m_data + offset));
1329 mbc->chain_offset += sizeof (int64_t);
1330 } else {
1331 tmp = (uint64_t)mbc_marshal_fetch_byte(mbc) << 32;
1332 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 40;
1333 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 48;
1334 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 56;
1335 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc);
1336 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 8;
1337 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 16;
1338 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 24;
1339
1340 *(uint64_t *)data = tmp;
1341 }
1342 return (0);
1343 }
1344
1345 static int
mbc_marshal_get_long_long(mbuf_chain_t * mbc,uint64_t * data)1346 mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data)
1347 {
1348 uint64_t tmp;
1349 mbuf_t *m = mbc->chain;
1350 int32_t offset = mbc->chain_offset;
1351
1352 if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) {
1353 /* Data will never be available */
1354 return (DECODE_NO_MORE_DATA);
1355 }
1356 while (offset >= m->m_len) {
1357 offset -= m->m_len;
1358 m = m->m_next;
1359 }
1360 if ((m->m_len - offset) >= sizeof (int64_t)) {
1361 *data = LE_IN64(m->m_data + offset);
1362 mbc->chain_offset += sizeof (int64_t);
1363 } else {
1364 tmp = (uint32_t)mbc_marshal_fetch_byte(mbc);
1365 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 8;
1366 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 16;
1367 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 24;
1368 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 32;
1369 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 40;
1370 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 48;
1371 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 56;
1372 *(uint64_t *)data = tmp;
1373 }
1374 return (0);
1375 }
1376
1377 /*
1378 * mbc_marshal_get_ascii_string
1379 *
1380 * The ascii string in smb includes oem chars. Since the
1381 * system needs utf8 encodes unicode char, conversion is
1382 * required to convert the oem char to unicode and then
1383 * to encode the converted wchars to utf8 format.
1384 * Therefore, the **ascii returned will be in such format
1385 * instead of the real ASCII format.
1386 */
1387 static int
mbc_marshal_get_ascii_string(smb_request_t * sr,mbuf_chain_t * mbc,uint8_t ** ascii,int max_ascii)1388 mbc_marshal_get_ascii_string(
1389 smb_request_t *sr,
1390 mbuf_chain_t *mbc,
1391 uint8_t **ascii,
1392 int max_ascii)
1393 {
1394 char *rcvbuf;
1395 char *ch;
1396 int max;
1397 int length = 0;
1398
1399 max = MALLOC_QUANTUM;
1400 rcvbuf = smb_srm_zalloc(sr, max);
1401
1402 if (max_ascii == 0)
1403 max_ascii = 0xffff;
1404
1405 ch = rcvbuf;
1406 for (;;) {
1407 while (length < max) {
1408 if (max_ascii-- <= 0) {
1409 *ch++ = 0;
1410 goto multibyte_encode;
1411 }
1412 if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
1413 /* Data will never be available */
1414 return (DECODE_NO_MORE_DATA);
1415 }
1416 if ((*ch++ = mbc_marshal_fetch_byte(mbc)) == 0)
1417 goto multibyte_encode;
1418 length++;
1419 }
1420 max += MALLOC_QUANTUM;
1421 rcvbuf = smb_srm_rezalloc(sr, rcvbuf, max);
1422 ch = rcvbuf + length;
1423 }
1424
1425 multibyte_encode:
1426 /*
1427 * UTF-8 encode the string for internal system use.
1428 */
1429 length = strlen(rcvbuf) + 1;
1430 *ascii = smb_srm_zalloc(sr, length * MTS_MB_CHAR_MAX);
1431 return (mbc_marshal_cstou8("CP850", (char *)*ascii,
1432 (size_t)length * MTS_MB_CHAR_MAX, rcvbuf, (size_t)length));
1433 }
1434
1435 static int
mbc_marshal_get_unicode_string(smb_request_t * sr,mbuf_chain_t * mbc,uint8_t ** ascii,int max_unicode)1436 mbc_marshal_get_unicode_string(smb_request_t *sr,
1437 mbuf_chain_t *mbc, uint8_t **ascii, int max_unicode)
1438 {
1439 int max;
1440 uint16_t wchar;
1441 char *ch;
1442 int emitted;
1443 int length = 0;
1444
1445 if (max_unicode == 0)
1446 max_unicode = 0xffff;
1447
1448 max = MALLOC_QUANTUM;
1449 *ascii = smb_srm_zalloc(sr, max);
1450
1451 ch = (char *)*ascii;
1452 for (;;) {
1453 while ((length + MTS_MB_CHAR_MAX) < max) {
1454 if (max_unicode <= 0)
1455 goto done;
1456 max_unicode -= 2;
1457
1458 if (mbc_marshal_get_short(mbc, &wchar) != 0)
1459 return (DECODE_NO_MORE_DATA);
1460
1461 if (wchar == 0) goto done;
1462
1463 emitted = smb_wctomb(ch, wchar);
1464 length += emitted;
1465 ch += emitted;
1466 }
1467 max += MALLOC_QUANTUM;
1468 *ascii = smb_srm_rezalloc(sr, *ascii, max);
1469 ch = (char *)*ascii + length;
1470 }
1471 done: *ch = 0;
1472 return (0);
1473 }
1474
1475 static int /*ARGSUSED*/
mbc_marshal_get_mbufs(mbuf_chain_t * mbc,int32_t bytes,mbuf_t ** m)1476 mbc_marshal_get_mbufs(mbuf_chain_t *mbc, int32_t bytes, mbuf_t **m)
1477 {
1478 *m = NULL;
1479 if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1480 /* Data will never be available */
1481 return (DECODE_NO_MORE_DATA);
1482 }
1483 /* not yet implemented */
1484 return (-1);
1485 }
1486
1487 static int
mbc_marshal_get_mbuf_chain(mbuf_chain_t * mbc,int32_t bytes,mbuf_chain_t * nmbc)1488 mbc_marshal_get_mbuf_chain(mbuf_chain_t *mbc, int32_t bytes, mbuf_chain_t *nmbc)
1489 {
1490 int rc;
1491 mbuf_t *m;
1492
1493 if (bytes == 0) {
1494 /* Get all the rest */
1495 bytes = mbc->max_bytes - mbc->chain_offset;
1496 }
1497
1498 MBC_SETUP(nmbc, mbc->max_bytes);
1499 if ((rc = mbc_marshal_get_mbufs(mbc, bytes, &m)) != 0) {
1500 if (m)
1501 m_freem(m);
1502 return (rc);
1503 }
1504 nmbc->chain = m;
1505 while (m != 0) {
1506 bytes += m->m_len;
1507 m = m->m_next;
1508 }
1509 nmbc->max_bytes = bytes;
1510 return (0);
1511 }
1512
1513 static int
mbc_marshal_get_uio(mbuf_chain_t * mbc,struct uio * uio)1514 mbc_marshal_get_uio(mbuf_chain_t *mbc, struct uio *uio)
1515 {
1516 int i, offset;
1517 int32_t bytes = uio->uio_resid;
1518 int32_t remainder;
1519 struct iovec *iov;
1520 mbuf_t *m;
1521
1522 /*
1523 * The residual count is tested because in the case of write requests
1524 * with no data (smbtorture RAW-WRITE test will generate that type of
1525 * request) this function is called with a residual count of zero
1526 * bytes.
1527 */
1528 if (bytes != 0) {
1529 iov = uio->uio_iov;
1530 uio->uio_segflg = UIO_SYSSPACE;
1531 uio->uio_extflg = UIO_COPY_DEFAULT;
1532
1533 if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1534 /* Data will never be available */
1535 return (DECODE_NO_MORE_DATA);
1536 }
1537
1538 m = mbc->chain;
1539 offset = mbc->chain_offset;
1540 while (offset >= m->m_len) {
1541 offset -= m->m_len;
1542 m = m->m_next;
1543 ASSERT((offset == 0) || (offset && m));
1544 }
1545
1546 for (i = 0; (bytes > 0) && (i < uio->uio_iovcnt); i++) {
1547 iov[i].iov_base = &m->m_data[offset];
1548 remainder = m->m_len - offset;
1549 if (remainder >= bytes) {
1550 iov[i].iov_len = bytes;
1551 mbc->chain_offset += bytes;
1552 uio->uio_iovcnt = i + 1;
1553 return (0);
1554 }
1555 iov[i].iov_len = remainder;
1556 mbc->chain_offset += remainder;
1557 bytes -= remainder;
1558 m = m->m_next;
1559 offset = 0;
1560 }
1561 return (DECODE_NO_MORE_DATA);
1562 }
1563 return (0);
1564 }
1565
1566 static int
mbc_marshal_get_skip(mbuf_chain_t * mbc,uint_t skip)1567 mbc_marshal_get_skip(mbuf_chain_t *mbc, uint_t skip)
1568 {
1569 if (MBC_ROOM_FOR(mbc, skip) == 0)
1570 return (DECODE_NO_MORE_DATA);
1571 mbc->chain_offset += skip;
1572 return (0);
1573 }
1574
1575 /*
1576 * Converts oem string to UTF-8 string with an output string of max
1577 * maxconv bytes. The string may be truncated or not null-terminated if
1578 * there is not enough room.
1579 *
1580 * returns -1, cnt (partial conversion) or 0 (success)
1581 */
1582
1583 static int
mbc_marshal_cstou8(char * cs,char * outbuf,size_t maxconv,char * inbuf,size_t srcbytes)1584 mbc_marshal_cstou8(char *cs, char *outbuf, size_t maxconv,
1585 char *inbuf, size_t srcbytes)
1586 {
1587 kiconv_t t2u;
1588 size_t inlen = srcbytes;
1589 size_t outlen = maxconv;
1590 int err = 0;
1591 size_t rc;
1592
1593 if ((t2u = kiconv_open("UTF-8", cs)) == (kiconv_t)-1)
1594 return (-1);
1595
1596 rc = kiconv(t2u, &inbuf, &inlen, &outbuf, &outlen, &err);
1597 (void) kiconv_close(t2u);
1598 return ((int)rc);
1599 }
1600