r17463: A bit of cleanup work:
[jra/samba/.git] / source3 / torture / local-groupmap.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Run some local tests for group mapping
4    Copyright (C) Volker Lendecke 2006
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 #define CHECK_STATUS(_status, _expected) do { \
24         if (!NT_STATUS_EQUAL(_status, _expected)) { \
25                 printf("(%d) Incorrect status %s - should be %s\n", \
26                        __LINE__, nt_errstr(status), nt_errstr(_expected)); \
27                 goto fail; \
28         }} while (0)
29
30 static NTSTATUS create_v2_mapping(struct tdb_context *tdb,
31                                   const char *sid, gid_t gid,
32                                   enum SID_NAME_USE type,
33                                   const char *nt_name,
34                                   const char *comment)
35 {
36         TDB_DATA key, data;
37         NTSTATUS status;
38
39         ZERO_STRUCT(data);
40
41         if (asprintf(&key.dptr, "UNIXGROUP/%s", sid) < 0) {
42                 d_fprintf(stderr, "(%s) asprintf failed\n",
43                           __location__);
44                 return NT_STATUS_NO_MEMORY;
45         }
46         key.dsize = strlen(key.dptr)+1;
47         
48         if (!tdb_pack_append(NULL, &data.dptr, &data.dsize, "ddff",
49                              (uint32)gid, (uint32)type, nt_name, comment)) {
50                 d_fprintf(stderr, "(%s) tdb_pack_append failed\n",
51                           __location__);
52                 SAFE_FREE(key.dptr);
53                 return NT_STATUS_NO_MEMORY;
54         }
55
56         if (tdb_store(tdb, key, data, TDB_INSERT) < 0) {
57                 status = map_ntstatus_from_tdb(tdb);
58                 d_fprintf(stderr, "(%s) tdb_store failed: %s\n", __location__,
59                           nt_errstr(status));
60                 SAFE_FREE(key.dptr);
61                 TALLOC_FREE(data.dptr);
62                 return status;
63         }
64
65         SAFE_FREE(key.dptr);
66         TALLOC_FREE(data.dptr);
67         return NT_STATUS_OK;
68 }
69
70 #define NUM_ENTRIES (50)
71
72 static NTSTATUS create_v2_db(BOOL invalid)
73 {
74         struct tdb_context *tdb;
75         NTSTATUS status;
76         int i;
77
78         tdb = tdb_open_log(lock_path("group_mapping.tdb"), 0, TDB_DEFAULT,
79                            O_RDWR|O_CREAT, 0600);
80         if (tdb == NULL) {
81                 d_fprintf(stderr, "(%s) tdb_open_log failed: %s\n",
82                           __location__, strerror(errno));
83                 status = map_nt_error_from_unix(errno);
84                 goto fail;
85         }
86
87         /* Empty the database */
88         tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
89
90         if (tdb_store_int32(tdb, "INFO/version", 2) < 0) {
91                 status = map_ntstatus_from_tdb(tdb);
92                 d_fprintf(stderr, "(%s) tdb_store_uint32 failed: %s\n",
93                           __location__, nt_errstr(status));
94                 goto fail;
95         }
96
97         for (i=1000; i<1000+NUM_ENTRIES; i++) {
98                 char *sid, *name;
99                 if (asprintf(&sid, "S-1-5-21-744032650-3806004166-77016029-%d",
100                              i) < 0) {
101                         d_fprintf(stderr, "(%s) asprintf failed\n",
102                                   __location__);
103                         goto fail;
104                 }
105                 if (asprintf(&name, "Unix group %d", i) < 0) {
106                         d_fprintf(stderr, "(%s) asprintf failed\n",
107                                   __location__);
108                         SAFE_FREE(sid);
109                         goto fail;
110                 }
111                 status = create_v2_mapping(tdb, sid, (gid_t)i,
112                                            SID_NAME_DOM_GRP, name, name);
113                 SAFE_FREE(sid);
114                 SAFE_FREE(name);
115                 CHECK_STATUS(status, NT_STATUS_OK);
116         }
117         status = create_v2_mapping(tdb, "S-1-5-32-544", 10000,
118                                    SID_NAME_ALIAS, "Administrators",
119                                    "Machine Admins");
120         CHECK_STATUS(status, NT_STATUS_OK);
121         status = create_v2_mapping(tdb, "S-1-5-32-545", 10001,
122                                    SID_NAME_ALIAS, "Users", "Machine Users");
123         CHECK_STATUS(status, NT_STATUS_OK);
124
125         if (invalid) {
126                 /* Map 10001 to two different SIDs */
127                 status = create_v2_mapping(tdb, "S-1-5-32-999", 10001,
128                                            SID_NAME_ALIAS, "Overlapping",
129                                            "Invalid mapping");
130                 CHECK_STATUS(status, NT_STATUS_OK);
131         }
132
133         status = create_v2_mapping(tdb, "S-1-5-32-546", -1,
134                                    SID_NAME_ALIAS, "notthere", "To remove");
135         CHECK_STATUS(status, NT_STATUS_OK);
136
137         status = NT_STATUS_OK;
138  fail:
139         if (tdb != NULL) {
140                 tdb_close(tdb);
141         }
142         return status;
143 }
144
145 static BOOL groupmap_diff(const GROUP_MAP *m1, const GROUP_MAP *m2)
146 {
147         return ((sid_compare(&m1->sid, &m2->sid) != 0) ||
148                 (m1->gid != m2->gid) ||
149                 (m1->sid_name_use != m2->sid_name_use) ||
150                 (strcmp(m1->nt_name, m2->nt_name) != 0) ||
151                 (strcmp(m1->comment, m2->comment) != 0));
152 }
153
154 #undef GROUPDB_V3
155
156 BOOL run_local_groupmap(int dummy)
157 {
158         TALLOC_CTX *mem_ctx;
159         BOOL ret = False;
160         NTSTATUS status;
161         GROUP_MAP *maps = NULL;
162         size_t num_maps = 0;
163
164         mem_ctx = talloc_init("run_local_groupmap");
165         if (mem_ctx == NULL) {
166                 d_fprintf(stderr, "(%s) talloc_init failed\n",
167                           __location__);
168                 return False;
169         }
170
171 #ifdef GROUPDB_V3
172         status = create_v2_db(True);
173         if (!NT_STATUS_IS_OK(status)) {
174                 goto fail;
175         }
176
177         {
178                 GROUP_MAP map;
179                 if (pdb_getgrgid(&map, 10001)) {
180                         d_fprintf(stderr, "(%s) upgrading an invalid group db "
181                                   "worked\n", __location__);
182                         goto fail;
183                 }
184         }
185 #endif
186
187         status = create_v2_db(False);
188         if (!NT_STATUS_IS_OK(status)) {
189                 goto fail;
190         }
191
192         /* This tests upgrading the database, as well as listing */
193
194         if (!pdb_enum_group_mapping(NULL, SID_NAME_UNKNOWN, &maps, &num_maps,
195                                     False)) {
196                 d_fprintf(stderr, "(%s) pdb_enum_group_mapping failed\n",
197                           __location__);
198                 goto fail;
199         }
200
201         if (num_maps != NUM_ENTRIES+2) {
202                 d_fprintf(stderr, "(%s) expected %d entries, got %d\n",
203                           __location__, NUM_ENTRIES+2, num_maps);
204                 goto fail;
205         }
206
207         /* See if getgrsid, getgrgid and getgrnam find the same entry */
208
209         {
210                 DOM_SID sid;
211                 GROUP_MAP map, map1;
212                 string_to_sid(&sid, "S-1-5-32-545");
213
214                 ZERO_STRUCT(map);
215                 status = pdb_getgrsid(&map, &sid);
216                 if (!NT_STATUS_IS_OK(status)) {
217                         d_fprintf(stderr, "(%s) pdb_getgrsid failed: %s\n",
218                                   __location__, nt_errstr(status));
219                         goto fail;
220                 }
221
222                 ZERO_STRUCT(map1);
223                 status = pdb_getgrgid(&map1, map.gid);
224                 if (!NT_STATUS_IS_OK(status)) {
225                         d_fprintf(stderr, "(%s) pdb_getgrgid failed: %s\n",
226                                   __location__, nt_errstr(status));
227                         goto fail;
228                 }
229
230                 if (groupmap_diff(&map1, &map)) {
231                         d_fprintf(stderr, "(%s) getgrsid/getgrgid disagree\n",
232                                   __location__);
233                         goto fail;
234                 }
235                         
236                 ZERO_STRUCT(map1);
237                 status = pdb_getgrnam(&map1, map.nt_name);
238                 if (!NT_STATUS_IS_OK(status)) {
239                         d_fprintf(stderr, "(%s) pdb_getgrnam failed: %s\n",
240                                   __location__, nt_errstr(status));
241                         goto fail;
242                 }
243
244                 if (groupmap_diff(&map1, &map)) {
245                         d_fprintf(stderr, "(%s) getgrsid/getgrnam disagree\n",
246                                   __location__);
247                         goto fail;
248                 }
249         }
250
251         /* See if pdb_delete_group_mapping_entry works */
252
253         {
254                 DOM_SID sid;
255                 GROUP_MAP map, map1;
256                 string_to_sid(&sid, "S-1-5-32-545");
257
258                 status = pdb_getgrsid(&map, &sid);
259                 if (!NT_STATUS_IS_OK(status)) {
260                         d_fprintf(stderr, "(%s) did not find S-1-5-32-545: "
261                                   "%s\n", __location__, nt_errstr(status));
262                         goto fail;
263                 }
264
265                 status = pdb_delete_group_mapping_entry(sid);
266                 CHECK_STATUS(status, NT_STATUS_OK);
267                 status = pdb_delete_group_mapping_entry(sid);
268 #ifdef GROUPDB_V3
269                 CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
270 #else
271                 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
272 #endif
273
274                 if (NT_STATUS_IS_OK(pdb_getgrsid(&map1, &sid))) {
275                         d_fprintf(stderr, "(%s) getgrsid found deleted "
276                                   "entry\n", __location__);
277                         goto fail;
278                 }
279
280                 if (NT_STATUS_IS_OK(pdb_getgrgid(&map1, map.gid))) {
281                         d_fprintf(stderr, "(%s) getgrgid found deleted "
282                                   "entry\n", __location__);
283                         goto fail;
284                 }
285
286                 if (NT_STATUS_IS_OK(pdb_getgrnam(&map1, map.nt_name))) {
287                         d_fprintf(stderr, "(%s) getgrnam found deleted "
288                                   "entry\n", __location__);
289                         goto fail;
290                 }
291                 
292         }
293
294         /* See if pdb_update_group_mapping_entry works */
295
296         {
297                 DOM_SID sid;
298                 gid_t oldgid;
299                 GROUP_MAP map, map1;
300                 string_to_sid(&sid, "S-1-5-32-544");
301
302                 status = pdb_getgrsid(&map, &sid);
303                 if (!NT_STATUS_IS_OK(status)) {
304                         d_fprintf(stderr, "(%s) did not find S-1-5-32-544: "
305                                   "%s\n", __location__, nt_errstr(status));
306                         goto fail;
307                 }
308
309                 oldgid = map.gid;
310                 map.gid = 4711;
311
312                 status = pdb_update_group_mapping_entry(&map);
313                 CHECK_STATUS(status, NT_STATUS_OK);
314
315                 if (NT_STATUS_IS_OK(pdb_getgrgid(&map1, oldgid))) {
316                         d_fprintf(stderr, "(%s) getgrgid found outdated "
317                                   "entry\n", __location__);
318                         goto fail;
319                 }
320
321                 /* Change to an existing entry, see "create_db_v2" */
322
323                 map.gid = 1000;
324                 status = pdb_update_group_mapping_entry(&map);
325 #ifdef GROUPDB_V3
326                 CHECK_STATUS(status, NT_STATUS_OBJECTID_EXISTS);
327                 if (!pdb_getgrgid(&map1, 4711)) {
328                         d_fprintf(stderr, "(%s) update_group changed entry "
329                                   "upon failure\n", __location__);
330                         goto fail;
331                 }
332 #else
333                 CHECK_STATUS(status, NT_STATUS_OK);
334 #endif
335         }
336
337         ret = True;
338  fail:
339         if (maps != NULL) {
340                 SAFE_FREE(maps);
341         }
342         TALLOC_FREE(mem_ctx);
343         return ret;
344 }
345