comparison src/group.c @ 250:93d5d8b098da noffle

[svn] *** empty log message ***
author mirkol
date Wed, 05 Jun 2002 23:03:44 +0100
parents 0340b9c17edc
children 94b7962a0fbe
comparison
equal deleted inserted replaced
249:0340b9c17edc 250:93d5d8b098da
5 the groups we know of. One database record is cached in the global struct 5 the groups we know of. One database record is cached in the global struct
6 grp. Group information is transfered between the grp and the database by 6 grp. Group information is transfered between the grp and the database by
7 loadGrp() and saveGrp(). This is done transparently. Access to the groups 7 loadGrp() and saveGrp(). This is done transparently. Access to the groups
8 database is done by group name, by the functions defined in group.h. 8 database is done by group name, by the functions defined in group.h.
9 9
10 $Id: group.c 381 2002-05-14 14:25:45Z mirkol $ 10 $Id: group.c 382 2002-06-05 22:03:44Z mirkol $
11 */ 11 */
12 12
13 #if HAVE_CONFIG_H 13 #if HAVE_CONFIG_H
14 #include <config.h> 14 #include <config.h>
15 #endif 15 #endif
18 #include <gdbm.h> 18 #include <gdbm.h>
19 #include <errno.h> 19 #include <errno.h>
20 #include <fcntl.h> 20 #include <fcntl.h>
21 #include <sys/stat.h> 21 #include <sys/stat.h>
22 #include "configfile.h" 22 #include "configfile.h"
23 #include "wildmat.h"
23 #include "group.h" 24 #include "group.h"
24 #include "log.h" 25 #include "log.h"
25 #include "util.h" 26 #include "util.h"
26 #include "portable.h" 27 #include "portable.h"
28
29 /* max length of a group name: */
30 #define MAX_GROUPNAME 78
27 31
28 /* currently only used within grp */ 32 /* currently only used within grp */
29 typedef struct 33 typedef struct
30 { 34 {
31 int first; /* number of first article within group */ 35 int first; /* number of first article within group */
60 { 64 {
61 if ( errno != 0 ) 65 if ( errno != 0 )
62 return strerror( errno ); 66 return strerror( errno );
63 return gdbm_strerror( gdbm_errno ); 67 return gdbm_strerror( gdbm_errno );
64 } 68 }
69
70 /* forbidden hierarchies */
71 struct ForbiddenGroupName
72 {
73 const char *pattern;
74 Bool match;
75 } forbiddenGroupNames[] =
76 {
77 /* { "*[^-+_.0-9a-zA-Z]*", TRUE}, */ /* allow only traditional group names */
78 { "*.*", FALSE }, /* Single component */
79 { "control.*", TRUE }, /* control.* groups */
80 { "to.*", TRUE }, /* to.* groups */
81 { "*.all", TRUE }, /* 'all' as a component */
82 { "*.all.*", TRUE },
83 { "all.*", TRUE },
84 { "*.ctl", TRUE }, /* 'ctl' as a component */
85 { "*.ctl.*", TRUE },
86 { "ctl.*", TRUE },
87 { "example.*", TRUE }, /* example.* groups */
88 { "*,*", TRUE }, /* newsgroups separator */
89 /* { "_*", TRUE }, */ /* reserved for future use, but accept nevertheless */
90 { "+*", TRUE }, /* reserved */
91 { "-*", TRUE }
92 };
65 93
66 Bool 94 Bool
67 Grp_open( void ) 95 Grp_open( void )
68 { 96 {
69 Str name; 97 Str name;
410 free( oldDptr ); 438 free( oldDptr );
411 *name = cursor.dptr; 439 *name = cursor.dptr;
412 return ( cursor.dptr != NULL ); 440 return ( cursor.dptr != NULL );
413 } 441 }
414 442
415 Bool 443 /* Group names' sanity checks. Groups with forbidden names
416 Grp_isValidGroupName( const char *name) 444 can't be safely deleted or created. */
417 { 445 Bool
418 const char *pname, *ppat; 446 Grp_isForbiddenName( const char *name)
419 const char *illegalchars = "\t\n\r,/:\\"; /* Are there any other dangerous characters? */ 447 {
420 448 const char *illegalchars = "\t\n\v\r /:\\";
421 /* Find directory prefixes to prevent exploits. */ 449 /* "\t\n\v\r " whitespace
422 switch ( name[0] ) 450 "/:\\" directory prefix (Unix, MacOS, Freedos filesystems) */
423 {
424 case '.': /* prevent noffle -C ../fetchlist */
425 case '+':
426 case '-': /* reserved for internal use of implementations
427 * rf. draft-ietf-usefor-article-06.txt, ch 5.5.1 */
428 return FALSE; /* group name invalid */
429 break;
430 default:
431 break;
432 }
433
434 /* Find illegal characters. */ 451 /* Find illegal characters. */
435 if ( strpbrk( name, illegalchars ) ) 452 if ( strpbrk( name, illegalchars ) )
453 return TRUE;
454 /* Find '.' dot directory prefix to prevent exploits. */
455 if ( name[0] == '.') /* prevent noffle -C ../fetchlist */
456 return TRUE; /* group name invalid */
457 return FALSE;
458 }
459
460 /*
461 Forbidden or restricted group names or hierarchies. Please refer to
462 draft-ietf-usefor-article-06, chapter 5.5.1. Groups with invalid
463 names can't be created, but can still be deleted.
464 */
465 Bool
466 Grp_isValidName( const char *name)
467 {
468 size_t i;
469
470 for ( i = 0;
471 i < sizeof( forbiddenGroupNames ) /
472 sizeof( struct ForbiddenGroupName );
473 ++i )
474 {
475 /* Negate result of Wld_match to ensure it is 1 or 0. */
476 if ( forbiddenGroupNames[i].match !=
477 ( ! Wld_match( name, forbiddenGroupNames[i].pattern ) ) )
478 return FALSE;
479 }
480 /* Groups with lengthy names like
481 alt.the.lame.troll.should.be.posting.again.in.just.a.few.more.weeks.from.what.he.said
482 or
483 microsoft.public.windows.inetexplorer.ie55.programming.components.codedownload
484 are most likely bogus groups that have been mistakenly created.
485 */
486 if ( strlen( name ) > MAX_GROUPNAME )
436 return FALSE; 487 return FALSE;
437 488 /* no match? then assume the group is valid. */
438 /* Find "all", "all.*", "*.all" or "*.all.*" */
439 pname = name;
440 while ( ( ppat = strstr( pname, "all" ) ) != NULL )
441 {
442 if ( ( ppat == name || *(ppat - 1) == '.' )
443 && ( *(ppat+4) == '\0' || *(ppat+4) == '.' ) )
444 return FALSE;
445 else
446 pname += 3;
447 }
448
449 /* Find "ctl", "ctl.*", "*.ctl" or "*.ctl.*" */
450 pname = name;
451 while ( ( ppat = strstr( pname, "ctl" ) ) != NULL )
452 {
453 if ( ( ppat == name || *(ppat - 1) == '.' )
454 && ( *(ppat+4) == '\0' || *(ppat+4) == '.' ) )
455 return FALSE;
456 else
457 pname += 3;
458 }
459 /* Find some special groups and hierarchies. */
460 if ( !( strcmp( name, "poster" ) && strcmp( name, "junk" )
461 && strcmp( name, "control" ) && strcmp( name, "to" )
462 && strncmp( name, "control.", 8 ) && strncmp( name, "to.", 3 )
463 && strncmp( name, "example.", 8 ) ) )
464 return FALSE;
465
466
467 /* Group name is hopefully valid. */
468 return TRUE; 489 return TRUE;
469 } 490 }