summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/printing/nt_printing.c155
1 files changed, 145 insertions, 10 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 40d815cead..552d2dfe35 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -38,8 +38,9 @@ static TDB_CONTEXT *tdb_printers; /* used for printers files */
#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 NTDRIVERS_DATABASE_VERSION_3
+#define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_4
/* Map generic permissions to printer object specific permissions */
@@ -283,6 +284,128 @@ static BOOL upgrade_to_version_3(void)
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 )
+{
+ prs_struct ps;
+ 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_new_sec;
+ DOM_SID sid;
+
+ if (!data.dptr || data.dsize == 0)
+ return 0;
+
+ if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 )
+ return 0;
+
+ /* upgrade the security descriptor */
+
+ ZERO_STRUCT( ps );
+
+ prs_init( &ps, 0, ctx, UNMARSHALL );
+ prs_give_memory( &ps, data.dptr, data.dsize, True );
+
+ if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
+ /* delete bad entries */
+ DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key.dptr ));
+ tdb_delete( tdb_printers, key );
+ return 0;
+ }
+
+ sec = sd_orig->sec;
+
+ /* is this even valid? */
+
+ if ( !sec->dacl )
+ return 0;
+
+ /* update access masks */
+
+ for ( i=0; i<sec->dacl->num_aces; i++ ) {
+ switch ( sec->dacl->ace[i].info.mask ) {
+ case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
+ sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
+ break;
+
+ case GENERIC_ALL_ACCESS:
+ sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
+ break;
+
+ case READ_CONTROL_ACCESS:
+ sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
+
+ default: /* no change */
+ break;
+ }
+ }
+
+ /* create a new SEC_DESC with the appropriate owner and group SIDs */
+
+ string_to_sid(&sid, "S-1-5-32-544" );
+ new_sec = make_sec_desc( ctx, SEC_DESC_REVISION,
+ &sid, &sid,
+ NULL, NULL, &size_new_sec );
+ sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
+
+ if ( !(sd_store = sec_desc_merge( 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 = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
+ prs_init(&ps, sd_size, ctx, MARSHALL);
+
+ if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
+ DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
+ return 0;
+ }
+
+ data.dptr = prs_data_p( &ps );
+ data.dsize = sd_size;
+
+ result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
+
+ prs_mem_free( &ps );
+
+ /* 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_named( "upgrade_to_version_4" )) )
+ return False;
+
+ result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
+
+ talloc_destroy( ctx );
+
+ return ( result != -1 );
+}
+
/****************************************************************************
Open the NT printing tdbs. Done once before fork().
****************************************************************************/
@@ -327,29 +450,41 @@ BOOL nt_printing_init(void)
/* handle a Samba upgrade */
tdb_lock_bystring(tdb_drivers, vstring, 0);
- {
- int32 vers_id;
- /* Cope with byte-reversed older versions of the db. */
- vers_id = tdb_fetch_int32(tdb_drivers, vstring);
+ /* ---------------- Start Lock Region ---------------- */
+
+ /* Cope with byte-reversed older versions of the db. */
+ vers_id = tdb_fetch_int32(tdb_drivers, vstring);
+
+ if ( vers_id != NTDRIVERS_DATABASE_VERSION ) {
+
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);
- vers_id = NTDRIVERS_DATABASE_VERSION;
+ tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
+ vers_id = NTDRIVERS_DATABASE_VERSION_3;
}
- if (vers_id != NTDRIVERS_DATABASE_VERSION) {
-
+ if (vers_id != NTDRIVERS_DATABASE_VERSION_3 ) {
+
if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
if (!upgrade_to_version_3())
return False;
} else
tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
- tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
+ tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
}
+
+ /* at this point we know that the database is at version 3 so upgrade to v4 */
+
+ if ( !upgrade_to_version_4() )
+ return False;
+ tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
}
+
+ /* ---------------- End Lock Region ------------------ */
+
tdb_unlock_bystring(tdb_drivers, vstring);
update_c_setprinter(True);