[PATCH] Universal groups support (first iteration)

Alexander Bokovoy a.bokovoy at sam-solutions.net
Sat Jan 5 11:00:06 GMT 2002


Greetings!

You'll find attached 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.

The code expects that somebody else (smbd and winbindd in currently)
opens netlogon_unigrp.tdb on startup and closes it before shutdown. This
is because we can't open same TDB multiple times in the same process.

There are three places in Samba code that call cli_save_universal_groups()
for storing universal groups for user:

1. source/auth/auth_domain.c:domain_client_validate()
2. source/nsswitch/winbindd_pam.c:winbindd_pam_auth()
3. source/nsswitch/winbindd_pam.c:winbindd_pam_auth_crap()

Similar code will need to be added into ADS support when KRB5 PAC will be
decoded.

Universal groups fetching is done currently only in
source/nsswitch/winbindd_rpc.c:lookup_usergroups(). Once KRB5 PAC work
will be finished, similar code needs to be added to
source/nsswitch/winbindd_ads.c:lookup_usergroups().

The code also includes fix for accidently not closed winbindd_idmap.tdb
handle in source/nsswitch/winbindd_idmap.c.

-- 
/ Alexander Bokovoy
$ cat /proc/identity >~/.signature
  `Senior software developer and analyst for SaM-Solutions Ltd.`
---
Nov 21 20:58:58 alconost kernel: VFS: Busy inodes after unmount. 
		    Self-destruct in 5 seconds.  Have a nice day...
-------------- next part --------------
diff -urk.original samba-3.0/source/Makefile.in.original samba-3.0/source/Makefile.in
--- samba-3.0/source/Makefile.in.original	Sat Jan  5 12:01:12 2002
+++ samba-3.0/source/Makefile.in	Sat Jan  5 19:58:17 2002
@@ -199,9 +199,11 @@
 
 PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o
 
+UNIGRP_OBJ = lib/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_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 -urk.original samba-3.0/source/auth/auth_domain.c.original samba-3.0/source/auth/auth_domain.c
--- samba-3.0/source/auth/auth_domain.c.original	Sat Jan  5 12:01:14 2002
+++ samba-3.0/source/auth/auth_domain.c	Sat Jan  5 18:41:33 2002
@@ -244,6 +244,7 @@
 	struct cli_state *cli;
 	NTSTATUS nt_status;
 	struct passwd *pass;
+	extern TDB_CONTEXT *netlogon_unigrp_tdb;
 
 	/*
 	 * At this point, smb_apasswd points to the lanman response to
@@ -352,6 +353,8 @@
 			sid_copy(&ptok->user_sids[i], &domain_sid);
 			sid_append_rid(&ptok->user_sids[i], info3.gids[i].g_rid);
 		}
+
+		cli_store_universal_groups(&info3, netlogon_unigrp_tdb);
 	}
 
 #if 0
diff -urk.original samba-3.0/source/lib/netlogon_unigrp.c.original samba-3.0/source/lib/netlogon_unigrp.c
--- samba-3.0/source/lib/netlogon_unigrp.c.original	Sat Jan  5 18:42:06 2002
+++ samba-3.0/source/lib/netlogon_unigrp.c	Sat Jan  5 17:39:18 2002
@@ -0,0 +1,85 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 3.0
+   Universal groups helpers
+   Copyright (C) Alexander Bokovoy                    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.
+*/
+
+#include "includes.h"
+
+/*
+    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 cli_store_universal_groups(NET_USER_INFO_3 *user, TDB_CONTEXT *tdb)
+{
+        TALLOC_CTX *mem_ctx = talloc_init();
+	TDB_DATA key,data;
+        fstring keystr;
+        int i;
+	if (mem_ctx && tdb) { 
+			slprintf(keystr, sizeof(keystr), "%s/%d", 
+				sid_string_static(&user->dom_sid.sid), user->user_rid);
+			key.dptr = keystr;
+			key.dsize = strlen(keystr) + 1;
+			data.dsize = (user->num_groups2+1)*sizeof(uint32);
+			data.dptr = talloc(mem_ctx, data.dsize);
+			((uint32*)data.dptr)[0] = user->num_groups2;
+			for(i=1; i<=user->num_groups2; i++) {
+			    ((uint32*)data.dptr)[i] = user->gids[i-1].g_rid;
+			}
+			tdb_store(tdb, key, data, TDB_REPLACE);
+			talloc_destroy(mem_ctx);
+		
+	}
+	
+}
+
+/*
+    Fetch universal groups info from given 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* cli_fetch_universal_groups(DOM_SID *domain, uint32 user_rid, TDB_CONTEXT *tdb,
+				    TALLOC_CTX *mem_ctx, uint32 *num_groups)
+{
+	TDB_DATA key,data;
+	fstring keystr;
+	uint32 *groups;
+	
+	if (!domain) return NULL;
+	if (mem_ctx && tdb) {
+			slprintf(keystr, sizeof(keystr), "%s/%d", 
+				sid_string_static(domain), user_rid);
+			key.dptr = keystr;
+			key.dsize = strlen(keystr) + 1;
+			data = tdb_fetch(tdb, key);
+			if (!data.dptr) return NULL;
+			*num_groups = ((uint32*)data.dptr)[0];
+			
+			groups = talloc_memdup(mem_ctx, &((uint32*)data.dptr)[1], 
+						(*num_groups)*sizeof(uint32));
+			SAFE_FREE(data.dptr);
+			return groups;
+	
+	}
+	return NULL;
+}
diff -urk.original samba-3.0/source/nsswitch/winbindd.c.original samba-3.0/source/nsswitch/winbindd.c
--- samba-3.0/source/nsswitch/winbindd.c.original	Sun Dec 30 19:12:40 2001
+++ samba-3.0/source/nsswitch/winbindd.c	Sat Jan  5 19:23:15 2002
@@ -28,6 +28,7 @@
 struct winbindd_cli_state *client_list;
 static int num_clients;
 BOOL opt_nocache;
+TDB_CONTEXT * netlogon_unigrp_tdb;
 
 /* Reload configuration */
 
