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