1/* 2 Unix SMB/CIFS implementation. 3 Transparent registry backend handling 4 Copyright (C) Jelmer Vernooij 2003-2007. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include "includes.h" 21#include "lib/registry/registry.h" 22#include "librpc/gen_ndr/winreg.h" 23 24/** 25 * @file 26 * @brief Registry utility functions 27 */ 28 29static const struct { 30 uint32_t id; 31 const char *name; 32} reg_value_types[] = { 33 { REG_SZ, "REG_SZ" }, 34 { REG_DWORD, "REG_DWORD" }, 35 { REG_BINARY, "REG_BINARY" }, 36 { REG_EXPAND_SZ, "REG_EXPAND_SZ" }, 37 { REG_NONE, "REG_NONE" }, 38 { 0, NULL } 39}; 40 41/** Return string description of registry value type */ 42_PUBLIC_ const char *str_regtype(int type) 43{ 44 int i; 45 for (i = 0; reg_value_types[i].name; i++) { 46 if (reg_value_types[i].id == type) 47 return reg_value_types[i].name; 48 } 49 50 return "Unknown"; 51} 52 53_PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, 54 struct smb_iconv_convenience *iconv_convenience, 55 uint32_t type, 56 const DATA_BLOB data) 57{ 58 char *ret = NULL; 59 60 if (data.length == 0) 61 return talloc_strdup(mem_ctx, ""); 62 63 switch (type) { 64 case REG_EXPAND_SZ: 65 case REG_SZ: 66 convert_string_talloc_convenience(mem_ctx, iconv_convenience, CH_UTF16, CH_UNIX, 67 data.data, data.length, 68 (void **)&ret, NULL, false); 69 return ret; 70 case REG_BINARY: 71 ret = data_blob_hex_string(mem_ctx, &data); 72 return ret; 73 case REG_DWORD: 74 if (*(int *)data.data == 0) 75 return talloc_strdup(mem_ctx, "0"); 76 return talloc_asprintf(mem_ctx, "0x%x", 77 *(int *)data.data); 78 case REG_MULTI_SZ: 79 /* FIXME */ 80 break; 81 default: 82 break; 83 } 84 85 return ret; 86} 87 88/** Generate a string that describes a registry value */ 89_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, 90 struct smb_iconv_convenience *iconv_convenience, 91 const char *name, 92 uint32_t data_type, 93 const DATA_BLOB data) 94{ 95 return talloc_asprintf(mem_ctx, "%s = %s : %s", name?name:"<No Name>", 96 str_regtype(data_type), 97 reg_val_data_string(mem_ctx, iconv_convenience, data_type, data)); 98} 99 100_PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx, 101 struct smb_iconv_convenience *iconv_convenience, 102 const char *type_str, 103 const char *data_str, uint32_t *type, 104 DATA_BLOB *data) 105{ 106 int i; 107 *type = -1; 108 109 /* Find the correct type */ 110 for (i = 0; reg_value_types[i].name; i++) { 111 if (!strcmp(reg_value_types[i].name, type_str)) { 112 *type = reg_value_types[i].id; 113 break; 114 } 115 } 116 117 if (*type == -1) 118 return false; 119 120 /* Convert data appropriately */ 121 122 switch (*type) 123 { 124 case REG_SZ: 125 case REG_EXPAND_SZ: 126 convert_string_talloc_convenience(mem_ctx, iconv_convenience, CH_UNIX, CH_UTF16, 127 data_str, strlen(data_str), 128 (void **)&data->data, &data->length, false); 129 break; 130 131 case REG_DWORD: { 132 uint32_t tmp = strtol(data_str, NULL, 0); 133 *data = data_blob_talloc(mem_ctx, &tmp, 4); 134 } 135 break; 136 137 case REG_NONE: 138 ZERO_STRUCTP(data); 139 break; 140 141 case REG_BINARY: 142 *data = strhex_to_data_blob(mem_ctx, data_str); 143 break; 144 145 default: 146 /* FIXME */ 147 return false; 148 } 149 return true; 150} 151 152/** Open a key by name (including the predefined key name!) */ 153WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, 154 const char *name, struct registry_key **result) 155{ 156 struct registry_key *predef; 157 WERROR error; 158 int predeflength; 159 char *predefname; 160 161 if (strchr(name, '\\') != NULL) 162 predeflength = strchr(name, '\\')-name; 163 else 164 predeflength = strlen(name); 165 166 predefname = talloc_strndup(mem_ctx, name, predeflength); 167 error = reg_get_predefined_key_by_name(handle, predefname, &predef); 168 talloc_free(predefname); 169 170 if (!W_ERROR_IS_OK(error)) { 171 return error; 172 } 173 174 if (strchr(name, '\\')) { 175 return reg_open_key(mem_ctx, predef, strchr(name, '\\')+1, 176 result); 177 } else { 178 *result = predef; 179 return WERR_OK; 180 } 181} 182 183static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx, 184 const char *path, struct registry_key **parent, 185 const char **name) 186{ 187 char *parent_name; 188 WERROR error; 189 190 if (strchr(path, '\\') == NULL) { 191 return WERR_FOOBAR; 192 } 193 194 parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-path); 195 196 error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent); 197 if (!W_ERROR_IS_OK(error)) { 198 return error; 199 } 200 201 *name = talloc_strdup(mem_ctx, strrchr(path, '\\')+1); 202 203 return WERR_OK; 204} 205 206WERROR reg_key_del_abs(struct registry_context *ctx, const char *path) 207{ 208 struct registry_key *parent; 209 const char *n; 210 TALLOC_CTX *mem_ctx = talloc_init("reg_key_del_abs"); 211 WERROR error; 212 213 if (!strchr(path, '\\')) { 214 return WERR_FOOBAR; 215 } 216 217 error = get_abs_parent(mem_ctx, ctx, path, &parent, &n); 218 if (W_ERROR_IS_OK(error)) { 219 error = reg_key_del(parent, n); 220 } 221 222 talloc_free(mem_ctx); 223 224 return error; 225} 226 227WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, 228 const char *path, uint32_t access_mask, 229 struct security_descriptor *sec_desc, 230 struct registry_key **result) 231{ 232 struct registry_key *parent; 233 const char *n; 234 WERROR error; 235 236 if (!strchr(path, '\\')) { 237 return WERR_ALREADY_EXISTS; 238 } 239 240 error = get_abs_parent(mem_ctx, ctx, path, &parent, &n); 241 if (!W_ERROR_IS_OK(error)) { 242 DEBUG(2, ("Opening parent of %s failed with %s\n", path, 243 win_errstr(error))); 244 return error; 245 } 246 247 error = reg_key_add_name(mem_ctx, parent, n, NULL, sec_desc, result); 248 249 return error; 250} 251