Lots of fixes for error paths where tdb_fetch() data need freeing.
[vlendec/samba-autobuild/.git] / source3 / libsmb / netlogon_unigrp.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Universal groups helpers
4    Copyright (C) Alexander Bokovoy                    2002.
5    Copyright (C) Andrew Bartlett                      2002.
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21    This work was sponsored by Optifacio Software Services, Inc.
22 */
23
24 #include "includes.h"
25
26 /*
27     Handle for netlogon_unigrp.tdb database. It is used internally
28     in cli_store_uni_groups_*() and cli_fetch_uni_groups()
29     and is initialized on first call to cli_store_uni_groups_*()
30 */
31 static TDB_CONTEXT *netlogon_unigrp_tdb = NULL;
32
33 /*
34     Store universal groups info into netlogon_unigrp.tdb for
35     later usage. We use 'domain_SID/user_rid' as key and
36     array of uint32 where array[0] is number of elements
37     and elements are array[1] ... array[array[0]]
38 */
39
40 BOOL uni_group_cache_init(void)
41 {
42         if (!netlogon_unigrp_tdb) {
43                 netlogon_unigrp_tdb = tdb_open_log(lock_path("netlogon_unigrp.tdb"), 0,
44                                                    TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
45         }
46
47         return (netlogon_unigrp_tdb != NULL);
48 }
49
50 void uni_group_cache_store_netlogon(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user)
51 {
52         TDB_DATA key,data;
53         fstring keystr;
54         int i;
55
56         if (!uni_group_cache_init()) {
57                 DEBUG(0,("uni_group_cache_store_netlogon: cannot open netlogon_unigrp.tdb for write!\n"));
58                 return;
59         }
60
61         /* Prepare key as DOMAIN-SID/USER-RID string */
62         slprintf(keystr, sizeof(keystr), "%s/%d", 
63                  sid_string_static(&user->dom_sid.sid), user->user_rid);
64         key.dptr = keystr;
65         key.dsize = strlen(keystr) + 1;
66         
67         /* Prepare data */
68         data.dsize = (user->num_groups2+1)*sizeof(uint32);
69         data.dptr = talloc(mem_ctx, data.dsize);
70         if(!data.dptr) {
71                 DEBUG(0,("uni_group_cache_store_netlogon: cannot allocate memory!\n"));
72                 talloc_destroy(mem_ctx);
73                 return;
74         }
75         
76         /* Store data in byteorder-independent format */
77         SIVAL(&((uint32*)data.dptr)[0],0,user->num_groups2);
78         for(i=1; i<=user->num_groups2; i++) {
79                 SIVAL(&((uint32*)data.dptr)[i],0,user->gids[i-1].g_rid);
80         }
81         tdb_store(netlogon_unigrp_tdb, key, data, TDB_REPLACE); 
82 }
83
84 /*
85     Fetch universal groups info from netlogon_unigrp.tdb for given
86     domain sid and user rid and allocate it using given mem_ctx.
87     Universal groups are returned as array of uint32 elements 
88     and elements are array[0] ... array[num_elements-1]
89     
90 */
91 uint32* uni_group_cache_fetch(DOM_SID *domain, uint32 user_rid,
92                               TALLOC_CTX *mem_ctx, uint32 *num_groups)
93 {
94         TDB_DATA key,data;
95         fstring keystr;
96         uint32 *groups;
97         uint32 i;
98         uint32 group_count;
99         
100         if (!domain) {
101                 DEBUG(1,("uni_group_cache_fetch: expected non-null domain sid\n"));
102                 return NULL;
103         }
104         if (!mem_ctx) {
105                 DEBUG(1,("uni_group_cache_fetch: expected non-null memory context\n"));
106                 return NULL;
107         }
108         if (!num_groups) {
109                 DEBUG(1,("uni_group_cache_fetch: expected non-null num_groups\n"));
110                 return NULL;
111         }
112         if (!netlogon_unigrp_tdb) {
113                 netlogon_unigrp_tdb = tdb_open_log(lock_path("netlogon_unigrp.tdb"), 0,
114                                                     TDB_DEFAULT, O_RDWR, 0644);
115         }
116         if (!netlogon_unigrp_tdb) {
117                 DEBUG(5,("uni_group_cache_fetch: cannot open netlogon_unigrp.tdb for read - normal if not created yet\n"));
118                 return NULL;
119         }
120         
121         *num_groups = 0;
122         
123         /* Fetch universal groups */
124         slprintf(keystr, sizeof(keystr), "%s/%d", 
125                  sid_string_static(domain), user_rid);
126         key.dptr = keystr;
127         key.dsize = strlen(keystr) + 1;
128         data = tdb_fetch(netlogon_unigrp_tdb, key);
129         
130         /* There is no cached universal groups in netlogon_unigrp.tdb */
131         /* for this user. */
132         if (!data.dptr)
133                 return NULL;
134         
135         /* Transfer data to receiver's memory context */
136         group_count = IVAL(&((uint32*)data.dptr)[0],0);
137         groups = talloc(mem_ctx, (group_count)*sizeof(uint32));
138         if (groups) {
139                 for(i=0; i<group_count; i++) {
140                         groups[i] = IVAL(&((uint32*)data.dptr)[i+1],0);
141                 }
142                 
143         } else {
144                 DEBUG(1,("uni_group_cache_fetch: cannot allocate uni groups in receiver's memory context\n"));
145         }
146         SAFE_FREE(data.dptr);
147         *num_groups = group_count;
148         return groups;
149 }
150
151 /* Shutdown netlogon_unigrp database */
152 void uni_group_cache_shutdown(void)
153 {
154         if(netlogon_unigrp_tdb) {
155                 tdb_close(netlogon_unigrp_tdb);
156         }
157 }
158