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