diff options
author | Gerald Carter <jerry@samba.org> | 2005-07-15 14:26:11 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:00:06 -0500 |
commit | 6fe54515435e351ba958886cb9a7175c436ef88d (patch) | |
tree | a188eb29a9701f714e0bc5a28eb447720ad23732 /source3/printing | |
parent | 63b3898a739c200dddf74950264881ebea5aec54 (diff) | |
download | samba-6fe54515435e351ba958886cb9a7175c436ef88d.tar.gz samba-6fe54515435e351ba958886cb9a7175c436ef88d.tar.bz2 samba-6fe54515435e351ba958886cb9a7175c436ef88d.zip |
r8501: * disable printer handle object cache (was mostly used
for NT4 clients enumerating printer data on slow CPUs)
* fix pinter and secdesc record upgrade to normalize the key
(rev'd printer tdb version)
* fixed problem that was normalizing the printername name field
in general, this should fix the issues upgrading print servers
from 3.0.14a to 3.0.20
(This used to be commit d07179de2f2a6eb1d13d0e25ac10de1a21475559)
Diffstat (limited to 'source3/printing')
-rw-r--r-- | source3/printing/nt_printing.c | 240 |
1 files changed, 174 insertions, 66 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 25083002c3..e7f10f4fc1 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -3,7 +3,7 @@ * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-2000, * Copyright (C) Jean François Micouleau 1998-2000. - * Copyright (C) Gerald Carter 2002-2003. + * Copyright (C) Gerald Carter 2002-2005. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,8 +39,7 @@ static TDB_CONTEXT *tdb_printers; /* used for printers files */ #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_4 +#define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */ /* Map generic permissions to printer object specific permissions */ @@ -225,6 +224,48 @@ static const struct table_node archi_table[]= { {NULL, "", -1 } }; + +/**************************************************************************** + generate a new TDB_DATA key for storing a printer +****************************************************************************/ + +static TDB_DATA make_printer_tdbkey( const char *sharename ) +{ + fstring share; + static pstring keystr; + TDB_DATA key; + + fstrcpy( share, sharename ); + strlower_m( share ); + + pstr_sprintf( keystr, "%s%s", PRINTERS_PREFIX, share ); + + key.dptr = keystr; + key.dsize = strlen(keystr)+1; + + return key; +} + +/**************************************************************************** + generate a new TDB_DATA key for storing a printer security descriptor +****************************************************************************/ + +static char* make_printers_secdesc_tdbkey( const char* sharename ) +{ + fstring share; + static pstring keystr; + + fstrcpy( share, sharename ); + strlower_m( share ); + + pstr_sprintf( keystr, "%s%s", SECDESC_PREFIX, share ); + + return keystr; +} + +/**************************************************************************** +****************************************************************************/ + static BOOL upgrade_to_version_3(void) { TDB_DATA kbuf, newkey, dbuf; @@ -406,6 +447,73 @@ static BOOL upgrade_to_version_4(void) 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 ) +{ + TDB_DATA new_key; + + if (!data.dptr || data.dsize == 0) + return 0; + + /* upgrade printer records and security descriptors */ + + if ( strncmp( key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) { + new_key = make_printer_tdbkey( key.dptr+strlen(PRINTERS_PREFIX) ); + } + else if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) { + new_key.dptr = make_printers_secdesc_tdbkey( key.dptr+strlen(SECDESC_PREFIX) ); + new_key.dsize = strlen( new_key.dptr ) + 1; + } + 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(). ****************************************************************************/ @@ -447,15 +555,18 @@ BOOL nt_printing_init(void) } /* handle a Samba upgrade */ - tdb_lock_bystring(tdb_drivers, vstring, 0); - - /* ---------------- 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_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. */ @@ -463,28 +574,27 @@ BOOL nt_printing_init(void) vers_id = NTDRIVERS_DATABASE_VERSION_3; } - 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_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; } - /* at this point we know that the database is at version 3 so upgrade to v4 */ + 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 ( !upgrade_to_version_4() ) + + if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) { + DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id)); return False; - tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION); + } } - - /* ---------------- End Lock Region ------------------ */ - - tdb_unlock_bystring(tdb_drivers, vstring); - + update_c_setprinter(True); /* @@ -501,12 +611,14 @@ BOOL nt_printing_init(void) message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata ); +#ifdef ENABLE_PRINT_HND_OBJECT_CACHE /* * register callback to handle invalidating the printer cache * between smbd processes. */ message_register( MSG_PRINTER_MOD, receive_printer_mod_msg); +#endif /* of course, none of the message callbacks matter if you don't tell messages.c that you interested in receiving PRINT_GENERAL @@ -2220,8 +2332,6 @@ uint32 del_a_printer(const char *sharename) ****************************************************************************/ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) { - pstring key; - fstring norm_sharename; char *buf; int buflen, len; WERROR ret; @@ -2303,15 +2413,8 @@ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) } - /* normalize the key */ - - fstrcpy( norm_sharename, info->sharename ); - strlower_m( norm_sharename ); + kbuf = make_printer_tdbkey( info->sharename ); - slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename); - - kbuf.dptr = key; - kbuf.dsize = strlen(key)+1; dbuf.dptr = buf; dbuf.dsize = len; @@ -3595,29 +3698,20 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const ****************************************************************************/ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename) { - pstring key; NT_PRINTER_INFO_LEVEL_2 info; int len = 0; int snum = lp_servicenumber(sharename); TDB_DATA kbuf, dbuf; fstring printername; char adevice[MAXDEVICENAME]; - fstring norm_sharename; ZERO_STRUCT(info); - /* normalize case */ - fstrcpy( norm_sharename, sharename ); - strlower_m( norm_sharename ); - - slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, norm_sharename); - - kbuf.dptr = key; - kbuf.dsize = strlen(key)+1; + kbuf = make_printer_tdbkey( sharename ); dbuf = tdb_fetch(tdb_printers, kbuf); if (!dbuf.dptr) - return get_a_printer_2_default(info_ptr, servername, norm_sharename); + return get_a_printer_2_default(info_ptr, servername, sharename); len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff", &info.attributes, @@ -3651,7 +3745,7 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *se slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername); if ( lp_force_printername(snum) ) - slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, norm_sharename ); + slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename ); else slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername); @@ -3781,6 +3875,7 @@ static uint32 rev_changeid(void) #endif } +#ifdef ENABLE_PRINT_HND_OBJECT_CACHE /******************************************************************** Send a message to all smbds about the printer that just changed ********************************************************************/ @@ -3801,6 +3896,8 @@ static BOOL send_printer_mod_msg( char* printername ) return True; } +#endif + /* * The function below are the high level ones. @@ -3818,6 +3915,7 @@ WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level) dump_a_printer(printer, level); +#ifdef ENABLE_PRINT_HND_OBJECT_CACHE /* * invalidate cache for all open handles to this printer. * cache for a given handle will be updated on the next @@ -3825,7 +3923,12 @@ WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level) */ invalidate_printer_hnd_cache( printer->info_2->sharename ); + + /* messages between smbds can only be sent as root */ + become_root(); send_printer_mod_msg( printer->info_2->sharename ); + unbecome_root(); +#endif switch (level) { case 2: @@ -4228,6 +4331,7 @@ WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *dat return status; } +#ifdef ENABLE_PRINT_HND_OBJECT_CACHE /**************************************************************************** Deep copy a NT_PRINTER_DATA ****************************************************************************/ @@ -4293,6 +4397,7 @@ NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 return copy; } +#endif /**************************************************************************** Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory. @@ -4333,6 +4438,8 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print fstrcpy( servername, "%L" ); standard_sub_basic( "", servername, sizeof(servername)-1 ); } + +#ifdef ENABLE_PRINT_HND_OBJECT_CACHE /* * check for cache first. A Printer handle cannot changed @@ -4373,12 +4480,17 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print if ( !print_hnd || !W_ERROR_IS_OK(result) ) result = get_a_printer_2(&printer->info_2, servername, sharename ); +#else + result = get_a_printer_2(&printer->info_2, servername, sharename ); +#endif + /* we have a new printer now. Save it with this handle */ if ( W_ERROR_IS_OK(result) ) { dump_a_printer(printer, level); - + +#ifdef ENABLE_PRINT_HND_OBJECT_CACHE /* save a copy in cache */ if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) { if ( !print_hnd->printer_info ) @@ -4395,6 +4507,7 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print DEBUG(0,("get_a_printer: unable to copy new printer info!\n")); } } +#endif *pp_printer = printer; } else @@ -4990,12 +5103,8 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr) SEC_DESC_BUF *old_secdesc_ctr = NULL; prs_struct ps; TALLOC_CTX *mem_ctx = NULL; - fstring key; + char *key; WERROR status; - fstring norm_sharename; - - fstrcpy( norm_sharename, sharename ); - strlower_m( norm_sharename ); mem_ctx = talloc_init("nt_printing_setsec"); if (mem_ctx == NULL) @@ -5012,7 +5121,7 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr) SEC_DESC *psd = NULL; size_t size; - nt_printing_getsec(mem_ctx, norm_sharename, &old_secdesc_ctr); + nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr); /* Pick out correct owner and group sids */ @@ -5058,12 +5167,12 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr) goto out; } - slprintf(key, sizeof(key)-1, "SECDESC/%s", norm_sharename); + key = make_printers_secdesc_tdbkey( sharename ); if (tdb_prs_store(tdb_printers, key, &ps)==0) { status = WERR_OK; } else { - DEBUG(1,("Failed to store secdesc for %s\n", norm_sharename)); + DEBUG(1,("Failed to store secdesc for %s\n", sharename)); status = WERR_BADFUNC; } @@ -5168,9 +5277,8 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr) { prs_struct ps; - fstring key; + char *key; char *temp; - fstring norm_sharename; if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) { sharename = temp + 1; @@ -5178,15 +5286,12 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **s /* Fetch security descriptor from tdb */ - fstrcpy( norm_sharename, sharename ); - strlower_m( norm_sharename ); - - slprintf(key, sizeof(key)-1, "SECDESC/%s", norm_sharename); + key = make_printers_secdesc_tdbkey( sharename ); if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 || !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) { - DEBUG(4,("using default secdesc for %s\n", norm_sharename)); + DEBUG(4,("using default secdesc for %s\n", sharename)); if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) { return False; @@ -5238,7 +5343,7 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **s /* Set it */ - nt_printing_setsec(norm_sharename, *secdesc_ctr); + nt_printing_setsec(sharename, *secdesc_ctr); } } @@ -5247,7 +5352,7 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **s int i; DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", - norm_sharename, the_acl->num_aces)); + sharename, the_acl->num_aces)); for (i = 0; i < the_acl->num_aces; i++) { fstring sid_str; @@ -5453,7 +5558,10 @@ BOOL print_time_access_check(int snum) /**************************************************************************** Fill in the servername sent in the _spoolss_open_printer_ex() call ****************************************************************************/ + char* get_server_name( Printer_entry *printer ) { return printer->servername; } + + |