Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/rpc_client/init_spoolss.c
Line
Count
Source
1
/*
2
 *  Unix SMB/CIFS implementation.
3
 *  RPC Pipe client / server routines
4
 *  Copyright (C) Guenther Deschner                  2009.
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 "../librpc/gen_ndr/ndr_spoolss.h"
22
#include "rpc_client/init_spoolss.h"
23
#include "../libcli/security/security.h"
24
#include "secrets.h"
25
#include "passdb/machine_sid.h"
26
27
/*******************************************************************
28
********************************************************************/
29
30
bool init_systemtime(struct spoolss_Time *r,
31
         struct tm *unixtime)
32
0
{
33
0
  if (!r || !unixtime) {
34
0
    return false;
35
0
  }
36
37
0
  r->year   = unixtime->tm_year+1900;
38
0
  r->month  = unixtime->tm_mon+1;
39
0
  r->day_of_week  = unixtime->tm_wday;
40
0
  r->day    = unixtime->tm_mday;
41
0
  r->hour   = unixtime->tm_hour;
42
0
  r->minute = unixtime->tm_min;
43
0
  r->second = unixtime->tm_sec;
44
0
  r->millisecond  = 0;
45
46
0
  return true;
47
0
}
48
49
time_t spoolss_Time_to_time_t(const struct spoolss_Time *r)
50
0
{
51
0
  struct tm unixtime = {
52
0
    .tm_year  = r->year - 1900,
53
0
    .tm_mon   = r->month - 1,
54
0
    .tm_wday  = r->day_of_week,
55
0
    .tm_mday  = r->day,
56
0
    .tm_hour  = r->hour,
57
0
    .tm_min   = r->minute,
58
0
    .tm_sec   = r->second,
59
0
  };
60
61
0
  return mktime(&unixtime);
62
0
}
63
64
/*******************************************************************
65
 ********************************************************************/
66
67
bool spoolss_timestr_to_NTTIME(const char *str,
68
             NTTIME *data)
69
0
{
70
0
  struct tm tm;
71
0
  time_t t;
72
73
0
  if (strequal(str, "01/01/1601")) {
74
0
    *data = 0;
75
0
    return true;
76
0
  }
77
78
0
  ZERO_STRUCT(tm);
79
80
0
  if (sscanf(str, "%d/%d/%d",
81
0
       &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) {
82
0
    return false;
83
0
  }
84
0
  tm.tm_mon -= 1;
85
0
  tm.tm_year -= 1900;
86
0
  tm.tm_isdst = -1;
87
88
0
  t = mktime(&tm);
89
0
  unix_to_nt_time(data, t);
90
91
0
  return true;
92
0
}
93
94
/*******************************************************************
95
 ********************************************************************/
96
97
bool spoolss_driver_version_to_qword(const char *str,
98
             uint64_t *data)
99
0
{
100
0
  unsigned int v1, v2, v3, v4 = 0;
101
102
0
  if ((sscanf(str, "%u.%u.%u.%u", &v1, &v2, &v3, &v4) != 4) &&
103
0
      (sscanf(str, "%u.%u.%u", &v1, &v2, &v3) != 3))
104
0
  {
105
0
    return false;
106
0
  }
107
108
0
  *data = ((uint64_t)(v1 & 0xFFFF) << 48) +
109
0
    ((uint64_t)(v2 & 0xFFFF) << 32) +
110
0
    ((uint64_t)(v3 & 0xFFFF) << 16) +
111
0
    (uint64_t)(v4 & 0xFFFF);
112
113
0
  return true;
114
0
}
115
116
/*******************************************************************
117
 ********************************************************************/
118
119
WERROR pull_spoolss_PrinterData(TALLOC_CTX *mem_ctx,
120
        const DATA_BLOB *blob,
121
        union spoolss_PrinterData *data,
122
        enum winreg_Type type)
123
0
{
124
0
  enum ndr_err_code ndr_err;
125
0
  ndr_err = ndr_pull_union_blob(blob, mem_ctx, data, type,
126
0
      (ndr_pull_flags_fn_t)ndr_pull_spoolss_PrinterData);
127
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
128
0
    return WERR_GEN_FAILURE;
129
0
  }
130
0
  return WERR_OK;
131
0
}
132
133
/*******************************************************************
134
 ********************************************************************/
135
136
WERROR push_spoolss_PrinterData(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
137
        enum winreg_Type type,
138
        union spoolss_PrinterData *data)
139
0
{
140
0
  enum ndr_err_code ndr_err;
141
0
  ndr_err = ndr_push_union_blob(blob, mem_ctx, data, type,
142
0
      (ndr_push_flags_fn_t)ndr_push_spoolss_PrinterData);
143
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
144
0
    return WERR_GEN_FAILURE;
145
0
  }
