~ubuntu-branches/ubuntu/edgy/lynx/edgy

« back to all changes in this revision

Viewing changes to WWW/Library/Implementation/HTGroup.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-16 12:14:10 UTC
  • Revision ID: james.westby@ubuntu.com-20040916121410-cz1gu92c4nqfeyrg
Tags: upstream-2.8.5
ImportĀ upstreamĀ versionĀ 2.8.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* MODULE                                                       HTGroup.c
 
3
**              GROUP FILE ROUTINES
 
4
**
 
5
**      Contains group file parser and routines to match IP
 
6
**      address templates and to find out group membership.
 
7
**
 
8
**
 
9
** AUTHORS:
 
10
**      AL      Ari Luotonen    luotonen@dxcern.cern.ch
 
11
**
 
12
** HISTORY:
 
13
**
 
14
**
 
15
** BUGS:
 
16
**
 
17
**
 
18
**
 
19
** GROUP DEFINITION GRAMMAR:
 
20
**
 
21
**      string = "sequence of alphanumeric characters"
 
22
**      user_name ::= string
 
23
**      group_name ::= string
 
24
**      group_ref ::= group_name
 
25
**      user_def ::= user_name | group_ref
 
26
**      user_def_list ::= user_def { ',' user_def }
 
27
**      user_part = user_def | '(' user_def_list ')'
 
28
**
 
29
**      templ = "sequence of alphanumeric characters and '*'s"
 
30
**      ip_number_mask ::= templ '.' templ '.' templ '.' templ
 
31
**      domain_name_mask ::= templ { '.' templ }
 
32
**      address ::= ip_number_mask | domain_name_mask
 
33
**      address_def ::= address
 
34
**      address_def_list ::= address_def { ',' address_def }
 
35
**      address_part = address_def | '(' address_def_list ')'
 
36
**
 
37
**      item ::= [user_part] ['@' address_part]
 
38
**      item_list ::= item { ',' item }
 
39
**      group_def ::= item_list
 
40
**      group_decl ::= group_name ':' group_def
 
41
**
 
42
*/
 
43
 
 
44
 
 
45
#include <HTUtils.h>
 
46
 
 
47
#include <HTAAUtil.h>
 
48
#include <HTLex.h>      /* Lexical analysor     */
 
49
#include <HTGroup.h>    /* Implemented here     */
 
50
 
 
51
#include <LYUtils.h>
 
52
#include <LYLeaks.h>
 
53
 
 
54
/*
 
55
** Group file parser
 
56
*/
 
57
 
 
58
typedef HTList UserDefList;
 
59
typedef HTList AddressDefList;
 
60
 
 
61
typedef struct {
 
62
    UserDefList *       user_def_list;
 
63
    AddressDefList *    address_def_list;
 
64
} Item;
 
65
 
 
66
typedef struct {
 
67
    char *      name;
 
68
    GroupDef *  translation;
 
69
} Ref;
 
70
 
 
71
 
 
72
 
 
73
PRIVATE void syntax_error ARGS3(FILE *,  fp,
 
74
                                char *,  msg,
 
75
                                LexItem, lex_item)
 
76
{
 
77
    char buffer[41];
 
78
    int cnt = 0;
 
79
    int ch;
 
80
 
 
81
    while ((ch = getc(fp)) != EOF  &&  ch != '\n')
 
82
        if (cnt < 40) buffer[cnt++] = (char) ch;
 
83
    buffer[cnt] = (char)0;
 
84
 
 
85
    CTRACE((tfp, "%s %d before: '%s'\nHTGroup.c: %s (got %s)\n",
 
86
                "HTGroup.c: Syntax error in rule file at line",
 
87
                HTlex_line, buffer, msg, lex_verbose(lex_item)));
 
88
    HTlex_line++;
 
89
}
 
90
 
 
91
 
 
92
PRIVATE AddressDefList *parse_address_part ARGS1(FILE *, fp)
 
