LCOV - code coverage report
Current view: top level - lib/tdr - tdr.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 98 187 52.4 %
Date: 2024-04-21 15:09:00 Functions: 18 30 60.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    TDR (Trivial Data Representation) helper functions
       5             :      Based loosely on ndr.c by Andrew Tridgell.
       6             : 
       7             :    Copyright (C) Jelmer Vernooij 2005
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "system/filesys.h"
      25             : #include "system/network.h"
      26             : #include "lib/tdr/tdr.h"
      27             : 
      28             : #define TDR_BASE_MARSHALL_SIZE 1024
      29             : 
      30             : #define TDR_PUSH_NEED_BYTES(tdr, n) TDR_CHECK(tdr_push_expand(tdr, tdr->data.length+(n)))
      31             : 
      32             : #define TDR_PULL_NEED_BYTES(tdr, n) do { \
      33             :         if ((n) > tdr->data.length || tdr->offset + (n) > tdr->data.length) { \
      34             :                 return NT_STATUS_BUFFER_TOO_SMALL; \
      35             :         } \
      36             : } while(0)
      37             : 
      38             : #define TDR_BE(tdr) ((tdr)->flags & TDR_BIG_ENDIAN)
      39             : 
      40             : #define TDR_CVAL(tdr, ofs) CVAL(tdr->data.data,ofs)
      41             : #define TDR_SVAL(tdr, ofs) (TDR_BE(tdr)?RSVAL(tdr->data.data,ofs):SVAL(tdr->data.data,ofs))
      42             : #define TDR_IVAL(tdr, ofs) (TDR_BE(tdr)?RIVAL(tdr->data.data,ofs):IVAL(tdr->data.data,ofs))
      43             : #define TDR_SCVAL(tdr, ofs, v) SCVAL(tdr->data.data,ofs,v)
      44             : #define TDR_SSVAL(tdr, ofs, v) do { if (TDR_BE(tdr))  { RSSVAL(tdr->data.data,ofs,v); } else SSVAL(tdr->data.data,ofs,v); } while (0)
      45             : #define TDR_SIVAL(tdr, ofs, v) do { if (TDR_BE(tdr))  { RSIVAL(tdr->data.data,ofs,v); } else SIVAL(tdr->data.data,ofs,v); } while (0)
      46             : 
      47             : /**
      48             :   expand the available space in the buffer to 'size'
      49             : */
      50        9484 : NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size)
      51             : {
      52        9484 :         if (talloc_get_size(tdr->data.data) >= size) {
      53        9411 :                 return NT_STATUS_OK;
      54             :         }
      55             : 
      56          73 :         tdr->data.data = talloc_realloc(tdr, tdr->data.data, uint8_t, tdr->data.length + TDR_BASE_MARSHALL_SIZE);
      57             : 
      58          73 :         if (tdr->data.data == NULL)
      59           0 :                 return NT_STATUS_NO_MEMORY;
      60             : 
      61          73 :         return NT_STATUS_OK;
      62             : }
      63             : 
      64             : 
      65         145 : NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint8_t *v)
      66             : {
      67         145 :         TDR_PULL_NEED_BYTES(tdr, 1);
      68         145 :         *v = TDR_CVAL(tdr, tdr->offset);
      69         145 :         tdr->offset += 1;
      70         145 :         return NT_STATUS_OK;
      71             : }
      72             : 
      73        8177 : NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v)
      74             : {
      75        8177 :         TDR_PUSH_NEED_BYTES(tdr, 1);
      76        8177 :         TDR_SCVAL(tdr, tdr->data.length, *v);
      77        8177 :         tdr->data.length += 1;
      78        8177 :         return NT_STATUS_OK;
      79             : }
      80             : 
      81           0 : NTSTATUS tdr_print_uint8(struct tdr_print *tdr, const char *name, uint8_t *v)
      82             : {
      83           0 :         tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v);
      84           0 :         return NT_STATUS_OK;
      85             : }
      86             : 
      87         167 : NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v)
      88             : {
      89         167 :         TDR_PULL_NEED_BYTES(tdr, 2);
      90         167 :         *v = TDR_SVAL(tdr, tdr->offset);
      91         167 :         tdr->offset += 2;
      92         167 :         return NT_STATUS_OK;
      93             : }
      94             : 
      95          44 : NTSTATUS tdr_pull_uint1632(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v)
      96             : {
      97          44 :         return tdr_pull_uint16(tdr, ctx, v);
      98             : }
      99             : 
     100         130 : NTSTATUS tdr_push_uint16(struct tdr_push *tdr, const uint16_t *v)
     101             : {
     102         130 :         TDR_PUSH_NEED_BYTES(tdr, 2);
     103         130 :         TDR_SSVAL(tdr, tdr->data.length, *v);
     104         130 :         tdr->data.length += 2;
     105         130 :         return NT_STATUS_OK;
     106             : }
     107             : 
     108          33 : NTSTATUS tdr_push_uint1632(struct tdr_push *tdr, const uint16_t *v)
     109             : {
     110          33 :         return tdr_push_uint16(tdr, v);
     111             : }
     112             : 
     113           0 : NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v)
     114             : {
     115           0 :         tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v);
     116           0 :         return NT_STATUS_OK;
     117             : }
     118             : 
     119         768 : NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint32_t *v)
     120             : {
     121         768 :         TDR_PULL_NEED_BYTES(tdr, 4);
     122         768 :         *v = TDR_IVAL(tdr, tdr->offset);
     123         768 :         tdr->offset += 4;
     124         768 :         return NT_STATUS_OK;
     125             : }
     126             : 
     127        1036 : NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint32_t *v)
     128             : {
     129        1036 :         TDR_PUSH_NEED_BYTES(tdr, 4);
     130        1036 :         TDR_SIVAL(tdr, tdr->data.length, *v);
     131        1036 :         tdr->data.length += 4;
     132        1036 :         return NT_STATUS_OK;
     133             : }
     134             : 
     135           0 : NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v)
     136             : {
     137           0 :         tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v);
     138           0 :         return NT_STATUS_OK;
     139             : }
     140             : 
     141         120 : NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, TALLOC_CTX *ctx, const char **v, uint32_t length, uint32_t el_size, charset_t chset)
     142             : {
     143         120 :         size_t ret;
     144             : 
     145         120 :         if (length == -1) {
     146           1 :                 switch (chset) {
     147           1 :                         case CH_DOS:
     148           1 :                                 length = ascii_len_n((const char*)tdr->data.data+tdr->offset, tdr->data.length-tdr->offset);
     149           1 :                                 break;
     150           0 :                         case CH_UTF16:
     151           0 :                                 length = utf16_null_terminated_len_n(tdr->data.data+tdr->offset, tdr->data.length-tdr->offset);
     152           0 :                                 break;
     153             : 
     154           0 :                         default:
     155           0 :                                 return NT_STATUS_INVALID_PARAMETER;
     156             :                 }
     157             :         }
     158             : 
     159         120 :         if (length == 0) {
     160           1 :                 *v = talloc_strdup(ctx, "");
     161           1 :                 return NT_STATUS_OK;
     162             :         }
     163             : 
     164         119 :         TDR_PULL_NEED_BYTES(tdr, el_size*length);
     165             : 
     166         119 :         if (!convert_string_talloc(ctx, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, v, &ret)) {
     167           0 :                 return NT_STATUS_INVALID_PARAMETER;
     168             :         }
     169             : 
     170         119 :         tdr->offset += length * el_size;
     171             : 
     172         119 :         return NT_STATUS_OK;
     173             : }
     174             : 
     175         102 : NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, uint32_t el_size, charset_t chset)
     176             : {
     177         102 :         size_t required, size = 0;
     178         102 :         bool ret;
     179             : 
     180         102 :         if (length == -1) {
     181           1 :                 length = strlen(*v) + 1; /* Extra element for null character */
     182             :         }
     183             : 
     184         102 :         required = el_size * length;
     185         102 :         TDR_PUSH_NEED_BYTES(tdr, required);
     186             : 
     187         102 :         ret = convert_string(CH_UNIX, chset, *v, strlen(*v), tdr->data.data+tdr->data.length, required, &size);
     188         102 :         if (ret == false) {
     189           0 :                 return NT_STATUS_INVALID_PARAMETER;
     190             :         }
     191             : 
     192             :         /* Make sure the remaining part of the string is filled with zeroes */
     193         102 :         if (size < required) {
     194           5 :                 memset(tdr->data.data+tdr->data.length+size, 0, required-size);
     195             :         }
     196             : 
     197         102 :         tdr->data.length += required;
     198             : 
     199         102 :         return NT_STATUS_OK;
     200             : }
     201             : 
     202           0 : NTSTATUS tdr_print_charset(struct tdr_print *tdr, const char *name, const char **v, uint32_t length, uint32_t el_size, charset_t chset)
     203             : {
     204           0 :         tdr->print(tdr, "%-25s: %s", name, *v);
     205           0 :         return NT_STATUS_OK;
     206             : }
     207             : 
     208             : /**
     209             :   parse a hyper
     210             : */
     211          44 : NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint64_t *v)
     212             : {
     213          44 :         TDR_PULL_NEED_BYTES(tdr, 8);
     214          44 :         *v = TDR_IVAL(tdr, tdr->offset);
     215          44 :         *v |= (uint64_t)(TDR_IVAL(tdr, tdr->offset+4)) << 32;
     216          44 :         tdr->offset += 8;
     217          44 :         return NT_STATUS_OK;
     218             : }
     219             : 
     220             : /**
     221             :   push a hyper
     222             : */
     223          39 : NTSTATUS tdr_push_hyper(struct tdr_push *tdr, uint64_t *v)
     224             : {
     225          39 :         TDR_PUSH_NEED_BYTES(tdr, 8);
     226          39 :         TDR_SIVAL(tdr, tdr->data.length, ((*v) & 0xFFFFFFFF));
     227          39 :         TDR_SIVAL(tdr, tdr->data.length+4, ((*v)>>32));
     228          39 :         tdr->data.length += 8;
     229          39 :         return NT_STATUS_OK;
     230             : }
     231             : 
     232             : /**
     233             :   push a NTTIME
     234             : */
     235          39 : NTSTATUS tdr_push_NTTIME(struct tdr_push *tdr, NTTIME *t)
     236             : {
     237          39 :         TDR_CHECK(tdr_push_hyper(tdr, t));
     238          39 :         return NT_STATUS_OK;
     239             : }
     240             : 
     241             : /**
     242             :   pull a NTTIME
     243             : */
     244          44 : NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, TALLOC_CTX *ctx, NTTIME *t)
     245             : {
     246          44 :         TDR_CHECK(tdr_pull_hyper(tdr, ctx, t));
     247          44 :         return NT_STATUS_OK;
     248             : }
     249             : 
     250             : /**
     251             :   push a time_t
     252             : */
     253           0 : NTSTATUS tdr_push_time_t(struct tdr_push *tdr, time_t *t)
     254             : {
     255           0 :         return tdr_push_uint32(tdr, (uint32_t *)t);
     256             : }
     257             : 
     258             : /**
     259             :   pull a time_t
     260             : */
     261           0 : NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, TALLOC_CTX *ctx, time_t *t)
     262             : {
     263           0 :         uint32_t tt;
     264           0 :         TDR_CHECK(tdr_pull_uint32(tdr, ctx, &tt));
     265           0 :         *t = tt;
     266           0 :         return NT_STATUS_OK;
     267             : }
     268             : 
     269           0 : NTSTATUS tdr_print_time_t(struct tdr_print *tdr, const char *name, time_t *t)
     270             : {
     271           0 :         if (*t == (time_t)-1 || *t == 0) {
     272           0 :                 tdr->print(tdr, "%-25s: (time_t)%d", name, (int)*t);
     273             :         } else {
     274           0 :                 tdr->print(tdr, "%-25s: %s", name, timestring(tdr, *t));
     275             :         }
     276             : 
     277           0 :         return NT_STATUS_OK;
     278             : }
     279             : 
     280           0 : NTSTATUS tdr_print_NTTIME(struct tdr_print *tdr, const char *name, NTTIME *t)
     281             : {
     282           0 :         tdr->print(tdr, "%-25s: %s", name, nt_time_string(tdr, *t));
     283             : 
     284           0 :         return NT_STATUS_OK;
     285             : }
     286             : 
     287           0 : NTSTATUS tdr_print_DATA_BLOB(struct tdr_print *tdr, const char *name, DATA_BLOB *r)
     288             : {
     289           0 :         tdr->print(tdr, "%-25s: DATA_BLOB length=%u", name, r->length);
     290           0 :         if (r->length) {
     291           0 :                 dump_data(10, r->data, r->length);
     292             :         }
     293             : 
     294           0 :         return NT_STATUS_OK;
     295             : }
     296             : 
     297             : #define TDR_ALIGN(l,n) (((l) & ((n)-1)) == 0?0:((n)-((l)&((n)-1))))
     298             : 
     299             : /*
     300             :   push a DATA_BLOB onto the wire.
     301             : */
     302           0 : NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob)
     303             : {
     304           0 :         if (tdr->flags & TDR_ALIGN2) {
     305           0 :                 blob->length = TDR_ALIGN(tdr->data.length, 2);
     306           0 :         } else if (tdr->flags & TDR_ALIGN4) {
     307           0 :                 blob->length = TDR_ALIGN(tdr->data.length, 4);
     308           0 :         } else if (tdr->flags & TDR_ALIGN8) {
     309           0 :                 blob->length = TDR_ALIGN(tdr->data.length, 8);
     310             :         }
     311             : 
     312           0 :         TDR_PUSH_NEED_BYTES(tdr, blob->length);
     313             : 
     314           0 :         memcpy(tdr->data.data+tdr->data.length, blob->data, blob->length);
     315           0 :         return NT_STATUS_OK;
     316             : }
     317             : 
     318             : /*
     319             :   pull a DATA_BLOB from the wire.
     320             : */
     321           0 : NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, TALLOC_CTX *ctx, DATA_BLOB *blob)
     322             : {
     323           0 :         uint32_t length;
     324             : 
     325           0 :         if (tdr->flags & TDR_ALIGN2) {
     326           0 :                 length = TDR_ALIGN(tdr->offset, 2);
     327           0 :         } else if (tdr->flags & TDR_ALIGN4) {
     328           0 :                 length = TDR_ALIGN(tdr->offset, 4);
     329           0 :         } else if (tdr->flags & TDR_ALIGN8) {
     330           0 :                 length = TDR_ALIGN(tdr->offset, 8);
     331           0 :         } else if (tdr->flags & TDR_REMAINING) {
     332           0 :                 length = tdr->data.length - tdr->offset;
     333             :         } else {
     334           0 :                 return NT_STATUS_INVALID_PARAMETER;
     335             :         }
     336             : 
     337           0 :         if (tdr->data.length - tdr->offset < length) {
     338           0 :                 length = tdr->data.length - tdr->offset;
     339             :         }
     340             : 
     341           0 :         TDR_PULL_NEED_BYTES(tdr, length);
     342             : 
     343           0 :         *blob = data_blob_talloc(tdr, tdr->data.data+tdr->offset, length);
     344           0 :         tdr->offset += length;
     345           0 :         return NT_STATUS_OK;
     346             : }
     347             : 
     348          89 : struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx)
     349             : {
     350          89 :         struct tdr_push *push = talloc_zero(mem_ctx, struct tdr_push);
     351             : 
     352          89 :         if (push == NULL)
     353           0 :                 return NULL;
     354             : 
     355           0 :         return push;
     356             : }
     357             : 
     358          73 : struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx)
     359             : {
     360          73 :         struct tdr_pull *pull = talloc_zero(mem_ctx, struct tdr_pull);
     361             : 
     362          73 :         if (pull == NULL)
     363           0 :                 return NULL;
     364             : 
     365           0 :         return pull;
     366             : }
     367             : 
     368           4 : NTSTATUS tdr_push_to_fd(int fd, tdr_push_fn_t push_fn, const void *p)
     369             : {
     370           4 :         struct tdr_push *push = tdr_push_init(NULL);
     371             : 
     372           4 :         if (push == NULL)
     373           0 :                 return NT_STATUS_NO_MEMORY;
     374             : 
     375           4 :         if (NT_STATUS_IS_ERR(push_fn(push, p))) {
     376           0 :                 DEBUG(1, ("Error pushing data\n"));
     377           0 :                 talloc_free(push);
     378           0 :                 return NT_STATUS_UNSUCCESSFUL;
     379             :         }
     380             : 
     381           4 :         if (write(fd, push->data.data, push->data.length) < push->data.length) {
     382           0 :                 DEBUG(1, ("Error writing all data\n"));
     383           0 :                 return NT_STATUS_UNSUCCESSFUL;
     384             :         }
     385             : 
     386           4 :         talloc_free(push);
     387             : 
     388           4 :         return NT_STATUS_OK;
     389             : }
     390             : 
     391           0 : void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...)
     392             : {
     393           0 :         va_list ap;
     394           0 :         char *s = NULL;
     395           0 :         int i, ret;
     396             : 
     397           0 :         va_start(ap, format);
     398           0 :         ret = vasprintf(&s, format, ap);
     399           0 :         va_end(ap);
     400             : 
     401           0 :         if (ret == -1) {
     402           0 :                 return;
     403             :         }
     404             : 
     405           0 :         for (i=0;i<tdr->level;i++) { DEBUG(0,("    ")); }
     406             : 
     407           0 :         DEBUG(0,("%s\n", s));
     408           0 :         free(s);
     409             : }

Generated by: LCOV version 1.14