mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
2992ba0690
Jeremy.
(This used to be commit 218c924d91
)
1073 lines
28 KiB
C
1073 lines
28 KiB
C
/*
|
|
* Unix SMB/CIFS implementation.
|
|
* MS-RPC client library implementation (LSA pipe)
|
|
* Copyright (C) Chris Nicholls 2005.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "libmsrpc.h"
|
|
#include "libsmb_internal.h"
|
|
|
|
int cac_LsaOpenPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenPolicy *op) {
|
|
SMBCSRV *srv = NULL;
|
|
POLICY_HND *policy = NULL;
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!mem_ctx || !op) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.pol = NULL;
|
|
|
|
srv = cac_GetServer(hnd);
|
|
if(!srv) {
|
|
hnd->status = NT_STATUS_INVALID_CONNECTION;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
/*see if there is already an active session on this pipe, if not then open one*/
|
|
if(!hnd->_internal.pipes[PI_LSARPC]) {
|
|
pipe_hnd = cli_rpc_pipe_open_noauth(&(srv->cli), PI_LSARPC, &(hnd->status));
|
|
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_UNSUCCESSFUL;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
hnd->_internal.pipes[PI_LSARPC] = True;
|
|
}
|
|
|
|
policy = SMB_MALLOC_P(POLICY_HND);
|
|
if(!policy) {
|
|
errno = ENOMEM;
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
/*need to make sure that our nt status is good otherwise check might fail below*/
|
|
hnd->status = NT_STATUS_OK;
|
|
|
|
if(hnd->_internal.srv_level >= SRV_WIN_2K) {
|
|
|
|
/*try using open_policy2, if this fails try again in next block using open_policy, if that works then adjust hnd->_internal.srv_level*/
|
|
|
|
/*we shouldn't need to modify the access mask to make it work here*/
|
|
hnd->status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, op->in.security_qos, op->in.access, policy);
|
|
|
|
}
|
|
|
|
if(hnd->_internal.srv_level < SRV_WIN_2K || !NT_STATUS_IS_OK(hnd->status)) {
|
|
hnd->status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, op->in.security_qos, op->in.access, policy);
|
|
|
|
if(hnd->_internal.srv_level > SRV_WIN_NT4 && NT_STATUS_IS_OK(hnd->status)) {
|
|
/*change the server level to 1*/
|
|
hnd->_internal.srv_level = SRV_WIN_NT4;
|
|
}
|
|
|
|
}
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
SAFE_FREE(policy);
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.pol = policy;
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaClosePolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *pol) {
|
|
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!pol)
|
|
return CAC_SUCCESS; /*if the policy handle doesnt exist then it's already closed*/
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
|
|
hnd->status = rpccli_lsa_close(pipe_hnd, mem_ctx, pol);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status))
|
|
return CAC_FAILURE;
|
|
|
|
SAFE_FREE(pol);
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaGetNamesFromSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetNamesFromSids *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
int result = -1;
|
|
|
|
int i;
|
|
|
|
/*buffers for outputs*/
|
|
char **domains = NULL;
|
|
char **names = NULL;
|
|
uint32 *types = NULL;
|
|
|
|
CacSidInfo *sids_out = NULL;
|
|
DOM_SID *unknown_out = NULL;
|
|
int num_unknown = 0;
|
|
|
|
int num_sids;
|
|
|
|
int found_idx;
|
|
int unknown_idx;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!mem_ctx || !op || !op->in.pol || !op->in.sids) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
num_sids = op->in.num_sids;
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
|
|
|
|
/*now actually lookup the names*/
|
|
hnd->status = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, op->in.pol, op->in.num_sids,
|
|
op->in.sids, &domains, &names, &types);
|
|
|
|
if(NT_STATUS_IS_OK(hnd->status)) {
|
|
/*this is the easy part, just make the out.sids array*/
|
|
sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, num_sids);
|
|
if(!sids_out) {
|
|
errno = ENOMEM;
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
for(i = 0; i < num_sids; i++) {
|
|
sids_out[i].sid = op->in.sids[i];
|
|
sids_out[i].name = names[i];
|
|
sids_out[i].domain = domains[i];
|
|
}
|
|
|
|
result = CAC_SUCCESS;
|
|
}
|
|
else if(NT_STATUS_V(hnd->status) == NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
|
|
/*first find out how many couldn't be looked up*/
|
|
|
|
for(i = 0; i < num_sids; i++) {
|
|
if(names[i] == NULL) {
|
|
num_unknown++;
|
|
}
|
|
}
|
|
|
|
if( num_unknown >= num_sids) {
|
|
hnd->status = NT_STATUS_UNSUCCESSFUL;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, (num_sids - num_unknown));
|
|
if(!sids_out) {
|
|
errno = ENOMEM;
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
unknown_out = TALLOC_ARRAY(mem_ctx, DOM_SID, num_unknown);
|
|
if(!unknown_out) {
|
|
errno = ENOMEM;
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
found_idx = unknown_idx = 0;
|
|
|
|
/*now we can actually do the real work*/
|
|
for(i = 0; i < num_sids; i++) {
|
|
if(names[i] != NULL) {
|
|
sids_out[found_idx].sid = op->in.sids[i];
|
|
sids_out[found_idx].name = names[i];
|
|
sids_out[found_idx].domain = domains[i];
|
|
|
|
found_idx++;
|
|
}
|
|
else { /*then this one didnt work out*/
|
|
unknown_out[unknown_idx] = op->in.sids[i];
|
|
|
|
unknown_idx++;
|
|
}
|
|
}
|
|
|
|
result = CAC_PARTIAL_SUCCESS;
|
|
}
|
|
else { /*then it failed for some reason*/
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.num_found = num_sids - num_unknown;
|
|
op->out.sids = sids_out;
|
|
op->out.unknown = unknown_out;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
int cac_LsaGetSidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetSidsFromNames *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
int result = -1;
|
|
|
|
int i;
|
|
|
|
/*buffers for outputs*/
|
|
DOM_SID *sids = NULL;
|
|
uint32 *types = NULL;
|
|
|
|
CacSidInfo *sids_out = NULL;
|
|
char **unknown_out = NULL;
|
|
int num_unknown = 0;
|
|
|
|
int num_names;
|
|
|
|
int found_idx = 0;
|
|
int unknown_idx = 0;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!mem_ctx || !op || !op->in.pol || !op->in.names) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
num_names = op->in.num_names;
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
|
|
/*now actually lookup the names*/
|
|
hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, num_names,
|
|
(const char **)op->in.names, NULL, &sids, &types);
|
|
|
|
if(NT_STATUS_IS_OK(hnd->status)) {
|
|
/*this is the easy part, just make the out.sids array*/
|
|
sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, num_names);
|
|
if(!sids_out) {
|
|
errno = ENOMEM;
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
for(i = 0; i < num_names; i++) {
|
|
sids_out[i].sid = sids[i];
|
|
sids_out[i].name = talloc_strdup(mem_ctx, op->in.names[i]);
|
|
sids_out[i].domain = NULL;
|
|
}
|
|
|
|
result = CAC_SUCCESS;
|
|
}
|
|
else if(NT_STATUS_V(hnd->status) == NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
|
|
/*first find out how many couldn't be looked up*/
|
|
|
|
for(i = 0; i < num_names; i++) {
|
|
if(types[i] == SID_NAME_UNKNOWN) {
|
|
num_unknown++;
|
|
}
|
|
}
|
|
|
|
if( num_unknown >= num_names) {
|
|
hnd->status = NT_STATUS_UNSUCCESSFUL;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, (num_names - num_unknown));
|
|
if(!sids_out) {
|
|
errno = ENOMEM;
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
unknown_out = TALLOC_ARRAY(mem_ctx, char *, num_unknown);
|
|
if(!unknown_out) {
|
|
errno = ENOMEM;
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
unknown_idx = found_idx = 0;
|
|
|
|
/*now we can actually do the real work*/
|
|
for(i = 0; i < num_names; i++) {
|
|
if(types[i] != SID_NAME_UNKNOWN) {
|
|
sids_out[found_idx].sid = sids[i];
|
|
sids_out[found_idx].name = talloc_strdup(mem_ctx, op->in.names[i]);
|
|
sids_out[found_idx].domain = NULL;
|
|
|
|
found_idx++;
|
|
}
|
|
else { /*then this one didnt work out*/
|
|
unknown_out[unknown_idx] = talloc_strdup(mem_ctx, op->in.names[i]);
|
|
|
|
unknown_idx++;
|
|
}
|
|
}
|
|
|
|
result = CAC_PARTIAL_SUCCESS;
|
|
}
|
|
else { /*then it failed for some reason*/
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.num_found = num_names - num_unknown;
|
|
op->out.sids = sids_out;
|
|
op->out.unknown = unknown_out;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
int cac_LsaFetchSid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaFetchSid *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
int result = -1;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!mem_ctx || !op || !op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.local_sid = NULL;
|
|
op->out.domain_sid = NULL;
|
|
|
|
if( (op->in.info_class & CAC_LOCAL_INFO) == CAC_LOCAL_INFO) {
|
|
DOM_SID *local_sid = NULL;
|
|
char *dom_name = NULL;
|
|
|
|
hnd->status = rpccli_lsa_query_info_policy( pipe_hnd, mem_ctx, op->in.pol, CAC_LOCAL_INFO, &dom_name, &local_sid);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
result = CAC_FAILURE;
|
|
goto domain;
|
|
}
|
|
|
|
op->out.local_sid = talloc(mem_ctx, CacSidInfo);
|
|
if(!op->out.local_sid) {
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
result = CAC_FAILURE;
|
|
goto domain;
|
|
}
|
|
|
|
op->out.local_sid->domain = dom_name;
|
|
|
|
sid_copy(&op->out.local_sid->sid, local_sid);
|
|
TALLOC_FREE(local_sid);
|
|
}
|
|
|
|
domain:
|
|
|
|
if( (op->in.info_class & CAC_DOMAIN_INFO) == CAC_DOMAIN_INFO) {
|
|
DOM_SID *domain_sid;
|
|
char *dom_name;
|
|
|
|
hnd->status = rpccli_lsa_query_info_policy( pipe_hnd, mem_ctx, op->in.pol, CAC_DOMAIN_INFO, &dom_name, &domain_sid);
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
/*if we succeeded above, report partial success*/
|
|
result = (result == CAC_SUCCESS) ? CAC_PARTIAL_SUCCESS : CAC_FAILURE;
|
|
goto done;
|
|
}
|
|
else if(result == CAC_FAILURE) {
|
|
/*if we failed above but succeded here then report partial success*/
|
|
result = CAC_PARTIAL_SUCCESS;
|
|
}
|
|
|
|
op->out.domain_sid = talloc(mem_ctx, CacSidInfo);
|
|
if(!op->out.domain_sid) {
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
result = CAC_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
op->out.domain_sid->domain = dom_name;
|
|
sid_copy(&op->out.domain_sid->sid, domain_sid);
|
|
TALLOC_FREE(domain_sid);
|
|
}
|
|
|
|
done:
|
|
return result;
|
|
}
|
|
|
|
int cac_LsaQueryInfoPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaQueryInfoPolicy *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
char *domain_name = NULL;
|
|
char *dns_name = NULL;
|
|
char *forest_name = NULL;
|
|
struct uuid *domain_guid = NULL;
|
|
DOM_SID *domain_sid = NULL;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
/*only works if info_class parm is 12*/
|
|
hnd->status = rpccli_lsa_query_info_policy2(pipe_hnd, mem_ctx, op->in.pol, 12,
|
|
&domain_name, &dns_name, &forest_name, &domain_guid, &domain_sid);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.domain_name = domain_name;
|
|
op->out.dns_name = dns_name;
|
|
op->out.forest_name = forest_name;
|
|
op->out.domain_guid = domain_guid;
|
|
op->out.domain_sid = domain_sid;
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaEnumSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumSids *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
uint32 num_sids;
|
|
DOM_SID *sids;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op || !op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_enum_sids(pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), op->in.pref_max_sids, &num_sids, &sids);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.num_sids = num_sids;
|
|
op->out.sids = sids;
|
|
|
|
return CAC_SUCCESS;
|
|
|
|
}
|
|
|
|
int cac_LsaEnumAccountRights(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumAccountRights *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
uint32 count = 0;
|
|
char **privs = NULL;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.name && !op->in.sid) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(op->in.name && !op->in.sid) {
|
|
DOM_SID *user_sid = NULL;
|
|
uint32 *type;
|
|
|
|
/*lookup the SID*/
|
|
hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status))
|
|
return CAC_FAILURE;
|
|
|
|
op->in.sid = user_sid;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_enum_account_rights( pipe_hnd, mem_ctx, op->in.pol, op->in.sid,
|
|
&count, &privs);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.num_privs = count;
|
|
op->out.priv_names = privs;
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaEnumTrustedDomains(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumTrustedDomains *op) {
|
|
struct rpc_pipe_client *pipe_hnd;
|
|
|
|
uint32 num_domains;
|
|
char **domain_names;
|
|
DOM_SID *domain_sids;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_enum_trust_dom( pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), &num_domains, &domain_names, &domain_sids);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.num_domains = num_domains;
|
|
op->out.domain_names = domain_names;
|
|
op->out.domain_sids = domain_sids;
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaOpenTrustedDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenTrustedDomain *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
POLICY_HND *dom_pol = NULL;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.pol || !op->in.access || !op->in.domain_sid) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
dom_pol = talloc(mem_ctx, POLICY_HND);
|
|
if(!dom_pol) {
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
errno = ENOMEM;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_open_trusted_domain( pipe_hnd, mem_ctx, op->in.pol, op->in.domain_sid, op->in.access, dom_pol);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.domain_pol = dom_pol;
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaQueryTrustedDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaQueryTrustedDomainInfo *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
LSA_TRUSTED_DOMAIN_INFO *dom_info;
|
|
|
|
if(!hnd)
|
|
return CAC_FAILURE;
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.pol || !op->in.info_class) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.domain_sid && !op->in.domain_name) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(op->in.domain_sid) {
|
|
hnd->status = rpccli_lsa_query_trusted_domain_info_by_sid( pipe_hnd, mem_ctx, op->in.pol, op->in.info_class, op->in.domain_sid, &dom_info);
|
|
}
|
|
else if(op->in.domain_name) {
|
|
hnd->status = rpccli_lsa_query_trusted_domain_info_by_name( pipe_hnd, mem_ctx, op->in.pol, op->in.info_class, op->in.domain_name, &dom_info);
|
|
}
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.info = dom_info;
|
|
|
|
return CAC_SUCCESS;
|
|
|
|
}
|
|
|
|
int cac_LsaEnumPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumPrivileges *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
uint32 num_privs;
|
|
char **priv_names;
|
|
uint32 *high_bits;
|
|
uint32 *low_bits;
|
|
|
|
if(!hnd) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op || !op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_enum_privilege(pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), op->in.pref_max_privs,
|
|
&num_privs, &priv_names, &high_bits, &low_bits);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.num_privs = num_privs;
|
|
op->out.priv_names = priv_names;
|
|
op->out.high_bits = high_bits;
|
|
op->out.low_bits = low_bits;
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaOpenAccount(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenAccount *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
POLICY_HND *user_pol = NULL;
|
|
|
|
if(!hnd) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op || !op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.sid && !op->in.name) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
|
|
/*look up the user's SID if we have to*/
|
|
if(op->in.name && !op->in.sid) {
|
|
DOM_SID *user_sid = NULL;
|
|
uint32 *type;
|
|
|
|
/*lookup the SID*/
|
|
hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status))
|
|
return CAC_FAILURE;
|
|
|
|
op->in.sid = user_sid;
|
|
}
|
|
|
|
user_pol = talloc(mem_ctx, POLICY_HND);
|
|
if(!user_pol) {
|
|
hnd->status = NT_STATUS_NO_MEMORY;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_open_account(pipe_hnd, mem_ctx, op->in.pol, op->in.sid, op->in.access, user_pol);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
TALLOC_FREE(user_pol);
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
op->out.user = user_pol;
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
|
|
int cac_LsaAddPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAddPrivileges *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
DOM_SID *user_sid = NULL;
|
|
uint32 *type = NULL;
|
|
|
|
if(!hnd) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op || !op->in.pol || !op->in.priv_names) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.sid && !op->in.name) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(op->in.name && !op->in.sid) {
|
|
/*lookup the SID*/
|
|
hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status))
|
|
return CAC_FAILURE;
|
|
|
|
op->in.sid = user_sid;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_add_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), op->in.num_privs, (const char **)op->in.priv_names);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaRemovePrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaRemovePrivileges *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
DOM_SID *user_sid = NULL;
|
|
uint32 *type = NULL;
|
|
|
|
if(!hnd) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op || !op->in.pol || !op->in.priv_names) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.sid && !op->in.name) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(op->in.name && !op->in.sid) {
|
|
/*lookup the SID*/
|
|
hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status))
|
|
return CAC_FAILURE;
|
|
|
|
op->in.sid = user_sid;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), False, op->in.num_privs, (const char **)op->in.priv_names);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaClearPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaClearPrivileges *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
DOM_SID *user_sid = NULL;
|
|
uint32 *type = NULL;
|
|
|
|
if(!hnd) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op || !op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.sid && !op->in.name) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(op->in.name && !op->in.sid) {
|
|
/*lookup the SID*/
|
|
hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status))
|
|
return CAC_FAILURE;
|
|
|
|
op->in.sid = user_sid;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), True, 0, NULL);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaSetPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAddPrivileges *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
DOM_SID *user_sid = NULL;
|
|
uint32 *type = NULL;
|
|
|
|
if(!hnd) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op || !op->in.pol || !op->in.priv_names) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op->in.sid && !op->in.name) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(op->in.name && !op->in.sid) {
|
|
/*lookup the SID*/
|
|
hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status))
|
|
return CAC_FAILURE;
|
|
|
|
op->in.sid = user_sid;
|
|
}
|
|
|
|
/*first remove all privileges*/
|
|
hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), True, 0, NULL);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_add_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), op->in.num_privs, (const char **)op->in.priv_names);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status)) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
return CAC_SUCCESS;
|
|
}
|
|
|
|
int cac_LsaGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetSecurityObject *op) {
|
|
struct rpc_pipe_client *pipe_hnd = NULL;
|
|
|
|
/*this is taken from rpcclient/cmd_lsarpc.c*/
|
|
uint16 info_level = 4;
|
|
|
|
SEC_DESC_BUF *sec_out = NULL;
|
|
|
|
if(!hnd) {
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
if(!op || !op->in.pol) {
|
|
hnd->status = NT_STATUS_INVALID_PARAMETER;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
|
|
if(!pipe_hnd) {
|
|
hnd->status = NT_STATUS_INVALID_HANDLE;
|
|
return CAC_FAILURE;
|
|
}
|
|
|
|
hnd->status = rpccli_lsa_query_secobj( pipe_hnd, mem_ctx, op->in.pol, info_level, &sec_out);
|
|
|
|
if(!NT_STATUS_IS_OK(hnd->status))
|
|
return CAC_FAILURE;
|
|
|
|
op->out.sec = sec_out;
|
|
|
|
return CAC_FAILURE;
|
|
}
|