/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Local Security Authority RPC (LSAR) client-side interface.
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/ntaccess.h>
#include <smbsrv/ntlocale.h>
#include <lsalib.h>
/*
* The maximum number of bytes we are prepared to deal with in a
* response.
*/
/*
* This structure is used when looking up names. We only lookup one
* name at a time but the structure will allow for more.
*/
typedef struct lsa_names {
} lsa_names_t;
smb_account_t *);
smb_account_t *);
smb_account_t *);
smb_account_t *);
smb_account_t *);
static char *lsar_get_username(const char *);
static void smb_account_trace(const smb_account_t *);
static void lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *,
static void lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *,
/*
* lsar_open
*
* This is a wrapper round lsar_open_policy2 to ensure that we connect
* using the appropriate domain information.
*
* If username argument is NULL, an anonymous connection will be established.
* Otherwise, an authenticated connection will be established.
*
* Returns 0 or NT status (Raw, not LSA-ized)
*/
{
return (NT_STATUS_INTERNAL_ERROR);
return (status);
}
/*
* lsar_open_policy2
*
* Obtain an LSA policy handle. A policy handle is required to access
* LSA resources on a remote server. The server name supplied here does
* not need the double backslash prefix; it is added here. Call this
* function via lsar_open to ensure that the appropriate connection is
* in place.
*
* Returns 0 or NT status (Raw, not LSA-ized)
*/
{
int opnum;
int len;
if (status != 0)
return (status);
goto out;
}
goto out;
}
if (status == NT_STATUS_SUCCESS) {
sizeof (ndr_hdid_t));
if (ndr_is_null_handle(lsa_handle))
}
out:
if (status != NT_STATUS_SUCCESS)
return (status);
}
/*
* lsar_open_account
*
* Obtain an LSA account handle. The lsa_handle must be a valid handle
* obtained via lsar_open_policy2. The main thing to remember here is
* to set up the context in the lsa_account_handle. I'm not sure what
* the requirements are for desired access. Some values require admin
* access.
*
* Returns 0 on success. Otherwise non-zero to indicate a failure.
*/
int
{
int opnum;
int rc;
return (-1);
#if 0
#endif
return (-1);
rc = -1;
} else {
rc = -1;
}
return (rc);
}
/*
* lsar_close
*
* Close the LSA connection associated with the handle. The lsa_handle
* must be a valid handle obtained via a call to lsar_open_policy2 or
* lsar_open_account. On success the handle will be zeroed out to
* ensure that it is not used again. If this is the top level handle
* (i.e. the one obtained via lsar_open_policy2) the pipe is closed.
*
* Returns 0 on success. Otherwise non-zero to indicate a failure.
*/
int
{
int opnum;
if (ndr_is_null_handle(lsa_handle))
return (-1);
if (ndr_is_bind_handle(lsa_handle))
return (0);
}
/*
* lsar_query_security_desc
*
* Don't use this call yet. It is just a place holder for now.
*/
int
{
int rc;
int opnum;
return (rc);
}
/*
* lsar_query_info_policy
*
* The general purpose of this function is to allow various pieces of
* information to be queried on the domain controller. The only
* information queries supported are MSLSA_POLICY_PRIMARY_DOMAIN_INFO
* and MSLSA_POLICY_ACCOUNT_DOMAIN_INFO.
*
* On success, the return code will be 0 and the user_info structure
* will be set up. The sid_name_use field will be set to SidTypeDomain
* indicating that the domain name and domain sid fields are vaild. If
* the infoClass returned from the server is not one of the supported
* values, the sid_name_use willbe set to SidTypeUnknown. If the RPC
* fails, a negative error code will be returned, in which case the
* user_info will not have been updated.
*/
{
int opnum;
return (NT_STATUS_INVALID_PARAMETER);
} else {
switch (infoClass) {
break;
break;
guid_str);
break;
default:
break;
}
}
return (status);
}
/*
* This is a wrapper for the various lookup sid RPCs.
*/
{
};
char *p;
int i;
return (NT_STATUS_INVALID_PARAMETER);
/*
* Windows 2000 doesn't like an LSA lookup for
* DOMAIN\Administrator.
*/
++p;
if (strcasecmp(p, "administrator") == 0)
name = p;
}
}
for (i = 0; i < n_op; ++i) {
if (status != NT_STATUS_INVALID_PARAMETER)
break;
}
} else {
}
if (status == NT_STATUS_SUCCESS) {
if (!smb_account_validate(info)) {
} else {
}
}
return (status);
}
/*
* The name may be in one of the following forms:
*
* domain\username
* username
* username@domain
*
* Return a strdup'd copy of the username. The caller is responsible
* for freeing the allocated memory.
*/
static char *
{
else
}
/*
* lsar_lookup_names1
*
* Lookup a name and obtain the domain and user rid.
*
* Note: NT returns an error if the mapped_count is non-zero when the RPC
* is called.
*
* If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED.
*/
static uint32_t
{
char *domname;
return (NT_STATUS_INVALID_PARAMETER);
}
}
if (arg.mapped_count == 0) {
return (NT_STATUS_NONE_MAPPED);
}
if (rid_entry->domain_index != 0) {
return (NT_STATUS_NONE_MAPPED);
}
return (status);
}
/*
* lsar_lookup_names2
*/
static uint32_t
{
char *domname;
return (NT_STATUS_INVALID_PARAMETER);
}
}
if (arg.mapped_count == 0) {
return (NT_STATUS_NONE_MAPPED);
}
if (rid_entry->domain_index != 0) {
return (NT_STATUS_NONE_MAPPED);
}
return (status);
}
/*
* lsar_lookup_names3
*/
static uint32_t
{
char *domname;
return (NT_STATUS_INVALID_PARAMETER);
}
}
if (arg.mapped_count == 0) {
return (NT_STATUS_NONE_MAPPED);
}
if (sid_entry->domain_index != 0) {
return (NT_STATUS_NONE_MAPPED);
}
return (status);
}
/*
* lsar_lookup_names4
*
* This function is only valid if the remote RPC server is a domain
* controller and requires the security extensions defined in MS-RPCE.
*
* Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
* because we don't support the RPC_C_AUTHN_NETLOGON security provider.
* Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
*/
static uint32_t /*LINTED E_STATIC_UNUSED*/
{
char *domname;
return (NT_STATUS_INVALID_PARAMETER);
}
return (NT_STATUS_INVALID_PARAMETER);
}
if (arg.mapped_count == 0) {
return (NT_STATUS_NONE_MAPPED);
}
if (sid_entry->domain_index != 0) {
return (NT_STATUS_NONE_MAPPED);
}
return (status);
}
/*
* Lookup a sid and obtain the domain sid and account name.
* This is a wrapper for the various lookup sid RPCs.
*/
{
return (NT_STATUS_INVALID_PARAMETER);
account);
else
account);
if (status == NT_STATUS_SUCCESS) {
if (!smb_account_validate(account)) {
} else {
}
}
return (status);
}
/*
* lsar_lookup_sids1
*/
static uint32_t
{
char *name;
return (NT_STATUS_INVALID_PARAMETER);
}
}
if (arg.mapped_count == 0) {
return (NT_STATUS_NONE_MAPPED);
}
if (name_entry->domain_ix != 0) {
return (NT_STATUS_NONE_MAPPED);
}
return (status);
}
/*
* lsar_lookup_sids2
*/
static uint32_t
{
char *name;
return (NT_STATUS_INVALID_PARAMETER);
}
}
if (arg.mapped_count == 0) {
return (NT_STATUS_NONE_MAPPED);
}
if (name_entry->domain_ix != 0) {
return (NT_STATUS_NONE_MAPPED);
}
return (status);
}
/*
* lsar_lookup_sids3
*
* This function is only valid if the remote RPC server is a domain
* controller and requires the security extensions defined in MS-RPCE.
*
* Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
* because we don't support the RPC_C_AUTHN_NETLOGON security provider.
* Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
*/
static uint32_t /*LINTED E_STATIC_UNUSED*/
{
char *name;
return (NT_STATUS_INVALID_PARAMETER);
}
return (NT_STATUS_INVALID_PARAMETER);
}
if (arg.mapped_count == 0) {
return (NT_STATUS_NONE_MAPPED);
}
if (name_entry->domain_ix != 0) {
return (NT_STATUS_NONE_MAPPED);
}
return (status);
}
/*
* lsar_enum_accounts
*
* Enumerate the list of accounts (i.e. SIDs). Use the handle returned
* from lsa_open_policy2. The enum_context is used to support multiple
* calls to this enumeration function. It should be set to 0 on the
* first call. It will be updated by the domain controller and should
* simply be passed unchanged to subsequent calls until there are no
* more accounts. A warning status of 0x1A indicates that no more data
* is available. The list of accounts will be returned in accounts.
* This list is dynamically allocated using malloc, it should be freed
* by the caller when it is no longer required.
*/
struct mslsa_EnumAccountBuf *accounts)
{
int opnum;
int rc;
DWORD i;
int nbytes;
return (NT_STATUS_INTERNAL_ERROR);
accounts->entries_read = 0;
if (rc == 0) {
} else {
}
return (NT_STATUS_NO_MEMORY);
}
for (i = 0; i < n_entries; ++i)
}
} else {
}
return (status);
}
/*
* lsar_enum_trusted_domains
*
* Enumerate the list of trusted domains. Use the handle returned from
* lsa_open_policy2. The enum_context is used to support multiple calls
* to this enumeration function. It should be set to 0 on the first
* call. It will be updated by the domain controller and should simply
* be passed unchanged to subsequent calls until there are no more
* domains.
*
* The trusted domains aren't actually returned here. They are added
* to the NT domain database. After all of the trusted domains have
* been discovered, the database can be interrogated to find all of
* the trusted domains.
*/
{
int opnum;
return (NT_STATUS_INVALID_PARAMETER);
/*
* STATUS_NO_MORE_ENTRIES provides call
* status but does not indicate an error.
*/
if (status != NT_STATUS_NO_MORE_ENTRIES)
status = 0;
} else {
status = 0;
}
return (status);
}
{
int opnum;
return (NT_STATUS_INVALID_PARAMETER);
/*
* STATUS_NO_MORE_ENTRIES provides call
* status but does not indicate an error.
*/
if (status != NT_STATUS_NO_MORE_ENTRIES)
status = 0;
} else {
status = 0;
}
return (status);
}
/*
* lsar_enum_privs_account
*
* Privileges enum? Need an account handle.
*/
/*ARGSUSED*/
int
{
int opnum;
int rc;
sizeof (mslsa_handle_t));
rc = -1;
}
return (rc);
}
/*
* lsar_lookup_priv_value
*
* Map a privilege name to a local unique id (LUID). Privilege names
* are consistent across the network. LUIDs are machine specific.
* This function provides the means to map a privilege name to the
* LUID used by a remote server to represent it. The handle here is
* a policy handle.
*/
int
{
int opnum;
int rc;
return (-1);
length += sizeof (smb_wchar_t);
if (rc == 0) {
rc = -1;
else
}
return (rc);
}
/*
* lsar_lookup_priv_name
*
* Map a local unique id (LUID) to a privilege name. Privilege names
* are consistent across the network. LUIDs are machine specific.
* This function the means to map the LUID used by a remote server to
* the appropriate privilege name. The handle here is a policy handle.
*/
int
{
int opnum;
int rc;
return (-1);
if (rc == 0) {
rc = -1;
else
namelen);
}
return (rc);
}
/*
* lsar_lookup_priv_display_name
*
* Map a privilege name to a privilege display name. The input handle
* should be an LSA policy handle and the name would normally be one
* of the privileges defined in smb_privilege.h
*
* There's something peculiar about the return status from NT servers,
* it's not always present. So for now, I'm ignoring the status in the
* RPC response.
*
* Returns NT status codes.
*/
char *display_name, int display_len)
{
int opnum;
return (NT_STATUS_INVALID_PARAMETER);
#if 0
#endif
else {
(void) strlcpy(display_name,
}
return (status);
}
static void
{
int i;
return;
sizeof (smb_domain_t));
return;
&list->td_domains[i]);
}
}
static void
{
int i;
return;
sizeof (smb_domain_t));
return;
}
}
static void
{
}