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 /* 22dc20a302Sas * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * This module provides the high level interface to the LSA RPC functions. 28da6c28aaSamw */ 29da6c28aaSamw 30da6c28aaSamw #include <strings.h> 31da6c28aaSamw #include <unistd.h> 32da6c28aaSamw #include <netdb.h> 33dc20a302Sas #include <pwd.h> 34dc20a302Sas #include <grp.h> 35da6c28aaSamw 36da6c28aaSamw #include <smbsrv/libsmb.h> 37da6c28aaSamw #include <smbsrv/libsmbns.h> 38da6c28aaSamw #include <smbsrv/libmlsvc.h> 3955bf511dSas #include <smbsrv/libsmbrdr.h> 40*8d7e4166Sjose borrego #include <lsalib.h> 41da6c28aaSamw #include <smbsrv/ntstatus.h> 42da6c28aaSamw #include <smbsrv/smbinfo.h> 43da6c28aaSamw #include <smbsrv/smb_token.h> 44da6c28aaSamw 45dc20a302Sas /* 46dc20a302Sas * Name Lookup modes 47dc20a302Sas */ 48dc20a302Sas #define MLSVC_LOOKUP_BUILTIN 1 49dc20a302Sas #define MLSVC_LOOKUP_LOCAL 2 50dc20a302Sas #define MLSVC_LOOKUP_DOMAIN 3 51dc20a302Sas #define MLSVC_LOOKUP_DOMLOC 4 52dc20a302Sas 53dc20a302Sas static int lsa_lookup_mode(const char *, const char *); 54dc20a302Sas static uint32_t lsa_lookup_name_builtin(char *, smb_userinfo_t *); 55dc20a302Sas static uint32_t lsa_lookup_name_local(char *, char *, uint16_t, 56dc20a302Sas smb_userinfo_t *); 576537f381Sas static uint32_t lsa_lookup_name_lusr(char *, smb_sid_t **); 586537f381Sas static uint32_t lsa_lookup_name_lgrp(char *, smb_sid_t **); 59dc20a302Sas static uint32_t lsa_lookup_name_domain(char *, char *, char *, 60dc20a302Sas smb_userinfo_t *); 61dc20a302Sas 626537f381Sas static uint32_t lsa_lookup_sid_builtin(smb_sid_t *, smb_userinfo_t *); 636537f381Sas static uint32_t lsa_lookup_sid_local(smb_sid_t *, smb_userinfo_t *); 646537f381Sas static uint32_t lsa_lookup_sid_domain(smb_sid_t *, smb_userinfo_t *); 65dc20a302Sas 66da6c28aaSamw static int lsa_list_accounts(mlsvc_handle_t *); 67da6c28aaSamw 68dc20a302Sas /* 69dc20a302Sas * lsa_lookup_name 70dc20a302Sas * 71dc20a302Sas * Lookup the given account and returns the account information 72dc20a302Sas * in 'ainfo' 73dc20a302Sas * 74dc20a302Sas * If the name is a domain account, it may refer to a user, group or 75dc20a302Sas * alias. If it is a local account, its type should be specified 76dc20a302Sas * in the sid_type parameter. In case the account type is unknown 77dc20a302Sas * sid_type should be set to SidTypeUnknown. 78dc20a302Sas * 79dc20a302Sas * account argument could be either [domain\\]name or [domain/]name. 80dc20a302Sas * If domain is not specified and service is in domain mode then it 81dc20a302Sas * first does a domain lookup and then a local lookup. 82dc20a302Sas */ 83dc20a302Sas uint32_t 84*8d7e4166Sjose borrego lsa_lookup_name(char *account, uint16_t sid_type, 85dc20a302Sas smb_userinfo_t *ainfo) 86dc20a302Sas { 87dc20a302Sas int lookup_mode; 88dc20a302Sas char *name; 89dc20a302Sas char *domain; 90dc20a302Sas uint32_t status = NT_STATUS_NONE_MAPPED; 91*8d7e4166Sjose borrego smb_domain_t dinfo; 92dc20a302Sas 93dc20a302Sas (void) strsubst(account, '\\', '/'); 94dc20a302Sas name = strchr(account, '/'); 95dc20a302Sas if (name) { 96dc20a302Sas /* domain is specified */ 97dc20a302Sas *name++ = '\0'; 98dc20a302Sas domain = account; 99dc20a302Sas } else { 100dc20a302Sas name = account; 101dc20a302Sas domain = NULL; 102dc20a302Sas } 103dc20a302Sas 104dc20a302Sas lookup_mode = lsa_lookup_mode(domain, name); 105dc20a302Sas 106dc20a302Sas switch (lookup_mode) { 107dc20a302Sas case MLSVC_LOOKUP_BUILTIN: 108dc20a302Sas return (lsa_lookup_name_builtin(name, ainfo)); 109dc20a302Sas 110dc20a302Sas case MLSVC_LOOKUP_LOCAL: 111dc20a302Sas return (lsa_lookup_name_local(domain, name, sid_type, ainfo)); 112dc20a302Sas 113dc20a302Sas case MLSVC_LOOKUP_DOMAIN: 114*8d7e4166Sjose borrego if (!smb_domain_getinfo(&dinfo)) 115*8d7e4166Sjose borrego return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 116*8d7e4166Sjose borrego 117*8d7e4166Sjose borrego return (lsa_lookup_name_domain(dinfo.d_dc, dinfo.d_nbdomain, 118*8d7e4166Sjose borrego name, ainfo)); 119dc20a302Sas 120dc20a302Sas default: 121dc20a302Sas /* lookup the name in domain */ 122*8d7e4166Sjose borrego if (!smb_domain_getinfo(&dinfo)) 123*8d7e4166Sjose borrego return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 124*8d7e4166Sjose borrego 125*8d7e4166Sjose borrego status = lsa_lookup_name_domain(dinfo.d_dc, dinfo.d_nbdomain, 126*8d7e4166Sjose borrego name, ainfo); 127*8d7e4166Sjose borrego 128dc20a302Sas if (status != NT_STATUS_NONE_MAPPED) 129dc20a302Sas return (status); 130dc20a302Sas 131dc20a302Sas mlsvc_release_user_info(ainfo); 132dc20a302Sas /* lookup the name locally */ 133dc20a302Sas status = lsa_lookup_name_local(domain, name, sid_type, ainfo); 134dc20a302Sas } 135dc20a302Sas 136dc20a302Sas return (status); 137dc20a302Sas } 138dc20a302Sas 139dc20a302Sas uint32_t 1406537f381Sas lsa_lookup_sid(smb_sid_t *sid, smb_userinfo_t *ainfo) 141dc20a302Sas { 1426537f381Sas if (!smb_sid_isvalid(sid)) 143dc20a302Sas return (NT_STATUS_INVALID_SID); 144dc20a302Sas 1456537f381Sas if (smb_sid_islocal(sid)) 146dc20a302Sas return (lsa_lookup_sid_local(sid, ainfo)); 147dc20a302Sas 1486537f381Sas if (smb_wka_lookup_sid(sid, NULL)) 149dc20a302Sas return (lsa_lookup_sid_builtin(sid, ainfo)); 150dc20a302Sas 151dc20a302Sas return (lsa_lookup_sid_domain(sid, ainfo)); 152dc20a302Sas } 153dc20a302Sas 154da6c28aaSamw /* 155da6c28aaSamw * lsa_query_primary_domain_info 156da6c28aaSamw * 157da6c28aaSamw * Obtains the primary domain SID and name from the specified server 158da6c28aaSamw * (domain controller). The information is stored in the NT domain 159da6c28aaSamw * database by the lower level lsar_query_info_policy call. The caller 160da6c28aaSamw * should query the database to obtain a reference to the primary 161da6c28aaSamw * domain information. 162da6c28aaSamw * 163*8d7e4166Sjose borrego * The requested information will be returned via 'info' argument. 164*8d7e4166Sjose borrego * Caller must call lsa_free_info() when done. 165*8d7e4166Sjose borrego * 166da6c28aaSamw * Returns NT status codes. 167da6c28aaSamw */ 168da6c28aaSamw DWORD 169*8d7e4166Sjose borrego lsa_query_primary_domain_info(char *server, char *domain, lsa_info_t *info) 170da6c28aaSamw { 171da6c28aaSamw mlsvc_handle_t domain_handle; 172da6c28aaSamw DWORD status; 17355bf511dSas char *user = smbrdr_ipc_get_user(); 174da6c28aaSamw 175*8d7e4166Sjose borrego if ((lsar_open(server, domain, user, &domain_handle)) != 0) 176da6c28aaSamw return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 177da6c28aaSamw 178da6c28aaSamw status = lsar_query_info_policy(&domain_handle, 179*8d7e4166Sjose borrego MSLSA_POLICY_PRIMARY_DOMAIN_INFO, info); 180da6c28aaSamw 181da6c28aaSamw (void) lsar_close(&domain_handle); 182da6c28aaSamw return (status); 183da6c28aaSamw } 184da6c28aaSamw 185da6c28aaSamw /* 186da6c28aaSamw * lsa_query_account_domain_info 187da6c28aaSamw * 188da6c28aaSamw * Obtains the account domain SID and name from the current server 189da6c28aaSamw * (domain controller). The information is stored in the NT domain 190da6c28aaSamw * database by the lower level lsar_query_info_policy call. The caller 191da6c28aaSamw * should query the database to obtain a reference to the account 192da6c28aaSamw * domain information. 193da6c28aaSamw * 194*8d7e4166Sjose borrego * The requested information will be returned via 'info' argument. 195*8d7e4166Sjose borrego * Caller must invoke lsa_free_info() to when done. 196*8d7e4166Sjose borrego * 197da6c28aaSamw * Returns NT status codes. 198da6c28aaSamw */ 199da6c28aaSamw DWORD 200*8d7e4166Sjose borrego lsa_query_account_domain_info(char *server, char *domain, lsa_info_t *info) 201da6c28aaSamw { 202da6c28aaSamw mlsvc_handle_t domain_handle; 203da6c28aaSamw DWORD status; 20455bf511dSas char *user = smbrdr_ipc_get_user(); 205da6c28aaSamw 206*8d7e4166Sjose borrego if ((lsar_open(server, domain, user, &domain_handle)) != 0) 207da6c28aaSamw return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 208da6c28aaSamw 209da6c28aaSamw status = lsar_query_info_policy(&domain_handle, 210*8d7e4166Sjose borrego MSLSA_POLICY_ACCOUNT_DOMAIN_INFO, info); 211*8d7e4166Sjose borrego 212*8d7e4166Sjose borrego (void) lsar_close(&domain_handle); 213*8d7e4166Sjose borrego return (status); 214*8d7e4166Sjose borrego } 215*8d7e4166Sjose borrego 216*8d7e4166Sjose borrego /* 217*8d7e4166Sjose borrego * lsa_query_dns_domain_info 218*8d7e4166Sjose borrego * 219*8d7e4166Sjose borrego * Obtains the DNS domain info from the specified server 220*8d7e4166Sjose borrego * (domain controller). 221*8d7e4166Sjose borrego * 222*8d7e4166Sjose borrego * The requested information will be returned via 'info' argument. 223*8d7e4166Sjose borrego * Caller must call lsa_free_info() when done. 224*8d7e4166Sjose borrego * 225*8d7e4166Sjose borrego * Returns NT status codes. 226*8d7e4166Sjose borrego */ 227*8d7e4166Sjose borrego DWORD 228*8d7e4166Sjose borrego lsa_query_dns_domain_info(char *server, char *domain, lsa_info_t *info) 229*8d7e4166Sjose borrego { 230*8d7e4166Sjose borrego mlsvc_handle_t domain_handle; 231*8d7e4166Sjose borrego DWORD status; 232*8d7e4166Sjose borrego char *user = smbrdr_ipc_get_user(); 233*8d7e4166Sjose borrego 234*8d7e4166Sjose borrego if ((lsar_open(server, domain, user, &domain_handle)) != 0) 235*8d7e4166Sjose borrego return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 236*8d7e4166Sjose borrego 237*8d7e4166Sjose borrego status = lsar_query_info_policy(&domain_handle, 238*8d7e4166Sjose borrego MSLSA_POLICY_DNS_DOMAIN_INFO, info); 239da6c28aaSamw 240da6c28aaSamw (void) lsar_close(&domain_handle); 241da6c28aaSamw return (status); 242da6c28aaSamw } 243da6c28aaSamw 244da6c28aaSamw /* 245da6c28aaSamw * lsa_enum_trusted_domains 246da6c28aaSamw * 247da6c28aaSamw * Enumerate the trusted domains in our primary domain. The information 248da6c28aaSamw * is stored in the NT domain database by the lower level 249da6c28aaSamw * lsar_enum_trusted_domains call. The caller should query the database 250da6c28aaSamw * to obtain a reference to the trusted domain information. 251da6c28aaSamw * 252*8d7e4166Sjose borrego * The requested information will be returned via 'info' argument. 253*8d7e4166Sjose borrego * Caller must call lsa_free_info() when done. 254*8d7e4166Sjose borrego * 255da6c28aaSamw * Returns NT status codes. 256da6c28aaSamw */ 257da6c28aaSamw DWORD 258*8d7e4166Sjose borrego lsa_enum_trusted_domains(char *server, char *domain, lsa_info_t *info) 259da6c28aaSamw { 260da6c28aaSamw mlsvc_handle_t domain_handle; 261da6c28aaSamw DWORD enum_context; 262da6c28aaSamw DWORD status; 26355bf511dSas char *user = smbrdr_ipc_get_user(); 264da6c28aaSamw 265*8d7e4166Sjose borrego if ((lsar_open(server, domain, user, &domain_handle)) != 0) 266da6c28aaSamw return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 267da6c28aaSamw 268da6c28aaSamw enum_context = 0; 269da6c28aaSamw 270*8d7e4166Sjose borrego status = lsar_enum_trusted_domains(&domain_handle, &enum_context, info); 271da6c28aaSamw if (status == MLSVC_NO_MORE_DATA) { 272da6c28aaSamw /* 273da6c28aaSamw * MLSVC_NO_MORE_DATA indicates that we 274da6c28aaSamw * have all of the available information. 275da6c28aaSamw */ 276da6c28aaSamw status = NT_STATUS_SUCCESS; 277da6c28aaSamw } 278da6c28aaSamw 279da6c28aaSamw (void) lsar_close(&domain_handle); 280da6c28aaSamw return (status); 281da6c28aaSamw } 282da6c28aaSamw 283*8d7e4166Sjose borrego /* 284*8d7e4166Sjose borrego * lsa_free_info 285*8d7e4166Sjose borrego */ 286*8d7e4166Sjose borrego void 287*8d7e4166Sjose borrego lsa_free_info(lsa_info_t *info) 288*8d7e4166Sjose borrego { 289*8d7e4166Sjose borrego lsa_trusted_domainlist_t *list; 290*8d7e4166Sjose borrego int i; 291*8d7e4166Sjose borrego 292*8d7e4166Sjose borrego if (!info) 293*8d7e4166Sjose borrego return; 294*8d7e4166Sjose borrego 295*8d7e4166Sjose borrego switch (info->i_type) { 296*8d7e4166Sjose borrego case LSA_INFO_PRIMARY_DOMAIN: 297*8d7e4166Sjose borrego smb_sid_free(info->i_domain.di_primary.n_sid); 298*8d7e4166Sjose borrego break; 299*8d7e4166Sjose borrego 300*8d7e4166Sjose borrego case LSA_INFO_ACCOUNT_DOMAIN: 301*8d7e4166Sjose borrego smb_sid_free(info->i_domain.di_account.n_sid); 302*8d7e4166Sjose borrego break; 303*8d7e4166Sjose borrego 304*8d7e4166Sjose borrego case LSA_INFO_DNS_DOMAIN: 305*8d7e4166Sjose borrego smb_sid_free(info->i_domain.di_dns.d_sid); 306*8d7e4166Sjose borrego break; 307*8d7e4166Sjose borrego 308*8d7e4166Sjose borrego case LSA_INFO_TRUSTED_DOMAINS: 309*8d7e4166Sjose borrego list = &info->i_domain.di_trust; 310*8d7e4166Sjose borrego for (i = 0; i < list->t_num; i++) 311*8d7e4166Sjose borrego smb_sid_free(list->t_domains[i].n_sid); 312*8d7e4166Sjose borrego free(list->t_domains); 313*8d7e4166Sjose borrego break; 314*8d7e4166Sjose borrego 315*8d7e4166Sjose borrego case LSA_INFO_NONE: 316*8d7e4166Sjose borrego break; 317*8d7e4166Sjose borrego } 318*8d7e4166Sjose borrego } 319*8d7e4166Sjose borrego 320da6c28aaSamw /* 321dc20a302Sas * lsa_lookup_name_builtin 322da6c28aaSamw * 323da6c28aaSamw * lookup builtin account table to see if account_name is 324da6c28aaSamw * there. If it is there, set sid_name_use, domain_sid, 325da6c28aaSamw * domain_name, and rid fields of the passed user_info 326dc20a302Sas * structure. 327da6c28aaSamw */ 328dc20a302Sas static uint32_t 329dc20a302Sas lsa_lookup_name_builtin(char *account_name, smb_userinfo_t *user_info) 330da6c28aaSamw { 331da6c28aaSamw char *domain; 332da6c28aaSamw int res; 333da6c28aaSamw 3346537f381Sas user_info->user_sid = smb_wka_lookup_name(account_name, 335da6c28aaSamw &user_info->sid_name_use); 336da6c28aaSamw 337dc20a302Sas if (user_info->user_sid == NULL) 338dc20a302Sas return (NT_STATUS_NONE_MAPPED); 339da6c28aaSamw 3406537f381Sas user_info->domain_sid = smb_sid_dup(user_info->user_sid); 3416537f381Sas res = smb_sid_split(user_info->domain_sid, &user_info->rid); 342da6c28aaSamw if (res < 0) 343dc20a302Sas return (NT_STATUS_INTERNAL_ERROR); 344da6c28aaSamw 3456537f381Sas domain = smb_wka_lookup_domain(account_name); 346da6c28aaSamw if (domain) { 347da6c28aaSamw user_info->domain_name = strdup(domain); 348dc20a302Sas return (NT_STATUS_SUCCESS); 349da6c28aaSamw } 350da6c28aaSamw 351dc20a302Sas return (NT_STATUS_INTERNAL_ERROR); 352da6c28aaSamw } 353da6c28aaSamw 354da6c28aaSamw /* 355dc20a302Sas * lsa_lookup_name_local 356da6c28aaSamw * 357dc20a302Sas * Obtains the infomation for the given local account name if it 358dc20a302Sas * can be found. The type of account is specified by sid_type, 359dc20a302Sas * which can be of user, group or unknown type. If the caller 360dc20a302Sas * doesn't know whether the name is a user or group name then 361dc20a302Sas * SidTypeUnknown should be passed, in which case this 362dc20a302Sas * function first tries to find a user and then a group match. 363da6c28aaSamw * 364dc20a302Sas * CAVEAT: if there are both a user and a group account with 365dc20a302Sas * the same name, user SID will always be returned. 366da6c28aaSamw */ 367dc20a302Sas static uint32_t 368dc20a302Sas lsa_lookup_name_local(char *domain, char *name, uint16_t sid_type, 369dc20a302Sas smb_userinfo_t *ainfo) 370da6c28aaSamw { 371da6c28aaSamw char hostname[MAXHOSTNAMELEN]; 3726537f381Sas smb_sid_t *sid; 373dc20a302Sas uint32_t status; 374dc20a302Sas 375dc20a302Sas switch (sid_type) { 376dc20a302Sas case SidTypeUser: 377dc20a302Sas status = lsa_lookup_name_lusr(name, &sid); 378dc20a302Sas if (status != NT_STATUS_SUCCESS) 379dc20a302Sas return (status); 380dc20a302Sas break; 381dc20a302Sas 382dc20a302Sas case SidTypeGroup: 383dc20a302Sas case SidTypeAlias: 384dc20a302Sas status = lsa_lookup_name_lgrp(name, &sid); 385dc20a302Sas if (status != NT_STATUS_SUCCESS) 386dc20a302Sas return (status); 387dc20a302Sas break; 388dc20a302Sas 389dc20a302Sas case SidTypeUnknown: 390dc20a302Sas sid_type = SidTypeUser; 391dc20a302Sas status = lsa_lookup_name_lusr(name, &sid); 392dc20a302Sas if (status == NT_STATUS_SUCCESS) 393dc20a302Sas break; 394dc20a302Sas 395dc20a302Sas if (status == NT_STATUS_NONE_MAPPED) 396dc20a302Sas return (status); 397dc20a302Sas 398dc20a302Sas sid_type = SidTypeAlias; 399dc20a302Sas status = lsa_lookup_name_lgrp(name, &sid); 400dc20a302Sas if (status != NT_STATUS_SUCCESS) 401dc20a302Sas return (status); 402dc20a302Sas break; 403dc20a302Sas 404dc20a302Sas default: 405dc20a302Sas return (NT_STATUS_INVALID_PARAMETER); 406da6c28aaSamw } 407da6c28aaSamw 408dc20a302Sas ainfo->sid_name_use = sid_type; 409dc20a302Sas ainfo->user_sid = sid; 4106537f381Sas ainfo->domain_sid = smb_sid_dup(sid); 411dc20a302Sas if (ainfo->domain_sid == NULL) 412dc20a302Sas return (NT_STATUS_NO_MEMORY); 413dc20a302Sas 4146537f381Sas (void) smb_sid_split(ainfo->domain_sid, &ainfo->rid); 415dc20a302Sas if ((domain == NULL) || (*domain == '\0')) { 416dc20a302Sas (void) smb_getnetbiosname(hostname, sizeof (hostname)); 417dc20a302Sas ainfo->domain_name = strdup(hostname); 418dc20a302Sas } else { 419dc20a302Sas ainfo->domain_name = strdup(domain); 420dc20a302Sas } 421da6c28aaSamw 422dc20a302Sas if (ainfo->domain_name == NULL) 423dc20a302Sas return (NT_STATUS_NO_MEMORY); 424da6c28aaSamw 425dc20a302Sas return (NT_STATUS_SUCCESS); 426da6c28aaSamw } 427da6c28aaSamw 428da6c28aaSamw /* 429dc20a302Sas * lsa_lookup_name_domain 430da6c28aaSamw * 431da6c28aaSamw * Lookup a name on the specified server (domain controller) and obtain 432da6c28aaSamw * the appropriate SID. The information is returned in the user_info 433da6c28aaSamw * structure. The caller is responsible for allocating and releasing 434da6c28aaSamw * this structure. On success sid_name_use will be set to indicate the 435da6c28aaSamw * type of SID. If the name is the domain name, this function will be 436da6c28aaSamw * identical to lsa_domain_info. Otherwise the rid and name fields will 437da6c28aaSamw * also be valid. On failure sid_name_use will be set to SidTypeUnknown. 438da6c28aaSamw */ 439dc20a302Sas static uint32_t 440dc20a302Sas lsa_lookup_name_domain(char *server, char *domain, char *account_name, 441da6c28aaSamw smb_userinfo_t *user_info) 442da6c28aaSamw { 443da6c28aaSamw mlsvc_handle_t domain_handle; 44455bf511dSas char *user = smbrdr_ipc_get_user(); 445dc20a302Sas uint32_t status; 446da6c28aaSamw 447dc20a302Sas if (lsar_open(server, domain, user, &domain_handle) != 0) 448da6c28aaSamw return (NT_STATUS_INVALID_PARAMETER); 449da6c28aaSamw 450da6c28aaSamw status = lsar_lookup_names2(&domain_handle, account_name, user_info); 451da6c28aaSamw if (status == NT_STATUS_REVISION_MISMATCH) { 452da6c28aaSamw /* 453da6c28aaSamw * Not a Windows 2000 domain controller: 454da6c28aaSamw * use the NT compatible call. 455da6c28aaSamw */ 456dc20a302Sas status = lsar_lookup_names(&domain_handle, account_name, 457dc20a302Sas user_info); 458da6c28aaSamw } 459da6c28aaSamw 460da6c28aaSamw (void) lsar_close(&domain_handle); 461da6c28aaSamw return (status); 462da6c28aaSamw } 463da6c28aaSamw 464da6c28aaSamw /* 465dc20a302Sas * lsa_test_lookup 466da6c28aaSamw * 467dc20a302Sas * Test routine for lsa_lookup_name_domain and lsa_lookup_sid2. 468da6c28aaSamw */ 469da6c28aaSamw void 470dc20a302Sas lsa_test_lookup(char *name) 471da6c28aaSamw { 472da6c28aaSamw smb_userinfo_t *user_info; 4736537f381Sas smb_sid_t *sid; 474da6c28aaSamw DWORD status; 475*8d7e4166Sjose borrego smb_domain_t di; 476da6c28aaSamw 477*8d7e4166Sjose borrego if (!smb_domain_getinfo(&di)) 478da6c28aaSamw return; 479da6c28aaSamw 480da6c28aaSamw user_info = mlsvc_alloc_user_info(); 481da6c28aaSamw 482dc20a302Sas if (lsa_lookup_name_builtin(name, user_info) != 0) { 483*8d7e4166Sjose borrego status = lsa_lookup_name_domain(di.d_dc, di.d_nbdomain, name, 484da6c28aaSamw user_info); 485da6c28aaSamw 486da6c28aaSamw if (status == 0) { 4876537f381Sas sid = smb_sid_splice(user_info->domain_sid, 488da6c28aaSamw user_info->rid); 489da6c28aaSamw 490dc20a302Sas (void) lsa_lookup_sid_domain(sid, user_info); 491da6c28aaSamw free(sid); 492da6c28aaSamw } 493da6c28aaSamw } 494da6c28aaSamw 495da6c28aaSamw mlsvc_free_user_info(user_info); 496da6c28aaSamw } 497da6c28aaSamw 498da6c28aaSamw /* 499da6c28aaSamw * lsa_lookup_privs 500da6c28aaSamw * 501da6c28aaSamw * Request the privileges associated with the specified account. In 502da6c28aaSamw * order to get the privileges, we first have to lookup the name on 503da6c28aaSamw * the specified domain controller and obtain the appropriate SID. 504da6c28aaSamw * The SID can then be used to open the account and obtain the 505da6c28aaSamw * account privileges. The results from both the name lookup and the 506da6c28aaSamw * privileges are returned in the user_info structure. The caller is 507da6c28aaSamw * responsible for allocating and releasing this structure. 508da6c28aaSamw * 509da6c28aaSamw * On success 0 is returned. Otherwise a -ve error code. 510da6c28aaSamw */ 511da6c28aaSamw /*ARGSUSED*/ 512da6c28aaSamw int 513*8d7e4166Sjose borrego lsa_lookup_privs(char *account_name, char *target_name, 514da6c28aaSamw smb_userinfo_t *user_info) 515da6c28aaSamw { 516da6c28aaSamw mlsvc_handle_t domain_handle; 517da6c28aaSamw int rc; 51855bf511dSas char *user = smbrdr_ipc_get_user(); 519*8d7e4166Sjose borrego smb_domain_t dinfo; 520da6c28aaSamw 521*8d7e4166Sjose borrego if (!smb_domain_getinfo(&dinfo)) 522*8d7e4166Sjose borrego return (-1); 523*8d7e4166Sjose borrego 524*8d7e4166Sjose borrego if ((lsar_open(dinfo.d_dc, dinfo.d_nbdomain, user, 525*8d7e4166Sjose borrego &domain_handle)) != 0) 526da6c28aaSamw return (-1); 527da6c28aaSamw 528da6c28aaSamw rc = lsa_list_accounts(&domain_handle); 529da6c28aaSamw (void) lsar_close(&domain_handle); 530da6c28aaSamw return (rc); 531da6c28aaSamw } 532da6c28aaSamw 533da6c28aaSamw /* 534da6c28aaSamw * lsa_list_privs 535da6c28aaSamw * 536da6c28aaSamw * List the privileges supported by the specified server. 537da6c28aaSamw * This function is only intended for diagnostics. 538da6c28aaSamw * 539da6c28aaSamw * Returns NT status codes. 540da6c28aaSamw */ 541da6c28aaSamw DWORD 542da6c28aaSamw lsa_list_privs(char *server, char *domain) 543da6c28aaSamw { 544da6c28aaSamw static char name[128]; 545da6c28aaSamw static struct ms_luid luid; 546da6c28aaSamw mlsvc_handle_t domain_handle; 547da6c28aaSamw int rc; 548da6c28aaSamw int i; 54955bf511dSas char *user = smbrdr_ipc_get_user(); 550da6c28aaSamw 55155bf511dSas rc = lsar_open(server, domain, user, &domain_handle); 552da6c28aaSamw if (rc != 0) 553da6c28aaSamw return (NT_STATUS_INVALID_PARAMETER); 554da6c28aaSamw 555da6c28aaSamw for (i = 0; i < 30; ++i) { 556da6c28aaSamw luid.low_part = i; 557da6c28aaSamw rc = lsar_lookup_priv_name(&domain_handle, &luid, name, 128); 558da6c28aaSamw if (rc != 0) 559da6c28aaSamw continue; 560da6c28aaSamw 561da6c28aaSamw (void) lsar_lookup_priv_value(&domain_handle, name, &luid); 562da6c28aaSamw (void) lsar_lookup_priv_display_name(&domain_handle, name, 563da6c28aaSamw name, 128); 564da6c28aaSamw } 565da6c28aaSamw 566da6c28aaSamw (void) lsar_close(&domain_handle); 567da6c28aaSamw return (NT_STATUS_SUCCESS); 568da6c28aaSamw } 569da6c28aaSamw 570da6c28aaSamw /* 571da6c28aaSamw * lsa_test 572da6c28aaSamw * 573da6c28aaSamw * LSA test routine: open and close the LSA interface. 574da6c28aaSamw * 575da6c28aaSamw * On success 0 is returned. Otherwise a -ve error code. 576da6c28aaSamw */ 577da6c28aaSamw int 578*8d7e4166Sjose borrego lsa_test(char *server, char *domain) 579da6c28aaSamw { 580da6c28aaSamw mlsvc_handle_t domain_handle; 581da6c28aaSamw int rc; 58255bf511dSas char *user = smbrdr_ipc_get_user(); 583da6c28aaSamw 584*8d7e4166Sjose borrego rc = lsar_open(server, domain, user, &domain_handle); 585da6c28aaSamw if (rc != 0) 586da6c28aaSamw return (-1); 587da6c28aaSamw 588da6c28aaSamw if (lsar_close(&domain_handle) != 0) 589da6c28aaSamw return (-1); 590da6c28aaSamw 591da6c28aaSamw return (0); 592da6c28aaSamw } 593da6c28aaSamw 594da6c28aaSamw /* 595da6c28aaSamw * lsa_list_accounts 596da6c28aaSamw * 597da6c28aaSamw * This function can be used to list the accounts in the specified 598da6c28aaSamw * domain. For now the SIDs are just listed in the system log. 599da6c28aaSamw * 600da6c28aaSamw * On success 0 is returned. Otherwise a -ve error code. 601da6c28aaSamw */ 602da6c28aaSamw static int 603da6c28aaSamw lsa_list_accounts(mlsvc_handle_t *domain_handle) 604da6c28aaSamw { 605da6c28aaSamw mlsvc_handle_t account_handle; 606da6c28aaSamw struct mslsa_EnumAccountBuf accounts; 607da6c28aaSamw struct mslsa_sid *sid; 608da6c28aaSamw char *name; 609da6c28aaSamw WORD sid_name_use; 610da6c28aaSamw smb_userinfo_t *user_info; 611da6c28aaSamw DWORD enum_context = 0; 612da6c28aaSamw int rc; 613da6c28aaSamw int i; 614da6c28aaSamw 615da6c28aaSamw user_info = mlsvc_alloc_user_info(); 616da6c28aaSamw bzero(&accounts, sizeof (struct mslsa_EnumAccountBuf)); 617da6c28aaSamw 618da6c28aaSamw do { 619da6c28aaSamw rc = lsar_enum_accounts(domain_handle, &enum_context, 620da6c28aaSamw &accounts); 621da6c28aaSamw if (rc != 0) 622da6c28aaSamw return (rc); 623da6c28aaSamw 624da6c28aaSamw for (i = 0; i < accounts.entries_read; ++i) { 625da6c28aaSamw sid = accounts.info[i].sid; 626da6c28aaSamw 6276537f381Sas name = smb_wka_lookup_sid((smb_sid_t *)sid, 628da6c28aaSamw &sid_name_use); 629da6c28aaSamw 630da6c28aaSamw if (name == 0) { 631da6c28aaSamw if (lsar_lookup_sids(domain_handle, sid, 632da6c28aaSamw user_info) == 0) { 633da6c28aaSamw name = user_info->name; 634da6c28aaSamw sid_name_use = user_info->sid_name_use; 635da6c28aaSamw } else { 636da6c28aaSamw name = "unknown"; 637da6c28aaSamw sid_name_use = SidTypeUnknown; 638da6c28aaSamw } 639da6c28aaSamw } 640da6c28aaSamw 641da6c28aaSamw if (lsar_open_account(domain_handle, sid, 642da6c28aaSamw &account_handle) == 0) { 643da6c28aaSamw (void) lsar_enum_privs_account(&account_handle, 644da6c28aaSamw user_info); 645da6c28aaSamw (void) lsar_close(&account_handle); 646da6c28aaSamw } 647da6c28aaSamw 648da6c28aaSamw free(accounts.info[i].sid); 649da6c28aaSamw mlsvc_release_user_info(user_info); 650da6c28aaSamw } 651da6c28aaSamw 652da6c28aaSamw if (accounts.info) 653da6c28aaSamw free(accounts.info); 654da6c28aaSamw } while (rc == 0 && accounts.entries_read != 0); 655da6c28aaSamw 656da6c28aaSamw mlsvc_free_user_info(user_info); 657da6c28aaSamw return (0); 658da6c28aaSamw } 659dc20a302Sas 660dc20a302Sas /* 661dc20a302Sas * lsa_lookup_name_lusr 662dc20a302Sas * 663dc20a302Sas * Obtains the SID for the given local user name if it 664dc20a302Sas * can be found. Upon successful return the allocated memory 665dc20a302Sas * for the returned SID must be freed by the caller. 666dc20a302Sas * 667dc20a302Sas * Note that in domain mode this function might actually return 668dc20a302Sas * a domain SID if local users are mapped to domain users. 669dc20a302Sas */ 670dc20a302Sas static uint32_t 6716537f381Sas lsa_lookup_name_lusr(char *name, smb_sid_t **sid) 672dc20a302Sas { 673dc20a302Sas struct passwd *pw; 674dc20a302Sas 675dc20a302Sas if ((pw = getpwnam(name)) == NULL) 676dc20a302Sas return (NT_STATUS_NO_SUCH_USER); 677dc20a302Sas 678dc20a302Sas if (smb_idmap_getsid(pw->pw_uid, SMB_IDMAP_USER, sid) != IDMAP_SUCCESS) 679dc20a302Sas return (NT_STATUS_NONE_MAPPED); 680dc20a302Sas 681dc20a302Sas return (NT_STATUS_SUCCESS); 682dc20a302Sas } 683dc20a302Sas 684dc20a302Sas /* 685dc20a302Sas * lsa_lookup_name_lgrp 686dc20a302Sas * 687dc20a302Sas * Obtains the SID for the given local group name if it 688dc20a302Sas * can be found. Upon successful return the allocated memory 689dc20a302Sas * for the returned SID must be freed by the caller. 690dc20a302Sas * 691dc20a302Sas * Note that in domain mode this function might actually return 692dc20a302Sas * a domain SID if local groups are mapped to domain groups. 693dc20a302Sas */ 694dc20a302Sas static uint32_t 6956537f381Sas lsa_lookup_name_lgrp(char *name, smb_sid_t **sid) 696dc20a302Sas { 697dc20a302Sas struct group *gr; 698dc20a302Sas 699dc20a302Sas if ((gr = getgrnam(name)) == NULL) 700dc20a302Sas return (NT_STATUS_NO_SUCH_ALIAS); 701dc20a302Sas 702dc20a302Sas if (smb_idmap_getsid(gr->gr_gid, SMB_IDMAP_GROUP, sid) != IDMAP_SUCCESS) 703dc20a302Sas return (NT_STATUS_NONE_MAPPED); 704dc20a302Sas 705dc20a302Sas return (NT_STATUS_SUCCESS); 706dc20a302Sas } 707dc20a302Sas 708dc20a302Sas static int 709dc20a302Sas lsa_lookup_mode(const char *domain, const char *name) 710dc20a302Sas { 711dc20a302Sas int lookup_mode; 712dc20a302Sas 7136537f381Sas if (smb_wka_lookup((char *)name)) 714dc20a302Sas return (MLSVC_LOOKUP_BUILTIN); 715dc20a302Sas 716dc20a302Sas if (smb_config_get_secmode() == SMB_SECMODE_WORKGRP) 717dc20a302Sas return (MLSVC_LOOKUP_LOCAL); 718dc20a302Sas 719dc20a302Sas if ((domain == NULL) || (*domain == '\0')) 720dc20a302Sas return (MLSVC_LOOKUP_DOMLOC); 721dc20a302Sas 722dc20a302Sas if (mlsvc_is_local_domain(domain) == 1) 723dc20a302Sas lookup_mode = MLSVC_LOOKUP_LOCAL; 724dc20a302Sas else 725dc20a302Sas lookup_mode = MLSVC_LOOKUP_DOMAIN; 726dc20a302Sas 727dc20a302Sas return (lookup_mode); 728dc20a302Sas } 729dc20a302Sas 730dc20a302Sas static uint32_t 7316537f381Sas lsa_lookup_sid_local(smb_sid_t *sid, smb_userinfo_t *ainfo) 732dc20a302Sas { 733dc20a302Sas char hostname[MAXHOSTNAMELEN]; 734dc20a302Sas struct passwd *pw; 735dc20a302Sas struct group *gr; 736dc20a302Sas uid_t id; 737dc20a302Sas int id_type; 738dc20a302Sas 739dc20a302Sas id_type = SMB_IDMAP_UNKNOWN; 740dc20a302Sas if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS) 741dc20a302Sas return (NT_STATUS_NONE_MAPPED); 742dc20a302Sas 743dc20a302Sas switch (id_type) { 744dc20a302Sas case SMB_IDMAP_USER: 745dc20a302Sas ainfo->sid_name_use = SidTypeUser; 746dc20a302Sas if ((pw = getpwuid(id)) == NULL) 747dc20a302Sas return (NT_STATUS_NO_SUCH_USER); 748dc20a302Sas 749dc20a302Sas ainfo->name = strdup(pw->pw_name); 750dc20a302Sas break; 751dc20a302Sas 752dc20a302Sas case SMB_IDMAP_GROUP: 753dc20a302Sas ainfo->sid_name_use = SidTypeAlias; 754dc20a302Sas if ((gr = getgrgid(id)) == NULL) 755dc20a302Sas return (NT_STATUS_NO_SUCH_ALIAS); 756dc20a302Sas 757dc20a302Sas ainfo->name = strdup(gr->gr_name); 758dc20a302Sas break; 759dc20a302Sas 760dc20a302Sas default: 761dc20a302Sas return (NT_STATUS_NONE_MAPPED); 762dc20a302Sas } 763dc20a302Sas 764dc20a302Sas if (ainfo->name == NULL) 765dc20a302Sas return (NT_STATUS_NO_MEMORY); 766dc20a302Sas 7676537f381Sas ainfo->domain_sid = smb_sid_dup(sid); 7686537f381Sas if (smb_sid_split(ainfo->domain_sid, &ainfo->rid) < 0) 769dc20a302Sas return (NT_STATUS_INTERNAL_ERROR); 770dc20a302Sas *hostname = '\0'; 771dc20a302Sas (void) smb_getnetbiosname(hostname, MAXHOSTNAMELEN); 772dc20a302Sas if ((ainfo->domain_name = strdup(hostname)) == NULL) 773dc20a302Sas return (NT_STATUS_NO_MEMORY); 774dc20a302Sas 775dc20a302Sas return (NT_STATUS_SUCCESS); 776dc20a302Sas } 777dc20a302Sas 778dc20a302Sas static uint32_t 7796537f381Sas lsa_lookup_sid_builtin(smb_sid_t *sid, smb_userinfo_t *ainfo) 780dc20a302Sas { 781dc20a302Sas char *name; 782dc20a302Sas WORD sid_name_use; 783dc20a302Sas 7846537f381Sas if ((name = smb_wka_lookup_sid(sid, &sid_name_use)) == NULL) 785dc20a302Sas return (NT_STATUS_NONE_MAPPED); 786dc20a302Sas 787dc20a302Sas ainfo->sid_name_use = sid_name_use; 788dc20a302Sas ainfo->name = strdup(name); 7896537f381Sas ainfo->domain_sid = smb_sid_dup(sid); 790dc20a302Sas 791dc20a302Sas if (ainfo->name == NULL || ainfo->domain_sid == NULL) 792dc20a302Sas return (NT_STATUS_NO_MEMORY); 793dc20a302Sas 794dc20a302Sas if (sid_name_use != SidTypeDomain) 7956537f381Sas (void) smb_sid_split(ainfo->domain_sid, &ainfo->rid); 796dc20a302Sas 7976537f381Sas if ((name = smb_wka_lookup_domain(ainfo->name)) != NULL) 798dc20a302Sas ainfo->domain_name = strdup(name); 799dc20a302Sas else 800dc20a302Sas ainfo->domain_name = strdup("UNKNOWN"); 801dc20a302Sas 802dc20a302Sas if (ainfo->domain_name == NULL) 803dc20a302Sas return (NT_STATUS_NO_MEMORY); 804dc20a302Sas 805dc20a302Sas return (NT_STATUS_SUCCESS); 806dc20a302Sas } 807dc20a302Sas 808dc20a302Sas static uint32_t 8096537f381Sas lsa_lookup_sid_domain(smb_sid_t *sid, smb_userinfo_t *ainfo) 810dc20a302Sas { 811dc20a302Sas mlsvc_handle_t domain_handle; 812dc20a302Sas char *user = smbrdr_ipc_get_user(); 813dc20a302Sas uint32_t status; 814*8d7e4166Sjose borrego smb_domain_t dinfo; 815*8d7e4166Sjose borrego 816*8d7e4166Sjose borrego if (!smb_domain_getinfo(&dinfo)) 817*8d7e4166Sjose borrego return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 818dc20a302Sas 819*8d7e4166Sjose borrego if (lsar_open(dinfo.d_dc, dinfo.d_nbdomain, user, &domain_handle) != 0) 820dc20a302Sas return (NT_STATUS_INVALID_PARAMETER); 821dc20a302Sas 822dc20a302Sas status = lsar_lookup_sids2(&domain_handle, 823dc20a302Sas (struct mslsa_sid *)sid, ainfo); 824dc20a302Sas 825dc20a302Sas if (status == NT_STATUS_REVISION_MISMATCH) { 826dc20a302Sas /* 827dc20a302Sas * Not a Windows 2000 domain controller: 828dc20a302Sas * use the NT compatible call. 829dc20a302Sas */ 830dc20a302Sas status = lsar_lookup_sids(&domain_handle, 831dc20a302Sas (struct mslsa_sid *)sid, ainfo); 832dc20a302Sas } 833dc20a302Sas 834dc20a302Sas (void) lsar_close(&domain_handle); 835dc20a302Sas return (status); 836dc20a302Sas } 837