146
0
  return WERR_OK;
147
0
}
148
149
/*******************************************************************
150
 ********************************************************************/
151
152
void spoolss_printerinfo2_to_setprinterinfo2(const struct spoolss_PrinterInfo2 *i,
153
               struct spoolss_SetPrinterInfo2 *s)
154
0
{
155
0
  s->servername   = i->servername;
156
0
  s->printername    = i->printername;
157
0
  s->sharename    = i->sharename;
158
0
  s->portname   = i->portname;
159
0
  s->drivername   = i->drivername;
160
0
  s->comment    = i->comment;
161
0
  s->location   = i->location;
162
0
  s->devmode_ptr    = 0;
163
0
  s->sepfile    = i->sepfile;
164
0
  s->printprocessor = i->printprocessor;
165
0
  s->datatype   = i->datatype;
166
0
  s->parameters   = i->parameters;
167
0
  s->secdesc_ptr    = 0;
168
0
  s->attributes   = i->attributes;
169
0
  s->priority   = i->priority;
170
0
  s->defaultpriority  = i->defaultpriority;
171
0
  s->starttime    = i->starttime;
172
0
  s->untiltime    = i->untiltime;
173
0
  s->status   = i->status;
174
0
  s->cjobs    = i->cjobs;
175
0
  s->averageppm   = i->averageppm;
176
0
}
177
178
/****************************************************************************
179
****************************************************************************/
180
181
bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
182
            struct spoolss_DriverInfo8 *_info8)
183
0
{
184
0
  struct spoolss_DriverInfo8 info8;
185
186
0
  ZERO_STRUCT(info8);
187
188
0
  switch (r->level) {
189
0
  case 3:
190
0
    info8.version   = r->info.info3->version;
191
0
    info8.driver_name = r->info.info3->driver_name;
192
0
    info8.architecture  = r->info.info3->architecture;
193
0
    info8.driver_path = r->info.info3->driver_path;
194
0
    info8.data_file   = r->info.info3->data_file;
195
0
    info8.config_file = r->info.info3->config_file;
196
0
    info8.help_file   = r->info.info3->help_file;
197
0
    info8.monitor_name  = r->info.info3->monitor_name;
198
0
    info8.default_datatype  = r->info.info3->default_datatype;
199
0
    if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
200
0
      info8.dependent_files = r->info.info3->dependent_files->string;
201
0
    }
202
0
    break;
203
0
  case 6:
204
0
    info8.version   = r->info.info6->version;
205
0
    info8.driver_name = r->info.info6->driver_name;
206
0
    info8.architecture  = r->info.info6->architecture;
207
0
    info8.driver_path = r->info.info6->driver_path;
208
0
    info8.data_file   = r->info.info6->data_file;
209
0
    info8.config_file = r->info.info6->config_file;
210
0
    info8.help_file   = r->info.info6->help_file;
211
0
    info8.monitor_name  = r->info.info6->monitor_name;
212
0
    info8.default_datatype  = r->info.info6->default_datatype;
213
0
    if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
214
0
      info8.dependent_files = r->info.info6->dependent_files->string;
215
0
    }
216
0
    info8.driver_date = r->info.info6->driver_date;
217
0
    info8.driver_version  = r->info.info6->driver_version;
218
0
    info8.manufacturer_name = r->info.info6->manufacturer_name;
219
0
    info8.manufacturer_url  = r->info.info6->manufacturer_url;
220
0
    info8.hardware_id = r->info.info6->hardware_id;
221
0
    info8.provider    = r->info.info6->provider;
222
0
    break;
223
0
  case 8:
224
0
    info8.version   = r->info.info8->version;
225
0
    info8.driver_name = r->info.info8->driver_name;
226
0
    info8.architecture  = r->info.info8->architecture;
227
0
    info8.driver_path = r->info.info8->driver_path;
228
0
    info8.data_file   = r->info.info8->data_file;
229
0
    info8.config_file = r->info.info8->config_file;
230
0
    info8.help_file   = r->info.info8->help_file;
231
0
    info8.monitor_name  = r->info.info8->monitor_name;
232
0
    info8.default_datatype  = r->info.info8->default_datatype;
233
0
    if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
234
0
      info8.dependent_files = r->info.info8->dependent_files->string;
235
0
    }
236
0
    if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
237
0
      info8.previous_names  = r->info.info8->previous_names->string;
238
0
    }
239
0
    info8.driver_date = r->info.info8->driver_date;
240
0
    info8.driver_version  = r->info.info8->driver_version;
241
0
    info8.manufacturer_name = r->info.info8->manufacturer_name;
242
0
    info8.manufacturer_url  = r->info.info8->manufacturer_url;
