LCOV - code coverage report
Current view: top level - source4/torture/basic - aliases.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 196 220 89.1 %
Date: 2024-01-11 09:59:51 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB trans2 alias scanner
       4             :    Copyright (C) Andrew Tridgell 2003
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "../lib/util/dlinklist.h"
      22             : #include "libcli/raw/libcliraw.h"
      23             : #include "libcli/raw/raw_proto.h"
      24             : #include "libcli/libcli.h"
      25             : #include "torture/util.h"
      26             : #include "torture/basic/proto.h"
      27             : 
      28             : int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *fname);
      29             : 
      30             : struct trans2_blobs {
      31             :         struct trans2_blobs *next, *prev;
      32             :         uint16_t level;
      33             :         DATA_BLOB params, data;
      34             : };
      35             : 
      36             : /* look for aliases for a query */
      37           8 : static bool gen_aliases(struct torture_context *tctx, 
      38             :                                                 struct smbcli_state *cli, struct smb_trans2 *t2, 
      39             :                                                 int level_offset)
      40             : {
      41           0 :         uint16_t level;
      42           8 :         struct trans2_blobs *alias_blobs = NULL;
      43           0 :         struct trans2_blobs *t2b, *t2b2;
      44           8 :         int count=0, alias_count=0;
      45             : 
      46       16008 :         for (level=0;level<2000;level++) {
      47           0 :                 NTSTATUS status;
      48             : 
      49       16000 :                 SSVAL(t2->in.params.data, level_offset, level);
      50             :                 
      51       16000 :                 status = smb_raw_trans2(cli->tree, tctx, t2);
      52       16000 :                 if (!NT_STATUS_IS_OK(status)) continue;
      53             : 
      54         152 :                 t2b = talloc(tctx, struct trans2_blobs);
      55         152 :                 t2b->level = level;
      56         152 :                 t2b->params = t2->out.params;
      57         152 :                 t2b->data = t2->out.data;
      58         152 :                 DLIST_ADD(alias_blobs, t2b);
      59         152 :                 torture_comment(tctx, 
      60             :                                                 "\tFound level %4u (0x%03x) of size %3d (0x%02x)\n", 
      61             :                          level, level,
      62         152 :                          (int)t2b->data.length, (int)t2b->data.length);
      63         152 :                 count++;
      64             :         }
      65             : 
      66           8 :         torture_comment(tctx, "Found %d levels with success status\n", count);
      67             : 
      68         160 :         for (t2b=alias_blobs; t2b; t2b=t2b->next) {
      69        3588 :                 for (t2b2=alias_blobs; t2b2; t2b2=t2b2->next) {
      70        3436 :                         if (t2b->level >= t2b2->level) continue;
      71        3284 :                         if (data_blob_cmp(&t2b->params, &t2b2->params) == 0 &&
      72        1642 :                             data_blob_cmp(&t2b->data, &t2b2->data) == 0) {
      73          48 :                                 torture_comment(tctx, 
      74             :                                 "\tLevel %u (0x%x) and level %u (0x%x) are possible aliases\n", 
      75          48 :                                        t2b->level, t2b->level, t2b2->level, t2b2->level);
      76          48 :                                 alias_count++;
      77             :                         }
      78             :                 }
      79             :         }
      80             : 
      81           8 :         torture_comment(tctx, "Found %d aliased levels\n", alias_count);
      82             : 
      83           8 :         return true;
      84             : }
      85             : 
      86             : /* look for qfsinfo aliases */
      87           2 : static bool qfsinfo_aliases(struct torture_context *tctx, struct smbcli_state *cli)
      88             : {
      89           0 :         struct smb_trans2 t2;
      90           2 :         uint16_t setup = TRANSACT2_QFSINFO;
      91             : 
      92           2 :         t2.in.max_param = 0;
      93           2 :         t2.in.max_data = UINT16_MAX;
      94           2 :         t2.in.max_setup = 0;
      95           2 :         t2.in.flags = 0;
      96           2 :         t2.in.timeout = 0;
      97           2 :         t2.in.setup_count = 1;
      98           2 :         t2.in.setup = &setup;
      99           2 :         t2.in.params = data_blob_talloc_zero(tctx, 2);
     100           2 :         t2.in.data = data_blob(NULL, 0);
     101           2 :         ZERO_STRUCT(t2.out);
     102             : 
     103           2 :         return gen_aliases(tctx, cli, &t2, 0);
     104             : }
     105             : 
     106             : /* look for qfileinfo aliases */
     107           2 : static bool qfileinfo_aliases(struct torture_context *tctx, struct smbcli_state *cli)
     108             : {
     109           0 :         struct smb_trans2 t2;
     110           2 :         uint16_t setup = TRANSACT2_QFILEINFO;
     111           2 :         const char *fname = "\\qfileinfo_aliases.txt";
     112           0 :         int fnum;
     113             : 
     114           2 :         t2.in.max_param = 2;
     115           2 :         t2.in.max_data = UINT16_MAX;
     116           2 :         t2.in.max_setup = 0;
     117           2 :         t2.in.flags = 0;
     118           2 :         t2.in.timeout = 0;
     119           2 :         t2.in.setup_count = 1;
     120           2 :         t2.in.setup = &setup;
     121           2 :         t2.in.params = data_blob_talloc_zero(tctx, 4);
     122           2 :         t2.in.data = data_blob(NULL, 0);
     123           2 :         ZERO_STRUCT(t2.out);
     124             : 
     125           2 :         smbcli_unlink(cli->tree, fname);
     126           2 :         fnum = create_complex_file(cli, cli, fname);
     127           2 :         torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, 
     128             :                                         "open of %s failed (%s)", fname, 
     129             :                                    smbcli_errstr(cli->tree)));
     130             : 
     131           2 :         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
     132             : 
     133           2 :         SSVAL(t2.in.params.data, 0, fnum);
     134             : 
     135           2 :         if (!gen_aliases(tctx, cli, &t2, 2))
     136           0 :                 return false;
     137             : 
     138           2 :         smbcli_close(cli->tree, fnum);
     139           2 :         smbcli_unlink(cli->tree, fname);
     140             : 
     141           2 :         return true;
     142             : }
     143             : 
     144             : 
     145             : /* look for qpathinfo aliases */
     146           2 : static bool qpathinfo_aliases(struct torture_context *tctx, struct smbcli_state *cli)
     147             : {
     148           0 :         struct smb_trans2 t2;
     149           2 :         uint16_t setup = TRANSACT2_QPATHINFO;
     150           2 :         const char *fname = "\\qpathinfo_aliases.txt";
     151           0 :         int fnum;
     152             : 
     153           2 :         ZERO_STRUCT(t2);
     154           2 :         t2.in.max_param = 2;
     155           2 :         t2.in.max_data = UINT16_MAX;
     156           2 :         t2.in.max_setup = 0;
     157           2 :         t2.in.flags = 0;
     158           2 :         t2.in.timeout = 0;
     159           2 :         t2.in.setup_count = 1;
     160           2 :         t2.in.setup = &setup;
     161           2 :         t2.in.params = data_blob_talloc_zero(tctx, 6);
     162           2 :         t2.in.data = data_blob(NULL, 0);
     163             : 
     164           2 :         smbcli_unlink(cli->tree, fname);
     165           2 :         fnum = create_complex_file(cli, cli, fname);
     166           2 :         torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, 
     167             :                                         "open of %s failed (%s)", fname, 
     168             :                                    smbcli_errstr(cli->tree)));
     169             : 
     170           2 :         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
     171           2 :         smbcli_close(cli->tree, fnum);
     172             : 
     173           2 :         SIVAL(t2.in.params.data, 2, 0);
     174             : 
     175           2 :         smbcli_blob_append_string(cli->session, tctx, &t2.in.params, 
     176             :                                fname, STR_TERMINATE);
     177             : 
     178           2 :         if (!gen_aliases(tctx, cli, &t2, 0))
     179           0 :                 return false;
     180             : 
     181           2 :         smbcli_unlink(cli->tree, fname);
     182             : 
     183           2 :         return true;
     184             : }
     185             : 
     186             : 
     187             : /* look for trans2 findfirst aliases */
     188           2 : static bool findfirst_aliases(struct torture_context *tctx, struct smbcli_state *cli)
     189             : {
     190           0 :         struct smb_trans2 t2;
     191           2 :         uint16_t setup = TRANSACT2_FINDFIRST;
     192           2 :         const char *fname = "\\findfirst_aliases.txt";
     193           0 :         int fnum;
     194             : 
     195           2 :         ZERO_STRUCT(t2);
     196           2 :         t2.in.max_param = 16;
     197           2 :         t2.in.max_data = UINT16_MAX;
     198           2 :         t2.in.max_setup = 0;
     199           2 :         t2.in.flags = 0;
     200           2 :         t2.in.timeout = 0;
     201           2 :         t2.in.setup_count = 1;
     202           2 :         t2.in.setup = &setup;
     203           2 :         t2.in.params = data_blob_talloc_zero(tctx, 12);
     204           2 :         t2.in.data = data_blob(NULL, 0);
     205             : 
     206           2 :         smbcli_unlink(cli->tree, fname);
     207           2 :         fnum = create_complex_file(cli, cli, fname);
     208           2 :         torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, 
     209             :                                         "open of %s failed (%s)", fname, 
     210             :                                    smbcli_errstr(cli->tree)));
     211             : 
     212           2 :         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
     213           2 :         smbcli_close(cli->tree, fnum);
     214             : 
     215           2 :         SSVAL(t2.in.params.data, 0, 0);
     216           2 :         SSVAL(t2.in.params.data, 2, 1);
     217           2 :         SSVAL(t2.in.params.data, 4, FLAG_TRANS2_FIND_CLOSE);
     218           2 :         SSVAL(t2.in.params.data, 6, 0);
     219           2 :         SIVAL(t2.in.params.data, 8, 0);
     220             : 
     221           2 :         smbcli_blob_append_string(cli->session, tctx, &t2.in.params, 
     222             :                                fname, STR_TERMINATE);
     223             : 
     224           2 :         if (!gen_aliases(tctx, cli, &t2, 6))
     225           0 :                 return false;
     226             : 
     227           2 :         smbcli_unlink(cli->tree, fname);
     228             : 
     229           2 :         return true;
     230             : }
     231             : 
     232             : 
     233             : 
     234             : /* look for aliases for a set function */
     235           4 : static bool gen_set_aliases(struct torture_context *tctx, 
     236             :                                                         struct smbcli_state *cli, 
     237             :                                                         struct smb_trans2 *t2, int level_offset)
     238             : {
     239           0 :         uint16_t level;
     240           4 :         struct trans2_blobs *alias_blobs = NULL;
     241           0 :         struct trans2_blobs *t2b;
     242           4 :         int count=0, dsize;
     243             : 
     244        4400 :         for (level=1;level<1100;level++) {
     245           0 :                 NTSTATUS status, status1;
     246        4396 :                 SSVAL(t2->in.params.data, level_offset, level);
     247             : 
     248        4396 :                 status1 = NT_STATUS_OK;
     249             : 
     250        4420 :                 for (dsize=2; dsize<1024; dsize += 2) {
     251        4420 :                         data_blob_free(&t2->in.data);
     252        4420 :                         t2->in.data = data_blob(NULL, dsize);
     253        4420 :                         data_blob_clear(&t2->in.data);
     254        4420 :                         status = smb_raw_trans2(cli->tree, tctx, t2);
     255             :                         /* some error codes mean that this whole level doesn't exist */
     256        4420 :                         if (NT_STATUS_EQUAL(NT_STATUS_INVALID_LEVEL, status) ||
     257          76 :                             NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status) ||
     258          76 :                             NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
     259             :                                 break;
     260             :                         }
     261          76 :                         if (NT_STATUS_IS_OK(status)) break;
     262             : 
     263             :                         /* invalid parameter means that the level exists at this 
     264             :                            size, but the contents are wrong (not surprising with
     265             :                            all zeros!) */
     266          60 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) break;
     267             : 
     268             :                         /* this is the usual code for 'wrong size' */
     269          24 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INFO_LENGTH_MISMATCH)) {
     270          24 :                                 continue;
     271             :                         }
     272             : 
     273           0 :                         if (!NT_STATUS_EQUAL(status, status1)) {
     274           0 :                                 torture_comment(tctx, "level=%d size=%d %s\n", level, dsize, nt_errstr(status));
     275             :                         }
     276           0 :                         status1 = status;
     277             :                 }
     278             : 
     279        4396 :                 if (!NT_STATUS_IS_OK(status) &&
     280        4380 :                     !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) continue;
     281             : 
     282          52 :                 t2b = talloc(tctx, struct trans2_blobs);
     283          52 :                 t2b->level = level;
     284          52 :                 t2b->params = t2->out.params;
     285          52 :                 t2b->data = t2->out.data;
     286          52 :                 DLIST_ADD(alias_blobs, t2b);
     287          52 :                 torture_comment(tctx, 
     288             :                                         "\tFound level %4u (0x%03x) of size %3d (0x%02x)\n", 
     289             :                          level, level,
     290          52 :                          (int)t2->in.data.length, (int)t2->in.data.length);
     291          52 :                 count++;
     292             :         }
     293             : 
     294           4 :         torture_comment(tctx, "Found %d valid levels\n", count);
     295             : 
     296           4 :         return true;
     297             : }
     298             : 
     299             : 
     300             : 
     301             : /* look for setfileinfo aliases */
     302           2 : static bool setfileinfo_aliases(struct torture_context *tctx, struct smbcli_state *cli)
     303             : {
     304           0 :         struct smb_trans2 t2;
     305           2 :         uint16_t setup = TRANSACT2_SETFILEINFO;
     306           2 :         const char *fname = "\\setfileinfo_aliases.txt";
     307           0 :         int fnum;
     308             : 
     309           2 :         ZERO_STRUCT(t2);
     310           2 :         t2.in.max_param = 2;
     311           2 :         t2.in.max_data = 0;
     312           2 :         t2.in.max_setup = 0;
     313           2 :         t2.in.flags = 0;
     314           2 :         t2.in.timeout = 0;
     315           2 :         t2.in.setup_count = 1;
     316           2 :         t2.in.setup = &setup;
     317           2 :         t2.in.params = data_blob_talloc_zero(tctx, 6);
     318           2 :         t2.in.data = data_blob(NULL, 0);
     319             : 
     320           2 :         smbcli_unlink(cli->tree, fname);
     321           2 :         fnum = create_complex_file(cli, cli, fname);
     322           2 :         torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, 
     323             :                                    "open of %s failed (%s)", fname, 
     324             :                                    smbcli_errstr(cli->tree)));
     325             : 
     326           2 :         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
     327             : 
     328           2 :         SSVAL(t2.in.params.data, 0, fnum);
     329           2 :         SSVAL(t2.in.params.data, 4, 0);
     330             : 
     331           2 :         gen_set_aliases(tctx, cli, &t2, 2);
     332             : 
     333           2 :         smbcli_close(cli->tree, fnum);
     334           2 :         smbcli_unlink(cli->tree, fname);
     335             : 
     336           2 :         return true;
     337             : }
     338             : 
     339             : /* look for setpathinfo aliases */
     340           2 : static bool setpathinfo_aliases(struct torture_context *tctx, 
     341             :                                                                 struct smbcli_state *cli)
     342             : {
     343           0 :         struct smb_trans2 t2;
     344           2 :         uint16_t setup = TRANSACT2_SETPATHINFO;
     345           2 :         const char *fname = "\\setpathinfo_aliases.txt";
     346           0 :         int fnum;
     347             : 
     348           2 :         ZERO_STRUCT(t2);
     349           2 :         t2.in.max_param = 32;
     350           2 :         t2.in.max_data = UINT16_MAX;
     351           2 :         t2.in.max_setup = 0;
     352           2 :         t2.in.flags = 0;
     353           2 :         t2.in.timeout = 0;
     354           2 :         t2.in.setup_count = 1;
     355           2 :         t2.in.setup = &setup;
     356           2 :         t2.in.params = data_blob_talloc_zero(tctx, 4);
     357           2 :         t2.in.data = data_blob(NULL, 0);
     358             : 
     359           2 :         smbcli_unlink(cli->tree, fname);
     360             : 
     361           2 :         fnum = create_complex_file(cli, cli, fname);
     362           2 :         torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, 
     363             :                                         "open of %s failed (%s)", fname, 
     364             :                                    smbcli_errstr(cli->tree)));
     365             : 
     366           2 :         smbcli_write(cli->tree, fnum, 0, &t2, 0, sizeof(t2));
     367           2 :         smbcli_close(cli->tree, fnum);
     368             : 
     369           2 :         SSVAL(t2.in.params.data, 2, 0);
     370             : 
     371           2 :         smbcli_blob_append_string(cli->session, tctx, &t2.in.params, 
     372             :                                fname, STR_TERMINATE);
     373             : 
     374           2 :         if (!gen_set_aliases(tctx, cli, &t2, 0))
     375           0 :                 return false;
     376             : 
     377           2 :         torture_assert_ntstatus_ok(tctx, smbcli_unlink(cli->tree, fname),
     378             :                 talloc_asprintf(tctx, "unlink: %s", smbcli_errstr(cli->tree)));
     379             : 
     380           2 :         return true;
     381             : }
     382             : 
     383             : 
     384             : /* look for aliased info levels in trans2 calls */
     385        2358 : struct torture_suite *torture_trans2_aliases(TALLOC_CTX *mem_ctx)
     386             : {
     387        2358 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "aliases");
     388             : 
     389        2358 :         torture_suite_add_1smb_test(suite, "QFSINFO aliases", qfsinfo_aliases);
     390        2358 :         torture_suite_add_1smb_test(suite, "QFILEINFO aliases", qfileinfo_aliases);
     391        2358 :         torture_suite_add_1smb_test(suite, "QPATHINFO aliases", qpathinfo_aliases);
     392        2358 :         torture_suite_add_1smb_test(suite, "FINDFIRST aliases", findfirst_aliases);
     393        2358 :         torture_suite_add_1smb_test(suite, "setfileinfo_aliases", setfileinfo_aliases);
     394        2358 :         torture_suite_add_1smb_test(suite, "setpathinfo_aliases", setpathinfo_aliases);
     395             : 
     396        2358 :         return suite;
     397             : }

Generated by: LCOV version 1.14