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 *
  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 }