LCOV - code coverage report
Current view: top level - libcli/smb - reparse_symlink.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 48 105 45.7 %
Date: 2024-02-14 10:14:15 Functions: 2 3 66.7 %

          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           8 : ssize_t reparse_buffer_marshall(
      32             :         uint32_t reparse_tag,
      33             :         uint16_t reserved,
      34             :         const struct iovec *iov,
      35             :         int iovlen,
      36             :         uint8_t *buf,
      37             :         size_t buflen)
      38             : {
      39           8 :         ssize_t reparse_data_length = iov_buflen(iov, iovlen);
      40             :         size_t needed;
      41             : 
      42           8 :         if (reparse_data_length == -1) {
      43           0 :                 return -1;
      44             :         }
      45           8 :         if (reparse_data_length > UINT16_MAX) {
      46           0 :                 return -1;
      47             :         }
      48             : 
      49           8 :         needed = reparse_data_length + 8;
      50           8 :         if (needed < reparse_data_length) {
      51           0 :                 return -1;
      52             :         }
      53             : 
      54           8 :         if (buflen >= needed) {
      55           4 :                 PUSH_LE_U32(buf, 0, reparse_tag);
      56           4 :                 PUSH_LE_U16(buf, 4, reparse_data_length);
      57           4 :                 PUSH_LE_U16(buf, 6, reserved);
      58           4 :                 iov_buf(iov, iovlen, buf+8, buflen-8);
      59             :         }
      60             : 
      61           8 :         return needed;
      62             : }
      63             : 
      64           4 : bool symlink_reparse_buffer_marshall(
      65             :         const char *substitute,
      66             :         const char *printname,
      67             :         uint16_t unparsed_path_length,
      68             :         uint32_t flags,
      69             :         TALLOC_CTX *mem_ctx,
      70             :         uint8_t **pdst,
      71             :         size_t *pdstlen)
      72             : {
      73             :         uint8_t sbuf[12];
      74             :         struct iovec iov[3];
      75           4 :         uint8_t *dst = NULL;
      76             :         ssize_t dst_len;
      77           4 :         uint8_t *subst_utf16 = NULL;
      78           4 :         uint8_t *print_utf16 = NULL;
      79           4 :         size_t subst_len = 0;
      80           4 :         size_t print_len = 0;
      81           4 :         bool ret = false;
      82             :         bool ok;
      83             : 
      84           4 :         if (substitute == NULL) {
      85           0 :                 return false;
      86             :         }
      87           4 :         if (printname == NULL) {
      88           4 :                 printname = substitute;
      89             :         }
      90             : 
      91           4 :         iov[0] = (struct iovec) { .iov_base = sbuf, .iov_len = sizeof(sbuf), };
      92             : 
      93           4 :         ok = convert_string_talloc(
      94             :                 mem_ctx,
      95             :                 CH_UNIX,
      96             :                 CH_UTF16,
      97             :                 substitute,
      98             :                 strlen(substitute),
      99             :                 &subst_utf16,
     100             :                 &subst_len);
     101           4 :         if (!ok) {
     102           0 :                 goto fail;
     103             :         }
     104           4 :         if (subst_len > UINT16_MAX) {
     105           0 :                 goto fail;
     106             :         }
     107           4 :         iov[1] = (struct iovec) {
     108             :                 .iov_base = subst_utf16, .iov_len = subst_len,
     109             :         };
     110             : 
     111           4 :         ok = convert_string_talloc(
     112             :                 mem_ctx,
     113             :                 CH_UNIX,
     114             :                 CH_UTF16,
     115             :                 printname,
     116             :                 strlen(printname),
     117             :                 &print_utf16,
     118             :                 &print_len);
     119           4 :         if (!ok) {
     120           0 :                 goto fail;
     121             :         }
     122           4 :         if (print_len > UINT16_MAX) {
     123           0 :                 goto fail;
     124             :         }
     125           4 :         iov[2] = (struct iovec) {
     126             :                 .iov_base = print_utf16, .iov_len = print_len,
     127             :         };
     128             : 
     129           4 :         PUSH_LE_U16(sbuf, 0, 0);         /* SubstituteNameOffset */
     130           4 :         PUSH_LE_U16(sbuf, 2, subst_len); /* SubstituteNameLength */
     131           4 :         PUSH_LE_U16(sbuf, 4, subst_len); /* PrintNameOffset */
     132           4 :         PUSH_LE_U16(sbuf, 6, print_len); /* PrintNameLength */
     133           4 :         PUSH_LE_U32(sbuf, 8, flags);     /* Flags */
     134             : 
     135           4 :         dst_len = reparse_buffer_marshall(
     136             :                 IO_REPARSE_TAG_SYMLINK,
     137             :                 unparsed_path_length,
     138             :                 iov,
     139             :                 ARRAY_SIZE(iov),
     140             :                 NULL,
     141             :                 0);
     142           4 :         if (dst_len == -1) {
     143           0 :                 goto fail;
     144             :         }
     145             : 
     146           4 :         dst = talloc_array(mem_ctx, uint8_t, dst_len);
     147           4 :         if (dst == NULL) {
     148           0 :                 goto fail;
     149             :         }
     150             : 
     151           4 :         reparse_buffer_marshall(
     152             :                 IO_REPARSE_TAG_SYMLINK,
     153             :                 unparsed_path_length,
     154             :                 iov,
     155             :                 ARRAY_SIZE(iov),
     156             :                 dst,
     157             :                 dst_len);
     158             : 
     159           4 :         *pdst = dst;
     160           4 :         *pdstlen = dst_len;
     161           4 :         ret = true;
     162             : 
     163           4 : fail:
     164           4 :         TALLOC_FREE(subst_utf16);
     165           4 :         TALLOC_FREE(print_utf16);
     166           4 :         return ret;
     167             : }
     168             : 
     169           0 : struct symlink_reparse_struct *symlink_reparse_buffer_parse(
     170             :         TALLOC_CTX *mem_ctx, const uint8_t *src, size_t srclen)
     171             : {
     172           0 :         struct symlink_reparse_struct *result = NULL;
     173             :         uint16_t reparse_data_length;
     174             :         uint16_t substitute_name_offset, substitute_name_length;
     175             :         uint16_t print_name_offset, print_name_length;
     176             :         bool ok;
     177             : 
     178           0 :         if (srclen < 20) {
     179           0 :                 DBG_DEBUG("srclen = %zu, expected >= 20\n", srclen);
     180           0 :                 goto fail;
     181             :         }
     182           0 :         if (IVAL(src, 0) != IO_REPARSE_TAG_SYMLINK) {
     183           0 :                 DBG_DEBUG("Got ReparseTag %8.8x, expected %8.8x\n",
     184             :                           IVAL(src, 0),
     185             :                           IO_REPARSE_TAG_SYMLINK);
     186           0 :                 goto fail;
     187             :         }
     188             : 
     189           0 :         reparse_data_length     = SVAL(src, 4);
     190           0 :         substitute_name_offset  = SVAL(src, 8);
     191           0 :         substitute_name_length  = SVAL(src, 10);
     192           0 :         print_name_offset       = SVAL(src, 12);
     193           0 :         print_name_length       = SVAL(src, 14);
     194             : 
     195           0 :         if (reparse_data_length < 12) {
     196           0 :                 DBG_DEBUG("reparse_data_length = %"PRIu16", expected >= 12\n",
     197             :                           reparse_data_length);
     198           0 :                 goto fail;
     199             :         }
     200           0 :         if (smb_buffer_oob(srclen - 8, reparse_data_length, 0)) {
     201           0 :                 DBG_DEBUG("reparse_data_length (%"PRIu16") too large for "
     202             :                            "src_len (%zu)\n",
     203             :                           reparse_data_length,
     204             :                           srclen);
     205           0 :                 goto fail;
     206             :         }
     207           0 :         if (smb_buffer_oob(reparse_data_length - 12, substitute_name_offset,
     208             :                            substitute_name_length)) {
     209           0 :                 DBG_DEBUG("substitute_name (%"PRIu16"/%"PRIu16") does not fit "
     210             :                           "in reparse_data_length (%"PRIu16")\n",
     211             :                           substitute_name_offset,
     212             :                           substitute_name_length,
     213             :                           reparse_data_length - 12);
     214           0 :                 goto fail;
     215             :         }
     216           0 :         if (smb_buffer_oob(reparse_data_length - 12, print_name_offset,
     217             :                            print_name_length)) {
     218           0 :                 DBG_DEBUG("print_name (%"PRIu16"/%"PRIu16") does not fit in "
     219             :                           "reparse_data_length (%"PRIu16")\n",
     220             :                           print_name_offset,
     221             :                           print_name_length,
     222             :                           reparse_data_length - 12);
     223           0 :                 goto fail;
     224             :         }
     225             : 
     226           0 :         result = talloc_zero(mem_ctx, struct symlink_reparse_struct);
     227           0 :         if (result == NULL) {
     228           0 :                 DBG_DEBUG("talloc failed\n");
     229           0 :                 goto fail;
     230             :         }
     231             : 
     232           0 :         ok = convert_string_talloc(
     233             :                 result,
     234             :                 CH_UTF16,
     235             :                 CH_UNIX,
     236           0 :                 src + 20 + substitute_name_offset,
     237             :                 substitute_name_length,
     238           0 :                 &result->substitute_name,
     239             :                 NULL);
     240           0 :         if (!ok) {
     241           0 :                 DBG_DEBUG("convert_string_talloc for substitute_name "
     242             :                           "failed\n");
     243           0 :                 goto fail;
     244             :         }
     245             : 
     246           0 :         ok = convert_string_talloc(
     247             :                 result,
     248             :                 CH_UTF16,
     249             :                 CH_UNIX,
     250           0 :                 src + 20 + print_name_offset,
     251             :                 print_name_length,
     252           0 :                 &result->print_name,
     253             :                 NULL);
     254           0 :         if (!ok) {
     255           0 :                 DBG_DEBUG("convert_string_talloc for print_name failed\n");
     256           0 :                 goto fail;
     257             :         }
     258             : 
     259           0 :         result->unparsed_path_length = SVAL(src, 6);
     260           0 :         result->flags = IVAL(src, 16);
     261             : 
     262           0 :         return result;
     263           0 : fail:
     264           0 :         TALLOC_FREE(result);
     265           0 :         return NULL;
     266             : }

Generated by: LCOV version 1.14