18474SJose.Borrego@Sun.COM /* 28474SJose.Borrego@Sun.COM * CDDL HEADER START 38474SJose.Borrego@Sun.COM * 48474SJose.Borrego@Sun.COM * The contents of this file are subject to the terms of the 58474SJose.Borrego@Sun.COM * Common Development and Distribution License (the "License"). 68474SJose.Borrego@Sun.COM * You may not use this file except in compliance with the License. 78474SJose.Borrego@Sun.COM * 88474SJose.Borrego@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98474SJose.Borrego@Sun.COM * or http://www.opensolaris.org/os/licensing. 108474SJose.Borrego@Sun.COM * See the License for the specific language governing permissions 118474SJose.Borrego@Sun.COM * and limitations under the License. 128474SJose.Borrego@Sun.COM * 138474SJose.Borrego@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 148474SJose.Borrego@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158474SJose.Borrego@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 168474SJose.Borrego@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 178474SJose.Borrego@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 188474SJose.Borrego@Sun.COM * 198474SJose.Borrego@Sun.COM * CDDL HEADER END 208474SJose.Borrego@Sun.COM */ 218474SJose.Borrego@Sun.COM /* 22*11447Samw@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 238474SJose.Borrego@Sun.COM * Use is subject to license terms. 248474SJose.Borrego@Sun.COM */ 258474SJose.Borrego@Sun.COM 268474SJose.Borrego@Sun.COM /* 278474SJose.Borrego@Sun.COM * Windows Registry RPC (WINREG) server-side interface. 288474SJose.Borrego@Sun.COM * 298670SJose.Borrego@Sun.COM * The registry is a database with a hierarchical structure similar to 308670SJose.Borrego@Sun.COM * a file system, with keys in place of directories and values in place 318670SJose.Borrego@Sun.COM * of files. The top level keys are known as root keys and each key can 328670SJose.Borrego@Sun.COM * contain subkeys and values. As with directories and sub-directories, 338670SJose.Borrego@Sun.COM * the terms key and subkey are used interchangeably. Values, analogous 348670SJose.Borrego@Sun.COM * to files, contain data. 358474SJose.Borrego@Sun.COM * 368670SJose.Borrego@Sun.COM * A specific subkey can be identifies by its fully qualified name (FQN), 378670SJose.Borrego@Sun.COM * which is analogous to a file system path. In the registry, the key 388670SJose.Borrego@Sun.COM * separator is the '\' character, which is reserved and cannot appear 398670SJose.Borrego@Sun.COM * in key or value names. Registry names are case-insensitive. 408670SJose.Borrego@Sun.COM * 418670SJose.Borrego@Sun.COM * For example: HKEY_LOCAL_MACHINE\System\CurrentControlSet 428670SJose.Borrego@Sun.COM * 439914Samw@Sun.COM * The HKEY_LOCAL_MACHINE root key contains a subkey called System, and 448670SJose.Borrego@Sun.COM * System contains a subkey called CurrentControlSet. 458670SJose.Borrego@Sun.COM * 468670SJose.Borrego@Sun.COM * The WINREG RPC interface returns Win32 error codes. 478474SJose.Borrego@Sun.COM */ 488474SJose.Borrego@Sun.COM 498474SJose.Borrego@Sun.COM #include <sys/utsname.h> 508474SJose.Borrego@Sun.COM #include <strings.h> 518474SJose.Borrego@Sun.COM 528474SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h> 538474SJose.Borrego@Sun.COM #include <smbsrv/ntstatus.h> 548474SJose.Borrego@Sun.COM #include <smbsrv/nterror.h> 558474SJose.Borrego@Sun.COM #include <smbsrv/nmpipes.h> 568474SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h> 578474SJose.Borrego@Sun.COM #include <smbsrv/ndl/winreg.ndl> 588474SJose.Borrego@Sun.COM 598474SJose.Borrego@Sun.COM /* 608474SJose.Borrego@Sun.COM * List of supported registry keys (case-insensitive). 618474SJose.Borrego@Sun.COM */ 628474SJose.Borrego@Sun.COM static char *winreg_keys[] = { 639914Samw@Sun.COM "HKLM", 649914Samw@Sun.COM "HKU", 659914Samw@Sun.COM "HKLM\\SOFTWARE", 669914Samw@Sun.COM "HKLM\\SYSTEM", 6710504SKeyur.Desai@Sun.COM "Application", 6810504SKeyur.Desai@Sun.COM "Security", 699914Samw@Sun.COM "System", 709914Samw@Sun.COM "CurrentControlSet", 718474SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Services\\Eventlog", 728670SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Services\\Eventlog\\Application", 738670SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Services\\Eventlog\\Security", 748474SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Services\\Eventlog\\System", 758474SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Control\\ProductOptions", 769914Samw@Sun.COM "SOFTWARE", 778474SJose.Borrego@Sun.COM "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" 788474SJose.Borrego@Sun.COM }; 798474SJose.Borrego@Sun.COM 808474SJose.Borrego@Sun.COM typedef struct winreg_subkey { 818474SJose.Borrego@Sun.COM list_node_t sk_lnd; 828474SJose.Borrego@Sun.COM ndr_hdid_t sk_handle; 838474SJose.Borrego@Sun.COM char sk_name[MAXPATHLEN]; 848474SJose.Borrego@Sun.COM boolean_t sk_predefined; 858474SJose.Borrego@Sun.COM } winreg_subkey_t; 868474SJose.Borrego@Sun.COM 878474SJose.Borrego@Sun.COM typedef struct winreg_keylist { 888474SJose.Borrego@Sun.COM list_t kl_list; 898474SJose.Borrego@Sun.COM int kl_count; 908474SJose.Borrego@Sun.COM } winreg_keylist_t; 918474SJose.Borrego@Sun.COM 928474SJose.Borrego@Sun.COM static winreg_keylist_t winreg_keylist; 938474SJose.Borrego@Sun.COM 948474SJose.Borrego@Sun.COM static boolean_t winreg_key_has_subkey(const char *); 958670SJose.Borrego@Sun.COM static char *winreg_enum_subkey(ndr_xa_t *, const char *, uint32_t); 968474SJose.Borrego@Sun.COM static char *winreg_lookup_value(const char *); 97*11447Samw@Sun.COM static uint32_t winreg_sd_format(smb_sd_t *); 98*11447Samw@Sun.COM uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *); 998474SJose.Borrego@Sun.COM 1008670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCR(void *, ndr_xa_t *); 1018670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCU(void *, ndr_xa_t *); 1028474SJose.Borrego@Sun.COM static int winreg_s_OpenHKLM(void *, ndr_xa_t *); 1038670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPD(void *, ndr_xa_t *); 1048670SJose.Borrego@Sun.COM static int winreg_s_OpenHKU(void *, ndr_xa_t *); 1058670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCC(void *, ndr_xa_t *); 1068670SJose.Borrego@Sun.COM static int winreg_s_OpenHKDD(void *, ndr_xa_t *); 1078670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPT(void *, ndr_xa_t *); 1088670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPN(void *, ndr_xa_t *); 1098670SJose.Borrego@Sun.COM static int winreg_s_OpenHK(void *, ndr_xa_t *, const char *); 1108474SJose.Borrego@Sun.COM static int winreg_s_Close(void *, ndr_xa_t *); 1118474SJose.Borrego@Sun.COM static int winreg_s_CreateKey(void *, ndr_xa_t *); 1128474SJose.Borrego@Sun.COM static int winreg_s_DeleteKey(void *, ndr_xa_t *); 1138474SJose.Borrego@Sun.COM static int winreg_s_DeleteValue(void *, ndr_xa_t *); 1148474SJose.Borrego@Sun.COM static int winreg_s_EnumKey(void *, ndr_xa_t *); 1158474SJose.Borrego@Sun.COM static int winreg_s_EnumValue(void *, ndr_xa_t *); 1168474SJose.Borrego@Sun.COM static int winreg_s_FlushKey(void *, ndr_xa_t *); 1178474SJose.Borrego@Sun.COM static int winreg_s_GetKeySec(void *, ndr_xa_t *); 1188474SJose.Borrego@Sun.COM static int winreg_s_NotifyChange(void *, ndr_xa_t *); 1198474SJose.Borrego@Sun.COM static int winreg_s_OpenKey(void *, ndr_xa_t *); 1208474SJose.Borrego@Sun.COM static int winreg_s_QueryKey(void *, ndr_xa_t *); 1218474SJose.Borrego@Sun.COM static int winreg_s_QueryValue(void *, ndr_xa_t *); 1228474SJose.Borrego@Sun.COM static int winreg_s_SetKeySec(void *, ndr_xa_t *); 1238474SJose.Borrego@Sun.COM static int winreg_s_CreateValue(void *, ndr_xa_t *); 1248474SJose.Borrego@Sun.COM static int winreg_s_Shutdown(void *, ndr_xa_t *); 1258474SJose.Borrego@Sun.COM static int winreg_s_AbortShutdown(void *, ndr_xa_t *); 1268474SJose.Borrego@Sun.COM static int winreg_s_GetVersion(void *, ndr_xa_t *); 1278474SJose.Borrego@Sun.COM 1288474SJose.Borrego@Sun.COM static ndr_stub_table_t winreg_stub_table[] = { 1298670SJose.Borrego@Sun.COM { winreg_s_OpenHKCR, WINREG_OPNUM_OpenHKCR }, 1308670SJose.Borrego@Sun.COM { winreg_s_OpenHKCU, WINREG_OPNUM_OpenHKCU }, 1318474SJose.Borrego@Sun.COM { winreg_s_OpenHKLM, WINREG_OPNUM_OpenHKLM }, 1328670SJose.Borrego@Sun.COM { winreg_s_OpenHKPD, WINREG_OPNUM_OpenHKPD }, 1338670SJose.Borrego@Sun.COM { winreg_s_OpenHKU, WINREG_OPNUM_OpenHKUsers }, 1348474SJose.Borrego@Sun.COM { winreg_s_Close, WINREG_OPNUM_Close }, 1358474SJose.Borrego@Sun.COM { winreg_s_CreateKey, WINREG_OPNUM_CreateKey }, 1368474SJose.Borrego@Sun.COM { winreg_s_DeleteKey, WINREG_OPNUM_DeleteKey }, 1378474SJose.Borrego@Sun.COM { winreg_s_DeleteValue, WINREG_OPNUM_DeleteValue }, 1388474SJose.Borrego@Sun.COM { winreg_s_EnumKey, WINREG_OPNUM_EnumKey }, 1398474SJose.Borrego@Sun.COM { winreg_s_EnumValue, WINREG_OPNUM_EnumValue }, 1408474SJose.Borrego@Sun.COM { winreg_s_FlushKey, WINREG_OPNUM_FlushKey }, 1418474SJose.Borrego@Sun.COM { winreg_s_GetKeySec, WINREG_OPNUM_GetKeySec }, 1428474SJose.Borrego@Sun.COM { winreg_s_NotifyChange, WINREG_OPNUM_NotifyChange }, 1438474SJose.Borrego@Sun.COM { winreg_s_OpenKey, WINREG_OPNUM_OpenKey }, 1448474SJose.Borrego@Sun.COM { winreg_s_QueryKey, WINREG_OPNUM_QueryKey }, 1458474SJose.Borrego@Sun.COM { winreg_s_QueryValue, WINREG_OPNUM_QueryValue }, 1468474SJose.Borrego@Sun.COM { winreg_s_SetKeySec, WINREG_OPNUM_SetKeySec }, 1478474SJose.Borrego@Sun.COM { winreg_s_CreateValue, WINREG_OPNUM_CreateValue }, 1488474SJose.Borrego@Sun.COM { winreg_s_Shutdown, WINREG_OPNUM_Shutdown }, 1498474SJose.Borrego@Sun.COM { winreg_s_AbortShutdown, WINREG_OPNUM_AbortShutdown }, 1508474SJose.Borrego@Sun.COM { winreg_s_GetVersion, WINREG_OPNUM_GetVersion }, 1518670SJose.Borrego@Sun.COM { winreg_s_OpenHKCC, WINREG_OPNUM_OpenHKCC }, 1528670SJose.Borrego@Sun.COM { winreg_s_OpenHKDD, WINREG_OPNUM_OpenHKDD }, 1538670SJose.Borrego@Sun.COM { winreg_s_OpenHKPT, WINREG_OPNUM_OpenHKPT }, 1548670SJose.Borrego@Sun.COM { winreg_s_OpenHKPN, WINREG_OPNUM_OpenHKPN }, 1558474SJose.Borrego@Sun.COM {0} 1568474SJose.Borrego@Sun.COM }; 1578474SJose.Borrego@Sun.COM 1588474SJose.Borrego@Sun.COM static ndr_service_t winreg_service = { 1598474SJose.Borrego@Sun.COM "Winreg", /* name */ 1608474SJose.Borrego@Sun.COM "Windows Registry", /* desc */ 1618474SJose.Borrego@Sun.COM "\\winreg", /* endpoint */ 1628474SJose.Borrego@Sun.COM PIPE_WINREG, /* sec_addr_port */ 1638474SJose.Borrego@Sun.COM "338cd001-2244-31f1-aaaa-900038001003", 1, /* abstract */ 1648474SJose.Borrego@Sun.COM NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ 1658474SJose.Borrego@Sun.COM 0, /* no bind_instance_size */ 1668474SJose.Borrego@Sun.COM 0, /* no bind_req() */ 1678474SJose.Borrego@Sun.COM 0, /* no unbind_and_close() */ 1688474SJose.Borrego@Sun.COM 0, /* use generic_call_stub() */ 1698474SJose.Borrego@Sun.COM &TYPEINFO(winreg_interface), /* interface ti */ 1708474SJose.Borrego@Sun.COM winreg_stub_table /* stub_table */ 1718474SJose.Borrego@Sun.COM }; 1728474SJose.Borrego@Sun.COM 1738474SJose.Borrego@Sun.COM static char winreg_sysname[SYS_NMLN]; 1748474SJose.Borrego@Sun.COM 1758474SJose.Borrego@Sun.COM /* 1768474SJose.Borrego@Sun.COM * winreg_initialize 1778474SJose.Borrego@Sun.COM * 1788474SJose.Borrego@Sun.COM * Initialize and register the WINREG RPC interface with the RPC runtime 1798474SJose.Borrego@Sun.COM * library. It must be called in order to use either the client side 1808474SJose.Borrego@Sun.COM * or the server side functions. 1818474SJose.Borrego@Sun.COM */ 1828474SJose.Borrego@Sun.COM void 1838474SJose.Borrego@Sun.COM winreg_initialize(void) 1848474SJose.Borrego@Sun.COM { 1858474SJose.Borrego@Sun.COM winreg_subkey_t *key; 1868474SJose.Borrego@Sun.COM struct utsname name; 1878474SJose.Borrego@Sun.COM char *sysname; 1888474SJose.Borrego@Sun.COM int i; 1898474SJose.Borrego@Sun.COM 1908474SJose.Borrego@Sun.COM list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t), 1918474SJose.Borrego@Sun.COM offsetof(winreg_subkey_t, sk_lnd)); 1928474SJose.Borrego@Sun.COM winreg_keylist.kl_count = 0; 1938474SJose.Borrego@Sun.COM 1948474SJose.Borrego@Sun.COM for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) { 1958474SJose.Borrego@Sun.COM if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) { 1968474SJose.Borrego@Sun.COM bzero(key, sizeof (winreg_subkey_t)); 1978474SJose.Borrego@Sun.COM (void) strlcpy(key->sk_name, winreg_keys[i], 1988474SJose.Borrego@Sun.COM MAXPATHLEN); 1998474SJose.Borrego@Sun.COM key->sk_predefined = B_TRUE; 2008474SJose.Borrego@Sun.COM list_insert_tail(&winreg_keylist.kl_list, key); 2018474SJose.Borrego@Sun.COM ++winreg_keylist.kl_count; 2028474SJose.Borrego@Sun.COM } 2038474SJose.Borrego@Sun.COM } 2048474SJose.Borrego@Sun.COM 2058474SJose.Borrego@Sun.COM if (uname(&name) < 0) 2068474SJose.Borrego@Sun.COM sysname = "Solaris"; 2078474SJose.Borrego@Sun.COM else 2088474SJose.Borrego@Sun.COM sysname = name.sysname; 2098474SJose.Borrego@Sun.COM 2108474SJose.Borrego@Sun.COM (void) strlcpy(winreg_sysname, sysname, SYS_NMLN); 2118474SJose.Borrego@Sun.COM (void) ndr_svc_register(&winreg_service); 2128474SJose.Borrego@Sun.COM } 2138474SJose.Borrego@Sun.COM 2148670SJose.Borrego@Sun.COM static int 2158670SJose.Borrego@Sun.COM winreg_s_OpenHKCR(void *arg, ndr_xa_t *mxa) 2168670SJose.Borrego@Sun.COM { 2178670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKCR")); 2188670SJose.Borrego@Sun.COM } 2198670SJose.Borrego@Sun.COM 2208474SJose.Borrego@Sun.COM static int 2218670SJose.Borrego@Sun.COM winreg_s_OpenHKCU(void *arg, ndr_xa_t *mxa) 2228670SJose.Borrego@Sun.COM { 2238670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKCU")); 2248670SJose.Borrego@Sun.COM } 2258670SJose.Borrego@Sun.COM 2268670SJose.Borrego@Sun.COM static int 2278670SJose.Borrego@Sun.COM winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa) 2288670SJose.Borrego@Sun.COM { 2298670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKLM")); 2308670SJose.Borrego@Sun.COM } 2318670SJose.Borrego@Sun.COM 2328670SJose.Borrego@Sun.COM static int 2338670SJose.Borrego@Sun.COM winreg_s_OpenHKPD(void *arg, ndr_xa_t *mxa) 2348474SJose.Borrego@Sun.COM { 2358670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKPD")); 2368670SJose.Borrego@Sun.COM } 2378670SJose.Borrego@Sun.COM 2388670SJose.Borrego@Sun.COM static int 2398670SJose.Borrego@Sun.COM winreg_s_OpenHKU(void *arg, ndr_xa_t *mxa) 2408670SJose.Borrego@Sun.COM { 2418670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKU")); 2428670SJose.Borrego@Sun.COM } 2438670SJose.Borrego@Sun.COM 2448670SJose.Borrego@Sun.COM static int 2458670SJose.Borrego@Sun.COM winreg_s_OpenHKCC(void *arg, ndr_xa_t *mxa) 2468670SJose.Borrego@Sun.COM { 2478670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKCC")); 2488670SJose.Borrego@Sun.COM } 2498474SJose.Borrego@Sun.COM 2508670SJose.Borrego@Sun.COM static int 2518670SJose.Borrego@Sun.COM winreg_s_OpenHKDD(void *arg, ndr_xa_t *mxa) 2528670SJose.Borrego@Sun.COM { 2538670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKDD")); 2548670SJose.Borrego@Sun.COM } 2558474SJose.Borrego@Sun.COM 2568670SJose.Borrego@Sun.COM static int 2578670SJose.Borrego@Sun.COM winreg_s_OpenHKPT(void *arg, ndr_xa_t *mxa) 2588670SJose.Borrego@Sun.COM { 2598670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKPT")); 2608670SJose.Borrego@Sun.COM } 2618670SJose.Borrego@Sun.COM 2628670SJose.Borrego@Sun.COM static int 2638670SJose.Borrego@Sun.COM winreg_s_OpenHKPN(void *arg, ndr_xa_t *mxa) 2648670SJose.Borrego@Sun.COM { 2658670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKPN")); 2668474SJose.Borrego@Sun.COM } 2678474SJose.Borrego@Sun.COM 2688474SJose.Borrego@Sun.COM /* 2698670SJose.Borrego@Sun.COM * winreg_s_OpenHK 2708474SJose.Borrego@Sun.COM * 2718670SJose.Borrego@Sun.COM * Common code to open root HKEYs. 2728474SJose.Borrego@Sun.COM */ 2738474SJose.Borrego@Sun.COM static int 2748670SJose.Borrego@Sun.COM winreg_s_OpenHK(void *arg, ndr_xa_t *mxa, const char *hkey) 2758474SJose.Borrego@Sun.COM { 2768670SJose.Borrego@Sun.COM struct winreg_OpenHKCR *param = arg; 2778474SJose.Borrego@Sun.COM ndr_hdid_t *id; 2788670SJose.Borrego@Sun.COM char *dupkey; 2798474SJose.Borrego@Sun.COM 2808670SJose.Borrego@Sun.COM if ((dupkey = strdup(hkey)) == NULL) { 2818474SJose.Borrego@Sun.COM bzero(¶m->handle, sizeof (winreg_handle_t)); 2828670SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 2838670SJose.Borrego@Sun.COM return (NDR_DRC_OK); 2848474SJose.Borrego@Sun.COM } 2858474SJose.Borrego@Sun.COM 2868670SJose.Borrego@Sun.COM if ((id = ndr_hdalloc(mxa, dupkey)) == NULL) { 2878670SJose.Borrego@Sun.COM free(dupkey); 2888474SJose.Borrego@Sun.COM bzero(¶m->handle, sizeof (winreg_handle_t)); 2898474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 2908474SJose.Borrego@Sun.COM } else { 2918474SJose.Borrego@Sun.COM bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); 2928474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 2938474SJose.Borrego@Sun.COM } 2948474SJose.Borrego@Sun.COM 2958474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 2968474SJose.Borrego@Sun.COM } 2978474SJose.Borrego@Sun.COM 2988474SJose.Borrego@Sun.COM /* 2998474SJose.Borrego@Sun.COM * winreg_s_Close 3008474SJose.Borrego@Sun.COM * 3018474SJose.Borrego@Sun.COM * This is a request to close the WINREG interface specified by the 3028474SJose.Borrego@Sun.COM * handle. We don't track handles (yet), so just zero out the handle 3038474SJose.Borrego@Sun.COM * and return NDR_DRC_OK. Setting the handle to zero appears to be 3048474SJose.Borrego@Sun.COM * standard behaviour. 3058474SJose.Borrego@Sun.COM */ 3068474SJose.Borrego@Sun.COM static int 3078474SJose.Borrego@Sun.COM winreg_s_Close(void *arg, ndr_xa_t *mxa) 3088474SJose.Borrego@Sun.COM { 3098474SJose.Borrego@Sun.COM struct winreg_Close *param = arg; 3108474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 3118670SJose.Borrego@Sun.COM ndr_handle_t *hd; 3128670SJose.Borrego@Sun.COM 3138670SJose.Borrego@Sun.COM if ((hd = ndr_hdlookup(mxa, id)) != NULL) { 3148670SJose.Borrego@Sun.COM free(hd->nh_data); 3158670SJose.Borrego@Sun.COM hd->nh_data = NULL; 3168670SJose.Borrego@Sun.COM } 3178474SJose.Borrego@Sun.COM 3188474SJose.Borrego@Sun.COM ndr_hdfree(mxa, id); 3198474SJose.Borrego@Sun.COM 3208474SJose.Borrego@Sun.COM bzero(¶m->result_handle, sizeof (winreg_handle_t)); 3218474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 3228474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3238474SJose.Borrego@Sun.COM } 3248474SJose.Borrego@Sun.COM 3258474SJose.Borrego@Sun.COM /* 3268474SJose.Borrego@Sun.COM * winreg_s_CreateKey 3278474SJose.Borrego@Sun.COM */ 3288474SJose.Borrego@Sun.COM static int 3298474SJose.Borrego@Sun.COM winreg_s_CreateKey(void *arg, ndr_xa_t *mxa) 3308474SJose.Borrego@Sun.COM { 3318474SJose.Borrego@Sun.COM struct winreg_CreateKey *param = arg; 3328474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 3338474SJose.Borrego@Sun.COM ndr_handle_t *hd; 3348474SJose.Borrego@Sun.COM winreg_subkey_t *key; 3358474SJose.Borrego@Sun.COM char *subkey; 3368670SJose.Borrego@Sun.COM char *dupkey; 3378474SJose.Borrego@Sun.COM DWORD *action; 3388474SJose.Borrego@Sun.COM 3398474SJose.Borrego@Sun.COM subkey = (char *)param->subkey.str; 3408474SJose.Borrego@Sun.COM 3418474SJose.Borrego@Sun.COM if (!ndr_is_admin(mxa) || (subkey == NULL)) { 3428474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3438474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 3448474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3458474SJose.Borrego@Sun.COM } 3468474SJose.Borrego@Sun.COM 3478474SJose.Borrego@Sun.COM hd = ndr_hdlookup(mxa, id); 3488474SJose.Borrego@Sun.COM if (hd == NULL) { 3498474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3508474SJose.Borrego@Sun.COM param->status = ERROR_INVALID_HANDLE; 3518474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3528474SJose.Borrego@Sun.COM } 3538474SJose.Borrego@Sun.COM 3548474SJose.Borrego@Sun.COM if ((action = NDR_NEW(mxa, DWORD)) == NULL) { 3558474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3568474SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 3578474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3588474SJose.Borrego@Sun.COM } 3598474SJose.Borrego@Sun.COM 3608474SJose.Borrego@Sun.COM if (list_is_empty(&winreg_keylist.kl_list)) 3618474SJose.Borrego@Sun.COM goto new_key; 3628474SJose.Borrego@Sun.COM 3638474SJose.Borrego@Sun.COM /* 3648474SJose.Borrego@Sun.COM * Check for an existing key. 3658474SJose.Borrego@Sun.COM */ 3668474SJose.Borrego@Sun.COM key = list_head(&winreg_keylist.kl_list); 3678474SJose.Borrego@Sun.COM do { 3688474SJose.Borrego@Sun.COM if (strcasecmp(subkey, key->sk_name) == 0) { 3698474SJose.Borrego@Sun.COM bcopy(&key->sk_handle, ¶m->result_handle, 3708474SJose.Borrego@Sun.COM sizeof (winreg_handle_t)); 3718474SJose.Borrego@Sun.COM *action = WINREG_ACTION_EXISTING_KEY; 3728474SJose.Borrego@Sun.COM param->action = action; 3738474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 3748474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3758474SJose.Borrego@Sun.COM } 3768474SJose.Borrego@Sun.COM } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 3778474SJose.Borrego@Sun.COM 3788474SJose.Borrego@Sun.COM new_key: 3798474SJose.Borrego@Sun.COM /* 3808474SJose.Borrego@Sun.COM * Create a new key. 3818474SJose.Borrego@Sun.COM */ 3828670SJose.Borrego@Sun.COM if ((dupkey = strdup(subkey)) == NULL) { 3838670SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3848670SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 3858670SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3868670SJose.Borrego@Sun.COM } 3878670SJose.Borrego@Sun.COM 3888670SJose.Borrego@Sun.COM id = ndr_hdalloc(mxa, dupkey); 3898474SJose.Borrego@Sun.COM key = malloc(sizeof (winreg_subkey_t)); 3908474SJose.Borrego@Sun.COM 3918474SJose.Borrego@Sun.COM if ((id == NULL) || (key == NULL)) { 3928670SJose.Borrego@Sun.COM free(dupkey); 3938474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3948474SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 3958474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3968474SJose.Borrego@Sun.COM } 3978474SJose.Borrego@Sun.COM 3988474SJose.Borrego@Sun.COM bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t)); 3998474SJose.Borrego@Sun.COM (void) strlcpy(key->sk_name, subkey, MAXPATHLEN); 4008474SJose.Borrego@Sun.COM key->sk_predefined = B_FALSE; 4018474SJose.Borrego@Sun.COM list_insert_tail(&winreg_keylist.kl_list, key); 4028474SJose.Borrego@Sun.COM ++winreg_keylist.kl_count; 4038474SJose.Borrego@Sun.COM 4048474SJose.Borrego@Sun.COM bcopy(id, ¶m->result_handle, sizeof (winreg_handle_t)); 4058474SJose.Borrego@Sun.COM *action = WINREG_ACTION_NEW_KEY; 4068474SJose.Borrego@Sun.COM param->action = action; 4078474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 4088474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4098474SJose.Borrego@Sun.COM } 4108474SJose.Borrego@Sun.COM 4118474SJose.Borrego@Sun.COM /* 4128474SJose.Borrego@Sun.COM * winreg_s_DeleteKey 4138474SJose.Borrego@Sun.COM */ 4148474SJose.Borrego@Sun.COM static int 4158474SJose.Borrego@Sun.COM winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa) 4168474SJose.Borrego@Sun.COM { 4178474SJose.Borrego@Sun.COM struct winreg_DeleteKey *param = arg; 4188474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 4198670SJose.Borrego@Sun.COM ndr_handle_t *hd; 4208474SJose.Borrego@Sun.COM winreg_subkey_t *key; 4218474SJose.Borrego@Sun.COM char *subkey; 4228474SJose.Borrego@Sun.COM 4238474SJose.Borrego@Sun.COM subkey = (char *)param->subkey.str; 4248474SJose.Borrego@Sun.COM 4258474SJose.Borrego@Sun.COM if (!ndr_is_admin(mxa) || (subkey == NULL)) { 4268474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 4278474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4288474SJose.Borrego@Sun.COM } 4298474SJose.Borrego@Sun.COM 4308474SJose.Borrego@Sun.COM if ((ndr_hdlookup(mxa, id) == NULL) || 4318474SJose.Borrego@Sun.COM list_is_empty(&winreg_keylist.kl_list) || 4328474SJose.Borrego@Sun.COM winreg_key_has_subkey(subkey)) { 4338474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 4348474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4358474SJose.Borrego@Sun.COM } 4368474SJose.Borrego@Sun.COM 4378474SJose.Borrego@Sun.COM key = list_head(&winreg_keylist.kl_list); 4388474SJose.Borrego@Sun.COM do { 4398474SJose.Borrego@Sun.COM if (strcasecmp(subkey, key->sk_name) == 0) { 4408474SJose.Borrego@Sun.COM if (key->sk_predefined == B_TRUE) { 4418474SJose.Borrego@Sun.COM /* Predefined keys cannot be deleted */ 4428474SJose.Borrego@Sun.COM break; 4438474SJose.Borrego@Sun.COM } 4448474SJose.Borrego@Sun.COM 4458474SJose.Borrego@Sun.COM list_remove(&winreg_keylist.kl_list, key); 4468474SJose.Borrego@Sun.COM --winreg_keylist.kl_count; 4478670SJose.Borrego@Sun.COM 4488670SJose.Borrego@Sun.COM hd = ndr_hdlookup(mxa, &key->sk_handle); 4498670SJose.Borrego@Sun.COM if (hd != NULL) { 4508670SJose.Borrego@Sun.COM free(hd->nh_data); 4518670SJose.Borrego@Sun.COM hd->nh_data = NULL; 4528670SJose.Borrego@Sun.COM } 4538670SJose.Borrego@Sun.COM 4548474SJose.Borrego@Sun.COM ndr_hdfree(mxa, &key->sk_handle); 4558474SJose.Borrego@Sun.COM free(key); 4568474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 4578474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4588474SJose.Borrego@Sun.COM } 4598474SJose.Borrego@Sun.COM } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 4608474SJose.Borrego@Sun.COM 4618474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 4628474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4638474SJose.Borrego@Sun.COM } 4648474SJose.Borrego@Sun.COM 4658474SJose.Borrego@Sun.COM static boolean_t 4668474SJose.Borrego@Sun.COM winreg_key_has_subkey(const char *subkey) 4678474SJose.Borrego@Sun.COM { 4688474SJose.Borrego@Sun.COM winreg_subkey_t *key; 4698474SJose.Borrego@Sun.COM int keylen; 4708474SJose.Borrego@Sun.COM 4718474SJose.Borrego@Sun.COM if (list_is_empty(&winreg_keylist.kl_list)) 4728474SJose.Borrego@Sun.COM return (B_FALSE); 4738474SJose.Borrego@Sun.COM 4748474SJose.Borrego@Sun.COM keylen = strlen(subkey); 4758474SJose.Borrego@Sun.COM 4768474SJose.Borrego@Sun.COM key = list_head(&winreg_keylist.kl_list); 4778474SJose.Borrego@Sun.COM do { 4788474SJose.Borrego@Sun.COM if (strncasecmp(subkey, key->sk_name, keylen) == 0) { 4798474SJose.Borrego@Sun.COM /* 4808474SJose.Borrego@Sun.COM * Potential match. If sk_name is longer than 4818474SJose.Borrego@Sun.COM * subkey, then sk_name is a subkey of our key. 4828474SJose.Borrego@Sun.COM */ 4838474SJose.Borrego@Sun.COM if (keylen < strlen(key->sk_name)) 4848474SJose.Borrego@Sun.COM return (B_TRUE); 4858474SJose.Borrego@Sun.COM } 4868474SJose.Borrego@Sun.COM } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 4878474SJose.Borrego@Sun.COM 4888474SJose.Borrego@Sun.COM return (B_FALSE); 4898474SJose.Borrego@Sun.COM } 4908474SJose.Borrego@Sun.COM 4918474SJose.Borrego@Sun.COM static char * 4928670SJose.Borrego@Sun.COM winreg_enum_subkey(ndr_xa_t *mxa, const char *subkey, uint32_t index) 4938474SJose.Borrego@Sun.COM { 4948474SJose.Borrego@Sun.COM winreg_subkey_t *key; 4958670SJose.Borrego@Sun.COM char *entry; 4968670SJose.Borrego@Sun.COM char *p; 4978670SJose.Borrego@Sun.COM int subkeylen; 4988670SJose.Borrego@Sun.COM int count = 0; 4998474SJose.Borrego@Sun.COM 5008474SJose.Borrego@Sun.COM if (subkey == NULL) 5018474SJose.Borrego@Sun.COM return (NULL); 5028474SJose.Borrego@Sun.COM 5038474SJose.Borrego@Sun.COM if (list_is_empty(&winreg_keylist.kl_list)) 5048474SJose.Borrego@Sun.COM return (NULL); 5058474SJose.Borrego@Sun.COM 5068670SJose.Borrego@Sun.COM subkeylen = strlen(subkey); 5078670SJose.Borrego@Sun.COM 5088670SJose.Borrego@Sun.COM for (key = list_head(&winreg_keylist.kl_list); 5098670SJose.Borrego@Sun.COM key != NULL; key = list_next(&winreg_keylist.kl_list, key)) { 5108670SJose.Borrego@Sun.COM if (strncasecmp(subkey, key->sk_name, subkeylen) == 0) { 5118670SJose.Borrego@Sun.COM p = key->sk_name + subkeylen; 5128670SJose.Borrego@Sun.COM 5138670SJose.Borrego@Sun.COM if ((*p != '\\') || (*p == '\0')) { 5148670SJose.Borrego@Sun.COM /* 5158670SJose.Borrego@Sun.COM * Not the same subkey or an exact match. 5168670SJose.Borrego@Sun.COM * We're looking for children of subkey. 5178670SJose.Borrego@Sun.COM */ 5188670SJose.Borrego@Sun.COM continue; 5198670SJose.Borrego@Sun.COM } 5208670SJose.Borrego@Sun.COM 5218670SJose.Borrego@Sun.COM ++p; 5228670SJose.Borrego@Sun.COM 5238670SJose.Borrego@Sun.COM if (count < index) { 5248670SJose.Borrego@Sun.COM ++count; 5258670SJose.Borrego@Sun.COM continue; 5268670SJose.Borrego@Sun.COM } 5278670SJose.Borrego@Sun.COM 5288670SJose.Borrego@Sun.COM if ((entry = NDR_STRDUP(mxa, p)) == NULL) 5298670SJose.Borrego@Sun.COM return (NULL); 5308670SJose.Borrego@Sun.COM 5318670SJose.Borrego@Sun.COM if ((p = strchr(entry, '\\')) != NULL) 5328670SJose.Borrego@Sun.COM *p = '\0'; 5338670SJose.Borrego@Sun.COM 5348670SJose.Borrego@Sun.COM return (entry); 5358474SJose.Borrego@Sun.COM } 5368670SJose.Borrego@Sun.COM } 5378474SJose.Borrego@Sun.COM 5388474SJose.Borrego@Sun.COM return (NULL); 5398474SJose.Borrego@Sun.COM } 5408474SJose.Borrego@Sun.COM 5418474SJose.Borrego@Sun.COM /* 5428474SJose.Borrego@Sun.COM * winreg_s_DeleteValue 5438474SJose.Borrego@Sun.COM */ 5448474SJose.Borrego@Sun.COM /*ARGSUSED*/ 5458474SJose.Borrego@Sun.COM static int 5468474SJose.Borrego@Sun.COM winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa) 5478474SJose.Borrego@Sun.COM { 5488474SJose.Borrego@Sun.COM struct winreg_DeleteValue *param = arg; 5498474SJose.Borrego@Sun.COM 5508474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 5518474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5528474SJose.Borrego@Sun.COM } 5538474SJose.Borrego@Sun.COM 5548474SJose.Borrego@Sun.COM /* 5558474SJose.Borrego@Sun.COM * winreg_s_EnumKey 5568474SJose.Borrego@Sun.COM */ 5578474SJose.Borrego@Sun.COM static int 5588474SJose.Borrego@Sun.COM winreg_s_EnumKey(void *arg, ndr_xa_t *mxa) 5598474SJose.Borrego@Sun.COM { 5608474SJose.Borrego@Sun.COM struct winreg_EnumKey *param = arg; 5618474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 5628670SJose.Borrego@Sun.COM ndr_handle_t *hd; 5638670SJose.Borrego@Sun.COM char *subkey; 5648670SJose.Borrego@Sun.COM char *name = NULL; 5658474SJose.Borrego@Sun.COM 5668670SJose.Borrego@Sun.COM if ((hd = ndr_hdlookup(mxa, id)) != NULL) 5678670SJose.Borrego@Sun.COM name = hd->nh_data; 5688474SJose.Borrego@Sun.COM 5698670SJose.Borrego@Sun.COM if (hd == NULL || name == NULL) { 5708474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumKey)); 5718474SJose.Borrego@Sun.COM param->status = ERROR_NO_MORE_ITEMS; 5728474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5738474SJose.Borrego@Sun.COM } 5748474SJose.Borrego@Sun.COM 5758670SJose.Borrego@Sun.COM subkey = winreg_enum_subkey(mxa, name, param->index); 5768670SJose.Borrego@Sun.COM if (subkey == NULL) { 5778474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumKey)); 5788670SJose.Borrego@Sun.COM param->status = ERROR_NO_MORE_ITEMS; 5798474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5808474SJose.Borrego@Sun.COM } 5818474SJose.Borrego@Sun.COM 5828670SJose.Borrego@Sun.COM if (NDR_MSTRING(mxa, subkey, (ndr_mstring_t *)¶m->name_out) == -1) { 5838474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumKey)); 5848474SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 5858474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5868474SJose.Borrego@Sun.COM } 5878670SJose.Borrego@Sun.COM /* 5888670SJose.Borrego@Sun.COM * This request requires that the length includes the null. 5898670SJose.Borrego@Sun.COM */ 5908670SJose.Borrego@Sun.COM param->name_out.length = param->name_out.allosize; 5918474SJose.Borrego@Sun.COM 5928474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 5938474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5948474SJose.Borrego@Sun.COM } 5958474SJose.Borrego@Sun.COM 5968474SJose.Borrego@Sun.COM /* 5978474SJose.Borrego@Sun.COM * winreg_s_EnumValue 5988474SJose.Borrego@Sun.COM */ 5998474SJose.Borrego@Sun.COM static int 6008474SJose.Borrego@Sun.COM winreg_s_EnumValue(void *arg, ndr_xa_t *mxa) 6018474SJose.Borrego@Sun.COM { 6028474SJose.Borrego@Sun.COM struct winreg_EnumValue *param = arg; 6038474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 6048474SJose.Borrego@Sun.COM 6058474SJose.Borrego@Sun.COM if (ndr_hdlookup(mxa, id) == NULL) { 6068474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumValue)); 6078474SJose.Borrego@Sun.COM param->status = ERROR_NO_MORE_ITEMS; 6088474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6098474SJose.Borrego@Sun.COM } 6108474SJose.Borrego@Sun.COM 6118474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumValue)); 6128474SJose.Borrego@Sun.COM param->status = ERROR_NO_MORE_ITEMS; 6138474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6148474SJose.Borrego@Sun.COM } 6158474SJose.Borrego@Sun.COM 6168474SJose.Borrego@Sun.COM /* 6178474SJose.Borrego@Sun.COM * winreg_s_FlushKey 6188474SJose.Borrego@Sun.COM * 6198474SJose.Borrego@Sun.COM * Flush the attributes associated with the specified open key to disk. 6208474SJose.Borrego@Sun.COM */ 6218474SJose.Borrego@Sun.COM static int 6228474SJose.Borrego@Sun.COM winreg_s_FlushKey(void *arg, ndr_xa_t *mxa) 6238474SJose.Borrego@Sun.COM { 6248474SJose.Borrego@Sun.COM struct winreg_FlushKey *param = arg; 6258474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 6268474SJose.Borrego@Sun.COM 6278474SJose.Borrego@Sun.COM if (ndr_hdlookup(mxa, id) == NULL) 6288474SJose.Borrego@Sun.COM param->status = ERROR_INVALID_HANDLE; 6298474SJose.Borrego@Sun.COM else 6308474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 6318474SJose.Borrego@Sun.COM 6328474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6338474SJose.Borrego@Sun.COM } 6348474SJose.Borrego@Sun.COM 6358474SJose.Borrego@Sun.COM /* 6368474SJose.Borrego@Sun.COM * winreg_s_GetKeySec 6378474SJose.Borrego@Sun.COM */ 6388474SJose.Borrego@Sun.COM static int 6398474SJose.Borrego@Sun.COM winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa) 6408474SJose.Borrego@Sun.COM { 6418474SJose.Borrego@Sun.COM struct winreg_GetKeySec *param = arg; 642*11447Samw@Sun.COM struct winreg_value *sd_buf; 643*11447Samw@Sun.COM smb_sd_t sd; 644*11447Samw@Sun.COM uint32_t sd_len; 645*11447Samw@Sun.COM uint32_t status; 6468474SJose.Borrego@Sun.COM 647*11447Samw@Sun.COM bzero(&sd, sizeof (smb_sd_t)); 648*11447Samw@Sun.COM 649*11447Samw@Sun.COM if ((status = winreg_sd_format(&sd)) != ERROR_SUCCESS) 650*11447Samw@Sun.COM goto winreg_getkeysec_error; 651*11447Samw@Sun.COM 652*11447Samw@Sun.COM sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO); 653*11447Samw@Sun.COM 654*11447Samw@Sun.COM param->sd = NDR_MALLOC(mxa, sizeof (struct winreg_secdesc)); 655*11447Samw@Sun.COM if (param->sd == NULL) { 656*11447Samw@Sun.COM status = ERROR_NOT_ENOUGH_MEMORY; 657*11447Samw@Sun.COM goto winreg_getkeysec_error; 658*11447Samw@Sun.COM } 659*11447Samw@Sun.COM 660*11447Samw@Sun.COM param->sd->sd_len = sd_len; 661*11447Samw@Sun.COM param->sd->sd_size = sd_len; 662*11447Samw@Sun.COM 663*11447Samw@Sun.COM sd_buf = NDR_MALLOC(mxa, sd_len + sizeof (struct winreg_value)); 664*11447Samw@Sun.COM param->sd->sd_buf = sd_buf; 665*11447Samw@Sun.COM 666*11447Samw@Sun.COM sd_buf->vc_first_is = 0; 667*11447Samw@Sun.COM sd_buf->vc_length_is = sd_len; 668*11447Samw@Sun.COM param->status = srvsvc_sd_set_relative(&sd, sd_buf->value); 669*11447Samw@Sun.COM 670*11447Samw@Sun.COM smb_sd_term(&sd); 671*11447Samw@Sun.COM return (NDR_DRC_OK); 672*11447Samw@Sun.COM 673*11447Samw@Sun.COM winreg_getkeysec_error: 674*11447Samw@Sun.COM smb_sd_term(&sd); 6758474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_GetKeySec)); 676*11447Samw@Sun.COM param->status = status; 6778474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6788474SJose.Borrego@Sun.COM } 6798474SJose.Borrego@Sun.COM 680*11447Samw@Sun.COM static uint32_t 681*11447Samw@Sun.COM winreg_sd_format(smb_sd_t *sd) 682*11447Samw@Sun.COM { 683*11447Samw@Sun.COM smb_fssd_t fs_sd; 684*11447Samw@Sun.COM acl_t *acl; 685*11447Samw@Sun.COM uint32_t status = ERROR_SUCCESS; 686*11447Samw@Sun.COM 687*11447Samw@Sun.COM if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0) 688*11447Samw@Sun.COM return (ERROR_NOT_ENOUGH_MEMORY); 689*11447Samw@Sun.COM 690*11447Samw@Sun.COM smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR); 691*11447Samw@Sun.COM fs_sd.sd_uid = 0; 692*11447Samw@Sun.COM fs_sd.sd_gid = 0; 693*11447Samw@Sun.COM fs_sd.sd_zdacl = acl; 694*11447Samw@Sun.COM fs_sd.sd_zsacl = NULL; 695*11447Samw@Sun.COM 696*11447Samw@Sun.COM if (smb_sd_fromfs(&fs_sd, sd) != NT_STATUS_SUCCESS) 697*11447Samw@Sun.COM status = ERROR_ACCESS_DENIED; 698*11447Samw@Sun.COM smb_fssd_term(&fs_sd); 699*11447Samw@Sun.COM return (status); 700*11447Samw@Sun.COM } 701*11447Samw@Sun.COM 7028474SJose.Borrego@Sun.COM /* 7038474SJose.Borrego@Sun.COM * winreg_s_NotifyChange 7048474SJose.Borrego@Sun.COM */ 7058474SJose.Borrego@Sun.COM static int 7068474SJose.Borrego@Sun.COM winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa) 7078474SJose.Borrego@Sun.COM { 7088474SJose.Borrego@Sun.COM struct winreg_NotifyChange *param = arg; 7098474SJose.Borrego@Sun.COM 7108474SJose.Borrego@Sun.COM if (ndr_is_admin(mxa)) 7118474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 7128474SJose.Borrego@Sun.COM else 7138474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 7148474SJose.Borrego@Sun.COM 7158474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7168474SJose.Borrego@Sun.COM } 7178474SJose.Borrego@Sun.COM 7188474SJose.Borrego@Sun.COM /* 7198474SJose.Borrego@Sun.COM * winreg_s_OpenKey 7208474SJose.Borrego@Sun.COM * 7218474SJose.Borrego@Sun.COM * This is a request to open a windows registry key. 7228474SJose.Borrego@Sun.COM * If we recognize the key, we return a handle. 7238474SJose.Borrego@Sun.COM * 7248474SJose.Borrego@Sun.COM * Returns: 7258474SJose.Borrego@Sun.COM * ERROR_SUCCESS Valid handle returned. 7268474SJose.Borrego@Sun.COM * ERROR_FILE_NOT_FOUND No key or unable to allocate a handle. 7278474SJose.Borrego@Sun.COM */ 7288474SJose.Borrego@Sun.COM static int 7298474SJose.Borrego@Sun.COM winreg_s_OpenKey(void *arg, ndr_xa_t *mxa) 7308474SJose.Borrego@Sun.COM { 7318474SJose.Borrego@Sun.COM struct winreg_OpenKey *param = arg; 7329914Samw@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 7339914Samw@Sun.COM ndr_handle_t *hd; 7348474SJose.Borrego@Sun.COM char *subkey = (char *)param->name.str; 7358474SJose.Borrego@Sun.COM winreg_subkey_t *key; 7368670SJose.Borrego@Sun.COM char *dupkey; 7378474SJose.Borrego@Sun.COM 7389914Samw@Sun.COM if (subkey == NULL || *subkey == '\0') { 7399914Samw@Sun.COM if ((hd = ndr_hdlookup(mxa, id)) != NULL) 7409914Samw@Sun.COM subkey = hd->nh_data; 7419914Samw@Sun.COM } 7429914Samw@Sun.COM 7439914Samw@Sun.COM id = NULL; 7449914Samw@Sun.COM 7458670SJose.Borrego@Sun.COM if (subkey == NULL || list_is_empty(&winreg_keylist.kl_list)) { 7468474SJose.Borrego@Sun.COM bzero(¶m->result_handle, sizeof (winreg_handle_t)); 7478474SJose.Borrego@Sun.COM param->status = ERROR_FILE_NOT_FOUND; 7488474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7498474SJose.Borrego@Sun.COM } 7508474SJose.Borrego@Sun.COM 7518474SJose.Borrego@Sun.COM key = list_head(&winreg_keylist.kl_list); 7528474SJose.Borrego@Sun.COM do { 7538474SJose.Borrego@Sun.COM if (strcasecmp(subkey, key->sk_name) == 0) { 7548670SJose.Borrego@Sun.COM if (key->sk_predefined == B_TRUE) { 7558670SJose.Borrego@Sun.COM if ((dupkey = strdup(subkey)) == NULL) 7568670SJose.Borrego@Sun.COM break; 7578670SJose.Borrego@Sun.COM 7588670SJose.Borrego@Sun.COM id = ndr_hdalloc(mxa, dupkey); 7598670SJose.Borrego@Sun.COM if (id == NULL) 7608670SJose.Borrego@Sun.COM free(dupkey); 7618670SJose.Borrego@Sun.COM } else { 7628474SJose.Borrego@Sun.COM id = &key->sk_handle; 7638670SJose.Borrego@Sun.COM } 7648474SJose.Borrego@Sun.COM 7658474SJose.Borrego@Sun.COM if (id == NULL) 7668474SJose.Borrego@Sun.COM break; 7678474SJose.Borrego@Sun.COM 7688474SJose.Borrego@Sun.COM bcopy(id, ¶m->result_handle, 7698474SJose.Borrego@Sun.COM sizeof (winreg_handle_t)); 7708474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 7718474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7728474SJose.Borrego@Sun.COM } 7738474SJose.Borrego@Sun.COM } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 7748474SJose.Borrego@Sun.COM 7758474SJose.Borrego@Sun.COM bzero(¶m->result_handle, sizeof (winreg_handle_t)); 7768474SJose.Borrego@Sun.COM param->status = ERROR_FILE_NOT_FOUND; 7778474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7788474SJose.Borrego@Sun.COM } 7798474SJose.Borrego@Sun.COM 7808474SJose.Borrego@Sun.COM /* 7818474SJose.Borrego@Sun.COM * winreg_s_QueryKey 7828474SJose.Borrego@Sun.COM */ 7838474SJose.Borrego@Sun.COM /*ARGSUSED*/ 7848474SJose.Borrego@Sun.COM static int 7858474SJose.Borrego@Sun.COM winreg_s_QueryKey(void *arg, ndr_xa_t *mxa) 7868474SJose.Borrego@Sun.COM { 7878474SJose.Borrego@Sun.COM struct winreg_QueryKey *param = arg; 7888474SJose.Borrego@Sun.COM int rc; 7898474SJose.Borrego@Sun.COM winreg_string_t *name; 7908474SJose.Borrego@Sun.COM 7918474SJose.Borrego@Sun.COM name = (winreg_string_t *)¶m->name; 7928474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_QueryKey)); 7938474SJose.Borrego@Sun.COM if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL) 7948474SJose.Borrego@Sun.COM rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name); 7958474SJose.Borrego@Sun.COM 7968474SJose.Borrego@Sun.COM if ((name == NULL) || (rc != 0)) { 7978474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_QueryKey)); 7988474SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 7998474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8008474SJose.Borrego@Sun.COM } 8018474SJose.Borrego@Sun.COM 8028474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 8038474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8048474SJose.Borrego@Sun.COM } 8058474SJose.Borrego@Sun.COM 8068474SJose.Borrego@Sun.COM /* 8078474SJose.Borrego@Sun.COM * winreg_s_QueryValue 8088474SJose.Borrego@Sun.COM * 8098474SJose.Borrego@Sun.COM * This is a request to get the value associated with a specified name. 8108474SJose.Borrego@Sun.COM * 8118474SJose.Borrego@Sun.COM * Returns: 8128474SJose.Borrego@Sun.COM * ERROR_SUCCESS Value returned. 8138474SJose.Borrego@Sun.COM * ERROR_FILE_NOT_FOUND PrimaryModule is not supported. 8148474SJose.Borrego@Sun.COM * ERROR_CANTREAD No such name or memory problem. 8158474SJose.Borrego@Sun.COM */ 8168474SJose.Borrego@Sun.COM static int 8178474SJose.Borrego@Sun.COM winreg_s_QueryValue(void *arg, ndr_xa_t *mxa) 8188474SJose.Borrego@Sun.COM { 8198474SJose.Borrego@Sun.COM struct winreg_QueryValue *param = arg; 8208474SJose.Borrego@Sun.COM struct winreg_value *pv; 8218474SJose.Borrego@Sun.COM char *name; 8228474SJose.Borrego@Sun.COM char *value; 8238474SJose.Borrego@Sun.COM DWORD slen; 8248474SJose.Borrego@Sun.COM DWORD msize; 8258474SJose.Borrego@Sun.COM 8268474SJose.Borrego@Sun.COM name = (char *)param->value_name.str; 8278474SJose.Borrego@Sun.COM 8288474SJose.Borrego@Sun.COM if (strcasecmp(name, "PrimaryModule") == 0) { 8298474SJose.Borrego@Sun.COM param->status = ERROR_FILE_NOT_FOUND; 8308474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8318474SJose.Borrego@Sun.COM } 8328474SJose.Borrego@Sun.COM 8338474SJose.Borrego@Sun.COM if ((value = winreg_lookup_value(name)) == NULL) { 8348474SJose.Borrego@Sun.COM param->status = ERROR_CANTREAD; 8358474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8368474SJose.Borrego@Sun.COM } 8378474SJose.Borrego@Sun.COM 83810966SJordan.Brown@Sun.COM slen = smb_wcequiv_strlen(value) + sizeof (smb_wchar_t); 8398474SJose.Borrego@Sun.COM msize = sizeof (struct winreg_value) + slen; 8408474SJose.Borrego@Sun.COM 8418474SJose.Borrego@Sun.COM param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize); 8428474SJose.Borrego@Sun.COM param->type = NDR_NEW(mxa, DWORD); 8438474SJose.Borrego@Sun.COM param->value_size = NDR_NEW(mxa, DWORD); 8448474SJose.Borrego@Sun.COM param->value_size_total = NDR_NEW(mxa, DWORD); 8458474SJose.Borrego@Sun.COM 8468474SJose.Borrego@Sun.COM if (param->value == NULL || param->type == NULL || 8478474SJose.Borrego@Sun.COM param->value_size == NULL || param->value_size_total == NULL) { 8488474SJose.Borrego@Sun.COM param->status = ERROR_CANTREAD; 8498474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8508474SJose.Borrego@Sun.COM } 8518474SJose.Borrego@Sun.COM 8528474SJose.Borrego@Sun.COM bzero(param->value, msize); 8538474SJose.Borrego@Sun.COM pv = param->value; 8548474SJose.Borrego@Sun.COM pv->vc_first_is = 0; 8558474SJose.Borrego@Sun.COM pv->vc_length_is = slen; 8568474SJose.Borrego@Sun.COM /*LINTED E_BAD_PTR_CAST_ALIGN*/ 85710966SJordan.Brown@Sun.COM (void) ndr_mbstowcs(NULL, (smb_wchar_t *)pv->value, value, slen); 8588474SJose.Borrego@Sun.COM 8598474SJose.Borrego@Sun.COM *param->type = 1; 8608474SJose.Borrego@Sun.COM *param->value_size = slen; 8618474SJose.Borrego@Sun.COM *param->value_size_total = slen; 8628474SJose.Borrego@Sun.COM 8638474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 8648474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8658474SJose.Borrego@Sun.COM } 8668474SJose.Borrego@Sun.COM 8678474SJose.Borrego@Sun.COM /* 8688474SJose.Borrego@Sun.COM * Lookup a name in the registry and return the associated value. 8698474SJose.Borrego@Sun.COM * Our registry is a case-insensitive, name-value pair table. 8708474SJose.Borrego@Sun.COM * 8718474SJose.Borrego@Sun.COM * Windows ProductType: WinNT, ServerNT, LanmanNT. 8728474SJose.Borrego@Sun.COM * Windows NT4.0 workstation: WinNT 8738474SJose.Borrego@Sun.COM * Windows NT4.0 server: ServerNT 8748474SJose.Borrego@Sun.COM * 8758474SJose.Borrego@Sun.COM * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy 8768474SJose.Borrego@Sun.COM * with info level 6, which we don't support. If we use ServerNT 8778474SJose.Borrego@Sun.COM * (as reported by NT4.0 Server) Windows 2000 send requests for 8788474SJose.Borrego@Sun.COM * levels 3 and 5, which are support. 8798474SJose.Borrego@Sun.COM * 8808474SJose.Borrego@Sun.COM * On success, returns a pointer to the value. Otherwise returns 8818474SJose.Borrego@Sun.COM * a null pointer. 8828474SJose.Borrego@Sun.COM */ 8838474SJose.Borrego@Sun.COM static char * 8848474SJose.Borrego@Sun.COM winreg_lookup_value(const char *name) 8858474SJose.Borrego@Sun.COM { 8868474SJose.Borrego@Sun.COM static struct registry { 8878474SJose.Borrego@Sun.COM char *name; 8888474SJose.Borrego@Sun.COM char *value; 8898474SJose.Borrego@Sun.COM } registry[] = { 89010504SKeyur.Desai@Sun.COM { "CurrentVersion", "4.0" }, 8918474SJose.Borrego@Sun.COM { "ProductType", "ServerNT" }, 8928474SJose.Borrego@Sun.COM { "Sources", NULL } /* product name */ 8938474SJose.Borrego@Sun.COM }; 8948474SJose.Borrego@Sun.COM 8958474SJose.Borrego@Sun.COM int i; 8968474SJose.Borrego@Sun.COM 8978474SJose.Borrego@Sun.COM for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) { 8988474SJose.Borrego@Sun.COM if (strcasecmp(registry[i].name, name) == 0) { 8998474SJose.Borrego@Sun.COM if (registry[i].value == NULL) 9008474SJose.Borrego@Sun.COM return (winreg_sysname); 9018474SJose.Borrego@Sun.COM else 9028474SJose.Borrego@Sun.COM return (registry[i].value); 9038474SJose.Borrego@Sun.COM } 9048474SJose.Borrego@Sun.COM } 9058474SJose.Borrego@Sun.COM 9068474SJose.Borrego@Sun.COM return (NULL); 9078474SJose.Borrego@Sun.COM } 9088474SJose.Borrego@Sun.COM 9098474SJose.Borrego@Sun.COM /* 9108474SJose.Borrego@Sun.COM * winreg_s_SetKeySec 9118474SJose.Borrego@Sun.COM */ 9128474SJose.Borrego@Sun.COM /*ARGSUSED*/ 9138474SJose.Borrego@Sun.COM static int 9148474SJose.Borrego@Sun.COM winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa) 9158474SJose.Borrego@Sun.COM { 9168474SJose.Borrego@Sun.COM struct winreg_SetKeySec *param = arg; 9178474SJose.Borrego@Sun.COM 9188474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 9198474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 9208474SJose.Borrego@Sun.COM } 9218474SJose.Borrego@Sun.COM 9228474SJose.Borrego@Sun.COM /* 9238474SJose.Borrego@Sun.COM * winreg_s_CreateValue 9248474SJose.Borrego@Sun.COM */ 9258474SJose.Borrego@Sun.COM /*ARGSUSED*/ 9268474SJose.Borrego@Sun.COM static int 9278474SJose.Borrego@Sun.COM winreg_s_CreateValue(void *arg, ndr_xa_t *mxa) 9288474SJose.Borrego@Sun.COM { 9298474SJose.Borrego@Sun.COM struct winreg_CreateValue *param = arg; 9308474SJose.Borrego@Sun.COM 9318474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 9328474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 9338474SJose.Borrego@Sun.COM } 9348474SJose.Borrego@Sun.COM 9358474SJose.Borrego@Sun.COM /* 9368474SJose.Borrego@Sun.COM * winreg_s_Shutdown 9378474SJose.Borrego@Sun.COM * 9388474SJose.Borrego@Sun.COM * Attempt to shutdown or reboot the system: access denied. 9398474SJose.Borrego@Sun.COM */ 9408474SJose.Borrego@Sun.COM /*ARGSUSED*/ 9418474SJose.Borrego@Sun.COM static int 9428474SJose.Borrego@Sun.COM winreg_s_Shutdown(void *arg, ndr_xa_t *mxa) 9438474SJose.Borrego@Sun.COM { 9448474SJose.Borrego@Sun.COM struct winreg_Shutdown *param = arg; 9458474SJose.Borrego@Sun.COM 9468474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 9478474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 9488474SJose.Borrego@Sun.COM } 9498474SJose.Borrego@Sun.COM 9508474SJose.Borrego@Sun.COM /* 9518474SJose.Borrego@Sun.COM * winreg_s_AbortShutdown 9528474SJose.Borrego@Sun.COM * 9538474SJose.Borrego@Sun.COM * Abort a shutdown request. 9548474SJose.Borrego@Sun.COM */ 9558474SJose.Borrego@Sun.COM static int 9568474SJose.Borrego@Sun.COM winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa) 9578474SJose.Borrego@Sun.COM { 9588474SJose.Borrego@Sun.COM struct winreg_AbortShutdown *param = arg; 9598474SJose.Borrego@Sun.COM 9608474SJose.Borrego@Sun.COM if (ndr_is_admin(mxa)) 9618474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 9628474SJose.Borrego@Sun.COM else 9638474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 9648474SJose.Borrego@Sun.COM 9658474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 9668474SJose.Borrego@Sun.COM } 9678474SJose.Borrego@Sun.COM 9688474SJose.Borrego@Sun.COM /* 9698474SJose.Borrego@Sun.COM * winreg_s_GetVersion 9708474SJose.Borrego@Sun.COM * 9718474SJose.Borrego@Sun.COM * Return the windows registry version. The current version is 5. 9728474SJose.Borrego@Sun.COM * This call is usually made prior to enumerating or querying registry 9738474SJose.Borrego@Sun.COM * keys or values. 9748474SJose.Borrego@Sun.COM */ 9758474SJose.Borrego@Sun.COM /*ARGSUSED*/ 9768474SJose.Borrego@Sun.COM static int 9778474SJose.Borrego@Sun.COM winreg_s_GetVersion(void *arg, ndr_xa_t *mxa) 9788474SJose.Borrego@Sun.COM { 9798474SJose.Borrego@Sun.COM struct winreg_GetVersion *param = arg; 9808474SJose.Borrego@Sun.COM 9818474SJose.Borrego@Sun.COM param->version = 5; 9828474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 9838474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 9848474SJose.Borrego@Sun.COM } 985