243
0
    info8.hardware_id = r->info.info8->hardware_id;
244
0
    info8.provider    = r->info.info8->provider;
245
0
    info8.print_processor = r->info.info8->print_processor;
246
0
    info8.vendor_setup  = r->info.info8->vendor_setup;
247
0
    if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
248
0
      info8.color_profiles = r->info.info8->color_profiles->string;
249
0
    }
250
0
    info8.inf_path    = r->info.info8->inf_path;
251
0
    info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
252
0
    if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
253
0
      info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
254
0
    }
255
0
    info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
256
0
    info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
257
0
    break;
258
0
  default:
259
0
    return false;
260
0
  }
261
262
0
  *_info8 = info8;
263
264
0
  return true;
265
0
}
266
267
/****************************************************************************
268
 Create and allocate a default devicemode.
269
****************************************************************************/
270
271
WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
272
              const char *devicename,
273
              struct spoolss_DeviceMode **devmode)
274
0
{
275
0
  struct spoolss_DeviceMode *dm;
276
0
  char *dname;
277
278
0
  dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
279
0
  if (dm == NULL) {
280
0
    return WERR_NOT_ENOUGH_MEMORY;
281
0
  }
282
283
0
  dname = talloc_asprintf(dm, "%s", devicename);
284
0
  if (dname == NULL) {
285
0
    return WERR_NOT_ENOUGH_MEMORY;
286
0
  }
287
0
  if (strlen(dname) > MAXDEVICENAME) {
288
0
    dname[MAXDEVICENAME] = '\0';
289
0
  }
290
0
  dm->devicename = dname;
291
292
0
  dm->formname = talloc_strdup(dm, "Letter");
293
0
  if (dm->formname == NULL) {
294
0
    return WERR_NOT_ENOUGH_MEMORY;
295
0
  }
296
297
0
  dm->specversion          = DMSPEC_NT4_AND_ABOVE;
298
0
  dm->driverversion        = 0x0400;
299
0
  dm->size                 = 0x00DC;
300
0
  dm->__driverextra_length = 0;
301
0
  dm->fields               = DEVMODE_FORMNAME |
302
0
           DEVMODE_TTOPTION |
303
0
           DEVMODE_PRINTQUALITY |
304
0
           DEVMODE_DEFAULTSOURCE |
305
0
           DEVMODE_COPIES |
306
0
           DEVMODE_SCALE |
307
0
           DEVMODE_PAPERSIZE |
308
0
           DEVMODE_ORIENTATION;
309
0
  dm->orientation          = DMORIENT_PORTRAIT;
310
0
  dm->papersize            = DMPAPER_LETTER;
311
0
  dm->paperlength          = 0;
312
0
  dm->paperwidth           = 0;
313
0
  dm->scale                = 0x64;
314
0
  dm->copies               = 1;
315
0
  dm->defaultsource        = DMBIN_FORMSOURCE;
316
0
  dm->printquality         = DMRES_HIGH;           /* 0x0258 */
317
0
  dm->color                = DMRES_MONOCHROME;
318
0
  dm->duplex               = DMDUP_SIMPLEX;
319
0
  dm->yresolution          = 0;
320
0
  dm->ttoption             = DMTT_SUBDEV;
321
0
  dm->collate              = DMCOLLATE_FALSE;
322
0
  dm->icmmethod            = 0;
323
0
  dm->icmintent            = 0;
324
0
  dm->mediatype            = 0;
325
0
  dm->dithertype           = 0;
326
327
0
  dm->logpixels            = 0;
328
0
  dm->bitsperpel           = 0;
329
0
  dm->pelswidth            = 0;
330
0
  dm->pelsheight           = 0;
331
0
  dm->displayflags         = 0;
332
0
  dm->displayfrequency     = 0;
333
0
  dm->reserved1            = 0;
334
0
  dm->reserved2            = 0;
335
0
  dm->panningwidth         = 0;
336
0
  dm->panningheight        = 0;
337
338
0
  dm->driverextra_data.data = NULL;
339
0
  dm->driverextra_data.length = 0;
340
341
0
        *devmode = dm;
342
0
  return WERR_OK;
343
0
}
344
345
WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
346
              struct spoolss_security_descriptor **secdesc)
