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 <smb/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