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