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