summaryrefslogtreecommitdiff
path: root/source4/lib/samba3/group.c
blob: cf76bddffe3b8be5406b0753e0ecf46116d13f8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* 
 *  Unix SMB/CIFS implementation.
 *  RPC Pipe client / server routines
 *  Copyright (C) Andrew Tridgell              1992-2000,
 *  Copyright (C) Jean François Micouleau      1998-2001.
 *  
 *  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"
#include "system/iconv.h"
#include "lib/samba3/samba3.h"
#include "lib/tdb/include/tdbutil.h"
#include "system/filesys.h"

#define DATABASE_VERSION_V1 1 /* native byte format. */
#define DATABASE_VERSION_V2 2 /* le format. */

#define GROUP_PREFIX "UNIXGROUP/"

/* Alias memberships are stored reverse, as memberships. The performance
 * critical operation is to determine the aliases a SID is member of, not
 * listing alias members. So we store a list of alias SIDs a SID is member of
 * hanging of the member as key.
 */
#define MEMBEROF_PREFIX "MEMBEROF/"

/****************************************************************************
 Open the group mapping tdb.
****************************************************************************/
NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_groupdb *db)
{
	int32_t vers_id;
	TDB_DATA kbuf, dbuf, newkey;
	int ret;
	TDB_CONTEXT *tdb; 

	tdb = tdb_open(file, 0, TDB_DEFAULT, O_RDONLY, 0600);
	if (!tdb) {
		DEBUG(0,("Failed to open group mapping database\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Cope with byte-reversed older versions of the db. */
	vers_id = tdb_fetch_int32(tdb, "INFO/version");
	if ((vers_id == DATABASE_VERSION_V1) || (IREV(vers_id) == DATABASE_VERSION_V1)) {
		/* Written on a bigendian machine with old fetch_int code. Save as le. */
		vers_id = DATABASE_VERSION_V2;
	}

	if (vers_id != DATABASE_VERSION_V2) {
		DEBUG(0, ("Group database version mismatch: %d\n", vers_id));
		return NT_STATUS_UNSUCCESSFUL;
	}

	db->groupmappings = NULL;
	db->groupmap_count = 0;
	db->aliases = NULL;
	db->alias_count = 0;

	for (kbuf = tdb_firstkey(tdb); 
	     kbuf.dptr; 
	     newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
		struct samba3_groupmapping map;

		if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) == 0)
		{
			dbuf = tdb_fetch(tdb, kbuf);
			if (!dbuf.dptr)
				continue;

			ZERO_STRUCT(map);

			map.sid = dom_sid_parse_talloc(ctx, kbuf.dptr+strlen(GROUP_PREFIX));

			ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "dd",
							 &map.gid, &map.sid_name_use);
			
			if ( ret == -1 ) {
				DEBUG(3,("enum_group_mapping: tdb_unpack failure\n"));
				continue;
			}

			map.nt_name = talloc_strdup(ctx, dbuf.dptr+ret);
			map.comment = talloc_strdup(ctx, dbuf.dptr+ret+strlen(map.nt_name));

			db->groupmappings = talloc_realloc(ctx, db->groupmappings, struct samba3_groupmapping, db->groupmap_count+1);

			if (!db->groupmappings) 
				return NT_STATUS_NO_MEMORY;

			db->groupmappings[db->groupmap_count] = map;

			db->groupmap_count++;
		} else if (strncmp(kbuf.dptr, MEMBEROF_PREFIX, strlen(MEMBEROF_PREFIX)) == 0)
		{
			struct samba3_alias alias;
			const char **member_strlist;
			int i;

			dbuf = tdb_fetch(tdb, kbuf);
			if (!dbuf.dptr)
				continue;

			alias.sid = dom_sid_parse_talloc(ctx, kbuf.dptr+strlen(MEMBEROF_PREFIX));
			alias.member_count = 0;
			alias.members = NULL;

			member_strlist = str_list_make_shell(ctx, dbuf.dptr, " ");

			for (i = 0; member_strlist[i]; i++) {
				alias.members = talloc_realloc(ctx, alias.members, struct dom_sid *, alias.member_count+1);
				alias.members[alias.member_count] = dom_sid_parse_talloc(ctx, member_strlist[i]);
				alias.member_count++;
			}

			talloc_free(member_strlist);

			db->aliases = talloc_realloc(ctx, db->aliases, struct samba3_alias, db->alias_count+1);
			db->aliases[db->alias_count] = alias;
			db->alias_count++;
		}
	}

	tdb_close(tdb);

	return NT_STATUS_OK;
}