diff options
48 files changed, 15096 insertions, 0 deletions
diff --git a/examples/libmsrpc/cacusermgr/Makefile b/examples/libmsrpc/cacusermgr/Makefile new file mode 100644 index 0000000000..ab8bea410e --- /dev/null +++ b/examples/libmsrpc/cacusermgr/Makefile @@ -0,0 +1,22 @@ +CC=gcc +INCLUDES= -I`pwd` -I../../../source/ -I../../../source/include -I../../../source/ubiqx + +DEFS= -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE + +CFLAGS= -g -Wall -ansi $(INCLUDES) + +OBJ= util.o mgr_group.o mgr_user.o + +LDFLAGS=-L. -L../../bin/ +LIBS=../../../source/bin/libmsrpc.so + +all: cacusermgr + +cacusermgr: cacusermgr.o $(OBJ) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(OBJ) $(LIBS) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f *.o cacusermgr diff --git a/examples/libmsrpc/cacusermgr/cacusermgr.c b/examples/libmsrpc/cacusermgr/cacusermgr.c new file mode 100644 index 0000000000..77dd2505f6 --- /dev/null +++ b/examples/libmsrpc/cacusermgr/cacusermgr.c @@ -0,0 +1,344 @@ +/* + * Unix SMB/CIFS implementation. + * cacusermgr main implementation. + * + * 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 "cacusermgr.h" + +#define DEFAULT_MENU_LINES 15 + + +void create_menu(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd) { + struct SamCreateUser cu; + struct SamCreateGroup cg; + + fstring in; + fstring tmp; + + if(!hnd || !mem_ctx || !dom_hnd) { + printf("No Handle to SAM.\n"); + return; + } + + /*the menu*/ + in[0] = '\0'; + while(in[0] != 'c' && in[0] != 'C' && in[0] != 'q' && in[0] != 'Q') { + printf("\n"); + printf("[u] Create User\n"); + printf("[g] Create Group\n"); + printf("[m] Create Machine Account\n"); + printf("[c] Cancel\n\n"); + + printf("Command: "); + mgr_getline(in); + + printf("\n"); + + switch(in[0]) { + case 'u': /*create user*/ + case 'U': + ZERO_STRUCT(cu); + cu.in.dom_hnd = dom_hnd; + cu.in.acb_mask = ACB_NORMAL; + + printf("Enter name: "); + mgr_getline(tmp); + cu.in.name = talloc_strdup(mem_ctx, tmp); + + if(!cac_SamCreateUser(hnd, mem_ctx, &cu)) { + printerr("Could not create user.", hnd->status); + } + else { + user_menu(hnd, mem_ctx, dom_hnd, cu.out.user_hnd); + } + + /*this will break the loop and send us back to the main menu*/ + in[0] = 'c'; + break; + + case 'g': /*create group*/ + case 'G': + ZERO_STRUCT(cg); + cg.in.dom_hnd = dom_hnd; + cg.in.access = MAXIMUM_ALLOWED_ACCESS; + + printf("Enter name: "); + mgr_getline(tmp); + cg.in.name = talloc_strdup(mem_ctx, tmp); + + if(!cac_SamCreateGroup(hnd, mem_ctx, &cg)) { + printerr("Could not create group.", hnd->status); + } + else { + group_menu(hnd, mem_ctx, dom_hnd, cg.out.group_hnd); + } + + /*this will break the loop and send us back to the main menu*/ + in[0] = 'c'; + break; + + case 'm': /*create machine account*/ + case 'M': + ZERO_STRUCT(cu); + cu.in.dom_hnd = dom_hnd; + cu.in.acb_mask = ACB_WSTRUST; + + printf("Enter machine name: "); + mgr_getline(tmp); + + /*make sure we have a $ on the end*/ + if(tmp[strlen(tmp) - 1] != '$') + cu.in.name = talloc_asprintf(mem_ctx, "%s$", tmp); + else + cu.in.name = talloc_strdup(mem_ctx, tmp); + + strlower_m(cu.in.name); + + printf("Creating account: %s\n", cu.in.name); + + if(!cac_SamCreateUser(hnd, mem_ctx, &cu)) { + printerr("Could not create account.", hnd->status); + } + else { + user_menu(hnd, mem_ctx, dom_hnd, cu.out.user_hnd); + } + + /*this will break the loop and send us back to the main menu*/ + in[0] = 'c'; + break; + + case 'c': /*cancel*/ + case 'C': + case 'q': + case 'Q': + /*do nothing*/ + break; + + default: + printf("Invalid option\n"); + } + } + + return; +} + +void main_menu(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd) { + fstring in; + + uint32 rid_type = 0; + + struct SamOpenUser openu; + struct SamOpenGroup openg; + struct SamEnumUsers enumu; + struct SamEnumGroups enumg; + struct SamFlush flush; + + char *name = NULL; + uint32 rid = 0; + + if(!hnd || !mem_ctx || !dom_hnd) { + printf("No handle to SAM.\n"); + return; + } + + /*initialize this here and don't worry about it later*/ + ZERO_STRUCT(flush); + flush.in.dom_hnd = dom_hnd; + + in[0] = '\0'; + + /*handle the menu and commands*/ + while(in[0] != 'q' && in[0] != 'Q') { + printf("\n"); + + printf("[o] Open User or Group\n"); + printf("[c] Create Account or Group\n"); + printf("[u] List Users\n"); + printf("[g] List Groups\n"); + printf("[m] List Machine Accounts\n"); + printf("[q] Quit\n\n"); + + printf("Command: "); + + mgr_getline(in); + + printf("\n"); + + switch(in[0]) { + case 'o': /*open user or group*/ + case 'O': + printf("Enter RID or Name: "); + rid_type = rid_or_name(hnd, mem_ctx, dom_hnd, &rid, &name); + + if(rid_type == CAC_USER_RID) { + ZERO_STRUCT(openu); + openu.in.dom_hnd = dom_hnd; + openu.in.rid = rid; + openu.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenUser(hnd, mem_ctx, &openu)) + printerr("Could not open user.", hnd->status); + else { + user_menu(hnd, mem_ctx, dom_hnd, openu.out.user_hnd); + + if(!cac_SamFlush(hnd, mem_ctx, &flush)) { + printerr("Lost handle while flushing SAM.", hnd->status); + /*we want to quit*/ + in[0] = 'q'; + } + } + } + else if(rid_type == CAC_GROUP_RID) { + ZERO_STRUCT(openg); + openg.in.dom_hnd = dom_hnd; + openg.in.rid = rid; + openg.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenGroup(hnd, mem_ctx, &openg)) + printerr("Could not open group.", hnd->status); + else { + group_menu(hnd, mem_ctx, dom_hnd, openg.out.group_hnd); + + if(!cac_SamFlush(hnd, mem_ctx, &flush)) { + printerr("Lost handle while flushing SAM.", hnd->status); + /*we want to quit*/ + in[0] = 'q'; + } + } + } + else { + printf("Unknown RID/Name.\n"); + } + + break; + + case 'c': /*create account/group*/ + case 'C': + create_menu(hnd, mem_ctx, dom_hnd); + if(!cac_SamFlush(hnd, mem_ctx, &flush)) { + printerr("Lost handle while flushing SAM.", hnd->status); + /*we want to quit*/ + in[0] = 'q'; + } + break; + + case 'u': /*list users*/ + case 'U': + ZERO_STRUCT(enumu); + enumu.in.dom_hnd = dom_hnd; + enumu.in.acb_mask = ACB_NORMAL; + + printf("Users:\n"); + while(cac_SamEnumUsers(hnd, mem_ctx, &enumu)) { + print_rid_list(enumu.out.rids, enumu.out.names, enumu.out.num_users); + } + if(CAC_OP_FAILED(hnd->status)) + printerr("Error occured while enumerating users.", hnd->status); + break; + + case 'g': /*list groups*/ + case 'G': + ZERO_STRUCT(enumg); + enumg.in.dom_hnd = dom_hnd; + + while(cac_SamEnumGroups(hnd, mem_ctx, &enumg)) { + print_rid_list( enumg.out.rids, enumg.out.names, enumg.out.num_groups); + } + + if(CAC_OP_FAILED(hnd->status)) + printerr("Error occured while enumerating groups.", hnd->status); + break; + + case 'm': /*list machine accounts*/ + case 'M': + ZERO_STRUCT(enumu); + enumu.in.dom_hnd = dom_hnd; + enumu.in.acb_mask = ACB_WSTRUST; + + printf("Users:\n"); + while(cac_SamEnumUsers(hnd, mem_ctx, &enumu)) { + print_rid_list( enumu.out.rids, enumu.out.names, enumu.out.num_users); + } + if(CAC_OP_FAILED(hnd->status)) + printerr("Error occured while enumerating accounts.", hnd->status); + break; + + case 'q': /*quit*/ + case 'Q': + /*just do nothing*/ + break; + + default: + printf("Invalid Command.\n"); + } + } +} + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + struct SamOpenDomain sod; + + mem_ctx = talloc_init("cacusermgr"); + if(!mem_ctx) { + printf("Could not initialize Talloc Context\n"); + exit(-1); + } + + /**first initialize the server handle with what we have*/ + hnd = cac_NewServerHandle(True); + if(!hnd) { + printf("Could not create server handle\n"); + exit(-1); + } + + /*fill in the blanks*/ + if(!process_cmd_line(hnd, mem_ctx, argc, argv)) + usage(); + + if(!cac_Connect(hnd, NULL)) { + printf("Could not connect to server %s. %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + /*open the domain sam*/ + ZERO_STRUCT(sod); + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + printf("Could not open handle to domain SAM. %s\n", nt_errstr(hnd->status)); + goto cleanup; + } + + main_menu(hnd, mem_ctx, sod.out.dom_hnd); + +cleanup: + + if(sod.out.dom_hnd) + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + + if(sod.out.sam) + cac_SamClose(hnd, mem_ctx, sod.out.sam); + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/examples/libmsrpc/cacusermgr/cacusermgr.h b/examples/libmsrpc/cacusermgr/cacusermgr.h new file mode 100644 index 0000000000..01dbb60acf --- /dev/null +++ b/examples/libmsrpc/cacusermgr/cacusermgr.h @@ -0,0 +1,65 @@ +/* + * Unix SMB/CIFS implementation. + * cacusermgr definitions and includes. + * + * 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. */ + +#ifndef CACUSERMGR_H_ +#define CACUSERMGR_H_ + +#include "libmsrpc.h" +#include "includes.h" + +/*used for the simple pager - mgr_page()*/ +#define DEFAULT_SCREEN_LINES 20 + +/************** + * prototypes * + **************/ + +/*util.c*/ +void usage(); +int process_cmd_line(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, int argc, char **argv); +void mgr_getline(fstring line); +void mgr_page(uint32 line_count); +uint32 rid_or_name(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd, uint32 *rid, char **name); +char *get_new_password(TALLOC_CTX *mem_ctx); +void printerr(const char *msg, NTSTATUS status); +void print_rid_list(uint32 *rids, char **names, uint32 num_rids); +void print_lookup_records(CacLookupRidsRecord *map, uint32 num_rids); +int list_groups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd); +void list_privs(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, CacUserInfo *info); +void add_privs(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, CacUserInfo *info); +void list_users(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd); + +void mgr_GetAuthDataFn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword); + + +/*mgr_group.c*/ +void group_menu(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd, POLICY_HND *group_hnd); + +/*mgr_user.c*/ +void user_menu(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd, POLICY_HND *user_hnd); + +#endif /*CACUSERMGR_H_*/ diff --git a/examples/libmsrpc/cacusermgr/mgr_group.c b/examples/libmsrpc/cacusermgr/mgr_group.c new file mode 100644 index 0000000000..a936433e60 --- /dev/null +++ b/examples/libmsrpc/cacusermgr/mgr_group.c @@ -0,0 +1,210 @@ +/* + * Unix SMB/CIFS implementation. + * cacusermgr group implementation. + * + * 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 "cacusermgr.h" + +CacGroupInfo *get_group_info(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) { + struct SamGetGroupInfo getinfo; + + if(!hnd || !mem_ctx ||!group_hnd) + return NULL; + + ZERO_STRUCT(getinfo); + getinfo.in.group_hnd = group_hnd; + + if(!cac_SamGetGroupInfo(hnd, mem_ctx, &getinfo)) + printerr("Could not get group info.", hnd->status); + + return getinfo.out.info; +} + +void print_group_info(CacGroupInfo *info) { + if(!info) + return; + + printf(" Group Name : %s\n", info->name); + printf(" Description : %s\n", info->description); + printf(" Number of Members : %d\n", info->num_members); +} + +CacGroupInfo *modify_group_info(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) { + struct SamSetGroupInfo setinfo; + CacGroupInfo *info = NULL; + fstring tmp; + + info = get_group_info(hnd, mem_ctx, group_hnd); + + if(!info) + return NULL; + + printf("Description [%s]: ", info->description); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->description = talloc_strdup(mem_ctx, tmp); + + ZERO_STRUCT(setinfo); + setinfo.in.group_hnd = group_hnd; + setinfo.in.info = info; + + if(!cac_SamSetGroupInfo(hnd, mem_ctx, &setinfo)) { + printerr("Could not set info.", hnd->status); + info = NULL; + } + + return info; +} + +void group_menu(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd, POLICY_HND *group_hnd) { + CacGroupInfo *info = NULL; + int rid_type = 0; + + fstring in; + + char *buf; + + struct SamGetGroupMembers getmem; + struct SamGetNamesFromRids getnames; + struct SamAddGroupMember add; + struct SamRemoveGroupMember del; + + info = get_group_info(hnd, mem_ctx, group_hnd); + + printf("\n"); + print_group_info(info); + + while(in[0] != 'b' && in[0] != 'B' && in[0] != 'q' && in[0] != 'Q') { + printf("\n"); + printf("[m] List Group Members\n"); + printf("[a] Add User To Group\n"); + printf("[r] Remove User From Group\n"); + printf("[l] List Users\n"); + printf("[v] View Group Info\n"); + printf("[d] Set Group Description\n"); + printf("[x] Delete Group\n"); + printf("[b] Back\n\n"); + + printf("Command: "); + mgr_getline(in); + + printf("\n"); + + switch(in[0]) { + case 'a': /*add member to group*/ + case 'A': + ZERO_STRUCT(add); + add.in.group_hnd = group_hnd; + + printf("Enter RID or Name: "); + rid_type = rid_or_name(hnd, mem_ctx, dom_hnd, &add.in.rid, &buf); + + if(rid_type != CAC_USER_RID) { + printf("Invalid User.\n"); + break; + } + + if(!cac_SamAddGroupMember(hnd, mem_ctx, &add)) { + printerr("Could not add user to group.", hnd->status); + } + break; + + case 'r': /*remove user from group*/ + case 'R': + ZERO_STRUCT(del); + del.in.group_hnd = group_hnd; + + printf("Enter RID or Name: "); + rid_type = rid_or_name(hnd, mem_ctx, dom_hnd, &del.in.rid, &buf); + + if(rid_type != CAC_USER_RID) { + printf("Invalid User.\n"); + break; + } + + if(!cac_SamRemoveGroupMember(hnd, mem_ctx, &del)) { + printerr("Could not remove use from group.", hnd->status); + } + break; + + case 'l': /*list users*/ + case 'L': + list_users(hnd, mem_ctx, dom_hnd); + break; + + case 'm': /*list members*/ + case 'M': + ZERO_STRUCT(getmem); + getmem.in.group_hnd = group_hnd; + + if(!cac_SamGetGroupMembers(hnd, mem_ctx, &getmem)) { + printerr("Could not get members.", hnd->status); + break; + } + + ZERO_STRUCT(getnames); + getnames.in.dom_hnd = dom_hnd; + getnames.in.rids = getmem.out.rids; + getnames.in.num_rids = getmem.out.num_members; + + if(!cac_SamGetNamesFromRids(hnd, mem_ctx, &getnames)) { + printerr("Could not lookup names.", hnd->status); + break; + } + + printf("Group has %d members:\n", getnames.out.num_names); + print_lookup_records(getnames.out.map, getnames.out.num_names); + + break; + + case 'd': /*set description*/ + case 'D': + info = modify_group_info(hnd, mem_ctx, group_hnd); + + if(info) + printf("Set Group Info.\n"); + break; + + case 'v': /*view info*/ + case 'V': + info = get_group_info(hnd, mem_ctx, group_hnd); + print_group_info(info); + break; + + case 'x': /*delete group*/ + case 'X': + if(!cac_SamDeleteGroup(hnd, mem_ctx, group_hnd)) + printerr("Could Not Delete Group.", hnd->status); + + /*we want to go back to the main menu*/ + in[0] = 'b'; + break; + + case 'b': /*back*/ + case 'B': + case 'q': + case 'Q': + break; + + default: + printf("Invalid Command.\n"); + } + } + + cac_SamClose(hnd, mem_ctx, group_hnd); +} diff --git a/examples/libmsrpc/cacusermgr/mgr_user.c b/examples/libmsrpc/cacusermgr/mgr_user.c new file mode 100644 index 0000000000..7e2e56499f --- /dev/null +++ b/examples/libmsrpc/cacusermgr/mgr_user.c @@ -0,0 +1,416 @@ +/* + * Unix SMB/CIFS implementation. + * cacusermgr user implementation. + * + * 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 "cacusermgr.h" + +void print_user_info(CacUserInfo *info) { + printf("\n"); + printf(" User Name : %s\n", info->username); + printf(" Full Name : %s\n", info->full_name); + printf(" Home Dir : %s\n", info->home_dir); + printf(" Home Drive : %s\n", info->home_drive); + printf(" Profile Path : %s\n", info->profile_path); + printf(" Logon Script : %s\n", info->logon_script); + printf(" Description : %s\n", info->description); + printf(" Workstations : %s\n", info->workstations); + printf(" Remote Dial : %s\n", info->dial); + + printf(" Logon Time : %s\n", http_timestring(info->logon_time)); + printf(" Logoff Time : %s\n", http_timestring(info->logoff_time)); + printf(" Kickoff Time : %s\n", http_timestring(info->kickoff_time)); + printf(" Pass last set : %s\n", http_timestring(info->pass_last_set_time)); + printf(" Pass can set : %s\n", http_timestring(info->pass_can_change_time)); + printf(" Pass must set : %s\n", http_timestring(info->pass_must_change_time)); + + printf(" User RID : 0x%x\n", info->rid); + printf(" Group RID : 0x%x\n", info->group_rid); + printf(" User Type : "); + + if(info->acb_mask & ACB_NORMAL) + printf("Normal User\n"); + else if(info->acb_mask & ACB_TEMPDUP) + printf("Temporary Duplicate Account\n"); + else if(info->acb_mask & ACB_DOMTRUST) + printf("Inter-Domain Trust Account\n"); + else if(info->acb_mask & ACB_WSTRUST) + printf("Workstation Trust Account\n"); + else if(info->acb_mask & ACB_SVRTRUST) + printf("Server Trust Account\n"); + else + printf("\n"); + + printf(" Disabled : %s\n", (info->acb_mask & ACB_DISABLED) ? "Yes" : "No"); + printf(" Locked : %s\n", (info->acb_mask & ACB_AUTOLOCK) ? "Yes" : "No"); + printf(" Pass Expires : %s\n", (info->acb_mask & ACB_PWNOEXP) ? "No" : "Yes"); + printf(" Pass Required : %s\n", (info->acb_mask & ACB_PWNOTREQ) ? "No" : "Yes"); + +} + +CacUserInfo *modify_user_info(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) { + CacUserInfo *info = NULL; + fstring tmp; + + struct SamGetUserInfo getinfo; + struct SamSetUserInfo setinfo; + + ZERO_STRUCT(getinfo); + ZERO_STRUCT(setinfo); + + getinfo.in.user_hnd = user_hnd; + + if(!cac_SamGetUserInfo(hnd, mem_ctx, &getinfo)) { + printerr("Could not get user info.", hnd->status); + return NULL; + } + + info = getinfo.out.info; + + printf("\n"); + printf(" User Name [%s]: ", info->username); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->username = talloc_strdup(mem_ctx, tmp); + + printf(" Full Name [%s]: ", info->full_name); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->full_name = talloc_strdup(mem_ctx, tmp); + + printf(" Description [%s]: ", info->description); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->description = talloc_strdup(mem_ctx, tmp); + + printf(" Home Dir [%s]: ", info->home_dir); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->home_dir = talloc_strdup(mem_ctx, tmp); + + printf(" Home Drive [%s]: ", info->home_drive); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->home_drive = talloc_strdup(mem_ctx, tmp); + + printf(" Profile Path [%s]: ", info->profile_path); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->profile_path = talloc_strdup(mem_ctx, tmp); + + printf(" Logon Script [%s]: ", info->logon_script); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->logon_script = talloc_strdup(mem_ctx, tmp); + + printf(" Workstations [%s]: ", info->workstations); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->workstations = talloc_strdup(mem_ctx, tmp); + + printf(" Remote Dial [%s]: ", info->dial); + mgr_getline(tmp); + if(tmp[0] != '\0') + info->dial = talloc_strdup(mem_ctx, tmp); + + printf(" Disabled [%s] (y/n): ", (info->acb_mask & ACB_DISABLED) ? "Yes" : "No"); + mgr_getline(tmp); + if(tmp[0] == 'y' || tmp[0] == 'Y') + info->acb_mask |= ACB_DISABLED; + else if(tmp[0] == 'n' || tmp[0] == 'N') + info->acb_mask ^= (info->acb_mask & ACB_DISABLED) ? ACB_DISABLED : 0x0; + + printf(" Pass Expires [%s] (y/n): ", (info->acb_mask & ACB_PWNOEXP) ? "No" : "Yes"); + mgr_getline(tmp); + if(tmp[0] == 'n' || tmp[0] == 'N') + info->acb_mask |= ACB_PWNOEXP; + else if(tmp[0] == 'y' || tmp[0] == 'Y') + info->acb_mask ^= (info->acb_mask & ACB_PWNOEXP) ? ACB_PWNOEXP : 0x0; + + printf(" Pass Required [%s] (y/n): ", (info->acb_mask & ACB_PWNOTREQ) ? "No" : "Yes"); + mgr_getline(tmp); + if(tmp[0] == 'n' || tmp[0] == 'N') + info->acb_mask |= ACB_PWNOTREQ; + else if(tmp[0] == 'y' || tmp[0] == 'Y') + info->acb_mask ^= (info->acb_mask & ACB_PWNOTREQ) ? ACB_PWNOTREQ : 0x0; + + setinfo.in.user_hnd = user_hnd; + setinfo.in.info = info; + + if(!cac_SamSetUserInfo(hnd, mem_ctx, &setinfo)) { + printerr("Could not set user info.", hnd->status); + } + + return info; +} + +void add_user_to_group(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, CacUserInfo *info, POLICY_HND *dom_hnd) { + int rid_type = 0; + + char *tmp = NULL; + + struct SamOpenGroup og; + struct SamAddGroupMember add; + + ZERO_STRUCT(og); + ZERO_STRUCT(add); + + printf("Group RID or Name:"); + + og.in.dom_hnd = dom_hnd; + og.in.access = MAXIMUM_ALLOWED_ACCESS; + rid_type = rid_or_name(hnd, mem_ctx, dom_hnd, &og.in.rid, &tmp); + + if(!cac_SamOpenGroup(hnd, mem_ctx, &og)) { + printerr("Could not open group.", hnd->status); + return; + } + + add.in.group_hnd = og.out.group_hnd; + add.in.rid = info->rid; + + if(!cac_SamAddGroupMember(hnd, mem_ctx, &add)) { + printerr("Could not add user to group.", hnd->status); + } + + cac_SamClose(hnd, mem_ctx, og.out.group_hnd); +} + +void remove_user_from_group(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, CacUserInfo *info, POLICY_HND *dom_hnd) { + int rid_type = 0; + + char *tmp = NULL; + + struct SamOpenGroup og; + struct SamRemoveGroupMember del; + + ZERO_STRUCT(og); + ZERO_STRUCT(del); + + printf("Group RID or Name:"); + + og.in.dom_hnd = dom_hnd; + og.in.access = MAXIMUM_ALLOWED_ACCESS; + rid_type = rid_or_name(hnd, mem_ctx, dom_hnd, &og.in.rid, &tmp); + + if(!cac_SamOpenGroup(hnd, mem_ctx, &og)) { + printerr("Could not open group.", hnd->status); + return; + } + + del.in.group_hnd = og.out.group_hnd; + del.in.rid = info->rid; + + if(!cac_SamRemoveGroupMember(hnd, mem_ctx, &del)) { + printerr("Could not add user to group.", hnd->status); + } + + cac_SamClose(hnd, mem_ctx, og.out.group_hnd); +} + +void user_menu(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd, POLICY_HND *user_hnd) { + fstring in; + + struct SamGetUserInfo getinfo; + struct SamSetPassword setpass; + struct SamGetGroupsForUser groups; + struct SamGetNamesFromRids gnfr; + + CacUserInfo *info = NULL; + + if(!hnd || !mem_ctx || !user_hnd) { + printf("Must open user.\n"); + return; + } + + /*get the userinfo and print it out*/ + ZERO_STRUCT(getinfo); + getinfo.in.user_hnd = user_hnd; + + if(!cac_SamGetUserInfo(hnd, mem_ctx, &getinfo)) { + printerr("Could not get info.", hnd->status); + info = NULL; + } + else { + info = getinfo.out.info; + print_user_info(info); + } + + /*now deal with the menu*/ + in[0] = '\0'; + while(in[0] != 'b' && in[0] != 'B' && in[0] != 'q' && in[0] != 'Q') { + printf("\n"); + printf("[s] Set Password\n"); + + if(info && (info->acb_mask & ACB_DISABLED)) + printf("[e] Enable User\n"); + else if(info) + printf("[d] Disable User\n"); + + printf("[v] View User Info\n"); + printf("[m] Modify User Info\n"); + printf("[x] Delete User\n\n"); + + printf("[g] List Group Membership\n"); + printf("[a] Add User To Group\n"); + printf("[l] List Domain Groups\n"); + printf("[r] Remove User From Group\n\n"); + + printf("[b] Back\n\n"); + + printf("Command: "); + mgr_getline(in); + + printf("\n"); + + switch(in[0]) { + case 'g': /*list group membership*/ + case 'G': + ZERO_STRUCT(groups); + groups.in.user_hnd = user_hnd; + + if(!cac_SamGetGroupsForUser(hnd, mem_ctx, &groups)) { + printerr("Could not get groups.", hnd->status); + break; + } + + ZERO_STRUCT(gnfr); + gnfr.in.dom_hnd = dom_hnd; + gnfr.in.rids = groups.out.rids; + gnfr.in.num_rids = groups.out.num_groups; + + if(!cac_SamGetNamesFromRids(hnd, mem_ctx, &gnfr)) { + printerr("Could not map RIDs to names.", hnd->status); + break; + } + + print_lookup_records(gnfr.out.map, gnfr.out.num_names); + + break; + case 's': /*reset password*/ + case 'S': + ZERO_STRUCT(setpass); + setpass.in.user_hnd = user_hnd; + setpass.in.password = get_new_password(mem_ctx); + + if(!setpass.in.password) { + printf("Out of memory.\n"); + break; + } + + if(!cac_SamSetPassword(hnd, mem_ctx, &setpass)) { + printerr("Could not set password.", hnd->status); + } + else { + printf("Reset password.\n"); + } + break; + + case 'e': /*enable user*/ + case 'E': + if(info && !(info->acb_mask & ACB_DISABLED)) + break; + + if(!cac_SamEnableUser(hnd, mem_ctx, user_hnd)) { + printerr("Could not enable user.", hnd->status); + } + else { + printf("Enabled User.\n"); + /*toggle the disabled ACB bit in our local copy of the info*/ + info->acb_mask ^= ACB_DISABLED; + } + break; + + case 'd': /*disable user*/ + case 'D': + if(info && (info->acb_mask & ACB_DISABLED)) + break; + + if(!cac_SamDisableUser(hnd, mem_ctx, user_hnd)) { + printerr("Could not disable user.", hnd->status); + } + else { + printf("Disabled User.\n"); + /*toggle the disabled ACB bit in our local copy of the info*/ + info->acb_mask ^= ACB_DISABLED; + } + break; + + case 'v': /*view user info*/ + case 'V': + ZERO_STRUCT(getinfo); + getinfo.in.user_hnd = user_hnd; + + if(!cac_SamGetUserInfo(hnd, mem_ctx, &getinfo)) { + printerr("Could not get info.", hnd->status); + info = NULL; + } + else { + info = getinfo.out.info; + print_user_info(info); + } + + break; + + case 'm': /*modify user info*/ + case 'M': + info = modify_user_info(hnd, mem_ctx, user_hnd); + + if(info) + printf("Updated user info.\n"); + break; + + case 'l': /*list domain groups*/ + case 'L': + list_groups(hnd, mem_ctx, dom_hnd); + break; + + case 'a': /*add user to group*/ + case 'A': + add_user_to_group(hnd, mem_ctx, info, dom_hnd); + break; + + case 'r': /*remove user from group*/ + case 'R': + remove_user_from_group(hnd, mem_ctx, info, dom_hnd); + break; + + case 'x': /*delete user*/ + case 'X': + if(!cac_SamDeleteUser(hnd, mem_ctx, user_hnd)) + printerr("Could not delete user.", hnd->status); + + /*we want to go back to the main menu*/ + in[0] = 'b'; + break; + + case 'b': /*back*/ + case 'B': + case 'q': + case 'Q': + /*do nothing*/ + break; + + default: + printf("Invalid command.\n"); + } + } + + /*close the user before returning*/ + cac_SamClose(hnd, mem_ctx, user_hnd); +} diff --git a/examples/libmsrpc/cacusermgr/util.c b/examples/libmsrpc/cacusermgr/util.c new file mode 100644 index 0000000000..1629911812 --- /dev/null +++ b/examples/libmsrpc/cacusermgr/util.c @@ -0,0 +1,343 @@ +/* + * Unix SMB/CIFS implementation. + * cacusermgr utility functions. + * + * 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 "cacusermgr.h" + +/*prints usage and quits*/ +void usage() { + printf("Usage:\n"); + printf(" cacusermgr [options] server\n\n"); + printf("options:\n"); + printf(" -u USERNAME Username to login with\n"); + printf(" -d/-w DOMAIN Domain name\n"); + printf(" -D LEVEL Debug level\n"); + printf(" -h Print this message\n"); + + exit(1); +} + +/*initializes values in the server handle from the command line returns 0 if there is a problem, non-zero if everything is ok*/ +int process_cmd_line(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, int argc, char **argv) { + char op; + + if(!hnd || !mem_ctx || !argc) + return 0; + + while( (op = getopt(argc, argv, "u:U:d:w:W:D:h")) != -1) { + switch(op) { + case 'u': /*username*/ + case 'U': + if(optarg) + strncpy(hnd->username, optarg, sizeof(fstring)); + else + usage(); + break; + + case 'd': /*domain name*/ + case 'w': + case 'W': + if(optarg) + strncpy(hnd->domain, optarg, sizeof(fstring)); + else + usage(); + break; + + case 'D': /*debug level*/ + if(optarg) + hnd->debug = atoi(optarg); + else + usage(); + break; + + case 'h': /*help*/ + usage(); + break; + + case '?': + default: + printf("Unknown option -%c\n", op); + usage(); + } + } + + if(optind >= argc) + usage(); + + /*whatever is less should be the server*/ + strncpy(hnd->server, argv[optind], sizeof(fstring)); + + return 1; +} + +void mgr_getline(fstring line) { + + fgets(line, sizeof(fstring), stdin); + + if(line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + +} + +/*this is pretty similar to the other get_auth_data_fn's*/ +void mgr_GetAuthDataFn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword) + +{ + char temp[sizeof(fstring)]; + + static char authUsername[sizeof(fstring)]; + static char authWorkgroup[sizeof(fstring)]; + static char authPassword[sizeof(fstring)]; + static char authSet = 0; + + char *pass = NULL; + + if (authSet) + { + strncpy(pWorkgroup, authWorkgroup, maxLenWorkgroup - 1); + strncpy(pUsername, authUsername, maxLenUsername - 1); + strncpy(pPassword, authPassword, maxLenPassword - 1); + } + else + { + if(pWorkgroup[0] != '\0') { + strncpy(authWorkgroup, pWorkgroup, maxLenWorkgroup - 1); + } + else { + d_printf("Domain: [%s] ", pWorkgroup); + mgr_getline(pWorkgroup); + + if (temp[0] != '\0') + { + strncpy(pWorkgroup, temp, maxLenWorkgroup - 1); + strncpy(authWorkgroup, temp, maxLenWorkgroup - 1); + } + } + + + if(pUsername[0] != '\0') { + strncpy(authUsername, pUsername, maxLenUsername - 1); + } + else { + d_printf("Username: [%s] ", pUsername); + mgr_getline(pUsername); + + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + + if (temp[0] != '\0') + { + strncpy(pUsername, temp, maxLenUsername - 1); + strncpy(authUsername, pUsername, maxLenUsername - 1); + } + } + if(pPassword[0] != '\0') { + strncpy(authPassword, pPassword, maxLenPassword - 1); + } + else { + pass = getpass("Password: "); + if (pass) + fstrcpy(temp, pass); + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + if (temp[0] != '\0') + { + strncpy(pPassword, temp, maxLenPassword - 1); + strncpy(authPassword, pPassword, maxLenPassword - 1); + } + } + authSet = 1; + } +} + +void mgr_page(uint32 line_count) { + + if( (line_count % DEFAULT_SCREEN_LINES) != 0) + return; + + printf("--Press enter to continue--\n"); + getchar(); +} + +/*reads a line from stdin, figures out if it is a RID or name, gets a CacLookupRidsRecord and then returns the type*/ +uint32 rid_or_name(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd, uint32 *rid, char **name) { + fstring line; + + BOOL is_rid = False; + uint32 rid_type = 0; + + struct SamGetNamesFromRids getnames; + struct SamGetRidsFromNames getrids; + + mgr_getline(line); + + if(strncmp(line, "0x", 2) == 0) { + /*then this is a RID*/ + sscanf( (line + 2), "%x", rid); + is_rid = True; + } + else { + /*then this is a name*/ + *name = talloc_strdup(mem_ctx, line); + } + + if(is_rid) { + ZERO_STRUCT(getnames); + + getnames.in.dom_hnd = dom_hnd; + getnames.in.rids = rid; + getnames.in.num_rids = 1; + + cac_SamGetNamesFromRids(hnd, mem_ctx, &getnames); + + if(getnames.out.num_names > 0) + rid_type = getnames.out.map[0].type; + + } + else { + ZERO_STRUCT(getrids); + + getrids.in.dom_hnd = dom_hnd; + getrids.in.names = name; + getrids.in.num_names = 1; + + cac_SamGetRidsFromNames(hnd, mem_ctx, &getrids); + + if(getrids.out.num_rids > 0) { + rid_type = getrids.out.map[0].type; + + /*send back the RID so cac_SamOpenXX() doesn't have to look it up*/ + *rid = getrids.out.map[0].rid; + } + } + + return rid_type; +} + +/*print's out some common error messages*/ +void printerr(const char *msg, NTSTATUS status) { + if(NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) + printf("%s You do not have sufficient rights.\n", msg); + + else if(NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) + printf("%s No such user.\n", msg); + + else if(NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_GROUP)) + printf("%s No such group.\n", msg); + + else if(NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) + printf("%s User already exists.\n", msg); + + else if(NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) + printf("%s Group already exists.\n", msg); + + else + printf("%s %s.\n", msg, nt_errstr(status)); +} + +char *get_new_password(TALLOC_CTX *mem_ctx) { + char *pass1 = NULL; + + pass1 = getpass("Enter new password: "); + + return talloc_strdup(mem_ctx, pass1); +} + +void print_rid_list(uint32 *rids, char **names, uint32 num_rids) { + uint32 i = 0; + + if(!names || !rids) + return; + + printf(" RID Name\n"); + + while(i < num_rids) { + printf("[0x%x] [%s]\n", rids[i], names[i]); + + i++; + + mgr_page(i); + } +} + +void print_lookup_records(CacLookupRidsRecord *map, uint32 num_rids) { + uint32 i = 0; + + if(!map) + return; + + printf("RID Name\n"); + + while(i < num_rids) { + if(map[i].found) { + printf("[0x%x] [%s]\n", map[i].rid, map[i].name); + } + + i++; + + mgr_page(i); + } +} + +int list_groups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd) { + struct SamEnumGroups eg; + + if(!hnd || !mem_ctx || !dom_hnd) + return 0; + + ZERO_STRUCT(eg); + eg.in.dom_hnd = dom_hnd; + + while(cac_SamEnumGroups(hnd, mem_ctx, &eg)) + print_rid_list(eg.out.rids, eg.out.names, eg.out.num_groups); + + if(CAC_OP_FAILED(hnd->status)) { + printerr("Could not enumerate groups.", hnd->status); + return 0; + } + + return 1; +} + +void list_users(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *dom_hnd) { + struct SamEnumUsers eu; + + if(!hnd || !mem_ctx || !dom_hnd) + return; + + ZERO_STRUCT(eu); + eu.in.dom_hnd = dom_hnd; + + while(cac_SamEnumUsers(hnd, mem_ctx, &eu)) + print_rid_list(eu.out.rids, eu.out.names, eu.out.num_users); + + if(CAC_OP_FAILED(hnd->status)) + printerr("Could not enumerate users.", hnd->status); +} diff --git a/examples/libmsrpc/test/Makefile b/examples/libmsrpc/test/Makefile new file mode 100644 index 0000000000..95fa5effa5 --- /dev/null +++ b/examples/libmsrpc/test/Makefile @@ -0,0 +1,99 @@ +CC=gcc +INCLUDES= -I`pwd` -I../../../source/ -I../../../source/include -I../../../source/ubiqx + +DEFS= -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE +#CFLAGS= -O -D_SAMBA_BUILD_ -gstabs -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER -Wdeclaration-after-statement -g $(INCLUDES) $(DEFS) -fPIC + +CFLAGS= -g -Wall -ansi $(INCLUDES) + +LDFLAGS=-L. -L../../bin/ +LIBS=../../../source/bin/libmsrpc.so + +TESTS= lsapol lsaq lsaenum lsaenumprivs lsapriv ear \ + regkey regopenkey regkeyenum regvalenum regsetval regqueryval regdelete security \ + adduser samenum samlookup samgroup enable disable dominfo samuser \ + svc \ + smbc + +all: $(TESTS) + +lsapol: lsa/lsapol.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +lsapriv: lsa/lsapriv.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +lsaq: lsa/lsaq.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +lsaenum: lsa/lsaenum.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +lsaenumprivs: lsa/lsaenumprivs.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +lsaaddrights: lsa/lsaaddrights.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +ear: lsa/ear.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +regkey: reg/regkey.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +regopenkey: reg/regopenkey.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +regkeyenum: reg/regkeyenum.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +regkeycreate: reg/regkeycreate.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +regvalenum: reg/regvalenum.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +regsetval: reg/regsetval.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +regqueryval: reg/regqueryval.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +regdelete: reg/regdelete.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +security: reg/security.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +adduser: sam/adduser.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +samenum: sam/samenum.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +samlookup: sam/samlookup.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +samgroup: sam/samgroup.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +enable: sam/enable.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +disable: sam/disable.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +samuser: sam/samuser.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +dominfo: sam/dominfo.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +svc: svcctl/svc.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) + +smbc: smbc_test/smbc.o test_util.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< test_util.o $(LIBS) ../../../source/bin/libsmbclient.so + +clean: + rm -f $(TESTS) *.o lsa/*.o reg/*.o sam/*.o diff --git a/examples/libmsrpc/test/README b/examples/libmsrpc/test/README new file mode 100644 index 0000000000..9352905b5b --- /dev/null +++ b/examples/libmsrpc/test/README @@ -0,0 +1,8 @@ +This code was written to test the different library functions. However, a simple example of almost every libmsrpc call can be found +in this code. + +notes: most of the programs use a modified smbc_get_auth_data_fn which will not prompt for a user/domain/password so expect flaky results +if you run the tests with just a server, ie: svc remote_machine + + +If you get errors about the libmsrpc.so object, make sure your LD_LIBRARY_PATH points to /path/to/samba3/source/bin diff --git a/examples/libmsrpc/test/lsa/ear.c b/examples/libmsrpc/test/lsa/ear.c new file mode 100644 index 0000000000..8a8202543d --- /dev/null +++ b/examples/libmsrpc/test/lsa/ear.c @@ -0,0 +1,261 @@ +/* connects to an LSA, asks for a list of server names, prints out their sids, then looks up their names from the sids and prints them out again + * if you run as lsaq -p, then it will simulate a partial success for cac_GetNamesFromSids. It will try to lookup the server's local and domain sids + */ + + +#include "libmsrpc.h" +#include "includes.h" + +void fill_conn_info(CacServerHandle *hnd) { + pstring domain; + pstring username; + pstring password; + pstring server; + + fprintf(stdout, "Enter domain name: "); + fscanf(stdin, "%s", domain); + + fprintf(stdout, "Enter username: "); + fscanf(stdin, "%s", username); + + fprintf(stdout, "Enter password (no input masking): "); + fscanf(stdin, "%s", password); + + fprintf(stdout, "Enter server (ip or name): "); + fscanf(stdin, "%s", server); + + hnd->domain = SMB_STRDUP(domain); + hnd->username = SMB_STRDUP(username); + hnd->password = SMB_STRDUP(password); + hnd->server = SMB_STRDUP(server); +} + +void get_server_names(TALLOC_CTX *mem_ctx, int *num_names, char ***names) { + int i = 0; + pstring tmp; + + fprintf(stdout, "How many names do you want to lookup?: "); + fscanf(stdin, "%d", num_names); + + *names = TALLOC_ARRAY(mem_ctx, char *, *num_names); + if(*names == NULL) { + fprintf(stderr, "No memory for allocation\n"); + exit(-1); + } + + for(i = 0; i < *num_names; i++) { + fprintf(stdout, "Enter name: "); + fscanf(stdin, "%s", tmp); + (*names)[i] = talloc_strdup(mem_ctx, tmp); + } +} + +int main(int argc, char **argv) { + int i; + int result; + char **names; + int num_names; + int num_sids; + CacServerHandle *hnd = NULL; + POLICY_HND *lsa_pol = NULL; + TALLOC_CTX *mem_ctx = NULL; + + DOM_SID *sid_buf = NULL; + + BOOL sim_partial = False; + + if(argc > 1 && strcmp(argv[1], "-p") == 0) + sim_partial = True; + + mem_ctx = talloc_init("lsaq"); + + hnd = cac_NewServerHandle(False); + + fill_conn_info(hnd); + + get_server_names(mem_ctx, &num_names, &names); + + /*connect to the PDC and open a LSA handle*/ + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error %s.\n", nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + exit(-1); + } + + fprintf(stdout, "Connected to server: %s\n", hnd->server); + + struct LsaOpenPolicy lop; + ZERO_STRUCT(lop); + + lop.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + lop.in.security_qos = True; + + if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) { + fprintf(stderr, "Could not get lsa policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + exit(-1); + } + + fprintf(stdout, "Opened Policy Handle\n"); + + /*just to make things neater*/ + lsa_pol = lop.out.pol; + + /*fetch the local sid and domain sid for the pdc*/ + + struct LsaFetchSid fsop; + ZERO_STRUCT(fsop); + + fsop.in.pol = lsa_pol; + fsop.in.info_class = (CAC_LOCAL_INFO|CAC_DOMAIN_INFO); + + fprintf(stdout, "fetching SID info for %s\n", hnd->server); + + result = cac_LsaFetchSid(hnd, mem_ctx, &fsop); + if(!result) { + fprintf(stderr, "Could not get sid for server: %s\n. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + exit(-1); + } + + if(result == CAC_PARTIAL_SUCCESS) { + fprintf(stdout, "could not retrieve both domain and local information\n"); + } + + + fprintf(stdout, "Fetched SID info for %s\n", hnd->server); + if(fsop.out.local_sid != NULL) + fprintf(stdout, " domain: %s. Local SID: %s\n", fsop.out.local_sid->domain, sid_string_static(&fsop.out.local_sid->sid)); + + if(fsop.out.domain_sid != NULL) + fprintf(stdout, " domain: %s, Domain SID: %s\n", fsop.out.domain_sid->domain, sid_string_static(&fsop.out.domain_sid->sid)); + + fprintf(stdout, "Looking up sids\n"); + + + struct LsaGetSidsFromNames gsop; + ZERO_STRUCT(gsop); + + gsop.in.pol = lsa_pol; + gsop.in.num_names = num_names; + gsop.in.names = names; + + result = cac_LsaGetSidsFromNames(hnd, mem_ctx, &gsop); + + if(!result) { + fprintf(stderr, "Could not lookup any sids!\n Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + if(result == CAC_PARTIAL_SUCCESS) { + fprintf(stdout, "Not all names could be looked up.\nThe following names were not found:\n"); + + for(i = 0; i < (num_names - gsop.out.num_found); i++) { + fprintf(stdout, " %s\n", gsop.out.unknown[i]); + } + + fprintf(stdout, "\n"); + } + + /*buffer the sids so we can look them up back to names*/ + num_sids = (sim_partial) ? gsop.out.num_found + 2: gsop.out.num_found; + sid_buf = TALLOC_ARRAY(mem_ctx, DOM_SID, num_sids); + + fprintf(stdout, "%d names were resolved: \n", gsop.out.num_found); + + + i = 0; + while(i < gsop.out.num_found) { + fprintf(stdout, " Name: %s\n SID: %s\n\n", gsop.out.sids[i].name, sid_string_static(&gsop.out.sids[i].sid)); + + sid_buf[i] = gsop.out.sids[i].sid; + + printf("Attempting to open account\n"); + + struct LsaOpenAccount loa; + ZERO_STRUCT(loa); + + loa.in.pol = lsa_pol; + loa.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + loa.in.sid = &gsop.out.sids[i].sid; + + if(!cac_LsaOpenAccount(hnd, mem_ctx, &loa)) { + fprintf(stderr, "Could not open account.\n Error: %s\n", nt_errstr(hnd->status)); + } + + printf("\nEnumerating privs:"); + struct LsaEnumAccountRights earop; + ZERO_STRUCT(earop); + + earop.in.pol = lsa_pol; + + earop.in.sid = &gsop.out.sids[i].sid; + + if(!cac_LsaEnumAccountRights(hnd, mem_ctx, &earop)) { + fprintf(stderr, "Could not enumerate account rights.\n Error: %s\n", nt_errstr(hnd->status)); + } + + int j; + printf( "Rights: "); + for(j = 0; j < earop.out.num_privs; j++) { + printf(" %s\n", earop.out.priv_names[j]); + } + + printf("\n"); + + + i++; + } + + /*if we want a partial success to occur below, then add the server's SIDs to the end of the array*/ + if(sim_partial) { + sid_buf[i] = fsop.out.local_sid->sid; + sid_buf[i+1] = fsop.out.domain_sid->sid; + } + + fprintf(stdout, "Looking up Names from SIDs\n"); + + struct LsaGetNamesFromSids gnop; + ZERO_STRUCT(gnop); + + gnop.in.pol = lsa_pol; + gnop.in.num_sids = num_sids; + gnop.in.sids = sid_buf; + + result = cac_LsaGetNamesFromSids(hnd, mem_ctx, &gnop); + + if(!result) { + fprintf(stderr, "Could not lookup any names!.\n Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + if(result == CAC_PARTIAL_SUCCESS) { + fprintf(stdout, "\nNot all SIDs could be looked up.\n. The following SIDs were not found:\n"); + + for(i = 0; i < (num_sids - gnop.out.num_found); i++) { + fprintf(stdout, "SID: %s\n", sid_string_static(&gnop.out.unknown[i])); + } + + fprintf(stdout, "\n"); + } + + fprintf(stdout, "%d SIDs were resolved: \n", gnop.out.num_found); + for(i = 0; i < gnop.out.num_found; i++) { + fprintf(stdout, " SID: %s\n Name: %s\n", sid_string_static(&gnop.out.sids[i].sid), gsop.out.sids[i].name); + } + +done: + + if(!cac_LsaClosePolicy(hnd, mem_ctx, lsa_pol)) { + fprintf(stderr, "Could not close LSA policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + } + else { + fprintf(stdout, "Closed Policy handle.\n"); + } + + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/examples/libmsrpc/test/lsa/lsaenum.c b/examples/libmsrpc/test/lsa/lsaenum.c new file mode 100644 index 0000000000..d4ad4f73aa --- /dev/null +++ b/examples/libmsrpc/test/lsa/lsaenum.c @@ -0,0 +1,96 @@ +/*enumerates SIDs*/ + +#include "libmsrpc.h" +#include "includes.h" + +int main(int argc, char **argv) { + + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + POLICY_HND *pol = NULL; + + int i; + int max_sids; + + mem_ctx = talloc_init("lsaenum"); + + hnd = cac_NewServerHandle(True); + + printf("Enter server to connect to: "); + fscanf(stdin, "%s", hnd->server); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s.\n errno: %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + printf("How many sids do you want to grab at a time? "); + fscanf(stdin, "%d", &max_sids); + + struct LsaOpenPolicy lop; + ZERO_STRUCT(lop); + + lop.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + lop.in.security_qos = True; + + + if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) { + fprintf(stderr, "Could not open policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + exit(-1); + } + + pol = lop.out.pol; + + + struct LsaEnumSids esop; + ZERO_STRUCT(esop); + esop.in.pol = pol; + /*grab a couple at a time to demonstrate multiple calls*/ + esop.in.pref_max_sids = max_sids; + + printf("Attempting to fetch SIDs %d at a time\n", esop.in.pref_max_sids); + + while(cac_LsaEnumSids(hnd, mem_ctx, &esop)) { + + printf("\nEnumerated %d sids: \n", esop.out.num_sids); + for(i = 0; i < esop.out.num_sids; i++) { + printf(" SID: %s\n", sid_string_static(&esop.out.sids[i])); + } + + printf("Resolving names\n"); + + struct LsaGetNamesFromSids gnop; + ZERO_STRUCT(gnop); + + gnop.in.pol = pol; + gnop.in.sids = esop.out.sids; + gnop.in.num_sids = esop.out.num_sids; + + if(!cac_LsaGetNamesFromSids(hnd, mem_ctx, &gnop)) { + fprintf(stderr, "Could not resolve names.\n Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + printf("\nResolved %d names: \n", gnop.out.num_found); + for(i = 0; i < gnop.out.num_found; i++) { + printf(" SID: %s\n", sid_string_static(&gnop.out.sids[i].sid)); + printf(" Name: %s\n", gnop.out.sids[i].name); + } + + /*clean up a little*/ + talloc_free(gnop.out.sids); + } + +done: + if(!cac_LsaClosePolicy(hnd, mem_ctx, pol)) { + fprintf(stderr, "Could not close policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + } + + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/examples/libmsrpc/test/lsa/lsaenumprivs.c b/examples/libmsrpc/test/lsa/lsaenumprivs.c new file mode 100644 index 0000000000..8b5c9deca6 --- /dev/null +++ b/examples/libmsrpc/test/lsa/lsaenumprivs.c @@ -0,0 +1,79 @@ +/*enumerates privileges*/ + +#include "libmsrpc.h" +#include "includes.h" + +#define MAX_STRING_LEN 50; + +int main() { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + POLICY_HND *lsa_pol = NULL; + + int i; + + mem_ctx = talloc_init("lsatrust"); + + hnd = cac_NewServerHandle(True); + + printf("Server: "); + fscanf(stdin, "%s", hnd->server); + + printf("Connecting to server....\n"); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s\n errno %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + printf("Connected to server\n"); + + struct LsaOpenPolicy lop; + ZERO_STRUCT(lop); + + lop.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + lop.in.security_qos = True; + + + if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) { + fprintf(stderr, "Could not open policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + exit(-1); + } + + lsa_pol = lop.out.pol; + + printf("Enumerating Privileges\n"); + + struct LsaEnumPrivileges ep; + ZERO_STRUCT(ep); + + ep.in.pol = lsa_pol; + ep.in.pref_max_privs = 50; + + while(cac_LsaEnumPrivileges(hnd, mem_ctx, &ep)) { + printf(" Enumerated %d privileges\n", ep.out.num_privs); + + for(i = 0; i < ep.out.num_privs; i++) { + printf("\"%s\"\n", ep.out.priv_names[i]); + } + + printf("\n"); + } + + if(CAC_OP_FAILED(hnd->status)) { + fprintf(stderr, "Error while enumerating privileges.\n Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + +done: + if(!cac_LsaClosePolicy(hnd, mem_ctx, lsa_pol)) { + fprintf(stderr, "Could not close policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + } + + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/examples/libmsrpc/test/lsa/lsapol.c b/examples/libmsrpc/test/lsa/lsapol.c new file mode 100644 index 0000000000..58407e4343 --- /dev/null +++ b/examples/libmsrpc/test/lsa/lsapol.c @@ -0,0 +1,87 @@ +/* simple test code, opens and closes an LSA policy handle using libmsrpc, careful.. there's no password input masking*/ + +#include "includes.h" +#include "libmsrpc.h" + +void fill_conn_info(CacServerHandle *hnd) { + pstring domain; + pstring username; + pstring password; + pstring server; + + fprintf(stdout, "Enter domain name: "); + fscanf(stdin, "%s", domain); + + fprintf(stdout, "Enter username: "); + fscanf(stdin, "%s", username); + + fprintf(stdout, "Enter password (no input masking): "); + fscanf(stdin, "%s", password); + + fprintf(stdout, "Enter server (ip or name): "); + fscanf(stdin, "%s", server); + + hnd->domain = SMB_STRDUP(domain); + hnd->username = SMB_STRDUP(username); + hnd->password = SMB_STRDUP(password); + hnd->server = SMB_STRDUP(server); +} + +int main() { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx; + struct LsaOpenPolicy op; + + mem_ctx = talloc_init("lsapol"); + + + hnd = cac_NewServerHandle(False); + + /*this line is unnecesary*/ + cac_SetAuthDataFn(hnd, cac_GetAuthDataFn); + + hnd->debug = 0; + + fill_conn_info(hnd); + + /*connect to the server, its name/ip is already in the handle so just pass NULL*/ + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server. \n Error %s\n errno(%d): %s\n", nt_errstr(hnd->status), errno, strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + else { + fprintf(stdout, "Connected to server\n"); + } + + op.in.access = GENERIC_EXECUTE_ACCESS; + op.in.security_qos = True; + + /*open the handle*/ + if(!cac_LsaOpenPolicy(hnd, mem_ctx, &op)) { + fprintf(stderr, "Could not open policy.\n Error: %s.errno: %d.\n", nt_errstr(hnd->status), errno); + cac_FreeHandle(hnd); + exit(-1); + } + else { + fprintf(stdout, "Opened Policy handle\n"); + } + + /*close the handle*/ + if(!cac_LsaClosePolicy(hnd, mem_ctx, op.out.pol)) { + fprintf(stderr, "Could not close policy. Error: %s\n", nt_errstr(hnd->status)); + } + else { + fprintf(stdout, "Closed Policy handle\n"); + } + + /*cleanup*/ + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + fprintf(stdout, "Free'd server handle\n"); + + return 0; +} + diff --git a/examples/libmsrpc/test/lsa/lsapriv.c b/examples/libmsrpc/test/lsa/lsapriv.c new file mode 100644 index 0000000000..80b3ea102f --- /dev/null +++ b/examples/libmsrpc/test/lsa/lsapriv.c @@ -0,0 +1,113 @@ +/*tries to set privileges for an account*/ + +#include "libmsrpc.h" +#include "test_util.h" + +#define BIGGEST_UINT32 0xffffffff + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + struct LsaOpenPolicy lop; + struct LsaEnumPrivileges ep; + struct LsaEnumAccountRights ar; + struct LsaAddPrivileges ap; + + fstring tmp; + + uint32 i = 0; + + mem_ctx = talloc_init("lsapriv"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + ZERO_STRUCT(lop); + + lop.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + + if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) { + fprintf(stderr, "Could not open LSA policy. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + /*first enumerate possible privileges*/ + ZERO_STRUCT(ep); + + ep.in.pol = lop.out.pol; + ep.in.pref_max_privs = BIGGEST_UINT32; + + printf("Enumerating supported privileges:\n"); + while(cac_LsaEnumPrivileges(hnd, mem_ctx, &ep)) { + for(i = 0; i < ep.out.num_privs; i++) { + printf("\t%s\n", ep.out.priv_names[i]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + fprintf(stderr, "Could not enumerate privileges. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + printf("Enter account name: "); + cactest_readline(stdin, tmp); + + ZERO_STRUCT(ar); + + ar.in.pol = lop.out.pol; + ar.in.name = talloc_strdup(mem_ctx, tmp); + + printf("Enumerating privileges for %s:\n", ar.in.name); + if(!cac_LsaEnumAccountRights(hnd, mem_ctx, &ar)) { + fprintf(stderr, "Could not enumerate privileges. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + printf("Enumerated %d privileges:\n", ar.out.num_privs); + + for(i = 0; i < ar.out.num_privs; i++) + printf("\t%s\n", ar.out.priv_names[i]); + + ZERO_STRUCT(ap); + + ap.in.pol = lop.out.pol; + ap.in.name = ar.in.name; + + printf("How many privileges will you set: "); + scanf("%d", &ap.in.num_privs); + + ap.in.priv_names = talloc_array(mem_ctx, char *, ap.in.num_privs); + if(!ap.in.priv_names) { + fprintf(stderr, "No memory\n"); + goto done; + } + + for(i = 0; i < ap.in.num_privs; i++) { + printf("Enter priv %d: ", i); + cactest_readline(stdin, tmp); + + ap.in.priv_names[i] = talloc_strdup(mem_ctx, tmp); + } + + if(!cac_LsaSetPrivileges(hnd, mem_ctx, &ap)) { + fprintf(stderr, "Could not set privileges. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + +done: + talloc_destroy(mem_ctx); + cac_FreeHandle(hnd); + + return 0; + +} + diff --git a/examples/libmsrpc/test/lsa/lsaq.c b/examples/libmsrpc/test/lsa/lsaq.c new file mode 100644 index 0000000000..54c1849bfd --- /dev/null +++ b/examples/libmsrpc/test/lsa/lsaq.c @@ -0,0 +1,245 @@ +/* connects to an LSA, asks for a list of server names, prints out their sids, then looks up their names from the sids and prints them out again + * if you run as lsaq -p, then it will simulate a partial success for cac_GetNamesFromSids. It will try to lookup the server's local and domain sids + */ + + +#include "libmsrpc.h" +#include "includes.h" + +void fill_conn_info(CacServerHandle *hnd) { + pstring domain; + pstring username; + pstring password; + pstring server; + + fprintf(stdout, "Enter domain name: "); + fscanf(stdin, "%s", domain); + + fprintf(stdout, "Enter username: "); + fscanf(stdin, "%s", username); + + fprintf(stdout, "Enter password (no input masking): "); + fscanf(stdin, "%s", password); + + fprintf(stdout, "Enter server (ip or name): "); + fscanf(stdin, "%s", server); + + hnd->domain = SMB_STRDUP(domain); + hnd->username = SMB_STRDUP(username); + hnd->password = SMB_STRDUP(password); + hnd->server = SMB_STRDUP(server); +} + +void get_server_names(TALLOC_CTX *mem_ctx, int *num_names, char ***names) { + int i = 0; + pstring tmp; + + fprintf(stdout, "How many names do you want to lookup?: "); + fscanf(stdin, "%d", num_names); + + *names = TALLOC_ARRAY(mem_ctx, char *, *num_names); + if(*names == NULL) { + fprintf(stderr, "No memory for allocation\n"); + exit(-1); + } + + for(i = 0; i < *num_names; i++) { + fprintf(stdout, "Enter name: "); + fscanf(stdin, "%s", tmp); + (*names)[i] = talloc_strdup(mem_ctx, tmp); + } +} + +int main(int argc, char **argv) { + int i; + int result; + char **names; + int num_names; + int num_sids; + CacServerHandle *hnd = NULL; + POLICY_HND *lsa_pol = NULL; + TALLOC_CTX *mem_ctx = NULL; + + DOM_SID *sid_buf = NULL; + + BOOL sim_partial = False; + + if(argc > 1 && strcmp(argv[1], "-p") == 0) + sim_partial = True; + + mem_ctx = talloc_init("lsaq"); + + hnd = cac_NewServerHandle(False); + + fill_conn_info(hnd); + + get_server_names(mem_ctx, &num_names, &names); + + /*connect to the PDC and open a LSA handle*/ + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error %s.\n", nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + exit(-1); + } + + fprintf(stdout, "Connected to server: %s\n", hnd->server); + + struct LsaOpenPolicy lop; + ZERO_STRUCT(lop); + + lop.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + lop.in.security_qos = True; + + if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) { + fprintf(stderr, "Could not get lsa policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + exit(-1); + } + + fprintf(stdout, "Opened Policy Handle\n"); + + /*just to make things neater*/ + lsa_pol = lop.out.pol; + + /*fetch the local sid and domain sid for the pdc*/ + + struct LsaFetchSid fsop; + ZERO_STRUCT(fsop); + + fsop.in.pol = lsa_pol; + fsop.in.info_class = (CAC_LOCAL_INFO|CAC_DOMAIN_INFO); + + fprintf(stdout, "fetching SID info for %s\n", hnd->server); + + result = cac_LsaFetchSid(hnd, mem_ctx, &fsop); + if(!result) { + fprintf(stderr, "Could not get sid for server: %s\n. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + exit(-1); + } + + if(result == CAC_PARTIAL_SUCCESS) { + fprintf(stdout, "could not retrieve both domain and local information\n"); + } + + + fprintf(stdout, "Fetched SID info for %s\n", hnd->server); + if(fsop.out.local_sid != NULL) + fprintf(stdout, " domain: %s. Local SID: %s\n", fsop.out.local_sid->domain, sid_string_static(&fsop.out.local_sid->sid)); + + if(fsop.out.domain_sid != NULL) + fprintf(stdout, " domain: %s, Domain SID: %s\n", fsop.out.domain_sid->domain, sid_string_static(&fsop.out.domain_sid->sid)); + + fprintf(stdout, "\nAttempting to query info policy\n"); + + struct LsaQueryInfoPolicy qop; + ZERO_STRUCT(qop); + + qop.in.pol = lsa_pol; + + if(!cac_LsaQueryInfoPolicy(hnd, mem_ctx, &qop)) { + fprintf(stderr, "Could not query information policy!.\n Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + fprintf(stdout, "Query result: \n"); + fprintf(stdout, " domain name: %s\n", qop.out.domain_name); + fprintf(stdout, " dns name: %s\n", qop.out.dns_name); + fprintf(stdout, " forest name: %s\n", qop.out.forest_name); + fprintf(stdout, " domain guid: %s\n", smb_uuid_string_static(*qop.out.domain_guid)); + fprintf(stdout, " domain sid: %s\n", sid_string_static(qop.out.domain_sid)); + + fprintf(stdout, "\nLooking up sids\n"); + + struct LsaGetSidsFromNames gsop; + ZERO_STRUCT(gsop); + + gsop.in.pol = lsa_pol; + gsop.in.num_names = num_names; + gsop.in.names = names; + + result = cac_LsaGetSidsFromNames(hnd, mem_ctx, &gsop); + + if(!result) { + fprintf(stderr, "Could not lookup any sids!\n Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + if(result == CAC_PARTIAL_SUCCESS) { + fprintf(stdout, "Not all names could be looked up.\nThe following names were not found:\n"); + + for(i = 0; i < (num_names - gsop.out.num_found); i++) { + fprintf(stdout, " %s\n", gsop.out.unknown[i]); + } + + fprintf(stdout, "\n"); + } + + /*buffer the sids so we can look them up back to names*/ + num_sids = (sim_partial) ? gsop.out.num_found + 2: gsop.out.num_found; + sid_buf = TALLOC_ARRAY(mem_ctx, DOM_SID, num_sids); + + fprintf(stdout, "%d names were resolved: \n", gsop.out.num_found); + + + i = 0; + while(i < gsop.out.num_found) { + fprintf(stdout, " Name: %s\n SID: %s\n\n", gsop.out.sids[i].name, sid_string_static(&gsop.out.sids[i].sid)); + + sid_buf[i] = gsop.out.sids[i].sid; + + i++; + } + + /*if we want a partial success to occur below, then add the server's SIDs to the end of the array*/ + if(sim_partial) { + sid_buf[i] = fsop.out.local_sid->sid; + sid_buf[i+1] = fsop.out.domain_sid->sid; + } + + fprintf(stdout, "Looking up Names from SIDs\n"); + + struct LsaGetNamesFromSids gnop; + ZERO_STRUCT(gnop); + + gnop.in.pol = lsa_pol; + gnop.in.num_sids = num_sids; + gnop.in.sids = sid_buf; + + result = cac_LsaGetNamesFromSids(hnd, mem_ctx, &gnop); + + if(!result) { + fprintf(stderr, "Could not lookup any names!.\n Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + if(result == CAC_PARTIAL_SUCCESS) { + fprintf(stdout, "\nNot all SIDs could be looked up.\n. The following SIDs were not found:\n"); + + for(i = 0; i < (num_sids - gnop.out.num_found); i++) { + fprintf(stdout, "SID: %s\n", sid_string_static(&gnop.out.unknown[i])); + } + + fprintf(stdout, "\n"); + } + + fprintf(stdout, "%d SIDs were resolved: \n", gnop.out.num_found); + for(i = 0; i < gnop.out.num_found; i++) { + fprintf(stdout, " SID: %s\n Name: %s\n", sid_string_static(&gnop.out.sids[i].sid), gsop.out.sids[i].name); + } + +done: + + if(!cac_LsaClosePolicy(hnd, mem_ctx, lsa_pol)) { + fprintf(stderr, "Could not close LSA policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + } + else { + fprintf(stdout, "Closed Policy handle.\n"); + } + + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/examples/libmsrpc/test/lsa/lsatrust.c b/examples/libmsrpc/test/lsa/lsatrust.c new file mode 100644 index 0000000000..6ad293f832 --- /dev/null +++ b/examples/libmsrpc/test/lsa/lsatrust.c @@ -0,0 +1,151 @@ +/*queries trusted domain information*/ + +#include "libmsrpc.h" +#include "includes.h" + +#define MAX_STRING_LEN 50; + +void print_info(LSA_TRUSTED_DOMAIN_INFO *info) { + switch(info->info_class) { + case CAC_INFO_TRUSTED_DOMAIN_FULL_INFO: + case CAC_INFO_TRUSTED_DOMAIN_INFO_ALL: + printf(" Domain Name: %s\n", unistr2_static(&info->info_ex.domain_name.unistring)); + printf(" Netbios Name: %s\n", unistr2_static(&info->info_ex.netbios_name.unistring)); + printf(" Domain Sid: %s\n", sid_string_static(&info->info_ex.sid.sid)); + printf(" Trust direction: %d\n", info->info_ex.trust_direction); + printf(" Trust Type: %d\n", info->info_ex.trust_type); + printf(" Trust attr: %d\n", info->info_ex.trust_attributes); + printf(" Posix Offset: %d\n", info->posix_offset.posix_offset); + break; + } +} + +int main() { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + POLICY_HND *lsa_pol = NULL; + + int i; + + mem_ctx = talloc_init("lsatrust"); + + hnd = cac_NewServerHandle(False); + + /*malloc some memory so get_auth_data_fn can work*/ + hnd->username = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + hnd->domain = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + hnd->netbios_name = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + hnd->password = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + + hnd->server = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + + + printf("Server: "); + fscanf(stdin, "%s", hnd->server); + + printf("Connecting to server....\n"); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s\n errno %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + printf("Connected to server\n"); + + struct LsaOpenPolicy lop; + ZERO_STRUCT(lop); + + lop.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + lop.in.security_qos = True; + + + if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) { + fprintf(stderr, "Could not open policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + cac_FreeHandle(hnd); + exit(-1); + } + + lsa_pol = lop.out.pol; + + printf("Enumerating Trusted Domains\n"); + + struct LsaEnumTrustedDomains etd; + ZERO_STRUCT(etd); + + etd.in.pol = lsa_pol; + + while(cac_LsaEnumTrustedDomains(hnd, mem_ctx, &etd)) { + printf(" Enumerated %d domains\n", etd.out.num_domains); + + for(i = 0; i < etd.out.num_domains; i++) { + printf(" Name: %s\n", etd.out.domain_names[i]); + printf(" SID: %s\n", sid_string_static(&etd.out.domain_sids[i])); + + printf("\n Attempting to open domain...\n"); + + struct LsaOpenTrustedDomain otd; + ZERO_STRUCT(otd); + + otd.in.pol = lsa_pol; + otd.in.domain_sid = &etd.out.domain_sids[i]; + otd.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + + /*try to query trusted domain info by name*/ + struct LsaQueryTrustedDomainInfo qtd; + ZERO_STRUCT(qtd); + + qtd.in.pol = lsa_pol; + qtd.in.domain_name = etd.out.domain_names[i]; + + + int j; + for(j = 0; j < 100; j++ ) { + qtd.in.info_class = j; + + printf(" Querying trustdom by name\n"); + if(!cac_LsaQueryTrustedDomainInfo(hnd, mem_ctx, &qtd)) { + fprintf(stderr, " could not query trusted domain info.\n Error %s\n", nt_errstr(hnd->status)); + continue; + } + + printf(" info_class %d succeeded\n", j); + printf(" Query result:\n"); + printf(" size %d\n", sizeof(*qtd.out.info)); + } + + /*try to query trusted domain info by SID*/ + printf(" Querying trustdom by sid\n"); + qtd.in.domain_sid = &etd.out.domain_sids[i]; + if(!cac_LsaQueryTrustedDomainInfo(hnd, mem_ctx, &qtd)) { + fprintf(stderr, " could not query trusted domain info.\n Error %s\n", nt_errstr(hnd->status)); + continue; + } + + printf(" Query result:\n"); +/* print_info(qtd.out.info);*/ + + if(CAC_OP_FAILED(hnd->status)) { + fprintf(stderr, " Could not enum sids.\n Error: %s\n", nt_errstr(hnd->status)); + continue; + } + } + + printf("\n"); + } + + if(CAC_OP_FAILED(hnd->status)) { + fprintf(stderr, "Error while enumerating trusted domains.\n Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + +done: + if(!cac_LsaClosePolicy(hnd, mem_ctx, lsa_pol)) { + fprintf(stderr, "Could not close policy handle.\n Error: %s\n", nt_errstr(hnd->status)); + } + + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/examples/libmsrpc/test/reg/regdelete.c b/examples/libmsrpc/test/reg/regdelete.c new file mode 100644 index 0000000000..50b08ba468 --- /dev/null +++ b/examples/libmsrpc/test/reg/regdelete.c @@ -0,0 +1,102 @@ +/*tests deleting a key or value*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + fstring tmp; + char input = 'v'; + + mem_ctx = talloc_init("regdelete"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + printf("enter key to open: \n"); + cactest_readline(stdin, tmp); + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.name = talloc_strdup(mem_ctx, tmp); + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s. Error %s\n", rok.in.name, nt_errstr(hnd->status)); + exit(-1); + } + + printf("getting version (just for testing\n"); + + struct RegGetVersion rgv; + ZERO_STRUCT(rgv); + + rgv.in.key = rok.out.key; + + if(!cac_RegGetVersion(hnd, mem_ctx, &rgv)) + fprintf(stderr, "Could not get version. Error: %s\n", nt_errstr(hnd->status)); + else + printf("Version: %d\n", rgv.out.version); + + + while(input == 'v' || input == 'k') { + printf("Delete [v]alue [k]ey or [q]uit: "); + scanf("%c", &input); + + switch(input) { + case 'v': + printf("Value to delete: "); + cactest_readline(stdin, tmp); + + struct RegDeleteValue rdv; + ZERO_STRUCT(rdv); + + rdv.in.parent_key = rok.out.key; + rdv.in.name = talloc_strdup(mem_ctx, tmp); + + if(!cac_RegDeleteValue(hnd, mem_ctx, &rdv)) + fprintf(stderr, "Could not delete value %s. Error: %s\n", rdv.in.name, nt_errstr(hnd->status)); + + break; + case 'k': + printf("Key to delete: "); + cactest_readline(stdin, tmp); + + struct RegDeleteKey rdk; + ZERO_STRUCT(rdk); + + rdk.in.parent_key = rok.out.key; + rdk.in.name = talloc_strdup(mem_ctx, tmp); + + printf("delete recursively? [y/n]: "); + cactest_readline(stdin, tmp); + + rdk.in.recursive = (tmp[0] == 'y') ? True : False; + + if(!cac_RegDeleteKey(hnd, mem_ctx, &rdk)) + fprintf(stderr, "Could not delete key %s. Error %s\n", rdk.in.name, nt_errstr(hnd->status)); + + break; + } + } + cac_RegClose(hnd, mem_ctx, rok.out.key); + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + + diff --git a/examples/libmsrpc/test/reg/regkey.c b/examples/libmsrpc/test/reg/regkey.c new file mode 100644 index 0000000000..a90d06c6ef --- /dev/null +++ b/examples/libmsrpc/test/reg/regkey.c @@ -0,0 +1,76 @@ +/*opens and closes a key*/ + +#include "libmsrpc.h" + +int main() { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + fstring key; + + mem_ctx = talloc_init("regkey"); + + hnd = cac_NewServerHandle(False); + + /*allocate some memory so get_auth_data_fn can do it's magic*/ + hnd->username = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + hnd->domain = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + hnd->netbios_name = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + hnd->password = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + + hnd->server = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + + printf("Enter server to connect to: "); + fscanf(stdin, "%s", hnd->server); + + printf("Enter key to open: "); + fscanf(stdin, "%s", key); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s.\n errno: %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + struct RegConnect rc; + ZERO_STRUCT(rc); + + rc.in.access = REG_KEY_ALL; + rc.in.root = HKEY_LOCAL_MACHINE; + + if(!cac_RegConnect(hnd, mem_ctx, &rc)) { + fprintf(stderr, " Could not connect to registry. %s\n", nt_errstr(hnd->status)); + goto done; + } + + printf("trying to open key %s...\n", key); + + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.parent_key = rc.out.key; + rok.in.name = key; + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s\n Error: %s\n", rok.in.name, nt_errstr(hnd->status)); + goto done; + } + + if(!cac_RegClose(hnd, mem_ctx, rok.out.key)) { + fprintf(stderr, "Could not close handle %s\n", nt_errstr(hnd->status)); + } + + if(!cac_RegClose(hnd, mem_ctx, rc.out.key)) { + fprintf(stderr, " Could not close handle. %s\n", nt_errstr(hnd->status)); + } + +done: + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; + +} diff --git a/examples/libmsrpc/test/reg/regkeycreate.c b/examples/libmsrpc/test/reg/regkeycreate.c new file mode 100644 index 0000000000..50764f1682 --- /dev/null +++ b/examples/libmsrpc/test/reg/regkeycreate.c @@ -0,0 +1,115 @@ +/*tests creating a registry key*/ + +#include "libmsrpc.h" + +#define MAX_KEYS_PER_ENUM 3 + +int main() { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + fstring key_name; + + fstring key_to_create; + + mem_ctx = talloc_init("regcreatekey"); + + hnd = cac_NewServerHandle(True); + + printf("Enter server to connect to: "); + fscanf(stdin, "%s", hnd->server); + + printf("Enter key to open: "); + fscanf(stdin, "%s", key_name); + + printf("Enter key to create: "); + fscanf(stdin, "%s", key_to_create); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s.\n errno: %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + printf("trying to open key %s...\n", key_name); + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.parent_key = NULL; + rok.in.name = key_name; + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s\n Error: %s\n", rok.in.name, nt_errstr(hnd->status)); + goto done; + } + + printf("Creating key %s...\n", key_to_create); + + struct RegCreateKey rck; + ZERO_STRUCT(rck); + + rck.in.parent_key = rok.out.key; + rck.in.key_name = talloc_strdup(mem_ctx, key_to_create); + rck.in.class_name = talloc_strdup(mem_ctx, ""); + rck.in.access = REG_KEY_ALL; + + if(!cac_RegCreateKey(hnd, mem_ctx, &rck)) { + fprintf(stderr, "Could not create key. Error %s\n", nt_errstr(hnd->status)); + goto done; + } + + if(!cac_RegClose(hnd, mem_ctx, rck.out.key)) { + fprintf(stderr, "Could not close key. Error %s\n", nt_errstr(hnd->status)); + goto done; + } + + /**enumerate all the subkeys*/ + printf("Enumerating all subkeys:\n"); + + struct RegEnumKeys ek; + ZERO_STRUCT(ek); + + ek.in.key = rok.out.key; + ek.in.max_keys = 50; + + while(cac_RegEnumKeys(hnd, mem_ctx, &ek)) { + int j; + + for(j = 0; j < ek.out.num_keys; j++) { + printf(" Key name: %s\n", ek.out.key_names[j]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + fprintf(stderr, "Could not enumerate keys: %s\n", nt_errstr(hnd->status)); + goto done; + } + + printf("deleting key %s\n", key_to_create); + + struct RegDeleteKey rdk; + ZERO_STRUCT(rdk); + + rdk.in.parent_key = rok.out.key; + rdk.in.name = key_to_create; + + if(!cac_RegDeleteKey(hnd, mem_ctx, &rdk)) { + fprintf(stderr, "Could not delete key. Error %s\n", nt_errstr(hnd->status)); + } + + printf("closing key %s...\n", key_name); + + if(!cac_RegClose(hnd, mem_ctx, rok.out.key)) { + fprintf(stderr, "Could not close handle %s\n", nt_errstr(hnd->status)); + } + +done: + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; + +} diff --git a/examples/libmsrpc/test/reg/regkeyenum.c b/examples/libmsrpc/test/reg/regkeyenum.c new file mode 100644 index 0000000000..f140d95723 --- /dev/null +++ b/examples/libmsrpc/test/reg/regkeyenum.c @@ -0,0 +1,99 @@ +/*tests enumerating keys or values*/ + +#include "libmsrpc.h" + +#define MAX_KEYS_PER_ENUM 3 + +int main() { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + int num_keys; + + int max_enum; + + int i; + + fstring *key_names; + + mem_ctx = talloc_init("regkeyenum"); + + hnd = cac_NewServerHandle(True); + + printf("Enter server to connect to: "); + fscanf(stdin, "%s", hnd->server); + + printf("How many keys do you want to open?: "); + fscanf(stdin, "%d", &num_keys); + + printf("How many keys per enum?: "); + fscanf(stdin, "%d", &max_enum); + + key_names = TALLOC_ARRAY(mem_ctx, fstring , num_keys); + if(!key_names) { + fprintf(stderr, "No memory\n"); + exit(-1); + } + + for(i = 0; i < num_keys; i++) { + printf("Enter key to open: "); + fscanf(stdin, "%s", key_names[i]); + } + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s.\n errno: %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + for(i = 0; i < num_keys; i++) { + printf("trying to open key %s...\n", key_names[i]); + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.parent_key = NULL; + rok.in.name = key_names[i]; + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s\n Error: %s\n", rok.in.name, nt_errstr(hnd->status)); + continue; + } + + /**enumerate all the subkeys*/ + printf("Enumerating all subkeys:\n"); + + struct RegEnumKeys ek; + ZERO_STRUCT(ek); + + ek.in.key = rok.out.key; + ek.in.max_keys = max_enum; + + while(cac_RegEnumKeys(hnd, mem_ctx, &ek)) { + int j; + + for(j = 0; j < ek.out.num_keys; j++) { + printf(" Key name: %s\n", ek.out.key_names[j]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + fprintf(stderr, "Could not enumerate keys: %s\n", nt_errstr(hnd->status)); + continue; + } + + printf("closing key %s...\n", key_names[i]); + + if(!cac_RegClose(hnd, mem_ctx, rok.out.key)) { + fprintf(stderr, "Could not close handle %s\n", nt_errstr(hnd->status)); + } + } + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; + +} diff --git a/examples/libmsrpc/test/reg/regopen.c b/examples/libmsrpc/test/reg/regopen.c new file mode 100644 index 0000000000..fedc52e40d --- /dev/null +++ b/examples/libmsrpc/test/reg/regopen.c @@ -0,0 +1,66 @@ +/*opens and closes a registry handle*/ + +#include "libmsrpc.h" + +int main() { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + POLICY_HND **keys = NULL; + + char roots[4][50] = { {CAC_HKCR}, {CAC_HKLM}, {CAC_HKU}, {CAC_HKPD} }; + + int i; + + + mem_ctx = talloc_init("regopen"); + + hnd = cac_NewServerHandle(True); + + keys = TALLOC_ARRAY(mem_ctx, POLICY_HND *, 4); + + printf("Enter server to connect to: "); + fscanf(stdin, "%s", hnd->server); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s.\n errno: %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + struct RegConnect rc; + ZERO_STRUCT(rc); + + rc.in.access = SEC_RIGHT_MAXIMUM_ALLOWED; + + for(i = 0; i < 4; i++) { + printf("opening: %s\n", roots[i]); + + rc.in.root = roots[i]; + + if(!cac_RegConnect(hnd, mem_ctx, &rc)) { + fprintf(stderr, " Could not connect to registry. %s\n", nt_errstr(hnd->status)); + continue; + } + + keys[i] = rc.out.key; + } + + for(i = 3; i >= 0; i--) { + if(keys[i] == NULL) + continue; + + printf("closing: %s\n", roots[i]); + + if(!cac_RegClose(hnd, mem_ctx, keys[i])) { + fprintf(stderr, " Could not close handle. %s\n", nt_errstr(hnd->status)); + } + } + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; + +} diff --git a/examples/libmsrpc/test/reg/regopenkey.c b/examples/libmsrpc/test/reg/regopenkey.c new file mode 100644 index 0000000000..732da17ccf --- /dev/null +++ b/examples/libmsrpc/test/reg/regopenkey.c @@ -0,0 +1,69 @@ +/*tests cac_RegOpenKey()*/ + +#include "libmsrpc.h" + +int main() { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + int num_keys; + int i; + + fstring *key_names; + + mem_ctx = talloc_init("regopenkey"); + + hnd = cac_NewServerHandle(True); + + printf("Enter server to connect to: "); + fscanf(stdin, "%s", hnd->server); + + printf("How many keys do you want to open?: "); + fscanf(stdin, "%d", &num_keys); + + key_names = TALLOC_ARRAY(mem_ctx, fstring , num_keys); + if(!key_names) { + fprintf(stderr, "No memory\n"); + exit(-1); + } + + for(i = 0; i < num_keys; i++) { + printf("Enter key to open: "); + fscanf(stdin, "%s", key_names[i]); + } + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s.\n errno: %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + for(i = 0; i < num_keys; i++) { + printf("trying to open key %s...\n", key_names[i]); + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.parent_key = NULL; + rok.in.name = key_names[i]; + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s\n Error: %s\n", rok.in.name, nt_errstr(hnd->status)); + continue; + } + + printf("closing key %s...\n", key_names[i]); + + if(!cac_RegClose(hnd, mem_ctx, rok.out.key)) { + fprintf(stderr, "Could not close handle %s\n", nt_errstr(hnd->status)); + } + } + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; + +} diff --git a/examples/libmsrpc/test/reg/regqueryval.c b/examples/libmsrpc/test/reg/regqueryval.c new file mode 100644 index 0000000000..9989651898 --- /dev/null +++ b/examples/libmsrpc/test/reg/regqueryval.c @@ -0,0 +1,79 @@ +/*tests cac_RegQueryValue()*/ + +#include "libmsrpc.h" +#include "test_util.h" + +#define MAX_KEYS_PER_ENUM 3 + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + fstring key_name; + + fstring val_name; + + mem_ctx = talloc_init("regqueryval"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + printf("Enter key to open: "); + fscanf(stdin, "%s", key_name); + + printf("Enter value to query: "); + fscanf(stdin, "%s", val_name); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s.\n errno: %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + printf("trying to open key %s...\n", key_name); + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.parent_key = NULL; + rok.in.name = key_name; + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s\n Error: %s\n", rok.in.name, nt_errstr(hnd->status)); + goto done; + } + + struct RegQueryValue rqv; + ZERO_STRUCT(rqv); + + rqv.in.key = rok.out.key; + rqv.in.val_name = talloc_strdup(mem_ctx, val_name); + + printf("querying value %s...\n", rqv.in.val_name); + if(!cac_RegQueryValue(hnd, mem_ctx, &rqv)) { + fprintf(stderr, "Could not query value. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Queried value %s\n", rqv.in.val_name); + print_value(rqv.out.type, rqv.out.data); + } + + + printf("closing key %s...\n", key_name); + + if(!cac_RegClose(hnd, mem_ctx, rok.out.key)) { + fprintf(stderr, "Could not close handle %s\n", nt_errstr(hnd->status)); + } + +done: + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; + +} diff --git a/examples/libmsrpc/test/reg/regsetval.c b/examples/libmsrpc/test/reg/regsetval.c new file mode 100644 index 0000000000..e7327910c2 --- /dev/null +++ b/examples/libmsrpc/test/reg/regsetval.c @@ -0,0 +1,59 @@ +/*tests cac_RegSetVal()*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + fstring tmp; + + mem_ctx = talloc_init("regsetval"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + printf("enter key to open: \n"); + scanf("%s", tmp); + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.name = talloc_strdup(mem_ctx, tmp); + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s. Error %s\n", rok.in.name, nt_errstr(hnd->status)); + exit(-1); + } + + struct RegSetValue rsv; + ZERO_STRUCT(rsv); + + rsv.in.key = rok.out.key; + + cactest_reg_input_val(mem_ctx, &rsv.in.type, &rsv.in.val_name, &rsv.in.value); + + if(!cac_RegSetValue(hnd, mem_ctx, &rsv)) { + fprintf(stderr, "Could not set value. Error: %s\n", nt_errstr(hnd->status)); + } + + cac_RegClose(hnd, mem_ctx, rok.out.key); + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + + diff --git a/examples/libmsrpc/test/reg/regvalenum.c b/examples/libmsrpc/test/reg/regvalenum.c new file mode 100644 index 0000000000..9778f4e2b3 --- /dev/null +++ b/examples/libmsrpc/test/reg/regvalenum.c @@ -0,0 +1,103 @@ +/*tests enumerating registry values*/ + +#include "libmsrpc.h" +#include "test_util.h" + +#define MAX_KEYS_PER_ENUM 3 + + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + int num_keys; + + int max_enum; + + fstring *key_names; + + int i; + + mem_ctx = talloc_init("regvalenum"); + + hnd = cac_NewServerHandle(True); + + cac_parse_cmd_line(argc, argv, hnd); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server.\n Error: %s.\n errno: %s\n", nt_errstr(hnd->status), strerror(errno)); + cac_FreeHandle(hnd); + exit(-1); + } + + printf("How many keys do you want to open?: "); + fscanf(stdin, "%d", &num_keys); + + printf("How many values per enum?: "); + fscanf(stdin, "%d", &max_enum); + + key_names = TALLOC_ARRAY(mem_ctx, fstring , num_keys); + if(!key_names) { + fprintf(stderr, "No memory\n"); + exit(-1); + } + + for(i = 0; i < num_keys; i++) { + printf("Enter key to open: "); + fscanf(stdin, "%s", key_names[i]); + } + + for(i = 0; i < num_keys; i++) { + printf("trying to open key %s...\n", key_names[i]); + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.parent_key = NULL; + rok.in.name = key_names[i]; + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s\n Error: %s\n", rok.in.name, nt_errstr(hnd->status)); + continue; + } + + /**enumerate all the subkeys*/ + printf("Enumerating all values:\n"); + + struct RegEnumValues rev; + ZERO_STRUCT(rev); + + rev.in.key = rok.out.key; + rev.in.max_values = max_enum; + + while(cac_RegEnumValues(hnd, mem_ctx, &rev)) { + int j; + + for(j = 0; j < rev.out.num_values; j++) { + printf(" Value name: %s\n", rev.out.value_names[j]); + print_value(rev.out.types[j], rev.out.values[j]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + fprintf(stderr, "Could not enumerate values: %s\n", nt_errstr(hnd->status)); + continue; + } + + printf("closing key %s...\n", key_names[i]); + + if(!cac_RegClose(hnd, mem_ctx, rok.out.key)) { + fprintf(stderr, "Could not close handle %s\n", nt_errstr(hnd->status)); + } + } + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; + +} diff --git a/examples/libmsrpc/test/reg/security.c b/examples/libmsrpc/test/reg/security.c new file mode 100644 index 0000000000..6808f8c1f3 --- /dev/null +++ b/examples/libmsrpc/test/reg/security.c @@ -0,0 +1,74 @@ +/*tests cac_RegSetKeySecurity()*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + fstring tmp; + + mem_ctx = talloc_init("regsetval"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + printf("enter key to query: "); + cactest_readline(stdin, tmp); + + rok.in.name = talloc_strdup(mem_ctx, tmp); + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) { + fprintf(stderr, "Could not open key %s. Error %s\n", rok.in.name, nt_errstr(hnd->status)); + exit(-1); + } + + struct RegGetKeySecurity rks; + ZERO_STRUCT(rks); + + rks.in.key = rok.out.key; + rks.in.info_type = ALL_SECURITY_INFORMATION; + + if(!cac_RegGetKeySecurity(hnd, mem_ctx, &rks)) { + fprintf(stderr, "Could not query security for %s. Error: %s\n", rok.in.name, nt_errstr(hnd->status)); + goto done; + } + + printf("resetting key security...\n"); + + struct RegSetKeySecurity rss; + ZERO_STRUCT(rss); + + rss.in.key = rok.out.key; + rss.in.info_type = ALL_SECURITY_INFORMATION; + rss.in.size = rks.out.size; + rss.in.descriptor = rks.out.descriptor; + + if(!cac_RegSetKeySecurity(hnd, mem_ctx, &rss)) { + fprintf(stderr, "Could not set security. Error %s\n", nt_errstr(hnd->status)); + } + +done: + cac_RegClose(hnd, mem_ctx, rok.out.key); + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + + diff --git a/examples/libmsrpc/test/reg/shutdown.c b/examples/libmsrpc/test/reg/shutdown.c new file mode 100644 index 0000000000..6184fbd976 --- /dev/null +++ b/examples/libmsrpc/test/reg/shutdown.c @@ -0,0 +1,68 @@ +/*tries to shut down a remote pc*/ + +#include "libmsrpc.h" +#include "test_util.h" + + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + fstring tmp; + + mem_ctx = talloc_init("cac_shutdown"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + hnd->_internal.srv_level = SRV_WIN_NT4; + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct Shutdown s; + ZERO_STRUCT(s); + + printf("Message: "); + cactest_readline(stdin, tmp); + + s.in.message = talloc_strdup(mem_ctx, tmp); + + printf("timeout: "); + scanf("%d", &s.in.timeout); + + printf("Reboot? [y/n]: "); + cactest_readline(stdin, tmp); + + s.in.reboot = ( tmp[0] == 'y') ? True : False; + + printf("Force? [y/n]: "); + cactest_readline(stdin, tmp); + + s.in.force = (tmp[0] == 'y') ? True : False; + + if(!cac_Shutdown(hnd, mem_ctx, &s)) { + fprintf(stderr, "could not shut down server: error %s\n", nt_errstr(hnd->status)); + goto done; + } + + printf("Server %s is shutting down. Would you like to try to abort? [y/n]: ", hnd->server); + fscanf(stdin, "%s", tmp); + + if(tmp[0] == 'y') { + if(!cac_AbortShutdown(hnd, mem_ctx)) { + fprintf(stderr, "Could not abort shutdown. Error %s\n", nt_errstr(hnd->status)); + } + } + +done: + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/examples/libmsrpc/test/sam/adduser.c b/examples/libmsrpc/test/sam/adduser.c new file mode 100644 index 0000000000..94482d0704 --- /dev/null +++ b/examples/libmsrpc/test/sam/adduser.c @@ -0,0 +1,92 @@ +/*add's a user to a domain*/ +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + fstring tmp; + + struct SamOpenUser ou; + + POLICY_HND *user_hnd = NULL; + + mem_ctx = talloc_init("cac_adduser"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct SamOpenDomain sod; + ZERO_STRUCT(sod); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + fprintf(stderr, "Could not open domain. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + struct SamCreateUser cdu; + ZERO_STRUCT(cdu); + + printf("Enter account name: "); + cactest_readline(stdin, tmp); + + cdu.in.dom_hnd = sod.out.dom_hnd; + cdu.in.name = talloc_strdup(mem_ctx, tmp); + cdu.in.acb_mask = ACB_NORMAL; + + if(!cac_SamCreateUser(hnd, mem_ctx, &cdu)) { + fprintf(stderr, "Could not create user %s. Error: %s\n", cdu.in.name, nt_errstr(hnd->status)); + } + + printf("would you like to delete this user? [y/n]: "); + cactest_readline(stdin, tmp); + + if(tmp[0] == 'y') { + + if(!cdu.out.user_hnd) { + ZERO_STRUCT(ou); + ou.in.dom_hnd = sod.out.dom_hnd; + ou.in.access = MAXIMUM_ALLOWED_ACCESS; + ou.in.name = talloc_strdup(mem_ctx, cdu.in.name); + + if(!cac_SamOpenUser(hnd, mem_ctx, &ou)) { + fprintf(stderr, "Could not open user for deletion. Error: %s\n", nt_errstr(hnd->status)); + } + + user_hnd = ou.out.user_hnd; + } + + else { + user_hnd = cdu.out.user_hnd; + } + + if(!cac_SamDeleteUser(hnd, mem_ctx, user_hnd)) + fprintf(stderr, "Could not delete user. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Nope..ok\n"); + } + + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + cac_SamClose(hnd, mem_ctx, sod.out.sam); + +done: + talloc_destroy(mem_ctx); + + cac_FreeHandle(hnd); + + return 0; +} + +/*TODO: add a function that will create a user and set userinfo and set the password*/ diff --git a/examples/libmsrpc/test/sam/disable.c b/examples/libmsrpc/test/sam/disable.c new file mode 100644 index 0000000000..f140bad50b --- /dev/null +++ b/examples/libmsrpc/test/sam/disable.c @@ -0,0 +1,63 @@ +/*disable a user*/ +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + struct SamOpenUser ou; + + fstring tmp; + + mem_ctx = talloc_init("cac_disable"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct SamOpenDomain sod; + ZERO_STRUCT(sod); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + fprintf(stderr, "Could not open domain. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + ZERO_STRUCT(ou); + printf("Enter username: "); + cactest_readline(stdin, tmp); + + ou.in.name = talloc_strdup(mem_ctx, tmp); + ou.in.access = MAXIMUM_ALLOWED_ACCESS; + ou.in.dom_hnd = sod.out.dom_hnd; + + if(!cac_SamOpenUser(hnd, mem_ctx, &ou)) { + fprintf(stderr, "Could not open user. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + /*enable the user*/ + if(!cac_SamDisableUser(hnd, mem_ctx, ou.out.user_hnd)) { + fprintf(stderr, "Could not disable user: %s\n", nt_errstr(hnd->status)); + } + +done: + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + diff --git a/examples/libmsrpc/test/sam/dominfo.c b/examples/libmsrpc/test/sam/dominfo.c new file mode 100644 index 0000000000..cd2eccefba --- /dev/null +++ b/examples/libmsrpc/test/sam/dominfo.c @@ -0,0 +1,55 @@ +/*gets domain info and prints it out*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + mem_ctx = talloc_init("cac_dominfo"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct SamOpenDomain sod; + ZERO_STRUCT(sod); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + fprintf(stderr, "Could not open domain. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + struct SamGetDomainInfo gdi; + ZERO_STRUCT(gdi); + + gdi.in.dom_hnd = sod.out.dom_hnd; + + if(!cac_SamGetDomainInfo(hnd, mem_ctx, &gdi)) { + fprintf(stderr, "Could not get domain info. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + printf("Got domain info:\n"); + print_cac_domain_info(gdi.out.info); + +done: + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + diff --git a/examples/libmsrpc/test/sam/enable.c b/examples/libmsrpc/test/sam/enable.c new file mode 100644 index 0000000000..bb91fb241c --- /dev/null +++ b/examples/libmsrpc/test/sam/enable.c @@ -0,0 +1,64 @@ +/*enable a user*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + struct SamOpenUser ou; + + fstring tmp; + + mem_ctx = talloc_init("cac_samgroup"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct SamOpenDomain sod; + ZERO_STRUCT(sod); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + fprintf(stderr, "Could not open domain. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + ZERO_STRUCT(ou); + printf("Enter username: "); + cactest_readline(stdin, tmp); + + ou.in.name = talloc_strdup(mem_ctx, tmp); + ou.in.access = MAXIMUM_ALLOWED_ACCESS; + ou.in.dom_hnd = sod.out.dom_hnd; + + if(!cac_SamOpenUser(hnd, mem_ctx, &ou)) { + fprintf(stderr, "Could not open user. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + /*enable the user*/ + if(!cac_SamEnableUser(hnd, mem_ctx, ou.out.user_hnd)) { + fprintf(stderr, "Could not enable user: %s\n", nt_errstr(hnd->status)); + } + +done: + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + diff --git a/examples/libmsrpc/test/sam/samenum.c b/examples/libmsrpc/test/sam/samenum.c new file mode 100644 index 0000000000..5b10475aac --- /dev/null +++ b/examples/libmsrpc/test/sam/samenum.c @@ -0,0 +1,117 @@ +/*enumerate users/groups/aliases*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + + struct SamEnumUsers eu; + struct SamEnumGroups eg; + struct SamEnumAliases ea; + + fstring tmp; + + int i; + + mem_ctx = talloc_init("cac_samenum"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct SamOpenDomain sod; + ZERO_STRUCT(sod); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + fprintf(stderr, "Could not open domain. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + tmp[0] = 0x00; + while(tmp[0] != 'q') { + printf("Enumerate [u]sers, [g]roups or [a]liases or [q]uit: "); + cactest_readline(stdin, tmp); + + switch(tmp[0]) { + case 'u': + ZERO_STRUCT(eu); + + eu.in.dom_hnd = sod.out.dom_hnd; + + printf("ACB mask (can be 0): "); + scanf("%hx", &eu.in.acb_mask); + + while(cac_SamEnumUsers(hnd, mem_ctx, &eu)) { + printf("Enumerated %d users:\n", eu.out.num_users); + for(i = 0; i < eu.out.num_users; i++) { + printf(" Name: %s\n", eu.out.names[i]); + printf(" RID: %d\n", eu.out.rids[i]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + printf("Could not enumerate users. Error: %s\n", nt_errstr(hnd->status)); + } + break; + case 'g': + ZERO_STRUCT(eg); + eg.in.dom_hnd = sod.out.dom_hnd; + + printf("Enumerating groups...\n"); + while(cac_SamEnumGroups(hnd, mem_ctx, &eg)) { + printf("Enumerated %d groups:\n", eg.out.num_groups); + for(i = 0; i < eg.out.num_groups; i++) { + printf("RID: %d\n", eg.out.rids[i]); + printf("Name: %s\n", eg.out.names[i]); + printf("Desc: %s\n", eg.out.descriptions[i]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + printf("Could not enumerate Groups. Error: %s\n", nt_errstr(hnd->status)); + } + break; + case 'a': + ZERO_STRUCT(ea); + ea.in.dom_hnd = sod.out.dom_hnd; + + printf("Enumerating Aliases...\n"); + while(cac_SamEnumAliases(hnd, mem_ctx, &ea)) { + printf("Enumerated %d aliases:\n", ea.out.num_aliases); + + for(i = 0; i < ea.out.num_aliases; i++) { + printf("RID: %d\n", ea.out.rids[i]); + printf("Name: %s\n", ea.out.names[i]); + printf("Desc: %s\n", ea.out.descriptions[i]); + } + } + if(CAC_OP_FAILED(hnd->status)) { + printf("Could not enumerate Aliases. Error: %s\n", nt_errstr(hnd->status)); + } + break; + } + } + + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + cac_SamClose(hnd, mem_ctx, sod.out.sam); + +done: + talloc_destroy(mem_ctx); + cac_FreeHandle(hnd); + + return 0; + +} + diff --git a/examples/libmsrpc/test/sam/samgroup.c b/examples/libmsrpc/test/sam/samgroup.c new file mode 100644 index 0000000000..39d9fa1137 --- /dev/null +++ b/examples/libmsrpc/test/sam/samgroup.c @@ -0,0 +1,480 @@ +/*Some group management stuff*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + + struct SamEnumGroups eg; + struct SamEnumUsers eu; + struct SamCreateGroup cg; + struct SamOpenGroup og; + struct SamGetGroupMembers ggm; + struct SamGetNamesFromRids gn; + struct SamAddGroupMember add; + struct SamRemoveGroupMember del; + struct SamSetGroupMembers set; + struct SamGetGroupsForUser gg; + struct SamOpenUser ou; + struct SamGetGroupInfo gi; + struct SamSetGroupInfo si; + struct SamRenameGroup rg; + struct SamGetSecurityObject gso; + + POLICY_HND *group_hnd = NULL; + + fstring tmp; + fstring input; + + int i; + + mem_ctx = talloc_init("cac_samgroup"); + + hnd = cac_NewServerHandle(True); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct SamOpenDomain sod; + ZERO_STRUCT(sod); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + fprintf(stderr, "Could not open domain. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + tmp[0] = 0x00; + while(tmp[0] != 'q') { + printf("\n"); + printf("[l]ist groups\n"); + printf("[c]reate group\n"); + printf("[o]pen group\n"); + printf("[d]elete group\n"); + printf("list [m]embers\n"); + printf("list [u]sers\n"); + printf("list [g]roup for users\n"); + printf("[a]dd member\n"); + printf("[r]emove member\n"); + printf("[x] clear members\n"); + printf("get group [i]nfo\n"); + printf("[e]dit group info\n"); + printf("[s]et members\n"); + printf("re[n]ame group\n"); + printf("[z] close group\n"); + printf("[t] get security info\n"); + + printf("[q]uit\n\n"); + printf("Enter option: "); + cactest_readline(stdin, tmp); + + printf("\n"); + + switch(tmp[0]) { + case 'c': /*create group*/ + if(group_hnd != NULL) { + /*then we have an open handle.. close it*/ + cac_SamClose(hnd, mem_ctx, group_hnd); + group_hnd = NULL; + } + + printf("Enter group name: "); + cactest_readline(stdin, input); + + ZERO_STRUCT(cg); + + cg.in.name = talloc_strdup(mem_ctx, input); + cg.in.access = MAXIMUM_ALLOWED_ACCESS; + cg.in.dom_hnd = sod.out.dom_hnd; + + if(!cac_SamCreateGroup(hnd, mem_ctx, &cg)) { + fprintf(stderr, "Could not create group. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Created group %s\n", cg.in.name); + + group_hnd = cg.out.group_hnd; + } + break; + + case 'o': /*open group*/ + if(group_hnd != NULL) { + /*then we have an open handle.. close it*/ + cac_SamClose(hnd, mem_ctx, group_hnd); + group_hnd = NULL; + } + + ZERO_STRUCT(og); + + og.in.dom_hnd = sod.out.dom_hnd; + og.in.access = MAXIMUM_ALLOWED_ACCESS; + + printf("Enter RID: 0x"); + scanf("%x", &og.in.rid); + + if(!cac_SamOpenGroup(hnd, mem_ctx, &og)) { + fprintf(stderr, "Could not open group. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Opened group\n"); + group_hnd = og.out.group_hnd; + } + + break; + + case 'l': /*list groups*/ + ZERO_STRUCT(eg); + eg.in.dom_hnd = sod.out.dom_hnd; + + while(cac_SamEnumGroups(hnd, mem_ctx, &eg)) { + for(i = 0; i < eg.out.num_groups; i++) { + printf("RID: 0x%x Name: %s\n", eg.out.rids[i], eg.out.names[i]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + printf("Could not enumerate Groups. Error: %s\n", nt_errstr(hnd->status)); + } + + break; + + case 'm': /*list group members*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + ZERO_STRUCT(ggm); + ggm.in.group_hnd = group_hnd; + + if(!cac_SamGetGroupMembers(hnd, mem_ctx, &ggm)) { + fprintf(stderr, "Could not get group members. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + printf("Group has %d members:\n", ggm.out.num_members); + + if(ggm.out.num_members == 0) /*just skip the rest of this case*/ + break; + + /**get the user names*/ + gn.in.dom_hnd = sod.out.dom_hnd; + gn.in.num_rids = ggm.out.num_members; + gn.in.rids = ggm.out.rids; + + if(!cac_SamGetNamesFromRids(hnd, mem_ctx, &gn)) { + fprintf(stderr, "Could not lookup names. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + for(i = 0; i < gn.out.num_names; i++) { + printf("RID: 0x%x Name: %s\n", gn.out.map[i].rid, gn.out.map[i].name); + } + + break; + + case 'd': /*delete group*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + if(!cac_SamDeleteGroup(hnd, mem_ctx, group_hnd)) { + fprintf(stderr, "Could not delete group. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Deleted group.\n"); + group_hnd = NULL; + } + break; + + case 'u': /*list users*/ + ZERO_STRUCT(eu); + + eu.in.dom_hnd = sod.out.dom_hnd; + + while(cac_SamEnumUsers(hnd, mem_ctx, &eu)) { + for(i = 0; i < eu.out.num_users; i++) { + printf(" RID: 0x%x Name: %s\n", eu.out.rids[i], eu.out.names[i]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + printf("Could not enumerate users. Error: %s\n", nt_errstr(hnd->status)); + } + + break; + + case 'a': /*add member to group*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + ZERO_STRUCT(add); + + add.in.group_hnd = group_hnd; + + printf("Enter user RID: 0x"); + scanf("%x", &add.in.rid); + + if(!cac_SamAddGroupMember(hnd, mem_ctx, &add)) { + fprintf(stderr, "Could not add user to group. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Successfully added user to group\n"); + } + break; + + case 'r': /*remove user from group*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + ZERO_STRUCT(del); + del.in.group_hnd = group_hnd; + + printf("Enter RID: 0x"); + scanf("%x", &del.in.rid); + + if(!cac_SamRemoveGroupMember(hnd, mem_ctx, &del)) { + fprintf(stderr, "Could not remove user from group. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Removed user from group.\n"); + } + + break; + + case 'x': /*clear group members*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + if(!cac_SamClearGroupMembers(hnd, mem_ctx, group_hnd)) { + fprintf(stderr, "Could not clear group members. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Cleared group members\n"); + } + + break; + + case 's': /*set members*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + ZERO_STRUCT(set); + + set.in.group_hnd = group_hnd; + + printf("Enter the number of members: "); + scanf("%d", &set.in.num_members); + + set.in.rids = TALLOC_ARRAY(mem_ctx, uint32, set.in.num_members); + + for(i = 0; i < set.in.num_members; i++) { + printf("Enter RID #%d: 0x", (i+1)); + scanf("%x", (set.in.rids + i)); + } + + if(!cac_SamSetGroupMembers(hnd, mem_ctx, &set)) { + printf("could not set members. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Set users\n"); + } + + break; + + case 'g': /*list groups for user*/ + ZERO_STRUCT(ou); + ZERO_STRUCT(gg); + + printf("Enter username: "); + cactest_readline(stdin, input); + + if(input[0] != '\0') { + ou.in.name = talloc_strdup(mem_ctx, input); + } + else { + printf("Enter RID: 0x"); + scanf("%x", &ou.in.rid); + } + + ou.in.access = MAXIMUM_ALLOWED_ACCESS; + ou.in.dom_hnd = sod.out.dom_hnd; + + if(!cac_SamOpenUser(hnd, mem_ctx, &ou)) { + fprintf(stderr, "Could not open user %s. Error: %s\n", ou.in.name, nt_errstr(hnd->status)); + break; + } + + /*now find the groups*/ + gg.in.user_hnd = ou.out.user_hnd; + + if(!cac_SamGetGroupsForUser(hnd, mem_ctx, &gg)) { + fprintf(stderr, "Could not get groups for user. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + cac_SamClose(hnd, mem_ctx, ou.out.user_hnd); + + ZERO_STRUCT(gn); + + gn.in.dom_hnd = sod.out.dom_hnd; + gn.in.num_rids = gg.out.num_groups; + gn.in.rids = gg.out.rids; + + if(!cac_SamGetNamesFromRids(hnd, mem_ctx, &gn)) { + fprintf(stderr, "Could not get names from RIDs. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + printf("%d groups: \n", gn.out.num_names); + + for(i = 0; i < gn.out.num_names; i++) { + printf("RID: 0x%x ", gn.out.map[i].rid); + + if(gn.out.map[i].found) + printf("Name: %s\n", gn.out.map[i].name); + else + printf("Unknown RID\n"); + } + + break; + + case 'z': /*close group*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + if(!cac_SamClose(hnd, mem_ctx, group_hnd)) { + printf("Could not close group\n"); + break; + } + + group_hnd = NULL; + break; + + case 'i': /*get group info*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + ZERO_STRUCT(gi); + gi.in.group_hnd = group_hnd; + + if(!cac_SamGetGroupInfo(hnd, mem_ctx, &gi)) { + printf("Could not get group info. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Retrieved Group info\n"); + print_cac_group_info(gi.out.info); + } + + break; + + case 'e': /*edit group info*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + ZERO_STRUCT(gi); + ZERO_STRUCT(si); + + gi.in.group_hnd = group_hnd; + + if(!cac_SamGetGroupInfo(hnd, mem_ctx, &gi)) { + printf("Could not get group info. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + edit_cac_group_info(mem_ctx, gi.out.info); + + si.in.group_hnd = group_hnd; + si.in.info = gi.out.info; + + if(!cac_SamSetGroupInfo(hnd, mem_ctx, &si)) { + printf("Could not set group info. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf(" Done.\n"); + } + + break; + + case 'n': /*rename group*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + ZERO_STRUCT(rg); + + printf("Enter new group name: "); + cactest_readline(stdin, tmp); + + rg.in.group_hnd = group_hnd; + rg.in.new_name = talloc_strdup(mem_ctx, tmp); + + if(!cac_SamRenameGroup(hnd, mem_ctx, &rg)) + printf("Could not rename group. Error: %s\n", nt_errstr(hnd->status)); + else + printf("Done.\n"); + + break; + case 't': /*get security info*/ + if(!group_hnd) { + printf("Must open group first!\n"); + break; + } + + ZERO_STRUCT(gso); + + gso.in.pol = group_hnd; + + if(!cac_SamGetSecurityObject(hnd, mem_ctx, &gso)) { + printf("Could not get security descriptor info. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Got it.\n"); + } + break; + + case 'q': + break; + + default: + printf("Invalid command\n"); + } + } + + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + + if(group_hnd) + cac_SamClose(hnd, mem_ctx, group_hnd); + +done: + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + diff --git a/examples/libmsrpc/test/sam/samlookup.c b/examples/libmsrpc/test/sam/samlookup.c new file mode 100644 index 0000000000..32be50d4b9 --- /dev/null +++ b/examples/libmsrpc/test/sam/samlookup.c @@ -0,0 +1,140 @@ +/*lookup names or rids*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + + struct SamGetNamesFromRids sgn; + struct SamGetRidsFromNames sgr; + + fstring tmp; + fstring input; + + int i; + + mem_ctx = talloc_init("cac_samenum"); + + hnd = cac_NewServerHandle(True); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct SamOpenDomain sod; + ZERO_STRUCT(sod); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + fprintf(stderr, "Could not open domain. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + tmp[0] = 0x00; + while(tmp[0] != 'q') { + printf("get [n]ames or get [r]ids or [q]uit: "); + cactest_readline(stdin, tmp); + + switch(tmp[0]) { + case 'n': + ZERO_STRUCT(sgn); + + sgn.in.dom_hnd = sod.out.dom_hnd; + + printf("How many rids will you enter: "); + scanf("%d", &sgn.in.num_rids); + + sgn.in.rids = talloc_array(mem_ctx, int, sgn.in.num_rids); + + for(i = 0; i < sgn.in.num_rids; i++) { + printf(" Enter RID %d: 0x", i); + scanf("%x", &sgn.in.rids[i]); + } + + printf("Getting names...\n"); + + if(!cac_SamGetNamesFromRids(hnd, mem_ctx, &sgn)) { + fprintf(stderr, "could not lookup names. Error: %s\n", nt_errstr(hnd->status)); + talloc_free(sgn.in.rids); + continue; + } + + printf("Found %d names:\n", sgn.out.num_names); + + for(i = 0; i < sgn.out.num_names; i++) { + printf(" RID: 0x%x ", sgn.out.map[i].rid); + + if(sgn.out.map[i].found) { + printf("Name: %s\n", sgn.out.map[i].name); + } + else { + printf("Unknown RID\n"); + } + + } + + break; + + case 'r': + ZERO_STRUCT(sgr); + + sgr.in.dom_hnd = sod.out.dom_hnd; + + printf("How many names will you enter: "); + scanf("%d", &sgr.in.num_names); + + sgr.in.names = talloc_array(mem_ctx, char *, sgr.in.num_names); + + for(i = 0; i < sgr.in.num_names; i++) { + printf(" Enter name %d: ", (i+1)); + cactest_readline(stdin, input); + + sgr.in.names[i] = talloc_strdup(mem_ctx, input); + } + + if(!cac_SamGetRidsFromNames(hnd, mem_ctx, &sgr)) { + fprintf(stderr, "Could not lookup names. Error: %s\n", nt_errstr(hnd->status)); + continue; + } + + printf("Found %d RIDs:\n", sgr.out.num_rids); + + for(i = 0; i < sgr.out.num_rids; i++) { + printf(" Name: %s ", sgr.out.map[i].name); + + if(sgr.out.map[i].found) { + printf("RID: 0x%x\n", sgr.out.map[i].rid); + } + else { + printf("Unknown name\n"); + } + } + + break; + case 'q': + printf("\n"); + break; + default: + printf("Invalid command!\n"); + } + } + + + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + cac_SamClose(hnd, mem_ctx, sod.out.sam); + +done: + talloc_destroy(mem_ctx); + cac_FreeHandle(hnd); + + return 0; + +} + diff --git a/examples/libmsrpc/test/sam/samuser.c b/examples/libmsrpc/test/sam/samuser.c new file mode 100644 index 0000000000..df56a2d991 --- /dev/null +++ b/examples/libmsrpc/test/sam/samuser.c @@ -0,0 +1,294 @@ +/*Some user management stuff*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + + struct SamOpenUser ou; + struct SamEnumUsers eu; + struct SamCreateUser cu; + struct SamGetUserInfo gi; + struct SamSetUserInfo si; + struct SamRenameUser ru; + struct SamSetPassword sp; + + POLICY_HND *user_hnd = NULL; + + fstring tmp; + fstring input; + + char *pass1 = NULL; + char *pass2 = NULL; + + int i; + + mem_ctx = talloc_init("cac_samgroup"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + struct SamOpenDomain sod; + ZERO_STRUCT(sod); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) { + fprintf(stderr, "Could not open domain. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + tmp[0] = 0x00; + while(tmp[0] != 'q') { + printf("\n"); + printf("[l]ist users\n"); + printf("[c]reate user\n"); + printf("[o]pen user\n"); + printf("[d]elete user\n"); + printf("[g]et user info\n"); + printf("[e]dit user info\n"); + printf("[r]ename user\n"); + printf("reset [p]assword\n"); + printf("[n] close user\n"); + + printf("[q]uit\n\n"); + printf("Enter option: "); + cactest_readline(stdin, tmp); + + printf("\n"); + + switch(tmp[0]) { + case 'c': /*create user*/ + if(user_hnd != NULL) { + /*then we have an open handle.. close it*/ + cac_SamClose(hnd, mem_ctx, user_hnd); + user_hnd = NULL; + } + + printf("Enter user name: "); + cactest_readline(stdin, input); + + ZERO_STRUCT(cu); + + cu.in.name = talloc_strdup(mem_ctx, input); + cu.in.dom_hnd = sod.out.dom_hnd; + cu.in.acb_mask = ACB_NORMAL; + + if(!cac_SamCreateUser(hnd, mem_ctx, &cu)) { + printf("Could not create user. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Created user %s with RID 0x%x\n", cu.in.name, cu.out.rid); + user_hnd = cu.out.user_hnd; + } + + break; + + case 'o': /*open group*/ + if(user_hnd != NULL) { + /*then we have an open handle.. close it*/ + cac_SamClose(hnd, mem_ctx, user_hnd); + user_hnd = NULL; + } + + ZERO_STRUCT(ou); + + ou.in.dom_hnd = sod.out.dom_hnd; + ou.in.access = MAXIMUM_ALLOWED_ACCESS; + + printf("Enter RID: 0x"); + scanf("%x", &ou.in.rid); + + if(!cac_SamOpenUser(hnd, mem_ctx, &ou)) { + fprintf(stderr, "Could not open user. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Opened user\n"); + user_hnd = ou.out.user_hnd; + } + + break; + + case 'l': /*list users*/ + ZERO_STRUCT(eu); + eu.in.dom_hnd = sod.out.dom_hnd; + + while(cac_SamEnumUsers(hnd, mem_ctx, &eu)) { + for(i = 0; i < eu.out.num_users; i++) { + printf("RID: 0x%x Name: %s\n", eu.out.rids[i], eu.out.names[i]); + } + } + + if(CAC_OP_FAILED(hnd->status)) { + printf("Could not enumerate Users. Error: %s\n", nt_errstr(hnd->status)); + } + + break; + + break; + + case 'd': /*delete group*/ + if(!user_hnd) { + printf("Must open group first!\n"); + break; + } + + if(!cac_SamDeleteGroup(hnd, mem_ctx, user_hnd)) { + fprintf(stderr, "Could not delete group. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Deleted group.\n"); + user_hnd = NULL; + } + break; + + + case 'n': + if(!user_hnd) { + printf("Must open user first!\n"); + break; + } + + if(!cac_SamClose(hnd, mem_ctx, user_hnd)) { + printf("Could not user group\n"); + break; + } + + user_hnd = NULL; + break; + + case 'g': /*get user info*/ + if(!user_hnd) { + printf("Must open user first!\n"); + break; + } + + ZERO_STRUCT(gi); + gi.in.user_hnd = ou.out.user_hnd; + + if(!cac_SamGetUserInfo(hnd, mem_ctx, &gi)) { + printf("Could not get user info. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Retrieved User information:\n"); + print_cac_user_info(gi.out.info); + } + + break; + + case 'e': /*edit user info*/ + if(!user_hnd) { + printf("Must Open user first!\n"); + break; + } + + ZERO_STRUCT(gi); + gi.in.user_hnd = ou.out.user_hnd; + if(!cac_SamGetUserInfo(hnd, mem_ctx, &gi)) { + printf("Could not get user info. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + edit_cac_user_info(mem_ctx, gi.out.info); + + printf("setting following info:\n"); + print_cac_user_info(gi.out.info); + + ZERO_STRUCT(si); + + si.in.user_hnd = user_hnd; + si.in.info = gi.out.info; + + if(!cac_SamSetUserInfo(hnd, mem_ctx, &si)) { + printf("Could not set user info. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Done.\n"); + } + + break; + + case 'r': /*rename user*/ + if(!user_hnd) { + printf("Must open user first!\n"); + break; + } + + ZERO_STRUCT(ru); + + printf("Enter new username: "); + cactest_readline(stdin, tmp); + + ru.in.user_hnd = user_hnd; + ru.in.new_name = talloc_strdup(mem_ctx, tmp); + + if(!cac_SamRenameUser(hnd, mem_ctx, &ru)) { + printf("Could not rename user. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Renamed user\n"); + } + + break; + + case 'p': /*reset password*/ + + if(!user_hnd) { + printf("Must open user first!\n"); + break; + } + + do { + if(pass1 && pass2) { + printf("Passwords do not match. Please try again\n"); + } + + pass1 = getpass("Enter new password: "); + pass2 = getpass("Re-enter new password: "); + } while(strncmp(pass1, pass2, MAX_PASS_LEN)); + + ZERO_STRUCT(sp); + sp.in.user_hnd = user_hnd; + sp.in.password = talloc_strdup(mem_ctx, pass1); + + if(!cac_SamSetPassword(hnd, mem_ctx, &sp)) { + printf("Could not set password. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Done.\n"); + } + + break; + + case 'q': + break; + + default: + printf("Invalid command\n"); + } + } + + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + + if(user_hnd) + cac_SamClose(hnd, mem_ctx, user_hnd); + +done: + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + diff --git a/examples/libmsrpc/test/smbc_test/smbc.c b/examples/libmsrpc/test/smbc_test/smbc.c new file mode 100644 index 0000000000..3db3ceadc6 --- /dev/null +++ b/examples/libmsrpc/test/smbc_test/smbc.c @@ -0,0 +1,87 @@ +/*simple test for libsmbclient compatibility. initialize a smbc context, open sessions on a couple pipes and quit*/ + +#include "libmsrpc.h" +#include "libsmbclient.h" +#include "test_util.h" + +int main(int argc, char **argv) { + SMBCCTX *ctx = NULL; + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + struct LsaOpenPolicy lop; + struct RegConnect rc; + struct SamOpenDomain sod; + + ZERO_STRUCT(lop); + ZERO_STRUCT(rc); + ZERO_STRUCT(sod); + + mem_ctx = talloc_init("cac_smbc"); + if(!mem_ctx) { + printf("Could not initialize talloc context\n"); + exit(-1); + } + + hnd = cac_NewServerHandle(True); + + cac_parse_cmd_line(argc, argv, hnd); + + /*initialize smbc context*/ + if( (ctx = smbc_new_context()) == NULL) { + exit(1); + } + + /*this probably isn't what someone would want to do, but it initializes the values we need*/ + ctx->debug = hnd->debug; + ctx->callbacks.auth_fn = cac_GetAuthDataFn; + + + if(smbc_init_context(ctx) == NULL) + exit(1); + + cac_SetSmbcContext(hnd, ctx); + + /*still have to call cac_Connect()*/ + if(!cac_Connect(hnd, NULL)) { + printf("Could not connect to server\n"); + exit(1); + } + + lop.in.access = MAXIMUM_ALLOWED_ACCESS; + if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) + printf("Could not open LSA policy. Error: %s\n", nt_errstr(hnd->status)); + + printf("Opened LSA policy.\n"); + + rc.in.access = MAXIMUM_ALLOWED_ACCESS; + rc.in.root = HKEY_LOCAL_MACHINE; + if(!cac_RegConnect(hnd, mem_ctx, &rc)) + printf("Could not connect to registry. Error: %s\n", nt_errstr(hnd->status)); + + printf("Connceted to Registry.\n"); + + sod.in.access = MAXIMUM_ALLOWED_ACCESS; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &sod)) + printf("Could not open domain SAM. Error: %s\n", nt_errstr(hnd->status)); + + printf("Opened domain.\n"); + + if(lop.out.pol) + cac_LsaClosePolicy(hnd, mem_ctx, lop.out.pol); + + if(rc.out.key) + cac_RegClose(hnd, mem_ctx, rc.out.key); + + if(sod.out.sam) + cac_SamClose(hnd, mem_ctx, sod.out.sam); + + if(sod.out.dom_hnd) + cac_SamClose(hnd, mem_ctx, sod.out.dom_hnd); + + cac_FreeHandle(hnd); + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/examples/libmsrpc/test/svcctl/svc.c b/examples/libmsrpc/test/svcctl/svc.c new file mode 100644 index 0000000000..db5fa27895 --- /dev/null +++ b/examples/libmsrpc/test/svcctl/svc.c @@ -0,0 +1,303 @@ +/*Tests all of the svcctl calls (at least at time of writing)*/ + +#include "libmsrpc.h" +#include "test_util.h" + +int main(int argc, char **argv) { + CacServerHandle *hnd = NULL; + TALLOC_CTX *mem_ctx = NULL; + + + struct SvcOpenScm sos; + struct SvcEnumServices es; + struct SvcOpenService os; + struct SvcGetStatus gs; + struct SvcStartService start; + struct SvcStopService stop; + struct SvcPauseService pause; + struct SvcContinueService res; + struct SvcGetDisplayName gdn; + struct SvcGetServiceConfig sgc; + + POLICY_HND *svc_hnd = NULL; + + fstring tmp; + fstring input; + + int i; + + mem_ctx = talloc_init("cac_samgroup"); + + hnd = cac_NewServerHandle(True); + + cac_SetAuthDataFn(hnd, cactest_GetAuthDataFn); + + cac_parse_cmd_line(argc, argv, hnd); + + if(!cac_Connect(hnd, NULL)) { + fprintf(stderr, "Could not connect to server %s. Error: %s\n", hnd->server, nt_errstr(hnd->status)); + exit(-1); + } + + /*open a handle to the scm*/ + ZERO_STRUCT(sos); + + sos.in.access = SC_MANAGER_ALL_ACCESS; + + if(!cac_SvcOpenScm(hnd, mem_ctx, &sos)) { + fprintf(stderr, "Could not open SCM. Error: %s\n", nt_errstr(hnd->status)); + goto done; + } + + printf("Opened SCM\n"); + + tmp[0] = 0x00; + while(tmp[0] != 'q') { + printf("\n"); + printf("[e] Enum Services\n"); + printf("[o] Open Service\n"); + printf("[x] Close Service\n"); + printf("[g] Get service status\n"); + printf("[s] Start service\n"); + printf("[t] Stop service\n"); + printf("[p] Pause service\n"); + printf("[r] Resume service\n"); + printf("[c] Get service config\n"); + + printf("[d] Get display name\n"); + + printf("[q]uit\n\n"); + printf("Enter option: "); + cactest_readline(stdin, tmp); + + printf("\n"); + + switch(tmp[0]) { + case 'e': /*enum services*/ + ZERO_STRUCT(es); + es.in.scm_hnd = sos.out.scm_hnd; + + if(!cac_SvcEnumServices(hnd, mem_ctx, &es)) { + printf("Could not enumerate services. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + for(i = 0; i < es.out.num_services; i++) { + print_cac_service(es.out.services[i]); + } + printf("Enumerated %d services:\n", es.out.num_services); + + break; + + case 'o': /*Open service*/ + ZERO_STRUCT(os); + + printf("Enter service name: "); + cactest_readline(stdin, tmp); + + os.in.name = talloc_strdup(mem_ctx, tmp); + os.in.scm_hnd = sos.out.scm_hnd; + os.in.access = SERVICE_ALL_ACCESS; + + if(!cac_SvcOpenService(hnd, mem_ctx, &os)) { + printf("Could not open service. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + printf("Opened service.\n"); + svc_hnd = os.out.svc_hnd; + + break; + case 'x': /*close service*/ + if(!svc_hnd) { + printf("Must open service first!\n"); + break; + } + + cac_SvcClose(hnd, mem_ctx, svc_hnd); + svc_hnd = NULL; + break; + case 'g': /*get svc status*/ + + if(!svc_hnd) { + printf("Must open service first!\n"); + break; + } + + ZERO_STRUCT(gs); + + gs.in.svc_hnd = svc_hnd; + + if(!cac_SvcGetStatus(hnd, mem_ctx, &gs)) { + printf("Could not get status. Error: %s\n", nt_errstr(hnd->status)); + break; + } + + print_service_status(gs.out.status); + break; + case 's': /*start service*/ + if(!svc_hnd) { + printf("Must open service first!\n"); + break; + } + + ZERO_STRUCT(start); + + start.in.svc_hnd = svc_hnd; + + printf("Enter number of parameters: "); + scanf("%d", &start.in.num_parms); + + start.in.parms = talloc_array(mem_ctx, char *, start.in.num_parms); + + for(i = 0; i < start.in.num_parms; i++) { + printf("Parm %d: ", i); + cactest_readline(stdin, tmp); + start.in.parms[i] = talloc_strdup(mem_ctx, tmp); + } + + printf("Timeout (seconds): "); + scanf("%d", &start.in.timeout); + + if(!cac_SvcStartService(hnd, mem_ctx, &start)) { + printf("Could not start service. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Started service.\n"); + } + + break; + case 't': /*stop service*/ + if(!svc_hnd) { + printf("Must open service first!\n"); + break; + } + + ZERO_STRUCT(stop); + stop.in.svc_hnd = svc_hnd; + + printf("Timeout (seconds): "); + scanf("%d", &stop.in.timeout); + + if(!cac_SvcStopService(hnd, mem_ctx, &stop)) { + if(CAC_OP_FAILED(hnd->status)) { + printf("Error occured: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Service was not stopped within %d seconds.\n", stop.in.timeout); + print_service_status(stop.out.status); + } + } + else { + printf("Done.\n"); + print_service_status(stop.out.status); + } + break; + case 'd': /*get display name*/ + if(!svc_hnd) { + printf("Must open service first!\n"); + break; + } + + ZERO_STRUCT(gdn); + gdn.in.svc_hnd = svc_hnd; + + if(!cac_SvcGetDisplayName(hnd, mem_ctx, &gdn)) { + printf("Could not get display name. Error: %s\n", nt_errstr(hnd->status)); + } + else { + printf("\tDisplay Name: %s\n", gdn.out.display_name); + } + break; + + case 'p': /*pause service*/ + if(!svc_hnd) { + printf("Must open service first!\n"); + break; + } + + ZERO_STRUCT(pause); + pause.in.svc_hnd = svc_hnd; + + printf("Timeout (seconds): "); + scanf("%d", &pause.in.timeout); + + if(!cac_SvcPauseService(hnd, mem_ctx, &pause)) { + if(CAC_OP_FAILED(hnd->status)) { + printf("Error occured: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Service was not paused within %d seconds.\n", pause.in.timeout); + print_service_status(pause.out.status); + } + } + else { + printf("Done.\n"); + print_service_status(pause.out.status); + } + + break; + + case 'r': /*resume service*/ + if(!svc_hnd) { + printf("Must open service first!\n"); + break; + } + + ZERO_STRUCT(res); + res.in.svc_hnd = svc_hnd; + + printf("Timeout (seconds): "); + scanf("%d", &res.in.timeout); + + if(!cac_SvcContinueService(hnd, mem_ctx, &res)) { + if(CAC_OP_FAILED(hnd->status)) { + printf("Error occured: %s\n", nt_errstr(hnd->status)); + } + else { + printf("Service was not resumed within %d seconds.\n", res.in.timeout); + print_service_status(res.out.status); + } + } + else { + printf("Done.\n"); + print_service_status(res.out.status); + } + + break; + + case 'c': /*get service config*/ + if(!svc_hnd) { + printf("Must open service first!\n"); + break; + } + + ZERO_STRUCT(sgc); + + sgc.in.svc_hnd = svc_hnd; + + if(!cac_SvcGetServiceConfig(hnd, mem_ctx, &sgc)) { + printf("Could not get service config. Error: %s\n", nt_errstr(hnd->status)); + } + else { + print_service_config(&sgc.out.config); + } + break; + + case 'q': /*quit*/ + break; + default: + printf("Invalid command\n"); + } + } + + cac_SvcClose(hnd, mem_ctx, sos.out.scm_hnd); + + done: + cac_FreeHandle(hnd); + + talloc_destroy(mem_ctx); + + return 0; +} + diff --git a/examples/libmsrpc/test/test_util.c b/examples/libmsrpc/test/test_util.c new file mode 100644 index 0000000000..81a9c9203d --- /dev/null +++ b/examples/libmsrpc/test/test_util.c @@ -0,0 +1,408 @@ +/*some utility functions for the registry tests*/ + +#include "libmsrpc.h" +#include "test_util.h" + + +void cactest_print_usage(char **argv) { + printf("Usage:\n"); + printf(" %s server [-U username] [-W domain] [-P passwprd] [-N netbios_name]\n", argv[0]); +} + +/*allocates memory for auth info and parses domain/user/server out of command line*/ +void cac_parse_cmd_line(int argc, char **argv, CacServerHandle *hnd) { + int i = 0; + + ZERO_STRUCTP(hnd->username); + ZERO_STRUCTP(hnd->domain); + ZERO_STRUCTP(hnd->netbios_name); + ZERO_STRUCTP(hnd->password); + + for(i = 1; i < argc; i++) { + if( strncmp(argv[i], "-U", sizeof(fstring)) == 0) { + strncpy(hnd->username, argv[i+1], sizeof(fstring)); + i++; + } + + else if(strncmp(argv[i], "-W", sizeof(fstring)) == 0) { + strncpy(hnd->domain, argv[i+1], sizeof(fstring)); + i++; + + } + + else if(strncmp(argv[i], "-P", sizeof(fstring)) == 0) { + strncpy(hnd->password, argv[i+1], sizeof(fstring)); + i++; + + } + + else if(strncmp(argv[i], "-N", sizeof(fstring)) == 0) { + strncpy(hnd->netbios_name, argv[i+1], sizeof(fstring)); + i++; + } + + else if(strncmp(argv[i], "-d", sizeof(fstring)) == 0) { + sscanf(argv[i+1], "%d", &hnd->debug); + i++; + } + + else { /*assume this is the server name*/ + strncpy(hnd->server, argv[i], sizeof(fstring)); + } + } + + if(!hnd->server) { + cactest_print_usage(argv); + cac_FreeHandle(hnd); + exit(-1); + } + +} + +void print_value(uint32 type, REG_VALUE_DATA *data) { + int i = 0; + + switch(type) { + case REG_SZ: + printf(" Type: REG_SZ\n"); + printf(" Value: %s\n", data->reg_sz); + break; + case REG_EXPAND_SZ: + printf(" Type: REG_EXPAND_SZ\n"); + printf(" Value: %s\n", data->reg_expand_sz); + break; + case REG_MULTI_SZ: + printf(" Type: REG_MULTI_SZ\n"); + printf(" Values: "); + + for(i = 0; i < data->reg_multi_sz.num_strings; i++) { + printf(" %d: %s\n", i, data->reg_multi_sz.strings[i]); + } + break; + case REG_DWORD: + printf(" Type: REG_DWORD\n"); + printf(" Value: %d\n", data->reg_dword); + break; + case REG_DWORD_BE: + printf(" Type: REG_DWORD_BE\n"); + printf(" Value: 0x%x\n", data->reg_dword_be); + break; + case REG_BINARY: + printf(" Type: REG_BINARY\n"); + break; + default: + printf(" Invalid type: %d\n", type); + + } + + printf("\n"); + +} + +void cactest_readline(FILE *in, fstring line) { + + int c; + + c = fgetc(in); + if(c != '\n') + ungetc(c, in); + + fgets(line, sizeof(fstring), in); + + if(line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + +} + +void cactest_GetAuthDataFn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword) + +{ + char temp[sizeof(fstring)]; + + static char authUsername[sizeof(fstring)]; + static char authWorkgroup[sizeof(fstring)]; + static char authPassword[sizeof(fstring)]; + static char authSet = 0; + + char *pass = NULL; + + if (authSet) + { + strncpy(pWorkgroup, authWorkgroup, maxLenWorkgroup - 1); + strncpy(pUsername, authUsername, maxLenUsername - 1); + strncpy(pPassword, authPassword, maxLenPassword - 1); + } + else + { + if(pWorkgroup[0] != '\0') { + strncpy(authWorkgroup, pWorkgroup, maxLenWorkgroup - 1); + } + else { + d_printf("Domain: [%s] ", pWorkgroup); + fscanf(stdin, "%s", temp); + + if (temp[0] != '\0') + { + strncpy(pWorkgroup, temp, maxLenWorkgroup - 1); + strncpy(authWorkgroup, temp, maxLenWorkgroup - 1); + } + } + + + if(pUsername[0] != '\0') { + strncpy(authUsername, pUsername, maxLenUsername - 1); + } + else { + d_printf("Username: [%s] ", pUsername); + fscanf(stdin, "%s", temp); + + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + + if (temp[0] != '\0') + { + strncpy(pUsername, temp, maxLenUsername - 1); + strncpy(authUsername, pUsername, maxLenUsername - 1); + } + } + if(pPassword[0] != '\0') { + strncpy(authPassword, pPassword, maxLenPassword - 1); + } + else { + pass = getpass("Password: "); + if (pass) + fstrcpy(temp, pass); + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + if (temp[0] != '\0') + { + strncpy(pPassword, temp, maxLenPassword - 1); + strncpy(authPassword, pPassword, maxLenPassword - 1); + } + } + authSet = 1; + } +} + +void cactest_reg_input_val(TALLOC_CTX *mem_ctx, int *type, char **name, REG_VALUE_DATA *data) { + fstring tmp; + int i; + + printf("Enter value name: \n"); + cactest_readline(stdin, tmp); + *name = talloc_strdup(mem_ctx, tmp); + + do { + printf("Enter type. %d = REG_SZ, %d = REG_DWORD, %d = REG_MULTI_SZ: ", REG_SZ, REG_DWORD, REG_MULTI_SZ); + scanf("%d", type); + } while(*type != REG_SZ && *type != REG_DWORD && *type != REG_MULTI_SZ); + + switch(*type) { + case REG_SZ: + printf("Enter string:\n"); + cactest_readline(stdin, tmp); + + data->reg_sz = talloc_strdup(mem_ctx, tmp); + break; + + case REG_DWORD: + printf("Enter dword: "); + scanf("%d", &data->reg_dword); + break; + + case REG_MULTI_SZ: + printf("Enter number of strings: "); + scanf("%d", &data->reg_multi_sz.num_strings); + + data->reg_multi_sz.strings = talloc_array(mem_ctx, char *, data->reg_multi_sz.num_strings); + + for(i = 0; i < data->reg_multi_sz.num_strings; i++) { + printf("String %d: ", i+1); + cactest_readline(stdin, tmp); + + data->reg_multi_sz.strings[i] = talloc_strdup(mem_ctx, tmp); + } + break; + } +} + +void print_cac_user_info(CacUserInfo *info) { + printf(" User Name : %s\n", info->username); + printf(" Full Name : %s\n", info->full_name); + printf(" Home Dir : %s\n", info->home_dir); + printf(" Home Drive : %s\n", info->home_drive); + printf(" Profile Path : %s\n", info->profile_path); + printf(" Logon Script : %s\n", info->logon_script); + printf(" Description : %s\n", info->description); + printf(" Workstations : %s\n", info->workstations); + printf(" Remote Dial : %s\n", info->dial); + + printf(" Logon Time : %s\n", http_timestring(info->logon_time)); + printf(" Logoff Time : %s\n", http_timestring(info->logoff_time)); + printf(" Kickoff Time : %s\n", http_timestring(info->kickoff_time)); + printf(" Pass last set: %s\n", http_timestring(info->pass_last_set_time)); + printf(" Pass can set : %s\n", http_timestring(info->pass_can_change_time)); + printf(" Pass must set: %s\n", http_timestring(info->pass_must_change_time)); + + printf(" User RID : 0x%x\n", info->rid); + printf(" Group RID : 0x%x\n", info->group_rid); + printf(" ACB Mask : 0x%x\n", info->acb_mask); + + printf(" Bad pwd count: %d\n", info->bad_passwd_count); + printf(" Logon Cuont : %d\n", info->logon_count); + + printf(" NT Password : %s\n", info->nt_password); + printf(" LM Password : %s\n", info->lm_password); + +} + +void edit_readline(fstring line) { + fgets(line, sizeof(fstring), stdin); + + if(line[strlen(line)-1] == '\n') + line[strlen(line)-1] = '\0'; +} +void edit_cac_user_info(TALLOC_CTX *mem_ctx, CacUserInfo *info) { + fstring tmp; + + printf(" User Name [%s]: ", info->username); + edit_readline(tmp); + + if(tmp[0] != '\0') + info->username = talloc_strdup(mem_ctx, tmp); + + printf(" Full Name [%s]: ", info->full_name); + + edit_readline(tmp); + if(tmp[0] != '\0') + info->full_name = talloc_strdup(mem_ctx, tmp); + + printf(" Description [%s]: ", info->description); + edit_readline(tmp); + if(tmp[0] != '\0') + info->description = talloc_strdup(mem_ctx, tmp); + + printf(" Remote Dial [%s]: ", info->dial); + edit_readline(tmp); + if(tmp[0] != '\0') + info->dial = talloc_strdup(mem_ctx, tmp); + + printf(" ACB Mask [0x%x]: ", info->acb_mask); + edit_readline(tmp); + if(tmp[0] != '\0') + sscanf(tmp, "%x", &info->acb_mask); + + printf(" Must change pass at next logon? [y/N]: "); + edit_readline(tmp); + + if(tmp[0] == 'y' || tmp[0] == 'Y') + info->pass_must_change= True; + +} + +void print_cac_group_info(CacGroupInfo *info) { + printf(" Group Name : %s\n", info->name); + printf(" Description : %s\n", info->description); + printf(" Num Members : %d\n", info->num_members); +} + +void edit_cac_group_info(TALLOC_CTX *mem_ctx, CacGroupInfo *info) { + fstring tmp; + + printf("Group Name [%s]: ", info->name); + edit_readline(tmp); + if(tmp[0] != '\0') + info->name = talloc_strdup(mem_ctx, tmp); + + printf("Description [%s]: ", info->description); + edit_readline(tmp); + if(tmp[0] != '\0') + info->description = talloc_strdup(mem_ctx, tmp); +} + +char *srv_role_str(uint32 role) { + switch(role) { + case ROLE_STANDALONE: + return "STANDALONE"; + break; + case ROLE_DOMAIN_MEMBER: + return "DOMAIN_MEMBER"; + break; + case ROLE_DOMAIN_BDC: + return "DOMAIN_BDC"; + break; + case ROLE_DOMAIN_PDC: + return "DOMAIN_PDC"; + break; + } + + return "Invalid role!\n"; +} + +char *cactime_str(CacTime ctime, fstring tmp) { + + snprintf(tmp, sizeof(fstring), "%u Days, %u Hours, %u Minutes, %u Seconds", ctime.days, ctime.hours, ctime.minutes, ctime.seconds); + + return tmp; +} + +void print_cac_domain_info(CacDomainInfo *info) { + fstring tmp; + + printf(" Server Role : %s\n", srv_role_str(info->server_role)); + printf(" Num Users : %d\n", info->num_users); + printf(" Num Domain Groups: %d\n", info->num_domain_groups); + printf(" Num Local Groups : %d\n", info->num_local_groups); + printf(" Comment : %s\n", info->comment); + printf(" Domain Name : %s\n", info->domain_name); + printf(" Server Name : %s\n", info->server_name); + printf(" Min. Pass. Length: %d\n", info->min_pass_length); + printf(" Password History : %d\n", info->pass_history); + printf("\n"); + printf(" Passwords Expire In : %s\n", cactime_str(info->expire, tmp)); + printf(" Passwords Can Change in: %s\n", cactime_str(info->min_pass_age, tmp)); + printf(" Lockouts last : %s\n", cactime_str(info->lockout_duration, tmp)); + printf(" Allowed Bad Attempts : %d\n", info->num_bad_attempts); +} + +void print_cac_service(CacService svc) { + printf("\tService Name: %s\n", svc.service_name); + printf("\tDisplay Name: %s\n", svc.display_name); + print_service_status(svc.status); +} + +void print_service_status(SERVICE_STATUS status) { + printf("\tStatus:\n"); + printf("\t Type: 0x%x\n", status.type); + printf("\t State: 0x%x\n", status.state); + printf("\t Controls: 0x%x\n", status.controls_accepted); + printf("\t W32 Exit Code: 0x%x\n", status.win32_exit_code); + printf("\t SVC Exit Code: 0x%x\n", status.service_exit_code); + printf("\t Checkpoint: 0x%x\n", status.check_point); + printf("\t Wait Hint: 0x%x\n", status.wait_hint); + printf("\n"); +} + +void print_service_config(CacServiceConfig *config) { + printf("\tConfig:\n"); + printf("\tType: 0x%x\n", config->type); + printf("\tStart Type: 0x%x\n", config->start_type); + printf("\tError config: 0x%x\n", config->error_control); + printf("\tExecutable Path: %s\n", config->exe_path); + printf("\tLoad Order Group: %s\n", config->load_order_group); + printf("\tTag ID: 0x%x\n", config->tag_id); + printf("\tDependencies: %s\n", config->dependencies); + printf("\tStart Name: %s\n", config->start_name); + printf("\tDisplay Name: %s\n", config->display_name); +} diff --git a/examples/libmsrpc/test/test_util.h b/examples/libmsrpc/test/test_util.h new file mode 100644 index 0000000000..9b27599da1 --- /dev/null +++ b/examples/libmsrpc/test/test_util.h @@ -0,0 +1,31 @@ +#ifndef TEST_UTIL_H +#define TEST_UTIL_H + +#include "libmsrpc.h" + +/*prototypes*/ +void cactest_GetAuthDataFn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword); + + +void cactest_print_usage(char **argv); +void cac_parse_cmd_line(int argc, char **argv, CacServerHandle *hnd); +void print_value(uint32 type, REG_VALUE_DATA *data); +void cactest_readline(FILE *in, fstring line); +void cactest_reg_input_val(TALLOC_CTX *mem_ctx, int *type, char **name, REG_VALUE_DATA *data); +void print_cac_user_info(CacUserInfo *info); +void edit_cac_user_info(TALLOC_CTX *mem_ctx, CacUserInfo *info); +void print_cac_group_info(CacGroupInfo *info); +void edit_cac_group_info(TALLOC_CTX *mem_ctx, CacGroupInfo *info); +void print_cac_domain_info(CacDomainInfo *info); +void print_cac_service(CacService svc); +void print_service_status(SERVICE_STATUS status); +void print_service_config(CacServiceConfig *config); + +#endif /*TEST_UTIL_H*/ diff --git a/source3/include/libmsrpc.h b/source3/include/libmsrpc.h new file mode 100644 index 0000000000..611db4f849 --- /dev/null +++ b/source3/include/libmsrpc.h @@ -0,0 +1,3048 @@ +/* + * Unix SMB/CIFS implementation. + * MS-RPC client library API definitions/prototypes + * + * 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. + */ + +#ifndef LIBMSRPC_H +#define LIBMSRPC_H + + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + +/*server capability levels*/ +#define SRV_WIN_NT4 1 +#define SRV_WIN_2K 2 +#define SRV_WIN_2K_SP3 3 +#define SRV_WIN_2K3 4 + +/**@defgroup handle Server Handle*/ +/**@defgroup Library_Functions Library/Utility Functions*/ +/**@defgroup lsa_defs LSA Definitions*/ +/**@defgroup LSA_Functions LSA Functions*/ +/**@defgroup reg_defs Registry Definitions*/ +/**@defgroup Reg_Functions Registry Functions*/ +/**@defgroup sam_defs SAM Definitions*/ +/**@defgroup SAM_Functions SAM Functions*/ +/**@defgroup svc_defs Service Control Definitions*/ +/**@defgroup SCM_Functions Service Control Functions*/ + +/**Operation was unsuccessful*/ +#define CAC_FAILURE 0 +/**Operation was successful*/ +#define CAC_SUCCESS 1 +/**Operation was only partially successful + * an example of this is if you try to lookup a list of accounts to SIDs and not all accounts can be resolved*/ +#define CAC_PARTIAL_SUCCESS 2 + +/**@ingroup CAC_errors Use this to see if the last operation failed - useful for enumeration functions that use multiple calls*/ +#define CAC_OP_FAILED(status) !NT_STATUS_IS_OK(status) && \ + NT_STATUS_V(status) != NT_STATUS_V(STATUS_SOME_UNMAPPED) && \ + NT_STATUS_V(status) != NT_STATUS_V(STATUS_NO_MORE_FILES) && \ + NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_NO_MORE_ENTRIES) && \ + NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_NONE_MAPPED) && \ + NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED) + + +/**Privilege string constants*/ +#define CAC_SE_CREATE_TOKEN "SeCreateTokenPrivilege" +#define CAC_SE_ASSIGN_PRIMARY_TOKEN "SeAssignPrimaryTokenPrivilege" +#define CAC_SE_LOCK_MEMORY "SeLockMemoryPrivilege" +#define CAC_SE_INCREASE_QUOTA "SeIncreaseQuotaPrivilege" +#define CAC_SE_MACHINE_ACCOUNT "SeMachineAccountPrivilege" +#define CAC_SE_TCB "SeTcbPrivilege" +#define CAC_SE_SECURITY "SeSecurityPrivilege" +#define CAC_SE_TAKE_OWNERSHIP "SeTakeOwnershipPrivilege" +#define CAC_SE_LOAD_DRIVER "SeLoadDriverPrivilege" +#define CAC_SE_SYSTEM_PROFILE "SeSystemProfilePrivilege" +#define CAC_SE_SYSTEM_TIME "SeSystemtimePrivilege" +#define CAC_SE_PROFILE_SINGLE_PROC "SeProfileSingleProcessPrivilege" +#define CAC_SE_INCREASE_BASE_PRIORITY "SeIncreaseBasePriorityPrivilege" +#define CAC_SE_CREATE_PAGEFILE "SeCreatePagefilePrivilege" +#define CAC_SE_CREATE_PERMANENT "SeCreatePermanentPrivilege" +#define CAC_SE_BACKUP "SeBackupPrivilege" +#define CAC_SE_RESTORE "SeRestorePrivilege" +#define CAC_SE_SHUTDOWN "SeShutdownPrivilege" +#define CAC_SE_DEBUG "SeDebugPrivilege" +#define CAC_SE_AUDIT "SeAuditPrivilege" +#define CAC_SE_SYSTEM_ENV "SeSystemEnvironmentPrivilege" +#define CAC_SE_CHANGE_NOTIFY "SeChangeNotifyPrivilege" +#define CAC_SE_REMOTE_SHUTDOWN "SeRemoteShutdownPrivilege" +#define CAC_SE_UNDOCK "SeUndockPrivilege" +#define CAC_SE_SYNC_AGENT "SeSyncAgentPrivilege" +#define CAC_SE_ENABLE_DELEGATION "SeEnableDelegationPrivilege" +#define CAC_SE_MANAGE_VOLUME "SeManageVolumePrivilege" +#define CAC_SE_IMPERSONATE "SeImpersonatePrivilege" +#define CAC_SE_CREATE_GLOBAL "SeCreateGlobalPrivilege" +#define CAC_SE_PRINT_OPERATOR "SePrintOperatorPrivilege" +#define CAC_SE_NETWORK_LOGON "SeNetworkLogonRight" +#define CAC_SE_INTERACTIVE_LOGON "SeInteractiveLogonRight" +#define CAC_SE_BATCH_LOGON "SeBatchLogonRight" +#define CAC_SE_SERVICE_LOGON "SeServiceLogonRight" +#define CAC_SE_ADD_USERS "SeAddUsersPrivilege" +#define CAC_SE_DISK_OPERATOR "SeDiskOperatorPrivilege" + +/** + * @addtogroup lsa_defs + * @{ + */ +/**used to specify what data to retrieve using cac_LsaQueryTrustedDomainInformation*/ +#define CAC_INFO_TRUSTED_DOMAIN_NAME 0x1 +#define CAC_INFO_TRUSTED_DOMAIN_POSIX_OFFSET 0x3 +#define CAC_INFO_TRUSTED_DOMAIN_PASSWORD 0x4 + +/**Used when requesting machine domain information*/ +#define CAC_DOMAIN_INFO 0x0003 + +/**Used when requesting machine local information*/ +#define CAC_LOCAL_INFO 0x0005 + +/**Stores information about a SID*/ +typedef struct _CACSIDINFO { + /**The actual SID*/ + DOM_SID sid; + + /**The name of the object which maps to this SID*/ + char *name; + + /**The domain the SID belongs to*/ + char *domain; +} CacSidInfo; +/* @} */ + +/** + * @addtogroup reg_defs + * @{ + */ +/**Null terminated string*/ +typedef char* REG_SZ_DATA; + +/**Null terminated string with windows environment variables that should be expanded*/ +typedef char* REG_EXPAND_SZ_DATA; + +/**Binary data of some kind*/ +typedef struct _REGBINARYDATA { + uint32 data_length; + uint8 * data; +} REG_BINARY_DATA; + +/**32-bit (little endian) number*/ +typedef uint32 REG_DWORD_DATA; + +/**32-bit big endian number*/ +typedef uint32 REG_DWORD_BE_DATA; + +/**array of strings*/ +typedef struct _REGMULTISZDATA { + uint32 num_strings; + + char **strings; +} REG_MULTI_SZ_DATA; + +typedef union _REGVALUEDATA { + REG_SZ_DATA reg_sz; + REG_EXPAND_SZ_DATA reg_expand_sz; + REG_BINARY_DATA reg_binary; + REG_DWORD_DATA reg_dword; + REG_DWORD_BE_DATA reg_dword_be; + REG_MULTI_SZ_DATA reg_multi_sz; +} REG_VALUE_DATA; +/**@}*/ + +/** + * @addtogroup sam_defs + * @{ + */ + +#define CAC_USER_RID 0x1 +#define CAC_GROUP_RID 0x2 + +typedef struct _CACLOOKUPRIDSRECORD { + char *name; + uint32 rid; + + /**If found, this will be one of: + * - CAC_USER_RID + * - CAC_GROUP_RID + */ + uint32 type; + + /*if the name or RID was looked up, then found = True*/ + BOOL found; +} CacLookupRidsRecord; + +typedef struct _CACUSERINFO { + /**Last logon time*/ + time_t logon_time; + + /**Last logoff time*/ + time_t logoff_time; + + /**Last kickoff time*/ + time_t kickoff_time; + + /**Last password set time*/ + time_t pass_last_set_time; + + /**Time password can change*/ + time_t pass_can_change_time; + + /**Time password must change*/ + time_t pass_must_change_time; + + /**LM user password*/ + uint8 lm_password[8]; + + /**NT user password*/ + uint8 nt_password[8]; + + /**User's RID*/ + uint32 rid; + + /**RID of primary group*/ + uint32 group_rid; + + /**User's ACB mask*/ + uint32 acb_mask; + + /**Bad password count*/ + uint16 bad_passwd_count; + + /**Number of logons*/ + uint16 logon_count; + + /**Change password at next logon?*/ + BOOL pass_must_change; + + /**Username*/ + char *username; + + /**User's full name*/ + char *full_name; + + /**User's home directory*/ + char *home_dir; + + /**Home directory drive*/ + char *home_drive; + + /**Logon script*/ + char *logon_script; + + /**Path to profile*/ + char *profile_path; + + /**Account description*/ + char *description; + + /**Login from workstations*/ + char *workstations; + + char *dial; + + /**Possible logon hours*/ + LOGON_HRS *logon_hours; + +} CacUserInfo; + +typedef struct _CACGROUPINFO { + /**Group name*/ + char *name; + + /**Description*/ + char *description; + + /**Number of members*/ + uint32 num_members; +} CacGroupInfo, CacAliasInfo; + +/**Represents a period (duration) of time*/ +typedef struct _CACTIME { + /**Number of days*/ + uint32 days; + + /**Number of hours*/ + uint32 hours; + + /**Number of minutes*/ + uint32 minutes; + + /**number of seconds*/ + uint32 seconds; +} CacTime; + + +typedef struct _CACDOMINFO { + /**The server role. Should be one of: + * ROLE_STANDALONE + * ROLE_DOMAIN_MEMBER + * ROLE_DOMAIN_BDC + * ROLE_DOMAIN_PDC + * see include/smb.h + */ + uint32 server_role; + + /**Number of domain users*/ + uint32 num_users; + + /**Number of domain groups*/ + uint32 num_domain_groups; + + /**Number of local groups*/ + uint32 num_local_groups; + + /**Comment*/ + char *comment; + + /**Domain name*/ + char *domain_name; + + /**Server name*/ + char *server_name; + + /**Minimum password length*/ + uint16 min_pass_length; + + /**How many previous passwords to remember - ie, password cannot be the same as N previous passwords*/ + uint16 pass_history; + + /**How long (from now) before passwords expire*/ + CacTime expire; + + /**How long (from now) before passwords can be changed*/ + CacTime min_pass_age; + + /**How long users are locked out for too many bad password attempts*/ + CacTime lockout_duration; + + /**How long before lockouts are reset*/ + CacTime lockout_reset; + + /**How many bad password attempts before lockout occurs*/ + uint16 num_bad_attempts; +} CacDomainInfo; + +/**@}*/ /*sam_defs*/ + +/**@addtogroup svc_defs + * @{ + */ +typedef struct _CACSERVICE { + /**The service name*/ + char *service_name; + + /**The display name of the service*/ + char *display_name; + + /**Current status of the service - see include/rpc_svcctl.h for SERVICE_STATUS definition*/ + SERVICE_STATUS status; +} CacService; + +typedef struct __CACSERVICECONFIG { + /**The service type*/ + uint32 type; + + /**The start type. Should be one of: + * - SVCCTL_BOOT_START + * - SVCCTL_SYSTEM_START + * - SVCCTL_AUTO_START + * - SVCCTL_DEMAND_START + */ + uint32 start_type; + + uint32 error_control; + + /**Path to executable*/ + char *exe_path; + + /***/ + char *load_order_group; + + uint32 tag_id; + + /**Any dependencies for the service*/ + char *dependencies; + + /**Run as...*/ + char *start_name; + + /**Service display name*/ + char *display_name; + +} CacServiceConfig; +/**@}*/ /*svc_defs*/ + +#include "libmsrpc_internal.h" + +/** + * @addtogroup handle + * @{ + */ + +/** + * Server handle used to keep track of client/server/pipe information. Use cac_NewServerHandle() to allocate. + * Initiliaze as many values as possible before calling cac_Connect(). + * + * @note When allocating memory for the fields, use SMB_MALLOC() (or equivalent) instead of talloc() (or equivalent) - + * If memory is not allocated for a field, cac_Connect will allocate sizeof(fstring) bytes for it. + * + * @note It may be wise to allocate large buffers for these fields and strcpy data into them. + * + * @see cac_NewServerHandle() + * @see cac_FreeHandle() + */ +typedef struct _CACSERVERHANDLE { + /** debug level + */ + int debug; + + /** netbios name used to make connections + */ + char *netbios_name; + + /** domain name used to make connections + */ + char *domain; + + /** username used to make connections + */ + char *username; + + /** user's password plain text string + */ + char *password; + + /** name or IP address of server we are currently working with + */ + char *server; + + /**stores the latest NTSTATUS code + */ + NTSTATUS status; + + /** internal. do not modify! + */ + struct CacServerHandleInternal _internal; + +} CacServerHandle; + +/*@}*/ + +/**internal function. do not call this function*/ +SMBCSRV *cac_GetServer(CacServerHandle *hnd); + + +/** @addtogroup Library_Functions + * @{ + */ +/** + * Initializes the library - do not need to call this function. Open's smb.conf as well as initializes logging. + * @param debug Debug level for library to use + */ + +void cac_Init(int debug); + +/** + * Creates an un-initialized CacServerHandle + * @param allocate_fields If True, the function will allocate sizeof(fstring) bytes for all char * fields in the handle + * @return - un-initialized server handle + * - NULL if no memory could be allocated + */ +CacServerHandle * cac_NewServerHandle(BOOL allocate_fields); + +/** + * Specifies the smbc_get_auth_data_fn to use if you do not want to use the default. + * @param hnd non-NULL server handle + * @param auth_fn auth_data_fn to set in server handle + */ + +void cac_SetAuthDataFn(CacServerHandle *hnd, smbc_get_auth_data_fn auth_fn); + +/** Use your own libsmbclient context - not necessary. + * @note You must still call cac_Connect() after specifying your own libsmbclient context + * @param hnd Initialized, but not connected CacServerHandle + * @param ctx The libsmbclient context you would like to use. + */ +void cac_SetSmbcContext(CacServerHandle *hnd, SMBCCTX *ctx); + +/** Connects to a specified server. If there is already a connection to a different server, + * it will be cleaned up before connecting to the new server. + * @param hnd Pre-initialized CacServerHandle + * @param srv (Optional) Name or IP of the server to connect to. If NULL, server from the CacServerHandle will be used. + * + * @return CAC_FAILURE if the operation could not be completed successfully (hnd->status will also be set with a NTSTATUS code) + * @return CAC_SUCCESS if the operation succeeded + */ +int cac_Connect(CacServerHandle *hnd, const char *srv); + + +/** + * Cleans up any data used by the CacServerHandle. If the libsmbclient context was set using cac_SetSmbcContext(), it will not be free'd. + * @param hnd the CacServerHandle to destroy + */ +void cac_FreeHandle(CacServerHandle * hnd); + +/** + * Initializes a CacTime structure based on an NTTIME structure + * If the function fails, then the CacTime structure will be zero'd out + */ +void cac_InitCacTime(CacTime *cactime, NTTIME nttime); + +/** + * Called by cac_NewServerHandle() if allocate_fields = True. You can call this if you want to, allocates sizeof(fstring) char's for every char * field + * @param hnd Uninitialized server handle + * @return CAC_FAILURE Memory could not be allocated + * @return CAC_SUCCESS Memory was allocated + */ +int cac_InitHandleMem(CacServerHandle *hnd); + +/** + * Default smbc_get_auth_data_fn for libmsrpc. This function is called when libmsrpc needs to get more information about the + * client (username/password, workgroup). + * This function provides simple prompts to the user to enter the information. This description his here so you know how to re-define this function. + * @see cac_SetAuthDataFn() + * @param pServer Name/IP of the server to connect to. + * @param pShare Share name to connect to + * @param pWorkgroup libmsrpc passes in the workgroup/domain name from hnd->domain. It can be modified in the function. + * @param maxLenWorkgroup The maximum length of a string pWogroup can hold. + * @param pUsername libmsrpc passes in the username from hnd->username. It can be modified in the function. + * @param maxLenUsername The maximum length of a string pUsername can hold. + * @param pPassword libmsrpc pass in the password from hnd->password. It can be modified in the function. + * @param maxLenPassword The maximum length of a string pPassword can hold. + */ +void cac_GetAuthDataFn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword); + + +/**@}*/ + +/***************** + * LSA Functions * + *****************/ + +/** @addtogroup LSA_Functions + * @{ + */ + +struct LsaOpenPolicy { + /**Inputs*/ + struct { + /**Access Mask. Refer to Security Access Masks in include/rpc_secdes.h*/ + uint32 access; + + /**Use security quality of service? (True/False)*/ + BOOL security_qos; + } in; + + /**Outputs*/ + struct { + /**Handle to the open policy (needed for all other operations)*/ + POLICY_HND *pol; + } out; +}; + +/** + * Opens a policy handle on a remote machine. + * @param hnd fully initialized CacServerHandle for remote machine + * @param mem_ctx Talloc context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE if the policy could not be opened. hnd->status set with appropriate NTSTATUS + * @return CAC_SUCCESS if the policy could be opened, the policy handle can be found + */ +int cac_LsaOpenPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenPolicy *op); + + +/** + * Closes an LSA policy handle (Retrieved using cac_LsaOpenPolicy). + * If successful, the handle will be closed on the server, and memory for pol will be freed + * @param hnd - An initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param pol - the policy handle to close + * @return CAC_FAILURE could not close the policy handle, hnd->status is set to the appropriate NTSTATUS error code + * @return CAC_SUCCESS the policy handle was closed + */ +int cac_LsaClosePolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *pol); + + +struct LsaGetNamesFromSids { + struct { + /**handle to and open LSA policy*/ + POLICY_HND *pol; + + /**the number of SIDs to lookup*/ + uint32 num_sids; + + /**array of SIDs to lookup*/ + DOM_SID *sids; + } in; + + struct { + /**The number of names returned (in case of CAC_PARTIAL_SUCCESS)*/ + uint32 num_found; + + /**array of SID info each index is one sid */ + CacSidInfo *sids; + + /**in case of partial success, an array of SIDs that could not be looked up (NULL if all sids were looked up)*/ + DOM_SID *unknown; + } out; +}; + +/** + * Looks up the names for a list of SIDS + * @param hnd initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op input and output parameters + * @return CAC_FAILURE none of the SIDs could be looked up hnd->status is set with appropriate NTSTATUS error code + * @return CAC_SUCCESS all of the SIDs were translated and a list of names has been output + * @return CAC_PARTIAL_SUCCESS not all of the SIDs were translated, as a result the number of returned names is less than the original list of SIDs + */ +int cac_LsaGetNamesFromSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetNamesFromSids *op); + +struct LsaGetSidsFromNames { + struct { + /**handle to an open LSA policy*/ + POLICY_HND *pol; + + /**number of SIDs to lookup*/ + uint32 num_names; + + /**array of strings listing the names*/ + char **names; + } in; + + struct { + /**The number of SIDs returned (in case of partial success*/ + uint32 num_found; + + /**array of SID info for the looked up names*/ + CacSidInfo *sids; + + /**in case of partial success, the names that were not looked up*/ + char **unknown; + } out; +}; + +/** + * Looks up the SIDs for a list of names + * @param hnd initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op input and output parameters + * @return CAC_FAILURE none of the SIDs could be looked up hnd->status is set with appropriate NTSTATUS error code + * @return CAC_SUCCESS all of the SIDs were translated and a list of names has been output + * @return CAC_PARTIAL_SUCCESS not all of the SIDs were translated, as a result the number of returned names is less than the original list of SIDs + */ +int cac_LsaGetSidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetSidsFromNames *op); + +struct LsaFetchSid { + struct { + /**handle to an open LSA policy*/ + POLICY_HND *pol; + + /**can be CAC_LOCAL_INFO, CAC_DOMAIN_INFO, or (CAC_LOCAL_INFO | CAC_DOMAIN_INFO)*/ + uint16 info_class; + } in; + + struct { + /**the machine's local SID and domain name (NULL if not asked for)*/ + CacSidInfo *local_sid; + + /**the machine's domain SID and name (NULL if not asked for)*/ + CacSidInfo *domain_sid; + + } out; +}; + +/** + * Looks up the domain or local sid of a machine with an open LSA policy handle + * @param hnd initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op input and output parameters + * @return CAC_FAILURE if the SID could not be fetched + * @return CAC_SUCCESS if the SID was fetched + * @return CAC_PARTIAL_SUCCESS if you asked for both local and domain sids but only one was returned + */ +int cac_LsaFetchSid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaFetchSid *op); + +struct LsaQueryInfoPolicy { + struct { + /**Open LSA policy handle on remote server*/ + POLICY_HND *pol; + } in; + + struct { + /**remote server's domain name*/ + char *domain_name; + + /**remote server's dns name*/ + char *dns_name; + + /**remote server's forest name*/ + char *forest_name; + + /**remote server's domain guid*/ + struct uuid *domain_guid; + + /**remote server's domain SID*/ + DOM_SID *domain_sid; + } out; +}; + +/** + * Retrieves information about the LSA machine/domain + * @param hnd initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op input and output parameters + * Note: for pre-Windows 2000 machines, only op->out.SID and op->out.domain will be set. @see cac_LsaFetchSid + * @return - CAC_FAILURE if the operation was not successful. hnd->status will be set with an accurate NT_STATUS code + * @return CAC_SUCCESS the operation was successful. + */ +int cac_LsaQueryInfoPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaQueryInfoPolicy *op); + +struct LsaEnumSids { + struct { + /**Open LSA Policy handle*/ + POLICY_HND *pol; + + /**The prefered maximum number of SIDs returned per call*/ + uint32 pref_max_sids; + } in; + + struct { + /**used to keep track of how many sids have been retrieved over multiple calls + * should be set to zero via ZERO_STRUCT() befrore the first call. Use the same struct LsaEnumSids for multiple calls*/ + uint32 resume_idx; + + /**The number of sids returned this call*/ + uint32 num_sids; + + /**Array of sids returned*/ + DOM_SID *sids; + + } out; +}; + +/** + * Enumerates the SIDs in the LSA. Can be enumerated in blocks by calling the function multiple times. + * Example: while(cac_LsaEnumSids(hnd, mem_ctx, op) { ... } + * @param hnd - An initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE there was an error during operations OR there are no more results + * @return CAC_SUCCESS the operation completed and results were returned + */ +int cac_LsaEnumSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumSids *op); + +struct LsaEnumAccountRights { + struct { + /**Open LSA Policy handle*/ + POLICY_HND *pol; + + /**(Optional) SID of the account - must supply either sid or name*/ + DOM_SID *sid; + + /**(Optional) name of the account - must supply either sid or name*/ + char *name; + } in; + + struct { + /**Count of rights for this account*/ + uint32 num_privs; + + /**array of privilege names*/ + char **priv_names; + } out; +}; + +/** + * Enumerates rights assigned to a given account. Takes a SID instead of account handle as input + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE the rights could not be retrieved. hnd->status is set with NT_STATUS code + * @return CAC_SUCCESS the operation was successful. + */ + +int cac_LsaEnumAccountRights(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumAccountRights *op); + +struct LsaEnumTrustedDomains { + struct { + /**Open LSA policy handle*/ + POLICY_HND *pol; + } in; + + struct { + /**used to keep track of how many domains have been retrieved over multiple calls + * should be set to zero via ZERO_STRUCT() before the first call. Use the same struct LsaEnumSids for multiple calls*/ + uint32 resume_idx; + + /**The number of domains returned by the remote server this call*/ + uint32 num_domains; + + /**array of trusted domain names returned by the remote server*/ + char **domain_names; + + /**array of trusted domain sids returned by the remote server*/ + DOM_SID *domain_sids; + } out; +}; + +/** + * Enumerates the trusted domains in the LSA. + * @param hnd - An initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op - initialized parameters + * @return CAC_FAILURE there was an error during operations OR there are no more results + * @return CAC_SUCCESS the operation completed and results were returned + */ +int cac_LsaEnumTrustedDomains(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumTrustedDomains *op); + +struct LsaOpenTrustedDomain { + struct { + /**an open LSA policy handle*/ + POLICY_HND *pol; + + /**SID of the trusted domain to open*/ + DOM_SID *domain_sid; + + /**Desired access on the open domain*/ + uint32 access; + } in; + + struct { + /**A handle to the policy that is opened*/ + POLICY_HND *domain_pol; + } out; +}; + +/** + * Opens a trusted domain by SID. + * @param hnd An initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op initialized I/O parameters + * @return CAC_FAILURE a handle to the domain could not be opened. hnd->status is set with approriate NT_STATUS code + * @return CAC_SUCCESS the domain was opened successfully + */ +int cac_LsaOpenTrustedDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenTrustedDomain *op); + +struct LsaQueryTrustedDomainInfo { + struct { + /**Open LSA policy handle*/ + POLICY_HND *pol; + + /**Info class of returned data*/ + uint16 info_class; + + /**(Optional)SID of trusted domain to query (must specify either SID or name of trusted domain)*/ + DOM_SID *domain_sid; + + /**(Optional)Name of trusted domain to query (must specify either SID or name of trusted domain)*/ + char *domain_name; + } in; + + struct { + /**information about the trusted domain*/ + LSA_TRUSTED_DOMAIN_INFO *info; + } out; +}; + +/** + * Retrieves information a trusted domain. + * @param hnd An initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op initialized I/O parameters + * @return CAC_FAILURE a handle to the domain could not be opened. hnd->status is set with approriate NT_STATUS code + * @return CAC_SUCCESS the domain was opened successfully + */ + +int cac_LsaQueryTrustedDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaQueryTrustedDomainInfo *op); + +struct LsaEnumPrivileges { + struct { + /**An open LSA policy handle*/ + POLICY_HND *pol; + + /**The _preferred_ maxinum number of privileges returned per call*/ + uint32 pref_max_privs; + } in; + + struct { + /**Used to keep track of how many privileges have been retrieved over multiple calls. Do not modify this value between calls*/ + uint32 resume_idx; + + /**The number of privileges returned this call*/ + uint32 num_privs; + + /**Array of privilege names*/ + char **priv_names; + + /**Array of high bits for privilege LUID*/ + uint32 *high_bits; + + /**Array of low bits for privilege LUID*/ + uint32 *low_bits; + } out; +}; + +/** + * Enumerates the Privileges supported by the LSA. Can be enumerated in blocks by calling the function multiple times. + * Example: while(cac_LsaEnumPrivileges(hnd, mem_ctx, op) { ... } + * @param hnd An initialized and connected server handle + * @param mem_ctx Talloc context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE there was an error during operations OR there are no more results + * @return CAC_SUCCESS the operation completed and results were returned + * @see CAC_OP_FAILED() + */ +int cac_LsaEnumPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumPrivileges *op); + +struct LsaOpenAccount { + struct { + /**An open LSA policy handle*/ + POLICY_HND *pol; + + /**(Optional) account SID - must supply either sid or name*/ + DOM_SID *sid; + + /**(Optional) account name - must supply either sid or name*/ + char *name; + + /**desired access for the handle*/ + uint32 access; + } in; + + struct { + /**A handle to the opened user*/ + POLICY_HND *user; + } out; +}; + +/** + * Opens a handle to an account in the LSA + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE the account could not be opened. hnd->status has appropriate NT_STATUS code + * @return CAC_SUCCESS the account was opened + */ +int cac_LsaOpenAccount(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenAccount *op); + +struct LsaAddPrivileges { + struct { + /**An open LSA policy handle*/ + POLICY_HND *pol; + + /**(Optional) The user's SID (must specify at least sid or name)*/ + DOM_SID *sid; + + /**(Optional) The user's name (must specify at least sid or name)*/ + char *name; + + /**The privilege names of the privileges to add for the account*/ + char **priv_names; + + /**The number of privileges in the priv_names array*/ + uint32 num_privs; + + } in; +}; + +/** + * Adds Privileges an account. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE the privileges could not be set. hnd->status has appropriate NT_STATUS code + * @return CAC_SUCCESS the privileges were set. + */ +int cac_LsaAddPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAddPrivileges *op); + +struct LsaRemovePrivileges { + struct { + /**An open handle to the LSA*/ + POLICY_HND *pol; + + /**(Optional) The account SID (must specify at least sid or name)*/ + DOM_SID *sid; + + /**(Optional) The account name (must specify at least sid or name)*/ + char *name; + + /**The privilege names of the privileges to remove from the account*/ + char **priv_names; + + /**The number of privileges in the priv_names array*/ + uint32 num_privs; + + } in; + + struct { + } out; +}; + +/** + * Removes a _specific_ set of privileges from an account + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE the privileges could not be removed. hnd->status is set with NT_STATUS code + * @return CAC_SUCCESS the privileges were removed + */ +int cac_LsaRemovePrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaRemovePrivileges *op); + +struct LsaClearPrivileges { + struct { + /**An open handle to the LSA*/ + POLICY_HND *pol; + + /**(Optional) The user's SID (must specify at least sid or name)*/ + DOM_SID *sid; + + /**(Optional) The user's name (must specify at least sid or name)*/ + char *name; + } in; + + struct { + } out; +}; + +/** + * Removes ALL privileges from an account + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE the operation was not successful, hnd->status set with NT_STATUS code + * @return CAC_SUCCESS the opeartion was successful. + */ +int cac_LsaClearPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaClearPrivileges *op); + +/** + * Sets an accounts priviliges. Removes all privileges and then adds specified privileges. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE The operation could not complete successfully + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_LsaSetPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAddPrivileges *op); + +struct LsaGetSecurityObject { + struct { + /**Open LSA policy handle*/ + POLICY_HND *pol; + } in; + + struct { + /**Returned security descriptor information*/ + SEC_DESC_BUF *sec; + } out; +}; + +/** + * Retrieves Security Descriptor information about the LSA + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE The operation could not complete successfully + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_LsaGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetSecurityObject *op); + + +/**@}*/ /*LSA_Functions*/ + +/********************** + * Registry Functions * + *********************/ + +/**@addtogroup Reg_Functions + * @{ + */ + +struct RegConnect { + struct { + /** must be one of : + * HKEY_CLASSES_ROOT, + * HKEY_LOCAL_MACHINE, + * HKEY_USERS, + * HKEY_PERFORMANCE_DATA, + */ + int root; + + /**desired access on the root key + * combination of: + * REG_KEY_READ, + * REG_KEY_WRITE, + * REG_KEY_EXECUTE, + * REG_KEY_ALL, + * found in include/rpc_secdes.h*/ + uint32 access; + } in; + + struct { + POLICY_HND *key; + } out; +}; + +/** + * Opens a handle to the registry on the server + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect *op); + +/** + * Closes an open registry handle + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param key The Key/Handle to close + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *key); + +struct RegOpenKey { + struct { + /**(Optional)parent key. + * If this is NULL, then cac_RegOpenKey() will attempt to connect to the registry, name MUST start with something like:<br> + * HKEY_LOCAL_MACHINE\ or an abbreviation like HKCR\ + * + * supported root names: + * - HKEY_LOCAL_MACHINE\ or HKLM\ + * - HKEY_CLASSES_ROOT\ or HKCR\ + * - HKEY_USERS\ or HKU\ + * - HKEY_PERFORMANCE_DATA or HKPD\ + */ + POLICY_HND *parent_key; + + /**name/path of key*/ + char *name; + + /**desired access on this key*/ + uint32 access; + } in; + + struct { + POLICY_HND *key; + } out; +}; + +/** + * Opens a registry key + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_RegOpenKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegOpenKey *op); + +struct RegEnumKeys { + struct { + /**enumerate subkeys of this key*/ + POLICY_HND *key; + + /**maximum number of keys to enumerate each call*/ + uint32 max_keys; + } in; + + struct { + /**keeps track of the index to resume enumerating*/ + uint32 resume_idx; + + /**the number of keys returned this call*/ + uint32 num_keys; + + /**array of key names*/ + char **key_names; + + /**class names of the keys*/ + char **class_names; + + /**last modification time of the key*/ + time_t *mod_times; + } out; +}; + +/** + * Enumerates Subkeys of a given key. Can be run in a loop. Example: while(cac_RegEnumKeys(hnd, mem_ctx, op)) { ... } + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @see CAC_OP_FAILED() + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegEnumKeys(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumKeys *op); + + +struct RegCreateKey { + struct { + /**create a subkey of parent_key*/ + POLICY_HND *parent_key; + + /**name of the key to create*/ + char *key_name; + + /**class of the key*/ + char *class_name; + + /**Access mask to open the key with. See REG_KEY_* in include/rpc_secdes.h*/ + uint32 access; + } in; + + struct { + /**Open handle to the key*/ + POLICY_HND *key; + } out; +}; + +/** + * Creates a registry key, if the key already exists, it will be opened __Creating keys is not currently working__. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parmeters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegCreateKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegCreateKey *op); + +struct RegDeleteKey { + struct { + /**handle to open registry key*/ + POLICY_HND *parent_key; + + /**name of the key to delete*/ + char *name; + + /**delete recursively. WARNING: this might not always work as planned*/ + BOOL recursive; + } in; + +}; + +/** + * Deletes a subkey of an open key. Note: if you run this with op->in.recursive == True, and the operation fails, it may leave the key in an inconsistent state. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op); + +struct RegDeleteValue { + struct { + /**handle to open registry key*/ + POLICY_HND *parent_key; + + /**name of the value to delete*/ + char *name; + } in; +}; + +/** + * Deletes a registry value. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegDeleteValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteValue *op); + +struct RegQueryKeyInfo { + struct { + /**Open handle to the key to query*/ + POLICY_HND *key; + } in; + + struct { + /**name of the key class*/ + char *class_name; + + /**number of subkeys of the key*/ + uint32 num_subkeys; + + /**length (in characters) of the longest subkey name*/ + uint32 longest_subkey; + + /**length (in characters) of the longest class name*/ + uint32 longest_class; + + /**number of values in this key*/ + uint32 num_values; + + /**length (in characters) of the longest value name*/ + uint32 longest_value_name; + + /**length (in bytes) of the biggest value data*/ + uint32 longest_value_data; + + /**size (in bytes) of the security descriptor*/ + uint32 security_desc_size; + + /**time of the last write*/ + time_t last_write_time; + } out; +}; + +/** + * Retrieves information about an open key + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_RegQueryKeyInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryKeyInfo *op); + +struct RegSaveKey { + struct { + /**Open key to be saved*/ + POLICY_HND *key; + + /**The path (on the remote computer) to save the file to*/ + char *filename; + } in; +}; + +/** + * Saves a key to a file on the remote machine __Not currently working__. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_RegSaveKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSaveKey *op); + +struct RegQueryValue { + struct { + /**handle to open registry key*/ + POLICY_HND *key; + + /**name of the value to query*/ + char *val_name; + } in; + + struct { + /**Value type. + * One of: + * - REG_DWORD (equivalent to REG_DWORD_LE) + * - REG_DWORD_BE + * - REG_SZ + * - REG_EXPAND_SZ + * - REG_MULTI_SZ + * - REG_BINARY + */ + uint32 type; + + /**The value*/ + REG_VALUE_DATA *data; + } out; +}; + +/** + * Retrieves a value (type and data) _not currently working_. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_RegQueryValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryValue *op); + +struct RegEnumValues { + struct { + /**handle to open key*/ + POLICY_HND *key; + + /**max number of values returned per call*/ + uint32 max_values; + + } in; + + struct { + /**keeps track of the index to resume from - used over multiple calls*/ + uint32 resume_idx; + + /**the number of values that were returned this call*/ + uint32 num_values; + + /**Array of value types. A type can be one of: + * - REG_DWORD (equivalent to REG_DWORD_LE) + * - REG_DWORD_BE + * - REG_SZ + * - REG_EXPAND_SZ + * - REG_MULTI_SZ + * - REG_BINARY + */ + uint32 *types; + + /**array of strings storing the names of the values*/ + char **value_names; + + /**array of pointers to the value data returned*/ + REG_VALUE_DATA **values; + } out; +}; + +/** + * Enumerates a number of Registry values in an open registry key. + * Can be run in a loop. Example: while(cac_RegEnumValues(hnd, mem_ctx, op)) { ... } + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @see CAC_OP_FAILED() + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegEnumValues(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumValues *op); + +struct RegSetValue { + struct { + /**Handle to open registry key*/ + POLICY_HND *key; + + /**Name of the value*/ + char *val_name; + + /**Value type. + * One of: + * - REG_DWORD (equivalent to REG_DWORD_LE) + * - REG_DWORD_BE + * - REG_SZ + * - REG_EXPAND_SZ + * - REG_MULTI_SZ + * - REG_BINARY + */ + uint32 type; + + /**the value*/ + REG_VALUE_DATA value; + } in; +}; + +/** + * Sets or creates value (type and data). + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegSetValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetValue *op); + +struct RegGetVersion { + struct { + /**open registry key*/ + POLICY_HND *key; + } in; + + struct { + /**version number*/ + uint32 version; + } out; +}; + +/** + * Retrieves the registry version number + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegGetVersion(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetVersion *op); + +struct RegGetKeySecurity { + struct { + /**Handle to key to query*/ + POLICY_HND *key; + + /**Info that you want. Should be a combination of (1 or more or'd): + * - OWNER_SECURITY_INFORMATION + * - GROUP_SECURITY_INFORMATION + * - DACL_SECURITY_INFORMATION + * - SACL_SECURITY_INFORMATION + * - UNPROTECTED_SACL_SECURITY_INFORMATION + * - UNPROTECTED_DACL_SECURITY_INFORMATION + * - PROTECTED_SACL_SECURITY_INFORMATION + * - PROTECTED_DACL_SECURITY_INFORMATION + * + * or use: + * - ALL_SECURITY_INFORMATION + * + * all definitions from include/rpc_secdes.h + */ + uint32 info_type; + } in; + + struct { + /**size of the data returned*/ + uint32 size; + + /**Security descriptor*/ + SEC_DESC *descriptor; + } out; +}; + +/** + * Retrieves a key security descriptor. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_RegGetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetKeySecurity *op); + +struct RegSetKeySecurity { + struct { + /**Handle to key to query*/ + POLICY_HND *key; + + /**Info that you want. Should be a combination of (1 or more or'd): + * - OWNER_SECURITY_INFORMATION + * - GROUP_SECURITY_INFORMATION + * - DACL_SECURITY_INFORMATION + * - SACL_SECURITY_INFORMATION + * - UNPROTECTED_SACL_SECURITY_INFORMATION + * - UNPROTECTED_DACL_SECURITY_INFORMATION + * - PROTECTED_SACL_SECURITY_INFORMATION + * - PROTECTED_DACL_SECURITY_INFORMATION + * + * or use: + * - ALL_SECURITY_INFORMATION + * + * all definitions from include/rpc_secdes.h + */ + uint32 info_type; + + /**size of the descriptor*/ + size_t size; + + /**Security descriptor*/ + SEC_DESC *descriptor; + } in; +}; + +/** + * Sets the key security descriptor. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_RegSetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetKeySecurity *op); + +/**@}*/ /*Reg_Functions*/ + +struct Shutdown { + struct { + /**the message to display (can be NULL)*/ + char *message; + + /**timeout in seconds*/ + uint32 timeout; + + /**False = shutdown, True = reboot*/ + BOOL reboot; + + /**force the*/ + BOOL force; + + /*FIXME: make this useful*/ + uint32 reason; + } in; +}; + + +/** + * Shutdown the server _not currently working_. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op); + +/** + * Attempt to abort initiated shutdown on the server _not currently working_. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_AbortShutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx); + +/***************** + * SAM Functions * + *****************/ + +/**@addtogroup SAM_Functions + * @{ + */ +struct SamConnect { + struct { + /**Access mask to open with + * see generic access masks in include/smb.h*/ + uint32 access; + } in; + + struct { + POLICY_HND *sam; + } out; +}; + +/** + * Connects to the SAM. This can be skipped by just calling cac_SamOpenDomain() + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_SamConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamConnect *op); + + +/** + * Closes any (SAM, domain, user, group, etc.) SAM handle. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param sam Handle to close + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_SamClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *sam); + +struct SamOpenDomain { + struct { + /**The desired access. See generic access masks - include/smb.h*/ + uint32 access; + + /**(Optional) An open handle to the SAM. If it is NULL, the function will connect to the SAM with the access mask above*/ + POLICY_HND *sam; + + /**(Optional) The SID of the domain to open. + * If this this is NULL, the function will attempt to open the domain specified in hnd->domain */ + DOM_SID *sid; + } in; + + struct { + /**handle to the open domain*/ + POLICY_HND *dom_hnd; + + /**Handle to the open SAM*/ + POLICY_HND *sam; + } out; +}; + +/** + * Opens a handle to a domain. This must be called before any other SAM functions + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamOpenDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenDomain *op); + +struct SamCreateUser { + struct { + /**Open domain handle*/ + POLICY_HND *dom_hnd; + + /**Username*/ + char *name; + + /**See Allowable account control bits in include/smb.h*/ + uint32 acb_mask; + } in; + + struct { + /**handle to the user*/ + POLICY_HND *user_hnd; + + /**rid of the user*/ + uint32 rid; + } out; +}; + +/** + * Creates a new domain user, if the account already exists it will _not_ be opened and hnd->status will be NT_STATUS_USER_EXISTS + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_SamCreateUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateUser *op); + +struct SamOpenUser { + struct { + /**Handle to open SAM connection*/ + POLICY_HND *dom_hnd; + + /**desired access - see generic access masks in include/smb.h*/ + uint32 access; + + /**RID of the user*/ + uint32 rid; + + /**(Optional) name of the user - must supply either RID or user name*/ + char *name; + } in; + + struct { + /**Handle to the user*/ + POLICY_HND *user_hnd; + } out; +}; + +/** + * Opens a domain user. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamOpenUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenUser *op); + +/** + * Deletes a domain user. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param user_hnd Open handle to the user + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamDeleteUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd); + + +struct SamEnumUsers { + struct { + /**Open handle to a domain*/ + POLICY_HND *dom_hnd; + + /**Enumerate users with specific ACB. If 0, all users will be enumerated*/ + uint16 acb_mask; + } in; + + struct { + /**where to resume from. Used over multiple calls*/ + uint32 resume_idx; + + /**the number of users returned this call*/ + uint32 num_users; + + /**Array storing the rids of the returned users*/ + uint32 *rids; + + /**Array storing the names of all the users returned*/ + char **names; + + BOOL done; + } out; +}; + +/** + * Enumerates domain users. Can be used as a loop condition. Example: while(cac_SamEnumUsers(hnd, mem_ctx, op)) { ... } + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamEnumUsers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumUsers *op); + +struct SamGetNamesFromRids { + struct { + /**An open handle to the domain SAM from cac_SamOpenDomain()*/ + POLICY_HND *dom_hnd; + + /**Number of RIDs to resolve*/ + uint32 num_rids; + + /**Array of RIDs to resolve*/ + uint32 *rids; + } in; + + struct { + /**the number of names returned - if this is 0, the map is NULL*/ + uint32 num_names; + + /**array contiaing the Names and RIDs*/ + CacLookupRidsRecord *map; + } out; +}; + +/** + * Returns a list of names which map to a list of RIDs. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetNamesFromRids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetNamesFromRids *op); + +struct SamGetRidsFromNames { + struct { + /**An open handle to the domain SAM from cac_SamOpenDomain()*/ + POLICY_HND *dom_hnd; + + /**Number of names to resolve*/ + uint32 num_names; + + /**Array of names to resolve*/ + char **names; + } in; + + struct { + /**the number of names returned - if this is 0, then map is NULL*/ + uint32 num_rids; + + /**array contiaing the Names and RIDs*/ + CacLookupRidsRecord *map; + } out; +}; + +/** + * Returns a list of RIDs which map to a list of names. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetRidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetRidsFromNames *op); + +struct SamGetGroupsForUser { + struct { + /**An open handle to the user*/ + POLICY_HND *user_hnd; + } in; + + struct { + /**The number of groups the user is a member of*/ + uint32 num_groups; + + /**The RIDs of the groups*/ + uint32 *rids; + + /**The attributes of the groups*/ + uint32 *attributes; + } out; +}; +/** + * Retrieves a list of groups that a user is a member of. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetGroupsForUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupsForUser *op); + +struct SamOpenGroup { + struct { + /**Open handle to the domain SAM*/ + POLICY_HND *dom_hnd; + + /**Desired access to open the group with. See Generic access masks in include/smb.h*/ + uint32 access; + + /**rid of the group*/ + uint32 rid; + } in; + + struct { + /**Handle to the group*/ + POLICY_HND *group_hnd; + } out; +}; + +/** + * Opens a domain group. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamOpenGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenGroup *op); + +struct SamCreateGroup { + struct { + /**Open handle to the domain SAM*/ + POLICY_HND *dom_hnd; + + /**Desired access to open the group with. See Generic access masks in include/smb.h*/ + uint32 access; + + /**The name of the group*/ + char *name; + } in; + + struct { + /**Handle to the group*/ + POLICY_HND *group_hnd; + } out; +}; + +/** + * Creates a group. If the group already exists it will not be opened. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamCreateGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateGroup *op); + +/** + * Deletes a domain group. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param group_hnd Open handle to the group. + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamDeleteGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd); + +struct SamGetGroupMembers { + struct { + /**Open handle to a group*/ + POLICY_HND *group_hnd; + } in; + + struct { + /**The number of members in the group*/ + uint32 num_members; + + /**An array storing the RIDs of the users*/ + uint32 *rids; + + /**The attributes*/ + uint32 *attributes; + } out; +}; + +/** + * Retrives a list of users in a group. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupMembers *op); + +struct SamAddGroupMember { + struct { + /**Open handle to a group*/ + POLICY_HND *group_hnd; + + /**RID of new member*/ + uint32 rid; + } in; +}; + +/** + * Adds a user to a group. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamAddGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddGroupMember *op); + +struct SamRemoveGroupMember { + struct { + /**Open handle to a group*/ + POLICY_HND *group_hnd; + + /**RID of member to remove*/ + uint32 rid; + } in; +}; + +/** + * Removes a user from a group. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamRemoveGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveGroupMember *op); + +/** + * Removes all the members of a group - warning: if this function fails is is possible that some but not all members were removed + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param group_hnd Open handle to the group to clear + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamClearGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd); + +struct SamSetGroupMembers { + struct { + /**Open handle to the group*/ + POLICY_HND *group_hnd; + + /**Number of members in the group - if this is 0, all members of the group will be removed*/ + uint32 num_members; + + /**The RIDs of the users to add*/ + uint32 *rids; + } in; +}; + +/** + * Clears the members of a group and adds a list of members to the group + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamSetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupMembers *op); + +struct SamEnumGroups { + struct { + /**Open handle to a domain*/ + POLICY_HND *dom_hnd; + } in; + + struct { + /**Where to resume from _do not_ modify this value. Used over multiple calls.*/ + uint32 resume_idx; + + /**the number of users returned this call*/ + uint32 num_groups; + + /**Array storing the rids of the returned groups*/ + uint32 *rids; + + /**Array storing the names of all the groups returned*/ + char **names; + + /**Array storing the descriptions of all the groups returned*/ + char **descriptions; + + BOOL done; + } out; +}; + +/** + * Enumerates domain groups. Can be used as a loop condition. Example: while(cac_SamEnumGroups(hnd, mem_ctx, op)) { ... } + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamEnumGroups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumGroups *op); + +struct SamEnumAliases { + struct { + /**Open handle to a domain*/ + POLICY_HND *dom_hnd; + } in; + + struct { + /**where to resume from. Used over multiple calls*/ + uint32 resume_idx; + + /**the number of users returned this call*/ + uint32 num_aliases; + + /**Array storing the rids of the returned groups*/ + uint32 *rids; + + /**Array storing the names of all the groups returned*/ + char **names; + + /**Array storing the descriptions of all the groups returned*/ + char **descriptions; + + BOOL done; + } out; +}; + +/** + * Enumerates domain aliases. Can be used as a loop condition. Example: while(cac_SamEnumAliases(hnd, mem_ctx, op)) { ... } + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamEnumAliases(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumAliases *op); + +struct SamCreateAlias { + struct { + /**Open handle to the domain SAM*/ + POLICY_HND *dom_hnd; + + /**The name of the alias*/ + char *name; + } in; + + struct { + /**Handle to the group*/ + POLICY_HND *alias_hnd; + } out; +}; + +/** + * Creates an alias. If the alias already exists it will not be opened. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_SamCreateAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateAlias *op); + +struct SamOpenAlias { + struct { + /**Open handle to the domain SAM*/ + POLICY_HND *dom_hnd; + + /**Desired access to open the group with. See Generic access masks in include/smb.h*/ + uint32 access; + + /**rid of the alias*/ + uint32 rid; + } in; + + struct { + /**Handle to the alias*/ + POLICY_HND *alias_hnd; + } out; +}; + +/** + * Opens a handle to an alias. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamOpenAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenAlias *op); + +/** + * Deletes an alias. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param alias_hnd Open handle to the alias + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamDeleteAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd); + +struct SamAddAliasMember { + struct { + /**Open handle to a alias*/ + POLICY_HND *alias_hnd; + + /**SID of new member*/ + DOM_SID *sid; + } in; +}; + +/** + * Adds an account to an alias. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamAddAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddAliasMember *op); + +struct SamRemoveAliasMember { + struct { + /**Open handle to the alias*/ + POLICY_HND *alias_hnd; + + /**The SID of the member*/ + DOM_SID *sid; + } in; +}; + +/** + * Removes an account from an alias. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamRemoveAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveAliasMember *op); + +struct SamGetAliasMembers { + struct { + /**Open handle to the alias*/ + POLICY_HND *alias_hnd; + } in; + + struct { + /**The number of members*/ + uint32 num_members; + + /**An array storing the SIDs of the accounts*/ + DOM_SID *sids; + } out; +}; + +/** + * Retrieves a list of all accounts in an alias. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasMembers *op); + +/** + * Removes all the members of an alias - warning: if this function fails is is possible that some but not all members were removed + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param alias_hnd Handle to the alias to clear + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_SamClearAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd); + +struct SamSetAliasMembers { + struct { + /**Open handle to the group*/ + POLICY_HND *alias_hnd; + + /**Number of members in the group - if this is 0, all members of the group will be removed*/ + uint32 num_members; + + /**The SIDs of the accounts to add*/ + DOM_SID *sids; + } in; +}; + +/** + * Clears the members of an alias and adds a list of members to the alias + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamSetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasMembers *op); + + +struct SamUserChangePasswd { + struct { + /**The username*/ + char *username; + + /**The current password*/ + char *password; + + /**The new password*/ + char *new_password; + } in; +}; +/**Used by a user to change their password*/ +int cac_SamUserChangePasswd(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamUserChangePasswd *op); + +/** + * Enables a user + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param user_hnd Open handle to the user to enable + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamEnableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd); + +/** + * Disables a user + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param user_hnd Open handle to the user to disables + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamDisableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd); + +struct SamSetPassword { + struct { + /**Open handle to a user*/ + POLICY_HND *user_hnd; + + /**The new password*/ + char *password; + } in; +}; + +/** + * Sets a user's password + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_SamSetPassword(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetPassword *op); + +struct SamGetUserInfo { + struct { + /**Open Handle to a user*/ + POLICY_HND *user_hnd; + } in; + + struct { + CacUserInfo *info; + } out; +}; + +/** + * Retrieves user information using a CacUserInfo structure. If you would like to use a SAM_USERINFO_CTR directly, use cac_SamGetUserInfoCtr() + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @see cac_SamGetUserInfoCtr() + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfo *op); + +struct SamSetUserInfo { + struct { + /**Open handle to a user*/ + POLICY_HND *user_hnd; + + /**Structure containing the data you would like to set*/ + CacUserInfo *info; + } in; +}; + +/** + * Sets the user info using a CacUserInfo structure. If you would like to use a SAM_USERINFO_CTR directly use cac_SamSetUserInfoCtr(). + * @note All fields in the CacUserInfo structure will be set. Best to call cac_GetUserInfo() modify fields that you want, and then call cac_SetUserInfo(). + * @note When calling this, you _must_ set the user's password. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @see cac_SamSetUserInfoCtr() + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamSetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfo *op); + +struct SamGetUserInfoCtr { + struct { + /**Open handle to a user*/ + POLICY_HND *user_hnd; + + /**What USER_INFO structure you want. See include/rpc_samr.h*/ + uint16 info_class; + } in; + + struct { + /**returned user info*/ + SAM_USERINFO_CTR *ctr; + } out; +}; + +/** + * Retrieves user information using a SAM_USERINFO_CTR structure. If you don't want to use this structure, user SamGetUserInfo() + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @see cac_SamGetUserInfo() + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfoCtr *op); + +struct SamSetUserInfoCtr { + struct { + /**Open handle to a user*/ + POLICY_HND *user_hnd; + + /**user info - make sure ctr->switch_value is set properly*/ + SAM_USERINFO_CTR *ctr; + } in; +}; + +/** + * Sets the user info using a SAM_USERINFO_CTR structure. If you don't want to use this structure, use cac_SamSetUserInfo() + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @see cac_SamSetUserInfo() + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_SamSetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfoCtr *op); + +struct SamRenameUser { + struct { + /**Open handle to user*/ + POLICY_HND *user_hnd; + + /**New user name*/ + char *new_name; + } in; +}; + +/** + * Changes the name of a user. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamRenameUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameUser *op); + +struct SamGetGroupInfo { + struct { + /**Open handle to a group*/ + POLICY_HND *group_hnd; + } in; + + struct { + /**Returned info about the group*/ + CacGroupInfo *info; + } out; +}; + +/** + * Retrieves information about a group. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupInfo *op); + +struct SamSetGroupInfo { + struct { + /**Open handle to a group*/ + POLICY_HND *group_hnd; + + /**group info*/ + CacGroupInfo *info; + } in; +}; + +/** + * Sets information about a group. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamSetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupInfo *op); + +struct SamRenameGroup { + struct { + /**Open handle to a group*/ + POLICY_HND *group_hnd; + + /**New name*/ + char *new_name; + } in; +}; + +/** + * Changes the name of a group + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ + +int cac_SamRenameGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameGroup *op); + +struct SamGetAliasInfo { + struct { + /**Open handle to an alias*/ + POLICY_HND *alias_hnd; + } in; + + struct { + /**Returned alias info*/ + CacAliasInfo *info; + } out; +}; + +/** + * Retrieves information about an alias. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamGetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasInfo *op); + +struct SamSetAliasInfo { + struct { + /**Open handle to an alias*/ + POLICY_HND *alias_hnd; + + /**Returned alias info*/ + CacAliasInfo *info; + } in; +}; + +/** + * Sets information about an alias. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE The operation could not complete successfully. hnd->status is set with appropriate NTSTATUS code + * @return CAC_SUCCESS The operation completed successfully + */ +int cac_SamSetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasInfo *op); + +struct SamGetDomainInfo { + struct { + /**Open handle to the domain SAM*/ + POLICY_HND *dom_hnd; + } in; + + struct { + /**Returned domain info*/ + CacDomainInfo *info; + } out; +}; + +/** + * Gets domain information in the form of a CacDomainInfo structure. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @see SamGetDomainInfoCtr() + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + * @return CAC_PARTIAL_SUCCESS - This function makes 3 rpc calls, if one or two fail and the rest succeed, + * not all fields in the CacDomainInfo structure will be filled + */ +int cac_SamGetDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfo *op); + +struct SamGetDomainInfoCtr { + struct { + /**Open handle to domain*/ + POLICY_HND *dom_hnd; + + /**What info level you want*/ + uint16 info_class; + } in; + + struct { + SAM_UNK_CTR *info; + } out; +}; + +/** + * Gets domain information in the form of a SAM_UNK_CTR structure. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @see SamGetDomainInfo() + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SamGetDomainInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfoCtr *op); + +struct SamGetDisplayInfo { + struct { + /**Open handle to domain*/ + POLICY_HND *dom_hnd; + + /**What type of data*/ + uint16 info_class; + + /**(Optional)If 0, max_entries and max_size will be filled in by the function*/ + uint32 max_entries; + + /**(Optional)If 0, max_entries and max_size will be filled in by the function*/ + uint32 max_size; + } in; + + struct { + /**Do not modify this value, use the same value between multiple calls (ie in while loop)*/ + uint32 resume_idx; + + /**Number of entries returned*/ + uint32 num_entries; + + /**Returned display info*/ + SAM_DISPINFO_CTR ctr; + + /**Internal value. Do not modify.*/ + uint32 loop_count; + + BOOL done; + } out; +}; + +/** + * Gets dislpay information using a SAM_DISPINFO_CTR. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SamGetDisplayInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDisplayInfo *op); + +struct SamLookupDomain { + struct { + /**Open handle to the sam (opened with cac_SamConnect() or cac_SamOpenDomain()*/ + POLICY_HND *sam; + + /**Name of the domain to lookup*/ + char *name; + } in; + + struct { + /**SID of the domain*/ + DOM_SID *sid; + } out; +}; + +/** + * Looks up a Domain SID given it's name. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SamLookupDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamLookupDomain *op); + +struct SamGetSecurityObject { + struct { + /**An open handle (SAM, domain or user)*/ + POLICY_HND *pol; + } in; + + struct { + SEC_DESC_BUF *sec; + } out; +}; + +/** + * Retrievies Security descriptor information for a SAM/Domain/user + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SamGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetSecurityObject *op); + +struct SamFlush { + struct { + /**Open handle to the domain SAM*/ + POLICY_HND *dom_hnd; + + /**(Optional)Domain SID. If NULL, the domain in hnd->domain will be opened*/ + DOM_SID *sid; + + /**(Optional)Desired access to re-open the domain with. If 0, MAXIMUM_ALLOWED_ACCESS is used.*/ + uint32 access; + } in; +}; + +/** + * Closes the domain handle, then re-opens it - effectively flushing any changes made. + * WARNING: if this fails you will no longer have an open handle to the domain SAM. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SamFlush(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamFlush *op); + +/**@}*/ /*SAM_Functions*/ + +/**@addtogroup SCM_Functions + * @{ + */ + +struct SvcOpenScm { + struct { + /**Desired access to open the Handle with. See SC_RIGHT_MGR_* or SC_MANAGER_* in include/rpc_secdes.h*/ + uint32 access; + } in; + + struct { + /**Handle to the SCM*/ + POLICY_HND *scm_hnd; + } out; +}; + +/** + * Opens a handle to the SCM on the remote machine. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcOpenScm(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenScm *op); + +/** + * Closes an Svc handle (SCM or Service) + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param scm_hnd The handle to close + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *scm_hnd); + +struct SvcEnumServices { + struct { + /**Open handle to the SCM*/ + POLICY_HND *scm_hnd; + + /**(Optional)Type of service to enumerate. Possible values: + * - SVCCTL_TYPE_WIN32 + * - SVCCTL_TYPE_DRIVER + * If this is 0, (SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32) is assumed. + */ + uint32 type; + + /**(Optional)State of service to enumerate. Possible values: + * - SVCCTL_STATE_ACTIVE + * - SVCCTL_STATE_INACTIVE + * - SVCCTL_STATE_ALL + * If this is 0, SVCCTL_STATE_ALL is assumed. + */ + uint32 state; + } in; + + struct { + /**Number of services returned*/ + uint32 num_services; + + /**Array of service structures*/ + CacService *services; + } out; +}; + +/** + * Enumerates services on the remote machine. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcEnumServices(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcEnumServices *op); + +struct SvcOpenService { + struct { + /**Handle to the Service Control Manager*/ + POLICY_HND *scm_hnd; + + /**Access mask to open service with see SERVICE_* or SC_RIGHT_SVC_* in include/rpc_secdes.h*/ + uint32 access; + + /**The name of the service. _not_ the display name*/ + char *name; + } in; + + struct { + /**Handle to the open service*/ + POLICY_HND *svc_hnd; + } out; +}; + +/** + * Opens a handle to a service. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ + +int cac_SvcOpenService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenService *op); + +struct SvcGetStatus { + struct { + /**Open handle to the service to query*/ + POLICY_HND *svc_hnd; + } in; + + struct { + /**The status of the service. See include/rpc_svcctl.h for SERVICE_STATUS definition.*/ + SERVICE_STATUS status; + } out; +}; + +/** + * Retrieves the status of a service. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcGetStatus(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetStatus *op); + +struct SvcStartService { + struct { + /**open handle to the service*/ + POLICY_HND *svc_hnd; + + /**Array of parameters to start the service with. Can be NULL if num_parms is 0*/ + char **parms; + + /**Number of parameters in the parms array*/ + uint32 num_parms; + + /**Number of seconds to wait for the service to actually start. If this is 0, then the status will not be checked after the initial call*/ + uint32 timeout; + } in; +}; + +/** + * Attempts to start a service. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ + +int cac_SvcStartService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStartService *op); + +struct SvcControlService { + struct { + /**Open handle to the service to control*/ + POLICY_HND *svc_hnd; + + /**The control operation to perform. Possible values (from include/rpc_svcctl.h): + * - SVCCTL_CONTROL_STOP + * - SVCCTL_CONTROL_PAUSE + * - SVCCTL_CONTROL_CONTINUE + * - SVCCTL_CONTROL_SHUTDOWN + */ + uint32 control; + } in; + + struct { + /**The returned status of the service, _immediately_ after the call*/ + SERVICE_STATUS *status; + } out; +}; + +/** + * Performs a control operation on a service and _immediately_ returns. + * @see cac_SvcStopService() + * @see cac_SvcPauseService() + * @see cac_SvcContinueService() + * @see cac_SvcShutdownService() + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcControlService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcControlService *op); + +struct SvcStopService { + struct { + /**Open handle to the service*/ + POLICY_HND *svc_hnd; + + /**Number of seconds to wait for the service to actually start. + * If this is 0, then the status will not be checked after the initial call and CAC_SUCCESS might be returned if the status isn't actually started + */ + uint32 timeout; + } in; + + struct { + /**Status of the service after the operation*/ + SERVICE_STATUS status; + } out; +}; + +/** + * Attempts to stop a service. + * @see cacSvcControlService() + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful. If hnd->status is NT_STATUS_OK, then a timeout occured. + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcStopService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStopService *op); + +struct SvcPauseService { + struct { + /**Open handle to the service*/ + POLICY_HND *svc_hnd; + + /**Number of seconds to wait for the service to actually start. + * If this is 0, then the status will not be checked after the initial call and CAC_SUCCESS might be returned if the status isn't actually started + */ + uint32 timeout; + } in; + + struct { + /**Status of the service after the operation*/ + SERVICE_STATUS status; + } out; +}; + +/** + * Attempts to pause a service. + * @see cacSvcControlService() + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful. If hnd->status is NT_STATUS_OK, then a timeout occured. + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcPauseService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcPauseService *op); + +struct SvcContinueService { + struct { + /**Open handle to the service*/ + POLICY_HND *svc_hnd; + + /**Number of seconds to wait for the service to actually start. + * If this is 0, then the status will not be checked after the initial call and CAC_SUCCESS might be returned if the status isn't actually started + */ + uint32 timeout; + } in; + + struct { + /**Status of the service after the operation*/ + SERVICE_STATUS status; + } out; +}; + +/** + * Attempts to continue a paused service. + * @see cacSvcControlService() + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful. If hnd->status is NT_STATUS_OK, then a timeout occured. + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcContinueService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcContinueService *op); + +struct SvcGetDisplayName { + struct { + /**Open handle to the service*/ + POLICY_HND *svc_hnd; + } in; + + struct { + /**The returned display name of the service*/ + char *display_name; + } out; +}; + +/** + * Retrieves the display name of a service _not currently working_ + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcGetDisplayName(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetDisplayName *op); + +struct SvcGetServiceConfig { + struct { + /**Open handle to the service*/ + POLICY_HND *svc_hnd; + } in; + + struct { + /**Returned Configuration information*/ + CacServiceConfig config; + } out; +}; + +/** + * Retrieves configuration information about a service. + * @param hnd Initialized and connected server handle + * @param mem_ctx Context for memory allocation + * @param op Initialized Parameters + * @return CAC_FAILURE - the operation was not successful hnd->status is set appropriately + * @return CAC_SUCCESS - the operation was successful + */ +int cac_SvcGetServiceConfig(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetServiceConfig *op); + +/**@}*/ /*SCM_Functions*/ + +#endif /* LIBMSRPC_H */ + + diff --git a/source3/include/libmsrpc_internal.h b/source3/include/libmsrpc_internal.h new file mode 100644 index 0000000000..5073813e21 --- /dev/null +++ b/source3/include/libmsrpc_internal.h @@ -0,0 +1,69 @@ +/* + * Unix SMB/CIFS implementation. + * MS-RPC client internal definitions + * 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. + */ + +#ifndef LIBMSRPC_INTERNAL_H +#define LIBMSRPC_INTERNAL_H + +#include "libmsrpc.h" + +/*definitions*/ + +struct CacServerHandleInternal { + /*stores the os type of the server*/ + uint16 srv_level; + + /*stores the initialized/active pipes*/ + BOOL pipes[PI_MAX_PIPES]; + + /*underlying smbc context*/ + SMBCCTX *ctx; + + /*did the user supply this SMBCCTX?*/ + BOOL user_supplied_ctx; +}; + +/*nessecary prototypes*/ +BOOL rid_in_list(uint32 rid, uint32 *list, uint32 list_len); + +int cac_ParseRegPath(char *path, uint32 *reg_type, char **key_name); + +REG_VALUE_DATA *cac_MakeRegValueData(TALLOC_CTX *mem_ctx, uint32 data_type, REGVAL_BUFFER buf); + +RPC_DATA_BLOB *cac_MakeRpcDataBlob(TALLOC_CTX *mem_ctx, uint32 data_type, REG_VALUE_DATA data); + +SAM_USERINFO_CTR *cac_MakeUserInfoCtr(TALLOC_CTX *mem_ctx, CacUserInfo *info); + +CacUserInfo *cac_MakeUserInfo(TALLOC_CTX *mem_ctx, SAM_USERINFO_CTR *ctr); +CacGroupInfo *cac_MakeGroupInfo(TALLOC_CTX *mem_ctx, GROUP_INFO_CTR *ctr); +GROUP_INFO_CTR *cac_MakeGroupInfoCtr(TALLOC_CTX *mem_ctx, CacGroupInfo *info); +CacAliasInfo *cac_MakeAliasInfo(TALLOC_CTX *mem_ctx, ALIAS_INFO_CTR ctr); +ALIAS_INFO_CTR *cac_MakeAliasInfoCtr(TALLOC_CTX *mem_ctx, CacAliasInfo *info); +CacDomainInfo *cac_MakeDomainInfo(TALLOC_CTX *mem_ctx, SAM_UNK_INFO_1 *info1, SAM_UNK_INFO_2 *info2, SAM_UNK_INFO_12 *info12); +CacService *cac_MakeServiceArray(TALLOC_CTX *mem_ctx, ENUM_SERVICES_STATUS *svc, uint32 num_services); +int cac_InitCacServiceConfig(TALLOC_CTX *mem_ctx, SERVICE_CONFIG *src, CacServiceConfig *dest); + +SMBCSRV *smbc_attr_server(SMBCCTX *context, + const char *server, const char *share, + fstring workgroup, + fstring username, fstring password, + POLICY_HND *pol); + + +#endif /* LIBMSRPC_INTERNAL_H */ diff --git a/source3/libmsrpc/Doxyfile b/source3/libmsrpc/Doxyfile new file mode 100644 index 0000000000..f4e6f5e51b --- /dev/null +++ b/source3/libmsrpc/Doxyfile @@ -0,0 +1,173 @@ +# Doxyfile 0.1 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = libmsrpc +PROJECT_NUMBER = + +# NOTE: By default, Doxygen writes into the dox/ subdirectory of the +# invocation directory. If you want to put it somewhere else, for +# example, to write straight into a webserver directory, then override +# this variable in a configuration concatenated to this one: Doxygen +# doesn't mind variables being redefined. + +OUTPUT_DIRECTORY = dox + +OUTPUT_LANGUAGE = English +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = $(PWD)/ +INTERNAL_DOCS = YES +CLASS_DIAGRAMS = YES +SOURCE_BROWSER = YES +INLINE_SOURCES = YES +STRIP_CODE_COMMENTS = NO +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = YES +VERBATIM_HEADERS = YES +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +SHOW_USED_FILES = YES +REFERENCED_BY_RELATION = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = NO +WARN_IF_UNDOCUMENTED = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../include/ +FILE_PATTERNS = libmsrpc.h +RECURSIVE = YES +EXCLUDE = +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 1 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = . +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 3 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = YES +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +#--------------------------------------------------------------------------- +# configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = NO +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# configuration options related to the dot tool +#--------------------------------------------------------------------------- +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = search.cgi +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = /usr/local/bin/ +EXT_DOC_PATHS = 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; +} diff --git a/source3/libmsrpc/cac_samr.c b/source3/libmsrpc/cac_samr.c new file mode 100644 index 0000000000..c6efaa2d38 --- /dev/null +++ b/source3/libmsrpc/cac_samr.c @@ -0,0 +1,2460 @@ +/* + * 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 0x000003e8 + +int cac_SamConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamConnect *op) { + SMBCSRV *srv = 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(!cli_nt_session_open(&srv->cli, PI_SAMR)) { + hnd->status = NT_STATUS_UNSUCCESSFUL; + return CAC_FAILURE; + } + + hnd->_internal.pipes[PI_SAMR] = True; + } + + srv->cli.pipe_idx = PI_SAMR; + + 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 = cli_samr_connect4( &(srv->cli), 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 = cli_samr_connect( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_close( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + 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; + } + + + 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 = cli_samr_open_domain( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + if(op->in.rid == 0 && op->in.name) { + /*lookup the name and then set rid_buf*/ + + hnd->status = cli_samr_lookup_names( &(srv->cli), 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 = cli_samr_open_user(&(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + user_out = talloc(mem_ctx, POLICY_HND); + if(!user_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + hnd->status = cli_samr_create_dom_user( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_delete_dom_user( &(srv->cli), 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) { + SMBCSRV *srv = 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; + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + resume_idx_out = op->out.resume_idx; + + hnd->status = cli_samr_enum_dom_users( &(srv->cli), 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) { + SMBCSRV *srv = 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; + } + + if(op->in.num_rids == 0) { + /*nothing to do*/ + op->out.num_names = 0; + return CAC_SUCCESS; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_lookup_rids( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.num_rids, op->in.rids, &num_names_out, &names_out, &name_types_out); + + if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED)) + return CAC_FAILURE; + + map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_names_out); + if(!map_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + for(i = 0; i < num_names_out; i++) { + if(name_types_out[i] == SAMR_RID_UNKNOWN) { + map_out[i].found = False; + map_out[i].name = NULL; + map_out[i].type = 0; + } + else { + map_out[i].found = True; + map_out[i].name = talloc_strdup(mem_ctx, names_out[i]); + map_out[i].type = name_types_out[i]; + } + map_out[i].rid = op->in.rids[i]; + } + + talloc_free(names_out); + talloc_free(name_types_out); + + op->out.num_names = num_names_out; + op->out.map = map_out; + + if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED)) + return CAC_PARTIAL_SUCCESS; + + return CAC_SUCCESS; +} + +int cac_SamGetRidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetRidsFromNames *op) { + SMBCSRV *srv = NULL; + + uint32 num_rids_out; + uint32 *rids_out; + uint32 *rid_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.names && op->in.num_names != 0) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + if(op->in.num_names == 0) { + /*then we don't have to do anything*/ + op->out.num_rids = 0; + return CAC_SUCCESS; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_lookup_names( &(srv->cli), mem_ctx, op->in.dom_hnd, SAMR_LOOKUP_FLAGS, op->in.num_names, (const char **)op->in.names, + &num_rids_out, &rids_out, &rid_types_out); + + if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED)) + return CAC_FAILURE; + + map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_rids_out); + if(!map_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + for(i = 0; i < num_rids_out; i++) { + + if(rid_types_out[i] == SAMR_RID_UNKNOWN) { + map_out[i].found = False; + map_out[i].rid = 0; + map_out[i].type = 0; + } + else { + map_out[i].found = True; + map_out[i].rid = rids_out[i]; + map_out[i].type = rid_types_out[i]; + } + + map_out[i].name = talloc_strdup(mem_ctx, op->in.names[i]); + } + + op->out.num_rids = num_rids_out; + op->out.map = map_out; + + talloc_free(rids_out); + talloc_free(rid_types_out); + + if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED)) + return CAC_PARTIAL_SUCCESS; + + return CAC_SUCCESS; +} + + +int cac_SamGetGroupsForUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupsForUser *op) { + SMBCSRV *srv = NULL; + + DOM_GID *groups = NULL; + uint32 num_groups_out = 0; + + uint32 *rids_out = NULL; + uint32 *attr_out = NULL; + + uint32 i; + + 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.user_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_usergroups(&(srv->cli), mem_ctx, op->in.user_hnd, &num_groups_out, &groups); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + + rids_out = talloc_array(mem_ctx, uint32, num_groups_out); + if(!rids_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + attr_out = talloc_array(mem_ctx, uint32, num_groups_out); + if(!attr_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + for(i = 0; i < num_groups_out; i++) { + rids_out[i] = groups[i].g_rid; + attr_out[i] = groups[i].attr; + } + + talloc_free(groups); + + op->out.num_groups = num_groups_out; + op->out.rids = rids_out; + op->out.attributes = attr_out; + + return CAC_SUCCESS; +} + + +int cac_SamOpenGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenGroup *op) { + SMBCSRV *srv = NULL; + + POLICY_HND *group_hnd_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.access == 0 || op->in.rid == 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; + } + + srv->cli.pipe_idx = PI_SAMR; + + group_hnd_out = talloc(mem_ctx, POLICY_HND); + if(!group_hnd_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + hnd->status = cli_samr_open_group( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.access, op->in.rid, group_hnd_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.group_hnd = group_hnd_out; + + return CAC_SUCCESS; +} + +int cac_SamCreateGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateGroup *op) { + SMBCSRV *srv = NULL; + + POLICY_HND *group_hnd_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.name || op->in.name[0] == '\0' || 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; + } + + srv->cli.pipe_idx = PI_SAMR; + + group_hnd_out = talloc(mem_ctx, POLICY_HND); + if(!group_hnd_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + hnd->status = cli_samr_create_dom_group( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.name, op->in.access, group_hnd_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.group_hnd = group_hnd_out; + + return CAC_SUCCESS; + +} + +int cac_SamDeleteGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) { + SMBCSRV *srv = 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(!group_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_delete_dom_group( &(srv->cli), mem_ctx, group_hnd); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; + +} + +int cac_SamGetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupMembers *op) { + SMBCSRV *srv = NULL; + + uint32 num_mem_out; + uint32 *rids_out; + uint32 *attr_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.group_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_groupmem( &(srv->cli), mem_ctx, op->in.group_hnd, &num_mem_out, &rids_out, &attr_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.num_members = num_mem_out; + op->out.rids = rids_out; + op->out.attributes = attr_out; + + return CAC_SUCCESS; +} + + +int cac_SamAddGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddGroupMember *op) { + SMBCSRV *srv = 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.group_hnd || op->in.rid == 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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_add_groupmem( &(srv->cli), mem_ctx, op->in.group_hnd, op->in.rid); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamRemoveGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveGroupMember *op) { + SMBCSRV *srv = 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.group_hnd || op->in.rid == 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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_del_groupmem( &(srv->cli), mem_ctx, op->in.group_hnd, op->in.rid); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamClearGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) { + SMBCSRV *srv = NULL; + + int result = CAC_SUCCESS; + + uint32 i = 0; + + uint32 num_mem = 0; + uint32 *rid = NULL; + uint32 *attr = NULL; + + NTSTATUS status; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!group_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_groupmem(&(srv->cli), mem_ctx, group_hnd, &num_mem, &rid, &attr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + /*try to delete the users one by one*/ + for(i = 0; i < num_mem && NT_STATUS_IS_OK(hnd->status); i++) { + hnd->status = cli_samr_del_groupmem(&(srv->cli), mem_ctx, group_hnd, rid[i]); + } + + /*if not all members could be removed, then try to re-add the members that were already deleted*/ + if(!NT_STATUS_IS_OK(hnd->status)) { + status = NT_STATUS_OK; + + for(i -= 1; i >= 0 && NT_STATUS_IS_OK(status); i--) { + status = cli_samr_add_groupmem( &(srv->cli), mem_ctx, group_hnd, rid[i]); + } + + /*we return with the NTSTATUS error that we got when trying to delete users*/ + if(!NT_STATUS_IS_OK(status)) + result = CAC_FAILURE; + } + + talloc_free(attr); + + return result; +} + +int cac_SamSetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupMembers *op) { + SMBCSRV *srv = NULL; + + uint32 i = 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.group_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + /*use cac_SamClearGroupMembers() to clear them*/ + if(!cac_SamClearGroupMembers(hnd, mem_ctx, op->in.group_hnd)) + return CAC_FAILURE; /*hnd->status is already set*/ + + + for(i = 0; i < op->in.num_members && NT_STATUS_IS_OK(hnd->status); i++) { + hnd->status = cli_samr_add_groupmem( &(srv->cli), mem_ctx, op->in.group_hnd, op->in.rids[i]); + } + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; + +} + +int cac_SamEnumGroups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumGroups *op) { + SMBCSRV *srv = NULL; + + uint32 i = 0; + + uint32 resume_idx_out = 0; + char **names_out = NULL; + char **desc_out = NULL; + uint32 *rids_out = NULL; + uint32 num_groups_out = 0; + + struct acct_info *acct_buf = 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 || !mem_ctx) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + /*using this BOOL is the only reliable way to know that we are done*/ + if(op->out.done == True) /*we return failure so the call will break out of a loop*/ + return CAC_FAILURE; + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + resume_idx_out = op->out.resume_idx; + + hnd->status = cli_samr_enum_dom_groups( &(srv->cli), mem_ctx, op->in.dom_hnd, &resume_idx_out, SAMR_ENUM_MAX_SIZE, + &acct_buf, &num_groups_out); + + + if(NT_STATUS_IS_OK(hnd->status)) { + op->out.done = True; + } + else if(NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES)) { + /*if there are no more entries, the operation will return NT_STATUS_OK. + * We want to return failure if no results were returned*/ + return CAC_FAILURE; + } + + names_out = talloc_array(mem_ctx, char *, num_groups_out); + if(!names_out) { + hnd->status = NT_STATUS_NO_MEMORY; + talloc_free(acct_buf); + return CAC_FAILURE; + } + + desc_out = talloc_array(mem_ctx, char *, num_groups_out); + if(!desc_out) { + hnd->status = NT_STATUS_NO_MEMORY; + talloc_free(acct_buf); + talloc_free(names_out); + return CAC_FAILURE; + } + + rids_out = talloc_array(mem_ctx, uint32, num_groups_out); + if(!rids_out) { + hnd->status = NT_STATUS_NO_MEMORY; + talloc_free(acct_buf); + talloc_free(names_out); + talloc_free(desc_out); + return CAC_FAILURE; + } + + for(i = 0; i < num_groups_out; i++) { + names_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_name); + desc_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_desc); + rids_out[i] = acct_buf[i].rid; + + if(!names_out[i] || !desc_out[i]) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + } + + op->out.resume_idx = resume_idx_out; + op->out.num_groups = num_groups_out; + op->out.rids = rids_out; + op->out.names = names_out; + op->out.descriptions = desc_out; + + return CAC_SUCCESS; +} + +int cac_SamEnumAliases(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumAliases *op) { + SMBCSRV *srv = NULL; + + uint32 i = 0; + + uint32 resume_idx_out = 0; + char **names_out = NULL; + char **desc_out = NULL; + uint32 *rids_out = NULL; + uint32 num_als_out = 0; + + struct acct_info *acct_buf = 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 || !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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + resume_idx_out = op->out.resume_idx; + + hnd->status = cli_samr_enum_als_groups( &(srv->cli), mem_ctx, op->in.dom_hnd, &resume_idx_out, SAMR_ENUM_MAX_SIZE, + &acct_buf, &num_als_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; + + names_out = talloc_array(mem_ctx, char *, num_als_out); + if(!names_out) { + hnd->status = NT_STATUS_NO_MEMORY; + talloc_free(acct_buf); + return CAC_FAILURE; + } + + desc_out = talloc_array(mem_ctx, char *, num_als_out); + if(!desc_out) { + hnd->status = NT_STATUS_NO_MEMORY; + talloc_free(acct_buf); + talloc_free(names_out); + return CAC_FAILURE; + } + + rids_out = talloc_array(mem_ctx, uint32, num_als_out); + if(!rids_out) { + hnd->status = NT_STATUS_NO_MEMORY; + talloc_free(acct_buf); + talloc_free(names_out); + talloc_free(desc_out); + return CAC_FAILURE; + } + + for(i = 0; i < num_als_out; i++) { + names_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_name); + desc_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_desc); + rids_out[i] = acct_buf[i].rid; + + if(!names_out[i] || !desc_out[i]) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + } + + op->out.resume_idx = resume_idx_out; + op->out.num_aliases = num_als_out; + op->out.rids = rids_out; + op->out.names = names_out; + op->out.descriptions = desc_out; + + return CAC_SUCCESS; +} + +int cac_SamCreateAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateAlias *op) { + SMBCSRV *srv = NULL; + + POLICY_HND *als_hnd_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.name || op->in.name[0] == '\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; + } + + srv->cli.pipe_idx = PI_SAMR; + + als_hnd_out = talloc(mem_ctx, POLICY_HND); + if(!als_hnd_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + hnd->status = cli_samr_create_dom_alias( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.name, als_hnd_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.alias_hnd = als_hnd_out; + + return CAC_SUCCESS; + +} + +int cac_SamOpenAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenAlias *op) { + SMBCSRV *srv = NULL; + + POLICY_HND *als_hnd_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.access == 0 || op->in.rid == 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; + } + + srv->cli.pipe_idx = PI_SAMR; + + als_hnd_out = talloc(mem_ctx, POLICY_HND); + if(!als_hnd_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + hnd->status = cli_samr_open_alias( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.access, op->in.rid, als_hnd_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.alias_hnd = als_hnd_out; + + return CAC_SUCCESS; +} + +int cac_SamDeleteAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) { + SMBCSRV *srv = 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(!alias_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_delete_dom_alias( &(srv->cli), mem_ctx, alias_hnd); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; + +} + +int cac_SamAddAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddAliasMember *op) { + SMBCSRV *srv = 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.alias_hnd || !op->in.sid || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_add_aliasmem( &(srv->cli), mem_ctx, op->in.alias_hnd, op->in.sid); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamRemoveAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveAliasMember *op) { + SMBCSRV *srv = 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.alias_hnd || !op->in.sid || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_del_aliasmem( &(srv->cli), mem_ctx, op->in.alias_hnd, op->in.sid); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamGetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasMembers *op) { + SMBCSRV *srv = NULL; + + uint32 num_mem_out; + DOM_SID *sids_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.alias_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_aliasmem( &(srv->cli), mem_ctx, op->in.alias_hnd, &num_mem_out, &sids_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.num_members = num_mem_out; + op->out.sids = sids_out; + + return CAC_SUCCESS; +} + +int cac_SamClearAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) { + SMBCSRV *srv = NULL; + + int result = CAC_SUCCESS; + + uint32 i = 0; + + uint32 num_mem = 0; + DOM_SID *sid = NULL; + + NTSTATUS status; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!alias_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_aliasmem(&(srv->cli), mem_ctx, alias_hnd, &num_mem, &sid); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + /*try to delete the users one by one*/ + for(i = 0; i < num_mem && NT_STATUS_IS_OK(hnd->status); i++) { + hnd->status = cli_samr_del_aliasmem(&(srv->cli), mem_ctx, alias_hnd, &sid[i]); + } + + /*if not all members could be removed, then try to re-add the members that were already deleted*/ + if(!NT_STATUS_IS_OK(hnd->status)) { + status = NT_STATUS_OK; + + for(i -= 1; i >= 0 && NT_STATUS_IS_OK(status); i--) { + status = cli_samr_add_aliasmem( &(srv->cli), mem_ctx, alias_hnd, &sid[i]); + } + + /*we return with the NTSTATUS error that we got when trying to delete users*/ + if(!NT_STATUS_IS_OK(status)) + result = CAC_FAILURE; + } + + talloc_free(sid); + return result; +} + +int cac_SamSetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasMembers *op) { + SMBCSRV *srv = NULL; + + uint32 i = 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.alias_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + /*use cac_SamClearAliasMembers() to clear them*/ + if(!cac_SamClearAliasMembers(hnd, mem_ctx, op->in.alias_hnd)) + return CAC_FAILURE; /*hnd->status is already set*/ + + + for(i = 0; i < op->in.num_members && NT_STATUS_IS_OK(hnd->status); i++) { + hnd->status = cli_samr_add_aliasmem( &(srv->cli), mem_ctx, op->in.alias_hnd, &(op->in.sids[i])); + } + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; + +} + +int cac_SamUserChangePasswd(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamUserChangePasswd *op) { + SMBCSRV *srv = NULL; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.username || !op->in.password || !op->in.new_password || !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; + } + + /*open a session on SAMR if we don't have one*/ + if(!hnd->_internal.pipes[PI_SAMR]) { + if(!cli_nt_session_open(&srv->cli, PI_SAMR)) { + hnd->status = NT_STATUS_UNSUCCESSFUL; + return CAC_FAILURE; + } + + hnd->_internal.pipes[PI_SAMR] = True; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_chgpasswd_user(&(srv->cli), mem_ctx, op->in.username, op->in.new_password, op->in.password); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamEnableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) { + SMBCSRV *srv = NULL; + + SAM_USERINFO_CTR *ctr; + + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked.*/ + hnd->status = cli_samr_query_userinfo( &(srv->cli), mem_ctx, user_hnd, 0x10, &ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + /**check the ACB mask*/ + if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) { + /*toggle the disabled bit*/ + ctr->info.id16->acb_info ^= ACB_DISABLED; + } + else { + /*the user is already enabled so just return success*/ + return CAC_SUCCESS; + } + + /*now set the userinfo*/ + hnd->status = cli_samr_set_userinfo2( &(srv->cli), mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr); + + /*this will only work properly if we use set_userinfo2 - fail if it is not supported*/ + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamDisableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) { + SMBCSRV *srv = NULL; + + SAM_USERINFO_CTR *ctr; + + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_userinfo( &(srv->cli), mem_ctx, user_hnd, 0x10, &ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) { + /*then the user is already disabled*/ + return CAC_SUCCESS; + } + + /*toggle the disabled bit*/ + ctr->info.id16->acb_info ^= ACB_DISABLED; + + /*this will only work properly if we use set_userinfo2*/ + hnd->status = cli_samr_set_userinfo2( &(srv->cli), mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr); + + /*this will only work properly if we use set_userinfo2 fail if it is not supported*/ + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamSetPassword(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetPassword *op) { + SMBCSRV *srv = NULL; + + SAM_USERINFO_CTR ctr; + SAM_USER_INFO_24 info24; + uint8 pw[516]; + + 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->in.user_hnd || !op->in.password || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + ZERO_STRUCT(ctr); + ZERO_STRUCT(info24); + + encode_pw_buffer(pw, op->in.password, STR_UNICODE); + + init_sam_user_info24(&info24, (char *)pw, 24); + + ctr.switch_value = 24; + ctr.info.id24 = &info24; + + hnd->status = cli_samr_set_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, 24, &(srv->cli.user_session_key), &ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamGetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfo *op) { + SMBCSRV *srv = NULL; + + SAM_USERINFO_CTR *ctr; + + 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->in.user_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, 21, &ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.info = cac_MakeUserInfo(mem_ctx, ctr); + + if(!op->out.info) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_SamSetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfo *op) { + SMBCSRV *srv = NULL; + + SAM_USERINFO_CTR *ctr; + + 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->in.user_hnd || !op->in.info || !mem_ctx) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + ctr = cac_MakeUserInfoCtr(mem_ctx, op->in.info); + if(!ctr) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + if(hnd->_internal.srv_level >= SRV_WIN_NT4) { + hnd->status = cli_samr_set_userinfo2( &(srv->cli), mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr); + } + + if(hnd->_internal.srv_level < SRV_WIN_NT4 || !NT_STATUS_IS_OK(hnd->status)) { + hnd->status = cli_samr_set_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr); + + if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_NT4) { + hnd->_internal.srv_level = SRV_WIN_NT4; + } + } + + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + + +int cac_SamGetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfoCtr *op) { + SMBCSRV *srv = NULL; + + SAM_USERINFO_CTR *ctr_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->in.user_hnd || op->in.info_class == 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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, op->in.info_class, &ctr_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.ctr = ctr_out; + + return CAC_SUCCESS; +} + +int cac_SamSetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfoCtr *op) { + SMBCSRV *srv = 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->in.user_hnd || !op->in.ctr || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + + hnd->status = cli_samr_set_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, op->in.ctr->switch_value, &(srv->cli.user_session_key), op->in.ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; + +} + +int cac_SamRenameUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameUser *op) { + SMBCSRV *srv = NULL; + + SAM_USERINFO_CTR ctr; + SAM_USER_INFO_7 info7; + + 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->in.user_hnd || !op->in.new_name || op->in.new_name[0] == '\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; + } + + srv->cli.pipe_idx = PI_SAMR; + + ZERO_STRUCT(ctr); + ZERO_STRUCT(info7); + + init_sam_user_info7(&info7, op->in.new_name); + + ctr.switch_value = 7; + ctr.info.id7 = &info7; + + hnd->status = cli_samr_set_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, 7, &(srv->cli.user_session_key), &ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + + +int cac_SamGetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupInfo *op) { + SMBCSRV *srv = NULL; + + GROUP_INFO_CTR *ctr; + + 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->in.group_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + /*get a GROUP_INFO_1 structure*/ + hnd->status = cli_samr_query_groupinfo( &(srv->cli), mem_ctx, op->in.group_hnd, 1, &ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.info = cac_MakeGroupInfo(mem_ctx, ctr); + if(!op->out.info) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_SamSetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupInfo *op) { + SMBCSRV *srv = NULL; + + GROUP_INFO_CTR *ctr = 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->in.group_hnd || !op->in.info || !mem_ctx) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + ctr = cac_MakeGroupInfoCtr(mem_ctx, op->in.info); + if(!ctr) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_set_groupinfo(&(srv->cli), mem_ctx, op->in.group_hnd, ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamRenameGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameGroup *op) { + SMBCSRV *srv = NULL; + + GROUP_INFO_CTR ctr; + + 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->in.group_hnd || !op->in.new_name || op->in.new_name[0] == '\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; + } + + srv->cli.pipe_idx = PI_SAMR; + + ZERO_STRUCT(ctr); + + init_samr_group_info2(&ctr.group.info2, op->in.new_name); + ctr.switch_value1 = 2; + + hnd->status = cli_samr_set_groupinfo( &(srv->cli), mem_ctx, op->in.group_hnd, &ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamGetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasInfo *op) { + SMBCSRV *srv = NULL; + + ALIAS_INFO_CTR ctr; + + 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->in.alias_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + /*get a GROUP_INFO_1 structure*/ + hnd->status = cli_samr_query_alias_info( &(srv->cli), mem_ctx, op->in.alias_hnd, 1, &ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.info = cac_MakeAliasInfo(mem_ctx, ctr); + if(!op->out.info) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + return CAC_SUCCESS; + +} + +int cac_SamSetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasInfo *op) { + SMBCSRV *srv = NULL; + + ALIAS_INFO_CTR *ctr = 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->in.alias_hnd || !op->in.info || !mem_ctx) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + ctr = cac_MakeAliasInfoCtr(mem_ctx, op->in.info); + if(!ctr) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_set_aliasinfo(&(srv->cli), mem_ctx, op->in.alias_hnd, ctr); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SamGetDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfo *op) { + SMBCSRV *srv = NULL; + + SAM_UNK_CTR ctr; + SAM_UNK_INFO_1 info1; + SAM_UNK_INFO_2 info2; + SAM_UNK_INFO_12 info12; + + /*use this to keep track of a failed call*/ + NTSTATUS status_buf = NT_STATUS_OK; + + uint16 fail_count = 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->in.dom_hnd || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + /*first try with info 1*/ + hnd->status = cli_samr_query_dom_info( &(srv->cli), mem_ctx, op->in.dom_hnd, 1, &ctr); + + if(NT_STATUS_IS_OK(hnd->status)) { + /*then we buffer the SAM_UNK_INFO_1 structure*/ + info1 = ctr.info.inf1; + } + else { + /*then the call failed, store the status and ZERO out the info structure*/ + ZERO_STRUCT(info1); + status_buf = hnd->status; + fail_count++; + } + + /*try again for the next one*/ + hnd->status = cli_samr_query_dom_info( &(srv->cli), mem_ctx, op->in.dom_hnd, 2, &ctr); + + if(NT_STATUS_IS_OK(hnd->status)) { + /*store the info*/ + info2 = ctr.info.inf2; + } + else { + /*ZERO out the structure and store the bad status*/ + ZERO_STRUCT(info2); + status_buf = hnd->status; + fail_count++; + } + + /*once more*/ + hnd->status = cli_samr_query_dom_info( &(srv->cli), mem_ctx, op->in.dom_hnd, 12, &ctr); + + if(NT_STATUS_IS_OK(hnd->status)) { + info12 = ctr.info.inf12; + } + else { + ZERO_STRUCT(info12); + status_buf = hnd->status; + fail_count++; + } + + /*return failure if all 3 calls failed*/ + if(fail_count == 3) + return CAC_FAILURE; + + op->out.info = cac_MakeDomainInfo(mem_ctx, &info1, &info2, &info12); + + if(!op->out.info) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + if(fail_count > 0) { + hnd->status = status_buf; + return CAC_PARTIAL_SUCCESS; + } + + return CAC_SUCCESS; +} + +int cac_SamGetDomainInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfoCtr *op) { + SMBCSRV *srv = NULL; + + SAM_UNK_CTR *ctr_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->in.dom_hnd || op->in.info_class == 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; + } + + srv->cli.pipe_idx = PI_SAMR; + + ctr_out = talloc(mem_ctx, SAM_UNK_CTR); + if(!ctr_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + hnd->status = cli_samr_query_dom_info( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.info_class, ctr_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.info = ctr_out; + + return CAC_SUCCESS; +} + +int cac_SamGetDisplayInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDisplayInfo *op) { + SMBCSRV *srv = NULL; + + SAM_DISPINFO_CTR ctr_out; + + uint32 max_entries_buf = 0; + uint32 max_size_buf = 0; + + uint32 resume_idx_out; + uint32 num_entries_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->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + if(op->out.done == True) /*this is done so we can use the function as a loop condition*/ + return CAC_FAILURE; + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + if(op->in.max_entries == 0 || op->in.max_size == 0) { + get_query_dispinfo_params(op->out.loop_count, &max_entries_buf, &max_size_buf); + } + else { + max_entries_buf = op->in.max_entries; + max_size_buf = op->in.max_size; + } + + resume_idx_out = op->out.resume_idx; + + hnd->status = cli_samr_query_dispinfo( &(srv->cli), mem_ctx, op->in.dom_hnd, &resume_idx_out, op->in.info_class, + &num_entries_out, max_entries_buf, max_size_buf, &ctr_out); + + if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_MORE_ENTRIES)) { + /*be defensive, maybe they'll call again without zeroing the struct*/ + op->out.loop_count = 0; + op->out.resume_idx = 0; + return CAC_FAILURE; + } + + if(NT_STATUS_IS_OK(hnd->status)) { + /*we want to quit once the function is called next. so it can be used in a loop*/ + op->out.done = True; + } + + op->out.resume_idx = resume_idx_out; + op->out.num_entries = num_entries_out; + op->out.ctr = ctr_out; + op->out.loop_count++; + + return CAC_SUCCESS; +} + +int cac_SamLookupDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamLookupDomain *op) { + SMBCSRV *srv = NULL; + + DOM_SID *sid_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->in.sam || !op->in.name || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + sid_out = talloc(mem_ctx, DOM_SID); + if(!sid_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + hnd->status = cli_samr_lookup_domain( &(srv->cli), mem_ctx, op->in.sam, op->in.name, sid_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.sid = sid_out; + + return CAC_SUCCESS; +} + +int cac_SamGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetSecurityObject *op) { + SMBCSRV *srv = NULL; + + /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level*/ + uint16 info_level = 4; + + SEC_DESC_BUF *sec_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->in.pol || !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; + } + + srv->cli.pipe_idx = PI_SAMR; + + hnd->status = cli_samr_query_sec_obj(&(srv->cli), mem_ctx, op->in.pol, info_level, mem_ctx, &sec_out); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.sec = sec_out; + + return CAC_SUCCESS; +} + +int cac_SamFlush(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamFlush *op) { + SMBCSRV *srv = NULL; + + struct SamOpenDomain od; + + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SAMR; + + if(!cac_SamClose(hnd, mem_ctx, op->in.dom_hnd)) + return CAC_FAILURE; + + ZERO_STRUCT(od); + od.in.access = (op->in.access) ? op->in.access : MAXIMUM_ALLOWED_ACCESS; + od.in.sid = op->in.sid; + + if(!cac_SamOpenDomain(hnd, mem_ctx, &od)) + return CAC_FAILURE; + + /*this function does not use an output parameter to make it as convenient as possible to use*/ + *op->in.dom_hnd = *od.out.dom_hnd; + + talloc_free(od.out.dom_hnd); + + return CAC_SUCCESS; +} diff --git a/source3/libmsrpc/cac_svcctl.c b/source3/libmsrpc/cac_svcctl.c new file mode 100644 index 0000000000..71c83eba94 --- /dev/null +++ b/source3/libmsrpc/cac_svcctl.c @@ -0,0 +1,583 @@ +/* + * Unix SMB/CIFS implementation. + * MS-RPC client library implementation (SVCCTL 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" + +#define WAIT_SLEEP_TIME 300 + +int cac_SvcOpenScm(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenScm *op) { + SMBCSRV *srv = NULL; + WERROR err; + + POLICY_HND *scm_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_SVCCTL]) { + if(!cli_nt_session_open(&srv->cli, PI_SVCCTL)) { + hnd->status = NT_STATUS_UNSUCCESSFUL; + return CAC_FAILURE; + } + + hnd->_internal.pipes[PI_SVCCTL] = True; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + scm_out = talloc(mem_ctx, POLICY_HND); + if(!scm_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + err = cli_svcctl_open_scm( &(srv->cli), mem_ctx, scm_out, op->in.access); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.scm_hnd = scm_out; + + return CAC_SUCCESS; +} + +int cac_SvcClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *scm_hnd) { + SMBCSRV *srv = NULL; + WERROR err; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!scm_hnd || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + err = cli_svcctl_close_service( &(srv->cli), mem_ctx, scm_hnd); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SvcEnumServices(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcEnumServices *op) { + SMBCSRV *srv = NULL; + WERROR err; + + uint32 type_buf = 0; + uint32 state_buf = 0; + + uint32 num_svc_out = 0; + + ENUM_SERVICES_STATUS *svc_buf = NULL; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.scm_hnd || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + type_buf = (op->in.type != 0) ? op->in.type : (SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32); + state_buf = (op->in.state != 0) ? op->in.state : SVCCTL_STATE_ALL; + + err = cli_svcctl_enumerate_services( &(srv->cli), mem_ctx, op->in.scm_hnd, type_buf, state_buf, &num_svc_out, &svc_buf); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.services = cac_MakeServiceArray(mem_ctx, svc_buf, num_svc_out); + + if(!op->out.services) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + talloc_free(svc_buf); + + op->out.num_services = num_svc_out; + + return CAC_SUCCESS; +} + +int cac_SvcOpenService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenService *op) { + SMBCSRV *srv = NULL; + WERROR err; + + POLICY_HND *svc_hnd_out = NULL; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.scm_hnd || !op->in.name || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + svc_hnd_out = talloc(mem_ctx, POLICY_HND); + if(!svc_hnd_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + err = cli_svcctl_open_service( &(srv->cli), mem_ctx, op->in.scm_hnd, svc_hnd_out, op->in.name, op->in.access); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.svc_hnd = svc_hnd_out; + + return CAC_SUCCESS; +} + +int cac_SvcControlService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcControlService *op) { + SMBCSRV *srv = NULL; + WERROR err; + + SERVICE_STATUS status_out; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.svc_hnd || !mem_ctx) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + if(op->in.control < SVCCTL_CONTROL_STOP || op->in.control > SVCCTL_CONTROL_SHUTDOWN) { + 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_SVCCTL; + + err = cli_svcctl_control_service( &(srv->cli), mem_ctx, op->in.svc_hnd, op->in.control, &status_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + +int cac_SvcGetStatus(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetStatus *op) { + SMBCSRV *srv = NULL; + WERROR err; + + SERVICE_STATUS status_out; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.svc_hnd || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + err = cli_svcctl_query_status( &(srv->cli), mem_ctx, op->in.svc_hnd, &status_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.status = status_out; + + return CAC_SUCCESS; +} + + + +/*Internal function - similar to code found in utils/net_rpc_service.c + * Waits for a service to reach a specific state. + * svc_hnd - Handle to the service + * state - the state we are waiting for + * timeout - number of seconds to wait + * returns CAC_FAILURE if the state is never reached + * or CAC_SUCCESS if the state is reached + */ +int cac_WaitForService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *svc_hnd, uint32 state, uint32 timeout, SERVICE_STATUS *status) { + SMBCSRV *srv = NULL; + /*number of milliseconds we have spent*/ + uint32 time_spent = 0; + WERROR err; + + if(!hnd || !mem_ctx || !svc_hnd || !status) + return CAC_FAILURE; + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + while(status->state != state && time_spent < (timeout * 1000) && NT_STATUS_IS_OK(hnd->status)) { + /*if this is the first call, then we _just_ got the status.. sleep now*/ + usleep(WAIT_SLEEP_TIME); + time_spent += WAIT_SLEEP_TIME; + + err = cli_svcctl_query_status(&(srv->cli), mem_ctx, svc_hnd, status); + hnd->status = werror_to_ntstatus(err); + } + + if(status->state == state) + return CAC_SUCCESS; + + return CAC_FAILURE; +} + +int cac_SvcStartService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStartService *op) { + SMBCSRV *srv = NULL; + WERROR err; + + SERVICE_STATUS status_buf; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.svc_hnd || !mem_ctx) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + if(op->in.num_parms != 0 && op->in.parms == NULL) { + 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_SVCCTL; + + err = cli_svcctl_start_service(&(srv->cli), mem_ctx, op->in.svc_hnd, (const char **)op->in.parms, op->in.num_parms); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + if(op->in.timeout == 0) + return CAC_SUCCESS; + + return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &status_buf); +} + +int cac_SvcStopService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStopService *op) { + SMBCSRV *srv = NULL; + WERROR err; + + SERVICE_STATUS status_out; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.svc_hnd || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + err = cli_svcctl_control_service( &(srv->cli), mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_STOP, &status_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.status = status_out; + + if(op->in.timeout == 0) + return CAC_SUCCESS; + + return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_STOPPED, op->in.timeout, &op->out.status); +} + +int cac_SvcPauseService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcPauseService *op) { + SMBCSRV *srv = NULL; + WERROR err; + + SERVICE_STATUS status_out; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.svc_hnd || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + err = cli_svcctl_control_service( &(srv->cli), mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_PAUSE, &status_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.status = status_out; + + if(op->in.timeout == 0) + return CAC_SUCCESS; + + return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_PAUSED, op->in.timeout, &op->out.status); +} + +int cac_SvcContinueService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcContinueService *op) { + SMBCSRV *srv = NULL; + WERROR err; + + SERVICE_STATUS status_out; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.svc_hnd || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + err = cli_svcctl_control_service( &(srv->cli), mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_CONTINUE, &status_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.status = status_out; + + if(op->in.timeout == 0) + return CAC_SUCCESS; + + return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &op->out.status); +} + +int cac_SvcGetDisplayName(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetDisplayName *op) { + SMBCSRV *srv = NULL; + WERROR err; + + fstring disp_name_out; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.svc_hnd || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + err = cli_svcctl_get_dispname( &(srv->cli), mem_ctx, op->in.svc_hnd, disp_name_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.display_name = talloc_strdup(mem_ctx, disp_name_out); + + if(!op->out.display_name) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + + +int cac_SvcGetServiceConfig(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetServiceConfig *op) { + SMBCSRV *srv = NULL; + WERROR err; + + SERVICE_CONFIG config_out; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.svc_hnd || !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; + } + + srv->cli.pipe_idx = PI_SVCCTL; + + err = cli_svcctl_query_config( &(srv->cli), mem_ctx, op->in.svc_hnd, &config_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + if(!cac_InitCacServiceConfig(mem_ctx, &config_out, &op->out.config)) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + return CAC_SUCCESS; + +} diff --git a/source3/libmsrpc/cac_winreg.c b/source3/libmsrpc/cac_winreg.c new file mode 100644 index 0000000000..3a90aa871e --- /dev/null +++ b/source3/libmsrpc/cac_winreg.c @@ -0,0 +1,1033 @@ +/* + * Unix SMB/CIFS implementation. + * MS-RPC client library implementation (WINREG 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" + + +int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect *op) { + SMBCSRV *srv = NULL; + POLICY_HND *key = NULL; + WERROR err; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.root || !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 winreg pipe if we have to*/ + if(!hnd->_internal.pipes[PI_WINREG]) { + if(!cli_nt_session_open(&srv->cli, PI_WINREG)) { + hnd->status = NT_STATUS_UNSUCCESSFUL; + return CAC_FAILURE; + } + + hnd->_internal.pipes[PI_WINREG] = True; + } + + key = talloc(mem_ctx, POLICY_HND); + if(!key) { + hnd->status = NT_STATUS_NO_MEMORY; + } + + err = cli_reg_connect( &(srv->cli), mem_ctx, op->in.root, op->in.access, key); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + op->out.key = key; + + return CAC_SUCCESS; +} + +int cac_RegClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *key) { + SMBCSRV *srv = NULL; + WERROR err; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!key || !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; + } + + err = cli_reg_close(&srv->cli, mem_ctx, key); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_RegOpenKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegOpenKey *op) { + SMBCSRV *srv = NULL; + WERROR err; + + POLICY_HND *key_out; + POLICY_HND *parent_key; + + char *key_name = NULL; + uint32 reg_type = 0; + + struct RegConnect rc; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.name || !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; + } + + + key_out = talloc(mem_ctx, POLICY_HND); + if(!key_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + if(!op->in.parent_key) { + /*then we need to connect to the registry*/ + if(!cac_ParseRegPath(op->in.name, ®_type, &key_name)) { + hnd->status = NT_STATUS_INVALID_PARAMETER; + return CAC_FAILURE; + } + + /*use cac_RegConnect because it handles the session setup*/ + ZERO_STRUCT(rc); + + rc.in.access = op->in.access; + rc.in.root = reg_type; + + if(!cac_RegConnect(hnd, mem_ctx, &rc)) { + return CAC_FAILURE; + } + + /**if they only specified the root key, return the key we just opened*/ + if(key_name == NULL) { + op->out.key = rc.out.key; + return CAC_SUCCESS; + } + + parent_key = rc.out.key; + } + else { + parent_key = op->in.parent_key; + key_name = op->in.name; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_open_entry( &(srv->cli), mem_ctx, parent_key, key_name, op->in.access, key_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + if(!op->in.parent_key) { + /*then close the one that we opened above*/ + err = cli_reg_close( &(srv->cli), mem_ctx, parent_key); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + } + + op->out.key = key_out; + + return CAC_SUCCESS; +} + +int cac_RegEnumKeys(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumKeys *op) { + SMBCSRV *srv = NULL; + WERROR err; + + /*buffers for cli_reg_enum_key call*/ + fstring key_name_in; + fstring class_name_in; + + /*output buffers*/ + char **key_names_out = NULL; + char **class_names_out = NULL; + time_t *mod_times_out = NULL; + uint32 num_keys_out = 0; + uint32 resume_idx = 0; + + if(!hnd) + return CAC_FAILURE; + + /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/ + if(NT_STATUS_V(hnd->status) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED)) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || op->in.max_keys == 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; + } + + srv->cli.pipe_idx = PI_WINREG; + + /**the only way to know how many keys to expect is to assume max_keys keys will be found*/ + key_names_out = TALLOC_ARRAY(mem_ctx, char *, op->in.max_keys); + if(!key_names_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + class_names_out = TALLOC_ARRAY(mem_ctx, char *, op->in.max_keys); + if(!class_names_out) { + hnd->status = NT_STATUS_NO_MEMORY; + talloc_free(key_names_out); + return CAC_FAILURE; + } + + mod_times_out = TALLOC_ARRAY(mem_ctx, time_t, op->in.max_keys); + if(!mod_times_out) { + hnd->status = NT_STATUS_NO_MEMORY; + talloc_free(key_names_out); + talloc_free(class_names_out); + + return CAC_FAILURE; + } + + resume_idx = op->out.resume_idx; + + do { + err = cli_reg_enum_key( &(srv->cli), mem_ctx, op->in.key, resume_idx, key_name_in, class_name_in, &mod_times_out[num_keys_out]); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + /*don't increment any values*/ + break; + } + + key_names_out[num_keys_out] = talloc_strdup(mem_ctx, key_name_in); + + class_names_out[num_keys_out] = talloc_strdup(mem_ctx, class_name_in); + + if(!key_names_out[num_keys_out] || !class_names_out[num_keys_out]) { + hnd->status = NT_STATUS_NO_MEMORY; + break; + } + + resume_idx++; + num_keys_out++; + } while(num_keys_out < op->in.max_keys); + + if(CAC_OP_FAILED(hnd->status)) { + op->out.num_keys = 0; + return CAC_FAILURE; + } + + op->out.resume_idx = resume_idx; + op->out.num_keys = num_keys_out; + op->out.key_names = key_names_out; + op->out.class_names = class_names_out; + op->out.mod_times = mod_times_out; + + return CAC_SUCCESS; +} + +int cac_RegCreateKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegCreateKey *op) { + SMBCSRV *srv = NULL; + WERROR err; + + POLICY_HND *key_out; + + struct RegOpenKey rok; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.parent_key || !op->in.key_name || !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; + } + + /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/ + ZERO_STRUCT(rok); + + rok.in.name = op->in.key_name; + rok.in.access = op->in.access; + rok.in.parent_key = op->in.parent_key; + + if(cac_RegOpenKey(hnd, mem_ctx, &rok)) { + /*then we got the key, return*/ + op->out.key = rok.out.key; + return CAC_SUCCESS; + } + + /*just be ultra-safe*/ + srv->cli.pipe_idx = PI_WINREG; + + key_out = talloc(mem_ctx, POLICY_HND); + if(!key_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + err = cli_reg_create_key_ex( &(srv->cli), mem_ctx, op->in.parent_key, op->in.key_name, op->in.class_name, op->in.access, key_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + op->out.key = key_out; + + return CAC_SUCCESS; + +} + +WERROR cac_delete_subkeys_recursive(struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *key) { + /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient + * so we use the cli_reg functions directly*/ + + WERROR err = WERR_OK; + + POLICY_HND subkey; + fstring subkey_name; + fstring class_buf; + time_t mod_time_buf; + + int cur_key = 0; + + while(W_ERROR_IS_OK(err)) { + err = cli_reg_enum_key( cli, mem_ctx, key, cur_key, subkey_name, class_buf, &mod_time_buf); + + if(!W_ERROR_IS_OK(err)) + break; + + /*try to open the key with full access*/ + err = cli_reg_open_entry(cli, mem_ctx, key, subkey_name, REG_KEY_ALL, &subkey); + + if(!W_ERROR_IS_OK(err)) + break; + + err = cac_delete_subkeys_recursive(cli, mem_ctx, &subkey); + + if(!W_ERROR_EQUAL(err,WERR_NO_MORE_ITEMS) && !W_ERROR_IS_OK(err)) + break; + + /*flush the key just to be safe*/ + cli_reg_flush_key(cli, mem_ctx, key); + + /*close the key that we opened*/ + cli_reg_close(cli, mem_ctx, &subkey); + + /*now we delete the subkey*/ + err = cli_reg_delete_key(cli, mem_ctx, key, subkey_name); + + + cur_key++; + } + + + return err; +} + + + +int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op) { + SMBCSRV *srv = NULL; + WERROR err; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.parent_key || !op->in.name || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + if(op->in.recursive) { + /*first open the key, and then delete all of it's subkeys recursively*/ + struct RegOpenKey rok; + ZERO_STRUCT(rok); + + rok.in.parent_key = op->in.parent_key; + rok.in.name = op->in.name; + rok.in.access = REG_KEY_ALL; + + if(!cac_RegOpenKey(hnd, mem_ctx, &rok)) + return CAC_FAILURE; + + err = cac_delete_subkeys_recursive(&(srv->cli), mem_ctx, rok.out.key); + + /*close the key that we opened*/ + cac_RegClose(hnd, mem_ctx, rok.out.key); + + hnd->status = werror_to_ntstatus(err); + + if(NT_STATUS_V(hnd->status) != NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED) && !NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + /*now go on to actually delete the key*/ + } + + err = cli_reg_delete_key( &(srv->cli), mem_ctx, op->in.parent_key, op->in.name); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_RegDeleteValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteValue *op) { + SMBCSRV *srv = NULL; + WERROR err; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.parent_key || !op->in.name || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_delete_val( &(srv->cli), mem_ctx, op->in.parent_key, op->in.name); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_RegQueryKeyInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryKeyInfo *op) { + SMBCSRV *srv = NULL; + WERROR err; + + char *class_name_out = NULL; + uint32 class_len = 0; + uint32 num_subkeys_out = 0; + uint32 long_subkey_out = 0; + uint32 long_class_out = 0; + uint32 num_values_out = 0; + uint32 long_value_out = 0; + uint32 long_data_out = 0; + uint32 secdesc_size = 0; + NTTIME mod_time; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.key || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_query_key( &(srv->cli), mem_ctx, op->in.key, + class_name_out, + &class_len, + &num_subkeys_out, + &long_subkey_out, + &long_class_out, + &num_values_out, + &long_value_out, + &long_data_out, + &secdesc_size, + &mod_time); + + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + if(!class_name_out) { + op->out.class_name = talloc_strdup(mem_ctx, ""); + } + else if(class_len != 0 && class_name_out[class_len - 1] != '\0') { + /*then we need to add a '\0'*/ + op->out.class_name = talloc_size(mem_ctx, sizeof(char)*(class_len + 1)); + + memcpy(op->out.class_name, class_name_out, class_len); + + op->out.class_name[class_len] = '\0'; + } + else { /*then everything worked out fine in the function*/ + op->out.class_name = talloc_strdup(mem_ctx, class_name_out); + } + + if(!op->out.class_name) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + op->out.num_subkeys = num_subkeys_out; + op->out.longest_subkey = long_subkey_out; + op->out.longest_class = long_class_out; + op->out.num_values = num_values_out; + op->out.longest_value_name = long_value_out; + op->out.longest_value_data = long_data_out; + op->out.security_desc_size = secdesc_size; + op->out.last_write_time = nt_time_to_unix(&mod_time); + + return CAC_FAILURE; +} + +int cac_RegQueryValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryValue *op) { + SMBCSRV *srv = NULL; + WERROR err; + + uint32 val_type; + REGVAL_BUFFER buffer; + REG_VALUE_DATA *data_out = NULL; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.key || !op->in.val_name || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_query_value(&srv->cli, mem_ctx, op->in.key, op->in.val_name, &val_type, &buffer); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + data_out = cac_MakeRegValueData(mem_ctx, val_type, buffer); + if(!data_out) { + if(errno == ENOMEM) + hnd->status = NT_STATUS_NO_MEMORY; + else + hnd->status = NT_STATUS_INVALID_PARAMETER; + + return CAC_FAILURE; + } + + op->out.type = val_type; + op->out.data = data_out; + + return CAC_SUCCESS; +} + + +int cac_RegEnumValues(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumValues *op) { + SMBCSRV *srv = NULL; + WERROR err; + + /*buffers for cli_reg_enum_key call*/ + fstring val_name_buf; + REGVAL_BUFFER val_buf; + + /*output buffers*/ + uint32 *types_out = NULL; + REG_VALUE_DATA **values_out = NULL; + char **val_names_out = NULL; + uint32 num_values_out = 0; + uint32 resume_idx = 0; + + if(!hnd) + return CAC_FAILURE; + + /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/ + if(NT_STATUS_V(hnd->status) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED)) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.key || op->in.max_values == 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; + } + + srv->cli.pipe_idx = PI_WINREG; + + /*we need to assume that the max number of values will be enumerated*/ + types_out = talloc_array(mem_ctx, int, op->in.max_values); + if(!types_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + values_out = talloc_array(mem_ctx, REG_VALUE_DATA *, op->in.max_values); + if(!values_out) { + talloc_free(types_out); + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + val_names_out = talloc_array(mem_ctx, char *, op->in.max_values); + if(!val_names_out) { + talloc_free(types_out); + talloc_free(values_out); + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + resume_idx = op->out.resume_idx; + do { + ZERO_STRUCT(val_buf); + + err = cli_reg_enum_val(&srv->cli, mem_ctx, op->in.key, resume_idx, val_name_buf, &types_out[num_values_out], &val_buf); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + break; + + values_out[num_values_out] = cac_MakeRegValueData(mem_ctx, types_out[num_values_out], val_buf); + val_names_out[num_values_out] = talloc_strdup(mem_ctx, val_name_buf); + + if(!val_names_out[num_values_out] || !values_out[num_values_out]) { + hnd->status = NT_STATUS_NO_MEMORY; + break; + } + + num_values_out++; + resume_idx++; + } while(num_values_out < op->in.max_values); + + if(CAC_OP_FAILED(hnd->status)) + return CAC_FAILURE; + + op->out.types = types_out; + op->out.num_values = num_values_out; + op->out.value_names = val_names_out; + op->out.values = values_out; + op->out.resume_idx = resume_idx; + + return CAC_SUCCESS; +} + +int cac_RegSetValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetValue *op) { + SMBCSRV *srv = NULL; + WERROR err; + + RPC_DATA_BLOB *buffer; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.key || !op->in.val_name || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + buffer = cac_MakeRpcDataBlob(mem_ctx, op->in.type, op->in.value); + + if(!buffer) { + if(errno == ENOMEM) + hnd->status = NT_STATUS_NO_MEMORY; + else + hnd->status = NT_STATUS_INVALID_PARAMETER; + + return CAC_FAILURE; + } + + err = cli_reg_set_val(&srv->cli, mem_ctx, op->in.key, op->in.val_name, op->in.type, buffer); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + /*flush*/ + err = cli_reg_flush_key(&(srv->cli), mem_ctx, op->in.key); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + + + +int cac_RegGetVersion(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetVersion *op) { + SMBCSRV *srv = NULL; + WERROR err; + + uint32 version_out; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.key || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_getversion( &(srv->cli), mem_ctx, op->in.key, &version_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + op->out.version = version_out; + + return CAC_SUCCESS; +} + +int cac_RegGetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetKeySecurity *op) { + SMBCSRV *srv = NULL; + WERROR err; + + uint32 buf_size; + SEC_DESC_BUF *buf = NULL; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.key || op->in.info_type == 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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_get_key_sec(&(srv->cli), mem_ctx, op->in.key, op->in.info_type, &buf_size, buf); + hnd->status = werror_to_ntstatus(err); + + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + op->out.size = buf->len; + op->out.descriptor = buf->sec; + + return CAC_SUCCESS; +} + +int cac_RegSetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetKeySecurity *op) { + SMBCSRV *srv = NULL; + WERROR err; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.key || op->in.info_type == 0 || op->in.size == 0 || !op->in.descriptor || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_set_key_sec(&(srv->cli), mem_ctx, op->in.key, op->in.info_type, op->in.size, op->in.descriptor); + hnd->status = werror_to_ntstatus(err); + + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_RegSaveKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSaveKey *op) { + SMBCSRV *srv = NULL; + WERROR err; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !op->in.key || !op->in.filename || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_save_key( &(srv->cli), mem_ctx, op->in.key, op->in.filename); + hnd->status = werror_to_ntstatus(err); + + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op) { + SMBCSRV *srv = NULL; + + char *msg; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + if(!op || !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 winreg pipe if we have to*/ + if(!hnd->_internal.pipes[PI_SHUTDOWN]) { + if(!cli_nt_session_open(&srv->cli, PI_SHUTDOWN)) { + hnd->status = NT_STATUS_UNSUCCESSFUL; + return CAC_FAILURE; + } + + hnd->_internal.pipes[PI_SHUTDOWN] = True; + } + + srv->cli.pipe_idx = PI_SHUTDOWN; + + msg = (op->in.message != NULL) ? op->in.message : talloc_strdup(mem_ctx, ""); + + hnd->status = NT_STATUS_OK; + + if(hnd->_internal.srv_level > SRV_WIN_NT4) { + hnd->status = cli_shutdown_init_ex( &(srv->cli), mem_ctx, msg, op->in.timeout, op->in.reboot, op->in.force, op->in.reason); + } + + if(hnd->_internal.srv_level < SRV_WIN_2K || !NT_STATUS_IS_OK(hnd->status)) { + hnd->status = cli_shutdown_init( &(srv->cli), mem_ctx, msg, op->in.timeout, op->in.reboot, op->in.force); + + hnd->_internal.srv_level = SRV_WIN_NT4; + } + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_AbortShutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx) { + SMBCSRV *srv = NULL; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SHUTDOWN; + + hnd->status = cli_shutdown_abort(&(srv->cli), mem_ctx); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + diff --git a/source3/libmsrpc/libmsrpc.c b/source3/libmsrpc/libmsrpc.c new file mode 100644 index 0000000000..05f2dfe627 --- /dev/null +++ b/source3/libmsrpc/libmsrpc.c @@ -0,0 +1,352 @@ +/* + * Unix SMB/CIFS implementation. + * MS-RPC client library implementation + * 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" +#include "libsmbclient.h" +#include "libsmb_internal.h" + +/*this function is based on code found in smbc_init_context() (libsmb/libsmbclient.c)*/ +void cac_Init(int debug) { + if(debug < 0 || debug > 99) + debug = 0; + + DEBUGLEVEL = debug; + + setup_logging("libmsrpc", True); +} + +int cac_InitHandleMem(CacServerHandle *hnd) { + hnd->username = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + if(!hnd->username) + return CAC_FAILURE; + + hnd->username[0] = '\0'; + + hnd->domain = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + if(!hnd->domain) + return CAC_FAILURE; + + hnd->domain[0] = '\0'; + + hnd->netbios_name = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + if(!hnd->netbios_name) + return CAC_FAILURE; + + hnd->netbios_name[0] = '\0'; + + hnd->password = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + if(!hnd->password) + return CAC_FAILURE; + + hnd->password[0] = '\0'; + + hnd->server = SMB_MALLOC_ARRAY(char, sizeof(fstring)); + if(!hnd->server) + return CAC_FAILURE; + + hnd->server[0] = '\0'; + + return CAC_SUCCESS; +} + +CacServerHandle *cac_NewServerHandle(BOOL allocate_fields) { + CacServerHandle * hnd; + + hnd = SMB_MALLOC_P(CacServerHandle); + + if(!hnd) { + errno = ENOMEM; + return NULL; + } + + ZERO_STRUCTP(hnd); + + if(allocate_fields == True) { + if(!cac_InitHandleMem(hnd)) { + SAFE_FREE(hnd); + return NULL; + } + } + + hnd->_internal.ctx = smbc_new_context(); + if(!hnd->_internal.ctx) { + cac_FreeHandle(hnd); + return NULL; + } + + hnd->_internal.ctx->callbacks.auth_fn = cac_GetAuthDataFn; + + /*add defaults*/ + hnd->debug = 0; + + /*start at the highest and it will fall down after trying the functions*/ + hnd->_internal.srv_level = SRV_WIN_2K3; + + hnd->_internal.user_supplied_ctx = False; + + return hnd; +} + +int cac_InitHandleData(CacServerHandle *hnd) { + /*store any automatically initialized values*/ + if(!hnd->netbios_name) { + hnd->netbios_name = SMB_STRDUP(hnd->_internal.ctx->netbios_name); + } + else if(hnd->netbios_name[0] == '\0') { + strncpy(hnd->netbios_name, hnd->_internal.ctx->netbios_name, sizeof(fstring)); + } + + if(!hnd->username) { + hnd->username = SMB_STRDUP(hnd->_internal.ctx->user); + } + else if(hnd->username[0] == '\0') { + strncpy(hnd->username, hnd->_internal.ctx->user, sizeof(fstring)); + } + + if(!hnd->domain) { + hnd->domain = SMB_STRDUP(hnd->_internal.ctx->workgroup); + } + else if(hnd->domain[0] == '\0') { + strncpy(hnd->domain, hnd->_internal.ctx->workgroup, sizeof(fstring)); + } + + return CAC_SUCCESS; +} + +void cac_SetAuthDataFn(CacServerHandle *hnd, smbc_get_auth_data_fn auth_fn) { + hnd->_internal.ctx->callbacks.auth_fn = auth_fn; +} + +void cac_SetSmbcContext(CacServerHandle *hnd, SMBCCTX *ctx) { + + SAFE_FREE(hnd->_internal.ctx); + + hnd->_internal.user_supplied_ctx = True; + + hnd->_internal.ctx = ctx; + + /*_try_ to avoid any problems that might occur if cac_Connect() isn't called*/ + /*cac_InitHandleData(hnd);*/ +} + +/*used internally*/ +SMBCSRV *cac_GetServer(CacServerHandle *hnd) { + SMBCSRV *srv; + + if(!hnd || !hnd->_internal.ctx) { + return NULL; + } + + srv = smbc_attr_server(hnd->_internal.ctx, hnd->server, "IPC$", hnd->domain, hnd->username, hnd->password, NULL); + if(!srv) { + hnd->status=NT_STATUS_UNSUCCESSFUL; + DEBUG(1, ("cac_GetServer: Could not find server connection.\n")); + } + + return srv; +} + + +int cac_Connect(CacServerHandle *hnd, const char *srv) { + if(!hnd) { + return CAC_FAILURE; + } + + /*these values should be initialized by the user*/ + if(!hnd->server && !srv) { + return CAC_FAILURE; + } + + + /*change the server name in the server handle if necessary*/ + if(srv && hnd->server && strcmp(hnd->server, srv) == 0) { + SAFE_FREE(hnd->server); + hnd->server = SMB_STRDUP(srv); + } + + + /*first see if the context has already been setup*/ + if( !(hnd->_internal.ctx->internal->_initialized) ) { + hnd->_internal.ctx->debug = hnd->debug; + + /*initialize the context*/ + if(!smbc_init_context(hnd->_internal.ctx)) { + return CAC_FAILURE; + } + } + + /*copy any uninitialized values out of the smbc context into the handle*/ + if(!cac_InitHandleData(hnd)) { + return CAC_FAILURE; + } + + DEBUG(3, ("cac_Connect: Username: %s\n", hnd->username)); + DEBUG(3, ("cac_Connect: Domain: %s\n", hnd->domain)); + DEBUG(3, ("cac_Connect: Netbios Name: %s\n", hnd->netbios_name)); + + if(!cac_GetServer(hnd)) { + return CAC_FAILURE; + } + + return CAC_SUCCESS; + +} + + +void cac_FreeHandle(CacServerHandle * hnd) { + SMBCSRV *srv = NULL; + uint32 i = 0; + + if(!hnd) + return; + + /*see if there are any sessions*/ + while(i <= PI_MAX_PIPES && hnd->_internal.pipes[i] == False) + i++; + + if(i < PI_MAX_PIPES) { + /*then one or more sessions are open*/ + srv = cac_GetServer(hnd); + + if(srv) + cli_nt_session_close(&(srv->cli)); + } + + /*only free the context if we created it*/ + if(!hnd->_internal.user_supplied_ctx) { + smbc_free_context(hnd->_internal.ctx, True); + } + + SAFE_FREE(hnd->netbios_name); + SAFE_FREE(hnd->domain); + SAFE_FREE(hnd->username); + SAFE_FREE(hnd->password); + SAFE_FREE(hnd->server); + SAFE_FREE(hnd); + +} + +void cac_InitCacTime(CacTime *cactime, NTTIME nttime) { + float high, low; + uint32 sec; + + if(!cactime) + return; + + ZERO_STRUCTP(cactime); + + /*this code is taken from display_time() found in rpcclient/cmd_samr.c*/ + if (nttime.high==0 && nttime.low==0) + return; + + if (nttime.high==0x80000000 && nttime.low==0) + return; + + high = 65536; + high = high/10000; + high = high*65536; + high = high/1000; + high = high * (~nttime.high); + + low = ~nttime.low; + low = low/(1000*1000*10); + + sec=high+low; + + cactime->days=sec/(60*60*24); + cactime->hours=(sec - (cactime->days*60*60*24)) / (60*60); + cactime->minutes=(sec - (cactime->days*60*60*24) - (cactime->hours*60*60) ) / 60; + cactime->seconds=sec - (cactime->days*60*60*24) - (cactime->hours*60*60) - (cactime->minutes*60); +} + +void cac_GetAuthDataFn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword) + +{ + char temp[sizeof(fstring)]; + + static char authUsername[sizeof(fstring)]; + static char authWorkgroup[sizeof(fstring)]; + static char authPassword[sizeof(fstring)]; + static char authSet = 0; + + char *pass = NULL; + + + if (authSet) + { + strncpy(pWorkgroup, authWorkgroup, maxLenWorkgroup - 1); + strncpy(pUsername, authUsername, maxLenUsername - 1); + strncpy(pPassword, authPassword, maxLenPassword - 1); + } + else + { + d_printf("Domain: [%s] ", pWorkgroup); + fgets(temp, sizeof(fstring), stdin); + + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + + + if (temp[0] != '\0') + { + strncpy(pWorkgroup, temp, maxLenWorkgroup - 1); + strncpy(authWorkgroup, temp, maxLenWorkgroup - 1); + } + + d_printf("Username: [%s] ", pUsername); + fgets(temp, sizeof(fstring), stdin); + + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + + if (temp[0] != '\0') + { + strncpy(pUsername, temp, maxLenUsername - 1); + strncpy(authUsername, pUsername, maxLenUsername - 1); + } + + pass = getpass("Password: "); + if (pass) + fstrcpy(temp, pass); + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + if (temp[0] != '\0') + { + strncpy(pPassword, temp, maxLenPassword - 1); + strncpy(authPassword, pPassword, maxLenPassword - 1); + } + authSet = 1; + } +} + diff --git a/source3/libmsrpc/libmsrpc.po b/source3/libmsrpc/libmsrpc.po Binary files differnew file mode 100644 index 0000000000..ca94f3d25c --- /dev/null +++ b/source3/libmsrpc/libmsrpc.po diff --git a/source3/libmsrpc/libmsrpc_internal.c b/source3/libmsrpc/libmsrpc_internal.c new file mode 100644 index 0000000000..2560fd602b --- /dev/null +++ b/source3/libmsrpc/libmsrpc_internal.c @@ -0,0 +1,684 @@ +/* + * Unix SMB/CIFS implementation. + * MS-RPC client internal functions + * 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" + +/*takes a string like HKEY_LOCAL_MACHINE\HARDWARE\ACPI and returns the reg_type code and then a pointer to the start of the path (HARDWARE)*/ +int cac_ParseRegPath(char *path, uint32 *reg_type, char **key_name) { + + if(!path) + return CAC_FAILURE; + + if(strncmp(path, "HKLM", 4) == 0) { + *reg_type = HKEY_LOCAL_MACHINE; + *key_name = (path[4] == '\\') ? path + 5 : NULL; + } + else if(strncmp(path, "HKEY_LOCAL_MACHINE", 18) == 0) { + *reg_type = HKEY_LOCAL_MACHINE; + *key_name = (path[18] == '\\') ? path + 19 : NULL; + } + else if(strncmp(path, "HKCR", 4) == 0) { + *reg_type = HKEY_CLASSES_ROOT; + *key_name = (path[4] == '\\') ? path + 5 : NULL; + } + else if(strncmp(path, "HKEY_CLASSES_ROOT", 17) == 0) { + *reg_type = HKEY_CLASSES_ROOT; + *key_name = (path[17] == '\\') ? path + 18 : NULL; + } + else if(strncmp(path, "HKU", 3) == 0) { + *reg_type = HKEY_USERS; + *key_name = (path[3] == '\\') ? path + 4 : NULL; + } + else if(strncmp(path, "HKEY_USERS", 10) == 0) { + *reg_type = HKEY_USERS; + *key_name = (path[10] == '\\') ? path + 11 : NULL; + } + else if(strncmp(path, "HKPD", 4) == 0) { + *reg_type = HKEY_PERFORMANCE_DATA; + *key_name = (path[4] == '\\') ? path + 5 : NULL; + } + else if(strncmp(path, "HKEY_PERFORMANCE_DATA", 21) == 0) { + *reg_type = HKEY_PERFORMANCE_DATA; + *key_name = (path[21] == '\\') ? path + 22 : NULL; + } + else { + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + + + +RPC_DATA_BLOB *cac_MakeRpcDataBlob(TALLOC_CTX *mem_ctx, uint32 data_type, REG_VALUE_DATA data) { + RPC_DATA_BLOB *blob = NULL; + int i; + uint32 size = 0; + uint32 len = 0; + uint8 *multi = NULL; + uint32 multi_idx = 0; + + blob = talloc(mem_ctx, RPC_DATA_BLOB); + + if(!blob) { + errno = ENOMEM; + return NULL; + } + + switch(data_type) { + case REG_SZ: + init_rpc_blob_str(blob, data.reg_sz, strlen(data.reg_sz ) + 1); + break; + + case REG_EXPAND_SZ: + init_rpc_blob_str(blob, data.reg_expand_sz, strlen(data.reg_sz) + 1); + break; + + case REG_BINARY: + init_rpc_blob_bytes(blob, data.reg_binary.data, data.reg_binary.data_length); + break; + + case REG_DWORD: + init_rpc_blob_uint32(blob, data.reg_dword); + break; + + case REG_DWORD_BE: + init_rpc_blob_uint32(blob, data.reg_dword_be); + break; + + case REG_MULTI_SZ: + /*need to find the size*/ + for(i = 0; i < data.reg_multi_sz.num_strings; i++) { + size += strlen(data.reg_multi_sz.strings[i]) + 1; + } + + /**need a whole bunch of unicode strings in a row (seperated by null characters), with an extra null-character on the end*/ + + multi = TALLOC_ZERO_ARRAY(mem_ctx, uint8, (size + 1)*2); /*size +1 for the extra null character*/ + if(!multi) { + errno = ENOMEM; + break; + } + + /*do it using rpcstr_push()*/ + multi_idx = 0; + for(i = 0; i < data.reg_multi_sz.num_strings; i++) { + len = strlen(data.reg_multi_sz.strings[i]) + 1; + + rpcstr_push((multi + multi_idx), data.reg_multi_sz.strings[i], len * 2, STR_TERMINATE); + + /* x2 becuase it is a uint8 buffer*/ + multi_idx += len * 2; + } + + /*now initialize the buffer as binary data*/ + init_rpc_blob_bytes(blob, multi, (size + 1)*2); + + break; + + default: + talloc_free(blob); + blob = NULL; + } + + if(!(blob->buffer)) { + talloc_free(blob); + return NULL; + } + + return blob; +} + +/*turns a string in a uint16 array to a char array*/ +char *cac_unistr_to_str(TALLOC_CTX *mem_ctx, uint16 *src, int num_bytes) { + char *buf; + + int i = 0; + + uint32 str_len = 0; + + /*don't allocate more space than we need*/ + while( (str_len) < num_bytes/2 && src[str_len] != 0x0000) + str_len++; + + /*need room for a '\0'*/ + str_len++; + + buf = talloc_array(mem_ctx, char, str_len); + if(!buf) { + return NULL; + } + + for(i = 0; i < num_bytes/2; i++) { + buf[i] = ((char *)src)[2*i]; + } + + buf[str_len - 1] = '\0'; + + return buf; +} + +REG_VALUE_DATA *cac_MakeRegValueData(TALLOC_CTX *mem_ctx, uint32 data_type, REGVAL_BUFFER buf) { + REG_VALUE_DATA *data; + + uint32 i; + + /*all of the following used for MULTI_SZ data*/ + uint32 size = 0; + uint32 len = 0; + uint32 multi_idx = 0; + uint32 num_strings= 0; + char **strings = NULL; + + data = talloc(mem_ctx, REG_VALUE_DATA); + if(!data) { + errno = ENOMEM; + return NULL; + } + + switch (data_type) { + case REG_SZ: + data->reg_sz = cac_unistr_to_str(mem_ctx, buf.buffer, buf.buf_len); + if(!data->reg_sz) { + talloc_free(data); + errno = ENOMEM; + data = NULL; + } + + break; + + case REG_EXPAND_SZ: + data->reg_expand_sz = cac_unistr_to_str(mem_ctx, buf.buffer, buf.buf_len); + + if(!data->reg_expand_sz) { + talloc_free(data); + errno = ENOMEM; + data = NULL; + } + + break; + + case REG_BINARY: + size = buf.buf_len; + + data->reg_binary.data_length = size; + + data->reg_binary.data = talloc_memdup(mem_ctx, buf.buffer, size); + if(!data->reg_binary.data) { + talloc_free(data); + errno = ENOMEM; + data = NULL; + } + break; + + case REG_DWORD: + data->reg_dword = *((uint32 *)buf.buffer); + break; + + case REG_DWORD_BE: + data->reg_dword_be = *((uint32 *)buf.buffer); + break; + + case REG_MULTI_SZ: + size = buf.buf_len; + + /*find out how many strings there are. size is # of bytes and we want to work uint16*/ + for(i = 0; i < (size/2 - 1); i++) { + if(buf.buffer[i] == 0x0000) + num_strings++; + + /*buffer is suppsed to be terminated with \0\0, but it might not be*/ + if(buf.buffer[i] == 0x0000 && buf.buffer[i + 1] == 0x0000) + break; + } + + strings = talloc_array(mem_ctx, char *, num_strings); + if(!strings) { + errno = ENOMEM; + talloc_free(data); + break; + } + + if(num_strings == 0) /*then our work here is done*/ + break; + + for(i = 0; i < num_strings; i++) { + /*find out how many characters are in this string*/ + len = 0; + /*make sure we don't go past the end of the buffer and keep looping until we have a uni \0*/ + while( multi_idx + len < size/2 && buf.buffer[multi_idx + len] != 0x0000) + len++; + + /*stay aware of the \0\0*/ + len++; + + strings[i] = TALLOC_ZERO_ARRAY(mem_ctx, char, len); + + /*pull out the unicode string*/ + rpcstr_pull(strings[i], (buf.buffer + multi_idx) , len, -1, STR_TERMINATE); + + /*keep track of where we are in the bigger array*/ + multi_idx += len; + } + + data->reg_multi_sz.num_strings = num_strings; + data->reg_multi_sz.strings = strings; + + break; + + default: + talloc_free(data); + data = NULL; + } + + return data; +} + +SAM_USERINFO_CTR *cac_MakeUserInfoCtr(TALLOC_CTX *mem_ctx, CacUserInfo *info) { + SAM_USERINFO_CTR *ctr = NULL; + + /*the flags we are 'setting'- include/passdb.h*/ + uint32 flags = ACCT_USERNAME | ACCT_FULL_NAME | ACCT_PRIMARY_GID | ACCT_ADMIN_DESC | ACCT_DESCRIPTION | + ACCT_HOME_DIR | ACCT_HOME_DRIVE | ACCT_LOGON_SCRIPT | ACCT_PROFILE | ACCT_WORKSTATIONS | + ACCT_FLAGS; + + NTTIME logon_time; + NTTIME logoff_time; + NTTIME kickoff_time; + NTTIME pass_last_set_time; + NTTIME pass_can_change_time; + NTTIME pass_must_change_time; + + UNISTR2 user_name; + UNISTR2 full_name; + UNISTR2 home_dir; + UNISTR2 dir_drive; + UNISTR2 log_scr; + UNISTR2 prof_path; + UNISTR2 desc; + UNISTR2 wkstas; + UNISTR2 mung_dial; + UNISTR2 unk; + + ctr = talloc(mem_ctx, SAM_USERINFO_CTR); + if(!ctr) + return NULL; + + ZERO_STRUCTP(ctr->info.id23); + + ctr->info.id21 = talloc(mem_ctx, SAM_USER_INFO_21); + if(!ctr->info.id21) + return NULL; + + ctr->switch_value = 21; + + ZERO_STRUCTP(ctr->info.id21); + + unix_to_nt_time(&logon_time, info->logon_time); + unix_to_nt_time(&logoff_time, info->logoff_time); + unix_to_nt_time(&kickoff_time, info->kickoff_time); + unix_to_nt_time(&pass_last_set_time, info->pass_last_set_time); + unix_to_nt_time(&pass_can_change_time, info->pass_can_change_time); + unix_to_nt_time(&pass_must_change_time, info->pass_must_change_time); + + /*initialize the strings*/ + init_unistr2(&user_name, info->username, STR_TERMINATE); + init_unistr2(&full_name, info->full_name, STR_TERMINATE); + init_unistr2(&home_dir, info->home_dir, STR_TERMINATE); + init_unistr2(&dir_drive, info->home_drive, STR_TERMINATE); + init_unistr2(&log_scr, info->logon_script, STR_TERMINATE); + init_unistr2(&prof_path, info->profile_path, STR_TERMINATE); + init_unistr2(&desc, info->description, STR_TERMINATE); + init_unistr2(&wkstas, info->workstations, STR_TERMINATE); + init_unistr2(&unk, "\0", STR_TERMINATE); + init_unistr2(&mung_dial, info->dial, STR_TERMINATE); + + /*manually set passmustchange*/ + ctr->info.id21->passmustchange = (info->pass_must_change) ? 0x01 : 0x00; + + init_sam_user_info21W(ctr->info.id21, + &logon_time, + &logoff_time, + &kickoff_time, + &pass_last_set_time, + &pass_can_change_time, + &pass_must_change_time, + &user_name, + &full_name, + &home_dir, + &dir_drive, + &log_scr, + &prof_path, + &desc, + &wkstas, + &unk, + &mung_dial, + info->lm_password, + info->nt_password, + info->rid, + info->group_rid, + info->acb_mask, + flags, + 168, /*logon divs*/ + info->logon_hours, + info->bad_passwd_count, + info->logon_count); + + return ctr; + +} + +char *talloc_unistr2_to_ascii(TALLOC_CTX *mem_ctx, UNISTR2 str) { + char *buf = NULL; + + if(!mem_ctx) + return NULL; + + buf = talloc_array(mem_ctx, char, (str.uni_str_len + 1)); + if(!buf) + return NULL; + + unistr2_to_ascii(buf, &str, str.uni_str_len + 1); + + return buf; +} + +CacUserInfo *cac_MakeUserInfo(TALLOC_CTX *mem_ctx, SAM_USERINFO_CTR *ctr) { + CacUserInfo *info = NULL; + SAM_USER_INFO_21 *id21 = NULL; + + if(!ctr || ctr->switch_value != 21) + return NULL; + + info = talloc(mem_ctx, CacUserInfo); + if(!info) + return NULL; + + id21 = ctr->info.id21; + + ZERO_STRUCTP(info); + + info->logon_time = nt_time_to_unix(&id21->logon_time); + info->logoff_time = nt_time_to_unix(&id21->logoff_time); + info->kickoff_time = nt_time_to_unix(&id21->kickoff_time); + info->pass_last_set_time = nt_time_to_unix(&id21->pass_last_set_time); + info->pass_can_change_time = nt_time_to_unix(&id21->pass_can_change_time); + info->pass_must_change_time = nt_time_to_unix(&id21->pass_must_change_time); + + info->username = talloc_unistr2_to_ascii(mem_ctx, id21->uni_user_name); + if(!info->username) + return NULL; + + info->full_name = talloc_unistr2_to_ascii(mem_ctx, id21->uni_full_name); + if(!info->full_name) + return NULL; + + info->home_dir = talloc_unistr2_to_ascii(mem_ctx, id21->uni_home_dir); + if(!info->home_dir) + return NULL; + + info->home_drive = talloc_unistr2_to_ascii(mem_ctx, id21->uni_dir_drive); + if(!info->home_drive) + return NULL; + + info->logon_script = talloc_unistr2_to_ascii(mem_ctx, id21->uni_logon_script); + if(!info->logon_script) + return NULL; + + info->profile_path = talloc_unistr2_to_ascii(mem_ctx, id21->uni_profile_path); + if(!info->profile_path) + return NULL; + + info->description = talloc_unistr2_to_ascii(mem_ctx, id21->uni_acct_desc); + if(!info->description) + return NULL; + + info->workstations = talloc_unistr2_to_ascii(mem_ctx, id21->uni_workstations); + if(!info->workstations) + return NULL; + + info->dial = talloc_unistr2_to_ascii(mem_ctx, id21->uni_munged_dial); + if(!info->dial) + return NULL; + + info->rid = id21->user_rid; + info->group_rid = id21->group_rid; + info->acb_mask = id21->acb_info; + info->bad_passwd_count = id21->bad_password_count; + info->logon_count = id21->logon_count; + + memcpy(info->nt_password, id21->nt_pwd, 8); + memcpy(info->lm_password, id21->lm_pwd, 8); + + info->logon_hours = talloc_memdup(mem_ctx, &(id21->logon_hrs), sizeof(LOGON_HRS)); + if(!info->logon_hours) + return NULL; + + info->pass_must_change = (id21->passmustchange) ? True : False; + + return info; +} + +CacGroupInfo *cac_MakeGroupInfo(TALLOC_CTX *mem_ctx, GROUP_INFO_CTR *ctr) { + CacGroupInfo *info = NULL; + + if(!mem_ctx || !ctr || ctr->switch_value1 != 1) + return NULL; + + info = talloc(mem_ctx, CacGroupInfo); + if(!info) + return NULL; + + info->name = talloc_unistr2_to_ascii(mem_ctx, ctr->group.info1.uni_acct_name); + if(!info->name) + return NULL; + + info->description = talloc_unistr2_to_ascii(mem_ctx, ctr->group.info1.uni_acct_desc); + if(!info->description) + return NULL; + + info->num_members = ctr->group.info1.num_members; + + return info; +} + +GROUP_INFO_CTR *cac_MakeGroupInfoCtr(TALLOC_CTX *mem_ctx, CacGroupInfo *info) { + GROUP_INFO_CTR *ctr = NULL; + + if(!mem_ctx || !info) + return NULL; + + ctr = talloc(mem_ctx, GROUP_INFO_CTR); + if(!ctr) + return NULL; + + ctr->switch_value1 = 1; + + init_samr_group_info1(&(ctr->group.info1), info->name, info->description, info->num_members); + + return ctr; +} + +CacAliasInfo *cac_MakeAliasInfo(TALLOC_CTX *mem_ctx, ALIAS_INFO_CTR ctr) { + CacGroupInfo *info = NULL; + + if(!mem_ctx || ctr.level != 1) + return NULL; + + info = talloc(mem_ctx, CacAliasInfo); + if(!info) + return NULL; + + info->name = talloc_unistr2_to_ascii(mem_ctx, *(ctr.alias.info1.name.string)); + if(!info->name) + return NULL; + + info->description = talloc_unistr2_to_ascii(mem_ctx, *(ctr.alias.info1.description.string)); + if(!info->name) + return NULL; + + info->num_members = ctr.alias.info1.num_member; + + return info; +} + +ALIAS_INFO_CTR *cac_MakeAliasInfoCtr(TALLOC_CTX *mem_ctx, CacAliasInfo *info) { + ALIAS_INFO_CTR *ctr = NULL; + + if(!mem_ctx || !info) + return NULL; + + ctr = talloc(mem_ctx, ALIAS_INFO_CTR); + if(!ctr) + return NULL; + + ctr->level = 1; + + init_samr_alias_info1(&(ctr->alias.info1), info->name, info->num_members, info->description); + + return ctr; +} + +CacDomainInfo *cac_MakeDomainInfo(TALLOC_CTX *mem_ctx, SAM_UNK_INFO_1 *info1, SAM_UNK_INFO_2 *info2, SAM_UNK_INFO_12 *info12) { + CacDomainInfo *info = NULL; + + if(!mem_ctx || !info1 || !info2 || !info12) + return NULL; + + info = talloc(mem_ctx, CacDomainInfo); + if(!info) + return NULL; + + info->min_pass_length = info1->min_length_password; + info->pass_history = info1->password_history; + + cac_InitCacTime(&(info->expire), info1->expire); + cac_InitCacTime(&(info->min_pass_age), info1->min_passwordage); + + info->server_role = info2->server_role; + info->num_users = info2->num_domain_usrs; + info->num_domain_groups = info2->num_domain_grps; + info->num_local_groups = info2->num_local_grps; + + /*if these have been ZERO'd out we need to know. uni_str_len will be 0*/ + if(info2->uni_comment.uni_str_len == 0) { + info->comment = talloc_strdup(mem_ctx, "\0"); + } + else { + info->comment = talloc_unistr2_to_ascii(mem_ctx, info2->uni_comment); + } + + if(info2->uni_domain.uni_str_len == 0) { + info->domain_name = talloc_strdup(mem_ctx, "\0"); + } + else { + info->domain_name = talloc_unistr2_to_ascii(mem_ctx, info2->uni_domain); + } + + if(info2->uni_server.uni_str_len == 0) { + info->server_name = talloc_strdup(mem_ctx, "\0"); + } + else { + info->server_name = talloc_unistr2_to_ascii(mem_ctx, info2->uni_server); + } + + + cac_InitCacTime(&(info->lockout_duration), info12->duration); + cac_InitCacTime(&(info->lockout_reset), info12->reset_count); + info->num_bad_attempts = info12->bad_attempt_lockout; + + return info; +} + +char *cac_unistr_ascii(TALLOC_CTX *mem_ctx, UNISTR src) { + char *buf; + uint32 len; + + if(!mem_ctx || !src.buffer) + return NULL; + + len = unistrlen(src.buffer) + 1; + + buf = TALLOC_ZERO_ARRAY(mem_ctx, char, len); + if(!buf) + return NULL; + + rpcstr_pull(buf, src.buffer, len, -1, STR_TERMINATE); + + return buf; +} + +CacService *cac_MakeServiceArray(TALLOC_CTX *mem_ctx, ENUM_SERVICES_STATUS *svc, uint32 num_services) { + int i; + CacService *services = NULL; + + if(!mem_ctx || !svc) + return NULL; + + services = TALLOC_ZERO_ARRAY(mem_ctx, CacService, num_services); + if(!services) + return NULL; + + for(i = 0; i < num_services; i++) { + services[i].service_name = cac_unistr_ascii(mem_ctx, svc[i].servicename); + services[i].display_name = cac_unistr_ascii(mem_ctx, svc[i].displayname); + + if(!services[i].service_name || !services[i].display_name) + return NULL; + + services[i].status = svc[i].status; + } + + return services; +} + +int cac_InitCacServiceConfig(TALLOC_CTX *mem_ctx, SERVICE_CONFIG *src, CacServiceConfig *dest) { + if(!src || !dest) + return CAC_FAILURE; + + dest->exe_path = talloc_unistr2_to_ascii(mem_ctx, *src->executablepath); + if(!dest->exe_path) + return CAC_FAILURE; + + dest->load_order_group = talloc_unistr2_to_ascii(mem_ctx, *src->loadordergroup); + if(!dest->load_order_group) + return CAC_FAILURE; + + dest->dependencies = talloc_unistr2_to_ascii(mem_ctx, *src->dependencies); + if(!dest->dependencies) + return CAC_FAILURE; + + dest->start_name = talloc_unistr2_to_ascii(mem_ctx, *src->startname); + if(!dest->start_name) + return CAC_FAILURE; + + dest->display_name = talloc_unistr2_to_ascii(mem_ctx, *src->displayname); + if(!dest->display_name) + return CAC_FAILURE; + + dest->type = src->service_type; + dest->start_type = src->start_type; + dest->error_control = src->error_control; + dest->tag_id = src->tag_id; + + return CAC_SUCCESS; +} |