From 3c6b0f965588aab0edbc4d115fb9e72c884ded3b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 3 Sep 2005 16:55:45 +0000 Subject: r10003: in the rush for 10k, I forgot to run add the rest of Chris' libmsrpc files (This used to be commit 32bebc452dffa8348b94c5b866350b1fe761986f) --- source3/libmsrpc/cac_lsarpc.c | 1111 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1111 insertions(+) create mode 100644 source3/libmsrpc/cac_lsarpc.c (limited to 'source3/libmsrpc/cac_lsarpc.c') diff --git a/source3/libmsrpc/cac_lsarpc.c b/source3/libmsrpc/cac_lsarpc.c new file mode 100644 index 0000000000..911dc906f0 --- /dev/null +++ b/source3/libmsrpc/cac_lsarpc.c @@ -0,0 +1,1111 @@ +/* + * 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; + + 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]) { + if(!cli_nt_session_open(&srv->cli, PI_LSARPC)) { + hnd->status = NT_STATUS_UNSUCCESSFUL; + return CAC_FAILURE; + } + + hnd->_internal.pipes[PI_LSARPC] = True; + } + + /**make sure we are working with the right pipe*/ + srv->cli.pipe_idx = PI_LSARPC; + + 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 = cli_lsa_open_policy2(&(srv->cli), 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 = cli_lsa_open_policy(&srv->cli, 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) { + + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + /*make sure we're on the right pipe*/ + srv->cli.pipe_idx = PI_LSARPC; + + hnd->status = cli_lsa_close(&(srv->cli), 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) { + SMBCSRV *srv = 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; + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + /*make sure we're on the right pipe*/ + srv->cli.pipe_idx = PI_LSARPC; + + /*now actually lookup the names*/ + hnd->status = cli_lsa_lookup_sids(&(srv->cli), 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) { + SMBCSRV *srv = 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; + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + /*make sure we're on the right pipe*/ + srv->cli.pipe_idx = PI_LSARPC; + + /*now actually lookup the names*/ + hnd->status = cli_lsa_lookup_names( &(srv->cli), mem_ctx, op->in.pol, num_names, + (const char **)op->in.names, &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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + /*now make sure that it's set up for the LSA pipe*/ + srv->cli.pipe_idx = PI_LSARPC; + + 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 = cli_lsa_query_info_policy( &srv->cli, 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 = cli_lsa_query_info_policy( &srv->cli, 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + /*make sure we're on the right pipe*/ + srv->cli.pipe_idx = PI_LSARPC; + + /*only works if info_class parm is 12*/ + hnd->status = cli_lsa_query_info_policy2(&(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + hnd->status = cli_lsa_enum_sids(&(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + /*make sure we are set up for the lsa pipe*/ + srv->cli.pipe_idx = PI_LSARPC; + + if(op->in.name && !op->in.sid) { + DOM_SID *user_sid = NULL; + uint32 *type; + + /*lookup the SID*/ + hnd->status = cli_lsa_lookup_names( &(srv->cli), mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->in.sid = user_sid; + } + + hnd->status = cli_lsa_enum_account_rights( &(srv->cli), 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) { + SMBCSRV *srv; + + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + hnd->status = cli_lsa_enum_trust_dom( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + dom_pol = talloc(mem_ctx, POLICY_HND); + if(!dom_pol) { + hnd->status = NT_STATUS_NO_MEMORY; + errno = ENOMEM; + return CAC_FAILURE; + } + + hnd->status = cli_lsa_open_trusted_domain( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + if(op->in.domain_sid) { + hnd->status = cli_lsa_query_trusted_domain_info_by_sid( &(srv->cli), mem_ctx, op->in.pol, op->in.info_class, op->in.domain_sid, &dom_info); + } + else if(op->in.domain_name) { + hnd->status = cli_lsa_query_trusted_domain_info_by_name( &(srv->cli), 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) { + SMBCSRV *srv = NULL; + + int 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + hnd->status = cli_lsa_enum_privilege(&(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + srv->cli.pipe_idx = PI_LSARPC; + + /*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 = cli_lsa_lookup_names( &(srv->cli), mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &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 = cli_lsa_open_account(&(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + if(op->in.name && !op->in.sid) { + /*lookup the SID*/ + hnd->status = cli_lsa_lookup_names( &(srv->cli), mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->in.sid = user_sid; + } + + hnd->status = cli_lsa_add_account_rights( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + if(op->in.name && !op->in.sid) { + /*lookup the SID*/ + hnd->status = cli_lsa_lookup_names( &(srv->cli), mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->in.sid = user_sid; + } + + hnd->status = cli_lsa_remove_account_rights( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + if(op->in.name && !op->in.sid) { + /*lookup the SID*/ + hnd->status = cli_lsa_lookup_names( &(srv->cli), mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->in.sid = user_sid; + } + + hnd->status = cli_lsa_remove_account_rights( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + srv->cli.pipe_idx = PI_LSARPC; + + if(op->in.name && !op->in.sid) { + /*lookup the SID*/ + hnd->status = cli_lsa_lookup_names( &(srv->cli), mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->in.sid = user_sid; + } + + /*first remove all privileges*/ + hnd->status = cli_lsa_remove_account_rights( &(srv->cli), mem_ctx, op->in.pol, *(op->in.sid), True, 0, NULL); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + hnd->status = cli_lsa_add_account_rights( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_LSARPC; + + hnd->status = cli_lsa_query_secobj( &(srv->cli), 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; +} -- cgit