s3/smbd: open the share_info.tdb on startup instead of tconx
[ira/wip.git] / source3 / rpc_server / srv_winreg_nt.c
index 92c178042f0e46eceaf1afbbb5b34b0271d7844a..3de9f0e623ad0757fb9e8ed1f9f35ffbae069fae 100644 (file)
 /* Implementation of registry functions. */
 
 #include "includes.h"
-#include "regfio.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
-static const struct generic_mapping reg_generic_map =
-       { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
-
 /******************************************************************
- free() function for struct registry_key
- *****************************************************************/
-static void free_regkey(void *ptr)
-{
-       struct registry_key *key = (struct registry_key *)ptr;
-       TALLOC_FREE(key);
-}
-
-/******************************************************************
- Find a registry key handle and return a REGISTRY_KEY
+ Find a registry key handle and return a struct registry_key *
  *****************************************************************/
 
 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
-                                              POLICY_HND *hnd)
+                                              struct policy_handle *hnd)
 {
        struct registry_key *regkey = NULL;
 
@@ -64,7 +50,7 @@ static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
  HK[LM|U]\<key>\<key>\...
  *******************************************************************/
  
-static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd, 
+static WERROR open_registry_key( pipes_struct *p, struct policy_handle *hnd,
                                 struct registry_key *parent,
                                 const char *subkeyname,
                                 uint32 access_desired  )
@@ -73,19 +59,19 @@ static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
        struct registry_key *key;
 
        if (parent == NULL) {
-               result = reg_openhive(NULL, subkeyname, access_desired,
-                                     p->pipe_user.nt_user_token, &key);
+               result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
+                                     p->server_info->ptok, &key);
        }
        else {
-               result = reg_openkey(NULL, parent, subkeyname, access_desired,
-                                    &key);
+               result = reg_openkey(p->mem_ctx, parent, subkeyname,
+                                    access_desired, &key);
        }
 
        if ( !W_ERROR_IS_OK(result) ) {
                return result;
        }
        
-       if ( !create_policy_hnd( p, hnd, free_regkey, key ) ) {
+       if ( !create_policy_hnd( p, hnd, key ) ) {
                return WERR_BADFILE; 
        }
        
@@ -97,7 +83,7 @@ static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd,
  Note that P should be valid & hnd should already have space
  *******************************************************************/
 
-static bool close_registry_key(pipes_struct *p, POLICY_HND *hnd)
+static bool close_registry_key(pipes_struct *p, struct policy_handle *hnd)
 {
        struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
        
@@ -234,7 +220,11 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
        if ( !regkey )
                return WERR_BADFID;
 
-       *r->out.value_length = *r->out.type = REG_NONE;
+       if ((r->out.data_length == NULL) || (r->out.type == NULL)) {
+               return WERR_INVALID_PARAM;
+       }
+
+       *r->out.data_length = *r->out.type = REG_NONE;
        
        DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->key->name));
        DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->key->type));
@@ -242,38 +232,40 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
        /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
        if(regkey->key->type == REG_KEY_HKPD) 
        {
-               if(strequal(r->in.value_name.name, "Global"))   {
-                       prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL);
+               if (strequal(r->in.value_name->name, "Global")) {
+                       if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
+                               return WERR_NOMEM;
                        status = reg_perfcount_get_hkpd(
                                &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
                        outbuf = (uint8_t *)prs_hkpd.data_p;
                        free_prs = True;
                }
-               else if(strequal(r->in.value_name.name, "Counter 009")) {
+               else if (strequal(r->in.value_name->name, "Counter 009")) {
                        outbuf_size = reg_perfcount_get_counter_names(
                                reg_perfcount_get_base_index(),
                                (char **)(void *)&outbuf);
                        free_buf = True;
                }
-               else if(strequal(r->in.value_name.name, "Explain 009")) {
+               else if (strequal(r->in.value_name->name, "Explain 009")) {
                        outbuf_size = reg_perfcount_get_counter_help(
                                reg_perfcount_get_base_index(),
                                (char **)(void *)&outbuf);
                        free_buf = True;
                }
-               else if(isdigit(r->in.value_name.name[0])) {
+               else if (isdigit(r->in.value_name->name[0])) {
                        /* we probably have a request for a specific object
                         * here */
-                       prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL);
+                       if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
+                               return WERR_NOMEM;
                        status = reg_perfcount_get_hkpd(
                                &prs_hkpd, *r->in.data_size, &outbuf_size,
-                               r->in.value_name.name);
+                               r->in.value_name->name);
                        outbuf = (uint8_t *)prs_hkpd.data_p;
                        free_prs = True;
                }
                else {
                        DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
-                                r->in.value_name.name));
+                                r->in.value_name->name));
                        return WERR_BADFILE;
                }
 
