1fe1c642dSBill Krier /* 2fe1c642dSBill Krier * CDDL HEADER START 3fe1c642dSBill Krier * 4fe1c642dSBill Krier * The contents of this file are subject to the terms of the 5fe1c642dSBill Krier * Common Development and Distribution License (the "License"). 6fe1c642dSBill Krier * You may not use this file except in compliance with the License. 7fe1c642dSBill Krier * 8fe1c642dSBill Krier * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fe1c642dSBill Krier * or http://www.opensolaris.org/os/licensing. 10fe1c642dSBill Krier * See the License for the specific language governing permissions 11fe1c642dSBill Krier * and limitations under the License. 12fe1c642dSBill Krier * 13fe1c642dSBill Krier * When distributing Covered Code, include this CDDL HEADER in each 14fe1c642dSBill Krier * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fe1c642dSBill Krier * If applicable, add the following below this CDDL HEADER, with the 16fe1c642dSBill Krier * fields enclosed by brackets "[]" replaced with your own identifying 17fe1c642dSBill Krier * information: Portions Copyright [yyyy] [name of copyright owner] 18fe1c642dSBill Krier * 19fe1c642dSBill Krier * CDDL HEADER END 20fe1c642dSBill Krier */ 21fe1c642dSBill Krier /* 22*f96bd5c8SAlan Wright * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23fe1c642dSBill Krier * Use is subject to license terms. 24fe1c642dSBill Krier */ 25fe1c642dSBill Krier 26fe1c642dSBill Krier /* 27fe1c642dSBill Krier * Security Accounts Manager RPC (SAMR) server-side interface. 28fe1c642dSBill Krier * 29fe1c642dSBill Krier * The SAM is a hierarchical database: 30fe1c642dSBill Krier * - If you want to talk to the SAM you need a SAM handle. 31fe1c642dSBill Krier * - If you want to work with a domain, use the SAM handle. 32fe1c642dSBill Krier * to obtain a domain handle. 33fe1c642dSBill Krier * - Use domain handles to obtain user handles etc. 34fe1c642dSBill Krier */ 35fe1c642dSBill Krier 36fe1c642dSBill Krier #include <strings.h> 37fe1c642dSBill Krier #include <unistd.h> 38fe1c642dSBill Krier #include <netdb.h> 39fe1c642dSBill Krier #include <assert.h> 40fe1c642dSBill Krier 41fe1c642dSBill Krier #include <smbsrv/libsmb.h> 42fe1c642dSBill Krier #include <smbsrv/libmlrpc.h> 43fe1c642dSBill Krier #include <smbsrv/libmlsvc.h> 44fe1c642dSBill Krier #include <smbsrv/ntstatus.h> 45fe1c642dSBill Krier #include <smbsrv/nterror.h> 46fe1c642dSBill Krier #include <smbsrv/smbinfo.h> 47fe1c642dSBill Krier #include <smbsrv/nmpipes.h> 48fe1c642dSBill Krier #include <smbsrv/ndl/samrpc.ndl> 49fe1c642dSBill Krier #include <samlib.h> 50fe1c642dSBill Krier 51fe1c642dSBill Krier /* 52fe1c642dSBill Krier * The keys associated with the various handles dispensed by the SAMR 53fe1c642dSBill Krier * server. These keys can be used to validate client activity. 54fe1c642dSBill Krier * These values are never passed over the wire so security shouldn't 55fe1c642dSBill Krier * be an issue. 56fe1c642dSBill Krier */ 57fe1c642dSBill Krier typedef enum { 58fe1c642dSBill Krier SAMR_KEY_NULL = 0, 59fe1c642dSBill Krier SAMR_KEY_CONNECT, 60fe1c642dSBill Krier SAMR_KEY_DOMAIN, 61fe1c642dSBill Krier SAMR_KEY_USER, 62fe1c642dSBill Krier SAMR_KEY_GROUP, 63fe1c642dSBill Krier SAMR_KEY_ALIAS 64fe1c642dSBill Krier } samr_key_t; 65fe1c642dSBill Krier 66fe1c642dSBill Krier typedef struct samr_keydata { 67fe1c642dSBill Krier samr_key_t kd_key; 68fe1c642dSBill Krier smb_domain_type_t kd_type; 69fe1c642dSBill Krier DWORD kd_rid; 70fe1c642dSBill Krier } samr_keydata_t; 71fe1c642dSBill Krier 72fe1c642dSBill Krier /* 73fe1c642dSBill Krier * DomainDisplayUser All user objects (or those derived from user) with 74fe1c642dSBill Krier * userAccountControl containing the UF_NORMAL_ACCOUNT bit. 75fe1c642dSBill Krier * 76fe1c642dSBill Krier * DomainDisplayMachine All user objects (or those derived from user) with 77fe1c642dSBill Krier * userAccountControl containing the 78fe1c642dSBill Krier * UF_WORKSTATION_TRUST_ACCOUNT or UF_SERVER_TRUST_ACCOUNT 79fe1c642dSBill Krier * bit. 80fe1c642dSBill Krier * 81fe1c642dSBill Krier * DomainDisplayGroup All group objects (or those derived from group) with 82fe1c642dSBill Krier * groupType equal to GROUP_TYPE_SECURITY_UNIVERSAL or 83fe1c642dSBill Krier * GROUP_TYPE_SECURITY_ACCOUNT. 84fe1c642dSBill Krier * 85fe1c642dSBill Krier * DomainDisplayOemUser Same as DomainDisplayUser with OEM strings 86fe1c642dSBill Krier * 87fe1c642dSBill Krier * DomainDisplayOemGroup Same as DomainDisplayGroup with OEM strings 88fe1c642dSBill Krier */ 89fe1c642dSBill Krier typedef enum { 90fe1c642dSBill Krier DomainDisplayUser = 1, 91fe1c642dSBill Krier DomainDisplayMachine, 92fe1c642dSBill Krier DomainDispalyGroup, 93fe1c642dSBill Krier DomainDisplayOemUser, 94fe1c642dSBill Krier DomainDisplayOemGroup 95fe1c642dSBill Krier } samr_displvl_t; 96fe1c642dSBill Krier 97fe1c642dSBill Krier #define SAMR_VALID_DISPLEVEL(lvl) \ 98fe1c642dSBill Krier (((lvl) >= DomainDisplayUser) && ((lvl) <= DomainDisplayOemGroup)) 99fe1c642dSBill Krier 100fe1c642dSBill Krier #define SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser) 101fe1c642dSBill Krier 102fe1c642dSBill Krier static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t, 103fe1c642dSBill Krier DWORD); 104fe1c642dSBill Krier static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *); 105fe1c642dSBill Krier static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t); 106fe1c642dSBill Krier static int samr_call_stub(ndr_xa_t *mxa); 107fe1c642dSBill Krier static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *, 108fe1c642dSBill Krier ndr_xa_t *); 109fe1c642dSBill Krier 110fe1c642dSBill Krier static ndr_stub_table_t samr_stub_table[]; 111fe1c642dSBill Krier 112fe1c642dSBill Krier static ndr_service_t samr_service = { 113fe1c642dSBill Krier "SAMR", /* name */ 114fe1c642dSBill Krier "Security Accounts Manager", /* desc */ 115fe1c642dSBill Krier "\\samr", /* endpoint */ 116fe1c642dSBill Krier PIPE_LSASS, /* sec_addr_port */ 117fe1c642dSBill Krier "12345778-1234-abcd-ef00-0123456789ac", 1, /* abstract */ 118fe1c642dSBill Krier NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ 119fe1c642dSBill Krier 0, /* no bind_instance_size */ 120fe1c642dSBill Krier NULL, /* no bind_req() */ 121fe1c642dSBill Krier NULL, /* no unbind_and_close() */ 122fe1c642dSBill Krier samr_call_stub, /* call_stub() */ 123fe1c642dSBill Krier &TYPEINFO(samr_interface), /* interface ti */ 124fe1c642dSBill Krier samr_stub_table /* stub_table */ 125fe1c642dSBill Krier }; 126fe1c642dSBill Krier 127fe1c642dSBill Krier /* 128fe1c642dSBill Krier * samr_initialize 129fe1c642dSBill Krier * 130fe1c642dSBill Krier * This function registers the SAM RPC interface with the RPC runtime 131fe1c642dSBill Krier * library. It must be called in order to use either the client side 132fe1c642dSBill Krier * or the server side functions. 133fe1c642dSBill Krier */ 134fe1c642dSBill Krier void 135fe1c642dSBill Krier samr_initialize(void) 136fe1c642dSBill Krier { 137fe1c642dSBill Krier (void) ndr_svc_register(&samr_service); 138fe1c642dSBill Krier } 139fe1c642dSBill Krier 140fe1c642dSBill Krier /* 141fe1c642dSBill Krier * Custom call_stub to set the stream string policy. 142fe1c642dSBill Krier */ 143fe1c642dSBill Krier static int 144fe1c642dSBill Krier samr_call_stub(ndr_xa_t *mxa) 145fe1c642dSBill Krier { 146fe1c642dSBill Krier NDS_SETF(&mxa->send_nds, NDS_F_NOTERM); 147fe1c642dSBill Krier NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM); 148fe1c642dSBill Krier 149fe1c642dSBill Krier return (ndr_generic_call_stub(mxa)); 150fe1c642dSBill Krier } 151fe1c642dSBill Krier 152fe1c642dSBill Krier /* 153fe1c642dSBill Krier * Handle allocation wrapper to setup the local context. 154fe1c642dSBill Krier */ 155fe1c642dSBill Krier static ndr_hdid_t * 156fe1c642dSBill Krier samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type, 157fe1c642dSBill Krier DWORD rid) 158fe1c642dSBill Krier { 159fe1c642dSBill Krier samr_keydata_t *data; 160fe1c642dSBill Krier 161fe1c642dSBill Krier if ((data = malloc(sizeof (samr_keydata_t))) == NULL) 162fe1c642dSBill Krier return (NULL); 163fe1c642dSBill Krier 164fe1c642dSBill Krier data->kd_key = key; 165fe1c642dSBill Krier data->kd_type = domain_type; 166fe1c642dSBill Krier data->kd_rid = rid; 167fe1c642dSBill Krier 168fe1c642dSBill Krier return (ndr_hdalloc(mxa, data)); 169fe1c642dSBill Krier } 170fe1c642dSBill Krier 171fe1c642dSBill Krier /* 172fe1c642dSBill Krier * Handle deallocation wrapper to free the local context. 173fe1c642dSBill Krier */ 174fe1c642dSBill Krier static void 175fe1c642dSBill Krier samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id) 176fe1c642dSBill Krier { 177fe1c642dSBill Krier ndr_handle_t *hd; 178fe1c642dSBill Krier 179fe1c642dSBill Krier if ((hd = ndr_hdlookup(mxa, id)) != NULL) { 180fe1c642dSBill Krier free(hd->nh_data); 181fe1c642dSBill Krier ndr_hdfree(mxa, id); 182fe1c642dSBill Krier } 183fe1c642dSBill Krier } 184fe1c642dSBill Krier 185fe1c642dSBill Krier /* 186fe1c642dSBill Krier * Handle lookup wrapper to validate the local context. 187fe1c642dSBill Krier */ 188fe1c642dSBill Krier static ndr_handle_t * 189fe1c642dSBill Krier samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key) 190fe1c642dSBill Krier { 191fe1c642dSBill Krier ndr_handle_t *hd; 192fe1c642dSBill Krier samr_keydata_t *data; 193fe1c642dSBill Krier 194fe1c642dSBill Krier if ((hd = ndr_hdlookup(mxa, id)) == NULL) 195fe1c642dSBill Krier return (NULL); 196fe1c642dSBill Krier 197fe1c642dSBill Krier if ((data = (samr_keydata_t *)hd->nh_data) == NULL) 198fe1c642dSBill Krier return (NULL); 199fe1c642dSBill Krier 200fe1c642dSBill Krier if (data->kd_key != key) 201fe1c642dSBill Krier return (NULL); 202fe1c642dSBill Krier 203fe1c642dSBill Krier return (hd); 204fe1c642dSBill Krier } 205fe1c642dSBill Krier 206fe1c642dSBill Krier /* 207fe1c642dSBill Krier * samr_s_ConnectAnon 208fe1c642dSBill Krier * 209fe1c642dSBill Krier * This is a request to connect to the local SAM database. We don't 210fe1c642dSBill Krier * support any form of update request and our database doesn't 211fe1c642dSBill Krier * contain any private information, so there is little point in 212fe1c642dSBill Krier * doing any access access checking here. 213fe1c642dSBill Krier * 214fe1c642dSBill Krier * Return a handle for use with subsequent SAM requests. 215fe1c642dSBill Krier */ 216fe1c642dSBill Krier static int 217fe1c642dSBill Krier samr_s_ConnectAnon(void *arg, ndr_xa_t *mxa) 218fe1c642dSBill Krier { 219fe1c642dSBill Krier struct samr_ConnectAnon *param = arg; 220fe1c642dSBill Krier ndr_hdid_t *id; 221fe1c642dSBill Krier 222fe1c642dSBill Krier id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0); 223fe1c642dSBill Krier if (id) { 224fe1c642dSBill Krier bcopy(id, ¶m->handle, sizeof (samr_handle_t)); 225fe1c642dSBill Krier param->status = 0; 226fe1c642dSBill Krier } else { 227fe1c642dSBill Krier bzero(¶m->handle, sizeof (samr_handle_t)); 228fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 229fe1c642dSBill Krier } 230fe1c642dSBill Krier 231fe1c642dSBill Krier return (NDR_DRC_OK); 232fe1c642dSBill Krier } 233fe1c642dSBill Krier 234fe1c642dSBill Krier /* 235fe1c642dSBill Krier * samr_s_CloseHandle 236fe1c642dSBill Krier * 237fe1c642dSBill Krier * Close the SAM interface specified by the handle. 238fe1c642dSBill Krier * Free the handle and zero out the result handle for the client. 239fe1c642dSBill Krier */ 240fe1c642dSBill Krier static int 241fe1c642dSBill Krier samr_s_CloseHandle(void *arg, ndr_xa_t *mxa) 242fe1c642dSBill Krier { 243fe1c642dSBill Krier struct samr_CloseHandle *param = arg; 244fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 245fe1c642dSBill Krier 246fe1c642dSBill Krier samr_hdfree(mxa, id); 247fe1c642dSBill Krier 248fe1c642dSBill Krier bzero(¶m->result_handle, sizeof (samr_handle_t)); 249fe1c642dSBill Krier param->status = 0; 250fe1c642dSBill Krier return (NDR_DRC_OK); 251fe1c642dSBill Krier } 252fe1c642dSBill Krier 253fe1c642dSBill Krier /* 254fe1c642dSBill Krier * samr_s_LookupDomain 255fe1c642dSBill Krier * 256fe1c642dSBill Krier * This is a request to map a domain name to a domain SID. We can map 257fe1c642dSBill Krier * the primary domain name, our local domain name (hostname) and the 258fe1c642dSBill Krier * builtin domain names to the appropriate SID. Anything else will be 259fe1c642dSBill Krier * rejected. 260fe1c642dSBill Krier */ 261fe1c642dSBill Krier static int 262fe1c642dSBill Krier samr_s_LookupDomain(void *arg, ndr_xa_t *mxa) 263fe1c642dSBill Krier { 264fe1c642dSBill Krier struct samr_LookupDomain *param = arg; 265fe1c642dSBill Krier char *domain_name; 266fe1c642dSBill Krier smb_domain_t di; 267fe1c642dSBill Krier 268fe1c642dSBill Krier if ((domain_name = (char *)param->domain_name.str) == NULL) { 269fe1c642dSBill Krier bzero(param, sizeof (struct samr_LookupDomain)); 270fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER); 271fe1c642dSBill Krier return (NDR_DRC_OK); 272fe1c642dSBill Krier } 273fe1c642dSBill Krier 274fe1c642dSBill Krier if (!smb_domain_lookup_name(domain_name, &di)) { 275fe1c642dSBill Krier bzero(param, sizeof (struct samr_LookupDomain)); 276fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN); 277fe1c642dSBill Krier return (NDR_DRC_OK); 278fe1c642dSBill Krier } 279fe1c642dSBill Krier 280fe1c642dSBill Krier param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid); 281fe1c642dSBill Krier if (param->sid == NULL) { 282fe1c642dSBill Krier bzero(param, sizeof (struct samr_LookupDomain)); 283fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 284fe1c642dSBill Krier return (NDR_DRC_OK); 285fe1c642dSBill Krier } 286fe1c642dSBill Krier 287fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 288fe1c642dSBill Krier return (NDR_DRC_OK); 289fe1c642dSBill Krier } 290fe1c642dSBill Krier 291fe1c642dSBill Krier /* 292fe1c642dSBill Krier * samr_s_EnumLocalDomains 293fe1c642dSBill Krier * 294fe1c642dSBill Krier * This is a request for the local domains supported by this server. 295fe1c642dSBill Krier * All we do here is validate the handle and set the status. The real 296fe1c642dSBill Krier * work is done in samr_s_enum_local_domains. 297fe1c642dSBill Krier */ 298fe1c642dSBill Krier static int 299fe1c642dSBill Krier samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa) 300fe1c642dSBill Krier { 301fe1c642dSBill Krier struct samr_EnumLocalDomain *param = arg; 302fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 303fe1c642dSBill Krier DWORD status; 304fe1c642dSBill Krier 305fe1c642dSBill Krier if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) 306fe1c642dSBill Krier status = NT_STATUS_ACCESS_DENIED; 307fe1c642dSBill Krier else 308fe1c642dSBill Krier status = samr_s_enum_local_domains(param, mxa); 309fe1c642dSBill Krier 310fe1c642dSBill Krier if (status == NT_STATUS_SUCCESS) { 311fe1c642dSBill Krier param->enum_context = param->info->entries_read; 312fe1c642dSBill Krier param->total_entries = param->info->entries_read; 313fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 314fe1c642dSBill Krier } else { 315fe1c642dSBill Krier bzero(param, sizeof (struct samr_EnumLocalDomain)); 316fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 317fe1c642dSBill Krier } 318fe1c642dSBill Krier 319fe1c642dSBill Krier return (NDR_DRC_OK); 320fe1c642dSBill Krier } 321fe1c642dSBill Krier 322fe1c642dSBill Krier 323fe1c642dSBill Krier /* 324fe1c642dSBill Krier * samr_s_enum_local_domains 325fe1c642dSBill Krier * 326fe1c642dSBill Krier * This function should only be called via samr_s_EnumLocalDomains to 327fe1c642dSBill Krier * ensure that the appropriate validation is performed. We will answer 328fe1c642dSBill Krier * queries about two domains: the local domain, synonymous with the 329fe1c642dSBill Krier * local hostname, and the BUILTIN domain. So we return these two 330fe1c642dSBill Krier * strings. 331fe1c642dSBill Krier * 332fe1c642dSBill Krier * Returns NT status values. 333fe1c642dSBill Krier */ 334fe1c642dSBill Krier static DWORD 335fe1c642dSBill Krier samr_s_enum_local_domains(struct samr_EnumLocalDomain *param, 336fe1c642dSBill Krier ndr_xa_t *mxa) 337fe1c642dSBill Krier { 338fe1c642dSBill Krier struct samr_LocalDomainInfo *info; 339fe1c642dSBill Krier struct samr_LocalDomainEntry *entry; 340fe1c642dSBill Krier char *hostname; 341fe1c642dSBill Krier 342fe1c642dSBill Krier hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ); 343fe1c642dSBill Krier if (hostname == NULL) 344fe1c642dSBill Krier return (NT_STATUS_NO_MEMORY); 345fe1c642dSBill Krier 346fe1c642dSBill Krier if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0) 347fe1c642dSBill Krier return (NT_STATUS_NO_MEMORY); 348fe1c642dSBill Krier 349fe1c642dSBill Krier entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2); 350fe1c642dSBill Krier if (entry == NULL) 351fe1c642dSBill Krier return (NT_STATUS_NO_MEMORY); 352fe1c642dSBill Krier 353fe1c642dSBill Krier bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2)); 354fe1c642dSBill Krier (void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name); 355fe1c642dSBill Krier (void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name); 356fe1c642dSBill Krier 357fe1c642dSBill Krier info = NDR_NEW(mxa, struct samr_LocalDomainInfo); 358fe1c642dSBill Krier if (info == NULL) 359fe1c642dSBill Krier return (NT_STATUS_NO_MEMORY); 360fe1c642dSBill Krier 361fe1c642dSBill Krier info->entries_read = 2; 362fe1c642dSBill Krier info->entry = entry; 363fe1c642dSBill Krier param->info = info; 364fe1c642dSBill Krier return (NT_STATUS_SUCCESS); 365fe1c642dSBill Krier } 366fe1c642dSBill Krier 367fe1c642dSBill Krier /* 368fe1c642dSBill Krier * samr_s_OpenDomain 369fe1c642dSBill Krier * 370fe1c642dSBill Krier * This is a request to open a domain within the local SAM database. 371fe1c642dSBill Krier * The caller must supply a valid connect handle. 372fe1c642dSBill Krier * We return a handle to be used to access objects within this domain. 373fe1c642dSBill Krier */ 374fe1c642dSBill Krier static int 375fe1c642dSBill Krier samr_s_OpenDomain(void *arg, ndr_xa_t *mxa) 376fe1c642dSBill Krier { 377fe1c642dSBill Krier struct samr_OpenDomain *param = arg; 378fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 379fe1c642dSBill Krier smb_domain_t domain; 380fe1c642dSBill Krier 381fe1c642dSBill Krier if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) { 382fe1c642dSBill Krier bzero(¶m->domain_handle, sizeof (samr_handle_t)); 383fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 384fe1c642dSBill Krier return (NDR_DRC_OK); 385fe1c642dSBill Krier } 386fe1c642dSBill Krier 387fe1c642dSBill Krier if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) { 388fe1c642dSBill Krier bzero(¶m->domain_handle, sizeof (samr_handle_t)); 389fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 390fe1c642dSBill Krier return (NDR_DRC_OK); 391fe1c642dSBill Krier } 392fe1c642dSBill Krier 393fe1c642dSBill Krier if ((domain.di_type != SMB_DOMAIN_BUILTIN) && 394fe1c642dSBill Krier (domain.di_type != SMB_DOMAIN_LOCAL)) { 395fe1c642dSBill Krier bzero(¶m->domain_handle, sizeof (samr_handle_t)); 396fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 397fe1c642dSBill Krier return (NDR_DRC_OK); 398fe1c642dSBill Krier } 399fe1c642dSBill Krier 400fe1c642dSBill Krier id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0); 401fe1c642dSBill Krier if (id) { 402fe1c642dSBill Krier bcopy(id, ¶m->domain_handle, sizeof (samr_handle_t)); 403fe1c642dSBill Krier param->status = 0; 404fe1c642dSBill Krier } else { 405fe1c642dSBill Krier bzero(¶m->domain_handle, sizeof (samr_handle_t)); 406fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 407fe1c642dSBill Krier } 408fe1c642dSBill Krier 409fe1c642dSBill Krier return (NDR_DRC_OK); 410fe1c642dSBill Krier } 411fe1c642dSBill Krier 412fe1c642dSBill Krier /* 413fe1c642dSBill Krier * samr_s_QueryDomainInfo 414fe1c642dSBill Krier * 415fe1c642dSBill Krier * The caller should pass a domain handle. 416fe1c642dSBill Krier * 417fe1c642dSBill Krier * Windows 95 Server Manager sends requests for levels 6 and 7 when 418fe1c642dSBill Krier * the services menu item is selected. Level 2 is basically for getting 419fe1c642dSBill Krier * number of users, groups, and aliases in a domain. 420fe1c642dSBill Krier * We have no information on what the various information levels mean. 421fe1c642dSBill Krier */ 422fe1c642dSBill Krier static int 423fe1c642dSBill Krier samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa) 424fe1c642dSBill Krier { 425fe1c642dSBill Krier struct samr_QueryDomainInfo *param = arg; 426fe1c642dSBill Krier struct samr_QueryDomainInfoRes *info; 427fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 428fe1c642dSBill Krier ndr_handle_t *hd; 429fe1c642dSBill Krier samr_keydata_t *data; 430fe1c642dSBill Krier char *domain; 431fe1c642dSBill Krier char hostname[NETBIOS_NAME_SZ]; 432fe1c642dSBill Krier int alias_cnt, user_cnt; 433fe1c642dSBill Krier int rc = 0; 434fe1c642dSBill Krier 435fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 436fe1c642dSBill Krier bzero(param, sizeof (struct samr_QueryDomainInfo)); 437fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 438fe1c642dSBill Krier return (NDR_DRC_OK); 439fe1c642dSBill Krier } 440fe1c642dSBill Krier 441fe1c642dSBill Krier info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes); 442fe1c642dSBill Krier if (info == NULL) { 443fe1c642dSBill Krier bzero(param, sizeof (struct samr_QueryDomainInfo)); 444fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 445fe1c642dSBill Krier return (NDR_DRC_OK); 446fe1c642dSBill Krier } 447fe1c642dSBill Krier info->switch_value = param->info_level; 448fe1c642dSBill Krier param->info = info; 449fe1c642dSBill Krier 450fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 451fe1c642dSBill Krier 452fe1c642dSBill Krier switch (data->kd_type) { 453fe1c642dSBill Krier case SMB_DOMAIN_BUILTIN: 454fe1c642dSBill Krier domain = "BUILTIN"; 455fe1c642dSBill Krier user_cnt = 0; 456fe1c642dSBill Krier alias_cnt = smb_sam_grp_cnt(data->kd_type); 457fe1c642dSBill Krier break; 458fe1c642dSBill Krier 459fe1c642dSBill Krier case SMB_DOMAIN_LOCAL: 460fe1c642dSBill Krier rc = smb_getnetbiosname(hostname, sizeof (hostname)); 461fe1c642dSBill Krier if (rc == 0) { 462fe1c642dSBill Krier domain = hostname; 463fe1c642dSBill Krier user_cnt = smb_sam_usr_cnt(); 464fe1c642dSBill Krier alias_cnt = smb_sam_grp_cnt(data->kd_type); 465fe1c642dSBill Krier } 466fe1c642dSBill Krier break; 467fe1c642dSBill Krier 468fe1c642dSBill Krier default: 469fe1c642dSBill Krier bzero(param, sizeof (struct samr_QueryDomainInfo)); 470fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 471fe1c642dSBill Krier return (NDR_DRC_OK); 472fe1c642dSBill Krier } 473fe1c642dSBill Krier 474fe1c642dSBill Krier if (rc != 0) { 475fe1c642dSBill Krier bzero(param, sizeof (struct samr_QueryDomainInfo)); 476fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR); 477fe1c642dSBill Krier return (NDR_DRC_OK); 478fe1c642dSBill Krier } 479fe1c642dSBill Krier 480fe1c642dSBill Krier switch (param->info_level) { 481fe1c642dSBill Krier case SAMR_QUERY_DOMAIN_INFO_6: 482fe1c642dSBill Krier info->ru.info6.unknown1 = 0x00000000; 483fe1c642dSBill Krier info->ru.info6.unknown2 = 0x00147FB0; 484fe1c642dSBill Krier info->ru.info6.unknown3 = 0x00000000; 485fe1c642dSBill Krier info->ru.info6.unknown4 = 0x00000000; 486fe1c642dSBill Krier info->ru.info6.unknown5 = 0x00000000; 487fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 488fe1c642dSBill Krier break; 489fe1c642dSBill Krier 490fe1c642dSBill Krier case SAMR_QUERY_DOMAIN_INFO_7: 491fe1c642dSBill Krier info->ru.info7.unknown1 = 0x00000003; 492fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 493fe1c642dSBill Krier break; 494fe1c642dSBill Krier 495fe1c642dSBill Krier case SAMR_QUERY_DOMAIN_INFO_2: 496fe1c642dSBill Krier info->ru.info2.unknown1 = 0x00000000; 497fe1c642dSBill Krier info->ru.info2.unknown2 = 0x80000000; 498fe1c642dSBill Krier 499fe1c642dSBill Krier (void) NDR_MSTRING(mxa, "", 500fe1c642dSBill Krier (ndr_mstring_t *)&(info->ru.info2.s1)); 501fe1c642dSBill Krier (void) NDR_MSTRING(mxa, domain, 502fe1c642dSBill Krier (ndr_mstring_t *)&(info->ru.info2.domain)); 503fe1c642dSBill Krier (void) NDR_MSTRING(mxa, "", 504fe1c642dSBill Krier (ndr_mstring_t *)&(info->ru.info2.s2)); 505fe1c642dSBill Krier 506fe1c642dSBill Krier info->ru.info2.sequence_num = 0x0000002B; 507fe1c642dSBill Krier info->ru.info2.unknown3 = 0x00000000; 508fe1c642dSBill Krier info->ru.info2.unknown4 = 0x00000001; 509fe1c642dSBill Krier info->ru.info2.unknown5 = 0x00000003; 510fe1c642dSBill Krier info->ru.info2.unknown6 = 0x00000001; 511fe1c642dSBill Krier info->ru.info2.num_users = user_cnt; 512fe1c642dSBill Krier info->ru.info2.num_groups = 0; 513fe1c642dSBill Krier info->ru.info2.num_aliases = alias_cnt; 514fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 515fe1c642dSBill Krier break; 516fe1c642dSBill Krier 517fe1c642dSBill Krier default: 518fe1c642dSBill Krier bzero(param, sizeof (struct samr_QueryDomainInfo)); 519fe1c642dSBill Krier return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID); 520fe1c642dSBill Krier }; 521fe1c642dSBill Krier 522fe1c642dSBill Krier return (NDR_DRC_OK); 523fe1c642dSBill Krier } 524fe1c642dSBill Krier 525fe1c642dSBill Krier /* 526*f96bd5c8SAlan Wright * QueryInfoDomain2: Identical to QueryDomainInfo. 527*f96bd5c8SAlan Wright */ 528*f96bd5c8SAlan Wright static int 529*f96bd5c8SAlan Wright samr_s_QueryInfoDomain2(void *arg, ndr_xa_t *mxa) 530*f96bd5c8SAlan Wright { 531*f96bd5c8SAlan Wright return (samr_s_QueryDomainInfo(arg, mxa)); 532*f96bd5c8SAlan Wright } 533*f96bd5c8SAlan Wright 534*f96bd5c8SAlan Wright /* 535fe1c642dSBill Krier * Looks up the given name in the specified domain which could 536fe1c642dSBill Krier * be either the built-in or local domain. 537fe1c642dSBill Krier * 538fe1c642dSBill Krier * CAVEAT: this function should be able to handle a list of 539fe1c642dSBill Krier * names but currently it can only handle one name at a time. 540fe1c642dSBill Krier */ 541fe1c642dSBill Krier static int 542fe1c642dSBill Krier samr_s_LookupNames(void *arg, ndr_xa_t *mxa) 543fe1c642dSBill Krier { 544fe1c642dSBill Krier struct samr_LookupNames *param = arg; 545fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 546fe1c642dSBill Krier ndr_handle_t *hd; 547fe1c642dSBill Krier samr_keydata_t *data; 548fe1c642dSBill Krier smb_account_t account; 549fe1c642dSBill Krier smb_wka_t *wka; 550fe1c642dSBill Krier uint32_t status = NT_STATUS_SUCCESS; 551fe1c642dSBill Krier 552fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) 553fe1c642dSBill Krier status = NT_STATUS_INVALID_HANDLE; 554fe1c642dSBill Krier 555fe1c642dSBill Krier if (param->n_entry != 1) 556fe1c642dSBill Krier status = NT_STATUS_ACCESS_DENIED; 557fe1c642dSBill Krier 558fe1c642dSBill Krier if (param->name.str == NULL) { 559fe1c642dSBill Krier /* 560fe1c642dSBill Krier * Windows NT returns NT_STATUS_NONE_MAPPED. 561fe1c642dSBill Krier * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME. 562fe1c642dSBill Krier */ 563fe1c642dSBill Krier status = NT_STATUS_NONE_MAPPED; 564fe1c642dSBill Krier } 565fe1c642dSBill Krier 566fe1c642dSBill Krier if (status != NT_STATUS_SUCCESS) { 567fe1c642dSBill Krier bzero(param, sizeof (struct samr_LookupNames)); 568fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 569fe1c642dSBill Krier return (NDR_DRC_OK); 570fe1c642dSBill Krier } 571fe1c642dSBill Krier 572fe1c642dSBill Krier param->rids.rid = NDR_NEW(mxa, DWORD); 573fe1c642dSBill Krier param->rid_types.rid_type = NDR_NEW(mxa, DWORD); 574fe1c642dSBill Krier 575fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 576fe1c642dSBill Krier 577fe1c642dSBill Krier switch (data->kd_type) { 578fe1c642dSBill Krier case SMB_DOMAIN_BUILTIN: 579*f96bd5c8SAlan Wright wka = smb_wka_lookup_builtin((char *)param->name.str); 580fe1c642dSBill Krier if (wka != NULL) { 581fe1c642dSBill Krier param->rids.n_entry = 1; 582fe1c642dSBill Krier (void) smb_sid_getrid(wka->wka_binsid, 583fe1c642dSBill Krier ¶m->rids.rid[0]); 584fe1c642dSBill Krier param->rid_types.n_entry = 1; 585fe1c642dSBill Krier param->rid_types.rid_type[0] = wka->wka_type; 586fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 587fe1c642dSBill Krier return (NDR_DRC_OK); 588fe1c642dSBill Krier } 589fe1c642dSBill Krier break; 590fe1c642dSBill Krier 591fe1c642dSBill Krier case SMB_DOMAIN_LOCAL: 592fe1c642dSBill Krier status = smb_sam_lookup_name(NULL, (char *)param->name.str, 593fe1c642dSBill Krier SidTypeUnknown, &account); 594fe1c642dSBill Krier if (status == NT_STATUS_SUCCESS) { 595fe1c642dSBill Krier param->rids.n_entry = 1; 596fe1c642dSBill Krier param->rids.rid[0] = account.a_rid; 597fe1c642dSBill Krier param->rid_types.n_entry = 1; 598fe1c642dSBill Krier param->rid_types.rid_type[0] = account.a_type; 599fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 600fe1c642dSBill Krier smb_account_free(&account); 601fe1c642dSBill Krier return (NDR_DRC_OK); 602fe1c642dSBill Krier } 603fe1c642dSBill Krier break; 604fe1c642dSBill Krier 605fe1c642dSBill Krier default: 606fe1c642dSBill Krier bzero(param, sizeof (struct samr_LookupNames)); 607fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 608fe1c642dSBill Krier return (NDR_DRC_OK); 609fe1c642dSBill Krier } 610fe1c642dSBill Krier 611fe1c642dSBill Krier param->rids.n_entry = 0; 612fe1c642dSBill Krier param->rid_types.n_entry = 0; 613fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED); 614fe1c642dSBill Krier return (NDR_DRC_OK); 615fe1c642dSBill Krier } 616fe1c642dSBill Krier 617fe1c642dSBill Krier /* 618fe1c642dSBill Krier * samr_s_OpenUser 619fe1c642dSBill Krier * 620fe1c642dSBill Krier * This is a request to open a user within a specified domain in the 621fe1c642dSBill Krier * local SAM database. The caller must supply a valid domain handle, 622fe1c642dSBill Krier * obtained via a successful domain open request. The user is 623fe1c642dSBill Krier * specified by the rid in the request. 624fe1c642dSBill Krier */ 625fe1c642dSBill Krier static int 626fe1c642dSBill Krier samr_s_OpenUser(void *arg, ndr_xa_t *mxa) 627fe1c642dSBill Krier { 628fe1c642dSBill Krier struct samr_OpenUser *param = arg; 629fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 630fe1c642dSBill Krier ndr_handle_t *hd; 631fe1c642dSBill Krier samr_keydata_t *data; 632fe1c642dSBill Krier 633fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 634fe1c642dSBill Krier bzero(¶m->user_handle, sizeof (samr_handle_t)); 635fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 636fe1c642dSBill Krier return (NDR_DRC_OK); 637fe1c642dSBill Krier } 638fe1c642dSBill Krier 639fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 640fe1c642dSBill Krier 641fe1c642dSBill Krier id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid); 642fe1c642dSBill Krier if (id == NULL) { 643fe1c642dSBill Krier bzero(¶m->user_handle, sizeof (samr_handle_t)); 644fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 645fe1c642dSBill Krier } else { 646fe1c642dSBill Krier bcopy(id, ¶m->user_handle, sizeof (samr_handle_t)); 647fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 648fe1c642dSBill Krier } 649fe1c642dSBill Krier 650fe1c642dSBill Krier return (NDR_DRC_OK); 651fe1c642dSBill Krier } 652fe1c642dSBill Krier 653fe1c642dSBill Krier /* 654fe1c642dSBill Krier * samr_s_DeleteUser 655fe1c642dSBill Krier * 656fe1c642dSBill Krier * Request to delete a user within a specified domain in the local 657fe1c642dSBill Krier * SAM database. The caller should supply a valid user handle. 658fe1c642dSBill Krier */ 659fe1c642dSBill Krier /*ARGSUSED*/ 660fe1c642dSBill Krier static int 661fe1c642dSBill Krier samr_s_DeleteUser(void *arg, ndr_xa_t *mxa) 662fe1c642dSBill Krier { 663fe1c642dSBill Krier struct samr_DeleteUser *param = arg; 664fe1c642dSBill Krier 665fe1c642dSBill Krier bzero(param, sizeof (struct samr_DeleteUser)); 666fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 667fe1c642dSBill Krier return (NDR_DRC_OK); 668fe1c642dSBill Krier } 669fe1c642dSBill Krier 670fe1c642dSBill Krier /* 671fe1c642dSBill Krier * samr_s_QueryUserInfo 672fe1c642dSBill Krier * 673fe1c642dSBill Krier * Returns: 674fe1c642dSBill Krier * NT_STATUS_SUCCESS 675fe1c642dSBill Krier * NT_STATUS_ACCESS_DENIED 676fe1c642dSBill Krier * NT_STATUS_INVALID_INFO_CLASS 677fe1c642dSBill Krier */ 678fe1c642dSBill Krier /*ARGSUSED*/ 679fe1c642dSBill Krier static int 680fe1c642dSBill Krier samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa) 681fe1c642dSBill Krier { 682fe1c642dSBill Krier static uint16_t owf_buf[8]; 683fe1c642dSBill Krier static uint8_t hour_buf[SAMR_SET_USER_HOURS_SZ]; 684fe1c642dSBill Krier struct samr_QueryUserInfo *param = arg; 685fe1c642dSBill Krier struct samr_QueryUserInfo21 *all_info; 686fe1c642dSBill Krier ndr_hdid_t *id; 687fe1c642dSBill Krier ndr_handle_t *hd; 688fe1c642dSBill Krier samr_keydata_t *data; 689fe1c642dSBill Krier smb_domain_t di; 690fe1c642dSBill Krier smb_account_t account; 691fe1c642dSBill Krier smb_sid_t *sid; 692fe1c642dSBill Krier uint32_t status; 693fe1c642dSBill Krier 694fe1c642dSBill Krier id = (ndr_hdid_t *)¶m->user_handle; 695fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) { 696fe1c642dSBill Krier status = NT_STATUS_INVALID_HANDLE; 697fe1c642dSBill Krier goto QueryUserInfoError; 698fe1c642dSBill Krier } 699fe1c642dSBill Krier 700fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 701fe1c642dSBill Krier 702fe1c642dSBill Krier if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) { 703fe1c642dSBill Krier status = NT_STATUS_ACCESS_DENIED; 704fe1c642dSBill Krier goto QueryUserInfoError; 705fe1c642dSBill Krier } 706fe1c642dSBill Krier 707fe1c642dSBill Krier if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) { 708fe1c642dSBill Krier status = NT_STATUS_ACCESS_DENIED; 709fe1c642dSBill Krier goto QueryUserInfoError; 710fe1c642dSBill Krier } 711fe1c642dSBill Krier 712fe1c642dSBill Krier if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) { 713fe1c642dSBill Krier status = NT_STATUS_ACCESS_DENIED; 714fe1c642dSBill Krier goto QueryUserInfoError; 715fe1c642dSBill Krier } 716fe1c642dSBill Krier 717fe1c642dSBill Krier if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) { 718fe1c642dSBill Krier status = NT_STATUS_ACCESS_DENIED; 719fe1c642dSBill Krier goto QueryUserInfoError; 720fe1c642dSBill Krier } 721fe1c642dSBill Krier 722fe1c642dSBill Krier all_info = ¶m->ru.info21; 723fe1c642dSBill Krier bzero(all_info, sizeof (struct samr_QueryUserInfo21)); 724fe1c642dSBill Krier 725fe1c642dSBill Krier all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID; 726fe1c642dSBill Krier 727fe1c642dSBill Krier (void) NDR_MSTRING(mxa, account.a_name, 728fe1c642dSBill Krier (ndr_mstring_t *)&all_info->UserName); 729fe1c642dSBill Krier all_info->UserId = data->kd_rid; 730fe1c642dSBill Krier 731fe1c642dSBill Krier all_info->LmOwfPassword.length = 16; 732fe1c642dSBill Krier all_info->LmOwfPassword.maxlen = 16; 733fe1c642dSBill Krier all_info->LmOwfPassword.buf = owf_buf; 734fe1c642dSBill Krier all_info->NtOwfPassword.length = 16; 735fe1c642dSBill Krier all_info->NtOwfPassword.maxlen = 16; 736fe1c642dSBill Krier all_info->NtOwfPassword.buf = owf_buf; 737fe1c642dSBill Krier all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK; 738fe1c642dSBill Krier all_info->LogonHours.hours = hour_buf; 739fe1c642dSBill Krier 740fe1c642dSBill Krier param->address = 1; 741fe1c642dSBill Krier param->switch_index = SAMR_QUERY_USER_ALL_INFO; 742fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 743fe1c642dSBill Krier return (NDR_DRC_OK); 744fe1c642dSBill Krier 745fe1c642dSBill Krier QueryUserInfoError: 746fe1c642dSBill Krier bzero(param, sizeof (struct samr_QueryUserInfo)); 747fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 748fe1c642dSBill Krier return (NDR_DRC_OK); 749fe1c642dSBill Krier } 750fe1c642dSBill Krier 751fe1c642dSBill Krier /* 752fe1c642dSBill Krier * samr_s_QueryUserGroups 753fe1c642dSBill Krier * 754fe1c642dSBill Krier * Request the list of groups of which a user is a member. 755fe1c642dSBill Krier * The user is identified from the handle, which contains an 756fe1c642dSBill Krier * rid in the discriminator field. Note that this is a local user. 757fe1c642dSBill Krier */ 758fe1c642dSBill Krier static int 759fe1c642dSBill Krier samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa) 760fe1c642dSBill Krier { 761fe1c642dSBill Krier struct samr_QueryUserGroups *param = arg; 762fe1c642dSBill Krier struct samr_UserGroupInfo *info; 763fe1c642dSBill Krier struct samr_UserGroups *group; 764fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->user_handle; 765fe1c642dSBill Krier ndr_handle_t *hd; 766fe1c642dSBill Krier samr_keydata_t *data; 767fe1c642dSBill Krier smb_sid_t *user_sid = NULL; 768fe1c642dSBill Krier smb_group_t grp; 769fe1c642dSBill Krier smb_giter_t gi; 770fe1c642dSBill Krier smb_domain_t di; 771fe1c642dSBill Krier uint32_t status; 772fe1c642dSBill Krier int size; 773fe1c642dSBill Krier int ngrp_max; 774fe1c642dSBill Krier 775fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) { 776fe1c642dSBill Krier status = NT_STATUS_ACCESS_DENIED; 777fe1c642dSBill Krier goto query_error; 778fe1c642dSBill Krier } 779fe1c642dSBill Krier 780fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 781fe1c642dSBill Krier switch (data->kd_type) { 782fe1c642dSBill Krier case SMB_DOMAIN_BUILTIN: 783fe1c642dSBill Krier case SMB_DOMAIN_LOCAL: 784fe1c642dSBill Krier if (!smb_domain_lookup_type(data->kd_type, &di)) { 785fe1c642dSBill Krier status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; 786fe1c642dSBill Krier goto query_error; 787fe1c642dSBill Krier } 788fe1c642dSBill Krier break; 789fe1c642dSBill Krier default: 790fe1c642dSBill Krier status = NT_STATUS_INVALID_HANDLE; 791fe1c642dSBill Krier goto query_error; 792fe1c642dSBill Krier } 793fe1c642dSBill Krier 794fe1c642dSBill Krier user_sid = smb_sid_splice(di.di_binsid, data->kd_rid); 795fe1c642dSBill Krier if (user_sid == NULL) { 796fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 797fe1c642dSBill Krier goto query_error; 798fe1c642dSBill Krier } 799fe1c642dSBill Krier 800fe1c642dSBill Krier info = NDR_NEW(mxa, struct samr_UserGroupInfo); 801fe1c642dSBill Krier if (info == NULL) { 802fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 803fe1c642dSBill Krier goto query_error; 804fe1c642dSBill Krier } 805fe1c642dSBill Krier bzero(info, sizeof (struct samr_UserGroupInfo)); 806fe1c642dSBill Krier 807fe1c642dSBill Krier size = 32 * 1024; 808fe1c642dSBill Krier info->groups = NDR_MALLOC(mxa, size); 809fe1c642dSBill Krier if (info->groups == NULL) { 810fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 811fe1c642dSBill Krier goto query_error; 812fe1c642dSBill Krier } 813fe1c642dSBill Krier ngrp_max = size / sizeof (struct samr_UserGroups); 814fe1c642dSBill Krier 815fe1c642dSBill Krier if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { 816fe1c642dSBill Krier status = NT_STATUS_INTERNAL_ERROR; 817fe1c642dSBill Krier goto query_error; 818fe1c642dSBill Krier } 819fe1c642dSBill Krier 820fe1c642dSBill Krier info->n_entry = 0; 821fe1c642dSBill Krier group = info->groups; 822fe1c642dSBill Krier while ((info->n_entry < ngrp_max) && 823fe1c642dSBill Krier (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) { 824fe1c642dSBill Krier if (smb_lgrp_is_member(&grp, user_sid)) { 825fe1c642dSBill Krier group->rid = grp.sg_rid; 826fe1c642dSBill Krier group->attr = grp.sg_attr; 827fe1c642dSBill Krier group++; 828fe1c642dSBill Krier info->n_entry++; 829fe1c642dSBill Krier } 830fe1c642dSBill Krier smb_lgrp_free(&grp); 831fe1c642dSBill Krier } 832fe1c642dSBill Krier smb_lgrp_iterclose(&gi); 833fe1c642dSBill Krier 834fe1c642dSBill Krier free(user_sid); 835fe1c642dSBill Krier param->info = info; 836fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 837fe1c642dSBill Krier return (NDR_DRC_OK); 838fe1c642dSBill Krier 839fe1c642dSBill Krier query_error: 840fe1c642dSBill Krier free(user_sid); 841fe1c642dSBill Krier bzero(param, sizeof (struct samr_QueryUserGroups)); 842fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 843fe1c642dSBill Krier return (NDR_DRC_OK); 844fe1c642dSBill Krier } 845fe1c642dSBill Krier 846fe1c642dSBill Krier /* 847fe1c642dSBill Krier * samr_s_OpenGroup 848fe1c642dSBill Krier * 849fe1c642dSBill Krier * This is a request to open a group within the specified domain in the 850fe1c642dSBill Krier * local SAM database. The caller must supply a valid domain handle, 851fe1c642dSBill Krier * obtained via a successful domain open request. The group is 852fe1c642dSBill Krier * specified by the rid in the request. If this is a local RID it 853fe1c642dSBill Krier * should already be encoded with type information. 854fe1c642dSBill Krier * 855fe1c642dSBill Krier * We return a handle to be used to access information about this group. 856fe1c642dSBill Krier */ 857fe1c642dSBill Krier static int 858fe1c642dSBill Krier samr_s_OpenGroup(void *arg, ndr_xa_t *mxa) 859fe1c642dSBill Krier { 860fe1c642dSBill Krier struct samr_OpenGroup *param = arg; 861fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 862fe1c642dSBill Krier ndr_handle_t *hd; 863fe1c642dSBill Krier samr_keydata_t *data; 864fe1c642dSBill Krier 865fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 866fe1c642dSBill Krier bzero(¶m->group_handle, sizeof (samr_handle_t)); 867fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 868fe1c642dSBill Krier return (NDR_DRC_OK); 869fe1c642dSBill Krier } 870fe1c642dSBill Krier 871fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 872fe1c642dSBill Krier id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid); 873fe1c642dSBill Krier 874fe1c642dSBill Krier if (id) { 875fe1c642dSBill Krier bcopy(id, ¶m->group_handle, sizeof (samr_handle_t)); 876fe1c642dSBill Krier param->status = 0; 877fe1c642dSBill Krier } else { 878fe1c642dSBill Krier bzero(¶m->group_handle, sizeof (samr_handle_t)); 879fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 880fe1c642dSBill Krier } 881fe1c642dSBill Krier 882fe1c642dSBill Krier return (NDR_DRC_OK); 883fe1c642dSBill Krier } 884fe1c642dSBill Krier 885fe1c642dSBill Krier /* 886fe1c642dSBill Krier * samr_s_Connect 887fe1c642dSBill Krier * 888fe1c642dSBill Krier * This is a request to connect to the local SAM database. 889fe1c642dSBill Krier * We don't support any form of update request and our database doesn't 890fe1c642dSBill Krier * contain any private information, so there is little point in doing 891fe1c642dSBill Krier * any access access checking here. 892fe1c642dSBill Krier * 893fe1c642dSBill Krier * Return a handle for use with subsequent SAM requests. 894fe1c642dSBill Krier */ 895fe1c642dSBill Krier static int 896fe1c642dSBill Krier samr_s_Connect(void *arg, ndr_xa_t *mxa) 897fe1c642dSBill Krier { 898fe1c642dSBill Krier struct samr_Connect *param = arg; 899fe1c642dSBill Krier ndr_hdid_t *id; 900fe1c642dSBill Krier 901fe1c642dSBill Krier id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0); 902fe1c642dSBill Krier if (id) { 903fe1c642dSBill Krier bcopy(id, ¶m->handle, sizeof (samr_handle_t)); 904fe1c642dSBill Krier param->status = 0; 905fe1c642dSBill Krier } else { 906fe1c642dSBill Krier bzero(¶m->handle, sizeof (samr_handle_t)); 907fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 908fe1c642dSBill Krier } 909fe1c642dSBill Krier 910fe1c642dSBill Krier return (NDR_DRC_OK); 911fe1c642dSBill Krier } 912fe1c642dSBill Krier 913fe1c642dSBill Krier /* 914fe1c642dSBill Krier * samr_s_GetUserPwInfo 915fe1c642dSBill Krier * 916*f96bd5c8SAlan Wright * Request for a user's password policy information. 917fe1c642dSBill Krier */ 918fe1c642dSBill Krier /*ARGSUSED*/ 919fe1c642dSBill Krier static int 920fe1c642dSBill Krier samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa) 921fe1c642dSBill Krier { 922*f96bd5c8SAlan Wright static samr_password_info_t pwinfo; 923fe1c642dSBill Krier struct samr_GetUserPwInfo *param = arg; 924fe1c642dSBill Krier 925*f96bd5c8SAlan Wright param->pwinfo = &pwinfo; 926*f96bd5c8SAlan Wright param->status = NT_STATUS_SUCCESS; 927fe1c642dSBill Krier return (NDR_DRC_OK); 928fe1c642dSBill Krier } 929fe1c642dSBill Krier 930fe1c642dSBill Krier /* 931fe1c642dSBill Krier * samr_s_CreateUser 932fe1c642dSBill Krier */ 933fe1c642dSBill Krier /*ARGSUSED*/ 934fe1c642dSBill Krier static int 935fe1c642dSBill Krier samr_s_CreateUser(void *arg, ndr_xa_t *mxa) 936fe1c642dSBill Krier { 937fe1c642dSBill Krier struct samr_CreateUser *param = arg; 938fe1c642dSBill Krier 939fe1c642dSBill Krier bzero(¶m->user_handle, sizeof (samr_handle_t)); 940fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 941fe1c642dSBill Krier return (NDR_DRC_OK); 942fe1c642dSBill Krier } 943fe1c642dSBill Krier 944fe1c642dSBill Krier /* 945fe1c642dSBill Krier * samr_s_ChangeUserPasswd 946fe1c642dSBill Krier */ 947fe1c642dSBill Krier /*ARGSUSED*/ 948fe1c642dSBill Krier static int 949fe1c642dSBill Krier samr_s_ChangeUserPasswd(void *arg, ndr_xa_t *mxa) 950fe1c642dSBill Krier { 951fe1c642dSBill Krier struct samr_ChangeUserPasswd *param = arg; 952fe1c642dSBill Krier 953fe1c642dSBill Krier bzero(param, sizeof (struct samr_ChangeUserPasswd)); 954fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 955fe1c642dSBill Krier return (NDR_DRC_OK); 956fe1c642dSBill Krier } 957fe1c642dSBill Krier 958fe1c642dSBill Krier /* 959fe1c642dSBill Krier * samr_s_GetDomainPwInfo 960*f96bd5c8SAlan Wright * 961*f96bd5c8SAlan Wright * Request for the domain password policy information. 962fe1c642dSBill Krier */ 963fe1c642dSBill Krier /*ARGSUSED*/ 964fe1c642dSBill Krier static int 965fe1c642dSBill Krier samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa) 966fe1c642dSBill Krier { 967*f96bd5c8SAlan Wright static samr_password_info_t pwinfo; 968fe1c642dSBill Krier struct samr_GetDomainPwInfo *param = arg; 969fe1c642dSBill Krier 970*f96bd5c8SAlan Wright param->pwinfo = &pwinfo; 971*f96bd5c8SAlan Wright param->status = NT_STATUS_SUCCESS; 972fe1c642dSBill Krier return (NDR_DRC_OK); 973fe1c642dSBill Krier } 974fe1c642dSBill Krier 975fe1c642dSBill Krier /* 976fe1c642dSBill Krier * samr_s_SetUserInfo 977fe1c642dSBill Krier */ 978fe1c642dSBill Krier /*ARGSUSED*/ 979fe1c642dSBill Krier static int 980fe1c642dSBill Krier samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa) 981fe1c642dSBill Krier { 982fe1c642dSBill Krier struct samr_SetUserInfo *param = arg; 983fe1c642dSBill Krier 984fe1c642dSBill Krier bzero(param, sizeof (struct samr_SetUserInfo)); 985fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 986fe1c642dSBill Krier return (NDR_DRC_OK); 987fe1c642dSBill Krier } 988fe1c642dSBill Krier 989fe1c642dSBill Krier /* 990fe1c642dSBill Krier * samr_s_QueryDispInfo 991fe1c642dSBill Krier * 992fe1c642dSBill Krier * This function currently return local users' information only. 993fe1c642dSBill Krier * This RPC is called repeatedly until all the users info are 994fe1c642dSBill Krier * retrieved. 995fe1c642dSBill Krier * 996fe1c642dSBill Krier * The total count and the returned count are returned as total size 997fe1c642dSBill Krier * and returned size. The client doesn't seem to care. 998fe1c642dSBill Krier */ 999fe1c642dSBill Krier static int 1000fe1c642dSBill Krier samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa) 1001fe1c642dSBill Krier { 1002fe1c642dSBill Krier struct samr_QueryDispInfo *param = arg; 1003fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 1004fe1c642dSBill Krier ndr_handle_t *hd; 1005fe1c642dSBill Krier samr_keydata_t *data; 1006fe1c642dSBill Krier DWORD status = NT_STATUS_SUCCESS; 1007fe1c642dSBill Krier struct user_acct_info *user; 1008fe1c642dSBill Krier smb_pwditer_t pwi; 1009fe1c642dSBill Krier smb_luser_t *uinfo; 1010fe1c642dSBill Krier int num_users; 1011fe1c642dSBill Krier int start_idx; 1012fe1c642dSBill Krier int max_retcnt, retcnt; 1013fe1c642dSBill Krier int skip; 1014fe1c642dSBill Krier 1015fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 1016fe1c642dSBill Krier status = NT_STATUS_INVALID_HANDLE; 1017fe1c642dSBill Krier goto error; 1018fe1c642dSBill Krier } 1019fe1c642dSBill Krier 1020fe1c642dSBill Krier if (!SAMR_VALID_DISPLEVEL(param->level)) { 1021fe1c642dSBill Krier status = NT_STATUS_INVALID_INFO_CLASS; 1022fe1c642dSBill Krier goto error; 1023fe1c642dSBill Krier } 1024fe1c642dSBill Krier 1025fe1c642dSBill Krier if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) { 1026fe1c642dSBill Krier status = NT_STATUS_NOT_IMPLEMENTED; 1027fe1c642dSBill Krier goto error; 1028fe1c642dSBill Krier } 1029fe1c642dSBill Krier 1030fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 1031fe1c642dSBill Krier 1032fe1c642dSBill Krier switch (data->kd_type) { 1033fe1c642dSBill Krier case SMB_DOMAIN_BUILTIN: 1034fe1c642dSBill Krier goto no_info; 1035fe1c642dSBill Krier 1036fe1c642dSBill Krier case SMB_DOMAIN_LOCAL: 1037fe1c642dSBill Krier num_users = smb_sam_usr_cnt(); 1038fe1c642dSBill Krier start_idx = param->start_idx; 1039fe1c642dSBill Krier if ((num_users == 0) || (start_idx >= num_users)) 1040fe1c642dSBill Krier goto no_info; 1041fe1c642dSBill Krier 1042fe1c642dSBill Krier max_retcnt = num_users - start_idx; 1043fe1c642dSBill Krier if (max_retcnt > param->max_entries) 1044fe1c642dSBill Krier max_retcnt = param->max_entries; 1045fe1c642dSBill Krier param->users.acct = NDR_MALLOC(mxa, 1046fe1c642dSBill Krier max_retcnt * sizeof (struct user_acct_info)); 1047fe1c642dSBill Krier user = param->users.acct; 1048fe1c642dSBill Krier if (user == NULL) { 1049fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 1050fe1c642dSBill Krier goto error; 1051fe1c642dSBill Krier } 1052fe1c642dSBill Krier bzero(user, max_retcnt * sizeof (struct user_acct_info)); 1053fe1c642dSBill Krier 1054fe1c642dSBill Krier if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS) 1055fe1c642dSBill Krier goto no_info; 1056fe1c642dSBill Krier 1057fe1c642dSBill Krier skip = retcnt = 0; 1058fe1c642dSBill Krier while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) { 1059fe1c642dSBill Krier if (skip++ < start_idx) 1060fe1c642dSBill Krier continue; 1061fe1c642dSBill Krier 1062fe1c642dSBill Krier if (retcnt++ >= max_retcnt) 1063fe1c642dSBill Krier break; 1064fe1c642dSBill Krier 1065fe1c642dSBill Krier assert(uinfo->su_name != NULL); 1066fe1c642dSBill Krier 1067fe1c642dSBill Krier user->index = start_idx + retcnt; 1068fe1c642dSBill Krier user->rid = uinfo->su_rid; 1069fe1c642dSBill Krier user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP; 1070fe1c642dSBill Krier if (uinfo->su_ctrl & SMB_PWF_DISABLE) 1071fe1c642dSBill Krier user->ctrl |= ACF_DISABLED; 1072fe1c642dSBill Krier if (NDR_MSTRING(mxa, uinfo->su_name, 1073fe1c642dSBill Krier (ndr_mstring_t *)&user->name) == -1) { 1074fe1c642dSBill Krier smb_pwd_iterclose(&pwi); 1075fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 1076fe1c642dSBill Krier goto error; 1077fe1c642dSBill Krier } 1078fe1c642dSBill Krier (void) NDR_MSTRING(mxa, uinfo->su_fullname, 1079fe1c642dSBill Krier (ndr_mstring_t *)&user->fullname); 1080fe1c642dSBill Krier (void) NDR_MSTRING(mxa, uinfo->su_desc, 1081fe1c642dSBill Krier (ndr_mstring_t *)&user->desc); 1082fe1c642dSBill Krier user++; 1083fe1c642dSBill Krier } 1084fe1c642dSBill Krier smb_pwd_iterclose(&pwi); 1085fe1c642dSBill Krier 1086fe1c642dSBill Krier if (retcnt >= max_retcnt) { 1087fe1c642dSBill Krier retcnt = max_retcnt; 1088fe1c642dSBill Krier param->status = status; 1089fe1c642dSBill Krier } else { 1090fe1c642dSBill Krier param->status = ERROR_MORE_ENTRIES; 1091fe1c642dSBill Krier } 1092fe1c642dSBill Krier 1093fe1c642dSBill Krier param->users.total_size = num_users; 1094fe1c642dSBill Krier param->users.returned_size = retcnt; 1095fe1c642dSBill Krier param->users.switch_value = param->level; 1096fe1c642dSBill Krier param->users.count = retcnt; 1097fe1c642dSBill Krier 1098fe1c642dSBill Krier break; 1099fe1c642dSBill Krier 1100fe1c642dSBill Krier default: 1101fe1c642dSBill Krier status = NT_STATUS_INVALID_HANDLE; 1102fe1c642dSBill Krier goto error; 1103fe1c642dSBill Krier } 1104fe1c642dSBill Krier 1105fe1c642dSBill Krier return (NDR_DRC_OK); 1106fe1c642dSBill Krier 1107fe1c642dSBill Krier no_info: 1108fe1c642dSBill Krier param->users.total_size = 0; 1109fe1c642dSBill Krier param->users.returned_size = 0; 1110fe1c642dSBill Krier param->users.switch_value = param->level; 1111fe1c642dSBill Krier param->users.count = 0; 1112fe1c642dSBill Krier param->users.acct = NULL; 1113fe1c642dSBill Krier param->status = status; 1114fe1c642dSBill Krier return (NDR_DRC_OK); 1115fe1c642dSBill Krier 1116fe1c642dSBill Krier error: 1117fe1c642dSBill Krier bzero(param, sizeof (struct samr_QueryDispInfo)); 1118fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 1119fe1c642dSBill Krier return (NDR_DRC_OK); 1120fe1c642dSBill Krier } 1121fe1c642dSBill Krier 1122fe1c642dSBill Krier /* 1123fe1c642dSBill Krier * samr_s_EnumDomainGroups 1124fe1c642dSBill Krier * 1125fe1c642dSBill Krier * 1126fe1c642dSBill Krier * This function is supposed to return local group information. 1127fe1c642dSBill Krier * As we don't support local users, this function dosen't send 1128fe1c642dSBill Krier * back any information. 1129fe1c642dSBill Krier * 1130fe1c642dSBill Krier * Added template that returns information for a domain group as None. 1131fe1c642dSBill Krier * All information is hard-coded from packet captures. 1132fe1c642dSBill Krier */ 1133fe1c642dSBill Krier static int 1134fe1c642dSBill Krier samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa) 1135fe1c642dSBill Krier { 1136fe1c642dSBill Krier struct samr_EnumDomainGroups *param = arg; 1137fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 1138fe1c642dSBill Krier DWORD status = NT_STATUS_SUCCESS; 1139fe1c642dSBill Krier 1140fe1c642dSBill Krier if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) 1141fe1c642dSBill Krier status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1142fe1c642dSBill Krier 1143fe1c642dSBill Krier param->total_size = 0; 1144fe1c642dSBill Krier param->returned_size = 0; 1145fe1c642dSBill Krier param->switch_value = 3; 1146fe1c642dSBill Krier param->count = 0; 1147fe1c642dSBill Krier param->groups = 0; 1148fe1c642dSBill Krier param->status = status; 1149fe1c642dSBill Krier return (NDR_DRC_OK); 1150fe1c642dSBill Krier 1151fe1c642dSBill Krier #ifdef SAMR_SUPPORT_GROUPS 1152fe1c642dSBill Krier if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) { 1153fe1c642dSBill Krier param->total_size = 0; 1154fe1c642dSBill Krier param->returned_size = 0; 1155fe1c642dSBill Krier param->switch_value = 3; 1156fe1c642dSBill Krier param->count = 0; 1157fe1c642dSBill Krier param->groups = 0; 1158fe1c642dSBill Krier } else { 1159fe1c642dSBill Krier param->total_size = 64; 1160fe1c642dSBill Krier param->returned_size = 64; 1161fe1c642dSBill Krier param->switch_value = 3; 1162fe1c642dSBill Krier param->count = 1; 1163fe1c642dSBill Krier param->groups = (struct group_disp_info *)NDR_MALLOC( 1164fe1c642dSBill Krier mxa, sizeof (struct group_disp_info)); 1165fe1c642dSBill Krier 1166fe1c642dSBill Krier param->groups->count = 1; 1167fe1c642dSBill Krier param->groups->acct[0].index = 1; 1168fe1c642dSBill Krier param->groups->acct[0].rid = 513; 1169fe1c642dSBill Krier param->groups->acct[0].ctrl = 0x7; 1170fe1c642dSBill Krier (void) NDR_MSTRING(mxa, "None", 1171fe1c642dSBill Krier (ndr_mstring_t *)¶m->groups->acct[0].name); 1172fe1c642dSBill Krier 1173fe1c642dSBill Krier (void) NDR_MSTRING(mxa, "Ordinary users", 1174fe1c642dSBill Krier (ndr_mstring_t *)¶m->groups->acct[0].desc); 1175fe1c642dSBill Krier } 1176fe1c642dSBill Krier 1177fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 1178fe1c642dSBill Krier return (NDR_DRC_OK); 1179fe1c642dSBill Krier #endif 1180fe1c642dSBill Krier } 1181fe1c642dSBill Krier 1182fe1c642dSBill Krier /* 1183fe1c642dSBill Krier * samr_s_OpenAlias 1184fe1c642dSBill Krier * 1185fe1c642dSBill Krier * Lookup for requested alias, if it exists return a handle 1186fe1c642dSBill Krier * for that alias. The alias domain sid should match with 1187fe1c642dSBill Krier * the passed domain handle. 1188fe1c642dSBill Krier */ 1189fe1c642dSBill Krier static int 1190fe1c642dSBill Krier samr_s_OpenAlias(void *arg, ndr_xa_t *mxa) 1191fe1c642dSBill Krier { 1192fe1c642dSBill Krier struct samr_OpenAlias *param = arg; 1193fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 1194fe1c642dSBill Krier ndr_handle_t *hd; 1195fe1c642dSBill Krier samr_keydata_t *data; 1196*f96bd5c8SAlan Wright smb_gdomain_t gd_type; 1197*f96bd5c8SAlan Wright smb_sid_t *sid; 1198*f96bd5c8SAlan Wright smb_wka_t *wka; 1199*f96bd5c8SAlan Wright char sidstr[SMB_SID_STRSZ]; 1200*f96bd5c8SAlan Wright uint32_t rid; 1201*f96bd5c8SAlan Wright uint32_t status; 1202fe1c642dSBill Krier int rc; 1203fe1c642dSBill Krier 1204fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 1205fe1c642dSBill Krier status = NT_STATUS_INVALID_HANDLE; 1206fe1c642dSBill Krier goto open_alias_err; 1207fe1c642dSBill Krier } 1208fe1c642dSBill Krier 1209fe1c642dSBill Krier if (param->access_mask != SAMR_ALIAS_ACCESS_GET_INFO) { 1210fe1c642dSBill Krier status = NT_STATUS_ACCESS_DENIED; 1211fe1c642dSBill Krier goto open_alias_err; 1212fe1c642dSBill Krier } 1213fe1c642dSBill Krier 1214fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 1215*f96bd5c8SAlan Wright gd_type = (smb_gdomain_t)data->kd_type; 1216*f96bd5c8SAlan Wright rid = param->rid; 1217*f96bd5c8SAlan Wright 1218*f96bd5c8SAlan Wright switch (gd_type) { 1219*f96bd5c8SAlan Wright case SMB_LGRP_BUILTIN: 1220*f96bd5c8SAlan Wright (void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d", 1221*f96bd5c8SAlan Wright NT_BUILTIN_DOMAIN_SIDSTR, rid); 1222*f96bd5c8SAlan Wright if ((sid = smb_sid_fromstr(sidstr)) == NULL) { 1223*f96bd5c8SAlan Wright status = NT_STATUS_NO_SUCH_ALIAS; 1224*f96bd5c8SAlan Wright goto open_alias_err; 1225*f96bd5c8SAlan Wright } 1226*f96bd5c8SAlan Wright 1227*f96bd5c8SAlan Wright wka = smb_wka_lookup_sid(sid); 1228*f96bd5c8SAlan Wright smb_sid_free(sid); 1229*f96bd5c8SAlan Wright 1230*f96bd5c8SAlan Wright if (wka == NULL) { 1231*f96bd5c8SAlan Wright status = NT_STATUS_NO_SUCH_ALIAS; 1232*f96bd5c8SAlan Wright goto open_alias_err; 1233*f96bd5c8SAlan Wright } 1234*f96bd5c8SAlan Wright break; 1235*f96bd5c8SAlan Wright 1236*f96bd5c8SAlan Wright case SMB_LGRP_LOCAL: 1237*f96bd5c8SAlan Wright rc = smb_lgrp_getbyrid(rid, gd_type, NULL); 1238fe1c642dSBill Krier if (rc != SMB_LGRP_SUCCESS) { 1239fe1c642dSBill Krier status = NT_STATUS_NO_SUCH_ALIAS; 1240fe1c642dSBill Krier goto open_alias_err; 1241fe1c642dSBill Krier } 1242*f96bd5c8SAlan Wright break; 1243*f96bd5c8SAlan Wright 1244*f96bd5c8SAlan Wright default: 1245*f96bd5c8SAlan Wright status = NT_STATUS_NO_SUCH_ALIAS; 1246*f96bd5c8SAlan Wright goto open_alias_err; 1247*f96bd5c8SAlan Wright } 1248fe1c642dSBill Krier 1249fe1c642dSBill Krier id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid); 1250fe1c642dSBill Krier if (id) { 1251fe1c642dSBill Krier bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t)); 1252fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 1253fe1c642dSBill Krier return (NDR_DRC_OK); 1254fe1c642dSBill Krier } 1255fe1c642dSBill Krier 1256fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 1257fe1c642dSBill Krier 1258fe1c642dSBill Krier open_alias_err: 1259fe1c642dSBill Krier bzero(¶m->alias_handle, sizeof (samr_handle_t)); 1260fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 1261fe1c642dSBill Krier return (NDR_DRC_OK); 1262fe1c642dSBill Krier } 1263fe1c642dSBill Krier 1264fe1c642dSBill Krier /* 1265fe1c642dSBill Krier * samr_s_CreateDomainAlias 1266fe1c642dSBill Krier * 1267fe1c642dSBill Krier * Creates a local group in the security database, which is the 1268fe1c642dSBill Krier * security accounts manager (SAM) 1269fe1c642dSBill Krier * For more information you can look at MSDN page for NetLocalGroupAdd. 1270fe1c642dSBill Krier * This RPC is used by CMC and right now it returns access denied. 1271fe1c642dSBill Krier * The peice of code that creates a local group doesn't get compiled. 1272fe1c642dSBill Krier */ 1273fe1c642dSBill Krier /*ARGSUSED*/ 1274fe1c642dSBill Krier static int 1275fe1c642dSBill Krier samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa) 1276fe1c642dSBill Krier { 1277fe1c642dSBill Krier struct samr_CreateDomainAlias *param = arg; 1278fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; 1279fe1c642dSBill Krier 1280fe1c642dSBill Krier if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) { 1281fe1c642dSBill Krier bzero(param, sizeof (struct samr_CreateDomainAlias)); 1282fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1283fe1c642dSBill Krier return (NDR_DRC_OK); 1284fe1c642dSBill Krier } 1285fe1c642dSBill Krier 1286fe1c642dSBill Krier bzero(param, sizeof (struct samr_CreateDomainAlias)); 1287fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 1288fe1c642dSBill Krier return (NDR_DRC_OK); 1289fe1c642dSBill Krier 1290fe1c642dSBill Krier #ifdef SAMR_SUPPORT_ADD_ALIAS 1291fe1c642dSBill Krier DWORD status = NT_STATUS_SUCCESS; 1292fe1c642dSBill Krier nt_group_t *grp; 1293fe1c642dSBill Krier char *alias_name; 1294fe1c642dSBill Krier 1295fe1c642dSBill Krier alias_name = param->alias_name.str; 1296fe1c642dSBill Krier if (alias_name == 0) { 1297fe1c642dSBill Krier status = NT_STATUS_INVALID_PARAMETER; 1298fe1c642dSBill Krier goto create_alias_err; 1299fe1c642dSBill Krier } 1300fe1c642dSBill Krier 1301fe1c642dSBill Krier /* 1302fe1c642dSBill Krier * Check access mask. User should be member of 1303fe1c642dSBill Krier * Administrators or Account Operators local group. 1304fe1c642dSBill Krier */ 1305fe1c642dSBill Krier status = nt_group_add(alias_name, 0, 1306fe1c642dSBill Krier NT_GROUP_AF_ADD | NT_GROUP_AF_LOCAL); 1307fe1c642dSBill Krier 1308fe1c642dSBill Krier if (status != NT_STATUS_SUCCESS) 1309fe1c642dSBill Krier goto create_alias_err; 1310fe1c642dSBill Krier 1311fe1c642dSBill Krier grp = nt_group_getinfo(alias_name, RWLOCK_READER); 1312fe1c642dSBill Krier if (grp == NULL) { 1313fe1c642dSBill Krier status = NT_STATUS_INTERNAL_ERROR; 1314fe1c642dSBill Krier goto create_alias_err; 1315fe1c642dSBill Krier } 1316fe1c642dSBill Krier 1317fe1c642dSBill Krier (void) smb_sid_getrid(grp->sid, ¶m->rid); 1318fe1c642dSBill Krier nt_group_putinfo(grp); 1319fe1c642dSBill Krier handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_ALIAS_KEY, 1320fe1c642dSBill Krier param->rid); 1321fe1c642dSBill Krier bcopy(handle, ¶m->alias_handle, sizeof (samr_handle_t)); 1322fe1c642dSBill Krier 1323fe1c642dSBill Krier param->status = 0; 1324fe1c642dSBill Krier return (NDR_DRC_OK); 1325fe1c642dSBill Krier 1326fe1c642dSBill Krier create_alias_err: 1327fe1c642dSBill Krier bzero(¶m->alias_handle, sizeof (samr_handle_t)); 1328fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 1329fe1c642dSBill Krier return (NDR_DRC_OK); 1330fe1c642dSBill Krier #endif 1331fe1c642dSBill Krier } 1332fe1c642dSBill Krier 1333fe1c642dSBill Krier /* 1334fe1c642dSBill Krier * samr_s_SetAliasInfo 1335fe1c642dSBill Krier * 1336fe1c642dSBill Krier * Similar to NetLocalGroupSetInfo. 1337fe1c642dSBill Krier */ 1338fe1c642dSBill Krier static int 1339fe1c642dSBill Krier samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa) 1340fe1c642dSBill Krier { 1341fe1c642dSBill Krier struct samr_SetAliasInfo *param = arg; 1342fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; 1343fe1c642dSBill Krier DWORD status = NT_STATUS_SUCCESS; 1344fe1c642dSBill Krier 1345fe1c642dSBill Krier if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) 1346fe1c642dSBill Krier status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1347fe1c642dSBill Krier 1348fe1c642dSBill Krier param->status = status; 1349fe1c642dSBill Krier return (NDR_DRC_OK); 1350fe1c642dSBill Krier } 1351fe1c642dSBill Krier 1352fe1c642dSBill Krier /* 1353fe1c642dSBill Krier * samr_s_QueryAliasInfo 1354fe1c642dSBill Krier * 1355fe1c642dSBill Krier * Retrieves information about the specified local group account 1356fe1c642dSBill Krier * by given handle. 1357fe1c642dSBill Krier */ 1358fe1c642dSBill Krier static int 1359fe1c642dSBill Krier samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa) 1360fe1c642dSBill Krier { 1361fe1c642dSBill Krier struct samr_QueryAliasInfo *param = arg; 1362fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; 1363fe1c642dSBill Krier ndr_handle_t *hd; 1364fe1c642dSBill Krier samr_keydata_t *data; 1365fe1c642dSBill Krier smb_group_t grp; 1366*f96bd5c8SAlan Wright smb_gdomain_t gd_type; 1367*f96bd5c8SAlan Wright smb_sid_t *sid; 1368*f96bd5c8SAlan Wright smb_wka_t *wka; 1369*f96bd5c8SAlan Wright char sidstr[SMB_SID_STRSZ]; 1370*f96bd5c8SAlan Wright char *name; 1371*f96bd5c8SAlan Wright char *desc; 1372*f96bd5c8SAlan Wright uint32_t rid; 1373fe1c642dSBill Krier uint32_t status; 1374fe1c642dSBill Krier int rc; 1375fe1c642dSBill Krier 1376fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) { 1377fe1c642dSBill Krier status = NT_STATUS_INVALID_HANDLE; 1378fe1c642dSBill Krier goto query_alias_err; 1379fe1c642dSBill Krier } 1380fe1c642dSBill Krier 1381fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 1382*f96bd5c8SAlan Wright gd_type = (smb_gdomain_t)data->kd_type; 1383*f96bd5c8SAlan Wright rid = data->kd_rid; 1384*f96bd5c8SAlan Wright 1385*f96bd5c8SAlan Wright switch (gd_type) { 1386*f96bd5c8SAlan Wright case SMB_LGRP_BUILTIN: 1387*f96bd5c8SAlan Wright (void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d", 1388*f96bd5c8SAlan Wright NT_BUILTIN_DOMAIN_SIDSTR, rid); 1389*f96bd5c8SAlan Wright if ((sid = smb_sid_fromstr(sidstr)) == NULL) { 1390*f96bd5c8SAlan Wright status = NT_STATUS_NO_SUCH_ALIAS; 1391*f96bd5c8SAlan Wright goto query_alias_err; 1392*f96bd5c8SAlan Wright } 1393*f96bd5c8SAlan Wright 1394*f96bd5c8SAlan Wright wka = smb_wka_lookup_sid(sid); 1395*f96bd5c8SAlan Wright smb_sid_free(sid); 1396*f96bd5c8SAlan Wright 1397*f96bd5c8SAlan Wright if (wka == NULL) { 1398*f96bd5c8SAlan Wright status = NT_STATUS_NO_SUCH_ALIAS; 1399*f96bd5c8SAlan Wright goto query_alias_err; 1400*f96bd5c8SAlan Wright } 1401*f96bd5c8SAlan Wright 1402*f96bd5c8SAlan Wright name = wka->wka_name; 1403*f96bd5c8SAlan Wright desc = (wka->wka_desc != NULL) ? wka->wka_desc : ""; 1404*f96bd5c8SAlan Wright break; 1405*f96bd5c8SAlan Wright 1406*f96bd5c8SAlan Wright case SMB_LGRP_LOCAL: 1407*f96bd5c8SAlan Wright rc = smb_lgrp_getbyrid(rid, gd_type, &grp); 1408fe1c642dSBill Krier if (rc != SMB_LGRP_SUCCESS) { 1409fe1c642dSBill Krier status = NT_STATUS_NO_SUCH_ALIAS; 1410fe1c642dSBill Krier goto query_alias_err; 1411fe1c642dSBill Krier } 1412*f96bd5c8SAlan Wright name = grp.sg_name; 1413*f96bd5c8SAlan Wright desc = grp.sg_cmnt; 1414*f96bd5c8SAlan Wright break; 1415*f96bd5c8SAlan Wright 1416*f96bd5c8SAlan Wright default: 1417*f96bd5c8SAlan Wright status = NT_STATUS_NO_SUCH_ALIAS; 1418*f96bd5c8SAlan Wright goto query_alias_err; 1419*f96bd5c8SAlan Wright } 1420fe1c642dSBill Krier 1421fe1c642dSBill Krier switch (param->level) { 1422fe1c642dSBill Krier case SAMR_QUERY_ALIAS_INFO_1: 1423fe1c642dSBill Krier param->ru.info1.level = param->level; 1424*f96bd5c8SAlan Wright (void) NDR_MSTRING(mxa, name, 1425fe1c642dSBill Krier (ndr_mstring_t *)¶m->ru.info1.name); 1426fe1c642dSBill Krier 1427*f96bd5c8SAlan Wright (void) NDR_MSTRING(mxa, desc, 1428fe1c642dSBill Krier (ndr_mstring_t *)¶m->ru.info1.desc); 1429fe1c642dSBill Krier 1430fe1c642dSBill Krier param->ru.info1.unknown = 1; 1431fe1c642dSBill Krier break; 1432fe1c642dSBill Krier 1433fe1c642dSBill Krier case SAMR_QUERY_ALIAS_INFO_3: 1434fe1c642dSBill Krier param->ru.info3.level = param->level; 1435*f96bd5c8SAlan Wright (void) NDR_MSTRING(mxa, desc, 1436fe1c642dSBill Krier (ndr_mstring_t *)¶m->ru.info3.desc); 1437fe1c642dSBill Krier break; 1438fe1c642dSBill Krier 1439fe1c642dSBill Krier default: 1440*f96bd5c8SAlan Wright if (gd_type == SMB_LGRP_LOCAL) 1441fe1c642dSBill Krier smb_lgrp_free(&grp); 1442fe1c642dSBill Krier status = NT_STATUS_INVALID_INFO_CLASS; 1443fe1c642dSBill Krier goto query_alias_err; 1444fe1c642dSBill Krier }; 1445fe1c642dSBill Krier 1446*f96bd5c8SAlan Wright if (gd_type == SMB_LGRP_LOCAL) 1447fe1c642dSBill Krier smb_lgrp_free(&grp); 1448fe1c642dSBill Krier param->address = (DWORD)(uintptr_t)¶m->ru; 1449fe1c642dSBill Krier param->status = 0; 1450fe1c642dSBill Krier return (NDR_DRC_OK); 1451fe1c642dSBill Krier 1452fe1c642dSBill Krier query_alias_err: 1453fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 1454fe1c642dSBill Krier return (NDR_DRC_OK); 1455fe1c642dSBill Krier } 1456fe1c642dSBill Krier 1457fe1c642dSBill Krier /* 1458fe1c642dSBill Krier * samr_s_DeleteDomainAlias 1459fe1c642dSBill Krier * 1460fe1c642dSBill Krier * Deletes a local group account and all its members from the 1461fe1c642dSBill Krier * security database, which is the security accounts manager (SAM) database. 1462fe1c642dSBill Krier * Only members of the Administrators or Account Operators local group can 1463fe1c642dSBill Krier * execute this function. 1464fe1c642dSBill Krier * For more information you can look at MSDN page for NetLocalGroupSetInfo. 1465fe1c642dSBill Krier * 1466fe1c642dSBill Krier * This RPC is used by CMC and right now it returns access denied. 1467fe1c642dSBill Krier * The peice of code that removes a local group doesn't get compiled. 1468fe1c642dSBill Krier */ 1469fe1c642dSBill Krier static int 1470fe1c642dSBill Krier samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa) 1471fe1c642dSBill Krier { 1472fe1c642dSBill Krier struct samr_DeleteDomainAlias *param = arg; 1473fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; 1474fe1c642dSBill Krier 1475fe1c642dSBill Krier if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) { 1476fe1c642dSBill Krier bzero(param, sizeof (struct samr_DeleteDomainAlias)); 1477fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1478fe1c642dSBill Krier return (NDR_DRC_OK); 1479fe1c642dSBill Krier } 1480fe1c642dSBill Krier 1481fe1c642dSBill Krier bzero(param, sizeof (struct samr_DeleteDomainAlias)); 1482fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 1483fe1c642dSBill Krier return (NDR_DRC_OK); 1484fe1c642dSBill Krier 1485fe1c642dSBill Krier #ifdef SAMR_SUPPORT_DEL_ALIAS 1486fe1c642dSBill Krier nt_group_t *grp; 1487fe1c642dSBill Krier char *alias_name; 1488fe1c642dSBill Krier DWORD status; 1489fe1c642dSBill Krier 1490fe1c642dSBill Krier grp = nt_groups_lookup_rid(desc->discrim); 1491fe1c642dSBill Krier if (grp == 0) { 1492fe1c642dSBill Krier status = NT_STATUS_NO_SUCH_ALIAS; 1493fe1c642dSBill Krier goto delete_alias_err; 1494fe1c642dSBill Krier } 1495fe1c642dSBill Krier 1496fe1c642dSBill Krier alias_name = strdup(grp->name); 1497fe1c642dSBill Krier if (alias_name == 0) { 1498fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 1499fe1c642dSBill Krier goto delete_alias_err; 1500fe1c642dSBill Krier } 1501fe1c642dSBill Krier 1502fe1c642dSBill Krier status = nt_group_delete(alias_name); 1503fe1c642dSBill Krier free(alias_name); 1504fe1c642dSBill Krier if (status != NT_STATUS_SUCCESS) 1505fe1c642dSBill Krier goto delete_alias_err; 1506fe1c642dSBill Krier 1507fe1c642dSBill Krier param->status = 0; 1508fe1c642dSBill Krier return (NDR_DRC_OK); 1509fe1c642dSBill Krier 1510fe1c642dSBill Krier delete_alias_err: 1511fe1c642dSBill Krier param->status = NT_SC_ERROR(status); 1512fe1c642dSBill Krier return (NDR_DRC_OK); 1513fe1c642dSBill Krier #endif 1514fe1c642dSBill Krier } 1515fe1c642dSBill Krier 1516fe1c642dSBill Krier /* 1517fe1c642dSBill Krier * samr_s_EnumDomainAliases 1518fe1c642dSBill Krier * 1519fe1c642dSBill Krier * This function sends back a list which contains all local groups' name. 1520fe1c642dSBill Krier */ 1521fe1c642dSBill Krier static int 1522fe1c642dSBill Krier samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa) 1523fe1c642dSBill Krier { 1524fe1c642dSBill Krier struct samr_EnumDomainAliases *param = arg; 1525fe1c642dSBill Krier ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 1526fe1c642dSBill Krier ndr_handle_t *hd; 1527fe1c642dSBill Krier samr_keydata_t *data; 1528fe1c642dSBill Krier smb_group_t grp; 1529fe1c642dSBill Krier smb_giter_t gi; 1530fe1c642dSBill Krier int cnt, skip, i; 1531fe1c642dSBill Krier struct name_rid *info; 1532fe1c642dSBill Krier 1533fe1c642dSBill Krier if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 1534fe1c642dSBill Krier bzero(param, sizeof (struct samr_EnumDomainAliases)); 1535fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1536fe1c642dSBill Krier return (NDR_DRC_OK); 1537fe1c642dSBill Krier } 1538fe1c642dSBill Krier 1539fe1c642dSBill Krier data = (samr_keydata_t *)hd->nh_data; 1540fe1c642dSBill Krier 1541fe1c642dSBill Krier cnt = smb_sam_grp_cnt(data->kd_type); 1542fe1c642dSBill Krier if (cnt <= param->resume_handle) { 1543fe1c642dSBill Krier param->aliases = (struct aliases_info *)NDR_MALLOC(mxa, 1544fe1c642dSBill Krier sizeof (struct aliases_info)); 1545fe1c642dSBill Krier 1546fe1c642dSBill Krier if (param->aliases == NULL) { 1547fe1c642dSBill Krier bzero(param, sizeof (struct samr_EnumDomainAliases)); 1548fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 1549fe1c642dSBill Krier return (NDR_DRC_OK); 1550fe1c642dSBill Krier } 1551fe1c642dSBill Krier 1552fe1c642dSBill Krier bzero(param->aliases, sizeof (struct aliases_info)); 1553fe1c642dSBill Krier param->out_resume = 0; 1554fe1c642dSBill Krier param->entries = 0; 1555fe1c642dSBill Krier param->status = NT_STATUS_SUCCESS; 1556fe1c642dSBill Krier return (NDR_DRC_OK); 1557fe1c642dSBill Krier } 1558fe1c642dSBill Krier 1559fe1c642dSBill Krier cnt -= param->resume_handle; 1560fe1c642dSBill Krier param->aliases = (struct aliases_info *)NDR_MALLOC(mxa, 1561fe1c642dSBill Krier sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid)); 1562fe1c642dSBill Krier 1563fe1c642dSBill Krier if (param->aliases == NULL) { 1564fe1c642dSBill Krier bzero(param, sizeof (struct samr_EnumDomainAliases)); 1565fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 1566fe1c642dSBill Krier return (NDR_DRC_OK); 1567fe1c642dSBill Krier } 1568fe1c642dSBill Krier 1569fe1c642dSBill Krier if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { 1570fe1c642dSBill Krier bzero(param, sizeof (struct samr_EnumDomainAliases)); 1571fe1c642dSBill Krier param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR); 1572fe1c642dSBill Krier return (NDR_DRC_OK); 1573fe1c642dSBill Krier } 1574fe1c642dSBill Krier 1575fe1c642dSBill Krier skip = i = 0; 1576fe1c642dSBill Krier info = param->aliases->info; 1577fe1c642dSBill Krier while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { 1578fe1c642dSBill Krier if ((skip++ >= param->resume_handle) && 1579fe1c642dSBill Krier (grp.sg_domain == data->kd_type) && (i++ < cnt)) { 1580fe1c642dSBill Krier info->rid = grp.sg_rid; 1581fe1c642dSBill Krier (void) NDR_MSTRING(mxa, grp.sg_name, 1582fe1c642dSBill Krier (ndr_mstring_t *)&info->name); 1583fe1c642dSBill Krier 1584fe1c642dSBill Krier info++; 1585fe1c642dSBill Krier } 1586fe1c642dSBill Krier smb_lgrp_free(&grp); 1587fe1c642dSBill Krier } 1588fe1c642dSBill Krier smb_lgrp_iterclose(&gi); 1589fe1c642dSBill Krier 1590fe1c642dSBill Krier param->aliases->count = i; 1591fe1c642dSBill Krier param->aliases->address = i; 1592fe1c642dSBill Krier 1593fe1c642dSBill Krier param->out_resume = i; 1594fe1c642dSBill Krier param->entries = i; 1595fe1c642dSBill Krier param->status = 0; 1596fe1c642dSBill Krier return (NDR_DRC_OK); 1597fe1c642dSBill Krier } 1598fe1c642dSBill Krier 1599fe1c642dSBill Krier /* 1600fe1c642dSBill Krier * samr_s_Connect3 1601fe1c642dSBill Krier */ 1602fe1c642dSBill Krier static int 1603fe1c642dSBill Krier samr_s_Connect3(void *arg, ndr_xa_t *mxa) 1604fe1c642dSBill Krier { 1605fe1c642dSBill Krier struct samr_Connect3 *param = arg; 1606*f96bd5c8SAlan Wright ndr_hdid_t *id; 1607fe1c642dSBill Krier 1608*f96bd5c8SAlan Wright id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0); 1609*f96bd5c8SAlan Wright if (id) { 1610*f96bd5c8SAlan Wright bcopy(id, ¶m->handle, sizeof (samr_handle_t)); 1611*f96bd5c8SAlan Wright param->status = 0; 1612*f96bd5c8SAlan Wright } else { 1613*f96bd5c8SAlan Wright bzero(¶m->handle, sizeof (samr_handle_t)); 1614*f96bd5c8SAlan Wright param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 1615fe1c642dSBill Krier } 1616fe1c642dSBill Krier 1617*f96bd5c8SAlan Wright return (NDR_DRC_OK); 1618*f96bd5c8SAlan Wright } 1619fe1c642dSBill Krier 1620fe1c642dSBill Krier /* 1621fe1c642dSBill Krier * samr_s_Connect4 1622fe1c642dSBill Krier * 1623fe1c642dSBill Krier * This is the connect4 form of the connect request used by Windows XP. 1624fe1c642dSBill Krier * Returns an RPC fault for now. 1625fe1c642dSBill Krier */ 1626fe1c642dSBill Krier /*ARGSUSED*/ 1627fe1c642dSBill Krier static int 1628fe1c642dSBill Krier samr_s_Connect4(void *arg, ndr_xa_t *mxa) 1629fe1c642dSBill Krier { 1630fe1c642dSBill Krier struct samr_Connect4 *param = arg; 1631fe1c642dSBill Krier 1632fe1c642dSBill Krier bzero(param, sizeof (struct samr_Connect4)); 1633fe1c642dSBill Krier return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID); 1634fe1c642dSBill Krier } 1635fe1c642dSBill Krier 1636fe1c642dSBill Krier static ndr_stub_table_t samr_stub_table[] = { 1637fe1c642dSBill Krier { samr_s_ConnectAnon, SAMR_OPNUM_ConnectAnon }, 1638fe1c642dSBill Krier { samr_s_CloseHandle, SAMR_OPNUM_CloseHandle }, 1639fe1c642dSBill Krier { samr_s_LookupDomain, SAMR_OPNUM_LookupDomain }, 1640fe1c642dSBill Krier { samr_s_EnumLocalDomains, SAMR_OPNUM_EnumLocalDomains }, 1641fe1c642dSBill Krier { samr_s_OpenDomain, SAMR_OPNUM_OpenDomain }, 1642fe1c642dSBill Krier { samr_s_QueryDomainInfo, SAMR_OPNUM_QueryDomainInfo }, 1643*f96bd5c8SAlan Wright { samr_s_QueryInfoDomain2, SAMR_OPNUM_QueryInfoDomain2 }, 1644fe1c642dSBill Krier { samr_s_LookupNames, SAMR_OPNUM_LookupNames }, 1645fe1c642dSBill Krier { samr_s_OpenUser, SAMR_OPNUM_OpenUser }, 1646fe1c642dSBill Krier { samr_s_DeleteUser, SAMR_OPNUM_DeleteUser }, 1647fe1c642dSBill Krier { samr_s_QueryUserInfo, SAMR_OPNUM_QueryUserInfo }, 1648fe1c642dSBill Krier { samr_s_QueryUserGroups, SAMR_OPNUM_QueryUserGroups }, 1649fe1c642dSBill Krier { samr_s_OpenGroup, SAMR_OPNUM_OpenGroup }, 1650fe1c642dSBill Krier { samr_s_Connect, SAMR_OPNUM_Connect }, 1651fe1c642dSBill Krier { samr_s_GetUserPwInfo, SAMR_OPNUM_GetUserPwInfo }, 1652fe1c642dSBill Krier { samr_s_CreateUser, SAMR_OPNUM_CreateUser }, 1653fe1c642dSBill Krier { samr_s_ChangeUserPasswd, SAMR_OPNUM_ChangeUserPasswd }, 1654fe1c642dSBill Krier { samr_s_GetDomainPwInfo, SAMR_OPNUM_GetDomainPwInfo }, 1655fe1c642dSBill Krier { samr_s_SetUserInfo, SAMR_OPNUM_SetUserInfo }, 1656fe1c642dSBill Krier { samr_s_Connect3, SAMR_OPNUM_Connect3 }, 1657fe1c642dSBill Krier { samr_s_Connect4, SAMR_OPNUM_Connect4 }, 1658fe1c642dSBill Krier { samr_s_QueryDispInfo, SAMR_OPNUM_QueryDispInfo }, 1659fe1c642dSBill Krier { samr_s_OpenAlias, SAMR_OPNUM_OpenAlias }, 1660fe1c642dSBill Krier { samr_s_CreateDomainAlias, SAMR_OPNUM_CreateDomainAlias }, 1661fe1c642dSBill Krier { samr_s_SetAliasInfo, SAMR_OPNUM_SetAliasInfo }, 1662fe1c642dSBill Krier { samr_s_QueryAliasInfo, SAMR_OPNUM_QueryAliasInfo }, 1663fe1c642dSBill Krier { samr_s_DeleteDomainAlias, SAMR_OPNUM_DeleteDomainAlias }, 1664fe1c642dSBill Krier { samr_s_EnumDomainAliases, SAMR_OPNUM_EnumDomainAliases }, 1665fe1c642dSBill Krier { samr_s_EnumDomainGroups, SAMR_OPNUM_EnumDomainGroups }, 1666fe1c642dSBill Krier {0} 1667fe1c642dSBill Krier }; 1668fe1c642dSBill Krier 1669fe1c642dSBill Krier /* 1670fe1c642dSBill Krier * There is a bug in the way that midl and the marshalling code handles 1671fe1c642dSBill Krier * unions so we need to fix some of the data offsets at runtime. The 1672fe1c642dSBill Krier * following macros and the fixup functions handle the corrections. 1673fe1c642dSBill Krier */ 1674fe1c642dSBill Krier 1675fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru); 1676fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes); 1677fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfo); 1678fe1c642dSBill Krier 1679fe1c642dSBill Krier DECL_FIXUP_STRUCT(QueryUserInfo_result_u); 1680fe1c642dSBill Krier DECL_FIXUP_STRUCT(QueryUserInfo_result); 1681fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryUserInfo); 1682fe1c642dSBill Krier 1683fe1c642dSBill Krier void 1684fe1c642dSBill Krier fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val) 1685fe1c642dSBill Krier { 1686fe1c642dSBill Krier unsigned short size1 = 0; 1687fe1c642dSBill Krier unsigned short size2 = 0; 1688fe1c642dSBill Krier unsigned short size3 = 0; 1689fe1c642dSBill Krier 1690fe1c642dSBill Krier switch (val->level) { 1691fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryAliasInfo, 1); 1692fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryAliasInfo, 3); 1693fe1c642dSBill Krier 1694fe1c642dSBill Krier default: 1695fe1c642dSBill Krier return; 1696fe1c642dSBill Krier }; 1697fe1c642dSBill Krier 1698fe1c642dSBill Krier size2 = size1 + (2 * sizeof (DWORD)); 1699fe1c642dSBill Krier size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD); 1700fe1c642dSBill Krier 1701fe1c642dSBill Krier FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1); 1702fe1c642dSBill Krier FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2); 1703fe1c642dSBill Krier FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3); 1704fe1c642dSBill Krier } 1705fe1c642dSBill Krier 1706fe1c642dSBill Krier void 1707fe1c642dSBill Krier fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val) 1708fe1c642dSBill Krier { 1709fe1c642dSBill Krier unsigned short size1 = 0; 1710fe1c642dSBill Krier unsigned short size2 = 0; 1711fe1c642dSBill Krier unsigned short size3 = 0; 1712fe1c642dSBill Krier 1713fe1c642dSBill Krier switch (val->switch_index) { 1714fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryUserInfo, 1); 1715fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryUserInfo, 6); 1716fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryUserInfo, 7); 1717fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryUserInfo, 8); 1718fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryUserInfo, 9); 1719fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryUserInfo, 16); 1720fe1c642dSBill Krier CASE_INFO_ENT(samr_QueryUserInfo, 21); 1721fe1c642dSBill Krier 1722fe1c642dSBill Krier default: 1723fe1c642dSBill Krier return; 1724fe1c642dSBill Krier }; 1725fe1c642dSBill Krier 1726fe1c642dSBill Krier size2 = size1 + (2 * sizeof (DWORD)); 1727fe1c642dSBill Krier size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD); 1728fe1c642dSBill Krier 1729fe1c642dSBill Krier FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1); 1730fe1c642dSBill Krier FIXUP_PDU_SIZE(QueryUserInfo_result, size2); 1731fe1c642dSBill Krier FIXUP_PDU_SIZE(samr_QueryUserInfo, size3); 1732fe1c642dSBill Krier } 1733fe1c642dSBill Krier 1734fe1c642dSBill Krier /* 1735fe1c642dSBill Krier * As long as there is only one entry in the union, there is no need 1736fe1c642dSBill Krier * to patch anything. 1737fe1c642dSBill Krier */ 1738fe1c642dSBill Krier /*ARGSUSED*/ 1739fe1c642dSBill Krier void 1740fe1c642dSBill Krier fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val) 1741fe1c642dSBill Krier { 1742fe1c642dSBill Krier } 1743