support_group.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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
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 
33 #include "squid.h"
34 #include "util.h"
35 
36 #if HAVE_LDAP
37 
38 #include "support.h"
39 
40 struct gdstruct *init_gd(void);
41 void free_gd(struct gdstruct *gdsp);
42 
43 struct gdstruct *
44 init_gd(void) {
45  struct gdstruct *gdsp;
46  gdsp = (struct gdstruct *) xmalloc(sizeof(struct gdstruct));
47  gdsp->group = nullptr;
48  gdsp->domain = nullptr;
49  gdsp->next = nullptr;
50  return gdsp;
51 }
52 
53 void
54 free_gd(struct gdstruct *gdsp)
55 {
56  while (gdsp) {
57  struct gdstruct *gdspn = gdsp->next;
58  xfree(gdsp->group);
59  xfree(gdsp->domain);
60  xfree(gdsp);
61  gdsp = gdspn;
62  }
63 }
64 
65 char *utf8dup(struct main_args *margs);
66 
67 char *
68 utf8dup(struct main_args *margs)
69 {
70  size_t c = 0;
71  size_t n;
72  char *src;
73  unsigned char *p;
74 
75  src = margs->glist;
76  if (!src)
77  return nullptr;
78  for (n = 0; n < strlen(src); ++n)
79  if ((unsigned char) src[n] > 127)
80  ++c;
81  if (c != 0) {
82  unsigned char *dupp;
83  p = (unsigned char *) xmalloc(strlen(src) + c);
84  dupp = p;
85  for (n = 0; n < strlen(src); ++n) {
86  unsigned char s;
87  s = (unsigned char) src[n];
88  if (s > 127 && s < 192) {
89  *p = 194;
90  ++p;
91  *p = s;
92  } else if (s > 191) {
93  *p = 195;
94  ++p;
95  *p = s - 64;
96  } else
97  *p = s;
98  ++p;
99  }
100  *p = '\0';
101  debug((char *) "%s| %s: INFO: Group %s as UTF-8: %s\n", LogTime(), PROGRAM, src, dupp);
102  return (char *) dupp;
103  } else
104  return xstrdup(src);
105 }
106 
107 char *hex_utf_char(struct main_args *margs, int flag);
108 /*
109  * UTF8 = UTF1 / UTFMB
110  * UTFMB = UTF2 / UTF3 / UTF4
111  *
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)
119  *
120  * http://www.utf8-chartable.de/unicode-utf8-table.pl
121  */
122 
123 char *
124 hex_utf_char(struct main_args *margs, int flag)
125 {
126  int ival, ichar;
127  int iUTF2, iUTF3, iUTF4;
128 
129  char *up = (flag ? margs->ulist : margs->tlist);
130  if (!up)
131  return nullptr;
132 
133  char *upd = strrchr(up, '@');
134  size_t a = (upd ? (size_t)(upd - up) : strlen(up) );
135 
136  char *ul = (char *) xmalloc(strlen(up)+1);
137  size_t n = 0;
138  int nl = 0;
139  iUTF2 = 0;
140  iUTF3 = 0;
141  iUTF4 = 0;
142 
143  while (n < strlen(up)) {
144  if (flag && n == a)
145  break;
146  if (up[n] == '@') {
147  ul[nl] = '@';
148  ++nl;
149  ++n;
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);
161  xfree(ul);
162  return nullptr;
163  }
164 
165  if (n == a - 1) {
166  debug((char *) "%s| %s: WARNING: Invalid Hex UTF-8 string %s\n", LogTime(), PROGRAM, up);
167  xfree(ul);
168  return nullptr;
169  }
170  ++n;
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);
180  xfree(ul);
181  return nullptr;
182  }
183 
184  if (iUTF2) {
185  if (iUTF2 == 0xC2 && ichar > 0x7F && ichar < 0xC0) {
186  iUTF2 = 0;
187  ul[nl - 1] = (char)ichar;
188  } else if (iUTF2 == 0xC3 && ichar > 0x7F && ichar < 0xC0) {
189  iUTF2 = 0;
190  ul[nl - 1] = (char)(ichar + 64);
191  } else if (iUTF2 > 0xC3 && iUTF2 < 0xE0 && ichar > 0x7F && ichar < 0xC0) {
192  iUTF2 = 0;
193  ul[nl] = (char)ichar;
194  ++nl;
195  } else {
196  iUTF2 = 0;
197  ul[nl] = (char)ichar;
198  ul[nl + 1] = '\0';
199  debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
200  xfree(ul);
201  return nullptr;
202  }
203  } else if (iUTF3) {
204  if (iUTF3 == 0xE0 && ichar > 0x9F && ichar < 0xC0) {
205  iUTF3 = 1;
206  ul[nl] = (char)ichar;
207  ++nl;
208  } else if (iUTF3 > 0xE0 && iUTF3 < 0xED && ichar > 0x7F && ichar < 0xC0) {
209  iUTF3 = 2;
210  ul[nl] = (char)ichar;
211  ++nl;
212  } else if (iUTF3 == 0xED && ichar > 0x7F && ichar < 0xA0) {
213  iUTF3 = 3;
214  ul[nl] = (char)ichar;
215  ++nl;
216  } else if (iUTF3 > 0xED && iUTF3 < 0xF0 && ichar > 0x7F && ichar < 0xC0) {
217  iUTF3 = 4;
218  ul[nl] = (char)ichar;
219  ++nl;
220  } else if (iUTF3 > 0 && iUTF3 < 5 && ichar > 0x7F && ichar < 0xC0) {
221  iUTF3 = 0;
222  ul[nl] = (char)ichar;
223  ++nl;
224  } else {
225  iUTF3 = 0;
226  ul[nl] = (char)ichar;
227  ul[nl + 1] = '\0';
228  debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
229  xfree(ul);
230  return nullptr;
231  }
232  } else if (iUTF4) {
233  if (iUTF4 == 0xF0 && ichar > 0x8F && ichar < 0xC0) {
234  iUTF4 = 1;
235  ul[nl] = (char)ichar;
236  ++nl;
237  } else if (iUTF4 > 0xF0 && iUTF3 < 0xF4 && ichar > 0x7F && ichar < 0xC0) {
238  iUTF4 = 2;
239  ul[nl] = (char)ichar;
240  ++nl;
241  } else if (iUTF4 == 0xF4 && ichar > 0x7F && ichar < 0x90) {
242  iUTF4 = 3;
243  ul[nl] = (char)ichar;
244  ++nl;
245  } else if (iUTF4 > 0 && iUTF4 < 5 && ichar > 0x7F && ichar < 0xC0) {
246  if (iUTF4 == 4)
247  iUTF4 = 0;
248  else
249  iUTF4 = 4;
250  ul[nl] = (char)ichar;
251  ++nl;
252  } else {
253  iUTF4 = 0;
254  ul[nl] = (char)ichar;
255  ul[nl + 1] = '\0';
256  debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
257  xfree(ul);
258  return nullptr;
259  }
260  } else if (ichar < 0x80) {
261  /* UTF1 */
262  ul[nl] = (char)ichar;
263  ++nl;
264  } else if (ichar > 0xC1 && ichar < 0xE0) {
265  /* UTF2 (Latin) */
266  iUTF2 = ichar;
267  ul[nl] = (char)ichar;
268  ++nl;
269  } else if (ichar > 0xDF && ichar < 0xF0) {
270  /* UTF3 */
271  iUTF3 = ichar;
272  ul[nl] = (char)ichar;
273  ++nl;
274  } else if (ichar > 0xEF && ichar < 0xF5) {
275  /* UTF4 */
276  iUTF4 = ichar;
277  ul[nl] = (char)ichar;
278  ++nl;
279  } else {
280  ul[nl] = (char)ichar;
281  ul[nl + 1] = '\0';
282  debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
283  xfree(ul);
284  return nullptr;
285  }
286  ++n;
287  }
288 
289  ul[nl] = '\0';
290  if (iUTF2 || iUTF3 || iUTF4) {
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);
293  xfree(ul);
294  return nullptr;
295  }
296  if (flag && upd)
297  ul = strcat(ul, upd);
298  return ul;
299 }
300 
301 int
302 create_gd(struct main_args *margs)
303 {
304  char *gp, *dp;
305  char *p;
306  struct gdstruct *gdsp = nullptr, *gdspn = nullptr;
307  /*
308  * Group list format:
309  *
310  * glist=Pattern1[:Pattern2]
311  *
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
314  * domain information.
315  * gdstruct.domain=NULL, gdstruct.group=Group
316  *
317  * or Pattern=Group@ Group for all Kerberos domains if no other group definition
318  * exists
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  */
326  char *hp1 = hex_utf_char(margs, 0);
327  char *hp2 = hex_utf_char(margs, 1);
328  char *up = utf8dup(margs);
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
333  char *gpbuf = nullptr;
334 
335  // release the allocated UTF decoding buffers
336 #define cleanup() { \
337  xfree(gpbuf); \
338  xfree(hp1); \
339  xfree(hp2); \
340  xfree(up); \
341  free_gd(gdsp); \
342  }
343 
344  p = up;
345  if (hp1) {
346  if (hp2) {
347  if (up) {
348  gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp1) + strlen(hp2) + 2);
349  strcpy(p, up);
350  strcat(p, ":");
351  strcat(p, hp1);
352  strcat(p, ":");
353  strcat(p, hp2);
354  } else {
355  gpbuf = p = (char *) xmalloc(strlen(hp1) + strlen(hp2) + 1);
356  strcpy(p, hp1);
357  strcat(p, ":");
358  strcat(p, hp2);
359  }
360  } else {
361  if (up) {
362  gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp1) + 1);
363  strcpy(p, up);
364  strcat(p, ":");
365  strcat(p, hp1);
366  } else
367  p = hp1;
368  }
369  } else {
370  if (hp2) {
371  if (up) {
372  gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp2) + 1);
373  strcpy(p, up);
374  strcat(p, ":");
375  strcat(p, hp2);
376  } else
377  p = hp2;
378  } else
379  p = up;
380  }
381  gp = p;
382  debug((char *) "%s| %s: INFO: Group list %s\n", LogTime(), PROGRAM, p ? p : "NULL");
383  dp = nullptr;
384 
385  if (!p) {
386  debug((char *) "%s| %s: ERROR: No groups defined.\n", LogTime(), PROGRAM);
387  cleanup();
388  return (1);
389  }
390  while (*p) { /* loop over group list */
391  if (*p == '\n' || *p == '\r') { /* Ignore CR and LF if exist */
392  ++p;
393  continue;
394  }
395  if (*p == '@') { /* end of group name - start of domain name */
396  if (p == gp) { /* empty group name not allowed */
397  debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
398  cleanup();
399  return (1);
400  }
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  }
406  *p = '\0';
407  ++p;
408  gdsp = init_gd();
409  gdsp->group = xstrdup(gp);
410  gdsp->next = gdspn;
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 */
414  debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
415  cleanup();
416  return (1);
417  }
418  *p = '\0';
419  ++p;
420  if (dp) { /* end of domain name */
421  gdsp->domain = xstrdup(dp);
422  dp = nullptr;
423  } else { /* end of group name and no domain name */
424  gdsp = init_gd();
425  gdsp->group = xstrdup(gp);
426  gdsp->next = gdspn;
427  }
428  gdspn = gdsp;
429  gp = p; /* after : starts new group name */
430  debug((char *) "%s| %s: INFO: Group %s Domain %s\n", LogTime(), PROGRAM, gdsp->group, gdsp->domain ? gdsp->domain : "NULL");
431  } else
432  ++p;
433  }
434  if (p == gp) { /* empty group name not allowed */
435  debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
436  cleanup();
437  return (1);
438  }
439  if (dp) { /* end of domain name */
440  gdsp->domain = xstrdup(dp);
441  } else { /* end of group name and no domain name */
442  gdsp = init_gd();
443  gdsp->group = xstrdup(gp);
444  if (gdspn) /* Have already an existing structure */
445  gdsp->next = gdspn;
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;
450  gdsp = nullptr; // prevent the cleanup() deallocating it.
451  cleanup();
452  return (0);
453 }
454 #endif
455 
#define xmalloc
#define PROGRAM
Definition: support.h:169
void debug(const char *format,...)
Definition: debug.cc:19
#define xstrdup
struct gdstruct * groups
Definition: support.h:90
char * ulist
Definition: support.h:76
int create_gd(struct main_args *margs)
int const char size_t
Definition: stub_liblog.cc:83
struct gdstruct * next
Definition: support.h:61
const char * LogTime(void)
#define xfree
char * group
Definition: support.h:59
char * glist
Definition: support.h:75
char * domain
Definition: support.h:60
char * tlist
Definition: support.h:77

 

Introduction

Documentation

Support

Miscellaneous