]>
Commit | Line | Data |
---|---|---|
6328cedc | 1 | /* |
262a0e14 | 2 | * $Id$ |
6328cedc | 3 | * |
4 | * This is a helper for the external ACL interface for Squid Cache | |
5 | * Copyright (C) 2002 Rodrigo Albani de Campos (rodrigo@geekbunker.org) | |
26ac0430 | 6 | * |
6328cedc | 7 | * It reads STDIN looking for a username that matches a specified group |
26ac0430 | 8 | * Returns `OK' if the user belongs to the group or `ERR' otherwise, as |
6328cedc | 9 | * described on http://devel.squid-cache.org/external_acl/config.html |
10 | * To compile this program, use: | |
11 | * | |
12 | * gcc -o check_group check_group.c | |
13 | * | |
14 | * Author: Rodrigo Albani de Campos | |
15 | * E-Mail: rodrigo@geekbunker.org | |
16 | * | |
17 | * This program is free software; you can redistribute it and/or modify | |
18 | * it under the terms of the GNU General Public License as published by | |
19 | * the Free Software Foundation; either version 2 of the License, or | |
20 | * (at your option) any later version. | |
21 | * | |
22 | * This program is distributed in the hope that it will be useful, | |
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | * GNU General Public License for more details. | |
26 | * | |
27 | * You should have received a copy of the GNU General Public License | |
28 | * along with this program; if not, write to the Free Software | |
29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
30 | * | |
31 | * Change Log: | |
056823c5 HN |
32 | * 2010-02-24 hno |
33 | * Removed group number limitation and fixed related uninitialized | |
34 | * pointer reference (Bug #2813) | |
35 | * | |
1958420a | 36 | * Revision 1.7 2004/08/15 00:29:33 hno |
37 | * helper protocol changed to URL-escaped strings in Squid-3.0 | |
38 | * | |
6328cedc | 39 | * Revision 1.6 2002/08/12 15:48:32 hno |
40 | * imported strwordtok from Squid, added man page, some minor fixes | |
41 | * | |
42 | * Revision 1.5 2002/07/27 14:26:49 rcampos | |
43 | * allow groups to be sent on stdin | |
44 | * | |
45 | * Revision 1.4 2002/04/17 01:58:48 camposr | |
46 | * minor corrections in the getopt | |
47 | * | |
48 | * Revision 1.3 2002/04/17 01:43:17 camposr | |
49 | * ready for action | |
50 | * | |
51 | * Revision 1.2 2002/04/17 01:32:16 camposr | |
52 | * all main routines ready | |
53 | * | |
54 | * Revision 1.1 2002/04/16 05:02:32 camposr | |
55 | * Initial revision | |
56 | * | |
57 | */ | |
f7f3304a | 58 | #include "squid.h" |
c152a447 | 59 | #include "helpers/defines.h" |
1fa9b1a7 | 60 | #include "rfc1738.h" |
7483aded | 61 | #include "util.h" |
62 | ||
c152a447 | 63 | #if HAVE_STDIO_H |
6328cedc | 64 | #include <stdio.h> |
c152a447 AJ |
65 | #endif |
66 | #if HAVE_STRING_H | |
6328cedc | 67 | #include <string.h> |
c152a447 AJ |
68 | #endif |
69 | #if HAVE_GRP_H | |
6328cedc | 70 | #include <grp.h> |
c152a447 AJ |
71 | #endif |
72 | #if HAVE_UNISTD_H | |
6328cedc | 73 | #include <unistd.h> |
c152a447 AJ |
74 | #endif |
75 | #if HAVE_PWD_H | |
6328cedc | 76 | #include <pwd.h> |
c152a447 AJ |
77 | #endif |
78 | #if HAVE_CTYPE_H | |
6328cedc | 79 | #include <ctype.h> |
c152a447 | 80 | #endif |
6328cedc | 81 | |
26ac0430 | 82 | /* |
9cee498b | 83 | * Verify if user's primary group matches groupname |
6328cedc | 84 | * Returns 0 if user is not on the group |
85 | * Returns 1 otherwise | |
86 | */ | |
87 | static int | |
88 | validate_user_pw(char *username, char *groupname) | |
89 | { | |
90 | struct passwd *p; | |
91 | struct group *g; | |
92 | ||
93 | if ((p = getpwnam(username)) == NULL) { | |
26ac0430 | 94 | /* Returns an error if user does not exist in the /etc/passwd */ |
c152a447 | 95 | fprintf(stderr, "ERROR: User does not exist '%s'\n", username); |
26ac0430 | 96 | return 0; |
6328cedc | 97 | } else { |
26ac0430 AJ |
98 | /* Verify if the this is the primary user group */ |
99 | if ((g = getgrgid(p->pw_gid)) != NULL) { | |
100 | if ((strcmp(groupname, g->gr_name)) == 0) | |
101 | return 1; | |
102 | } | |
6328cedc | 103 | } |
104 | ||
105 | return 0; | |
106 | } | |
107 | ||
108 | static int | |
109 | validate_user_gr(char *username, char *groupname) | |
110 | { | |
26ac0430 | 111 | /* |
6328cedc | 112 | * Verify if the user belongs to groupname as listed in the |
113 | * /etc/group file | |
114 | */ | |
115 | struct group *g; | |
116 | ||
117 | if ((g = getgrnam(groupname)) == NULL) { | |
c152a447 | 118 | fprintf(stderr, "ERROR: Group does not exist '%s'\n", groupname); |
26ac0430 | 119 | return 0; |
6328cedc | 120 | } else { |
26ac0430 AJ |
121 | while (*(g->gr_mem) != NULL) { |
122 | if (strcmp(*((g->gr_mem)++), username) == 0) { | |
123 | return 1; | |
124 | } | |
125 | } | |
6328cedc | 126 | } |
127 | return 0; | |
128 | } | |
129 | ||
130 | static void | |
131 | usage(char *program) | |
132 | { | |
42aa79b5 | 133 | fprintf(stderr, "Usage: %s -g group1 [-g group2 ...] [-p] [-s]\n\n", |
26ac0430 | 134 | program); |
6328cedc | 135 | fprintf(stderr, "-g group\n"); |
136 | fprintf(stderr, | |
26ac0430 | 137 | " The group name or id that the user must belong in order to\n"); |
6328cedc | 138 | fprintf(stderr, |
26ac0430 | 139 | " be allowed to authenticate.\n"); |
6328cedc | 140 | fprintf(stderr, |
26ac0430 | 141 | "-p Verify primary user group as well\n"); |
42aa79b5 | 142 | fprintf(stderr, |
26ac0430 | 143 | "-s Strip NT domain from usernames\n"); |
6328cedc | 144 | } |
145 | ||
6328cedc | 146 | int |
147 | main(int argc, char *argv[]) | |
148 | { | |
42aa79b5 | 149 | char *user, *suser, *p; |
c152a447 | 150 | char buf[HELPER_INPUT_BUFFER]; |
056823c5 HN |
151 | char **grents = NULL; |
152 | int check_pw = 0, ch, ngroups = 0, i, j = 0, strip_dm = 0; | |
6328cedc | 153 | |
154 | /* make standard output line buffered */ | |
155 | setvbuf(stdout, NULL, _IOLBF, 0); | |
156 | ||
157 | /* get user options */ | |
c152a447 | 158 | while ((ch = getopt(argc, argv, "dspg:")) != -1) { |
26ac0430 | 159 | switch (ch) { |
c152a447 AJ |
160 | case 'd': |
161 | debug_enabled = 1; | |
162 | break; | |
26ac0430 AJ |
163 | case 's': |
164 | strip_dm = 1; | |
165 | break; | |
166 | case 'p': | |
167 | check_pw = 1; | |
168 | break; | |
169 | case 'g': | |
c152a447 | 170 | grents = (char**)realloc(grents, sizeof(*grents) * (ngroups+1)); |
f207fe64 FC |
171 | grents[ngroups] = optarg; |
172 | ++ngroups; | |
26ac0430 AJ |
173 | break; |
174 | case '?': | |
175 | if (xisprint(optopt)) { | |
26ac0430 AJ |
176 | fprintf(stderr, "Unknown option '-%c'.\n", optopt); |
177 | } else { | |
178 | fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); | |
179 | } | |
180 | ||
181 | default: | |
182 | usage(argv[0]); | |
183 | exit(1); | |
184 | } | |
6328cedc | 185 | } |
186 | if (optind < argc) { | |
c152a447 | 187 | fprintf(stderr, "FATAL: Unknown option '%s'\n", argv[optind]); |
26ac0430 AJ |
188 | usage(argv[0]); |
189 | exit(1); | |
6328cedc | 190 | } |
c152a447 | 191 | while (fgets(buf, HELPER_INPUT_BUFFER, stdin)) { |
26ac0430 AJ |
192 | j = 0; |
193 | if ((p = strchr(buf, '\n')) == NULL) { | |
194 | /* too large message received.. skip and deny */ | |
c152a447 | 195 | fprintf(stderr, "ERROR: %s: Too large: %s\n", argv[0], buf); |
26ac0430 | 196 | while (fgets(buf, sizeof(buf), stdin)) { |
c152a447 | 197 | fprintf(stderr, "ERROR: %s: Too large..: %s\n", argv[0], buf); |
26ac0430 AJ |
198 | if (strchr(buf, '\n') != NULL) |
199 | break; | |
200 | } | |
c152a447 AJ |
201 | SEND_ERR("Username Input too large."); |
202 | continue; | |
26ac0430 AJ |
203 | } |
204 | *p = '\0'; | |
205 | if ((p = strtok(buf, " ")) == NULL) { | |
c152a447 AJ |
206 | SEND_ERR("No username given."); |
207 | continue; | |
26ac0430 AJ |
208 | } else { |
209 | user = p; | |
210 | rfc1738_unescape(user); | |
211 | if (user && strip_dm) { | |
212 | suser = strchr(user, '\\'); | |
213 | if (!suser) suser = strchr(user, '/'); | |
214 | if (suser && suser[1]) user = suser + 1; | |
215 | } | |
216 | /* check groups supplied by Squid */ | |
217 | while ((p = strtok(NULL, " ")) != NULL) { | |
218 | rfc1738_unescape(p); | |
219 | if (check_pw == 1) | |
220 | j += validate_user_pw(user, p); | |
26ac0430 AJ |
221 | j += validate_user_gr(user, p); |
222 | } | |
223 | } | |
224 | ||
225 | /* check groups supplied on the command line */ | |
a2f5277a | 226 | for (i = 0; i < ngroups; ++i) { |
26ac0430 AJ |
227 | if (check_pw == 1) { |
228 | j += validate_user_pw(user, grents[i]); | |
229 | } | |
230 | j += validate_user_gr(user, grents[i]); | |
231 | } | |
232 | ||
233 | if (j > 0) { | |
c152a447 | 234 | SEND_OK(""); |
26ac0430 | 235 | } else { |
c152a447 | 236 | SEND_ERR(""); |
26ac0430 | 237 | } |
6328cedc | 238 | } |
239 | return 0; | |
240 | } |