LCOV - code coverage report
Current view: top level - source4/torture/rpc - iremotewinspool_driver.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 9 429 2.1 %
Date: 2024-04-21 15:09:00 Functions: 1 24 4.2 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    test suite for iremotewinspool driver rpc operations
       4             : 
       5             :    Copyright (C) Justin Stephenson 2018
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <dirent.h>
      22             : #include <talloc.h>
      23             : #include <libgen.h>
      24             : #include "includes.h"
      25             : #include "torture/torture.h"
      26             : #include "librpc/gen_ndr/ndr_winspool.h"
      27             : #include "librpc/gen_ndr/ndr_winspool_c.h"
      28             : #include "librpc/gen_ndr/ndr_spoolss_c.h"
      29             : #include "librpc/gen_ndr/ndr_winreg_c.h"
      30             : #include "torture/rpc/torture_rpc.h"
      31             : #include "libcli/registry/util_reg.h"
      32             : #include "torture/rpc/iremotewinspool_common.h"
      33             : #include "libcli/libcli.h"
      34             : #include "param/param.h"
      35             : #include "lib/registry/registry.h"
      36             : #include "libcli/libcli.h"
      37             : #include "libcli/raw/raw_proto.h"
      38             : #include "libcli/resolve/resolve.h"
      39             : #include "libcli/smb2/smb2.h"
      40             : #include "libcli/smb2/smb2_calls.h"
      41             : #include "lib/cmdline/cmdline.h"
      42             : #include "system/filesys.h"
      43             : #include "lib/util/tftw.h"
      44             : 
      45             : /* Connect to print driver share //server_name/share */
      46           0 : static bool smb_connect_print_share(struct torture_context *tctx,
      47             :                                     const char *server_name,
      48             :                                     const char *share_name,
      49             :                                     struct smbcli_state **cli)
      50             : {
      51           0 :         NTSTATUS status;
      52           0 :         bool ok = true;
      53             : 
      54           0 :         struct smbcli_options smb_options;
      55           0 :         struct smbcli_session_options smb_session_options;
      56             : 
      57           0 :         torture_comment(tctx, "Connecting to printer driver share '//%s/%s'\n",
      58             :                         server_name, share_name);
      59             : 
      60           0 :         lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
      61           0 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
      62             : 
      63             :         /* On Windows, SMB1 must be enabled! */
      64           0 :         status = smbcli_full_connection(tctx, cli, server_name,
      65             :                                         lpcfg_smb_ports(tctx->lp_ctx),
      66             :                                         share_name, NULL,
      67             :                                         lpcfg_socket_options(tctx->lp_ctx),
      68             :                                         samba_cmdline_get_creds(),
      69             :                                         lpcfg_resolve_context(tctx->lp_ctx),
      70             :                                         tctx->ev,
      71             :                                         &smb_options,
      72             :                                         &smb_session_options,
      73             :                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx));
      74             : 
      75           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "Failed to connect to print$ share");
      76             : 
      77           0 : done:
      78             : 
      79           0 :         return ok;
      80             : }
      81             : 
      82             : /* Copy file to destination where dst_fpath is a smb share path,
      83             :  * files are either created or overwritten */
      84           0 : static bool smb_copy_files(TALLOC_CTX *tctx,
      85             :                                 const char *fpath,
      86             :                                 const char *dst_fpath,
      87             :                                 struct test_driver_info *dinfo)
      88             : {
      89           0 :         FILE *fp;
      90           0 :         int smbfp = 0;
      91           0 :         char *buffer = NULL;
      92           0 :         int maxwrite = 64512;
      93           0 :         size_t nread;
      94           0 :         ssize_t nwrote;
      95           0 :         bool ok = true;
      96           0 :         size_t total_read;
      97             : 
      98           0 :         fp = fopen(fpath, "r");
      99           0 :         torture_assert_goto(tctx, fp, ok, done, "Failed to open local file\n");
     100             : 
     101           0 :         smbfp = smbcli_open(dinfo->cli->tree, dst_fpath, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
     102           0 :         torture_assert_int_not_equal_goto(tctx, smbfp, -1, ok, done, "Failed to open dst file\n");
     103             : 
     104           0 :         buffer = talloc_array(tctx, char, maxwrite);
     105           0 :         torture_assert_not_null_goto(tctx, buffer, ok, done, "Failed to allocate buffer\n");
     106             : 
     107           0 :         total_read = 0;
     108             : 
     109           0 :         while (!feof(fp)) {
     110           0 :                 nread = fread(buffer, 1, maxwrite, fp);
     111           0 :                 if (ferror(fp)) {
     112           0 :                         torture_warning(tctx, "Error reading file [%s]\n", fpath);
     113           0 :                         continue;
     114             :                 }
     115             : 
     116           0 :                 nwrote = smbcli_write(dinfo->cli->tree, smbfp, 0, buffer, total_read, nread);
     117           0 :                 if (nwrote != nread) {
     118           0 :                         torture_warning(tctx, "Not all data in stream written!\n");
     119             :                 }
     120             : 
     121           0 :                 total_read += nread;
     122             :         }
     123             : 
     124           0 :         fclose(fp);
     125           0 :         smbcli_close(dinfo->cli->tree, smbfp);
     126           0 : done:
     127             : 
     128           0 :         TALLOC_FREE(buffer);
     129           0 :         return ok;
     130             : }
     131             : 
     132             : /* Callback function provided to tftw() to
     133             :  * copy driver files to smb share */
     134           0 : static int copy_driver_files(TALLOC_CTX *tctx,
     135             :                              const char *fpath,
     136             :                              const struct stat *sb,
     137             :                              enum tftw_flags_e flag,
     138             :                              void *userdata)
     139             : {
     140           0 :         char *dst_fpath = NULL;
     141           0 :         struct test_driver_info *dinfo = userdata;
     142           0 :         char *path = NULL;
     143           0 :         NTSTATUS status;
     144           0 :         bool ok = true;
     145             : 
     146           0 :         path = talloc_strdup(tctx, fpath + dinfo->driver_path_len);
     147           0 :         torture_assert_not_null_goto(tctx, path, ok, done, "Cannot allocate memory");
     148             : 
     149           0 :         string_replace(path, '/', '\\');
     150             : 
     151           0 :         dst_fpath = talloc_asprintf(tctx, "%s%s", dinfo->print_upload_guid_dir, path);
     152           0 :         torture_assert_not_null_goto(tctx, dst_fpath, ok, done, "Cannot allocate memory");
     153             : 
     154           0 :         switch (flag) {
     155           0 :                 case TFTW_FLAG_FILE:
     156           0 :                         ok = smb_copy_files(tctx, fpath, dst_fpath, dinfo);
     157           0 :                         torture_assert_goto(tctx, ok, ok, done, "Failed to copy files over smb");
     158           0 :                         break;
     159           0 :                 case TFTW_FLAG_DIR:
     160           0 :                         status = smbcli_mkdir(dinfo->cli->tree, dst_fpath);
     161           0 :                         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "Failed to create directories");
     162           0 :                         break;
     163           0 :                 case TFTW_FLAG_SLINK:
     164             :                 case TFTW_FLAG_DNR:
     165             :                 case TFTW_FLAG_NSTAT:
     166             :                 case TFTW_FLAG_SPEC:
     167             :                 case TFTW_FLAG_DP:
     168             :                 case TFTW_FLAG_SLN:
     169           0 :                         torture_warning(tctx, "WARN: Unhandled typeflag [%s]\n", fpath);
     170           0 :                         break;
     171             :         }
     172             : 
     173           0 : done:
     174           0 :         TALLOC_FREE(path);
     175           0 :         TALLOC_FREE(dst_fpath);
     176             : 
     177           0 :         if (ok == true) {
     178           0 :                 return 0;
     179             :         } else {
     180           0 :                 return 1;
     181             :         }
     182             : }
     183             : 
     184           0 : static bool test_get_driver_torture_options(struct torture_context *tctx,
     185             :                                             const char **_local_driver_path,
     186             :                                             const char **_inf_file,
     187             :                                             const char **_driver_name,
     188             :                                             const char **_driver_arch,
     189             :                                             const char **_core_driver_inf)
     190             : {
     191           0 :         const char *local_driver_path = NULL;
     192           0 :         const char *inf_file = NULL;
     193           0 :         const char *driver_name = NULL;
     194           0 :         const char *driver_arch = NULL;
     195           0 :         const char *core_driver_inf = NULL;
     196           0 :         const char *arches_list[] = {
     197             :                 SPOOLSS_ARCHITECTURE_x64,
     198             :                 SPOOLSS_ARCHITECTURE_NT_X86,
     199             :                 SPOOLSS_ARCHITECTURE_IA_64,
     200             :                 SPOOLSS_ARCHITECTURE_ARM,
     201             :                 SPOOLSS_ARCHITECTURE_4_0,
     202             :                 NULL,
     203             :         };
     204           0 :         const char **p;
     205           0 :         bool valid = false;
     206           0 :         bool ok = true;
     207             : 
     208           0 :         local_driver_path = torture_setting_string(tctx, "driver_path", NULL);
     209           0 :         if (local_driver_path == NULL) {
     210           0 :                 torture_fail(tctx,
     211             :                              "option --option=torture:driver_path="
     212             :                              "/full/path/to/local/driver/dir\n");
     213             :         }
     214             : 
     215           0 :         inf_file = torture_setting_string(tctx, "inf_file", NULL);
     216           0 :         if (inf_file == NULL) {
     217           0 :                 torture_fail(tctx,
     218             :                              "option --option=torture:inf_file="
     219             :                              "filename.inf\n");
     220             :         }
     221             : 
     222           0 :         driver_name = torture_setting_string(tctx, "driver_name", NULL);
     223           0 :         if (driver_name == NULL) {
     224           0 :                 torture_fail(tctx,
     225             :                              "option --option=torture:driver_name="
     226             :                              "driver name\n");
     227             :         }
     228             : 
     229           0 :         driver_arch = torture_setting_string(tctx, "driver_arch", NULL);
     230           0 :         if (driver_arch == NULL) {
     231           0 :                 torture_fail(tctx,
     232             :                              "option --option=torture:driver_arch="
     233             :                              "driver arch\n");
     234             :         }
     235             : 
     236           0 :         core_driver_inf = torture_setting_string(tctx, "core_driver_inf", NULL);
     237             : 
     238           0 :         for (p = arches_list; *p != NULL; p++) {
     239           0 :                 if (strequal(*p, driver_arch) == 0) {
     240           0 :                         valid = true;
     241           0 :                         break;
     242             :                 }
     243             :         }
     244           0 :         torture_assert_goto(tctx, valid, ok, done, "Invalid driver arch provided");
     245             : 
     246           0 :         *_local_driver_path = local_driver_path;
     247           0 :         *_inf_file = inf_file;
     248           0 :         *_driver_name = driver_name;
     249           0 :         *_driver_arch = driver_arch;
     250           0 :         *_core_driver_inf = core_driver_inf;
     251           0 : done:
     252           0 :         return ok;
     253             : }
     254             : 
     255             : 
     256           0 : static bool test_get_misc_driver_info(struct torture_context *tctx,
     257             :                                       struct test_driver_info *dinfo,
     258             :                                       const char **_abs_inf_path,
     259             :                                       size_t *_driver_path_len)
     260             : {
     261           0 :         const char *abs_inf_path;
     262           0 :         size_t driver_path_len;
     263           0 :         bool ok = true;
     264             : 
     265           0 :         driver_path_len = strlen(dinfo->local_driver_path);
     266           0 :         torture_assert_int_not_equal_goto(tctx, driver_path_len, 0, ok, done, "driver path length is 0");
     267             : 
     268           0 :         abs_inf_path = talloc_asprintf(tctx, "%s/%s", dinfo->local_driver_path, dinfo->inf_file);
     269           0 :         torture_assert_not_null_goto(tctx, abs_inf_path, ok, done, "Cannot allocate memory");
     270             : 
     271           0 :         *_abs_inf_path = abs_inf_path;
     272           0 :         *_driver_path_len = driver_path_len;
     273           0 : done:
     274             : 
     275           0 :         return ok;
     276             : }
     277             : 
     278             : /* Uninstall the previously installed print driver */
     279           0 : static bool test_uninstall_printer_driver(struct torture_context *tctx,
     280             :                                           struct test_iremotewinspool_context *ctx)
     281             : {
     282           0 :         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
     283           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     284           0 :         struct winspool_AsyncDeletePrinterDriverEx r;
     285           0 :         bool ok = true;
     286           0 :         NTSTATUS status;
     287             : 
     288           0 :         r.in.pName = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     289             : 
     290           0 :         r.in.pDriverName = talloc_strdup(tctx, ctx->dinfo->driver_name);
     291           0 :         torture_assert_not_null_goto(tctx, r.in.pDriverName, ok, done, "Cannot allocate memory");
     292             : 
     293           0 :         r.in.pEnvironment = SPOOLSS_ARCHITECTURE_x64;
     294             : 
     295           0 :         r.in.dwDeleteFlag = 0;
     296           0 :         r.in.dwVersionNum = 0;
     297             : 
     298           0 :         status = dcerpc_winspool_AsyncDeletePrinterDriverEx_r(b, tctx, &r);
     299           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "AsyncDeletePrinterDriverEx failed");
     300             : 
     301           0 :         torture_assert_werr_ok(tctx, r.out.result, "AsyncDeletePrinterDriverEx failed");
     302           0 : done:
     303             : 
     304           0 :         return ok;
     305             : }
     306             : 
     307             : /* Remove the leftover print driver package files from the driver store */
     308           0 : static bool test_remove_driver_package(struct torture_context *tctx,
     309             :                                        struct test_iremotewinspool_context *ctx)
     310             : {
     311           0 :         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
     312           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     313           0 :         struct winspool_AsyncDeletePrinterDriverPackage r;
     314           0 :         bool ok = true;
     315           0 :         NTSTATUS status;
     316             : 
     317           0 :         r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     318           0 :         torture_assert_not_null_goto(tctx, r.in.pszServer, ok, done, "Cannot allocate memory");
     319             : 
     320           0 :         r.in.pszInfPath = ctx->dinfo->uploaded_inf_path;
     321             : 
     322           0 :         r.in.pszEnvironment = SPOOLSS_ARCHITECTURE_x64;
     323             : 
     324           0 :         status = dcerpc_winspool_AsyncDeletePrinterDriverPackage_r(b, tctx, &r);
     325           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "AsyncDeletePrinterPackage failed");
     326             : 
     327           0 :         torture_assert_hresult_ok(tctx, r.out.result, "AsyncDeletePrinterDriverPackage failed");
     328           0 : done:
     329             : 
     330           0 :         return ok;
     331             : }
     332             : 
     333           0 : static bool test_winreg_iremotewinspool_openhklm(struct torture_context *tctx,
     334             :                                                  struct dcerpc_binding_handle *winreg_bh,
     335             :                                                  struct policy_handle *_hklm_handle)
     336             : {
     337           0 :         struct winreg_OpenHKLM r;
     338           0 :         NTSTATUS status;
     339           0 :         bool ok = true;
     340             : 
     341           0 :         r.in.system_name = NULL;
     342           0 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     343           0 :         r.out.handle = _hklm_handle;
     344             : 
     345           0 :         status = dcerpc_winreg_OpenHKLM_r(winreg_bh, tctx, &r);
     346           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "Failed to Open HKLM");
     347             : 
     348           0 :         torture_assert_werr_ok(tctx, r.out.result, "Failed to Open HKLM");
     349           0 : done:
     350             : 
     351           0 :         return ok;
     352             : }
     353             : 
     354           0 : static bool test_winreg_iremotewinspool_openkey(struct torture_context *tctx,
     355             :                                                 struct dcerpc_binding_handle *winreg_bh,
     356             :                                                 struct policy_handle *hklm_handle,
     357             :                                                 const char *keyname,
     358             :                                                 struct policy_handle *_key_handle)
     359             : {
     360           0 :         struct winreg_OpenKey r;
     361           0 :         NTSTATUS status;
     362           0 :         bool ok = true;
     363             : 
     364           0 :         r.in.parent_handle = hklm_handle;
     365           0 :         init_winreg_String(&r.in.keyname, keyname);
     366           0 :         r.in.options = REG_OPTION_NON_VOLATILE;
     367           0 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     368           0 :         r.out.handle = _key_handle;
     369             : 
     370           0 :         status = dcerpc_winreg_OpenKey_r(winreg_bh, tctx, &r);
     371           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "OpenKey failed");
     372             : 
     373           0 :         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
     374           0 : done:
     375             : 
     376           0 :         return ok;
     377             : }
     378             : 
     379           0 : static bool test_winreg_iremotewinspool_queryvalue(struct torture_context *tctx,
     380             :                                                    struct dcerpc_binding_handle *b,
     381             :                                                    struct policy_handle *key_handle,
     382             :                                                    const char *value_name,
     383             :                                                    const char **_valuestr)
     384             : {
     385           0 :         struct winreg_QueryValue r;
     386           0 :         enum winreg_Type type = REG_NONE;
     387           0 :         struct winreg_String valuename;
     388           0 :         DATA_BLOB blob;
     389           0 :         const char *str;
     390           0 :         uint32_t data_size = 0;
     391           0 :         uint32_t data_length = 0;
     392           0 :         uint8_t *data = NULL;
     393           0 :         NTSTATUS status;
     394           0 :         bool ok = true;
     395             : 
     396           0 :         init_winreg_String(&valuename, value_name);
     397             : 
     398           0 :         data = talloc_zero_array(tctx, uint8_t, 0);
     399             : 
     400           0 :         r.in.handle = key_handle;
     401           0 :         r.in.value_name = &valuename;
     402           0 :         r.in.type = &type;
     403           0 :         r.in.data_size = &data_size;
     404           0 :         r.in.data_length = &data_length;
     405           0 :         r.in.data = data;
     406             : 
     407           0 :         r.out.type = &type;
     408           0 :         r.out.data = data;
     409           0 :         r.out.data_size = &data_size;
     410           0 :         r.out.data_length = &data_length;
     411             : 
     412           0 :         status = dcerpc_winreg_QueryValue_r(b, tctx, &r);
     413           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "winreg_QueryValue failure");
     414             : 
     415           0 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
     416           0 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
     417           0 :                 *r.in.data_size = *r.out.data_size;
     418           0 :                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
     419           0 :                 r.in.data = data;
     420           0 :                 r.out.data = data;
     421           0 :                 status = dcerpc_winreg_QueryValue_r(b, tctx, &r);
     422           0 :                 torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "QueryValue failed");
     423             :         }
     424           0 :         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
     425             : 
     426           0 :         torture_assert_int_equal_goto(tctx, *r.out.type, REG_SZ, ok, done, "unexpected type");
     427           0 :         blob = data_blob(r.out.data, *r.out.data_size);
     428           0 :         str = reg_val_data_string(tctx, REG_SZ, blob);
     429             : 
     430           0 :         *_valuestr = str;
     431           0 : done:
     432             : 
     433           0 :         return ok;
     434             : }
     435             : 
     436             : /* Validate the installed driver subkey exists, and the InfPath
     437             :  * value matches the pszDestInfPath from test_UploadPrinterDriverPackage */
     438           0 : static bool test_winreg_validate_driver(struct torture_context *tctx,
     439             :                                         struct dcerpc_pipe *winreg_pipe,
     440             :                                         struct test_driver_info *dinfo)
     441             : {
     442           0 :         struct policy_handle hklm_handle;
     443           0 :         struct policy_handle key_handle;
     444           0 :         char *driver_key = NULL;
     445           0 :         const char *val_name = NULL;
     446           0 :         const char *val_str = NULL;
     447           0 :         bool ok = true;
     448             : 
     449           0 :         struct dcerpc_binding_handle *winreg_bh;
     450           0 :         struct spoolss_AddDriverInfo8 *parsed_dinfo;
     451             : 
     452           0 :         winreg_bh = winreg_pipe->binding_handle;
     453           0 :         parsed_dinfo = dinfo->info;
     454             : 
     455             :         /* OpenHKLM */
     456           0 :         ok = test_winreg_iremotewinspool_openhklm(tctx, winreg_bh, &hklm_handle);
     457           0 :         torture_assert_goto(tctx, ok, ok, done, "Failed to perform winreg OpenHKLM");
     458             : 
     459             :         /* Open registry subkey for the installed print driver */
     460           0 :         driver_key = talloc_asprintf(tctx, "%s\\Environments\\%s\\Drivers\\Version-%d\\%s",
     461             :                                      REG_DRIVER_CONTROL_KEY,
     462             :                                      parsed_dinfo->architecture,
     463           0 :                                      parsed_dinfo->version,
     464             :                                      parsed_dinfo->driver_name);
     465           0 :         torture_assert_not_null_goto(tctx, driver_key, ok, done, "Cannot allocate driver_key string");
     466           0 :         ok = test_winreg_iremotewinspool_openkey(tctx, winreg_bh, &hklm_handle,
     467             :                                                  driver_key,
     468             :                                                  &key_handle);
     469           0 :         torture_assert_goto(tctx, ok, ok, done, "Failed to perform winreg OpenKey");
     470             : 
     471             :         /* Read infpath value and validate this matches what was uploaded */
     472           0 :         val_name = "InfPath";
     473           0 :         ok = test_winreg_iremotewinspool_queryvalue(tctx, winreg_bh, &key_handle, val_name,
     474             :                                                     &val_str);
     475           0 :         torture_assert_goto(tctx, ok, ok, done, "QueryValue failed");
     476             : 
     477           0 :         torture_assert_casestr_equal(tctx, val_str,
     478             :                                  dinfo->uploaded_inf_path,
     479             :                                  "InfPath does not match uploaded inf");
     480           0 : done:
     481             : 
     482           0 :         return ok;
     483             : }
     484             : 
     485           0 : static bool test_init_iremotewinspool_conn(struct torture_context *tctx,
     486             :                                            struct test_iremotewinspool_context *t)
     487             : {
     488           0 :         struct dcerpc_binding *binding = {0};
     489           0 :         bool ok = true;
     490           0 :         NTSTATUS status;
     491             : 
     492           0 :         status = GUID_from_string(IREMOTEWINSPOOL_OBJECT_GUID, &t->object_uuid);
     493           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "failed to parse GUID");
     494             : 
     495           0 :         status = torture_rpc_binding(tctx, &binding);
     496           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "failed to retrieve torture binding");
     497             : 
     498           0 :         status = dcerpc_binding_set_object(binding, t->object_uuid);
     499           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "failed to set object_uuid");
     500             : 
     501           0 :         status = torture_rpc_connection_with_binding(tctx, binding, &t->iremotewinspool_pipe,
     502             :                                                      &ndr_table_iremotewinspool);
     503           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "Error connecting to server");
     504             : 
     505           0 : done:
     506             : 
     507           0 :         return ok;
     508             : 
     509             : }
     510             : 
     511           0 : static bool test_init_iremotewinspool_openprinter(struct torture_context *tctx,
     512             :                                                   struct test_iremotewinspool_context *t)
     513             : {
     514           0 :         struct spoolss_UserLevel1 client_info = {0};
     515           0 :         char *printer_name = NULL;
     516           0 :         bool ok = true;
     517             : 
     518           0 :         printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(t->iremotewinspool_pipe));
     519           0 :         torture_assert_not_null_goto(tctx, printer_name, ok, done, "Cannot allocate memory");
     520             : 
     521           0 :         client_info = test_get_client_info(tctx, WIN_7, 3, SPOOLSS_MINOR_VERSION_0,
     522             :                                            "testclient_machine", "testclient_user");
     523             : 
     524           0 :         ok = test_AsyncOpenPrinter_byprinter(tctx, t, t->iremotewinspool_pipe, printer_name,
     525             :                                              client_info, &t->server_handle);
     526           0 :         torture_assert_goto(tctx, ok, ok, done, "failed to open printserver");
     527             : 
     528           0 :         ok = test_get_environment(tctx, t->iremotewinspool_pipe->binding_handle,
     529             :                                   &t->server_handle, &t->environment);
     530           0 :         torture_assert_goto(tctx, ok, ok, done, "failed to get environment");
     531             : 
     532           0 : done:
     533           0 :         TALLOC_FREE(printer_name);
     534             : 
     535           0 :         return ok;
     536             : }
     537             : 
     538           0 : static bool test_init_driver_info(struct torture_context *tctx,
     539             :                                   struct test_iremotewinspool_context *t)
     540             : {
     541           0 :         bool ok = true;
     542           0 :         const char *abs_inf_path;
     543           0 :         struct test_driver_info *drv_info = {0};
     544             : 
     545           0 :         drv_info = talloc_zero(tctx, struct test_driver_info);
     546           0 :         torture_assert_not_null_goto(tctx, drv_info, ok, done, "Cannot allocate memory");
     547             : 
     548           0 :         t->dinfo = drv_info;
     549             : 
     550           0 :         ok = test_get_driver_torture_options(tctx,
     551             :                                              &drv_info->local_driver_path,
     552             :                                              &drv_info->inf_file,
     553             :                                              &drv_info->driver_name,
     554             :                                              &drv_info->driver_arch,
     555             :                                              &drv_info->core_driver_inf);
     556           0 :         torture_assert_goto(tctx, ok, ok, done, "Failed to get driver torture options");
     557             : 
     558           0 :         ok = test_get_misc_driver_info(tctx, drv_info,
     559             :                                        &abs_inf_path,
     560             :                                        &drv_info->driver_path_len);
     561           0 :         torture_assert_goto(tctx, ok, ok, done, "Failed to get misc driver info");
     562             : 
     563           0 :         ok = parse_inf_driver(tctx, drv_info->driver_name, abs_inf_path, drv_info->driver_arch,
     564             :                               drv_info->core_driver_inf, &drv_info->info);
     565           0 :         torture_assert_goto(tctx, ok, ok, done, "Failed to parse inf driver");
     566             : 
     567             :         /* Ensure that we are trying to install the correct device class:
     568             :          * https://docs.microsoft.com/en-us/windows-hardware/drivers/install/system-defined-device-setup-classes-available-to-vendors
     569             :          */
     570           0 :         if (!(drv_info->info->printer_driver_attributes & PRINTER_DRIVER_CLASS)) {
     571           0 :                                 ok = false;
     572           0 :                                 torture_fail_goto(tctx, done, "Inf file Class value must be Printer");
     573             :         }
     574           0 : done:
     575           0 :         return ok;
     576             : 
     577             : }
     578             : 
     579           0 : static bool test_init_server_and_share_info(struct torture_context *tctx,
     580             :                                             struct test_iremotewinspool_context *t)
     581             : {
     582           0 :         struct GUID guid;
     583           0 :         bool ok = true;
     584             : 
     585           0 :         t->dinfo->server_name = talloc_asprintf(tctx, "%s", dcerpc_server_name(t->iremotewinspool_pipe));
     586           0 :         torture_assert_not_null_goto(tctx, t->dinfo->server_name, ok, done, "Cannot allocate memory");
     587             : 
     588           0 :         t->dinfo->share_name = talloc_strdup(tctx, "print$");
     589           0 :         torture_assert_not_null_goto(tctx, t->dinfo->share_name, ok, done, "Cannot allocate memory");
     590             : 
     591           0 :         guid = GUID_random();
     592           0 :         t->dinfo->print_upload_guid_dir = GUID_string2(tctx, &guid);
     593           0 : done:
     594           0 :         return ok;
     595             : }
     596             : 
     597             : 
     598           0 : static bool torture_rpc_iremotewinspool_drv_setup_common(struct torture_context *tctx,
     599             :                                                      struct test_iremotewinspool_context *t)
     600             : {
     601           0 :         bool ok = true;
     602           0 :         int ret = 0;
     603             : 
     604           0 :         ok = test_init_driver_info(tctx, t);
     605           0 :         torture_assert_goto(tctx, ok, ok, done, "failed to init driver info");
     606             : 
     607           0 :         ok = test_init_iremotewinspool_conn(tctx, t);
     608           0 :         torture_assert_goto(tctx, ok, ok, done, "failed to init iremotewinspool conn");
     609             : 
     610           0 :         ok = test_init_iremotewinspool_openprinter(tctx, t);
     611           0 :         torture_assert_goto(tctx, ok, ok, done, "failed to init iremotewinspool openprinter");
     612             : 
     613           0 :         ok = test_init_server_and_share_info(tctx, t);
     614           0 :         torture_assert_goto(tctx, ok, ok, done, "failed to init server and share info");
     615             : 
     616           0 :         ret = smb_connect_print_share(tctx, t->dinfo->server_name, t->dinfo->share_name, &t->dinfo->cli);
     617           0 :         torture_assert_goto(tctx, ret, ok, done, "Failed to connect to print share");
     618             : 
     619           0 : done:
     620             : 
     621           0 :         return ok;
     622             : }
     623             : 
     624           0 : static bool torture_rpc_iremotewinspool_drv_setup(struct torture_context *tctx,
     625             :                                               void **data)
     626             : {
     627           0 :         struct test_iremotewinspool_context *t;
     628             : 
     629           0 :         *data = t = talloc_zero(tctx, struct test_iremotewinspool_context);
     630             : 
     631           0 :         return torture_rpc_iremotewinspool_drv_setup_common(tctx, t);
     632             : }
     633             : 
     634           0 : static bool torture_rpc_iremotewinspool_drv_teardown_common(struct torture_context *tctx,
     635             :                                                         struct test_iremotewinspool_context *t)
     636             : {
     637           0 :         smbcli_deltree(t->dinfo->cli->tree, t->dinfo->print_upload_guid_dir);
     638           0 :         smb_raw_exit(t->dinfo->cli->session);
     639             : 
     640           0 :         test_uninstall_printer_driver(tctx, t);
     641           0 :         test_remove_driver_package(tctx, t);
     642             : 
     643           0 :         test_AsyncClosePrinter_byhandle(tctx, t, t->iremotewinspool_pipe, &t->server_handle);
     644             : 
     645           0 :         return true;
     646             : }
     647             : 
     648           0 : static bool torture_rpc_iremotewinspool_drv_teardown(struct torture_context *tctx,
     649             :                                                  void *data)
     650             : {
     651           0 :         struct test_iremotewinspool_context *t = talloc_get_type(data, struct test_iremotewinspool_context);
     652           0 :         bool ret;
     653             : 
     654           0 :         ret = torture_rpc_iremotewinspool_drv_teardown_common(tctx, t);
     655           0 :         talloc_free(t);
     656             : 
     657           0 :         return ret;
     658             : }
     659             : 
     660             : /* Creates {GUID} directory inside //server/print$ then copies driver files
     661             :  * and directories from torture option driver_path to this directory over smb */
     662           0 : static bool test_CopyDriverFiles(struct torture_context *tctx,
     663             :                                    void *private_data)
     664             : {
     665           0 :         struct test_iremotewinspool_context *ctx =
     666           0 :         talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
     667             : 
     668           0 :         bool ret = false;
     669           0 :         bool ok = true;
     670           0 :         NTSTATUS status;
     671             : 
     672           0 :         status = smbcli_mkdir(ctx->dinfo->cli->tree, ctx->dinfo->print_upload_guid_dir);
     673           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "Failed to create upload directory");
     674             : 
     675             :         /* Walk the provided torture option driver_path file tree, creating the directory hierarchy and
     676             :          * copying all files to print$/{GUID}/ share */
     677           0 :         ret = tftw(tctx, ctx->dinfo->local_driver_path, copy_driver_files, TFTW_MAX_DEPTH, ctx->dinfo);
     678           0 :         torture_assert_int_equal_goto(tctx, ret, 0, ok, done, "Failed to copy driver files to print$/{GUID}/ dir");
     679             : 
     680           0 : done:
     681             : 
     682           0 :         return ok;
     683             : }
     684             : 
     685             : /*
     686             :  * Upload print driver package files and inf file, preparing the print server
     687             :  * for driver installation
     688             :  */
     689           0 : static bool test_UploadPrinterDriverPackage(struct torture_context *tctx,
     690             :                                             void *private_data)
     691             : {
     692           0 :         struct test_iremotewinspool_context *ctx =
     693           0 :                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
     694             : 
     695           0 :         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
     696           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     697             : 
     698           0 :         struct spoolss_AddDriverInfo8 *parsed_dinfo;
     699           0 :         struct winspool_AsyncUploadPrinterDriverPackage r;
     700           0 :         uint32_t pcchDestInfPath = 0;
     701           0 :         NTSTATUS status;
     702           0 :         bool ok = true;
     703             : 
     704           0 :         parsed_dinfo = ctx->dinfo->info;
     705             : 
     706           0 :         r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     707           0 :         torture_assert_not_null_goto(tctx, r.in.pszServer, ok, done, "Cannot allocate memory");
     708             : 
     709           0 :         r.in.pszInfPath = talloc_asprintf(tctx, "\\\\%s\\%s\\%s\\%s", ctx->dinfo->server_name,
     710           0 :                                                                       ctx->dinfo->share_name,
     711           0 :                                                                       ctx->dinfo->print_upload_guid_dir,
     712           0 :                                                                       ctx->dinfo->inf_file);
     713           0 :         torture_assert_not_null_goto(tctx, r.in.pszInfPath, ok, done, "Cannot allocate memory");
     714             : 
     715           0 :         r.in.pszEnvironment = parsed_dinfo->architecture;
     716             :         /* Upload driver package files even if the driver package is already present
     717             :          * on the print server */
     718           0 :         r.in.dwFlags = UPDP_UPLOAD_ALWAYS;
     719           0 :         pcchDestInfPath = 260;
     720           0 :         r.in.pszDestInfPath = NULL;
     721           0 :         r.in.pcchDestInfPath = &pcchDestInfPath;
     722           0 :         r.out.pszDestInfPath = NULL;
     723           0 :         r.out.pcchDestInfPath = &pcchDestInfPath;
     724             : 
     725           0 :         r.in.pszDestInfPath = talloc_zero(tctx, const char);
     726           0 :         torture_assert_not_null_goto(tctx, r.in.pszDestInfPath, ok, done, "Cannot allocate memory");
     727           0 :         r.out.pszDestInfPath = talloc_zero(tctx, const char);
     728           0 :         torture_assert_not_null_goto(tctx, r.out.pszDestInfPath, ok, done, "Cannot allocate memory");
     729             : 
     730           0 :         status = dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r);
     731           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "AsyncUploadPrinterDriverPackage failed");
     732             : 
     733           0 :         torture_assert_hresult_ok(tctx, r.out.result, "AsyncUploadPrinterDriverPackage failed");
     734             : 
     735           0 :         ctx->dinfo->uploaded_inf_path = talloc_strdup(tctx, r.out.pszDestInfPath);
     736           0 :         torture_assert_not_null_goto(tctx, ctx->dinfo->uploaded_inf_path, ok, done, "Cannot allocate memory");
     737             : 
     738           0 : done:
     739             : 
     740           0 :         return ok;
     741             : }
     742             : 
     743             : /* Install the driver that was successfully uploaded to the printer driver
     744             :  * store, note that Windows validates the pszDriverName as mentioned below */
     745           0 : static bool test_InstallPrinterDriverFromPackage(struct torture_context *tctx,
     746             :                                              void *private_data)
     747             : {
     748           0 :         struct test_iremotewinspool_context *ctx =
     749           0 :                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
     750             : 
     751           0 :         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
     752           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     753             : 
     754           0 :         char *abs_inf_path = NULL;
     755           0 :         struct spoolss_AddDriverInfo8 *parsed_dinfo;
     756           0 :         struct winspool_AsyncInstallPrinterDriverFromPackage r;
     757           0 :         bool ok = true;
     758           0 :         NTSTATUS status;
     759             : 
     760           0 :         parsed_dinfo = ctx->dinfo->info;
     761             : 
     762           0 :         r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     763           0 :         torture_assert_not_null_goto(tctx, r.in.pszServer, ok, done, "Cannot allocate memory");
     764             : 
     765             :         /* output string(pszDestInfPath) from test_UploadPrinterDriverPackage() */
     766           0 :         r.in.pszInfPath = talloc_strdup(tctx, ctx->dinfo->uploaded_inf_path);
     767           0 :         torture_assert_not_null_goto(tctx, r.in.pszInfPath, ok, done, "Cannot allocate memory");
     768             : 
     769           0 :         abs_inf_path = talloc_asprintf(tctx, "%s/%s", ctx->dinfo->local_driver_path, ctx->dinfo->inf_file);
     770           0 :         torture_assert_not_null_goto(tctx, abs_inf_path, ok, done, "Cannot allocate memory");
     771             : 
     772           0 :         r.in.pszEnvironment = parsed_dinfo->architecture;
     773           0 :         torture_assert_not_null_goto(tctx, r.in.pszEnvironment, ok, done, "Cannot allocate memory");
     774             : 
     775             :         /* Windows validates the print driver name by checking the pszDriverName input against the inf file:
     776             :          * 1) "DriverName" value
     777             :          * 2) "CompatName" value
     778             :          * 3) left-hand-side value under the [Model] section
     779             :          * otherwise ERROR_UNKNOWN_PRINTER_DRIVER is returned */
     780           0 :         r.in.pszDriverName = parsed_dinfo->driver_name;
     781           0 :         torture_assert_not_null_goto(tctx, r.in.pszDriverName, ok, done, "Cannot allocate memory");
     782             : 
     783             :         /* All files should be installed, even if doing so would overwrite some newer
     784             :          * versions */
     785           0 :         r.in.dwFlags = IPDFP_COPY_ALL_FILES;
     786             : 
     787           0 :         status = dcerpc_winspool_AsyncInstallPrinterDriverFromPackage_r(b, tctx, &r);
     788           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "AsyncInstallPrinterDriverFromPackage failed");
     789             : 
     790           0 :         torture_assert_hresult_ok(tctx, r.out.result, "AsyncInstallPrinterDriverFromPackage failed");
     791           0 : done:
     792           0 :         TALLOC_FREE(abs_inf_path);
     793             : 
     794           0 :         return ok;
     795             : }
     796             : 
     797             : /* Check the registry to validate the print driver installed successfully */
     798           0 : static bool test_ValidatePrinterDriverInstalled(struct torture_context *tctx,
     799             :                                                  void *private_data)
     800             : {
     801           0 :         struct test_iremotewinspool_context *ctx =
     802           0 :                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
     803             : 
     804           0 :         struct dcerpc_pipe *winreg_pipe = NULL;
     805           0 :         NTSTATUS status;
     806           0 :         bool ok = true;
     807             : 
     808             :         /* winreg is not available over ncacn_ip_tcp */
     809           0 :         status = torture_rpc_connection_transport(tctx, &winreg_pipe, &ndr_table_winreg, NCACN_NP, 0, 0);
     810           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_NOT_AVAILABLE)) {
     811             :                 /* retry */
     812           0 :                 status = torture_rpc_connection_transport(tctx, &winreg_pipe, &ndr_table_winreg, NCACN_NP, 0, 0);
     813             :         }
     814           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "Failed to connect to winreg");
     815             : 
     816           0 :         ok = test_winreg_validate_driver(tctx, winreg_pipe, ctx->dinfo);
     817           0 :         torture_assert_goto(tctx, ok, ok, done, "Failed to validate driver with winreg");
     818             : 
     819           0 : done:
     820           0 :         TALLOC_FREE(winreg_pipe);
     821             : 
     822           0 :         return ok;
     823             : }
     824             : 
     825        2354 : struct torture_suite *torture_rpc_iremotewinspool_drv(TALLOC_CTX *mem_ctx)
     826             : {
     827        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "iremotewinspool_driver");
     828        2354 :         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "drivers");
     829             : 
     830        2354 :         torture_tcase_set_fixture(tcase,
     831             :                                   torture_rpc_iremotewinspool_drv_setup,
     832             :                                   torture_rpc_iremotewinspool_drv_teardown);
     833             : 
     834        2354 :         torture_tcase_add_simple_test(tcase, "CopyDriverFiles", test_CopyDriverFiles);
     835        2354 :         torture_tcase_add_simple_test(tcase, "UploadPrinterDriverPackage", test_UploadPrinterDriverPackage);
     836        2354 :         torture_tcase_add_simple_test(tcase, "InstallPrinterDriverFromPackage", test_InstallPrinterDriverFromPackage);
     837        2354 :         torture_tcase_add_simple_test(tcase, "ValidatePrinterDriverInstalled", test_ValidatePrinterDriverInstalled);
     838             : 
     839        2354 :         return suite;
     840             : }

Generated by: LCOV version 1.14