93
{
 
94
    AddressDefList *address_def_list = NULL;
 
95
    LexItem lex_item;
 
96
    BOOL only_one = NO;
 
97
 
 
98
    lex_item = lex(fp);
 
99
    if (lex_item == LEX_ALPH_STR || lex_item == LEX_TMPL_STR)
 
100
        only_one = YES;
 
101
    else if (lex_item != LEX_OPEN_PAREN  ||
 
102
             ((lex_item = lex(fp)) != LEX_ALPH_STR &&
 
103
              lex_item != LEX_TMPL_STR)) {
 
104
        syntax_error(fp, "Expecting a single address or '(' beginning list",
 
105
                     lex_item);
 
106
        return NULL;
 
107
    }
 
108
    address_def_list = HTList_new();
 
109
 
 
110
    for(;;) {
 
111
        Ref *ref = typecalloc(Ref);
 
112
        if (ref == NULL)
 
113
            outofmem(__FILE__, "parse_address_part");
 
114
        ref->name = NULL;
 
115
        ref->translation = NULL;
 
116
        StrAllocCopy(ref->name, HTlex_buffer);
 
117
 
 
118
        HTList_addObject(address_def_list, (void*)ref);
 
119
 
 
120
        if (only_one || (lex_item = lex(fp)) != LEX_ITEM_SEP)
 
121
            break;
 
122
        /*
 
123
        ** Here lex_item == LEX_ITEM_SEP; after item separator it
 
124
        ** is ok to have one or more newlines (LEX_REC_SEP) and
 
125
        ** they are ignored (continuation line).
 
126
        */
 
127
        do {
 
128
            lex_item = lex(fp);
 
129
        } while (lex_item == LEX_REC_SEP);
 
130
 
 
131
        if (lex_item != LEX_ALPH_STR && lex_item != LEX_TMPL_STR) {
 
132
            syntax_error(fp, "Expecting an address template", lex_item);
 
133
            HTList_delete(address_def_list);
 
134
            address_def_list = NULL;
 
135
            return NULL;
 
136
        }
 
137
    }
 
138
 
 
139
    if (!only_one && lex_item != LEX_CLOSE_PAREN) {
 
140
        HTList_delete(address_def_list);
 
141
        address_def_list = NULL;
 
142
        syntax_error(fp, "Expecting ')' closing address list", lex_item);
 
143
        return NULL;
 
144
    }
 
145
    return address_def_list;
 
146
}
 
147
 
 
148
 
 
149
PRIVATE UserDefList *parse_user_part ARGS1(FILE *, fp)
 
150
{
 
151
    UserDefList *user_def_list = NULL;
 
152
    LexItem lex_item;
 
153
    BOOL only_one = NO;
 
154
 
 
155
    lex_item = lex(fp);
 
156
    if (lex_item == LEX_ALPH_STR)
 
157
        only_one = YES;
 
158
    else if (lex_item != LEX_OPEN_PAREN  ||
 
159
             (lex_item = lex(fp)) != LEX_ALPH_STR) {
 
160
        syntax_error(fp, "Expecting a single name or '(' beginning list",
 
161
                     lex_item);
 
162
        return NULL;
 
163
    }
 
164
    user_def_list = HTList_new();
 
165
 
 
166
    for (;;) {
 
167
        Ref *ref = typecalloc(Ref);
 
168
        if (ref == NULL)
 
169
            outofmem(__FILE__, "parse_user_part");
 
170
        ref->name = NULL;
 
171
        ref->translation = NULL;
 
172
        StrAllocCopy(ref->name, HTlex_buffer);
 
173
 
 
174
        HTList_addObject(user_def_list, (void*)ref);
 
175
 
 
176
        if (only_one || (lex_item = lex(fp)) != LEX_ITEM_SEP)
 
177
            break;
 
178
        /*
 
179
        ** Here lex_item == LEX_ITEM_SEP; after item separator it
 
180
        ** is ok to have one or more newlines (LEX_REC_SEP) and
 
181
        ** they are ignored (continuation line).
 
182
        */
 
183
        do {
 
184
            lex_item = lex(fp);
 
185
        } while (lex_item == LEX_REC_SEP);
 
186
 
 
187
        if (lex_item != LEX_ALPH_STR) {
 
188
            syntax_error(fp, "Expecting user or group name", lex_item);
 
189
            HTList_delete(user_def_list);
 
190
            user_def_list = NULL;
 
191
            return NULL;
 
192
        }
 
193
    }
 
194
 
 
195
    if (!only_one && lex_item != LEX_CLOSE_PAREN) {
 
196
        HTList_delete(user_def_list);
 
197
        user_def_list = NULL;
 
198
        syntax_error(fp, "Expecting ')' closing user/group list", lex_item);
 
199
        return NULL;
 
200
    }
 
201
    return user_def_list;
 
202
}
 
