1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2020, Vaisala Oyj.
4  */
5 
6 #include <teeacl.h>
7 
8 #include <errno.h>
9 #include <grp.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 
teeacl_getgr_r_size_max(void)15 static long teeacl_getgr_r_size_max(void)
16 {
17 	long s = sysconf(_SC_GETGR_R_SIZE_MAX);
18 
19 	if (s == -1)
20 		return 1024;
21 	return s;
22 };
23 
teeacl_gid_from_name(gid_t * gid_out,const char * group_name)24 int teeacl_gid_from_name(gid_t *gid_out, const char *group_name)
25 {
26 	struct group grp = { 0 };
27 	char *buffer = NULL;
28 	struct group *result = NULL;
29 	size_t b_size = 0;
30 	int rv = 0;
31 
32 	b_size = teeacl_getgr_r_size_max();
33 	buffer = calloc(1, b_size);
34 	if (!buffer)
35 		return -ENOMEM;
36 
37 	rv = getgrnam_r(group_name, &grp, buffer, b_size, &result);
38 
39 	free(buffer);
40 	if (!result) {
41 		if (rv == 0)
42 			return -ENOENT;
43 		else
44 			return rv;
45 	} else {
46 		*gid_out = grp.gr_gid;
47 		return 0;
48 	}
49 }
50 
teeacl_current_user_is_member_of(gid_t group)51 enum rv_groupmember teeacl_current_user_is_member_of(gid_t group)
52 {
53 	char username[L_cuserid] = { 0 };
54 
55 	cuserid(username);
56 	return teeacl_user_is_member_of(username, group);
57 }
58 
teeacl_user_is_member_of(const char * user,gid_t group)59 enum rv_groupmember teeacl_user_is_member_of(const char *user, gid_t group)
60 {
61 	enum rv_groupmember result = E_MEMORY;
62 	int ret = 0;
63 	int i = 0;
64 	int grouplistsize = 8; /* initial guess */
65 	gid_t *p_groups = NULL;
66 	gid_t *groups = calloc(grouplistsize, sizeof(gid_t));
67 
68 	if (!groups)
69 		return E_MEMORY;
70 	ret = getgrouplist(user, group, groups, &grouplistsize);
71 
72 	if (ret == -1) {
73 		p_groups = groups;
74 
75 		groups = reallocarray(groups, grouplistsize, sizeof(gid_t));
76 		if (!groups) {
77 			free(p_groups);
78 			return E_MEMORY;
79 		}
80 		ret = getgrouplist(user, group, groups, &grouplistsize);
81 		if (ret == -1) {
82 			result = E_GROUPLIST;
83 			goto out;
84 		}
85 	}
86 
87 	for (i = 0; i < grouplistsize; ++i) {
88 		if (group == groups[i]) {
89 			result = IS_MEMBER;
90 			goto out;
91 		}
92 	}
93 	result = NOT_MEMBER;
94 out:
95 	free(groups);
96 	return result;
97 }
98