s3/param: Fix use after free with popt-1.19
[Samba.git] / source3 / printing / nt_printing_migrate.c
blobf56aa702bf16308a40e484436c0518614d77b3f5
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (c) Andreas Schneider 2010.
6 * Copyright (C) Bjoern Baumbach <bb@sernet.de> 2011
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "printing/nt_printing_migrate.h"
25 #include "rpc_client/rpc_client.h"
26 #include "librpc/gen_ndr/ndr_ntprinting.h"
27 #include "librpc/gen_ndr/ndr_spoolss_c.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "rpc_client/cli_winreg_spoolss.h"
31 static const char *driver_file_basename(const char *file)
33 const char *basefile;
35 basefile = strrchr(file, '\\');
36 if (basefile == NULL) {
37 basefile = file;
38 } else {
39 basefile++;
42 return basefile;
45 NTSTATUS printing_tdb_migrate_form(TALLOC_CTX *mem_ctx,
46 struct rpc_pipe_client *winreg_pipe,
47 const char *key_name,
48 unsigned char *data,
49 size_t length)
51 struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
52 enum ndr_err_code ndr_err;
53 struct ntprinting_form r;
54 struct spoolss_AddFormInfo1 f1;
55 DATA_BLOB blob;
56 WERROR result;
58 blob = data_blob_const(data, length);
60 ZERO_STRUCT(r);
62 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
63 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
64 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
65 DEBUG(2, ("Form pull failed: %s\n",
66 ndr_errstr(ndr_err)));
67 return NT_STATUS_NO_MEMORY;
70 /* Don't migrate builtin forms */
71 if (r.flag == SPOOLSS_FORM_BUILTIN) {
72 return NT_STATUS_OK;
75 DEBUG(2, ("Migrating Form: %s\n", key_name));
77 f1.form_name = key_name;
78 f1.flags = r.flag;
80 f1.size.width = r.width;
81 f1.size.height = r.length;
83 f1.area.top = r.top;
84 f1.area.right = r.right;
85 f1.area.bottom = r.bottom;
86 f1.area.left = r.left;
88 result = winreg_printer_addform1(mem_ctx,
90 &f1);
91 if (W_ERROR_EQUAL(result, WERR_FILE_EXISTS)) {
92 /* Don't migrate form if it already exists. */
93 result = WERR_OK;
95 if (!W_ERROR_IS_OK(result)) {
96 return werror_to_ntstatus(result);
99 return NT_STATUS_OK;
102 NTSTATUS printing_tdb_migrate_driver(TALLOC_CTX *mem_ctx,
103 struct rpc_pipe_client *winreg_pipe,
104 const char *key_name,
105 unsigned char *data,
106 size_t length,
107 bool do_string_conversion)
109 struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
110 enum ndr_err_code ndr_err;
111 struct ntprinting_driver r;
112 struct spoolss_AddDriverInfoCtr d;
113 struct spoolss_AddDriverInfo3 d3;
114 struct spoolss_StringArray a;
115 DATA_BLOB blob;
116 WERROR result;
117 const char *driver_name;
118 uint32_t driver_version;
119 int i;
121 blob = data_blob_const(data, length);
123 ZERO_STRUCT(r);
125 if (do_string_conversion) {
126 r.string_flags = LIBNDR_FLAG_STR_ASCII;
129 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
130 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
131 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
132 DEBUG(2, ("Driver pull failed: %s\n",
133 ndr_errstr(ndr_err)));
134 return NT_STATUS_NO_MEMORY;
137 DEBUG(2, ("Migrating Printer Driver: %s\n", key_name));
139 ZERO_STRUCT(d3);
140 ZERO_STRUCT(a);
142 /* remove paths from file names */
143 if (r.dependent_files != NULL) {
144 for (i = 0 ; r.dependent_files[i] != NULL; i++) {
145 r.dependent_files[i] = driver_file_basename(r.dependent_files[i]);
148 a.string = r.dependent_files;
150 r.driverpath = driver_file_basename(r.driverpath);
151 r.configfile = driver_file_basename(r.configfile);
152 r.datafile = driver_file_basename(r.datafile);
153 r.helpfile = driver_file_basename(r.helpfile);
155 d3.architecture = r.environment;
156 d3.config_file = r.configfile;
157 d3.data_file = r.datafile;
158 d3.default_datatype = r.defaultdatatype;
159 d3.dependent_files = &a;
160 d3.driver_path = r.driverpath;
161 d3.help_file = r.helpfile;
162 d3.monitor_name = r.monitorname;
163 d3.driver_name = r.name;
164 d3.version = r.version;
166 d.level = 3;
167 d.info.info3 = &d3;
169 result = winreg_add_driver(mem_ctx,
172 &driver_name,
173 &driver_version);
174 if (!W_ERROR_IS_OK(result)) {
175 return werror_to_ntstatus(result);
178 return NT_STATUS_OK;
181 NTSTATUS printing_tdb_migrate_printer(TALLOC_CTX *mem_ctx,
182 struct rpc_pipe_client *winreg_pipe,
183 const char *key_name,
184 unsigned char *data,
185 size_t length,
186 bool do_string_conversion)
188 struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
189 enum ndr_err_code ndr_err;
190 struct ntprinting_printer r;
191 struct spoolss_SetPrinterInfo2 info2;
192 struct spoolss_DeviceMode dm;
193 struct spoolss_DevmodeContainer devmode_ctr;
194 DATA_BLOB blob;
195 NTSTATUS status;
196 WERROR result;
197 int j;
198 uint32_t info2_mask = (SPOOLSS_PRINTER_INFO_ALL)
199 & ~SPOOLSS_PRINTER_INFO_SECDESC;
201 if (strequal(key_name, "printers")) {
202 return NT_STATUS_OK;
205 blob = data_blob_const(data, length);
207 ZERO_STRUCT(r);
209 if (do_string_conversion) {
210 r.info.string_flags = LIBNDR_FLAG_STR_ASCII;
213 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
214 (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
215 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
216 DEBUG(2, ("printer pull failed: %s\n",
217 ndr_errstr(ndr_err)));
218 return NT_STATUS_NO_MEMORY;
221 DEBUG(2, ("Migrating Printer: %s\n", key_name));
223 ZERO_STRUCT(devmode_ctr);
225 /* Create printer info level 2 */
226 ZERO_STRUCT(info2);
228 info2.attributes = r.info.attributes;
229 info2.averageppm = r.info.averageppm;
230 info2.cjobs = r.info.cjobs;
231 info2.comment = r.info.comment;
232 info2.datatype = r.info.datatype;
233 info2.defaultpriority = r.info.default_priority;
234 info2.drivername = r.info.drivername;
235 info2.location = r.info.location;
236 info2.parameters = r.info.parameters;
237 info2.portname = r.info.portname;
238 info2.printername = r.info.printername;
239 info2.printprocessor = r.info.printprocessor;
240 info2.priority = r.info.priority;
241 info2.sepfile = r.info.sepfile;
242 info2.sharename = r.info.sharename;
243 info2.starttime = r.info.starttime;
244 info2.status = r.info.status;
245 info2.untiltime = r.info.untiltime;
247 /* Create Device Mode */
248 if (r.devmode == NULL) {
249 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
250 } else {
251 ZERO_STRUCT(dm);
253 dm.bitsperpel = r.devmode->bitsperpel;
254 dm.collate = r.devmode->collate;
255 dm.color = r.devmode->color;
256 dm.copies = r.devmode->copies;
257 dm.defaultsource = r.devmode->defaultsource;
258 dm.devicename = r.devmode->devicename;
259 dm.displayflags = r.devmode->displayflags;
260 dm.displayfrequency = r.devmode->displayfrequency;
261 dm.dithertype = r.devmode->dithertype;
262 dm.driverversion = r.devmode->driverversion;
263 dm.duplex = r.devmode->duplex;
264 dm.fields = r.devmode->fields;
265 dm.formname = r.devmode->formname;
266 dm.icmintent = r.devmode->icmintent;
267 dm.icmmethod = r.devmode->icmmethod;
268 dm.logpixels = r.devmode->logpixels;
269 dm.mediatype = r.devmode->mediatype;
270 dm.orientation = r.devmode->orientation;
271 dm.panningheight = r.devmode->pelsheight;
272 dm.panningwidth = r.devmode->panningwidth;
273 dm.paperlength = r.devmode->paperlength;
274 dm.papersize = r.devmode->papersize;
275 dm.paperwidth = r.devmode->paperwidth;
276 dm.pelsheight = r.devmode->pelsheight;
277 dm.pelswidth = r.devmode->pelswidth;
278 dm.printquality = r.devmode->printquality;
279 dm.size = r.devmode->size;
280 dm.scale = r.devmode->scale;
281 dm.specversion = r.devmode->specversion;
282 dm.ttoption = r.devmode->ttoption;
283 dm.yresolution = r.devmode->yresolution;
285 if (r.devmode->nt_dev_private != NULL) {
286 dm.driverextra_data.data = r.devmode->nt_dev_private->data;
287 dm.driverextra_data.length = r.devmode->nt_dev_private->length;
288 dm.__driverextra_length = r.devmode->nt_dev_private->length;
291 devmode_ctr.devmode = &dm;
294 result = winreg_update_printer(mem_ctx, b,
295 key_name,
296 info2_mask,
297 &info2,
298 &dm,
299 NULL);
300 if (!W_ERROR_IS_OK(result)) {
301 DEBUG(2, ("SetPrinter(%s) level 2 refused -- %s.\n",
302 key_name, win_errstr(result)));
303 status = werror_to_ntstatus(result);
304 goto done;
307 /* migrate printerdata */
308 for (j = 0; j < r.count; j++) {
309 char *valuename;
310 const char *keyname;
312 if (r.printer_data[j].type == REG_NONE) {
313 continue;
316 keyname = r.printer_data[j].name;
317 valuename = strchr(keyname, '\\');
318 if (valuename == NULL) {
319 continue;
320 } else {
321 valuename[0] = '\0';
322 valuename++;
325 result = winreg_set_printer_dataex(mem_ctx, b,
326 key_name,
327 keyname,
328 valuename,
329 r.printer_data[j].type,
330 r.printer_data[j].data.data,
331 r.printer_data[j].data.length);
332 if (!W_ERROR_IS_OK(result)) {
333 DEBUG(2, ("SetPrinterDataEx: printer [%s], keyname [%s], "
334 "valuename [%s] refused -- %s.\n",
335 key_name, keyname, valuename,
336 win_errstr(result)));
337 status = werror_to_ntstatus(result);
338 break;
342 status = NT_STATUS_OK;
343 done:
345 return status;
348 NTSTATUS printing_tdb_migrate_secdesc(TALLOC_CTX *mem_ctx,
349 struct rpc_pipe_client *winreg_pipe,
350 const char *key_name,
351 unsigned char *data,
352 size_t length)
354 struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
355 enum ndr_err_code ndr_err;
356 struct sec_desc_buf secdesc_ctr;
357 DATA_BLOB blob;
358 WERROR result;
360 if (strequal(key_name, "printers")) {
361 return NT_STATUS_OK;
364 blob = data_blob_const(data, length);
366 ZERO_STRUCT(secdesc_ctr);
368 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
369 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
371 DEBUG(2, ("security descriptor pull failed: %s\n",
372 ndr_errstr(ndr_err)));
373 return NT_STATUS_NO_MEMORY;
376 DEBUG(2, ("Migrating Security Descriptor: %s\n", key_name));
378 result = winreg_set_printer_secdesc(mem_ctx, b,
379 key_name,
380 secdesc_ctr.sd);
381 if (!W_ERROR_IS_OK(result)) {
382 return werror_to_ntstatus(result);
385 return NT_STATUS_OK;