347
0
{
348
0
  struct security_ace ace[7] = {0}; /* max number of ace entries */
349
0
  int i = 0;
350
0
  uint32_t sa;
351
0
  struct security_acl *psa = NULL;
352
0
  struct security_descriptor *psd = NULL;
353
0
  struct dom_sid adm_sid;
354
0
  size_t sd_size;
355
356
  /* Create an ACE where Everyone is allowed to print */
357
358
0
  sa = PRINTER_ACE_PRINT;
359
0
  init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
360
0
         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
361
362
  /* Add the domain admins group if we are a DC */
363
364
0
  if ( IS_DC ) {
365
0
    struct dom_sid domadmins_sid;
366
367
0
    sid_compose(&domadmins_sid, get_global_sam_sid(),
368
0
          DOMAIN_RID_ADMINS);
369
370
0
    sa = PRINTER_ACE_FULL_CONTROL;
371
0
    init_sec_ace(&ace[i++], &domadmins_sid,
372
0
      SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
373
0
      SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
374
0
    init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
375
0
      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
376
0
  }
377
0
  else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
378
0
    sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
379
380
0
    sa = PRINTER_ACE_FULL_CONTROL;
381
0
    init_sec_ace(&ace[i++], &adm_sid,
382
0
      SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
383
0
      SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
384
0
    init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
385
0
      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
386
0
  }
387
388
  /* add BUILTIN\Administrators as FULL CONTROL */
389
390
0
  sa = PRINTER_ACE_FULL_CONTROL;
391
0
  init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
392
0
    SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
393
0
    SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
394
0
  init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
395
0
    SEC_ACE_TYPE_ACCESS_ALLOWED,
396
0
    sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
397
398
  /* add BUILTIN\Print Operators as FULL CONTROL */
399
400
0
  sa = PRINTER_ACE_FULL_CONTROL;
401
0
  init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
402
0
    SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
403
0
    SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
404
0
  init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
405
0
    SEC_ACE_TYPE_ACCESS_ALLOWED,
406
0
    sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
407
408
  /* Make the security descriptor owned by the BUILTIN\Administrators */
409
410
  /* The ACL revision number in rpc_secdesc.h differs from the one
411
     created by NT when setting ACE entries in printer
412
     descriptors.  NT4 complains about the property being edited by a
413
     NT5 machine. */
414
415
0
  if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
416
0
    psd = make_sec_desc(mem_ctx,
417
0
            SD_REVISION,
418
0
            SEC_DESC_SELF_RELATIVE,
419
0
            &global_sid_Builtin_Administrators,
420
0
            &global_sid_Builtin_Administrators,
421
0
            NULL,
422
0
            psa,
423
0
            &sd_size);
424
0
  }
425
426
0
  if (psd == NULL) {
427
0
    DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
428
0
    return WERR_NOT_ENOUGH_MEMORY;
429
0
  }
430
431
0
  DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
432
0
     (unsigned int)sd_size));
433
434
0
  *secdesc = psd;
435
436
0
  return WERR_OK;
437
0
}
438
439
const char *spoolss_get_short_filesys_environment(const char *environment)
440
0
{
441
0
  if (strequal(environment, SPOOLSS_ARCHITECTURE_x64)) {
442
0
    return "amd64";
443
0
  } else if (strequal(environment, SPOOLSS_ARCHITECTURE_NT_X86)) {
444
0
    return "x86";
445
0
  } else {
446
0
    return NULL;
447
0
  }
448
0
}
449
450
/* Windows 7 and Windows Server 2008 R2 */
451
0
#define GLOBAL_SPOOLSS_CLIENT_OS_MAJOR_DEFAULT 6
452
0
#define GLOBAL_SPOOLSS_CLIENT_OS_MINOR_DEFAULT 1
453
0
#define GLOBAL_SPOOLSS_CLIENT_OS_BUILD_DEFAULT 7007
454
455
WERROR spoolss_init_spoolss_UserLevel1(TALLOC_CTX *mem_ctx,
456
               const char *username,
457
               struct spoolss_UserLevel1 *r)
458
0
{
459
0
  ZERO_STRUCTP(r);
460
461
0
  r->size   = 28;
462
0
  r->client = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
463
0
  W_ERROR_HAVE_NO_MEMORY(r->client);
464
0
  r->user   = talloc_strdup(mem_ctx, username);
465
0
  W_ERROR_HAVE_NO_MEMORY(r->user);
466
0
  r->processor  = 0;
467
468
0
  r->major  = lp_parm_int(GLOBAL_SECTION_SNUM,
469
0
              "spoolss_client", "os_major",
470
0
              GLOBAL_SPOOLSS_CLIENT_OS_MAJOR_DEFAULT);
471
0
  r->minor  = lp_parm_int(GLOBAL_SECTION_SNUM,
472
0
              "spoolss_client", "os_minor",
473
0
              GLOBAL_SPOOLSS_CLIENT_OS_MINOR_DEFAULT);
474
0
  r->build  = lp_parm_int(GLOBAL_SECTION_SNUM,
475
0
              "spoolss_client", "os_build",
476
0
              GLOBAL_SPOOLSS_CLIENT_OS_BUILD_DEFAULT);
477
478
0
  return WERR_OK;
479
0
}