X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fprinting%2Fnt_printing.c;h=9ead42df5b6b11b148fc02621305adbc77d241de;hb=c136b84f0d28d1a88c5918b06f81766a271a3780;hp=a8bc577370544e8ba42f9cb8bc381026f3893736;hpb=348b4b9bab0cd0f87860441218658802e8aba410;p=kai%2Fsamba.git diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index a8bc5773705..9ead42df5b6 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -22,23 +22,15 @@ #include "includes.h" #include "librpc/gen_ndr/messaging.h" #include "printing/pcap.h" - -static TDB_CONTEXT *tdb_forms; /* used for forms files */ -static TDB_CONTEXT *tdb_drivers; /* used for driver files */ -static TDB_CONTEXT *tdb_printers; /* used for printers files */ - -#define FORMS_PREFIX "FORMS/" -#define DRIVERS_PREFIX "DRIVERS/" -#define DRIVER_INIT_PREFIX "DRIVER_INIT/" -#define PRINTERS_PREFIX "PRINTERS/" -#define SECDESC_PREFIX "SECDESC/" -#define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter" - -#define NTDRIVERS_DATABASE_VERSION_1 1 -#define NTDRIVERS_DATABASE_VERSION_2 2 -#define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */ -#define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */ -#define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */ +#include "printing/nt_printing_tdb.h" +#include "printing/nt_printing_migrate.h" +#include "registry.h" +#include "registry/reg_objects.h" +#include "../librpc/gen_ndr/ndr_security.h" +#include "../librpc/gen_ndr/ndr_spoolss.h" +#include "rpc_server/srv_spoolss_util.h" +#include "nt_printing.h" +#include "secrets.h" /* Map generic permissions to printer object specific permissions */ @@ -49,13 +41,6 @@ const struct generic_mapping printer_generic_mapping = { PRINTER_ALL_ACCESS }; -const struct standard_mapping printer_std_mapping = { - PRINTER_READ, - PRINTER_WRITE, - PRINTER_EXECUTE, - PRINTER_ALL_ACCESS -}; - /* Map generic permissions to print server object specific permissions */ const struct generic_mapping printserver_generic_mapping = { @@ -65,13 +50,6 @@ const struct generic_mapping printserver_generic_mapping = { SERVER_ALL_ACCESS }; -const struct generic_mapping printserver_std_mapping = { - SERVER_READ, - SERVER_WRITE, - SERVER_EXECUTE, - SERVER_ALL_ACCESS -}; - /* Map generic permissions to job object specific permissions */ const struct generic_mapping job_generic_mapping = { @@ -81,131 +59,6 @@ const struct generic_mapping job_generic_mapping = { JOB_ALL_ACCESS }; -/* We need one default form to support our default printer. Msoft adds the -forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an -array index). Letter is always first, so (for the current code) additions -always put things in the correct order. */ -static const nt_forms_struct default_forms[] = { - {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368}, - {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368}, - {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8}, - {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368}, - {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10}, - {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c}, - {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc}, - {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0}, - {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828}, - {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828}, - {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450}, - {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0}, - {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8}, - {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8}, - {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238}, - {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10}, - {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8}, - {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368}, - {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091}, - {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94}, - {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565}, - {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368}, - {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504}, - {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0}, - {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70}, - {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0}, - {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60}, - {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88}, - {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10}, - {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0}, - {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0}, - {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88}, - {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8}, - {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090}, - {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848}, - {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270}, - {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824}, - {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec}, - {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368}, - {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0}, - {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8}, - {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8}, - {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220}, - {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368}, - {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368}, - {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368}, - {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60}, - {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1}, - {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1}, - {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0}, - {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048}, - {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0}, - {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16}, - {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368}, - {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828}, - {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0}, - {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0}, - {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58}, - {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16}, - {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910}, - {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450}, - {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8}, - {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48}, - {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8}, - {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620}, - {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050}, - {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0}, - {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48}, - {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220}, - {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220}, - {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0}, - {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08}, - {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8}, - {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8}, - {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c}, - {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828}, - {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450}, - {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220}, - {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8}, - {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0}, - {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0}, - {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40}, - {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28}, - {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980}, - {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0}, - {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0}, - {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90}, - {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0}, - {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400}, - {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1}, - {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8}, - {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28}, - {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0}, - {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0}, - {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8}, - {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488}, - {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80}, - {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80}, - {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80}, - {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60}, - {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270}, - {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270}, - {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708}, - {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0}, - {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10}, - {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60}, - {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0}, - {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0}, - {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70}, - {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70}, - {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848}, - {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0}, - {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0}, - {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0}, - {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100}, - {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0}, - {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88}, - {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0} -}; - static const struct print_architecture_table_node archi_table[]= { {"Windows 4.0", SPL_ARCH_WIN40, 0 }, @@ -218,418 +71,36 @@ static const struct print_architecture_table_node archi_table[]= { {NULL, "", -1 } }; - -/**************************************************************************** - generate a new TDB_DATA key for storing a printer -****************************************************************************/ - -static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename ) -{ - fstring share; - char *keystr = NULL; - TDB_DATA key; - - fstrcpy(share, sharename); - strlower_m(share); - - keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share); - key = string_term_tdb_data(keystr ? keystr : ""); - - return key; -} - -/**************************************************************************** - generate a new TDB_DATA key for storing a printer security descriptor -****************************************************************************/ - -static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx, - const char* sharename ) -{ - fstring share; - char *keystr = NULL; - TDB_DATA key; - - fstrcpy(share, sharename ); - strlower_m(share); - - keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share); - key = string_term_tdb_data(keystr ? keystr : ""); - - return key; -} - -/**************************************************************************** -****************************************************************************/ - -static bool upgrade_to_version_3(void) -{ - TDB_DATA kbuf, newkey, dbuf; - - DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n")); - - for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr; - newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) { - - dbuf = tdb_fetch(tdb_drivers, kbuf); - - if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) { - DEBUG(0,("upgrade_to_version_3:moving form\n")); - if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms))); - return False; - } - if (tdb_delete(tdb_drivers, kbuf) != 0) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers))); - return False; - } - } - - if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) { - DEBUG(0,("upgrade_to_version_3:moving printer\n")); - if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers))); - return False; - } - if (tdb_delete(tdb_drivers, kbuf) != 0) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers))); - return False; - } - } - - if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) { - DEBUG(0,("upgrade_to_version_3:moving secdesc\n")); - if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers))); - return False; - } - if (tdb_delete(tdb_drivers, kbuf) != 0) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers))); - return False; - } - } - - SAFE_FREE(dbuf.dptr); - } - - return True; -} - -/******************************************************************* - Fix an issue with security descriptors. Printer sec_desc must - use more than the generic bits that were previously used - in <= 3.0.14a. They must also have a owner and group SID assigned. - Otherwise, any printers than have been migrated to a Windows - host using printmig.exe will not be accessible. -*******************************************************************/ - -static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key, - TDB_DATA data, void *state ) -{ - NTSTATUS status; - SEC_DESC_BUF *sd_orig = NULL; - SEC_DESC_BUF *sd_new, *sd_store; - SEC_DESC *sec, *new_sec; - TALLOC_CTX *ctx = state; - int result, i; - uint32 sd_size; - size_t size_new_sec; - - if (!data.dptr || data.dsize == 0) { - return 0; - } - - if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) { - return 0; - } - - /* upgrade the security descriptor */ - - status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig); - if (!NT_STATUS_IS_OK(status)) { - /* delete bad entries */ - DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", - (const char *)key.dptr )); - tdb_delete( tdb_printers, key ); - return 0; - } - - if (!sd_orig) { - return 0; - } - sec = sd_orig->sd; - - /* is this even valid? */ - - if ( !sec->dacl ) { - return 0; - } - - /* update access masks */ - - for ( i=0; idacl->num_aces; i++ ) { - switch ( sec->dacl->aces[i].access_mask ) { - case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS): - sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT; - break; - - case GENERIC_ALL_ACCESS: - sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL; - break; - - case READ_CONTROL_ACCESS: - sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS; - - default: /* no change */ - break; - } - } - - /* create a new SEC_DESC with the appropriate owner and group SIDs */ - - new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, - &global_sid_Builtin_Administrators, - &global_sid_Builtin_Administrators, - NULL, NULL, &size_new_sec ); - if (!new_sec) { - return 0; - } - sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec ); - if (!sd_new) { - return 0; - } - - if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) { - DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr )); - return 0; - } - - /* store it back */ - - sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0) - + sizeof(SEC_DESC_BUF); - - status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr )); - return 0; - } - - result = tdb_store( tdb_printers, key, data, TDB_REPLACE ); - - /* 0 to continue and non-zero to stop traversal */ - - return (result == -1); -} - -/******************************************************************* -*******************************************************************/ - -static bool upgrade_to_version_4(void) -{ - TALLOC_CTX *ctx; - int result; - - DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n")); - - if ( !(ctx = talloc_init( "upgrade_to_version_4" )) ) - return False; - - result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx ); - - talloc_destroy( ctx ); - - return ( result != -1 ); -} - -/******************************************************************* - Fix an issue with security descriptors. Printer sec_desc must - use more than the generic bits that were previously used - in <= 3.0.14a. They must also have a owner and group SID assigned. - Otherwise, any printers than have been migrated to a Windows - host using printmig.exe will not be accessible. -*******************************************************************/ - -static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key, - TDB_DATA data, void *state ) -{ - TALLOC_CTX *ctx = talloc_tos(); - TDB_DATA new_key; - - if (!data.dptr || data.dsize == 0) - return 0; - - /* upgrade printer records and security descriptors */ - - if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) { - new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) ); - } - else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) { - new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) ); - } - else { - /* ignore this record */ - return 0; - } - - /* delete the original record and store under the normalized key */ - - if ( tdb_delete( the_tdb, key ) != 0 ) { - DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n", - key.dptr)); - return 1; - } - - if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) { - DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n", - key.dptr)); - return 1; - } - - return 0; -} - -/******************************************************************* -*******************************************************************/ - -static bool upgrade_to_version_5(void) -{ - TALLOC_CTX *ctx; - int result; - - DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n")); - - if ( !(ctx = talloc_init( "upgrade_to_version_5" )) ) - return False; - - result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL ); - - talloc_destroy( ctx ); - - return ( result != -1 ); -} - /**************************************************************************** Open the NT printing tdbs. Done once before fork(). ****************************************************************************/ bool nt_printing_init(struct messaging_context *msg_ctx) { - const char *vstring = "INFO/version"; WERROR win_rc; - int32 vers_id; - - if ( tdb_drivers && tdb_printers && tdb_forms ) - return True; - - if (tdb_drivers) - tdb_close(tdb_drivers); - tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - if (!tdb_drivers) { - DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n", - state_path("ntdrivers.tdb"), strerror(errno) )); - return False; - } - - if (tdb_printers) - tdb_close(tdb_printers); - tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - if (!tdb_printers) { - DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n", - state_path("ntprinters.tdb"), strerror(errno) )); - return False; - } - - if (tdb_forms) - tdb_close(tdb_forms); - tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - if (!tdb_forms) { - DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n", - state_path("ntforms.tdb"), strerror(errno) )); - return False; - } - - /* handle a Samba upgrade */ - - vers_id = tdb_fetch_int32(tdb_drivers, vstring); - if (vers_id == -1) { - DEBUG(10, ("Fresh database\n")); - tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 ); - vers_id = NTDRIVERS_DATABASE_VERSION_5; - } - - if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) { - - if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { - if (!upgrade_to_version_3()) - return False; - tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3); - vers_id = NTDRIVERS_DATABASE_VERSION_3; - } - if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) { - /* Written on a bigendian machine with old fetch_int code. Save as le. */ - /* The only upgrade between V2 and V3 is to save the version in little-endian. */ - tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3); - vers_id = NTDRIVERS_DATABASE_VERSION_3; - } - - if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) { - if ( !upgrade_to_version_4() ) - return False; - tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4); - vers_id = NTDRIVERS_DATABASE_VERSION_4; - } - - if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) { - if ( !upgrade_to_version_5() ) - return False; - tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5); - vers_id = NTDRIVERS_DATABASE_VERSION_5; - } - - - if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) { - DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id)); - return False; - } + if (!nt_printing_tdb_upgrade()) { + return false; } - update_c_setprinter(True); - /* * register callback to handle updating printers as new * drivers are installed */ - messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer); - /* - * register callback to handle updating printer data - * when a driver is initialized - */ - - messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET, - reset_all_printerdata); - /* of course, none of the message callbacks matter if you don't tell messages.c that you interested in receiving PRINT_GENERAL msgs. This is done in serverid_register() */ - if ( lp_security() == SEC_ADS ) { win_rc = check_published_printers(); if (!W_ERROR_IS_OK(win_rc)) DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc))); } - return True; + return true; } /******************************************************************* @@ -662,403 +133,60 @@ static NTSTATUS driver_unix_convert(connection_struct *conn, return NT_STATUS_OK; } -/******************************************************************* - tdb traversal function for counting printers. -********************************************************************/ - -static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key, - TDB_DATA data, void *context) -{ - int *printer_count = (int*)context; - - if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) { - (*printer_count)++; - DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count)); - } - - return 0; -} - -/******************************************************************* - Update the spooler global c_setprinter. This variable is initialized - when the parent smbd starts with the number of existing printers. It - is monotonically increased by the current number of printers *after* - each add or delete printer RPC. Only Microsoft knows why... JRR020119 -********************************************************************/ +/**************************************************************************** + Function to do the mapping between the long architecture name and + the short one. +****************************************************************************/ -uint32 update_c_setprinter(bool initialize) +const char *get_short_archi(const char *long_archi) { - int32 c_setprinter; - int32 printer_count = 0; - - tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); - - /* Traverse the tdb, counting the printers */ - tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count); - - /* If initializing, set c_setprinter to current printers count - * otherwise, bump it by the current printer count - */ - if (!initialize) - c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count; - else - c_setprinter = printer_count; - - DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter)); - tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter); - - tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); - - return (uint32)c_setprinter; -} + int i=-1; -/******************************************************************* - Get the spooler global c_setprinter, accounting for initialization. -********************************************************************/ + DEBUG(107,("Getting architecture dependant directory\n")); + do { + i++; + } while ( (archi_table[i].long_archi!=NULL ) && + StrCaseCmp(long_archi, archi_table[i].long_archi) ); -uint32 get_c_setprinter(void) -{ - int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER); + if (archi_table[i].long_archi==NULL) { + DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi)); + return NULL; + } - if (c_setprinter == (int32)-1) - c_setprinter = update_c_setprinter(True); + /* this might be client code - but shouldn't this be an fstrcpy etc? */ - DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter)); + DEBUGADD(108,("index: [%d]\n", i)); + DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi)); + DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi)); - return (uint32)c_setprinter; + return archi_table[i].short_archi; } /**************************************************************************** - Get builtin form struct list. + Version information in Microsoft files is held in a VS_VERSION_INFO structure. + There are two case to be covered here: PE (Portable Executable) and NE (New + Executable) files. Both files support the same INFO structure, but PE files + store the signature in unicode, and NE files store it as !unicode. + returns -1 on error, 1 on version info found, and 0 on no version info found. ****************************************************************************/ -int get_builtin_ntforms(nt_forms_struct **list) +static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor) { - *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms)); - if (!*list) { - return 0; - } - return ARRAY_SIZE(default_forms); -} - -/**************************************************************************** - get a builtin form struct -****************************************************************************/ + int i; + char *buf = NULL; + ssize_t byte_count; -bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form) -{ - int i; - DEBUGADD(6,("Looking for builtin form %s \n", form_name)); - for (i=0; iform_name) ) { - update=True; - break; - } - } - - if (update==False) { - if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) { - DEBUG(0,("add_a_form: failed to enlarge forms list!\n")); - return False; - } - fstrcpy((*list)[n].name, form->form_name); - (*count)++; - } - - (*list)[n].flag = form->flags; - (*list)[n].width = form->size.width; - (*list)[n].length = form->size.height; - (*list)[n].left = form->area.left; - (*list)[n].top = form->area.top; - (*list)[n].right = form->area.right; - (*list)[n].bottom = form->area.bottom; - - DEBUG(6,("add_a_form: Successfully %s form [%s]\n", - update ? "updated" : "added", form->form_name)); - - return True; -} - -/**************************************************************************** - Delete a named form struct. -****************************************************************************/ - -bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret) -{ - char *key = NULL; - int n=0; - - *ret = WERR_OK; - - for (n=0; n<*count; n++) { - if (!strncmp((*list)[n].name, del_name, strlen(del_name))) { - DEBUG(103, ("delete_a_form, [%s] in list\n", del_name)); - break; - } - } - - if (n == *count) { - DEBUG(10,("delete_a_form, [%s] not found\n", del_name)); - *ret = WERR_INVALID_FORM_NAME; - return False; - } - - if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) { - *ret = WERR_NOMEM; - return false; - } - if (tdb_delete_bystring(tdb_forms, key) != 0) { - SAFE_FREE(key); - *ret = WERR_NOMEM; - return False; - } - SAFE_FREE(key); - return true; -} - -/**************************************************************************** - Update a form struct. -****************************************************************************/ - -void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count) -{ - int n=0; - - DEBUG(106, ("[%s]\n", form->form_name)); - for (n=0; nform_name, strlen(form->form_name))) - break; - } - - if (n==count) return; - - (*list)[n].flag = form->flags; - (*list)[n].width = form->size.width; - (*list)[n].length = form->size.height; - (*list)[n].left = form->area.left; - (*list)[n].top = form->area.top; - (*list)[n].right = form->area.right; - (*list)[n].bottom = form->area.bottom; -} - -/**************************************************************************** - Get the nt drivers list. - Traverse the database and look-up the matching names. -****************************************************************************/ -int get_ntdrivers(fstring **list, const char *architecture, uint32 version) -{ - int total=0; - const char *short_archi; - char *key = NULL; - TDB_DATA kbuf, newkey; - - short_archi = get_short_archi(architecture); - if (!short_archi) { - return 0; - } - - if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX, - short_archi, version) < 0) { - return 0; - } - - for (kbuf = tdb_firstkey(tdb_drivers); - kbuf.dptr; - newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) { - - if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0) - continue; - - if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) { - DEBUG(0,("get_ntdrivers: failed to enlarge list!\n")); - SAFE_FREE(key); - return -1; - } - - fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key)); - total++; - } - - SAFE_FREE(key); - return(total); -} - -/**************************************************************************** - Function to do the mapping between the long architecture name and - the short one. -****************************************************************************/ - -const char *get_short_archi(const char *long_archi) -{ - int i=-1; - - DEBUG(107,("Getting architecture dependant directory\n")); - do { - i++; - } while ( (archi_table[i].long_archi!=NULL ) && - StrCaseCmp(long_archi, archi_table[i].long_archi) ); - - if (archi_table[i].long_archi==NULL) { - DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi)); - return NULL; - } - - /* this might be client code - but shouldn't this be an fstrcpy etc? */ - - DEBUGADD(108,("index: [%d]\n", i)); - DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi)); - DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi)); - - return archi_table[i].short_archi; -} - -/**************************************************************************** - Version information in Microsoft files is held in a VS_VERSION_INFO structure. - There are two case to be covered here: PE (Portable Executable) and NE (New - Executable) files. Both files support the same INFO structure, but PE files - store the signature in unicode, and NE files store it as !unicode. - returns -1 on error, 1 on version info found, and 0 on no version info found. -****************************************************************************/ - -static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor) -{ - int i; - char *buf = NULL; - ssize_t byte_count; - - if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) { - DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n", - fname, DOS_HEADER_SIZE)); - goto error_exit; - } - - if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) { - DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n", - fname, (unsigned long)byte_count)); - goto no_version_info; - } + if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) { + DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n", + fname, (unsigned long)byte_count)); + goto no_version_info; + } /* Is this really a DOS header? */ if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) { @@ -1680,12 +808,13 @@ static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx, /**************************************************************************** ****************************************************************************/ -WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe, +WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx, + struct pipes_struct *rpc_pipe, struct spoolss_AddDriverInfoCtr *r) { switch (r->level) { case 3: - return clean_up_driver_struct_level(r, rpc_pipe, + return clean_up_driver_struct_level(mem_ctx, rpc_pipe, r->info.info3->architecture, &r->info.info3->driver_path, &r->info.info3->data_file, @@ -1694,7 +823,7 @@ WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe, r->info.info3->dependent_files, &r->info.info3->version); case 6: - return clean_up_driver_struct_level(r, rpc_pipe, + return clean_up_driver_struct_level(mem_ctx, rpc_pipe, r->info.info6->architecture, &r->info.info6->driver_path, &r->info.info6->data_file, @@ -1728,32 +857,6 @@ static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst, dst->dependent_files = src->dependent_files; } -/**************************************************************************** - This function sucks and should be replaced. JRA. -****************************************************************************/ - -static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx, - struct spoolss_AddDriverInfo3 *dst, - const struct spoolss_DriverInfo8 *src) -{ - dst->version = src->version; - dst->driver_name = src->driver_name; - dst->architecture = src->architecture; - dst->driver_path = src->driver_path; - dst->data_file = src->data_file; - dst->config_file = src->config_file; - dst->help_file = src->help_file; - dst->monitor_name = src->monitor_name; - dst->default_datatype = src->default_datatype; - if (src->dependent_files) { - dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray); - if (!dst->dependent_files) return; - dst->dependent_files->string = src->dependent_files; - } else { - dst->dependent_files = NULL; - } -} - /**************************************************************************** ****************************************************************************/ @@ -2039,546 +1142,32 @@ WERROR move_driver_to_download_area(struct pipes_struct *p, } /**************************************************************************** + Create and allocate a default devicemode. ****************************************************************************/ -static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver) -{ - TALLOC_CTX *ctx = talloc_tos(); - int len, buflen; - const char *architecture; - char *directory = NULL; - char *key = NULL; - uint8 *buf; - int i, ret; - TDB_DATA dbuf; - - architecture = get_short_archi(driver->architecture); - if (!architecture) { - return (uint32)-1; - } - - /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx - * \\server is added in the rpc server layer. - * It does make sense to NOT store the server's name in the printer TDB. - */ - - directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\", - architecture, driver->version); - if (!directory) { - return (uint32)-1; - } - -#define gen_full_driver_unc_path(ctx, directory, file) \ - do { \ - if (file && strlen(file)) { \ - file = talloc_asprintf(ctx, "%s%s", directory, file); \ - } else { \ - file = talloc_strdup(ctx, ""); \ - } \ - if (!file) { \ - return (uint32_t)-1; \ - } \ - } while (0); - - /* .inf files do not always list a file for each of the four standard files. - * Don't prepend a path to a null filename, or client claims: - * "The server on which the printer resides does not have a suitable - * printer driver installed. Click OK if you - * wish to install the driver on your local machine." - */ - - gen_full_driver_unc_path(ctx, directory, driver->driver_path); - gen_full_driver_unc_path(ctx, directory, driver->data_file); - gen_full_driver_unc_path(ctx, directory, driver->config_file); - gen_full_driver_unc_path(ctx, directory, driver->help_file); - - if (driver->dependent_files && driver->dependent_files->string) { - for (i=0; driver->dependent_files->string[i]; i++) { - gen_full_driver_unc_path(ctx, directory, - driver->dependent_files->string[i]); - } - } - - key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX, - architecture, driver->version, driver->driver_name); - if (!key) { - return (uint32)-1; - } - - DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key )); - - buf = NULL; - len = buflen = 0; - - again: - len = 0; - len += tdb_pack(buf+len, buflen-len, "dffffffff", - driver->version, - driver->driver_name, - driver->architecture, - driver->driver_path, - driver->data_file, - driver->config_file, - driver->help_file, - driver->monitor_name ? driver->monitor_name : "", - driver->default_datatype ? driver->default_datatype : ""); - - if (driver->dependent_files && driver->dependent_files->string) { - for (i=0; driver->dependent_files->string[i]; i++) { - len += tdb_pack(buf+len, buflen-len, "f", - driver->dependent_files->string[i]); - } - } - - if (len != buflen) { - buf = (uint8 *)SMB_REALLOC(buf, len); - if (!buf) { - DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!")); - ret = -1; - goto done; - } - buflen = len; - goto again; - } - - dbuf.dptr = buf; - dbuf.dsize = len; - - ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE); - -done: - if (ret) - DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key )); - - SAFE_FREE(buf); - return ret; -} - -/**************************************************************************** -****************************************************************************/ - -static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver) -{ - TALLOC_CTX *mem_ctx = talloc_new(talloc_tos()); - struct spoolss_AddDriverInfo3 info3; - uint32_t ret; - - convert_level_8_to_level3(mem_ctx, &info3, driver); - - ret = add_a_printer_driver_3(&info3); - talloc_free(mem_ctx); - - return ret; -} - -/**************************************************************************** -****************************************************************************/ - -static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx, - struct spoolss_DriverInfo3 *info, - const char *driver, const char *arch) +WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx, + const char *devicename, + struct spoolss_DeviceMode **devmode) { - info->driver_name = talloc_strdup(mem_ctx, driver); - if (!info->driver_name) { - return WERR_NOMEM; - } + struct spoolss_DeviceMode *dm; + char *dname; - info->default_datatype = talloc_strdup(mem_ctx, "RAW"); - if (!info->default_datatype) { + dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode); + if (dm == NULL) { return WERR_NOMEM; } - info->driver_path = talloc_strdup(mem_ctx, ""); - info->data_file = talloc_strdup(mem_ctx, ""); - info->config_file = talloc_strdup(mem_ctx, ""); - info->help_file = talloc_strdup(mem_ctx, ""); - if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) { + dname = talloc_asprintf(dm, "%s", devicename); + if (dname == NULL) { return WERR_NOMEM; } - - return WERR_OK; -} - -/**************************************************************************** -****************************************************************************/ - -static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx, - struct spoolss_DriverInfo3 *driver, - const char *drivername, const char *arch, - uint32_t version) -{ - TDB_DATA dbuf; - const char *architecture; - int len = 0; - int i; - char *key = NULL; - fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype; - - architecture = get_short_archi(arch); - if ( !architecture ) { - return WERR_UNKNOWN_PRINTER_DRIVER; + if (strlen(dname) > MAXDEVICENAME) { + dname[MAXDEVICENAME] = '\0'; } + dm->devicename = dname; - /* Windows 4.0 (i.e. win9x) should always use a version of 0 */ - - if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 ) - version = 0; - - DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername)); - - if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX, - architecture, version, drivername) < 0) { - return WERR_NOMEM; - } - - dbuf = tdb_fetch_bystring(tdb_drivers, key); - if (!dbuf.dptr) { - SAFE_FREE(key); - return WERR_UNKNOWN_PRINTER_DRIVER; - } - - len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff", - &driver->version, - name, - environment, - driverpath, - datafile, - configfile, - helpfile, - monitorname, - defaultdatatype); - - driver->driver_name = talloc_strdup(mem_ctx, name); - driver->architecture = talloc_strdup(mem_ctx, environment); - driver->driver_path = talloc_strdup(mem_ctx, driverpath); - driver->data_file = talloc_strdup(mem_ctx, datafile); - driver->config_file = talloc_strdup(mem_ctx, configfile); - driver->help_file = talloc_strdup(mem_ctx, helpfile); - driver->monitor_name = talloc_strdup(mem_ctx, monitorname); - driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype); - - i=0; - - while (len < dbuf.dsize) { - - fstring file; - - driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2); - if (!driver->dependent_files ) { - DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n")); - break; - } - - len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", - &file); - - driver->dependent_files[i] = talloc_strdup(mem_ctx, file); - - i++; - } - - if (driver->dependent_files) - driver->dependent_files[i] = NULL; - - SAFE_FREE(dbuf.dptr); - SAFE_FREE(key); - - if (len != dbuf.dsize) { - return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch); - } - - return WERR_OK; -} - -/**************************************************************************** -****************************************************************************/ -int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen) -{ - int len = 0; - - len += tdb_pack(buf+len, buflen-len, "p", nt_devmode); - - if (!nt_devmode) - return len; - - len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp", - nt_devmode->devicename, - nt_devmode->formname, - - nt_devmode->specversion, - nt_devmode->driverversion, - nt_devmode->size, - nt_devmode->driverextra, - nt_devmode->orientation, - nt_devmode->papersize, - nt_devmode->paperlength, - nt_devmode->paperwidth, - nt_devmode->scale, - nt_devmode->copies, - nt_devmode->defaultsource, - nt_devmode->printquality, - nt_devmode->color, - nt_devmode->duplex, - nt_devmode->yresolution, - nt_devmode->ttoption, - nt_devmode->collate, - nt_devmode->logpixels, - - nt_devmode->fields, - nt_devmode->bitsperpel, - nt_devmode->pelswidth, - nt_devmode->pelsheight, - nt_devmode->displayflags, - nt_devmode->displayfrequency, - nt_devmode->icmmethod, - nt_devmode->icmintent, - nt_devmode->mediatype, - nt_devmode->dithertype, - nt_devmode->reserved1, - nt_devmode->reserved2, - nt_devmode->panningwidth, - nt_devmode->panningheight, - nt_devmode->nt_dev_private); - - if (nt_devmode->nt_dev_private) { - len += tdb_pack(buf+len, buflen-len, "B", - nt_devmode->driverextra, - nt_devmode->nt_dev_private); - } - - DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname)); - - return len; -} - -/**************************************************************************** - Pack all values in all printer keys - ***************************************************************************/ - -static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen) -{ - int len = 0; - int i, j; - struct regval_blob *val; - struct regval_ctr *val_ctr; - char *path = NULL; - int num_values; - - if ( !data ) - return 0; - - /* loop over all keys */ - - for ( i=0; inum_keys; i++ ) { - val_ctr = data->keys[i].values; - num_values = regval_ctr_numvals( val_ctr ); - - /* pack the keyname followed by a empty value */ - - len += tdb_pack(buf+len, buflen-len, "pPdB", - &data->keys[i].name, - data->keys[i].name, - REG_NONE, - 0, - NULL); - - /* now loop over all values */ - - for ( j=0; j\ */ - - val = regval_ctr_specific_value( val_ctr, j ); - if (asprintf(&path, "%s\\%s", - data->keys[i].name, - regval_name(val)) < 0) { - return -1; - } - - len += tdb_pack(buf+len, buflen-len, "pPdB", - val, - path, - regval_type(val), - regval_size(val), - regval_data_p(val) ); - - DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val))); - SAFE_FREE(path); - } - - } - - /* terminator */ - - len += tdb_pack(buf+len, buflen-len, "p", NULL); - - return len; -} - - -/**************************************************************************** - Delete a printer - this just deletes the printer info file, any open - handles are not affected. -****************************************************************************/ - -uint32 del_a_printer(const char *sharename) -{ - TDB_DATA kbuf; - char *printdb_path = NULL; - TALLOC_CTX *ctx = talloc_tos(); - - kbuf = make_printer_tdbkey(ctx, sharename); - tdb_delete(tdb_printers, kbuf); - - kbuf= make_printers_secdesc_tdbkey(ctx, sharename); - tdb_delete(tdb_printers, kbuf); - - close_all_print_db(); - - if (geteuid() == sec_initial_uid()) { - if (asprintf(&printdb_path, "%s%s.tdb", - cache_path("printing/"), - sharename) < 0) { - return (uint32)-1; - } - unlink(printdb_path); - SAFE_FREE(printdb_path); - } - - return 0; -} - -/**************************************************************************** -****************************************************************************/ -static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) -{ - uint8 *buf; - int buflen, len; - int retlen; - WERROR ret; - TDB_DATA kbuf, dbuf; - - /* - * in addprinter: no servername and the printer is the name - * in setprinter: servername is \\server - * and printer is \\server\\printer - * - * Samba manages only local printers. - * we currently don't support things like i - * path=\\other_server\printer - * - * We only store the printername, not \\server\printername - */ - - if ( info->servername[0] != '\0' ) { - trim_string(info->printername, info->servername, NULL); - trim_char(info->printername, '\\', '\0'); - info->servername[0]='\0'; - } - - /* - * JFM: one day I'll forget. - * below that's info->portname because that's the SAMBA sharename - * and I made NT 'thinks' it's the portname - * the info->sharename is the thing you can name when you add a printer - * that's the short-name when you create shared printer for 95/98 - * So I've made a limitation in SAMBA: you can only have 1 printer model - * behind a SAMBA share. - */ - - buf = NULL; - buflen = 0; - - again: - len = 0; - len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff", - info->attributes, - info->priority, - info->default_priority, - info->starttime, - info->untiltime, - info->status, - info->cjobs, - info->averageppm, - info->changeid, - info->c_setprinter, - info->setuptime, - info->servername, - info->printername, - info->sharename, - info->portname, - info->drivername, - info->comment, - info->location, - info->sepfile, - info->printprocessor, - info->datatype, - info->parameters); - - len += pack_devicemode(info->devmode, buf+len, buflen-len); - retlen = pack_values( info->data, buf+len, buflen-len ); - if (retlen == -1) { - ret = WERR_NOMEM; - goto done; - } - len += retlen; - - if (buflen != len) { - buf = (uint8 *)SMB_REALLOC(buf, len); - if (!buf) { - DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n")); - ret = WERR_NOMEM; - goto done; - } - buflen = len; - goto again; - } - - kbuf = make_printer_tdbkey(talloc_tos(), info->sharename ); - - dbuf.dptr = buf; - dbuf.dsize = len; - - ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM); - -done: - if (!W_ERROR_IS_OK(ret)) - DEBUG(8, ("error updating printer to tdb on disk\n")); - - SAFE_FREE(buf); - - DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n", - info->sharename, info->drivername, info->portname, len)); - - return ret; -} - -/**************************************************************************** - Create and allocate a default devicemode. -****************************************************************************/ - -WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx, - const char *devicename, - struct spoolss_DeviceMode **devmode) -{ - struct spoolss_DeviceMode *dm; - char *dname; - - dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode); - if (dm == NULL) { - return WERR_NOMEM; - } - - dname = talloc_asprintf(dm, "%s", devicename); - if (dname == NULL) { - return WERR_NOMEM; - } - if (strlen(dname) > MAXDEVICENAME) { - dname[MAXDEVICENAME] = '\0'; - } - dm->devicename = dname; - - dm->formname = talloc_strdup(dm, "Letter"); - if (dm->formname == NULL) { + dm->formname = talloc_strdup(dm, "Letter"); + if (dm->formname == NULL) { return WERR_NOMEM; } @@ -2633,2193 +1222,239 @@ WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx, WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx, struct spoolss_security_descriptor **secdesc) { - SEC_ACE ace[5]; /* max number of ace entries */ + struct security_ace ace[7]; /* max number of ace entries */ int i = 0; uint32_t sa; - SEC_ACL *psa = NULL; - SEC_DESC *psd = NULL; - DOM_SID adm_sid; + struct security_acl *psa = NULL; + struct security_descriptor *psd = NULL; + struct dom_sid adm_sid; size_t sd_size; - /* Create an ACE where Everyone is allowed to print */ - - sa = PRINTER_ACE_PRINT; - init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, - sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - - /* Add the domain admins group if we are a DC */ - - if ( IS_DC ) { - DOM_SID domadmins_sid; - - sid_compose(&domadmins_sid, get_global_sam_sid(), - DOMAIN_GROUP_RID_ADMINS); - - sa = PRINTER_ACE_FULL_CONTROL; - init_sec_ace(&ace[i++], &domadmins_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, sa, - SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); - init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, - sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - } - else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) { - sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN); - - sa = PRINTER_ACE_FULL_CONTROL; - init_sec_ace(&ace[i++], &adm_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, sa, - SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); - init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, - sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - } - - /* add BUILTIN\Administrators as FULL CONTROL */ - - sa = PRINTER_ACE_FULL_CONTROL; - init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, - SEC_ACE_TYPE_ACCESS_ALLOWED, sa, - SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); - init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, - SEC_ACE_TYPE_ACCESS_ALLOWED, - sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - - /* Make the security descriptor owned by the BUILTIN\Administrators */ - - /* The ACL revision number in rpc_secdesc.h differs from the one - created by NT when setting ACE entries in printer - descriptors. NT4 complains about the property being edited by a - NT5 machine. */ - - if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) { - psd = make_sec_desc(mem_ctx, - SEC_DESC_REVISION, - SEC_DESC_SELF_RELATIVE, - &global_sid_Builtin_Administrators, - &global_sid_Builtin_Administrators, - NULL, - psa, - &sd_size); - } - - if (psd == NULL) { - DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n")); - return WERR_NOMEM; - } - - DEBUG(4,("construct_default_printer_sdb: size = %u.\n", - (unsigned int)sd_size)); - - *secdesc = psd; - - return WERR_OK; -} - -/**************************************************************************** - Malloc and return an NT devicemode. -****************************************************************************/ - -NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename) -{ - - char adevice[MAXDEVICENAME]; - NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE); - - if (nt_devmode == NULL) { - DEBUG(0,("construct_nt_devicemode: malloc fail.\n")); - return NULL; - } - - ZERO_STRUCTP(nt_devmode); - - slprintf(adevice, sizeof(adevice), "%s", default_devicename); - fstrcpy(nt_devmode->devicename, adevice); - - fstrcpy(nt_devmode->formname, "Letter"); - - nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE; - nt_devmode->driverversion = 0x0400; - nt_devmode->size = 0x00DC; - nt_devmode->driverextra = 0x0000; - nt_devmode->fields = DEVMODE_FORMNAME | - DEVMODE_TTOPTION | - DEVMODE_PRINTQUALITY | - DEVMODE_DEFAULTSOURCE | - DEVMODE_COPIES | - DEVMODE_SCALE | - DEVMODE_PAPERSIZE | - DEVMODE_ORIENTATION; - nt_devmode->orientation = DMORIENT_PORTRAIT; - nt_devmode->papersize = DMPAPER_LETTER; - nt_devmode->paperlength = 0; - nt_devmode->paperwidth = 0; - nt_devmode->scale = 0x64; - nt_devmode->copies = 1; - nt_devmode->defaultsource = DMBIN_FORMSOURCE; - nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */ - nt_devmode->color = DMRES_MONOCHROME; - nt_devmode->duplex = DMDUP_SIMPLEX; - nt_devmode->yresolution = 0; - nt_devmode->ttoption = DMTT_SUBDEV; - nt_devmode->collate = DMCOLLATE_FALSE; - nt_devmode->icmmethod = 0; - nt_devmode->icmintent = 0; - nt_devmode->mediatype = 0; - nt_devmode->dithertype = 0; - - /* non utilisés par un driver d'imprimante */ - nt_devmode->logpixels = 0; - nt_devmode->bitsperpel = 0; - nt_devmode->pelswidth = 0; - nt_devmode->pelsheight = 0; - nt_devmode->displayflags = 0; - nt_devmode->displayfrequency = 0; - nt_devmode->reserved1 = 0; - nt_devmode->reserved2 = 0; - nt_devmode->panningwidth = 0; - nt_devmode->panningheight = 0; - - nt_devmode->nt_dev_private = NULL; - return nt_devmode; -} - -/**************************************************************************** - Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE. -****************************************************************************/ - -void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr) -{ - NT_DEVICEMODE *nt_devmode = *devmode_ptr; - - if(nt_devmode == NULL) - return; - - DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n")); - - SAFE_FREE(nt_devmode->nt_dev_private); - SAFE_FREE(*devmode_ptr); -} - -/**************************************************************************** - Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2. -****************************************************************************/ - -static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr) -{ - NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr; - - if ( !info ) - return; - - free_nt_devicemode(&info->devmode); - - TALLOC_FREE( *info_ptr ); -} - - -/**************************************************************************** -****************************************************************************/ -int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen) -{ - int len = 0; - int extra_len = 0; - NT_DEVICEMODE devmode; - - ZERO_STRUCT(devmode); - - len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode); - - if (!*nt_devmode) return len; - - len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp", - devmode.devicename, - devmode.formname, - - &devmode.specversion, - &devmode.driverversion, - &devmode.size, - &devmode.driverextra, - &devmode.orientation, - &devmode.papersize, - &devmode.paperlength, - &devmode.paperwidth, - &devmode.scale, - &devmode.copies, - &devmode.defaultsource, - &devmode.printquality, - &devmode.color, - &devmode.duplex, - &devmode.yresolution, - &devmode.ttoption, - &devmode.collate, - &devmode.logpixels, - - &devmode.fields, - &devmode.bitsperpel, - &devmode.pelswidth, - &devmode.pelsheight, - &devmode.displayflags, - &devmode.displayfrequency, - &devmode.icmmethod, - &devmode.icmintent, - &devmode.mediatype, - &devmode.dithertype, - &devmode.reserved1, - &devmode.reserved2, - &devmode.panningwidth, - &devmode.panningheight, - &devmode.nt_dev_private); - - if (devmode.nt_dev_private) { - /* the len in tdb_unpack is an int value and - * devmode.driverextra is only a short - */ - len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private); - devmode.driverextra=(uint16)extra_len; - - /* check to catch an invalid TDB entry so we don't segfault */ - if (devmode.driverextra == 0) { - devmode.nt_dev_private = NULL; - } - } - - *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode)); - if (!*nt_devmode) { - SAFE_FREE(devmode.nt_dev_private); - return -1; - } - - DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname)); - if (devmode.nt_dev_private) - DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra)); - - return len; -} - -/**************************************************************************** - Allocate and initialize a new slot. -***************************************************************************/ - -int add_new_printer_key( NT_PRINTER_DATA *data, const char *name ) -{ - NT_PRINTER_KEY *d; - int key_index; - - if ( !name || !data ) - return -1; - - /* allocate another slot in the NT_PRINTER_KEY array */ - - if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) { - DEBUG(0,("add_new_printer_key: Realloc() failed!\n")); - return -1; - } - - data->keys = d; - - key_index = data->num_keys; - - /* initialze new key */ - - data->keys[key_index].name = talloc_strdup( data, name ); - - if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) ) - return -1; - - data->num_keys++; - - DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name )); - - return key_index; -} - -/**************************************************************************** - search for a registry key name in the existing printer data - ***************************************************************************/ - -int delete_printer_key( NT_PRINTER_DATA *data, const char *name ) -{ - int i; - - for ( i=0; inum_keys; i++ ) { - if ( strequal( data->keys[i].name, name ) ) { - - /* cleanup memory */ - - TALLOC_FREE( data->keys[i].name ); - TALLOC_FREE( data->keys[i].values ); - - /* if not the end of the array, move remaining elements down one slot */ - - data->num_keys--; - if ( data->num_keys && (i < data->num_keys) ) - memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) ); - - break; - } - } - - - return data->num_keys; -} - -/**************************************************************************** - search for a registry key name in the existing printer data - ***************************************************************************/ - -int lookup_printerkey( NT_PRINTER_DATA *data, const char *name ) -{ - int key_index = -1; - int i; - - if ( !data || !name ) - return -1; - - DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name)); - - /* loop over all existing keys */ - - for ( i=0; inum_keys; i++ ) { - if ( strequal(data->keys[i].name, name) ) { - DEBUG(12,("lookup_printerkey: Found [%s]!\n", name)); - key_index = i; - break; - - } - } - - return key_index; -} - -/**************************************************************************** - ***************************************************************************/ - -int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys ) -{ - int i, j; - int key_len; - int num_subkeys = 0; - char *p; - fstring *subkeys_ptr = NULL; - fstring subkeyname; - - *subkeys = NULL; - - if ( !data ) - return 0; - - if ( !key ) - return -1; - - /* special case of asking for the top level printer data registry key names */ - - if ( strlen(key) == 0 ) { - for ( i=0; inum_keys; i++ ) { - - /* found a match, so allocate space and copy the name */ - - if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) { - DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", - num_subkeys+1)); - return -1; - } - - fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name ); - num_subkeys++; - } - - goto done; - } - - /* asking for the subkeys of some key */ - /* subkey paths are stored in the key name using '\' as the delimiter */ - - for ( i=0; inum_keys; i++ ) { - if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) { - - /* if we found the exact key, then break */ - key_len = strlen( key ); - if ( strlen(data->keys[i].name) == key_len ) - break; - - /* get subkey path */ - - p = data->keys[i].name + key_len; - if ( *p == '\\' ) - p++; - fstrcpy( subkeyname, p ); - if ( (p = strchr( subkeyname, '\\' )) ) - *p = '\0'; - - /* don't add a key more than once */ - - for ( j=0; jnum_keys ) { - SAFE_FREE(subkeys_ptr); - return -1; - } - -done: - /* tag off the end */ - - if (num_subkeys) - fstrcpy(subkeys_ptr[num_subkeys], "" ); - - *subkeys = subkeys_ptr; - - return num_subkeys; -} - -#ifdef HAVE_ADS -static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name, - const char *sz) -{ - regval_ctr_delvalue(ctr, val_name); - regval_ctr_addvalue_sz(ctr, val_name, sz); -} - -static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name, - uint32 dword) -{ - regval_ctr_delvalue(ctr, val_name); - regval_ctr_addvalue(ctr, val_name, REG_DWORD, - (char *) &dword, sizeof(dword)); -} - -static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name, - bool b) -{ - uint8 bin_bool = (b ? 1 : 0); - regval_ctr_delvalue(ctr, val_name); - regval_ctr_addvalue(ctr, val_name, REG_BINARY, - (char *) &bin_bool, sizeof(bin_bool)); -} - -static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name, - const char *multi_sz) -{ - const char *a[2]; - - a[0] = multi_sz; - a[1] = NULL; - - regval_ctr_delvalue(ctr, val_name); - regval_ctr_addvalue_multi_sz(ctr, val_name, a); -} - -/**************************************************************************** - * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing. - * - * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified - * @return bool indicating success or failure - ***************************************************************************/ - -static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2) -{ - struct regval_ctr *ctr = NULL; - fstring longname; - const char *dnssuffix; - char *allocated_string = NULL; - const char *ascii_str; - int i; - - if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0) - i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY); - ctr = info2->data->keys[i].values; - - map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename); - map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname()); - - /* we make the assumption that the netbios name is the same - as the DNS name sinc ethe former will be what we used to - join the domain */ - - dnssuffix = get_mydnsdomname(talloc_tos()); - if (dnssuffix && *dnssuffix) { - fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix ); - } else { - fstrcpy( longname, global_myname() ); - } - - map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname); - - if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) { - return false; - } - map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string); - SAFE_FREE(allocated_string); - - map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4); - map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername); - map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location); - map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment); - map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname); - map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile); - map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime); - map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime); - map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority); - - map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS, - (info2->attributes & - PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS)); - - switch (info2->attributes & 0x3) { - case 0: - ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING; - break; - case 1: - ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED; - break; - case 2: - ascii_str = SPOOL_REGVAL_PRINTDIRECT; - break; - default: - ascii_str = "unknown"; - } - map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str); - - return True; -} - -/***************************************************************** - ****************************************************************/ - -static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, - struct GUID guid) -{ - int i; - struct regval_ctr *ctr=NULL; - - /* find the DsSpooler key */ - if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0) - i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY); - ctr = info2->data->keys[i].values; - - regval_ctr_delvalue(ctr, "objectGUID"); - - /* We used to store this as a REG_BINARY but that causes - Vista to whine */ - - regval_ctr_addvalue_sz(ctr, "objectGUID", - GUID_string(talloc_tos(), &guid)); -} - -static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, - NT_PRINTER_INFO_LEVEL *printer) -{ - ADS_STATUS ads_rc; - LDAPMessage *res; - char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped; - char *srv_dn_utf8, **srv_cn_utf8; - TALLOC_CTX *ctx; - ADS_MODLIST mods; - const char *attrs[] = {"objectGUID", NULL}; - struct GUID guid; - WERROR win_rc = WERR_OK; - size_t converted_size; - - /* build the ads mods */ - ctx = talloc_init("nt_printer_publish_ads"); - if (ctx == NULL) { - return WERR_NOMEM; - } - - DEBUG(5, ("publishing printer %s\n", printer->info_2->printername)); - - /* figure out where to publish */ - ads_find_machine_acct(ads, &res, global_myname()); - - /* We use ldap_get_dn here as we need the answer - * in utf8 to call ldap_explode_dn(). JRA. */ - - srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res); - if (!srv_dn_utf8) { - TALLOC_FREE(ctx); - return WERR_SERVER_UNAVAILABLE; - } - ads_msgfree(ads, res); - srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1); - if (!srv_cn_utf8) { - TALLOC_FREE(ctx); - ldap_memfree(srv_dn_utf8); - return WERR_SERVER_UNAVAILABLE; - } - /* Now convert to CH_UNIX. */ - if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) { - TALLOC_FREE(ctx); - ldap_memfree(srv_dn_utf8); - ldap_memfree(srv_cn_utf8); - return WERR_SERVER_UNAVAILABLE; - } - if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) { - TALLOC_FREE(ctx); - ldap_memfree(srv_dn_utf8); - ldap_memfree(srv_cn_utf8); - TALLOC_FREE(srv_dn); - return WERR_SERVER_UNAVAILABLE; - } - - ldap_memfree(srv_dn_utf8); - ldap_memfree(srv_cn_utf8); - - srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0); - if (!srv_cn_escaped) { - TALLOC_FREE(ctx); - return WERR_SERVER_UNAVAILABLE; - } - sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename); - if (!sharename_escaped) { - SAFE_FREE(srv_cn_escaped); - TALLOC_FREE(ctx); - return WERR_SERVER_UNAVAILABLE; - } - - prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn); - - SAFE_FREE(srv_cn_escaped); - SAFE_FREE(sharename_escaped); - - mods = ads_init_mods(ctx); - - if (mods == NULL) { - SAFE_FREE(prt_dn); - TALLOC_FREE(ctx); - return WERR_NOMEM; - } - - get_local_printer_publishing_data(ctx, &mods, printer->info_2->data); - ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, - printer->info_2->sharename); - - /* publish it */ - ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods); - if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) { - int i; - for (i=0; mods[i] != 0; i++) - ; - mods[i] = (LDAPMod *)-1; - ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); - } - - if (!ADS_ERR_OK(ads_rc)) - DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc))); - - /* retreive the guid and store it locally */ - if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { - ZERO_STRUCT(guid); - ads_pull_guid(ads, res, &guid); - ads_msgfree(ads, res); - store_printer_guid(printer->info_2, guid); - win_rc = mod_a_printer(printer, 2); - } - TALLOC_FREE(ctx); - - return win_rc; -} - -static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads, - NT_PRINTER_INFO_LEVEL *printer) -{ - ADS_STATUS ads_rc; - LDAPMessage *res = NULL; - char *prt_dn = NULL; - - DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername)); - - /* remove the printer from the directory */ - ads_rc = ads_find_printer_on_server(ads, &res, - printer->info_2->sharename, global_myname()); - - if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) { - prt_dn = ads_get_dn(ads, talloc_tos(), res); - if (!prt_dn) { - ads_msgfree(ads, res); - return WERR_NOMEM; - } - ads_rc = ads_del_dn(ads, prt_dn); - TALLOC_FREE(prt_dn); - } - - if (res) { - ads_msgfree(ads, res); - } - return WERR_OK; -} - -/**************************************************************************** - * Publish a printer in the directory - * - * @param snum describing printer service - * @return WERROR indicating status of publishing - ***************************************************************************/ - -WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action) -{ - ADS_STATUS ads_rc; - ADS_STRUCT *ads = NULL; - NT_PRINTER_INFO_LEVEL *printer = NULL; - WERROR win_rc; - - win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum)); - if (!W_ERROR_IS_OK(win_rc)) - goto done; - - switch (action) { - case DSPRINT_PUBLISH: - case DSPRINT_UPDATE: - /* set the DsSpooler info and attributes */ - if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) { - win_rc = WERR_NOMEM; - goto done; - } - - printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED; - break; - case DSPRINT_UNPUBLISH: - printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED; - break; - default: - win_rc = WERR_NOT_SUPPORTED; - goto done; - } - - win_rc = mod_a_printer(printer, 2); - if (!W_ERROR_IS_OK(win_rc)) { - DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc))); - goto done; - } - - ads = ads_init(lp_realm(), lp_workgroup(), NULL); - if (!ads) { - DEBUG(3, ("ads_init() failed\n")); - win_rc = WERR_SERVER_UNAVAILABLE; - goto done; - } - setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1); - SAFE_FREE(ads->auth.password); - ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), - NULL, NULL); - - /* ads_connect() will find the DC for us */ - ads_rc = ads_connect(ads); - if (!ADS_ERR_OK(ads_rc)) { - DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); - win_rc = WERR_ACCESS_DENIED; - goto done; - } - - switch (action) { - case DSPRINT_PUBLISH: - case DSPRINT_UPDATE: - win_rc = nt_printer_publish_ads(ads, printer); - break; - case DSPRINT_UNPUBLISH: - win_rc = nt_printer_unpublish_ads(ads, printer); - break; - } - -done: - free_a_printer(&printer, 2); - ads_destroy(&ads); - return win_rc; -} - -WERROR check_published_printers(void) -{ - ADS_STATUS ads_rc; - ADS_STRUCT *ads = NULL; - int snum; - int n_services = lp_numservices(); - NT_PRINTER_INFO_LEVEL *printer = NULL; - - ads = ads_init(lp_realm(), lp_workgroup(), NULL); - if (!ads) { - DEBUG(3, ("ads_init() failed\n")); - return WERR_SERVER_UNAVAILABLE; - } - setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1); - SAFE_FREE(ads->auth.password); - ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), - NULL, NULL); - - /* ads_connect() will find the DC for us */ - ads_rc = ads_connect(ads); - if (!ADS_ERR_OK(ads_rc)) { - DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); - ads_destroy(&ads); - ads_kdestroy("MEMORY:prtpub_cache"); - return WERR_ACCESS_DENIED; - } - - for (snum = 0; snum < n_services; snum++) { - if (!(lp_snum_ok(snum) && lp_print_ok(snum))) - continue; - - if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, - lp_servicename(snum))) && - (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) - nt_printer_publish_ads(ads, printer); - - free_a_printer(&printer, 2); - } - - ads_destroy(&ads); - ads_kdestroy("MEMORY:prtpub_cache"); - return WERR_OK; -} - -bool is_printer_published(Printer_entry *print_hnd, int snum, - struct GUID *guid) -{ - NT_PRINTER_INFO_LEVEL *printer = NULL; - struct regval_ctr *ctr; - struct regval_blob *guid_val; - WERROR win_rc; - int i; - bool ret = False; - DATA_BLOB blob; - - win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum)); - - if (!W_ERROR_IS_OK(win_rc) || - !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) || - ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) || - !(ctr = printer->info_2->data->keys[i].values) || - !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) - { - free_a_printer(&printer, 2); - return False; - } - - /* fetching printer guids really ought to be a separate function. */ - - if ( guid ) { - char *guid_str; - - /* We used to store the guid as REG_BINARY, then swapped - to REG_SZ for Vista compatibility so check for both */ - - switch ( regval_type(guid_val) ){ - case REG_SZ: - blob = data_blob_const(regval_data_p(guid_val), - regval_size(guid_val)); - pull_reg_sz(talloc_tos(), NULL, &blob, (const char **)&guid_str); - ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid )); - talloc_free(guid_str); - break; - case REG_BINARY: - if ( regval_size(guid_val) != sizeof(struct GUID) ) { - ret = False; - break; - } - memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID)); - break; - default: - DEBUG(0,("is_printer_published: GUID value stored as " - "invaluid type (%d)\n", regval_type(guid_val) )); - break; - } - } - - free_a_printer(&printer, 2); - return ret; -} -#else -WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action) -{ - return WERR_OK; -} - -WERROR check_published_printers(void) -{ - return WERR_OK; -} - -bool is_printer_published(Printer_entry *print_hnd, int snum, - struct GUID *guid) -{ - return False; -} -#endif /* HAVE_ADS */ - -/**************************************************************************** - ***************************************************************************/ - -WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key ) -{ - NT_PRINTER_DATA *data; - int i; - int removed_keys = 0; - int empty_slot; - - data = p2->data; - empty_slot = data->num_keys; - - if ( !key ) - return WERR_INVALID_PARAM; - - /* remove all keys */ - - if ( !strlen(key) ) { - - TALLOC_FREE( data ); - - p2->data = NULL; - - DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n", - p2->printername )); - - return WERR_OK; - } - - /* remove a specific key (and all subkeys) */ - - for ( i=0; inum_keys; i++ ) { - if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) { - DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n", - data->keys[i].name)); - - TALLOC_FREE( data->keys[i].name ); - TALLOC_FREE( data->keys[i].values ); - - /* mark the slot as empty */ - - ZERO_STRUCTP( &data->keys[i] ); - } - } - - /* find the first empty slot */ - - for ( i=0; inum_keys; i++ ) { - if ( !data->keys[i].name ) { - empty_slot = i; - removed_keys++; - break; - } - } - - if ( i == data->num_keys ) - /* nothing was removed */ - return WERR_INVALID_PARAM; - - /* move everything down */ - - for ( i=empty_slot+1; inum_keys; i++ ) { - if ( data->keys[i].name ) { - memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); - ZERO_STRUCTP( &data->keys[i] ); - empty_slot++; - removed_keys++; - } - } - - /* update count */ - - data->num_keys -= removed_keys; - - /* sanity check to see if anything is left */ - - if ( !data->num_keys ) { - DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername )); - - SAFE_FREE( data->keys ); - ZERO_STRUCTP( data ); - } - - return WERR_OK; -} - -/**************************************************************************** - ***************************************************************************/ - -WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value ) -{ - WERROR result = WERR_OK; - int key_index; - - /* we must have names on non-zero length */ - - if ( !key || !*key|| !value || !*value ) - return WERR_INVALID_NAME; - - /* find the printer key first */ - - key_index = lookup_printerkey( p2->data, key ); - if ( key_index == -1 ) - return WERR_OK; - - /* make sure the value exists so we can return the correct error code */ - - if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) ) - return WERR_BADFILE; - - regval_ctr_delvalue( p2->data->keys[key_index].values, value ); - - DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n", - key, value )); - - return result; -} - -/**************************************************************************** - ***************************************************************************/ - -WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, - uint32 type, uint8 *data, int real_len ) -{ - WERROR result = WERR_OK; - int key_index; - - /* we must have names on non-zero length */ - - if ( !key || !*key|| !value || !*value ) - return WERR_INVALID_NAME; - - /* find the printer key first */ - - key_index = lookup_printerkey( p2->data, key ); - if ( key_index == -1 ) - key_index = add_new_printer_key( p2->data, key ); - - if ( key_index == -1 ) - return WERR_NOMEM; - - regval_ctr_addvalue( p2->data->keys[key_index].values, value, - type, (const char *)data, real_len ); - - DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n", - key, value, type, real_len )); - - return result; -} - -/**************************************************************************** - ***************************************************************************/ - -struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value ) -{ - int key_index; - - if ( (key_index = lookup_printerkey( p2->data, key )) == -1 ) - return NULL; - - DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n", - key, value )); - - return regval_ctr_getvalue( p2->data->keys[key_index].values, value ); -} - -/**************************************************************************** - Unpack a list of registry values frem the TDB - ***************************************************************************/ - -static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen) -{ - int len = 0; - uint32 type; - fstring string; - const char *valuename = NULL; - const char *keyname = NULL; - char *str; - int size; - uint8 *data_p; - struct regval_blob *regval_p; - int key_index; - - /* add the "PrinterDriverData" key first for performance reasons */ - - add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY ); - - /* loop and unpack the rest of the registry values */ - - while ( True ) { - - /* check to see if there are any more registry values */ - - regval_p = NULL; - len += tdb_unpack(buf+len, buflen-len, "p", ®val_p); - if ( !regval_p ) - break; - - /* unpack the next regval */ - - len += tdb_unpack(buf+len, buflen-len, "fdB", - string, - &type, - &size, - &data_p); - - /* lookup for subkey names which have a type of REG_NONE */ - /* there's no data with this entry */ - - if ( type == REG_NONE ) { - if ( (key_index=lookup_printerkey( printer_data, string)) == -1 ) - add_new_printer_key( printer_data, string ); - continue; - } - - /* - * break of the keyname from the value name. - * Valuenames can have embedded '\'s so be careful. - * only support one level of keys. See the - * "Konica Fiery S300 50C-K v1.1. enu" 2k driver. - * -- jerry - */ - - str = strchr_m( string, '\\'); - - /* Put in "PrinterDriverData" is no key specified */ - - if ( !str ) { - keyname = SPOOL_PRINTERDATA_KEY; - valuename = string; - } - else { - *str = '\0'; - keyname = string; - valuename = str+1; - } - - /* see if we need a new key */ - - if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 ) - key_index = add_new_printer_key( printer_data, keyname ); - - if ( key_index == -1 ) { - DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n", - keyname)); - break; - } - - DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size)); - - /* Vista doesn't like unknown REG_BINARY values in DsSpooler. - Thanks to Martin Zielinski for the hint. */ - - if ( type == REG_BINARY && - strequal( keyname, SPOOL_DSSPOOLER_KEY ) && - strequal( valuename, "objectGUID" ) ) - { - struct GUID guid; - - /* convert the GUID to a UNICODE string */ - - memcpy( &guid, data_p, sizeof(struct GUID) ); - - regval_ctr_addvalue_sz(printer_data->keys[key_index].values, - valuename, - GUID_string(talloc_tos(), &guid)); - - } else { - /* add the value */ - - regval_ctr_addvalue( printer_data->keys[key_index].values, - valuename, type, (const char *)data_p, - size ); - } - - SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */ - - } - - return len; -} - -/**************************************************************************** - ***************************************************************************/ - -static char *last_from; -static char *last_to; - -static const char *get_last_from(void) -{ - if (!last_from) { - return ""; - } - return last_from; -} - -static const char *get_last_to(void) -{ - if (!last_to) { - return ""; - } - return last_to; -} - -static bool set_last_from_to(const char *from, const char *to) -{ - char *orig_from = last_from; - char *orig_to = last_to; - - last_from = SMB_STRDUP(from); - last_to = SMB_STRDUP(to); - - SAFE_FREE(orig_from); - SAFE_FREE(orig_to); - - if (!last_from || !last_to) { - SAFE_FREE(last_from); - SAFE_FREE(last_to); - return false; - } - return true; -} - -static void map_to_os2_driver(fstring drivername) -{ - char *mapfile = lp_os2_driver_map(); - char **lines = NULL; - int numlines = 0; - int i; - - if (!strlen(drivername)) - return; - - if (!*mapfile) - return; - - if (strequal(drivername,get_last_from())) { - DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n", - drivername,get_last_to())); - fstrcpy(drivername,get_last_to()); - return; - } - - lines = file_lines_load(mapfile, &numlines,0,NULL); - if (numlines == 0 || lines == NULL) { - DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile)); - TALLOC_FREE(lines); - return; - } - - DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile)); - - for( i = 0; i < numlines; i++) { - char *nt_name = lines[i]; - char *os2_name = strchr(nt_name,'='); - - if (!os2_name) - continue; - - *os2_name++ = 0; - - while (isspace(*nt_name)) - nt_name++; - - if (!*nt_name || strchr("#;",*nt_name)) - continue; - - { - int l = strlen(nt_name); - while (l && isspace(nt_name[l-1])) { - nt_name[l-1] = 0; - l--; - } - } - - while (isspace(*os2_name)) - os2_name++; - - { - int l = strlen(os2_name); - while (l && isspace(os2_name[l-1])) { - os2_name[l-1] = 0; - l--; - } - } - - if (strequal(nt_name,drivername)) { - DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name)); - set_last_from_to(drivername,os2_name); - fstrcpy(drivername,os2_name); - TALLOC_FREE(lines); - return; - } - } - - TALLOC_FREE(lines); -} - -/**************************************************************************** - Get a default printer info 2 struct. -****************************************************************************/ - -static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, - const char *servername, - const char* sharename, - bool get_loc_com) -{ - int snum = lp_servicenumber(sharename); - - slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername); - slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", - servername, sharename); - fstrcpy(info->sharename, sharename); - fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME); - - /* by setting the driver name to an empty string, a local NT admin - can now run the **local** APW to install a local printer driver - for a Samba shared printer in 2.2. Without this, drivers **must** be - installed on the Samba server for NT clients --jerry */ -#if 0 /* JERRY --do not uncomment-- */ - if (!*info->drivername) - fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER"); -#endif - - - DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername)); - - strlcpy(info->comment, "", sizeof(info->comment)); - fstrcpy(info->printprocessor, "winprint"); - fstrcpy(info->datatype, "RAW"); - -#ifdef HAVE_CUPS - if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) { - /* Pull the location and comment strings from cups if we don't - already have one */ - if ( !strlen(info->location) || !strlen(info->comment) ) { - char *comment = NULL; - char *location = NULL; - if (cups_pull_comment_location(info, info->sharename, - &comment, &location)) { - strlcpy(info->comment, comment, sizeof(info->comment)); - fstrcpy(info->location, location); - TALLOC_FREE(comment); - TALLOC_FREE(location); - } - } - } -#endif - - info->attributes = PRINTER_ATTRIBUTE_SAMBA; - - info->starttime = 0; /* Minutes since 12:00am GMT */ - info->untiltime = 0; /* Minutes since 12:00am GMT */ - info->priority = 1; - info->default_priority = 1; - info->setuptime = (uint32)time(NULL); - - /* - * I changed this as I think it is better to have a generic - * DEVMODE than to crash Win2k explorer.exe --jerry - * See the HP Deskjet 990c Win2k drivers for an example. - * - * However the default devmode appears to cause problems - * with the HP CLJ 8500 PCL driver. Hence the addition of - * the "default devmode" parameter --jerry 22/01/2002 - */ - - if (lp_default_devmode(snum)) { - if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) { - goto fail; - } - } else { - info->devmode = NULL; - } - - if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) { - goto fail; - } - - info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA); - if (!info->data) { - goto fail; - } - - add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY); - - return WERR_OK; - -fail: - if (info->devmode) - free_nt_devicemode(&info->devmode); - - return WERR_ACCESS_DENIED; -} - -/**************************************************************************** -****************************************************************************/ - -static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, - const char *servername, - const char *sharename, - bool get_loc_com) -{ - int len = 0; - int snum = lp_servicenumber(sharename); - TDB_DATA kbuf, dbuf; - fstring printername; - char adevice[MAXDEVICENAME]; - char *comment = NULL; - - kbuf = make_printer_tdbkey(talloc_tos(), sharename); - - dbuf = tdb_fetch(tdb_printers, kbuf); - if (!dbuf.dptr) { - return get_a_printer_2_default(info, servername, - sharename, get_loc_com); - } - - len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff", - &info->attributes, - &info->priority, - &info->default_priority, - &info->starttime, - &info->untiltime, - &info->status, - &info->cjobs, - &info->averageppm, - &info->changeid, - &info->c_setprinter, - &info->setuptime, - info->servername, - info->printername, - info->sharename, - info->portname, - info->drivername, - &comment, - info->location, - info->sepfile, - info->printprocessor, - info->datatype, - info->parameters); - - if (comment) { - strlcpy(info->comment, comment, sizeof(info->comment)); - SAFE_FREE(comment); - } - - /* Samba has to have shared raw drivers. */ - info->attributes |= PRINTER_ATTRIBUTE_SAMBA; - info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA; - - /* Restore the stripped strings. */ - slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername); - - if ( lp_force_printername(snum) ) { - slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename ); - } else { - slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername); - } - - fstrcpy(info->printername, printername); - -#ifdef HAVE_CUPS - if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) { - /* Pull the location and comment strings from cups if we don't - already have one */ - if ( !strlen(info->location) || !strlen(info->comment) ) { - char *location = NULL; - comment = NULL; - if (cups_pull_comment_location(info, info->sharename, - &comment, &location)) { - strlcpy(info->comment, comment, sizeof(info->comment)); - fstrcpy(info->location, location); - TALLOC_FREE(comment); - TALLOC_FREE(location); - } - } - } -#endif - - len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len); - - /* - * Some client drivers freak out if there is a NULL devmode - * (probably the driver is not checking before accessing - * the devmode pointer) --jerry - * - * See comments in get_a_printer_2_default() - */ - - if (lp_default_devmode(snum) && !info->devmode) { - DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n", - printername)); - info->devmode = construct_nt_devicemode(printername); - } - - slprintf( adevice, sizeof(adevice), "%s", info->printername ); - if (info->devmode) { - fstrcpy(info->devmode->devicename, adevice); - } - - if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) { - DEBUG(0,("unpack_values: talloc() failed!\n")); - SAFE_FREE(dbuf.dptr); - return WERR_NOMEM; - } - len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len ); - - /* This will get the current RPC talloc context, but we should be - passing this as a parameter... fixme... JRA ! */ - - if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) { - SAFE_FREE(dbuf.dptr); - return WERR_NOMEM; - } - - /* Fix for OS/2 drivers. */ - - if (get_remote_arch() == RA_OS2) { - map_to_os2_driver(info->drivername); - } - - SAFE_FREE(dbuf.dptr); - - DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n", - sharename, info->printername, info->drivername)); - - return WERR_OK; -} - -/**************************************************************************** - Debugging function, dump at level 6 the struct in the logs. -****************************************************************************/ -static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level) -{ - uint32 result; - NT_PRINTER_INFO_LEVEL_2 *info2; - - DEBUG(106,("Dumping printer at level [%d]\n", level)); - - switch (level) { - case 2: - { - if (printer->info_2 == NULL) - result=5; - else - { - info2=printer->info_2; - - DEBUGADD(106,("attributes:[%d]\n", info2->attributes)); - DEBUGADD(106,("priority:[%d]\n", info2->priority)); - DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority)); - DEBUGADD(106,("starttime:[%d]\n", info2->starttime)); - DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime)); - DEBUGADD(106,("status:[%d]\n", info2->status)); - DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs)); - DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm)); - DEBUGADD(106,("changeid:[%d]\n", info2->changeid)); - DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter)); - DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime)); - - DEBUGADD(106,("servername:[%s]\n", info2->servername)); - DEBUGADD(106,("printername:[%s]\n", info2->printername)); - DEBUGADD(106,("sharename:[%s]\n", info2->sharename)); - DEBUGADD(106,("portname:[%s]\n", info2->portname)); - DEBUGADD(106,("drivername:[%s]\n", info2->drivername)); - DEBUGADD(106,("comment:[%s]\n", info2->comment)); - DEBUGADD(106,("location:[%s]\n", info2->location)); - DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile)); - DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor)); - DEBUGADD(106,("datatype:[%s]\n", info2->datatype)); - DEBUGADD(106,("parameters:[%s]\n", info2->parameters)); - result=0; - } - break; - } - default: - DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level )); - result=1; - break; - } - - return result; -} - -/**************************************************************************** - Update the changeid time. - This is SO NASTY as some drivers need this to change, others need it - static. This value will change every second, and I must hope that this - is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF - UTAH ! JRA. -****************************************************************************/ - -static uint32 rev_changeid(void) -{ - struct timeval tv; - - get_process_uptime(&tv); - -#if 1 /* JERRY */ - /* Return changeid as msec since spooler restart */ - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -#else - /* - * This setting seems to work well but is too untested - * to replace the above calculation. Left in for experiementation - * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002) - */ - return tv.tv_sec * 10 + tv.tv_usec / 100000; -#endif -} - - -/* - * The function below are the high level ones. - * only those ones must be called from the spoolss code. - * JFM. - */ - -/**************************************************************************** - Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA. -****************************************************************************/ - -WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level) -{ - WERROR result; - - dump_a_printer(printer, level); - - switch (level) { - case 2: - { - /* - * Update the changestamp. Emperical tests show that the - * ChangeID is always updated,but c_setprinter is - * global spooler variable (not per printer). - */ - - /* ChangeID **must** be increasing over the lifetime - of client's spoolss service in order for the - client's cache to show updates */ - - printer->info_2->changeid = rev_changeid(); - - /* - * Because one day someone will ask: - * NT->NT An admin connection to a remote - * printer show changes imeediately in - * the properities dialog - * - * A non-admin connection will only show the - * changes after viewing the properites page - * 2 times. Seems to be related to a - * race condition in the client between the spooler - * updating the local cache and the Explorer.exe GUI - * actually displaying the properties. - * - * This is fixed in Win2k. admin/non-admin - * connections both display changes immediately. - * - * 14/12/01 --jerry - */ - - result=update_a_printer_2(printer->info_2); - break; - } - default: - result=WERR_UNKNOWN_LEVEL; - break; - } - - return result; -} - -/**************************************************************************** - Initialize printer devmode & data with previously saved driver init values. -****************************************************************************/ - -static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr ) -{ - int len = 0; - char *key = NULL; - TDB_DATA dbuf; - NT_PRINTER_INFO_LEVEL_2 info; - - - ZERO_STRUCT(info); - - /* - * Delete any printer data 'values' already set. When called for driver - * replace, there will generally be some, but during an add printer, there - * should not be any (if there are delete them). - */ - - if ( info_ptr->data ) - delete_all_printer_data( info_ptr, "" ); - - if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, - info_ptr->drivername) < 0) { - return false; - } - - dbuf = tdb_fetch_bystring(tdb_drivers, key); - if (!dbuf.dptr) { - /* - * When changing to a driver that has no init info in the tdb, remove - * the previous drivers init info and leave the new on blank. - */ - free_nt_devicemode(&info_ptr->devmode); - SAFE_FREE(key); - return false; - } - - SAFE_FREE(key); - /* - * Get the saved DEVMODE.. - */ - - len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len); - - /* - * The saved DEVMODE contains the devicename from the printer used during - * the initialization save. Change it to reflect the new printer. - */ - - if ( info.devmode ) { - ZERO_STRUCT(info.devmode->devicename); - fstrcpy(info.devmode->devicename, info_ptr->printername); - } - - /* - * NT/2k does not change out the entire DeviceMode of a printer - * when changing the driver. Only the driverextra, private, & - * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002) - * - * Later examination revealed that Windows NT/2k does reset the - * the printer's device mode, bit **only** when you change a - * property of the device mode such as the page orientation. - * --jerry - */ - - - /* Bind the saved DEVMODE to the new the printer */ - - free_nt_devicemode(&info_ptr->devmode); - info_ptr->devmode = info.devmode; - - DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n", - info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername)); - - /* Add the printer data 'values' to the new printer */ - - if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) { - DEBUG(0,("set_driver_init_2: talloc() failed!\n")); - return False; - } - - len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len ); - - SAFE_FREE(dbuf.dptr); - - return true; -} - -/**************************************************************************** - Initialize printer devmode & data with previously saved driver init values. - When a printer is created using AddPrinter, the drivername bound to the - printer is used to lookup previously saved driver initialization info, which - is bound to the new printer. -****************************************************************************/ - -bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) -{ - bool result = False; - - switch (level) { - case 2: - result = set_driver_init_2(printer->info_2); - break; + /* Create an ACE where Everyone is allowed to print */ - default: - DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n", - level)); - break; - } + sa = PRINTER_ACE_PRINT; + init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - return result; -} + /* Add the domain admins group if we are a DC */ -/**************************************************************************** - Delete driver init data stored for a specified driver -****************************************************************************/ + if ( IS_DC ) { + struct dom_sid domadmins_sid; -bool del_driver_init(const char *drivername) -{ - char *key; - bool ret; + sid_compose(&domadmins_sid, get_global_sam_sid(), + DOMAIN_RID_ADMINS); - if (!drivername || !*drivername) { - DEBUG(3,("del_driver_init: No drivername specified!\n")); - return false; + sa = PRINTER_ACE_FULL_CONTROL; + init_sec_ace(&ace[i++], &domadmins_sid, + SEC_ACE_TYPE_ACCESS_ALLOWED, sa, + SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); } + else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) { + sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR); - if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) { - return false; + sa = PRINTER_ACE_FULL_CONTROL; + init_sec_ace(&ace[i++], &adm_sid, + SEC_ACE_TYPE_ACCESS_ALLOWED, sa, + SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); } - DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", - drivername)); - - ret = (tdb_delete_bystring(tdb_drivers, key) == 0); - SAFE_FREE(key); - return ret; -} + /* add BUILTIN\Administrators as FULL CONTROL */ -/**************************************************************************** - Pack up the DEVMODE and values for a printer into a 'driver init' entry - in the tdb. Note: this is different from the driver entry and the printer - entry. There should be a single driver init entry for each driver regardless - of whether it was installed from NT or 2K. Technically, they should be - different, but they work out to the same struct. -****************************************************************************/ + sa = PRINTER_ACE_FULL_CONTROL; + init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, + SEC_ACE_TYPE_ACCESS_ALLOWED, sa, + SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, + SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); -static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info) -{ - char *key = NULL; - uint8 *buf; - int buflen, len, ret; - int retlen; - TDB_DATA dbuf; - - buf = NULL; - buflen = 0; - - again: - len = 0; - len += pack_devicemode(info->devmode, buf+len, buflen-len); - - retlen = pack_values( info->data, buf+len, buflen-len ); - if (retlen == -1) { - ret = -1; - goto done; - } - len += retlen; + /* add BUILTIN\Print Operators as FULL CONTROL */ - if (buflen < len) { - buf = (uint8 *)SMB_REALLOC(buf, len); - if (!buf) { - DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n")); - ret = -1; - goto done; - } - buflen = len; - goto again; - } + sa = PRINTER_ACE_FULL_CONTROL; + init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators, + SEC_ACE_TYPE_ACCESS_ALLOWED, sa, + SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators, + SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - SAFE_FREE(key); - if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) { - ret = (uint32)-1; - goto done; - } + /* Make the security descriptor owned by the BUILTIN\Administrators */ - dbuf.dptr = buf; - dbuf.dsize = len; + /* The ACL revision number in rpc_secdesc.h differs from the one + created by NT when setting ACE entries in printer + descriptors. NT4 complains about the property being edited by a + NT5 machine. */ - ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE); + if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) { + psd = make_sec_desc(mem_ctx, + SD_REVISION, + SEC_DESC_SELF_RELATIVE, + &global_sid_Builtin_Administrators, + &global_sid_Builtin_Administrators, + NULL, + psa, + &sd_size); + } -done: - if (ret == -1) - DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n")); + if (psd == NULL) { + DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n")); + return WERR_NOMEM; + } - SAFE_FREE(buf); + DEBUG(4,("construct_default_printer_sdb: size = %u.\n", + (unsigned int)sd_size)); - DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n", - info->sharename, info->drivername)); + *secdesc = psd; - return ret; + return WERR_OK; } /**************************************************************************** - Update (i.e. save) the driver init info (DEVMODE and values) for a printer -****************************************************************************/ - -static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) -{ - uint32 result; + ***************************************************************************/ - dump_a_printer(printer, level); +static char *win_driver; +static char *os2_driver; - switch (level) { - case 2: - result = update_driver_init_2(printer->info_2); - break; - default: - result = 1; - break; +static const char *get_win_driver(void) +{ + if (win_driver == NULL) { + return ""; } - - return result; + return win_driver; } -/**************************************************************************** - Convert the printer data value, a REG_BINARY array, into an initialization - DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc... - got to keep the endians happy :). -****************************************************************************/ - -static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode, - const uint8_t *data, uint32_t data_len) +static const char *get_os2_driver(void) { - struct spoolss_DeviceMode devmode; - enum ndr_err_code ndr_err; - DATA_BLOB blob; + if (os2_driver == NULL) { + return ""; + } + return os2_driver; +} - ZERO_STRUCT(devmode); +static bool set_driver_mapping(const char *from, const char *to) +{ + SAFE_FREE(win_driver); + SAFE_FREE(os2_driver); - blob = data_blob_const(data, data_len); + win_driver = SMB_STRDUP(from); + os2_driver = SMB_STRDUP(to); - ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode, - (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n")); + if (win_driver == NULL || os2_driver == NULL) { + SAFE_FREE(win_driver); + SAFE_FREE(os2_driver); return false; } - - return convert_devicemode("", &devmode, &nt_devmode); + return true; } -/**************************************************************************** - Set the DRIVER_INIT info in the tdb. Requires Win32 client code that: - - 1. Use the driver's config DLL to this UNC printername and: - a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE - b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE - 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data. - - The last step triggers saving the "driver initialization" information for - this printer into the tdb. Later, new printers that use this driver will - have this initialization information bound to them. This simulates the - driver initialization, as if it had run on the Samba server (as it would - have done on NT). - - The Win32 client side code requirement sucks! But until we can run arbitrary - Win32 printer driver code on any Unix that Samba runs on, we are stuck with it. - - It would have been easier to use SetPrinter because all the UNMARSHALLING of - the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think - about it and you will realize why. JRR 010720 -****************************************************************************/ - -static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len ) +/** + * @internal + * + * @brief Map a Windows driver to a OS/2 driver. + * + * @param[in] mem_ctx The memory context to use. + * + * @param[in,out] pdrivername The drivername of Windows to remap. + * + * @return WERR_OK on success, a corresponding WERROR on failure. + */ +WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername) { - WERROR status = WERR_OK; - TALLOC_CTX *ctx = NULL; - NT_DEVICEMODE *nt_devmode = NULL; - NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode; - - /* - * When the DEVMODE is already set on the printer, don't try to unpack it. - */ - DEBUG(8,("save_driver_init_2: Enter...\n")); - - if ( !printer->info_2->devmode && data_len ) { - /* - * Set devmode on printer info, so entire printer initialization can be - * saved to tdb. - */ - - if ((ctx = talloc_init("save_driver_init_2")) == NULL) - return WERR_NOMEM; - - if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) { - status = WERR_NOMEM; - goto done; - } - - ZERO_STRUCTP(nt_devmode); - - /* - * The DEVMODE is held in the 'data' component of the param in raw binary. - * Convert it to to a devmode structure - */ - if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) { - DEBUG(10,("save_driver_init_2: error converting DEVMODE\n")); - status = WERR_INVALID_PARAM; - goto done; - } + const char *mapfile = lp_os2_driver_map(); + char **lines = NULL; + const char *drivername; + int numlines = 0; + int i; - printer->info_2->devmode = nt_devmode; + if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') { + return WERR_INVALID_PARAMETER; } - /* - * Pack up and add (or update) the DEVMODE and any current printer data to - * a 'driver init' element in the tdb - * - */ + drivername = *pdrivername; - if ( update_driver_init(printer, 2) != 0 ) { - DEBUG(10,("save_driver_init_2: error updating DEVMODE\n")); - status = WERR_NOMEM; - goto done; + if (mapfile[0] == '\0') { + return WERR_BADFILE; } - /* - * If driver initialization info was successfully saved, set the current - * printer to match it. This allows initialization of the current printer - * as well as the driver. - */ - status = mod_a_printer(printer, 2); - if (!W_ERROR_IS_OK(status)) { - DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n", - printer->info_2->printername)); + if (strequal(drivername, get_win_driver())) { + DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n", + drivername, get_os2_driver())); + drivername = talloc_strdup(mem_ctx, get_os2_driver()); + if (drivername == NULL) { + return WERR_NOMEM; + } + *pdrivername = drivername; + return WERR_OK; } - done: - talloc_destroy(ctx); - free_nt_devicemode( &nt_devmode ); - - printer->info_2->devmode = tmp_devmode; - - return status; -} - -/**************************************************************************** - Update the driver init info (DEVMODE and specifics) for a printer -****************************************************************************/ - -WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len) -{ - WERROR status = WERR_OK; - - switch (level) { - case 2: - status = save_driver_init_2( printer, data, data_len ); - break; - default: - status = WERR_UNKNOWN_LEVEL; - break; + lines = file_lines_load(mapfile, &numlines, 0, NULL); + if (numlines == 0 || lines == NULL) { + DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile)); + TALLOC_FREE(lines); + return WERR_EMPTY; } - return status; -} - -/**************************************************************************** - Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory. - - Previously the code had a memory allocation problem because it always - used the TALLOC_CTX from the Printer_entry*. This context lasts - as a long as the original handle is open. So if the client made a lot - of getprinter[data]() calls, the memory usage would climb. Now we use - a short lived TALLOC_CTX for printer_info_2 objects returned. We - still use the Printer_entry->ctx for maintaining the cache copy though - since that object must live as long as the handle by definition. - --jerry + DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile)); -****************************************************************************/ + for( i = 0; i < numlines; i++) { + char *nt_name = lines[i]; + char *os2_name = strchr(nt_name, '='); -static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, - const char *sharename, bool get_loc_com) -{ - WERROR result; - fstring servername; + if (os2_name == NULL) { + continue; + } - DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level)); + *os2_name++ = '\0'; - if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) { - DEBUG(0,("get_a_printer: talloc() fail.\n")); - return WERR_NOMEM; - } + while (isspace(*nt_name)) { + nt_name++; + } - switch (level) { - case 2: - if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) { - DEBUG(0,("get_a_printer: talloc() fail.\n")); - TALLOC_FREE( *pp_printer ); - return WERR_NOMEM; - } + if (*nt_name == '\0' || strchr("#;", *nt_name)) { + continue; + } - if ( print_hnd ) - fstrcpy( servername, print_hnd->servername ); - else { - fstrcpy( servername, "%L" ); - standard_sub_basic( "", "", servername, - sizeof(servername)-1 ); + { + int l = strlen(nt_name); + while (l && isspace(nt_name[l - 1])) { + nt_name[l - 1] = 0; + l--; } + } - result = get_a_printer_2( (*pp_printer)->info_2, - servername, sharename, get_loc_com); - - /* we have a new printer now. Save it with this handle */ + while (isspace(*os2_name)) { + os2_name++; + } - if ( !W_ERROR_IS_OK(result) ) { - TALLOC_FREE( *pp_printer ); - DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", - sharename, (unsigned int)level, win_errstr(result))); - return result; + { + int l = strlen(os2_name); + while (l && isspace(os2_name[l-1])) { + os2_name[l-1] = 0; + l--; } + } - dump_a_printer( *pp_printer, level); - - break; - - default: - TALLOC_FREE( *pp_printer ); - return WERR_UNKNOWN_LEVEL; + if (strequal(nt_name, drivername)) { + DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name)); + set_driver_mapping(drivername, os2_name); + drivername = talloc_strdup(mem_ctx, os2_name); + TALLOC_FREE(lines); + if (drivername == NULL) { + return WERR_NOMEM; + } + *pdrivername = drivername; + return WERR_OK; + } } + TALLOC_FREE(lines); return WERR_OK; } -WERROR get_a_printer( Printer_entry *print_hnd, - NT_PRINTER_INFO_LEVEL **pp_printer, - uint32 level, - const char *sharename) -{ - return get_a_printer_internal(print_hnd, pp_printer, level, - sharename, true); -} - -WERROR get_a_printer_search( Printer_entry *print_hnd, - NT_PRINTER_INFO_LEVEL **pp_printer, - uint32 level, - const char *sharename) -{ - return get_a_printer_internal(print_hnd, pp_printer, level, - sharename, false); -} - -/**************************************************************************** - Deletes a NT_PRINTER_INFO_LEVEL struct. -****************************************************************************/ - -uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level) -{ - NT_PRINTER_INFO_LEVEL *printer = *pp_printer; - - if ( !printer ) - return 0; - - switch (level) { - case 2: - if ( printer->info_2 ) - free_nt_printer_info_level_2(&printer->info_2); - break; - - default: - DEBUG(0,("free_a_printer: unknown level! [%d]\n", level )); - return 1; - } - - TALLOC_FREE(*pp_printer); - - return 0; -} - /**************************************************************************** ****************************************************************************/ @@ -4881,127 +1516,32 @@ bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r, if (r->info.info8->previous_names && r->info.info8->previous_names->string) { info8.previous_names = r->info.info8->previous_names->string; } - info8.driver_date = r->info.info8->driver_date; - info8.driver_version = r->info.info8->driver_version; - info8.manufacturer_name = r->info.info8->manufacturer_name; - info8.manufacturer_url = r->info.info8->manufacturer_url; - info8.hardware_id = r->info.info8->hardware_id; - info8.provider = r->info.info8->provider; - info8.print_processor = r->info.info8->print_processor; - info8.vendor_setup = r->info.info8->vendor_setup; - if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) { - info8.color_profiles = r->info.info8->color_profiles->string; - } - info8.inf_path = r->info.info8->inf_path; - info8.printer_driver_attributes = r->info.info8->printer_driver_attributes; - if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) { - info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string; - } - info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date; - info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version; - break; - default: - return false; - } - - *_info8 = info8; - - return true; -} - - -uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx, - struct spoolss_AddDriverInfoCtr *r, - char **driver_name, - uint32_t *version) -{ - struct spoolss_DriverInfo8 info8; - - ZERO_STRUCT(info8); - - DEBUG(10,("adding a printer at level [%d]\n", r->level)); - - if (!driver_info_ctr_to_info8(r, &info8)) { - return -1; - } - - *driver_name = talloc_strdup(mem_ctx, info8.driver_name); - if (!*driver_name) { - return -1; - } - *version = info8.version; - - return add_a_printer_driver_8(&info8); -} - -/**************************************************************************** -****************************************************************************/ - -WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx, - struct spoolss_DriverInfo8 **driver, - const char *drivername, const char *architecture, - uint32_t version) -{ - WERROR result; - struct spoolss_DriverInfo3 info3; - struct spoolss_DriverInfo8 *info8; - - ZERO_STRUCT(info3); - - /* Sometime we just want any version of the driver */ - - if (version == DRIVER_ANY_VERSION) { - /* look for Win2k first and then for NT4 */ - result = get_a_printer_driver_3(mem_ctx, - &info3, - drivername, - architecture, 3); - if (!W_ERROR_IS_OK(result)) { - result = get_a_printer_driver_3(mem_ctx, - &info3, - drivername, - architecture, 2); + info8.driver_date = r->info.info8->driver_date; + info8.driver_version = r->info.info8->driver_version; + info8.manufacturer_name = r->info.info8->manufacturer_name; + info8.manufacturer_url = r->info.info8->manufacturer_url; + info8.hardware_id = r->info.info8->hardware_id; + info8.provider = r->info.info8->provider; + info8.print_processor = r->info.info8->print_processor; + info8.vendor_setup = r->info.info8->vendor_setup; + if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) { + info8.color_profiles = r->info.info8->color_profiles->string; } - } else { - result = get_a_printer_driver_3(mem_ctx, - &info3, - drivername, - architecture, - version); - } - - if (!W_ERROR_IS_OK(result)) { - return result; - } - - info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8); - if (!info8) { - return WERR_NOMEM; + info8.inf_path = r->info.info8->inf_path; + info8.printer_driver_attributes = r->info.info8->printer_driver_attributes; + if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) { + info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string; + } + info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date; + info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version; + break; + default: + return false; } - info8->version = info3.version; - info8->driver_name = info3.driver_name; - info8->architecture = info3.architecture; - info8->driver_path = info3.driver_path; - info8->data_file = info3.data_file; - info8->config_file = info3.config_file; - info8->help_file = info3.help_file; - info8->dependent_files = info3.dependent_files; - info8->monitor_name = info3.monitor_name; - info8->default_datatype = info3.default_datatype; - - *driver = info8; - - return WERR_OK; -} - -/**************************************************************************** -****************************************************************************/ + *_info8 = info8; -uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver) -{ - talloc_free(driver); - return 0; + return true; } @@ -5010,12 +1550,15 @@ uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver) to a printer ****************************************************************************/ -bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r) +bool printer_driver_in_use(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + const struct spoolss_DriverInfo8 *r) { int snum; int n_services = lp_numservices(); - NT_PRINTER_INFO_LEVEL *printer = NULL; bool in_use = False; + struct spoolss_PrinterInfo2 *pinfo2 = NULL; + WERROR result; if (!r) { return false; @@ -5026,22 +1569,27 @@ bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r) /* loop through the printers.tdb and check for the drivername */ for (snum=0; snumdriver_name, printer->info_2->drivername)) + if (strequal(r->driver_name, pinfo2->drivername)) { in_use = True; + } - free_a_printer( &printer, 2 ); + TALLOC_FREE(pinfo2); } DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n")); if ( in_use ) { - struct spoolss_DriverInfo8 *d; + struct spoolss_DriverInfo8 *driver; WERROR werr; DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name)); @@ -5050,22 +1598,26 @@ bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r) "Windows NT x86" version 2 or 3 left */ if (!strequal("Windows NT x86", r->architecture)) { - werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION); - } - else { - switch (r->version) { - case 2: - werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3); - break; - case 3: - werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2); - break; - default: - DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", - r->version)); - werr = WERR_UNKNOWN_PRINTER_DRIVER; - break; - } + werr = winreg_get_driver(mem_ctx, server_info, + "Windows NT x86", + r->driver_name, + DRIVER_ANY_VERSION, + &driver); + } else if (r->version == 2) { + werr = winreg_get_driver(mem_ctx, server_info, + "Windows NT x86", + r->driver_name, + 3, &driver); + } else if (r->version == 3) { + werr = winreg_get_driver(mem_ctx, server_info, + "Windows NT x86", + r->driver_name, + 2, &driver); + } else { + DEBUG(0, ("printer_driver_in_use: ERROR!" + " unknown driver version (%d)\n", + r->version)); + werr = WERR_UNKNOWN_PRINTER_DRIVER; } /* now check the error code */ @@ -5073,7 +1625,7 @@ bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r) if ( W_ERROR_IS_OK(werr) ) { /* it's ok to remove the driver, we have other architctures left */ in_use = False; - free_a_printer_driver(d); + talloc_free(driver); } } @@ -5225,14 +1777,16 @@ static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx, ****************************************************************************/ bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, struct spoolss_DriverInfo8 *info) { int i; - int ndrivers; uint32 version; - fstring *list = NULL; struct spoolss_DriverInfo8 *driver; bool in_use = false; + uint32_t num_drivers; + const char **drivers; + WERROR result; if ( !info ) return False; @@ -5241,25 +1795,32 @@ bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx, /* loop over all driver versions */ - DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n")); + DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n")); /* get the list of drivers */ - list = NULL; - ndrivers = get_ntdrivers(&list, info->architecture, version); + result = winreg_get_driver_list(mem_ctx, server_info, + info->architecture, version, + &num_drivers, &drivers); + if (!W_ERROR_IS_OK(result)) { + return true; + } - DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", - ndrivers, info->architecture, version)); + DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n", + num_drivers, info->architecture, version)); /* check each driver for overlap in files */ - for (i=0; iarchitecture, version))) { - SAFE_FREE(list); + result = winreg_get_driver(mem_ctx, server_info, + info->architecture, drivers[i], + version, &driver); + if (!W_ERROR_IS_OK(result)) { + talloc_free(drivers); return True; } @@ -5275,12 +1836,12 @@ bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx, } } - free_a_printer_driver(driver); + talloc_free(driver); } - SAFE_FREE(list); + talloc_free(drivers); - DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n")); + DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n")); return in_use; } @@ -5309,8 +1870,8 @@ static NTSTATUS driver_unlink_internals(connection_struct *conn, this. ****************************************************************************/ -static bool delete_driver_files(struct pipes_struct *rpc_pipe, - const struct spoolss_DriverInfo8 *r) +bool delete_driver_files(struct auth_serversupplied_info *server_info, + const struct spoolss_DriverInfo8 *r) { int i = 0; char *s; @@ -5338,7 +1899,7 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe, nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum, lp_pathname(printdollar_snum), - rpc_pipe->server_info, &oldcwd); + server_info, &oldcwd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("delete_driver_files: create_conn_struct " "returned %s\n", nt_errstr(nt_status))); @@ -5414,363 +1975,6 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe, return ret; } -/**************************************************************************** - Remove a printer driver from the TDB. This assumes that the the driver was - previously looked up. - ***************************************************************************/ - -WERROR delete_printer_driver(struct pipes_struct *rpc_pipe, - const struct spoolss_DriverInfo8 *r, - uint32 version, bool delete_files ) -{ - char *key = NULL; - const char *arch; - TDB_DATA dbuf; - - /* delete the tdb data first */ - - arch = get_short_archi(r->architecture); - if (!arch) { - return WERR_UNKNOWN_PRINTER_DRIVER; - } - if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX, - arch, version, r->driver_name) < 0) { - return WERR_NOMEM; - } - - DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n", - key, delete_files ? "TRUE" : "FALSE" )); - - /* check if the driver actually exists for this environment */ - - dbuf = tdb_fetch_bystring( tdb_drivers, key ); - if ( !dbuf.dptr ) { - DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key)); - SAFE_FREE(key); - return WERR_UNKNOWN_PRINTER_DRIVER; - } - - SAFE_FREE( dbuf.dptr ); - - /* ok... the driver exists so the delete should return success */ - - if (tdb_delete_bystring(tdb_drivers, key) == -1) { - DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key)); - SAFE_FREE(key); - return WERR_ACCESS_DENIED; - } - - /* - * now delete any associated files if delete_files == True - * even if this part failes, we return succes because the - * driver doesn not exist any more - */ - - if ( delete_files ) - delete_driver_files(rpc_pipe, r); - - DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key)); - SAFE_FREE(key); - - return WERR_OK; -} - -/**************************************************************************** - Store a security desc for a printer. -****************************************************************************/ - -WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr) -{ - SEC_DESC_BUF *new_secdesc_ctr = NULL; - SEC_DESC_BUF *old_secdesc_ctr = NULL; - TALLOC_CTX *mem_ctx = NULL; - TDB_DATA kbuf; - TDB_DATA dbuf; - DATA_BLOB blob; - WERROR status; - NTSTATUS nt_status; - - mem_ctx = talloc_init("nt_printing_setsec"); - if (mem_ctx == NULL) - return WERR_NOMEM; - - /* The old owner and group sids of the security descriptor are not - present when new ACEs are added or removed by changing printer - permissions through NT. If they are NULL in the new security - descriptor then copy them over from the old one. */ - - if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) { - DOM_SID *owner_sid, *group_sid; - SEC_ACL *dacl, *sacl; - SEC_DESC *psd = NULL; - size_t size; - - if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) { - status = WERR_NOMEM; - goto out; - } - - /* Pick out correct owner and group sids */ - - owner_sid = secdesc_ctr->sd->owner_sid ? - secdesc_ctr->sd->owner_sid : - old_secdesc_ctr->sd->owner_sid; - - group_sid = secdesc_ctr->sd->group_sid ? - secdesc_ctr->sd->group_sid : - old_secdesc_ctr->sd->group_sid; - - dacl = secdesc_ctr->sd->dacl ? - secdesc_ctr->sd->dacl : - old_secdesc_ctr->sd->dacl; - - sacl = secdesc_ctr->sd->sacl ? - secdesc_ctr->sd->sacl : - old_secdesc_ctr->sd->sacl; - - /* Make a deep copy of the security descriptor */ - - psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type, - owner_sid, group_sid, - sacl, - dacl, - &size); - - if (!psd) { - status = WERR_NOMEM; - goto out; - } - - new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd); - } - - if (!new_secdesc_ctr) { - new_secdesc_ctr = secdesc_ctr; - } - - /* Store the security descriptor in a tdb */ - - nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr, - &blob.data, &blob.length); - if (!NT_STATUS_IS_OK(nt_status)) { - status = ntstatus_to_werror(nt_status); - goto out; - } - - kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename ); - - dbuf.dptr = (unsigned char *)blob.data; - dbuf.dsize = blob.length; - - if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) { - status = WERR_OK; - } else { - DEBUG(1,("Failed to store secdesc for %s\n", sharename)); - status = WERR_BADFUNC; - } - - /* Free malloc'ed memory */ - talloc_free(blob.data); - - out: - - if (mem_ctx) - talloc_destroy(mem_ctx); - return status; -} - -/**************************************************************************** - Construct a default security descriptor buffer for a printer. -****************************************************************************/ - -static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) -{ - SEC_ACE ace[5]; /* max number of ace entries */ - int i = 0; - uint32_t sa; - SEC_ACL *psa = NULL; - SEC_DESC_BUF *sdb = NULL; - SEC_DESC *psd = NULL; - DOM_SID adm_sid; - size_t sd_size; - - /* Create an ACE where Everyone is allowed to print */ - - sa = PRINTER_ACE_PRINT; - init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, - sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - - /* Add the domain admins group if we are a DC */ - - if ( IS_DC ) { - DOM_SID domadmins_sid; - - sid_compose(&domadmins_sid, get_global_sam_sid(), - DOMAIN_GROUP_RID_ADMINS); - - sa = PRINTER_ACE_FULL_CONTROL; - init_sec_ace(&ace[i++], &domadmins_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, sa, - SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); - init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, - sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - } - else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) { - sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN); - - sa = PRINTER_ACE_FULL_CONTROL; - init_sec_ace(&ace[i++], &adm_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, sa, - SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); - init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, - sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - } - - /* add BUILTIN\Administrators as FULL CONTROL */ - - sa = PRINTER_ACE_FULL_CONTROL; - init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, - SEC_ACE_TYPE_ACCESS_ALLOWED, sa, - SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); - init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, - SEC_ACE_TYPE_ACCESS_ALLOWED, - sa, SEC_ACE_FLAG_CONTAINER_INHERIT); - - /* Make the security descriptor owned by the BUILTIN\Administrators */ - - /* The ACL revision number in rpc_secdesc.h differs from the one - created by NT when setting ACE entries in printer - descriptors. NT4 complains about the property being edited by a - NT5 machine. */ - - if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) { - psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, - &global_sid_Builtin_Administrators, - &global_sid_Builtin_Administrators, - NULL, psa, &sd_size); - } - - if (!psd) { - DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n")); - return NULL; - } - - sdb = make_sec_desc_buf(ctx, sd_size, psd); - - DEBUG(4,("construct_default_printer_sdb: size = %u.\n", - (unsigned int)sd_size)); - - return sdb; -} - -/**************************************************************************** - Get a security desc for a printer. -****************************************************************************/ - -bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr) -{ - TDB_DATA kbuf; - TDB_DATA dbuf; - DATA_BLOB blob; - char *temp; - NTSTATUS status; - - if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) { - sharename = temp + 1; - } - - /* Fetch security descriptor from tdb */ - - kbuf = make_printers_secdesc_tdbkey(ctx, sharename); - - dbuf = tdb_fetch(tdb_printers, kbuf); - if (dbuf.dptr) { - - status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize, - secdesc_ctr); - SAFE_FREE(dbuf.dptr); - - if (NT_STATUS_IS_OK(status)) { - return true; - } - } - - *secdesc_ctr = construct_default_printer_sdb(ctx); - if (!*secdesc_ctr) { - return false; - } - - status = marshall_sec_desc_buf(ctx, *secdesc_ctr, - &blob.data, &blob.length); - if (NT_STATUS_IS_OK(status)) { - dbuf.dptr = (unsigned char *)blob.data; - dbuf.dsize = blob.length; - tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE); - talloc_free(blob.data); - } - - /* If security descriptor is owned by S-1-1-0 and winbindd is up, - this security descriptor has been created when winbindd was - down. Take ownership of security descriptor. */ - - if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) { - DOM_SID owner_sid; - - /* Change sd owner to workgroup administrator */ - - if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) { - SEC_DESC_BUF *new_secdesc_ctr = NULL; - SEC_DESC *psd = NULL; - size_t size; - - /* Create new sd */ - - sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN); - - psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type, - &owner_sid, - (*secdesc_ctr)->sd->group_sid, - (*secdesc_ctr)->sd->sacl, - (*secdesc_ctr)->sd->dacl, - &size); - - if (!psd) { - return False; - } - - new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd); - if (!new_secdesc_ctr) { - return False; - } - - /* Swap with other one */ - - *secdesc_ctr = new_secdesc_ctr; - - /* Set it */ - - nt_printing_setsec(sharename, *secdesc_ctr); - } - } - - if (DEBUGLEVEL >= 10) { - SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl; - int i; - - DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", - sharename, the_acl->num_aces)); - - for (i = 0; i < the_acl->num_aces; i++) { - DEBUG(10, ("%s %d %d 0x%08x\n", - sid_string_dbg(&the_acl->aces[i].trustee), - the_acl->aces[i].type, the_acl->aces[i].flags, - the_acl->aces[i].access_mask)); - } - } - - return True; -} - /* error code: 0: everything OK 1: level not implemented @@ -5811,7 +2015,7 @@ jfm: I should use this comment for the text file to explain It turns out that NT4 security descriptors use generic access rights and NT5 the object specific ones. */ -void map_printer_permissions(SEC_DESC *sd) +void map_printer_permissions(struct security_descriptor *sd) { int i; @@ -5821,7 +2025,7 @@ void map_printer_permissions(SEC_DESC *sd) } } -void map_job_permissions(SEC_DESC *sd) +void map_job_permissions(struct security_descriptor *sd) { int i; @@ -5858,9 +2062,11 @@ void map_job_permissions(SEC_DESC *sd) bool print_access_check(struct auth_serversupplied_info *server_info, int snum, int access_type) { - SEC_DESC_BUF *secdesc = NULL; + struct spoolss_security_descriptor *secdesc = NULL; uint32 access_granted; + size_t sd_size; NTSTATUS status; + WERROR result; const char *pname; TALLOC_CTX *mem_ctx = NULL; SE_PRIV se_printop = SE_PRINT_OPERATOR; @@ -5876,7 +2082,7 @@ bool print_access_check(struct auth_serversupplied_info *server_info, int snum, /* Get printer name */ - pname = PRINTERNAME(snum); + pname = lp_printername(snum); if (!pname || !*pname) { errno = EACCES; @@ -5890,34 +2096,42 @@ bool print_access_check(struct auth_serversupplied_info *server_info, int snum, return False; } - if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) { + result = winreg_get_printer_secdesc(mem_ctx, + server_info, + pname, + &secdesc); + if (!W_ERROR_IS_OK(result)) { talloc_destroy(mem_ctx); errno = ENOMEM; return False; } if (access_type == JOB_ACCESS_ADMINISTER) { - SEC_DESC_BUF *parent_secdesc = secdesc; + struct spoolss_security_descriptor *parent_secdesc = secdesc; /* Create a child security descriptor to check permissions against. This is because print jobs are child objects objects of a printer. */ - - status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False); - + status = se_create_child_secdesc(mem_ctx, + &secdesc, + &sd_size, + parent_secdesc, + parent_secdesc->owner_sid, + parent_secdesc->group_sid, + false); if (!NT_STATUS_IS_OK(status)) { talloc_destroy(mem_ctx); errno = map_errno_from_nt_status(status); return False; } - map_job_permissions(secdesc->sd); + map_job_permissions(secdesc); } else { - map_printer_permissions(secdesc->sd); + map_printer_permissions(secdesc); } /* Check access */ - status = se_access_check(secdesc->sd, server_info->ptok, access_type, + status = se_access_check(secdesc, server_info->ptok, access_type, &access_granted); DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE")); @@ -5926,7 +2140,8 @@ bool print_access_check(struct auth_serversupplied_info *server_info, int snum, if (!NT_STATUS_IS_OK(status) && (token_contains_name_in_list(uidtoname(server_info->utok.uid), - NULL, NULL, server_info->ptok, + server_info->info3->base.domain.string, + NULL, server_info->ptok, lp_printer_admin(snum)))) { talloc_destroy(mem_ctx); return True; @@ -5945,41 +2160,51 @@ bool print_access_check(struct auth_serversupplied_info *server_info, int snum, Check the time parameters allow a print operation. *****************************************************************************/ -bool print_time_access_check(const char *servicename) +bool print_time_access_check(struct auth_serversupplied_info *server_info, + const char *servicename) { - NT_PRINTER_INFO_LEVEL *printer = NULL; + struct spoolss_PrinterInfo2 *pinfo2 = NULL; + WERROR result; bool ok = False; time_t now = time(NULL); struct tm *t; uint32 mins; - if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename))) + result = winreg_get_printer(NULL, server_info, + NULL, servicename, &pinfo2); + if (!W_ERROR_IS_OK(result)) { return False; + } - if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0) + if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) { ok = True; + } t = gmtime(&now); mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min; - if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime) + if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) { ok = True; + } - free_a_printer(&printer, 2); + TALLOC_FREE(pinfo2); - if (!ok) + if (!ok) { errno = EACCES; + } return ok; } -/**************************************************************************** - Fill in the servername sent in the _spoolss_open_printer_ex() call -****************************************************************************/ - -char* get_server_name( Printer_entry *printer ) +void nt_printer_remove(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + const char *printer) { - return printer->servername; -} - + WERROR result; + result = winreg_delete_printer_key(mem_ctx, server_info, printer, ""); + if (!W_ERROR_IS_OK(result)) { + DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s", + printer)); + } +}