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 2013 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 /*
29 * Legacy encode/decode routines for door clients and servers.
30 */
31
32 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
33 #include <errno.h>
34 #include <string.h>
35 #include <strings.h>
36 #else
37 #include <sys/types.h>
38 #include <sys/sunddi.h>
39 #include <sys/errno.h>
40 #endif
41
42 #include <smbsrv/wintypes.h>
43 #include <smbsrv/smb_share.h>
44 #include <smbsrv/smb_door.h>
45 #include <smbsrv/alloc.h>
46 #include <smbsrv/smbinfo.h>
47
48 smb_dr_ctx_t *
smb_dr_decode_start(char * ptr,int size)49 smb_dr_decode_start(char *ptr, int size)
50 {
51 smb_dr_ctx_t *ctx = MEM_MALLOC("CommonDoor", sizeof (smb_dr_ctx_t));
52 if (ctx) {
53 ctx->start_ptr = ctx->ptr = ptr;
54 ctx->end_ptr = ptr + size;
55 ctx->status = 0;
56 }
57 return (ctx);
58 }
59
60 int
smb_dr_decode_finish(smb_dr_ctx_t * ctx)61 smb_dr_decode_finish(smb_dr_ctx_t *ctx)
62 {
63 int status = ctx->status;
64 if (status == 0 && ctx->ptr != ctx->end_ptr)
65 status = ENOTEMPTY;
66
67 MEM_FREE("CommonDoor", ctx);
68 return (status);
69 }
70
71 smb_dr_ctx_t *
smb_dr_encode_start(char * ptr,int size)72 smb_dr_encode_start(char *ptr, int size)
73 {
74 smb_dr_ctx_t *ctx = MEM_MALLOC("CommonDoor", sizeof (smb_dr_ctx_t));
75 if (ctx) {
76 ctx->start_ptr = ctx->ptr = ptr;
77 ctx->end_ptr = ptr + size;
78 ctx->status = 0;
79 }
80 return (ctx);
81 }
82
83 int
smb_dr_encode_finish(smb_dr_ctx_t * ctx,unsigned int * used)84 smb_dr_encode_finish(smb_dr_ctx_t *ctx, unsigned int *used)
85 {
86 int status = ctx->status;
87 if (status == 0) {
88 if (ctx->ptr < ctx->end_ptr) {
89 /*LINTED E_PTRDIFF_OVERFLOW*/
90 *used = ctx->ptr - ctx->start_ptr;
91 } else {
92 status = ENOSPC;
93 }
94 }
95
96 MEM_FREE("CommonDoor", ctx);
97 return (status);
98 }
99
100 DWORD
smb_dr_get_dword(smb_dr_ctx_t * ctx)101 smb_dr_get_dword(smb_dr_ctx_t *ctx)
102 {
103 DWORD num = 0;
104 if (ctx->status == 0) {
105 if (ctx->ptr + sizeof (DWORD) <= ctx->end_ptr) {
106 (void) memcpy(&num, ctx->ptr, sizeof (DWORD));
107 ctx->ptr += sizeof (DWORD);
108 } else {
109 ctx->status = ENOSPC;
110 }
111 }
112 return (num);
113 }
114
115 int32_t
smb_dr_get_int32(smb_dr_ctx_t * ctx)116 smb_dr_get_int32(smb_dr_ctx_t *ctx)
117 {
118 int32_t num = 0;
119 if (ctx->status == 0) {
120 if (ctx->ptr + sizeof (int32_t) <= ctx->end_ptr) {
121 (void) memcpy(&num, ctx->ptr, sizeof (int32_t));
122 ctx->ptr += sizeof (int32_t);
123 } else {
124 ctx->status = ENOSPC;
125 }
126 }
127 return (num);
128 }
129
130 uint32_t
smb_dr_get_uint32(smb_dr_ctx_t * ctx)131 smb_dr_get_uint32(smb_dr_ctx_t *ctx)
132 {
133 return ((uint32_t)smb_dr_get_int32(ctx));
134 }
135
136 char *
smb_dr_get_string(smb_dr_ctx_t * ctx)137 smb_dr_get_string(smb_dr_ctx_t *ctx)
138 {
139 char *buf = NULL;
140 int len = smb_dr_get_int32(ctx);
141
142 if (ctx->status == 0) {
143 if (len == -1)
144 return (buf);
145
146 if (ctx->ptr + len <= ctx->end_ptr) {
147 buf = MEM_MALLOC("CommonDoor", len +1);
148 if (buf) {
149 if (len == 0) {
150 (void) strcpy(buf, "");
151 } else {
152 (void) memcpy(buf, ctx->ptr, len);
153 ctx->ptr += len;
154 *(buf + len) = '\0';
155 }
156 } else {
157 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
158 ctx->status = errno;
159 #else
160 ctx->status = ENOMEM;
161 #endif
162 }
163 } else {
164 ctx->status = ENOSPC;
165 }
166 }
167 return (buf);
168 }
169
170 void
smb_dr_put_dword(smb_dr_ctx_t * ctx,DWORD num)171 smb_dr_put_dword(smb_dr_ctx_t *ctx, DWORD num)
172 {
173 if (ctx->status == 0) {
174 if (ctx->ptr + sizeof (DWORD) <= ctx->end_ptr) {
175 (void) memcpy(ctx->ptr, &num, sizeof (DWORD));
176 ctx->ptr += sizeof (DWORD);
177 } else {
178 ctx->status = ENOSPC;
179 }
180 }
181 }
182
183 void
smb_dr_put_int32(smb_dr_ctx_t * ctx,int32_t num)184 smb_dr_put_int32(smb_dr_ctx_t *ctx, int32_t num)
185 {
186 if (ctx->status == 0) {
187 if (ctx->ptr + sizeof (int32_t) <= ctx->end_ptr) {
188 (void) memcpy(ctx->ptr, &num, sizeof (int32_t));
189 ctx->ptr += sizeof (int32_t);
190 } else {
191 ctx->status = ENOSPC;
192 }
193 }
194 }
195
196 void
smb_dr_put_uint32(smb_dr_ctx_t * ctx,uint32_t num)197 smb_dr_put_uint32(smb_dr_ctx_t *ctx, uint32_t num)
198 {
199 smb_dr_put_int32(ctx, (int32_t)num);
200 }
201
202 void
smb_dr_put_string(smb_dr_ctx_t * ctx,const char * buf)203 smb_dr_put_string(smb_dr_ctx_t *ctx, const char *buf)
204 {
205 int len;
206
207 if (!buf)
208 len = -1;
209 else
210 len = strlen(buf);
211
212 if (ctx->status == 0) {
213 smb_dr_put_int32(ctx, len);
214 if (len <= 0)
215 return;
216
217 if (ctx->ptr + len <= ctx->end_ptr) {
218 (void) memcpy(ctx->ptr, buf, len);
219 ctx->ptr += len;
220 } else {
221 ctx->status = ENOSPC;
222 }
223 }
224 }
225
226 void
smb_dr_free_string(char * buf)227 smb_dr_free_string(char *buf)
228 {
229 if (buf)
230 MEM_FREE("CommonDoor", buf);
231 }
232
233 int64_t
smb_dr_get_int64(smb_dr_ctx_t * ctx)234 smb_dr_get_int64(smb_dr_ctx_t *ctx)
235 {
236 int64_t num = 0;
237 if (ctx->status == 0) {
238 if (ctx->ptr + sizeof (int64_t) <= ctx->end_ptr) {
239 (void) memcpy(&num, ctx->ptr, sizeof (int64_t));
240 ctx->ptr += sizeof (int64_t);
241 } else {
242 ctx->status = ENOSPC;
243 }
244 }
245 return (num);
246 }
247
248 uint64_t
smb_dr_get_uint64(smb_dr_ctx_t * ctx)249 smb_dr_get_uint64(smb_dr_ctx_t *ctx)
250 {
251 return ((uint64_t)smb_dr_get_int64(ctx));
252 }
253
254
255 void
smb_dr_put_int64(smb_dr_ctx_t * ctx,int64_t num)256 smb_dr_put_int64(smb_dr_ctx_t *ctx, int64_t num)
257 {
258 if (ctx->status == 0) {
259 if (ctx->ptr + sizeof (int64_t) <= ctx->end_ptr) {
260 (void) memcpy(ctx->ptr, &num, sizeof (int64_t));
261 ctx->ptr += sizeof (int64_t);
262 } else {
263 ctx->status = ENOSPC;
264 }
265 }
266 }
267
268 void
smb_dr_put_uint64(smb_dr_ctx_t * ctx,uint64_t num)269 smb_dr_put_uint64(smb_dr_ctx_t *ctx, uint64_t num)
270 {
271 smb_dr_put_int64(ctx, (int64_t)num);
272 }
273
274 void
smb_dr_put_short(smb_dr_ctx_t * ctx,short num)275 smb_dr_put_short(smb_dr_ctx_t *ctx, short num)
276 {
277 if (ctx->status == 0) {
278 if (ctx->ptr + sizeof (short) <= ctx->end_ptr) {
279 (void) memcpy(ctx->ptr, &num, sizeof (short));
280 ctx->ptr += sizeof (short);
281 } else {
282 ctx->status = ENOSPC;
283 }
284 }
285 }
286
287 short
smb_dr_get_short(smb_dr_ctx_t * ctx)288 smb_dr_get_short(smb_dr_ctx_t *ctx)
289 {
290 short num = 0;
291 if (ctx->status == 0) {
292 if (ctx->ptr + sizeof (short) <= ctx->end_ptr) {
293 (void) memcpy(&num, ctx->ptr, sizeof (short));
294 ctx->ptr += sizeof (short);
295 } else {
296 ctx->status = ENOSPC;
297 }
298 }
299 return (num);
300 }
301
302 void
smb_dr_put_ushort(smb_dr_ctx_t * ctx,unsigned short num)303 smb_dr_put_ushort(smb_dr_ctx_t *ctx, unsigned short num)
304 {
305 smb_dr_put_short(ctx, (short)num);
306 }
307
308 unsigned short
smb_dr_get_ushort(smb_dr_ctx_t * ctx)309 smb_dr_get_ushort(smb_dr_ctx_t *ctx)
310 {
311 return ((unsigned short)smb_dr_get_short(ctx));
312 }
313
314 void
smb_dr_put_word(smb_dr_ctx_t * ctx,WORD num)315 smb_dr_put_word(smb_dr_ctx_t *ctx, WORD num)
316 {
317 smb_dr_put_ushort(ctx, num);
318 }
319
320 WORD
smb_dr_get_word(smb_dr_ctx_t * ctx)321 smb_dr_get_word(smb_dr_ctx_t *ctx)
322 {
323 return (smb_dr_get_ushort(ctx));
324 }
325
326 void
smb_dr_put_BYTE(smb_dr_ctx_t * ctx,BYTE byte)327 smb_dr_put_BYTE(smb_dr_ctx_t *ctx, BYTE byte)
328 {
329 if (ctx->status == 0) {
330 if (ctx->ptr + sizeof (BYTE) <= ctx->end_ptr) {
331 (void) memcpy(ctx->ptr, &byte, sizeof (BYTE));
332 ctx->ptr += sizeof (BYTE);
333 } else {
334 ctx->status = ENOSPC;
335 }
336 }
337 }
338
339 BYTE
smb_dr_get_BYTE(smb_dr_ctx_t * ctx)340 smb_dr_get_BYTE(smb_dr_ctx_t *ctx)
341 {
342 BYTE byte = 0;
343 if (ctx->status == 0) {
344 if (ctx->ptr + sizeof (BYTE) <= ctx->end_ptr) {
345 (void) memcpy(&byte, ctx->ptr, sizeof (BYTE));
346 ctx->ptr += sizeof (BYTE);
347 } else {
348 ctx->status = ENOSPC;
349 }
350 }
351 return (byte);
352 }
353
354 void
smb_dr_put_buf(smb_dr_ctx_t * ctx,unsigned char * start,int len)355 smb_dr_put_buf(smb_dr_ctx_t *ctx, unsigned char *start, int len)
356 {
357 smb_dr_put_int32(ctx, len);
358 if (ctx->status == 0) {
359 if (ctx->ptr + len <= ctx->end_ptr) {
360 (void) memcpy(ctx->ptr, start, len);
361 ctx->ptr += len;
362 } else {
363 ctx->status = ENOSPC;
364 }
365 }
366 }
367
368 int
smb_dr_get_buf(smb_dr_ctx_t * ctx,unsigned char * buf,int bufsize)369 smb_dr_get_buf(smb_dr_ctx_t *ctx, unsigned char *buf, int bufsize)
370 {
371 int len = -1;
372
373 if (!buf)
374 return (-1);
375
376 len = smb_dr_get_int32(ctx);
377 if (ctx->status == 0) {
378 if (bufsize < len) {
379 ctx->status = ENOSPC;
380 return (-2);
381 }
382
383 if (ctx->ptr + len <= ctx->end_ptr) {
384 (void) memcpy(buf, ctx->ptr, len);
385 ctx->ptr += len;
386 } else {
387 ctx->status = ENOSPC;
388 return (-3);
389 }
390 }
391
392 return (len);
393 }
394
395 void
smb_dr_get_share(smb_dr_ctx_t * ctx,smb_share_t * si)396 smb_dr_get_share(smb_dr_ctx_t *ctx, smb_share_t *si)
397 {
398 if (ctx->status == 0) {
399 if (smb_dr_get_int32(ctx)) {
400 (void) memcpy(si, ctx->ptr, sizeof (smb_share_t));
401 ctx->ptr += sizeof (smb_share_t);
402 } else {
403 bzero(si, sizeof (smb_share_t));
404 }
405 } else {
406 bzero(si, sizeof (smb_share_t));
407 }
408 }
409
410 void
smb_dr_put_share(smb_dr_ctx_t * ctx,smb_share_t * si)411 smb_dr_put_share(smb_dr_ctx_t *ctx, smb_share_t *si)
412 {
413 if (si) {
414 smb_dr_put_int32(ctx, 1);
415 if (ctx->ptr + sizeof (smb_share_t) <= ctx->end_ptr) {
416 (void) memcpy(ctx->ptr, si, sizeof (smb_share_t));
417 ctx->ptr += sizeof (smb_share_t);
418 } else {
419 ctx->status = ENOSPC;
420 }
421 } else {
422 smb_dr_put_int32(ctx, 0);
423 }
424 }
425