1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22*dc20a302Sas * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw #pragma ident "%Z%%M% %I% %E% SMI" 27da6c28aaSamw 28da6c28aaSamw /* 29da6c28aaSamw * This module provides the high level interface to the LSA RPC functions. 30da6c28aaSamw */ 31da6c28aaSamw 32da6c28aaSamw #include <strings.h> 33da6c28aaSamw #include <unistd.h> 34da6c28aaSamw #include <netdb.h> 35*dc20a302Sas #include <pwd.h> 36*dc20a302Sas #include <grp.h> 37da6c28aaSamw 38da6c28aaSamw #include <smbsrv/libsmb.h> 39da6c28aaSamw #include <smbsrv/libsmbns.h> 40da6c28aaSamw #include <smbsrv/libmlsvc.h> 4155bf511dSas #include <smbsrv/libsmbrdr.h> 42da6c28aaSamw #include <smbsrv/lsalib.h> 43da6c28aaSamw #include <smbsrv/ntstatus.h> 44da6c28aaSamw #include <smbsrv/smbinfo.h> 45da6c28aaSamw #include <smbsrv/ntsid.h> 46da6c28aaSamw #include <smbsrv/smb_token.h> 47da6c28aaSamw 48*dc20a302Sas /* 49*dc20a302Sas * Name Lookup modes 50*dc20a302Sas */ 51*dc20a302Sas #define MLSVC_LOOKUP_BUILTIN 1 52*dc20a302Sas #define MLSVC_LOOKUP_LOCAL 2 53*dc20a302Sas #define MLSVC_LOOKUP_DOMAIN 3 54*dc20a302Sas #define MLSVC_LOOKUP_DOMLOC 4 55*dc20a302Sas 56*dc20a302Sas static int lsa_lookup_mode(const char *, const char *); 57*dc20a302Sas static uint32_t lsa_lookup_name_builtin(char *, smb_userinfo_t *); 58*dc20a302Sas static uint32_t lsa_lookup_name_local(char *, char *, uint16_t, 59*dc20a302Sas smb_userinfo_t *); 60*dc20a302Sas static uint32_t lsa_lookup_name_lusr(char *, nt_sid_t **); 61*dc20a302Sas static uint32_t lsa_lookup_name_lgrp(char *, nt_sid_t **); 62*dc20a302Sas static uint32_t lsa_lookup_name_domain(char *, char *, char *, 63*dc20a302Sas smb_userinfo_t *); 64*dc20a302Sas 65*dc20a302Sas static uint32_t lsa_lookup_sid_builtin(nt_sid_t *, smb_userinfo_t *); 66*dc20a302Sas static uint32_t lsa_lookup_sid_local(nt_sid_t *, smb_userinfo_t *); 67*dc20a302Sas static uint32_t lsa_lookup_sid_domain(nt_sid_t *, smb_userinfo_t *); 68*dc20a302Sas 69da6c28aaSamw static int lsa_list_accounts(mlsvc_handle_t *); 70da6c28aaSamw 71*dc20a302Sas /* 72*dc20a302Sas * lsa_lookup_name 73*dc20a302Sas * 74*dc20a302Sas * Lookup the given account and returns the account information 75*dc20a302Sas * in 'ainfo' 76*dc20a302Sas * 77*dc20a302Sas * If the name is a domain account, it may refer to a user, group or 78*dc20a302Sas * alias. If it is a local account, its type should be specified 79*dc20a302Sas * in the sid_type parameter. In case the account type is unknown 80*dc20a302Sas * sid_type should be set to SidTypeUnknown. 81*dc20a302Sas * 82*dc20a302Sas * account argument could be either [domain\\]name or [domain/]name. 83*dc20a302Sas * If domain is not specified and service is in domain mode then it 84*dc20a302Sas * first does a domain lookup and then a local lookup. 85*dc20a302Sas */ 86*dc20a302Sas uint32_t 87*dc20a302Sas lsa_lookup_name(char *server, char *account, uint16_t sid_type, 88*dc20a302Sas smb_userinfo_t *ainfo) 89*dc20a302Sas { 90*dc20a302Sas nt_domain_t *dominfo; 91*dc20a302Sas int lookup_mode; 92*dc20a302Sas char *name; 93*dc20a302Sas char *domain; 94*dc20a302Sas uint32_t status = NT_STATUS_NONE_MAPPED; 95*dc20a302Sas 96*dc20a302Sas (void) strsubst(account, '\\', '/'); 97*dc20a302Sas name = strchr(account, '/'); 98*dc20a302Sas if (name) { 99*dc20a302Sas /* domain is specified */ 100*dc20a302Sas *name++ = '\0'; 101*dc20a302Sas domain = account; 102*dc20a302Sas } else { 103*dc20a302Sas name = account; 104*dc20a302Sas domain = NULL; 105*dc20a302Sas } 106*dc20a302Sas 107*dc20a302Sas lookup_mode = lsa_lookup_mode(domain, name); 108*dc20a302Sas 109*dc20a302Sas switch (lookup_mode) { 110*dc20a302Sas case MLSVC_LOOKUP_BUILTIN: 111*dc20a302Sas return (lsa_lookup_name_builtin(name, ainfo)); 112*dc20a302Sas 113*dc20a302Sas case MLSVC_LOOKUP_LOCAL: 114*dc20a302Sas return (lsa_lookup_name_local(domain, name, sid_type, ainfo)); 115*dc20a302Sas 116*dc20a302Sas case MLSVC_LOOKUP_DOMAIN: 117*dc20a302Sas return (lsa_lookup_name_domain(server, domain, name, ainfo)); 118*dc20a302Sas 119*dc20a302Sas default: 120*dc20a302Sas /* lookup the name in domain */ 121*dc20a302Sas dominfo = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY); 122*dc20a302Sas if (dominfo == NULL) 123*dc20a302Sas return (NT_STATUS_INTERNAL_ERROR); 124*dc20a302Sas status = lsa_lookup_name_domain(server, dominfo->name, name, 125*dc20a302Sas ainfo); 126*dc20a302Sas if (status != NT_STATUS_NONE_MAPPED) 127*dc20a302Sas return (status); 128*dc20a302Sas 129*dc20a302Sas mlsvc_release_user_info(ainfo); 130*dc20a302Sas /* lookup the name locally */ 131*dc20a302Sas status = lsa_lookup_name_local(domain, name, sid_type, ainfo); 132*dc20a302Sas } 133*dc20a302Sas 134*dc20a302Sas return (status); 135*dc20a302Sas } 136*dc20a302Sas 137*dc20a302Sas uint32_t 138*dc20a302Sas lsa_lookup_sid(nt_sid_t *sid, smb_userinfo_t *ainfo) 139*dc20a302Sas { 140*dc20a302Sas if (!nt_sid_is_valid(sid)) 141*dc20a302Sas return (NT_STATUS_INVALID_SID); 142*dc20a302Sas 143*dc20a302Sas if (nt_sid_is_local(sid)) 144*dc20a302Sas return (lsa_lookup_sid_local(sid, ainfo)); 145*dc20a302Sas 146*dc20a302Sas if (nt_builtin_lookup_sid(sid, NULL)) 147*dc20a302Sas return (lsa_lookup_sid_builtin(sid, ainfo)); 148*dc20a302Sas 149*dc20a302Sas return (lsa_lookup_sid_domain(sid, ainfo)); 150*dc20a302Sas } 151*dc20a302Sas 152da6c28aaSamw /* 153da6c28aaSamw * lsa_query_primary_domain_info 154da6c28aaSamw * 155da6c28aaSamw * Obtains the primary domain SID and name from the specified server 156da6c28aaSamw * (domain controller). The information is stored in the NT domain 157da6c28aaSamw * database by the lower level lsar_query_info_policy call. The caller 158da6c28aaSamw * should query the database to obtain a reference to the primary 159da6c28aaSamw * domain information. 160da6c28aaSamw * 161da6c28aaSamw * Returns NT status codes. 162da6c28aaSamw */ 163da6c28aaSamw DWORD 164da6c28aaSamw lsa_query_primary_domain_info(void) 165da6c28aaSamw { 166da6c28aaSamw mlsvc_handle_t domain_handle; 167da6c28aaSamw DWORD status; 16855bf511dSas char *user = smbrdr_ipc_get_user(); 169da6c28aaSamw 17055bf511dSas if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0) 171da6c28aaSamw return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 172da6c28aaSamw 173da6c28aaSamw status = lsar_query_info_policy(&domain_handle, 174da6c28aaSamw MSLSA_POLICY_PRIMARY_DOMAIN_INFO); 175da6c28aaSamw 176da6c28aaSamw (void) lsar_close(&domain_handle); 177da6c28aaSamw return (status); 178da6c28aaSamw } 179da6c28aaSamw 180da6c28aaSamw /* 181da6c28aaSamw * lsa_query_account_domain_info 182da6c28aaSamw * 183da6c28aaSamw * Obtains the account domain SID and name from the current server 184da6c28aaSamw * (domain controller). The information is stored in the NT domain 185da6c28aaSamw * database by the lower level lsar_query_info_policy call. The caller 186da6c28aaSamw * should query the database to obtain a reference to the account 187da6c28aaSamw * domain information. 188da6c28aaSamw * 189da6c28aaSamw * Returns NT status codes. 190da6c28aaSamw */ 191da6c28aaSamw DWORD 192da6c28aaSamw lsa_query_account_domain_info(void) 193da6c28aaSamw { 194da6c28aaSamw mlsvc_handle_t domain_handle; 195da6c28aaSamw DWORD status; 19655bf511dSas char *user = smbrdr_ipc_get_user(); 197da6c28aaSamw 19855bf511dSas if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0) 199da6c28aaSamw return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 200da6c28aaSamw 201da6c28aaSamw status = lsar_query_info_policy(&domain_handle, 202da6c28aaSamw MSLSA_POLICY_ACCOUNT_DOMAIN_INFO); 203da6c28aaSamw 204da6c28aaSamw (void) lsar_close(&domain_handle); 205da6c28aaSamw return (status); 206da6c28aaSamw } 207da6c28aaSamw 208da6c28aaSamw /* 209da6c28aaSamw * lsa_enum_trusted_domains 210da6c28aaSamw * 211da6c28aaSamw * Enumerate the trusted domains in our primary domain. The information 212da6c28aaSamw * is stored in the NT domain database by the lower level 213da6c28aaSamw * lsar_enum_trusted_domains call. The caller should query the database 214da6c28aaSamw * to obtain a reference to the trusted domain information. 215da6c28aaSamw * 216da6c28aaSamw * Returns NT status codes. 217da6c28aaSamw */ 218da6c28aaSamw DWORD 219da6c28aaSamw lsa_enum_trusted_domains(void) 220da6c28aaSamw { 221da6c28aaSamw mlsvc_handle_t domain_handle; 222da6c28aaSamw DWORD enum_context; 223da6c28aaSamw DWORD status; 22455bf511dSas char *user = smbrdr_ipc_get_user(); 225da6c28aaSamw 22655bf511dSas if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0) 227da6c28aaSamw return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 228da6c28aaSamw 229da6c28aaSamw enum_context = 0; 230da6c28aaSamw 231da6c28aaSamw status = lsar_enum_trusted_domains(&domain_handle, &enum_context); 232da6c28aaSamw if (status == MLSVC_NO_MORE_DATA) { 233da6c28aaSamw /* 234da6c28aaSamw * MLSVC_NO_MORE_DATA indicates that we 235da6c28aaSamw * have all of the available information. 236da6c28aaSamw */ 237da6c28aaSamw status = NT_STATUS_SUCCESS; 238da6c28aaSamw } 239da6c28aaSamw 240da6c28aaSamw (void) lsar_close(&domain_handle); 241da6c28aaSamw return (status); 242da6c28aaSamw } 243da6c28aaSamw 244da6c28aaSamw /* 245*dc20a302Sas * lsa_lookup_name_builtin 246da6c28aaSamw * 247da6c28aaSamw * lookup builtin account table to see if account_name is 248da6c28aaSamw * there. If it is there, set sid_name_use, domain_sid, 249da6c28aaSamw * domain_name, and rid fields of the passed user_info 250*dc20a302Sas * structure. 251da6c28aaSamw */ 252*dc20a302Sas static uint32_t 253*dc20a302Sas lsa_lookup_name_builtin(char *account_name, smb_userinfo_t *user_info) 254da6c28aaSamw { 255da6c28aaSamw char *domain; 256da6c28aaSamw int res; 257da6c28aaSamw 258*dc20a302Sas user_info->user_sid = nt_builtin_lookup_name(account_name, 259da6c28aaSamw &user_info->sid_name_use); 260da6c28aaSamw 261*dc20a302Sas if (user_info->user_sid == NULL) 262*dc20a302Sas return (NT_STATUS_NONE_MAPPED); 263da6c28aaSamw 264*dc20a302Sas user_info->domain_sid = nt_sid_dup(user_info->user_sid); 265da6c28aaSamw res = nt_sid_split(user_info->domain_sid, &user_info->rid); 266da6c28aaSamw if (res < 0) 267*dc20a302Sas return (NT_STATUS_INTERNAL_ERROR); 268da6c28aaSamw 269da6c28aaSamw domain = nt_builtin_lookup_domain(account_name); 270da6c28aaSamw if (domain) { 271da6c28aaSamw user_info->domain_name = strdup(domain); 272*dc20a302Sas return (NT_STATUS_SUCCESS); 273da6c28aaSamw } 274da6c28aaSamw 275*dc20a302Sas return (NT_STATUS_INTERNAL_ERROR); 276da6c28aaSamw } 277da6c28aaSamw 278da6c28aaSamw /* 279*dc20a302Sas * lsa_lookup_name_local 280da6c28aaSamw * 281*dc20a302Sas * Obtains the infomation for the given local account name if it 282*dc20a302Sas * can be found. The type of account is specified by sid_type, 283*dc20a302Sas * which can be of user, group or unknown type. If the caller 284*dc20a302Sas * doesn't know whether the name is a user or group name then 285*dc20a302Sas * SidTypeUnknown should be passed, in which case this 286*dc20a302Sas * function first tries to find a user and then a group match. 287da6c28aaSamw * 288*dc20a302Sas * CAVEAT: if there are both a user and a group account with 289*dc20a302Sas * the same name, user SID will always be returned. 290da6c28aaSamw */ 291*dc20a302Sas static uint32_t 292*dc20a302Sas lsa_lookup_name_local(char *domain, char *name, uint16_t sid_type, 293*dc20a302Sas smb_userinfo_t *ainfo) 294da6c28aaSamw { 295da6c28aaSamw char hostname[MAXHOSTNAMELEN]; 296*dc20a302Sas nt_sid_t *sid; 297*dc20a302Sas uint32_t status; 298*dc20a302Sas 299*dc20a302Sas switch (sid_type) { 300*dc20a302Sas case SidTypeUser: 301*dc20a302Sas status = lsa_lookup_name_lusr(name, &sid); 302*dc20a302Sas if (status != NT_STATUS_SUCCESS) 303*dc20a302Sas return (status); 304*dc20a302Sas break; 305*dc20a302Sas 306*dc20a302Sas case SidTypeGroup: 307*dc20a302Sas case SidTypeAlias: 308*dc20a302Sas status = lsa_lookup_name_lgrp(name, &sid); 309*dc20a302Sas if (status != NT_STATUS_SUCCESS) 310*dc20a302Sas return (status); 311*dc20a302Sas break; 312*dc20a302Sas 313*dc20a302Sas case SidTypeUnknown: 314*dc20a302Sas sid_type = SidTypeUser; 315*dc20a302Sas status = lsa_lookup_name_lusr(name, &sid); 316*dc20a302Sas if (status == NT_STATUS_SUCCESS) 317*dc20a302Sas break; 318*dc20a302Sas 319*dc20a302Sas if (status == NT_STATUS_NONE_MAPPED) 320*dc20a302Sas return (status); 321*dc20a302Sas 322*dc20a302Sas sid_type = SidTypeAlias; 323*dc20a302Sas status = lsa_lookup_name_lgrp(name, &sid); 324*dc20a302Sas if (status != NT_STATUS_SUCCESS) 325*dc20a302Sas return (status); 326*dc20a302Sas break; 327*dc20a302Sas 328*dc20a302Sas default: 329*dc20a302Sas return (NT_STATUS_INVALID_PARAMETER); 330da6c28aaSamw } 331da6c28aaSamw 332*dc20a302Sas ainfo->sid_name_use = sid_type; 333*dc20a302Sas ainfo->user_sid = sid; 334*dc20a302Sas ainfo->domain_sid = nt_sid_dup(sid); 335*dc20a302Sas if (ainfo->domain_sid == NULL) 336*dc20a302Sas return (NT_STATUS_NO_MEMORY); 337*dc20a302Sas 338*dc20a302Sas (void) nt_sid_split(ainfo->domain_sid, &ainfo->rid); 339*dc20a302Sas if ((domain == NULL) || (*domain == '\0')) { 340*dc20a302Sas (void) smb_getnetbiosname(hostname, sizeof (hostname)); 341*dc20a302Sas ainfo->domain_name = strdup(hostname); 342*dc20a302Sas } else { 343*dc20a302Sas ainfo->domain_name = strdup(domain); 344*dc20a302Sas } 345da6c28aaSamw 346*dc20a302Sas if (ainfo->domain_name == NULL) 347*dc20a302Sas return (NT_STATUS_NO_MEMORY); 348da6c28aaSamw 349*dc20a302Sas return (NT_STATUS_SUCCESS); 350da6c28aaSamw } 351da6c28aaSamw 352da6c28aaSamw /* 353*dc20a302Sas * lsa_lookup_name_domain 354da6c28aaSamw * 355da6c28aaSamw * Lookup a name on the specified server (domain controller) and obtain 356da6c28aaSamw * the appropriate SID. The information is returned in the user_info 357da6c28aaSamw * structure. The caller is responsible for allocating and releasing 358da6c28aaSamw * this structure. On success sid_name_use will be set to indicate the 359da6c28aaSamw * type of SID. If the name is the domain name, this function will be 360da6c28aaSamw * identical to lsa_domain_info. Otherwise the rid and name fields will 361da6c28aaSamw * also be valid. On failure sid_name_use will be set to SidTypeUnknown. 362da6c28aaSamw */ 363*dc20a302Sas static uint32_t 364*dc20a302Sas lsa_lookup_name_domain(char *server, char *domain, char *account_name, 365da6c28aaSamw smb_userinfo_t *user_info) 366da6c28aaSamw { 367da6c28aaSamw mlsvc_handle_t domain_handle; 36855bf511dSas char *user = smbrdr_ipc_get_user(); 369*dc20a302Sas uint32_t status; 370da6c28aaSamw 371*dc20a302Sas if (lsar_open(server, domain, user, &domain_handle) != 0) 372da6c28aaSamw return (NT_STATUS_INVALID_PARAMETER); 373da6c28aaSamw 374da6c28aaSamw status = lsar_lookup_names2(&domain_handle, account_name, user_info); 375da6c28aaSamw if (status == NT_STATUS_REVISION_MISMATCH) { 376da6c28aaSamw /* 377da6c28aaSamw * Not a Windows 2000 domain controller: 378da6c28aaSamw * use the NT compatible call. 379da6c28aaSamw */ 380*dc20a302Sas status = lsar_lookup_names(&domain_handle, account_name, 381*dc20a302Sas user_info); 382da6c28aaSamw } 383da6c28aaSamw 384da6c28aaSamw (void) lsar_close(&domain_handle); 385da6c28aaSamw return (status); 386da6c28aaSamw } 387da6c28aaSamw 388da6c28aaSamw /* 389*dc20a302Sas * lsa_test_lookup 390da6c28aaSamw * 391*dc20a302Sas * Test routine for lsa_lookup_name_domain and lsa_lookup_sid2. 392da6c28aaSamw */ 393da6c28aaSamw void 394*dc20a302Sas lsa_test_lookup(char *name) 395da6c28aaSamw { 396da6c28aaSamw smb_userinfo_t *user_info; 397da6c28aaSamw nt_sid_t *sid; 398da6c28aaSamw DWORD status; 399da6c28aaSamw smb_ntdomain_t *di; 400da6c28aaSamw 401da6c28aaSamw if ((di = smb_getdomaininfo(0)) == 0) 402da6c28aaSamw return; 403da6c28aaSamw 404da6c28aaSamw user_info = mlsvc_alloc_user_info(); 405da6c28aaSamw 406*dc20a302Sas if (lsa_lookup_name_builtin(name, user_info) != 0) { 407*dc20a302Sas status = lsa_lookup_name_domain(di->server, di->domain, name, 408da6c28aaSamw user_info); 409da6c28aaSamw 410da6c28aaSamw if (status == 0) { 411da6c28aaSamw sid = nt_sid_splice(user_info->domain_sid, 412da6c28aaSamw user_info->rid); 413da6c28aaSamw 414*dc20a302Sas (void) lsa_lookup_sid_domain(sid, user_info); 415da6c28aaSamw free(sid); 416da6c28aaSamw } 417da6c28aaSamw } 418da6c28aaSamw 419da6c28aaSamw mlsvc_free_user_info(user_info); 420da6c28aaSamw } 421da6c28aaSamw 422da6c28aaSamw /* 423da6c28aaSamw * lsa_lookup_privs 424da6c28aaSamw * 425da6c28aaSamw * Request the privileges associated with the specified account. In 426da6c28aaSamw * order to get the privileges, we first have to lookup the name on 427da6c28aaSamw * the specified domain controller and obtain the appropriate SID. 428da6c28aaSamw * The SID can then be used to open the account and obtain the 429da6c28aaSamw * account privileges. The results from both the name lookup and the 430da6c28aaSamw * privileges are returned in the user_info structure. The caller is 431da6c28aaSamw * responsible for allocating and releasing this structure. 432da6c28aaSamw * 433da6c28aaSamw * On success 0 is returned. Otherwise a -ve error code. 434da6c28aaSamw */ 435da6c28aaSamw /*ARGSUSED*/ 436da6c28aaSamw int 437da6c28aaSamw lsa_lookup_privs(char *server, char *account_name, char *target_name, 438da6c28aaSamw smb_userinfo_t *user_info) 439da6c28aaSamw { 440da6c28aaSamw mlsvc_handle_t domain_handle; 441da6c28aaSamw int rc; 44255bf511dSas char *user = smbrdr_ipc_get_user(); 443da6c28aaSamw 44455bf511dSas if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0) 445da6c28aaSamw return (-1); 446da6c28aaSamw 447da6c28aaSamw rc = lsa_list_accounts(&domain_handle); 448da6c28aaSamw (void) lsar_close(&domain_handle); 449da6c28aaSamw return (rc); 450da6c28aaSamw } 451da6c28aaSamw 452da6c28aaSamw /* 453da6c28aaSamw * lsa_list_privs 454da6c28aaSamw * 455da6c28aaSamw * List the privileges supported by the specified server. 456da6c28aaSamw * This function is only intended for diagnostics. 457da6c28aaSamw * 458da6c28aaSamw * Returns NT status codes. 459da6c28aaSamw */ 460da6c28aaSamw DWORD 461da6c28aaSamw lsa_list_privs(char *server, char *domain) 462da6c28aaSamw { 463da6c28aaSamw static char name[128]; 464da6c28aaSamw static struct ms_luid luid; 465da6c28aaSamw mlsvc_handle_t domain_handle; 466da6c28aaSamw int rc; 467da6c28aaSamw int i; 46855bf511dSas char *user = smbrdr_ipc_get_user(); 469da6c28aaSamw 47055bf511dSas rc = lsar_open(server, domain, user, &domain_handle); 471da6c28aaSamw if (rc != 0) 472da6c28aaSamw return (NT_STATUS_INVALID_PARAMETER); 473da6c28aaSamw 474da6c28aaSamw for (i = 0; i < 30; ++i) { 475da6c28aaSamw luid.low_part = i; 476da6c28aaSamw rc = lsar_lookup_priv_name(&domain_handle, &luid, name, 128); 477da6c28aaSamw if (rc != 0) 478da6c28aaSamw continue; 479da6c28aaSamw 480da6c28aaSamw (void) lsar_lookup_priv_value(&domain_handle, name, &luid); 481da6c28aaSamw (void) lsar_lookup_priv_display_name(&domain_handle, name, 482da6c28aaSamw name, 128); 483da6c28aaSamw } 484da6c28aaSamw 485da6c28aaSamw (void) lsar_close(&domain_handle); 486da6c28aaSamw return (NT_STATUS_SUCCESS); 487da6c28aaSamw } 488da6c28aaSamw 489da6c28aaSamw /* 490da6c28aaSamw * lsa_test 491da6c28aaSamw * 492da6c28aaSamw * LSA test routine: open and close the LSA interface. 493da6c28aaSamw * TBD: the parameters should be server and domain. 494da6c28aaSamw * 495da6c28aaSamw * On success 0 is returned. Otherwise a -ve error code. 496da6c28aaSamw */ 497da6c28aaSamw /*ARGSUSED*/ 498da6c28aaSamw int 499da6c28aaSamw lsa_test(char *server, char *account_name) 500da6c28aaSamw { 501da6c28aaSamw mlsvc_handle_t domain_handle; 502da6c28aaSamw int rc; 50355bf511dSas char *user = smbrdr_ipc_get_user(); 504da6c28aaSamw 50555bf511dSas rc = lsar_open(NULL, NULL, user, &domain_handle); 506da6c28aaSamw if (rc != 0) 507da6c28aaSamw return (-1); 508da6c28aaSamw 509da6c28aaSamw if (lsar_close(&domain_handle) != 0) 510da6c28aaSamw return (-1); 511da6c28aaSamw 512da6c28aaSamw return (0); 513da6c28aaSamw } 514da6c28aaSamw 515da6c28aaSamw /* 516da6c28aaSamw * lsa_list_accounts 517da6c28aaSamw * 518da6c28aaSamw * This function can be used to list the accounts in the specified 519da6c28aaSamw * domain. For now the SIDs are just listed in the system log. 520da6c28aaSamw * 521da6c28aaSamw * On success 0 is returned. Otherwise a -ve error code. 522da6c28aaSamw */ 523da6c28aaSamw static int 524da6c28aaSamw lsa_list_accounts(mlsvc_handle_t *domain_handle) 525da6c28aaSamw { 526da6c28aaSamw mlsvc_handle_t account_handle; 527da6c28aaSamw struct mslsa_EnumAccountBuf accounts; 528da6c28aaSamw struct mslsa_sid *sid; 529da6c28aaSamw char *name; 530da6c28aaSamw WORD sid_name_use; 531da6c28aaSamw smb_userinfo_t *user_info; 532da6c28aaSamw DWORD enum_context = 0; 533da6c28aaSamw int rc; 534da6c28aaSamw int i; 535da6c28aaSamw 536da6c28aaSamw user_info = mlsvc_alloc_user_info(); 537da6c28aaSamw bzero(&accounts, sizeof (struct mslsa_EnumAccountBuf)); 538da6c28aaSamw 539da6c28aaSamw do { 540da6c28aaSamw rc = lsar_enum_accounts(domain_handle, &enum_context, 541da6c28aaSamw &accounts); 542da6c28aaSamw if (rc != 0) 543da6c28aaSamw return (rc); 544da6c28aaSamw 545da6c28aaSamw for (i = 0; i < accounts.entries_read; ++i) { 546da6c28aaSamw sid = accounts.info[i].sid; 547da6c28aaSamw 548da6c28aaSamw name = nt_builtin_lookup_sid((nt_sid_t *)sid, 549da6c28aaSamw &sid_name_use); 550da6c28aaSamw 551da6c28aaSamw if (name == 0) { 552da6c28aaSamw if (lsar_lookup_sids(domain_handle, sid, 553da6c28aaSamw user_info) == 0) { 554da6c28aaSamw name = user_info->name; 555da6c28aaSamw sid_name_use = user_info->sid_name_use; 556da6c28aaSamw } else { 557da6c28aaSamw name = "unknown"; 558da6c28aaSamw sid_name_use = SidTypeUnknown; 559da6c28aaSamw } 560da6c28aaSamw } 561da6c28aaSamw 562da6c28aaSamw nt_sid_logf((nt_sid_t *)sid); 563da6c28aaSamw 564da6c28aaSamw if (lsar_open_account(domain_handle, sid, 565da6c28aaSamw &account_handle) == 0) { 566da6c28aaSamw (void) lsar_enum_privs_account(&account_handle, 567da6c28aaSamw user_info); 568da6c28aaSamw (void) lsar_close(&account_handle); 569da6c28aaSamw } 570da6c28aaSamw 571da6c28aaSamw free(accounts.info[i].sid); 572da6c28aaSamw mlsvc_release_user_info(user_info); 573da6c28aaSamw } 574da6c28aaSamw 575da6c28aaSamw if (accounts.info) 576da6c28aaSamw free(accounts.info); 577da6c28aaSamw } while (rc == 0 && accounts.entries_read != 0); 578da6c28aaSamw 579da6c28aaSamw mlsvc_free_user_info(user_info); 580da6c28aaSamw return (0); 581da6c28aaSamw } 582*dc20a302Sas 583*dc20a302Sas /* 584*dc20a302Sas * lsa_lookup_name_lusr 585*dc20a302Sas * 586*dc20a302Sas * Obtains the SID for the given local user name if it 587*dc20a302Sas * can be found. Upon successful return the allocated memory 588*dc20a302Sas * for the returned SID must be freed by the caller. 589*dc20a302Sas * 590*dc20a302Sas * Note that in domain mode this function might actually return 591*dc20a302Sas * a domain SID if local users are mapped to domain users. 592*dc20a302Sas */ 593*dc20a302Sas static uint32_t 594*dc20a302Sas lsa_lookup_name_lusr(char *name, nt_sid_t **sid) 595*dc20a302Sas { 596*dc20a302Sas struct passwd *pw; 597*dc20a302Sas 598*dc20a302Sas if ((pw = getpwnam(name)) == NULL) 599*dc20a302Sas return (NT_STATUS_NO_SUCH_USER); 600*dc20a302Sas 601*dc20a302Sas if (smb_idmap_getsid(pw->pw_uid, SMB_IDMAP_USER, sid) != IDMAP_SUCCESS) 602*dc20a302Sas return (NT_STATUS_NONE_MAPPED); 603*dc20a302Sas 604*dc20a302Sas return (NT_STATUS_SUCCESS); 605*dc20a302Sas } 606*dc20a302Sas 607*dc20a302Sas /* 608*dc20a302Sas * lsa_lookup_name_lgrp 609*dc20a302Sas * 610*dc20a302Sas * Obtains the SID for the given local group name if it 611*dc20a302Sas * can be found. Upon successful return the allocated memory 612*dc20a302Sas * for the returned SID must be freed by the caller. 613*dc20a302Sas * 614*dc20a302Sas * Note that in domain mode this function might actually return 615*dc20a302Sas * a domain SID if local groups are mapped to domain groups. 616*dc20a302Sas */ 617*dc20a302Sas static uint32_t 618*dc20a302Sas lsa_lookup_name_lgrp(char *name, nt_sid_t **sid) 619*dc20a302Sas { 620*dc20a302Sas struct group *gr; 621*dc20a302Sas 622*dc20a302Sas if ((gr = getgrnam(name)) == NULL) 623*dc20a302Sas return (NT_STATUS_NO_SUCH_ALIAS); 624*dc20a302Sas 625*dc20a302Sas if (smb_idmap_getsid(gr->gr_gid, SMB_IDMAP_GROUP, sid) != IDMAP_SUCCESS) 626*dc20a302Sas return (NT_STATUS_NONE_MAPPED); 627*dc20a302Sas 628*dc20a302Sas return (NT_STATUS_SUCCESS); 629*dc20a302Sas } 630*dc20a302Sas 631*dc20a302Sas static int 632*dc20a302Sas lsa_lookup_mode(const char *domain, const char *name) 633*dc20a302Sas { 634*dc20a302Sas int lookup_mode; 635*dc20a302Sas 636*dc20a302Sas if (nt_builtin_lookup((char *)name)) 637*dc20a302Sas return (MLSVC_LOOKUP_BUILTIN); 638*dc20a302Sas 639*dc20a302Sas if (smb_config_get_secmode() == SMB_SECMODE_WORKGRP) 640*dc20a302Sas return (MLSVC_LOOKUP_LOCAL); 641*dc20a302Sas 642*dc20a302Sas if ((domain == NULL) || (*domain == '\0')) 643*dc20a302Sas return (MLSVC_LOOKUP_DOMLOC); 644*dc20a302Sas 645*dc20a302Sas if (mlsvc_is_local_domain(domain) == 1) 646*dc20a302Sas lookup_mode = MLSVC_LOOKUP_LOCAL; 647*dc20a302Sas else 648*dc20a302Sas lookup_mode = MLSVC_LOOKUP_DOMAIN; 649*dc20a302Sas 650*dc20a302Sas return (lookup_mode); 651*dc20a302Sas } 652*dc20a302Sas 653*dc20a302Sas static uint32_t 654*dc20a302Sas lsa_lookup_sid_local(nt_sid_t *sid, smb_userinfo_t *ainfo) 655*dc20a302Sas { 656*dc20a302Sas char hostname[MAXHOSTNAMELEN]; 657*dc20a302Sas struct passwd *pw; 658*dc20a302Sas struct group *gr; 659*dc20a302Sas uid_t id; 660*dc20a302Sas int id_type; 661*dc20a302Sas 662*dc20a302Sas id_type = SMB_IDMAP_UNKNOWN; 663*dc20a302Sas if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS) 664*dc20a302Sas return (NT_STATUS_NONE_MAPPED); 665*dc20a302Sas 666*dc20a302Sas switch (id_type) { 667*dc20a302Sas case SMB_IDMAP_USER: 668*dc20a302Sas ainfo->sid_name_use = SidTypeUser; 669*dc20a302Sas if ((pw = getpwuid(id)) == NULL) 670*dc20a302Sas return (NT_STATUS_NO_SUCH_USER); 671*dc20a302Sas 672*dc20a302Sas ainfo->name = strdup(pw->pw_name); 673*dc20a302Sas break; 674*dc20a302Sas 675*dc20a302Sas case SMB_IDMAP_GROUP: 676*dc20a302Sas ainfo->sid_name_use = SidTypeAlias; 677*dc20a302Sas if ((gr = getgrgid(id)) == NULL) 678*dc20a302Sas return (NT_STATUS_NO_SUCH_ALIAS); 679*dc20a302Sas 680*dc20a302Sas ainfo->name = strdup(gr->gr_name); 681*dc20a302Sas break; 682*dc20a302Sas 683*dc20a302Sas default: 684*dc20a302Sas return (NT_STATUS_NONE_MAPPED); 685*dc20a302Sas } 686*dc20a302Sas 687*dc20a302Sas if (ainfo->name == NULL) 688*dc20a302Sas return (NT_STATUS_NO_MEMORY); 689*dc20a302Sas 690*dc20a302Sas ainfo->domain_sid = nt_sid_dup(sid); 691*dc20a302Sas if (nt_sid_split(ainfo->domain_sid, &ainfo->rid) < 0) 692*dc20a302Sas return (NT_STATUS_INTERNAL_ERROR); 693*dc20a302Sas *hostname = '\0'; 694*dc20a302Sas (void) smb_getnetbiosname(hostname, MAXHOSTNAMELEN); 695*dc20a302Sas if ((ainfo->domain_name = strdup(hostname)) == NULL) 696*dc20a302Sas return (NT_STATUS_NO_MEMORY); 697*dc20a302Sas 698*dc20a302Sas return (NT_STATUS_SUCCESS); 699*dc20a302Sas } 700*dc20a302Sas 701*dc20a302Sas static uint32_t 702*dc20a302Sas lsa_lookup_sid_builtin(nt_sid_t *sid, smb_userinfo_t *ainfo) 703*dc20a302Sas { 704*dc20a302Sas char *name; 705*dc20a302Sas WORD sid_name_use; 706*dc20a302Sas 707*dc20a302Sas if ((name = nt_builtin_lookup_sid(sid, &sid_name_use)) == NULL) 708*dc20a302Sas return (NT_STATUS_NONE_MAPPED); 709*dc20a302Sas 710*dc20a302Sas ainfo->sid_name_use = sid_name_use; 711*dc20a302Sas ainfo->name = strdup(name); 712*dc20a302Sas ainfo->domain_sid = nt_sid_dup(sid); 713*dc20a302Sas 714*dc20a302Sas if (ainfo->name == NULL || ainfo->domain_sid == NULL) 715*dc20a302Sas return (NT_STATUS_NO_MEMORY); 716*dc20a302Sas 717*dc20a302Sas if (sid_name_use != SidTypeDomain) 718*dc20a302Sas (void) nt_sid_split(ainfo->domain_sid, &ainfo->rid); 719*dc20a302Sas 720*dc20a302Sas if ((name = nt_builtin_lookup_domain(ainfo->name)) != NULL) 721*dc20a302Sas ainfo->domain_name = strdup(name); 722*dc20a302Sas else 723*dc20a302Sas ainfo->domain_name = strdup("UNKNOWN"); 724*dc20a302Sas 725*dc20a302Sas if (ainfo->domain_name == NULL) 726*dc20a302Sas return (NT_STATUS_NO_MEMORY); 727*dc20a302Sas 728*dc20a302Sas return (NT_STATUS_SUCCESS); 729*dc20a302Sas } 730*dc20a302Sas 731*dc20a302Sas static uint32_t 732*dc20a302Sas lsa_lookup_sid_domain(nt_sid_t *sid, smb_userinfo_t *ainfo) 733*dc20a302Sas { 734*dc20a302Sas mlsvc_handle_t domain_handle; 735*dc20a302Sas char *user = smbrdr_ipc_get_user(); 736*dc20a302Sas uint32_t status; 737*dc20a302Sas 738*dc20a302Sas if (lsar_open(NULL, NULL, user, &domain_handle) != 0) 739*dc20a302Sas return (NT_STATUS_INVALID_PARAMETER); 740*dc20a302Sas 741*dc20a302Sas status = lsar_lookup_sids2(&domain_handle, 742*dc20a302Sas (struct mslsa_sid *)sid, ainfo); 743*dc20a302Sas 744*dc20a302Sas if (status == NT_STATUS_REVISION_MISMATCH) { 745*dc20a302Sas /* 746*dc20a302Sas * Not a Windows 2000 domain controller: 747*dc20a302Sas * use the NT compatible call. 748*dc20a302Sas */ 749*dc20a302Sas status = lsar_lookup_sids(&domain_handle, 750*dc20a302Sas (struct mslsa_sid *)sid, ainfo); 751*dc20a302Sas } 752*dc20a302Sas 753*dc20a302Sas (void) lsar_close(&domain_handle); 754*dc20a302Sas return (status); 755*dc20a302Sas } 756