@@ -282,14 +274,14 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
        else {
                struct registry_value *val;
 
-               status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name.name,
+               status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
                                        &val);
                if (!W_ERROR_IS_OK(status)) {
                        if (r->out.data_size) {
                                *r->out.data_size = 0;
                        }
-                       if (r->out.value_length) {
-                               *r->out.value_length = 0;
+                       if (r->out.data_length) {
+                               *r->out.data_length = 0;
                        }
                        return status;
                }
@@ -304,18 +296,18 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
                *r->out.type = val->type;
        }
 
-       *r->out.value_length = outbuf_size;
+       *r->out.data_length = outbuf_size;
 
        if ( *r->in.data_size == 0 || !r->out.data ) {
                status = WERR_OK;
-       } else if ( *r->out.value_length > *r->in.data_size ) {
+       } else if ( *r->out.data_length > *r->in.data_size ) {
                status = WERR_MORE_DATA;
        } else {
-               memcpy( r->out.data, outbuf, *r->out.value_length );
+               memcpy( r->out.data, outbuf, *r->out.data_length );
                status = WERR_OK;
        }
 
-       *r->out.data_size = *r->out.value_length;
+       *r->out.data_size = *r->out.data_length;
 
        if (free_prs) prs_mem_free(&prs_hkpd);
        if (free_buf) SAFE_FREE(outbuf);
@@ -473,7 +465,7 @@ WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSys
        s.in.message = r->in.message;
        s.in.timeout = r->in.timeout;
        s.in.force_apps = r->in.force_apps;
-       s.in.reboot = r->in.reboot;
+       s.in.do_reboot = r->in.do_reboot;
        s.in.reason = 0;
 
        /* thunk down to _winreg_InitiateSystemShutdownEx() 
@@ -497,7 +489,7 @@ WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateS
        char *chkmsg = NULL;
        fstring str_timeout;
        fstring str_reason;
-       fstring reboot;
+       fstring do_reboot;
        fstring f;
        int ret;
        bool can_shutdown;
@@ -512,10 +504,8 @@ WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateS
 
        /* pull the message string and perform necessary sanity checks on it */
 
-       chkmsg[0] = '\0';
-
-       if ( r->in.message && r->in.message->name && r->in.message->name->name ) {
-               if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->name->name )) == NULL ) {
+       if ( r->in.message && r->in.message->string ) {
+               if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
                        return WERR_NOMEM;
                }
                chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
@@ -526,7 +516,7 @@ WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateS
        }
 
        fstr_sprintf(str_timeout, "%d", r->in.timeout);
-       fstr_sprintf(reboot, r->in.reboot ? SHUTDOWN_R_STRING : "");
+       fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
        fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
        fstr_sprintf(str_reason, "%d", r->in.reason );
 
@@ -541,7 +531,7 @@ WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateS
                return WERR_NOMEM;
        }
        shutdown_script = talloc_all_string_sub(p->mem_ctx,
-                                               shutdown_script, "%r", reboot);
+                                               shutdown_script, "%r", do_reboot);
        if (!shutdown_script) {
                return WERR_NOMEM;
        }
@@ -556,7 +546,8 @@ WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateS
                return WERR_NOMEM;
        }
 
-       can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
+       can_shutdown = user_has_privileges( p->server_info->ptok,
+                                           &se_remote_shutdown );
 
        /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
           Take the error return from the script and provide it as the Windows return code. */
@@ -594,7 +585,8 @@ WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShu
        if (!*abort_shutdown_script)
                return WERR_ACCESS_DENIED;
 
-       can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
+       can_shutdown = user_has_privileges( p->server_info->ptok,
+                                           &se_remote_shutdown );
 
        /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
 
@@ -654,125 +646,6 @@ static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
        return (snum < num_services) ? snum : -1;
 }
 
