1/* 2 Samba Unix/Linux SMB implementation 3 RPC backend for the registry library 4 Copyright (C) 2003-2007 Jelmer Vernooij, jelmer@samba.org 5 Copyright (C) 2008 Matthias Dieter Walln��fer, mwallnoefer@yahoo.de 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "includes.h" 21#include "registry.h" 22#include "librpc/gen_ndr/ndr_winreg_c.h" 23 24#define MAX_NAMESIZE 512 25#define MAX_VALSIZE 32768 26 27struct rpc_key { 28 struct registry_key key; 29 struct policy_handle pol; 30 struct dcerpc_pipe *pipe; 31 32 const char* classname; 33 uint32_t num_subkeys; 34 uint32_t max_subkeylen; 35 uint32_t max_classlen; 36 uint32_t num_values; 37 uint32_t max_valnamelen; 38 uint32_t max_valbufsize; 39 uint32_t secdescsize; 40 NTTIME last_changed_time; 41}; 42 43struct rpc_registry_context { 44 struct registry_context context; 45 struct dcerpc_pipe *pipe; 46}; 47 48static struct registry_operations reg_backend_rpc; 49 50/** 51 * This is the RPC backend for the registry library. 52 */ 53 54#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \ 55{ \ 56 struct winreg_Open ## u r; \ 57 NTSTATUS status; \ 58\ 59 ZERO_STRUCT(r); \ 60 r.in.system_name = NULL; \ 61 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \ 62 r.out.handle = hnd;\ 63\ 64 status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \ 65\ 66 if (!NT_STATUS_IS_OK(status)) { \ 67 DEBUG(1, ("OpenHive failed - %s\n", nt_errstr(status))); \ 68 return ntstatus_to_werror(status); \ 69 } \ 70\ 71 return r.out.result;\ 72} 73 74openhive(HKLM) 75openhive(HKCU) 76openhive(HKPD) 77openhive(HKU) 78openhive(HKCR) 79openhive(HKDD) 80openhive(HKCC) 81 82static struct { 83 uint32_t hkey; 84 WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, 85 struct policy_handle *h); 86} known_hives[] = { 87 { HKEY_LOCAL_MACHINE, open_HKLM }, 88 { HKEY_CURRENT_USER, open_HKCU }, 89 { HKEY_CLASSES_ROOT, open_HKCR }, 90 { HKEY_PERFORMANCE_DATA, open_HKPD }, 91 { HKEY_USERS, open_HKU }, 92 { HKEY_DYN_DATA, open_HKDD }, 93 { HKEY_CURRENT_CONFIG, open_HKCC }, 94 { 0, NULL } 95}; 96 97static WERROR rpc_query_key(TALLOC_CTX *mem_ctx, const struct registry_key *k); 98 99static WERROR rpc_get_predefined_key(struct registry_context *ctx, 100 uint32_t hkey_type, 101 struct registry_key **k) 102{ 103 int n; 104 struct rpc_key *mykeydata; 105 struct rpc_registry_context *rctx = talloc_get_type(ctx, struct rpc_registry_context); 106 107 *k = NULL; 108 109 for(n = 0; known_hives[n].hkey; n++) { 110 if(known_hives[n].hkey == hkey_type) 111 break; 112 } 113 114 if (known_hives[n].open == NULL) { 115 DEBUG(1, ("No such hive %d\n", hkey_type)); 116 return WERR_NO_MORE_ITEMS; 117 } 118 119 mykeydata = talloc_zero(ctx, struct rpc_key); 120 mykeydata->key.context = ctx; 121 mykeydata->pipe = talloc_reference(mykeydata, rctx->pipe); 122 mykeydata->num_values = -1; 123 mykeydata->num_subkeys = -1; 124 *k = (struct registry_key *)mykeydata; 125 return known_hives[n].open(mykeydata->pipe, mykeydata, &(mykeydata->pol)); 126} 127 128#if 0 129static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) 130{ 131 struct winreg_OpenKey r; 132 struct rpc_key_data *mykeydata; 133 134 k->backend_data = mykeydata = talloc_zero(mem_ctx, struct rpc_key_data); 135 mykeydata->num_values = -1; 136 mykeydata->num_subkeys = -1; 137 138 /* Then, open the handle using the hive */ 139 140 ZERO_STRUCT(r); 141 r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol); 142 r.in.keyname.name = k->path; 143 r.in.unknown = 0x00000000; 144 r.in.access_mask = 0x02000000; 145 r.out.handle = &mykeydata->pol; 146 147 dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, 148 mem_ctx, &r); 149 150 return r.out.result; 151} 152#endif 153 154static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, 155 const char *name, struct registry_key **key) 156{ 157 struct rpc_key *parentkeydata = talloc_get_type(h, struct rpc_key), 158 *mykeydata; 159 struct winreg_OpenKey r; 160 NTSTATUS status; 161 162 mykeydata = talloc_zero(mem_ctx, struct rpc_key); 163 mykeydata->key.context = parentkeydata->key.context; 164 mykeydata->pipe = talloc_reference(mykeydata, parentkeydata->pipe); 165 mykeydata->num_values = -1; 166 mykeydata->num_subkeys = -1; 167 *key = (struct registry_key *)mykeydata; 168 169 /* Then, open the handle using the hive */ 170 ZERO_STRUCT(r); 171 r.in.parent_handle = &parentkeydata->pol; 172 r.in.keyname.name = name; 173 r.in.unknown = 0x00000000; 174 r.in.access_mask = 0x02000000; 175 r.out.handle = &mykeydata->pol; 176 177 status = dcerpc_winreg_OpenKey(mykeydata->pipe, mem_ctx, &r); 178 179 if (!NT_STATUS_IS_OK(status)) { 180 DEBUG(1, ("OpenKey failed - %s\n", nt_errstr(status))); 181 return ntstatus_to_werror(status); 182 } 183 184 return r.out.result; 185} 186 187static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, 188 const struct registry_key *parent, 189 uint32_t n, 190 const char **value_name, 191 uint32_t *type, 192 DATA_BLOB *data) 193{ 194 struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key); 195 struct winreg_EnumValue r; 196 struct winreg_ValNameBuf name; 197 uint8_t value; 198 uint32_t val_size = MAX_VALSIZE; 199 uint32_t zero = 0; 200 WERROR error; 201 NTSTATUS status; 202 203 if (mykeydata->num_values == -1) { 204 error = rpc_query_key(mem_ctx, parent); 205 if(!W_ERROR_IS_OK(error)) return error; 206 } 207 208 name.name = ""; 209 name.size = MAX_NAMESIZE; 210 211 ZERO_STRUCT(r); 212 r.in.handle = &mykeydata->pol; 213 r.in.enum_index = n; 214 r.in.name = &name; 215 r.in.type = type; 216 r.in.value = &value; 217 r.in.size = &val_size; 218 r.in.length = &zero; 219 r.out.name = &name; 220 r.out.type = type; 221 r.out.value = &value; 222 r.out.size = &val_size; 223 r.out.length = &zero; 224 225 status = dcerpc_winreg_EnumValue(mykeydata->pipe, mem_ctx, &r); 226 227 if (!NT_STATUS_IS_OK(status)) { 228 DEBUG(1, ("EnumValue failed - %s\n", nt_errstr(status))); 229 return ntstatus_to_werror(status); 230 } 231 232 *value_name = talloc_reference(mem_ctx, r.out.name->name); 233 *type = *(r.out.type); 234 *data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length); 235 236 return r.out.result; 237} 238 239static WERROR rpc_get_value_by_name(TALLOC_CTX *mem_ctx, 240 const struct registry_key *parent, 241 const char *value_name, 242 uint32_t *type, 243 DATA_BLOB *data) 244{ 245 struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key); 246 struct winreg_QueryValue r; 247 struct winreg_String name; 248 uint8_t value; 249 uint32_t val_size = MAX_VALSIZE; 250 uint32_t zero = 0; 251 WERROR error; 252 NTSTATUS status; 253 254 if (mykeydata->num_values == -1) { 255 error = rpc_query_key(mem_ctx, parent); 256 if(!W_ERROR_IS_OK(error)) return error; 257 } 258 259 name.name = value_name; 260 261 ZERO_STRUCT(r); 262 r.in.handle = &mykeydata->pol; 263 r.in.value_name = &name; 264 r.in.type = type; 265 r.in.data = &value; 266 r.in.data_size = &val_size; 267 r.in.data_length = &zero; 268 r.out.type = type; 269 r.out.data = &value; 270 r.out.data_size = &val_size; 271 r.out.data_length = &zero; 272 273 status = dcerpc_winreg_QueryValue(mykeydata->pipe, mem_ctx, &r); 274 275 if (!NT_STATUS_IS_OK(status)) { 276 DEBUG(1, ("QueryValue failed - %s\n", nt_errstr(status))); 277 return ntstatus_to_werror(status); 278 } 279 280 *type = *(r.out.type); 281 *data = data_blob_talloc(mem_ctx, r.out.data, *r.out.data_length); 282 283 return r.out.result; 284} 285 286static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, 287 const struct registry_key *parent, 288 uint32_t n, 289 const char **name, 290 const char **keyclass, 291 NTTIME *last_changed_time) 292{ 293 struct winreg_EnumKey r; 294 struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key); 295 struct winreg_StringBuf namebuf, classbuf; 296 NTTIME change_time = 0; 297 NTSTATUS status; 298 299 namebuf.name = ""; 300 namebuf.size = MAX_NAMESIZE; 301 classbuf.name = NULL; 302 classbuf.size = 0; 303 304 ZERO_STRUCT(r); 305 r.in.handle = &mykeydata->pol; 306 r.in.enum_index = n; 307 r.in.name = &namebuf; 308 r.in.keyclass = &classbuf; 309 r.in.last_changed_time = &change_time; 310 r.out.name = &namebuf; 311 r.out.keyclass = &classbuf; 312 r.out.last_changed_time = &change_time; 313 314 status = dcerpc_winreg_EnumKey(mykeydata->pipe, mem_ctx, &r); 315 316 if (!NT_STATUS_IS_OK(status)) { 317 DEBUG(1, ("EnumKey failed - %s\n", nt_errstr(status))); 318 return ntstatus_to_werror(status); 319 } 320 321 if (name != NULL) 322 *name = talloc_reference(mem_ctx, r.out.name->name); 323 if (keyclass != NULL) 324 *keyclass = talloc_reference(mem_ctx, r.out.keyclass->name); 325 if (last_changed_time != NULL) 326 *last_changed_time = *(r.out.last_changed_time); 327 328 return r.out.result; 329} 330 331static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, 332 struct registry_key *parent, const char *name, 333 const char *key_class, 334 struct security_descriptor *sec, 335 struct registry_key **key) 336{ 337 struct winreg_CreateKey r; 338 struct rpc_key *parentkd = talloc_get_type(parent, struct rpc_key); 339 struct rpc_key *rpck = talloc(mem_ctx, struct rpc_key); 340 341 NTSTATUS status; 342 343 ZERO_STRUCT(r); 344 r.in.handle = &parentkd->pol; 345 r.in.name.name = name; 346 r.in.keyclass.name = NULL; 347 r.in.options = 0; 348 r.in.access_mask = 0x02000000; 349 r.in.secdesc = NULL; 350 r.in.action_taken = NULL; 351 r.out.new_handle = &rpck->pol; 352 r.out.action_taken = NULL; 353 354 status = dcerpc_winreg_CreateKey(parentkd->pipe, mem_ctx, &r); 355 356 if (!NT_STATUS_IS_OK(status)) { 357 talloc_free(rpck); 358 DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status))); 359 return ntstatus_to_werror(status); 360 } 361 362 rpck->pipe = talloc_reference(rpck, parentkd->pipe); 363 *key = (struct registry_key *)rpck; 364 365 return r.out.result; 366} 367 368static WERROR rpc_query_key(TALLOC_CTX *mem_ctx, const struct registry_key *k) 369{ 370 struct winreg_QueryInfoKey r; 371 struct rpc_key *mykeydata = talloc_get_type(k, struct rpc_key); 372 struct winreg_String classname; 373 NTSTATUS status; 374 375 classname.name = NULL; 376 377 ZERO_STRUCT(r); 378 r.in.handle = &mykeydata->pol; 379 r.in.classname = &classname; 380 r.out.classname = &classname; 381 r.out.num_subkeys = &mykeydata->num_subkeys; 382 r.out.max_subkeylen = &mykeydata->max_subkeylen; 383 r.out.max_classlen = &mykeydata->max_classlen; 384 r.out.num_values = &mykeydata->num_values; 385 r.out.max_valnamelen = &mykeydata->max_valnamelen; 386 r.out.max_valbufsize = &mykeydata->max_valbufsize; 387 r.out.secdescsize = &mykeydata->secdescsize; 388 r.out.last_changed_time = &mykeydata->last_changed_time; 389 390 status = dcerpc_winreg_QueryInfoKey(mykeydata->pipe, mem_ctx, &r); 391 392 if (!NT_STATUS_IS_OK(status)) { 393 DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status))); 394 return ntstatus_to_werror(status); 395 } 396 397 mykeydata->classname = talloc_reference(mem_ctx, r.out.classname->name); 398 399 return r.out.result; 400} 401 402static WERROR rpc_del_key(struct registry_key *parent, const char *name) 403{ 404 NTSTATUS status; 405 struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key); 406 struct winreg_DeleteKey r; 407 TALLOC_CTX *mem_ctx = talloc_init("del_key"); 408 409 ZERO_STRUCT(r); 410 r.in.handle = &mykeydata->pol; 411 r.in.key.name = name; 412 413 status = dcerpc_winreg_DeleteKey(mykeydata->pipe, mem_ctx, &r); 414 415 talloc_free(mem_ctx); 416 417 if (!NT_STATUS_IS_OK(status)) { 418 DEBUG(1, ("DeleteKey failed - %s\n", nt_errstr(status))); 419 return ntstatus_to_werror(status); 420 } 421 422 return r.out.result; 423} 424 425static WERROR rpc_get_info(TALLOC_CTX *mem_ctx, const struct registry_key *key, 426 const char **classname, 427 uint32_t *num_subkeys, 428 uint32_t *num_values, 429 NTTIME *last_changed_time, 430 uint32_t *max_subkeylen, 431 uint32_t *max_valnamelen, 432 uint32_t *max_valbufsize) 433{ 434 struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key); 435 WERROR error; 436 437 if (mykeydata->num_values == -1) { 438 error = rpc_query_key(mem_ctx, key); 439 if(!W_ERROR_IS_OK(error)) return error; 440 } 441 442 if (classname != NULL) 443 *classname = mykeydata->classname; 444 445 if (num_subkeys != NULL) 446 *num_subkeys = mykeydata->num_subkeys; 447 448 if (num_values != NULL) 449 *num_values = mykeydata->num_values; 450 451 if (last_changed_time != NULL) 452 *last_changed_time = mykeydata->last_changed_time; 453 454 if (max_subkeylen != NULL) 455 *max_subkeylen = mykeydata->max_subkeylen; 456 457 if (max_valnamelen != NULL) 458 *max_valnamelen = mykeydata->max_valnamelen; 459 460 if (max_valbufsize != NULL) 461 *max_valbufsize = mykeydata->max_valbufsize; 462 463 return WERR_OK; 464} 465 466static struct registry_operations reg_backend_rpc = { 467 .name = "rpc", 468 .open_key = rpc_open_key, 469 .get_predefined_key = rpc_get_predefined_key, 470 .enum_key = rpc_get_subkey_by_index, 471 .enum_value = rpc_get_value_by_index, 472 .get_value = rpc_get_value_by_name, 473 .create_key = rpc_add_key, 474 .delete_key = rpc_del_key, 475 .get_key_info = rpc_get_info, 476 .get_predefined_key = rpc_get_predefined_key, 477}; 478 479_PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx, 480 struct auth_session_info *session_info, 481 struct cli_credentials *credentials, 482 struct loadparm_context *lp_ctx, 483 const char *location, struct tevent_context *ev) 484{ 485 NTSTATUS status; 486 struct dcerpc_pipe *p; 487 struct rpc_registry_context *rctx; 488 489 dcerpc_init(lp_ctx); 490 491 rctx = talloc(NULL, struct rpc_registry_context); 492 493 /* Default to local smbd if no connection is specified */ 494 if (!location) { 495 location = talloc_strdup(rctx, "ncalrpc:"); 496 } 497 498 status = dcerpc_pipe_connect(rctx /* TALLOC_CTX */, 499 &p, location, 500 &ndr_table_winreg, 501 credentials, ev, lp_ctx); 502 rctx->pipe = p; 503 504 if(NT_STATUS_IS_ERR(status)) { 505 DEBUG(1, ("Unable to open '%s': %s\n", location, 506 nt_errstr(status))); 507 talloc_free(rctx); 508 *ctx = NULL; 509 return ntstatus_to_werror(status); 510 } 511 512 *ctx = (struct registry_context *)rctx; 513 (*ctx)->ops = ®_backend_rpc; 514 515 return WERR_OK; 516} 517