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