LCOV - code coverage report
Current view: top level - libcli/auth - msrpc_parse.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 185 253 73.1 %
Date: 2024-02-29 22:57:05 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    simple kerberos5/SPNEGO routines
       4             :    Copyright (C) Andrew Tridgell 2001
       5             :    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
       6             :    Copyright (C) Andrew Bartlett 2002-2003
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libcli/auth/msrpc_parse.h"
      24             : 
      25             : /*
      26             :   this is a tiny msrpc packet generator. I am only using this to
      27             :   avoid tying this code to a particular variant of our rpc code. This
      28             :   generator is not general enough for all our rpc needs, its just
      29             :   enough for the spnego/ntlmssp code
      30             : 
      31             :   format specifiers are:
      32             : 
      33             :   U = unicode string (input is unix string)
      34             :   a = address (input is char *unix_string)
      35             :       (1 byte type, 1 byte length, unicode/ASCII string, all inline)
      36             :   A = ASCII string (input is unix string)
      37             :   B = data blob (pointer + length)
      38             :   b = data blob in header (pointer + length)
      39             :   D
      40             :   d = word (4 bytes)
      41             :   C = constant ascii string
      42             :  */
      43      167786 : NTSTATUS msrpc_gen(TALLOC_CTX *mem_ctx, 
      44             :                DATA_BLOB *blob,
      45             :                const char *format, ...)
      46             : {
      47        1404 :         int i, j;
      48        1404 :         bool ret;
      49        1404 :         va_list ap;
      50        1404 :         char *s;
      51        1404 :         uint8_t *b;
      52      167786 :         int head_size=0, data_size=0;
      53        1404 :         int head_ofs, data_ofs;
      54        1404 :         int *intargs;
      55        1404 :         size_t n;
      56             : 
      57        1404 :         DATA_BLOB *pointers;
      58             : 
      59      167786 :         pointers = talloc_array(mem_ctx, DATA_BLOB, strlen(format));
      60      167786 :         if (!pointers) {
      61           0 :                 return NT_STATUS_NO_MEMORY;
      62             :         }
      63      167786 :         intargs = talloc_array(pointers, int, strlen(format));
      64      167786 :         if (!intargs) {
      65           0 :                 return NT_STATUS_NO_MEMORY;
      66             :         }
      67             : 
      68             :         /* first scan the format to work out the header and body size */
      69      167786 :         va_start(ap, format);
      70     1455630 :         for (i=0; format[i]; i++) {
      71     1287844 :                 switch (format[i]) {
      72      152941 :                 case 'U':
      73      152941 :                         s = va_arg(ap, char *);
      74      152941 :                         head_size += 8;
      75      153533 :                         ret = push_ucs2_talloc(
      76             :                                 pointers,
      77      152941 :                                 (smb_ucs2_t **)(void *)&pointers[i].data,
      78             :                                 s, &n);
      79      152941 :                         if (!ret) {
      80           0 :                                 va_end(ap);
      81           0 :                                 return map_nt_error_from_unix_common(errno);
      82             :                         }
      83      152941 :                         pointers[i].length = n;
      84      152941 :                         pointers[i].length -= 2;
      85      152941 :                         data_size += pointers[i].length;
      86     1279795 :                         break;
      87       78694 :                 case 'A':
      88       78694 :                         s = va_arg(ap, char *);
      89       78694 :                         head_size += 8;
      90       79286 :                         ret = push_ascii_talloc(
      91       78694 :                                 pointers, (char **)(void *)&pointers[i].data,
      92             :                                 s, &n);
      93       78694 :                         if (!ret) {
      94           0 :                                 va_end(ap);
      95           0 :                                 return map_nt_error_from_unix_common(errno);
      96             :                         }
      97       78694 :                         pointers[i].length = n;
      98       78694 :                         pointers[i].length -= 1;
      99       78694 :                         data_size += pointers[i].length;
     100       78694 :                         break;
     101       17909 :                 case 'a':
     102       17909 :                         j = va_arg(ap, int);
     103       17909 :                         intargs[i] = j;
     104       17909 :                         s = va_arg(ap, char *);
     105       18850 :                         ret = push_ucs2_talloc(
     106             :                                 pointers,
     107       17909 :                                 (smb_ucs2_t **)(void *)&pointers[i].data,
     108             :                                 s, &n);
     109       17909 :                         if (!ret) {
     110           0 :                                 va_end(ap);
     111           0 :                                 return map_nt_error_from_unix_common(errno);
     112             :                         }
     113       17909 :                         pointers[i].length = n;
     114       17909 :                         pointers[i].length -= 2;
     115       17909 :                         data_size += pointers[i].length + 4;
     116       17909 :                         break;
     117      152941 :                 case 'B':
     118      152941 :                         b = va_arg(ap, uint8_t *);
     119      152941 :                         head_size += 8;
     120      152941 :                         pointers[i].data = b;
     121      152941 :                         pointers[i].length = va_arg(ap, int);
     122      152941 :                         data_size += pointers[i].length;
     123      152941 :                         break;
     124      320455 :                 case 'b':
     125      320455 :                         b = va_arg(ap, uint8_t *);
     126      320455 :                         pointers[i].data = b;
     127      320455 :                         pointers[i].length = va_arg(ap, int);
     128      320455 :                         head_size += pointers[i].length;
     129      320455 :                         break;
     130      449182 :                 case 'd':
     131      449182 :                         j = va_arg(ap, int);
     132      449182 :                         intargs[i] = j;
     133      449182 :                         head_size += 4;
     134      449182 :                         break;
     135      115722 :                 case 'C':
     136      115722 :                         s = va_arg(ap, char *);
     137      115722 :                         pointers[i].data = (uint8_t *)s;
     138      115722 :                         pointers[i].length = strlen(s)+1;
     139      115722 :                         head_size += pointers[i].length;
     140      115722 :                         break;
     141           0 :                 default:
     142           0 :                         va_end(ap);
     143           0 :                         return NT_STATUS_INVALID_PARAMETER;
     144             :                 }
     145             :         }
     146      167786 :         va_end(ap);
     147             : 
     148      167786 :         if (head_size + data_size == 0) {
     149           0 :                 return NT_STATUS_INVALID_PARAMETER;
     150             :         }
     151             : 
     152             :         /* allocate the space, then scan the format again to fill in the values */
     153      167786 :         *blob = data_blob_talloc(mem_ctx, NULL, head_size + data_size);
     154      167786 :         if (!blob->data) {
     155           0 :                 return NT_STATUS_NO_MEMORY;
     156             :         }
     157      167786 :         head_ofs = 0;
     158      167786 :         data_ofs = head_size;
     159             : 
     160      167786 :         va_start(ap, format);
     161     1455630 :         for (i=0; format[i]; i++) {
     162     1287844 :                 switch (format[i]) {
     163      384576 :                 case 'U':
     164             :                 case 'A':
     165             :                 case 'B':
     166      384576 :                         n = pointers[i].length;
     167      384576 :                         SSVAL(blob->data, head_ofs, n); head_ofs += 2;
     168      384576 :                         SSVAL(blob->data, head_ofs, n); head_ofs += 2;
     169      384576 :                         SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
     170      384576 :                         if (pointers[i].data && n) /* don't follow null pointers... */
     171      301052 :                                 memcpy(blob->data+data_ofs, pointers[i].data, n);
     172      384576 :                         data_ofs += n;
     173     1280979 :                         break;
     174       17909 :                 case 'a':
     175       17909 :                         j = intargs[i];
     176       17909 :                         SSVAL(blob->data, data_ofs, j); data_ofs += 2;
     177             : 
     178       17909 :                         n = pointers[i].length;
     179       17909 :                         SSVAL(blob->data, data_ofs, n); data_ofs += 2;
     180       17909 :                         memcpy(blob->data+data_ofs, pointers[i].data, n);
     181       17909 :                         data_ofs += n;
     182       17909 :                         break;
     183      449182 :                 case 'd':
     184      449182 :                         j = intargs[i];
     185      449182 :                         SIVAL(blob->data, head_ofs, j); 
     186      449182 :                         head_ofs += 4;
     187      449182 :                         break;
     188      320455 :                 case 'b':
     189      320455 :                         n = pointers[i].length;
     190      320455 :                         if (pointers[i].data && n) {
     191             :                                 /* don't follow null pointers... */
     192      320455 :                                 memcpy(blob->data + head_ofs, pointers[i].data, n);
     193             :                         }
     194      320455 :                         head_ofs += n;
     195      320455 :                         break;
     196      115722 :                 case 'C':
     197      115722 :                         n = pointers[i].length;
     198      115722 :                         memcpy(blob->data + head_ofs, pointers[i].data, n);
     199      115722 :                         head_ofs += n;
     200      115722 :                         break;
     201           0 :                 default:
     202           0 :                         va_end(ap);
     203           0 :                         return NT_STATUS_INVALID_PARAMETER;
     204             :                 }
     205             :         }
     206      167786 :         va_end(ap);
     207             :         
     208      167786 :         talloc_free(pointers);
     209             : 
     210      167786 :         return NT_STATUS_OK;
     211             : }
     212             : 
     213             : 
     214             : /* a helpful macro to avoid running over the end of our blob */
     215             : #define NEED_DATA(amount) \
     216             : if ((head_ofs + amount) > blob->length) { \
     217             :         va_end(ap); \
     218             :         return false; \
     219             : }
     220             : 
     221             : /**
     222             :   this is a tiny msrpc packet parser. This the the partner of msrpc_gen
     223             : 
     224             :   format specifiers are:
     225             : 
     226             :   U = unicode string (output is unix string)
     227             :   A = ascii string
     228             :   B = data blob
     229             :   b = data blob in header
     230             :   d = word (4 bytes)
     231             :   C = constant ascii string
     232             :  */
     233             : 
     234      267527 : bool msrpc_parse(TALLOC_CTX *mem_ctx, 
     235             :                  const DATA_BLOB *blob,
     236             :                  const char *format, ...)
     237             : {
     238        1036 :         int i;
     239        1036 :         va_list ap;
     240        1036 :         char **ps, *s;
     241        1036 :         DATA_BLOB *b;
     242      267527 :         size_t head_ofs = 0;
     243        1036 :         uint16_t len1, len2;
     244        1036 :         uint32_t ptr;
     245        1036 :         uint32_t *v;
     246      267527 :         bool ret = true;
     247             : 
     248      267527 :         va_start(ap, format);
     249     1489908 :         for (i=0; format[i]; i++) {
     250     1222381 :                 switch (format[i]) {
     251      152336 :                 case 'U':
     252      152336 :                         NEED_DATA(8);
     253      152336 :                         len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
     254      152336 :                         len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
     255      152336 :                         ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
     256             : 
     257      152336 :                         ps = va_arg(ap, char **);
     258      152336 :                         if (len1 == 0 && len2 == 0) {
     259        3058 :                                 *ps = talloc_strdup(mem_ctx, "");
     260        3058 :                                 if (*ps == NULL) {
     261           0 :                                         ret = false;
     262           0 :                                         goto cleanup;
     263             :                                 }
     264             :                         } else {
     265             :                                 /* make sure its in the right format - be strict */
     266      149278 :                                 if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) {
     267           0 :                                         ret = false;
     268           0 :                                         goto cleanup;
     269             :                                 }
     270      149278 :                                 if (len1 & 1) {
     271             :                                         /* if odd length and unicode */
     272           0 :                                         ret = false;
     273           0 :                                         goto cleanup;
     274             :                                 }
     275      149278 :                                 if (blob->data + ptr < (uint8_t *)(uintptr_t)ptr ||
     276             :                                                 blob->data + ptr < blob->data) {
     277           0 :                                         ret = false;
     278           0 :                                         goto cleanup;
     279             :                                 }
     280             : 
     281      149278 :                                 if (0 < len1) {
     282         556 :                                         size_t pull_len;
     283      149278 :                                         if (!convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, 
     284      148722 :                                                                    blob->data + ptr, len1, 
     285             :                                                                    ps, &pull_len)) {
     286           0 :                                                 ret = false;
     287           0 :                                                 goto cleanup;
     288             :                                         }
     289             :                                 } else {
     290           0 :                                         *ps = talloc_strdup(mem_ctx, "");
     291           0 :                                         if (*ps == NULL) {
     292           0 :                                                 ret = false;
     293           0 :                                                 goto cleanup;
     294             :                                         }
     295             :                                 }
     296             :                         }
     297      151744 :                         break;
     298           0 :                 case 'A':
     299           0 :                         NEED_DATA(8);
     300           0 :                         len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
     301           0 :                         len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
     302           0 :                         ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
     303             : 
     304           0 :                         ps = (char **)va_arg(ap, char **);
     305             :                         /* make sure its in the right format - be strict */
     306           0 :                         if (len1 == 0 && len2 == 0) {
     307           0 :                                 *ps = talloc_strdup(mem_ctx, "");
     308           0 :                                 if (*ps == NULL) {
     309           0 :                                         ret = false;
     310           0 :                                         goto cleanup;
     311             :                                 }
     312             :                         } else {
     313           0 :                                 if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) {
     314           0 :                                         ret = false;
     315           0 :                                         goto cleanup;
     316             :                                 }
     317             : 
     318           0 :                                 if (blob->data + ptr < (uint8_t *)(uintptr_t)ptr ||
     319             :                                                 blob->data + ptr < blob->data) {
     320           0 :                                         ret = false;
     321           0 :                                         goto cleanup;
     322             :                                 }
     323             : 
     324           0 :                                 if (0 < len1) {
     325           0 :                                         size_t pull_len;
     326             : 
     327           0 :                                         if (!convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, 
     328           0 :                                                                    blob->data + ptr, len1, 
     329             :                                                                    ps, &pull_len)) {
     330           0 :                                                 ret = false;
     331           0 :                                                 goto cleanup;
     332             :                                         }
     333             :                                 } else {
     334           0 :                                         *ps = talloc_strdup(mem_ctx, "");
     335           0 :                                         if (*ps == NULL) {
     336           0 :                                                 ret = false;
     337           0 :                                                 goto cleanup;
     338             :                                         }
     339             :                                 }
     340             :                         }
     341           0 :                         break;
     342      190771 :                 case 'B':
     343      190771 :                         NEED_DATA(8);
     344      190771 :                         len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
     345      190771 :                         len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
     346      190771 :                         ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
     347             : 
     348      190771 :                         b = (DATA_BLOB *)va_arg(ap, void *);
     349      190771 :                         if (len1 == 0 && len2 == 0) {
     350        1978 :                                 *b = data_blob_talloc(mem_ctx, NULL, 0);
     351             :                         } else {
     352             :                                 /* make sure its in the right format - be strict */
     353      188793 :                                 if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) {
     354           0 :                                         ret = false;
     355           0 :                                         goto cleanup;
     356             :                                 }
     357             : 
     358      188793 :                                 if (blob->data + ptr < (uint8_t *)(uintptr_t)ptr ||
     359             :                                                 blob->data + ptr < blob->data) {
     360           0 :                                         ret = false;
     361           0 :                                         goto cleanup;
     362             :                                 }
     363             : 
     364      188793 :                                 *b = data_blob_talloc(mem_ctx, blob->data + ptr, len1);
     365             :                         }
     366      190031 :                         break;
     367      114369 :                 case 'b':
     368      114369 :                         b = (DATA_BLOB *)va_arg(ap, void *);
     369      114369 :                         len1 = va_arg(ap, unsigned int);
     370             :                         /* make sure its in the right format - be strict */
     371      114369 :                         NEED_DATA(len1);
     372      114369 :                         if (blob->data + head_ofs < (uint8_t *)head_ofs ||
     373      114369 :                                         blob->data + head_ofs < blob->data) {
     374           0 :                                 ret = false;
     375           0 :                                 goto cleanup;
     376             :                         }
     377             : 
     378      114369 :                         *b = data_blob_talloc(mem_ctx, blob->data + head_ofs, len1);
     379      114369 :                         head_ofs += len1;
     380      114369 :                         break;
     381      497378 :                 case 'd':
     382      497378 :                         v = va_arg(ap, uint32_t *);
     383      497378 :                         NEED_DATA(4);
     384      497378 :                         *v = IVAL(blob->data, head_ofs); head_ofs += 4;
     385      497378 :                         break;
     386      267527 :                 case 'C':
     387      267527 :                         s = va_arg(ap, char *);
     388             : 
     389      267527 :                         if (blob->data + head_ofs < (uint8_t *)head_ofs ||
     390      267527 :                                         blob->data + head_ofs < blob->data ||
     391      267527 :                             (head_ofs + (strlen(s) + 1)) > blob->length) {
     392           0 :                                 ret = false;
     393           0 :                                 goto cleanup;
     394             :                         }
     395             : 
     396      267527 :                         if (memcmp(blob->data + head_ofs, s, strlen(s)+1) != 0) {
     397           0 :                                 ret = false;
     398           0 :                                 goto cleanup;
     399             :                         }
     400      266491 :                         head_ofs += (strlen(s) + 1);
     401             : 
     402      266491 :                         break;
     403             :                 }
     404             :         }
     405             : 
     406      267527 : cleanup:
     407      267527 :         va_end(ap);
     408      267527 :         return ret;
     409             : }

Generated by: LCOV version 1.14