PennMUSH Community

Changeset 1062

Show
Ignore:
Timestamp:
08/05/07 02:52:17 (1 year ago)
Author:
shawnw
Message:

sitelock improvements

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • 1.8.3/branches/devel/CHANGES.183

    r1054 r1062  
    2626   algorithm, with constant-time lookups even in the worst case. 
    2727   (And appears to have generally faster lookup even in normal usage.) 
    28  
     28 * Regular expression @sitelocks save the compiled regexp instead of 
     29   recompiling every time the rule is tested. 
     30  
    2931Fixes: 
    3032 * decode64() does better validation of its input.  
    3133 * Various compile fixes reported by Interevis and Kimiko. 
    3234   Win32 patched by Intrevis. 
     35 * @sitelock does better error reporting. 
    3336 
    3437Version 1.8.3 patchlevel 4                      July 9, 2007 
  • 1.8.3/branches/devel/hdrs/access.h

    r905 r1062  
    1010  char comment[BUFFER_LEN];     /**< A comment about the rule */ 
    1111  dbref who;                    /**< Who created this rule if sitelock used */ 
    12   int can;                      /**< Bitflags of what the host can do */ 
    13   int cant;                     /**< Bitflags of what the host can't do */ 
     12  uint32_t can;                      /**< Bitflags of what the host can do */ 
     13  uint32_t cant;                     /**< Bitflags of what the host can't do */ 
     14  pcre *re;                     /**< Compiled regexp */ 
    1415  struct access *next;          /**< Pointer to next rule in the list */ 
    1516}; 
     
    1718 
    1819/* These flags are can/can't - a site may or may not be allowed to do them */ 
    19 #define ACS_CONNECT     0x1     /* Connect to non-guests */ 
    20 #define ACS_CREATE      0x2     /* Create new players */ 
    21 #define ACS_GUEST       0x4     /* Connect to guests */ 
    22 #define ACS_REGISTER    0x8     /* Site can use the 'register' command */ 
     20#define ACS_CONNECT     0x1U     /* Connect to non-guests */ 
     21#define ACS_CREATE      0x2U     /* Create new players */ 
     22#define ACS_GUEST       0x4U     /* Connect to guests */ 
     23#define ACS_REGISTER    0x8U     /* Site can use the 'register' command */ 
    2324/* These flags are set in the 'can' bit, but they mark special processing */ 
    24 #define ACS_SITELOCK    0x10    /* Marker for where to insert @sitelock */ 
    25 #define ACS_SUSPECT     0x20    /* All players from this site get SUSPECT */ 
    26 #define ACS_DENY_SILENT 0x40    /* Don't log failed attempts */ 
    27 #define ACS_REGEXP      0x80    /* Treat the host pattern as a regexp */ 
     25#define ACS_SITELOCK    0x10U    /* Marker for where to insert @sitelock */ 
     26#define ACS_SUSPECT     0x20U    /* All players from this site get SUSPECT */ 
     27#define ACS_DENY_SILENT 0x40U    /* Don't log failed attempts */ 
     28#define ACS_REGEXP      0x80U    /* Treat the host pattern as a regexp */ 
    2829 
    29 #define ACS_GOD         0x100   /* God can connect from this site */ 
    30 #define ACS_WIZARD      0x200   /* Wizards can connect from this site */ 
    31 #define ACS_ADMIN       0x400   /* Admins can connect from this site */ 
     30#define ACS_GOD         0x100U   /* God can connect from this site */ 
     31#define ACS_WIZARD      0x200U   /* Wizards can connect from this site */ 
     32#define ACS_ADMIN       0x400U   /* Admins can connect from this site */ 
    3233 
    3334/* This is the usual default access */ 
     
    4546 
    4647/* Public functions */ 
    47 int read_access_file(void); 
     48bool read_access_file(void); 
    4849void write_access_file(void); 
    49 int site_can_access(const char *hname, int flag, dbref who); 
     50bool site_can_access(const char *hname, uint32_t flag, dbref who); 
    5051struct access *site_check_access(const char *hname, dbref who, int *rulenum); 
    51 int format_access(struct access *ap, int rulenum, 
     52void format_access(struct access *ap, int rulenum, 
    5253                  dbref who 
    5354                  __attribute__ ((__unused__)), char *buff, char **bp); 
    54 int add_access_sitelock(dbref player, const char *host, dbref who, int can
    55                         int cant); 
     55bool add_access_sitelock(dbref player, const char *host, dbref who
     56                        uint32_t can, uint32_t cant); 
    5657int remove_access_sitelock(const char *pattern); 
    5758void do_list_access(dbref player); 
    5859int parse_access_options 
    59   (const char *opts, dbref *who, int *can, int *cant, dbref player); 
     60  (const char *opts, dbref *who, uint32_t *can, uint32_t *cant, dbref player); 
    6061 
    6162#endif                          /* __ACCESS_H */ 
  • 1.8.3/branches/devel/hdrs/externs.h

    r1017 r1062  
    591591    bool quick_regexp_match(const char *restrict s, 
    592592                            const char *restrict d, bool cs); 
     593bool qcomp_regexp_match(const pcre *re, const char *s); 
    593594    bool wild_match_case_r(const char *restrict s, 
    594595                           const char *restrict d, bool cs, 
  • 1.8.3/branches/devel/src/access.c

    r945 r1062  
    7878#include "conf.h" 
    7979#include "externs.h" 
     80#include "pcre.h" 
    8081#include "access.h" 
    8182#include "mymalloc.h" 
     
    9596struct a_acsflag { 
    9697  const char *name;             /**< Name of the access flag */ 
    97   int toggle;                   /**< Is this a negatable flag? */ 
    98   int flag;                     /**< Bitmask of the flag */ 
     98  bool toggle;                   /**< Is this a negatable flag? */ 
     99  uint32_t flag;                     /**< Bitmask of the flag */ 
    99100}; 
    100101static acsflag acslist[] = { 
     
    114115 
    115116static struct access *access_top; 
    116 static int add_access_node 
    117   (const char *host, const dbref who, const int can, const int cant, 
    118    const char *comment); 
    119117static void free_access_list(void); 
    120118 
    121 static int 
    122 add_access_node(const char *host, const dbref who, const int can, 
    123                 const int cant, const char *comment) 
    124 
    125   struct access *end; 
     119extern const unsigned char *tables; 
     120 
     121static struct access* sitelock_alloc(const char *host, dbref who, 
     122                                     uint32_t can, uint32_t cant, 
     123                                     const char *comment, const char **errptr) 
     124  __attribute_malloc__; 
     125 
     126static struct access* 
     127sitelock_alloc(const char *host, dbref who, uint32_t can, uint32_t cant, 
     128               const char *comment, const char **errptr) 
     129
    126130  struct access *tmp; 
    127  
    128   tmp = (struct access *) mush_malloc(sizeof(struct access), "struct_access"); 
    129   if (!tmp) 
    130     return 0; 
     131  tmp = mush_malloc(sizeof(struct access), "sitelock.rule"); 
     132  if (!tmp) { 
     133    static const char *memerr = "unable to allocate memory"; 
     134    if (errptr) 
     135      *errptr = memerr; 
     136    return NULL; 
     137  } 
    131138  tmp->who = who; 
    132139  tmp->can = can; 
    133140  tmp->cant = cant; 
    134   strcpy(tmp->host, host); 
     141  mush_strncpy(tmp->host, host, BUFFER_LEN); 
    135142  if (comment) 
    136     strcpy(tmp->comment, comment); 
     143    mush_strncpy(tmp->comment, comment, BUFFER_LEN); 
    137144  else 
    138145    tmp->comment[0] = '\0'; 
    139146  tmp->next = NULL; 
     147 
     148  if (can & ACS_REGEXP) { 
     149    int erroffset = 0; 
     150    tmp->re = pcre_compile(host, 0, errptr, &erroffset, tables); 
     151    if (!tmp->re) { 
     152      mush_free(tmp, "sitelock.rule"); 
     153      return NULL; 
     154    } 
     155  } else 
     156    tmp->re = NULL; 
     157 
     158  return tmp; 
     159} 
     160 
     161static bool 
     162add_access_node(const char *host, dbref who, uint32_t can, 
     163                uint32_t cant, const char *comment, const char **errptr) 
     164{ 
     165  struct access *end, *tmp; 
     166 
     167  tmp = sitelock_alloc(host, who, can, cant, comment, errptr); 
     168  if (!tmp) 
     169    return false; 
    140170 
    141171  if (!access_top) { 
     
    148178    end->next = tmp; 
    149179  } 
    150  
    151   return 1; 
     180  return true; 
    152181} 
    153182 
     
    155184/** Read the access.cnf file. 
    156185 * Initialize the access rules linked list and read in the access.cnf file. 
    157  * Return 1 if successful, 0 if not 
    158  */ 
    159 int 
     186 * \return true if successful, false if not 
     187 */ 
     188bool 
    160189read_access_file(void) 
    161190{ 
     
    163192  char buf[BUFFER_LEN]; 
    164193  char *p; 
    165   int can, cant; 
     194  uint32_t can, cant; 
    166195  int retval; 
    167196  dbref who; 
    168197  char *comment; 
     198  const char *errptr = NULL; 
    169199 
    170200  if (access_top) { 
     
    198228        /* Is this the @sitelock entry? */ 
    199229        if (!strncasecmp(p, "@sitelock", 9)) { 
    200           if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "")) 
    201             do_log(LT_ERR, GOD, GOD, T("Failed to add sitelock node!")); 
     230          if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "", 
     231                               &errptr)) 
     232            do_log(LT_ERR, GOD, GOD, T("Failed to add sitelock node: %s"), 
     233                                       errptr); 
    202234        } else { 
    203235          if ((comment = strchr(p, '#'))) { 
     
    214246            /* Nothing listed, so assume we can't do anything! */ 
    215247            cant = ACS_DEFAULT; 
    216           if (!add_access_node(buf, who, can, cant, comment)) 
    217             do_log(LT_ERR, GOD, GOD, T("Failed to add access node!")); 
     248          if (!add_access_node(buf, who, can, cant, comment, &errptr)) 
     249            do_log(LT_ERR, GOD, GOD, T("Failed to add access node: %s"), 
     250                   errptr); 
    218251        } 
    219252      } 
     
    317350 * \endverbatim 
    318351 */ 
    319 int 
    320 site_can_access(const char *hname, int flag, dbref who) 
     352bool 
     353site_can_access(const char *hname, uint32_t flag, dbref who) 
    321354{ 
    322355  struct access *ap; 
     
    333366    if (!(ap->can & ACS_SITELOCK) 
    334367        && ((ap->can & ACS_REGEXP) 
    335             ? (quick_regexp_match(ap->host, hname, 0
    336                || (p && quick_regexp_match(ap->host, p, 0)) 
     368            ? (qcomp_regexp_match(ap->re, hname
     369               || (p && qcomp_regexp_match(ap->re, p)) 
    337370#ifdef FORCE_IPV4 
    338                || quick_regexp_match(ip4_to_ip6(ap->host), hname, 0
    339                || (p && quick_regexp_match(ip4_to_ip6(ap->host), p, 0)) 
     371               || qcomp_regexp_match(ip4_to_ip6(ap->re), hname
     372               || (p && qcomp_regexp_match(ip4_to_ip6(ap->re), p)) 
    340373#endif 
    341374            ) 
     
    403436    if (!(ap->can & ACS_SITELOCK) 
    404437        && ((ap->can & ACS_REGEXP) 
    405             ? (quick_regexp_match(ap->host, hname, 0
    406                || (p && quick_regexp_match(ap->host, p, 0)) 
     438            ? (qcomp_regexp_match(ap->re, hname
     439               || (p && qcomp_regexp_match(ap->re, p)) 
    407440#ifdef FORCE_IPV4 
    408                || quick_regexp_match(ip4_to_ip6(ap->host), hname, 0
    409                || (p && quick_regexp_match(ip4_to_ip6(ap->host), p, 0)) 
     441               || qcomp_regexp_match(ip4_to_ip6(ap->host), hname
     442               || (p && qcomp_regexp_match(ip4_to_ip6(ap->host), p)) 
    410443#endif 
    411444            ) 
     
    434467 * in the list. 
    435468 */ 
    436 int 
     469void 
    437470format_access(struct access *ap, int rulenum, 
    438471              dbref who __attribute__ ((__unused__)), char *buff, char **bp) 
     
    475508    safe_str(T("No matching access rule"), buff, bp); 
    476509  } 
    477   return 0; 
    478510} 
    479511 
     
    494526 * \endverbatim 
    495527 */ 
    496 int 
    497 add_access_sitelock(dbref player, const char *host, dbref who, int can, 
    498                     int cant) 
     528bool 
     529add_access_sitelock(dbref player, const char *host, dbref who, uint32_t can, 
     530                    uint32_t cant) 
    499531{ 
    500532  struct access *end; 
    501533  struct access *tmp; 
    502  
    503   tmp = (struct access *) mush_malloc(sizeof(struct access), "struct_access"); 
    504   if (!tmp) 
    505     return 0; 
    506  
    507   tmp->who = who; 
    508   tmp->can = can; 
    509   tmp->cant = cant; 
    510   strcpy(tmp->host, host); 
    511   snprintf(tmp->comment, sizeof tmp->comment, 
    512            "By %s(#%d) on %s", Name(player), player, show_time(mudtime, 0)); 
    513   tmp->next = NULL; 
     534  const char *errptr = NULL; 
     535 
     536 
     537  tmp = sitelock_alloc(host, who, can, cant, "", &errptr); 
     538 
     539  if (!tmp) { 
     540    notify_format(player, T("Unable to add sitelock entry: %s"), errptr); 
     541    return false; 
     542  } 
    514543 
    515544  if (!access_top) { 
    516545    /* Add to the beginning, but first add a sitelock marker */ 
    517     if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "")) 
     546    if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "", 
     547                         &errptr)) { 
     548      notify_format(player, T("Unable to add @sitelock separator: %s"), errptr); 
    518549      return 0; 
     550    } 
    519551    access_top->next = tmp; 
    520552  } else { 
     
    525557    if (end->can != ACS_SITELOCK) { 
    526558      /* We're at the end and there's no sitelock marker. Add one */ 
    527       if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "")) 
     559      if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "", 
     560                           &errptr)) { 
     561        notify_format(player, T("Unable to add @sitelock separator: %s"), 
     562                      errptr);         
    528563        return 0; 
     564      } 
    529565      end = end->next; 
    530566    } else { 
     
    540576 * \param pattern access rule host pattern to match. 
    541577 * \return number of rule removed. 
    542  * \verbatim 
    543578 * This function removes an access rule from the list. 
    544579 * Only rules that appear after the "@sitelock" rule can be 
    545580 * removed with this function. 
    546  * \endverbatim 
    547581 */ 
    548582int 
     
    564598    if (strcasecmp(pattern, ap->host) == 0) { 
    565599      n++; 
    566       mush_free(ap, "struct_access"); 
     600      if (ap->re) 
     601        free(ap->re); 
     602      mush_free(ap, "sitelock.rule"); 
    567603      if (prev) 
    568604        prev->next = next; 
     
    586622  while (ap) { 
    587623    next = ap->next; 
    588     mush_free((Malloc_t) ap, "struct_access"); 
     624    if (ap->re) 
     625      free(ap->re); 
     626    mush_free(ap, "sitelock.rule"); 
    589627    ap = next; 
    590628  } 
     
    649687 */ 
    650688int 
    651 parse_access_options(const char *opts, dbref *who, int *can, int *cant
    652                      dbref player) 
     689parse_access_options(const char *opts, dbref *who, uint32_t *can
     690                     uint32_t *cant, dbref player) 
    653691{ 
    654692  char myopts[BUFFER_LEN]; 
  • 1.8.3/branches/devel/src/wild.c

    r931 r1062  
    625625 
    626626  return r >= 0; 
     627} 
     628 
     629/** Regexp match of a pre-compiled regexp, with no memory. 
     630 * \param re the regular expression 
     631 * \param subj the string to match against. 
     632 * \return true or false 
     633 */ 
     634bool 
     635qcomp_regexp_match(const pcre *re, const char *subj) 
     636{ 
     637  int len; 
     638  int offsets[99]; 
     639 
     640  if (!re || !subj) 
     641    return false; 
     642 
     643  len = strlen(subj); 
     644 
     645  return pcre_exec(re, NULL, subj, len, 0, 0, offsets, 99) >= 0; 
     646 
    627647} 
    628648 
  • 1.8.3/branches/devel/src/wiz.c

    r1048 r1062  
    14461446  } 
    14471447  if (opts && *opts) { 
    1448     int can, cant; 
     1448    uint32_t can, cant; 
    14491449    dbref whod = AMBIGUOUS; 
    14501450    /* Options form of the command. */ 
     
    14661466    } 
    14671467 
    1468     add_access_sitelock(player, site, whod, can, cant); 
    1469     write_access_file(); 
    1470     if (whod != AMBIGUOUS) { 
    1471       notify_format(player, 
    1472                     T("Site %s access options for %s(%s) set to %s"), 
    1473                     site, Name(whod), unparse_dbref(whod), opts); 
    1474       do_log(LT_WIZ, player, NOTHING, 
    1475              T("*** SITELOCK *** %s for %s(%s) --> %s"), site, 
    1476              Name(whod), unparse_dbref(whod), opts); 
    1477     } else { 
    1478       notify_format(player, T("Site %s access options set to %s"), site, opts); 
    1479       do_log(LT_WIZ, player, NOTHING, "*** SITELOCK *** %s --> %s", site, opts); 
    1480     } 
    1481     return; 
     1468    if (add_access_sitelock(player, site, whod, can, cant)) { 
     1469      write_access_file(); 
     1470      if (whod != AMBIGUOUS) { 
     1471        notify_format(player, 
     1472                      T("Site %s access options for %s(%s) set to %s"), 
     1473                      site, Name(whod), unparse_dbref(whod), opts); 
     1474        do_log(LT_WIZ, player, NOTHING, 
     1475               T("*** SITELOCK *** %s for %s(%s) --> %s"), site, 
     1476               Name(whod), unparse_dbref(whod), opts); 
     1477      } else { 
     1478        notify_format(player, T("Site %s access options set to %s"), site, opts); 
     1479        do_log(LT_WIZ, player, NOTHING, "*** SITELOCK *** %s --> %s", site, opts); 
     1480      } 
     1481      return; 
     1482    } 
    14821483  } else { 
    14831484    /* Backward-compatible non-options form of the command, 
     
    14901491      return; 
    14911492    case SITELOCK_ADD: 
    1492       add_access_sitelock(player, site, AMBIGUOUS, 0, ACS_CREATE); 
    1493       write_access_file(); 
    1494       notify_format(player, T("Site %s locked"), site); 
    1495       do_log(LT_WIZ, player, NOTHING, "*** SITELOCK *** %s", site); 
     1493      if (add_access_sitelock(player, site, AMBIGUOUS, 0, ACS_CREATE)) { 
     1494        write_access_file(); 
     1495        notify_format(player, T("Site %s locked"), site); 
     1496        do_log(LT_WIZ, player, NOTHING, "*** SITELOCK *** %s", site); 
     1497      } 
    14961498      break; 
    14971499    case SITELOCK_BAN: 
    1498       add_access_sitelock(player, site, AMBIGUOUS, 0, ACS_DEFAULT); 
    1499       write_access_file(); 
    1500       notify_format(player, T("Site %s banned"), site); 
    1501       do_log(LT_WIZ, player, NOTHING, "*** SITELOCK *** %s", site); 
     1500      if (add_access_sitelock(player, site, AMBIGUOUS, 0, ACS_DEFAULT)) { 
     1501        write_access_file(); 
     1502        notify_format(player, T("Site %s banned"), site); 
     1503        do_log(LT_WIZ, player, NOTHING, "*** SITELOCK *** %s", site); 
     1504      } 
    15021505      break; 
    15031506    case SITELOCK_CHECK:{