LCOV - code coverage report
Current view: top level - libcli/smb - reparse_symlink.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 39 92 42.4 %
Date: 2024-06-13 04:01:37 Functions: 1 2 50.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  *
       4             :  * Implementation of
       5             :  * http://msdn.microsoft.com/en-us/library/cc232006%28v=PROT.13%29.aspx
       6             :  *
       7             :  * Copyright (C) Volker Lendecke 2011
       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 "replace.h"
      24             : #include "reparse_symlink.h"
      25             : #include "lib/util/charset/charset.h"
      26             : #include "lib/util/byteorder.h"
      27             : #include "libcli/smb/smb_constants.h"
      28             : #include "libcli/smb/smb_util.h"
      29             : #include "lib/util/debug.h"
      30             : 
      31           4 : bool symlink_reparse_buffer_marshall(
      32             :         const char *substitute, const char *printname, uint32_t flags,
      33             :         TALLOC_CTX *mem_ctx, uint8_t **pdst, size_t *pdstlen)
      34             : {
      35           4 :         uint8_t *dst = NULL;
      36             :         size_t dst_len;
      37           4 :         uint8_t *subst_utf16 = NULL;
      38           4 :         uint8_t *print_utf16 = NULL;
      39           4 :         size_t subst_len = 0;
      40           4 :         size_t print_len = 0;
      41           4 :         bool ret = false;
      42             :         bool ok;
      43             : 
      44           4 :         if (substitute == NULL) {
      45           0 :                 return false;
      46             :         }
      47           4 :         if (printname == NULL) {
      48           4 :                 printname = substitute;
      49             :         }
      50             : 
      51           4 :         ok = convert_string_talloc(
      52             :                 mem_ctx,
      53             :                 CH_UNIX,
      54             :                 CH_UTF16,
      55             :                 substitute,
      56             :                 strlen(substitute),
      57             :                 &subst_utf16,
      58             :                 &subst_len);
      59           4 :         if (!ok) {
      60           0 :                 goto fail;
      61             :         }
      62             : 
      63           4 :         ok = convert_string_talloc(
      64             :                 mem_ctx,
      65             :                 CH_UNIX,
      66             :                 CH_UTF16,
      67             :                 printname,
      68             :                 strlen(printname),
      69             :                 &print_utf16,
      70             :                 &print_len);
      71           4 :         if (!ok) {
      72           0 :                 goto fail;
      73             :         }
      74             : 
      75           4 :         dst_len = subst_len + 20;
      76           4 :         if (dst_len < 20) {
      77           0 :                 goto fail;
      78             :         }
      79           4 :         dst_len += print_len;
      80           4 :         if (dst_len < print_len) {
      81           0 :                 goto fail;
      82             :         }
      83           4 :         dst = talloc_array(mem_ctx, uint8_t, dst_len);
      84           4 :         if (dst == NULL) {
      85           0 :                 goto fail;
      86             :         }
      87             : 
      88           4 :         SIVAL(dst, 0, IO_REPARSE_TAG_SYMLINK);     /* ReparseTag */
      89           4 :         SSVAL(dst, 4, 12 + subst_len + print_len); /* ReparseDataLength */
      90           4 :         SSVAL(dst, 6, 0);                          /* Reserved */
      91           4 :         SSVAL(dst, 8, 0);                          /* SubstituteNameOffset */
      92           4 :         SSVAL(dst, 10, subst_len);                 /* SubstituteNameLength */
      93           4 :         SSVAL(dst, 12, subst_len);                 /* PrintNameOffset */
      94           4 :         SSVAL(dst, 14, print_len);                 /* PrintNameLength */
      95           4 :         SIVAL(dst, 16, flags);                     /* Flags */
      96             : 
      97           4 :         if ((subst_utf16 != NULL) && (subst_len != 0)) {
      98           4 :                 memcpy(dst + 20, subst_utf16, subst_len);
      99             :         }
     100             : 
     101           4 :         if ((print_utf16 != NULL) && (print_len != 0)) {
     102           4 :                 memcpy(dst + 20 + subst_len, print_utf16, print_len);
     103             :         }
     104             : 
     105           4 :         *pdst = dst;
     106           4 :         *pdstlen = dst_len;
     107           4 :         ret = true;
     108             : 
     109           4 : fail:
     110           4 :         TALLOC_FREE(subst_utf16);
     111           4 :         TALLOC_FREE(print_utf16);
     112           4 :         return ret;
     113             : }
     114             : 
     115           0 : struct symlink_reparse_struct *symlink_reparse_buffer_parse(
     116             :         TALLOC_CTX *mem_ctx, const uint8_t *src, size_t srclen)
     117             : {
     118           0 :         struct symlink_reparse_struct *result = NULL;
     119             :         uint16_t reparse_data_length;
     120             :         uint16_t substitute_name_offset, substitute_name_length;
     121             :         uint16_t print_name_offset, print_name_length;
     122             :         bool ok;
     123             : 
     124           0 :         if (srclen < 20) {
     125           0 :                 DBG_DEBUG("srclen = %zu, expected >= 20\n", srclen);
     126           0 :                 goto fail;
     127             :         }
     128           0 :         if (IVAL(src, 0) != IO_REPARSE_TAG_SYMLINK) {
     129           0 :                 DBG_DEBUG("Got ReparseTag %8.8x, expected %8.8x\n",
     130             :                           IVAL(src, 0),
     131             :                           IO_REPARSE_TAG_SYMLINK);
     132           0 :                 goto fail;
     133             :         }
     134             : 
     135           0 :         reparse_data_length     = SVAL(src, 4);
     136           0 :         substitute_name_offset  = SVAL(src, 8);
     137           0 :         substitute_name_length  = SVAL(src, 10);
     138           0 :         print_name_offset       = SVAL(src, 12);
     139           0 :         print_name_length       = SVAL(src, 14);
     140             : 
     141           0 :         if (reparse_data_length < 12) {
     142           0 :                 DBG_DEBUG("reparse_data_length = %"PRIu16", expected >= 12\n",
     143             :                           reparse_data_length);
     144           0 :                 goto fail;
     145             :         }
     146           0 :         if (smb_buffer_oob(srclen - 8, reparse_data_length, 0)) {
     147           0 :                 DBG_DEBUG("reparse_data_length (%"PRIu16") too large for "
     148             :                            "src_len (%zu)\n",
     149             :                           reparse_data_length,
     150             :                           srclen);
     151           0 :                 goto fail;
     152             :         }
     153           0 :         if (smb_buffer_oob(reparse_data_length - 12, substitute_name_offset,
     154             :                            substitute_name_length)) {
     155           0 :                 DBG_DEBUG("substitute_name (%"PRIu16"/%"PRIu16") does not fit "
     156             :                           "in reparse_data_length (%"PRIu16")\n",
     157             :                           substitute_name_offset,
     158             :                           substitute_name_length,
     159             :                           reparse_data_length - 12);
     160           0 :                 goto fail;
     161             :         }
     162           0 :         if (smb_buffer_oob(reparse_data_length - 12, print_name_offset,
     163             :                            print_name_length)) {
     164           0 :                 DBG_DEBUG("print_name (%"PRIu16"/%"PRIu16") does not fit in "
     165             :                           "reparse_data_length (%"PRIu16")\n",
     166             :                           print_name_offset,
     167             :                           print_name_length,
     168             :                           reparse_data_length - 12);
     169           0 :                 goto fail;
     170             :         }
     171             : 
     172           0 :         result = talloc_zero(mem_ctx, struct symlink_reparse_struct);
     173           0 :         if (result == NULL) {
     174           0 :                 DBG_DEBUG("talloc failed\n");
     175           0 :                 goto fail;
     176             :         }
     177             : 
     178           0 :         ok = convert_string_talloc(
     179             :                 result,
     180             :                 CH_UTF16,
     181             :                 CH_UNIX,
     182           0 :                 src + 20 + substitute_name_offset,
     183             :                 substitute_name_length,
     184           0 :                 &result->substitute_name,
     185             :                 NULL);
     186           0 :         if (!ok) {
     187           0 :                 DBG_DEBUG("convert_string_talloc for substitute_name "
     188             :                           "failed\n");
     189           0 :                 goto fail;
     190             :         }
     191             : 
     192           0 :         ok = convert_string_talloc(
     193             :                 result,
     194             :                 CH_UTF16,
     195             :                 CH_UNIX,
     196           0 :                 src + 20 + print_name_offset,
     197             :                 print_name_length,
     198           0 :                 &result->print_name,
     199             :                 NULL);
     200           0 :         if (!ok) {
     201           0 :                 DBG_DEBUG("convert_string_talloc for print_name failed\n");
     202           0 :                 goto fail;
     203             :         }
     204             : 
     205           0 :         result->unparsed_path_length = SVAL(src, 6);
     206           0 :         result->flags = IVAL(src, 16);
     207             : 
     208           0 :         return result;
     209           0 : fail:
     210           0 :         TALLOC_FREE(result);
     211           0 :         return NULL;
     212             : }

Generated by: LCOV version 1.13