203
 
 
204
 
 
205
PRIVATE Item *parse_item ARGS1(FILE *, fp)
 
206
{
 
207
    Item *item = NULL;
 
208
    UserDefList *user_def_list = NULL;
 
209
    AddressDefList *address_def_list = NULL;
 
210
    LexItem lex_item;
 
211
 
 
212
    lex_item = lex(fp);
 
213
    if (lex_item == LEX_ALPH_STR || lex_item == LEX_OPEN_PAREN) {
 
214
        unlex(lex_item);
 
215
        user_def_list = parse_user_part(fp);
 
216
        lex_item = lex(fp);
 
217
    }
 
218
 
 
219
    if (lex_item == LEX_AT_SIGN) {
 
220
        lex_item = lex(fp);
 
221
        if (lex_item == LEX_ALPH_STR || lex_item == LEX_TMPL_STR ||
 
222
            lex_item == LEX_OPEN_PAREN) {
 
223
            unlex(lex_item);
 
224
            address_def_list = parse_address_part(fp);
 
225
        }
 
226
        else {
 
227
            if (user_def_list) {
 
228
                HTList_delete(user_def_list);   /* @@@@ */
 
229
                user_def_list = NULL;
 
230
            }
 
231
            syntax_error(fp, "Expected address part (single address or list)",
 
232
                         lex_item);
 
233
            return NULL;
 
234
        }
 
235
    }
 
236
    else unlex(lex_item);
 
237
 
 
238
    if (!user_def_list && !address_def_list) {
 
239
        syntax_error(fp, "Empty item not allowed", lex_item);
 
240
        return NULL;
 
241
    }
 
242
    item = typecalloc(Item);
 
243
    if (item == NULL)
 
244
        outofmem(__FILE__, "parse_item");
 
245
    item->user_def_list = user_def_list;
 
246
    item->address_def_list = address_def_list;
 
247
    return item;
 
248
}
 
249
 
 
250
 
 
251
PRIVATE ItemList *parse_item_list ARGS1(FILE *, fp)
 
252
{
 
253
    ItemList *item_list = HTList_new();
 
254
    Item *item;
 
255
    LexItem lex_item;
 
256
 
 
257
    for(;;) {
 
258
        if (!(item = parse_item(fp))) {
 
259
            HTList_delete(item_list);   /* @@@@ */
 
260
            item_list = NULL;
 
261
            return NULL;
 
262
        }
 
263
        HTList_addObject(item_list, (void*)item);
 
264
        lex_item = lex(fp);
 
265
        if (lex_item != LEX_ITEM_SEP) {
 
266
            unlex(lex_item);
 
267
            return item_list;
 
268
        }
 
269
        /*
 
270
        ** Here lex_item == LEX_ITEM_SEP; after item separator it
 
271
        ** is ok to have one or more newlines (LEX_REC_SEP) and
 
272
        ** they are ignored (continuation line).
 
273
        */
 
274
        do {
 
275
            lex_item = lex(fp);
 
276
        } while (lex_item == LEX_REC_SEP);
 
277
        unlex(lex_item);
 
278
    }
 
279
}
 
280
 
 
281
 
 
282
PUBLIC GroupDef *HTAA_parseGroupDef ARGS1(FILE *, fp)
 
