Project

General

Profile

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

acl setting binary - Andrew Bartlett, 2013-04-04 02:02 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)
27
{
28
	gid_t gids_found[NGROUPS_MAX + 1];
29
	gid_t gids_saved[NGROUPS_MAX + 1];
30
	gid_t gids_set[NGROUPS_MAX + 1];
31
	int ret, ngrp_saved, ngrp_found;
32
	int i, j, num_groups = 0;
33
	const int gid = 65536;
34
	const int uid = 2000;
35
	
36
	ngrp_saved = getgroups(NGROUPS_MAX, gids_saved);
37
	if (ngrp_saved == -1) {
38
		return -1;
39
	}
40

    
41
	umask(002);
42

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

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

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

    
128
	for (j=0; j<num_groups; j++) {
129
		if (gids_found[j] != gids_set[j]) {
130
			err(1, "got gid %d, expected %d at idx %d", gids_found[j], gids_set[j], j);
131
		}
132
	}
133

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

    
146
	return ret;
147
}
148

    
149
int main(int argc, char *argv[])
150
{
151
	int ret;
152
	
153
	int test_num_groups = atoi(argv[1]);
154

    
155
	ret = testgroups(test_num_groups);
156

    
157
	return 0;
158
}
(1-1/7)