-/*******************************************************************
- Note: topkeypat is the *full* path that this *key will be
- loaded into (including the name of the key)
- ********************************************************************/
-
-static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
-                             REGF_NK_REC *key )
-{
-       REGF_NK_REC *subkey;
-       REGISTRY_KEY registry_key;
-       REGVAL_CTR *values;
-       REGSUBKEY_CTR *subkeys;
-       int i;
-       char *path = NULL;
-       WERROR result = WERR_OK;
-
-       /* initialize the REGISTRY_KEY structure */
-
-       if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
-               DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
-                       topkeypath ));
-               return WERR_BADFILE;
-       }
-
-       registry_key.name = talloc_strdup( regfile->mem_ctx, topkeypath );
-       if ( !registry_key.name ) {
-               DEBUG(0,("reg_load_tree: Talloc failed for reg_key.name!\n"));
-               return WERR_NOMEM;
-       }
-
-       /* now start parsing the values and subkeys */
-
-       if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
-               return WERR_NOMEM;
-
-       if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
-               return WERR_NOMEM;
-
-       /* copy values into the REGVAL_CTR */
-
-       for ( i=0; i<key->num_values; i++ ) {
-               regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
-                       (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
-       }
-
-       /* copy subkeys into the REGSUBKEY_CTR */
-
-       key->subkey_index = 0;
-       while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
-               regsubkey_ctr_addkey( subkeys, subkey->keyname );
-       }
-
-       /* write this key and values out */
-
-       if ( !store_reg_values( &registry_key, values )
-               || !store_reg_keys( &registry_key, subkeys ) )
-       {
-               DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
-               result = WERR_REG_IO_FAILURE;
-       }
-
-       TALLOC_FREE( subkeys );
-
-       if ( !W_ERROR_IS_OK(result) )
-               return result;
-
-       /* now continue to load each subkey registry tree */
-
-       key->subkey_index = 0;
-       while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
-               path = talloc_asprintf(regfile->mem_ctx,
-                               "%s\\%s",
-                               topkeypath,
-                               subkey->keyname);
-               if (!path) {
-                       return WERR_NOMEM;
-               }
-               result = reg_load_tree( regfile, path, subkey );
-               if ( !W_ERROR_IS_OK(result) )
-                       break;
-       }
-
-       return result;
-}
-
-/*******************************************************************
- ********************************************************************/
-
-static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
-{
-       REGF_FILE *regfile;
-       REGF_NK_REC *rootkey;
-       WERROR result;
-               
-       /* open the registry file....fail if the file already exists */
-       
-       if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
-                DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n", 
-                       fname, strerror(errno) ));
-               return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
-        }
-       
-       /* get the rootkey from the regf file and then load the tree
-          via recursive calls */
-          
-       if ( !(rootkey = regfio_rootkey( regfile )) ) {
-               regfio_close( regfile );
-               return WERR_REG_FILE_INVALID;
-       }
-
-       result = reg_load_tree( regfile, krecord->name, rootkey );
-
-       /* cleanup */
-
-       regfio_close( regfile );
-
-       return result;
-}
-
 /*******************************************************************
  ********************************************************************/
 
@@ -801,181 +674,15 @@ WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
 
        /* user must posses SeRestorePrivilege for this this proceed */
 
-       if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
+       if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
                return WERR_ACCESS_DENIED;
 
        DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
                 regkey->key->name, fname, lp_servicename(snum) ));
 
-       return restore_registry_key( regkey->key, fname );
+       return reg_restorekey(regkey, fname);
 }
 
-/********************************************************************
-********************************************************************/
-
-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;
-       char *key_tmp = NULL;
-       char *keyname, *parentpath;
-       char *subkeypath = NULL;
-       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 */
-
-       key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
-       if (!key_tmp) {
-               return WERR_NOMEM;
-       }
-       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 );
-
-       if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
-               return WERR_NOMEM;
-
-       if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
-               return WERR_BADFILE;
-
-       /* lookup the values and subkeys */
-
-       if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
-               return WERR_NOMEM;
-
-       if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
-               return WERR_NOMEM;
-
-       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 );
-               subkeypath = talloc_asprintf(regfile->mem_ctx,
-                                       "%s\\%s", keypath, subkeyname);
-               if (!subkeypath) {
-                       result = WERR_NOMEM;
-                       goto done;
-               }
-               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:
-       TALLOC_FREE( subkeys );
-       TALLOC_FREE( registry_key.name );
-
-       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;
-       size_t 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_generic_map.generic_execute | reg_generic_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_generic_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, SECURITY_DESCRIPTOR_REVISION_1,
-                                 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;
-}
-
-/*******************************************************************
- ********************************************************************/
-
 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
 {
        struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
@@ -1002,7 +709,7 @@ WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
        DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
                 regkey->key->name, fname, lp_servicename(snum) ));
 
-       return backup_registry_key( regkey->key, fname );
+       return reg_savekey(regkey, fname);
 }
 
 /*******************************************************************
@@ -1029,13 +736,16 @@ WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
        if ( !parent )
                return WERR_BADFID;
 
+       DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
+                  "subkey name '%s'\n", parent->key->name, r->in.name.name));
+
        result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
                               &new_key, r->out.action_taken);
        if (!W_ERROR_IS_OK(result)) {
                return result;
        }
 
-       if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
+       if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
                TALLOC_FREE(new_key);
                return WERR_BADFILE;
        }