283
{
 
284
    ItemList *item_list = NULL;
 
285
    GroupDef *group_def = NULL;
 
286
    LexItem lex_item;
 
287
 
 
288
    if (!(item_list = parse_item_list(fp))) {
 
289
        return NULL;
 
290
    }
 
291
    group_def = typecalloc(GroupDef);
 
292
    if (group_def == NULL)
 
293
        outofmem(__FILE__, "HTAA_parseGroupDef");
 
294
    group_def->group_name = NULL;
 
295
    group_def->item_list = item_list;
 
296
 
 
297
    if ((lex_item = lex(fp)) != LEX_REC_SEP) {
 
298
        syntax_error(fp, "Garbage after group definition", lex_item);
 
299
    }
 
300
 
 
301
    return group_def;
 
302
}
 
303
 
 
304
 
 
305
PRIVATE GroupDef *parse_group_decl ARGS1(FILE *, fp)
 
306
{
 
307
    char *group_name = NULL;
 
308
    GroupDef *group_def = NULL;
 
309
    LexItem lex_item;
 
310
 
 
311
    do {
 
312
        lex_item = lex(fp);
 
313
    } while (lex_item == LEX_REC_SEP);  /* Ignore empty lines */
 
314
 
 
315
    if (lex_item != LEX_ALPH_STR) {
 
316
        if (lex_item != LEX_EOF)
 
317
            syntax_error(fp, "Expecting group name", lex_item);
 
318
        return NULL;
 
319
    }
 
320
    StrAllocCopy(group_name, HTlex_buffer);
 
321
 
 
322
    if (LEX_FIELD_SEP != (lex_item = lex(fp))) {
 
323
        syntax_error(fp, "Expecting field separator", lex_item);
 
324
        FREE(group_name);
 
325
        return NULL;
 
326
    }
 
327
 
 
328
    if (!(group_def = HTAA_parseGroupDef(fp))) {
 
329
        FREE(group_name);
 
330
        return NULL;
 
331
    }
 
332
    group_def->group_name = group_name;
 
333
 
 
334
    return group_def;
 
335
}
 
336
 
 
337
 
 
338
 
 
339
/*
 
340
** Group manipulation routines
 
341
*/
 
342
 
 
343
PRIVATE GroupDef *find_group_def ARGS2(GroupDefList *,  group_list,
 
344
                                       CONST char *,    group_name)
 
345
{
 
346
    if (group_list && group_name) {
 
347
        GroupDefList *cur = group_list;
 
348
        GroupDef *group_def;
 
349
 
 
350
        while (NULL != (group_def = (GroupDef*)HTList_nextObject(cur))) {
 
351
            if (!strcmp(group_name, group_def->group_name)) {
 
352
                return group_def;
 
353
            }
 
354
        }
 
355
    }
 
356
    return NULL;
 
357
}
 
358
 
 
359
 
 
360
PUBLIC void HTAA_resolveGroupReferences ARGS2(GroupDef *,       group_def,
 
361
                                              GroupDefList *,   group_def_list)
 
362
{
 
363
    if (group_def && group_def->item_list && group_def_list) {
 
364
        ItemList *cur1 = group_def->item_list;
 
365
        Item *item;
 
366
 
 
367
        while (NULL != (item = (Item*)HTList_nextObject(cur1))) {
 
368
            UserDefList *cur2 = item->user_def_list;
 
369
            Ref *ref;
 
370
 
 
371
            while (NULL != (ref = (Ref*)HTList_nextObject(cur2)))
 
372
                ref->translation = find_group_def(group_def_list, ref->name);
 
373
 
 
374
            /* Does NOT translate address_def_list */
 
375
        }
 
376
    }
 
377
}
 
378
 
 
379
 
 
380
PRIVATE void add_group_def ARGS2(GroupDefList *, group_def_list,
 
381
                                 GroupDef *,     group_def)
 
382
{
 
383
    HTAA_resolveGroupReferences(group_def, group_def_list);
 
384
    HTList_addObject(group_def_list, (void*)group_def);
 
385
}
 
