pyldb: avoid segfault when adding an element with no name
[sfrench/samba-autobuild/.git] / source3 / rpc_client / init_spoolss.c
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 {
33         if (!r || !unixtime) {
34                 return false;
35         }
36
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;
44         r->millisecond  = 0;
45
46         return true;
47 }
48
49 time_t spoolss_Time_to_time_t(const struct spoolss_Time *r)
50 {
51         struct tm unixtime = {
52                 .tm_year        = r->year - 1900,
53                 .tm_mon         = r->month - 1,
54                 .tm_wday        = r->day_of_week,
55                 .tm_mday        = r->day,
56                 .tm_hour        = r->hour,
57                 .tm_min         = r->minute,
58                 .tm_sec         = r->second,
59         };
60
61         return mktime(&unixtime);
62 }
63
64 /*******************************************************************
65  ********************************************************************/
66
67 bool spoolss_timestr_to_NTTIME(const char *str,
68                                NTTIME *data)
69 {
70         struct tm tm;
71         time_t t;
72
73         if (strequal(str, "01/01/1601")) {
74                 *data = 0;
75                 return true;
76         }
77
78         ZERO_STRUCT(tm);
79
80         if (sscanf(str, "%d/%d/%d",
81                    &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) {
82                 return false;
83         }
84         tm.tm_mon -= 1;
85         tm.tm_year -= 1900;
86         tm.tm_isdst = -1;
87
88         t = mktime(&tm);
89         unix_to_nt_time(data, t);
90
91         return true;
92 }
93
94 /*******************************************************************
95  ********************************************************************/
96
97 bool spoolss_driver_version_to_qword(const char *str,
98                                      uint64_t *data)
99 {
100         unsigned int v1, v2, v3, v4 = 0;
101
102         if ((sscanf(str, "%u.%u.%u.%u", &v1, &v2, &v3, &v4) != 4) &&
103             (sscanf(str, "%u.%u.%u", &v1, &v2, &v3) != 3))
104         {
105                 return false;
106         }
107
108         *data = ((uint64_t)(v1 & 0xFFFF) << 48) +
109                 ((uint64_t)(v2 & 0xFFFF) << 32) +
110                 ((uint64_t)(v3 & 0xFFFF) << 16) +
111                 (uint64_t)(v4 & 0xFFFF);
112
113         return true;
114 }
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 {
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;
129         }
130         return WERR_OK;
131 }
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 {
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;
145         }
146         return WERR_OK;
147 }
148
149 /*******************************************************************
150  ********************************************************************/
151
152 void spoolss_printerinfo2_to_setprinterinfo2(const struct spoolss_PrinterInfo2 *i,
153                                              struct spoolss_SetPrinterInfo2 *s)
154 {
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;
162         s->devmode_ptr          = 0;
163         s->sepfile              = i->sepfile;
164         s->printprocessor       = i->printprocessor;
165         s->datatype             = i->datatype;
166         s->parameters           = i->parameters;
167         s->secdesc_ptr          = 0;
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;
174         s->cjobs                = i->cjobs;
175         s->averageppm           = i->averageppm;
176 }
177
178 /****************************************************************************
179 ****************************************************************************/
180
181 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
182                               struct spoolss_DriverInfo8 *_info8)
183 {
184         struct spoolss_DriverInfo8 info8;
185
186         ZERO_STRUCT(info8);
187
188         switch (r->level) {
189         case 3:
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;
201                 }
202                 break;
203         case 6:
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;
215                 }
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;
222                 break;
223         case 8:
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;
235                 }
236                 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
237                         info8.previous_names    = r->info.info8->previous_names->string;
238                 }
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;
249                 }
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;
254                 }
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;
257                 break;
258         default:
259                 return false;
260         }
261
262         *_info8 = info8;
263
264         return true;
265 }
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 {
275         struct spoolss_DeviceMode *dm;
276         char *dname;
277
278         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
279         if (dm == NULL) {
280                 return WERR_NOT_ENOUGH_MEMORY;
281         }
282
283         dname = talloc_asprintf(dm, "%s", devicename);
284         if (dname == NULL) {
285                 return WERR_NOT_ENOUGH_MEMORY;
286         }
287         if (strlen(dname) > MAXDEVICENAME) {
288                 dname[MAXDEVICENAME] = '\0';
289         }
290         dm->devicename = dname;
291
292         dm->formname = talloc_strdup(dm, "Letter");
293         if (dm->formname == NULL) {
294                 return WERR_NOT_ENOUGH_MEMORY;
295         }
296
297         dm->specversion          = DMSPEC_NT4_AND_ABOVE;
298         dm->driverversion        = 0x0400;
299         dm->size                 = 0x00DC;
300         dm->__driverextra_length = 0;
301         dm->fields               = DEVMODE_FORMNAME |
302                                    DEVMODE_TTOPTION |
303                                    DEVMODE_PRINTQUALITY |
304                                    DEVMODE_DEFAULTSOURCE |
305                                    DEVMODE_COPIES |
306                                    DEVMODE_SCALE |
307                                    DEVMODE_PAPERSIZE |
308                                    DEVMODE_ORIENTATION;
309         dm->orientation          = DMORIENT_PORTRAIT;
310         dm->papersize            = DMPAPER_LETTER;
311         dm->paperlength          = 0;
312         dm->paperwidth           = 0;
313         dm->scale                = 0x64;
314         dm->copies               = 1;
315         dm->defaultsource        = DMBIN_FORMSOURCE;
316         dm->printquality         = DMRES_HIGH;           /* 0x0258 */
317         dm->color                = DMRES_MONOCHROME;
318         dm->duplex               = DMDUP_SIMPLEX;
319         dm->yresolution          = 0;
320         dm->ttoption             = DMTT_SUBDEV;
321         dm->collate              = DMCOLLATE_FALSE;
322         dm->icmmethod            = 0;
323         dm->icmintent            = 0;
324         dm->mediatype            = 0;
325         dm->dithertype           = 0;
326
327         dm->logpixels            = 0;
328         dm->bitsperpel           = 0;
329         dm->pelswidth            = 0;
330         dm->pelsheight           = 0;
331         dm->displayflags         = 0;
332         dm->displayfrequency     = 0;
333         dm->reserved1            = 0;
334         dm->reserved2            = 0;
335         dm->panningwidth         = 0;
336         dm->panningheight        = 0;
337
338         dm->driverextra_data.data = NULL;
339         dm->driverextra_data.length = 0;
340
341         *devmode = dm;
342         return WERR_OK;
343 }
344
345 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
346                                       struct spoolss_security_descriptor **secdesc)
347 {
348         struct security_ace ace[7];     /* max number of ace entries */
349         int i = 0;
350         uint32_t sa;
351         struct security_acl *psa = NULL;
352         struct security_descriptor *psd = NULL;
353         struct dom_sid adm_sid;
354         size_t sd_size;
355
356         /* Create an ACE where Everyone is allowed to print */
357
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);
361
362         /* Add the domain admins group if we are a DC */
363
364         if ( IS_DC ) {
365                 struct dom_sid domadmins_sid;
366
367                 sid_compose(&domadmins_sid, get_global_sam_sid(),
368                             DOMAIN_RID_ADMINS);
369
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);
376         }
377         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
378                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
379
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);
386         }
387
388         /* add BUILTIN\Administrators as FULL CONTROL */
389
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);
397
398         /* add BUILTIN\Print Operators as FULL CONTROL */
399
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);
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         if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
416                 psd = make_sec_desc(mem_ctx,
417                                     SD_REVISION,
418                                     SEC_DESC_SELF_RELATIVE,
419                                     &global_sid_Builtin_Administrators,
420                                     &global_sid_Builtin_Administrators,
421                                     NULL,
422                                     psa,
423                                     &sd_size);
424         }
425
426         if (psd == NULL) {
427                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
428                 return WERR_NOT_ENOUGH_MEMORY;
429         }
430
431         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
432                  (unsigned int)sd_size));
433
434         *secdesc = psd;
435
436         return WERR_OK;
437 }
438
439 const char *spoolss_get_short_filesys_environment(const char *environment)
440 {
441         if (strequal(environment, SPOOLSS_ARCHITECTURE_x64)) {
442                 return "amd64";
443         } else if (strequal(environment, SPOOLSS_ARCHITECTURE_NT_X86)) {
444                 return "x86";
445         } else {
446                 return NULL;
447         }
448 }
449
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
454
455 WERROR spoolss_init_spoolss_UserLevel1(TALLOC_CTX *mem_ctx,
456                                        const char *username,
457                                        struct spoolss_UserLevel1 *r)
458 {
459         ZERO_STRUCTP(r);
460
461         r->size         = 28;
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);
466         r->processor    = 0;
467
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);
477
478         return WERR_OK;
479 }