#include "includes.h"
-extern DOM_SID global_sid_World;
+extern struct current_user current_user;
static TDB_CONTEXT *tdb_forms; /* used for forms files */
static TDB_CONTEXT *tdb_drivers; /* used for driver 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 */
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, SEC_DESC_SELF_RELATIVE,
+ &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( "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().
****************************************************************************/
BOOL nt_printing_init(void)
{
- static pid_t local_pid;
const char *vstring = "INFO/version";
WERROR win_rc;
+ uint32 vers_id;
- if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
+ if ( tdb_drivers && tdb_printers && tdb_forms )
return True;
if (tdb_drivers)
return False;
}
- local_pid = sys_getpid();
-
/* 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);
SMB_STRUCT_STAT stat_buf;
BOOL bad_path;
- ZERO_STRUCT(st);
- ZERO_STRUCT(stat_buf);
+ SET_STAT_INVALID(st);
+ SET_STAT_INVALID(stat_buf);
new_create_time = (time_t)0;
old_create_time = (time_t)0;
SMB_STRUCT_STAT st;
connection_struct *conn;
- ZERO_STRUCT(st);
+ SET_STAT_INVALID(st);
*perr = WERR_INVALID_PARAM;
driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
+ if ( !vfs_file_exist( conn, driverpath, &st ) ) {
+ *perr = WERR_BADFILE;
+ goto error_exit;
+ }
+
fsp = open_file_shared(conn, driverpath, &st,
- SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
+ SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
+ FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
+
if (!fsp) {
DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
driverpath, errno));
driverpath, major, minor));
}
- DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
- driverpath, cversion));
+ DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
+ driverpath, cversion));
close_file(fsp, True);
close_cnum(conn, user->vuid);
* NT 4: cversion=2
* NT2K: cversion=3
*/
- if ((driver->cversion = get_correct_cversion( architecture,
- driver->driverpath, user, &err)) == -1)
- return err;
+ if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
+ return err;
return WERR_OK;
}
* NT 4: cversion=2
* NT2K: cversion=3
*/
+
if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
- return err;
+ return err;
return WERR_OK;
}
/****************************************************************************
****************************************************************************/
-BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
+WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
struct current_user *user, WERROR *perr)
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
SMB_STRUCT_STAT st;
int ver = 0;
int i;
+ int err;
memset(inbuf, '\0', sizeof(inbuf));
memset(outbuf, '\0', sizeof(outbuf));
driver = &converted_driver;
} else {
DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
- return False;
+ return WERR_UNKNOWN_LEVEL;
}
architecture = get_short_archi(driver->environment);
if (conn == NULL) {
DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
*perr = ntstatus_to_werror(nt_status);
- return False;
+ return WERR_NO_SUCH_SHARE;
}
/*
if (!become_user(conn, conn->vuid)) {
DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
- return False;
+ return WERR_ACCESS_DENIED;
}
/*
DEBUG(5,("Creating first directory\n"));
slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
- mkdir_internal(conn, new_dir);
+ mkdir_internal(conn, new_dir, bad_path);
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
* listed for this driver which has already been moved, skip it (note:
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- NTSTATUS status;
driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- status = rename_internals(conn, new_name, old_name, 0, True);
- if (!NT_STATUS_IS_OK(status)) {
+ if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = ntstatus_to_werror(status);
- unlink_internals(conn, 0, new_name);
+ *perr = WERR_ACCESS_DENIED;
ver = -1;
}
- } else {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- unlink_internals(conn, 0, new_name);
- }
+ }
}
if (driver->datafile && strlen(driver->datafile)) {
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- NTSTATUS status;
driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- status = rename_internals(conn, new_name, old_name, 0, True);
- if (!NT_STATUS_IS_OK(status)) {
+ if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = ntstatus_to_werror(status);
- unlink_internals(conn, 0, new_name);
+ *perr = WERR_ACCESS_DENIED;
ver = -1;
}
- } else {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- unlink_internals(conn, 0, new_name);
}
}
}
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- NTSTATUS status;
driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- status = rename_internals(conn, new_name, old_name, 0, True);
- if (!NT_STATUS_IS_OK(status)) {
+ if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = ntstatus_to_werror(status);
- unlink_internals(conn, 0, new_name);
+ *perr = WERR_ACCESS_DENIED;
ver = -1;
}
- } else {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- unlink_internals(conn, 0, new_name);
}
}
}
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- NTSTATUS status;
driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- status = rename_internals(conn, new_name, old_name, 0, True);
- if (!NT_STATUS_IS_OK(status)) {
+ if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = ntstatus_to_werror(status);
- unlink_internals(conn, 0, new_name);
+ *perr = WERR_ACCESS_DENIED;
ver = -1;
}
- } else {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- unlink_internals(conn, 0, new_name);
}
}
}
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- NTSTATUS status;
driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- status = rename_internals(conn, new_name, old_name, 0, True);
- if (!NT_STATUS_IS_OK(status)) {
+ if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = ntstatus_to_werror(status);
- unlink_internals(conn, 0, new_name);
+ *perr = WERR_ACCESS_DENIED;
ver = -1;
}
- } else {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- unlink_internals(conn, 0, new_name);
}
}
NextDriver: ;
close_cnum(conn, user->vuid);
unbecome_user();
- return ver == -1 ? False : True;
+ return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
}
/****************************************************************************
ZERO_STRUCT(driver);
architecture = get_short_archi(arch);
+
+ if ( !architecture )
+ return WERR_UNKNOWN_PRINTER_DRIVER;
/* Windows 4.0 (i.e. win9x) should always use a version of 0 */
nt_devmode->reserved2,
nt_devmode->panningwidth,
nt_devmode->panningheight,
- nt_devmode->private);
+ nt_devmode->nt_dev_private);
- if (nt_devmode->private) {
+ if (nt_devmode->nt_dev_private) {
len += tdb_pack(buf+len, buflen-len, "B",
nt_devmode->driverextra,
- nt_devmode->private);
+ nt_devmode->nt_dev_private);
}
DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
for ( i=0; i<data->num_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);
- /* loop over all values */
+ /* now loop over all values */
for ( j=0; j<num_values; j++ ) {
/* pathname should be stored as <key>\<value> */
static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
{
pstring key;
+ fstring norm_sharename;
char *buf;
int buflen, len;
WERROR ret;
}
+ /* normalize the key */
+
+ fstrcpy( norm_sharename, info->sharename );
+ strlower_m( norm_sharename );
+
slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
kbuf.dptr = key;
nt_devmode->panningwidth = 0;
nt_devmode->panningheight = 0;
- nt_devmode->private = NULL;
+ nt_devmode->nt_dev_private = NULL;
return nt_devmode;
}
return NULL;
}
- new_nt_devicemode->private = NULL;
- if (nt_devicemode->private != NULL) {
- if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
+ new_nt_devicemode->nt_dev_private = NULL;
+ if (nt_devicemode->nt_dev_private != NULL) {
+ if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
SAFE_FREE(new_nt_devicemode);
DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
return NULL;
DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
- SAFE_FREE(nt_devmode->private);
+ SAFE_FREE(nt_devmode->nt_dev_private);
SAFE_FREE(*devmode_ptr);
}
&devmode.reserved2,
&devmode.panningwidth,
&devmode.panningheight,
- &devmode.private);
+ &devmode.nt_dev_private);
- if (devmode.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.private);
+ 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.private = NULL;
+ devmode.nt_dev_private = NULL;
}
}
*nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
- if (devmode.private)
+ 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.
***************************************************************************/
-static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
+int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
{
NT_PRINTER_KEY *d;
int key_index;
/* allocate another slot in the NT_PRINTER_KEY array */
- d = SMB_REALLOC_ARRAY( data->keys, NT_PRINTER_KEY, data->num_keys+1);
- if ( d )
- data->keys = d;
+ if ( !(d = SMB_REALLOC_ARRAY( 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;
data->num_keys++;
data->keys[key_index].name = SMB_STRDUP( name );
- ZERO_STRUCTP( &data->keys[key_index].values );
-
regval_ctr_init( &data->keys[key_index].values );
DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
/****************************************************************************
***************************************************************************/
-uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
+int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
{
int i, j;
int key_len;
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; i<data->num_keys; i++ ) {
+ /* found a match, so allocate space and copy the name */
+
+ if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
+ DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
+ num_subkeys+1));
+ SAFE_FREE( subkeys );
+ return -1;
+ }
+
+ subkeys_ptr = ptr;
+ 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; i<data->num_keys; i++ ) {
if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
- /* match sure it is a subkey and not the key itself */
+ /* if we found the exact key, then break */
key_len = strlen( key );
if ( strlen(data->keys[i].name) == key_len )
- continue;
+ break;
/* get subkey path */
}
- /* tag of the end */
+ /* return error if the key was not found */
+
+ if ( i == data->num_keys )
+ return -1;
+
+done:
+ /* tag off the end */
if (num_subkeys)
fstrcpy(subkeys_ptr[num_subkeys], "" );
{
REGVAL_CTR *ctr = NULL;
fstring longname;
+ fstring dnssuffix;
char *allocated_string = NULL;
const char *ascii_str;
int i;
map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
- get_mydnsfullname(longname);
+ /* 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 */
+
+ if ( get_mydnsdomname( dnssuffix ) )
+ fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
+ else
+ fstrcpy( longname, global_myname() );
+
map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
&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.
TDB_DATA kbuf, dbuf;
fstring printername;
char adevice[MAXDEVICENAME];
+ fstring norm_sharename;
ZERO_STRUCT(info);
- slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
+ /* 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;
dbuf = tdb_fetch(tdb_printers, kbuf);
if (!dbuf.dptr)
- return get_a_printer_2_default(info_ptr, servername, sharename);
+ return get_a_printer_2_default(info_ptr, servername, norm_sharename);
len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
&info.attributes,
slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
if ( lp_force_printername(snum) )
- slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
+ slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, norm_sharename );
else
slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
int snum;
int n_services = lp_numservices();
NT_PRINTER_INFO_LEVEL *printer = NULL;
+ BOOL in_use = False;
if ( !info_3 )
return False;
- DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
+ DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
/* loop through the printers.tdb and check for the drivername */
- for (snum=0; snum<n_services; snum++) {
+ for (snum=0; snum<n_services && !in_use; 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))) )
continue;
- if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
- free_a_printer( &printer, 2 );
- return True;
- }
+ if ( strequal(info_3->name, printer->info_2->drivername) )
+ in_use = True;
free_a_printer( &printer, 2 );
}
- DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
+ DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
+
+ if ( in_use ) {
+ NT_PRINTER_DRIVER_INFO_LEVEL d;
+ WERROR werr;
+
+ DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
+
+ /* we can still remove the driver if there is one of
+ "Windows NT x86" version 2 or 3 left */
+
+ if ( !strequal( "Windows NT x86", info_3->environment ) ) {
+ werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
+ }
+ else {
+ switch ( info_3->cversion ) {
+ case 2:
+ werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
+ break;
+ case 3:
+ werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
+ break;
+ default:
+ DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
+ info_3->cversion));
+ werr = WERR_UNKNOWN_PRINTER_DRIVER;
+ break;
+ }
+ }
+
+ /* now check the error code */
+
+ 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, 3 );
+ }
+ }
/* report that the driver is not in use by default */
- return False;
+ return in_use;
}
Store a security desc for a printer.
****************************************************************************/
-WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
+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;
fstring 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)
SEC_DESC *psd = NULL;
size_t size;
- nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
+ nt_printing_getsec(mem_ctx, norm_sharename, &old_secdesc_ctr);
/* Pick out correct owner and group sids */
goto out;
}
- slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
+ slprintf(key, sizeof(key)-1, "SECDESC/%s", norm_sharename);
if (tdb_prs_store(tdb_printers, key, &ps)==0) {
status = WERR_OK;
} else {
- DEBUG(1,("Failed to store secdesc for %s\n", printername));
+ DEBUG(1,("Failed to store secdesc for %s\n", norm_sharename));
status = WERR_BADFUNC;
}
static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
{
- SEC_ACE ace[3];
+ SEC_ACE ace[5]; /* max number of ace entries */
+ int i = 0;
SEC_ACCESS sa;
SEC_ACL *psa = NULL;
SEC_DESC_BUF *sdb = NULL;
SEC_DESC *psd = NULL;
- DOM_SID owner_sid;
+ DOM_SID adm_sid;
size_t sd_size;
/* Create an ACE where Everyone is allowed to print */
init_sec_access(&sa, PRINTER_ACE_PRINT);
- init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
+ init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
- /* Make the security descriptor owned by the Administrators group
- on the PDC of the domain. */
-
- if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
- sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
- } else {
-
- /* Backup plan - make printer owned by admins.
- This should emulate a lanman printer as security
- settings can't be changed. */
+ /* Add the domain admins group if we are a DC */
+
+ if ( IS_DC ) {
+ DOM_SID domadmins_sid;
+
+ sid_copy(&domadmins_sid, get_global_sam_sid());
+ sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
+
+ init_sec_access(&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);
- sid_copy(&owner_sid, get_global_sam_sid());
- sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
+ init_sec_access(&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);
}
- init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
- init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
- sa, SEC_ACE_FLAG_OBJECT_INHERIT |
- SEC_ACE_FLAG_INHERIT_ONLY);
+ /* add BUILTIN\Administrators as FULL CONTROL */
init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
- init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
- sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
+ 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, 3, ace)) != NULL) {
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
- &owner_sid, NULL,
- NULL, psa, &sd_size);
+ &global_sid_Builtin_Administrators,
+ &global_sid_Builtin_Administrators,
+ NULL, psa, &sd_size);
}
if (!psd) {
Get a security desc for a printer.
****************************************************************************/
-BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
+BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
{
prs_struct ps;
fstring key;
char *temp;
+ fstring norm_sharename;
- if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
- printername = temp + 1;
+ if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
+ sharename = temp + 1;
}
/* Fetch security descriptor from tdb */
- slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
+ fstrcpy( norm_sharename, sharename );
+ strlower_m( norm_sharename );
+
+ slprintf(key, sizeof(key)-1, "SECDESC/%s", norm_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", printername));
+ DEBUG(4,("using default secdesc for %s\n", norm_sharename));
if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
return False;
/* Set it */
- nt_printing_setsec(printername, *secdesc_ctr);
+ nt_printing_setsec(norm_sharename, *secdesc_ctr);
}
}
int i;
DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
- printername, the_acl->num_aces));
+ norm_sharename, the_acl->num_aces));
for (i = 0; i < the_acl->num_aces; i++) {
fstring sid_str;
BOOL result;
const char *pname;
TALLOC_CTX *mem_ctx = NULL;
- extern struct current_user current_user;
+ SE_PRIV se_printop = SE_PRINT_OPERATOR;
/* If user is NULL then use the current_user structure */
/* Always allow root or SE_PRINT_OPERATROR to do anything */
- if ( user->uid == 0 || user_has_privilege(user->nt_user_token, SE_PRINT_OPERATOR) ) {
+ if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
return True;
}