home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / www / library / implemen / htgroup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  18.8 KB  |  775 lines

  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"capalloc.h"
  46. #include"capstdio.h"
  47. #include <string.h>
  48.  
  49. #include "HTUtils.h"
  50. #include "HTAAUtil.h"
  51. #include "HTLex.h"    /* Lexical analysor    */
  52. #include "HTGroup.h"    /* Implemented here    */
  53.  
  54.  
  55. /*
  56. ** Group file parser
  57. */
  58.  
  59. typedef HTList UserDefList;
  60. typedef HTList AddressDefList;
  61.  
  62. typedef struct {
  63.     UserDefList *    user_def_list;
  64.     AddressDefList *    address_def_list;
  65. } Item;
  66.  
  67. typedef struct {
  68.     char *    name;
  69.     GroupDef *    translation;
  70. } Ref;
  71.  
  72.     
  73.  
  74. PRIVATE void syntax_error ARGS3(FILE *,     fp,
  75.                 char *,     msg,
  76.                 LexItem, lex_item)
  77. {
  78.     char buffer[41];
  79.     int cnt = 0;
  80.     char ch;
  81.  
  82.     while ((ch = getc(fp)) != EOF  &&  ch != '\n')
  83.     if (cnt < 40) buffer[cnt++] = ch;
  84.     buffer[cnt] = (char)0;
  85.  
  86. #ifndef RELEASE
  87.     if (TRACE)
  88.     fprintf(stderr, "%s %d before: '%s'\nHTGroup.c: %s (got %s)\n",
  89.         "HTGroup.c: Syntax error in rule file at line",
  90.         lex_line, buffer, msg, lex_verbose(lex_item));
  91. #endif /* RELEASE */
  92.     lex_line++;
  93. }
  94.  
  95.  
  96. PRIVATE AddressDefList *parse_address_part ARGS1(FILE *, fp)
  97. {
  98.     AddressDefList *address_def_list = NULL;
  99.     LexItem lex_item;
  100.     BOOL only_one = NO;
  101.  
  102.     lex_item = lex(fp);
  103.     if (lex_item == LEX_ALPH_STR || lex_item == LEX_TMPL_STR)
  104.     only_one = YES;
  105.     else if (lex_item != LEX_OPEN_PAREN  ||
  106.          ((lex_item = lex(fp)) != LEX_ALPH_STR &&
  107.           lex_item != LEX_TMPL_STR)) {
  108.     syntax_error(fp, "Expecting a single address or '(' beginning list",
  109.              lex_item);
  110.     return NULL;
  111.     }
  112.     address_def_list = HTList_new();
  113.  
  114.     for(;;) {
  115.     Ref *ref = (Ref*)malloc(sizeof(Ref));
  116.     ref->name = NULL;
  117.     ref->translation = NULL;
  118.     StrAllocCopy(ref->name, lex_buffer);
  119.     
  120.     HTList_addObject(address_def_list, (void*)ref);
  121.  
  122.     if (only_one || (lex_item = lex(fp)) != LEX_ITEM_SEP)
  123.         break;
  124.     /*
  125.     ** Here lex_item == LEX_ITEM_SEP; after item separator it
  126.     ** is ok to have one or more newlines (LEX_REC_SEP) and
  127.     ** they are ignored (continuation line).
  128.     */
  129.     do {
  130.         lex_item = lex(fp);
  131.     } while (lex_item == LEX_REC_SEP);
  132.  
  133.     if (lex_item != LEX_ALPH_STR && lex_item != LEX_TMPL_STR) {
  134.         syntax_error(fp, "Expecting an address template", lex_item);
  135.         HTList_delete(address_def_list);
  136.         return NULL;
  137.     }
  138.     }
  139.  
  140.     if (!only_one && lex_item != LEX_CLOSE_PAREN) {
  141.     HTList_delete(address_def_list);
  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 = (Ref*)malloc(sizeof(Ref));
  168.     ref->name = NULL;
  169.     ref->translation = NULL;
  170.     StrAllocCopy(ref->name, lex_buffer);
  171.  
  172.     HTList_addObject(user_def_list, (void*)ref);
  173.     
  174.     if (only_one || (lex_item = lex(fp)) != LEX_ITEM_SEP)
  175.         break;
  176.     /*
  177.     ** Here lex_item == LEX_ITEM_SEP; after item separator it
  178.     ** is ok to have one or more newlines (LEX_REC_SEP) and
  179.     ** they are ignored (continuation line).
  180.     */
  181.     do {
  182.         lex_item = lex(fp);
  183.     } while (lex_item == LEX_REC_SEP);
  184.  
  185.     if (lex_item != LEX_ALPH_STR) {
  186.         syntax_error(fp, "Expecting user or group name", lex_item);
  187.         HTList_delete(user_def_list);
  188.         return NULL;
  189.     }
  190.     }
  191.  
  192.     if (!only_one && lex_item != LEX_CLOSE_PAREN) {
  193.     HTList_delete(user_def_list);
  194.     syntax_error(fp, "Expecting ')' closing user/group list", lex_item);
  195.     return NULL;
  196.     }
  197.     return user_def_list;
  198. }
  199.  
  200.  
  201. PRIVATE Item *parse_item ARGS1(FILE *, fp)
  202. {
  203.     Item *item = NULL;
  204.     UserDefList *user_def_list = NULL;
  205.     AddressDefList *address_def_list = NULL;
  206.     LexItem lex_item;
  207.  
  208.     lex_item = lex(fp);
  209.     if (lex_item == LEX_ALPH_STR || lex_item == LEX_OPEN_PAREN) {
  210.     unlex(lex_item);
  211.     user_def_list = parse_user_part(fp);
  212.     lex_item = lex(fp);
  213.     }
  214.  
  215.     if (lex_item == LEX_AT_SIGN) {
  216.     lex_item = lex(fp);
  217.     if (lex_item == LEX_ALPH_STR || lex_item == LEX_TMPL_STR ||
  218.         lex_item == LEX_OPEN_PAREN) {
  219.         unlex(lex_item);
  220.         address_def_list = parse_address_part(fp);
  221.     }
  222.     else {
  223.         if (user_def_list) HTList_delete(user_def_list);    /* @@@@ */
  224.         syntax_error(fp, "Expected address part (single address or list)",
  225.              lex_item);
  226.         return NULL;
  227.     }
  228.     }
  229.     else unlex(lex_item);
  230.  
  231.     if (!user_def_list && !address_def_list) {
  232.     syntax_error(fp, "Empty item not allowed", lex_item);
  233.     return NULL;
  234.     }
  235.     item = (Item*)malloc(sizeof(Item));
  236.     item->user_def_list = user_def_list;
  237.     item->address_def_list = address_def_list;
  238.     return item;
  239. }
  240.  
  241.  
  242. PRIVATE ItemList *parse_item_list ARGS1(FILE *, fp)
  243. {
  244.     ItemList *item_list = HTList_new();
  245.     Item *item;
  246.     LexItem lex_item;
  247.  
  248.     for(;;) {
  249.     if (!(item = parse_item(fp))) {
  250.         HTList_delete(item_list);    /* @@@@ */
  251.         return NULL;
  252.     }
  253.     HTList_addObject(item_list, (void*)item);
  254.     lex_item = lex(fp);
  255.     if (lex_item != LEX_ITEM_SEP) {
  256.         unlex(lex_item);
  257.         return item_list;
  258.     }
  259.     /*
  260.     ** Here lex_item == LEX_ITEM_SEP; after item separator it
  261.     ** is ok to have one or more newlines (LEX_REC_SEP) and
  262.     ** they are ignored (continuation line).
  263.     */
  264.     do {
  265.         lex_item = lex(fp);
  266.     } while (lex_item == LEX_REC_SEP);
  267.     unlex(lex_item);
  268.     }
  269. }
  270.  
  271.  
  272. PUBLIC GroupDef *HTAA_parseGroupDef ARGS1(FILE *, fp)
  273. {
  274.     ItemList *item_list = NULL;
  275.     GroupDef *group_def = NULL;
  276.     LexItem lex_item;
  277.  
  278.     if (!(item_list = parse_item_list(fp))) {
  279.     return NULL;
  280.     }
  281.     group_def = (GroupDef*)malloc(sizeof(GroupDef));
  282.     group_def->group_name = NULL;
  283.     group_def->item_list = item_list;
  284.  
  285.     if ((lex_item = lex(fp)) != LEX_REC_SEP) {
  286.     syntax_error(fp, "Garbage after group definition", lex_item);
  287.     }
  288.     
  289.     return group_def;
  290. }    
  291.  
  292.  
  293. PRIVATE GroupDef *parse_group_decl ARGS1(FILE *, fp)
  294. {
  295.     char *group_name = NULL;
  296.     GroupDef *group_def = NULL;
  297.     LexItem lex_item;
  298.  
  299.     do {
  300.     lex_item = lex(fp);
  301.     } while (lex_item == LEX_REC_SEP);    /* Ignore empty lines */
  302.  
  303.     if (lex_item != LEX_ALPH_STR) {
  304.     if (lex_item != LEX_EOF)
  305.         syntax_error(fp, "Expecting group name", lex_item);
  306.     return NULL;
  307.     }
  308.     StrAllocCopy(group_name, lex_buffer);
  309.  
  310.     if (LEX_FIELD_SEP != (lex_item = lex(fp))) {
  311.     syntax_error(fp, "Expecting field separator", lex_item);
  312.     free(group_name);
  313.     return NULL;
  314.     }
  315.  
  316.     if (!(group_def = HTAA_parseGroupDef(fp))) {
  317.     free(group_name);
  318.     return NULL;
  319.     }
  320.     group_def->group_name = group_name;
  321.  
  322.     return group_def;
  323. }
  324.     
  325.  
  326.  
  327. /*
  328. ** Group manipulation routines
  329. */
  330.  
  331. PRIVATE GroupDef *find_group_def ARGS2(GroupDefList *,    group_list,
  332.                        CONST char *,    group_name)
  333. {
  334.     if (group_list && group_name) {
  335.     GroupDefList *cur = group_list;
  336.     GroupDef *group_def;
  337.  
  338.     while (NULL != (group_def = (GroupDef*)HTList_nextObject(cur))) {
  339.         if (!strcmp(group_name, group_def->group_name)) {
  340.         return group_def;
  341.             }
  342.         }
  343.     }
  344.     return NULL;
  345. }
  346.  
  347.  
  348. PUBLIC void HTAA_resolveGroupReferences ARGS2(GroupDef *,    group_def,
  349.                           GroupDefList *,    group_def_list)
  350. {
  351.     if (group_def && group_def->item_list && group_def_list) {
  352.     ItemList *cur1 = group_def->item_list;
  353.     Item *item;
  354.  
  355.     while (NULL != (item = (Item*)HTList_nextObject(cur1))) {
  356.         UserDefList *cur2 = item->user_def_list;
  357.         Ref *ref;
  358.  
  359.         while (NULL != (ref = (Ref*)HTList_nextObject(cur2)))
  360.         ref->translation = find_group_def(group_def_list, ref->name);
  361.  
  362.         /* Does NOT translate address_def_list */
  363.     }
  364.     }
  365. }
  366.  
  367.  
  368. PRIVATE void add_group_def ARGS2(GroupDefList *, group_def_list,
  369.                  GroupDef *,     group_def)
  370. {
  371.     HTAA_resolveGroupReferences(group_def, group_def_list);
  372.     HTList_addObject(group_def_list, (void*)group_def);
  373. }
  374.  
  375.  
  376. PRIVATE GroupDefList *parse_group_file ARGS1(FILE *, fp)
  377. {
  378.     GroupDefList *group_def_list = HTList_new();
  379.     GroupDef *group_def;
  380.     
  381.     while (NULL != (group_def = parse_group_decl(fp)))
  382.     add_group_def(group_def_list, group_def);
  383.     
  384.     return group_def_list;
  385. }
  386.  
  387.  
  388. /*
  389. ** Trace functions
  390. */
  391.  
  392. PRIVATE void print_item ARGS1(Item *, item)
  393. {
  394.     if (!item)
  395.     fprintf(stderr, "\tNULL-ITEM\n");
  396.     else {
  397.     UserDefList *cur1 = item->user_def_list;
  398.     AddressDefList *cur2 = item->address_def_list;
  399.     Ref *user_ref = (Ref*)HTList_nextObject(cur1);
  400.     Ref *addr_ref = (Ref*)HTList_nextObject(cur2);
  401.  
  402.     if (user_ref) {
  403.         fprintf(stderr, "\t[%s%s", user_ref->name,
  404.             (user_ref->translation ? "*REF*" : ""));
  405.         while (NULL != (user_ref = (Ref*)HTList_nextObject(cur1)))
  406.         fprintf(stderr, "; %s%s", user_ref->name,
  407.             (user_ref->translation ? "*REF*" : ""));
  408.         fprintf(stderr, "] ");
  409.     } else fprintf(stderr, "\tANYBODY ");
  410.  
  411.     if (addr_ref) {
  412.         fprintf(stderr, "@ [%s", addr_ref->name);
  413.         while (NULL != (addr_ref = (Ref*)HTList_nextObject(cur2)))
  414.         fprintf(stderr, "; %s", addr_ref->name);
  415.         fprintf(stderr, "]\n");
  416.     } else fprintf(stderr, "@ ANYADDRESS\n");
  417.     }
  418. }
  419.  
  420.  
  421. PRIVATE void print_item_list ARGS1(ItemList *, item_list)
  422. {
  423.     ItemList *cur = item_list;
  424.     Item *item;
  425.  
  426.     if (!item_list)
  427.     fprintf(stderr, "EMPTY");
  428.     else while (NULL != (item = (Item*)HTList_nextObject(cur)))
  429.     print_item(item);
  430. }
  431.  
  432.  
  433. PUBLIC void HTAA_printGroupDef ARGS1(GroupDef *, group_def)
  434. {
  435.     if (!group_def) {
  436.     fprintf(stderr, "\nNULL RECORD\n");
  437.     return;
  438.     }
  439.  
  440.     fprintf(stderr, "\nGroup %s:\n",
  441.         (group_def->group_name ? group_def->group_name : "NULL"));
  442.  
  443.     print_item_list(group_def->item_list);
  444.     fprintf(stderr, "\n");
  445. }
  446.  
  447.  
  448. PRIVATE void print_group_def_list ARGS1(GroupDefList *, group_list)
  449. {
  450.     GroupDefList *cur = group_list;
  451.     GroupDef *group_def;
  452.     
  453.     while (NULL != (group_def = (GroupDef*)HTList_nextObject(cur)))
  454.     HTAA_printGroupDef(group_def);
  455. }
  456.  
  457.  
  458.  
  459. /*
  460. ** IP address template matching
  461. */
  462.  
  463. /* PRIVATE                        part_match()
  464. **        MATCH ONE PART OF INET ADDRESS AGAIST
  465. **        A PART OF MASK (inet address has 4 parts)
  466. ** ON ENTRY:
  467. **    tcur    pointer to the beginning of template part.
  468. **    icur    pointer to the beginning of actual inet
  469. **        number part.
  470. **
  471. ** ON EXIT:
  472. **    returns    YES, if match.
  473. */
  474. PRIVATE BOOL part_match ARGS2(CONST char *, tcur,
  475.                   CONST char *, icur)
  476. {
  477.     char required[4];
  478.     char actual[4];
  479.     CONST char *cur;
  480.     int cnt;
  481.  
  482.     if (!tcur || !icur) return NO;
  483.  
  484.     cur=tcur;
  485.     cnt=0;
  486.     while (cnt < 3  &&  *cur && *cur != '.')
  487.     required[cnt++] = *(cur++);
  488.     required[cnt] = (char)0;
  489.  
  490.     cur=icur;
  491.     cnt=0;
  492.     while (cnt < 3  &&  *cur && *cur != '.')
  493.     actual[cnt++] = *(cur++);
  494.     actual[cnt] = (char)0;
  495. #ifndef RELEASE
  496.     if (TRACE) {
  497.     BOOL status = HTAA_templateMatch(required, actual);
  498.     fprintf(stderr, "part_match: req: '%s' act: '%s' match: %s\n",
  499.         required, actual, (status ? "yes" : "no"));
  500.     return status;
  501.     }
  502. #endif /* RELEASE */
  503.  
  504.     return HTAA_templateMatch(required, actual);
  505. }
  506.  
  507.  
  508.  
  509. /* PRIVATE                        ip_number_match()
  510. **        MATCH INET NUMBER AGAINST AN INET NUMBER MASK
  511. ** ON ENTRY:
  512. **    template    mask to match agaist, e.g. 128.141.*.*
  513. **    inet_addr    actual inet address, e.g. 128.141.201.74
  514. **
  515. ** ON EXIT:
  516. **    returns        YES, if match;  NO, if not.
  517. */
  518. PRIVATE BOOL ip_number_match ARGS2(CONST char *,    template,
  519.                    CONST char *,    inet_addr)
  520. {
  521.     CONST char *tcur = template;
  522.     CONST char *icur = inet_addr;
  523.     int cnt;
  524.     
  525.     for (cnt=0; cnt<4; cnt++) {
  526.     if (!tcur || !icur || !part_match(tcur, icur))
  527.         return NO;
  528.     if (NULL != (tcur = strchr(tcur, '.'))) tcur++;
  529.     if (NULL != (icur = strchr(icur, '.'))) icur++;
  530.     }
  531.     return YES;
  532. }
  533.  
  534.  
  535.  
  536. /* PRIVATE                        is_domain_mask()
  537. **        DETERMINE IF A GIVEN MASK IS A
  538. **        DOMAIN NAME MASK OR AN INET NUMBER MASK
  539. ** ON ENTRY:
  540. **    mask    either a domain name mask,
  541. **        e.g.
  542. **            *.cern.ch
  543. **
  544. **        or an inet number mask,
  545. **        e.g.
  546. **            128.141.*.*
  547. **
  548. ** ON EXIT:
  549. **    returns    YES, if mask is a domain name mask.
  550. **        NO, if it is an inet number mask.
  551. */
  552. PRIVATE BOOL is_domain_mask ARGS1(CONST char *,    mask)
  553. {
  554.     CONST char *cur = mask;
  555.  
  556.     if (!mask) return NO;
  557.  
  558.     while (*cur) {
  559.     if (*cur != '.'  &&  *cur != '*'  &&  (*cur < '0' || *cur > '9'))
  560.         return YES;    /* Even one non-digit makes it a domain name mask */
  561.     cur++;
  562.     }
  563.     return NO;    /* All digits and dots, so it is an inet number mask */
  564. }
  565.  
  566.  
  567.  
  568. /* PRIVATE                            ip_mask_match()
  569. **        MATCH AN IP NUMBER MASK OR IP NAME MASK
  570. **        AGAINST ACTUAL IP NUMBER OR IP NAME
  571. **        
  572. ** ON ENTRY:
  573. **    mask        mask. Mask may be either an inet number
  574. **            mask or a domain name mask,
  575. **            e.g.
  576. **                128.141.*.*
  577. **            or
  578. **                *.cern.ch
  579. **
  580. **    ip_number    IP number of connecting host.
  581. **    ip_name        IP name of the connecting host.
  582. **
  583. ** ON EXIT:
  584. **    returns        YES, if hostname/internet number
  585. **            matches the mask.
  586. **            NO, if no match (no fire).
  587. */
  588. PRIVATE BOOL ip_mask_match ARGS3(CONST char *,    mask,
  589.                  CONST char *,    ip_number,
  590.                  CONST char *,    ip_name)
  591. {
  592.     if (mask && (ip_number || ip_name)) {
  593.     if (is_domain_mask(mask)) {
  594.         if (HTAA_templateMatch(mask, ip_name))
  595.         return YES;
  596.     }
  597.     else {
  598.         if (ip_number_match(mask, ip_number))
  599.         return YES;
  600.     }
  601.     }
  602.     return NO;
  603. }
  604.  
  605.  
  606.  
  607.  
  608. PRIVATE BOOL ip_in_def_list ARGS3(AddressDefList *,    address_def_list,
  609.                   char *,        ip_number,
  610.                   char *,        ip_name)
  611. {
  612.     if (address_def_list && (ip_number || ip_name)) {
  613.     AddressDefList *cur = address_def_list;
  614.     Ref *ref;
  615.  
  616.     while (NULL != (ref = (Ref*)HTList_nextObject(cur))) {
  617.         /* Value of ref->translation is ignored, i.e. */
  618.         /* no recursion for ip address tamplates.      */
  619.         if (ip_mask_match(ref->name, ip_number, ip_name))
  620.         return YES;
  621.     }
  622.     }
  623.     return NO;
  624. }
  625.  
  626.  
  627. /*
  628. ** Group file cached reading
  629. */
  630.  
  631. typedef struct {
  632.     char *       group_filename;
  633.     GroupDefList * group_list;
  634. } GroupCache;
  635.  
  636. typedef HTList GroupCacheList;
  637.  
  638. PRIVATE GroupCacheList *group_cache_list = NULL;
  639.  
  640.  
  641. PUBLIC GroupDefList *HTAA_readGroupFile ARGS1(CONST char *, filename)
  642. {
  643.     FILE *fp;
  644.     GroupCache *group_cache;
  645.  
  646.     if (!filename || !*filename) return NULL;
  647.  
  648.     if (!group_cache_list)
  649.     group_cache_list = HTList_new();
  650.     else {
  651.     GroupCacheList *cur = group_cache_list;
  652.  
  653.     while (NULL != (group_cache = (GroupCache*)HTList_nextObject(cur))) {
  654.         if (!strcmp(filename, group_cache->group_filename)) {
  655. #ifndef RELEASE
  656.         if (TRACE) fprintf(stderr, "%s '%s' %s\n",
  657.                    "HTAA_readGroupFile: group file",
  658.                    filename, "already found in cache");
  659. #endif /* RELEASE */
  660.         return group_cache->group_list;
  661.         } /* if cache match */
  662.     } /* while cached files remain */
  663.     } /* cache exists */
  664.  
  665. #ifndef RELEASE
  666.     if (TRACE) fprintf(stderr, "HTAA_readGroupFile: reading group file `%s'\n",
  667.                filename);
  668. #endif /* RELEASE */
  669.  
  670.     if (!(fp = fopen(filename, "r"))) {
  671. #ifndef RELEASE
  672.     if (TRACE) fprintf(stderr, "%s '%s'\n",
  673.                "HTAA_readGroupFile: unable to open group file",
  674.                filename);
  675. #endif /* RELEASE */
  676.     return NULL;
  677.     }
  678.  
  679.     if (!(group_cache = (GroupCache*)malloc(sizeof(GroupCache))))
  680.     outofmem(__FILE__, "HTAA_readGroupFile");
  681.  
  682.     group_cache->group_filename = NULL;
  683.     StrAllocCopy(group_cache->group_filename, filename);
  684.     group_cache->group_list = parse_group_file(fp);
  685.     HTList_addObject(group_cache_list, (void*)group_cache);
  686.     fclose(fp);
  687.  
  688. #ifndef RELEASE
  689.     if (TRACE) {
  690.     fprintf(stderr, "Read group file '%s', results follow:\n", filename);
  691.     print_group_def_list(group_cache->group_list);
  692.     }
  693. #endif /* RELEASE */
  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.     free(group_def);
  772.     }
  773. }
  774.  
  775.