386
 
 
387
 
 
388
PRIVATE GroupDefList *parse_group_file ARGS1(FILE *, fp)
 
389
{
 
390
    GroupDefList *group_def_list = HTList_new();
 
391
    GroupDef *group_def;
 
392
 
 
393
    while (NULL != (group_def = parse_group_decl(fp)))
 
394
        add_group_def(group_def_list, group_def);
 
395
 
 
396
    return group_def_list;
 
397
}
 
398
 
 
399
 
 
400
/*
 
401
** Trace functions
 
402
*/
 
403
 
 
404
PRIVATE void print_item ARGS1(Item *, item)
 
405
{
 
406
    if (!item)
 
407
        fprintf(tfp, "\tNULL-ITEM\n");
 
408
    else {
 
409
        UserDefList *cur1 = item->user_def_list;
 
410
        AddressDefList *cur2 = item->address_def_list;
 
411
        Ref *user_ref = (Ref*)HTList_nextObject(cur1);
 
412
        Ref *addr_ref = (Ref*)HTList_nextObject(cur2);
 
413
 
 
414
        if (user_ref) {
 
415
            fprintf(tfp, "\t[%s%s", user_ref->name,
 
416
                    (user_ref->translation ? "*REF*" : ""));
 
417
            while (NULL != (user_ref = (Ref*)HTList_nextObject(cur1)))
 
418
                fprintf(tfp, "; %s%s", user_ref->name,
 
419
                        (user_ref->translation ? "*REF*" : ""));
 
420
            fprintf(tfp, "] ");
 
421
        } else fprintf(tfp, "\tANYBODY ");
 
422
 
 
423
        if (addr_ref) {
 
424
            fprintf(tfp, "@ [%s", addr_ref->name);
 
425
            while (NULL != (addr_ref = (Ref*)HTList_nextObject(cur2)))
 
426
                fprintf(tfp, "; %s", addr_ref->name);
 
427
            fprintf(tfp, "]\n");
 
428
        } else fprintf(tfp, "@ ANYADDRESS\n");
 
429
    }
 
430
}
 
431
 
 
432
 
 
433
PRIVATE void print_item_list ARGS1(ItemList *, item_list)
 
434
{
 
435
    ItemList *cur = item_list;
 
436
    Item *item;
 
437
 
 
438
    if (!item_list)
 
439
        fprintf(tfp, "EMPTY");
 
440
    else while (NULL != (item = (Item*)HTList_nextObject(cur)))
 
441
        print_item(item);
 
442
}
 
443
 
 
444
 
 
445
PUBLIC void HTAA_printGroupDef ARGS1(GroupDef *, group_def)
 
446
{
 
447
    if (!group_def) {
 
448
        fprintf(tfp, "\nNULL RECORD\n");
 
449
        return;
 
450
    }
 
451
 
 
452
    fprintf(tfp, "\nGroup %s:\n",
 
453
            (group_def->group_name ? group_def->group_name : "NULL"));
 
454
 
 
455
    print_item_list(group_def->item_list);
 
456
    fprintf(tfp, "\n");
 
457
}
 
458
 
 
459
 
 
460
PRIVATE void print_group_def_list ARGS1(GroupDefList *, group_list)
 
461
{
 
462
    GroupDefList *cur = group_list;
 
463
    GroupDef *group_def;
 
464
 
 
465
    while (NULL != (group_def = (GroupDef*)HTList_nextObject(cur)))
 
466
        HTAA_printGroupDef(group_def);
 
467
}
 
468
 
 
469
 
 
470
 
 
471
/*
 
472
** IP address template matching
 
473
*/
 
474
 
 
475
/* PRIVATE                                              part_match()
 
476
**              MATCH ONE PART OF INET ADDRESS AGAIST
 
477
**              A PART OF MASK (inet address has 4 parts)
 
478
** ON ENTRY:
 
479
**      tcur    pointer to the beginning of template part.
 
480
**      icur    pointer to the beginning of actual inet
 
481
**              number part.
 
482
**
 
483
** ON EXIT:
 
484
**      returns YES, if match.
 
485
*/
 
