1 /*
2  * Copyright (C) 2013 Nikos Mavrogiannopoulos
3  *
4  * This file is part of ocserv.
5  *
6  * ocserv is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * ocserv is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <config.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <pwd.h>
25 #include <grp.h>
26 #include <sec-mod-auth.h>
27 #include "auth-unix.h"
28 
29 #ifdef HAVE_GET_USER_AUTH_GROUP
30 /* Fills-in groupname, if the user is in a unix group, via getpwnam().
31  * Returns -1 if the suggested group doesn't match one the groups, or
32  * zero otherwise (an empty group is still success).
33  */
get_user_auth_group(const char * username,const char * suggested,char * groupname,int groupname_size)34 int get_user_auth_group(const char *username, const char *suggested,
35 			char *groupname, int groupname_size)
36 {
37 struct passwd * pwd;
38 struct group *grp;
39 int ret;
40 unsigned found;
41 
42 	groupname[0] = 0;
43 
44 	pwd = getpwnam(username);
45 	if (pwd != NULL) {
46 		if (suggested != NULL) {
47 			gid_t groups[MAX_GROUPS];
48 			int ngroups = sizeof(groups)/sizeof(groups[0]);
49 			unsigned i;
50 
51 			ret = getgrouplist(username, pwd->pw_gid, groups, &ngroups);
52 			if (ret <= 0) {
53 				return 0;
54 			}
55 
56 			found = 0;
57 			for (i=0;i<ngroups;i++) {
58 				grp = getgrgid(groups[i]);
59 				if (grp != NULL && strcmp(suggested, grp->gr_name) == 0) {
60 					strlcpy(groupname, grp->gr_name, groupname_size);
61 					found = 1;
62 					break;
63 				}
64 			}
65 
66 			if (found == 0) {
67 				syslog(LOG_NOTICE,
68 				       "user '%s' requested group '%s' but is not a member",
69 				       username, suggested);
70 				return -1;
71 			}
72 		} else {
73 			struct group* grp = getgrgid(pwd->pw_gid);
74 			if (grp != NULL)
75 				strlcpy(groupname, grp->gr_name, groupname_size);
76 		}
77 	}
78 
79 	return 0;
80 }
81 
unix_group_list(void * pool,unsigned gid_min,char *** groupname,unsigned * groupname_size)82 void unix_group_list(void *pool, unsigned gid_min, char ***groupname, unsigned *groupname_size)
83 {
84 	struct group *grp;
85 
86 	setgrent();
87 
88 	*groupname_size = 0;
89 	*groupname = talloc_size(pool, sizeof(char*)*MAX_GROUPS);
90 	if (*groupname == NULL) {
91 		goto exit;
92 	}
93 
94 	while((grp = getgrent()) != NULL && (*groupname_size) < MAX_GROUPS) {
95 		if (grp->gr_gid >= gid_min) {
96 			(*groupname)[(*groupname_size)] = talloc_strdup(*groupname, grp->gr_name);
97 			if ((*groupname)[(*groupname_size)] == NULL)
98 				break;
99 			(*groupname_size)++;
100 		}
101 	}
102 
103  exit:
104 	endgrent();
105 	return;
106 }
107 
108 #endif
109