1    | /***************************************
2    |   $Revision: 1.20 $
3    | 
4    |   which_keytypes:  Determine which keys to look for.
5    |   
6    |   This is based on the existing Perl code. 
7    | 
8    |   Authors: ottrey, marek
9    | 
10   |   ******************/ /******************
11   |   Copyright (c) 1999                              RIPE NCC
12   |  
13   |   All Rights Reserved
14   |   
15   |   Permission to use, copy, modify, and distribute this software and its
16   |   documentation for any purpose and without fee is hereby granted,
17   |   provided that the above copyright notice appear in all copies and that
18   |   both that copyright notice and this permission notice appear in
19   |   supporting documentation, and that the name of the author not be
20   |   used in advertising or publicity pertaining to distribution of the
21   |   software without specific, written prior permission.
22   |   
23   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
25   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
26   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
28   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29   |   ***************************************/
30   | #include <stdio.h>
31   | #include <stdlib.h>
32   | #include <strings.h>
33   | /* #include <libgen.h> */
34   | #include <glib.h>
35   | 
36   | #include "bitmask.h"
37   | #include "memwrap.h"
38   | 
39   | #define  WK_IMPL
40   | #include "which_keytypes.h"
41   | #include <regex.h>
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 VALIDIP6PREFIX "^[0-9A-F:]*:[0-9A-F:/]*$"     /* at least one colon */
50   | /* "^[0-9A-F]{1,4}(:[0-9A-F]{1,4}){7}$"*/
51   | 
52   | #define NET "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
53   | 
54   | #define ASNUM "^AS[1-9]+[0-9]{0,4}$"
55   | 
56   | #define ASRANGE "^AS[0-9]{1,5}[ ]*([-][ ]*AS[0-9]{1,5}){0,1}$"   /* [ ]*(-[ ]*AS[0-9]+)?   */
57   | 
58   | #define NETNAME "^[A-Z][A-Z0-9-]*$"
59   | 
60   | #define MAINTAINER "^[A-Z][A-Z0-9-]*$"
61   | 
62   | #define LIMERICK "^LIM-[A-Z0-9-]+$"
63   | 
64   | #define KEYCERT "^PGPKEY-[0-9A-F]{8}$"
65   | 
66   | #define ROUTESETNAME "^RS-[A-Z0-9_-]*$"
67   | 
68   | #define ASSETNAME "^AS-[A-Z0-9_-]*$"
69   | 
70   | #define AUTONICPREFIXREGULAR "^AUTO-"
71   | 
72   | #define IPRANGE "^[0-9]{1,3}(\\.[0-9]{1,3}){0,3}[ ]*-[ ]*[0-9]{1,3}(\\.[0-9]{1,3}){0,3}$"
73   | 
74   | #define IPADDRESS "^[0-9.]+$"
75   | 
76   | #define IPPREFIX "^[0-9.]+/[0-9]+$"
77   | 
78   | #define PEERINGSET "^PRNG-"
79   | 
80   | #define FILTERSET  "^FLTR-"
81   | 
82   | #define RTRSET     "^RTRS-"
83   | 
84   | #define NICHANDLE "^[A-Z0-9-]+$"
85   | 
86   | /*
87   |   XXX This seems to be the same as the Perl code.  But I don't see where a " " is allowed for.
88   |   I.e. Perl -> ^[a-zA-Z][\w\-\.\'\|\`]*$
89   |   Does \w include [ ;:,?/}{()+*#] ?
90   | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`-]*$"
91   | */
92   | #define NAME_B "^[a-zA-Z][a-zA-Z_0-9.'|`;:,?/}{()+*#&-]*$"
93   | 
94   | #define VALIDIP4PREFIX
95   | 
96   | #define EMAIL "^[.a-zA-Z0-9-]*@[a-zA-Z0-9-]*(\\.[a-zA-Z0-9-]+)*$"
97   | 
98   | /*****************************************************************/
99   | 
100  | 
101  | /*++++++++++++++++++++++++++++++++++++++
102  | 
103  |   compile a regular expression and run on the text given.
104  | 
105  |   unsigned perform_regex_test   returns 1 for match, 0 for no match
106  | 
107  |   const char *pattern           regular expression pattern
108  | 
109  |   char *string                  text to be checked
110  | 
111  |   ++++++++++++++++++++++++++++++++++++++*/
112  | static unsigned perform_regex_test(const char *pattern, char *string)
113  | {
114  | 
115  |   int match = 0;
116  | 
117  |   /* These are not used, since REG_NOSUB is specified in regcomp() */
118  |   size_t nmatch = 0;
119  |   regmatch_t pmatch[1];
120  |   regex_t re;
121  |   int err;
122  | 
123  |   if( (err = regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB)) != 0) 
124  |     {
125  |       char erbuf[2048];      
126  |       regerror(err,&re,erbuf,sizeof(erbuf));
127  |       die;
128  |     }
129  |   if (regexec(&re, string, nmatch, pmatch, 0))
130  |     match = 0;
131  |   else
132  |     match = 1;
133  | 
134  |   regfree(&re);
135  | 
136  |   return(match);
137  | 
138  | } 
139  | 
140  | /*
141  |  I split the isname up into isname_a & isname_b.  And created isname_ab to join them together.
142  |   - So I can test it properly.  -ottrey
143  |  */
144  | #if 0
145  | static unsigned int isname_a(char *string) {
146  |     return perform_regex_test(AUTONICPREFIXREGULAR, string);
147  | }
148  | 
149  | static unsigned int isname_b(char *string) {
150  |     return perform_regex_test(NAME_B, string);
151  | }
152  | 
153  | static unsigned int isname_ab(char *string) {
154  |     return (isname_a(string) || isname_b(string));
155  | }
156  | #endif 
157  | 
158  | static unsigned int wk_is_name(char *key) {
159  |     /* Everything apart from addresses matches to name */
160  |     if( perform_regex_test(IPADDRESS, key)
161  | 	|| perform_regex_test(IPPREFIX, key)
162  | 	|| perform_regex_test(VALIDIP6PREFIX, key) ) {
163  |       return 0;
164  |     }
165  |     else {
166  |       return 1;
167  |     }
168  | } /* wk_is_name() */
169  | 
170  | /***************************************************************/
171  | 
172  | static unsigned int isdomname(char *string) {
173  |     return (    perform_regex_test(DOMAINNAME, string)
174  | 	     && perform_regex_test(DOMAINALPHA, string));
175  | }
176  | 
177  | static unsigned int wk_is_domain(char *key) {
178  |     return isdomname(key);
179  | } /* wk_is_domname() */
180  | 
181  | static unsigned int wk_is_iprange(char *key) {
182  |   return perform_regex_test(IPRANGE, key);
183  | } /* wk_is_iprange() */
184  | 
185  | static unsigned int wk_is_hostname(char *key) {
186  |   /* XXX Why is there a hostname & a domainname? */
187  |   /* Answer - hostname can be a domainname or an IP */
188  |     return (isdomname(key) || wk_is_iprange(key));
189  | } /* wk_is_hostname() */
190  | 
191  | /* WK_to_string() */
192  | /*++++++++++++++++++++++++++++++++++++++
193  |   Convert the which keytypes bitmap into a string.
194  | 
195  |   mask_t wk The which keytypes mask to be converted.
196  | 
197  |   More:
198  |   +html+ <PRE>
199  |   Authors:
200  |         ottrey
201  |   +html+ </PRE><DL COMPACT>
202  |   +html+ <DT>Online References:
203  |   +html+ <DD><UL>
204  |   +html+ </UL></DL>
205  | 
206  |   ++++++++++++++++++++++++++++++++++++++*/
207  | char *WK_to_string(mask_t wk) {
208  | 
209  |   return MA_to_string(wk, Keytypes);
210  | 
211  | } /* WK_to_string() */
212  | 
213  | /* WK_new() */
214  | /*++++++++++++++++++++++++++++++++++++++
215  |   Create a new which keytypes bitmap.
216  | 
217  |   char *key The key to be examined.
218  | 
219  |   More:
220  |   +html+ <PRE>
221  |   Authors:
222  |         ottrey
223  |   +html+ </PRE><DL COMPACT>
224  |   +html+ <DT>Online References:
225  |   +html+ <DD><UL>
226  |   +html+ </UL></DL>
227  | 
228  |   ++++++++++++++++++++++++++++++++++++++*/
229  | mask_t WK_new(char *key) {
230  |   mask_t wk; 
231  | 
232  |   wk = MA_new(MA_END);
233  | 
234  |   MA_set(&wk, WK_NAME,         wk_is_name(key));
235  |   MA_set(&wk, WK_NIC_HDL,      perform_regex_test(NICHANDLE, key));
236  |   MA_set(&wk, WK_EMAIL,        perform_regex_test(EMAIL, key));
237  |   MA_set(&wk, WK_MNTNER,       perform_regex_test(MAINTAINER, key));
238  |   MA_set(&wk, WK_KEY_CERT,     perform_regex_test(KEYCERT, key));
239  |   MA_set(&wk, WK_IPADDRESS,    perform_regex_test(IPADDRESS, key));
240  |   MA_set(&wk, WK_IPRANGE,      wk_is_iprange(key));
241  |   MA_set(&wk, WK_IPPREFIX,     perform_regex_test(IPPREFIX, key));
242  |   MA_set(&wk, WK_IP6PREFIX,    perform_regex_test(VALIDIP6PREFIX, key));
243  |   MA_set(&wk, WK_NETNAME,      perform_regex_test(NETNAME, key));
244  |   MA_set(&wk, WK_NET6NAME,     perform_regex_test(NETNAME, key));
245  |   MA_set(&wk, WK_AUTNUM,       perform_regex_test(ASNUM, key));
246  |   MA_set(&wk, WK_ASSETNAME,    perform_regex_test(ASSETNAME, key));
247  |   MA_set(&wk, WK_ROUTESETNAME, perform_regex_test(ROUTESETNAME, key));
248  |   MA_set(&wk, WK_DOMAIN,       wk_is_domain(key));
249  |   MA_set(&wk, WK_HOSTNAME,     wk_is_hostname(key));
250  |   MA_set(&wk, WK_LIMERICK,     perform_regex_test(LIMERICK, key));
251  |   MA_set(&wk, WK_ASRANGE,      perform_regex_test(ASRANGE, key));
252  |   MA_set(&wk, WK_PEERINGSET,   perform_regex_test(PEERINGSET, key));
253  |   MA_set(&wk, WK_FILTERSET,    perform_regex_test(FILTERSET, key));
254  |   MA_set(&wk, WK_RTRSET,       perform_regex_test(RTRSET, key));
255  |   
256  |   return wk;
257  | 
258  | } /* WK_new() */