486
PRIVATE BOOL part_match ARGS2(CONST char *, tcur,
 
487
                              CONST char *, icur)
 
488
{
 
489
    char required[4];
 
490
    char actual[4];
 
491
    CONST char *cur;
 
492
    int cnt;
 
493
    BOOL status;
 
494
 
 
495
    if (!tcur || !icur) return NO;
 
496
 
 
497
    cur=tcur;
 
498
    cnt=0;
 
499
    while (cnt < 3  &&  *cur && *cur != '.')
 
500
        required[cnt++] = *(cur++);
 
501
    required[cnt] = (char)0;
 
502
 
 
503
    cur=icur;
 
504
    cnt=0;
 
505
    while (cnt < 3  &&  *cur && *cur != '.')
 
506
        actual[cnt++] = *(cur++);
 
507
    actual[cnt] = (char)0;
 
508
 
 
509
    status = HTAA_templateMatch(required, actual);
 
510
    CTRACE((tfp, "part_match: req: '%s' act: '%s' match: %s\n",
 
511
                required, actual, (status ? "yes" : "no")));
 
512
 
 
513
    return status;
 
514
}
 
515
 
 
516
 
 
517
 
 
518
/* PRIVATE                                              ip_number_match()
 
519
**              MATCH INET NUMBER AGAINST AN INET NUMBER MASK
 
520
** ON ENTRY:
 
521
**      template        mask to match agaist, e.g., 128.141.*.*
 
522
**      the_inet_addr   actual inet address, e.g., 128.141.201.74
 
523
**
 
524
** ON EXIT:
 
525
**      returns         YES, if match;  NO, if not.
 
526
*/
 
527
PRIVATE BOOL ip_number_match ARGS2(CONST char *,        template,
 
528
                                   CONST char *,        the_inet_addr)
 
529
{
 
530
    CONST char *tcur = template;
 
531
    CONST char *icur = the_inet_addr;
 
532
    int cnt;
 
533
 
 
534
    for (cnt=0; cnt<4; cnt++) {
 
535
        if (!tcur || !icur || !part_match(tcur, icur))
 
536
            return NO;
 
537
        if (NULL != (tcur = strchr(tcur, '.'))) tcur++;
 
538
        if (NULL != (icur = strchr(icur, '.'))) icur++;
 
539
    }
 
540
    return YES;
 
541
}
 
542
 
 
543
 
 
544
 
 
545
/* PRIVATE                                              is_domain_mask()
 
546
**              DETERMINE IF A GIVEN MASK IS A
 
547
**              DOMAIN NAME MASK OR AN INET NUMBER MASK
 
548
** ON ENTRY:
 
549
**      mask    either a domain name mask,
 
550
**              e.g.
 
551
**                      *.cern.ch
 
552
**
 
553
**              or an inet number mask,
 
554
**              e.g.
 
555
**                      128.141.*.*
 
556
**
 
557
** ON EXIT:
 
558
**      returns YES, if mask is a domain name mask.
 
559
**              NO, if it is an inet number mask.
 
560
*/
 
561
PRIVATE BOOL is_domain_mask ARGS1(CONST char *, mask)
 
562
{
 
563
    CONST char *cur = mask;
 
564
 
 
565
    if (!mask) return NO;
 
566
 
 
567
    while (*cur) {
 
568
        if (*cur != '.'  &&  *cur != '*'  &&  (*cur < '0' || *cur > '9'))
 
569
            return YES; /* Even one non-digit makes it a domain name mask */
 
570
        cur++;
 
571
    }
 
572
    return NO;  /* All digits and dots, so it is an inet number mask */
 
573
}
 
