Mercurial > noffle
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 } |
