1 /*
2 * $Id$
3 *
4 * This function provides common methods for checking if a user is in a
5 * specified group.
6 */
7
8 #include "pam_modutil_private.h"
9
10 #include <stdlib.h>
11 #include <pwd.h>
12 #include <grp.h>
13
14 #ifdef HAVE_GETGROUPLIST
15
16 #define NGROUPS_MIN 100
17 #define NGROUPS_MAX 65536
18
19 static int checkgrouplist(const char *user, gid_t primary, gid_t target)
20 {
21 int ngroups, pgroups, i;
22
23 ngroups = NGROUPS_MIN;
24 do {
25 gid_t *grouplist;
26
27 pgroups = ngroups;
28 grouplist = malloc(sizeof(gid_t) * ngroups);
29 if (grouplist == NULL) {
30 return 0;
31 }
32 i = getgrouplist(user, primary, grouplist, &ngroups);
33 if (i >= 0) {
34 for (i = 0; i < ngroups; i++) {
35 if (grouplist[i] == target) {
36 free(grouplist);
37 return 1;
38 }
39 }
40 }
41 free(grouplist);
42 } while (i < 0 && ngroups > 0 && ngroups != pgroups && ngroups <= NGROUPS_MAX);
43 return 0;
44 }
45 #endif
46
47 static int
48 pam_modutil_user_in_group_common(pam_handle_t *pamh UNUSED,
49 struct passwd *pwd,
50 struct group *grp)
51 {
52 int i;
53
54 if (pwd == NULL) {
55 return 0;
56 }
57 if (grp == NULL) {
58 return 0;
59 }
60
61 if (pwd->pw_gid == grp->gr_gid) {
62 return 1;
63 }
64
65 for (i = 0; (grp->gr_mem != NULL) && (grp->gr_mem[i] != NULL); i++) {
66 if (strcmp(pwd->pw_name, grp->gr_mem[i]) == 0) {
67 return 1;
68 }
69 }
70
71 #ifdef HAVE_GETGROUPLIST
72 if (checkgrouplist(pwd->pw_name, pwd->pw_gid, grp->gr_gid)) {
73 return 1;
74 }
75 #endif
76
77 return 0;
78 }
79
80 int
81 pam_modutil_user_in_group_nam_nam(pam_handle_t *pamh,
82 const char *user, const char *group)
83 {
84 struct passwd *pwd;
85 struct group *grp;
86
87 pwd = pam_modutil_getpwnam(pamh, user);
88 grp = pam_modutil_getgrnam(pamh, group);
89
90 return pam_modutil_user_in_group_common(pamh, pwd, grp);
91 }
92
93 int
94 pam_modutil_user_in_group_nam_gid(pam_handle_t *pamh,
95 const char *user, gid_t group)
96 {
97 struct passwd *pwd;
98 struct group *grp;
99
100 pwd = pam_modutil_getpwnam(pamh, user);
101 grp = pam_modutil_getgrgid(pamh, group);
102
103 return pam_modutil_user_in_group_common(pamh, pwd, grp);
104 }
105
106 int
107 pam_modutil_user_in_group_uid_nam(pam_handle_t *pamh,
108 uid_t user, const char *group)
109 {
110 struct passwd *pwd;
111 struct group *grp;
112
113 pwd = pam_modutil_getpwuid(pamh, user);
114 grp = pam_modutil_getgrnam(pamh, group);
115
116 return pam_modutil_user_in_group_common(pamh, pwd, grp);
117 }
118
119 int
120 pam_modutil_user_in_group_uid_gid(pam_handle_t *pamh,
121 uid_t user, gid_t group)
122 {
123 struct passwd *pwd;
124 struct group *grp;
125
126 pwd = pam_modutil_getpwuid(pamh, user);
127 grp = pam_modutil_getgrgid(pamh, group);
128
129 return pam_modutil_user_in_group_common(pamh, pwd, grp);
130 }