574
 
 
575
 
 
576
 
 
577
/* PRIVATE                                                      ip_mask_match()
 
578
**              MATCH AN IP NUMBER MASK OR IP NAME MASK
 
579
**              AGAINST ACTUAL IP NUMBER OR IP NAME
 
580
**
 
581
** ON ENTRY:
 
582
**      mask            mask.  Mask may be either an inet number
 
583
**                      mask or a domain name mask,
 
584
**                      e.g.
 
585
**                              128.141.*.*
 
586
**                      or
 
587
**                              *.cern.ch
 
588
**
 
589
**      ip_number       IP number of connecting host.
 
590
**      ip_name         IP name of the connecting host.
 
591
**
 
592
** ON EXIT:
 
593
**      returns         YES, if hostname/internet number
 
594
**                      matches the mask.
 
595
**                      NO, if no match (no fire).
 
596
*/
 
597
PRIVATE BOOL ip_mask_match ARGS3(CONST char *,  mask,
 
598
                                 CONST char *,  ip_number,
 
599
                                 CONST char *,  ip_name)
 
600
{
 
601
    if (mask && (ip_number || ip_name)) {
 
602
        if (is_domain_mask(mask)) {
 
603
            if (HTAA_templateMatch(mask, ip_name))
 
604
                return YES;
 
605
        }
 
606
        else {
 
607
            if (ip_number_match(mask, ip_number))
 
608
                return YES;
 
609
        }
 
610
    }
 
611
    return NO;
 
612
}
 
613
 
 
614
 
 
615
 
 
616
 
 
617
PRIVATE BOOL ip_in_def_list ARGS3(AddressDefList *,     address_def_list,
 
618
                                  char *,               ip_number,
 
619
                                  char *,               ip_name)
 
620
{
 
621
    if (address_def_list && (ip_number || ip_name)) {
 
622
        AddressDefList *cur = address_def_list;
 
623
        Ref *ref;
 
624
 
 
625
        while (NULL != (ref = (Ref*)HTList_nextObject(cur))) {
 
626
            /* Value of ref->translation is ignored, i.e., */
 
627
            /* no recursion for ip address tamplates.     */
 
628
            if (ip_mask_match(ref->name, ip_number, ip_name))
 
629
                return YES;
 
630
        }
 
631
    }
 
632
    return NO;
 
633
}
 
634
 
 
635
 
 
636
/*
 
637
** Group file cached reading
 
638
*/
 
639
 
 
640
typedef struct {
 
641
    char *         group_filename;
 
642
    GroupDefList * group_list;
 
643
} GroupCache;
 
644
 
 
645
typedef HTList GroupCacheList;
 
646
 
 
647
PRIVATE GroupCacheList *group_cache_list = NULL;
 
648
 
 
649
 
 
650
PUBLIC GroupDefList *HTAA_readGroupFile ARGS1(CONST char *, filename)
 
651
{
 
652
    FILE *fp;
 
653
    GroupCache *group_cache;
 
654
 
 
655
    if (isEmpty(filename)) return NULL;
 
656
 
 
657
    if (!group_cache_list)
 
658
        group_cache_list = HTList_new();
 
659
    else {
 
660
        GroupCacheList *cur = group_cache_list;
 
661
 
 
662
        while (NULL != (group_cache = (GroupCache*)HTList_nextObject(cur))) {
 
663
            if (!strcmp(filename, group_cache->group_filename)) {
 
664
                CTRACE((tfp, "%s '%s' %s\n",
 
665
                            "HTAA_readGroupFile: group file",
 
666
                            filename, "already found in cache"));
 
667
                return group_cache->group_list;
 
668
            } /* if cache match */
 
669
        } /* while cached files remain */
 
670
    } /* cache exists */
 
671
 
 
672
    CTRACE((tfp, "HTAA_readGroupFile: reading group file `%s'\n",
 
673
                filename));
 
674
 
 
675
    if (!(fp = fopen(filename, TXT_R))) {
 
676
        CTRACE((tfp, "%s '%s'\n",
 
677
                    "HTAA_readGroupFile: unable to open group file",
 
678
                    filename));
 
679
        return NULL;
 
680
    }
 
681
 
 
682
    if ((group_cache = typecalloc(GroupCache)) == 0)
 
683
        outofmem(__FILE__, "HTAA_readGroupFile");
 
684
 
 
685
    group_cache->group_filename = NULL;
 
686
    StrAllocCopy(group_cache->group_filename, filename);
 
687
    group_cache->group_list = parse_group_file(fp);
 
688
    HTList_addObject(group_cache_list, (void*)group_cache);
 
689
    fclose(fp);
 
690
 
 
691
    CTRACE((tfp, "Read group file '%s', results follow:\n", filename));
 
692
    if (TRACE)
 
693
        print_group_def_list(group_cache->group_list);
 
694
 
 
695
    return group_cache->group_list;
 
696
}
 
