From 8db18a0775a66ee3073484b987d4a9ff0fd22c90 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 May 2004 14:58:08 +0000 Subject: r458: this is the (very primitive) beginnings of a SAMR server for Samba4. I'm committing this now so I can get comments on the approach. Note that you need to do something like this to initialise the SAM db: edit script/provision.pl script/provision.pl > provision.ldif.out bin/ldbadd /path/to/private/sam.ldb provision.ldif.out (This used to be commit e2002e40a5abe0cd33a2056b1da8ba5732f9021f) --- source4/param/loadparm.c | 6 +- source4/rpc_server/config.m4 | 1 + source4/rpc_server/samr/dcesrv_samr.c | 933 ++++++++++++++++++++++++++++++++++ source4/rpc_server/samr/samdb.c | 189 +++++++ source4/script/provision.pl | 107 ++++ 5 files changed, 1235 insertions(+), 1 deletion(-) create mode 100644 source4/rpc_server/samr/dcesrv_samr.c create mode 100644 source4/rpc_server/samr/samdb.c create mode 100755 source4/script/provision.pl diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index 7218b2ecab..d36bd83e66 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -106,6 +106,7 @@ typedef struct char *szLogFile; char *szConfigFile; char *szSMBPasswdFile; + char *szSAM_URL; char *szPrivateDir; char **szPassdbBackend; char **szPreloadModules; @@ -558,6 +559,7 @@ static struct parm_struct parm_table[] = { {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, @@ -930,12 +932,13 @@ static void init_globals(void) string_set(&sDefault.fstype, FSTYPE_STRING); string_set(&sDefault.ntvfs_handler, "default"); - Globals.dcerpc_ep_servers = str_list_make("epmapper srvsvc wkssvc rpcecho", NULL); + Globals.dcerpc_ep_servers = str_list_make("epmapper srvsvc wkssvc rpcecho samr", NULL); Globals.AuthMethods = str_list_make("guest sam_ignoredomain", NULL); string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE); string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR); + asprintf(&Globals.szSAM_URL, "tdb://%s/sam.ldb", dyn_PRIVATE_DIR); /* use the new 'hash2' method by default, with a prefix of 1 */ @@ -1182,6 +1185,7 @@ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset) FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile) FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile) FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile) +FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL) FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir) FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString) FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname) diff --git a/source4/rpc_server/config.m4 b/source4/rpc_server/config.m4 index eeecc7642f..09e76c2ead 100644 --- a/source4/rpc_server/config.m4 +++ b/source4/rpc_server/config.m4 @@ -8,6 +8,7 @@ SMB_MODULE(dcerpc_epmapper,DCERPC,STATIC,[rpc_server/epmapper/rpc_epmapper.o]) SMB_MODULE(dcerpc_remote,DCERPC,STATIC,[rpc_server/remote/dcesrv_remote.o]) SMB_MODULE(dcerpc_srvsvc,DCERPC,STATIC,[rpc_server/srvsvc/dcesrv_srvsvc.o]) SMB_MODULE(dcerpc_wkssvc,DCERPC,STATIC,[rpc_server/wkssvc/dcesrv_wkssvc.o]) +SMB_MODULE(dcerpc_samr,DCERPC,STATIC,[rpc_server/samr/dcesrv_samr.o rpc_server/samr/samdb.o]) SMB_MODULE(dcerpc_winreg,DCERPC,STATIC,[rpc_server/winreg/rpc_winreg.o \$(REG_OBJS)],[],[\$(REG_LIBS)]) SMB_SUBSYSTEM(DCERPC,rpc_server/dcerpc_server.o, diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c new file mode 100644 index 0000000000..e4dcf398a2 --- /dev/null +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -0,0 +1,933 @@ +/* + Unix SMB/CIFS implementation. + + endpoint server for the samr pipe + + Copyright (C) Andrew Tridgell 2004 + + 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 "includes.h" + +/* + this type allows us to distinguish handle types +*/ +enum samr_handle { + SAMR_HANDLE_CONNECT, + SAMR_HANDLE_DOMAIN, + SAMR_HANDLE_USER, + SAMR_HANDLE_GROUP, + SAMR_HANDLE_ALIAS +}; + + +/* + state asscoiated with a samr_Connect*() operation +*/ +struct samr_connect_state { + TALLOC_CTX *mem_ctx; + uint32 access_mask; +}; + + +/* + destroy an open connection. This closes the database connection +*/ +static void samr_Connect_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h) +{ + struct samr_connect_state *state = h->data; + talloc_destroy(state->mem_ctx); +} + +/* + samr_Connect + + create a connection to the SAM database +*/ +static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_Connect *r) +{ + struct samr_connect_state *state; + struct dcesrv_handle *handle; + TALLOC_CTX *connect_mem_ctx; + + ZERO_STRUCTP(r->out.handle); + + connect_mem_ctx = talloc_init("samr_Connect"); + if (!connect_mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + state = talloc_p(connect_mem_ctx, struct samr_connect_state); + if (!state) { + return NT_STATUS_NO_MEMORY; + } + state->mem_ctx = connect_mem_ctx; + + /* make sure the sam database is accessible */ + if (samdb_connect() != 0) { + r->out.result = NT_STATUS_INVALID_SYSTEM_SERVICE; + talloc_destroy(state->mem_ctx); + return NT_STATUS_OK; + } + + handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_CONNECT); + if (!handle) { + talloc_destroy(state->mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + handle->data = state; + handle->destroy = samr_Connect_destroy; + + state->access_mask = r->in.access_mask; + *r->out.handle = handle->wire_handle; + r->out.result = NT_STATUS_OK; + + return NT_STATUS_OK; +} + + +/* + samr_Close +*/ +static NTSTATUS samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_Close *r) +{ + struct dcesrv_handle *h = dcesrv_handle_fetch(dce_call->conn, + r->in.handle, + DCESRV_HANDLE_ANY); + if (!h) { + return NT_STATUS_INVALID_HANDLE; + } + + /* this causes the callback samr_XXX_destroy() to be called by + the handle destroy code which destroys the state associated + with the handle */ + dcesrv_handle_destroy(dce_call->conn, h); + + r->out.result = NT_STATUS_OK; + ZERO_STRUCTP(r->out.handle); + + return NT_STATUS_OK; +} + + +/* + samr_SetSecurity +*/ +static NTSTATUS samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetSecurity *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QuerySecurity +*/ +static NTSTATUS samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QuerySecurity *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_Shutdown + + we refuse this operation completely. If a admin wants to shutdown samr + in Samba then they should use the samba admin tools to disable the samr pipe +*/ +static NTSTATUS samr_Shutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_Shutdown *r) +{ + return NT_STATUS_ACCESS_DENIED; +} + + +/* + samr_LookupDomain + + this maps from a domain name to a SID +*/ +static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_LookupDomain *r) +{ + struct dcesrv_handle *h; + struct dom_sid2 *sid; + const char *sidstr; + + h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, SAMR_HANDLE_CONNECT); + if (!h) { + return NT_STATUS_INVALID_HANDLE; + } + + r->out.sid = NULL; + + if (r->in.domain->name == NULL) { + r->out.result = NT_STATUS_INVALID_PARAMETER; + return NT_STATUS_OK; + } + + sidstr = samdb_search_string(mem_ctx, "objectSid", + "(&(name=%s)(objectclass=domain))", + r->in.domain->name); + if (sidstr == NULL) { + r->out.result = NT_STATUS_NO_SUCH_DOMAIN; + return NT_STATUS_OK; + } + + sid = dom_sid_parse_talloc(mem_ctx, sidstr); + if (sid == NULL) { + DEBUG(1,("samdb: Invalid sid '%s' for domain %s\n", + sidstr, r->in.domain->name)); + r->out.result = NT_STATUS_INTERNAL_DB_CORRUPTION; + return NT_STATUS_OK; + } + + r->out.sid = sid; + r->out.result = NT_STATUS_OK; + + return NT_STATUS_OK; +} + + +/* + samr_EnumDomains + + list the domains in the SAM +*/ +static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_EnumDomains *r) +{ + struct dcesrv_handle *h; + struct samr_SamArray *array; + char **domains; + int count, i, start_i; + + h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, SAMR_HANDLE_CONNECT); + if (!h) { + return NT_STATUS_INVALID_HANDLE; + } + + *r->out.resume_handle = 0; + r->out.sam = NULL; + r->out.num_entries = 0; + + count = samdb_search_string_multiple(mem_ctx, &domains, + "name", "(objectclass=domain)"); + if (count == -1) { + DEBUG(1,("samdb: no domains found in EnumDomains\n")); + r->out.result = NT_STATUS_INTERNAL_DB_CORRUPTION; + return NT_STATUS_OK; + } + + *r->out.resume_handle = count; + + start_i = *r->in.resume_handle; + + if (start_i >= count) { + /* search past end of list is not an error for this call */ + r->out.result = NT_STATUS_OK; + return NT_STATUS_OK; + } + + array = talloc_p(mem_ctx, struct samr_SamArray); + if (array == NULL) { + r->out.result = NT_STATUS_NO_MEMORY; + return NT_STATUS_OK; + } + + array->count = 0; + array->entries = NULL; + + array->entries = talloc_array_p(mem_ctx, struct samr_SamEntry, count - start_i); + if (array->entries == NULL) { + r->out.result = NT_STATUS_NO_MEMORY; + return NT_STATUS_OK; + } + + for (i=0;ientries[i].idx = start_i + i; + array->entries[i].name.name = domains[start_i+i]; + } + + r->out.sam = array; + r->out.num_entries = i - start_i; + array->count = r->out.num_entries; + r->out.result = NT_STATUS_OK; + + return NT_STATUS_OK; +} + + +/* + samr_OpenDomain +*/ +static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_OpenDomain *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryDomainInfo +*/ +static NTSTATUS samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryDomainInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_SetDomainInfo +*/ +static NTSTATUS samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetDomainInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_CreateDomainGroup +*/ +static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_CreateDomainGroup *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_EnumDomainGroups +*/ +static NTSTATUS samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_EnumDomainGroups *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_CreateUser +*/ +static NTSTATUS samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_CreateUser *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_EnumDomainUsers +*/ +static NTSTATUS samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_EnumDomainUsers *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_CreateDomAlias +*/ +static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_CreateDomAlias *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_EnumDomainAliases +*/ +static NTSTATUS samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_EnumDomainAliases *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_GetAliasMembership +*/ +static NTSTATUS samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_GetAliasMembership *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_LookupNames +*/ +static NTSTATUS samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_LookupNames *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_LookupRids +*/ +static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_LookupRids *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_OpenGroup +*/ +static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_OpenGroup *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryGroupInfo +*/ +static NTSTATUS samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryGroupInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_SetGroupInfo +*/ +static NTSTATUS samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetGroupInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_AddGroupMember +*/ +static NTSTATUS samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_AddGroupMember *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_DeleteDomainGroup +*/ +static NTSTATUS samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_DeleteDomainGroup *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_DeleteGroupMember +*/ +static NTSTATUS samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_DeleteGroupMember *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryGroupMember +*/ +static NTSTATUS samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryGroupMember *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_SetMemberAttributesOfGroup +*/ +static NTSTATUS samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetMemberAttributesOfGroup *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_OpenAlias +*/ +static NTSTATUS samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_OpenAlias *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryAliasInfo +*/ +static NTSTATUS samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryAliasInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_SetAliasInfo +*/ +static NTSTATUS samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetAliasInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_DeleteDomAlias +*/ +static NTSTATUS samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_DeleteDomAlias *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_AddAliasMember +*/ +static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_AddAliasMember *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_DeleteAliasMember +*/ +static NTSTATUS samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_DeleteAliasMember *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_GetMembersInAlias +*/ +static NTSTATUS samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_GetMembersInAlias *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_OpenUser +*/ +static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_OpenUser *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_DeleteUser +*/ +static NTSTATUS samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_DeleteUser *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryUserInfo +*/ +static NTSTATUS samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryUserInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_SetUserInfo +*/ +static NTSTATUS samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetUserInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_ChangePasswordUser +*/ +static NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_ChangePasswordUser *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_GetGroupsForUser +*/ +static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_GetGroupsForUser *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryDisplayInfo +*/ +static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryDisplayInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_GetDisplayEnumerationIndex +*/ +static NTSTATUS samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_GetDisplayEnumerationIndex *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_TestPrivateFunctionsDomain +*/ +static NTSTATUS samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_TestPrivateFunctionsDomain *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_TestPrivateFunctionsUser +*/ +static NTSTATUS samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_TestPrivateFunctionsUser *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_GetUserPwInfo +*/ +static NTSTATUS samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_GetUserPwInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_RemoveMemberFromForeignDomain +*/ +static NTSTATUS samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_RemoveMemberFromForeignDomain *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryDomainInfo2 +*/ +static NTSTATUS samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryDomainInfo2 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryUserInfo2 +*/ +static NTSTATUS samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryUserInfo2 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryDisplayInfo2 +*/ +static NTSTATUS samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryDisplayInfo2 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_GetDisplayEnumerationIndex2 +*/ +static NTSTATUS samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_GetDisplayEnumerationIndex2 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_CreateUser2 +*/ +static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_CreateUser2 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_QueryDisplayInfo3 +*/ +static NTSTATUS samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_QueryDisplayInfo3 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_AddMultipleMembersToAlias +*/ +static NTSTATUS samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_AddMultipleMembersToAlias *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_RemoveMultipleMembersFromAlias +*/ +static NTSTATUS samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_RemoveMultipleMembersFromAlias *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_OemChangePasswordUser2 +*/ +static NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_OemChangePasswordUser2 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_ChangePasswordUser2 +*/ +static NTSTATUS samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_ChangePasswordUser2 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_GetDomPwInfo +*/ +static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_GetDomPwInfo *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_Connect2 +*/ +static NTSTATUS samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_Connect2 *r) +{ + struct samr_Connect c; + NTSTATUS status; + + c.in.system_name = NULL; + c.in.access_mask = r->in.access_mask; + c.out.handle = r->out.handle; + + status = samr_Connect(dce_call, mem_ctx, &c); + r->out.result = c.out.result; + + return status; +} + + +/* + samr_SetUserInfo2 +*/ +static NTSTATUS samr_SetUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetUserInfo2 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_SetBootKeyInformation +*/ +static NTSTATUS samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetBootKeyInformation *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_GetBootKeyInformation +*/ +static NTSTATUS samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_GetBootKeyInformation *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_Connect3 +*/ +static NTSTATUS samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_Connect3 *r) +{ + struct samr_Connect c; + NTSTATUS status; + + c.in.system_name = NULL; + c.in.access_mask = r->in.access_mask; + c.out.handle = r->out.handle; + + status = samr_Connect(dce_call, mem_ctx, &c); + r->out.result = c.out.result; + + return status; +} + + +/* + samr_Connect4 +*/ +static NTSTATUS samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_Connect4 *r) +{ + struct samr_Connect c; + NTSTATUS status; + + c.in.system_name = NULL; + c.in.access_mask = r->in.access_mask; + c.out.handle = r->out.handle; + + status = samr_Connect(dce_call, mem_ctx, &c); + r->out.result = c.out.result; + + return status; +} + + +/* + samr_ChangePasswordUser3 +*/ +static NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_ChangePasswordUser3 *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_Connect5 +*/ +static NTSTATUS samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_Connect5 *r) +{ + struct samr_Connect c; + NTSTATUS status; + + c.in.system_name = NULL; + c.in.access_mask = r->in.access_mask; + c.out.handle = r->out.handle; + + status = samr_Connect(dce_call, mem_ctx, &c); + + r->out.info->info1.unknown1 = 3; + r->out.info->info1.unknown2 = 0; + r->out.level = r->in.level; + r->out.result = c.out.result; + + return status; +} + + +/* + samr_RidToSid +*/ +static NTSTATUS samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_RidToSid *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_SetDsrmPassword +*/ +static NTSTATUS samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_SetDsrmPassword *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* + samr_ValidatePassword +*/ +static NTSTATUS samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct samr_ValidatePassword *r) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + + +/* include the generated boilerplate */ +#include "librpc/gen_ndr/ndr_samr_s.c" diff --git a/source4/rpc_server/samr/samdb.c b/source4/rpc_server/samr/samdb.c new file mode 100644 index 0000000000..ac58fe2c01 --- /dev/null +++ b/source4/rpc_server/samr/samdb.c @@ -0,0 +1,189 @@ +/* + Unix SMB/CIFS implementation. + + interface functions for the sam database + + Copyright (C) Andrew Tridgell 2004 + + 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 "includes.h" + + +/* + the way that unix fcntl locking works forces us to have a static ldb + handle here rather than a much more sensible approach of having the + ldb handle as part of the samr_Connect() pipe state. Otherwise we + would try to open the ldb more than once, and tdb would rightly + refuse the second open due to the broken nature of unix locking. +*/ +static struct ldb_context *sam_db; + +/* + connect to the SAM database + return 0 on success, -1 on failure + */ +int samdb_connect(void) +{ + if (sam_db != NULL) { + return 0; + } + sam_db = ldb_connect(lp_sam_url(), 0, NULL); + + if (sam_db == NULL) { + return -1; + } + + return 0; +} + + +/* + search the sam for the specified attributes - va_list varient +*/ +int samdb_search_v(struct ldb_message ***res, + const char * const *attrs, + const char *format, + va_list ap) +{ + char *expr = NULL; + int count; + + vasprintf(&expr, format, ap); + if (expr == NULL) { + return -1; + } + + count = ldb_search(sam_db, NULL, LDB_SCOPE_SUBTREE, expr, attrs, res); + + free(expr); + + return count; +} + + +/* + search the sam for the specified attributes - varargs varient +*/ +int samdb_search(struct ldb_message ***res, + const char * const *attrs, + const char *format, ...) +{ + va_list ap; + int count; + + va_start(ap, format); + count = samdb_search_v(res, attrs, format, ap); + va_end(ap); + + return count; +} + + +/* + search the sam for a single string attribute in exactly 1 record +*/ +const char *samdb_search_string(TALLOC_CTX *mem_ctx, + const char *attr_name, + const char *format, ...) +{ + va_list ap; + int count; + const char * const attrs[2] = { attr_name, NULL }; + struct ldb_message **res = NULL; + const char *str = NULL; + + va_start(ap, format); + count = samdb_search_v(&res, attrs, format, ap); + va_end(ap); + + if (count == 0) { + return NULL; + } + + /* make sure its single valued */ + if (count != 1 || + res[0]->num_elements != 1 || + res[0]->elements[0].num_values != 1 || + res[0]->elements[0].values[0].data == NULL) { + DEBUG(1,("samdb: search for %s %s not single valued\n", + attr_name, format)); + ldb_search_free(sam_db, res); + return NULL; + } + + str = talloc_strndup(mem_ctx, + res[0]->elements[0].values[0].data, + res[0]->elements[0].values[0].length); + + ldb_search_free(sam_db, res); + + return str; +} + + +/* + search the sam for multipe records each giving a single string attribute + return the number of matches, or -1 on error +*/ +int samdb_search_string_multiple(TALLOC_CTX *mem_ctx, + char ***strs, + const char *attr_name, + const char *format, ...) +{ + va_list ap; + int count, i; + const char * const attrs[2] = { attr_name, NULL }; + struct ldb_message **res = NULL; + + va_start(ap, format); + count = samdb_search_v(&res, attrs, format, ap); + va_end(ap); + + if (count <= 0) { + return count; + } + + /* make sure its single valued */ + for (i=0;inum_elements != 1 || + res[i]->elements[0].num_values != 1 || + res[i]->elements[0].values[0].data == NULL) { + DEBUG(1,("samdb: search for %s %s not single valued\n", + attr_name, format)); + ldb_search_free(sam_db, res); + return -1; + } + } + + *strs = talloc_array_p(mem_ctx, char *, count+1); + if (! *strs) { + ldb_search_free(sam_db, res); + return -1; + } + + for (i=0;ielements[0].values[0].data, + res[i]->elements[0].values[0].length); + } + (*strs)[count] = NULL; + + ldb_search_free(sam_db, res); + + return count; +} + diff --git a/source4/script/provision.pl b/source4/script/provision.pl new file mode 100755 index 0000000000..e927ac13d2 --- /dev/null +++ b/source4/script/provision.pl @@ -0,0 +1,107 @@ +#!/usr/bin/perl -w + +use strict; + +my $hostname = `hostname`; +chomp $hostname; +my $realm = "tridgell.net"; +my $domain = "BLUDOM"; +my $dnsname = "$hostname.$realm"; + +my $basedn = "DC=" . join(",DN=", split(/\./, $dnsname)); + +# return the current NTTIME as an integer +sub nttime() +{ + my $t = time(); + $t += (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60)); + $t *= 1.0e7; + return sprintf("%lld", $t); +} + +# generate a random guid. Not a good algorithm. +sub randguid() +{ + my $r1 = int(rand(2**32)); + my $r2 = int(rand(2**16)); + my $r3 = int(rand(2**16)); + my $r4 = int(rand(2**16)); + my $r5 = int(rand(2**32)); + return sprintf("%08x-%04x-%04x-%04x-%08x", $r1, $r2, $r3, $r4, $r5); +} + +sub randsid() +{ + return sprintf("S-1-5-21-%d-%d-%d", + int(rand(10**8)), int(rand(10**8)), int(rand(10**8))); +} + +####################### +# substitute a single variable +sub substitute($) +{ + my $var = shift; + + if ($var eq "BASEDN") { + return $basedn; + } + + if ($var eq "DOMAINSID") { + return randsid(); + } + + if ($var eq "DOMAIN") { + return $domain; + } + + if ($var eq "HOSTNAME") { + return $hostname; + } + + if ($var eq "DNSNAME") { + return $dnsname; + } + + if ($var eq "LDAPTIME") { + return "20040408072022.0Z"; + } + + if ($var eq "NEWGUID") { + return randguid(); + } + + if ($var eq "NTTIME") { + return "" . nttime(); + } + + die "ERROR: Uknown substitution variable $var\n"; +} + +##################################################################### +# read a file into a string +sub FileLoad($) +{ + my($filename) = shift; + local(*INPUTFILE); + open(INPUTFILE, $filename) || return undef; + my($saved_delim) = $/; + undef $/; + my($data) = ; + close(INPUTFILE); + $/ = $saved_delim; + return $data; +} + + +my $data = FileLoad("provision.ldif") || die "Unable to load provision.ldif\n"; + +my $res = ""; + +while ($data =~ /(.*?)\$\{(\w*)\}(.*)/s) { + my $sub = substitute($2); + $res .= "$1$sub"; + $data = $3; +} + +print $res . $data; + -- cgit