diff options
author | Gerald Carter <jerry@samba.org> | 2005-05-23 16:25:31 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:56:57 -0500 |
commit | f0c650a38286c07b9f3e83139c15bfbadc70ad5f (patch) | |
tree | 2c63cd42bf12e46c94628a82a40b19db47fd0aae /source3/rpc_server | |
parent | e2404c81295fe3468c9b635b549f1b16f5c5f323 (diff) | |
download | samba-f0c650a38286c07b9f3e83139c15bfbadc70ad5f.tar.gz samba-f0c650a38286c07b9f3e83139c15bfbadc70ad5f.tar.bz2 samba-f0c650a38286c07b9f3e83139c15bfbadc70ad5f.zip |
r6942: * merging the registry changes back to the 3.0 tree
* removing the testprns tool
(This used to be commit 81ffb0dbbbd244623507880c323a3c37e2b8dc4d)
Diffstat (limited to 'source3/rpc_server')
-rw-r--r-- | source3/rpc_server/srv_reg_nt.c | 237 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 103 | ||||
-rw-r--r-- | source3/rpc_server/srv_srvsvc_nt.c | 22 |
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( ®istry_key, &subkeys ); + fetch_reg_values( ®istry_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); |