Imported Upstream version 1.1.6
[platform/upstream/pam.git] / libpam / pam_modutil_ingroup.c
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 static int checkgrouplist(const char *user, gid_t primary, gid_t target)
16 {
17         gid_t *grouplist = NULL;
18         int agroups, ngroups, i;
19         ngroups = agroups = 3;
20         do {
21                 grouplist = malloc(sizeof(gid_t) * agroups);
22                 if (grouplist == NULL) {
23                         return 0;
24                 }
25                 ngroups = agroups;
26                 i = getgrouplist(user, primary, grouplist, &ngroups);
27                 if ((i < 0) || (ngroups < 1)) {
28                         agroups *= 2;
29                         free(grouplist);
30                 } else {
31                         for (i = 0; i < ngroups; i++) {
32                                 if (grouplist[i] == target) {
33                                         free(grouplist);
34                                         return 1;
35                                 }
36                         }
37                         free(grouplist);
38                 }
39         } while (((i < 0) || (ngroups < 1)) && (agroups < 10000));
40         return 0;
41 }
42 #endif
43
44 static int
45 pam_modutil_user_in_group_common(pam_handle_t *pamh UNUSED,
46                                  struct passwd *pwd,
47                                  struct group *grp)
48 {
49         int i;
50
51         if (pwd == NULL) {
52                 return 0;
53         }
54         if (grp == NULL) {
55                 return 0;
56         }
57
58         if (pwd->pw_gid == grp->gr_gid) {
59                 return 1;
60         }
61
62         for (i = 0; (grp->gr_mem != NULL) && (grp->gr_mem[i] != NULL); i++) {
63                 if (strcmp(pwd->pw_name, grp->gr_mem[i]) == 0) {
64                         return 1;
65                 }
66         }
67
68 #ifdef HAVE_GETGROUPLIST
69         if (checkgrouplist(pwd->pw_name, pwd->pw_gid, grp->gr_gid)) {
70                 return 1;
71         }
72 #endif
73
74         return 0;
75 }
76
77 int
78 pam_modutil_user_in_group_nam_nam(pam_handle_t *pamh,
79                                  const char *user, const char *group)
80 {
81         struct passwd *pwd;
82         struct group *grp;
83
84         pwd = pam_modutil_getpwnam(pamh, user);
85         grp = pam_modutil_getgrnam(pamh, group);
86
87         return pam_modutil_user_in_group_common(pamh, pwd, grp);
88 }
89
90 int
91 pam_modutil_user_in_group_nam_gid(pam_handle_t *pamh,
92                                   const char *user, gid_t group)
93 {
94         struct passwd *pwd;
95         struct group *grp;
96
97         pwd = pam_modutil_getpwnam(pamh, user);
98         grp = pam_modutil_getgrgid(pamh, group);
99
100         return pam_modutil_user_in_group_common(pamh, pwd, grp);
101 }
102
103 int
104 pam_modutil_user_in_group_uid_nam(pam_handle_t *pamh,
105                                   uid_t user, const char *group)
106 {
107         struct passwd *pwd;
108         struct group *grp;
109
110         pwd = pam_modutil_getpwuid(pamh, user);
111         grp = pam_modutil_getgrnam(pamh, group);
112
113         return pam_modutil_user_in_group_common(pamh, pwd, grp);
114 }
115
116 int
117 pam_modutil_user_in_group_uid_gid(pam_handle_t *pamh,
118                                   uid_t user, gid_t group)
119 {
120         struct passwd *pwd;
121         struct group *grp;
122
123         pwd = pam_modutil_getpwuid(pamh, user);
124         grp = pam_modutil_getgrgid(pamh, group);
125
126         return pam_modutil_user_in_group_common(pamh, pwd, grp);
127 }