@@ -851,6 +852,10 @@
 	if (!winbindd_idmap_init())
 		return 1;
 
+	if(!(netlogon_unigrp_tdb = tdb_open_log(lock_path("netlogon_unigrp.tdb"), 0,
+            				        TDB_NOLOCK, O_RDWR | O_CREAT, 0600)))
+		return 1;
+		
 	/* Unblock all signals we are interested in as they may have been
 	   blocked by the parent process. */
 
@@ -882,5 +887,13 @@
 
 	process_loop(accept_sock);
 
+	/* Shutdown opened database connections */
+	
+	winbindd_idmap_done();
+
+	if(netlogon_unigrp_tdb) {
+	    tdb_close(netlogon_unigrp_tdb);
+	}
+	
 	return 0;
 }
diff -urk.original samba-3.0/source/nsswitch/winbindd_idmap.c.original samba-3.0/source/nsswitch/winbindd_idmap.c
--- samba-3.0/source/nsswitch/winbindd_idmap.c.original	Thu Nov 15 18:41:36 2001
+++ samba-3.0/source/nsswitch/winbindd_idmap.c	Sat Jan  5 19:21:55 2002
@@ -240,6 +240,14 @@
     return True;   
 }
 
+/* Shutdown idmap database */
+void winbindd_idmap_done(void)
+{
+    if(idmap_tdb) {
+	tdb_close(idmap_tdb);
+    }
+}
+
 /* Dump status information to log file.  Display different stuff based on
    the debug level:
 
diff -urk.original samba-3.0/source/nsswitch/winbindd_pam.c.original samba-3.0/source/nsswitch/winbindd_pam.c
--- samba-3.0/source/nsswitch/winbindd_pam.c.original	Sat Jan  5 18:52:16 2002
+++ samba-3.0/source/nsswitch/winbindd_pam.c	Sat Jan  5 18:50:41 2002
@@ -25,6 +25,8 @@
 
 #include "winbindd.h"
 
+extern TDB_CONTEXT *netlogon_unigrp_tdb;
+
 /* Return a password structure from a username.  */
 
 enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) 
@@ -105,6 +107,7 @@
 						lm_resp, nt_resp, 
 						&info3);
         
+	cli_store_universal_groups(&info3, netlogon_unigrp_tdb);
 done:
 	data_blob_free(&lm_resp);
 	data_blob_free(&nt_resp);
@@ -176,6 +179,7 @@
 						lm_resp, nt_resp, 
 						&info3);
         
+	cli_store_universal_groups(&info3, netlogon_unigrp_tdb);
 done:
 	talloc_destroy(mem_ctx);
 
diff -urk.original samba-3.0/source/nsswitch/winbindd_rpc.c.original samba-3.0/source/nsswitch/winbindd_rpc.c
--- samba-3.0/source/nsswitch/winbindd_rpc.c.original	Tue Dec 11 18:51:41 2001
+++ samba-3.0/source/nsswitch/winbindd_rpc.c	Sat Jan  5 18:56:34 2002
@@ -298,8 +298,19 @@
 	BOOL got_dom_pol = False, got_user_pol = False;
 	DOM_GID *user_groups;
 	int i;
+	extern TDB_CONTEXT *netlogon_unigrp_tdb;
 
 	*num_groups = 0;
+
+	/* First try cached universal groups from logon */
+	*user_gids = cli_fetch_universal_groups(&domain->sid, user_rid,  netlogon_unigrp_tdb, 
+						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)))
diff -urk.original samba-3.0/source/smbd/server.c.original samba-3.0/source/smbd/server.c
--- samba-3.0/source/smbd/server.c.original	Sat Jan  5 18:53:02 2002
+++ samba-3.0/source/smbd/server.c	Sat Jan  5 19:27:05 2002
@@ -21,6 +21,8 @@
 
 #include "includes.h"
 
+TDB_CONTEXT *netlogon_unigrp_tdb;
+
 extern fstring global_myworkgroup;
 extern pstring global_myname;
 
@@ -880,7 +882,16 @@
 		exit(1);
 	}
 
+	if(!(netlogon_unigrp_tdb = tdb_open_log(lock_path("netlogon_unigrp.tdb"), 0,
+            				        TDB_NOLOCK, O_RDWR | O_CREAT, 0600))) {
+		exit(1);
+	}
+
 	smbd_process();
+	
+	if(netlogon_unigrp_tdb) {
+	    tdb_close(netlogon_unigrp_tdb);
+	}
 	
 	exit_server("normal exit");
 	return(0);


More information about the samba-technical mailing list