Squid Web Cache v8/master
Loading...
Searching...
No Matches
support_group.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2026 The Squid Software Foundation and contributors
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
9/*
10 * -----------------------------------------------------------------------------
11 *
12 * Author: Markus Moeller (markus_moeller at compuserve.com)
13 *
14 * Copyright (C) 2007 Markus Moeller. All rights reserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, see <https://www.gnu.org/licenses/>.
28 *
29 * -----------------------------------------------------------------------------
30 */
31
32#include "squid.h"
33#include "util.h"
34
35#if HAVE_LDAP
36
37#include "support.h"
38
39struct gdstruct *init_gd(void);
40void free_gd(struct gdstruct *gdsp);
41
42struct gdstruct *
43init_gd(void) {
44 struct gdstruct *gdsp;
45 gdsp = (struct gdstruct *) xmalloc(sizeof(struct gdstruct));
46 gdsp->group = nullptr;
47 gdsp->domain = nullptr;
48 gdsp->next = nullptr;
49 return gdsp;
50}
51
52void
53free_gd(struct gdstruct *gdsp)
54{
55 while (gdsp) {
56 struct gdstruct *gdspn = gdsp->next;
57 xfree(gdsp->group);
58 xfree(gdsp->domain);
59 xfree(gdsp);
60 gdsp = gdspn;
61 }
62}
63
64char *utf8dup(struct main_args *margs);
65
66char *
67utf8dup(struct main_args *margs)
68{
69 size_t c = 0;
70 size_t n;
71 char *src;
72 unsigned char *p;
73
74 src = margs->glist;
75 if (!src)
76 return nullptr;
77 for (n = 0; n < strlen(src); ++n)
78 if ((unsigned char) src[n] > 127)
79 ++c;
80 if (c != 0) {
81 unsigned char *dupp;
82 p = (unsigned char *) xmalloc(strlen(src) + c);
83 dupp = p;
84 for (n = 0; n < strlen(src); ++n) {
85 unsigned char s;
86 s = (unsigned char) src[n];
87 if (s > 127 && s < 192) {
88 *p = 194;
89 ++p;
90 *p = s;
91 } else if (s > 191) {
92 *p = 195;
93 ++p;
94 *p = s - 64;
95 } else
96 *p = s;
97 ++p;
98 }
99 *p = '\0';
100 debug((char *) "%s| %s: INFO: Group %s as UTF-8: %s\n", LogTime(), PROGRAM, src, dupp);
101 return (char *) dupp;
102 } else
103 return xstrdup(src);
104}
105
106char *hex_utf_char(struct main_args *margs, int flag);
107/*
108 * UTF8 = UTF1 / UTFMB
109 * UTFMB = UTF2 / UTF3 / UTF4
110 *
111 * UTF0 = %x80-BF
112 * UTF1 = %x00-7F
113 * UTF2 = %xC2-DF UTF0
114 * UTF3 = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) /
115 * %xED %x80-9F UTF0 / %xEE-EF 2(UTF0)
116 * UTF4 = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) /
117 * %xF4 %x80-8F 2(UTF0)
118 *
119 * http://www.utf8-chartable.de/unicode-utf8-table.pl
120 */
121
122char *
123hex_utf_char(struct main_args *margs, int flag)
124{
125 int ival, ichar;
126 int iUTF2, iUTF3, iUTF4;
127
128 char *up = (flag ? margs->ulist : margs->tlist);
129 if (!up)
130 return nullptr;
131
132 char *upd = strrchr(up, '@');
133 size_t a = (upd ? (size_t)(upd - up) : strlen(up) );
134
135 char *ul = (char *) xmalloc(strlen(up)+1);
136 size_t n = 0;
137 int nl = 0;
138 iUTF2 = 0;
139 iUTF3 = 0;
140 iUTF4 = 0;
141
142 while (n < strlen(up)) {
143 if (flag && n == a)
144 break;
145 if (up[n] == '@') {
146 ul[nl] = '@';
147 ++nl;
148 ++n;
149 continue;
150 }
151 ival = up[n];
152 if (ival > 64 && ival < 71)
153 ichar = (ival - 55) * 16;
154 else if (ival > 96 && ival < 103)
155 ichar = (ival - 87) * 16;
156 else if (ival > 47 && ival < 58)
157 ichar = (ival - 48) * 16;
158 else {
159 debug((char *) "%s| %s: WARNING: Invalid Hex value %c\n", LogTime(), PROGRAM, ival);
160 xfree(ul);
161 return nullptr;
162 }
163
164 if (n == a - 1) {
165 debug((char *) "%s| %s: WARNING: Invalid Hex UTF-8 string %s\n", LogTime(), PROGRAM, up);
166 xfree(ul);
167 return nullptr;
168 }
169 ++n;
170 ival = up[n];
171 if (ival > 64 && ival < 71)
172 ichar = ichar + ival - 55;
173 else if (ival > 96 && ival < 103)
174 ichar = ichar + ival - 87;
175 else if (ival > 47 && ival < 58)
176 ichar = ichar + ival - 48;
177 else {
178 debug((char *) "%s| %s: WARNING: Invalid Hex value %c\n", LogTime(), PROGRAM, ival);
179 xfree(ul);
180 return nullptr;
181 }
182
183 if (iUTF2) {
184 if (iUTF2 == 0xC2 && ichar > 0x7F && ichar < 0xC0) {
185 iUTF2 = 0;
186 ul[nl - 1] = (char)ichar;
187 } else if (iUTF2 == 0xC3 && ichar > 0x7F && ichar < 0xC0) {
188 iUTF2 = 0;
189 ul[nl - 1] = (char)(ichar + 64);
190 } else if (iUTF2 > 0xC3 && iUTF2 < 0xE0 && ichar > 0x7F && ichar < 0xC0) {
191 iUTF2 = 0;
192 ul[nl] = (char)ichar;
193 ++nl;
194 } else {
195 iUTF2 = 0;
196 ul[nl] = (char)ichar;
197 ul[nl + 1] = '\0';
198 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
199 xfree(ul);
200 return nullptr;
201 }
202 } else if (iUTF3) {
203 if (iUTF3 == 0xE0 && ichar > 0x9F && ichar < 0xC0) {
204 iUTF3 = 1;
205 ul[nl] = (char)ichar;
206 ++nl;
207 } else if (iUTF3 > 0xE0 && iUTF3 < 0xED && ichar > 0x7F && ichar < 0xC0) {
208 iUTF3 = 2;
209 ul[nl] = (char)ichar;
210 ++nl;
211 } else if (iUTF3 == 0xED && ichar > 0x7F && ichar < 0xA0) {
212 iUTF3 = 3;
213 ul[nl] = (char)ichar;
214 ++nl;
215 } else if (iUTF3 > 0xED && iUTF3 < 0xF0 && ichar > 0x7F && ichar < 0xC0) {
216 iUTF3 = 4;
217 ul[nl] = (char)ichar;
218 ++nl;
219 } else if (iUTF3 > 0 && iUTF3 < 5 && ichar > 0x7F && ichar < 0xC0) {
220 iUTF3 = 0;
221 ul[nl] = (char)ichar;
222 ++nl;
223 } else {
224 iUTF3 = 0;
225 ul[nl] = (char)ichar;
226 ul[nl + 1] = '\0';
227 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
228 xfree(ul);
229 return nullptr;
230 }
231 } else if (iUTF4) {
232 if (iUTF4 == 0xF0 && ichar > 0x8F && ichar < 0xC0) {
233 iUTF4 = 1;
234 ul[nl] = (char)ichar;
235 ++nl;
236 } else if (iUTF4 > 0xF0 && iUTF3 < 0xF4 && ichar > 0x7F && ichar < 0xC0) {
237 iUTF4 = 2;
238 ul[nl] = (char)ichar;
239 ++nl;
240 } else if (iUTF4 == 0xF4 && ichar > 0x7F && ichar < 0x90) {
241 iUTF4 = 3;
242 ul[nl] = (char)ichar;
243 ++nl;
244 } else if (iUTF4 > 0 && iUTF4 < 5 && ichar > 0x7F && ichar < 0xC0) {
245 if (iUTF4 == 4)
246 iUTF4 = 0;
247 else
248 iUTF4 = 4;
249 ul[nl] = (char)ichar;
250 ++nl;
251 } else {
252 iUTF4 = 0;
253 ul[nl] = (char)ichar;
254 ul[nl + 1] = '\0';
255 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
256 xfree(ul);
257 return nullptr;
258 }
259 } else if (ichar < 0x80) {
260 /* UTF1 */
261 ul[nl] = (char)ichar;
262 ++nl;
263 } else if (ichar > 0xC1 && ichar < 0xE0) {
264 /* UTF2 (Latin) */
265 iUTF2 = ichar;
266 ul[nl] = (char)ichar;
267 ++nl;
268 } else if (ichar > 0xDF && ichar < 0xF0) {
269 /* UTF3 */
270 iUTF3 = ichar;
271 ul[nl] = (char)ichar;
272 ++nl;
273 } else if (ichar > 0xEF && ichar < 0xF5) {
274 /* UTF4 */
275 iUTF4 = ichar;
276 ul[nl] = (char)ichar;
277 ++nl;
278 } else {
279 ul[nl] = (char)ichar;
280 ul[nl + 1] = '\0';
281 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
282 xfree(ul);
283 return nullptr;
284 }
285 ++n;
286 }
287
288 ul[nl] = '\0';
289 if (iUTF2 || iUTF3 || iUTF4) {
290 debug((char *) "%s| %s: INFO: iUTF2: %d iUTF3: %d iUTF4: %d\n", LogTime(), PROGRAM, iUTF2, iUTF3, iUTF4);
291 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
292 xfree(ul);
293 return nullptr;
294 }
295 if (flag && upd)
296 ul = strcat(ul, upd);
297 return ul;
298}
299
300int
301create_gd(struct main_args *margs)
302{
303 char *gp, *dp;
304 char *p;
305 struct gdstruct *gdsp = nullptr, *gdspn = nullptr;
306 /*
307 * Group list format:
308 *
309 * glist=Pattern1[:Pattern2]
310 *
311 * Pattern=Group Group for all domains(including non Kerberos domains using ldap url options) if no
312 * other group definition for domain exists or users without
313 * domain information.
314 * gdstruct.domain=NULL, gdstruct.group=Group
315 *
316 * or Pattern=Group@ Group for all Kerberos domains if no other group definition
317 * exists
318 * gdstruct.domain="", gdstruct.group=Group
319 *
320 * or Pattern=Group@Domain Group for a specific Kerberos domain
321 * gdstruct.domain=Domain, gdstruct.group=Group
322 *
323 *
324 */
325 char *hp1 = hex_utf_char(margs, 0);
326 char *hp2 = hex_utf_char(margs, 1);
327 char *up = utf8dup(margs);
328
329 // NP: will point to the start of a temporary assembly buffer used by 'p' and 'gp'
330 // for catenation of the hp1, hp2, and up buffer contents from above.
331 // necessary for xfree() because both p and gp move over the assembly area
332 char *gpbuf = nullptr;
333
334 // release the allocated UTF decoding buffers
335#define cleanup() { \
336 xfree(gpbuf); \
337 xfree(hp1); \
338 xfree(hp2); \
339 xfree(up); \
340 free_gd(gdsp); \
341 }
342
343 p = up;
344 if (hp1) {
345 if (hp2) {
346 if (up) {
347 gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp1) + strlen(hp2) + 2);
348 strcpy(p, up);
349 strcat(p, ":");
350 strcat(p, hp1);
351 strcat(p, ":");
352 strcat(p, hp2);
353 } else {
354 gpbuf = p = (char *) xmalloc(strlen(hp1) + strlen(hp2) + 1);
355 strcpy(p, hp1);
356 strcat(p, ":");
357 strcat(p, hp2);
358 }
359 } else {
360 if (up) {
361 gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp1) + 1);
362 strcpy(p, up);
363 strcat(p, ":");
364 strcat(p, hp1);
365 } else
366 p = hp1;
367 }
368 } else {
369 if (hp2) {
370 if (up) {
371 gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp2) + 1);
372 strcpy(p, up);
373 strcat(p, ":");
374 strcat(p, hp2);
375 } else
376 p = hp2;
377 } else
378 p = up;
379 }
380 gp = p;
381 debug((char *) "%s| %s: INFO: Group list %s\n", LogTime(), PROGRAM, p ? p : "NULL");
382 dp = nullptr;
383
384 if (!p) {
385 debug((char *) "%s| %s: ERROR: No groups defined.\n", LogTime(), PROGRAM);
386 cleanup();
387 return (1);
388 }
389 while (*p) { /* loop over group list */
390 if (*p == '\n' || *p == '\r') { /* Ignore CR and LF if exist */
391 ++p;
392 continue;
393 }
394 if (*p == '@') { /* end of group name - start of domain name */
395 if (p == gp) { /* empty group name not allowed */
396 debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
397 cleanup();
398 return (1);
399 }
400 if (dp) { /* end of domain name - twice */
401 debug((char *) "%s| %s: @ is not allowed in group name %s@%s\n",LogTime(), PROGRAM,gp,dp);
402 cleanup();
403 return(1);
404 }
405 *p = '\0';
406 ++p;
407 gdsp = init_gd();
408 gdsp->group = xstrdup(gp);
409 gdsp->next = gdspn;
410 dp = p; /* after @ starts new domain name */
411 } else if (*p == ':') { /* end of group name or end of domain name */
412 if (p == gp) { /* empty group name not allowed */
413 debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
414 cleanup();
415 return (1);
416 }
417 *p = '\0';
418 ++p;
419 if (dp) { /* end of domain name */
420 gdsp->domain = xstrdup(dp);
421 dp = nullptr;
422 } else { /* end of group name and no domain name */
423 gdsp = init_gd();
424 gdsp->group = xstrdup(gp);
425 gdsp->next = gdspn;
426 }
427 gdspn = gdsp;
428 gp = p; /* after : starts new group name */
429 debug((char *) "%s| %s: INFO: Group %s Domain %s\n", LogTime(), PROGRAM, gdsp->group, gdsp->domain ? gdsp->domain : "NULL");
430 } else
431 ++p;
432 }
433 if (p == gp) { /* empty group name not allowed */
434 debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
435 cleanup();
436 return (1);
437 }
438 if (dp) { /* end of domain name */
439 gdsp->domain = xstrdup(dp);
440 } else { /* end of group name and no domain name */
441 gdsp = init_gd();
442 gdsp->group = xstrdup(gp);
443 if (gdspn) /* Have already an existing structure */
444 gdsp->next = gdspn;
445 }
446 debug((char *) "%s| %s: INFO: Group %s Domain %s\n", LogTime(), PROGRAM, gdsp->group, gdsp->domain ? gdsp->domain : "NULL");
447
448 margs->groups = gdsp;
449 gdsp = nullptr; // prevent the cleanup() deallocating it.
450 cleanup();
451 return (0);
452}
453#endif
454
int create_gd(struct main_args *margs)
#define PROGRAM
Definition support.h:168
const char * LogTime(void)
void debug(const char *format,...)
Definition debug.cc:19
#define xfree
#define xstrdup
#define xmalloc
struct gdstruct * next
Definition support.h:60
char * group
Definition support.h:58
char * domain
Definition support.h:59
char * ulist
Definition support.h:75
char * glist
Definition support.h:74
char * tlist
Definition support.h:76
struct gdstruct * groups
Definition support.h:89
int const char size_t