diff options
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; } + + |