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 */ 21148c5f43SAlan Wright 22fe1c642dSBill Krier /* 23148c5f43SAlan Wright * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24*b3700b07SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 25fe1c642dSBill Krier */ 26fe1c642dSBill Krier 27fe1c642dSBill Krier /* 28fe1c642dSBill Krier * Local Security Authority RPC (LSAR) client-side interface. 29fe1c642dSBill Krier */ 30fe1c642dSBill Krier 31fe1c642dSBill Krier #include <sys/errno.h> 32fe1c642dSBill Krier #include <stdio.h> 33fe1c642dSBill Krier #include <stdlib.h> 34fe1c642dSBill Krier #include <strings.h> 35fe1c642dSBill Krier 36fe1c642dSBill Krier #include <smbsrv/libsmb.h> 37fe1c642dSBill Krier #include <smbsrv/libmlsvc.h> 38fe1c642dSBill Krier #include <smbsrv/smbinfo.h> 39fe1c642dSBill Krier #include <smbsrv/ntaccess.h> 40fe1c642dSBill Krier #include <smbsrv/ntlocale.h> 41fe1c642dSBill Krier #include <smbsrv/string.h> 42fe1c642dSBill Krier #include <lsalib.h> 43fe1c642dSBill Krier 44fe1c642dSBill Krier /* 45fe1c642dSBill Krier * The maximum number of bytes we are prepared to deal with in a 46fe1c642dSBill Krier * response. 47fe1c642dSBill Krier */ 48fe1c642dSBill Krier #define MLSVC_MAX_RESPONSE_LEN 1024 49fe1c642dSBill Krier 50fe1c642dSBill Krier /* 51fe1c642dSBill Krier * This structure is used when looking up names. We only lookup one 52fe1c642dSBill Krier * name at a time but the structure will allow for more. 53fe1c642dSBill Krier */ 54fe1c642dSBill Krier typedef struct lsa_names { 55fe1c642dSBill Krier uint32_t n_entry; 56fe1c642dSBill Krier mslsa_string_t name[8]; 57fe1c642dSBill Krier } lsa_names_t; 58fe1c642dSBill Krier 59fe1c642dSBill Krier typedef DWORD (*lsar_nameop_t)(mlsvc_handle_t *, lsa_names_t *, 60fe1c642dSBill Krier smb_account_t *); 61fe1c642dSBill Krier 62fe1c642dSBill Krier static uint32_t lsar_lookup_names1(mlsvc_handle_t *, lsa_names_t *, 63fe1c642dSBill Krier smb_account_t *); 64fe1c642dSBill Krier static uint32_t lsar_lookup_names2(mlsvc_handle_t *, lsa_names_t *, 65fe1c642dSBill Krier smb_account_t *); 66fe1c642dSBill Krier static uint32_t lsar_lookup_names3(mlsvc_handle_t *, lsa_names_t *, 67fe1c642dSBill Krier smb_account_t *); 68fe1c642dSBill Krier static uint32_t lsar_lookup_sids1(mlsvc_handle_t *, lsa_sid_t *, 69fe1c642dSBill Krier smb_account_t *); 70fe1c642dSBill Krier static uint32_t lsar_lookup_sids2(mlsvc_handle_t *, lsa_sid_t *, 71fe1c642dSBill Krier smb_account_t *account); 72fe1c642dSBill Krier 73fe1c642dSBill Krier static char *lsar_get_username(const char *); 74fe1c642dSBill Krier static void smb_account_trace(const smb_account_t *); 75fe1c642dSBill Krier 76fe1c642dSBill Krier static void lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *, 77fe1c642dSBill Krier smb_trusted_domains_t *); 78fe1c642dSBill Krier static void lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *, 79fe1c642dSBill Krier smb_trusted_domains_t *); 80fe1c642dSBill Krier 81fe1c642dSBill Krier /* 82fe1c642dSBill Krier * lsar_open 83fe1c642dSBill Krier * 84fe1c642dSBill Krier * This is a wrapper round lsar_open_policy2 to ensure that we connect 85fe1c642dSBill Krier * using the appropriate domain information. 86fe1c642dSBill Krier * 87fe1c642dSBill Krier * If username argument is NULL, an anonymous connection will be established. 88fe1c642dSBill Krier * Otherwise, an authenticated connection will be established. 89fe1c642dSBill Krier * 90*b3700b07SGordon Ross * Returns 0 or NT status (Raw, not LSA-ized) 91fe1c642dSBill Krier */ 92*b3700b07SGordon Ross DWORD 931ed6b69aSGordon Ross lsar_open(char *server, char *domain, char *username, 94fe1c642dSBill Krier mlsvc_handle_t *domain_handle) 95fe1c642dSBill Krier { 96*b3700b07SGordon Ross DWORD status; 97*b3700b07SGordon Ross 98fe1c642dSBill Krier if (server == NULL || domain == NULL) 99*b3700b07SGordon Ross return (NT_STATUS_INTERNAL_ERROR); 100fe1c642dSBill Krier 101fe1c642dSBill Krier if (username == NULL) 102fe1c642dSBill Krier username = MLSVC_ANON_USER; 103fe1c642dSBill Krier 104*b3700b07SGordon Ross status = lsar_open_policy2(server, domain, username, domain_handle); 105*b3700b07SGordon Ross 106*b3700b07SGordon Ross return (status); 107fe1c642dSBill Krier } 108fe1c642dSBill Krier 109fe1c642dSBill Krier /* 110fe1c642dSBill Krier * lsar_open_policy2 111fe1c642dSBill Krier * 112fe1c642dSBill Krier * Obtain an LSA policy handle. A policy handle is required to access 113fe1c642dSBill Krier * LSA resources on a remote server. The server name supplied here does 114fe1c642dSBill Krier * not need the double backslash prefix; it is added here. Call this 115fe1c642dSBill Krier * function via lsar_open to ensure that the appropriate connection is 116fe1c642dSBill Krier * in place. 117fe1c642dSBill Krier * 118*b3700b07SGordon Ross * Returns 0 or NT status (Raw, not LSA-ized) 119fe1c642dSBill Krier */ 120*b3700b07SGordon Ross DWORD 121*b3700b07SGordon Ross lsar_open_policy2(char *server, char *domain, char *user, 122fe1c642dSBill Krier mlsvc_handle_t *lsa_handle) 123fe1c642dSBill Krier { 124fe1c642dSBill Krier struct mslsa_OpenPolicy2 arg; 125*b3700b07SGordon Ross DWORD status; 126fe1c642dSBill Krier int opnum; 127fe1c642dSBill Krier int len; 128fe1c642dSBill Krier 129*b3700b07SGordon Ross status = ndr_rpc_bind(lsa_handle, server, domain, user, "LSARPC"); 130*b3700b07SGordon Ross if (status != 0) 131*b3700b07SGordon Ross return (status); 132fe1c642dSBill Krier 133fe1c642dSBill Krier opnum = LSARPC_OPNUM_OpenPolicy2; 134fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_OpenPolicy2)); 135fe1c642dSBill Krier 136fe1c642dSBill Krier len = strlen(server) + 4; 137fe1c642dSBill Krier arg.servername = ndr_rpc_malloc(lsa_handle, len); 138fe1c642dSBill Krier if (arg.servername == NULL) { 139*b3700b07SGordon Ross status = NT_STATUS_NO_MEMORY; 140*b3700b07SGordon Ross goto out; 141fe1c642dSBill Krier } 142fe1c642dSBill Krier 143fe1c642dSBill Krier (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 144fe1c642dSBill Krier arg.attributes.length = sizeof (struct mslsa_object_attributes); 145fe1c642dSBill Krier arg.desiredAccess = MAXIMUM_ALLOWED; 146fe1c642dSBill Krier 147*b3700b07SGordon Ross if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 148*b3700b07SGordon Ross status = RPC_NT_CALL_FAILED; 149*b3700b07SGordon Ross goto out; 150fe1c642dSBill Krier } 151*b3700b07SGordon Ross status = arg.status; 152*b3700b07SGordon Ross if (status == NT_STATUS_SUCCESS) { 153fe1c642dSBill Krier (void) memcpy(&lsa_handle->handle, &arg.domain_handle, 154fe1c642dSBill Krier sizeof (ndr_hdid_t)); 155fe1c642dSBill Krier 156fe1c642dSBill Krier if (ndr_is_null_handle(lsa_handle)) 157*b3700b07SGordon Ross status = NT_STATUS_INVALID_PARAMETER; 158fe1c642dSBill Krier } 159fe1c642dSBill Krier 160fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 161fe1c642dSBill Krier 162*b3700b07SGordon Ross out: 163*b3700b07SGordon Ross if (status != NT_STATUS_SUCCESS) 164fe1c642dSBill Krier ndr_rpc_unbind(lsa_handle); 165*b3700b07SGordon Ross return (status); 166fe1c642dSBill Krier } 167fe1c642dSBill Krier 168fe1c642dSBill Krier /* 169fe1c642dSBill Krier * lsar_open_account 170fe1c642dSBill Krier * 171fe1c642dSBill Krier * Obtain an LSA account handle. The lsa_handle must be a valid handle 172fe1c642dSBill Krier * obtained via lsar_open_policy2. The main thing to remember here is 173fe1c642dSBill Krier * to set up the context in the lsa_account_handle. I'm not sure what 174fe1c642dSBill Krier * the requirements are for desired access. Some values require admin 175fe1c642dSBill Krier * access. 176fe1c642dSBill Krier * 177fe1c642dSBill Krier * Returns 0 on success. Otherwise non-zero to indicate a failure. 178fe1c642dSBill Krier */ 179fe1c642dSBill Krier int 180fe1c642dSBill Krier lsar_open_account(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, 181fe1c642dSBill Krier mlsvc_handle_t *lsa_account_handle) 182fe1c642dSBill Krier { 183fe1c642dSBill Krier struct mslsa_OpenAccount arg; 184fe1c642dSBill Krier int opnum; 185fe1c642dSBill Krier int rc; 186fe1c642dSBill Krier 187fe1c642dSBill Krier if (ndr_is_null_handle(lsa_handle) || sid == NULL) 188fe1c642dSBill Krier return (-1); 189fe1c642dSBill Krier 190fe1c642dSBill Krier opnum = LSARPC_OPNUM_OpenAccount; 191fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_OpenAccount)); 192fe1c642dSBill Krier 193fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 194fe1c642dSBill Krier arg.sid = sid; 195fe1c642dSBill Krier arg.access_mask = STANDARD_RIGHTS_REQUIRED 196fe1c642dSBill Krier #if 0 197fe1c642dSBill Krier | POLICY_VIEW_AUDIT_INFORMATION 198fe1c642dSBill Krier | POLICY_GET_PRIVATE_INFORMATION 199fe1c642dSBill Krier | POLICY_TRUST_ADMIN 200fe1c642dSBill Krier #endif 201fe1c642dSBill Krier | POLICY_VIEW_LOCAL_INFORMATION; 202fe1c642dSBill Krier 203fe1c642dSBill Krier if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0) 204fe1c642dSBill Krier return (-1); 205fe1c642dSBill Krier 206fe1c642dSBill Krier if (arg.status != 0) { 207fe1c642dSBill Krier rc = -1; 208fe1c642dSBill Krier } else { 209fe1c642dSBill Krier ndr_inherit_handle(lsa_account_handle, lsa_handle); 210fe1c642dSBill Krier 211fe1c642dSBill Krier (void) memcpy(&lsa_account_handle->handle, 212fe1c642dSBill Krier &arg.account_handle, sizeof (ndr_hdid_t)); 213fe1c642dSBill Krier 214fe1c642dSBill Krier if (ndr_is_null_handle(lsa_account_handle)) 215fe1c642dSBill Krier rc = -1; 216fe1c642dSBill Krier } 217fe1c642dSBill Krier 218fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 219fe1c642dSBill Krier return (rc); 220fe1c642dSBill Krier } 221fe1c642dSBill Krier 222fe1c642dSBill Krier /* 223fe1c642dSBill Krier * lsar_close 224fe1c642dSBill Krier * 225fe1c642dSBill Krier * Close the LSA connection associated with the handle. The lsa_handle 226fe1c642dSBill Krier * must be a valid handle obtained via a call to lsar_open_policy2 or 227fe1c642dSBill Krier * lsar_open_account. On success the handle will be zeroed out to 228fe1c642dSBill Krier * ensure that it is not used again. If this is the top level handle 229fe1c642dSBill Krier * (i.e. the one obtained via lsar_open_policy2) the pipe is closed. 230fe1c642dSBill Krier * 231fe1c642dSBill Krier * Returns 0 on success. Otherwise non-zero to indicate a failure. 232fe1c642dSBill Krier */ 233fe1c642dSBill Krier int 234fe1c642dSBill Krier lsar_close(mlsvc_handle_t *lsa_handle) 235fe1c642dSBill Krier { 236fe1c642dSBill Krier struct mslsa_CloseHandle arg; 237fe1c642dSBill Krier int opnum; 238fe1c642dSBill Krier 239fe1c642dSBill Krier if (ndr_is_null_handle(lsa_handle)) 240fe1c642dSBill Krier return (-1); 241fe1c642dSBill Krier 242fe1c642dSBill Krier opnum = LSARPC_OPNUM_CloseHandle; 243fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_CloseHandle)); 244fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 245fe1c642dSBill Krier 246fe1c642dSBill Krier (void) ndr_rpc_call(lsa_handle, opnum, &arg); 247fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 248fe1c642dSBill Krier 249fe1c642dSBill Krier if (ndr_is_bind_handle(lsa_handle)) 250fe1c642dSBill Krier ndr_rpc_unbind(lsa_handle); 251fe1c642dSBill Krier 252fe1c642dSBill Krier bzero(lsa_handle, sizeof (mlsvc_handle_t)); 253fe1c642dSBill Krier return (0); 254fe1c642dSBill Krier } 255fe1c642dSBill Krier 256fe1c642dSBill Krier /* 257fe1c642dSBill Krier * lsar_query_security_desc 258fe1c642dSBill Krier * 259fe1c642dSBill Krier * Don't use this call yet. It is just a place holder for now. 260fe1c642dSBill Krier */ 261fe1c642dSBill Krier int 262fe1c642dSBill Krier lsar_query_security_desc(mlsvc_handle_t *lsa_handle) 263fe1c642dSBill Krier { 264fe1c642dSBill Krier struct mslsa_QuerySecurityObject arg; 265fe1c642dSBill Krier int rc; 266fe1c642dSBill Krier int opnum; 267fe1c642dSBill Krier 268fe1c642dSBill Krier opnum = LSARPC_OPNUM_QuerySecurityObject; 269fe1c642dSBill Krier 270fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_QuerySecurityObject)); 271fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 272fe1c642dSBill Krier 273fe1c642dSBill Krier rc = ndr_rpc_call(lsa_handle, opnum, &arg); 274fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 275fe1c642dSBill Krier return (rc); 276fe1c642dSBill Krier } 277fe1c642dSBill Krier 278fe1c642dSBill Krier /* 279fe1c642dSBill Krier * lsar_query_info_policy 280fe1c642dSBill Krier * 281fe1c642dSBill Krier * The general purpose of this function is to allow various pieces of 282fe1c642dSBill Krier * information to be queried on the domain controller. The only 283fe1c642dSBill Krier * information queries supported are MSLSA_POLICY_PRIMARY_DOMAIN_INFO 284fe1c642dSBill Krier * and MSLSA_POLICY_ACCOUNT_DOMAIN_INFO. 285fe1c642dSBill Krier * 286fe1c642dSBill Krier * On success, the return code will be 0 and the user_info structure 287fe1c642dSBill Krier * will be set up. The sid_name_use field will be set to SidTypeDomain 288fe1c642dSBill Krier * indicating that the domain name and domain sid fields are vaild. If 289fe1c642dSBill Krier * the infoClass returned from the server is not one of the supported 290fe1c642dSBill Krier * values, the sid_name_use willbe set to SidTypeUnknown. If the RPC 291fe1c642dSBill Krier * fails, a negative error code will be returned, in which case the 292fe1c642dSBill Krier * user_info will not have been updated. 293fe1c642dSBill Krier */ 294fe1c642dSBill Krier DWORD 295fe1c642dSBill Krier lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass, 296fe1c642dSBill Krier smb_domain_t *info) 297fe1c642dSBill Krier { 298fe1c642dSBill Krier struct mslsa_QueryInfoPolicy arg; 299fe1c642dSBill Krier struct mslsa_PrimaryDomainInfo *pd_info; 300fe1c642dSBill Krier struct mslsa_AccountDomainInfo *ad_info; 301fe1c642dSBill Krier struct mslsa_DnsDomainInfo *dns_info; 302fe1c642dSBill Krier char guid_str[UUID_PRINTABLE_STRING_LENGTH]; 303fe1c642dSBill Krier char sidstr[SMB_SID_STRSZ]; 304fe1c642dSBill Krier int opnum; 305fe1c642dSBill Krier DWORD status; 306fe1c642dSBill Krier 307fe1c642dSBill Krier if (lsa_handle == NULL || info == NULL) 308fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 309fe1c642dSBill Krier 310fe1c642dSBill Krier opnum = LSARPC_OPNUM_QueryInfoPolicy; 311fe1c642dSBill Krier 312fe1c642dSBill Krier bzero(info, sizeof (smb_domain_t)); 313fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_QueryInfoPolicy)); 314fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 315fe1c642dSBill Krier 316fe1c642dSBill Krier arg.info_class = infoClass; 317fe1c642dSBill Krier 318fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 319fe1c642dSBill Krier status = NT_STATUS_INVALID_PARAMETER; 320fe1c642dSBill Krier } else if (arg.status != 0) { 321fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 322fe1c642dSBill Krier status = NT_SC_VALUE(arg.status); 323fe1c642dSBill Krier } else { 324fe1c642dSBill Krier 325fe1c642dSBill Krier switch (infoClass) { 326fe1c642dSBill Krier case MSLSA_POLICY_PRIMARY_DOMAIN_INFO: 327fe1c642dSBill Krier pd_info = &arg.ru.pd_info; 328fe1c642dSBill Krier 329fe1c642dSBill Krier smb_sid_tostr((smb_sid_t *)pd_info->sid, sidstr); 330fe1c642dSBill Krier info->di_type = SMB_DOMAIN_PRIMARY; 331fe1c642dSBill Krier smb_domain_set_basic_info(sidstr, 332fe1c642dSBill Krier (char *)pd_info->name.str, "", info); 333fe1c642dSBill Krier 334fe1c642dSBill Krier status = NT_STATUS_SUCCESS; 335fe1c642dSBill Krier break; 336fe1c642dSBill Krier 337fe1c642dSBill Krier case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO: 338fe1c642dSBill Krier ad_info = &arg.ru.ad_info; 339fe1c642dSBill Krier 340fe1c642dSBill Krier smb_sid_tostr((smb_sid_t *)ad_info->sid, sidstr); 341fe1c642dSBill Krier info->di_type = SMB_DOMAIN_ACCOUNT; 342fe1c642dSBill Krier smb_domain_set_basic_info(sidstr, 343fe1c642dSBill Krier (char *)ad_info->name.str, "", info); 344fe1c642dSBill Krier 345fe1c642dSBill Krier status = NT_STATUS_SUCCESS; 346fe1c642dSBill Krier break; 347fe1c642dSBill Krier 348fe1c642dSBill Krier case MSLSA_POLICY_DNS_DOMAIN_INFO: 349fe1c642dSBill Krier dns_info = &arg.ru.dns_info; 350fe1c642dSBill Krier ndr_uuid_unparse((ndr_uuid_t *)&dns_info->guid, 351fe1c642dSBill Krier guid_str); 352fe1c642dSBill Krier smb_sid_tostr((smb_sid_t *)dns_info->sid, sidstr); 353fe1c642dSBill Krier 354fe1c642dSBill Krier info->di_type = SMB_DOMAIN_PRIMARY; 355fe1c642dSBill Krier smb_domain_set_dns_info(sidstr, 356fe1c642dSBill Krier (char *)dns_info->nb_domain.str, 357fe1c642dSBill Krier (char *)dns_info->dns_domain.str, 358fe1c642dSBill Krier (char *)dns_info->forest.str, 359fe1c642dSBill Krier guid_str, info); 360fe1c642dSBill Krier status = NT_STATUS_SUCCESS; 361fe1c642dSBill Krier break; 362fe1c642dSBill Krier 363fe1c642dSBill Krier default: 364fe1c642dSBill Krier status = NT_STATUS_INVALID_INFO_CLASS; 365fe1c642dSBill Krier break; 366fe1c642dSBill Krier } 367fe1c642dSBill Krier } 368fe1c642dSBill Krier 369fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 370fe1c642dSBill Krier return (status); 371fe1c642dSBill Krier } 372fe1c642dSBill Krier 373fe1c642dSBill Krier /* 374fe1c642dSBill Krier * Lookup a name and obtain the sid/rid. 375fe1c642dSBill Krier * This is a wrapper for the various lookup sid RPCs. 376fe1c642dSBill Krier */ 377fe1c642dSBill Krier uint32_t 378fe1c642dSBill Krier lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info) 379fe1c642dSBill Krier { 380fe1c642dSBill Krier static lsar_nameop_t ops[] = { 381fe1c642dSBill Krier lsar_lookup_names3, 382fe1c642dSBill Krier lsar_lookup_names2, 383fe1c642dSBill Krier lsar_lookup_names1 384fe1c642dSBill Krier }; 385fe1c642dSBill Krier 386fe1c642dSBill Krier const srvsvc_server_info_t *svinfo; 387fe1c642dSBill Krier lsa_names_t names; 388fe1c642dSBill Krier char *p; 389fe1c642dSBill Krier uint32_t length; 390fe1c642dSBill Krier uint32_t status = NT_STATUS_INVALID_PARAMETER; 391fe1c642dSBill Krier int n_op = (sizeof (ops) / sizeof (ops[0])); 392fe1c642dSBill Krier int i; 393fe1c642dSBill Krier 394fe1c642dSBill Krier if (lsa_handle == NULL || name == NULL || info == NULL) 395fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 396fe1c642dSBill Krier 397fe1c642dSBill Krier bzero(info, sizeof (smb_account_t)); 398fe1c642dSBill Krier 399fe1c642dSBill Krier svinfo = ndr_rpc_server_info(lsa_handle); 400fe1c642dSBill Krier if (svinfo->sv_os == NATIVE_OS_WIN2000 && 401fe1c642dSBill Krier svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) { 402fe1c642dSBill Krier /* 403fe1c642dSBill Krier * Windows 2000 doesn't like an LSA lookup for 404fe1c642dSBill Krier * DOMAIN\Administrator. 405fe1c642dSBill Krier */ 406fe1c642dSBill Krier if ((p = strchr(name, '\\')) != 0) { 407fe1c642dSBill Krier ++p; 408fe1c642dSBill Krier 409fe1c642dSBill Krier if (strcasecmp(p, "administrator") == 0) 410fe1c642dSBill Krier name = p; 411fe1c642dSBill Krier } 412fe1c642dSBill Krier 413fe1c642dSBill Krier } 414fe1c642dSBill Krier 415fe1c642dSBill Krier length = smb_wcequiv_strlen(name); 416fe1c642dSBill Krier names.name[0].length = length; 417fe1c642dSBill Krier names.name[0].allosize = length; 418fe1c642dSBill Krier names.name[0].str = (unsigned char *)name; 419fe1c642dSBill Krier names.n_entry = 1; 420fe1c642dSBill Krier 421fe1c642dSBill Krier if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) { 422fe1c642dSBill Krier for (i = 0; i < n_op; ++i) { 423fe1c642dSBill Krier ndr_rpc_set_nonull(lsa_handle); 424fe1c642dSBill Krier status = (*ops[i])(lsa_handle, &names, info); 425fe1c642dSBill Krier 426fe1c642dSBill Krier if (status != NT_STATUS_INVALID_PARAMETER) 427fe1c642dSBill Krier break; 428fe1c642dSBill Krier } 429fe1c642dSBill Krier } else { 430fe1c642dSBill Krier ndr_rpc_set_nonull(lsa_handle); 431fe1c642dSBill Krier status = lsar_lookup_names1(lsa_handle, &names, info); 432fe1c642dSBill Krier } 433fe1c642dSBill Krier 434fe1c642dSBill Krier if (status == NT_STATUS_SUCCESS) { 435fe1c642dSBill Krier info->a_name = lsar_get_username(name); 436fe1c642dSBill Krier 437fe1c642dSBill Krier if (!smb_account_validate(info)) { 438fe1c642dSBill Krier smb_account_free(info); 439fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 440fe1c642dSBill Krier } else { 441fe1c642dSBill Krier smb_account_trace(info); 442fe1c642dSBill Krier } 443fe1c642dSBill Krier } 444fe1c642dSBill Krier 445fe1c642dSBill Krier return (status); 446fe1c642dSBill Krier } 447fe1c642dSBill Krier 448fe1c642dSBill Krier /* 449fe1c642dSBill Krier * The name may be in one of the following forms: 450fe1c642dSBill Krier * 451fe1c642dSBill Krier * domain\username 452fe1c642dSBill Krier * domain/username 453fe1c642dSBill Krier * username 454fe1c642dSBill Krier * username@domain 455fe1c642dSBill Krier * 456fe1c642dSBill Krier * Return a strdup'd copy of the username. The caller is responsible 457fe1c642dSBill Krier * for freeing the allocated memory. 458fe1c642dSBill Krier */ 459fe1c642dSBill Krier static char * 460fe1c642dSBill Krier lsar_get_username(const char *name) 461fe1c642dSBill Krier { 462fe1c642dSBill Krier char tmp[MAXNAMELEN]; 463fe1c642dSBill Krier char *dp = NULL; 464fe1c642dSBill Krier char *np = NULL; 465fe1c642dSBill Krier 466fe1c642dSBill Krier (void) strlcpy(tmp, name, MAXNAMELEN); 467fe1c642dSBill Krier smb_name_parse(tmp, &np, &dp); 468fe1c642dSBill Krier 469fe1c642dSBill Krier if (dp != NULL && np != NULL) 470fe1c642dSBill Krier return (strdup(np)); 471fe1c642dSBill Krier else 472fe1c642dSBill Krier return (strdup(name)); 473fe1c642dSBill Krier } 474fe1c642dSBill Krier 475fe1c642dSBill Krier /* 476fe1c642dSBill Krier * lsar_lookup_names1 477fe1c642dSBill Krier * 478fe1c642dSBill Krier * Lookup a name and obtain the domain and user rid. 479fe1c642dSBill Krier * 480fe1c642dSBill Krier * Note: NT returns an error if the mapped_count is non-zero when the RPC 481fe1c642dSBill Krier * is called. 482fe1c642dSBill Krier * 483fe1c642dSBill Krier * If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED. 484fe1c642dSBill Krier */ 485fe1c642dSBill Krier static uint32_t 486fe1c642dSBill Krier lsar_lookup_names1(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 487fe1c642dSBill Krier smb_account_t *info) 488fe1c642dSBill Krier { 489fe1c642dSBill Krier struct mslsa_LookupNames arg; 490fe1c642dSBill Krier struct mslsa_rid_entry *rid_entry; 491fe1c642dSBill Krier struct mslsa_domain_entry *domain_entry; 492fe1c642dSBill Krier uint32_t status = NT_STATUS_SUCCESS; 493fe1c642dSBill Krier char *domname; 494fe1c642dSBill Krier int opnum = LSARPC_OPNUM_LookupNames; 495fe1c642dSBill Krier 496fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_LookupNames)); 497fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 498fe1c642dSBill Krier arg.lookup_level = LSA_LOOKUP_WKSTA; 499fe1c642dSBill Krier arg.name_table = (struct mslsa_lup_name_table *)names; 500fe1c642dSBill Krier 501fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 502fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 503fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 504fe1c642dSBill Krier } 505fe1c642dSBill Krier 506fe1c642dSBill Krier if (arg.status != NT_STATUS_SUCCESS) { 507fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 508fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 509fe1c642dSBill Krier return (NT_SC_VALUE(arg.status)); 510fe1c642dSBill Krier } 511fe1c642dSBill Krier 512fe1c642dSBill Krier if (arg.mapped_count == 0) { 513fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 514fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 515fe1c642dSBill Krier } 516fe1c642dSBill Krier 517fe1c642dSBill Krier rid_entry = &arg.translated_sids.rids[0]; 518fe1c642dSBill Krier if (rid_entry->domain_index != 0) { 519fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 520fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 521fe1c642dSBill Krier } 522fe1c642dSBill Krier 523fe1c642dSBill Krier domain_entry = &arg.domain_table->entries[0]; 524fe1c642dSBill Krier 525fe1c642dSBill Krier info->a_type = rid_entry->sid_name_use; 526fe1c642dSBill Krier info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 527fe1c642dSBill Krier if ((domname = (char *)domain_entry->domain_name.str) != NULL) 528fe1c642dSBill Krier info->a_domain = strdup(domname); 529fe1c642dSBill Krier info->a_rid = rid_entry->rid; 530fe1c642dSBill Krier info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid); 531fe1c642dSBill Krier 532fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 533fe1c642dSBill Krier return (status); 534fe1c642dSBill Krier } 535fe1c642dSBill Krier 536fe1c642dSBill Krier /* 537fe1c642dSBill Krier * lsar_lookup_names2 538fe1c642dSBill Krier */ 539fe1c642dSBill Krier static uint32_t 540fe1c642dSBill Krier lsar_lookup_names2(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 541fe1c642dSBill Krier smb_account_t *info) 542fe1c642dSBill Krier { 543fe1c642dSBill Krier struct lsar_LookupNames2 arg; 544fe1c642dSBill Krier struct lsar_rid_entry2 *rid_entry; 545fe1c642dSBill Krier struct mslsa_domain_entry *domain_entry; 546fe1c642dSBill Krier uint32_t status = NT_STATUS_SUCCESS; 547fe1c642dSBill Krier char *domname; 548fe1c642dSBill Krier int opnum = LSARPC_OPNUM_LookupNames2; 549fe1c642dSBill Krier 550fe1c642dSBill Krier bzero(&arg, sizeof (struct lsar_LookupNames2)); 551fe1c642dSBill Krier (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 552fe1c642dSBill Krier arg.lookup_level = LSA_LOOKUP_WKSTA; 553fe1c642dSBill Krier arg.client_revision = LSA_CLIENT_REVISION_AD; 554fe1c642dSBill Krier arg.name_table = (struct mslsa_lup_name_table *)names; 555fe1c642dSBill Krier 556fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 557fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 558fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 559fe1c642dSBill Krier } 560fe1c642dSBill Krier 561fe1c642dSBill Krier if (arg.status != NT_STATUS_SUCCESS) { 562fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 563fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 564fe1c642dSBill Krier return (NT_SC_VALUE(arg.status)); 565fe1c642dSBill Krier } 566fe1c642dSBill Krier 567fe1c642dSBill Krier if (arg.mapped_count == 0) { 568fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 569fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 570fe1c642dSBill Krier } 571fe1c642dSBill Krier 572fe1c642dSBill Krier rid_entry = &arg.translated_sids.rids[0]; 573fe1c642dSBill Krier if (rid_entry->domain_index != 0) { 574fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 575fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 576fe1c642dSBill Krier } 577fe1c642dSBill Krier 578fe1c642dSBill Krier domain_entry = &arg.domain_table->entries[0]; 579fe1c642dSBill Krier 580fe1c642dSBill Krier info->a_type = rid_entry->sid_name_use; 581fe1c642dSBill Krier info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 582fe1c642dSBill Krier if ((domname = (char *)domain_entry->domain_name.str) != NULL) 583fe1c642dSBill Krier info->a_domain = strdup(domname); 584fe1c642dSBill Krier info->a_rid = rid_entry->rid; 585fe1c642dSBill Krier info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid); 586fe1c642dSBill Krier 587fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 588fe1c642dSBill Krier return (status); 589fe1c642dSBill Krier } 590fe1c642dSBill Krier 591fe1c642dSBill Krier /* 592fe1c642dSBill Krier * lsar_lookup_names3 593fe1c642dSBill Krier */ 594fe1c642dSBill Krier static uint32_t 595fe1c642dSBill Krier lsar_lookup_names3(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 596fe1c642dSBill Krier smb_account_t *info) 597fe1c642dSBill Krier { 598fe1c642dSBill Krier struct lsar_LookupNames3 arg; 599fe1c642dSBill Krier lsar_translated_sid_ex2_t *sid_entry; 600fe1c642dSBill Krier struct mslsa_domain_entry *domain_entry; 601fe1c642dSBill Krier uint32_t status = NT_STATUS_SUCCESS; 602fe1c642dSBill Krier char *domname; 603fe1c642dSBill Krier int opnum = LSARPC_OPNUM_LookupNames3; 604fe1c642dSBill Krier 605fe1c642dSBill Krier bzero(&arg, sizeof (struct lsar_LookupNames3)); 606fe1c642dSBill Krier (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 607fe1c642dSBill Krier arg.lookup_level = LSA_LOOKUP_WKSTA; 608fe1c642dSBill Krier arg.client_revision = LSA_CLIENT_REVISION_AD; 609fe1c642dSBill Krier arg.name_table = (struct mslsa_lup_name_table *)names; 610fe1c642dSBill Krier 611fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 612fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 613fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 614fe1c642dSBill Krier } 615fe1c642dSBill Krier 616fe1c642dSBill Krier if (arg.status != NT_STATUS_SUCCESS) { 617fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 618fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 619fe1c642dSBill Krier return (NT_SC_VALUE(arg.status)); 620fe1c642dSBill Krier } 621fe1c642dSBill Krier 622fe1c642dSBill Krier if (arg.mapped_count == 0) { 623fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 624fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 625fe1c642dSBill Krier } 626fe1c642dSBill Krier 627fe1c642dSBill Krier sid_entry = &arg.translated_sids.sids[0]; 628fe1c642dSBill Krier if (sid_entry->domain_index != 0) { 629fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 630fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 631fe1c642dSBill Krier } 632fe1c642dSBill Krier 633fe1c642dSBill Krier domain_entry = &arg.domain_table->entries[0]; 634fe1c642dSBill Krier 635fe1c642dSBill Krier info->a_type = sid_entry->sid_name_use; 636fe1c642dSBill Krier info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 637fe1c642dSBill Krier if ((domname = (char *)domain_entry->domain_name.str) != NULL) 638fe1c642dSBill Krier info->a_domain = strdup(domname); 639fe1c642dSBill Krier info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid); 640fe1c642dSBill Krier (void) smb_sid_getrid(info->a_sid, &info->a_rid); 641fe1c642dSBill Krier 642fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 643fe1c642dSBill Krier return (status); 644fe1c642dSBill Krier } 645fe1c642dSBill Krier 646fe1c642dSBill Krier /* 647fe1c642dSBill Krier * lsar_lookup_names4 648fe1c642dSBill Krier * 649fe1c642dSBill Krier * This function is only valid if the remote RPC server is a domain 650fe1c642dSBill Krier * controller and requires the security extensions defined in MS-RPCE. 651fe1c642dSBill Krier * 652fe1c642dSBill Krier * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here 653fe1c642dSBill Krier * because we don't support the RPC_C_AUTHN_NETLOGON security provider. 654fe1c642dSBill Krier * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE. 655fe1c642dSBill Krier */ 656fe1c642dSBill Krier static uint32_t /*LINTED E_STATIC_UNUSED*/ 657fe1c642dSBill Krier lsar_lookup_names4(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 658fe1c642dSBill Krier smb_account_t *info) 659fe1c642dSBill Krier { 660fe1c642dSBill Krier struct lsar_LookupNames4 arg; 661fe1c642dSBill Krier lsar_translated_sid_ex2_t *sid_entry; 662fe1c642dSBill Krier struct mslsa_domain_entry *domain_entry; 663fe1c642dSBill Krier uint32_t status = NT_STATUS_SUCCESS; 664fe1c642dSBill Krier char *domname; 665fe1c642dSBill Krier int opnum = LSARPC_OPNUM_LookupNames4; 666fe1c642dSBill Krier 667fe1c642dSBill Krier bzero(&arg, sizeof (struct lsar_LookupNames4)); 668fe1c642dSBill Krier arg.lookup_level = LSA_LOOKUP_WKSTA; 669fe1c642dSBill Krier arg.client_revision = LSA_CLIENT_REVISION_AD; 670fe1c642dSBill Krier arg.name_table = (struct mslsa_lup_name_table *)names; 671fe1c642dSBill Krier 672fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 673fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 674fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 675fe1c642dSBill Krier } 676fe1c642dSBill Krier 677fe1c642dSBill Krier if (arg.status != NT_STATUS_SUCCESS) { 678fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 679fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 680fe1c642dSBill Krier if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED || 681fe1c642dSBill Krier arg.status == NT_STATUS_INVALID_SERVER_STATE) 682fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 683fe1c642dSBill Krier return (NT_SC_VALUE(arg.status)); 684fe1c642dSBill Krier } 685fe1c642dSBill Krier 686fe1c642dSBill Krier if (arg.mapped_count == 0) { 687fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 688fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 689fe1c642dSBill Krier } 690fe1c642dSBill Krier 691fe1c642dSBill Krier sid_entry = &arg.translated_sids.sids[0]; 692fe1c642dSBill Krier if (sid_entry->domain_index != 0) { 693fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 694fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 695fe1c642dSBill Krier } 696fe1c642dSBill Krier 697fe1c642dSBill Krier domain_entry = &arg.domain_table->entries[0]; 698fe1c642dSBill Krier 699fe1c642dSBill Krier info->a_type = sid_entry->sid_name_use; 700fe1c642dSBill Krier info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 701fe1c642dSBill Krier if ((domname = (char *)domain_entry->domain_name.str) != NULL) 702fe1c642dSBill Krier info->a_domain = strdup(domname); 703fe1c642dSBill Krier info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid); 704fe1c642dSBill Krier (void) smb_sid_getrid(info->a_sid, &info->a_rid); 705fe1c642dSBill Krier 706fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 707fe1c642dSBill Krier return (status); 708fe1c642dSBill Krier } 709fe1c642dSBill Krier 710fe1c642dSBill Krier /* 711fe1c642dSBill Krier * Lookup a sid and obtain the domain sid and account name. 712fe1c642dSBill Krier * This is a wrapper for the various lookup sid RPCs. 713fe1c642dSBill Krier */ 714fe1c642dSBill Krier uint32_t 715fe1c642dSBill Krier lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid, 716fe1c642dSBill Krier smb_account_t *account) 717fe1c642dSBill Krier { 718fe1c642dSBill Krier char sidbuf[SMB_SID_STRSZ]; 719fe1c642dSBill Krier uint32_t status; 720fe1c642dSBill Krier 721fe1c642dSBill Krier if (lsa_handle == NULL || sid == NULL || account == NULL) 722fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 723fe1c642dSBill Krier 724fe1c642dSBill Krier bzero(account, sizeof (smb_account_t)); 725fe1c642dSBill Krier bzero(sidbuf, SMB_SID_STRSZ); 726fe1c642dSBill Krier smb_sid_tostr(sid, sidbuf); 727fe1c642dSBill Krier smb_tracef("%s", sidbuf); 728fe1c642dSBill Krier 729fe1c642dSBill Krier if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) 730fe1c642dSBill Krier status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, 731fe1c642dSBill Krier account); 732fe1c642dSBill Krier else 733fe1c642dSBill Krier status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid, 734fe1c642dSBill Krier account); 735fe1c642dSBill Krier 736fe1c642dSBill Krier if (status == NT_STATUS_SUCCESS) { 737fe1c642dSBill Krier if (!smb_account_validate(account)) { 738fe1c642dSBill Krier smb_account_free(account); 739fe1c642dSBill Krier status = NT_STATUS_NO_MEMORY; 740fe1c642dSBill Krier } else { 741fe1c642dSBill Krier smb_account_trace(account); 742fe1c642dSBill Krier } 743fe1c642dSBill Krier } 744fe1c642dSBill Krier 745fe1c642dSBill Krier return (status); 746fe1c642dSBill Krier } 747fe1c642dSBill Krier 748fe1c642dSBill Krier /* 749fe1c642dSBill Krier * lsar_lookup_sids1 750fe1c642dSBill Krier */ 751fe1c642dSBill Krier static uint32_t 752fe1c642dSBill Krier lsar_lookup_sids1(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 753fe1c642dSBill Krier smb_account_t *account) 754fe1c642dSBill Krier { 755fe1c642dSBill Krier struct mslsa_LookupSids arg; 756fe1c642dSBill Krier struct mslsa_lup_sid_entry sid_entry; 757fe1c642dSBill Krier struct mslsa_name_entry *name_entry; 758fe1c642dSBill Krier struct mslsa_domain_entry *domain_entry; 759fe1c642dSBill Krier uint32_t status = NT_STATUS_SUCCESS; 760fe1c642dSBill Krier char *name; 761fe1c642dSBill Krier int opnum = LSARPC_OPNUM_LookupSids; 762fe1c642dSBill Krier 763fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_LookupSids)); 764fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 765fe1c642dSBill Krier arg.lookup_level = LSA_LOOKUP_WKSTA; 766fe1c642dSBill Krier 767fe1c642dSBill Krier sid_entry.psid = sid; 768fe1c642dSBill Krier arg.lup_sid_table.n_entry = 1; 769fe1c642dSBill Krier arg.lup_sid_table.entries = &sid_entry; 770fe1c642dSBill Krier 771fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 772fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 773fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 774fe1c642dSBill Krier } 775fe1c642dSBill Krier 776fe1c642dSBill Krier if (arg.status != NT_STATUS_SUCCESS) { 777fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 778fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 779fe1c642dSBill Krier return (NT_SC_VALUE(arg.status)); 780fe1c642dSBill Krier } 781fe1c642dSBill Krier 782fe1c642dSBill Krier if (arg.mapped_count == 0) { 783fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 784fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 785fe1c642dSBill Krier } 786fe1c642dSBill Krier 787fe1c642dSBill Krier name_entry = &arg.name_table.entries[0]; 788fe1c642dSBill Krier if (name_entry->domain_ix != 0) { 789fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 790fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 791fe1c642dSBill Krier } 792fe1c642dSBill Krier 793fe1c642dSBill Krier name = (char *)name_entry->name.str; 794fe1c642dSBill Krier account->a_name = (name) ? strdup(name) : strdup(""); 795fe1c642dSBill Krier account->a_type = name_entry->sid_name_use; 796fe1c642dSBill Krier account->a_sid = smb_sid_dup((smb_sid_t *)sid); 797fe1c642dSBill Krier (void) smb_sid_getrid(account->a_sid, &account->a_rid); 798fe1c642dSBill Krier 799fe1c642dSBill Krier domain_entry = &arg.domain_table->entries[0]; 800fe1c642dSBill Krier if ((name = (char *)domain_entry->domain_name.str) != NULL) 801fe1c642dSBill Krier account->a_domain = strdup(name); 802fe1c642dSBill Krier account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 803fe1c642dSBill Krier 804fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 805fe1c642dSBill Krier return (status); 806fe1c642dSBill Krier } 807fe1c642dSBill Krier 808fe1c642dSBill Krier /* 809fe1c642dSBill Krier * lsar_lookup_sids2 810fe1c642dSBill Krier */ 811fe1c642dSBill Krier static uint32_t 812fe1c642dSBill Krier lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 813fe1c642dSBill Krier smb_account_t *account) 814fe1c642dSBill Krier { 815fe1c642dSBill Krier struct lsar_lookup_sids2 arg; 816fe1c642dSBill Krier struct lsar_name_entry2 *name_entry; 817fe1c642dSBill Krier struct mslsa_lup_sid_entry sid_entry; 818fe1c642dSBill Krier struct mslsa_domain_entry *domain_entry; 819fe1c642dSBill Krier uint32_t status = NT_STATUS_SUCCESS; 820fe1c642dSBill Krier char *name; 821fe1c642dSBill Krier int opnum = LSARPC_OPNUM_LookupSids2; 822fe1c642dSBill Krier 823fe1c642dSBill Krier bzero(&arg, sizeof (struct lsar_lookup_sids2)); 824fe1c642dSBill Krier (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 825fe1c642dSBill Krier 826fe1c642dSBill Krier sid_entry.psid = sid; 827fe1c642dSBill Krier arg.lup_sid_table.n_entry = 1; 828fe1c642dSBill Krier arg.lup_sid_table.entries = &sid_entry; 829fe1c642dSBill Krier arg.lookup_level = LSA_LOOKUP_WKSTA; 830fe1c642dSBill Krier arg.client_revision = LSA_CLIENT_REVISION_AD; 831fe1c642dSBill Krier 832fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 833fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 834fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 835fe1c642dSBill Krier } 836fe1c642dSBill Krier 837fe1c642dSBill Krier if (arg.status != NT_STATUS_SUCCESS) { 838fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 839fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 840fe1c642dSBill Krier return (NT_SC_VALUE(arg.status)); 841fe1c642dSBill Krier } 842fe1c642dSBill Krier 843fe1c642dSBill Krier if (arg.mapped_count == 0) { 844fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 845fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 846fe1c642dSBill Krier } 847fe1c642dSBill Krier 848fe1c642dSBill Krier name_entry = &arg.name_table.entries[0]; 849fe1c642dSBill Krier if (name_entry->domain_ix != 0) { 850fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 851fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 852fe1c642dSBill Krier } 853fe1c642dSBill Krier 854fe1c642dSBill Krier name = (char *)name_entry->name.str; 855fe1c642dSBill Krier account->a_name = (name) ? strdup(name) : strdup(""); 856fe1c642dSBill Krier account->a_type = name_entry->sid_name_use; 857fe1c642dSBill Krier account->a_sid = smb_sid_dup((smb_sid_t *)sid); 858fe1c642dSBill Krier (void) smb_sid_getrid(account->a_sid, &account->a_rid); 859fe1c642dSBill Krier 860fe1c642dSBill Krier domain_entry = &arg.domain_table->entries[0]; 861fe1c642dSBill Krier if ((name = (char *)domain_entry->domain_name.str) != NULL) 862fe1c642dSBill Krier account->a_domain = strdup(name); 863fe1c642dSBill Krier account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 864fe1c642dSBill Krier 865fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 866fe1c642dSBill Krier return (status); 867fe1c642dSBill Krier } 868fe1c642dSBill Krier 869fe1c642dSBill Krier /* 870fe1c642dSBill Krier * lsar_lookup_sids3 871fe1c642dSBill Krier * 872fe1c642dSBill Krier * This function is only valid if the remote RPC server is a domain 873fe1c642dSBill Krier * controller and requires the security extensions defined in MS-RPCE. 874fe1c642dSBill Krier * 875fe1c642dSBill Krier * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here 876fe1c642dSBill Krier * because we don't support the RPC_C_AUTHN_NETLOGON security provider. 877fe1c642dSBill Krier * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE. 878fe1c642dSBill Krier */ 879fe1c642dSBill Krier static uint32_t /*LINTED E_STATIC_UNUSED*/ 880fe1c642dSBill Krier lsar_lookup_sids3(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 881fe1c642dSBill Krier smb_account_t *account) 882fe1c642dSBill Krier { 883fe1c642dSBill Krier struct lsar_lookup_sids3 arg; 884fe1c642dSBill Krier lsar_translated_name_ex_t *name_entry; 885fe1c642dSBill Krier struct mslsa_lup_sid_entry sid_entry; 886fe1c642dSBill Krier struct mslsa_domain_entry *domain_entry; 887fe1c642dSBill Krier uint32_t status = NT_STATUS_SUCCESS; 888fe1c642dSBill Krier char *name; 889fe1c642dSBill Krier int opnum = LSARPC_OPNUM_LookupSids3; 890fe1c642dSBill Krier 891fe1c642dSBill Krier bzero(&arg, sizeof (struct lsar_lookup_sids3)); 892fe1c642dSBill Krier 893fe1c642dSBill Krier sid_entry.psid = sid; 894fe1c642dSBill Krier arg.lup_sid_table.n_entry = 1; 895fe1c642dSBill Krier arg.lup_sid_table.entries = &sid_entry; 896fe1c642dSBill Krier arg.lookup_level = LSA_LOOKUP_WKSTA; 897fe1c642dSBill Krier arg.client_revision = LSA_CLIENT_REVISION_AD; 898fe1c642dSBill Krier 899fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 900fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 901fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 902fe1c642dSBill Krier } 903fe1c642dSBill Krier 904fe1c642dSBill Krier if (arg.status != NT_STATUS_SUCCESS) { 905fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 906fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 907fe1c642dSBill Krier if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED || 908fe1c642dSBill Krier arg.status == NT_STATUS_INVALID_SERVER_STATE) 909fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 910fe1c642dSBill Krier return (NT_SC_VALUE(arg.status)); 911fe1c642dSBill Krier } 912fe1c642dSBill Krier 913fe1c642dSBill Krier if (arg.mapped_count == 0) { 914fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 915fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 916fe1c642dSBill Krier } 917fe1c642dSBill Krier 918fe1c642dSBill Krier name_entry = &arg.name_table.entries[0]; 919fe1c642dSBill Krier if (name_entry->domain_ix != 0) { 920fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 921fe1c642dSBill Krier return (NT_STATUS_NONE_MAPPED); 922fe1c642dSBill Krier } 923fe1c642dSBill Krier 924fe1c642dSBill Krier name = (char *)name_entry->name.str; 925fe1c642dSBill Krier account->a_name = (name) ? strdup(name) : strdup(""); 926fe1c642dSBill Krier account->a_type = name_entry->sid_name_use; 927fe1c642dSBill Krier account->a_sid = smb_sid_dup((smb_sid_t *)sid); 928fe1c642dSBill Krier (void) smb_sid_getrid(account->a_sid, &account->a_rid); 929fe1c642dSBill Krier 930fe1c642dSBill Krier domain_entry = &arg.domain_table->entries[0]; 931fe1c642dSBill Krier if ((name = (char *)domain_entry->domain_name.str) != NULL) 932fe1c642dSBill Krier account->a_domain = strdup(name); 933fe1c642dSBill Krier account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 934fe1c642dSBill Krier 935fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 936fe1c642dSBill Krier return (status); 937fe1c642dSBill Krier } 938fe1c642dSBill Krier 939fe1c642dSBill Krier /* 940fe1c642dSBill Krier * lsar_enum_accounts 941fe1c642dSBill Krier * 942fe1c642dSBill Krier * Enumerate the list of accounts (i.e. SIDs). Use the handle returned 943fe1c642dSBill Krier * from lsa_open_policy2. The enum_context is used to support multiple 944fe1c642dSBill Krier * calls to this enumeration function. It should be set to 0 on the 945fe1c642dSBill Krier * first call. It will be updated by the domain controller and should 946fe1c642dSBill Krier * simply be passed unchanged to subsequent calls until there are no 947fe1c642dSBill Krier * more accounts. A warning status of 0x1A indicates that no more data 948fe1c642dSBill Krier * is available. The list of accounts will be returned in accounts. 949fe1c642dSBill Krier * This list is dynamically allocated using malloc, it should be freed 950fe1c642dSBill Krier * by the caller when it is no longer required. 951fe1c642dSBill Krier */ 952*b3700b07SGordon Ross DWORD 953fe1c642dSBill Krier lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 954fe1c642dSBill Krier struct mslsa_EnumAccountBuf *accounts) 955fe1c642dSBill Krier { 956fe1c642dSBill Krier struct mslsa_EnumerateAccounts arg; 957fe1c642dSBill Krier struct mslsa_AccountInfo *info; 958fe1c642dSBill Krier int opnum; 959fe1c642dSBill Krier int rc; 960*b3700b07SGordon Ross DWORD status; 961fe1c642dSBill Krier DWORD n_entries; 962fe1c642dSBill Krier DWORD i; 963fe1c642dSBill Krier int nbytes; 964fe1c642dSBill Krier 965fe1c642dSBill Krier if (lsa_handle == NULL || enum_context == NULL || accounts == NULL) 966*b3700b07SGordon Ross return (NT_STATUS_INTERNAL_ERROR); 967fe1c642dSBill Krier 968fe1c642dSBill Krier accounts->entries_read = 0; 969fe1c642dSBill Krier accounts->info = 0; 970fe1c642dSBill Krier 971fe1c642dSBill Krier opnum = LSARPC_OPNUM_EnumerateAccounts; 972fe1c642dSBill Krier 973fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_EnumerateAccounts)); 974fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 975fe1c642dSBill Krier arg.enum_context = *enum_context; 976fe1c642dSBill Krier arg.max_length = MLSVC_MAX_RESPONSE_LEN; 977fe1c642dSBill Krier 978fe1c642dSBill Krier rc = ndr_rpc_call(lsa_handle, opnum, &arg); 979fe1c642dSBill Krier if (rc == 0) { 980*b3700b07SGordon Ross status = arg.status; 981fe1c642dSBill Krier if (arg.status != 0) { 982148c5f43SAlan Wright if (arg.status == NT_STATUS_NO_MORE_ENTRIES) { 983fe1c642dSBill Krier *enum_context = arg.enum_context; 984fe1c642dSBill Krier } else { 985fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 986fe1c642dSBill Krier } 987fe1c642dSBill Krier } else if (arg.enum_buf->entries_read != 0) { 988fe1c642dSBill Krier n_entries = arg.enum_buf->entries_read; 989fe1c642dSBill Krier nbytes = n_entries * sizeof (struct mslsa_AccountInfo); 990fe1c642dSBill Krier 991fe1c642dSBill Krier if ((info = malloc(nbytes)) == NULL) { 992fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 993*b3700b07SGordon Ross return (NT_STATUS_NO_MEMORY); 994fe1c642dSBill Krier } 995fe1c642dSBill Krier 996fe1c642dSBill Krier for (i = 0; i < n_entries; ++i) 997fe1c642dSBill Krier info[i].sid = (lsa_sid_t *)smb_sid_dup( 998fe1c642dSBill Krier (smb_sid_t *)arg.enum_buf->info[i].sid); 999fe1c642dSBill Krier 1000fe1c642dSBill Krier accounts->entries_read = n_entries; 1001fe1c642dSBill Krier accounts->info = info; 1002fe1c642dSBill Krier *enum_context = arg.enum_context; 1003fe1c642dSBill Krier } 1004*b3700b07SGordon Ross } else { 1005*b3700b07SGordon Ross status = NT_STATUS_INVALID_PARAMETER; 1006fe1c642dSBill Krier } 1007fe1c642dSBill Krier 1008fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 1009*b3700b07SGordon Ross return (status); 1010fe1c642dSBill Krier } 1011fe1c642dSBill Krier 1012fe1c642dSBill Krier /* 1013fe1c642dSBill Krier * lsar_enum_trusted_domains 1014fe1c642dSBill Krier * 1015fe1c642dSBill Krier * Enumerate the list of trusted domains. Use the handle returned from 1016fe1c642dSBill Krier * lsa_open_policy2. The enum_context is used to support multiple calls 1017fe1c642dSBill Krier * to this enumeration function. It should be set to 0 on the first 1018fe1c642dSBill Krier * call. It will be updated by the domain controller and should simply 1019fe1c642dSBill Krier * be passed unchanged to subsequent calls until there are no more 1020fe1c642dSBill Krier * domains. 1021fe1c642dSBill Krier * 1022fe1c642dSBill Krier * The trusted domains aren't actually returned here. They are added 1023fe1c642dSBill Krier * to the NT domain database. After all of the trusted domains have 1024fe1c642dSBill Krier * been discovered, the database can be interrogated to find all of 1025fe1c642dSBill Krier * the trusted domains. 1026fe1c642dSBill Krier */ 1027fe1c642dSBill Krier DWORD 1028fe1c642dSBill Krier lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 1029fe1c642dSBill Krier smb_trusted_domains_t *list) 1030fe1c642dSBill Krier { 1031fe1c642dSBill Krier struct mslsa_EnumTrustedDomain arg; 1032fe1c642dSBill Krier int opnum; 1033fe1c642dSBill Krier DWORD status; 1034fe1c642dSBill Krier 1035fe1c642dSBill Krier if (list == NULL) 1036fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 1037fe1c642dSBill Krier 1038fe1c642dSBill Krier opnum = LSARPC_OPNUM_EnumTrustedDomain; 1039fe1c642dSBill Krier 1040fe1c642dSBill Krier bzero(list, sizeof (smb_trusted_domains_t)); 1041fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_EnumTrustedDomain)); 1042fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1043fe1c642dSBill Krier arg.enum_context = *enum_context; 1044fe1c642dSBill Krier arg.max_length = MLSVC_MAX_RESPONSE_LEN; 1045fe1c642dSBill Krier 1046fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 1047fe1c642dSBill Krier status = NT_STATUS_INVALID_PARAMETER; 1048fe1c642dSBill Krier } else if (arg.status != 0) { 1049fe1c642dSBill Krier *enum_context = arg.enum_context; 1050fe1c642dSBill Krier status = NT_SC_VALUE(arg.status); 1051fe1c642dSBill Krier 1052fe1c642dSBill Krier /* 1053148c5f43SAlan Wright * STATUS_NO_MORE_ENTRIES provides call 1054148c5f43SAlan Wright * status but does not indicate an error. 1055fe1c642dSBill Krier */ 1056148c5f43SAlan Wright if (status != NT_STATUS_NO_MORE_ENTRIES) 1057fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 1058fe1c642dSBill Krier } else if (arg.enum_buf->entries_read == 0) { 1059fe1c642dSBill Krier *enum_context = arg.enum_context; 1060fe1c642dSBill Krier status = 0; 1061fe1c642dSBill Krier } else { 1062fe1c642dSBill Krier lsar_set_trusted_domains(arg.enum_buf, list); 1063fe1c642dSBill Krier *enum_context = arg.enum_context; 1064fe1c642dSBill Krier status = 0; 1065fe1c642dSBill Krier } 1066fe1c642dSBill Krier 1067fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 1068fe1c642dSBill Krier return (status); 1069fe1c642dSBill Krier } 1070fe1c642dSBill Krier 1071fe1c642dSBill Krier DWORD 1072fe1c642dSBill Krier lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 1073fe1c642dSBill Krier smb_trusted_domains_t *list) 1074fe1c642dSBill Krier { 1075fe1c642dSBill Krier struct mslsa_EnumTrustedDomainEx arg; 1076fe1c642dSBill Krier int opnum; 1077fe1c642dSBill Krier DWORD status; 1078fe1c642dSBill Krier 1079fe1c642dSBill Krier if (list == NULL) 1080fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 1081fe1c642dSBill Krier 1082fe1c642dSBill Krier opnum = LSARPC_OPNUM_EnumTrustedDomainsEx; 1083fe1c642dSBill Krier 1084fe1c642dSBill Krier bzero(list, sizeof (smb_trusted_domains_t)); 1085fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_EnumTrustedDomainEx)); 1086fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1087fe1c642dSBill Krier arg.enum_context = *enum_context; 1088fe1c642dSBill Krier arg.max_length = MLSVC_MAX_RESPONSE_LEN; 1089fe1c642dSBill Krier 1090fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 1091fe1c642dSBill Krier status = NT_STATUS_INVALID_PARAMETER; 1092fe1c642dSBill Krier } else if (arg.status != 0) { 1093fe1c642dSBill Krier *enum_context = arg.enum_context; 1094fe1c642dSBill Krier status = NT_SC_VALUE(arg.status); 1095fe1c642dSBill Krier 1096fe1c642dSBill Krier /* 1097148c5f43SAlan Wright * STATUS_NO_MORE_ENTRIES provides call 1098148c5f43SAlan Wright * status but does not indicate an error. 1099fe1c642dSBill Krier */ 1100148c5f43SAlan Wright if (status != NT_STATUS_NO_MORE_ENTRIES) 1101fe1c642dSBill Krier ndr_rpc_status(lsa_handle, opnum, arg.status); 1102fe1c642dSBill Krier } else if (arg.enum_buf->entries_read == 0) { 1103fe1c642dSBill Krier *enum_context = arg.enum_context; 1104fe1c642dSBill Krier status = 0; 1105fe1c642dSBill Krier } else { 1106fe1c642dSBill Krier lsar_set_trusted_domains_ex(arg.enum_buf, list); 1107fe1c642dSBill Krier *enum_context = arg.enum_context; 1108fe1c642dSBill Krier status = 0; 1109fe1c642dSBill Krier } 1110fe1c642dSBill Krier 1111fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 1112fe1c642dSBill Krier return (status); 1113fe1c642dSBill Krier } 1114fe1c642dSBill Krier 1115fe1c642dSBill Krier /* 1116fe1c642dSBill Krier * lsar_enum_privs_account 1117fe1c642dSBill Krier * 1118fe1c642dSBill Krier * Privileges enum? Need an account handle. 1119fe1c642dSBill Krier */ 1120fe1c642dSBill Krier /*ARGSUSED*/ 1121fe1c642dSBill Krier int 1122fe1c642dSBill Krier lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account) 1123fe1c642dSBill Krier { 1124fe1c642dSBill Krier struct mslsa_EnumPrivsAccount arg; 1125fe1c642dSBill Krier int opnum; 1126fe1c642dSBill Krier int rc; 1127fe1c642dSBill Krier 1128fe1c642dSBill Krier opnum = LSARPC_OPNUM_EnumPrivsAccount; 1129fe1c642dSBill Krier 1130fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_EnumPrivsAccount)); 1131fe1c642dSBill Krier (void) memcpy(&arg.account_handle, &account_handle->handle, 1132fe1c642dSBill Krier sizeof (mslsa_handle_t)); 1133fe1c642dSBill Krier 1134fe1c642dSBill Krier rc = ndr_rpc_call(account_handle, opnum, &arg); 1135fe1c642dSBill Krier if ((rc == 0) && (arg.status != 0)) { 1136fe1c642dSBill Krier ndr_rpc_status(account_handle, opnum, arg.status); 1137fe1c642dSBill Krier rc = -1; 1138fe1c642dSBill Krier } 1139fe1c642dSBill Krier ndr_rpc_release(account_handle); 1140fe1c642dSBill Krier return (rc); 1141fe1c642dSBill Krier } 1142fe1c642dSBill Krier 1143fe1c642dSBill Krier /* 1144fe1c642dSBill Krier * lsar_lookup_priv_value 1145fe1c642dSBill Krier * 1146fe1c642dSBill Krier * Map a privilege name to a local unique id (LUID). Privilege names 1147fe1c642dSBill Krier * are consistent across the network. LUIDs are machine specific. 1148fe1c642dSBill Krier * This function provides the means to map a privilege name to the 1149fe1c642dSBill Krier * LUID used by a remote server to represent it. The handle here is 1150fe1c642dSBill Krier * a policy handle. 1151fe1c642dSBill Krier */ 1152fe1c642dSBill Krier int 1153fe1c642dSBill Krier lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name, 1154fe1c642dSBill Krier struct ms_luid *luid) 1155fe1c642dSBill Krier { 1156fe1c642dSBill Krier struct mslsa_LookupPrivValue arg; 1157fe1c642dSBill Krier int opnum; 1158fe1c642dSBill Krier int rc; 1159fe1c642dSBill Krier size_t length; 1160fe1c642dSBill Krier 1161fe1c642dSBill Krier if (lsa_handle == NULL || name == NULL || luid == NULL) 1162fe1c642dSBill Krier return (-1); 1163fe1c642dSBill Krier 1164fe1c642dSBill Krier opnum = LSARPC_OPNUM_LookupPrivValue; 1165fe1c642dSBill Krier 1166fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_LookupPrivValue)); 1167fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1168fe1c642dSBill Krier 1169fe1c642dSBill Krier length = smb_wcequiv_strlen(name); 1170fe1c642dSBill Krier if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) 1171fe1c642dSBill Krier length += sizeof (smb_wchar_t); 1172fe1c642dSBill Krier 1173fe1c642dSBill Krier arg.name.length = length; 1174fe1c642dSBill Krier arg.name.allosize = length; 1175fe1c642dSBill Krier arg.name.str = (unsigned char *)name; 1176fe1c642dSBill Krier 1177fe1c642dSBill Krier rc = ndr_rpc_call(lsa_handle, opnum, &arg); 1178fe1c642dSBill Krier if (rc == 0) { 1179fe1c642dSBill Krier if (arg.status != 0) 1180fe1c642dSBill Krier rc = -1; 1181fe1c642dSBill Krier else 1182fe1c642dSBill Krier (void) memcpy(luid, &arg.luid, sizeof (struct ms_luid)); 1183fe1c642dSBill Krier } 1184fe1c642dSBill Krier 1185fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 1186fe1c642dSBill Krier return (rc); 1187fe1c642dSBill Krier } 1188fe1c642dSBill Krier 1189fe1c642dSBill Krier /* 1190fe1c642dSBill Krier * lsar_lookup_priv_name 1191fe1c642dSBill Krier * 1192fe1c642dSBill Krier * Map a local unique id (LUID) to a privilege name. Privilege names 1193fe1c642dSBill Krier * are consistent across the network. LUIDs are machine specific. 1194fe1c642dSBill Krier * This function the means to map the LUID used by a remote server to 1195fe1c642dSBill Krier * the appropriate privilege name. The handle here is a policy handle. 1196fe1c642dSBill Krier */ 1197fe1c642dSBill Krier int 1198fe1c642dSBill Krier lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle, struct ms_luid *luid, 1199fe1c642dSBill Krier char *name, int namelen) 1200fe1c642dSBill Krier { 1201fe1c642dSBill Krier struct mslsa_LookupPrivName arg; 1202fe1c642dSBill Krier int opnum; 1203fe1c642dSBill Krier int rc; 1204fe1c642dSBill Krier 1205fe1c642dSBill Krier if (lsa_handle == NULL || luid == NULL || name == NULL) 1206fe1c642dSBill Krier return (-1); 1207fe1c642dSBill Krier 1208fe1c642dSBill Krier opnum = LSARPC_OPNUM_LookupPrivName; 1209fe1c642dSBill Krier 1210fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_LookupPrivName)); 1211fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1212fe1c642dSBill Krier (void) memcpy(&arg.luid, luid, sizeof (struct ms_luid)); 1213fe1c642dSBill Krier 1214fe1c642dSBill Krier rc = ndr_rpc_call(lsa_handle, opnum, &arg); 1215fe1c642dSBill Krier if (rc == 0) { 1216fe1c642dSBill Krier if (arg.status != 0) 1217fe1c642dSBill Krier rc = -1; 1218fe1c642dSBill Krier else 1219fe1c642dSBill Krier (void) strlcpy(name, (char const *)arg.name->str, 1220fe1c642dSBill Krier namelen); 1221fe1c642dSBill Krier } 1222fe1c642dSBill Krier 1223fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 1224fe1c642dSBill Krier return (rc); 1225fe1c642dSBill Krier } 1226fe1c642dSBill Krier 1227fe1c642dSBill Krier /* 1228fe1c642dSBill Krier * lsar_lookup_priv_display_name 1229fe1c642dSBill Krier * 1230fe1c642dSBill Krier * Map a privilege name to a privilege display name. The input handle 1231fe1c642dSBill Krier * should be an LSA policy handle and the name would normally be one 1232fe1c642dSBill Krier * of the privileges defined in smb_privilege.h 1233fe1c642dSBill Krier * 1234fe1c642dSBill Krier * There's something peculiar about the return status from NT servers, 1235fe1c642dSBill Krier * it's not always present. So for now, I'm ignoring the status in the 1236fe1c642dSBill Krier * RPC response. 1237fe1c642dSBill Krier * 1238fe1c642dSBill Krier * Returns NT status codes. 1239fe1c642dSBill Krier */ 1240fe1c642dSBill Krier DWORD 1241fe1c642dSBill Krier lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name, 1242fe1c642dSBill Krier char *display_name, int display_len) 1243fe1c642dSBill Krier { 1244fe1c642dSBill Krier struct mslsa_LookupPrivDisplayName arg; 1245fe1c642dSBill Krier int opnum; 1246fe1c642dSBill Krier size_t length; 1247fe1c642dSBill Krier DWORD status; 1248fe1c642dSBill Krier 1249fe1c642dSBill Krier if (lsa_handle == NULL || name == NULL || display_name == NULL) 1250fe1c642dSBill Krier return (NT_STATUS_INVALID_PARAMETER); 1251fe1c642dSBill Krier 1252fe1c642dSBill Krier opnum = LSARPC_OPNUM_LookupPrivDisplayName; 1253fe1c642dSBill Krier 1254fe1c642dSBill Krier bzero(&arg, sizeof (struct mslsa_LookupPrivDisplayName)); 1255fe1c642dSBill Krier (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1256fe1c642dSBill Krier 1257fe1c642dSBill Krier length = smb_wcequiv_strlen(name); 1258fe1c642dSBill Krier arg.name.length = length; 1259fe1c642dSBill Krier arg.name.allosize = length; 1260fe1c642dSBill Krier arg.name.str = (unsigned char *)name; 1261fe1c642dSBill Krier 1262fe1c642dSBill Krier arg.client_language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 1263fe1c642dSBill Krier arg.default_language = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL); 1264fe1c642dSBill Krier 1265fe1c642dSBill Krier if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) 1266fe1c642dSBill Krier status = NT_STATUS_INVALID_PARAMETER; 1267fe1c642dSBill Krier #if 0 1268fe1c642dSBill Krier else if (arg.status != 0) 1269fe1c642dSBill Krier status = NT_SC_VALUE(arg.status); 1270fe1c642dSBill Krier #endif 1271fe1c642dSBill Krier else { 1272fe1c642dSBill Krier (void) strlcpy(display_name, 1273fe1c642dSBill Krier (char const *)arg.display_name->str, display_len); 1274fe1c642dSBill Krier status = NT_STATUS_SUCCESS; 1275fe1c642dSBill Krier } 1276fe1c642dSBill Krier 1277fe1c642dSBill Krier ndr_rpc_release(lsa_handle); 1278fe1c642dSBill Krier return (status); 1279fe1c642dSBill Krier } 1280fe1c642dSBill Krier 1281fe1c642dSBill Krier static void 1282fe1c642dSBill Krier lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *enum_buf, 1283fe1c642dSBill Krier smb_trusted_domains_t *list) 1284fe1c642dSBill Krier { 1285fe1c642dSBill Krier char sidstr[SMB_SID_STRSZ]; 1286fe1c642dSBill Krier int i; 1287fe1c642dSBill Krier 1288fe1c642dSBill Krier if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0) 1289fe1c642dSBill Krier return; 1290fe1c642dSBill Krier 1291fe1c642dSBill Krier list->td_num = 0; 1292fe1c642dSBill Krier list->td_domains = calloc(enum_buf->entries_read, 1293fe1c642dSBill Krier sizeof (smb_domain_t)); 1294fe1c642dSBill Krier 1295fe1c642dSBill Krier if (list->td_domains == NULL) 1296fe1c642dSBill Krier return; 1297fe1c642dSBill Krier 1298fe1c642dSBill Krier list->td_num = enum_buf->entries_read; 1299fe1c642dSBill Krier for (i = 0; i < list->td_num; i++) { 1300fe1c642dSBill Krier smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr); 1301fe1c642dSBill Krier smb_domain_set_trust_info( 1302fe1c642dSBill Krier sidstr, 1303fe1c642dSBill Krier (char *)enum_buf->info[i].nb_name.str, 1304fe1c642dSBill Krier (char *)enum_buf->info[i].dns_name.str, 1305fe1c642dSBill Krier enum_buf->info[i].trust_direction, 1306fe1c642dSBill Krier enum_buf->info[i].trust_type, 1307fe1c642dSBill Krier enum_buf->info[i].trust_attrs, 1308fe1c642dSBill Krier &list->td_domains[i]); 1309fe1c642dSBill Krier } 1310fe1c642dSBill Krier } 1311fe1c642dSBill Krier 1312fe1c642dSBill Krier static void 1313fe1c642dSBill Krier lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf, 1314fe1c642dSBill Krier smb_trusted_domains_t *list) 1315fe1c642dSBill Krier { 1316fe1c642dSBill Krier char sidstr[SMB_SID_STRSZ]; 1317fe1c642dSBill Krier int i; 1318fe1c642dSBill Krier 1319fe1c642dSBill Krier if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0) 1320fe1c642dSBill Krier return; 1321fe1c642dSBill Krier 1322fe1c642dSBill Krier list->td_num = 0; 1323fe1c642dSBill Krier list->td_domains = calloc(enum_buf->entries_read, 1324fe1c642dSBill Krier sizeof (smb_domain_t)); 1325fe1c642dSBill Krier 1326fe1c642dSBill Krier if (list->td_domains == NULL) 1327fe1c642dSBill Krier return; 1328fe1c642dSBill Krier 1329fe1c642dSBill Krier list->td_num = enum_buf->entries_read; 1330fe1c642dSBill Krier for (i = 0; i < list->td_num; i++) { 1331fe1c642dSBill Krier smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr); 1332fe1c642dSBill Krier smb_domain_set_trust_info( 1333fe1c642dSBill Krier sidstr, (char *)enum_buf->info[i].name.str, 1334fe1c642dSBill Krier "", 0, 0, 0, &list->td_domains[i]); 1335fe1c642dSBill Krier } 1336fe1c642dSBill Krier } 1337fe1c642dSBill Krier 1338fe1c642dSBill Krier static void 1339fe1c642dSBill Krier smb_account_trace(const smb_account_t *info) 1340fe1c642dSBill Krier { 1341fe1c642dSBill Krier char sidbuf[SMB_SID_STRSZ]; 1342fe1c642dSBill Krier 1343fe1c642dSBill Krier bzero(sidbuf, SMB_SID_STRSZ); 1344fe1c642dSBill Krier smb_sid_tostr(info->a_sid, sidbuf); 1345fe1c642dSBill Krier 1346fe1c642dSBill Krier smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name, 1347fe1c642dSBill Krier sidbuf, info->a_rid, smb_sid_type2str(info->a_type)); 1348fe1c642dSBill Krier } 1349