2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Guenther Deschner 2009.
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.
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.
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/>.
21 #include "../librpc/gen_ndr/ndr_spoolss.h"
22 #include "rpc_client/init_spoolss.h"
23 #include "../libcli/security/security.h"
25 #include "passdb/machine_sid.h"
27 /*******************************************************************
28 ********************************************************************/
30 bool init_systemtime(struct spoolss_Time
*r
,
33 if (!r
|| !unixtime
) {
37 r
->year
= unixtime
->tm_year
+1900;
38 r
->month
= unixtime
->tm_mon
+1;
39 r
->day_of_week
= unixtime
->tm_wday
;
40 r
->day
= unixtime
->tm_mday
;
41 r
->hour
= unixtime
->tm_hour
;
42 r
->minute
= unixtime
->tm_min
;
43 r
->second
= unixtime
->tm_sec
;
49 time_t spoolss_Time_to_time_t(const struct spoolss_Time
*r
)
51 struct tm unixtime
= {
52 .tm_year
= r
->year
- 1900,
53 .tm_mon
= r
->month
- 1,
54 .tm_wday
= r
->day_of_week
,
61 return mktime(&unixtime
);
64 /*******************************************************************
65 ********************************************************************/
67 bool spoolss_timestr_to_NTTIME(const char *str
,
73 if (strequal(str
, "01/01/1601")) {
80 if (sscanf(str
, "%d/%d/%d",
81 &tm
.tm_mon
, &tm
.tm_mday
, &tm
.tm_year
) != 3) {
89 unix_to_nt_time(data
, t
);
94 /*******************************************************************
95 ********************************************************************/
97 bool spoolss_driver_version_to_qword(const char *str
,
100 unsigned int v1
, v2
, v3
, v4
= 0;
102 if ((sscanf(str
, "%u.%u.%u.%u", &v1
, &v2
, &v3
, &v4
) != 4) &&
103 (sscanf(str
, "%u.%u.%u", &v1
, &v2
, &v3
) != 3))
108 *data
= ((uint64_t)(v1
& 0xFFFF) << 48) +
109 ((uint64_t)(v2
& 0xFFFF) << 32) +
110 ((uint64_t)(v3
& 0xFFFF) << 16) +
111 (uint64_t)(v4
& 0xFFFF);
116 /*******************************************************************
117 ********************************************************************/
119 WERROR
pull_spoolss_PrinterData(TALLOC_CTX
*mem_ctx
,
120 const DATA_BLOB
*blob
,
121 union spoolss_PrinterData
*data
,
122 enum winreg_Type type
)
124 enum ndr_err_code ndr_err
;
125 ndr_err
= ndr_pull_union_blob(blob
, mem_ctx
, data
, type
,
126 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PrinterData
);
127 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
128 return WERR_GEN_FAILURE
;
133 /*******************************************************************
134 ********************************************************************/
136 WERROR
push_spoolss_PrinterData(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*blob
,
137 enum winreg_Type type
,
138 union spoolss_PrinterData
*data
)
140 enum ndr_err_code ndr_err
;
141 ndr_err
= ndr_push_union_blob(blob
, mem_ctx
, data
, type
,
142 (ndr_push_flags_fn_t
)ndr_push_spoolss_PrinterData
);
143 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
144 return WERR_GEN_FAILURE
;
149 /*******************************************************************
150 ********************************************************************/
152 void spoolss_printerinfo2_to_setprinterinfo2(const struct spoolss_PrinterInfo2
*i
,
153 struct spoolss_SetPrinterInfo2
*s
)
155 s
->servername
= i
->servername
;
156 s
->printername
= i
->printername
;
157 s
->sharename
= i
->sharename
;
158 s
->portname
= i
->portname
;
159 s
->drivername
= i
->drivername
;
160 s
->comment
= i
->comment
;
161 s
->location
= i
->location
;
163 s
->sepfile
= i
->sepfile
;
164 s
->printprocessor
= i
->printprocessor
;
165 s
->datatype
= i
->datatype
;
166 s
->parameters
= i
->parameters
;
168 s
->attributes
= i
->attributes
;
169 s
->priority
= i
->priority
;
170 s
->defaultpriority
= i
->defaultpriority
;
171 s
->starttime
= i
->starttime
;
172 s
->untiltime
= i
->untiltime
;
173 s
->status
= i
->status
;
175 s
->averageppm
= i
->averageppm
;
178 /****************************************************************************
179 ****************************************************************************/
181 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr
*r
,
182 struct spoolss_DriverInfo8
*_info8
)
184 struct spoolss_DriverInfo8 info8
;
190 info8
.version
= r
->info
.info3
->version
;
191 info8
.driver_name
= r
->info
.info3
->driver_name
;
192 info8
.architecture
= r
->info
.info3
->architecture
;
193 info8
.driver_path
= r
->info
.info3
->driver_path
;
194 info8
.data_file
= r
->info
.info3
->data_file
;
195 info8
.config_file
= r
->info
.info3
->config_file
;
196 info8
.help_file
= r
->info
.info3
->help_file
;
197 info8
.monitor_name
= r
->info
.info3
->monitor_name
;
198 info8
.default_datatype
= r
->info
.info3
->default_datatype
;
199 if (r
->info
.info3
->dependent_files
&& r
->info
.info3
->dependent_files
->string
) {
200 info8
.dependent_files
= r
->info
.info3
->dependent_files
->string
;
204 info8
.version
= r
->info
.info6
->version
;
205 info8
.driver_name
= r
->info
.info6
->driver_name
;
206 info8
.architecture
= r
->info
.info6
->architecture
;
207 info8
.driver_path
= r
->info
.info6
->driver_path
;
208 info8
.data_file
= r
->info
.info6
->data_file
;
209 info8
.config_file
= r
->info
.info6
->config_file
;
210 info8
.help_file
= r
->info
.info6
->help_file
;
211 info8
.monitor_name
= r
->info
.info6
->monitor_name
;
212 info8
.default_datatype
= r
->info
.info6
->default_datatype
;
213 if (r
->info
.info6
->dependent_files
&& r
->info
.info6
->dependent_files
->string
) {
214 info8
.dependent_files
= r
->info
.info6
->dependent_files
->string
;
216 info8
.driver_date
= r
->info
.info6
->driver_date
;
217 info8
.driver_version
= r
->info
.info6
->driver_version
;
218 info8
.manufacturer_name
= r
->info
.info6
->manufacturer_name
;
219 info8
.manufacturer_url
= r
->info
.info6
->manufacturer_url
;
220 info8
.hardware_id
= r
->info
.info6
->hardware_id
;
221 info8
.provider
= r
->info
.info6
->provider
;
224 info8
.version
= r
->info
.info8
->version
;
225 info8
.driver_name
= r
->info
.info8
->driver_name
;
226 info8
.architecture
= r
->info
.info8
->architecture
;
227 info8
.driver_path
= r
->info
.info8
->driver_path
;
228 info8
.data_file
= r
->info
.info8
->data_file
;
229 info8
.config_file
= r
->info
.info8
->config_file
;
230 info8
.help_file
= r
->info
.info8
->help_file
;
231 info8
.monitor_name
= r
->info
.info8
->monitor_name
;
232 info8
.default_datatype
= r
->info
.info8
->default_datatype
;
233 if (r
->info
.info8
->dependent_files
&& r
->info
.info8
->dependent_files
->string
) {
234 info8
.dependent_files
= r
->info
.info8
->dependent_files
->string
;
236 if (r
->info
.info8
->previous_names
&& r
->info
.info8
->previous_names
->string
) {
237 info8
.previous_names
= r
->info
.info8
->previous_names
->string
;
239 info8
.driver_date
= r
->info
.info8
->driver_date
;
240 info8
.driver_version
= r
->info
.info8
->driver_version
;
241 info8
.manufacturer_name
= r
->info
.info8
->manufacturer_name
;
242 info8
.manufacturer_url
= r
->info
.info8
->manufacturer_url
;
243 info8
.hardware_id
= r
->info
.info8
->hardware_id
;
244 info8
.provider
= r
->info
.info8
->provider
;
245 info8
.print_processor
= r
->info
.info8
->print_processor
;
246 info8
.vendor_setup
= r
->info
.info8
->vendor_setup
;
247 if (r
->info
.info8
->color_profiles
&& r
->info
.info8
->color_profiles
->string
) {
248 info8
.color_profiles
= r
->info
.info8
->color_profiles
->string
;
250 info8
.inf_path
= r
->info
.info8
->inf_path
;
251 info8
.printer_driver_attributes
= r
->info
.info8
->printer_driver_attributes
;
252 if (r
->info
.info8
->core_driver_dependencies
&& r
->info
.info8
->core_driver_dependencies
->string
) {
253 info8
.core_driver_dependencies
= r
->info
.info8
->core_driver_dependencies
->string
;
255 info8
.min_inbox_driver_ver_date
= r
->info
.info8
->min_inbox_driver_ver_date
;
256 info8
.min_inbox_driver_ver_version
= r
->info
.info8
->min_inbox_driver_ver_version
;
267 /****************************************************************************
268 Create and allocate a default devicemode.
269 ****************************************************************************/
271 WERROR
spoolss_create_default_devmode(TALLOC_CTX
*mem_ctx
,
272 const char *devicename
,
273 struct spoolss_DeviceMode
**devmode
)
275 struct spoolss_DeviceMode
*dm
;
278 dm
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
280 return WERR_NOT_ENOUGH_MEMORY
;
283 dname
= talloc_asprintf(dm
, "%s", devicename
);
285 return WERR_NOT_ENOUGH_MEMORY
;
287 if (strlen(dname
) > MAXDEVICENAME
) {
288 dname
[MAXDEVICENAME
] = '\0';
290 dm
->devicename
= dname
;
292 dm
->formname
= talloc_strdup(dm
, "Letter");
293 if (dm
->formname
== NULL
) {
294 return WERR_NOT_ENOUGH_MEMORY
;
297 dm
->specversion
= DMSPEC_NT4_AND_ABOVE
;
298 dm
->driverversion
= 0x0400;
300 dm
->__driverextra_length
= 0;
301 dm
->fields
= DEVMODE_FORMNAME
|
303 DEVMODE_PRINTQUALITY
|
304 DEVMODE_DEFAULTSOURCE
|
309 dm
->orientation
= DMORIENT_PORTRAIT
;
310 dm
->papersize
= DMPAPER_LETTER
;
315 dm
->defaultsource
= DMBIN_FORMSOURCE
;
316 dm
->printquality
= DMRES_HIGH
; /* 0x0258 */
317 dm
->color
= DMRES_MONOCHROME
;
318 dm
->duplex
= DMDUP_SIMPLEX
;
320 dm
->ttoption
= DMTT_SUBDEV
;
321 dm
->collate
= DMCOLLATE_FALSE
;
331 dm
->displayflags
= 0;
332 dm
->displayfrequency
= 0;
335 dm
->panningwidth
= 0;
336 dm
->panningheight
= 0;
338 dm
->driverextra_data
.data
= NULL
;
339 dm
->driverextra_data
.length
= 0;
345 WERROR
spoolss_create_default_secdesc(TALLOC_CTX
*mem_ctx
,
346 struct spoolss_security_descriptor
**secdesc
)
348 struct security_ace ace
[7] = {0}; /* max number of ace entries */
351 struct security_acl
*psa
= NULL
;
352 struct security_descriptor
*psd
= NULL
;
353 struct dom_sid adm_sid
;
356 /* Create an ACE where Everyone is allowed to print */
358 sa
= PRINTER_ACE_PRINT
;
359 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
360 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
362 /* Add the domain admins group if we are a DC */
365 struct dom_sid domadmins_sid
;
367 sid_compose(&domadmins_sid
, get_global_sam_sid(),
370 sa
= PRINTER_ACE_FULL_CONTROL
;
371 init_sec_ace(&ace
[i
++], &domadmins_sid
,
372 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
373 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
374 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
375 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
377 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
378 sid_append_rid(&adm_sid
, DOMAIN_RID_ADMINISTRATOR
);
380 sa
= PRINTER_ACE_FULL_CONTROL
;
381 init_sec_ace(&ace
[i
++], &adm_sid
,
382 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
383 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
384 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
385 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
388 /* add BUILTIN\Administrators as FULL CONTROL */
390 sa
= PRINTER_ACE_FULL_CONTROL
;
391 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
392 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
393 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
394 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
395 SEC_ACE_TYPE_ACCESS_ALLOWED
,
396 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
398 /* add BUILTIN\Print Operators as FULL CONTROL */
400 sa
= PRINTER_ACE_FULL_CONTROL
;
401 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
402 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
403 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
404 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
405 SEC_ACE_TYPE_ACCESS_ALLOWED
,
406 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
408 /* Make the security descriptor owned by the BUILTIN\Administrators */
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
415 if ((psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
416 psd
= make_sec_desc(mem_ctx
,
418 SEC_DESC_SELF_RELATIVE
,
419 &global_sid_Builtin_Administrators
,
420 &global_sid_Builtin_Administrators
,
427 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
428 return WERR_NOT_ENOUGH_MEMORY
;
431 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
432 (unsigned int)sd_size
));
439 const char *spoolss_get_short_filesys_environment(const char *environment
)
441 if (strequal(environment
, SPOOLSS_ARCHITECTURE_x64
)) {
443 } else if (strequal(environment
, SPOOLSS_ARCHITECTURE_NT_X86
)) {
450 /* Windows 7 and Windows Server 2008 R2 */
451 #define GLOBAL_SPOOLSS_CLIENT_OS_MAJOR_DEFAULT 6
452 #define GLOBAL_SPOOLSS_CLIENT_OS_MINOR_DEFAULT 1
453 #define GLOBAL_SPOOLSS_CLIENT_OS_BUILD_DEFAULT 7007
455 WERROR
spoolss_init_spoolss_UserLevel1(TALLOC_CTX
*mem_ctx
,
456 const char *username
,
457 struct spoolss_UserLevel1
*r
)
462 r
->client
= talloc_asprintf(mem_ctx
, "\\\\%s", lp_netbios_name());
463 W_ERROR_HAVE_NO_MEMORY(r
->client
);
464 r
->user
= talloc_strdup(mem_ctx
, username
);
465 W_ERROR_HAVE_NO_MEMORY(r
->user
);
468 r
->major
= lp_parm_int(GLOBAL_SECTION_SNUM
,
469 "spoolss_client", "os_major",
470 GLOBAL_SPOOLSS_CLIENT_OS_MAJOR_DEFAULT
);
471 r
->minor
= lp_parm_int(GLOBAL_SECTION_SNUM
,
472 "spoolss_client", "os_minor",
473 GLOBAL_SPOOLSS_CLIENT_OS_MINOR_DEFAULT
);
474 r
->build
= lp_parm_int(GLOBAL_SECTION_SNUM
,
475 "spoolss_client", "os_build",
476 GLOBAL_SPOOLSS_CLIENT_OS_BUILD_DEFAULT
);