Print this page
1575 untangle libmlrpc ... (libmlrpc)


   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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.


  24  */
  25 
  26 /*
  27  * NDR heap management. The heap is used for temporary storage by
  28  * both the client and server side library routines.  In order to
  29  * support the different requirements of the various RPCs, the heap
  30  * can grow dynamically if required.  We start with a single block
  31  * and perform sub-allocations from it.  If an RPC requires more space
  32  * we will continue to add it a block at a time.  This means that we
  33  * don't hog lots of memory on every call to support the few times
  34  * that we actually need a lot heap space.
  35  *
  36  * Note that there is no individual free function.  Once space has been
  37  * allocated, it remains allocated until the heap is destroyed.  This
  38  * shouldn't be an issue because the heap is being filled with data to
  39  * be marshalled or unmarshalled and we need it all to be there until
  40  * the point that the entire heap is no longer required.
  41  */
  42 
  43 #include <sys/errno.h>
  44 #include <stdlib.h>
  45 #include <string.h>
  46 #include <strings.h>
  47 #include <sys/uio.h>
  48 
  49 #include <smbsrv/libsmb.h>
  50 #include <smbsrv/libmlrpc.h>
  51 #include <smbsrv/smb_sid.h>
  52 
  53 /*
  54  * Allocate a heap structure and the first heap block.  For many RPC
  55  * operations this will be the only time we need to malloc memory
  56  * in this instance of the heap.  The only point of note here is that
  57  * we put the heap management data in the first block to avoid a
  58  * second malloc. Make sure that sizeof(ndr_heap_t) is smaller
  59  * than NDR_HEAP_BLKSZ.
  60  *
  61  * Note that the heap management data is at the start of the first block.
  62  *
  63  * Returns a pointer to the newly created heap, which is used like an
  64  * opaque handle with the rest of the heap management interface..
  65  */
  66 ndr_heap_t *
  67 ndr_heap_create(void)
  68 {
  69         ndr_heap_t *heap;
  70         char *base;
  71         size_t allocsize = sizeof (ndr_heap_t) + NDR_HEAP_BLKSZ;


 137                 if ((heap->iovcnt == 0) || ((--heap->iovcnt) == 0))
 138                         return (NULL);
 139 
 140                 incr_size = (size < NDR_HEAP_BLKSZ) ? NDR_HEAP_BLKSZ : size;
 141 
 142                 if ((p = (char *)malloc(incr_size)) == NULL)
 143                         return (NULL);
 144 
 145                 ++heap->iov;
 146                 heap->iov->iov_base = p;
 147                 heap->iov->iov_len = 0;
 148                 heap->top = p + incr_size;
 149         }
 150 
 151         heap->next = p + size;
 152         heap->iov->iov_len += size;
 153         return ((void *)p);
 154 }
 155 
 156 /*

















 157  * Convenience function to do heap strdup.
 158  */
 159 void *
 160 ndr_heap_strdup(ndr_heap_t *heap, const char *s)
 161 {
 162         int len;
 163         void *p;
 164 
 165         if (s == NULL)
 166                 return (NULL);
 167 
 168         /*
 169          * We don't need to clutter the heap with empty strings.
 170          */
 171         if ((len = strlen(s)) == 0)
 172                 return ("");
 173 
 174         if ((p = ndr_heap_malloc(heap, len+1)) != NULL)
 175                 (void) strcpy((char *)p, s);
 176 
 177         return (p);
 178 }
 179 
 180 /*
 181  * Make an ndr_mstring_t from a regular string.
 182  */
 183 int
 184 ndr_heap_mstring(ndr_heap_t *heap, const char *s, ndr_mstring_t *out)
 185 {


 186         if (s == NULL || out == NULL)
 187                 return (-1);
 188 
 189         out->length = smb_wcequiv_strlen(s);
 190         out->allosize = out->length + sizeof (smb_wchar_t);





 191 



 192         if ((out->str = ndr_heap_strdup(heap, s)) == NULL)
 193                 return (-1);
 194 
 195         return (0);
 196 }
 197 
 198 /*
 199  * Our regular string marshalling always creates null terminated strings
 200  * but some Windows clients and servers are pedantic about the string
 201  * formats they will accept and require non-null terminated strings.
 202  * This function can be used to build a wide-char, non-null terminated
 203  * string in the heap as a varying/conformant array.  We need to do the
 204  * wide-char conversion here because the marshalling code won't be
 205  * aware that this is really a string.
 206  */
 207 void
 208 ndr_heap_mkvcs(ndr_heap_t *heap, char *s, ndr_vcstr_t *vc)
 209 {

 210         int mlen;
 211 
 212         vc->wclen = smb_wcequiv_strlen(s);








 213         vc->wcsize = vc->wclen;
 214 
 215         mlen = sizeof (ndr_vcs_t) + vc->wcsize + sizeof (smb_wchar_t);
 216 



 217         vc->vcs = ndr_heap_malloc(heap, mlen);
 218 
 219         if (vc->vcs) {
 220                 vc->vcs->vc_first_is = 0;
 221                 vc->vcs->vc_length_is = vc->wclen / sizeof (smb_wchar_t);
 222                 (void) smb_mbstowcs((smb_wchar_t *)vc->vcs->buffer, s,
 223                     vc->vcs->vc_length_is);
 224         }
 225 }
 226 
 227 void
 228 ndr_heap_mkvcb(ndr_heap_t *heap, uint8_t *data, uint32_t datalen,
 229     ndr_vcbuf_t *vcbuf)
 230 {
 231         int mlen;
 232 
 233         if (data == NULL || datalen == 0) {
 234                 bzero(vcbuf, sizeof (ndr_vcbuf_t));
 235                 return;
 236         }
 237 
 238         vcbuf->len = datalen;
 239         vcbuf->size = datalen;
 240 
 241         mlen = sizeof (ndr_vcbuf_t) + datalen;
 242 
 243         vcbuf->vcb = ndr_heap_malloc(heap, mlen);
 244 
 245         if (vcbuf->vcb) {
 246                 vcbuf->vcb->vc_first_is = 0;
 247                 vcbuf->vcb->vc_length_is = datalen;
 248                 bcopy(data, vcbuf->vcb->buffer, datalen);
 249         }
 250 }
 251 
 252 /*
 253  * Duplcate a SID in the heap.
 254  */
 255 smb_sid_t *
 256 ndr_heap_siddup(ndr_heap_t *heap, smb_sid_t *sid)
 257 {
 258         smb_sid_t *new_sid;
 259         unsigned size;
 260 
 261         if (sid == NULL)
 262                 return (NULL);
 263 
 264         size = smb_sid_len(sid);
 265 
 266         if ((new_sid = ndr_heap_malloc(heap, size)) == NULL)
 267                 return (NULL);
 268 
 269         bcopy(sid, new_sid, size);
 270         return (new_sid);
 271 }
 272 
 273 int
 274 ndr_heap_used(ndr_heap_t *heap)
 275 {
 276         int used = 0;
 277         int i;
 278 
 279         for (i = 0; i < NDR_HEAP_MAXIOV; ++i)
 280                 used += heap->iovec[i].iov_len;
 281 
 282         return (used);
 283 }
 284 
 285 int
 286 ndr_heap_avail(ndr_heap_t *heap)
 287 {
 288         int avail;
 289         int count;
 290 
 291         count = (heap->iovcnt == 0) ? 0 : (heap->iovcnt - 1);
 292 


   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 2009 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  * NDR heap management. The heap is used for temporary storage by
  30  * both the client and server side library routines.  In order to
  31  * support the different requirements of the various RPCs, the heap
  32  * can grow dynamically if required.  We start with a single block
  33  * and perform sub-allocations from it.  If an RPC requires more space
  34  * we will continue to add it a block at a time.  This means that we
  35  * don't hog lots of memory on every call to support the few times
  36  * that we actually need a lot heap space.
  37  *
  38  * Note that there is no individual free function.  Once space has been
  39  * allocated, it remains allocated until the heap is destroyed.  This
  40  * shouldn't be an issue because the heap is being filled with data to
  41  * be marshalled or unmarshalled and we need it all to be there until
  42  * the point that the entire heap is no longer required.
  43  */
  44 
  45 #include <sys/errno.h>
  46 #include <stdlib.h>
  47 #include <string.h>
  48 #include <strings.h>
  49 #include <sys/uio.h>
  50 
  51 #include <libmlrpc.h>
  52 #include <ndr_wchar.h>

  53 
  54 /*
  55  * Allocate a heap structure and the first heap block.  For many RPC
  56  * operations this will be the only time we need to malloc memory
  57  * in this instance of the heap.  The only point of note here is that
  58  * we put the heap management data in the first block to avoid a
  59  * second malloc. Make sure that sizeof(ndr_heap_t) is smaller
  60  * than NDR_HEAP_BLKSZ.
  61  *
  62  * Note that the heap management data is at the start of the first block.
  63  *
  64  * Returns a pointer to the newly created heap, which is used like an
  65  * opaque handle with the rest of the heap management interface..
  66  */
  67 ndr_heap_t *
  68 ndr_heap_create(void)
  69 {
  70         ndr_heap_t *heap;
  71         char *base;
  72         size_t allocsize = sizeof (ndr_heap_t) + NDR_HEAP_BLKSZ;


 138                 if ((heap->iovcnt == 0) || ((--heap->iovcnt) == 0))
 139                         return (NULL);
 140 
 141                 incr_size = (size < NDR_HEAP_BLKSZ) ? NDR_HEAP_BLKSZ : size;
 142 
 143                 if ((p = (char *)malloc(incr_size)) == NULL)
 144                         return (NULL);
 145 
 146                 ++heap->iov;
 147                 heap->iov->iov_base = p;
 148                 heap->iov->iov_len = 0;
 149                 heap->top = p + incr_size;
 150         }
 151 
 152         heap->next = p + size;
 153         heap->iov->iov_len += size;
 154         return ((void *)p);
 155 }
 156 
 157 /*
 158  * Convenience function to copy some memory into the heap.
 159  */
 160 void *
 161 ndr_heap_dupmem(ndr_heap_t *heap, const void *mem, size_t len)
 162 {
 163         void *p;
 164 
 165         if (mem == NULL)
 166                 return (NULL);
 167 
 168         if ((p = ndr_heap_malloc(heap, len)) != NULL)
 169                 (void) memcpy(p, mem, len);
 170 
 171         return (p);
 172 }
 173 
 174 /*
 175  * Convenience function to do heap strdup.
 176  */
 177 void *
 178 ndr_heap_strdup(ndr_heap_t *heap, const char *s)
 179 {
 180         int len;
 181         void *p;
 182 
 183         if (s == NULL)
 184                 return (NULL);
 185 
 186         /*
 187          * We don't need to clutter the heap with empty strings.
 188          */
 189         if ((len = strlen(s)) == 0)
 190                 return ("");
 191 
 192         p = ndr_heap_dupmem(heap, s, len+1);

 193 
 194         return (p);
 195 }
 196 
 197 /*
 198  * Make an ndr_mstring_t from a regular string.
 199  */
 200 int
 201 ndr_heap_mstring(ndr_heap_t *heap, const char *s, ndr_mstring_t *out)
 202 {
 203         size_t slen;
 204 
 205         if (s == NULL || out == NULL)
 206                 return (-1);
 207 
 208         /*
 209          * Determine the WC strlen of s
 210          * Was ndr__wcequiv_strlen(s)
 211          */
 212         slen = ndr__mbstowcs(NULL, s, NDR_STRING_MAX);
 213         if (slen == (size_t)-1)
 214                 return (-1);
 215 
 216         out->length = slen * sizeof (ndr_wchar_t);
 217         out->allosize = out->length + sizeof (ndr_wchar_t);
 218 
 219         if ((out->str = ndr_heap_strdup(heap, s)) == NULL)
 220                 return (-1);
 221 
 222         return (0);
 223 }
 224 
 225 /*
 226  * Our regular string marshalling always creates null terminated strings
 227  * but some Windows clients and servers are pedantic about the string
 228  * formats they will accept and require non-null terminated strings.
 229  * This function can be used to build a wide-char, non-null terminated
 230  * string in the heap as a varying/conformant array.  We need to do the
 231  * wide-char conversion here because the marshalling code won't be
 232  * aware that this is really a string.
 233  */
 234 void
 235 ndr_heap_mkvcs(ndr_heap_t *heap, char *s, ndr_vcstr_t *vc)
 236 {
 237         size_t slen;
 238         int mlen;
 239 
 240         /*
 241          * Determine the WC strlen of s
 242          * Was ndr__wcequiv_strlen(s)
 243          */
 244         slen = ndr__mbstowcs(NULL, s, NDR_STRING_MAX);
 245         if (slen == (size_t)-1)
 246                 slen = 0;
 247 
 248         vc->wclen = slen * sizeof (ndr_wchar_t);
 249         vc->wcsize = vc->wclen;
 250 
 251         /*
 252          * alloc one extra wchar for a null
 253          * See slen + 1 arg for mbstowcs
 254          */
 255         mlen = sizeof (ndr_vcs_t) + vc->wcsize + sizeof (ndr_wchar_t);
 256         vc->vcs = ndr_heap_malloc(heap, mlen);
 257 
 258         if (vc->vcs) {
 259                 vc->vcs->vc_first_is = 0;
 260                 vc->vcs->vc_length_is = slen;
 261                 (void) ndr__mbstowcs(vc->vcs->buffer, s, slen + 1);

 262         }
 263 }
 264 
 265 void
 266 ndr_heap_mkvcb(ndr_heap_t *heap, uint8_t *data, uint32_t datalen,
 267     ndr_vcbuf_t *vcbuf)
 268 {
 269         int mlen;
 270 
 271         if (data == NULL || datalen == 0) {
 272                 bzero(vcbuf, sizeof (ndr_vcbuf_t));
 273                 return;
 274         }
 275 
 276         vcbuf->len = datalen;
 277         vcbuf->size = datalen;
 278 
 279         mlen = sizeof (ndr_vcbuf_t) + datalen;
 280 
 281         vcbuf->vcb = ndr_heap_malloc(heap, mlen);
 282 
 283         if (vcbuf->vcb) {
 284                 vcbuf->vcb->vc_first_is = 0;
 285                 vcbuf->vcb->vc_length_is = datalen;
 286                 bcopy(data, vcbuf->vcb->buffer, datalen);
 287         }
 288 }
 289 
 290 /*
 291  * Removed ndr_heap_siddup(), now using ndr_heap_dupmem().
 292  */





 293 












 294 int
 295 ndr_heap_used(ndr_heap_t *heap)
 296 {
 297         int used = 0;
 298         int i;
 299 
 300         for (i = 0; i < NDR_HEAP_MAXIOV; ++i)
 301                 used += heap->iovec[i].iov_len;
 302 
 303         return (used);
 304 }
 305 
 306 int
 307 ndr_heap_avail(ndr_heap_t *heap)
 308 {
 309         int avail;
 310         int count;
 311 
 312         count = (heap->iovcnt == 0) ? 0 : (heap->iovcnt - 1);
 313