1/* 2 Unix SMB/CIFS implementation. 3 4 endpoint server for the winreg pipe 5 6 Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org 7 Copyright (C) 2008 Matthias Dieter Walln��fer, mwallnoefer@yahoo.de 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21*/ 22 23#include "includes.h" 24#include "rpc_server/dcerpc_server.h" 25#include "lib/registry/registry.h" 26#include "librpc/gen_ndr/ndr_winreg.h" 27#include "librpc/gen_ndr/ndr_security.h" 28#include "libcli/security/security.h" 29 30enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY }; 31 32static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call, 33 const struct dcesrv_interface *iface) 34{ 35 struct registry_context *ctx; 36 WERROR err; 37 38 err = reg_open_samba(dce_call->context, 39 &ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, 40 NULL); 41 42 if (!W_ERROR_IS_OK(err)) { 43 DEBUG(0, ("Error opening registry: %s\n", win_errstr(err))); 44 return NT_STATUS_UNSUCCESSFUL; 45 } 46 47 dce_call->context->private_data = ctx; 48 49 return NT_STATUS_OK; 50} 51 52#define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind 53 54static WERROR dcesrv_winreg_openhive(struct dcesrv_call_state *dce_call, 55 TALLOC_CTX *mem_ctx, uint32_t hkey, 56 struct policy_handle **outh) 57{ 58 struct registry_context *ctx = dce_call->context->private_data; 59 struct dcesrv_handle *h; 60 WERROR result; 61 62 h = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY); 63 64 result = reg_get_predefined_key(ctx, hkey, 65 (struct registry_key **)&h->data); 66 if (!W_ERROR_IS_OK(result)) { 67 return result; 68 } 69 *outh = &h->wire_handle; 70 71 return result; 72} 73 74#define func_winreg_OpenHive(k,n) static WERROR dcesrv_winreg_Open ## k (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_Open ## k *r) \ 75{ \ 76 return dcesrv_winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\ 77} 78 79func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT) 80func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER) 81func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE) 82func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA) 83func_winreg_OpenHive(HKU,HKEY_USERS) 84func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG) 85func_winreg_OpenHive(HKDD,HKEY_DYN_DATA) 86func_winreg_OpenHive(HKPT,HKEY_PERFORMANCE_TEXT) 87func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT) 88 89/* 90 winreg_CloseKey 91*/ 92static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call, 93 TALLOC_CTX *mem_ctx, 94 struct winreg_CloseKey *r) 95{ 96 struct dcesrv_handle *h; 97 98 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 99 100 talloc_free(h); 101 102 ZERO_STRUCTP(r->out.handle); 103 104 return WERR_OK; 105} 106 107/* 108 winreg_CreateKey 109*/ 110static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call, 111 TALLOC_CTX *mem_ctx, 112 struct winreg_CreateKey *r) 113{ 114 struct dcesrv_handle *h, *newh; 115 struct security_descriptor sd; 116 struct registry_key *key; 117 WERROR result; 118 119 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 120 key = h->data; 121 122 newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY); 123 124 switch (security_session_user_level(dce_call->conn->auth_state.session_info)) 125 { 126 case SECURITY_SYSTEM: 127 case SECURITY_ADMINISTRATOR: 128 /* the security descriptor is optional */ 129 if (r->in.secdesc != NULL) { 130 DATA_BLOB sdblob; 131 enum ndr_err_code ndr_err; 132 sdblob.data = r->in.secdesc->sd.data; 133 sdblob.length = r->in.secdesc->sd.len; 134 if (sdblob.data == NULL) { 135 return WERR_INVALID_PARAM; 136 } 137 ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd, 138 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); 139 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 140 return WERR_INVALID_PARAM; 141 } 142 } 143 144 result = reg_key_add_name(newh, key, r->in.name.name, NULL, 145 r->in.secdesc?&sd:NULL, (struct registry_key **)&newh->data); 146 if (W_ERROR_IS_OK(result)) { 147 r->out.new_handle = &newh->wire_handle; 148 } else { 149 talloc_free(newh); 150 } 151 152 return result; 153 default: 154 return WERR_ACCESS_DENIED; 155 } 156} 157 158 159/* 160 winreg_DeleteKey 161*/ 162static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call, 163 TALLOC_CTX *mem_ctx, 164 struct winreg_DeleteKey *r) 165{ 166 struct dcesrv_handle *h; 167 struct registry_key *key; 168 169 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 170 key = h->data; 171 172 switch (security_session_user_level(dce_call->conn->auth_state.session_info)) 173 { 174 case SECURITY_SYSTEM: 175 case SECURITY_ADMINISTRATOR: 176 return reg_key_del(key, r->in.key.name); 177 default: 178 return WERR_ACCESS_DENIED; 179 } 180} 181 182 183/* 184 winreg_DeleteValue 185*/ 186static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call, 187 TALLOC_CTX *mem_ctx, 188 struct winreg_DeleteValue *r) 189{ 190 struct dcesrv_handle *h; 191 struct registry_key *key; 192 193 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 194 key = h->data; 195 196 switch (security_session_user_level(dce_call->conn->auth_state.session_info)) 197 { 198 case SECURITY_SYSTEM: 199 case SECURITY_ADMINISTRATOR: 200 return reg_del_value(key, r->in.value.name); 201 default: 202 return WERR_ACCESS_DENIED; 203 } 204} 205 206 207/* 208 winreg_EnumKey 209*/ 210static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call, 211 TALLOC_CTX *mem_ctx, 212 struct winreg_EnumKey *r) 213{ 214 struct dcesrv_handle *h; 215 struct registry_key *key; 216 const char *name, *classname; 217 NTTIME last_mod; 218 WERROR result; 219 220 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 221 key = h->data; 222 223 result = reg_key_get_subkey_by_index(mem_ctx, 224 key, r->in.enum_index, &name, &classname, &last_mod); 225 226 if (2*strlen_m_term(name) > r->in.name->size) { 227 return WERR_MORE_DATA; 228 } 229 230 if (name != NULL) { 231 r->out.name->name = name; 232 r->out.name->length = 2*strlen_m_term(name); 233 } else { 234 r->out.name->name = r->in.name->name; 235 r->out.name->length = r->in.name->length; 236 } 237 r->out.name->size = r->in.name->size; 238 239 r->out.keyclass = r->in.keyclass; 240 if (classname != NULL) { 241 r->out.keyclass->name = classname; 242 r->out.keyclass->length = 2*strlen_m_term(classname); 243 } else { 244 r->out.keyclass->name = r->in.keyclass->name; 245 r->out.keyclass->length = r->in.keyclass->length; 246 } 247 r->out.keyclass->size = r->in.keyclass->size; 248 249 if (r->in.last_changed_time != NULL) 250 r->out.last_changed_time = &last_mod; 251 252 return result; 253} 254 255 256/* 257 winreg_EnumValue 258*/ 259static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call, 260 TALLOC_CTX *mem_ctx, 261 struct winreg_EnumValue *r) 262{ 263 struct dcesrv_handle *h; 264 struct registry_key *key; 265 const char *data_name; 266 uint32_t data_type; 267 DATA_BLOB data; 268 WERROR result; 269 270 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 271 key = h->data; 272 273 result = reg_key_get_value_by_index(mem_ctx, key, 274 r->in.enum_index, &data_name, &data_type, &data); 275 276 if (!W_ERROR_IS_OK(result)) { 277 /* if the lookup wasn't successful, send client query back */ 278 data_name = r->in.name->name; 279 data_type = *r->in.type; 280 data.data = r->in.value; 281 data.length = *r->in.length; 282 } 283 284 /* check if there is enough room for the name */ 285 if (r->in.name->size < 2*strlen_m_term(data_name)) { 286 return WERR_MORE_DATA; 287 } 288 289 /* "data_name" is NULL when we query the default attribute */ 290 if (data_name != NULL) { 291 r->out.name->name = data_name; 292 r->out.name->length = 2*strlen_m_term(data_name); 293 } else { 294 r->out.name->name = r->in.name->name; 295 r->out.name->length = r->in.name->length; 296 } 297 r->out.name->size = r->in.name->size; 298 299 r->out.type = talloc(mem_ctx, uint32_t); 300 if (!r->out.type) { 301 return WERR_NOMEM; 302 } 303 *r->out.type = data_type; 304 305 /* check the client has enough room for the value */ 306 if (r->in.value != NULL && 307 r->in.size != NULL && 308 data.length > *r->in.size) { 309 return WERR_MORE_DATA; 310 } 311 312 if (r->in.value != NULL) { 313 r->out.value = data.data; 314 } 315 316 if (r->in.size != NULL) { 317 r->out.size = talloc(mem_ctx, uint32_t); 318 *r->out.size = data.length; 319 r->out.length = r->out.size; 320 } 321 322 return result; 323} 324 325 326/* 327 winreg_FlushKey 328*/ 329static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call, 330 TALLOC_CTX *mem_ctx, 331 struct winreg_FlushKey *r) 332{ 333 struct dcesrv_handle *h; 334 struct registry_key *key; 335 336 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 337 key = h->data; 338 339 switch (security_session_user_level(dce_call->conn->auth_state.session_info)) 340 { 341 case SECURITY_SYSTEM: 342 case SECURITY_ADMINISTRATOR: 343 return reg_key_flush(key); 344 default: 345 return WERR_ACCESS_DENIED; 346 } 347} 348 349 350/* 351 winreg_GetKeySecurity 352*/ 353static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call, 354 TALLOC_CTX *mem_ctx, 355 struct winreg_GetKeySecurity *r) 356{ 357 struct dcesrv_handle *h; 358 359 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 360 361 return WERR_NOT_SUPPORTED; 362} 363 364 365/* 366 winreg_LoadKey 367*/ 368static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call, 369 TALLOC_CTX *mem_ctx, 370 struct winreg_LoadKey *r) 371{ 372 return WERR_NOT_SUPPORTED; 373} 374 375 376/* 377 winreg_NotifyChangeKeyValue 378*/ 379static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call, 380 TALLOC_CTX *mem_ctx, 381 struct winreg_NotifyChangeKeyValue *r) 382{ 383 return WERR_NOT_SUPPORTED; 384} 385 386 387/* 388 winreg_OpenKey 389*/ 390static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call, 391 TALLOC_CTX *mem_ctx, 392 struct winreg_OpenKey *r) 393{ 394 struct dcesrv_handle *h, *newh; 395 struct registry_key *key; 396 WERROR result; 397 398 DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY); 399 key = h->data; 400 401 switch (security_session_user_level(dce_call->conn->auth_state.session_info)) 402 { 403 case SECURITY_SYSTEM: 404 case SECURITY_ADMINISTRATOR: 405 case SECURITY_USER: 406 if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) { 407 newh = talloc_reference(dce_call->context, h); 408 result = WERR_OK; 409 } else { 410 newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY); 411 result = reg_open_key(newh, key, r->in.keyname.name, 412 (struct registry_key **)&newh->data); 413 } 414 415 if (W_ERROR_IS_OK(result)) { 416 r->out.handle = &newh->wire_handle; 417 } else { 418 talloc_free(newh); 419 } 420 return result; 421 default: 422 return WERR_ACCESS_DENIED; 423 } 424 425} 426 427 428/* 429 winreg_QueryInfoKey 430*/ 431static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call, 432 TALLOC_CTX *mem_ctx, 433 struct winreg_QueryInfoKey *r) 434{ 435 struct dcesrv_handle *h; 436 struct registry_key *key; 437 const char *classname = NULL; 438 WERROR result; 439 440 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 441 key = h->data; 442 443 switch (security_session_user_level(dce_call->conn->auth_state.session_info)) 444 { 445 case SECURITY_SYSTEM: 446 case SECURITY_ADMINISTRATOR: 447 case SECURITY_USER: 448 result = reg_key_get_info(mem_ctx, key, &classname, 449 r->out.num_subkeys, r->out.num_values, 450 r->out.last_changed_time, r->out.max_subkeylen, 451 r->out.max_valnamelen, r->out.max_valbufsize); 452 453 if (classname != NULL) { 454 r->out.classname->name = classname; 455 r->out.classname->name_len = 2*strlen_m_term(classname); 456 } else { 457 r->out.classname->name = r->in.classname->name; 458 r->out.classname->name_len = r->in.classname->name_len; 459 } 460 r->out.classname->name_size = r->in.classname->name_size; 461 462 return result; 463 default: 464 return WERR_ACCESS_DENIED; 465 } 466} 467 468 469/* 470 winreg_QueryValue 471*/ 472static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call, 473 TALLOC_CTX *mem_ctx, 474 struct winreg_QueryValue *r) 475{ 476 struct dcesrv_handle *h; 477 struct registry_key *key; 478 uint32_t value_type; 479 DATA_BLOB value_data; 480 WERROR result; 481 482 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 483 key = h->data; 484 485 switch (security_session_user_level(dce_call->conn->auth_state.session_info)) 486 { 487 case SECURITY_SYSTEM: 488 case SECURITY_ADMINISTRATOR: 489 case SECURITY_USER: 490 result = reg_key_get_value_by_name(mem_ctx, key, 491 r->in.value_name->name, &value_type, &value_data); 492 493 if (!W_ERROR_IS_OK(result)) { 494 /* if the lookup wasn't successful, send client query back */ 495 value_type = *r->in.type; 496 value_data.data = r->in.data; 497 value_data.length = *r->in.data_length; 498 } 499 500 r->out.type = talloc(mem_ctx, uint32_t); 501 if (!r->out.type) { 502 return WERR_NOMEM; 503 } 504 *r->out.type = value_type; 505 r->out.data_length = talloc(mem_ctx, uint32_t); 506 if (!r->out.data_length) { 507 return WERR_NOMEM; 508 } 509 *r->out.data_length = value_data.length; 510 r->out.data_size = talloc(mem_ctx, uint32_t); 511 if (!r->out.data_size) { 512 return WERR_NOMEM; 513 } 514 *r->out.data_size = value_data.length; 515 r->out.data = value_data.data; 516 517 return result; 518 default: 519 return WERR_ACCESS_DENIED; 520 } 521} 522 523 524/* 525 winreg_ReplaceKey 526*/ 527static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call, 528 TALLOC_CTX *mem_ctx, 529 struct winreg_ReplaceKey *r) 530{ 531 return WERR_NOT_SUPPORTED; 532} 533 534 535/* 536 winreg_RestoreKey 537*/ 538static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call, 539 TALLOC_CTX *mem_ctx, 540 struct winreg_RestoreKey *r) 541{ 542 return WERR_NOT_SUPPORTED; 543} 544 545 546/* 547 winreg_SaveKey 548*/ 549static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call, 550 TALLOC_CTX *mem_ctx, 551 struct winreg_SaveKey *r) 552{ 553 return WERR_NOT_SUPPORTED; 554} 555 556 557/* 558 winreg_SetKeySecurity 559*/ 560static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call, 561 TALLOC_CTX *mem_ctx, 562 struct winreg_SetKeySecurity *r) 563{ 564 return WERR_NOT_SUPPORTED; 565} 566 567 568/* 569 winreg_SetValue 570*/ 571static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call, 572 TALLOC_CTX *mem_ctx, 573 struct winreg_SetValue *r) 574{ 575 struct dcesrv_handle *h; 576 struct registry_key *key; 577 DATA_BLOB data; 578 WERROR result; 579 580 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 581 key = h->data; 582 583 switch (security_session_user_level(dce_call->conn->auth_state.session_info)) 584 { 585 case SECURITY_SYSTEM: 586 case SECURITY_ADMINISTRATOR: 587 data.data = r->in.data; 588 data.length = r->in.size; 589 result = reg_val_set(key, r->in.name.name, r->in.type, data); 590 return result; 591 default: 592 return WERR_ACCESS_DENIED; 593 } 594} 595 596 597/* 598 winreg_UnLoadKey 599*/ 600static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call, 601 TALLOC_CTX *mem_ctx, 602 struct winreg_UnLoadKey *r) 603{ 604 return WERR_NOT_SUPPORTED; 605} 606 607 608/* 609 winreg_InitiateSystemShutdown 610*/ 611static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call, 612 TALLOC_CTX *mem_ctx, 613 struct winreg_InitiateSystemShutdown *r) 614{ 615 return WERR_NOT_SUPPORTED; 616} 617 618 619/* 620 winreg_AbortSystemShutdown 621*/ 622static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call, 623 TALLOC_CTX *mem_ctx, 624 struct winreg_AbortSystemShutdown *r) 625{ 626 return WERR_NOT_SUPPORTED; 627} 628 629 630/* 631 winreg_GetVersion 632*/ 633static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call, 634 TALLOC_CTX *mem_ctx, 635 struct winreg_GetVersion *r) 636{ 637 struct dcesrv_handle *h; 638 639 DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); 640 641 r->out.version = talloc(mem_ctx, uint32_t); 642 W_ERROR_HAVE_NO_MEMORY(r->out.version); 643 644 *r->out.version = 5; 645 646 return WERR_OK; 647} 648 649 650/* 651 winreg_QueryMultipleValues 652*/ 653static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call, 654 TALLOC_CTX *mem_ctx, 655 struct winreg_QueryMultipleValues *r) 656{ 657 return WERR_NOT_SUPPORTED; 658} 659 660 661/* 662 winreg_InitiateSystemShutdownEx 663*/ 664static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call, 665 TALLOC_CTX *mem_ctx, 666 struct winreg_InitiateSystemShutdownEx *r) 667{ 668 return WERR_NOT_SUPPORTED; 669} 670 671 672/* 673 winreg_SaveKeyEx 674*/ 675static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call, 676 TALLOC_CTX *mem_ctx, 677 struct winreg_SaveKeyEx *r) 678{ 679 return WERR_NOT_SUPPORTED; 680} 681 682 683/* 684 winreg_QueryMultipleValues2 685*/ 686static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call, 687 TALLOC_CTX *mem_ctx, 688 struct winreg_QueryMultipleValues2 *r) 689{ 690 return WERR_NOT_SUPPORTED; 691} 692 693 694/* include the generated boilerplate */ 695#include "librpc/gen_ndr/ndr_winreg_s.c" 696