diff options
-rw-r--r-- | source3/Makefile.in | 6 | ||||
-rw-r--r-- | source3/auth/auth_domain.c | 4 | ||||
-rw-r--r-- | source3/libsmb/netlogon_unigrp.c | 152 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.c | 1 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 9 | ||||
-rw-r--r-- | source3/smbd/server.c | 1 |
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); } |