summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_reg_nt.c237
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c103
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c22
3 files changed, 274 insertions, 88 deletions
diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c
index f031a3213f..4211e9b9f4 100644
--- a/source3/rpc_server/srv_reg_nt.c
+++ b/source3/rpc_server/srv_reg_nt.c
@@ -25,6 +25,7 @@
/* Implementation of registry functions. */
#include "includes.h"
+#include "regfio.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
@@ -38,6 +39,10 @@
((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
+/* no idea if this is correct, just use the file access bits for now */
+
+struct generic_mapping reg_map = { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
+
static REGISTRY_KEY *regkeys_list;
@@ -534,7 +539,7 @@ WERROR _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
/* subkey has the string name now */
- init_reg_r_enum_key( r_u, subkey, q_u->unknown_1, q_u->unknown_2 );
+ init_reg_r_enum_key( r_u, subkey );
DEBUG(5,("_reg_enum_key: Exit\n"));
@@ -625,6 +630,7 @@ WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_
int ret;
BOOL can_shutdown;
+
pstrcpy(shutdown_script, lp_shutdown_script());
if ( !*shutdown_script )
@@ -635,7 +641,7 @@ WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_
pstrcpy( message, "" );
if ( q_u->message ) {
UNISTR2 *msg_string = q_u->message->string;
-
+
rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
}
alpha_strcpy (chkmsg, message, NULL, sizeof(message));
@@ -650,7 +656,7 @@ WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_
all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
-
+
can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
/* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
@@ -667,7 +673,7 @@ WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_
unbecome_root();
/********** END SeRemoteShutdownPrivilege BLOCK **********/
-
+
DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
shutdown_script, ret));
@@ -717,18 +723,56 @@ WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABO
/*******************************************************************
********************************************************************/
+static int validate_reg_filename( pstring fname )
+{
+ char *p;
+ int num_services = lp_numservices();
+ int snum;
+ pstring share_path;
+ pstring unix_fname;
+
+ /* convert to a unix path, stripping the C:\ along the way */
+
+ if ( !(p = valid_share_pathname( fname ) ))
+ return -1;
+
+ /* has to exist within a valid file share */
+
+ for ( snum=0; snum<num_services; snum++ ) {
+
+ if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
+ continue;
+
+ pstrcpy( share_path, lp_pathname(snum) );
+
+ /* make sure we have a path (e.g. [homes] ) */
+
+ if ( strlen( share_path ) == 0 )
+ continue;
+
+ if ( strncmp( share_path, p, strlen( share_path )) == 0 )
+ break;
+ }
+
+ /* p and fname are overlapping memory so copy out and back in again */
+
+ pstrcpy( unix_fname, p );
+ pstrcpy( fname, unix_fname );
+
+ return (snum < num_services) ? snum : -1;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u)
{
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
pstring filename;
+ int snum;
DEBUG(5,("_reg_restore_key: Enter\n"));
- /*
- * basically this is a no op function which just verifies
- * that the client gave us a valid registry key handle
- */
-
if ( !regkey )
return WERR_BADFID;
@@ -736,14 +780,169 @@ WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_
DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
+ if ( (snum = validate_reg_filename( filename )) == -1 )
+ return WERR_OBJECT_PATH_INVALID;
+
+ DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
+
#if 0
- validate_reg_filemame( filename );
return restore_registry_key( regkey, filename );
#endif
return WERR_OK;
}
+/********************************************************************
+********************************************************************/
+
+static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
+ REGF_NK_REC *parent, SEC_DESC *sec_desc )
+{
+ REGF_NK_REC *key;
+ REGVAL_CTR values;
+ REGSUBKEY_CTR subkeys;
+ int i, num_subkeys;
+ pstring key_tmp;
+ char *keyname, *parentpath;
+ pstring subkeypath;
+ char *subkeyname;
+ REGISTRY_KEY registry_key;
+ WERROR result = WERR_OK;
+
+ if ( !regfile )
+ return WERR_GENERAL_FAILURE;
+
+ if ( !keypath )
+ return WERR_OBJECT_PATH_INVALID;
+
+ /* split up the registry key path */
+
+ pstrcpy( key_tmp, keypath );
+ if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
+ return WERR_OBJECT_PATH_INVALID;
+
+ if ( !keyname )
+ keyname = parentpath;
+
+ /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
+
+ ZERO_STRUCT( registry_key );
+ pstrcpy( registry_key.name, keypath );
+ if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
+ return WERR_BADFILE;
+
+
+ /* lookup the values and subkeys */
+
+ ZERO_STRUCT( values );
+ ZERO_STRUCT( subkeys );
+
+ regsubkey_ctr_init( &subkeys );
+ regval_ctr_init( &values );
+
+ fetch_reg_keys( &registry_key, &subkeys );
+ fetch_reg_values( &registry_key, &values );
+
+ /* write out this key */
+
+ if ( !(key = regfio_write_key( regfile, keyname, &values, &subkeys, sec_desc, parent )) ) {
+ result = WERR_CAN_NOT_COMPLETE;
+ goto done;
+ }
+
+ /* write each one of the subkeys out */
+
+ num_subkeys = regsubkey_ctr_numkeys( &subkeys );
+ for ( i=0; i<num_subkeys; i++ ) {
+ subkeyname = regsubkey_ctr_specific_key( &subkeys, i );
+ pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
+ result = reg_write_tree( regfile, subkeypath, key, sec_desc );
+ if ( !W_ERROR_IS_OK(result) )
+ goto done;
+ }
+
+ DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
+
+done:
+ regval_ctr_destroy( &values );
+ regsubkey_ctr_destroy( &subkeys );
+
+ return result;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
+{
+ DOM_SID adm_sid, owner_sid;
+ SEC_ACE ace[2]; /* at most 2 entries */
+ SEC_ACCESS mask;
+ SEC_ACL *psa = NULL;
+ uint32 sd_size;
+
+ /* set the owner to BUILTIN\Administrator */
+
+ sid_copy(&owner_sid, &global_sid_Builtin);
+ sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
+
+
+ /* basic access for Everyone */
+
+ init_sec_access(&mask, reg_map.generic_execute | reg_map.generic_read );
+ init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /* add Full Access 'BUILTIN\Administrators' */
+
+ init_sec_access(&mask, reg_map.generic_all);
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+ init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /* create the security descriptor */
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
+ return WERR_NOMEM;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
+ return WERR_NOMEM;
+
+ return WERR_OK;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
+{
+ REGF_FILE *regfile;
+ WERROR result;
+ SEC_DESC *sd = NULL;
+
+ /* open the registry file....fail if the file already exists */
+
+ if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
+ DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
+ fname, strerror(errno) ));
+ return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
+ }
+
+ if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
+ regfio_close( regfile );
+ return result;
+ }
+
+ /* write the registry tree to the file */
+
+ result = reg_write_tree( regfile, krecord->name, NULL, sd );
+
+ /* cleanup */
+
+ regfio_close( regfile );
+
+ return result;
+}
+
/*******************************************************************
********************************************************************/
@@ -751,25 +950,23 @@ WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
{
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
pstring filename;
+ int snum;
DEBUG(5,("_reg_save_key: Enter\n"));
-
- /*
- * basically this is a no op function which just verifies
- * that the client gave us a valid registry key handle
- */
-
+
if ( !regkey )
return WERR_BADFID;
rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
-
-#if 0
- validate_reg_filemame( filename );
+
+ if ( (snum = validate_reg_filename( filename )) == -1 )
+ return WERR_OBJECT_PATH_INVALID;
+
+ DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
+
return backup_registry_key( regkey, filename );
-#endif
return WERR_OK;
}
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index b7091b2ade..2fee1972ab 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -2353,9 +2353,8 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
*type = REG_BINARY;
*needed = 0x114;
- if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
+ if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, *needed)) )
return WERR_NOMEM;
- ZERO_STRUCTP( *data );
SIVAL(*data, 0, *needed); /* size */
SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
@@ -7249,16 +7248,11 @@ static void fill_port_2(PORT_INFO_2 *port, const char *name)
}
/****************************************************************************
- enumports level 1.
+ wrapper around the enumer ports command
****************************************************************************/
-static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
+WERROR enumports_hook( int *count, char ***lines )
{
- PORT_INFO_1 *ports=NULL;
- int i=0;
- WERROR result = WERR_OK;
-
- if (*lp_enumports_cmd()) {
char *cmd = lp_enumports_cmd();
char **qlines;
pstring command;
@@ -7266,6 +7260,18 @@ static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *need
int ret;
int fd;
+
+ /* if no hook then just fill in the default port */
+
+ if ( !*cmd ) {
+ qlines = SMB_MALLOC_ARRAY( char*, 2 );
+ qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
+ qlines[1] = NULL;
+ numlines = 1;
+ }
+ else {
+ /* we have a valid enumport command */
+
slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
DEBUG(10,("Running [%s]\n", command));
@@ -7274,7 +7280,7 @@ static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *need
if (ret != 0) {
if (fd != -1)
close(fd);
- /* Is this the best error to return here? */
+
return WERR_ACCESS_DENIED;
}
@@ -7282,6 +7288,28 @@ static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *need
qlines = fd_lines_load(fd, &numlines);
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
close(fd);
+ }
+
+ *count = numlines;
+ *lines = qlines;
+
+ return WERR_OK;
+}
+
+/****************************************************************************
+ enumports level 1.
+****************************************************************************/
+
+static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
+{
+ PORT_INFO_1 *ports=NULL;
+ int i=0;
+ WERROR result = WERR_OK;
+ char **qlines;
+ int numlines;
+
+ if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
+ return result;
if(numlines) {
if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
@@ -7301,17 +7329,6 @@ static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *need
*returned = numlines;
- } else {
- *returned = 1; /* Sole Samba port returned. */
-
- if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
- return WERR_NOMEM;
-
- DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
-
- fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
- }
-
/* check the required size. */
for (i=0; i<*returned; i++) {
DEBUGADD(6,("adding port [%d]'s size\n", i));
@@ -7352,40 +7369,12 @@ static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *need
PORT_INFO_2 *ports=NULL;
int i=0;
WERROR result = WERR_OK;
-
- if (*lp_enumports_cmd()) {
- char *cmd = lp_enumports_cmd();
- char *path;
char **qlines;
- pstring tmp_file;
- pstring command;
int numlines;
- int ret;
- int fd;
-
- if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
- path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
- else
- path = lp_lockdir();
-
- slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
- slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
- unlink(tmp_file);
- DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
- ret = smbrun(command, &fd);
- DEBUGADD(10,("returned [%d]\n", ret));
- if (ret != 0) {
- if (fd != -1)
- close(fd);
- /* Is this the best error to return here? */
- return WERR_ACCESS_DENIED;
- }
+ if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
+ return result;
- numlines = 0;
- qlines = fd_lines_load(fd, &numlines);
- DEBUGADD(10,("Lines returned = [%d]\n", numlines));
- close(fd);
if(numlines) {
if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
@@ -7403,18 +7392,6 @@ static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *need
*returned = numlines;
- } else {
-
- *returned = 1;
-
- if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
- return WERR_NOMEM;
-
- DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
-
- fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
- }
-
/* check the required size. */
for (i=0; i<*returned; i++) {
DEBUGADD(6,("adding port [%d]'s size\n", i));
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index b5768a09af..0e699d922b 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -1480,7 +1480,7 @@ WERROR _srv_net_share_get_info(pipes_struct *p, SRV_Q_NET_SHARE_GET_INFO *q_u, S
Check a given DOS pathname is valid for a share.
********************************************************************/
-static char *valid_share_pathname(char *dos_pathname)
+char *valid_share_pathname(char *dos_pathname)
{
char *ptr;
@@ -1493,7 +1493,7 @@ static char *valid_share_pathname(char *dos_pathname)
if (strlen(dos_pathname) > 2 && ptr[1] == ':' && ptr[0] != '/')
ptr += 2;
- /* Only abolute paths allowed. */
+ /* Only absolute paths allowed. */
if (*ptr != '/')
return NULL;
@@ -1525,8 +1525,12 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
r_u->parm_error = 0;
- if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
+ if ( strequal(share_name,"IPC$")
+ || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
+ || strequal(share_name,"global") )
+ {
return WERR_ACCESS_DENIED;
+ }
snum = find_service(share_name);
@@ -1756,8 +1760,12 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
return WERR_UNKNOWN_LEVEL;
}
- if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
+ if ( strequal(share_name,"IPC$")
+ || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
+ || strequal(share_name,"global") )
+ {
return WERR_ACCESS_DENIED;
+ }
snum = find_service(share_name);
@@ -1839,8 +1847,12 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
unistr2_to_ascii(share_name, &q_u->uni_share_name, sizeof(share_name));
- if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
+ if ( strequal(share_name,"IPC$")
+ || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
+ || strequal(share_name,"global") )
+ {
return WERR_ACCESS_DENIED;
+ }
snum = find_service(share_name);