summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2002-01-12 23:57:10 +0000
committerAndrew Bartlett <abartlet@samba.org>2002-01-12 23:57:10 +0000
commite895b9004e57c62d7517198618f9fd788107629e (patch)
treeb369bcf4236a797f059e4ea742b9f3a7059a377b
parentb79fa88b4db3bc88b0a5ae567b19286f64fd113c (diff)
downloadsamba-e895b9004e57c62d7517198618f9fd788107629e.tar.gz
samba-e895b9004e57c62d7517198618f9fd788107629e.tar.bz2
samba-e895b9004e57c62d7517198618f9fd788107629e.zip
Many thanks to Alexander Bokovoy <a.bokovoy@sam-solutions.net>.
This work was sponsored by Optifacio Software Services, Inc. Andrew Bartlett (various e-mails announcements merged into some form of commit message below:) This patch which adds basics of universal groups support into Samba 3. Currently, only Winbind with RPC calls supports this, ADS support requires additional (possibly huge) work on KRB5 PAC. However, basic infrastructure is here. This patch adds: 1. Storing of universal groups for particular user logged into Samba software (smbd/ two winbind-pam methods) into netlogon_unigrp.tdb as array of uint32 supplemental group rids keyed as DOMAIN_SID/USER_RID in tdb. 2. Fetching of unversal groups for given user rid and domain sid from netlogon_unigrp.tdb. Since this is used in both smbd and winbindd, main code is in source/lib/netlogon_uingrp.c. Dependencies are added to AUTH_OBJ as UNIGRP_OBJ and WINBINDD_OBJ as UNIGRP_OBJ. This patch has had a few versions, the final version in particular: Many thanks to Andrew Bartlett for critics and comments, and partly rewritten code. New: - updated fetching code to changed byte order macros - moved functions to proper namespace - optimized memory usage by reusing caller's memory context - enhanced code to more follow Samba coding rules Todo: - proper universal group expiration after timeout (This used to be commit 80c2aefbe7c1aa363dd286a47d50c5d8b4595f43)
-rw-r--r--source3/Makefile.in6
-rw-r--r--source3/auth/auth_domain.c4
-rw-r--r--source3/libsmb/netlogon_unigrp.c152
-rw-r--r--source3/nsswitch/winbindd.c1
-rw-r--r--source3/nsswitch/winbindd_pam.c2
-rw-r--r--source3/nsswitch/winbindd_rpc.c9
-rw-r--r--source3/smbd/server.c1
7 files changed, 173 insertions, 2 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index bf39b8c422..00da4cf74f 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -199,9 +199,11 @@ NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o
PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o
+UNIGRP_OBJ = libsmb/netlogon_unigrp.o
+
AUTH_OBJ = auth/auth.o auth/auth_sam.o auth/auth_server.o auth/auth_domain.o \
auth/auth_rhosts.o auth/auth_unix.o auth/auth_util.o auth/auth_winbind.o \
- auth/auth_builtin.o auth/auth_compat.o $(PLAINTEXT_AUTH_OBJ)
+ auth/auth_builtin.o auth/auth_compat.o $(PLAINTEXT_AUTH_OBJ) $(UNIGRP_OBJ)
SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
@@ -430,7 +432,7 @@ WINBINDD_OBJ = \
$(WINBINDD_OBJ1) $(NOPROTO_OBJ) $(PASSDB_OBJ) \
$(LIBNMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
- $(GROUPDB_OBJ) $(PROFILE_OBJ)
+ $(GROUPDB_OBJ) $(PROFILE_OBJ) $(UNIGRP_OBJ)
WBINFO_OBJ = nsswitch/wbinfo.o libsmb/smbencrypt.o libsmb/smbdes.o \
passdb/secrets.o
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index eba61114d6..6dcf3119ea 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -352,6 +352,10 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
sid_copy(&ptok->user_sids[i], &domain_sid);
sid_append_rid(&ptok->user_sids[i], info3.gids[i].g_rid);
}
+
+ become_root();
+ uni_group_cache_store_netlogon(mem_ctx, &info3);
+ unbecome_root();
}
#if 0
diff --git a/source3/libsmb/netlogon_unigrp.c b/source3/libsmb/netlogon_unigrp.c
new file mode 100644
index 0000000000..317a5bc3d0
--- /dev/null
+++ b/source3/libsmb/netlogon_unigrp.c
@@ -0,0 +1,152 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ Universal groups helpers
+ Copyright (C) Alexander Bokovoy 2002.
+ Copyright (C) Andrew Bartlett 2002.
+
+ 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.
+
+ This work was sponsored by Optifacio Software Services, Inc.
+*/
+
+#include "includes.h"
+
+/*
+ Handle for netlogon_unigrp.tdb database. It is used internally
+ in cli_store_uni_groups_*() and cli_fetch_uni_groups()
+ and is initialized on first call to cli_store_uni_groups_*()
+*/
+static TDB_CONTEXT *netlogon_unigrp_tdb = NULL;
+
+/*
+ Store universal groups info into netlogon_unigrp.tdb for
+ later usage. We use 'domain_SID/user_rid' as key and
+ array of uint32 where array[0] is number of elements
+ and elements are array[1] ... array[array[0]]
+*/
+void uni_group_cache_store_netlogon(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user)
+{
+ TDB_DATA key,data;
+ fstring keystr;
+ int i;
+
+ if (!netlogon_unigrp_tdb) {
+ netlogon_unigrp_tdb = tdb_open_log(lock_path("netlogon_unigrp.tdb"), 0,
+ TDB_NOLOCK, O_RDWR | O_CREAT, 0644);
+ }
+
+ if (!netlogon_unigrp_tdb) {
+ DEBUG(0,("uni_group_cache_store_netlogon: cannot open netlogon_unigrp.tdb for write!\n"));
+ return;
+ }
+
+ /* Prepare key as DOMAIN-SID/USER-RID string */
+ slprintf(keystr, sizeof(keystr), "%s/%d",
+ sid_string_static(&user->dom_sid.sid), user->user_rid);
+ key.dptr = keystr;
+ key.dsize = strlen(keystr) + 1;
+
+ /* Prepare data */
+ data.dsize = (user->num_groups2+1)*sizeof(uint32);
+ data.dptr = talloc(mem_ctx, data.dsize);
+ if(!data.dptr) {
+ DEBUG(0,("uni_group_cache_store_netlogon: cannot allocate memory!\n"));
+ talloc_destroy(mem_ctx);
+ return;
+ }
+
+ /* Store data in byteorder-independent format */
+ SIVAL(&((uint32*)data.dptr)[0],0,user->num_groups2);
+ for(i=1; i<=user->num_groups2; i++) {
+ SIVAL(&((uint32*)data.dptr)[i],0,user->gids[i-1].g_rid);
+ }
+ tdb_store(netlogon_unigrp_tdb, key, data, TDB_REPLACE);
+}
+
+/*
+ Fetch universal groups info from netlogon_unigrp.tdb for given
+ domain sid and user rid and allocate it using given mem_ctx.
+ Universal groups are returned as array of uint32 elements
+ and elements are array[0] ... array[num_elements-1]
+
+*/
+uint32* uni_group_cache_fetch(DOM_SID *domain, uint32 user_rid,
+ TALLOC_CTX *mem_ctx, uint32 *num_groups)
+{
+ TDB_DATA key,data;
+ fstring keystr;
+ uint32 *groups;
+ uint32 i;
+ uint32 group_count;
+
+ if (!domain) {
+ DEBUG(1,("uni_group_cache_fetch: expected non-null domain sid\n"));
+ return NULL;
+ }
+ if (!mem_ctx) {
+ DEBUG(1,("uni_group_cache_fetch: expected non-null memory context\n"));
+ return NULL;
+ }
+ if (!num_groups) {
+ DEBUG(1,("uni_group_cache_fetch: expected non-null num_groups\n"));
+ return NULL;
+ }
+ if (!netlogon_unigrp_tdb) {
+ netlogon_unigrp_tdb = tdb_open_log(lock_path("netlogon_unigrp.tdb"), 0,
+ TDB_NOLOCK, O_RDWR, 0644);
+ }
+ if (!netlogon_unigrp_tdb) {
+ DEBUG(5,("uni_group_cache_fetch: cannot open netlogon_unigrp.tdb for read - normal if not created yet\n"));
+ return NULL;
+ }
+
+ *num_groups = 0;
+
+ /* Fetch universal groups */
+ slprintf(keystr, sizeof(keystr), "%s/%d",
+ sid_string_static(domain), user_rid);
+ key.dptr = keystr;
+ key.dsize = strlen(keystr) + 1;
+ data = tdb_fetch(netlogon_unigrp_tdb, key);
+
+ /* There is no cached universal groups in netlogon_unigrp.tdb */
+ /* for this user. */
+ if (!data.dptr) return NULL;
+
+ /* Transfer data to receiver's memory context */
+ group_count = IVAL(&((uint32*)data.dptr)[0],0);
+ groups = talloc(mem_ctx, (group_count)*sizeof(uint32));
+ if (groups) {
+ for(i=0; i<group_count; i++) {
+ groups[i] = IVAL(&((uint32*)data.dptr)[i+1],0);
+ }
+
+ } else {
+ DEBUG(1,("uni_group_cache_fetch: cannot allocate uni groups in receiver's memory context\n"));
+ }
+ SAFE_FREE(data.dptr);
+ *num_groups = group_count;
+ return groups;
+}
+
+/* Shutdown netlogon_unigrp database */
+void uni_group_cache_shutdown(void)
+{
+ if(netlogon_unigrp_tdb) {
+ tdb_close(netlogon_unigrp_tdb);
+ }
+}
+
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index bd995611cd..1a9eae7afa 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -881,5 +881,6 @@ int main(int argc, char **argv)
process_loop(accept_sock);
+ uni_group_cache_shutdown();
return 0;
}
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 87086586ec..aab1302a94 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -107,6 +107,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
lm_resp, nt_resp,
&info3);
+ uni_group_cache_store_netlogon(mem_ctx, &info3);
done:
cli_shutdown(cli);
@@ -168,6 +169,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
lm_resp, nt_resp,
&info3);
+ uni_group_cache_store_netlogon(mem_ctx, &info3);
done:
talloc_destroy(mem_ctx);
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index 18186b629a..badbd459a7 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -301,6 +301,15 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
*num_groups = 0;
+ /* First try cached universal groups from logon */
+ *user_gids = uni_group_cache_fetch(&domain->sid, user_rid, mem_ctx, num_groups);
+ if((*num_groups > 0) && *user_gids) {
+ return NT_STATUS_OK;
+ } else {
+ *user_gids = NULL;
+ *num_groups = 0;
+ }
+
/* Get sam handle */
if (!(hnd = cm_get_sam_handle(domain->name)))
goto done;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 2f831cdd97..b8e9c2beae 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -884,6 +884,7 @@ static void usage(char *pname)
smbd_process();
+ uni_group_cache_shutdown();
exit_server("normal exit");
return(0);
}