697
 
 
698
 
 
699
/* PUBLIC                                       HTAA_userAndInetInGroup()
 
700
**              CHECK IF USER BELONGS TO TO A GIVEN GROUP
 
701
**              AND THAT THE CONNECTION COMES FROM AN
 
702
**              ADDRESS THAT IS ALLOWED BY THAT GROUP
 
703
** ON ENTRY:
 
704
**      group           the group definition structure.
 
705
**      username        connecting user.
 
706
**      ip_number       browser host IP number, optional.
 
707
**      ip_name         browser host IP name, optional.
 
708
**                      However, one of ip_number or ip_name
 
709
**                      must be given.
 
710
** ON EXIT:
 
711
**      returns         HTAA_IP_MASK, if IP address mask was
 
712
**                      reason for failing.
 
713
**                      HTAA_NOT_MEMBER, if user does not belong
 
714
**                      to the group.
 
715
**                      HTAA_OK if both IP address and user are ok.
 
716
*/
 
717
PUBLIC HTAAFailReasonType HTAA_userAndInetInGroup ARGS4(GroupDef *, group,
 
718
                                                        char *,     username,
 
719
                                                        char *,     ip_number,
 
720
                                                        char *,     ip_name)
 
721
{
 
722
    HTAAFailReasonType reason = HTAA_NOT_MEMBER;
 
723
 
 
724
    if (group && username) {
 
725
        ItemList *cur1 = group->item_list;
 
726
        Item *item;
 
727
 
 
728
        while (NULL != (item = (Item*)HTList_nextObject(cur1))) {
 
729
            if (!item->address_def_list ||      /* Any address allowed */
 
730
                ip_in_def_list(item->address_def_list, ip_number, ip_name)) {
 
731
 
 
732
                if (!item->user_def_list)       /* Any user allowed */
 
733
                    return HTAA_OK;
 
734
                else {
 
735
                    UserDefList *cur2 = item->user_def_list;
 
736
                    Ref *ref;
 
737
 
 
738
                    while (NULL != (ref = (Ref*)HTList_nextObject(cur2))) {
 
739
 
 
740
                        if (ref->translation) { /* Group, check recursively */
 
741
                            reason = HTAA_userAndInetInGroup(ref->translation,
 
742
                                                             username,
 
743
                                                             ip_number,ip_name);
 
744
                            if (reason == HTAA_OK)
 
745
                                return HTAA_OK;
 
746
                        }
 
747
                        else {  /* Username, check directly */
 
748
                            if (username && *username &&
 
749
                                0==strcmp(ref->name, username))
 
750
                                return HTAA_OK;
 
751
                        }
 
752
                    } /* Every user/group name in this group */
 
753
                } /* search for username */
 
754
            } /* IP address ok */
 
755
            else {
 
756
                reason = HTAA_IP_MASK;
 
757
            }
 
758
        } /* while items in group */
 
759
    } /* valid parameters */
 
760
 
 
761
    return reason;              /* No match, or invalid parameters */
 
762
}
 
763
 
 
764
 
 
765
PUBLIC void GroupDef_delete ARGS1(GroupDef *, group_def)
 
766
{
 
767
    if (group_def) {
 
768
        FREE(group_def->group_name);
 
769
        if (group_def->item_list) {
 
770
            HTList_delete(group_def->item_list);        /* @@@@ */
 
771
            group_def->item_list = NULL;
 
772
        }
 
773
        FREE(group_def);
 
774
    }
 
775
}
 
776