Source File modules/wk/which_keytypes.c

    1    | /***************************************
    2    |   $Revision: 1.15 $
    3    |
    4    |   Example code: Determine which keys to look for.
    5    |
    6    |   This is based on the C code that was reversed engineered from existing Perl
    7    |   code.  (~ottrey/which_table/which_table.c)
    8    |
    9    |   ******************/ /******************
    10   |   Copyright (c) 1999                              RIPE NCC
    11   |
    12   |   All Rights Reserved
    13   |
    14   |   Permission to use, copy, modify, and distribute this software and its
    15   |   documentation for any purpose and without fee is hereby granted,
    16   |   provided that the above copyright notice appear in all copies and that
    17   |   both that copyright notice and this permission notice appear in
    18   |   supporting documentation, and that the name of the author not be
    19   |   used in advertising or publicity pertaining to distribution of the
    20   |   software without specific, written prior permission.
    21   |
    22   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    23   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    24   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    25   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    26   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    27   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    28   |   ***************************************/
    29   | #include <stdio.h>
    30   | #include <stdlib.h>
    31   | #include <strings.h>
    32   | #include <libgen.h>
    33   | #include <glib.h>
    34   |
    35   | #include "isnic.h"
    36   | #include "bitmask.h"
    37   | #include "memwrap.h"
    38   |
    39   | #define  WK_IMPL
    40   | #include "which_keytypes.h"
    41   |
    42   |
    43   |
    44   | #define DOMAINNAME "^[ ]*[a-zA-Z0-9--]*(\\.[a-zA-Z0-9--]+)*[ ]*$"
    45   | /* add a constraint: there must be at least one character in the domain name
    46   |    because the TLD must not be composed of digits only */
    47   | #define DOMAINALPHA  "[a-zA-Z]"
    48   |
    49   | #define LEN_MIN 0
    50   | #define LEN_MAX 32
    51   |
    52   | #define NETLEN 16
    53   | #define NETQUADS 4
    54   | #define NETQUAD_MIN 0
    55   | #define NETQUAD_MAX 255
    56   |
    57   | #define ASNUM_MIN 1
    58   | #define ASNUM_MAX 65535
    59   | #define ASNUM_NUMOFFSET 2   /* XXX - (This is really kludgy!) Offset to the number bit of ASNUM */
    60   |
    61   | #define VALIDIP6PREFIX "^[0-9A-F:]*:[0-9A-F:/]*$"     /* at least one colon */
    62   | /* "^[0-9A-F]{1,4}(:[0-9A-F]{1,4}){7}$"*/
    63   |
    64   | #define NET "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
    65   |
    66   | #define ASNUM "^AS[1-9]+[0-9]*$"
    67   |
    68   | #define ASRANGE "^AS[0-9]+[ ]*([-][ ]*AS[0-9]+){0,1}$"   /* [ ]*(-[ ]*AS[0-9]+)?   */
    69   |
    70   | #define NETNAME "^[A-Z][A-Z0-9-]*$"
    71   |
    72   | #define MAINTAINER "^[A-Z][A-Z0-9-]*$"
    73   |
    74   | #define LIMERICK "^LIM-[A-Z0-9-]+$"
    75   |
    76   | #define KEYCERT "^PGPKEY-[0-9A-F]{8}$"
    77   |
    78   | #define ROUTESETNAME "^RS-[A-Z0-9-_]*$"
    79   |
    80   | #define ASSETNAME "^AS-[A-Z0-9-_]*$"
    81   |
    82   | #define AUTONICPREFIXREGULAR "^AUTO-"
    83   |
    84   | #define IPRANGE "^[0-9]{1,3}(\\.[0-9]{1,3}){0,3}[ ]*-[ ]*[0-9]{1,3}(\\.[0-9]{1,3}){0,3}$"
    85   |
    86   | #define IPADDRESS "^[0-9.]+$"
    87   |
    88   | #define IPPREFIX "^[0-9.]+/[0-9]+$"
    89   |
    90   | #define PEERINGSET "^PRNG-"
    91   |
    92   | #define FILTERSET  "^FLTR-"
    93   |
    94   | #define RTRSET     "^RTRS-"
    95   |
    96   | /*
    97   |   XXX This seems to be the same as the Perl code.  But I don't see where a " " is allowed for.
    98   |   I.e. Perl -> ^[a-zA-Z][\w\-\.\'\|\`]*$
    99   |   Does \w include [ ;:,?/}{()+*#] ?
    100  | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`-]*$"
    101  | */
    102  | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`;:,?/}{()+*#&-]*$"
    103  |
    104  | #define VALIDIP4PREFIX
    105  |
    106  | #define EMAIL "^[.a-zA-Z0-9--]*@[a-zA-Z0-9--]*(\\.[a-zA-Z0-9--]+)*$"
    107  |
    108  | static int perform_regex_test(const char *pattern, char *string) {
    109  |   int match;
    110  |
    111  |   char *re;
    112  |
    113  |   re = regcmp(pattern, (char*)0);
    114  |   if (regex(re, string) == NULL) {
    115  |     match = 0;
    116  |   }
    117  |   else {
    118  |     match = 1;
    119  |   }
    120  |
    121  |   free(re); /* not a wrapper, because we have not allocated it */
    122  |
    123  |   return match;
    124  | } /* perform_regex_test() */
    125  |
    126  | static int isasnum(char *string) {
    127  |   int result='-';
    128  |   int as_value;
    129  |
    130  |   /* First check if the string matches an ASNUM */
    131  |   result = perform_regex_test(ASNUM, string);
    132  |
    133  |   /* Then check if the value is between ASNUM_MIN and ASNUM_MAX */
    134  |   if (result == 1) {
    135  |     as_value = atoi(string+ASNUM_NUMOFFSET);
    136  |     if ((as_value < ASNUM_MIN) || (as_value > ASNUM_MAX)) {
    137  |       /* an invalid value */
    138  |       result=0;
    139  |     }
    140  |   }
    141  |
    142  |   return result;
    143  | }
    144  |
    145  | /*******************************************************
    146  |     # the problem is as follows:
    147  |     #
    148  |     # we can never find out which NIC handles are possible on the
    149  |     # globe since we don't know that they exist
    150  |     #
    151  |     # we want to solve this with once with DNS :
    152  |     #
    153  |     # RIPE.registries.int     CNAME whois.ripe.net
    154  |     # InterNIC.registries.int CNAME whois.internic.net
    155  |     # and so on...
    156  |
    157  |     #
    158  |     # 1) it first does a basic syntax check
    159  |     #
    160  |     #    notes:
    161  |     #
    162  |     #    - catches InterNIC handles
    163  |     #    - catches the JP|JP-JP APNIC exceptions
    164  |     #    - limits the number of initials to three with a good reason:
    165  |     #      we have a much better chance to find syntax errors like:
    166  |     #      RIPE-DK13 and other problems like this
    167  |     #
    168  |     # 2) checks for valid suffixes
    169  |     #    - all 'source:' attribute values from sites that we mirror
    170  |     #      are allowed
    171  |     #    - country codes are allowed for APNIC compatibility
    172  |     #    - APNIC AP|CC-AU exceptions are handled correctly
    173  |     #    - -ORG organization InterNIC handles
    174  |     #    - -ARIN ARIN handles
    175  |     #    - -ORG-ARIN ARIN handles
    176  | ********************************************************/
    177  | static int isnichandle(char *nichdl) {
    178  |
    179  |   char *regexp, *match;
    180  |   char ret[1024];
    181  |   char *suffix;
    182  |
    183  |   int i;
    184  |
    185  | /* set ret to the empty string */
    186  |   ret[0]='\0';
    187  |
    188  | /*
    189  |   # Japanese NIC handles
    190  |   #
    191  |   # leading zeros in the number part *are* allowed
    192  |   #
    193  |   # e.g. AB021JP AB199JP-JP
    194  |   #
    195  | */
    196  |   regexp = regcmp("[A-Z]{2}[0-9]{3}JP(-JP){0,1}",(char *)0);
    197  |   match =  regex(regexp,nichdl);
    198  |   free(regexp); /* not a wrapper, because we have not allocated it */
    199  |   if (match) return 1;
    200  |
    201  | /*
    202  |   # Standard NIC handles
    203  |   #
    204  |   # leading zeros in the number part are *not* allowed
    205  |   #
    206  |   # InterNIC - TBQ, IP4
    207  |   # RIPE format - AB1-RIPE
    208  |   # APNIC use two letter country code suffix
    209  |   # Austraila have used -1-AU, -2-AU, -CC-AU suffix.
    210  |   # Internic used -ORG suffix
    211  |   # ARIN use -ARIN suffix
    212  |   # ARIN also use -ORG-ARIN suffix
    213  |   #
    214  | */
    215  |   regexp = regcmp("^[A-Z]{2,4}([1-9][0-9]{0,5}){0,1}((-[^ ]+){0,1})$0$",(char *)0);
    216  |   match =  regex(regexp,nichdl,ret);
    217  |
    218  |   free(regexp); /* not a wrapper, because we have not allocated it */
    219  |
    220  |   if (match == NULL) {
    221  |     return 0;
    222  |   } else {
    223  |     if (ret[0] == '\0') {
    224  |       return 1;
    225  |     } else {
    226  | /*   strip leading '-' */
    227  |       suffix = ret+1;
    228  | /* suffix of local sources */
    229  |       for (i=0;i<=NUM_NICPOSTFIX;i++) {
    230  |         if ( !strcmp(suffix,nicpostfix[i]) ) {
    231  |           return 1;
    232  |         }
    233  |       }
    234  | /* country codes */
    235  |       for (i=0;i<NUM_COUNTRIES;i++) {
    236  |         if ( !strcmp(suffix,countries[i]) ) {
    237  |           return 1;
    238  |         }
    239  |       }
    240  | /* special suffix */
    241  |       for (i=0;i<NUM_SPECIAL;i++) {
    242  |         if ( !strcmp(suffix,special[i]) ) {
    243  |           return 1;
    244  |         }
    245  |       }
    246  |     }
    247  |   }
    248  |   return 0;
    249  | } /* isnichandle() */
    250  |
    251  | static int isdomname(char *string) {
    252  |     return (    perform_regex_test(DOMAINNAME, string)
    253  | 	     && perform_regex_test(DOMAINALPHA, string));
    254  | }
    255  |
    256  | /*
    257  |  I split the isname up into isname_a & isname_b.  And created isname_ab to join them together.
    258  |   - So I can test it properly.  -ottrey
    259  |  */
    260  | static int isname_a(char *string) {
    261  |     return perform_regex_test(AUTONICPREFIXREGULAR, string);
    262  | }
    263  |
    264  | static int isname_b(char *string) {
    265  |     return perform_regex_test(NAME_B, string);
    266  | }
    267  |
    268  | static int isname_ab(char *string) {
    269  |     return (isname_a(string) || isname_b(string));
    270  | }
    271  |
    272  | static int isnetname(char *string) {
    273  |     return perform_regex_test(NETNAME, string);
    274  | } /* wk_is_netname() */
    275  |
    276  | static int wk_is_name(char *key) {
    277  |     /* Everything matches to name */
    278  |     return 1;
    279  | } /* wk_is_name() */
    280  |
    281  | static int wk_is_nic_hdl(char *key) {
    282  |     return isnichandle(key);
    283  | } /* wk_is_nic_hdl() */
    284  |
    285  | static int wk_is_email(char *key) {
    286  |     return perform_regex_test(EMAIL, key);
    287  | } /* wk_is_email() */
    288  |
    289  | static int wk_is_mntner(char *key) {
    290  |     return perform_regex_test(MAINTAINER, key);
    291  | } /* wk_is_mntner() */
    292  |
    293  | static int wk_is_key_cert(char *key) {
    294  |     return perform_regex_test(KEYCERT, key);
    295  | } /* wk_is_key_cert() */
    296  |
    297  | static int wk_is_ipaddress(char *key) {
    298  |     return perform_regex_test(IPADDRESS, key);
    299  | } /* wk_is_key_cert() */
    300  |
    301  | static int wk_is_iprange(char *key) {
    302  |     return perform_regex_test(IPRANGE, key);
    303  | } /* wk_is_iprange() */
    304  |
    305  | static int wk_is_ipprefix(char *key) {
    306  |     return perform_regex_test(IPPREFIX, key);
    307  | } /* wk_is_iprange() */
    308  |
    309  | static int wk_is_ip6prefix(char *key) {
    310  |     return perform_regex_test(VALIDIP6PREFIX, key);
    311  | } /* wk_is_ip6prefix() */
    312  |
    313  | static int wk_is_netname(char *key) {
    314  |     return isnetname(key);
    315  | } /* wk_is_netname() */
    316  |
    317  | /* XXX Note: This function uses the same call as wk_is_netname(). */
    318  | static int wk_is_net6name(char *key) {
    319  |     return isnetname(key);
    320  | } /* wk_is_netname() */
    321  |
    322  | static int wk_is_autnum(char *key) {
    323  |     return isasnum(key);
    324  | } /* wk_is_autnum() */
    325  |
    326  | static int wk_is_asrange(char *key) {
    327  |     return perform_regex_test(ASRANGE, key);
    328  | } /* wk_is_autnum() */
    329  |
    330  | static int wk_is_assetname(char *key) {
    331  |     return perform_regex_test(ASSETNAME, key);
    332  | } /* wk_is_assetname() */
    333  |
    334  | static int wk_is_routesetname(char *key) {
    335  |     return perform_regex_test(ROUTESETNAME, key);
    336  | } /* wk_is_routesetname() */
    337  |
    338  | static int wk_is_domain(char *key) {
    339  |     return isdomname(key);
    340  | } /* wk_is_domname() */
    341  |
    342  | static int wk_is_hostname(char *key) {
    343  |   /* XXX Why is there a hostname & a domainname? */
    344  |   /* Answer - hostname can be a domainname or an IP */
    345  |     return (isdomname(key) || wk_is_iprange(key));
    346  | } /* wk_is_hostname() */
    347  |
    348  | static int wk_is_limerick(char *key) {
    349  |     return perform_regex_test(LIMERICK, key);
    350  | } /* wk_is_limerick() */
    351  |
    352  | static int wk_is_peeringset(char *key) {
    353  |     return perform_regex_test(PEERINGSET, key);
    354  | } /* wk_is_peeringset() */
    355  |
    356  | static int wk_is_rtrset(char *key) {
    357  |     return perform_regex_test(RTRSET, key);
    358  | } /* wk_is_rtrset() */
    359  |
    360  | static int wk_is_filterset(char *key) {
    361  |     return perform_regex_test(FILTERSET, key);
    362  | } /* wk_is_filterset() */
    363  |
    364  | /* WK_to_string() */
    365  | /*++++++++++++++++++++++++++++++++++++++
    366  |   Convert the which keytypes bitmap into a string.
    367  |
    368  |   mask_t wk The which keytypes mask to be converted.
    369  |
    370  |   More:
    371  |   +html+ <PRE>
    372  |   Authors:
    373  |         ottrey
    374  |   +html+ </PRE><DL COMPACT>
    375  |   +html+ <DT>Online References:
    376  |   +html+ <DD><UL>
    377  |   +html+ </UL></DL>
    378  |
    379  |   ++++++++++++++++++++++++++++++++++++++*/
    380  | char *WK_to_string(mask_t wk) {
    381  |
    382  |   return MA_to_string(wk, Keytypes);
    383  |
    384  | } /* WK_to_string() */
    385  |
    386  | /* WK_new() */
    387  | /*++++++++++++++++++++++++++++++++++++++
    388  |   Create a new which keytypes bitmap.
    389  |
    390  |   char *key The key to be examined.
    391  |
    392  |   More:
    393  |   +html+ <PRE>
    394  |   Authors:
    395  |         ottrey
    396  |   +html+ </PRE><DL COMPACT>
    397  |   +html+ <DT>Online References:
    398  |   +html+ <DD><UL>
    399  |   +html+ </UL></DL>
    400  |
    401  |   ++++++++++++++++++++++++++++++++++++++*/
    402  | mask_t WK_new(char *key) {
    403  |   mask_t wk;
    404  |
    405  |   wk = MA_new(MA_END);
    406  |
    407  |   MA_set(&wk, WK_NAME,         wk_is_name(key));
    408  |   MA_set(&wk, WK_NIC_HDL,      wk_is_nic_hdl(key));
    409  |   MA_set(&wk, WK_EMAIL,        wk_is_email(key));
    410  |   MA_set(&wk, WK_MNTNER,       wk_is_mntner(key));
    411  |   MA_set(&wk, WK_KEY_CERT,     wk_is_key_cert(key));
    412  |   MA_set(&wk, WK_IPADDRESS,    wk_is_ipaddress(key));
    413  |   MA_set(&wk, WK_IPRANGE,      wk_is_iprange(key));
    414  |   MA_set(&wk, WK_IPPREFIX,     wk_is_ipprefix(key));
    415  |   MA_set(&wk, WK_IP6PREFIX,    wk_is_ip6prefix(key));
    416  |   MA_set(&wk, WK_NETNAME,      wk_is_netname(key));
    417  |   MA_set(&wk, WK_NET6NAME,     wk_is_net6name(key));
    418  |   MA_set(&wk, WK_AUTNUM,       wk_is_autnum(key));
    419  |   MA_set(&wk, WK_ASSETNAME,    wk_is_assetname(key));
    420  |   MA_set(&wk, WK_ROUTESETNAME, wk_is_routesetname(key));
    421  |   MA_set(&wk, WK_DOMAIN,       wk_is_domain(key));
    422  |   MA_set(&wk, WK_HOSTNAME,     wk_is_hostname(key));
    423  |   MA_set(&wk, WK_LIMERICK,     wk_is_limerick(key));
    424  |   MA_set(&wk, WK_ASRANGE,      wk_is_asrange(key));
    425  |   MA_set(&wk, WK_PEERINGSET,   wk_is_peeringset(key));
    426  |   MA_set(&wk, WK_FILTERSET,    wk_is_filterset(key));
    427  |   MA_set(&wk, WK_RTRSET,       wk_is_rtrset(key));
    428  |
    429  |   return wk;
    430  |
    431  | } /* WK_new() */