Ticket #33: nnrpd-cancel-lock.patch

File nnrpd-cancel-lock.patch, 10.6 KB (added by eagle, 14 years ago)

Patch against INN 2.3.5

  • doc/man/readers.conf.5

    old new  
    407407The client may post articles with Approved: headers (in other words, may
    408408approve articles for moderated newsgroups).  By default, this is not
    409409allowed.
     410.IP "C" 3
     411.IX Item "C"
     412The client may post cancels for articles not originating from him nor
     413this site (in other words, may forge cancels; this is needed by spam
     414cancellers, but can do harm if used unsound).  By default, this is not
     415allowed.
    410416.IP "N" 3
    411417.IX Item "N"
    412418The client may use the \s-1NEWNEWS\s0 command, overriding the global setting.
  • nnrpd/Makefile

    diff -Nur inn-2.3.5.orig/nnrpd/Makefile inn-2.3.5/nnrpd/Makefile
    old new  
    66
    77ALL             = nnrpd
    88
     9CANLOCKLIB = -lcanlock
     10
    911SOURCES         = article.c group.c commands.c loadave.c misc.c newnews.c \
    1012                  nnrpd.c perl.c perm.c post.c python.c sasl_config.c \
    11                   tls.c track.c
     13                  tls.c track.c canlock.c
    1214
    1315INCLUDES        = nnrpd.h post.h sasl_config.h tls.h
    1416
     
    3234##  Compilation rules.
    3335
    3436NNRPDLIBS       = $(LIBSTORAGE) $(LIBINN) $(EXTSTORAGELIBS) $(PERLLIB) \
    35                   $(PYTHONLIB) $(SSLLIB) $(LIBS)
     37                  $(PYTHONLIB) $(SSLLIB) $(LIBS) $(CANLOCKLIB)
    3638
    3739perl.o:         perl.c          ; $(CC) $(CFLAGS) $(PERLINC) -c perl.c
    3840python.o:       python.c        ; $(CC) $(CFLAGS) $(PYTHONINC) -c python.c
  • nnrpd/article.c

    diff -Nur inn-2.3.5.orig/nnrpd/article.c inn-2.3.5/nnrpd/article.c
    old new  
    353353/*
    354354**  Open the article for a given Message-ID.
    355355*/
    356 STATIC BOOL ARTopenbyid(char *msg_id, ARTNUM *ap)
     356BOOL ARTopenbyid(char *msg_id, ARTNUM *ap)
    357357{
    358358    char                *p;
    359359    HASH                hash = HashMessageID(msg_id);
  • nnrpd/canlock.c

    Binary files inn-2.3.5.orig/nnrpd/article.o and inn-2.3.5/nnrpd/article.o differ
    diff -Nur inn-2.3.5.orig/nnrpd/canlock.c inn-2.3.5/nnrpd/canlock.c
    old new  
     1/*
     2 * $Revision: 1.2 $
     3 */
     4
     5#if ! defined (lint)
     6static const char *rcsid = "$Id: $";
     7static void use_rcsid (const char *rid) {   /* Never called */
     8                  use_rcsid (rcsid) ; use_rcsid (rid) ;
     9}
     10#endif
     11
     12
     13#include <stdio.h>
     14#include <sys/types.h>
     15#include "configdata.h"
     16#include "clibrary.h"
     17#include "nnrpd.h"
     18#include <canlock.h>
     19
     20BOOL checker(const char *key, const char *lock);
     21BOOL ARTopenbyid(char *msg_id, ARTNUM *ap);
     22
     23char* canlock (char *msgid, char *name, int mode)
     24{
     25        FILE *secret;
     26        unsigned char *p;
     27        long filelen;
     28        char csec[1024];
     29       
     30        if (!(secret=fopen(name, "r"))) {
     31                syslog(L_ERROR, "Cant open input file %s (%m)", name);
     32                return NULL;
     33        }
     34        if (!fgets(csec, 1024, secret)) {
     35                syslog(L_ERROR, "Cant read input file %s (%m)", name);
     36                return NULL;
     37        }
     38        fclose(secret);
     39               
     40        if (mode == CL_KEY) {
     41                return sha_key(csec, strlen(csec), msgid, strlen(msgid));
     42        }
     43
     44        return sha_lock(csec, strlen(csec), msgid, strlen(msgid));
     45               
     46}
     47
     48/*
     49** Get the Cancel-Lock-Header and test
     50** Partly cloned from CMDxpat by Andreas Barth
     51**
     52** some administrative decisions are compiled in here (what to do if the
     53** articel doesn't exist, ...)
     54*/
     55#define ACCEPTOLD 1
     56BOOL testcanlock(const char *Keys, const char *MessageID)
     57{
     58    char                *lock,*date;
     59        ARTNUM              artnum;
     60    time_t      t;
     61
     62    if (!ARTopenbyid(MessageID, &artnum)) return TRUE;
     63    lock = GetHeader("Cancel-Lock", FALSE);
     64#if ACCEPTOLD
     65    date = GetHeader("Date", FALSE);
     66#endif
     67    ARTclose();
     68    if (lock == NULL)
     69#if ACCEPTOLD
     70    {
     71        if ((t = parsedate(date, NULL)) == -1)
     72        //  Can't parse Date header, so we accept
     73            return TRUE;
     74        if (t < 1054425600)
     75        // posted before 1st of June 2003, 0:00 UTC
     76            return TRUE;
     77        return FALSE;
     78    // XXX isn't it needed to get rid of date? But CMDxpat doesn't do this.
     79    }
     80#else
     81        return FALSE;
     82#endif
     83    // XXX isn't it needed to get rid of lock? But CMDxpat doesn't do this.
     84    return checker(Keys, lock);
     85}
     86
     87BOOL allowedhashchar(const char c) {
     88    if ('\0' == c) return FALSE;
     89    switch (c) {
     90        case ':':
     91        case '=':
     92        case '-':
     93        case '+':
     94        case '/':
     95            // XXX are base64 chars missing here?
     96            return TRUE;
     97    }
     98    return isalnum(c);
     99}
     100
     101char * tokencpy(const char *src, char *dest, int max) {
     102    int i=0;
     103    if (src[i]!='\0')
     104        while((src[i]!='\0') && !allowedhashchar(src[i]))
     105            i++;
     106
     107    while(allowedhashchar(src[i]) && (i < max)) {
     108        dest[i]=src[i];
     109        i++;
     110    }
     111
     112    dest[i]='\0';
     113    if (src[i]!='\0')
     114        while((src[i]!='\0') && !allowedhashchar(src[i]))
     115            i++;
     116    return src+i;
     117}
     118
     119#define BUFFSIZE 512
     120BOOL checker(const char *key, const char *lock)
     121{
     122    char *k, *l;
     123    char lockbuff[BUFFSIZE], keybuff[BUFFSIZE];
     124    int i=0;
     125
     126    k=key;
     127    l=lock;
     128    while (*k != '\0') {
     129        k=tokencpy(k, keybuff, BUFFSIZE);
     130        while (*l != '\0') {
     131            l=tokencpy(l, lockbuff, BUFFSIZE);
     132            i++;
     133            if (realchecker(keybuff, lockbuff)) return TRUE;
     134        }
     135    }
     136    return FALSE;
     137}
     138
     139
     140/*
     141 * cloned by Andreas Barth from
     142 * canlocktest.c written by buffy
     143 */
     144
     145BOOL realchecker(char *key, char *lock)
     146{
     147    char *rawkey, *rawlock;
     148    char keytype[BUFFSIZE], locktype[BUFFSIZE];
     149
     150    rawkey = lock_strip_alpha(key, keytype);
     151    rawlock = lock_strip_alpha(lock, locktype);
     152
     153    if (!strcmp(keytype, locktype)) {
     154        if (!strcmp(keytype, "md5")) {
     155            if (!md5_verify(rawkey, rawlock)) return TRUE;
     156            else return FALSE;
     157        } else if (!strcmp(keytype, "sha1")) {
     158            if (!sha_verify(rawkey, rawlock)) return TRUE;
     159            else return FALSE;
     160        } else return FALSE;
     161    } else return FALSE;
     162}
  • nnrpd/commands.c

    diff -Nur inn-2.3.5.orig/nnrpd/commands.c inn-2.3.5/nnrpd/commands.c
    old new  
    9191    PERMcanpost = FALSE;
    9292    PERMaccessconf->locpost = FALSE;
    9393    PERMaccessconf->allowapproved = FALSE;
     94    PERMaccessconf->allowforgecancel = FALSE;
    9495
    9596    if (!*av) {
    9697        Reply("%d no authenticator\r\n", NNTP_SYNTAX_VAL);
     
    196197    PERMaccessconf->locpost = strchr(fields[1], 'L') != NULL;
    197198    if (strchr(fields[1], 'N') != NULL) PERMaccessconf->allownewnews = TRUE;
    198199    PERMaccessconf->allowapproved = strchr(fields[1], 'A') != NULL;
     200    PERMaccessconf->allowapproved = strchr(fields[1], 'C') != NULL;
    199201    sprintf(PERMuser, "%s@%s", fields[2], fields[0]);
    200202    (void)strcpy(PERMpass, fields[3]);
    201203    (void)strcpy(accesslist, fields[4]);
  • nnrpd/nnrpd.h

    diff -Nur inn-2.3.5.orig/nnrpd/nnrpd.h inn-2.3.5/nnrpd/nnrpd.h
    old new  
    6666    int allownewnews;
    6767    int locpost;
    6868    int allowapproved;
     69    int allowforgecancel;
    6970    int used;
    7071    int localtime;
    7172    int strippath;               
     
    231232int PY_authenticate(char *ClientHost, char *ClientIP, char *ServerHost, char *Username, char *Password, char *accesslist);
    232233int PY_authorize(char *ClientHost, char *ClientIP, char *ServerHost, char *Username, char *NewsGroup, int PostFlag, char **reply_message);
    233234#endif  /* DO_PYTHON */
     235
     236#define CL_LOCK 1
     237#define CL_KEY 2
     238char* canlock (char *msgid, char *name, int mode);
  • nnrpd/perm.c

    diff -Nur inn-2.3.5.orig/nnrpd/perm.c inn-2.3.5/nnrpd/perm.c
    old new  
    407407    curaccess->allownewnews = innconf->allownewnews;
    408408    curaccess->locpost = FALSE;
    409409    curaccess->allowapproved = FALSE;
     410    curaccess->allowforgecancel = FALSE;
    410411    curaccess->localtime = FALSE;
    411412    curaccess->strippath = FALSE;
    412413    curaccess->nnrpdperlfilter = TRUE;
     
    752753            CLEAR_CONFIG(PERMpost);
    753754        }
    754755        curaccess->allowapproved = (strchr(tok->name, 'A') != NULL);
     756        curaccess->allowforgecancel = (strchr(tok->name, 'C') != NULL);
    755757        curaccess->allownewnews = (strchr(tok->name, 'N') != NULL);
    756758        curaccess->locpost = (strchr(tok->name, 'L') != NULL);
    757759        SET_CONFIG(oldtype);
  • nnrpd/post.c

    diff -Nur inn-2.3.5.orig/nnrpd/post.c inn-2.3.5/nnrpd/post.c
    old new  
    7777#define _xcomplaintsto  22
    7878    {   "NNTP-Posting-Date",    FALSE, HTstd },
    7979#define _nntppostdate   23
     80    {   "Cancel-Lock",  TRUE, HTstd },
     81#define _canlock        24
     82    {   "Cancel-Key",   TRUE, HTstd },
     83#define _cankey 25
    8084    {   "Injector-Info",        FALSE,  HTstd },
    8185    {   "Xref",                 FALSE,  HTstd },
    8286    {   "Summary",              TRUE,   HTstd },
     
    318322    static char datebuff[40];
    319323    static char localdatebuff[40];
    320324    static char orgbuff[SMBUF];
     325    static char canlockbuff[SMBUF];
     326    static char cankeybuff[SMBUF];
    321327    static char linebuff[40];
    322328    static char tracebuff[SMBUF];
    323329    static char complaintsbuff[SMBUF];
     
    521527        sprintf (complaintsbuff, "%s", NEWSMASTER);
    522528    }
    523529    HDR_SET(_xcomplaintsto ,complaintsbuff);
     530
     531
     532        /* Set Cancel-Lock */
     533    {
     534        char *admlock, *userlock;
     535        userlock=HDR(_canlock);
     536        if (!(userlock))
     537            userlock=canlock(HDR(_messageid), "/etc/news/canlock.def", CL_LOCK);
     538
     539        admlock=canlock(HDR(_messageid), "/etc/news/canlock.adm", CL_LOCK);
     540        snprintf(canlockbuff, SMBUF, "%s %s", userlock, admlock);
     541        HDR_SET(_canlock, canlockbuff);
     542    }
     543
     544    /* Set Cancel-Key */
     545    {
     546        char *messageid=NULL;
     547        if ((HDR(_control) && !(strncasecmp(HDR(_control), "cancel <", 7))))
     548            messageid=HDR(_control)+7;
     549
     550        if (HDR(_supersedes)) messageid=HDR(_supersedes);
     551
     552        if (messageid) {
     553            char *userkey;
     554            userkey=canlock(messageid, "/etc/news/canlock.def", CL_KEY);
     555            if (HDR(_cankey))
     556                snprintf(cankeybuff, SMBUF, "%s %s", HDR(_cankey), userkey);
     557            else snprintf(cankeybuff, SMBUF, "%s", userkey);
     558
     559            HDR_SET(_cankey, cankeybuff);
     560
     561            /* Verify the Cancel-Lock with the Key of the original article */
     562            if (!PERMaccessconf->allowforgecancel &&
     563                (!(testcanlock(cankeybuff, messageid)))) return Error;
     564                        /* This may be a place to verify that spam cancels follow
     565                         * the cybercancel-Conventions
     566                         */
     567        }
     568    }
    524569
    525570    /* Clear out some headers that should not be here */
    526571    if (PERMaccessconf->strippostcc) {