Make sure we can read SACLs from the registry.
[tprouty/samba.git] / source3 / utils / net_rpc_registry.c
index c684b04b8eb99bd412ebeca9298a93a4c0c187c2..e1d65fb06b0916d6df6c75b54f2d9a70e19ebfbd 100644 (file)
@@ -6,7 +6,7 @@
 
    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
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
  
 #include "includes.h"
 #include "utils/net.h"
 #include "regfio.h"
 #include "reg_objects.h"
 
-static BOOL reg_hive_key(const char *fullname, uint32 *reg_type,
+static bool reg_hive_key(const char *fullname, uint32 *reg_type,
                         const char **key_name)
 {
        const char *sep;
@@ -49,6 +48,9 @@ static BOOL reg_hive_key(const char *fullname, uint32 *reg_type,
        else if (strnequal(fullname, "HKU", len) ||
                 strnequal(fullname, "HKEY_USERS", len))
                (*reg_type) = HKEY_USERS;
+       else if (strnequal(fullname, "HKCU", len) ||
+                strnequal(fullname, "HKEY_CURRENT_USER", len))
+               (*reg_type) = HKEY_CURRENT_USER;
        else if (strnequal(fullname, "HKPD", len) ||
                 strnequal(fullname, "HKEY_PERFORMANCE_DATA", len))
                (*reg_type) = HKEY_PERFORMANCE_DATA;
@@ -71,6 +73,8 @@ static NTSTATUS registry_openkey(TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        struct winreg_String key;
 
+       ZERO_STRUCT(key);
+
        if (!reg_hive_key(name, &hive, &key.name)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
@@ -139,10 +143,8 @@ static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
        for (i=0; i<num_subkeys; i++) {
                char c, n;
                struct winreg_StringBuf class_buf;
-               struct winreg_StringBuf *pclass_buf = &class_buf;
                struct winreg_StringBuf name_buf;
                NTTIME modtime;
-               NTTIME *pmodtime = &modtime;
 
                c = '\0';
                class_buf.name = &c;
@@ -155,8 +157,8 @@ static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
                ZERO_STRUCT(modtime);
 
                status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key_hnd,
-                                              i, &name_buf, &pclass_buf,
-                                              &pmodtime);
+                                              i, &name_buf, &class_buf,
+                                              &modtime);
                
                if (W_ERROR_EQUAL(ntstatus_to_werror(status),
                                  WERR_NO_MORE_ITEMS) ) {
@@ -169,9 +171,8 @@ static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
 
                classes[i] = NULL;
 
-               if (pclass_buf && pclass_buf->name &&
-                   (!(classes[i] = talloc_strdup(classes,
-                                                 pclass_buf->name)))) {
+               if (class_buf.name &&
+                   (!(classes[i] = talloc_strdup(classes, class_buf.name)))) {
                        status = NT_STATUS_NO_MEMORY;
                        goto error;
                }
@@ -181,9 +182,8 @@ static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
                        goto error;
                }
 
-               if ((pmodtime) &&
-                   (!(modtimes[i] = (NTTIME *)talloc_memdup(
-                              modtimes, pmodtime, sizeof(*pmodtime))))) {
+               if ((!(modtimes[i] = (NTTIME *)talloc_memdup(
+                              modtimes, &modtime, sizeof(modtime))))) {
                        status = NT_STATUS_NO_MEMORY;
                        goto error;
                }
@@ -254,30 +254,26 @@ static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
 
        for (i=0; i<num_values; i++) {
                enum winreg_Type type = REG_NONE;
-               enum winreg_Type *ptype = &type;
-               uint8 d = 0;
-               uint8 *data = &d;
-
+               uint8 *data = NULL;
                uint32 data_size;
-               uint32 *pdata_size = &data_size;
-
                uint32 value_length;
-               uint32 *pvalue_length = &value_length;
 
                char n;
                struct winreg_ValNameBuf name_buf;
+               WERROR err;
 
                n = '\0';
                name_buf.name = &n;
                name_buf.size = max_valnamelen + 2;
 
                data_size = max_valbufsize;
+               data = (uint8 *)TALLOC(mem_ctx, data_size);
                value_length = 0;
 
                status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, key_hnd,
-                                                i, &name_buf, &ptype,
-                                                &data, &pdata_size,
-                                                &pvalue_length );
+                                                i, &name_buf, &type,
+                                                data, &data_size,
+                                                &value_length );
 
                if ( W_ERROR_EQUAL(ntstatus_to_werror(status),
                                   WERR_NO_MORE_ITEMS) ) {
@@ -289,9 +285,7 @@ static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
                        goto error;
                }
 
-               if ((name_buf.name == NULL) || (ptype == NULL) ||
-                   (data == NULL) || (pdata_size == 0) ||
-                   (pvalue_length == NULL)) {
+               if (name_buf.name == NULL) {
                        status = NT_STATUS_INVALID_PARAMETER;
                        goto error;
                }
@@ -301,9 +295,10 @@ static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
                        goto error;
                }
 
-               status = registry_pull_value(values, &values[i], *ptype, data,
-                                            *pdata_size, *pvalue_length);
-               if (!(NT_STATUS_IS_OK(status))) {
+               err = registry_pull_value(values, &values[i], type, data,
+                                         data_size, value_length);
+               if (!W_ERROR_IS_OK(err)) {
+                       status = werror_to_ntstatus(err);
                        goto error;
                }
        }
@@ -324,6 +319,17 @@ static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
        return status;
 }
 
+static NTSTATUS registry_getsd(TALLOC_CTX *mem_ctx,
+                              struct rpc_pipe_client *pipe_hnd,
+                              struct policy_handle *key_hnd,
+                              uint32_t sec_info,
+                              struct KeySecurityData *sd)
+{
+       return rpccli_winreg_GetKeySecurity(pipe_hnd, mem_ctx, key_hnd,
+                                           sec_info, sd);
+}
+
+
 static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
                                  struct rpc_pipe_client *pipe_hnd,
                                  struct policy_handle *key_hnd,
@@ -333,12 +339,15 @@ static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
        struct winreg_String name_string;
        DATA_BLOB blob;
        NTSTATUS result;
+       WERROR err;
 
-       result = registry_push_value(mem_ctx, value, &blob);
-       if (!NT_STATUS_IS_OK(result)) {
-               return result;
+       err = registry_push_value(mem_ctx, value, &blob);
+       if (!W_ERROR_IS_OK(err)) {
+               return werror_to_ntstatus(err);
        }
 
+       ZERO_STRUCT(name_string);
+
        name_string.name = name;
        result = rpccli_winreg_SetValue(pipe_hnd, blob.data, key_hnd,
                                        name_string, value->type,
@@ -359,7 +368,8 @@ static NTSTATUS rpc_registry_setvalue_internal(const DOM_SID *domain_sid,
        NTSTATUS status;
        struct registry_value value;
 
-       status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_WRITE,
+       status = registry_openkey(mem_ctx, pipe_hnd, argv[0], 
+                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
                                  &hive_hnd, &key_hnd);
        if (!NT_STATUS_IS_OK(status)) {
                d_fprintf(stderr, "registry_openkey failed: %s\n",
@@ -382,7 +392,7 @@ static NTSTATUS rpc_registry_setvalue_internal(const DOM_SID *domain_sid,
                value.v.sz.str = CONST_DISCARD(char *, argv[3]);
        }
        else {
-               d_fprintf(stderr, "type \"%s\" not implemented\n", argv[3]);
+               d_fprintf(stderr, "type \"%s\" not implemented\n", argv[2]);
                status = NT_STATUS_NOT_IMPLEMENTED;
                goto error;
        }
@@ -426,7 +436,10 @@ static NTSTATUS rpc_registry_deletevalue_internal(const DOM_SID *domain_sid,
        NTSTATUS status;
        struct winreg_String valuename;
 
-       status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_WRITE,
+       ZERO_STRUCT(valuename);
+
+       status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
+                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
                                  &hive_hnd, &key_hnd);
        if (!NT_STATUS_IS_OK(status)) {
                d_fprintf(stderr, "registry_openkey failed: %s\n",
@@ -474,15 +487,17 @@ static NTSTATUS rpc_registry_createkey_internal(const DOM_SID *domain_sid,
        struct policy_handle hive_hnd, key_hnd;
        struct winreg_String key, keyclass;
        enum winreg_CreateAction action;
-       enum winreg_CreateAction *paction = &action;
        NTSTATUS status;
 
+       ZERO_STRUCT(key);
+       ZERO_STRUCT(keyclass);
+
        if (!reg_hive_key(argv[0], &hive, &key.name)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
-                                      REG_KEY_READ|REG_KEY_WRITE,
+                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
                                       &hive_hnd);
        if (!(NT_STATUS_IS_OK(status))) {
                return status;
@@ -493,7 +508,7 @@ static NTSTATUS rpc_registry_createkey_internal(const DOM_SID *domain_sid,
 
        status = rpccli_winreg_CreateKey(pipe_hnd, mem_ctx, &hive_hnd, key,
                                         keyclass, 0, REG_KEY_READ, NULL,
-                                        &key_hnd, &paction);
+                                        &key_hnd, &action);
        if (!NT_STATUS_IS_OK(status)) {
                d_fprintf(stderr, "createkey returned %s\n",
                          nt_errstr(status));
@@ -501,8 +516,7 @@ static NTSTATUS rpc_registry_createkey_internal(const DOM_SID *domain_sid,
                return status;
        }
 
-       if (paction) {
-               switch (*paction) {
+       switch (action) {
                case REG_ACTION_NONE:
                        d_printf("createkey did nothing -- huh?\n");
                        break;
@@ -512,7 +526,6 @@ static NTSTATUS rpc_registry_createkey_internal(const DOM_SID *domain_sid,
                case REG_OPENED_EXISTING_KEY:
                        d_printf("createkey opened existing %s\n", argv[0]);
                        break;
-               }
        }
 
        rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
@@ -545,11 +558,14 @@ static NTSTATUS rpc_registry_deletekey_internal(const DOM_SID *domain_sid,
        struct winreg_String key;
        NTSTATUS status;
 
+       ZERO_STRUCT(key);
+
        if (!reg_hive_key(argv[0], &hive, &key.name)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, REG_KEY_WRITE,
+       status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
+                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
                                       &hive_hnd);
        if (!(NT_STATUS_IS_OK(status))) {
                return status;
@@ -590,16 +606,16 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
 {
        POLICY_HND pol_hive, pol_key; 
        NTSTATUS status;
-       uint32 num_subkeys;
-       uint32 num_values;
-       char **names, **classes;
-       NTTIME **modtimes;
+       uint32 num_subkeys = 0;
+       uint32 num_values = 0;
+       char **names = NULL, **classes = NULL;
+       NTTIME **modtimes = NULL;
        uint32 i;
-       struct registry_value **values;
+       struct registry_value **values = NULL;
        
        if (argc != 1 ) {
-               d_printf("Usage:    net rpc enumerate <path> [recurse]\n");
-               d_printf("Example:  net rpc enumerate 'HKLM\\Software\\Samba'\n");
+               d_printf("Usage:    net rpc registry enumerate <path> [recurse]\n");
+               d_printf("Example:  net rpc registry enumerate 'HKLM\\Software\\Samba'\n");
                return NT_STATUS_OK;
        }
 
@@ -658,7 +674,7 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
                }
                case REG_BINARY:
                        d_printf("Value      = %d bytes\n",
-                                v->v.binary.length);
+                                (int)v->v.binary.length);
                        break;
                default:
                        d_printf("Value      = <unprintable>\n");
@@ -700,7 +716,7 @@ static NTSTATUS rpc_registry_save_internal(const DOM_SID *domain_sid,
        struct winreg_String filename;
        
        if (argc != 2 ) {
-               d_printf("Usage:    net rpc backup <path> <file> \n");
+               d_printf("Usage:    net rpc registry backup <path> <file> \n");
                return NT_STATUS_OK;
        }
        
@@ -786,7 +802,7 @@ static void dump_values( REGF_NK_REC *nk )
 /********************************************************************
 ********************************************************************/
 
-static BOOL dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
+static bool dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
 {
        REGF_NK_REC *key;
        pstring regpath;
@@ -807,7 +823,7 @@ static BOOL dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *pa
 /********************************************************************
 ********************************************************************/
 
-static BOOL write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk, 
+static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk, 
                                  REGF_NK_REC *parent, REGF_FILE *outfile,
                                 const char *parentpath )
 {
@@ -866,7 +882,7 @@ static int rpc_registry_dump( int argc, const char **argv )
        REGF_NK_REC *nk;
        
        if (argc != 1 ) {
-               d_printf("Usage:    net rpc dump <file> \n");
+               d_printf("Usage:    net rpc registry dump <file> \n");
                return 0;
        }
        
@@ -910,7 +926,7 @@ static int rpc_registry_copy( int argc, const char **argv )
        int result = 1;
        
        if (argc != 2 ) {
-               d_printf("Usage:    net rpc copy <srcfile> <newfile>\n");
+               d_printf("Usage:    net rpc registry copy <srcfile> <newfile>\n");
                return 0;
        }
        
@@ -960,6 +976,88 @@ out:
 /********************************************************************
 ********************************************************************/
 
+static NTSTATUS rpc_registry_getsd_internal(const DOM_SID *domain_sid,
+                                           const char *domain_name,
+                                           struct cli_state *cli,
+                                           struct rpc_pipe_client *pipe_hnd,
+                                           TALLOC_CTX *mem_ctx,
+                                           int argc,
+                                           const char **argv)
+{
+       POLICY_HND pol_hive, pol_key;
+       NTSTATUS status;
+       struct KeySecurityData *sd = NULL;
+       uint32_t sec_info;
+       DATA_BLOB blob;
+       struct security_descriptor sec_desc;
+       uint32_t access_mask = REG_KEY_READ |
+                              SEC_RIGHT_MAXIMUM_ALLOWED |
+                              SEC_RIGHT_SYSTEM_SECURITY;
+
+       if (argc <1 || argc > 2) {
+               d_printf("Usage:    net rpc registry getsd <path> <secinfo>\n");
+               d_printf("Example:  net rpc registry getsd 'HKLM\\Software\\Samba'\n");
+               return NT_STATUS_OK;
+       }
+
+       status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
+                                 access_mask,
+                                 &pol_hive, &pol_key);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "registry_openkey failed: %s\n",
+                         nt_errstr(status));
+               return status;
+       }
+
+       sd = TALLOC_ZERO_P(mem_ctx, struct KeySecurityData);
+       if (!sd) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+
+       sd->size = 0x1000;
+
+       if (argc >= 2) {
+               sscanf(argv[1], "%x", &sec_info);
+       } else {
+               sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
+       }
+
+       status = registry_getsd(mem_ctx, pipe_hnd, &pol_key, sec_info, sd);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "getting sd failed: %s\n",
+                         nt_errstr(status));
+               goto out;
+       }
+
+       blob.data = sd->data;
+       blob.length = sd->size;
+
+       status = ndr_pull_struct_blob(&blob, mem_ctx, &sec_desc,
+                                     (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
+       display_sec_desc(&sec_desc);
+
+ out:
+       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key);
+       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive);
+
+       return status;
+}
+
+
+static int rpc_registry_getsd(int argc, const char **argv)
+{
+       return run_rpc_command(NULL, PI_WINREG, 0,
+               rpc_registry_getsd_internal, argc, argv);
+}
+
+/********************************************************************
+********************************************************************/
+
 int net_rpc_registry(int argc, const char **argv) 
 {
        struct functable2 func[] = {
@@ -979,6 +1077,8 @@ int net_rpc_registry(int argc, const char **argv)
                  "Dump a registry file" },
                { "copy", rpc_registry_copy,
                  "Copy a registry file" },
+               { "getsd", rpc_registry_getsd,
+                 "Get security descriptor" },
                {NULL, NULL, NULL}
        };