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 * 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 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 * 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 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 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 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 131 smb_dr_get_uint32(smb_dr_ctx_t *ctx) 132 { 133 return ((uint32_t)smb_dr_get_int32(ctx)); 134 } 135 136 char * 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 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 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 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 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 227 smb_dr_free_string(char *buf) 228 { 229 if (buf) 230 MEM_FREE("CommonDoor", buf); 231 } 232 233 int64_t 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 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 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 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 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 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 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 309 smb_dr_get_ushort(smb_dr_ctx_t *ctx) 310 { 311 return ((unsigned short)smb_dr_get_short(ctx)); 312 } 313 314 void 315 smb_dr_put_word(smb_dr_ctx_t *ctx, WORD num) 316 { 317 smb_dr_put_ushort(ctx, num); 318 } 319 320 WORD 321 smb_dr_get_word(smb_dr_ctx_t *ctx) 322 { 323 return (smb_dr_get_ushort(ctx)); 324 } 325 326 void 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 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 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 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 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 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