Project

General

Profile

Bug #3691 » testgroups-match-samba-acl4.c

Demonstration of reverse sorted GID values (fails on both OpenIndiana and our NAS) - Andrew Bartlett, 2013-04-09 06:06 AM

 
1
#define NGROUPS_MAX 1000
2

    
3
#include <stdio.h>
4
#include <unistd.h>
5
#include <stdlib.h>
6
#include <errno.h>
7

    
8
#include <sys/types.h>
9
#include <string.h>
10
#include <grp.h>
11
#include <pwd.h>
12
#include <err.h>
13
#include <sys/stat.h>
14
#include <sys/acl.h>
15

    
16
/*
17
  This is a *much* faster way of getting the list of groups for a user
18
  without changing the current supplemenrary group list. The old
19
  method user getgrent() which could take 20 minutes on a really big
20
  network with hundeds of thousands of groups and users. The new method
21
  takes a couple of seconds. (tridge@samba.org)
22

    
23
  unfortunately it only works if we are root!
24
  */
25
int
26
testgroups(int test_num_groups, int gid_base)
27
{
28
	gid_t gids_found[NGROUPS_MAX + 1];
29
	gid_t gids_saved[NGROUPS_MAX + 1];
30
	gid_t gids[NGROUPS_MAX + 1];
31
	int ret, ngrp_saved, ngrp_found;
32
	int i, j, num_groups = 0;
33
	const gid_t gid = gid_base;
34
	const uid_t uid = gid_base;
35

    
36
	for (i=test_num_groups -1; i >=0; i--) {
37
		gids[num_groups] = i+gid_base;
38
		num_groups++;
39
	}
40

    
41
	ngrp_saved = getgroups(NGROUPS_MAX, gids_saved);
42
	if (ngrp_saved == -1) {
43
		return -1;
44
	}
45

    
46
	umask(002);
47

    
48
	ret = mkdir("test", 0775);
49
	if (ret != 0) {
50
		err(1, "failed to mkdir test");
51
	}
52
		
53
	for (i=0; i < test_num_groups; i++) {
54
		char dirname[20];
55
		char dirname2[20];
56
		ace_t aces[] = {
57
		  {
58
		    .a_who = 0,
59
		    // rwxp-DaARWcCo-
60
		    .a_access_mask = ACE_LIST_DIRECTORY|ACE_WRITE_DATA|ACE_ADD_SUBDIRECTORY|ACE_DELETE_CHILD|ACE_EXECUTE|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|ACE_READ_ACL|ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS|ACE_WRITE_ACL|ACE_WRITE_OWNER,
61
		    .a_flags = ACE_DIRECTORY_INHERIT_ACE|ACE_FILE_INHERIT_ACE,
62
		    .a_type = ACE_ACCESS_ALLOWED_ACE_TYPE
63
		  },
64
		  {
65
		    .a_who = 0,
66
		    // r-x---a-R-c
67
		    .a_access_mask = ACE_LIST_DIRECTORY|ACE_EXECUTE|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|ACE_READ_ACL,
68
		    .a_flags = ACE_DIRECTORY_INHERIT_ACE|ACE_FILE_INHERIT_ACE,
69
		    .a_type = ACE_ACCESS_ALLOWED_ACE_TYPE
70
		  },
71
		  {
72
		    .a_who = gids[i],
73
		    // r-x---a-R-c
74
		    .a_access_mask = ACE_LIST_DIRECTORY|ACE_EXECUTE|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|ACE_READ_ACL,
75
		    .a_flags = ACE_IDENTIFIER_GROUP|ACE_DIRECTORY_INHERIT_ACE|ACE_FILE_INHERIT_ACE,
76
		    .a_type = ACE_ACCESS_ALLOWED_ACE_TYPE
77
		  }
78
		};
79
		snprintf(dirname, sizeof(dirname), "test/%d", gids[i]);
80
		snprintf(dirname2, sizeof(dirname), "test/%d/test", gids[i]);
81
		
82
		ret = mkdir(dirname, 0770);
83
		if (ret != 0) {
84
			err(1, "failed to mkdir %s", dirname);
85
		}
86
		
87
		ret = mkdir(dirname2, 0750);
88
		if (ret != 0) {
89
			err(1, "failed to mkdir %s", dirname2);
90
		}
91
		ret = acl(dirname, ACE_SETACL, sizeof(aces)/sizeof(ace_t), aces);
92
		if (ret != 0) { 
93
		  err(1, "failed to set acl on %s", dirname);
94
		}
95
		ret = chown(dirname2, 0, gids[i]);
96
		if (ret != 0) {
97
			err(1, "failed to chown %s", dirname2);
98
		}
99
	}
100

    
101
	ret = setgroups(test_num_groups, gids);
102
	if (ret != 0) {
103
		err(1, "failed to setgroups %d groups", test_num_groups);
104
	}
105
	ret = setregid(gid, gid);
106
	if (ret != 0) {
107
		err(1, "failed to setregid to %d", gid);
108
	}
109
	ret = setreuid(uid, uid);
110
	if (ret != 0) {
111
		err(1, "failed to setreuid to %d", uid);
112
	}
113
		
114
	ret = getgroups(NGROUPS_MAX, gids_found);
115
	if (ret >= 0) {
116
		ngrp_found = ret;
117
	} else {
118
		err(1, "failed to getgroups");
119
	}
120

    
121
	printf("Got %d groups\n", ngrp_found);
122
	for (i=0;i<ngrp_found;i++) {
123
		printf("%u ", (unsigned)gids_found[i]);
124
	}
125
	printf("\n");
126
	
127
	if (ngrp_found != test_num_groups) {
128
		err(1, "getgroups returned the wrong number of groups");
129
	}
130

    
131
	for (j=0; j<test_num_groups; j++) {
132
		if (gids_found[j] != gids[j]) {
133
			err(1, "got gid %d, expected %d at idx %d", gids_found[j], gids[j], j);
134
		}
135
	}
136

    
137
	for (j=0; j<test_num_groups; j++) {
138
		struct stat st;
139
		char dirname[20];
140
		char dirname2[20];
141
		char shell_dirname2[20];
142
		snprintf(dirname2, sizeof(dirname), "test/%d/test", gids[j]);
143
		ret = stat(dirname2, &st);
144
		if (ret != 0) {
145
			err(1, "failed to stat %s", dirname2);
146
		}
147
	}
148

    
149
	return ret;
150
}
151

    
152
int main(int argc, char *argv[])
153
{
154
	int ret;
155
	
156
	int test_num_groups = atoi(argv[1]);
157
	int gid_base = 65500;
158
	if (argc >= 3) {
159
		gid_base = atoi(argv[2]);
160
	}
161

    
162
	ret = testgroups(test_num_groups, gid_base);
163

    
164
	return 0;
165
}
(7-7/7)