LCOV - code coverage report
Current view: top level - source3/smbd - smb1_utils.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 80 98 81.6 %
Date: 2024-04-21 15:09:00 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  * Util functions valid in the SMB1 server
       4             :  *
       5             :  * Copyright (C) Volker Lendecke 2019
       6             :  * Copyright by the authors of the functions moved here eventually
       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 "smbd/smbd.h"
      24             : #include "smbd/globals.h"
      25             : #include "libcli/security/security.h"
      26             : #include "lib/util/sys_rw_data.h"
      27             : #include "smbd/fd_handle.h"
      28             : 
      29             : /****************************************************************************
      30             :  Special FCB or DOS processing in the case of a sharing violation.
      31             :  Try and find a duplicated file handle.
      32             : ****************************************************************************/
      33             : 
      34        4425 : struct files_struct *fcb_or_dos_open(
      35             :         struct smb_request *req,
      36             :         const struct smb_filename *smb_fname,
      37             :         uint32_t access_mask,
      38             :         uint32_t create_options,
      39             :         uint32_t private_flags)
      40             : {
      41        4425 :         struct connection_struct *conn = req->conn;
      42        4425 :         struct file_id id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
      43        4425 :         struct files_struct *fsp = NULL, *new_fsp = NULL;
      44           9 :         NTSTATUS status;
      45             : 
      46        4425 :         if ((private_flags &
      47             :              (NTCREATEX_FLAG_DENY_DOS|
      48             :               NTCREATEX_FLAG_DENY_FCB))
      49             :             == 0) {
      50        2976 :                 return NULL;
      51             :         }
      52             : 
      53        1441 :         for(fsp = file_find_di_first(conn->sconn, id, true);
      54        1981 :             fsp != NULL;
      55         540 :             fsp = file_find_di_next(fsp, true)) {
      56             : 
      57         677 :                 DBG_DEBUG("Checking file %s, fd = %d, vuid = %"PRIu64", "
      58             :                           "file_pid = %"PRIu16", "
      59             :                           "private_options = 0x%"PRIx32", "
      60             :                           "access_mask = 0x%"PRIx32"\n",
      61             :                           fsp_str_dbg(fsp),
      62             :                           fsp_get_pathref_fd(fsp),
      63             :                           fsp->vuid,
      64             :                           fsp->file_pid,
      65             :                           fh_get_private_options(fsp->fh),
      66             :                           fsp->access_mask);
      67             : 
      68         677 :                 if (fsp_get_pathref_fd(fsp) != -1 &&
      69         677 :                     fsp->vuid == req->vuid &&
      70         677 :                     fsp->file_pid == req->smbpid &&
      71         677 :                     (fh_get_private_options(fsp->fh) &
      72             :                      (NTCREATEX_FLAG_DENY_DOS |
      73         169 :                       NTCREATEX_FLAG_DENY_FCB)) &&
      74         306 :                     (fsp->access_mask & FILE_WRITE_DATA) &&
      75         274 :                     strequal(fsp->fsp_name->base_name, smb_fname->base_name) &&
      76         137 :                     strequal(fsp->fsp_name->stream_name,
      77         137 :                              smb_fname->stream_name)) {
      78         137 :                         DBG_DEBUG("file match\n");
      79         136 :                         break;
      80             :                 }
      81             :         }
      82             : 
      83        1441 :         if (fsp == NULL) {
      84        1304 :                 return NULL;
      85             :         }
      86             : 
      87             :         /* quite an insane set of semantics ... */
      88         137 :         if (is_executable(smb_fname->base_name) &&
      89          60 :             (fh_get_private_options(fsp->fh) & NTCREATEX_FLAG_DENY_DOS)) {
      90          24 :                 DBG_DEBUG("file fail due to is_executable.\n");
      91          24 :                 return NULL;
      92             :         }
      93             : 
      94         113 :         status = file_new(req, conn, &new_fsp);
      95         113 :         if (!NT_STATUS_IS_OK(status)) {
      96           0 :                 DBG_DEBUG("file_new failed: %s\n", nt_errstr(status));
      97           0 :                 return NULL;
      98             :         }
      99             : 
     100         113 :         status = dup_file_fsp(fsp, access_mask, new_fsp);
     101             : 
     102         113 :         if (!NT_STATUS_IS_OK(status)) {
     103           0 :                 DBG_DEBUG("dup_file_fsp failed: %s\n", nt_errstr(status));
     104           0 :                 file_free(req, new_fsp);
     105           0 :                 return NULL;
     106             :         }
     107             : 
     108         113 :         return new_fsp;
     109             : }
     110             : 
     111             : /****************************************************************************
     112             :  Send a keepalive packet (rfc1002).
     113             : ****************************************************************************/
     114             : 
     115           0 : bool send_keepalive(int client)
     116             : {
     117           0 :         unsigned char buf[4];
     118             : 
     119           0 :         buf[0] = NBSSkeepalive;
     120           0 :         buf[1] = buf[2] = buf[3] = 0;
     121             : 
     122           0 :         return(write_data(client,(char *)buf,4) == 4);
     123             : }
     124             : 
     125             : /*******************************************************************
     126             :  Add a string to the end of a smb_buf, adjusting bcc and smb_len.
     127             :  Return the bytes added
     128             : ********************************************************************/
     129             : 
     130       54610 : ssize_t message_push_string(uint8_t **outbuf, const char *str, int flags)
     131             : {
     132       54610 :         size_t buf_size = smb_len(*outbuf) + 4;
     133         677 :         size_t grow_size;
     134       54610 :         size_t result = 0;
     135         677 :         uint8_t *tmp;
     136         677 :         NTSTATUS status;
     137             : 
     138             :         /*
     139             :          * We need to over-allocate, now knowing what srvstr_push will
     140             :          * actually use. This is very generous by incorporating potential
     141             :          * padding, the terminating 0 and at most 4 chars per UTF-16 code
     142             :          * point.
     143             :          */
     144       54610 :         grow_size = (strlen(str) + 2) * 4;
     145             : 
     146       54610 :         if (!(tmp = talloc_realloc(NULL, *outbuf, uint8_t,
     147             :                                          buf_size + grow_size))) {
     148           0 :                 DEBUG(0, ("talloc failed\n"));
     149           0 :                 return -1;
     150             :         }
     151             : 
     152       54610 :         status = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
     153             :                              tmp + buf_size, str, grow_size, flags, &result);
     154             : 
     155       54610 :         if (!NT_STATUS_IS_OK(status)) {
     156           0 :                 DEBUG(0, ("srvstr_push failed\n"));
     157           0 :                 return -1;
     158             :         }
     159             : 
     160             :         /*
     161             :          * Ensure we clear out the extra data we have
     162             :          * grown the buffer by, but not written to.
     163             :          */
     164       54610 :         if (buf_size + result < buf_size) {
     165           0 :                 return -1;
     166             :         }
     167       54610 :         if (grow_size < result) {
     168           0 :                 return -1;
     169             :         }
     170             : 
     171       54610 :         memset(tmp + buf_size + result, '\0', grow_size - result);
     172             : 
     173       54610 :         set_message_bcc((char *)tmp, smb_buflen(tmp) + result);
     174             : 
     175       54610 :         *outbuf = tmp;
     176             : 
     177       54610 :         return result;
     178             : }
     179             : 
     180             : /*
     181             :  * Deal with the SMB1 semantics of sending a pathname with a
     182             :  * wildcard as the terminal component for a SMB1search or
     183             :  * trans2 findfirst.
     184             :  */
     185             : 
     186        8912 : NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
     187             :                                            connection_struct *conn,
     188             :                                            char *name_in,
     189             :                                            uint32_t ucf_flags,
     190             :                                            struct files_struct **_dirfsp,
     191             :                                            struct smb_filename **_smb_fname_out,
     192             :                                            char **_mask_out)
     193             : {
     194         175 :         NTSTATUS status;
     195        8912 :         char *p = NULL;
     196        8912 :         char *mask = NULL;
     197        8912 :         struct smb_filename *smb_fname = NULL;
     198        8912 :         NTTIME twrp = 0;
     199             : 
     200        8912 :         *_smb_fname_out = NULL;
     201        8912 :         *_dirfsp = NULL;
     202        8912 :         *_mask_out = NULL;
     203             : 
     204        8912 :         DBG_DEBUG("name_in: %s\n", name_in);
     205             : 
     206        8912 :         if (ucf_flags & UCF_GMT_PATHNAME) {
     207          68 :                 extract_snapshot_token(name_in, &twrp);
     208          68 :                 ucf_flags &= ~UCF_GMT_PATHNAME;
     209             :         }
     210             : 
     211             :         /* Get the original lcomp. */
     212        8912 :         mask = get_original_lcomp(ctx, conn, name_in, ucf_flags);
     213        8912 :         if (mask == NULL) {
     214           0 :                 return NT_STATUS_NO_MEMORY;
     215             :         }
     216             : 
     217        8912 :         if (mask[0] == '\0') {
     218             :                 /* Windows and OS/2 systems treat search on the root as * */
     219           6 :                 TALLOC_FREE(mask);
     220           6 :                 mask = talloc_strdup(ctx, "*");
     221           6 :                 if (mask == NULL) {
     222           0 :                         return NT_STATUS_NO_MEMORY;
     223             :                 }
     224             :         }
     225             : 
     226        8912 :         DBG_DEBUG("mask = %s\n", mask);
     227             : 
     228             :         /*
     229             :          * Remove the terminal component so
     230             :          * filename_convert_dirfsp never sees the mask.
     231             :          */
     232        8912 :         p = strrchr_m(name_in, '/');
     233        8912 :         if (p == NULL) {
     234             :                 /* filename_convert_dirfsp handles a '\0' name. */
     235        1258 :                 name_in[0] = '\0';
     236             :         } else {
     237        7654 :                 *p = '\0';
     238             :         }
     239             : 
     240        8912 :         DBG_DEBUG("For filename_convert_dirfsp: name_in = %s\n", name_in);
     241             : 
     242             :         /* Convert the parent directory path. */
     243        8912 :         status = filename_convert_dirfsp(ctx,
     244             :                                          conn,
     245             :                                          name_in,
     246             :                                          ucf_flags,
     247             :                                          twrp,
     248             :                                          _dirfsp,
     249             :                                          &smb_fname);
     250             : 
     251        8912 :         if (!NT_STATUS_IS_OK(status)) {
     252         114 :                 DBG_DEBUG("filename_convert error for %s: %s\n",
     253             :                           name_in,
     254             :                           nt_errstr(status));
     255             :         }
     256             : 
     257        8912 :         *_smb_fname_out = talloc_move(ctx, &smb_fname);
     258        8912 :         *_mask_out = talloc_move(ctx, &mask);
     259             : 
     260        8912 :         return status;
     261             : }

Generated by: LCOV version 1.14