cac_samr.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,412 行 · 第 1/5 页
C
2,412 行
/* * Unix SMB/CIFS implementation. * MS-RPC client library implementation (SAMR 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 "libmsrpc_internal.h"/*used by cac_SamGetNamesFromRids*/#define SAMR_RID_UNKNOWN 8#define SAMR_ENUM_MAX_SIZE 0xffff/*not sure what this is.. taken from rpcclient/cmd_samr.c*/#define SAMR_LOOKUP_FLAGS 0x000003e8int cac_SamConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamConnect *op) { SMBCSRV *srv = NULL; struct rpc_pipe_client *pipe_hnd = NULL; POLICY_HND *sam_out = NULL; if(!hnd) return CAC_FAILURE; if(!hnd->_internal.ctx) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(!op || op->in.access == 0 || !mem_ctx) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } srv = cac_GetServer(hnd); if(!srv) { hnd->status = NT_STATUS_INVALID_CONNECTION; return CAC_FAILURE; } /*initialize for samr pipe if we have to*/ if(!hnd->_internal.pipes[PI_SAMR]) { if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SAMR, &(hnd->status)))) { return CAC_FAILURE; } hnd->_internal.pipes[PI_SAMR] = True; } pipe_hnd = cac_GetPipe(hnd, PI_SAMR); if(!pipe_hnd) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } sam_out = talloc(mem_ctx, POLICY_HND); if(!sam_out) { hnd->status = NT_STATUS_NO_MEMORY; return CAC_FAILURE; } if(hnd->_internal.srv_level >= SRV_WIN_2K_SP3) { hnd->status = rpccli_samr_connect4( pipe_hnd, mem_ctx, op->in.access, sam_out); } if(hnd->_internal.srv_level < SRV_WIN_2K_SP3 || !NT_STATUS_IS_OK(hnd->status)) { /*if sam_connect4 failed, the use sam_connect and lower srv_level*/ hnd->status = rpccli_samr_connect( pipe_hnd, mem_ctx, op->in.access, sam_out); if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_2K) { hnd->_internal.srv_level = SRV_WIN_2K; } } if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; op->out.sam = sam_out; return CAC_SUCCESS;}int cac_SamClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *sam) { struct rpc_pipe_client *pipe_hnd = NULL; if(!hnd) return CAC_FAILURE; if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(!sam || !mem_ctx) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } pipe_hnd = cac_GetPipe(hnd, PI_SAMR); if(!pipe_hnd) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; return CAC_SUCCESS;}/*this is an internal function. Due to a circular dependency, it must be prototyped in libmsrpc.h (which I don't want to do) * cac_SamOpenDomain() is the only function that calls it, so I just put the definition here *//*attempts to find the sid of the domain we are connected to*/DOM_SID *cac_get_domain_sid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, uint32 des_access) { struct LsaOpenPolicy lop; struct LsaFetchSid fs; DOM_SID *sid; ZERO_STRUCT(lop); ZERO_STRUCT(fs); lop.in.access = des_access; lop.in.security_qos = True; if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) return NULL; fs.in.pol = lop.out.pol; fs.in.info_class = CAC_DOMAIN_INFO; if(!cac_LsaFetchSid(hnd, mem_ctx, &fs)) return NULL; cac_LsaClosePolicy(hnd, mem_ctx, lop.out.pol); if(!fs.out.domain_sid) return NULL; sid = talloc_memdup(mem_ctx, &(fs.out.domain_sid->sid), sizeof(DOM_SID)); if(!sid) { hnd->status = NT_STATUS_NO_MEMORY; } return sid;}int cac_SamOpenDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenDomain *op) { struct rpc_pipe_client *pipe_hnd = NULL; DOM_SID *sid_buf; POLICY_HND *sam_out; POLICY_HND *pol_out; struct SamLookupDomain sld; if(!hnd) return CAC_FAILURE; if(!hnd->_internal.ctx) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(!op || op->in.access == 0 || !mem_ctx) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } if(!op->in.sam) { /*use cac_SamConnect() since it does the session setup*/ struct SamConnect sc; ZERO_STRUCT(sc); sc.in.access = op->in.access; if(!cac_SamConnect(hnd, mem_ctx, &sc)) { return CAC_FAILURE; } sam_out = sc.out.sam; } else { sam_out = op->in.sam; } if(!op->in.sid) { /*find the sid for the SAM's domain*/ /*try using cac_SamLookupDomain() first*/ ZERO_STRUCT(sld); sld.in.sam = sam_out; sld.in.name = hnd->domain; if(cac_SamLookupDomain(hnd, mem_ctx, &sld)) { /*then we got the sid*/ sid_buf = sld.out.sid; } else { /*try to get it from the LSA*/ sid_buf = cac_get_domain_sid(hnd, mem_ctx, op->in.access); } } else { /*we already have the sid for the domain we want*/ sid_buf = op->in.sid; } pipe_hnd = cac_GetPipe(hnd, PI_SAMR); if(!pipe_hnd) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } pol_out = talloc(mem_ctx, POLICY_HND); if(!pol_out) { hnd->status = NT_STATUS_NO_MEMORY; return CAC_FAILURE; } /*now open the domain*/ hnd->status = rpccli_samr_open_domain( pipe_hnd, mem_ctx, sam_out, op->in.access, sid_buf, pol_out); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; op->out.sam = sam_out; op->out.dom_hnd = pol_out; return CAC_SUCCESS;}int cac_SamOpenUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenUser *op) { struct rpc_pipe_client *pipe_hnd = NULL; uint32 *rid_buf = NULL; uint32 num_rids = 0; uint32 *rid_types = NULL; POLICY_HND *user_out = NULL; if(!hnd) return CAC_FAILURE; if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(!op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } if(op->in.rid == 0 && op->in.name == NULL) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } pipe_hnd = cac_GetPipe(hnd, PI_SAMR); if(!pipe_hnd) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(op->in.rid == 0 && op->in.name) { /*lookup the name and then set rid_buf*/ hnd->status = rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd, SAMR_LOOKUP_FLAGS, 1, (const char **)&op->in.name, &num_rids, &rid_buf, &rid_types); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; if(num_rids == 0 || rid_buf == NULL || rid_types[0] == SAMR_RID_UNKNOWN) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } talloc_free(rid_types); } else { rid_buf = &op->in.rid; } user_out = talloc(mem_ctx, POLICY_HND); if(!user_out) { hnd->status = NT_STATUS_NO_MEMORY; return CAC_FAILURE; } hnd->status = rpccli_samr_open_user(pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.access, *rid_buf, user_out); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; op->out.user_hnd = user_out; return CAC_SUCCESS;}int cac_SamCreateUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateUser *op) { struct rpc_pipe_client *pipe_hnd = NULL; POLICY_HND *user_out = NULL; uint32 rid_out; /**found in rpcclient/cmd_samr.c*/ uint32 unknown = 0xe005000b; if(!hnd) return CAC_FAILURE; if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(!op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0 || !mem_ctx) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } pipe_hnd = cac_GetPipe(hnd, PI_SAMR); if(!pipe_hnd) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } user_out = talloc(mem_ctx, POLICY_HND); if(!user_out) { hnd->status = NT_STATUS_NO_MEMORY; return CAC_FAILURE; } hnd->status = rpccli_samr_create_dom_user( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.name, op->in.acb_mask, unknown, user_out, &rid_out); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; op->out.user_hnd = user_out; op->out.rid = rid_out; return CAC_SUCCESS;}int cac_SamDeleteUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) { struct rpc_pipe_client *pipe_hnd = NULL; if(!hnd) return CAC_FAILURE; if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(!user_hnd || !mem_ctx) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } pipe_hnd = cac_GetPipe(hnd, PI_SAMR); if(!pipe_hnd) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } hnd->status = rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd); if(!NT_STATUS_IS_OK(hnd->status)) return CAC_FAILURE; return CAC_SUCCESS;}int cac_SamEnumUsers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumUsers *op) { struct rpc_pipe_client *pipe_hnd = NULL; uint32 resume_idx_out = 0; char **names_out = NULL; uint32 *rids_out = NULL; uint32 num_users_out = 0; if(!hnd) return CAC_FAILURE; if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(!op || !op->in.dom_hnd || !mem_ctx) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/ if(op->out.done == True) return CAC_FAILURE; pipe_hnd = cac_GetPipe(hnd, PI_SAMR); if(!pipe_hnd) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } resume_idx_out = op->out.resume_idx; hnd->status = rpccli_samr_enum_dom_users( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, op->in.acb_mask, SAMR_ENUM_MAX_SIZE, &names_out, &rids_out, &num_users_out); if(NT_STATUS_IS_OK(hnd->status)) op->out.done = True; /*if there are no more entries, the operation will return NT_STATUS_OK. * We want to return failure if no results were returned*/ if(!NT_STATUS_IS_OK(hnd->status) && NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES)) return CAC_FAILURE; op->out.resume_idx= resume_idx_out; op->out.num_users = num_users_out; op->out.rids = rids_out; op->out.names = names_out; return CAC_SUCCESS;}int cac_SamGetNamesFromRids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetNamesFromRids *op) { struct rpc_pipe_client *pipe_hnd = NULL; uint32 num_names_out; char **names_out; uint32 *name_types_out; uint32 i = 0; CacLookupRidsRecord *map_out; if(!hnd) return CAC_FAILURE; if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) { hnd->status = NT_STATUS_INVALID_HANDLE; return CAC_FAILURE; } if(!op || !op->in.dom_hnd || !mem_ctx) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; } if(!op->in.rids && op->in.num_rids != 0) { hnd->status = NT_STATUS_INVALID_PARAMETER; return CAC_FAILURE; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?