cac_lsarpc.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,072 行 · 第 1/2 页

C
1,072
字号
/*  *  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, &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;   }   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;   }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?