189dc44ceSjose borrego /* 289dc44ceSjose borrego * CDDL HEADER START 389dc44ceSjose borrego * 489dc44ceSjose borrego * The contents of this file are subject to the terms of the 589dc44ceSjose borrego * Common Development and Distribution License (the "License"). 689dc44ceSjose borrego * You may not use this file except in compliance with the License. 789dc44ceSjose borrego * 889dc44ceSjose borrego * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 989dc44ceSjose borrego * or http://www.opensolaris.org/os/licensing. 1089dc44ceSjose borrego * See the License for the specific language governing permissions 1189dc44ceSjose borrego * and limitations under the License. 1289dc44ceSjose borrego * 1389dc44ceSjose borrego * When distributing Covered Code, include this CDDL HEADER in each 1489dc44ceSjose borrego * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1589dc44ceSjose borrego * If applicable, add the following below this CDDL HEADER, with the 1689dc44ceSjose borrego * fields enclosed by brackets "[]" replaced with your own identifying 1789dc44ceSjose borrego * information: Portions Copyright [yyyy] [name of copyright owner] 1889dc44ceSjose borrego * 1989dc44ceSjose borrego * CDDL HEADER END 2089dc44ceSjose borrego */ 2189dc44ceSjose borrego /* 22f96bd5c8SAlan Wright * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2389dc44ceSjose borrego * Use is subject to license terms. 2489dc44ceSjose borrego */ 2589dc44ceSjose borrego 2689dc44ceSjose borrego /* 2789dc44ceSjose borrego * Windows Registry RPC (WINREG) server-side interface. 2889dc44ceSjose borrego * 297f667e74Sjose borrego * The registry is a database with a hierarchical structure similar to 307f667e74Sjose borrego * a file system, with keys in place of directories and values in place 317f667e74Sjose borrego * of files. The top level keys are known as root keys and each key can 327f667e74Sjose borrego * contain subkeys and values. As with directories and sub-directories, 337f667e74Sjose borrego * the terms key and subkey are used interchangeably. Values, analogous 347f667e74Sjose borrego * to files, contain data. 3589dc44ceSjose borrego * 367f667e74Sjose borrego * A specific subkey can be identifies by its fully qualified name (FQN), 377f667e74Sjose borrego * which is analogous to a file system path. In the registry, the key 387f667e74Sjose borrego * separator is the '\' character, which is reserved and cannot appear 397f667e74Sjose borrego * in key or value names. Registry names are case-insensitive. 407f667e74Sjose borrego * 417f667e74Sjose borrego * For example: HKEY_LOCAL_MACHINE\System\CurrentControlSet 427f667e74Sjose borrego * 43b1352070SAlan Wright * The HKEY_LOCAL_MACHINE root key contains a subkey called System, and 447f667e74Sjose borrego * System contains a subkey called CurrentControlSet. 457f667e74Sjose borrego * 467f667e74Sjose borrego * The WINREG RPC interface returns Win32 error codes. 4789dc44ceSjose borrego */ 4889dc44ceSjose borrego 4989dc44ceSjose borrego #include <sys/utsname.h> 5089dc44ceSjose borrego #include <strings.h> 5189dc44ceSjose borrego 5289dc44ceSjose borrego #include <smbsrv/libsmb.h> 5389dc44ceSjose borrego #include <smbsrv/ntstatus.h> 5489dc44ceSjose borrego #include <smbsrv/nterror.h> 5589dc44ceSjose borrego #include <smbsrv/nmpipes.h> 5689dc44ceSjose borrego #include <smbsrv/libmlsvc.h> 5789dc44ceSjose borrego #include <smbsrv/ndl/winreg.ndl> 5889dc44ceSjose borrego 5989dc44ceSjose borrego /* 6089dc44ceSjose borrego * List of supported registry keys (case-insensitive). 6189dc44ceSjose borrego */ 6289dc44ceSjose borrego static char *winreg_keys[] = { 63b1352070SAlan Wright "HKLM", 64b1352070SAlan Wright "HKU", 65b1352070SAlan Wright "HKLM\\SOFTWARE", 66b1352070SAlan Wright "HKLM\\SYSTEM", 67e3f2c991SKeyur Desai "Application", 68e3f2c991SKeyur Desai "Security", 69b1352070SAlan Wright "System", 70b1352070SAlan Wright "CurrentControlSet", 7189dc44ceSjose borrego "System\\CurrentControlSet\\Services\\Eventlog", 727f667e74Sjose borrego "System\\CurrentControlSet\\Services\\Eventlog\\Application", 737f667e74Sjose borrego "System\\CurrentControlSet\\Services\\Eventlog\\Security", 7489dc44ceSjose borrego "System\\CurrentControlSet\\Services\\Eventlog\\System", 7589dc44ceSjose borrego "System\\CurrentControlSet\\Control\\ProductOptions", 76b1352070SAlan Wright "SOFTWARE", 7789dc44ceSjose borrego "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" 7889dc44ceSjose borrego }; 7989dc44ceSjose borrego 8089dc44ceSjose borrego typedef struct winreg_subkey { 8189dc44ceSjose borrego list_node_t sk_lnd; 8289dc44ceSjose borrego ndr_hdid_t sk_handle; 8389dc44ceSjose borrego char sk_name[MAXPATHLEN]; 8489dc44ceSjose borrego boolean_t sk_predefined; 8589dc44ceSjose borrego } winreg_subkey_t; 8689dc44ceSjose borrego 8789dc44ceSjose borrego typedef struct winreg_keylist { 8889dc44ceSjose borrego list_t kl_list; 8989dc44ceSjose borrego int kl_count; 9089dc44ceSjose borrego } winreg_keylist_t; 9189dc44ceSjose borrego 9289dc44ceSjose borrego static winreg_keylist_t winreg_keylist; 9389dc44ceSjose borrego 9489dc44ceSjose borrego static boolean_t winreg_key_has_subkey(const char *); 957f667e74Sjose borrego static char *winreg_enum_subkey(ndr_xa_t *, const char *, uint32_t); 9689dc44ceSjose borrego static char *winreg_lookup_value(const char *); 97f96bd5c8SAlan Wright static uint32_t winreg_sd_format(smb_sd_t *); 98f96bd5c8SAlan Wright uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *); 9989dc44ceSjose borrego 1007f667e74Sjose borrego static int winreg_s_OpenHKCR(void *, ndr_xa_t *); 1017f667e74Sjose borrego static int winreg_s_OpenHKCU(void *, ndr_xa_t *); 10289dc44ceSjose borrego static int winreg_s_OpenHKLM(void *, ndr_xa_t *); 1037f667e74Sjose borrego static int winreg_s_OpenHKPD(void *, ndr_xa_t *); 1047f667e74Sjose borrego static int winreg_s_OpenHKU(void *, ndr_xa_t *); 1057f667e74Sjose borrego static int winreg_s_OpenHKCC(void *, ndr_xa_t *); 1067f667e74Sjose borrego static int winreg_s_OpenHKDD(void *, ndr_xa_t *); 1077f667e74Sjose borrego static int winreg_s_OpenHKPT(void *, ndr_xa_t *); 1087f667e74Sjose borrego static int winreg_s_OpenHKPN(void *, ndr_xa_t *); 1097f667e74Sjose borrego static int winreg_s_OpenHK(void *, ndr_xa_t *, const char *); 11089dc44ceSjose borrego static int winreg_s_Close(void *, ndr_xa_t *); 11189dc44ceSjose borrego static int winreg_s_CreateKey(void *, ndr_xa_t *); 11289dc44ceSjose borrego static int winreg_s_DeleteKey(void *, ndr_xa_t *); 11389dc44ceSjose borrego static int winreg_s_DeleteValue(void *, ndr_xa_t *); 11489dc44ceSjose borrego static int winreg_s_EnumKey(void *, ndr_xa_t *); 11589dc44ceSjose borrego static int winreg_s_EnumValue(void *, ndr_xa_t *); 11689dc44ceSjose borrego static int winreg_s_FlushKey(void *, ndr_xa_t *); 11789dc44ceSjose borrego static int winreg_s_GetKeySec(void *, ndr_xa_t *); 11889dc44ceSjose borrego static int winreg_s_NotifyChange(void *, ndr_xa_t *); 11989dc44ceSjose borrego static int winreg_s_OpenKey(void *, ndr_xa_t *); 12089dc44ceSjose borrego static int winreg_s_QueryKey(void *, ndr_xa_t *); 12189dc44ceSjose borrego static int winreg_s_QueryValue(void *, ndr_xa_t *); 12289dc44ceSjose borrego static int winreg_s_SetKeySec(void *, ndr_xa_t *); 12389dc44ceSjose borrego static int winreg_s_CreateValue(void *, ndr_xa_t *); 12489dc44ceSjose borrego static int winreg_s_Shutdown(void *, ndr_xa_t *); 12589dc44ceSjose borrego static int winreg_s_AbortShutdown(void *, ndr_xa_t *); 12689dc44ceSjose borrego static int winreg_s_GetVersion(void *, ndr_xa_t *); 12789dc44ceSjose borrego 12889dc44ceSjose borrego static ndr_stub_table_t winreg_stub_table[] = { 1297f667e74Sjose borrego { winreg_s_OpenHKCR, WINREG_OPNUM_OpenHKCR }, 1307f667e74Sjose borrego { winreg_s_OpenHKCU, WINREG_OPNUM_OpenHKCU }, 13189dc44ceSjose borrego { winreg_s_OpenHKLM, WINREG_OPNUM_OpenHKLM }, 1327f667e74Sjose borrego { winreg_s_OpenHKPD, WINREG_OPNUM_OpenHKPD }, 1337f667e74Sjose borrego { winreg_s_OpenHKU, WINREG_OPNUM_OpenHKUsers }, 13489dc44ceSjose borrego { winreg_s_Close, WINREG_OPNUM_Close }, 13589dc44ceSjose borrego { winreg_s_CreateKey, WINREG_OPNUM_CreateKey }, 13689dc44ceSjose borrego { winreg_s_DeleteKey, WINREG_OPNUM_DeleteKey }, 13789dc44ceSjose borrego { winreg_s_DeleteValue, WINREG_OPNUM_DeleteValue }, 13889dc44ceSjose borrego { winreg_s_EnumKey, WINREG_OPNUM_EnumKey }, 13989dc44ceSjose borrego { winreg_s_EnumValue, WINREG_OPNUM_EnumValue }, 14089dc44ceSjose borrego { winreg_s_FlushKey, WINREG_OPNUM_FlushKey }, 14189dc44ceSjose borrego { winreg_s_GetKeySec, WINREG_OPNUM_GetKeySec }, 14289dc44ceSjose borrego { winreg_s_NotifyChange, WINREG_OPNUM_NotifyChange }, 14389dc44ceSjose borrego { winreg_s_OpenKey, WINREG_OPNUM_OpenKey }, 14489dc44ceSjose borrego { winreg_s_QueryKey, WINREG_OPNUM_QueryKey }, 14589dc44ceSjose borrego { winreg_s_QueryValue, WINREG_OPNUM_QueryValue }, 14689dc44ceSjose borrego { winreg_s_SetKeySec, WINREG_OPNUM_SetKeySec }, 14789dc44ceSjose borrego { winreg_s_CreateValue, WINREG_OPNUM_CreateValue }, 14889dc44ceSjose borrego { winreg_s_Shutdown, WINREG_OPNUM_Shutdown }, 14989dc44ceSjose borrego { winreg_s_AbortShutdown, WINREG_OPNUM_AbortShutdown }, 15089dc44ceSjose borrego { winreg_s_GetVersion, WINREG_OPNUM_GetVersion }, 1517f667e74Sjose borrego { winreg_s_OpenHKCC, WINREG_OPNUM_OpenHKCC }, 1527f667e74Sjose borrego { winreg_s_OpenHKDD, WINREG_OPNUM_OpenHKDD }, 1537f667e74Sjose borrego { winreg_s_OpenHKPT, WINREG_OPNUM_OpenHKPT }, 1547f667e74Sjose borrego { winreg_s_OpenHKPN, WINREG_OPNUM_OpenHKPN }, 15589dc44ceSjose borrego {0} 15689dc44ceSjose borrego }; 15789dc44ceSjose borrego 15889dc44ceSjose borrego static ndr_service_t winreg_service = { 15989dc44ceSjose borrego "Winreg", /* name */ 16089dc44ceSjose borrego "Windows Registry", /* desc */ 16189dc44ceSjose borrego "\\winreg", /* endpoint */ 16289dc44ceSjose borrego PIPE_WINREG, /* sec_addr_port */ 16389dc44ceSjose borrego "338cd001-2244-31f1-aaaa-900038001003", 1, /* abstract */ 16489dc44ceSjose borrego NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ 16589dc44ceSjose borrego 0, /* no bind_instance_size */ 16689dc44ceSjose borrego 0, /* no bind_req() */ 16789dc44ceSjose borrego 0, /* no unbind_and_close() */ 16889dc44ceSjose borrego 0, /* use generic_call_stub() */ 16989dc44ceSjose borrego &TYPEINFO(winreg_interface), /* interface ti */ 17089dc44ceSjose borrego winreg_stub_table /* stub_table */ 17189dc44ceSjose borrego }; 17289dc44ceSjose borrego 17389dc44ceSjose borrego static char winreg_sysname[SYS_NMLN]; 17489dc44ceSjose borrego 17589dc44ceSjose borrego /* 17689dc44ceSjose borrego * winreg_initialize 17789dc44ceSjose borrego * 17889dc44ceSjose borrego * Initialize and register the WINREG RPC interface with the RPC runtime 17989dc44ceSjose borrego * library. It must be called in order to use either the client side 18089dc44ceSjose borrego * or the server side functions. 18189dc44ceSjose borrego */ 18289dc44ceSjose borrego void 18389dc44ceSjose borrego winreg_initialize(void) 18489dc44ceSjose borrego { 18589dc44ceSjose borrego winreg_subkey_t *key; 18689dc44ceSjose borrego struct utsname name; 18789dc44ceSjose borrego char *sysname; 18889dc44ceSjose borrego int i; 18989dc44ceSjose borrego 19089dc44ceSjose borrego list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t), 19189dc44ceSjose borrego offsetof(winreg_subkey_t, sk_lnd)); 19289dc44ceSjose borrego winreg_keylist.kl_count = 0; 19389dc44ceSjose borrego 19489dc44ceSjose borrego for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) { 19589dc44ceSjose borrego if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) { 19689dc44ceSjose borrego bzero(key, sizeof (winreg_subkey_t)); 19789dc44ceSjose borrego (void) strlcpy(key->sk_name, winreg_keys[i], 19889dc44ceSjose borrego MAXPATHLEN); 19989dc44ceSjose borrego key->sk_predefined = B_TRUE; 20089dc44ceSjose borrego list_insert_tail(&winreg_keylist.kl_list, key); 20189dc44ceSjose borrego ++winreg_keylist.kl_count; 20289dc44ceSjose borrego } 20389dc44ceSjose borrego } 20489dc44ceSjose borrego 20589dc44ceSjose borrego if (uname(&name) < 0) 20689dc44ceSjose borrego sysname = "Solaris"; 20789dc44ceSjose borrego else 20889dc44ceSjose borrego sysname = name.sysname; 20989dc44ceSjose borrego 21089dc44ceSjose borrego (void) strlcpy(winreg_sysname, sysname, SYS_NMLN); 21189dc44ceSjose borrego (void) ndr_svc_register(&winreg_service); 21289dc44ceSjose borrego } 21389dc44ceSjose borrego 21489dc44ceSjose borrego static int 2157f667e74Sjose borrego winreg_s_OpenHKCR(void *arg, ndr_xa_t *mxa) 21689dc44ceSjose borrego { 2177f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKCR")); 21889dc44ceSjose borrego } 21989dc44ceSjose borrego 2207f667e74Sjose borrego static int 2217f667e74Sjose borrego winreg_s_OpenHKCU(void *arg, ndr_xa_t *mxa) 2227f667e74Sjose borrego { 2237f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKCU")); 22489dc44ceSjose borrego } 22589dc44ceSjose borrego 22689dc44ceSjose borrego static int 22789dc44ceSjose borrego winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa) 22889dc44ceSjose borrego { 2297f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKLM")); 23089dc44ceSjose borrego } 23189dc44ceSjose borrego 2327f667e74Sjose borrego static int 2337f667e74Sjose borrego winreg_s_OpenHKPD(void *arg, ndr_xa_t *mxa) 2347f667e74Sjose borrego { 2357f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKPD")); 2367f667e74Sjose borrego } 2377f667e74Sjose borrego 2387f667e74Sjose borrego static int 2397f667e74Sjose borrego winreg_s_OpenHKU(void *arg, ndr_xa_t *mxa) 2407f667e74Sjose borrego { 2417f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKU")); 2427f667e74Sjose borrego } 2437f667e74Sjose borrego 2447f667e74Sjose borrego static int 2457f667e74Sjose borrego winreg_s_OpenHKCC(void *arg, ndr_xa_t *mxa) 2467f667e74Sjose borrego { 2477f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKCC")); 2487f667e74Sjose borrego } 2497f667e74Sjose borrego 2507f667e74Sjose borrego static int 2517f667e74Sjose borrego winreg_s_OpenHKDD(void *arg, ndr_xa_t *mxa) 2527f667e74Sjose borrego { 2537f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKDD")); 2547f667e74Sjose borrego } 2557f667e74Sjose borrego 2567f667e74Sjose borrego static int 2577f667e74Sjose borrego winreg_s_OpenHKPT(void *arg, ndr_xa_t *mxa) 2587f667e74Sjose borrego { 2597f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKPT")); 2607f667e74Sjose borrego } 2617f667e74Sjose borrego 2627f667e74Sjose borrego static int 2637f667e74Sjose borrego winreg_s_OpenHKPN(void *arg, ndr_xa_t *mxa) 2647f667e74Sjose borrego { 2657f667e74Sjose borrego return (winreg_s_OpenHK(arg, mxa, "HKPN")); 26689dc44ceSjose borrego } 26789dc44ceSjose borrego 26889dc44ceSjose borrego /* 2697f667e74Sjose borrego * winreg_s_OpenHK 27089dc44ceSjose borrego * 2717f667e74Sjose borrego * Common code to open root HKEYs. 27289dc44ceSjose borrego */ 27389dc44ceSjose borrego static int 2747f667e74Sjose borrego winreg_s_OpenHK(void *arg, ndr_xa_t *mxa, const char *hkey) 27589dc44ceSjose borrego { 2767f667e74Sjose borrego struct winreg_OpenHKCR *param = arg; 27789dc44ceSjose borrego ndr_hdid_t *id; 2787f667e74Sjose borrego char *dupkey; 27989dc44ceSjose borrego 2807f667e74Sjose borrego if ((dupkey = strdup(hkey)) == NULL) { 2817f667e74Sjose borrego bzero(¶m->handle, sizeof (winreg_handle_t)); 2827f667e74Sjose borrego param->status = ERROR_NOT_ENOUGH_MEMORY; 2837f667e74Sjose borrego return (NDR_DRC_OK); 2847f667e74Sjose borrego } 2857f667e74Sjose borrego 2867f667e74Sjose borrego if ((id = ndr_hdalloc(mxa, dupkey)) == NULL) { 2877f667e74Sjose borrego free(dupkey); 28889dc44ceSjose borrego bzero(¶m->handle, sizeof (winreg_handle_t)); 28989dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 29089dc44ceSjose borrego } else { 29189dc44ceSjose borrego bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); 29289dc44ceSjose borrego param->status = ERROR_SUCCESS; 29389dc44ceSjose borrego } 29489dc44ceSjose borrego 29589dc44ceSjose borrego return (NDR_DRC_OK); 29689dc44ceSjose borrego } 29789dc44ceSjose borrego 29889dc44ceSjose borrego /* 29989dc44ceSjose borrego * winreg_s_Close 30089dc44ceSjose borrego * 30189dc44ceSjose borrego * This is a request to close the WINREG interface specified by the 30289dc44ceSjose borrego * handle. We don't track handles (yet), so just zero out the handle 30389dc44ceSjose borrego * and return NDR_DRC_OK. Setting the handle to zero appears to be 30489dc44ceSjose borrego * standard behaviour. 30589dc44ceSjose borrego */ 30689dc44ceSjose borrego static int 30789dc44ceSjose borrego winreg_s_Close(void *arg, ndr_xa_t *mxa) 30889dc44ceSjose borrego { 30989dc44ceSjose borrego struct winreg_Close *param = arg; 31089dc44ceSjose borrego ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 3117f667e74Sjose borrego ndr_handle_t *hd; 3127f667e74Sjose borrego 3137f667e74Sjose borrego if ((hd = ndr_hdlookup(mxa, id)) != NULL) { 3147f667e74Sjose borrego free(hd->nh_data); 3157f667e74Sjose borrego hd->nh_data = NULL; 3167f667e74Sjose borrego } 31789dc44ceSjose borrego 31889dc44ceSjose borrego ndr_hdfree(mxa, id); 31989dc44ceSjose borrego 32089dc44ceSjose borrego bzero(¶m->result_handle, sizeof (winreg_handle_t)); 32189dc44ceSjose borrego param->status = ERROR_SUCCESS; 32289dc44ceSjose borrego return (NDR_DRC_OK); 32389dc44ceSjose borrego } 32489dc44ceSjose borrego 32589dc44ceSjose borrego /* 32689dc44ceSjose borrego * winreg_s_CreateKey 32789dc44ceSjose borrego */ 32889dc44ceSjose borrego static int 32989dc44ceSjose borrego winreg_s_CreateKey(void *arg, ndr_xa_t *mxa) 33089dc44ceSjose borrego { 33189dc44ceSjose borrego struct winreg_CreateKey *param = arg; 33289dc44ceSjose borrego ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 33389dc44ceSjose borrego ndr_handle_t *hd; 33489dc44ceSjose borrego winreg_subkey_t *key; 33589dc44ceSjose borrego char *subkey; 3367f667e74Sjose borrego char *dupkey; 33789dc44ceSjose borrego DWORD *action; 33889dc44ceSjose borrego 33989dc44ceSjose borrego subkey = (char *)param->subkey.str; 34089dc44ceSjose borrego 34189dc44ceSjose borrego if (!ndr_is_admin(mxa) || (subkey == NULL)) { 34289dc44ceSjose borrego bzero(param, sizeof (struct winreg_CreateKey)); 34389dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 34489dc44ceSjose borrego return (NDR_DRC_OK); 34589dc44ceSjose borrego } 34689dc44ceSjose borrego 34789dc44ceSjose borrego hd = ndr_hdlookup(mxa, id); 34889dc44ceSjose borrego if (hd == NULL) { 34989dc44ceSjose borrego bzero(param, sizeof (struct winreg_CreateKey)); 35089dc44ceSjose borrego param->status = ERROR_INVALID_HANDLE; 35189dc44ceSjose borrego return (NDR_DRC_OK); 35289dc44ceSjose borrego } 35389dc44ceSjose borrego 35489dc44ceSjose borrego if ((action = NDR_NEW(mxa, DWORD)) == NULL) { 35589dc44ceSjose borrego bzero(param, sizeof (struct winreg_CreateKey)); 35689dc44ceSjose borrego param->status = ERROR_NOT_ENOUGH_MEMORY; 35789dc44ceSjose borrego return (NDR_DRC_OK); 35889dc44ceSjose borrego } 35989dc44ceSjose borrego 36089dc44ceSjose borrego if (list_is_empty(&winreg_keylist.kl_list)) 36189dc44ceSjose borrego goto new_key; 36289dc44ceSjose borrego 36389dc44ceSjose borrego /* 36489dc44ceSjose borrego * Check for an existing key. 36589dc44ceSjose borrego */ 36689dc44ceSjose borrego key = list_head(&winreg_keylist.kl_list); 36789dc44ceSjose borrego do { 36889dc44ceSjose borrego if (strcasecmp(subkey, key->sk_name) == 0) { 36989dc44ceSjose borrego bcopy(&key->sk_handle, ¶m->result_handle, 37089dc44ceSjose borrego sizeof (winreg_handle_t)); 37189dc44ceSjose borrego *action = WINREG_ACTION_EXISTING_KEY; 37289dc44ceSjose borrego param->action = action; 37389dc44ceSjose borrego param->status = ERROR_SUCCESS; 37489dc44ceSjose borrego return (NDR_DRC_OK); 37589dc44ceSjose borrego } 37689dc44ceSjose borrego } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 37789dc44ceSjose borrego 37889dc44ceSjose borrego new_key: 37989dc44ceSjose borrego /* 38089dc44ceSjose borrego * Create a new key. 38189dc44ceSjose borrego */ 3827f667e74Sjose borrego if ((dupkey = strdup(subkey)) == NULL) { 3837f667e74Sjose borrego bzero(param, sizeof (struct winreg_CreateKey)); 3847f667e74Sjose borrego param->status = ERROR_NOT_ENOUGH_MEMORY; 3857f667e74Sjose borrego return (NDR_DRC_OK); 3867f667e74Sjose borrego } 3877f667e74Sjose borrego 3887f667e74Sjose borrego id = ndr_hdalloc(mxa, dupkey); 38989dc44ceSjose borrego key = malloc(sizeof (winreg_subkey_t)); 39089dc44ceSjose borrego 39189dc44ceSjose borrego if ((id == NULL) || (key == NULL)) { 3927f667e74Sjose borrego free(dupkey); 39389dc44ceSjose borrego bzero(param, sizeof (struct winreg_CreateKey)); 39489dc44ceSjose borrego param->status = ERROR_NOT_ENOUGH_MEMORY; 39589dc44ceSjose borrego return (NDR_DRC_OK); 39689dc44ceSjose borrego } 39789dc44ceSjose borrego 39889dc44ceSjose borrego bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t)); 39989dc44ceSjose borrego (void) strlcpy(key->sk_name, subkey, MAXPATHLEN); 40089dc44ceSjose borrego key->sk_predefined = B_FALSE; 40189dc44ceSjose borrego list_insert_tail(&winreg_keylist.kl_list, key); 40289dc44ceSjose borrego ++winreg_keylist.kl_count; 40389dc44ceSjose borrego 40489dc44ceSjose borrego bcopy(id, ¶m->result_handle, sizeof (winreg_handle_t)); 40589dc44ceSjose borrego *action = WINREG_ACTION_NEW_KEY; 40689dc44ceSjose borrego param->action = action; 40789dc44ceSjose borrego param->status = ERROR_SUCCESS; 40889dc44ceSjose borrego return (NDR_DRC_OK); 40989dc44ceSjose borrego } 41089dc44ceSjose borrego 41189dc44ceSjose borrego /* 41289dc44ceSjose borrego * winreg_s_DeleteKey 41389dc44ceSjose borrego */ 41489dc44ceSjose borrego static int 41589dc44ceSjose borrego winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa) 41689dc44ceSjose borrego { 41789dc44ceSjose borrego struct winreg_DeleteKey *param = arg; 41889dc44ceSjose borrego ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 4197f667e74Sjose borrego ndr_handle_t *hd; 42089dc44ceSjose borrego winreg_subkey_t *key; 42189dc44ceSjose borrego char *subkey; 42289dc44ceSjose borrego 42389dc44ceSjose borrego subkey = (char *)param->subkey.str; 42489dc44ceSjose borrego 42589dc44ceSjose borrego if (!ndr_is_admin(mxa) || (subkey == NULL)) { 42689dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 42789dc44ceSjose borrego return (NDR_DRC_OK); 42889dc44ceSjose borrego } 42989dc44ceSjose borrego 43089dc44ceSjose borrego if ((ndr_hdlookup(mxa, id) == NULL) || 43189dc44ceSjose borrego list_is_empty(&winreg_keylist.kl_list) || 43289dc44ceSjose borrego winreg_key_has_subkey(subkey)) { 43389dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 43489dc44ceSjose borrego return (NDR_DRC_OK); 43589dc44ceSjose borrego } 43689dc44ceSjose borrego 43789dc44ceSjose borrego key = list_head(&winreg_keylist.kl_list); 43889dc44ceSjose borrego do { 43989dc44ceSjose borrego if (strcasecmp(subkey, key->sk_name) == 0) { 44089dc44ceSjose borrego if (key->sk_predefined == B_TRUE) { 44189dc44ceSjose borrego /* Predefined keys cannot be deleted */ 44289dc44ceSjose borrego break; 44389dc44ceSjose borrego } 44489dc44ceSjose borrego 44589dc44ceSjose borrego list_remove(&winreg_keylist.kl_list, key); 44689dc44ceSjose borrego --winreg_keylist.kl_count; 4477f667e74Sjose borrego 4487f667e74Sjose borrego hd = ndr_hdlookup(mxa, &key->sk_handle); 4497f667e74Sjose borrego if (hd != NULL) { 4507f667e74Sjose borrego free(hd->nh_data); 4517f667e74Sjose borrego hd->nh_data = NULL; 4527f667e74Sjose borrego } 4537f667e74Sjose borrego 45489dc44ceSjose borrego ndr_hdfree(mxa, &key->sk_handle); 45589dc44ceSjose borrego free(key); 45689dc44ceSjose borrego param->status = ERROR_SUCCESS; 45789dc44ceSjose borrego return (NDR_DRC_OK); 45889dc44ceSjose borrego } 45989dc44ceSjose borrego } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 46089dc44ceSjose borrego 46189dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 46289dc44ceSjose borrego return (NDR_DRC_OK); 46389dc44ceSjose borrego } 46489dc44ceSjose borrego 46589dc44ceSjose borrego static boolean_t 46689dc44ceSjose borrego winreg_key_has_subkey(const char *subkey) 46789dc44ceSjose borrego { 46889dc44ceSjose borrego winreg_subkey_t *key; 46989dc44ceSjose borrego int keylen; 47089dc44ceSjose borrego 47189dc44ceSjose borrego if (list_is_empty(&winreg_keylist.kl_list)) 47289dc44ceSjose borrego return (B_FALSE); 47389dc44ceSjose borrego 47489dc44ceSjose borrego keylen = strlen(subkey); 47589dc44ceSjose borrego 47689dc44ceSjose borrego key = list_head(&winreg_keylist.kl_list); 47789dc44ceSjose borrego do { 47889dc44ceSjose borrego if (strncasecmp(subkey, key->sk_name, keylen) == 0) { 47989dc44ceSjose borrego /* 48089dc44ceSjose borrego * Potential match. If sk_name is longer than 48189dc44ceSjose borrego * subkey, then sk_name is a subkey of our key. 48289dc44ceSjose borrego */ 48389dc44ceSjose borrego if (keylen < strlen(key->sk_name)) 48489dc44ceSjose borrego return (B_TRUE); 48589dc44ceSjose borrego } 48689dc44ceSjose borrego } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 48789dc44ceSjose borrego 48889dc44ceSjose borrego return (B_FALSE); 48989dc44ceSjose borrego } 49089dc44ceSjose borrego 49189dc44ceSjose borrego static char * 4927f667e74Sjose borrego winreg_enum_subkey(ndr_xa_t *mxa, const char *subkey, uint32_t index) 49389dc44ceSjose borrego { 49489dc44ceSjose borrego winreg_subkey_t *key; 4957f667e74Sjose borrego char *entry; 4967f667e74Sjose borrego char *p; 4977f667e74Sjose borrego int subkeylen; 4987f667e74Sjose borrego int count = 0; 49989dc44ceSjose borrego 50089dc44ceSjose borrego if (subkey == NULL) 50189dc44ceSjose borrego return (NULL); 50289dc44ceSjose borrego 50389dc44ceSjose borrego if (list_is_empty(&winreg_keylist.kl_list)) 50489dc44ceSjose borrego return (NULL); 50589dc44ceSjose borrego 5067f667e74Sjose borrego subkeylen = strlen(subkey); 5077f667e74Sjose borrego 5087f667e74Sjose borrego for (key = list_head(&winreg_keylist.kl_list); 5097f667e74Sjose borrego key != NULL; key = list_next(&winreg_keylist.kl_list, key)) { 5107f667e74Sjose borrego if (strncasecmp(subkey, key->sk_name, subkeylen) == 0) { 5117f667e74Sjose borrego p = key->sk_name + subkeylen; 5127f667e74Sjose borrego 5137f667e74Sjose borrego if ((*p != '\\') || (*p == '\0')) { 5147f667e74Sjose borrego /* 5157f667e74Sjose borrego * Not the same subkey or an exact match. 5167f667e74Sjose borrego * We're looking for children of subkey. 5177f667e74Sjose borrego */ 5187f667e74Sjose borrego continue; 51989dc44ceSjose borrego } 5207f667e74Sjose borrego 5217f667e74Sjose borrego ++p; 5227f667e74Sjose borrego 5237f667e74Sjose borrego if (count < index) { 5247f667e74Sjose borrego ++count; 5257f667e74Sjose borrego continue; 5267f667e74Sjose borrego } 5277f667e74Sjose borrego 5287f667e74Sjose borrego if ((entry = NDR_STRDUP(mxa, p)) == NULL) 5297f667e74Sjose borrego return (NULL); 5307f667e74Sjose borrego 5317f667e74Sjose borrego if ((p = strchr(entry, '\\')) != NULL) 5327f667e74Sjose borrego *p = '\0'; 5337f667e74Sjose borrego 5347f667e74Sjose borrego return (entry); 5357f667e74Sjose borrego } 5367f667e74Sjose borrego } 53789dc44ceSjose borrego 53889dc44ceSjose borrego return (NULL); 53989dc44ceSjose borrego } 54089dc44ceSjose borrego 54189dc44ceSjose borrego /* 54289dc44ceSjose borrego * winreg_s_DeleteValue 54389dc44ceSjose borrego */ 54489dc44ceSjose borrego /*ARGSUSED*/ 54589dc44ceSjose borrego static int 54689dc44ceSjose borrego winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa) 54789dc44ceSjose borrego { 54889dc44ceSjose borrego struct winreg_DeleteValue *param = arg; 54989dc44ceSjose borrego 55089dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 55189dc44ceSjose borrego return (NDR_DRC_OK); 55289dc44ceSjose borrego } 55389dc44ceSjose borrego 55489dc44ceSjose borrego /* 55589dc44ceSjose borrego * winreg_s_EnumKey 55689dc44ceSjose borrego */ 55789dc44ceSjose borrego static int 55889dc44ceSjose borrego winreg_s_EnumKey(void *arg, ndr_xa_t *mxa) 55989dc44ceSjose borrego { 56089dc44ceSjose borrego struct winreg_EnumKey *param = arg; 56189dc44ceSjose borrego ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 5627f667e74Sjose borrego ndr_handle_t *hd; 5637f667e74Sjose borrego char *subkey; 5647f667e74Sjose borrego char *name = NULL; 56589dc44ceSjose borrego 5667f667e74Sjose borrego if ((hd = ndr_hdlookup(mxa, id)) != NULL) 5677f667e74Sjose borrego name = hd->nh_data; 5687f667e74Sjose borrego 5697f667e74Sjose borrego if (hd == NULL || name == NULL) { 57089dc44ceSjose borrego bzero(param, sizeof (struct winreg_EnumKey)); 57189dc44ceSjose borrego param->status = ERROR_NO_MORE_ITEMS; 57289dc44ceSjose borrego return (NDR_DRC_OK); 57389dc44ceSjose borrego } 57489dc44ceSjose borrego 5757f667e74Sjose borrego subkey = winreg_enum_subkey(mxa, name, param->index); 5767f667e74Sjose borrego if (subkey == NULL) { 57789dc44ceSjose borrego bzero(param, sizeof (struct winreg_EnumKey)); 57889dc44ceSjose borrego param->status = ERROR_NO_MORE_ITEMS; 57989dc44ceSjose borrego return (NDR_DRC_OK); 58089dc44ceSjose borrego } 58189dc44ceSjose borrego 5827f667e74Sjose borrego if (NDR_MSTRING(mxa, subkey, (ndr_mstring_t *)¶m->name_out) == -1) { 58389dc44ceSjose borrego bzero(param, sizeof (struct winreg_EnumKey)); 58489dc44ceSjose borrego param->status = ERROR_NOT_ENOUGH_MEMORY; 58589dc44ceSjose borrego return (NDR_DRC_OK); 58689dc44ceSjose borrego } 5877f667e74Sjose borrego /* 5887f667e74Sjose borrego * This request requires that the length includes the null. 5897f667e74Sjose borrego */ 5907f667e74Sjose borrego param->name_out.length = param->name_out.allosize; 59189dc44ceSjose borrego 59289dc44ceSjose borrego param->status = ERROR_SUCCESS; 59389dc44ceSjose borrego return (NDR_DRC_OK); 59489dc44ceSjose borrego } 59589dc44ceSjose borrego 59689dc44ceSjose borrego /* 59789dc44ceSjose borrego * winreg_s_EnumValue 59889dc44ceSjose borrego */ 59989dc44ceSjose borrego static int 60089dc44ceSjose borrego winreg_s_EnumValue(void *arg, ndr_xa_t *mxa) 60189dc44ceSjose borrego { 60289dc44ceSjose borrego struct winreg_EnumValue *param = arg; 60389dc44ceSjose borrego ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 60489dc44ceSjose borrego 60589dc44ceSjose borrego if (ndr_hdlookup(mxa, id) == NULL) { 60689dc44ceSjose borrego bzero(param, sizeof (struct winreg_EnumValue)); 60789dc44ceSjose borrego param->status = ERROR_NO_MORE_ITEMS; 60889dc44ceSjose borrego return (NDR_DRC_OK); 60989dc44ceSjose borrego } 61089dc44ceSjose borrego 61189dc44ceSjose borrego bzero(param, sizeof (struct winreg_EnumValue)); 61289dc44ceSjose borrego param->status = ERROR_NO_MORE_ITEMS; 61389dc44ceSjose borrego return (NDR_DRC_OK); 61489dc44ceSjose borrego } 61589dc44ceSjose borrego 61689dc44ceSjose borrego /* 61789dc44ceSjose borrego * winreg_s_FlushKey 61889dc44ceSjose borrego * 61989dc44ceSjose borrego * Flush the attributes associated with the specified open key to disk. 62089dc44ceSjose borrego */ 62189dc44ceSjose borrego static int 62289dc44ceSjose borrego winreg_s_FlushKey(void *arg, ndr_xa_t *mxa) 62389dc44ceSjose borrego { 62489dc44ceSjose borrego struct winreg_FlushKey *param = arg; 62589dc44ceSjose borrego ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 62689dc44ceSjose borrego 62789dc44ceSjose borrego if (ndr_hdlookup(mxa, id) == NULL) 62889dc44ceSjose borrego param->status = ERROR_INVALID_HANDLE; 62989dc44ceSjose borrego else 63089dc44ceSjose borrego param->status = ERROR_SUCCESS; 63189dc44ceSjose borrego 63289dc44ceSjose borrego return (NDR_DRC_OK); 63389dc44ceSjose borrego } 63489dc44ceSjose borrego 63589dc44ceSjose borrego /* 63689dc44ceSjose borrego * winreg_s_GetKeySec 63789dc44ceSjose borrego */ 63889dc44ceSjose borrego static int 63989dc44ceSjose borrego winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa) 64089dc44ceSjose borrego { 641*96a62adaSjoyce mcintosh static struct winreg_secdesc error_sd; 64289dc44ceSjose borrego struct winreg_GetKeySec *param = arg; 643f96bd5c8SAlan Wright struct winreg_value *sd_buf; 644f96bd5c8SAlan Wright smb_sd_t sd; 645f96bd5c8SAlan Wright uint32_t sd_len; 646f96bd5c8SAlan Wright uint32_t status; 64789dc44ceSjose borrego 648f96bd5c8SAlan Wright bzero(&sd, sizeof (smb_sd_t)); 649f96bd5c8SAlan Wright 650f96bd5c8SAlan Wright if ((status = winreg_sd_format(&sd)) != ERROR_SUCCESS) 651f96bd5c8SAlan Wright goto winreg_getkeysec_error; 652f96bd5c8SAlan Wright 653f96bd5c8SAlan Wright sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO); 654*96a62adaSjoyce mcintosh sd_buf = NDR_MALLOC(mxa, sd_len + sizeof (struct winreg_value)); 655f96bd5c8SAlan Wright 656f96bd5c8SAlan Wright param->sd = NDR_MALLOC(mxa, sizeof (struct winreg_secdesc)); 657*96a62adaSjoyce mcintosh if ((param->sd == NULL) || (sd_buf == NULL)) { 658f96bd5c8SAlan Wright status = ERROR_NOT_ENOUGH_MEMORY; 659f96bd5c8SAlan Wright goto winreg_getkeysec_error; 660f96bd5c8SAlan Wright } 661f96bd5c8SAlan Wright 662f96bd5c8SAlan Wright param->sd->sd_len = sd_len; 663f96bd5c8SAlan Wright param->sd->sd_size = sd_len; 664f96bd5c8SAlan Wright param->sd->sd_buf = sd_buf; 665f96bd5c8SAlan Wright 666f96bd5c8SAlan Wright sd_buf->vc_first_is = 0; 667f96bd5c8SAlan Wright sd_buf->vc_length_is = sd_len; 668f96bd5c8SAlan Wright param->status = srvsvc_sd_set_relative(&sd, sd_buf->value); 669f96bd5c8SAlan Wright 670f96bd5c8SAlan Wright smb_sd_term(&sd); 67189dc44ceSjose borrego return (NDR_DRC_OK); 672f96bd5c8SAlan Wright 673f96bd5c8SAlan Wright winreg_getkeysec_error: 674f96bd5c8SAlan Wright smb_sd_term(&sd); 675f96bd5c8SAlan Wright bzero(param, sizeof (struct winreg_GetKeySec)); 676*96a62adaSjoyce mcintosh param->sd = &error_sd; 677f96bd5c8SAlan Wright param->status = status; 678f96bd5c8SAlan Wright return (NDR_DRC_OK); 679f96bd5c8SAlan Wright } 680f96bd5c8SAlan Wright 681f96bd5c8SAlan Wright static uint32_t 682f96bd5c8SAlan Wright winreg_sd_format(smb_sd_t *sd) 683f96bd5c8SAlan Wright { 684f96bd5c8SAlan Wright smb_fssd_t fs_sd; 685f96bd5c8SAlan Wright acl_t *acl; 686f96bd5c8SAlan Wright uint32_t status = ERROR_SUCCESS; 687f96bd5c8SAlan Wright 688f96bd5c8SAlan Wright if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0) 689f96bd5c8SAlan Wright return (ERROR_NOT_ENOUGH_MEMORY); 690f96bd5c8SAlan Wright 691f96bd5c8SAlan Wright smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR); 692f96bd5c8SAlan Wright fs_sd.sd_uid = 0; 693f96bd5c8SAlan Wright fs_sd.sd_gid = 0; 694f96bd5c8SAlan Wright fs_sd.sd_zdacl = acl; 695f96bd5c8SAlan Wright fs_sd.sd_zsacl = NULL; 696f96bd5c8SAlan Wright 697f96bd5c8SAlan Wright if (smb_sd_fromfs(&fs_sd, sd) != NT_STATUS_SUCCESS) 698f96bd5c8SAlan Wright status = ERROR_ACCESS_DENIED; 699f96bd5c8SAlan Wright smb_fssd_term(&fs_sd); 700f96bd5c8SAlan Wright return (status); 70189dc44ceSjose borrego } 70289dc44ceSjose borrego 70389dc44ceSjose borrego /* 70489dc44ceSjose borrego * winreg_s_NotifyChange 70589dc44ceSjose borrego */ 70689dc44ceSjose borrego static int 70789dc44ceSjose borrego winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa) 70889dc44ceSjose borrego { 70989dc44ceSjose borrego struct winreg_NotifyChange *param = arg; 71089dc44ceSjose borrego 71189dc44ceSjose borrego if (ndr_is_admin(mxa)) 71289dc44ceSjose borrego param->status = ERROR_SUCCESS; 71389dc44ceSjose borrego else 71489dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 71589dc44ceSjose borrego 71689dc44ceSjose borrego return (NDR_DRC_OK); 71789dc44ceSjose borrego } 71889dc44ceSjose borrego 71989dc44ceSjose borrego /* 72089dc44ceSjose borrego * winreg_s_OpenKey 72189dc44ceSjose borrego * 72289dc44ceSjose borrego * This is a request to open a windows registry key. 72389dc44ceSjose borrego * If we recognize the key, we return a handle. 72489dc44ceSjose borrego * 72589dc44ceSjose borrego * Returns: 72689dc44ceSjose borrego * ERROR_SUCCESS Valid handle returned. 72789dc44ceSjose borrego * ERROR_FILE_NOT_FOUND No key or unable to allocate a handle. 72889dc44ceSjose borrego */ 72989dc44ceSjose borrego static int 73089dc44ceSjose borrego winreg_s_OpenKey(void *arg, ndr_xa_t *mxa) 73189dc44ceSjose borrego { 73289dc44ceSjose borrego struct winreg_OpenKey *param = arg; 733b1352070SAlan Wright ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 734b1352070SAlan Wright ndr_handle_t *hd; 73589dc44ceSjose borrego char *subkey = (char *)param->name.str; 73689dc44ceSjose borrego winreg_subkey_t *key; 7377f667e74Sjose borrego char *dupkey; 73889dc44ceSjose borrego 739b1352070SAlan Wright if (subkey == NULL || *subkey == '\0') { 740b1352070SAlan Wright if ((hd = ndr_hdlookup(mxa, id)) != NULL) 741b1352070SAlan Wright subkey = hd->nh_data; 742b1352070SAlan Wright } 743b1352070SAlan Wright 744b1352070SAlan Wright id = NULL; 745b1352070SAlan Wright 7467f667e74Sjose borrego if (subkey == NULL || list_is_empty(&winreg_keylist.kl_list)) { 74789dc44ceSjose borrego bzero(¶m->result_handle, sizeof (winreg_handle_t)); 74889dc44ceSjose borrego param->status = ERROR_FILE_NOT_FOUND; 74989dc44ceSjose borrego return (NDR_DRC_OK); 75089dc44ceSjose borrego } 75189dc44ceSjose borrego 75289dc44ceSjose borrego key = list_head(&winreg_keylist.kl_list); 75389dc44ceSjose borrego do { 75489dc44ceSjose borrego if (strcasecmp(subkey, key->sk_name) == 0) { 7557f667e74Sjose borrego if (key->sk_predefined == B_TRUE) { 7567f667e74Sjose borrego if ((dupkey = strdup(subkey)) == NULL) 7577f667e74Sjose borrego break; 7587f667e74Sjose borrego 7597f667e74Sjose borrego id = ndr_hdalloc(mxa, dupkey); 7607f667e74Sjose borrego if (id == NULL) 7617f667e74Sjose borrego free(dupkey); 7627f667e74Sjose borrego } else { 76389dc44ceSjose borrego id = &key->sk_handle; 7647f667e74Sjose borrego } 76589dc44ceSjose borrego 76689dc44ceSjose borrego if (id == NULL) 76789dc44ceSjose borrego break; 76889dc44ceSjose borrego 76989dc44ceSjose borrego bcopy(id, ¶m->result_handle, 77089dc44ceSjose borrego sizeof (winreg_handle_t)); 77189dc44ceSjose borrego param->status = ERROR_SUCCESS; 77289dc44ceSjose borrego return (NDR_DRC_OK); 77389dc44ceSjose borrego } 77489dc44ceSjose borrego } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 77589dc44ceSjose borrego 77689dc44ceSjose borrego bzero(¶m->result_handle, sizeof (winreg_handle_t)); 77789dc44ceSjose borrego param->status = ERROR_FILE_NOT_FOUND; 77889dc44ceSjose borrego return (NDR_DRC_OK); 77989dc44ceSjose borrego } 78089dc44ceSjose borrego 78189dc44ceSjose borrego /* 78289dc44ceSjose borrego * winreg_s_QueryKey 78389dc44ceSjose borrego */ 78489dc44ceSjose borrego /*ARGSUSED*/ 78589dc44ceSjose borrego static int 78689dc44ceSjose borrego winreg_s_QueryKey(void *arg, ndr_xa_t *mxa) 78789dc44ceSjose borrego { 78889dc44ceSjose borrego struct winreg_QueryKey *param = arg; 78989dc44ceSjose borrego int rc; 79089dc44ceSjose borrego winreg_string_t *name; 79189dc44ceSjose borrego 79289dc44ceSjose borrego name = (winreg_string_t *)¶m->name; 79389dc44ceSjose borrego bzero(param, sizeof (struct winreg_QueryKey)); 79489dc44ceSjose borrego if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL) 79589dc44ceSjose borrego rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name); 79689dc44ceSjose borrego 79789dc44ceSjose borrego if ((name == NULL) || (rc != 0)) { 79889dc44ceSjose borrego bzero(param, sizeof (struct winreg_QueryKey)); 79989dc44ceSjose borrego param->status = ERROR_NOT_ENOUGH_MEMORY; 80089dc44ceSjose borrego return (NDR_DRC_OK); 80189dc44ceSjose borrego } 80289dc44ceSjose borrego 80389dc44ceSjose borrego param->status = ERROR_SUCCESS; 80489dc44ceSjose borrego return (NDR_DRC_OK); 80589dc44ceSjose borrego } 80689dc44ceSjose borrego 80789dc44ceSjose borrego /* 80889dc44ceSjose borrego * winreg_s_QueryValue 80989dc44ceSjose borrego * 81089dc44ceSjose borrego * This is a request to get the value associated with a specified name. 81189dc44ceSjose borrego * 81289dc44ceSjose borrego * Returns: 81389dc44ceSjose borrego * ERROR_SUCCESS Value returned. 81489dc44ceSjose borrego * ERROR_FILE_NOT_FOUND PrimaryModule is not supported. 81589dc44ceSjose borrego * ERROR_CANTREAD No such name or memory problem. 81689dc44ceSjose borrego */ 81789dc44ceSjose borrego static int 81889dc44ceSjose borrego winreg_s_QueryValue(void *arg, ndr_xa_t *mxa) 81989dc44ceSjose borrego { 82089dc44ceSjose borrego struct winreg_QueryValue *param = arg; 82189dc44ceSjose borrego struct winreg_value *pv; 82289dc44ceSjose borrego char *name; 82389dc44ceSjose borrego char *value; 82489dc44ceSjose borrego DWORD slen; 82589dc44ceSjose borrego DWORD msize; 82689dc44ceSjose borrego 82789dc44ceSjose borrego name = (char *)param->value_name.str; 82889dc44ceSjose borrego 82989dc44ceSjose borrego if (strcasecmp(name, "PrimaryModule") == 0) { 83089dc44ceSjose borrego param->status = ERROR_FILE_NOT_FOUND; 83189dc44ceSjose borrego return (NDR_DRC_OK); 83289dc44ceSjose borrego } 83389dc44ceSjose borrego 83489dc44ceSjose borrego if ((value = winreg_lookup_value(name)) == NULL) { 83589dc44ceSjose borrego param->status = ERROR_CANTREAD; 83689dc44ceSjose borrego return (NDR_DRC_OK); 83789dc44ceSjose borrego } 83889dc44ceSjose borrego 839bbf6f00cSJordan Brown slen = smb_wcequiv_strlen(value) + sizeof (smb_wchar_t); 84089dc44ceSjose borrego msize = sizeof (struct winreg_value) + slen; 84189dc44ceSjose borrego 84289dc44ceSjose borrego param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize); 84389dc44ceSjose borrego param->type = NDR_NEW(mxa, DWORD); 84489dc44ceSjose borrego param->value_size = NDR_NEW(mxa, DWORD); 84589dc44ceSjose borrego param->value_size_total = NDR_NEW(mxa, DWORD); 84689dc44ceSjose borrego 84789dc44ceSjose borrego if (param->value == NULL || param->type == NULL || 84889dc44ceSjose borrego param->value_size == NULL || param->value_size_total == NULL) { 84989dc44ceSjose borrego param->status = ERROR_CANTREAD; 85089dc44ceSjose borrego return (NDR_DRC_OK); 85189dc44ceSjose borrego } 85289dc44ceSjose borrego 85389dc44ceSjose borrego bzero(param->value, msize); 85489dc44ceSjose borrego pv = param->value; 85589dc44ceSjose borrego pv->vc_first_is = 0; 85689dc44ceSjose borrego pv->vc_length_is = slen; 85789dc44ceSjose borrego /*LINTED E_BAD_PTR_CAST_ALIGN*/ 858bbf6f00cSJordan Brown (void) ndr_mbstowcs(NULL, (smb_wchar_t *)pv->value, value, slen); 85989dc44ceSjose borrego 86089dc44ceSjose borrego *param->type = 1; 86189dc44ceSjose borrego *param->value_size = slen; 86289dc44ceSjose borrego *param->value_size_total = slen; 86389dc44ceSjose borrego 86489dc44ceSjose borrego param->status = ERROR_SUCCESS; 86589dc44ceSjose borrego return (NDR_DRC_OK); 86689dc44ceSjose borrego } 86789dc44ceSjose borrego 86889dc44ceSjose borrego /* 86989dc44ceSjose borrego * Lookup a name in the registry and return the associated value. 87089dc44ceSjose borrego * Our registry is a case-insensitive, name-value pair table. 87189dc44ceSjose borrego * 87289dc44ceSjose borrego * Windows ProductType: WinNT, ServerNT, LanmanNT. 87389dc44ceSjose borrego * Windows NT4.0 workstation: WinNT 87489dc44ceSjose borrego * Windows NT4.0 server: ServerNT 87589dc44ceSjose borrego * 87689dc44ceSjose borrego * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy 87789dc44ceSjose borrego * with info level 6, which we don't support. If we use ServerNT 87889dc44ceSjose borrego * (as reported by NT4.0 Server) Windows 2000 send requests for 87989dc44ceSjose borrego * levels 3 and 5, which are support. 88089dc44ceSjose borrego * 88189dc44ceSjose borrego * On success, returns a pointer to the value. Otherwise returns 88289dc44ceSjose borrego * a null pointer. 88389dc44ceSjose borrego */ 88489dc44ceSjose borrego static char * 88589dc44ceSjose borrego winreg_lookup_value(const char *name) 88689dc44ceSjose borrego { 88789dc44ceSjose borrego static struct registry { 88889dc44ceSjose borrego char *name; 88989dc44ceSjose borrego char *value; 89089dc44ceSjose borrego } registry[] = { 891e3f2c991SKeyur Desai { "CurrentVersion", "4.0" }, 89289dc44ceSjose borrego { "ProductType", "ServerNT" }, 89389dc44ceSjose borrego { "Sources", NULL } /* product name */ 89489dc44ceSjose borrego }; 89589dc44ceSjose borrego 89689dc44ceSjose borrego int i; 89789dc44ceSjose borrego 89889dc44ceSjose borrego for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) { 89989dc44ceSjose borrego if (strcasecmp(registry[i].name, name) == 0) { 90089dc44ceSjose borrego if (registry[i].value == NULL) 90189dc44ceSjose borrego return (winreg_sysname); 90289dc44ceSjose borrego else 90389dc44ceSjose borrego return (registry[i].value); 90489dc44ceSjose borrego } 90589dc44ceSjose borrego } 90689dc44ceSjose borrego 90789dc44ceSjose borrego return (NULL); 90889dc44ceSjose borrego } 90989dc44ceSjose borrego 91089dc44ceSjose borrego /* 91189dc44ceSjose borrego * winreg_s_SetKeySec 91289dc44ceSjose borrego */ 91389dc44ceSjose borrego /*ARGSUSED*/ 91489dc44ceSjose borrego static int 91589dc44ceSjose borrego winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa) 91689dc44ceSjose borrego { 91789dc44ceSjose borrego struct winreg_SetKeySec *param = arg; 91889dc44ceSjose borrego 91989dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 92089dc44ceSjose borrego return (NDR_DRC_OK); 92189dc44ceSjose borrego } 92289dc44ceSjose borrego 92389dc44ceSjose borrego /* 92489dc44ceSjose borrego * winreg_s_CreateValue 92589dc44ceSjose borrego */ 92689dc44ceSjose borrego /*ARGSUSED*/ 92789dc44ceSjose borrego static int 92889dc44ceSjose borrego winreg_s_CreateValue(void *arg, ndr_xa_t *mxa) 92989dc44ceSjose borrego { 93089dc44ceSjose borrego struct winreg_CreateValue *param = arg; 93189dc44ceSjose borrego 93289dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 93389dc44ceSjose borrego return (NDR_DRC_OK); 93489dc44ceSjose borrego } 93589dc44ceSjose borrego 93689dc44ceSjose borrego /* 93789dc44ceSjose borrego * winreg_s_Shutdown 93889dc44ceSjose borrego * 93989dc44ceSjose borrego * Attempt to shutdown or reboot the system: access denied. 94089dc44ceSjose borrego */ 94189dc44ceSjose borrego /*ARGSUSED*/ 94289dc44ceSjose borrego static int 94389dc44ceSjose borrego winreg_s_Shutdown(void *arg, ndr_xa_t *mxa) 94489dc44ceSjose borrego { 94589dc44ceSjose borrego struct winreg_Shutdown *param = arg; 94689dc44ceSjose borrego 94789dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 94889dc44ceSjose borrego return (NDR_DRC_OK); 94989dc44ceSjose borrego } 95089dc44ceSjose borrego 95189dc44ceSjose borrego /* 95289dc44ceSjose borrego * winreg_s_AbortShutdown 95389dc44ceSjose borrego * 95489dc44ceSjose borrego * Abort a shutdown request. 95589dc44ceSjose borrego */ 95689dc44ceSjose borrego static int 95789dc44ceSjose borrego winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa) 95889dc44ceSjose borrego { 95989dc44ceSjose borrego struct winreg_AbortShutdown *param = arg; 96089dc44ceSjose borrego 96189dc44ceSjose borrego if (ndr_is_admin(mxa)) 96289dc44ceSjose borrego param->status = ERROR_SUCCESS; 96389dc44ceSjose borrego else 96489dc44ceSjose borrego param->status = ERROR_ACCESS_DENIED; 96589dc44ceSjose borrego 96689dc44ceSjose borrego return (NDR_DRC_OK); 96789dc44ceSjose borrego } 96889dc44ceSjose borrego 96989dc44ceSjose borrego /* 97089dc44ceSjose borrego * winreg_s_GetVersion 97189dc44ceSjose borrego * 97289dc44ceSjose borrego * Return the windows registry version. The current version is 5. 97389dc44ceSjose borrego * This call is usually made prior to enumerating or querying registry 97489dc44ceSjose borrego * keys or values. 97589dc44ceSjose borrego */ 97689dc44ceSjose borrego /*ARGSUSED*/ 97789dc44ceSjose borrego static int 97889dc44ceSjose borrego winreg_s_GetVersion(void *arg, ndr_xa_t *mxa) 97989dc44ceSjose borrego { 98089dc44ceSjose borrego struct winreg_GetVersion *param = arg; 98189dc44ceSjose borrego 98289dc44ceSjose borrego param->version = 5; 98389dc44ceSjose borrego param->status = ERROR_SUCCESS; 98489dc44ceSjose borrego return (NDR_DRC_OK); 98589dc44ceSjose borrego } 986