1/* 2 * Unix SMB/CIFS implementation. 3 * RPC Pipe client / server routines 4 * Copyright (C) Andrew Tridgell 1992-2000, 5 * Copyright (C) Jean François Micouleau 1998-2000. 6 * Copyright (C) Gerald Carter 2002-2005. 7 * 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. 12 * 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. 17 * 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/>. 20 */ 21 22#include "includes.h" 23 24static TDB_CONTEXT *tdb_forms; /* used for forms files */ 25static TDB_CONTEXT *tdb_drivers; /* used for driver files */ 26static TDB_CONTEXT *tdb_printers; /* used for printers files */ 27 28#define FORMS_PREFIX "FORMS/" 29#define DRIVERS_PREFIX "DRIVERS/" 30#define DRIVER_INIT_PREFIX "DRIVER_INIT/" 31#define PRINTERS_PREFIX "PRINTERS/" 32#define SECDESC_PREFIX "SECDESC/" 33#define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter" 34 35#define NTDRIVERS_DATABASE_VERSION_1 1 36#define NTDRIVERS_DATABASE_VERSION_2 2 37#define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */ 38#define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */ 39#define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */ 40 41/* Map generic permissions to printer object specific permissions */ 42 43const struct generic_mapping printer_generic_mapping = { 44 PRINTER_READ, 45 PRINTER_WRITE, 46 PRINTER_EXECUTE, 47 PRINTER_ALL_ACCESS 48}; 49 50const struct standard_mapping printer_std_mapping = { 51 PRINTER_READ, 52 PRINTER_WRITE, 53 PRINTER_EXECUTE, 54 PRINTER_ALL_ACCESS 55}; 56 57/* Map generic permissions to print server object specific permissions */ 58 59const struct generic_mapping printserver_generic_mapping = { 60 SERVER_READ, 61 SERVER_WRITE, 62 SERVER_EXECUTE, 63 SERVER_ALL_ACCESS 64}; 65 66const struct generic_mapping printserver_std_mapping = { 67 SERVER_READ, 68 SERVER_WRITE, 69 SERVER_EXECUTE, 70 SERVER_ALL_ACCESS 71}; 72 73/* Map generic permissions to job object specific permissions */ 74 75const struct generic_mapping job_generic_mapping = { 76 JOB_READ, 77 JOB_WRITE, 78 JOB_EXECUTE, 79 JOB_ALL_ACCESS 80}; 81 82/* We need one default form to support our default printer. Msoft adds the 83forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an 84array index). Letter is always first, so (for the current code) additions 85always put things in the correct order. */ 86static const nt_forms_struct default_forms[] = { 87 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368}, 88 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368}, 89 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8}, 90 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368}, 91 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10}, 92 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c}, 93 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc}, 94 {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488}, 95 {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528}, 96 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0}, 97 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828}, 98 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828}, 99 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450}, 100 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0}, 101 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8}, 102 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8}, 103 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238}, 104 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10}, 105 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8}, 106 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368}, 107 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091}, 108 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94}, 109 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565}, 110 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368}, 111 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504}, 112 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0}, 113 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70}, 114 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0}, 115 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60}, 116 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88}, 117 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10}, 118 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0}, 119 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0}, 120 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88}, 121 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8}, 122 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090}, 123 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848}, 124 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270}, 125 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824}, 126 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec}, 127 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368}, 128 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0}, 129 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8}, 130 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8}, 131 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220}, 132 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368}, 133 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368}, 134 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368}, 135 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60}, 136 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1}, 137 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1}, 138 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0}, 139 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048}, 140 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0}, 141 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16}, 142 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368}, 143 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828}, 144 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0}, 145 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0}, 146 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58}, 147 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16}, 148 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910}, 149 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450}, 150 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8}, 151 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48}, 152 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8}, 153 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620}, 154 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050}, 155 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0}, 156 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48}, 157 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220}, 158 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220}, 159 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0}, 160 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08}, 161 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8}, 162 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8}, 163 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c}, 164 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828}, 165 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450}, 166 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220}, 167 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8}, 168 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0}, 169 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0}, 170 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40}, 171 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28}, 172 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980}, 173 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0}, 174 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0}, 175 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90}, 176 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0}, 177 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400}, 178 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1}, 179 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8}, 180 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28}, 181 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0}, 182 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0}, 183 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8}, 184 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488}, 185 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80}, 186 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80}, 187 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80}, 188 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60}, 189 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270}, 190 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270}, 191 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708}, 192 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0}, 193 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10}, 194 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60}, 195 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0}, 196 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0}, 197 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70}, 198 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70}, 199 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848}, 200 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0}, 201 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0}, 202 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0}, 203 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100}, 204 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0}, 205 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88}, 206 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0} 207}; 208 209static const struct print_architecture_table_node archi_table[]= { 210 211 {"Windows 4.0", SPL_ARCH_WIN40, 0 }, 212 {"Windows NT x86", SPL_ARCH_W32X86, 2 }, 213 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 }, 214 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 }, 215 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 }, 216 {"Windows IA64", SPL_ARCH_IA64, 3 }, 217 {"Windows x64", SPL_ARCH_X64, 3 }, 218 {NULL, "", -1 } 219}; 220 221 222/**************************************************************************** 223 generate a new TDB_DATA key for storing a printer 224****************************************************************************/ 225 226static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename ) 227{ 228 fstring share; 229 char *keystr = NULL; 230 TDB_DATA key; 231 232 fstrcpy(share, sharename); 233 strlower_m(share); 234 235 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share); 236 key = string_term_tdb_data(keystr ? keystr : ""); 237 238 return key; 239} 240 241/**************************************************************************** 242 generate a new TDB_DATA key for storing a printer security descriptor 243****************************************************************************/ 244 245static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx, 246 const char* sharename ) 247{ 248 fstring share; 249 char *keystr = NULL; 250 TDB_DATA key; 251 252 fstrcpy(share, sharename ); 253 strlower_m(share); 254 255 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share); 256 key = string_term_tdb_data(keystr ? keystr : ""); 257 258 return key; 259} 260 261/**************************************************************************** 262****************************************************************************/ 263 264static bool upgrade_to_version_3(void) 265{ 266 TDB_DATA kbuf, newkey, dbuf; 267 268 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n")); 269 270 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr; 271 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) { 272 273 dbuf = tdb_fetch(tdb_drivers, kbuf); 274 275 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) { 276 DEBUG(0,("upgrade_to_version_3:moving form\n")); 277 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) { 278 SAFE_FREE(dbuf.dptr); 279 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms))); 280 return False; 281 } 282 if (tdb_delete(tdb_drivers, kbuf) != 0) { 283 SAFE_FREE(dbuf.dptr); 284 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers))); 285 return False; 286 } 287 } 288 289 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) { 290 DEBUG(0,("upgrade_to_version_3:moving printer\n")); 291 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) { 292 SAFE_FREE(dbuf.dptr); 293 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers))); 294 return False; 295 } 296 if (tdb_delete(tdb_drivers, kbuf) != 0) { 297 SAFE_FREE(dbuf.dptr); 298 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers))); 299 return False; 300 } 301 } 302 303 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) { 304 DEBUG(0,("upgrade_to_version_3:moving secdesc\n")); 305 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) { 306 SAFE_FREE(dbuf.dptr); 307 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers))); 308 return False; 309 } 310 if (tdb_delete(tdb_drivers, kbuf) != 0) { 311 SAFE_FREE(dbuf.dptr); 312 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers))); 313 return False; 314 } 315 } 316 317 SAFE_FREE(dbuf.dptr); 318 } 319 320 return True; 321} 322 323/******************************************************************* 324 Fix an issue with security descriptors. Printer sec_desc must 325 use more than the generic bits that were previously used 326 in <= 3.0.14a. They must also have a owner and group SID assigned. 327 Otherwise, any printers than have been migrated to a Windows 328 host using printmig.exe will not be accessible. 329*******************************************************************/ 330 331static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key, 332 TDB_DATA data, void *state ) 333{ 334 NTSTATUS status; 335 SEC_DESC_BUF *sd_orig = NULL; 336 SEC_DESC_BUF *sd_new, *sd_store; 337 SEC_DESC *sec, *new_sec; 338 TALLOC_CTX *ctx = state; 339 int result, i; 340 uint32 sd_size; 341 size_t size_new_sec; 342 343 if (!data.dptr || data.dsize == 0) { 344 return 0; 345 } 346 347 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) { 348 return 0; 349 } 350 351 /* upgrade the security descriptor */ 352 353 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig); 354 if (!NT_STATUS_IS_OK(status)) { 355 /* delete bad entries */ 356 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", 357 (const char *)key.dptr )); 358 tdb_delete( tdb_printers, key ); 359 return 0; 360 } 361 362 if (!sd_orig) { 363 return 0; 364 } 365 sec = sd_orig->sd; 366 367 /* is this even valid? */ 368 369 if ( !sec->dacl ) { 370 return 0; 371 } 372 373 /* update access masks */ 374 375 for ( i=0; i<sec->dacl->num_aces; i++ ) { 376 switch ( sec->dacl->aces[i].access_mask ) { 377 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS): 378 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT; 379 break; 380 381 case GENERIC_ALL_ACCESS: 382 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL; 383 break; 384 385 case READ_CONTROL_ACCESS: 386 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS; 387 388 default: /* no change */ 389 break; 390 } 391 } 392 393 /* create a new SEC_DESC with the appropriate owner and group SIDs */ 394 395 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, 396 &global_sid_Builtin_Administrators, 397 &global_sid_Builtin_Administrators, 398 NULL, NULL, &size_new_sec ); 399 if (!new_sec) { 400 return 0; 401 } 402 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec ); 403 if (!sd_new) { 404 return 0; 405 } 406 407 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) { 408 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr )); 409 return 0; 410 } 411 412 /* store it back */ 413 414 sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0) 415 + sizeof(SEC_DESC_BUF); 416 417 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize); 418 if (!NT_STATUS_IS_OK(status)) { 419 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr )); 420 return 0; 421 } 422 423 result = tdb_store( tdb_printers, key, data, TDB_REPLACE ); 424 425 /* 0 to continue and non-zero to stop traversal */ 426 427 return (result == -1); 428} 429 430/******************************************************************* 431*******************************************************************/ 432 433static bool upgrade_to_version_4(void) 434{ 435 TALLOC_CTX *ctx; 436 int result; 437 438 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n")); 439 440 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) ) 441 return False; 442 443 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx ); 444 445 talloc_destroy( ctx ); 446 447 return ( result != -1 ); 448} 449 450/******************************************************************* 451 Fix an issue with security descriptors. Printer sec_desc must 452 use more than the generic bits that were previously used 453 in <= 3.0.14a. They must also have a owner and group SID assigned. 454 Otherwise, any printers than have been migrated to a Windows 455 host using printmig.exe will not be accessible. 456*******************************************************************/ 457 458static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key, 459 TDB_DATA data, void *state ) 460{ 461 TALLOC_CTX *ctx = talloc_tos(); 462 TDB_DATA new_key; 463 464 if (!data.dptr || data.dsize == 0) 465 return 0; 466 467 /* upgrade printer records and security descriptors */ 468 469 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) { 470 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) ); 471 } 472 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) { 473 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) ); 474 } 475 else { 476 /* ignore this record */ 477 return 0; 478 } 479 480 /* delete the original record and store under the normalized key */ 481 482 if ( tdb_delete( the_tdb, key ) != 0 ) { 483 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n", 484 key.dptr)); 485 return 1; 486 } 487 488 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) { 489 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n", 490 key.dptr)); 491 return 1; 492 } 493 494 return 0; 495} 496 497/******************************************************************* 498*******************************************************************/ 499 500static bool upgrade_to_version_5(void) 501{ 502 TALLOC_CTX *ctx; 503 int result; 504 505 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n")); 506 507 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) ) 508 return False; 509 510 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL ); 511 512 talloc_destroy( ctx ); 513 514 return ( result != -1 ); 515} 516 517/**************************************************************************** 518 Open the NT printing tdbs. Done once before fork(). 519****************************************************************************/ 520 521bool nt_printing_init(struct messaging_context *msg_ctx) 522{ 523 const char *vstring = "INFO/version"; 524 WERROR win_rc; 525 int32 vers_id; 526 527 if ( tdb_drivers && tdb_printers && tdb_forms ) 528 return True; 529 530 if (tdb_drivers) 531 tdb_close(tdb_drivers); 532 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); 533 if (!tdb_drivers) { 534 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n", 535 state_path("ntdrivers.tdb"), strerror(errno) )); 536 return False; 537 } 538 539 if (tdb_printers) 540 tdb_close(tdb_printers); 541 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); 542 if (!tdb_printers) { 543 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n", 544 state_path("ntprinters.tdb"), strerror(errno) )); 545 return False; 546 } 547 548 if (tdb_forms) 549 tdb_close(tdb_forms); 550 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); 551 if (!tdb_forms) { 552 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n", 553 state_path("ntforms.tdb"), strerror(errno) )); 554 return False; 555 } 556 557 /* handle a Samba upgrade */ 558 559 vers_id = tdb_fetch_int32(tdb_drivers, vstring); 560 if (vers_id == -1) { 561 DEBUG(10, ("Fresh database\n")); 562 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 ); 563 vers_id = NTDRIVERS_DATABASE_VERSION_5; 564 } 565 566 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) { 567 568 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { 569 if (!upgrade_to_version_3()) 570 return False; 571 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3); 572 vers_id = NTDRIVERS_DATABASE_VERSION_3; 573 } 574 575 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) { 576 /* Written on a bigendian machine with old fetch_int code. Save as le. */ 577 /* The only upgrade between V2 and V3 is to save the version in little-endian. */ 578 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3); 579 vers_id = NTDRIVERS_DATABASE_VERSION_3; 580 } 581 582 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) { 583 if ( !upgrade_to_version_4() ) 584 return False; 585 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4); 586 vers_id = NTDRIVERS_DATABASE_VERSION_4; 587 } 588 589 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) { 590 if ( !upgrade_to_version_5() ) 591 return False; 592 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5); 593 vers_id = NTDRIVERS_DATABASE_VERSION_5; 594 } 595 596 597 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) { 598 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id)); 599 return False; 600 } 601 } 602 603 update_c_setprinter(True); 604 605 /* 606 * register callback to handle updating printers as new 607 * drivers are installed 608 */ 609 610 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE, 611 do_drv_upgrade_printer); 612 613 /* 614 * register callback to handle updating printer data 615 * when a driver is initialized 616 */ 617 618 messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET, 619 reset_all_printerdata); 620 621 /* of course, none of the message callbacks matter if you don't 622 tell messages.c that you interested in receiving PRINT_GENERAL 623 msgs. This is done in claim_connection() */ 624 625 626 if ( lp_security() == SEC_ADS ) { 627 win_rc = check_published_printers(); 628 if (!W_ERROR_IS_OK(win_rc)) 629 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc))); 630 } 631 632 return True; 633} 634 635/******************************************************************* 636 Function to allow filename parsing "the old way". 637********************************************************************/ 638 639static NTSTATUS driver_unix_convert(connection_struct *conn, 640 const char *old_name, 641 struct smb_filename **smb_fname) 642{ 643 NTSTATUS status; 644 TALLOC_CTX *ctx = talloc_tos(); 645 char *name = talloc_strdup(ctx, old_name); 646 647 if (!name) { 648 return NT_STATUS_NO_MEMORY; 649 } 650 unix_format(name); 651 name = unix_clean_name(ctx, name); 652 if (!name) { 653 return NT_STATUS_NO_MEMORY; 654 } 655 trim_string(name,"/","/"); 656 657 status = unix_convert(ctx, conn, name, smb_fname, 0); 658 if (!NT_STATUS_IS_OK(status)) { 659 return NT_STATUS_NO_MEMORY; 660 } 661 662 return NT_STATUS_OK; 663} 664 665/******************************************************************* 666 tdb traversal function for counting printers. 667********************************************************************/ 668 669static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key, 670 TDB_DATA data, void *context) 671{ 672 int *printer_count = (int*)context; 673 674 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) { 675 (*printer_count)++; 676 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count)); 677 } 678 679 return 0; 680} 681 682/******************************************************************* 683 Update the spooler global c_setprinter. This variable is initialized 684 when the parent smbd starts with the number of existing printers. It 685 is monotonically increased by the current number of printers *after* 686 each add or delete printer RPC. Only Microsoft knows why... JRR020119 687********************************************************************/ 688 689uint32 update_c_setprinter(bool initialize) 690{ 691 int32 c_setprinter; 692 int32 printer_count = 0; 693 694 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); 695 696 /* Traverse the tdb, counting the printers */ 697 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count); 698 699 /* If initializing, set c_setprinter to current printers count 700 * otherwise, bump it by the current printer count 701 */ 702 if (!initialize) 703 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count; 704 else 705 c_setprinter = printer_count; 706 707 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter)); 708 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter); 709 710 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); 711 712 return (uint32)c_setprinter; 713} 714 715/******************************************************************* 716 Get the spooler global c_setprinter, accounting for initialization. 717********************************************************************/ 718 719uint32 get_c_setprinter(void) 720{ 721 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER); 722 723 if (c_setprinter == (int32)-1) 724 c_setprinter = update_c_setprinter(True); 725 726 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter)); 727 728 return (uint32)c_setprinter; 729} 730 731/**************************************************************************** 732 Get builtin form struct list. 733****************************************************************************/ 734 735int get_builtin_ntforms(nt_forms_struct **list) 736{ 737 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms)); 738 if (!*list) { 739 return 0; 740 } 741 return ARRAY_SIZE(default_forms); 742} 743 744/**************************************************************************** 745 get a builtin form struct 746****************************************************************************/ 747 748bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form) 749{ 750 int i; 751 DEBUGADD(6,("Looking for builtin form %s \n", form_name)); 752 for (i=0; i<ARRAY_SIZE(default_forms); i++) { 753 if (strequal(form_name,default_forms[i].name)) { 754 DEBUGADD(6,("Found builtin form %s \n", form_name)); 755 memcpy(form,&default_forms[i],sizeof(*form)); 756 return true; 757 } 758 } 759 760 return false; 761} 762 763/**************************************************************************** 764 get a form struct list. 765****************************************************************************/ 766 767int get_ntforms(nt_forms_struct **list) 768{ 769 TDB_DATA kbuf, newkey, dbuf; 770 nt_forms_struct form; 771 int ret; 772 int i; 773 int n = 0; 774 775 *list = NULL; 776 777 for (kbuf = tdb_firstkey(tdb_forms); 778 kbuf.dptr; 779 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey) 780 { 781 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) 782 continue; 783 784 dbuf = tdb_fetch(tdb_forms, kbuf); 785 if (!dbuf.dptr) 786 continue; 787 788 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX)); 789 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd", 790 &i, &form.flag, &form.width, &form.length, &form.left, 791 &form.top, &form.right, &form.bottom); 792 SAFE_FREE(dbuf.dptr); 793 if (ret != dbuf.dsize) 794 continue; 795 796 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1); 797 if (!*list) { 798 DEBUG(0,("get_ntforms: Realloc fail.\n")); 799 return 0; 800 } 801 (*list)[n] = form; 802 n++; 803 } 804 805 806 return n; 807} 808 809/**************************************************************************** 810write a form struct list 811****************************************************************************/ 812 813int write_ntforms(nt_forms_struct **list, int number) 814{ 815 TALLOC_CTX *ctx = talloc_tos(); 816 char *buf = NULL; 817 char *key = NULL; 818 int len; 819 TDB_DATA dbuf; 820 int i; 821 822 for (i=0;i<number;i++) { 823 /* save index, so list is rebuilt in correct order */ 824 len = tdb_pack(NULL, 0, "dddddddd", 825 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length, 826 (*list)[i].left, (*list)[i].top, (*list)[i].right, 827 (*list)[i].bottom); 828 if (!len) { 829 continue; 830 } 831 buf = TALLOC_ARRAY(ctx, char, len); 832 if (!buf) { 833 return 0; 834 } 835 len = tdb_pack((uint8 *)buf, len, "dddddddd", 836 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length, 837 (*list)[i].left, (*list)[i].top, (*list)[i].right, 838 (*list)[i].bottom); 839 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name); 840 if (!key) { 841 return 0; 842 } 843 dbuf.dsize = len; 844 dbuf.dptr = (uint8 *)buf; 845 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) { 846 TALLOC_FREE(key); 847 TALLOC_FREE(buf); 848 break; 849 } 850 TALLOC_FREE(key); 851 TALLOC_FREE(buf); 852 } 853 854 return i; 855} 856 857/**************************************************************************** 858add a form struct at the end of the list 859****************************************************************************/ 860bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count) 861{ 862 int n=0; 863 bool update; 864 865 /* 866 * NT tries to add forms even when 867 * they are already in the base 868 * only update the values if already present 869 */ 870 871 update=False; 872 873 for (n=0; n<*count; n++) { 874 if ( strequal((*list)[n].name, form->form_name) ) { 875 update=True; 876 break; 877 } 878 } 879 880 if (update==False) { 881 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) { 882 DEBUG(0,("add_a_form: failed to enlarge forms list!\n")); 883 return False; 884 } 885 fstrcpy((*list)[n].name, form->form_name); 886 (*count)++; 887 } 888 889 (*list)[n].flag = form->flags; 890 (*list)[n].width = form->size.width; 891 (*list)[n].length = form->size.height; 892 (*list)[n].left = form->area.left; 893 (*list)[n].top = form->area.top; 894 (*list)[n].right = form->area.right; 895 (*list)[n].bottom = form->area.bottom; 896 897 DEBUG(6,("add_a_form: Successfully %s form [%s]\n", 898 update ? "updated" : "added", form->form_name)); 899 900 return True; 901} 902 903/**************************************************************************** 904 Delete a named form struct. 905****************************************************************************/ 906 907bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret) 908{ 909 char *key = NULL; 910 int n=0; 911 912 *ret = WERR_OK; 913 914 for (n=0; n<*count; n++) { 915 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) { 916 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name)); 917 break; 918 } 919 } 920 921 if (n == *count) { 922 DEBUG(10,("delete_a_form, [%s] not found\n", del_name)); 923 *ret = WERR_INVALID_PARAM; 924 return False; 925 } 926 927 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) { 928 *ret = WERR_NOMEM; 929 return false; 930 } 931 if (tdb_delete_bystring(tdb_forms, key) != 0) { 932 SAFE_FREE(key); 933 *ret = WERR_NOMEM; 934 return False; 935 } 936 SAFE_FREE(key); 937 return true; 938} 939 940/**************************************************************************** 941 Update a form struct. 942****************************************************************************/ 943 944void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count) 945{ 946 int n=0; 947 948 DEBUG(106, ("[%s]\n", form->form_name)); 949 for (n=0; n<count; n++) { 950 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name)); 951 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name))) 952 break; 953 } 954 955 if (n==count) return; 956 957 (*list)[n].flag = form->flags; 958 (*list)[n].width = form->size.width; 959 (*list)[n].length = form->size.height; 960 (*list)[n].left = form->area.left; 961 (*list)[n].top = form->area.top; 962 (*list)[n].right = form->area.right; 963 (*list)[n].bottom = form->area.bottom; 964} 965 966/**************************************************************************** 967 Get the nt drivers list. 968 Traverse the database and look-up the matching names. 969****************************************************************************/ 970int get_ntdrivers(fstring **list, const char *architecture, uint32 version) 971{ 972 int total=0; 973 const char *short_archi; 974 char *key = NULL; 975 TDB_DATA kbuf, newkey; 976 977 short_archi = get_short_archi(architecture); 978 if (!short_archi) { 979 return 0; 980 } 981 982 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX, 983 short_archi, version) < 0) { 984 return 0; 985 } 986 987 for (kbuf = tdb_firstkey(tdb_drivers); 988 kbuf.dptr; 989 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) { 990 991 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0) 992 continue; 993 994 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) { 995 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n")); 996 SAFE_FREE(key); 997 return -1; 998 } 999 1000 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key)); 1001 total++; 1002 } 1003 1004 SAFE_FREE(key); 1005 return(total); 1006} 1007 1008/**************************************************************************** 1009 Function to do the mapping between the long architecture name and 1010 the short one. 1011****************************************************************************/ 1012 1013const char *get_short_archi(const char *long_archi) 1014{ 1015 int i=-1; 1016 1017 DEBUG(107,("Getting architecture dependant directory\n")); 1018 do { 1019 i++; 1020 } while ( (archi_table[i].long_archi!=NULL ) && 1021 StrCaseCmp(long_archi, archi_table[i].long_archi) ); 1022 1023 if (archi_table[i].long_archi==NULL) { 1024 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi)); 1025 return NULL; 1026 } 1027 1028 /* this might be client code - but shouldn't this be an fstrcpy etc? */ 1029 1030 DEBUGADD(108,("index: [%d]\n", i)); 1031 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi)); 1032 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi)); 1033 1034 return archi_table[i].short_archi; 1035} 1036 1037/**************************************************************************** 1038 Version information in Microsoft files is held in a VS_VERSION_INFO structure. 1039 There are two case to be covered here: PE (Portable Executable) and NE (New 1040 Executable) files. Both files support the same INFO structure, but PE files 1041 store the signature in unicode, and NE files store it as !unicode. 1042 returns -1 on error, 1 on version info found, and 0 on no version info found. 1043****************************************************************************/ 1044 1045static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor) 1046{ 1047 int i; 1048 char *buf = NULL; 1049 ssize_t byte_count; 1050 1051 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) { 1052 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n", 1053 fname, DOS_HEADER_SIZE)); 1054 goto error_exit; 1055 } 1056 1057 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) { 1058 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n", 1059 fname, (unsigned long)byte_count)); 1060 goto no_version_info; 1061 } 1062 1063 /* Is this really a DOS header? */ 1064 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) { 1065 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n", 1066 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET))); 1067 goto no_version_info; 1068 } 1069 1070 /* Skip OEM header (if any) and the DOS stub to start of Windows header */ 1071 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) { 1072 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n", 1073 fname, errno)); 1074 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */ 1075 goto no_version_info; 1076 } 1077 1078 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */ 1079 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) { 1080 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n", 1081 fname, (unsigned long)byte_count)); 1082 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */ 1083 goto no_version_info; 1084 } 1085 1086 /* The header may be a PE (Portable Executable) or an NE (New Executable) */ 1087 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) { 1088 unsigned int num_sections; 1089 unsigned int section_table_bytes; 1090 1091 /* Just skip over optional header to get to section table */ 1092 if (SMB_VFS_LSEEK(fsp, 1093 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE), 1094 SEEK_CUR) == (SMB_OFF_T)-1) { 1095 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n", 1096 fname, errno)); 1097 goto error_exit; 1098 } 1099 1100 /* get the section table */ 1101 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS); 1102 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE; 1103 if (section_table_bytes == 0) 1104 goto error_exit; 1105 1106 SAFE_FREE(buf); 1107 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) { 1108 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n", 1109 fname, section_table_bytes)); 1110 goto error_exit; 1111 } 1112 1113 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) { 1114 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n", 1115 fname, (unsigned long)byte_count)); 1116 goto error_exit; 1117 } 1118 1119 /* Iterate the section table looking for the resource section ".rsrc" */ 1120 for (i = 0; i < num_sections; i++) { 1121 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE; 1122 1123 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) { 1124 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET); 1125 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET); 1126 1127 if (section_bytes == 0) 1128 goto error_exit; 1129 1130 SAFE_FREE(buf); 1131 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) { 1132 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n", 1133 fname, section_bytes)); 1134 goto error_exit; 1135 } 1136 1137 /* Seek to the start of the .rsrc section info */ 1138 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) { 1139 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n", 1140 fname, errno)); 1141 goto error_exit; 1142 } 1143 1144 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) { 1145 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n", 1146 fname, (unsigned long)byte_count)); 1147 goto error_exit; 1148 } 1149 1150 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) 1151 goto error_exit; 1152 1153 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) { 1154 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */ 1155 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') { 1156 /* Align to next long address */ 1157 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc; 1158 1159 if (IVAL(buf,pos) == VS_MAGIC_VALUE) { 1160 *major = IVAL(buf,pos+VS_MAJOR_OFFSET); 1161 *minor = IVAL(buf,pos+VS_MINOR_OFFSET); 1162 1163 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n", 1164 fname, *major, *minor, 1165 (*major>>16)&0xffff, *major&0xffff, 1166 (*minor>>16)&0xffff, *minor&0xffff)); 1167 SAFE_FREE(buf); 1168 return 1; 1169 } 1170 } 1171 } 1172 } 1173 } 1174 1175 /* Version info not found, fall back to origin date/time */ 1176 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname)); 1177 SAFE_FREE(buf); 1178 return 0; 1179 1180 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) { 1181 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) { 1182 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n", 1183 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET))); 1184 /* At this point, we assume the file is in error. It still could be somthing 1185 * else besides a NE file, but it unlikely at this point. */ 1186 goto error_exit; 1187 } 1188 1189 /* Allocate a bit more space to speed up things */ 1190 SAFE_FREE(buf); 1191 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) { 1192 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n", 1193 fname, PE_HEADER_SIZE)); 1194 goto error_exit; 1195 } 1196 1197 /* This is a HACK! I got tired of trying to sort through the messy 1198 * 'NE' file format. If anyone wants to clean this up please have at 1199 * it, but this works. 'NE' files will eventually fade away. JRR */ 1200 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) { 1201 /* Cover case that should not occur in a well formed 'NE' .dll file */ 1202 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break; 1203 1204 for(i=0; i<byte_count; i++) { 1205 /* Fast skip past data that can't possibly match */ 1206 if (buf[i] != 'V') continue; 1207 1208 /* Potential match data crosses buf boundry, move it to beginning 1209 * of buf, and fill the buf with as much as it will hold. */ 1210 if (i>byte_count-VS_VERSION_INFO_SIZE) { 1211 int bc; 1212 1213 memcpy(buf, &buf[i], byte_count-i); 1214 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE- 1215 (byte_count-i))) < 0) { 1216 1217 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n", 1218 fname, errno)); 1219 goto error_exit; 1220 } 1221 1222 byte_count = bc + (byte_count - i); 1223 if (byte_count<VS_VERSION_INFO_SIZE) break; 1224 1225 i = 0; 1226 } 1227 1228 /* Check that the full signature string and the magic number that 1229 * follows exist (not a perfect solution, but the chances that this 1230 * occurs in code is, well, remote. Yes I know I'm comparing the 'V' 1231 * twice, as it is simpler to read the code. */ 1232 if (strcmp(&buf[i], VS_SIGNATURE) == 0) { 1233 /* Compute skip alignment to next long address */ 1234 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) + 1235 sizeof(VS_SIGNATURE)) & 3; 1236 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue; 1237 1238 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET); 1239 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET); 1240 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n", 1241 fname, *major, *minor, 1242 (*major>>16)&0xffff, *major&0xffff, 1243 (*minor>>16)&0xffff, *minor&0xffff)); 1244 SAFE_FREE(buf); 1245 return 1; 1246 } 1247 } 1248 } 1249 1250 /* Version info not found, fall back to origin date/time */ 1251 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname)); 1252 SAFE_FREE(buf); 1253 return 0; 1254 1255 } else 1256 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */ 1257 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n", 1258 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET))); 1259 1260 no_version_info: 1261 SAFE_FREE(buf); 1262 return 0; 1263 1264 error_exit: 1265 SAFE_FREE(buf); 1266 return -1; 1267} 1268 1269/**************************************************************************** 1270Drivers for Microsoft systems contain multiple files. Often, multiple drivers 1271share one or more files. During the MS installation process files are checked 1272to insure that only a newer version of a shared file is installed over an 1273older version. There are several possibilities for this comparison. If there 1274is no previous version, the new one is newer (obviously). If either file is 1275missing the version info structure, compare the creation date (on Unix use 1276the modification date). Otherwise chose the numerically larger version number. 1277****************************************************************************/ 1278 1279static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file) 1280{ 1281 bool use_version = true; 1282 1283 uint32 new_major; 1284 uint32 new_minor; 1285 time_t new_create_time; 1286 1287 uint32 old_major; 1288 uint32 old_minor; 1289 time_t old_create_time; 1290 1291 struct smb_filename *smb_fname = NULL; 1292 files_struct *fsp = NULL; 1293 SMB_STRUCT_STAT st; 1294 1295 NTSTATUS status; 1296 int ret; 1297 1298 SET_STAT_INVALID(st); 1299 new_create_time = (time_t)0; 1300 old_create_time = (time_t)0; 1301 1302 /* Get file version info (if available) for previous file (if it exists) */ 1303 status = driver_unix_convert(conn, old_file, &smb_fname); 1304 if (!NT_STATUS_IS_OK(status)) { 1305 goto error_exit; 1306 } 1307 1308 status = SMB_VFS_CREATE_FILE( 1309 conn, /* conn */ 1310 NULL, /* req */ 1311 0, /* root_dir_fid */ 1312 smb_fname, /* fname */ 1313 FILE_GENERIC_READ, /* access_mask */ 1314 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */ 1315 FILE_OPEN, /* create_disposition*/ 1316 0, /* create_options */ 1317 FILE_ATTRIBUTE_NORMAL, /* file_attributes */ 1318 INTERNAL_OPEN_ONLY, /* oplock_request */ 1319 0, /* allocation_size */ 1320 NULL, /* sd */ 1321 NULL, /* ea_list */ 1322 &fsp, /* result */ 1323 NULL); /* pinfo */ 1324 1325 if (!NT_STATUS_IS_OK(status)) { 1326 /* Old file not found, so by definition new file is in fact newer */ 1327 DEBUG(10,("file_version_is_newer: Can't open old file [%s], " 1328 "errno = %d\n", smb_fname_str_dbg(smb_fname), 1329 errno)); 1330 ret = 1; 1331 goto done; 1332 1333 } else { 1334 ret = get_file_version(fsp, old_file, &old_major, &old_minor); 1335 if (ret == -1) { 1336 goto error_exit; 1337 } 1338 1339 if (!ret) { 1340 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n", 1341 old_file)); 1342 use_version = false; 1343 if (SMB_VFS_FSTAT(fsp, &st) == -1) { 1344 goto error_exit; 1345 } 1346 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime); 1347 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", 1348 (long)old_create_time)); 1349 } 1350 } 1351 close_file(NULL, fsp, NORMAL_CLOSE); 1352 fsp = NULL; 1353 1354 /* Get file version info (if available) for new file */ 1355 status = driver_unix_convert(conn, new_file, &smb_fname); 1356 if (!NT_STATUS_IS_OK(status)) { 1357 goto error_exit; 1358 } 1359 1360 status = SMB_VFS_CREATE_FILE( 1361 conn, /* conn */ 1362 NULL, /* req */ 1363 0, /* root_dir_fid */ 1364 smb_fname, /* fname */ 1365 FILE_GENERIC_READ, /* access_mask */ 1366 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */ 1367 FILE_OPEN, /* create_disposition*/ 1368 0, /* create_options */ 1369 FILE_ATTRIBUTE_NORMAL, /* file_attributes */ 1370 INTERNAL_OPEN_ONLY, /* oplock_request */ 1371 0, /* allocation_size */ 1372 NULL, /* sd */ 1373 NULL, /* ea_list */ 1374 &fsp, /* result */ 1375 NULL); /* pinfo */ 1376 1377 if (!NT_STATUS_IS_OK(status)) { 1378 /* New file not found, this shouldn't occur if the caller did its job */ 1379 DEBUG(3,("file_version_is_newer: Can't open new file [%s], " 1380 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno)); 1381 goto error_exit; 1382 1383 } else { 1384 ret = get_file_version(fsp, new_file, &new_major, &new_minor); 1385 if (ret == -1) { 1386 goto error_exit; 1387 } 1388 1389 if (!ret) { 1390 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n", 1391 new_file)); 1392 use_version = false; 1393 if (SMB_VFS_FSTAT(fsp, &st) == -1) { 1394 goto error_exit; 1395 } 1396 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime); 1397 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", 1398 (long)new_create_time)); 1399 } 1400 } 1401 close_file(NULL, fsp, NORMAL_CLOSE); 1402 fsp = NULL; 1403 1404 if (use_version && (new_major != old_major || new_minor != old_minor)) { 1405 /* Compare versions and choose the larger version number */ 1406 if (new_major > old_major || 1407 (new_major == old_major && new_minor > old_minor)) { 1408 1409 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file)); 1410 ret = 1; 1411 goto done; 1412 } 1413 else { 1414 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file)); 1415 ret = 0; 1416 goto done; 1417 } 1418 1419 } else { 1420 /* Compare modification time/dates and choose the newest time/date */ 1421 if (new_create_time > old_create_time) { 1422 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file)); 1423 ret = 1; 1424 goto done; 1425 } 1426 else { 1427 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file)); 1428 ret = 0; 1429 goto done; 1430 } 1431 } 1432 1433 error_exit: 1434 if(fsp) 1435 close_file(NULL, fsp, NORMAL_CLOSE); 1436 ret = -1; 1437 done: 1438 TALLOC_FREE(smb_fname); 1439 return ret; 1440} 1441 1442/**************************************************************************** 1443Determine the correct cVersion associated with an architecture and driver 1444****************************************************************************/ 1445static uint32 get_correct_cversion(struct pipes_struct *p, 1446 const char *architecture, 1447 const char *driverpath_in, 1448 WERROR *perr) 1449{ 1450 int cversion; 1451 NTSTATUS nt_status; 1452 struct smb_filename *smb_fname = NULL; 1453 char *driverpath = NULL; 1454 files_struct *fsp = NULL; 1455 connection_struct *conn = NULL; 1456 NTSTATUS status; 1457 char *oldcwd; 1458 fstring printdollar; 1459 int printdollar_snum; 1460 1461 *perr = WERR_INVALID_PARAM; 1462 1463 /* If architecture is Windows 95/98/ME, the version is always 0. */ 1464 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) { 1465 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n")); 1466 *perr = WERR_OK; 1467 return 0; 1468 } 1469 1470 /* If architecture is Windows x64, the version is always 3. */ 1471 if (strcmp(architecture, SPL_ARCH_X64) == 0) { 1472 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n")); 1473 *perr = WERR_OK; 1474 return 3; 1475 } 1476 1477 fstrcpy(printdollar, "print$"); 1478 1479 printdollar_snum = find_service(printdollar); 1480 if (printdollar_snum == -1) { 1481 *perr = WERR_NO_SUCH_SHARE; 1482 return -1; 1483 } 1484 1485 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum, 1486 lp_pathname(printdollar_snum), 1487 p->server_info, &oldcwd); 1488 if (!NT_STATUS_IS_OK(nt_status)) { 1489 DEBUG(0,("get_correct_cversion: create_conn_struct " 1490 "returned %s\n", nt_errstr(nt_status))); 1491 *perr = ntstatus_to_werror(nt_status); 1492 return -1; 1493 } 1494 1495 /* Open the driver file (Portable Executable format) and determine the 1496 * deriver the cversion. */ 1497 driverpath = talloc_asprintf(talloc_tos(), 1498 "%s/%s", 1499 architecture, 1500 driverpath_in); 1501 if (!driverpath) { 1502 *perr = WERR_NOMEM; 1503 goto error_exit; 1504 } 1505 1506 nt_status = driver_unix_convert(conn, driverpath, &smb_fname); 1507 if (!NT_STATUS_IS_OK(nt_status)) { 1508 *perr = ntstatus_to_werror(nt_status); 1509 goto error_exit; 1510 } 1511 1512 nt_status = vfs_file_exist(conn, smb_fname); 1513 if (!NT_STATUS_IS_OK(nt_status)) { 1514 *perr = WERR_BADFILE; 1515 goto error_exit; 1516 } 1517 1518 status = SMB_VFS_CREATE_FILE( 1519 conn, /* conn */ 1520 NULL, /* req */ 1521 0, /* root_dir_fid */ 1522 smb_fname, /* fname */ 1523 FILE_GENERIC_READ, /* access_mask */ 1524 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */ 1525 FILE_OPEN, /* create_disposition*/ 1526 0, /* create_options */ 1527 FILE_ATTRIBUTE_NORMAL, /* file_attributes */ 1528 INTERNAL_OPEN_ONLY, /* oplock_request */ 1529 0, /* allocation_size */ 1530 NULL, /* sd */ 1531 NULL, /* ea_list */ 1532 &fsp, /* result */ 1533 NULL); /* pinfo */ 1534 1535 if (!NT_STATUS_IS_OK(status)) { 1536 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = " 1537 "%d\n", smb_fname_str_dbg(smb_fname), errno)); 1538 *perr = WERR_ACCESS_DENIED; 1539 goto error_exit; 1540 } else { 1541 uint32 major; 1542 uint32 minor; 1543 int ret; 1544 1545 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor); 1546 if (ret == -1) goto error_exit; 1547 1548 if (!ret) { 1549 DEBUG(6,("get_correct_cversion: Version info not " 1550 "found [%s]\n", 1551 smb_fname_str_dbg(smb_fname))); 1552 goto error_exit; 1553 } 1554 1555 /* 1556 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION 1557 * for more details. Version in this case is not just the version of the 1558 * file, but the version in the sense of kernal mode (2) vs. user mode 1559 * (3) drivers. Other bits of the version fields are the version info. 1560 * JRR 010716 1561 */ 1562 cversion = major & 0x0000ffff; 1563 switch (cversion) { 1564 case 2: /* WinNT drivers */ 1565 case 3: /* Win2K drivers */ 1566 break; 1567 1568 default: 1569 DEBUG(6,("get_correct_cversion: cversion " 1570 "invalid [%s] cversion = %d\n", 1571 smb_fname_str_dbg(smb_fname), 1572 cversion)); 1573 goto error_exit; 1574 } 1575 1576 DEBUG(10,("get_correct_cversion: Version info found [%s] major" 1577 " = 0x%x minor = 0x%x\n", 1578 smb_fname_str_dbg(smb_fname), major, minor)); 1579 } 1580 1581 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n", 1582 smb_fname_str_dbg(smb_fname), cversion)); 1583 1584 goto done; 1585 1586 error_exit: 1587 cversion = -1; 1588 done: 1589 TALLOC_FREE(smb_fname); 1590 if (fsp != NULL) { 1591 close_file(NULL, fsp, NORMAL_CLOSE); 1592 } 1593 if (conn != NULL) { 1594 vfs_ChDir(conn, oldcwd); 1595 conn_free(conn); 1596 } 1597 if (cversion != -1) { 1598 *perr = WERR_OK; 1599 } 1600 return cversion; 1601} 1602 1603/**************************************************************************** 1604****************************************************************************/ 1605 1606#define strip_driver_path(_mem_ctx, _element) do { \ 1607 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \ 1608 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \ 1609 W_ERROR_HAVE_NO_MEMORY((_element)); \ 1610 } \ 1611} while (0); 1612 1613static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx, 1614 struct pipes_struct *rpc_pipe, 1615 const char *architecture, 1616 const char **driver_path, 1617 const char **data_file, 1618 const char **config_file, 1619 const char **help_file, 1620 struct spoolss_StringArray *dependent_files, 1621 uint32_t *version) 1622{ 1623 const char *short_architecture; 1624 int i; 1625 WERROR err; 1626 char *_p; 1627 1628 if (!*driver_path || !*data_file) { 1629 return WERR_INVALID_PARAM; 1630 } 1631 1632 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) { 1633 return WERR_INVALID_PARAM; 1634 } 1635 1636 /* clean up the driver name. 1637 * we can get .\driver.dll 1638 * or worse c:\windows\system\driver.dll ! 1639 */ 1640 /* using an intermediate string to not have overlaping memcpy()'s */ 1641 1642 strip_driver_path(mem_ctx, *driver_path); 1643 strip_driver_path(mem_ctx, *data_file); 1644 if (*config_file) { 1645 strip_driver_path(mem_ctx, *config_file); 1646 } 1647 if (help_file) { 1648 strip_driver_path(mem_ctx, *help_file); 1649 } 1650 1651 if (dependent_files && dependent_files->string) { 1652 for (i=0; dependent_files->string[i]; i++) { 1653 strip_driver_path(mem_ctx, dependent_files->string[i]); 1654 } 1655 } 1656 1657 short_architecture = get_short_archi(architecture); 1658 if (!short_architecture) { 1659 return WERR_UNKNOWN_PRINTER_DRIVER; 1660 } 1661 1662 /* jfm:7/16/2000 the client always sends the cversion=0. 1663 * The server should check which version the driver is by reading 1664 * the PE header of driver->driverpath. 1665 * 1666 * For Windows 95/98 the version is 0 (so the value sent is correct) 1667 * For Windows NT (the architecture doesn't matter) 1668 * NT 3.1: cversion=0 1669 * NT 3.5/3.51: cversion=1 1670 * NT 4: cversion=2 1671 * NT2K: cversion=3 1672 */ 1673 1674 *version = get_correct_cversion(rpc_pipe, short_architecture, 1675 *driver_path, &err); 1676 if (*version == -1) { 1677 return err; 1678 } 1679 1680 return WERR_OK; 1681} 1682 1683/**************************************************************************** 1684****************************************************************************/ 1685 1686WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe, 1687 struct spoolss_AddDriverInfoCtr *r) 1688{ 1689 switch (r->level) { 1690 case 3: 1691 return clean_up_driver_struct_level(r, rpc_pipe, 1692 r->info.info3->architecture, 1693 &r->info.info3->driver_path, 1694 &r->info.info3->data_file, 1695 &r->info.info3->config_file, 1696 &r->info.info3->help_file, 1697 r->info.info3->dependent_files, 1698 &r->info.info3->version); 1699 case 6: 1700 return clean_up_driver_struct_level(r, rpc_pipe, 1701 r->info.info6->architecture, 1702 &r->info.info6->driver_path, 1703 &r->info.info6->data_file, 1704 &r->info.info6->config_file, 1705 &r->info.info6->help_file, 1706 r->info.info6->dependent_files, 1707 &r->info.info6->version); 1708 default: 1709 return WERR_NOT_SUPPORTED; 1710 } 1711} 1712 1713/**************************************************************************** 1714 This function sucks and should be replaced. JRA. 1715****************************************************************************/ 1716 1717static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst, 1718 const struct spoolss_AddDriverInfo6 *src) 1719{ 1720 dst->version = src->version; 1721 1722 dst->driver_name = src->driver_name; 1723 dst->architecture = src->architecture; 1724 dst->driver_path = src->driver_path; 1725 dst->data_file = src->data_file; 1726 dst->config_file = src->config_file; 1727 dst->help_file = src->help_file; 1728 dst->monitor_name = src->monitor_name; 1729 dst->default_datatype = src->default_datatype; 1730 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files; 1731 dst->dependent_files = src->dependent_files; 1732} 1733 1734/**************************************************************************** 1735 This function sucks and should be replaced. JRA. 1736****************************************************************************/ 1737 1738static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx, 1739 struct spoolss_AddDriverInfo3 *dst, 1740 const struct spoolss_DriverInfo8 *src) 1741{ 1742 dst->version = src->version; 1743 dst->driver_name = src->driver_name; 1744 dst->architecture = src->architecture; 1745 dst->driver_path = src->driver_path; 1746 dst->data_file = src->data_file; 1747 dst->config_file = src->config_file; 1748 dst->help_file = src->help_file; 1749 dst->monitor_name = src->monitor_name; 1750 dst->default_datatype = src->default_datatype; 1751 if (src->dependent_files) { 1752 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray); 1753 if (!dst->dependent_files) return; 1754 dst->dependent_files->string = src->dependent_files; 1755 } else { 1756 dst->dependent_files = NULL; 1757 } 1758} 1759 1760/**************************************************************************** 1761****************************************************************************/ 1762 1763static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx, 1764 connection_struct *conn, 1765 const char *driver_file, 1766 const char *short_architecture, 1767 uint32_t driver_version, 1768 uint32_t version) 1769{ 1770 struct smb_filename *smb_fname_old = NULL; 1771 struct smb_filename *smb_fname_new = NULL; 1772 char *old_name = NULL; 1773 char *new_name = NULL; 1774 NTSTATUS status; 1775 WERROR ret; 1776 1777 old_name = talloc_asprintf(mem_ctx, "%s/%s", 1778 short_architecture, driver_file); 1779 W_ERROR_HAVE_NO_MEMORY(old_name); 1780 1781 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s", 1782 short_architecture, driver_version, driver_file); 1783 if (new_name == NULL) { 1784 TALLOC_FREE(old_name); 1785 return WERR_NOMEM; 1786 } 1787 1788 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) { 1789 1790 status = driver_unix_convert(conn, old_name, &smb_fname_old); 1791 if (!NT_STATUS_IS_OK(status)) { 1792 ret = WERR_NOMEM; 1793 goto out; 1794 } 1795 1796 /* Setup a synthetic smb_filename struct */ 1797 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename); 1798 if (!smb_fname_new) { 1799 ret = WERR_NOMEM; 1800 goto out; 1801 } 1802 1803 smb_fname_new->base_name = new_name; 1804 1805 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to " 1806 "'%s'\n", smb_fname_old->base_name, 1807 smb_fname_new->base_name)); 1808 1809 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new, 1810 OPENX_FILE_EXISTS_TRUNCATE | 1811 OPENX_FILE_CREATE_IF_NOT_EXIST, 1812 0, false); 1813 1814 if (!NT_STATUS_IS_OK(status)) { 1815 DEBUG(0,("move_driver_file_to_download_area: Unable " 1816 "to rename [%s] to [%s]: %s\n", 1817 smb_fname_old->base_name, new_name, 1818 nt_errstr(status))); 1819 ret = WERR_ACCESS_DENIED; 1820 goto out; 1821 } 1822 } 1823 1824 ret = WERR_OK; 1825 out: 1826 TALLOC_FREE(smb_fname_old); 1827 TALLOC_FREE(smb_fname_new); 1828 return ret; 1829} 1830 1831WERROR move_driver_to_download_area(struct pipes_struct *p, 1832 struct spoolss_AddDriverInfoCtr *r, 1833 WERROR *perr) 1834{ 1835 struct spoolss_AddDriverInfo3 *driver; 1836 struct spoolss_AddDriverInfo3 converted_driver; 1837 const char *short_architecture; 1838 struct smb_filename *smb_dname = NULL; 1839 char *new_dir = NULL; 1840 connection_struct *conn = NULL; 1841 NTSTATUS nt_status; 1842 int i; 1843 TALLOC_CTX *ctx = talloc_tos(); 1844 int ver = 0; 1845 char *oldcwd; 1846 fstring printdollar; 1847 int printdollar_snum; 1848 1849 *perr = WERR_OK; 1850 1851 switch (r->level) { 1852 case 3: 1853 driver = r->info.info3; 1854 break; 1855 case 6: 1856 convert_level_6_to_level3(&converted_driver, r->info.info6); 1857 driver = &converted_driver; 1858 break; 1859 default: 1860 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level)); 1861 return WERR_UNKNOWN_LEVEL; 1862 } 1863 1864 short_architecture = get_short_archi(driver->architecture); 1865 if (!short_architecture) { 1866 return WERR_UNKNOWN_PRINTER_DRIVER; 1867 } 1868 1869 fstrcpy(printdollar, "print$"); 1870 1871 printdollar_snum = find_service(printdollar); 1872 if (printdollar_snum == -1) { 1873 *perr = WERR_NO_SUCH_SHARE; 1874 return WERR_NO_SUCH_SHARE; 1875 } 1876 1877 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum, 1878 lp_pathname(printdollar_snum), 1879 p->server_info, &oldcwd); 1880 if (!NT_STATUS_IS_OK(nt_status)) { 1881 DEBUG(0,("move_driver_to_download_area: create_conn_struct " 1882 "returned %s\n", nt_errstr(nt_status))); 1883 *perr = ntstatus_to_werror(nt_status); 1884 return *perr; 1885 } 1886 1887 new_dir = talloc_asprintf(ctx, 1888 "%s/%d", 1889 short_architecture, 1890 driver->version); 1891 if (!new_dir) { 1892 *perr = WERR_NOMEM; 1893 goto err_exit; 1894 } 1895 nt_status = driver_unix_convert(conn, new_dir, &smb_dname); 1896 if (!NT_STATUS_IS_OK(nt_status)) { 1897 *perr = WERR_NOMEM; 1898 goto err_exit; 1899 } 1900 1901 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name)); 1902 1903 create_directory(conn, NULL, smb_dname); 1904 1905 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file 1906 * listed for this driver which has already been moved, skip it (note: 1907 * drivers may list the same file name several times. Then check if the 1908 * file already exists in archi\version\, if so, check that the version 1909 * info (or time stamps if version info is unavailable) is newer (or the 1910 * date is later). If it is, move it to archi\version\filexxx.yyy. 1911 * Otherwise, delete the file. 1912 * 1913 * If a file is not moved to archi\version\ because of an error, all the 1914 * rest of the 'unmoved' driver files are removed from archi\. If one or 1915 * more of the driver's files was already moved to archi\version\, it 1916 * potentially leaves the driver in a partially updated state. Version 1917 * trauma will most likely occur if an client attempts to use any printer 1918 * bound to the driver. Perhaps a rewrite to make sure the moves can be 1919 * done is appropriate... later JRR 1920 */ 1921 1922 DEBUG(5,("Moving files now !\n")); 1923 1924 if (driver->driver_path && strlen(driver->driver_path)) { 1925 1926 *perr = move_driver_file_to_download_area(ctx, 1927 conn, 1928 driver->driver_path, 1929 short_architecture, 1930 driver->version, 1931 ver); 1932 if (!W_ERROR_IS_OK(*perr)) { 1933 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) { 1934 ver = -1; 1935 } 1936 goto err_exit; 1937 } 1938 } 1939 1940 if (driver->data_file && strlen(driver->data_file)) { 1941 if (!strequal(driver->data_file, driver->driver_path)) { 1942 1943 *perr = move_driver_file_to_download_area(ctx, 1944 conn, 1945 driver->data_file, 1946 short_architecture, 1947 driver->version, 1948 ver); 1949 if (!W_ERROR_IS_OK(*perr)) { 1950 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) { 1951 ver = -1; 1952 } 1953 goto err_exit; 1954 } 1955 } 1956 } 1957 1958 if (driver->config_file && strlen(driver->config_file)) { 1959 if (!strequal(driver->config_file, driver->driver_path) && 1960 !strequal(driver->config_file, driver->data_file)) { 1961 1962 *perr = move_driver_file_to_download_area(ctx, 1963 conn, 1964 driver->config_file, 1965 short_architecture, 1966 driver->version, 1967 ver); 1968 if (!W_ERROR_IS_OK(*perr)) { 1969 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) { 1970 ver = -1; 1971 } 1972 goto err_exit; 1973 } 1974 } 1975 } 1976 1977 if (driver->help_file && strlen(driver->help_file)) { 1978 if (!strequal(driver->help_file, driver->driver_path) && 1979 !strequal(driver->help_file, driver->data_file) && 1980 !strequal(driver->help_file, driver->config_file)) { 1981 1982 *perr = move_driver_file_to_download_area(ctx, 1983 conn, 1984 driver->help_file, 1985 short_architecture, 1986 driver->version, 1987 ver); 1988 if (!W_ERROR_IS_OK(*perr)) { 1989 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) { 1990 ver = -1; 1991 } 1992 goto err_exit; 1993 } 1994 } 1995 } 1996 1997 if (driver->dependent_files && driver->dependent_files->string) { 1998 for (i=0; driver->dependent_files->string[i]; i++) { 1999 if (!strequal(driver->dependent_files->string[i], driver->driver_path) && 2000 !strequal(driver->dependent_files->string[i], driver->data_file) && 2001 !strequal(driver->dependent_files->string[i], driver->config_file) && 2002 !strequal(driver->dependent_files->string[i], driver->help_file)) { 2003 int j; 2004 for (j=0; j < i; j++) { 2005 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) { 2006 goto NextDriver; 2007 } 2008 } 2009 2010 *perr = move_driver_file_to_download_area(ctx, 2011 conn, 2012 driver->dependent_files->string[i], 2013 short_architecture, 2014 driver->version, 2015 ver); 2016 if (!W_ERROR_IS_OK(*perr)) { 2017 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) { 2018 ver = -1; 2019 } 2020 goto err_exit; 2021 } 2022 } 2023 NextDriver: ; 2024 } 2025 } 2026 2027 err_exit: 2028 TALLOC_FREE(smb_dname); 2029 2030 if (conn != NULL) { 2031 vfs_ChDir(conn, oldcwd); 2032 conn_free(conn); 2033 } 2034 2035 if (W_ERROR_EQUAL(*perr, WERR_OK)) { 2036 return WERR_OK; 2037 } 2038 if (ver == -1) { 2039 return WERR_UNKNOWN_PRINTER_DRIVER; 2040 } 2041 return (*perr); 2042} 2043 2044/**************************************************************************** 2045****************************************************************************/ 2046 2047static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver) 2048{ 2049 TALLOC_CTX *ctx = talloc_tos(); 2050 int len, buflen; 2051 const char *architecture; 2052 char *directory = NULL; 2053 char *key = NULL; 2054 uint8 *buf; 2055 int i, ret; 2056 TDB_DATA dbuf; 2057 2058 architecture = get_short_archi(driver->architecture); 2059 if (!architecture) { 2060 return (uint32)-1; 2061 } 2062 2063 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx 2064 * \\server is added in the rpc server layer. 2065 * It does make sense to NOT store the server's name in the printer TDB. 2066 */ 2067 2068 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\", 2069 architecture, driver->version); 2070 if (!directory) { 2071 return (uint32)-1; 2072 } 2073 2074#define gen_full_driver_unc_path(ctx, directory, file) \ 2075 do { \ 2076 if (file && strlen(file)) { \ 2077 file = talloc_asprintf(ctx, "%s%s", directory, file); \ 2078 } else { \ 2079 file = talloc_strdup(ctx, ""); \ 2080 } \ 2081 if (!file) { \ 2082 return (uint32_t)-1; \ 2083 } \ 2084 } while (0); 2085 2086 /* .inf files do not always list a file for each of the four standard files. 2087 * Don't prepend a path to a null filename, or client claims: 2088 * "The server on which the printer resides does not have a suitable 2089 * <printer driver name> printer driver installed. Click OK if you 2090 * wish to install the driver on your local machine." 2091 */ 2092 2093 gen_full_driver_unc_path(ctx, directory, driver->driver_path); 2094 gen_full_driver_unc_path(ctx, directory, driver->data_file); 2095 gen_full_driver_unc_path(ctx, directory, driver->config_file); 2096 gen_full_driver_unc_path(ctx, directory, driver->help_file); 2097 2098 if (driver->dependent_files && driver->dependent_files->string) { 2099 for (i=0; driver->dependent_files->string[i]; i++) { 2100 gen_full_driver_unc_path(ctx, directory, 2101 driver->dependent_files->string[i]); 2102 } 2103 } 2104 2105 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX, 2106 architecture, driver->version, driver->driver_name); 2107 if (!key) { 2108 return (uint32)-1; 2109 } 2110 2111 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key )); 2112 2113 buf = NULL; 2114 len = buflen = 0; 2115 2116 again: 2117 len = 0; 2118 len += tdb_pack(buf+len, buflen-len, "dffffffff", 2119 driver->version, 2120 driver->driver_name, 2121 driver->architecture, 2122 driver->driver_path, 2123 driver->data_file, 2124 driver->config_file, 2125 driver->help_file, 2126 driver->monitor_name ? driver->monitor_name : "", 2127 driver->default_datatype ? driver->default_datatype : ""); 2128 2129 if (driver->dependent_files && driver->dependent_files->string) { 2130 for (i=0; driver->dependent_files->string[i]; i++) { 2131 len += tdb_pack(buf+len, buflen-len, "f", 2132 driver->dependent_files->string[i]); 2133 } 2134 } 2135 2136 if (len != buflen) { 2137 buf = (uint8 *)SMB_REALLOC(buf, len); 2138 if (!buf) { 2139 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!")); 2140 ret = -1; 2141 goto done; 2142 } 2143 buflen = len; 2144 goto again; 2145 } 2146 2147 dbuf.dptr = buf; 2148 dbuf.dsize = len; 2149 2150 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE); 2151 2152done: 2153 if (ret) 2154 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key )); 2155 2156 SAFE_FREE(buf); 2157 return ret; 2158} 2159 2160/**************************************************************************** 2161****************************************************************************/ 2162 2163static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver) 2164{ 2165 TALLOC_CTX *mem_ctx = talloc_new(talloc_tos()); 2166 struct spoolss_AddDriverInfo3 info3; 2167 uint32_t ret; 2168 2169 convert_level_8_to_level3(mem_ctx, &info3, driver); 2170 2171 ret = add_a_printer_driver_3(&info3); 2172 talloc_free(mem_ctx); 2173 2174 return ret; 2175} 2176 2177/**************************************************************************** 2178****************************************************************************/ 2179 2180static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx, 2181 struct spoolss_DriverInfo3 *info, 2182 const char *driver, const char *arch) 2183{ 2184 info->driver_name = talloc_strdup(mem_ctx, driver); 2185 if (!info->driver_name) { 2186 return WERR_NOMEM; 2187 } 2188 2189 info->default_datatype = talloc_strdup(mem_ctx, "RAW"); 2190 if (!info->default_datatype) { 2191 return WERR_NOMEM; 2192 } 2193 2194 info->driver_path = talloc_strdup(mem_ctx, ""); 2195 info->data_file = talloc_strdup(mem_ctx, ""); 2196 info->config_file = talloc_strdup(mem_ctx, ""); 2197 info->help_file = talloc_strdup(mem_ctx, ""); 2198 if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) { 2199 return WERR_NOMEM; 2200 } 2201 2202 return WERR_OK; 2203} 2204 2205/**************************************************************************** 2206****************************************************************************/ 2207 2208static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx, 2209 struct spoolss_DriverInfo3 *driver, 2210 const char *drivername, const char *arch, 2211 uint32_t version) 2212{ 2213 TDB_DATA dbuf; 2214 const char *architecture; 2215 int len = 0; 2216 int i; 2217 char *key = NULL; 2218 fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype; 2219 2220 architecture = get_short_archi(arch); 2221 if ( !architecture ) { 2222 return WERR_UNKNOWN_PRINTER_DRIVER; 2223 } 2224 2225 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */ 2226 2227 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 ) 2228 version = 0; 2229 2230 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername)); 2231 2232 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX, 2233 architecture, version, drivername) < 0) { 2234 return WERR_NOMEM; 2235 } 2236 2237 dbuf = tdb_fetch_bystring(tdb_drivers, key); 2238 if (!dbuf.dptr) { 2239 SAFE_FREE(key); 2240 return WERR_UNKNOWN_PRINTER_DRIVER; 2241 } 2242 2243 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff", 2244 &driver->version, 2245 name, 2246 environment, 2247 driverpath, 2248 datafile, 2249 configfile, 2250 helpfile, 2251 monitorname, 2252 defaultdatatype); 2253 2254 driver->driver_name = talloc_strdup(mem_ctx, name); 2255 driver->architecture = talloc_strdup(mem_ctx, environment); 2256 driver->driver_path = talloc_strdup(mem_ctx, driverpath); 2257 driver->data_file = talloc_strdup(mem_ctx, datafile); 2258 driver->config_file = talloc_strdup(mem_ctx, configfile); 2259 driver->help_file = talloc_strdup(mem_ctx, helpfile); 2260 driver->monitor_name = talloc_strdup(mem_ctx, monitorname); 2261 driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype); 2262 2263 i=0; 2264 2265 while (len < dbuf.dsize) { 2266 2267 fstring file; 2268 2269 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2); 2270 if (!driver->dependent_files ) { 2271 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n")); 2272 break; 2273 } 2274 2275 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", 2276 &file); 2277 2278 driver->dependent_files[i] = talloc_strdup(mem_ctx, file); 2279 2280 i++; 2281 } 2282 2283 if (driver->dependent_files) 2284 driver->dependent_files[i] = NULL; 2285 2286 SAFE_FREE(dbuf.dptr); 2287 SAFE_FREE(key); 2288 2289 if (len != dbuf.dsize) { 2290 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch); 2291 } 2292 2293 return WERR_OK; 2294} 2295 2296/**************************************************************************** 2297****************************************************************************/ 2298int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen) 2299{ 2300 int len = 0; 2301 2302 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode); 2303 2304 if (!nt_devmode) 2305 return len; 2306 2307 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp", 2308 nt_devmode->devicename, 2309 nt_devmode->formname, 2310 2311 nt_devmode->specversion, 2312 nt_devmode->driverversion, 2313 nt_devmode->size, 2314 nt_devmode->driverextra, 2315 nt_devmode->orientation, 2316 nt_devmode->papersize, 2317 nt_devmode->paperlength, 2318 nt_devmode->paperwidth, 2319 nt_devmode->scale, 2320 nt_devmode->copies, 2321 nt_devmode->defaultsource, 2322 nt_devmode->printquality, 2323 nt_devmode->color, 2324 nt_devmode->duplex, 2325 nt_devmode->yresolution, 2326 nt_devmode->ttoption, 2327 nt_devmode->collate, 2328 nt_devmode->logpixels, 2329 2330 nt_devmode->fields, 2331 nt_devmode->bitsperpel, 2332 nt_devmode->pelswidth, 2333 nt_devmode->pelsheight, 2334 nt_devmode->displayflags, 2335 nt_devmode->displayfrequency, 2336 nt_devmode->icmmethod, 2337 nt_devmode->icmintent, 2338 nt_devmode->mediatype, 2339 nt_devmode->dithertype, 2340 nt_devmode->reserved1, 2341 nt_devmode->reserved2, 2342 nt_devmode->panningwidth, 2343 nt_devmode->panningheight, 2344 nt_devmode->nt_dev_private); 2345 2346 if (nt_devmode->nt_dev_private) { 2347 len += tdb_pack(buf+len, buflen-len, "B", 2348 nt_devmode->driverextra, 2349 nt_devmode->nt_dev_private); 2350 } 2351 2352 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname)); 2353 2354 return len; 2355} 2356 2357/**************************************************************************** 2358 Pack all values in all printer keys 2359 ***************************************************************************/ 2360 2361static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen) 2362{ 2363 int len = 0; 2364 int i, j; 2365 struct regval_blob *val; 2366 struct regval_ctr *val_ctr; 2367 char *path = NULL; 2368 int num_values; 2369 2370 if ( !data ) 2371 return 0; 2372 2373 /* loop over all keys */ 2374 2375 for ( i=0; i<data->num_keys; i++ ) { 2376 val_ctr = data->keys[i].values; 2377 num_values = regval_ctr_numvals( val_ctr ); 2378 2379 /* pack the keyname followed by a empty value */ 2380 2381 len += tdb_pack(buf+len, buflen-len, "pPdB", 2382 &data->keys[i].name, 2383 data->keys[i].name, 2384 REG_NONE, 2385 0, 2386 NULL); 2387 2388 /* now loop over all values */ 2389 2390 for ( j=0; j<num_values; j++ ) { 2391 /* pathname should be stored as <key>\<value> */ 2392 2393 val = regval_ctr_specific_value( val_ctr, j ); 2394 if (asprintf(&path, "%s\\%s", 2395 data->keys[i].name, 2396 regval_name(val)) < 0) { 2397 return -1; 2398 } 2399 2400 len += tdb_pack(buf+len, buflen-len, "pPdB", 2401 val, 2402 path, 2403 regval_type(val), 2404 regval_size(val), 2405 regval_data_p(val) ); 2406 2407 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val))); 2408 SAFE_FREE(path); 2409 } 2410 2411 } 2412 2413 /* terminator */ 2414 2415 len += tdb_pack(buf+len, buflen-len, "p", NULL); 2416 2417 return len; 2418} 2419 2420 2421/**************************************************************************** 2422 Delete a printer - this just deletes the printer info file, any open 2423 handles are not affected. 2424****************************************************************************/ 2425 2426uint32 del_a_printer(const char *sharename) 2427{ 2428 TDB_DATA kbuf; 2429 char *printdb_path = NULL; 2430 TALLOC_CTX *ctx = talloc_tos(); 2431 2432 kbuf = make_printer_tdbkey(ctx, sharename); 2433 tdb_delete(tdb_printers, kbuf); 2434 2435 kbuf= make_printers_secdesc_tdbkey(ctx, sharename); 2436 tdb_delete(tdb_printers, kbuf); 2437 2438 close_all_print_db(); 2439 2440 if (geteuid() == sec_initial_uid()) { 2441 if (asprintf(&printdb_path, "%s%s.tdb", 2442 cache_path("printing/"), 2443 sharename) < 0) { 2444 return (uint32)-1; 2445 } 2446 unlink(printdb_path); 2447 SAFE_FREE(printdb_path); 2448 } 2449 2450 return 0; 2451} 2452 2453/**************************************************************************** 2454****************************************************************************/ 2455static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) 2456{ 2457 uint8 *buf; 2458 int buflen, len; 2459 int retlen; 2460 WERROR ret; 2461 TDB_DATA kbuf, dbuf; 2462 2463 /* 2464 * in addprinter: no servername and the printer is the name 2465 * in setprinter: servername is \\server 2466 * and printer is \\server\\printer 2467 * 2468 * Samba manages only local printers. 2469 * we currently don't support things like i 2470 * path=\\other_server\printer 2471 * 2472 * We only store the printername, not \\server\printername 2473 */ 2474 2475 if ( info->servername[0] != '\0' ) { 2476 trim_string(info->printername, info->servername, NULL); 2477 trim_char(info->printername, '\\', '\0'); 2478 info->servername[0]='\0'; 2479 } 2480 2481 /* 2482 * JFM: one day I'll forget. 2483 * below that's info->portname because that's the SAMBA sharename 2484 * and I made NT 'thinks' it's the portname 2485 * the info->sharename is the thing you can name when you add a printer 2486 * that's the short-name when you create shared printer for 95/98 2487 * So I've made a limitation in SAMBA: you can only have 1 printer model 2488 * behind a SAMBA share. 2489 */ 2490 2491 buf = NULL; 2492 buflen = 0; 2493 2494 again: 2495 len = 0; 2496 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff", 2497 info->attributes, 2498 info->priority, 2499 info->default_priority, 2500 info->starttime, 2501 info->untiltime, 2502 info->status, 2503 info->cjobs, 2504 info->averageppm, 2505 info->changeid, 2506 info->c_setprinter, 2507 info->setuptime, 2508 info->servername, 2509 info->printername, 2510 info->sharename, 2511 info->portname, 2512 info->drivername, 2513 info->comment, 2514 info->location, 2515 info->sepfile, 2516 info->printprocessor, 2517 info->datatype, 2518 info->parameters); 2519 2520 len += pack_devicemode(info->devmode, buf+len, buflen-len); 2521 retlen = pack_values( info->data, buf+len, buflen-len ); 2522 if (retlen == -1) { 2523 ret = WERR_NOMEM; 2524 goto done; 2525 } 2526 len += retlen; 2527 2528 if (buflen != len) { 2529 buf = (uint8 *)SMB_REALLOC(buf, len); 2530 if (!buf) { 2531 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n")); 2532 ret = WERR_NOMEM; 2533 goto done; 2534 } 2535 buflen = len; 2536 goto again; 2537 } 2538 2539 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename ); 2540 2541 dbuf.dptr = buf; 2542 dbuf.dsize = len; 2543 2544 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM); 2545 2546done: 2547 if (!W_ERROR_IS_OK(ret)) 2548 DEBUG(8, ("error updating printer to tdb on disk\n")); 2549 2550 SAFE_FREE(buf); 2551 2552 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n", 2553 info->sharename, info->drivername, info->portname, len)); 2554 2555 return ret; 2556} 2557 2558 2559/**************************************************************************** 2560 Malloc and return an NT devicemode. 2561****************************************************************************/ 2562 2563NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename) 2564{ 2565 2566 char adevice[MAXDEVICENAME]; 2567 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE); 2568 2569 if (nt_devmode == NULL) { 2570 DEBUG(0,("construct_nt_devicemode: malloc fail.\n")); 2571 return NULL; 2572 } 2573 2574 ZERO_STRUCTP(nt_devmode); 2575 2576 slprintf(adevice, sizeof(adevice), "%s", default_devicename); 2577 fstrcpy(nt_devmode->devicename, adevice); 2578 2579 fstrcpy(nt_devmode->formname, "Letter"); 2580 2581 nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE; 2582 nt_devmode->driverversion = 0x0400; 2583 nt_devmode->size = 0x00DC; 2584 nt_devmode->driverextra = 0x0000; 2585 nt_devmode->fields = DEVMODE_FORMNAME | 2586 DEVMODE_TTOPTION | 2587 DEVMODE_PRINTQUALITY | 2588 DEVMODE_DEFAULTSOURCE | 2589 DEVMODE_COPIES | 2590 DEVMODE_SCALE | 2591 DEVMODE_PAPERSIZE | 2592 DEVMODE_ORIENTATION; 2593 nt_devmode->orientation = DMORIENT_PORTRAIT; 2594 nt_devmode->papersize = DMPAPER_LETTER; 2595 nt_devmode->paperlength = 0; 2596 nt_devmode->paperwidth = 0; 2597 nt_devmode->scale = 0x64; 2598 nt_devmode->copies = 1; 2599 nt_devmode->defaultsource = DMBIN_FORMSOURCE; 2600 nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */ 2601 nt_devmode->color = DMRES_MONOCHROME; 2602 nt_devmode->duplex = DMDUP_SIMPLEX; 2603 nt_devmode->yresolution = 0; 2604 nt_devmode->ttoption = DMTT_SUBDEV; 2605 nt_devmode->collate = DMCOLLATE_FALSE; 2606 nt_devmode->icmmethod = 0; 2607 nt_devmode->icmintent = 0; 2608 nt_devmode->mediatype = 0; 2609 nt_devmode->dithertype = 0; 2610 2611 /* non utilisés par un driver d'imprimante */ 2612 nt_devmode->logpixels = 0; 2613 nt_devmode->bitsperpel = 0; 2614 nt_devmode->pelswidth = 0; 2615 nt_devmode->pelsheight = 0; 2616 nt_devmode->displayflags = 0; 2617 nt_devmode->displayfrequency = 0; 2618 nt_devmode->reserved1 = 0; 2619 nt_devmode->reserved2 = 0; 2620 nt_devmode->panningwidth = 0; 2621 nt_devmode->panningheight = 0; 2622 2623 nt_devmode->nt_dev_private = NULL; 2624 return nt_devmode; 2625} 2626 2627/**************************************************************************** 2628 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE. 2629****************************************************************************/ 2630 2631void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr) 2632{ 2633 NT_DEVICEMODE *nt_devmode = *devmode_ptr; 2634 2635 if(nt_devmode == NULL) 2636 return; 2637 2638 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n")); 2639 2640 SAFE_FREE(nt_devmode->nt_dev_private); 2641 SAFE_FREE(*devmode_ptr); 2642} 2643 2644/**************************************************************************** 2645 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2. 2646****************************************************************************/ 2647 2648static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr) 2649{ 2650 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr; 2651 2652 if ( !info ) 2653 return; 2654 2655 free_nt_devicemode(&info->devmode); 2656 2657 TALLOC_FREE( *info_ptr ); 2658} 2659 2660 2661/**************************************************************************** 2662****************************************************************************/ 2663int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen) 2664{ 2665 int len = 0; 2666 int extra_len = 0; 2667 NT_DEVICEMODE devmode; 2668 2669 ZERO_STRUCT(devmode); 2670 2671 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode); 2672 2673 if (!*nt_devmode) return len; 2674 2675 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp", 2676 devmode.devicename, 2677 devmode.formname, 2678 2679 &devmode.specversion, 2680 &devmode.driverversion, 2681 &devmode.size, 2682 &devmode.driverextra, 2683 &devmode.orientation, 2684 &devmode.papersize, 2685 &devmode.paperlength, 2686 &devmode.paperwidth, 2687 &devmode.scale, 2688 &devmode.copies, 2689 &devmode.defaultsource, 2690 &devmode.printquality, 2691 &devmode.color, 2692 &devmode.duplex, 2693 &devmode.yresolution, 2694 &devmode.ttoption, 2695 &devmode.collate, 2696 &devmode.logpixels, 2697 2698 &devmode.fields, 2699 &devmode.bitsperpel, 2700 &devmode.pelswidth, 2701 &devmode.pelsheight, 2702 &devmode.displayflags, 2703 &devmode.displayfrequency, 2704 &devmode.icmmethod, 2705 &devmode.icmintent, 2706 &devmode.mediatype, 2707 &devmode.dithertype, 2708 &devmode.reserved1, 2709 &devmode.reserved2, 2710 &devmode.panningwidth, 2711 &devmode.panningheight, 2712 &devmode.nt_dev_private); 2713 2714 if (devmode.nt_dev_private) { 2715 /* the len in tdb_unpack is an int value and 2716 * devmode.driverextra is only a short 2717 */ 2718 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private); 2719 devmode.driverextra=(uint16)extra_len; 2720 2721 /* check to catch an invalid TDB entry so we don't segfault */ 2722 if (devmode.driverextra == 0) { 2723 devmode.nt_dev_private = NULL; 2724 } 2725 } 2726 2727 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode)); 2728 if (!*nt_devmode) { 2729 SAFE_FREE(devmode.nt_dev_private); 2730 return -1; 2731 } 2732 2733 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname)); 2734 if (devmode.nt_dev_private) 2735 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra)); 2736 2737 return len; 2738} 2739 2740/**************************************************************************** 2741 Allocate and initialize a new slot. 2742***************************************************************************/ 2743 2744int add_new_printer_key( NT_PRINTER_DATA *data, const char *name ) 2745{ 2746 NT_PRINTER_KEY *d; 2747 int key_index; 2748 2749 if ( !name || !data ) 2750 return -1; 2751 2752 /* allocate another slot in the NT_PRINTER_KEY array */ 2753 2754 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) { 2755 DEBUG(0,("add_new_printer_key: Realloc() failed!\n")); 2756 return -1; 2757 } 2758 2759 data->keys = d; 2760 2761 key_index = data->num_keys; 2762 2763 /* initialze new key */ 2764 2765 data->keys[key_index].name = talloc_strdup( data, name ); 2766 2767 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) ) 2768 return -1; 2769 2770 data->num_keys++; 2771 2772 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name )); 2773 2774 return key_index; 2775} 2776 2777/**************************************************************************** 2778 search for a registry key name in the existing printer data 2779 ***************************************************************************/ 2780 2781int delete_printer_key( NT_PRINTER_DATA *data, const char *name ) 2782{ 2783 int i; 2784 2785 for ( i=0; i<data->num_keys; i++ ) { 2786 if ( strequal( data->keys[i].name, name ) ) { 2787 2788 /* cleanup memory */ 2789 2790 TALLOC_FREE( data->keys[i].name ); 2791 TALLOC_FREE( data->keys[i].values ); 2792 2793 /* if not the end of the array, move remaining elements down one slot */ 2794 2795 data->num_keys--; 2796 if ( data->num_keys && (i < data->num_keys) ) 2797 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) ); 2798 2799 break; 2800 } 2801 } 2802 2803 2804 return data->num_keys; 2805} 2806 2807/**************************************************************************** 2808 search for a registry key name in the existing printer data 2809 ***************************************************************************/ 2810 2811int lookup_printerkey( NT_PRINTER_DATA *data, const char *name ) 2812{ 2813 int key_index = -1; 2814 int i; 2815 2816 if ( !data || !name ) 2817 return -1; 2818 2819 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name)); 2820 2821 /* loop over all existing keys */ 2822 2823 for ( i=0; i<data->num_keys; i++ ) { 2824 if ( strequal(data->keys[i].name, name) ) { 2825 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name)); 2826 key_index = i; 2827 break; 2828 2829 } 2830 } 2831 2832 return key_index; 2833} 2834 2835/**************************************************************************** 2836 ***************************************************************************/ 2837 2838int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys ) 2839{ 2840 int i, j; 2841 int key_len; 2842 int num_subkeys = 0; 2843 char *p; 2844 fstring *subkeys_ptr = NULL; 2845 fstring subkeyname; 2846 2847 *subkeys = NULL; 2848 2849 if ( !data ) 2850 return 0; 2851 2852 if ( !key ) 2853 return -1; 2854 2855 /* special case of asking for the top level printer data registry key names */ 2856 2857 if ( strlen(key) == 0 ) { 2858 for ( i=0; i<data->num_keys; i++ ) { 2859 2860 /* found a match, so allocate space and copy the name */ 2861 2862 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) { 2863 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 2864 num_subkeys+1)); 2865 return -1; 2866 } 2867 2868 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name ); 2869 num_subkeys++; 2870 } 2871 2872 goto done; 2873 } 2874 2875 /* asking for the subkeys of some key */ 2876 /* subkey paths are stored in the key name using '\' as the delimiter */ 2877 2878 for ( i=0; i<data->num_keys; i++ ) { 2879 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) { 2880 2881 /* if we found the exact key, then break */ 2882 key_len = strlen( key ); 2883 if ( strlen(data->keys[i].name) == key_len ) 2884 break; 2885 2886 /* get subkey path */ 2887 2888 p = data->keys[i].name + key_len; 2889 if ( *p == '\\' ) 2890 p++; 2891 fstrcpy( subkeyname, p ); 2892 if ( (p = strchr( subkeyname, '\\' )) ) 2893 *p = '\0'; 2894 2895 /* don't add a key more than once */ 2896 2897 for ( j=0; j<num_subkeys; j++ ) { 2898 if ( strequal( subkeys_ptr[j], subkeyname ) ) 2899 break; 2900 } 2901 2902 if ( j != num_subkeys ) 2903 continue; 2904 2905 /* found a match, so allocate space and copy the name */ 2906 2907 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) { 2908 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 2909 num_subkeys+1)); 2910 return 0; 2911 } 2912 2913 fstrcpy( subkeys_ptr[num_subkeys], subkeyname ); 2914 num_subkeys++; 2915 } 2916 2917 } 2918 2919 /* return error if the key was not found */ 2920 2921 if ( i == data->num_keys ) { 2922 SAFE_FREE(subkeys_ptr); 2923 return -1; 2924 } 2925 2926done: 2927 /* tag off the end */ 2928 2929 if (num_subkeys) 2930 fstrcpy(subkeys_ptr[num_subkeys], "" ); 2931 2932 *subkeys = subkeys_ptr; 2933 2934 return num_subkeys; 2935} 2936 2937#ifdef HAVE_ADS 2938static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name, 2939 const char *sz) 2940{ 2941 regval_ctr_delvalue(ctr, val_name); 2942 regval_ctr_addvalue_sz(ctr, val_name, sz); 2943} 2944 2945static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name, 2946 uint32 dword) 2947{ 2948 regval_ctr_delvalue(ctr, val_name); 2949 regval_ctr_addvalue(ctr, val_name, REG_DWORD, 2950 (char *) &dword, sizeof(dword)); 2951} 2952 2953static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name, 2954 bool b) 2955{ 2956 uint8 bin_bool = (b ? 1 : 0); 2957 regval_ctr_delvalue(ctr, val_name); 2958 regval_ctr_addvalue(ctr, val_name, REG_BINARY, 2959 (char *) &bin_bool, sizeof(bin_bool)); 2960} 2961 2962static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name, 2963 const char *multi_sz) 2964{ 2965 const char *a[2]; 2966 2967 a[0] = multi_sz; 2968 a[1] = NULL; 2969 2970 regval_ctr_delvalue(ctr, val_name); 2971 regval_ctr_addvalue_multi_sz(ctr, val_name, a); 2972} 2973 2974/**************************************************************************** 2975 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing. 2976 * 2977 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified 2978 * @return bool indicating success or failure 2979 ***************************************************************************/ 2980 2981static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2) 2982{ 2983 struct regval_ctr *ctr = NULL; 2984 fstring longname; 2985 const char *dnssuffix; 2986 char *allocated_string = NULL; 2987 const char *ascii_str; 2988 int i; 2989 2990 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0) 2991 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY); 2992 ctr = info2->data->keys[i].values; 2993 2994 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename); 2995 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname()); 2996 2997 /* we make the assumption that the netbios name is the same 2998 as the DNS name sinc ethe former will be what we used to 2999 join the domain */ 3000 3001 dnssuffix = get_mydnsdomname(talloc_tos()); 3002 if (dnssuffix && *dnssuffix) { 3003 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix ); 3004 } else { 3005 fstrcpy( longname, global_myname() ); 3006 } 3007 3008 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname); 3009 3010 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) { 3011 return false; 3012 } 3013 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string); 3014 SAFE_FREE(allocated_string); 3015 3016 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4); 3017 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername); 3018 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location); 3019 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment); 3020 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname); 3021 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile); 3022 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime); 3023 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime); 3024 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority); 3025 3026 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS, 3027 (info2->attributes & 3028 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS)); 3029 3030 switch (info2->attributes & 0x3) { 3031 case 0: 3032 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING; 3033 break; 3034 case 1: 3035 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED; 3036 break; 3037 case 2: 3038 ascii_str = SPOOL_REGVAL_PRINTDIRECT; 3039 break; 3040 default: 3041 ascii_str = "unknown"; 3042 } 3043 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str); 3044 3045 return True; 3046} 3047 3048/***************************************************************** 3049 ****************************************************************/ 3050 3051static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, 3052 struct GUID guid) 3053{ 3054 int i; 3055 struct regval_ctr *ctr=NULL; 3056 3057 /* find the DsSpooler key */ 3058 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0) 3059 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY); 3060 ctr = info2->data->keys[i].values; 3061 3062 regval_ctr_delvalue(ctr, "objectGUID"); 3063 3064 /* We used to store this as a REG_BINARY but that causes 3065 Vista to whine */ 3066 3067 regval_ctr_addvalue_sz(ctr, "objectGUID", 3068 GUID_string(talloc_tos(), &guid)); 3069} 3070 3071static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, 3072 NT_PRINTER_INFO_LEVEL *printer) 3073{ 3074 ADS_STATUS ads_rc; 3075 LDAPMessage *res; 3076 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped; 3077 char *srv_dn_utf8, **srv_cn_utf8; 3078 TALLOC_CTX *ctx; 3079 ADS_MODLIST mods; 3080 const char *attrs[] = {"objectGUID", NULL}; 3081 struct GUID guid; 3082 WERROR win_rc = WERR_OK; 3083 size_t converted_size; 3084 3085 /* build the ads mods */ 3086 ctx = talloc_init("nt_printer_publish_ads"); 3087 if (ctx == NULL) { 3088 return WERR_NOMEM; 3089 } 3090 3091 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername)); 3092 3093 /* figure out where to publish */ 3094 ads_find_machine_acct(ads, &res, global_myname()); 3095 3096 /* We use ldap_get_dn here as we need the answer 3097 * in utf8 to call ldap_explode_dn(). JRA. */ 3098 3099 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res); 3100 if (!srv_dn_utf8) { 3101 TALLOC_FREE(ctx); 3102 return WERR_SERVER_UNAVAILABLE; 3103 } 3104 ads_msgfree(ads, res); 3105 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1); 3106 if (!srv_cn_utf8) { 3107 TALLOC_FREE(ctx); 3108 ldap_memfree(srv_dn_utf8); 3109 return WERR_SERVER_UNAVAILABLE; 3110 } 3111 /* Now convert to CH_UNIX. */ 3112 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) { 3113 TALLOC_FREE(ctx); 3114 ldap_memfree(srv_dn_utf8); 3115 ldap_memfree(srv_cn_utf8); 3116 return WERR_SERVER_UNAVAILABLE; 3117 } 3118 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) { 3119 TALLOC_FREE(ctx); 3120 ldap_memfree(srv_dn_utf8); 3121 ldap_memfree(srv_cn_utf8); 3122 TALLOC_FREE(srv_dn); 3123 return WERR_SERVER_UNAVAILABLE; 3124 } 3125 3126 ldap_memfree(srv_dn_utf8); 3127 ldap_memfree(srv_cn_utf8); 3128 3129 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0); 3130 if (!srv_cn_escaped) { 3131 TALLOC_FREE(ctx); 3132 return WERR_SERVER_UNAVAILABLE; 3133 } 3134 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename); 3135 if (!sharename_escaped) { 3136 SAFE_FREE(srv_cn_escaped); 3137 TALLOC_FREE(ctx); 3138 return WERR_SERVER_UNAVAILABLE; 3139 } 3140 3141 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn); 3142 3143 SAFE_FREE(srv_cn_escaped); 3144 SAFE_FREE(sharename_escaped); 3145 3146 mods = ads_init_mods(ctx); 3147 3148 if (mods == NULL) { 3149 SAFE_FREE(prt_dn); 3150 TALLOC_FREE(ctx); 3151 return WERR_NOMEM; 3152 } 3153 3154 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data); 3155 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, 3156 printer->info_2->sharename); 3157 3158 /* publish it */ 3159 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods); 3160 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) { 3161 int i; 3162 for (i=0; mods[i] != 0; i++) 3163 ; 3164 mods[i] = (LDAPMod *)-1; 3165 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); 3166 } 3167 3168 if (!ADS_ERR_OK(ads_rc)) 3169 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc))); 3170 3171 /* retreive the guid and store it locally */ 3172 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { 3173 ZERO_STRUCT(guid); 3174 ads_pull_guid(ads, res, &guid); 3175 ads_msgfree(ads, res); 3176 store_printer_guid(printer->info_2, guid); 3177 win_rc = mod_a_printer(printer, 2); 3178 } 3179 TALLOC_FREE(ctx); 3180 3181 return win_rc; 3182} 3183 3184static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads, 3185 NT_PRINTER_INFO_LEVEL *printer) 3186{ 3187 ADS_STATUS ads_rc; 3188 LDAPMessage *res = NULL; 3189 char *prt_dn = NULL; 3190 3191 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername)); 3192 3193 /* remove the printer from the directory */ 3194 ads_rc = ads_find_printer_on_server(ads, &res, 3195 printer->info_2->sharename, global_myname()); 3196 3197 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) { 3198 prt_dn = ads_get_dn(ads, talloc_tos(), res); 3199 if (!prt_dn) { 3200 ads_msgfree(ads, res); 3201 return WERR_NOMEM; 3202 } 3203 ads_rc = ads_del_dn(ads, prt_dn); 3204 TALLOC_FREE(prt_dn); 3205 } 3206 3207 if (res) { 3208 ads_msgfree(ads, res); 3209 } 3210 return WERR_OK; 3211} 3212 3213/**************************************************************************** 3214 * Publish a printer in the directory 3215 * 3216 * @param snum describing printer service 3217 * @return WERROR indicating status of publishing 3218 ***************************************************************************/ 3219 3220WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action) 3221{ 3222 ADS_STATUS ads_rc; 3223 ADS_STRUCT *ads = NULL; 3224 NT_PRINTER_INFO_LEVEL *printer = NULL; 3225 WERROR win_rc; 3226 3227 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum)); 3228 if (!W_ERROR_IS_OK(win_rc)) 3229 goto done; 3230 3231 switch (action) { 3232 case DSPRINT_PUBLISH: 3233 case DSPRINT_UPDATE: 3234 /* set the DsSpooler info and attributes */ 3235 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) { 3236 win_rc = WERR_NOMEM; 3237 goto done; 3238 } 3239 3240 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED; 3241 break; 3242 case DSPRINT_UNPUBLISH: 3243 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED; 3244 break; 3245 default: 3246 win_rc = WERR_NOT_SUPPORTED; 3247 goto done; 3248 } 3249 3250 win_rc = mod_a_printer(printer, 2); 3251 if (!W_ERROR_IS_OK(win_rc)) { 3252 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc))); 3253 goto done; 3254 } 3255 3256 ads = ads_init(lp_realm(), lp_workgroup(), NULL); 3257 if (!ads) { 3258 DEBUG(3, ("ads_init() failed\n")); 3259 win_rc = WERR_SERVER_UNAVAILABLE; 3260 goto done; 3261 } 3262 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1); 3263 SAFE_FREE(ads->auth.password); 3264 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), 3265 NULL, NULL); 3266 3267 /* ads_connect() will find the DC for us */ 3268 ads_rc = ads_connect(ads); 3269 if (!ADS_ERR_OK(ads_rc)) { 3270 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); 3271 win_rc = WERR_ACCESS_DENIED; 3272 goto done; 3273 } 3274 3275 switch (action) { 3276 case DSPRINT_PUBLISH: 3277 case DSPRINT_UPDATE: 3278 win_rc = nt_printer_publish_ads(ads, printer); 3279 break; 3280 case DSPRINT_UNPUBLISH: 3281 win_rc = nt_printer_unpublish_ads(ads, printer); 3282 break; 3283 } 3284 3285done: 3286 free_a_printer(&printer, 2); 3287 ads_destroy(&ads); 3288 return win_rc; 3289} 3290 3291WERROR check_published_printers(void) 3292{ 3293 ADS_STATUS ads_rc; 3294 ADS_STRUCT *ads = NULL; 3295 int snum; 3296 int n_services = lp_numservices(); 3297 NT_PRINTER_INFO_LEVEL *printer = NULL; 3298 3299 ads = ads_init(lp_realm(), lp_workgroup(), NULL); 3300 if (!ads) { 3301 DEBUG(3, ("ads_init() failed\n")); 3302 return WERR_SERVER_UNAVAILABLE; 3303 } 3304 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1); 3305 SAFE_FREE(ads->auth.password); 3306 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), 3307 NULL, NULL); 3308 3309 /* ads_connect() will find the DC for us */ 3310 ads_rc = ads_connect(ads); 3311 if (!ADS_ERR_OK(ads_rc)) { 3312 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); 3313 ads_destroy(&ads); 3314 ads_kdestroy("MEMORY:prtpub_cache"); 3315 return WERR_ACCESS_DENIED; 3316 } 3317 3318 for (snum = 0; snum < n_services; snum++) { 3319 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) 3320 continue; 3321 3322 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, 3323 lp_servicename(snum))) && 3324 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) 3325 nt_printer_publish_ads(ads, printer); 3326 3327 free_a_printer(&printer, 2); 3328 } 3329 3330 ads_destroy(&ads); 3331 ads_kdestroy("MEMORY:prtpub_cache"); 3332 return WERR_OK; 3333} 3334 3335bool is_printer_published(Printer_entry *print_hnd, int snum, 3336 struct GUID *guid) 3337{ 3338 NT_PRINTER_INFO_LEVEL *printer = NULL; 3339 struct regval_ctr *ctr; 3340 struct regval_blob *guid_val; 3341 WERROR win_rc; 3342 int i; 3343 bool ret = False; 3344 DATA_BLOB blob; 3345 3346 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum)); 3347 3348 if (!W_ERROR_IS_OK(win_rc) || 3349 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) || 3350 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) || 3351 !(ctr = printer->info_2->data->keys[i].values) || 3352 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) 3353 { 3354 free_a_printer(&printer, 2); 3355 return False; 3356 } 3357 3358 /* fetching printer guids really ought to be a separate function. */ 3359 3360 if ( guid ) { 3361 char *guid_str; 3362 3363 /* We used to store the guid as REG_BINARY, then swapped 3364 to REG_SZ for Vista compatibility so check for both */ 3365 3366 switch ( regval_type(guid_val) ){ 3367 case REG_SZ: 3368 blob = data_blob_const(regval_data_p(guid_val), 3369 regval_size(guid_val)); 3370 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str); 3371 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid )); 3372 talloc_free(guid_str); 3373 break; 3374 case REG_BINARY: 3375 if ( regval_size(guid_val) != sizeof(struct GUID) ) { 3376 ret = False; 3377 break; 3378 } 3379 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID)); 3380 break; 3381 default: 3382 DEBUG(0,("is_printer_published: GUID value stored as " 3383 "invaluid type (%d)\n", regval_type(guid_val) )); 3384 break; 3385 } 3386 } 3387 3388 free_a_printer(&printer, 2); 3389 return ret; 3390} 3391#else 3392WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action) 3393{ 3394 return WERR_OK; 3395} 3396 3397WERROR check_published_printers(void) 3398{ 3399 return WERR_OK; 3400} 3401 3402bool is_printer_published(Printer_entry *print_hnd, int snum, 3403 struct GUID *guid) 3404{ 3405 return False; 3406} 3407#endif /* HAVE_ADS */ 3408 3409/**************************************************************************** 3410 ***************************************************************************/ 3411 3412WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key ) 3413{ 3414 NT_PRINTER_DATA *data; 3415 int i; 3416 int removed_keys = 0; 3417 int empty_slot; 3418 3419 data = p2->data; 3420 empty_slot = data->num_keys; 3421 3422 if ( !key ) 3423 return WERR_INVALID_PARAM; 3424 3425 /* remove all keys */ 3426 3427 if ( !strlen(key) ) { 3428 3429 TALLOC_FREE( data ); 3430 3431 p2->data = NULL; 3432 3433 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n", 3434 p2->printername )); 3435 3436 return WERR_OK; 3437 } 3438 3439 /* remove a specific key (and all subkeys) */ 3440 3441 for ( i=0; i<data->num_keys; i++ ) { 3442 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) { 3443 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n", 3444 data->keys[i].name)); 3445 3446 TALLOC_FREE( data->keys[i].name ); 3447 TALLOC_FREE( data->keys[i].values ); 3448 3449 /* mark the slot as empty */ 3450 3451 ZERO_STRUCTP( &data->keys[i] ); 3452 } 3453 } 3454 3455 /* find the first empty slot */ 3456 3457 for ( i=0; i<data->num_keys; i++ ) { 3458 if ( !data->keys[i].name ) { 3459 empty_slot = i; 3460 removed_keys++; 3461 break; 3462 } 3463 } 3464 3465 if ( i == data->num_keys ) 3466 /* nothing was removed */ 3467 return WERR_INVALID_PARAM; 3468 3469 /* move everything down */ 3470 3471 for ( i=empty_slot+1; i<data->num_keys; i++ ) { 3472 if ( data->keys[i].name ) { 3473 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 3474 ZERO_STRUCTP( &data->keys[i] ); 3475 empty_slot++; 3476 removed_keys++; 3477 } 3478 } 3479 3480 /* update count */ 3481 3482 data->num_keys -= removed_keys; 3483 3484 /* sanity check to see if anything is left */ 3485 3486 if ( !data->num_keys ) { 3487 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername )); 3488 3489 SAFE_FREE( data->keys ); 3490 ZERO_STRUCTP( data ); 3491 } 3492 3493 return WERR_OK; 3494} 3495 3496/**************************************************************************** 3497 ***************************************************************************/ 3498 3499WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value ) 3500{ 3501 WERROR result = WERR_OK; 3502 int key_index; 3503 3504 /* we must have names on non-zero length */ 3505 3506 if ( !key || !*key|| !value || !*value ) 3507 return WERR_INVALID_NAME; 3508 3509 /* find the printer key first */ 3510 3511 key_index = lookup_printerkey( p2->data, key ); 3512 if ( key_index == -1 ) 3513 return WERR_OK; 3514 3515 /* make sure the value exists so we can return the correct error code */ 3516 3517 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) ) 3518 return WERR_BADFILE; 3519 3520 regval_ctr_delvalue( p2->data->keys[key_index].values, value ); 3521 3522 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n", 3523 key, value )); 3524 3525 return result; 3526} 3527 3528/**************************************************************************** 3529 ***************************************************************************/ 3530 3531WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 3532 uint32 type, uint8 *data, int real_len ) 3533{ 3534 WERROR result = WERR_OK; 3535 int key_index; 3536 3537 /* we must have names on non-zero length */ 3538 3539 if ( !key || !*key|| !value || !*value ) 3540 return WERR_INVALID_NAME; 3541 3542 /* find the printer key first */ 3543 3544 key_index = lookup_printerkey( p2->data, key ); 3545 if ( key_index == -1 ) 3546 key_index = add_new_printer_key( p2->data, key ); 3547 3548 if ( key_index == -1 ) 3549 return WERR_NOMEM; 3550 3551 regval_ctr_addvalue( p2->data->keys[key_index].values, value, 3552 type, (const char *)data, real_len ); 3553 3554 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n", 3555 key, value, type, real_len )); 3556 3557 return result; 3558} 3559 3560/**************************************************************************** 3561 ***************************************************************************/ 3562 3563struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value ) 3564{ 3565 int key_index; 3566 3567 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 ) 3568 return NULL; 3569 3570 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n", 3571 key, value )); 3572 3573 return regval_ctr_getvalue( p2->data->keys[key_index].values, value ); 3574} 3575 3576/**************************************************************************** 3577 Unpack a list of registry values frem the TDB 3578 ***************************************************************************/ 3579 3580static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen) 3581{ 3582 int len = 0; 3583 uint32 type; 3584 fstring string; 3585 const char *valuename = NULL; 3586 const char *keyname = NULL; 3587 char *str; 3588 int size; 3589 uint8 *data_p; 3590 struct regval_blob *regval_p; 3591 int key_index; 3592 3593 /* add the "PrinterDriverData" key first for performance reasons */ 3594 3595 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY ); 3596 3597 /* loop and unpack the rest of the registry values */ 3598 3599 while ( True ) { 3600 3601 /* check to see if there are any more registry values */ 3602 3603 regval_p = NULL; 3604 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p); 3605 if ( !regval_p ) 3606 break; 3607 3608 /* unpack the next regval */ 3609 3610 len += tdb_unpack(buf+len, buflen-len, "fdB", 3611 string, 3612 &type, 3613 &size, 3614 &data_p); 3615 3616 /* lookup for subkey names which have a type of REG_NONE */ 3617 /* there's no data with this entry */ 3618 3619 if ( type == REG_NONE ) { 3620 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 ) 3621 add_new_printer_key( printer_data, string ); 3622 continue; 3623 } 3624 3625 /* 3626 * break of the keyname from the value name. 3627 * Valuenames can have embedded '\'s so be careful. 3628 * only support one level of keys. See the 3629 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver. 3630 * -- jerry 3631 */ 3632 3633 str = strchr_m( string, '\\'); 3634 3635 /* Put in "PrinterDriverData" is no key specified */ 3636 3637 if ( !str ) { 3638 keyname = SPOOL_PRINTERDATA_KEY; 3639 valuename = string; 3640 } 3641 else { 3642 *str = '\0'; 3643 keyname = string; 3644 valuename = str+1; 3645 } 3646 3647 /* see if we need a new key */ 3648 3649 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 ) 3650 key_index = add_new_printer_key( printer_data, keyname ); 3651 3652 if ( key_index == -1 ) { 3653 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n", 3654 keyname)); 3655 break; 3656 } 3657 3658 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size)); 3659 3660 /* Vista doesn't like unknown REG_BINARY values in DsSpooler. 3661 Thanks to Martin Zielinski for the hint. */ 3662 3663 if ( type == REG_BINARY && 3664 strequal( keyname, SPOOL_DSSPOOLER_KEY ) && 3665 strequal( valuename, "objectGUID" ) ) 3666 { 3667 struct GUID guid; 3668 3669 /* convert the GUID to a UNICODE string */ 3670 3671 memcpy( &guid, data_p, sizeof(struct GUID) ); 3672 3673 regval_ctr_addvalue_sz(printer_data->keys[key_index].values, 3674 valuename, 3675 GUID_string(talloc_tos(), &guid)); 3676 3677 } else { 3678 /* add the value */ 3679 3680 regval_ctr_addvalue( printer_data->keys[key_index].values, 3681 valuename, type, (const char *)data_p, 3682 size ); 3683 } 3684 3685 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */ 3686 3687 } 3688 3689 return len; 3690} 3691 3692/**************************************************************************** 3693 ***************************************************************************/ 3694 3695static char *last_from; 3696static char *last_to; 3697 3698static const char *get_last_from(void) 3699{ 3700 if (!last_from) { 3701 return ""; 3702 } 3703 return last_from; 3704} 3705 3706static const char *get_last_to(void) 3707{ 3708 if (!last_to) { 3709 return ""; 3710 } 3711 return last_to; 3712} 3713 3714static bool set_last_from_to(const char *from, const char *to) 3715{ 3716 char *orig_from = last_from; 3717 char *orig_to = last_to; 3718 3719 last_from = SMB_STRDUP(from); 3720 last_to = SMB_STRDUP(to); 3721 3722 SAFE_FREE(orig_from); 3723 SAFE_FREE(orig_to); 3724 3725 if (!last_from || !last_to) { 3726 SAFE_FREE(last_from); 3727 SAFE_FREE(last_to); 3728 return false; 3729 } 3730 return true; 3731} 3732 3733static void map_to_os2_driver(fstring drivername) 3734{ 3735 char *mapfile = lp_os2_driver_map(); 3736 char **lines = NULL; 3737 int numlines = 0; 3738 int i; 3739 3740 if (!strlen(drivername)) 3741 return; 3742 3743 if (!*mapfile) 3744 return; 3745 3746 if (strequal(drivername,get_last_from())) { 3747 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n", 3748 drivername,get_last_to())); 3749 fstrcpy(drivername,get_last_to()); 3750 return; 3751 } 3752 3753 lines = file_lines_load(mapfile, &numlines,0,NULL); 3754 if (numlines == 0 || lines == NULL) { 3755 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile)); 3756 TALLOC_FREE(lines); 3757 return; 3758 } 3759 3760 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile)); 3761 3762 for( i = 0; i < numlines; i++) { 3763 char *nt_name = lines[i]; 3764 char *os2_name = strchr(nt_name,'='); 3765 3766 if (!os2_name) 3767 continue; 3768 3769 *os2_name++ = 0; 3770 3771 while (isspace(*nt_name)) 3772 nt_name++; 3773 3774 if (!*nt_name || strchr("#;",*nt_name)) 3775 continue; 3776 3777 { 3778 int l = strlen(nt_name); 3779 while (l && isspace(nt_name[l-1])) { 3780 nt_name[l-1] = 0; 3781 l--; 3782 } 3783 } 3784 3785 while (isspace(*os2_name)) 3786 os2_name++; 3787 3788 { 3789 int l = strlen(os2_name); 3790 while (l && isspace(os2_name[l-1])) { 3791 os2_name[l-1] = 0; 3792 l--; 3793 } 3794 } 3795 3796 if (strequal(nt_name,drivername)) { 3797 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name)); 3798 set_last_from_to(drivername,os2_name); 3799 fstrcpy(drivername,os2_name); 3800 TALLOC_FREE(lines); 3801 return; 3802 } 3803 } 3804 3805 TALLOC_FREE(lines); 3806} 3807 3808/**************************************************************************** 3809 Get a default printer info 2 struct. 3810****************************************************************************/ 3811 3812static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, 3813 const char *servername, 3814 const char* sharename, 3815 bool get_loc_com) 3816{ 3817 int snum = lp_servicenumber(sharename); 3818 3819 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername); 3820 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", 3821 servername, sharename); 3822 fstrcpy(info->sharename, sharename); 3823 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME); 3824 3825 /* by setting the driver name to an empty string, a local NT admin 3826 can now run the **local** APW to install a local printer driver 3827 for a Samba shared printer in 2.2. Without this, drivers **must** be 3828 installed on the Samba server for NT clients --jerry */ 3829#if 0 /* JERRY --do not uncomment-- */ 3830 if (!*info->drivername) 3831 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER"); 3832#endif 3833 3834 3835 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername)); 3836 3837 strlcpy(info->comment, "", sizeof(info->comment)); 3838 fstrcpy(info->printprocessor, "winprint"); 3839 fstrcpy(info->datatype, "RAW"); 3840 3841#ifdef HAVE_CUPS 3842 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) { 3843 /* Pull the location and comment strings from cups if we don't 3844 already have one */ 3845 if ( !strlen(info->location) || !strlen(info->comment) ) 3846 cups_pull_comment_location( info ); 3847 } 3848#endif 3849 3850 info->attributes = PRINTER_ATTRIBUTE_SAMBA; 3851 3852 info->starttime = 0; /* Minutes since 12:00am GMT */ 3853 info->untiltime = 0; /* Minutes since 12:00am GMT */ 3854 info->priority = 1; 3855 info->default_priority = 1; 3856 info->setuptime = (uint32)time(NULL); 3857 3858 /* 3859 * I changed this as I think it is better to have a generic 3860 * DEVMODE than to crash Win2k explorer.exe --jerry 3861 * See the HP Deskjet 990c Win2k drivers for an example. 3862 * 3863 * However the default devmode appears to cause problems 3864 * with the HP CLJ 8500 PCL driver. Hence the addition of 3865 * the "default devmode" parameter --jerry 22/01/2002 3866 */ 3867 3868 if (lp_default_devmode(snum)) { 3869 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) { 3870 goto fail; 3871 } 3872 } else { 3873 info->devmode = NULL; 3874 } 3875 3876 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) { 3877 goto fail; 3878 } 3879 3880 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA); 3881 if (!info->data) { 3882 goto fail; 3883 } 3884 3885 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY); 3886 3887 return WERR_OK; 3888 3889fail: 3890 if (info->devmode) 3891 free_nt_devicemode(&info->devmode); 3892 3893 return WERR_ACCESS_DENIED; 3894} 3895 3896/**************************************************************************** 3897****************************************************************************/ 3898 3899static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, 3900 const char *servername, 3901 const char *sharename, 3902 bool get_loc_com) 3903{ 3904 int len = 0; 3905 int snum = lp_servicenumber(sharename); 3906 TDB_DATA kbuf, dbuf; 3907 fstring printername; 3908 char adevice[MAXDEVICENAME]; 3909 char *comment = NULL; 3910 3911 kbuf = make_printer_tdbkey(talloc_tos(), sharename); 3912 3913 dbuf = tdb_fetch(tdb_printers, kbuf); 3914 if (!dbuf.dptr) { 3915 return get_a_printer_2_default(info, servername, 3916 sharename, get_loc_com); 3917 } 3918 3919 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff", 3920 &info->attributes, 3921 &info->priority, 3922 &info->default_priority, 3923 &info->starttime, 3924 &info->untiltime, 3925 &info->status, 3926 &info->cjobs, 3927 &info->averageppm, 3928 &info->changeid, 3929 &info->c_setprinter, 3930 &info->setuptime, 3931 info->servername, 3932 info->printername, 3933 info->sharename, 3934 info->portname, 3935 info->drivername, 3936 &comment, 3937 info->location, 3938 info->sepfile, 3939 info->printprocessor, 3940 info->datatype, 3941 info->parameters); 3942 3943 if (comment) { 3944 strlcpy(info->comment, comment, sizeof(info->comment)); 3945 SAFE_FREE(comment); 3946 } 3947 3948 /* Samba has to have shared raw drivers. */ 3949 info->attributes |= PRINTER_ATTRIBUTE_SAMBA; 3950 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA; 3951 3952 /* Restore the stripped strings. */ 3953 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername); 3954 3955 if ( lp_force_printername(snum) ) { 3956 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename ); 3957 } else { 3958 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername); 3959 } 3960 3961 fstrcpy(info->printername, printername); 3962 3963#ifdef HAVE_CUPS 3964 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) { 3965 /* Pull the location and comment strings from cups if we don't 3966 already have one */ 3967 if ( !strlen(info->location) || !strlen(info->comment) ) 3968 cups_pull_comment_location( info ); 3969 } 3970#endif 3971 3972 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len); 3973 3974 /* 3975 * Some client drivers freak out if there is a NULL devmode 3976 * (probably the driver is not checking before accessing 3977 * the devmode pointer) --jerry 3978 * 3979 * See comments in get_a_printer_2_default() 3980 */ 3981 3982 if (lp_default_devmode(snum) && !info->devmode) { 3983 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n", 3984 printername)); 3985 info->devmode = construct_nt_devicemode(printername); 3986 } 3987 3988 slprintf( adevice, sizeof(adevice), "%s", info->printername ); 3989 if (info->devmode) { 3990 fstrcpy(info->devmode->devicename, adevice); 3991 } 3992 3993 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) { 3994 DEBUG(0,("unpack_values: talloc() failed!\n")); 3995 SAFE_FREE(dbuf.dptr); 3996 return WERR_NOMEM; 3997 } 3998 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len ); 3999 4000 /* This will get the current RPC talloc context, but we should be 4001 passing this as a parameter... fixme... JRA ! */ 4002 4003 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) { 4004 SAFE_FREE(dbuf.dptr); 4005 return WERR_NOMEM; 4006 } 4007 4008 /* Fix for OS/2 drivers. */ 4009 4010 if (get_remote_arch() == RA_OS2) { 4011 map_to_os2_driver(info->drivername); 4012 } 4013 4014 SAFE_FREE(dbuf.dptr); 4015 4016 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n", 4017 sharename, info->printername, info->drivername)); 4018 4019 return WERR_OK; 4020} 4021 4022/**************************************************************************** 4023 Debugging function, dump at level 6 the struct in the logs. 4024****************************************************************************/ 4025static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level) 4026{ 4027 uint32 result; 4028 NT_PRINTER_INFO_LEVEL_2 *info2; 4029 4030 DEBUG(106,("Dumping printer at level [%d]\n", level)); 4031 4032 switch (level) { 4033 case 2: 4034 { 4035 if (printer->info_2 == NULL) 4036 result=5; 4037 else 4038 { 4039 info2=printer->info_2; 4040 4041 DEBUGADD(106,("attributes:[%d]\n", info2->attributes)); 4042 DEBUGADD(106,("priority:[%d]\n", info2->priority)); 4043 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority)); 4044 DEBUGADD(106,("starttime:[%d]\n", info2->starttime)); 4045 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime)); 4046 DEBUGADD(106,("status:[%d]\n", info2->status)); 4047 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs)); 4048 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm)); 4049 DEBUGADD(106,("changeid:[%d]\n", info2->changeid)); 4050 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter)); 4051 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime)); 4052 4053 DEBUGADD(106,("servername:[%s]\n", info2->servername)); 4054 DEBUGADD(106,("printername:[%s]\n", info2->printername)); 4055 DEBUGADD(106,("sharename:[%s]\n", info2->sharename)); 4056 DEBUGADD(106,("portname:[%s]\n", info2->portname)); 4057 DEBUGADD(106,("drivername:[%s]\n", info2->drivername)); 4058 DEBUGADD(106,("comment:[%s]\n", info2->comment)); 4059 DEBUGADD(106,("location:[%s]\n", info2->location)); 4060 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile)); 4061 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor)); 4062 DEBUGADD(106,("datatype:[%s]\n", info2->datatype)); 4063 DEBUGADD(106,("parameters:[%s]\n", info2->parameters)); 4064 result=0; 4065 } 4066 break; 4067 } 4068 default: 4069 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level )); 4070 result=1; 4071 break; 4072 } 4073 4074 return result; 4075} 4076 4077/**************************************************************************** 4078 Update the changeid time. 4079 This is SO NASTY as some drivers need this to change, others need it 4080 static. This value will change every second, and I must hope that this 4081 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF 4082 UTAH ! JRA. 4083****************************************************************************/ 4084 4085static uint32 rev_changeid(void) 4086{ 4087 struct timeval tv; 4088 4089 get_process_uptime(&tv); 4090 4091#if 1 /* JERRY */ 4092 /* Return changeid as msec since spooler restart */ 4093 return tv.tv_sec * 1000 + tv.tv_usec / 1000; 4094#else 4095 /* 4096 * This setting seems to work well but is too untested 4097 * to replace the above calculation. Left in for experiementation 4098 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002) 4099 */ 4100 return tv.tv_sec * 10 + tv.tv_usec / 100000; 4101#endif 4102} 4103 4104 4105/* 4106 * The function below are the high level ones. 4107 * only those ones must be called from the spoolss code. 4108 * JFM. 4109 */ 4110 4111/**************************************************************************** 4112 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA. 4113****************************************************************************/ 4114 4115WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level) 4116{ 4117 WERROR result; 4118 4119 dump_a_printer(printer, level); 4120 4121 switch (level) { 4122 case 2: 4123 { 4124 /* 4125 * Update the changestamp. Emperical tests show that the 4126 * ChangeID is always updated,but c_setprinter is 4127 * global spooler variable (not per printer). 4128 */ 4129 4130 /* ChangeID **must** be increasing over the lifetime 4131 of client's spoolss service in order for the 4132 client's cache to show updates */ 4133 4134 printer->info_2->changeid = rev_changeid(); 4135 4136 /* 4137 * Because one day someone will ask: 4138 * NT->NT An admin connection to a remote 4139 * printer show changes imeediately in 4140 * the properities dialog 4141 * 4142 * A non-admin connection will only show the 4143 * changes after viewing the properites page 4144 * 2 times. Seems to be related to a 4145 * race condition in the client between the spooler 4146 * updating the local cache and the Explorer.exe GUI 4147 * actually displaying the properties. 4148 * 4149 * This is fixed in Win2k. admin/non-admin 4150 * connections both display changes immediately. 4151 * 4152 * 14/12/01 --jerry 4153 */ 4154 4155 result=update_a_printer_2(printer->info_2); 4156 break; 4157 } 4158 default: 4159 result=WERR_UNKNOWN_LEVEL; 4160 break; 4161 } 4162 4163 return result; 4164} 4165 4166/**************************************************************************** 4167 Initialize printer devmode & data with previously saved driver init values. 4168****************************************************************************/ 4169 4170static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr ) 4171{ 4172 int len = 0; 4173 char *key = NULL; 4174 TDB_DATA dbuf; 4175 NT_PRINTER_INFO_LEVEL_2 info; 4176 4177 4178 ZERO_STRUCT(info); 4179 4180 /* 4181 * Delete any printer data 'values' already set. When called for driver 4182 * replace, there will generally be some, but during an add printer, there 4183 * should not be any (if there are delete them). 4184 */ 4185 4186 if ( info_ptr->data ) 4187 delete_all_printer_data( info_ptr, "" ); 4188 4189 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, 4190 info_ptr->drivername) < 0) { 4191 return false; 4192 } 4193 4194 dbuf = tdb_fetch_bystring(tdb_drivers, key); 4195 if (!dbuf.dptr) { 4196 /* 4197 * When changing to a driver that has no init info in the tdb, remove 4198 * the previous drivers init info and leave the new on blank. 4199 */ 4200 free_nt_devicemode(&info_ptr->devmode); 4201 SAFE_FREE(key); 4202 return false; 4203 } 4204 4205 SAFE_FREE(key); 4206 /* 4207 * Get the saved DEVMODE.. 4208 */ 4209 4210 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len); 4211 4212 /* 4213 * The saved DEVMODE contains the devicename from the printer used during 4214 * the initialization save. Change it to reflect the new printer. 4215 */ 4216 4217 if ( info.devmode ) { 4218 ZERO_STRUCT(info.devmode->devicename); 4219 fstrcpy(info.devmode->devicename, info_ptr->printername); 4220 } 4221 4222 /* 4223 * NT/2k does not change out the entire DeviceMode of a printer 4224 * when changing the driver. Only the driverextra, private, & 4225 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002) 4226 * 4227 * Later examination revealed that Windows NT/2k does reset the 4228 * the printer's device mode, bit **only** when you change a 4229 * property of the device mode such as the page orientation. 4230 * --jerry 4231 */ 4232 4233 4234 /* Bind the saved DEVMODE to the new the printer */ 4235 4236 free_nt_devicemode(&info_ptr->devmode); 4237 info_ptr->devmode = info.devmode; 4238 4239 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n", 4240 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername)); 4241 4242 /* Add the printer data 'values' to the new printer */ 4243 4244 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) { 4245 DEBUG(0,("set_driver_init_2: talloc() failed!\n")); 4246 return False; 4247 } 4248 4249 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len ); 4250 4251 SAFE_FREE(dbuf.dptr); 4252 4253 return true; 4254} 4255 4256/**************************************************************************** 4257 Initialize printer devmode & data with previously saved driver init values. 4258 When a printer is created using AddPrinter, the drivername bound to the 4259 printer is used to lookup previously saved driver initialization info, which 4260 is bound to the new printer. 4261****************************************************************************/ 4262 4263bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) 4264{ 4265 bool result = False; 4266 4267 switch (level) { 4268 case 2: 4269 result = set_driver_init_2(printer->info_2); 4270 break; 4271 4272 default: 4273 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n", 4274 level)); 4275 break; 4276 } 4277 4278 return result; 4279} 4280 4281/**************************************************************************** 4282 Delete driver init data stored for a specified driver 4283****************************************************************************/ 4284 4285bool del_driver_init(const char *drivername) 4286{ 4287 char *key; 4288 bool ret; 4289 4290 if (!drivername || !*drivername) { 4291 DEBUG(3,("del_driver_init: No drivername specified!\n")); 4292 return false; 4293 } 4294 4295 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) { 4296 return false; 4297 } 4298 4299 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", 4300 drivername)); 4301 4302 ret = (tdb_delete_bystring(tdb_drivers, key) == 0); 4303 SAFE_FREE(key); 4304 return ret; 4305} 4306 4307/**************************************************************************** 4308 Pack up the DEVMODE and values for a printer into a 'driver init' entry 4309 in the tdb. Note: this is different from the driver entry and the printer 4310 entry. There should be a single driver init entry for each driver regardless 4311 of whether it was installed from NT or 2K. Technically, they should be 4312 different, but they work out to the same struct. 4313****************************************************************************/ 4314 4315static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info) 4316{ 4317 char *key = NULL; 4318 uint8 *buf; 4319 int buflen, len, ret; 4320 int retlen; 4321 TDB_DATA dbuf; 4322 4323 buf = NULL; 4324 buflen = 0; 4325 4326 again: 4327 len = 0; 4328 len += pack_devicemode(info->devmode, buf+len, buflen-len); 4329 4330 retlen = pack_values( info->data, buf+len, buflen-len ); 4331 if (retlen == -1) { 4332 ret = -1; 4333 goto done; 4334 } 4335 len += retlen; 4336 4337 if (buflen < len) { 4338 buf = (uint8 *)SMB_REALLOC(buf, len); 4339 if (!buf) { 4340 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n")); 4341 ret = -1; 4342 goto done; 4343 } 4344 buflen = len; 4345 goto again; 4346 } 4347 4348 SAFE_FREE(key); 4349 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) { 4350 ret = (uint32)-1; 4351 goto done; 4352 } 4353 4354 dbuf.dptr = buf; 4355 dbuf.dsize = len; 4356 4357 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE); 4358 4359done: 4360 if (ret == -1) 4361 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n")); 4362 4363 SAFE_FREE(buf); 4364 4365 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n", 4366 info->sharename, info->drivername)); 4367 4368 return ret; 4369} 4370 4371/**************************************************************************** 4372 Update (i.e. save) the driver init info (DEVMODE and values) for a printer 4373****************************************************************************/ 4374 4375static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) 4376{ 4377 uint32 result; 4378 4379 dump_a_printer(printer, level); 4380 4381 switch (level) { 4382 case 2: 4383 result = update_driver_init_2(printer->info_2); 4384 break; 4385 default: 4386 result = 1; 4387 break; 4388 } 4389 4390 return result; 4391} 4392 4393/**************************************************************************** 4394 Convert the printer data value, a REG_BINARY array, into an initialization 4395 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc... 4396 got to keep the endians happy :). 4397****************************************************************************/ 4398 4399static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode, 4400 const uint8_t *data, uint32_t data_len) 4401{ 4402 struct spoolss_DeviceMode devmode; 4403 enum ndr_err_code ndr_err; 4404 DATA_BLOB blob; 4405 4406 ZERO_STRUCT(devmode); 4407 4408 blob = data_blob_const(data, data_len); 4409 4410 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode, 4411 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode); 4412 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 4413 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n")); 4414 return false; 4415 } 4416 4417 return convert_devicemode("", &devmode, &nt_devmode); 4418} 4419 4420/**************************************************************************** 4421 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that: 4422 4423 1. Use the driver's config DLL to this UNC printername and: 4424 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE 4425 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE 4426 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data. 4427 4428 The last step triggers saving the "driver initialization" information for 4429 this printer into the tdb. Later, new printers that use this driver will 4430 have this initialization information bound to them. This simulates the 4431 driver initialization, as if it had run on the Samba server (as it would 4432 have done on NT). 4433 4434 The Win32 client side code requirement sucks! But until we can run arbitrary 4435 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it. 4436 4437 It would have been easier to use SetPrinter because all the UNMARSHALLING of 4438 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think 4439 about it and you will realize why. JRR 010720 4440****************************************************************************/ 4441 4442static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len ) 4443{ 4444 WERROR status = WERR_OK; 4445 TALLOC_CTX *ctx = NULL; 4446 NT_DEVICEMODE *nt_devmode = NULL; 4447 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode; 4448 4449 /* 4450 * When the DEVMODE is already set on the printer, don't try to unpack it. 4451 */ 4452 DEBUG(8,("save_driver_init_2: Enter...\n")); 4453 4454 if ( !printer->info_2->devmode && data_len ) { 4455 /* 4456 * Set devmode on printer info, so entire printer initialization can be 4457 * saved to tdb. 4458 */ 4459 4460 if ((ctx = talloc_init("save_driver_init_2")) == NULL) 4461 return WERR_NOMEM; 4462 4463 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) { 4464 status = WERR_NOMEM; 4465 goto done; 4466 } 4467 4468 ZERO_STRUCTP(nt_devmode); 4469 4470 /* 4471 * The DEVMODE is held in the 'data' component of the param in raw binary. 4472 * Convert it to to a devmode structure 4473 */ 4474 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) { 4475 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n")); 4476 status = WERR_INVALID_PARAM; 4477 goto done; 4478 } 4479 4480 printer->info_2->devmode = nt_devmode; 4481 } 4482 4483 /* 4484 * Pack up and add (or update) the DEVMODE and any current printer data to 4485 * a 'driver init' element in the tdb 4486 * 4487 */ 4488 4489 if ( update_driver_init(printer, 2) != 0 ) { 4490 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n")); 4491 status = WERR_NOMEM; 4492 goto done; 4493 } 4494 4495 /* 4496 * If driver initialization info was successfully saved, set the current 4497 * printer to match it. This allows initialization of the current printer 4498 * as well as the driver. 4499 */ 4500 status = mod_a_printer(printer, 2); 4501 if (!W_ERROR_IS_OK(status)) { 4502 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n", 4503 printer->info_2->printername)); 4504 } 4505 4506 done: 4507 talloc_destroy(ctx); 4508 free_nt_devicemode( &nt_devmode ); 4509 4510 printer->info_2->devmode = tmp_devmode; 4511 4512 return status; 4513} 4514 4515/**************************************************************************** 4516 Update the driver init info (DEVMODE and specifics) for a printer 4517****************************************************************************/ 4518 4519WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len) 4520{ 4521 WERROR status = WERR_OK; 4522 4523 switch (level) { 4524 case 2: 4525 status = save_driver_init_2( printer, data, data_len ); 4526 break; 4527 default: 4528 status = WERR_UNKNOWN_LEVEL; 4529 break; 4530 } 4531 4532 return status; 4533} 4534 4535/**************************************************************************** 4536 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory. 4537 4538 Previously the code had a memory allocation problem because it always 4539 used the TALLOC_CTX from the Printer_entry*. This context lasts 4540 as a long as the original handle is open. So if the client made a lot 4541 of getprinter[data]() calls, the memory usage would climb. Now we use 4542 a short lived TALLOC_CTX for printer_info_2 objects returned. We 4543 still use the Printer_entry->ctx for maintaining the cache copy though 4544 since that object must live as long as the handle by definition. 4545 --jerry 4546 4547****************************************************************************/ 4548 4549static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 4550 const char *sharename, bool get_loc_com) 4551{ 4552 WERROR result; 4553 fstring servername; 4554 4555 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level)); 4556 4557 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) { 4558 DEBUG(0,("get_a_printer: talloc() fail.\n")); 4559 return WERR_NOMEM; 4560 } 4561 4562 switch (level) { 4563 case 2: 4564 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) { 4565 DEBUG(0,("get_a_printer: talloc() fail.\n")); 4566 TALLOC_FREE( *pp_printer ); 4567 return WERR_NOMEM; 4568 } 4569 4570 if ( print_hnd ) 4571 fstrcpy( servername, print_hnd->servername ); 4572 else { 4573 fstrcpy( servername, "%L" ); 4574 standard_sub_basic( "", "", servername, 4575 sizeof(servername)-1 ); 4576 } 4577 4578 result = get_a_printer_2( (*pp_printer)->info_2, 4579 servername, sharename, get_loc_com); 4580 4581 /* we have a new printer now. Save it with this handle */ 4582 4583 if ( !W_ERROR_IS_OK(result) ) { 4584 TALLOC_FREE( *pp_printer ); 4585 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 4586 sharename, (unsigned int)level, win_errstr(result))); 4587 return result; 4588 } 4589 4590 dump_a_printer( *pp_printer, level); 4591 4592 break; 4593 4594 default: 4595 TALLOC_FREE( *pp_printer ); 4596 return WERR_UNKNOWN_LEVEL; 4597 } 4598 4599 return WERR_OK; 4600} 4601 4602WERROR get_a_printer( Printer_entry *print_hnd, 4603 NT_PRINTER_INFO_LEVEL **pp_printer, 4604 uint32 level, 4605 const char *sharename) 4606{ 4607 return get_a_printer_internal(print_hnd, pp_printer, level, 4608 sharename, true); 4609} 4610 4611WERROR get_a_printer_search( Printer_entry *print_hnd, 4612 NT_PRINTER_INFO_LEVEL **pp_printer, 4613 uint32 level, 4614 const char *sharename) 4615{ 4616 return get_a_printer_internal(print_hnd, pp_printer, level, 4617 sharename, false); 4618} 4619 4620/**************************************************************************** 4621 Deletes a NT_PRINTER_INFO_LEVEL struct. 4622****************************************************************************/ 4623 4624uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level) 4625{ 4626 NT_PRINTER_INFO_LEVEL *printer = *pp_printer; 4627 4628 if ( !printer ) 4629 return 0; 4630 4631 switch (level) { 4632 case 2: 4633 if ( printer->info_2 ) 4634 free_nt_printer_info_level_2(&printer->info_2); 4635 break; 4636 4637 default: 4638 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level )); 4639 return 1; 4640 } 4641 4642 TALLOC_FREE(*pp_printer); 4643 4644 return 0; 4645} 4646 4647/**************************************************************************** 4648****************************************************************************/ 4649 4650uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx, 4651 struct spoolss_AddDriverInfoCtr *r, 4652 char **driver_name, 4653 uint32_t *version) 4654{ 4655 struct spoolss_DriverInfo8 info8; 4656 4657 ZERO_STRUCT(info8); 4658 4659 DEBUG(10,("adding a printer at level [%d]\n", r->level)); 4660 4661 switch (r->level) { 4662 case 3: 4663 info8.version = r->info.info3->version; 4664 info8.driver_name = r->info.info3->driver_name; 4665 info8.architecture = r->info.info3->architecture; 4666 info8.driver_path = r->info.info3->driver_path; 4667 info8.data_file = r->info.info3->data_file; 4668 info8.config_file = r->info.info3->config_file; 4669 info8.help_file = r->info.info3->help_file; 4670 info8.monitor_name = r->info.info3->monitor_name; 4671 info8.default_datatype = r->info.info3->default_datatype; 4672 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) { 4673 info8.dependent_files = r->info.info3->dependent_files->string; 4674 } 4675 break; 4676 case 6: 4677 info8.version = r->info.info6->version; 4678 info8.driver_name = r->info.info6->driver_name; 4679 info8.architecture = r->info.info6->architecture; 4680 info8.driver_path = r->info.info6->driver_path; 4681 info8.data_file = r->info.info6->data_file; 4682 info8.config_file = r->info.info6->config_file; 4683 info8.help_file = r->info.info6->help_file; 4684 info8.monitor_name = r->info.info6->monitor_name; 4685 info8.default_datatype = r->info.info6->default_datatype; 4686 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) { 4687 info8.dependent_files = r->info.info6->dependent_files->string; 4688 } 4689 info8.driver_date = r->info.info6->driver_date; 4690 info8.driver_version = r->info.info6->driver_version; 4691 info8.manufacturer_name = r->info.info6->manufacturer_name; 4692 info8.manufacturer_url = r->info.info6->manufacturer_url; 4693 info8.hardware_id = r->info.info6->hardware_id; 4694 info8.provider = r->info.info6->provider; 4695 break; 4696 case 8: 4697 info8.version = r->info.info8->version; 4698 info8.driver_name = r->info.info8->driver_name; 4699 info8.architecture = r->info.info8->architecture; 4700 info8.driver_path = r->info.info8->driver_path; 4701 info8.data_file = r->info.info8->data_file; 4702 info8.config_file = r->info.info8->config_file; 4703 info8.help_file = r->info.info8->help_file; 4704 info8.monitor_name = r->info.info8->monitor_name; 4705 info8.default_datatype = r->info.info8->default_datatype; 4706 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) { 4707 info8.dependent_files = r->info.info8->dependent_files->string; 4708 } 4709 if (r->info.info8->previous_names && r->info.info8->previous_names->string) { 4710 info8.previous_names = r->info.info8->previous_names->string; 4711 } 4712 info8.driver_date = r->info.info8->driver_date; 4713 info8.driver_version = r->info.info8->driver_version; 4714 info8.manufacturer_name = r->info.info8->manufacturer_name; 4715 info8.manufacturer_url = r->info.info8->manufacturer_url; 4716 info8.hardware_id = r->info.info8->hardware_id; 4717 info8.provider = r->info.info8->provider; 4718 info8.print_processor = r->info.info8->print_processor; 4719 info8.vendor_setup = r->info.info8->vendor_setup; 4720 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) { 4721 info8.color_profiles = r->info.info8->color_profiles->string; 4722 } 4723 info8.inf_path = r->info.info8->inf_path; 4724 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes; 4725 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) { 4726 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string; 4727 } 4728 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date; 4729 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version; 4730 break; 4731 default: 4732 return -1; 4733 } 4734 4735 *driver_name = talloc_strdup(mem_ctx, info8.driver_name); 4736 if (!*driver_name) { 4737 return -1; 4738 } 4739 *version = info8.version; 4740 4741 return add_a_printer_driver_8(&info8); 4742} 4743 4744/**************************************************************************** 4745****************************************************************************/ 4746 4747WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx, 4748 struct spoolss_DriverInfo8 **driver, 4749 const char *drivername, const char *architecture, 4750 uint32_t version) 4751{ 4752 WERROR result; 4753 struct spoolss_DriverInfo3 info3; 4754 struct spoolss_DriverInfo8 *info8; 4755 4756 ZERO_STRUCT(info3); 4757 4758 /* Sometime we just want any version of the driver */ 4759 4760 if (version == DRIVER_ANY_VERSION) { 4761 /* look for Win2k first and then for NT4 */ 4762 result = get_a_printer_driver_3(mem_ctx, 4763 &info3, 4764 drivername, 4765 architecture, 3); 4766 if (!W_ERROR_IS_OK(result)) { 4767 result = get_a_printer_driver_3(mem_ctx, 4768 &info3, 4769 drivername, 4770 architecture, 2); 4771 } 4772 } else { 4773 result = get_a_printer_driver_3(mem_ctx, 4774 &info3, 4775 drivername, 4776 architecture, 4777 version); 4778 } 4779 4780 if (!W_ERROR_IS_OK(result)) { 4781 return result; 4782 } 4783 4784 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8); 4785 if (!info8) { 4786 return WERR_NOMEM; 4787 } 4788 4789 info8->version = info3.version; 4790 info8->driver_name = info3.driver_name; 4791 info8->architecture = info3.architecture; 4792 info8->driver_path = info3.driver_path; 4793 info8->data_file = info3.data_file; 4794 info8->config_file = info3.config_file; 4795 info8->help_file = info3.help_file; 4796 info8->dependent_files = info3.dependent_files; 4797 info8->monitor_name = info3.monitor_name; 4798 info8->default_datatype = info3.default_datatype; 4799 4800 *driver = info8; 4801 4802 return WERR_OK; 4803} 4804 4805/**************************************************************************** 4806****************************************************************************/ 4807 4808uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver) 4809{ 4810 talloc_free(driver); 4811 return 0; 4812} 4813 4814 4815/**************************************************************************** 4816 Determine whether or not a particular driver is currently assigned 4817 to a printer 4818****************************************************************************/ 4819 4820bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r) 4821{ 4822 int snum; 4823 int n_services = lp_numservices(); 4824 NT_PRINTER_INFO_LEVEL *printer = NULL; 4825 bool in_use = False; 4826 4827 if (!r) { 4828 return false; 4829 } 4830 4831 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n")); 4832 4833 /* loop through the printers.tdb and check for the drivername */ 4834 4835 for (snum=0; snum<n_services && !in_use; snum++) { 4836 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) ) 4837 continue; 4838 4839 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) ) 4840 continue; 4841 4842 if (strequal(r->driver_name, printer->info_2->drivername)) 4843 in_use = True; 4844 4845 free_a_printer( &printer, 2 ); 4846 } 4847 4848 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n")); 4849 4850 if ( in_use ) { 4851 struct spoolss_DriverInfo8 *d; 4852 WERROR werr; 4853 4854 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name)); 4855 4856 /* we can still remove the driver if there is one of 4857 "Windows NT x86" version 2 or 3 left */ 4858 4859 if (!strequal("Windows NT x86", r->architecture)) { 4860 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION); 4861 } 4862 else { 4863 switch (r->version) { 4864 case 2: 4865 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3); 4866 break; 4867 case 3: 4868 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2); 4869 break; 4870 default: 4871 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 4872 r->version)); 4873 werr = WERR_UNKNOWN_PRINTER_DRIVER; 4874 break; 4875 } 4876 } 4877 4878 /* now check the error code */ 4879 4880 if ( W_ERROR_IS_OK(werr) ) { 4881 /* it's ok to remove the driver, we have other architctures left */ 4882 in_use = False; 4883 free_a_printer_driver(d); 4884 } 4885 } 4886 4887 /* report that the driver is not in use by default */ 4888 4889 return in_use; 4890} 4891 4892 4893/********************************************************************** 4894 Check to see if a ogiven file is in use by *info 4895 *********************************************************************/ 4896 4897static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info) 4898{ 4899 int i = 0; 4900 4901 if ( !info ) 4902 return False; 4903 4904 /* mz: skip files that are in the list but already deleted */ 4905 if (!file || !file[0]) { 4906 return false; 4907 } 4908 4909 if (strequal(file, info->driver_path)) 4910 return True; 4911 4912 if (strequal(file, info->data_file)) 4913 return True; 4914 4915 if (strequal(file, info->config_file)) 4916 return True; 4917 4918 if (strequal(file, info->help_file)) 4919 return True; 4920 4921 /* see of there are any dependent files to examine */ 4922 4923 if (!info->dependent_files) 4924 return False; 4925 4926 while (info->dependent_files[i] && *info->dependent_files[i]) { 4927 if (strequal(file, info->dependent_files[i])) 4928 return True; 4929 i++; 4930 } 4931 4932 return False; 4933 4934} 4935 4936/********************************************************************** 4937 Utility function to remove the dependent file pointed to by the 4938 input parameter from the list 4939 *********************************************************************/ 4940 4941static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx) 4942{ 4943 4944 /* bump everything down a slot */ 4945 4946 while (files && files[idx+1]) { 4947 files[idx] = talloc_strdup(mem_ctx, files[idx+1]); 4948 idx++; 4949 } 4950 4951 files[idx] = NULL; 4952 4953 return; 4954} 4955 4956/********************************************************************** 4957 Check if any of the files used by src are also used by drv 4958 *********************************************************************/ 4959 4960static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx, 4961 struct spoolss_DriverInfo8 *src, 4962 const struct spoolss_DriverInfo8 *drv) 4963{ 4964 bool in_use = False; 4965 int i = 0; 4966 4967 if ( !src || !drv ) 4968 return False; 4969 4970 /* check each file. Remove it from the src structure if it overlaps */ 4971 4972 if (drv_file_in_use(src->driver_path, drv)) { 4973 in_use = True; 4974 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path)); 4975 src->driver_path = talloc_strdup(mem_ctx, ""); 4976 if (!src->driver_path) { return false; } 4977 } 4978 4979 if (drv_file_in_use(src->data_file, drv)) { 4980 in_use = True; 4981 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file)); 4982 src->data_file = talloc_strdup(mem_ctx, ""); 4983 if (!src->data_file) { return false; } 4984 } 4985 4986 if (drv_file_in_use(src->config_file, drv)) { 4987 in_use = True; 4988 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file)); 4989 src->config_file = talloc_strdup(mem_ctx, ""); 4990 if (!src->config_file) { return false; } 4991 } 4992 4993 if (drv_file_in_use(src->help_file, drv)) { 4994 in_use = True; 4995 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file)); 4996 src->help_file = talloc_strdup(mem_ctx, ""); 4997 if (!src->help_file) { return false; } 4998 } 4999 5000 /* are there any dependentfiles to examine? */ 5001 5002 if (!src->dependent_files) 5003 return in_use; 5004 5005 while (src->dependent_files[i] && *src->dependent_files[i]) { 5006 if (drv_file_in_use(src->dependent_files[i], drv)) { 5007 in_use = True; 5008 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i])); 5009 trim_dependent_file(mem_ctx, src->dependent_files, i); 5010 } else 5011 i++; 5012 } 5013 5014 return in_use; 5015} 5016 5017/**************************************************************************** 5018 Determine whether or not a particular driver files are currently being 5019 used by any other driver. 5020 5021 Return value is True if any files were in use by other drivers 5022 and False otherwise. 5023 5024 Upon return, *info has been modified to only contain the driver files 5025 which are not in use 5026 5027 Fix from mz: 5028 5029 This needs to check all drivers to ensure that all files in use 5030 have been removed from *info, not just the ones in the first 5031 match. 5032****************************************************************************/ 5033 5034bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx, 5035 struct spoolss_DriverInfo8 *info) 5036{ 5037 int i; 5038 int ndrivers; 5039 uint32 version; 5040 fstring *list = NULL; 5041 struct spoolss_DriverInfo8 *driver; 5042 bool in_use = false; 5043 5044 if ( !info ) 5045 return False; 5046 5047 version = info->version; 5048 5049 /* loop over all driver versions */ 5050 5051 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n")); 5052 5053 /* get the list of drivers */ 5054 5055 list = NULL; 5056 ndrivers = get_ntdrivers(&list, info->architecture, version); 5057 5058 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 5059 ndrivers, info->architecture, version)); 5060 5061 /* check each driver for overlap in files */ 5062 5063 for (i=0; i<ndrivers; i++) { 5064 DEBUGADD(5,("\tdriver: [%s]\n", list[i])); 5065 5066 driver = NULL; 5067 5068 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) { 5069 SAFE_FREE(list); 5070 return True; 5071 } 5072 5073 /* check if d2 uses any files from d1 */ 5074 /* only if this is a different driver than the one being deleted */ 5075 5076 if (!strequal(info->driver_name, driver->driver_name)) { 5077 if (trim_overlap_drv_files(mem_ctx, info, driver)) { 5078 /* mz: Do not instantly return - 5079 * we need to ensure this file isn't 5080 * also in use by other drivers. */ 5081 in_use = true; 5082 } 5083 } 5084 5085 free_a_printer_driver(driver); 5086 } 5087 5088 SAFE_FREE(list); 5089 5090 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n")); 5091 5092 return in_use; 5093} 5094 5095static NTSTATUS driver_unlink_internals(connection_struct *conn, 5096 const char *name) 5097{ 5098 struct smb_filename *smb_fname = NULL; 5099 NTSTATUS status; 5100 5101 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL, 5102 &smb_fname); 5103 if (!NT_STATUS_IS_OK(status)) { 5104 return status; 5105 } 5106 5107 status = unlink_internals(conn, NULL, 0, smb_fname, false); 5108 5109 TALLOC_FREE(smb_fname); 5110 return status; 5111} 5112 5113/**************************************************************************** 5114 Actually delete the driver files. Make sure that 5115 printer_driver_files_in_use() return False before calling 5116 this. 5117****************************************************************************/ 5118 5119static bool delete_driver_files(struct pipes_struct *rpc_pipe, 5120 const struct spoolss_DriverInfo8 *r) 5121{ 5122 int i = 0; 5123 char *s; 5124 const char *file; 5125 connection_struct *conn; 5126 NTSTATUS nt_status; 5127 char *oldcwd; 5128 fstring printdollar; 5129 int printdollar_snum; 5130 bool ret = false; 5131 5132 if (!r) { 5133 return false; 5134 } 5135 5136 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", 5137 r->driver_name, r->version)); 5138 5139 fstrcpy(printdollar, "print$"); 5140 5141 printdollar_snum = find_service(printdollar); 5142 if (printdollar_snum == -1) { 5143 return false; 5144 } 5145 5146 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum, 5147 lp_pathname(printdollar_snum), 5148 rpc_pipe->server_info, &oldcwd); 5149 if (!NT_STATUS_IS_OK(nt_status)) { 5150 DEBUG(0,("delete_driver_files: create_conn_struct " 5151 "returned %s\n", nt_errstr(nt_status))); 5152 return false; 5153 } 5154 5155 if ( !CAN_WRITE(conn) ) { 5156 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n")); 5157 goto fail; 5158 } 5159 5160 /* now delete the files; must strip the '\print$' string from 5161 fron of path */ 5162 5163 if (r->driver_path && r->driver_path[0]) { 5164 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) { 5165 file = s; 5166 DEBUG(10,("deleting driverfile [%s]\n", s)); 5167 driver_unlink_internals(conn, file); 5168 } 5169 } 5170 5171 if (r->config_file && r->config_file[0]) { 5172 if ((s = strchr(&r->config_file[1], '\\')) != NULL) { 5173 file = s; 5174 DEBUG(10,("deleting configfile [%s]\n", s)); 5175 driver_unlink_internals(conn, file); 5176 } 5177 } 5178 5179 if (r->data_file && r->data_file[0]) { 5180 if ((s = strchr(&r->data_file[1], '\\')) != NULL) { 5181 file = s; 5182 DEBUG(10,("deleting datafile [%s]\n", s)); 5183 driver_unlink_internals(conn, file); 5184 } 5185 } 5186 5187 if (r->help_file && r->help_file[0]) { 5188 if ((s = strchr(&r->help_file[1], '\\')) != NULL) { 5189 file = s; 5190 DEBUG(10,("deleting helpfile [%s]\n", s)); 5191 driver_unlink_internals(conn, file); 5192 } 5193 } 5194 5195 /* check if we are done removing files */ 5196 5197 if (r->dependent_files) { 5198 while (r->dependent_files[i] && r->dependent_files[i][0]) { 5199 char *p; 5200 5201 /* bypass the "\print$" portion of the path */ 5202 5203 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) { 5204 file = p; 5205 DEBUG(10,("deleting dependent file [%s]\n", file)); 5206 driver_unlink_internals(conn, file); 5207 } 5208 5209 i++; 5210 } 5211 } 5212 5213 goto done; 5214 fail: 5215 ret = false; 5216 done: 5217 if (conn != NULL) { 5218 vfs_ChDir(conn, oldcwd); 5219 conn_free(conn); 5220 } 5221 return ret; 5222} 5223 5224/**************************************************************************** 5225 Remove a printer driver from the TDB. This assumes that the the driver was 5226 previously looked up. 5227 ***************************************************************************/ 5228 5229WERROR delete_printer_driver(struct pipes_struct *rpc_pipe, 5230 const struct spoolss_DriverInfo8 *r, 5231 uint32 version, bool delete_files ) 5232{ 5233 char *key = NULL; 5234 const char *arch; 5235 TDB_DATA dbuf; 5236 5237 /* delete the tdb data first */ 5238 5239 arch = get_short_archi(r->architecture); 5240 if (!arch) { 5241 return WERR_UNKNOWN_PRINTER_DRIVER; 5242 } 5243 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX, 5244 arch, version, r->driver_name) < 0) { 5245 return WERR_NOMEM; 5246 } 5247 5248 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n", 5249 key, delete_files ? "TRUE" : "FALSE" )); 5250 5251 /* check if the driver actually exists for this environment */ 5252 5253 dbuf = tdb_fetch_bystring( tdb_drivers, key ); 5254 if ( !dbuf.dptr ) { 5255 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key)); 5256 SAFE_FREE(key); 5257 return WERR_UNKNOWN_PRINTER_DRIVER; 5258 } 5259 5260 SAFE_FREE( dbuf.dptr ); 5261 5262 /* ok... the driver exists so the delete should return success */ 5263 5264 if (tdb_delete_bystring(tdb_drivers, key) == -1) { 5265 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key)); 5266 SAFE_FREE(key); 5267 return WERR_ACCESS_DENIED; 5268 } 5269 5270 /* 5271 * now delete any associated files if delete_files == True 5272 * even if this part failes, we return succes because the 5273 * driver doesn not exist any more 5274 */ 5275 5276 if ( delete_files ) 5277 delete_driver_files(rpc_pipe, r); 5278 5279 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key)); 5280 SAFE_FREE(key); 5281 5282 return WERR_OK; 5283} 5284 5285/**************************************************************************** 5286 Store a security desc for a printer. 5287****************************************************************************/ 5288 5289WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr) 5290{ 5291 SEC_DESC_BUF *new_secdesc_ctr = NULL; 5292 SEC_DESC_BUF *old_secdesc_ctr = NULL; 5293 TALLOC_CTX *mem_ctx = NULL; 5294 TDB_DATA kbuf; 5295 TDB_DATA dbuf; 5296 DATA_BLOB blob; 5297 WERROR status; 5298 NTSTATUS nt_status; 5299 5300 mem_ctx = talloc_init("nt_printing_setsec"); 5301 if (mem_ctx == NULL) 5302 return WERR_NOMEM; 5303 5304 /* The old owner and group sids of the security descriptor are not 5305 present when new ACEs are added or removed by changing printer 5306 permissions through NT. If they are NULL in the new security 5307 descriptor then copy them over from the old one. */ 5308 5309 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) { 5310 DOM_SID *owner_sid, *group_sid; 5311 SEC_ACL *dacl, *sacl; 5312 SEC_DESC *psd = NULL; 5313 size_t size; 5314 5315 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) { 5316 status = WERR_NOMEM; 5317 goto out; 5318 } 5319 5320 /* Pick out correct owner and group sids */ 5321 5322 owner_sid = secdesc_ctr->sd->owner_sid ? 5323 secdesc_ctr->sd->owner_sid : 5324 old_secdesc_ctr->sd->owner_sid; 5325 5326 group_sid = secdesc_ctr->sd->group_sid ? 5327 secdesc_ctr->sd->group_sid : 5328 old_secdesc_ctr->sd->group_sid; 5329 5330 dacl = secdesc_ctr->sd->dacl ? 5331 secdesc_ctr->sd->dacl : 5332 old_secdesc_ctr->sd->dacl; 5333 5334 sacl = secdesc_ctr->sd->sacl ? 5335 secdesc_ctr->sd->sacl : 5336 old_secdesc_ctr->sd->sacl; 5337 5338 /* Make a deep copy of the security descriptor */ 5339 5340 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type, 5341 owner_sid, group_sid, 5342 sacl, 5343 dacl, 5344 &size); 5345 5346 if (!psd) { 5347 status = WERR_NOMEM; 5348 goto out; 5349 } 5350 5351 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd); 5352 } 5353 5354 if (!new_secdesc_ctr) { 5355 new_secdesc_ctr = secdesc_ctr; 5356 } 5357 5358 /* Store the security descriptor in a tdb */ 5359 5360 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr, 5361 &blob.data, &blob.length); 5362 if (!NT_STATUS_IS_OK(nt_status)) { 5363 status = ntstatus_to_werror(nt_status); 5364 goto out; 5365 } 5366 5367 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename ); 5368 5369 dbuf.dptr = (unsigned char *)blob.data; 5370 dbuf.dsize = blob.length; 5371 5372 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) { 5373 status = WERR_OK; 5374 } else { 5375 DEBUG(1,("Failed to store secdesc for %s\n", sharename)); 5376 status = WERR_BADFUNC; 5377 } 5378 5379 /* Free malloc'ed memory */ 5380 talloc_free(blob.data); 5381 5382 out: 5383 5384 if (mem_ctx) 5385 talloc_destroy(mem_ctx); 5386 return status; 5387} 5388 5389/**************************************************************************** 5390 Construct a default security descriptor buffer for a printer. 5391****************************************************************************/ 5392 5393static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) 5394{ 5395 SEC_ACE ace[5]; /* max number of ace entries */ 5396 int i = 0; 5397 uint32_t sa; 5398 SEC_ACL *psa = NULL; 5399 SEC_DESC_BUF *sdb = NULL; 5400 SEC_DESC *psd = NULL; 5401 DOM_SID adm_sid; 5402 size_t sd_size; 5403 5404 /* Create an ACE where Everyone is allowed to print */ 5405 5406 sa = PRINTER_ACE_PRINT; 5407 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, 5408 sa, SEC_ACE_FLAG_CONTAINER_INHERIT); 5409 5410 /* Add the domain admins group if we are a DC */ 5411 5412 if ( IS_DC ) { 5413 DOM_SID domadmins_sid; 5414 5415 sid_copy(&domadmins_sid, get_global_sam_sid()); 5416 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS); 5417 5418 sa = PRINTER_ACE_FULL_CONTROL; 5419 init_sec_ace(&ace[i++], &domadmins_sid, 5420 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 5421 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); 5422 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, 5423 sa, SEC_ACE_FLAG_CONTAINER_INHERIT); 5424 } 5425 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) { 5426 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN); 5427 5428 sa = PRINTER_ACE_FULL_CONTROL; 5429 init_sec_ace(&ace[i++], &adm_sid, 5430 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 5431 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); 5432 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, 5433 sa, SEC_ACE_FLAG_CONTAINER_INHERIT); 5434 } 5435 5436 /* add BUILTIN\Administrators as FULL CONTROL */ 5437 5438 sa = PRINTER_ACE_FULL_CONTROL; 5439 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 5440 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 5441 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); 5442 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 5443 SEC_ACE_TYPE_ACCESS_ALLOWED, 5444 sa, SEC_ACE_FLAG_CONTAINER_INHERIT); 5445 5446 /* Make the security descriptor owned by the BUILTIN\Administrators */ 5447 5448 /* The ACL revision number in rpc_secdesc.h differs from the one 5449 created by NT when setting ACE entries in printer 5450 descriptors. NT4 complains about the property being edited by a 5451 NT5 machine. */ 5452 5453 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) { 5454 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, 5455 &global_sid_Builtin_Administrators, 5456 &global_sid_Builtin_Administrators, 5457 NULL, psa, &sd_size); 5458 } 5459 5460 if (!psd) { 5461 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n")); 5462 return NULL; 5463 } 5464 5465 sdb = make_sec_desc_buf(ctx, sd_size, psd); 5466 5467 DEBUG(4,("construct_default_printer_sdb: size = %u.\n", 5468 (unsigned int)sd_size)); 5469 5470 return sdb; 5471} 5472 5473/**************************************************************************** 5474 Get a security desc for a printer. 5475****************************************************************************/ 5476 5477bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr) 5478{ 5479 TDB_DATA kbuf; 5480 TDB_DATA dbuf; 5481 DATA_BLOB blob; 5482 char *temp; 5483 NTSTATUS status; 5484 5485 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) { 5486 sharename = temp + 1; 5487 } 5488 5489 /* Fetch security descriptor from tdb */ 5490 5491 kbuf = make_printers_secdesc_tdbkey(ctx, sharename); 5492 5493 dbuf = tdb_fetch(tdb_printers, kbuf); 5494 if (dbuf.dptr) { 5495 5496 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize, 5497 secdesc_ctr); 5498 SAFE_FREE(dbuf.dptr); 5499 5500 if (NT_STATUS_IS_OK(status)) { 5501 return true; 5502 } 5503 } 5504 5505 *secdesc_ctr = construct_default_printer_sdb(ctx); 5506 if (!*secdesc_ctr) { 5507 return false; 5508 } 5509 5510 status = marshall_sec_desc_buf(ctx, *secdesc_ctr, 5511 &blob.data, &blob.length); 5512 if (NT_STATUS_IS_OK(status)) { 5513 dbuf.dptr = (unsigned char *)blob.data; 5514 dbuf.dsize = blob.length; 5515 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE); 5516 talloc_free(blob.data); 5517 } 5518 5519 /* If security descriptor is owned by S-1-1-0 and winbindd is up, 5520 this security descriptor has been created when winbindd was 5521 down. Take ownership of security descriptor. */ 5522 5523 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) { 5524 DOM_SID owner_sid; 5525 5526 /* Change sd owner to workgroup administrator */ 5527 5528 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) { 5529 SEC_DESC_BUF *new_secdesc_ctr = NULL; 5530 SEC_DESC *psd = NULL; 5531 size_t size; 5532 5533 /* Create new sd */ 5534 5535 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN); 5536 5537 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type, 5538 &owner_sid, 5539 (*secdesc_ctr)->sd->group_sid, 5540 (*secdesc_ctr)->sd->sacl, 5541 (*secdesc_ctr)->sd->dacl, 5542 &size); 5543 5544 if (!psd) { 5545 return False; 5546 } 5547 5548 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd); 5549 if (!new_secdesc_ctr) { 5550 return False; 5551 } 5552 5553 /* Swap with other one */ 5554 5555 *secdesc_ctr = new_secdesc_ctr; 5556 5557 /* Set it */ 5558 5559 nt_printing_setsec(sharename, *secdesc_ctr); 5560 } 5561 } 5562 5563 if (DEBUGLEVEL >= 10) { 5564 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl; 5565 int i; 5566 5567 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 5568 sharename, the_acl->num_aces)); 5569 5570 for (i = 0; i < the_acl->num_aces; i++) { 5571 DEBUG(10, ("%s %d %d 0x%08x\n", 5572 sid_string_dbg(&the_acl->aces[i].trustee), 5573 the_acl->aces[i].type, the_acl->aces[i].flags, 5574 the_acl->aces[i].access_mask)); 5575 } 5576 } 5577 5578 return True; 5579} 5580 5581/* error code: 5582 0: everything OK 5583 1: level not implemented 5584 2: file doesn't exist 5585 3: can't allocate memory 5586 4: can't free memory 5587 5: non existant struct 5588*/ 5589 5590/* 5591 A printer and a printer driver are 2 different things. 5592 NT manages them separatelly, Samba does the same. 5593 Why ? Simply because it's easier and it makes sense ! 5594 5595 Now explanation: You have 3 printers behind your samba server, 5596 2 of them are the same make and model (laser A and B). But laser B 5597 has an 3000 sheet feeder and laser A doesn't such an option. 5598 Your third printer is an old dot-matrix model for the accounting :-). 5599 5600 If the /usr/local/samba/lib directory (default dir), you will have 5601 5 files to describe all of this. 5602 5603 3 files for the printers (1 by printer): 5604 NTprinter_laser A 5605 NTprinter_laser B 5606 NTprinter_accounting 5607 2 files for the drivers (1 for the laser and 1 for the dot matrix) 5608 NTdriver_printer model X 5609 NTdriver_printer model Y 5610 5611jfm: I should use this comment for the text file to explain 5612 same thing for the forms BTW. 5613 Je devrais mettre mes commentaires en francais, ca serait mieux :-) 5614 5615*/ 5616 5617/* Convert generic access rights to printer object specific access rights. 5618 It turns out that NT4 security descriptors use generic access rights and 5619 NT5 the object specific ones. */ 5620 5621void map_printer_permissions(SEC_DESC *sd) 5622{ 5623 int i; 5624 5625 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { 5626 se_map_generic(&sd->dacl->aces[i].access_mask, 5627 &printer_generic_mapping); 5628 } 5629} 5630 5631void map_job_permissions(SEC_DESC *sd) 5632{ 5633 int i; 5634 5635 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { 5636 se_map_generic(&sd->dacl->aces[i].access_mask, 5637 &job_generic_mapping); 5638 } 5639} 5640 5641 5642/**************************************************************************** 5643 Check a user has permissions to perform the given operation. We use the 5644 permission constants defined in include/rpc_spoolss.h to check the various 5645 actions we perform when checking printer access. 5646 5647 PRINTER_ACCESS_ADMINISTER: 5648 print_queue_pause, print_queue_resume, update_printer_sec, 5649 update_printer, spoolss_addprinterex_level_2, 5650 _spoolss_setprinterdata 5651 5652 PRINTER_ACCESS_USE: 5653 print_job_start 5654 5655 JOB_ACCESS_ADMINISTER: 5656 print_job_delete, print_job_pause, print_job_resume, 5657 print_queue_purge 5658 5659 Try access control in the following order (for performance reasons): 5660 1) root and SE_PRINT_OPERATOR can do anything (easy check) 5661 2) check security descriptor (bit comparisons in memory) 5662 3) "printer admins" (may result in numerous calls to winbind) 5663 5664 ****************************************************************************/ 5665bool print_access_check(struct auth_serversupplied_info *server_info, int snum, 5666 int access_type) 5667{ 5668 SEC_DESC_BUF *secdesc = NULL; 5669 uint32 access_granted; 5670 NTSTATUS status; 5671 const char *pname; 5672 TALLOC_CTX *mem_ctx = NULL; 5673 SE_PRIV se_printop = SE_PRINT_OPERATOR; 5674 5675 /* If user is NULL then use the current_user structure */ 5676 5677 /* Always allow root or SE_PRINT_OPERATROR to do anything */ 5678 5679 if (server_info->utok.uid == sec_initial_uid() 5680 || user_has_privileges(server_info->ptok, &se_printop ) ) { 5681 return True; 5682 } 5683 5684 /* Get printer name */ 5685 5686 pname = PRINTERNAME(snum); 5687 5688 if (!pname || !*pname) { 5689 errno = EACCES; 5690 return False; 5691 } 5692 5693 /* Get printer security descriptor */ 5694 5695 if(!(mem_ctx = talloc_init("print_access_check"))) { 5696 errno = ENOMEM; 5697 return False; 5698 } 5699 5700 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) { 5701 talloc_destroy(mem_ctx); 5702 errno = ENOMEM; 5703 return False; 5704 } 5705 5706 if (access_type == JOB_ACCESS_ADMINISTER) { 5707 SEC_DESC_BUF *parent_secdesc = secdesc; 5708 5709 /* Create a child security descriptor to check permissions 5710 against. This is because print jobs are child objects 5711 objects of a printer. */ 5712 5713 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False); 5714 5715 if (!NT_STATUS_IS_OK(status)) { 5716 talloc_destroy(mem_ctx); 5717 errno = map_errno_from_nt_status(status); 5718 return False; 5719 } 5720 5721 map_job_permissions(secdesc->sd); 5722 } else { 5723 map_printer_permissions(secdesc->sd); 5724 } 5725 5726 /* Check access */ 5727 status = se_access_check(secdesc->sd, server_info->ptok, access_type, 5728 &access_granted); 5729 5730 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE")); 5731 5732 /* see if we need to try the printer admin list */ 5733 5734 if (!NT_STATUS_IS_OK(status) && 5735 (token_contains_name_in_list(uidtoname(server_info->utok.uid), 5736 pdb_get_domain(server_info->sam_account), 5737 NULL, 5738 server_info->ptok, 5739 lp_printer_admin(snum)))) { 5740 talloc_destroy(mem_ctx); 5741 return True; 5742 } 5743 5744 talloc_destroy(mem_ctx); 5745 5746 if (!NT_STATUS_IS_OK(status)) { 5747 errno = EACCES; 5748 } 5749 5750 return NT_STATUS_IS_OK(status); 5751} 5752 5753/**************************************************************************** 5754 Check the time parameters allow a print operation. 5755*****************************************************************************/ 5756 5757bool print_time_access_check(const char *servicename) 5758{ 5759 NT_PRINTER_INFO_LEVEL *printer = NULL; 5760 bool ok = False; 5761 time_t now = time(NULL); 5762 struct tm *t; 5763 uint32 mins; 5764 5765 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename))) 5766 return False; 5767 5768 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0) 5769 ok = True; 5770 5771 t = gmtime(&now); 5772 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min; 5773 5774 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime) 5775 ok = True; 5776 5777 free_a_printer(&printer, 2); 5778 5779 if (!ok) 5780 errno = EACCES; 5781 5782 return ok; 5783} 5784 5785/**************************************************************************** 5786 Fill in the servername sent in the _spoolss_open_printer_ex() call 5787****************************************************************************/ 5788 5789char* get_server_name( Printer_entry *printer ) 5790{ 5791 return printer->servername; 5792} 5793 5794 5795