1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Windows Registry RPC (WINREG) server-side interface. 28 * 29 * The WINREG RPC interface returns Win32 error codes. 30 * 31 * HKLM Hive Key Local Machine 32 * HKU Hive Key Users 33 */ 34 35 #include <sys/utsname.h> 36 #include <strings.h> 37 38 #include <smbsrv/libsmb.h> 39 #include <smbsrv/ntstatus.h> 40 #include <smbsrv/nterror.h> 41 #include <smbsrv/nmpipes.h> 42 #include <smbsrv/libmlsvc.h> 43 #include <smbsrv/ndl/winreg.ndl> 44 45 #define WINREG_LOGR_SYSTEMKEY \ 46 "System\\CurrentControlSet\\Services\\Eventlog\\System" 47 48 /* 49 * Local handle management keys. 50 */ 51 static int winreg_hk; 52 static int winreg_hklm; 53 static int winreg_hkuser; 54 static int winreg_hkkey; 55 56 /* 57 * List of supported registry keys (case-insensitive). 58 */ 59 static char *winreg_keys[] = { 60 "System\\CurrentControlSet\\Services\\Eventlog", 61 "System\\CurrentControlSet\\Services\\Eventlog\\System", 62 "System\\CurrentControlSet\\Control\\ProductOptions", 63 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" 64 }; 65 66 typedef struct winreg_subkey { 67 list_node_t sk_lnd; 68 ndr_hdid_t sk_handle; 69 char sk_name[MAXPATHLEN]; 70 boolean_t sk_predefined; 71 } winreg_subkey_t; 72 73 typedef struct winreg_keylist { 74 list_t kl_list; 75 int kl_count; 76 } winreg_keylist_t; 77 78 static winreg_keylist_t winreg_keylist; 79 80 static boolean_t winreg_key_has_subkey(const char *); 81 static char *winreg_lookup_value(const char *); 82 static char *winreg_lookup_eventlog_registry(char *, char *); 83 84 static int winreg_s_OpenHK(void *, ndr_xa_t *); 85 static int winreg_s_OpenHKLM(void *, ndr_xa_t *); 86 static int winreg_s_OpenHKUsers(void *, ndr_xa_t *); 87 static int winreg_s_Close(void *, ndr_xa_t *); 88 static int winreg_s_CreateKey(void *, ndr_xa_t *); 89 static int winreg_s_DeleteKey(void *, ndr_xa_t *); 90 static int winreg_s_DeleteValue(void *, ndr_xa_t *); 91 static int winreg_s_EnumKey(void *, ndr_xa_t *); 92 static int winreg_s_EnumValue(void *, ndr_xa_t *); 93 static int winreg_s_FlushKey(void *, ndr_xa_t *); 94 static int winreg_s_GetKeySec(void *, ndr_xa_t *); 95 static int winreg_s_NotifyChange(void *, ndr_xa_t *); 96 static int winreg_s_OpenKey(void *, ndr_xa_t *); 97 static int winreg_s_QueryKey(void *, ndr_xa_t *); 98 static int winreg_s_QueryValue(void *, ndr_xa_t *); 99 static int winreg_s_SetKeySec(void *, ndr_xa_t *); 100 static int winreg_s_CreateValue(void *, ndr_xa_t *); 101 static int winreg_s_Shutdown(void *, ndr_xa_t *); 102 static int winreg_s_AbortShutdown(void *, ndr_xa_t *); 103 static int winreg_s_GetVersion(void *, ndr_xa_t *); 104 105 static ndr_stub_table_t winreg_stub_table[] = { 106 { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCR }, 107 { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCU }, 108 { winreg_s_OpenHKLM, WINREG_OPNUM_OpenHKLM }, 109 { winreg_s_OpenHK, WINREG_OPNUM_OpenHKPD }, 110 { winreg_s_OpenHKUsers, WINREG_OPNUM_OpenHKUsers }, 111 { winreg_s_Close, WINREG_OPNUM_Close }, 112 { winreg_s_CreateKey, WINREG_OPNUM_CreateKey }, 113 { winreg_s_DeleteKey, WINREG_OPNUM_DeleteKey }, 114 { winreg_s_DeleteValue, WINREG_OPNUM_DeleteValue }, 115 { winreg_s_EnumKey, WINREG_OPNUM_EnumKey }, 116 { winreg_s_EnumValue, WINREG_OPNUM_EnumValue }, 117 { winreg_s_FlushKey, WINREG_OPNUM_FlushKey }, 118 { winreg_s_GetKeySec, WINREG_OPNUM_GetKeySec }, 119 { winreg_s_NotifyChange, WINREG_OPNUM_NotifyChange }, 120 { winreg_s_OpenKey, WINREG_OPNUM_OpenKey }, 121 { winreg_s_QueryKey, WINREG_OPNUM_QueryKey }, 122 { winreg_s_QueryValue, WINREG_OPNUM_QueryValue }, 123 { winreg_s_SetKeySec, WINREG_OPNUM_SetKeySec }, 124 { winreg_s_CreateValue, WINREG_OPNUM_CreateValue }, 125 { winreg_s_Shutdown, WINREG_OPNUM_Shutdown }, 126 { winreg_s_AbortShutdown, WINREG_OPNUM_AbortShutdown }, 127 { winreg_s_GetVersion, WINREG_OPNUM_GetVersion }, 128 { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCC }, 129 { winreg_s_OpenHK, WINREG_OPNUM_OpenHKDD }, 130 { winreg_s_OpenHK, WINREG_OPNUM_OpenHKPT }, 131 { winreg_s_OpenHK, WINREG_OPNUM_OpenHKPN }, 132 {0} 133 }; 134 135 static ndr_service_t winreg_service = { 136 "Winreg", /* name */ 137 "Windows Registry", /* desc */ 138 "\\winreg", /* endpoint */ 139 PIPE_WINREG, /* sec_addr_port */ 140 "338cd001-2244-31f1-aaaa-900038001003", 1, /* abstract */ 141 NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ 142 0, /* no bind_instance_size */ 143 0, /* no bind_req() */ 144 0, /* no unbind_and_close() */ 145 0, /* use generic_call_stub() */ 146 &TYPEINFO(winreg_interface), /* interface ti */ 147 winreg_stub_table /* stub_table */ 148 }; 149 150 static char winreg_sysname[SYS_NMLN]; 151 152 /* 153 * winreg_initialize 154 * 155 * Initialize and register the WINREG RPC interface with the RPC runtime 156 * library. It must be called in order to use either the client side 157 * or the server side functions. 158 */ 159 void 160 winreg_initialize(void) 161 { 162 winreg_subkey_t *key; 163 struct utsname name; 164 char *sysname; 165 int i; 166 167 list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t), 168 offsetof(winreg_subkey_t, sk_lnd)); 169 winreg_keylist.kl_count = 0; 170 171 for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) { 172 if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) { 173 bzero(key, sizeof (winreg_subkey_t)); 174 (void) strlcpy(key->sk_name, winreg_keys[i], 175 MAXPATHLEN); 176 key->sk_predefined = B_TRUE; 177 list_insert_tail(&winreg_keylist.kl_list, key); 178 ++winreg_keylist.kl_count; 179 } 180 } 181 182 if (uname(&name) < 0) 183 sysname = "Solaris"; 184 else 185 sysname = name.sysname; 186 187 (void) strlcpy(winreg_sysname, sysname, SYS_NMLN); 188 (void) ndr_svc_register(&winreg_service); 189 } 190 191 /* 192 * winreg_s_OpenHK 193 * 194 * Stub. 195 */ 196 static int 197 winreg_s_OpenHK(void *arg, ndr_xa_t *mxa) 198 { 199 struct winreg_OpenHKCR *param = arg; 200 ndr_hdid_t *id; 201 202 if ((id = ndr_hdalloc(mxa, &winreg_hk)) == NULL) { 203 bzero(¶m->handle, sizeof (winreg_handle_t)); 204 param->status = ERROR_ACCESS_DENIED; 205 } else { 206 bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); 207 param->status = ERROR_SUCCESS; 208 } 209 210 return (NDR_DRC_OK); 211 } 212 213 /* 214 * winreg_s_OpenHKLM 215 * 216 * This is a request to open the HKLM and get a handle. 217 * The client should treat the handle as an opaque object. 218 * 219 * Status: 220 * ERROR_SUCCESS Valid handle returned. 221 * ERROR_ACCESS_DENIED Unable to allocate a handle. 222 */ 223 static int 224 winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa) 225 { 226 struct winreg_OpenHKLM *param = arg; 227 ndr_hdid_t *id; 228 229 if ((id = ndr_hdalloc(mxa, &winreg_hklm)) == NULL) { 230 bzero(¶m->handle, sizeof (winreg_handle_t)); 231 param->status = ERROR_ACCESS_DENIED; 232 } else { 233 bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); 234 param->status = ERROR_SUCCESS; 235 } 236 237 return (NDR_DRC_OK); 238 } 239 240 /* 241 * winreg_s_OpenHKUsers 242 * 243 * This is a request to get a HKUsers handle. I'm not sure we are 244 * ready to fully support this interface yet, mostly due to the need 245 * to support subsequent requests, but we may support enough now. It 246 * seems okay with regedt32. 247 */ 248 static int 249 winreg_s_OpenHKUsers(void *arg, ndr_xa_t *mxa) 250 { 251 struct winreg_OpenHKUsers *param = arg; 252 ndr_hdid_t *id; 253 254 if ((id = ndr_hdalloc(mxa, &winreg_hkuser)) == NULL) { 255 bzero(¶m->handle, sizeof (winreg_handle_t)); 256 param->status = ERROR_ACCESS_DENIED; 257 } else { 258 bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); 259 param->status = ERROR_SUCCESS; 260 } 261 262 return (NDR_DRC_OK); 263 } 264 265 /* 266 * winreg_s_Close 267 * 268 * This is a request to close the WINREG interface specified by the 269 * handle. We don't track handles (yet), so just zero out the handle 270 * and return NDR_DRC_OK. Setting the handle to zero appears to be 271 * standard behaviour. 272 */ 273 static int 274 winreg_s_Close(void *arg, ndr_xa_t *mxa) 275 { 276 struct winreg_Close *param = arg; 277 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 278 279 ndr_hdfree(mxa, id); 280 281 bzero(¶m->result_handle, sizeof (winreg_handle_t)); 282 param->status = ERROR_SUCCESS; 283 return (NDR_DRC_OK); 284 } 285 286 /* 287 * winreg_s_CreateKey 288 */ 289 static int 290 winreg_s_CreateKey(void *arg, ndr_xa_t *mxa) 291 { 292 struct winreg_CreateKey *param = arg; 293 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 294 ndr_handle_t *hd; 295 winreg_subkey_t *key; 296 char *subkey; 297 DWORD *action; 298 299 subkey = (char *)param->subkey.str; 300 301 if (!ndr_is_admin(mxa) || (subkey == NULL)) { 302 bzero(param, sizeof (struct winreg_CreateKey)); 303 param->status = ERROR_ACCESS_DENIED; 304 return (NDR_DRC_OK); 305 } 306 307 hd = ndr_hdlookup(mxa, id); 308 if (hd == NULL) { 309 bzero(param, sizeof (struct winreg_CreateKey)); 310 param->status = ERROR_INVALID_HANDLE; 311 return (NDR_DRC_OK); 312 } 313 314 if ((action = NDR_NEW(mxa, DWORD)) == NULL) { 315 bzero(param, sizeof (struct winreg_CreateKey)); 316 param->status = ERROR_NOT_ENOUGH_MEMORY; 317 return (NDR_DRC_OK); 318 } 319 320 if (list_is_empty(&winreg_keylist.kl_list)) 321 goto new_key; 322 323 /* 324 * Check for an existing key. 325 */ 326 key = list_head(&winreg_keylist.kl_list); 327 do { 328 if (strcasecmp(subkey, key->sk_name) == 0) { 329 bcopy(&key->sk_handle, ¶m->result_handle, 330 sizeof (winreg_handle_t)); 331 *action = WINREG_ACTION_EXISTING_KEY; 332 param->action = action; 333 param->status = ERROR_SUCCESS; 334 return (NDR_DRC_OK); 335 } 336 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 337 338 new_key: 339 /* 340 * Create a new key. 341 */ 342 id = ndr_hdalloc(mxa, &winreg_hkkey); 343 key = malloc(sizeof (winreg_subkey_t)); 344 345 if ((id == NULL) || (key == NULL)) { 346 bzero(param, sizeof (struct winreg_CreateKey)); 347 param->status = ERROR_NOT_ENOUGH_MEMORY; 348 return (NDR_DRC_OK); 349 } 350 351 bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t)); 352 (void) strlcpy(key->sk_name, subkey, MAXPATHLEN); 353 key->sk_predefined = B_FALSE; 354 list_insert_tail(&winreg_keylist.kl_list, key); 355 ++winreg_keylist.kl_count; 356 357 bcopy(id, ¶m->result_handle, sizeof (winreg_handle_t)); 358 *action = WINREG_ACTION_NEW_KEY; 359 param->action = action; 360 param->status = ERROR_SUCCESS; 361 return (NDR_DRC_OK); 362 } 363 364 /* 365 * winreg_s_DeleteKey 366 */ 367 static int 368 winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa) 369 { 370 struct winreg_DeleteKey *param = arg; 371 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 372 winreg_subkey_t *key; 373 char *subkey; 374 375 subkey = (char *)param->subkey.str; 376 377 if (!ndr_is_admin(mxa) || (subkey == NULL)) { 378 param->status = ERROR_ACCESS_DENIED; 379 return (NDR_DRC_OK); 380 } 381 382 if ((ndr_hdlookup(mxa, id) == NULL) || 383 list_is_empty(&winreg_keylist.kl_list) || 384 winreg_key_has_subkey(subkey)) { 385 param->status = ERROR_ACCESS_DENIED; 386 return (NDR_DRC_OK); 387 } 388 389 key = list_head(&winreg_keylist.kl_list); 390 do { 391 if (strcasecmp(subkey, key->sk_name) == 0) { 392 if (key->sk_predefined == B_TRUE) { 393 /* Predefined keys cannot be deleted */ 394 break; 395 } 396 397 list_remove(&winreg_keylist.kl_list, key); 398 --winreg_keylist.kl_count; 399 ndr_hdfree(mxa, &key->sk_handle); 400 free(key); 401 param->status = ERROR_SUCCESS; 402 return (NDR_DRC_OK); 403 } 404 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 405 406 param->status = ERROR_ACCESS_DENIED; 407 return (NDR_DRC_OK); 408 } 409 410 static boolean_t 411 winreg_key_has_subkey(const char *subkey) 412 { 413 winreg_subkey_t *key; 414 int keylen; 415 416 if (list_is_empty(&winreg_keylist.kl_list)) 417 return (B_FALSE); 418 419 keylen = strlen(subkey); 420 421 key = list_head(&winreg_keylist.kl_list); 422 do { 423 if (strncasecmp(subkey, key->sk_name, keylen) == 0) { 424 /* 425 * Potential match. If sk_name is longer than 426 * subkey, then sk_name is a subkey of our key. 427 */ 428 if (keylen < strlen(key->sk_name)) 429 return (B_TRUE); 430 } 431 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 432 433 return (B_FALSE); 434 } 435 436 /* 437 * winreg_subkey_get_relative_name 438 * 439 * Each key contains one or more child keys, each called a subkey. 440 * For any specified key, its name MUST be unique for any other subkeys that 441 * have the same parent key. 442 * 443 * To accurately identify a given subkey within the key namespace, its fully 444 * qualified name (FQN) is used. The FQN MUST consist of the name of the subkey 445 * and the name of all of its parent keys all the way to the root of the tree. 446 * 447 * The "\" character MUST be used as a hierarchy separator to identify each key 448 * in the FQN and therefore MUST not be used in the name of a single key. 449 * For example, the subkey "MountedDevices" belongs to the subtree 450 * HKEY_LOCAL_MACHINE, as shown in the following example. 451 * 452 * HKEY_LOCAL_MACHINE -> SYSTEM -> MountedDevices 453 * 454 * The FQN for MountedDevices is HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices. 455 * The relative name of the subkey is "MountedDevices". The relative name 456 * MUST be used only for operations that are performed on its immediate parent 457 * key (SYSTEM in the previous example). 458 */ 459 static char * 460 winreg_subkey_get_relative_name(const char *subkey) 461 { 462 winreg_subkey_t *key; 463 char *value; 464 465 if (subkey == NULL) 466 return (NULL); 467 468 if (list_is_empty(&winreg_keylist.kl_list)) 469 return (NULL); 470 471 key = list_head(&winreg_keylist.kl_list); 472 do { 473 if (strcasecmp(subkey, key->sk_name) == 0) { 474 value = strrchr(key->sk_name, '\\'); 475 if (value != NULL) 476 return (++value); 477 } 478 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 479 480 return (NULL); 481 } 482 483 /* 484 * winreg_s_DeleteValue 485 */ 486 /*ARGSUSED*/ 487 static int 488 winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa) 489 { 490 struct winreg_DeleteValue *param = arg; 491 492 param->status = ERROR_ACCESS_DENIED; 493 return (NDR_DRC_OK); 494 } 495 496 /* 497 * winreg_s_EnumKey 498 */ 499 static int 500 winreg_s_EnumKey(void *arg, ndr_xa_t *mxa) 501 { 502 struct winreg_EnumKey *param = arg; 503 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 504 winreg_string_t *name, *class; 505 char *value, *namep = NULL, *classp = NULL; 506 int slen = 0; 507 508 if (ndr_hdlookup(mxa, id) == NULL) { 509 bzero(param, sizeof (struct winreg_EnumKey)); 510 param->status = ERROR_NO_MORE_ITEMS; 511 return (NDR_DRC_OK); 512 } 513 514 if (param->index > 0) { 515 bzero(param, sizeof (struct winreg_EnumKey)); 516 param->status = ERROR_NO_MORE_ITEMS; 517 return (NDR_DRC_OK); 518 } 519 520 name = (winreg_string_t *)¶m->name_in; 521 class = (winreg_string_t *)¶m->class_in; 522 if (name->length != 0) 523 namep = (char *)name->str; 524 525 if (class->length != 0) 526 classp = (char *)class->str; 527 528 value = winreg_lookup_eventlog_registry(namep, classp); 529 if (value == NULL) { 530 bzero(param, sizeof (struct winreg_EnumKey)); 531 param->status = ERROR_CANTREAD; 532 return (NDR_DRC_OK); 533 } 534 535 slen = mts_wcequiv_strlen(value) + sizeof (mts_wchar_t); 536 param->name_out.length = slen; 537 param->name_out.allosize = slen; 538 if ((param->name_out.str = NDR_STRDUP(mxa, value)) == NULL) { 539 bzero(param, sizeof (struct winreg_EnumKey)); 540 param->status = ERROR_NOT_ENOUGH_MEMORY; 541 return (NDR_DRC_OK); 542 } 543 544 param->status = ERROR_SUCCESS; 545 return (NDR_DRC_OK); 546 } 547 548 /* 549 * winreg_s_EnumValue 550 */ 551 static int 552 winreg_s_EnumValue(void *arg, ndr_xa_t *mxa) 553 { 554 struct winreg_EnumValue *param = arg; 555 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 556 557 if (ndr_hdlookup(mxa, id) == NULL) { 558 bzero(param, sizeof (struct winreg_EnumValue)); 559 param->status = ERROR_NO_MORE_ITEMS; 560 return (NDR_DRC_OK); 561 } 562 563 bzero(param, sizeof (struct winreg_EnumValue)); 564 param->status = ERROR_NO_MORE_ITEMS; 565 return (NDR_DRC_OK); 566 } 567 568 /* 569 * winreg_s_FlushKey 570 * 571 * Flush the attributes associated with the specified open key to disk. 572 */ 573 static int 574 winreg_s_FlushKey(void *arg, ndr_xa_t *mxa) 575 { 576 struct winreg_FlushKey *param = arg; 577 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 578 579 if (ndr_hdlookup(mxa, id) == NULL) 580 param->status = ERROR_INVALID_HANDLE; 581 else 582 param->status = ERROR_SUCCESS; 583 584 return (NDR_DRC_OK); 585 } 586 587 /* 588 * winreg_s_GetKeySec 589 */ 590 /*ARGSUSED*/ 591 static int 592 winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa) 593 { 594 struct winreg_GetKeySec *param = arg; 595 596 bzero(param, sizeof (struct winreg_GetKeySec)); 597 param->status = ERROR_ACCESS_DENIED; 598 return (NDR_DRC_OK); 599 } 600 601 /* 602 * winreg_s_NotifyChange 603 */ 604 static int 605 winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa) 606 { 607 struct winreg_NotifyChange *param = arg; 608 609 if (ndr_is_admin(mxa)) 610 param->status = ERROR_SUCCESS; 611 else 612 param->status = ERROR_ACCESS_DENIED; 613 614 return (NDR_DRC_OK); 615 } 616 617 /* 618 * winreg_s_OpenKey 619 * 620 * This is a request to open a windows registry key. 621 * If we recognize the key, we return a handle. 622 * 623 * Returns: 624 * ERROR_SUCCESS Valid handle returned. 625 * ERROR_FILE_NOT_FOUND No key or unable to allocate a handle. 626 */ 627 static int 628 winreg_s_OpenKey(void *arg, ndr_xa_t *mxa) 629 { 630 struct winreg_OpenKey *param = arg; 631 char *subkey = (char *)param->name.str; 632 ndr_hdid_t *id = NULL; 633 winreg_subkey_t *key; 634 635 if (list_is_empty(&winreg_keylist.kl_list)) { 636 bzero(¶m->result_handle, sizeof (winreg_handle_t)); 637 param->status = ERROR_FILE_NOT_FOUND; 638 return (NDR_DRC_OK); 639 } 640 641 key = list_head(&winreg_keylist.kl_list); 642 do { 643 if (strcasecmp(subkey, key->sk_name) == 0) { 644 if (key->sk_predefined == B_TRUE) 645 id = ndr_hdalloc(mxa, &winreg_hkkey); 646 else 647 id = &key->sk_handle; 648 649 if (id == NULL) 650 break; 651 652 bcopy(id, ¶m->result_handle, 653 sizeof (winreg_handle_t)); 654 param->status = ERROR_SUCCESS; 655 return (NDR_DRC_OK); 656 } 657 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 658 659 bzero(¶m->result_handle, sizeof (winreg_handle_t)); 660 param->status = ERROR_FILE_NOT_FOUND; 661 return (NDR_DRC_OK); 662 } 663 664 /* 665 * winreg_s_QueryKey 666 */ 667 /*ARGSUSED*/ 668 static int 669 winreg_s_QueryKey(void *arg, ndr_xa_t *mxa) 670 { 671 struct winreg_QueryKey *param = arg; 672 int rc; 673 winreg_string_t *name; 674 675 name = (winreg_string_t *)¶m->name; 676 bzero(param, sizeof (struct winreg_QueryKey)); 677 if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL) 678 rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name); 679 680 if ((name == NULL) || (rc != 0)) { 681 bzero(param, sizeof (struct winreg_QueryKey)); 682 param->status = ERROR_NOT_ENOUGH_MEMORY; 683 return (NDR_DRC_OK); 684 } 685 686 param->status = ERROR_SUCCESS; 687 return (NDR_DRC_OK); 688 } 689 690 /* 691 * winreg_s_QueryValue 692 * 693 * This is a request to get the value associated with a specified name. 694 * 695 * Returns: 696 * ERROR_SUCCESS Value returned. 697 * ERROR_FILE_NOT_FOUND PrimaryModule is not supported. 698 * ERROR_CANTREAD No such name or memory problem. 699 */ 700 static int 701 winreg_s_QueryValue(void *arg, ndr_xa_t *mxa) 702 { 703 struct winreg_QueryValue *param = arg; 704 struct winreg_value *pv; 705 char *name; 706 char *value; 707 DWORD slen; 708 DWORD msize; 709 710 name = (char *)param->value_name.str; 711 712 if (strcasecmp(name, "PrimaryModule") == 0) { 713 param->status = ERROR_FILE_NOT_FOUND; 714 return (NDR_DRC_OK); 715 } 716 717 if ((value = winreg_lookup_value(name)) == NULL) { 718 param->status = ERROR_CANTREAD; 719 return (NDR_DRC_OK); 720 } 721 722 slen = mts_wcequiv_strlen(value) + sizeof (mts_wchar_t); 723 msize = sizeof (struct winreg_value) + slen; 724 725 param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize); 726 param->type = NDR_NEW(mxa, DWORD); 727 param->value_size = NDR_NEW(mxa, DWORD); 728 param->value_size_total = NDR_NEW(mxa, DWORD); 729 730 if (param->value == NULL || param->type == NULL || 731 param->value_size == NULL || param->value_size_total == NULL) { 732 param->status = ERROR_CANTREAD; 733 return (NDR_DRC_OK); 734 } 735 736 bzero(param->value, msize); 737 pv = param->value; 738 pv->vc_first_is = 0; 739 pv->vc_length_is = slen; 740 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 741 (void) ndr_mbstowcs(NULL, (mts_wchar_t *)pv->value, value, slen); 742 743 *param->type = 1; 744 *param->value_size = slen; 745 *param->value_size_total = slen; 746 747 param->status = ERROR_SUCCESS; 748 return (NDR_DRC_OK); 749 } 750 751 /* 752 * Lookup a name in the registry and return the associated value. 753 * Our registry is a case-insensitive, name-value pair table. 754 * 755 * Windows ProductType: WinNT, ServerNT, LanmanNT. 756 * Windows NT4.0 workstation: WinNT 757 * Windows NT4.0 server: ServerNT 758 * 759 * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy 760 * with info level 6, which we don't support. If we use ServerNT 761 * (as reported by NT4.0 Server) Windows 2000 send requests for 762 * levels 3 and 5, which are support. 763 * 764 * On success, returns a pointer to the value. Otherwise returns 765 * a null pointer. 766 */ 767 static char * 768 winreg_lookup_value(const char *name) 769 { 770 static struct registry { 771 char *name; 772 char *value; 773 } registry[] = { 774 { "ProductType", "ServerNT" }, 775 { "Sources", NULL } /* product name */ 776 }; 777 778 int i; 779 780 for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) { 781 if (strcasecmp(registry[i].name, name) == 0) { 782 if (registry[i].value == NULL) 783 return (winreg_sysname); 784 else 785 return (registry[i].value); 786 } 787 } 788 789 return (NULL); 790 } 791 792 /* 793 * winreg_lookup_eventlog_registry 794 * 795 * Return the subkey of the specified EventLog key. Decoding of 796 * class paramater not yet supported. 797 */ 798 /*ARGSUSED*/ 799 static char * 800 winreg_lookup_eventlog_registry(char *name, char *class) 801 { 802 if (name == NULL) 803 return (winreg_subkey_get_relative_name(WINREG_LOGR_SYSTEMKEY)); 804 805 return (winreg_subkey_get_relative_name(name)); 806 } 807 808 /* 809 * winreg_s_SetKeySec 810 */ 811 /*ARGSUSED*/ 812 static int 813 winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa) 814 { 815 struct winreg_SetKeySec *param = arg; 816 817 param->status = ERROR_ACCESS_DENIED; 818 return (NDR_DRC_OK); 819 } 820 821 /* 822 * winreg_s_CreateValue 823 */ 824 /*ARGSUSED*/ 825 static int 826 winreg_s_CreateValue(void *arg, ndr_xa_t *mxa) 827 { 828 struct winreg_CreateValue *param = arg; 829 830 param->status = ERROR_ACCESS_DENIED; 831 return (NDR_DRC_OK); 832 } 833 834 /* 835 * winreg_s_Shutdown 836 * 837 * Attempt to shutdown or reboot the system: access denied. 838 */ 839 /*ARGSUSED*/ 840 static int 841 winreg_s_Shutdown(void *arg, ndr_xa_t *mxa) 842 { 843 struct winreg_Shutdown *param = arg; 844 845 param->status = ERROR_ACCESS_DENIED; 846 return (NDR_DRC_OK); 847 } 848 849 /* 850 * winreg_s_AbortShutdown 851 * 852 * Abort a shutdown request. 853 */ 854 static int 855 winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa) 856 { 857 struct winreg_AbortShutdown *param = arg; 858 859 if (ndr_is_admin(mxa)) 860 param->status = ERROR_SUCCESS; 861 else 862 param->status = ERROR_ACCESS_DENIED; 863 864 return (NDR_DRC_OK); 865 } 866 867 /* 868 * winreg_s_GetVersion 869 * 870 * Return the windows registry version. The current version is 5. 871 * This call is usually made prior to enumerating or querying registry 872 * keys or values. 873 */ 874 /*ARGSUSED*/ 875 static int 876 winreg_s_GetVersion(void *arg, ndr_xa_t *mxa) 877 { 878 struct winreg_GetVersion *param = arg; 879 880 param->version = 5; 881 param->status = ERROR_SUCCESS; 882 return (NDR_DRC_OK); 883 } 884