File: pm-jacookie.rc

package info (click to toggle)
procmail-lib 1%3A2009.1202-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,384 kB
  • sloc: perl: 294; makefile: 177; sh: 4
file content (460 lines) | stat: -rw-r--r-- 15,345 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# pm-jacookie.rc -- Handle cookie (unique id) confirmations
#
#   File id
#
#       Copyright (C) 1997-2010 Jari Aalto
#
#       This program is free software; you can redistribute it and/or
#       modify it under the terms of the GNU General Public License as
#       published by the Free Software Foundation; either version 2 of the
#       License, or (at your option) any later version
#
#       This program is distributed in the hope that it will be useful, but
#       WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#       General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with program. If not, write to the
#       Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
#       Boston, MA 02110-1301, USA.
#
#       Visit <http://www.gnu.org/copyleft/gpl.html>
#
#   Overview of features
#
#       o   Each user must register himself to cookie cache before he
#           is considered "known"
#       o   Unless user return the generated cookie string; which is
#           typically a decimal or hex number, he is not considered as
#           known and should not have access to services you provide.
#       o   Can be used as a "doorbell" spam/UBE shield
#
#   Description
#
#	This recipe handles generating the cookie to new users, comparing
#       the returned cookie against the original one and passing known
#       users through if they already had returned their cookie.
#
#       When you run automatised scripts, eg. to manage mailing lists
#       where users can subscribe and unsubscribe, you have better to
#       install safety measure so that someone can not subscribe his enemy
#       to 30 mailing lists.
#
#       The *cookie* is any continuous block of random characters that
#       is sent to person who wanted to use the service. He must send
#       back the *cookie* before the service starts an action, like
#       subscribe. If someone forges the From address to pretend to be
#       someone else and then subscribes as-beeing-someone-else to a
#       mailing list, the cookie protects this from happening.
#
#       The cookie is sent to someone-else, and he must return the cookie
#       before the "subscribe" service is activated. Obviously this
#       someone-else will not be interested in sending back the cookie and
#       thus the forgery fails. Isn't that simple, but efective protection
#       against misuse?
#
#   Should I use this as Challenge-Response Spam shield?
#
#       Unsolicited Bulk Email aka Spam is crawling from every possible
#       domain thinkable, so you might think that a challenge-response
#       policy could be deployed to regular email communication as well.
#       The idea would be that unknown people are requested to
#       "join" to a white list, before discussion is initiated with them.
#       Bulk email shotguns do not reply to challenges (here: cookies),
#       so confirmations are not returned. Individual people that want to
#       talk, *may* want to return the cookies.
#
#       Sounds like a perfect Unsolicited Bulk Email shield? No more
#       non-invited mail? Wrong. Don't use this module for that. The
#       whole idea of challenge-response is flawed and causes trouble
#       for every person who tries to contact. Imagine for 10 people
#       using C-R systems; they would all need to authenticate
#       themselves. Who is going to believe that he is not replying to
#       a spammer who is collecting email addresses? And what about
#       automatic messages that might be received -- there is no
#       artificial intelligence to deparate "human" messages from
#       automatically generated messages, so challenges just
#       increase the overall mail traffic. Every C-R system doubles
#       the mail traffic and becomes spam problem by itself.
#
#       In short, don't use this module for implementing a C-R system
#       to block regular mail to you.
#
#   How it works
#
#       By default the cookie generated uses CRC 32 `cksum', but if you have
#       md5, you should use it. The cookie is generated from the reply
#       address and immediately stored to cookie database file with entry
#
#           DATE FROM-a COOKIE-a
#           DATE FROM-b COOKIE-b
#
#       If this was a new user or an old user, who has not registered his
#       cookie yet, then original message is sent back to the sender with
#       instructions: "please place the magic string to Subject line and
#       resent the message."
#
#       When cookie is returned back, a new line to the database is added,
#       simply by adding a duplicate entry. The file now looks like this:
#
#           DATE FROM-a COOKIE-a
#           DATE FROM-b COOKIE-b
#           DATE FROM-a COOKIE-a
#
#       When there is two or more same entries, like FROM-a, the address
#       is supposed to be known and person behind it "cleared".
#
#   Required settings
#
#       PMSRC must point to source directory of procmail code. This subroutine
#       will include
#
#       o   pm-javar.rc
#       o   pm-jadate.rc
#       o   pm-jacookie1.rc
#       o   pm-jastore.rc
#
#   Call arguments (variables to set before calling)
#
#       o   JA_COOKIE_SEND, flag. Default is "yes". Set to "no" if you want
#           to take full control of the message returned to user. You can check
#           variable `ERROR' and use `key' which holds the unique `cookie'
#       o   JA_COOKIE_CACHE, cache to determine if this is new user or not.
#       o   JA_COOKIE_AUTO_KEY, flag. If set to "yes"; the cookie is
#           initially put to the Subject when the message is bounched back.
#           Receiver only has to press "r" to reply to send the cookie
#           and message back (convenient). You set this flag to "no" when
#           you want to avoid accidnebts eg. when receiver is about to
#           subscribe to a mailing lists: he has to manually insert the cookie
#           into subject. But keep flag to "yes" if you use this module to
#           get your friends registered easily.
#       o   JA_COOKIE_KEYS, the cookie database. Email address and person's
#           access cookie.
#       o   JA_COOKIE_RC, dubroutine to generate the cookie id from INPUT.
#           By default uses CRC 32.
#       o   JA_COOKIE, the string from which the cookie will be generated.
#           If you already have the return addres for the sender derived,
#           you should assing a value to this to save unnecessary formail call.
#
#   Returned values
#
#       ERROR will contain the efective action when this recipe file ends
#
#       o   "new-user", This is first message from sender.
#       o   "known-user", message has email that has been "cleared" ie.
#           cookie had been returned and user registered.
#       o   "key-mismatch", This is at least second message from sender.
#           But he dind't send the confirmation in this message.
#
#       `key' is an internal variable in this recipe file and will hold the
#       cookie id in case of "new-user" and "key-mismatch". You may want to
#       use it if you generate your own reply.
#
#   Example usage for UBE shield
#
#       This is what I use to prevent unknown people from sending me UBE.
#       It takes a bit extra, but they can easily return the message.
#       Fill in the missing variables, this won't work out of the box for you.
#
#           WORK 	= "(domain1|domain2|domain3)"
#           LISTS 	= "(procmail|list-2|list-3|list-4)"
#           VALID 	= "(postmaster|abuse|$LISTS|$WORK)"
#           RC_COOKIE   = $PMSRC/pm-jacookie.rc
#           UBE_SPOOL   = $HOME/Mail/junk.ube.spool   # Save spam here
#
#           :0
#           *$ ! From:.*$VALID
#           *$ ! ^FROM_DAEMON
#           {
#               JA_COOKIE_SEND  = "yes"         # Activate it
#               INCLUDERC       = $RC_COOKIE
#
#               :0 :
#               * ! ERROR ?? known-user
#               $UBE_SPOOL
#
#               #  ... Past this point: it was user in whitelist, so the
#               #  recipes after this block will take care of it
#           }
#
#   Example usage for subscriptions
#
#           $RC_COOKIE   = $PMSRC/pm-jacookie.rc
#
#           ...Mailing lists handled here...
#           ...Your work messages filed here..
#
#           TO            = `formail -rt -zxTo:`  # We need this elswhere
#           JA_COOKIE_TO  = $TO
#
#           #   For List-X all subscribe requests must
#           #   be confirmaed
#
#           * ^TO_()list-x
#           * ^Subject: +subscribe\>
#           {
#               JA_COOKIE_SEND  = "no"
#               INCLUDERC       = $RC_COOKIE
#
#               :0
#               * ERROR ?? known-user
#               {
#                   #   User sent the subsribe request again, allow joining
#                   #   immediately.
#               }
#               :0 E
#               {
#                   # Because the Send was set to "no"; we're in charge
#                   # to send a reply to the user.
#                   # ...generate suitable message with formail -rt
#               }
#
#           }
#
#           #  End of example
#
#   Change Log: (none)

# ............................................................ &init ...

dummy = "
======================================================================
pm-jacookie.rc: init:
"

:0
* !  WSPC ?? [ ]
{
    INCLUDERC = $PMSRC/pm-javar.rc
}

:0
*$ ! YYYY ?? ^^$d$d$d$d^^
{
    INCLUDERC = $PMSRC/pm-jadate.rc
}

JA_COOKIE_SEND       = ${JA_COOKIE_SEND:-"yes"}
JA_COOKIE_AUTO_KEY   = ${JA_COOKIE_AUTO_KEY:-"yes"}

JA_COOKIE_CACHE      = ${JA_COOKIE_CACHE:-$HOME/.cookie-cache-new-user}
JA_COOKIE_CACHE_SIZE = ${JA_COOKIE_CACHE_SIZE:-8192}
JA_COOKIE_KEYS       = ${JA_COOKIE_KEYS:-$HOME/.cookie-cache-keys}
JA_COOKIE_WHITELIST  = ${JA_COOKIE_WHITELIST:-$HOME/.cookie-cache-whitelist}

JA_COOKIE_RC         = ${JA_COOKIE_RC:-$PMSRC/pm-jacookie1.rc}

JA_COOKIE_XLOOP      = ${JA_COOKIE_XLOOP:-"\
Procmail Authentication service (PAS)"}

JA_COOKIE_SUBJECT_TAG= ${JA_COOKIE_SUBJECT_TAG:-"PAS-cookie-"}
JA_COOKIE_HEADER     = ${JA_COOKIE_HEADER:-"X-PAS-Auth-Key:"}
cookie = ""

JA_COOKIE_MSG        = ${JA_COOKIE_MSG:-"\
Your message need to be authenticated. Include the authentication key
at the end of Subject header and resend your message."}

# - If not set, set the variable. We use `r' instead of `rt'
#   because of `-rD' later.
# - User can preset the JA_COOKIE to his liking if the "to" field's
#   string is not enough to generate a unique cookie from it.

JA_COOKIE_FROM = ${JA_COOKIE_FROM:-`$FORMAIL -r -zxTo:`}

# - Should non-authenticated messages be saved? Change this
#   to mailbox name as needed.

JA_COOKIE_DEVNULL = ${JA_COOKIE_DEVNULL:-/dev/null}

# ..................................................... &read-cookie ...

jaCookieData = ""
jaCookieKey  = ""

:0
*$ $SUPREME^0 H ?? ^Subject:()\/.* +$JA_COOKIE_SUBJECT_TAG[0-9]+
*$ $SUPREME^0 B ?? ^Subject:()\/.* +$JA_COOKIE_SUBJECT_TAG[0-9]+
{
    jaCookieSubject = $MATCH

    :0
    * ^FROM_DAEMON
    {
        #   The sender is not there, drop this message

        :0 h
        * JA_COOKIE_DEVNULL ?? /dev
        $JA_COOKIE_DEVNULL

        #   For mailbox, use lock

        :0 :
        $JA_COOKIE_DEVNULL
    }

    :0
    *$ jaCookieSubject ?? $JA_COOKIE_SUBJECT_TAG\/[0-9]+
    {
        jaCookieData = $MATCH
    }

    #   Remove cookie from subject

    :0
    *$ jaCookieSubject  ?? ^()\/.* +$JA_COOKIE_SUBJECT_TAG
    *$ MATCH            ?? ^()\/.*[ ]
    *$ MATCH            ?? ^()\/.*[^ ]
    {
	jaCookieSubject = $MATCH
    }
}

#   No cookie was in the subject

:0 E
* ^Subject: \/.*
{
    jaCookieSubject = $MATCH
}

# ....................................................... &whitelist ...

#   Is this user in whitelist already?

ERROR             = ""
jaCookieWhitelist = ""

:0
* jaCookieData ?? ^^^^
* ? $GREP '\<$JA_COOKIE_FROM\>' $JA_COOKIE_WHITELIST
{
    jaCookieWhitelist = "yes"
    ERROR             = "known-user"
}

# ........................................................... &do-it ...

jaCookieNewUser     = "yes"
jaCookieDate        = $YYYY-$MM-$DD

#   - Mail arrived, check cache. Use regional lock because formail
#     is in the condition line.
#   - If user was there already, formail returns success
#   - Options -rD cause adding the email to the cache.

LOCKFILE    = ${JA_COOKIE_CACHE}.lock
dummy       = "pm-jacookie.rc: Testing new user"

:0
* jaCookieWhitelist ?? ^^^^
* ? $FORMAIL -rD $JA_COOKIE_CACHE_SIZE $JA_COOKIE_CACHE
{
    jaCookieNewUser = "no"
}

LOCKFILE
mail = ""

#   He is not in whitelist (ERROR="") and he did not return
#   the cookie (cookie="")

dummy ="pm-jacookie.rc: Check if white [$jaCookieWhitelist] ERROR [$ERROR] cookie [$cookie]"

:0
* jaCookieWhitelist ?? ^^^^
* jaCookieNewUser   ?? no
{
    dummy = "pm-jacookie.rc: Old user, did he return a cookie [$jaCookieData]"

    :0
    * jaCookieData ?? [0-9]
    {
	#  This user has returned confirmation. Check that it is correct

        dummy = "pm-jacookie.rc: confirming the cookie"

	:0
	*$ ? $GREP ".*$JA_COOKIE_FROM.+$jaCookieData" $JA_COOKIE_KEYS
	{
	    dummy = "pm-jacookie.rc: Adding to whitelist"
            msg   = "$JA_COOKIE_FROM"

	    :0 hwc : $JA_COOKIE_WHITELIST$LOCKEXT
	    | echo "$msg" >> $JA_COOKIE_WHITELIST

	    ERROR = "known-user"
	}

	:0 E
	{
	    #   Ask to send again

	    ERROR         = "cookie-error"
	    jaCookieKey   = $jaCookieData
	    jaCookieMail  = "yes"
	}
    }

    :0 E
    {
	dummy   = "pm-jacookie.rc: Unknown user. Generate new key"
        jaCookieNewUser = "yes"
    }
}

:0
* jaCookieNewUser ?? yes
{
    saved = $ERROR

        INPUT       = $JA_COOKIE_FROM
        INCLUDERC   = $JA_COOKIE_RC
        jaCookieKey = $OUTPUT

    ERROR         = $saved  #  restore value that got changed in subroutine

    jaCookieMail  = "yes"
    jaCookieMsg   = "$jaCookieDate $JA_COOKIE_FROM $jaCookieKey"
    dummy         = `echo "$jaCookieMsg" >> $JA_COOKIE_KEYS`
}

dummy = "pm-jacookie.rc: If new user/mismatched key, maybe send mail [$jaCookieMail]"

:0
*     jaCookieMail              ?? yes
*     jaCookieWhitelist         ?? ^^^^
*     JA_COOKIE_SEND            ?? yes
*  !  jaCookieKey               ?? ^^^^
*$ ! ^X-Loop:.*$JA_COOKIE_XLOOP
*$ !  $JA_FROM_DAEMON
{
    dummy = "pm-jacookie.rc: Request authentication $JA_COOKIE_FROM"

    #   - If auto-mode is "on"; then put the key in the subject
    #   - Sender only has to reply to message.

    jaCookieKey = "$JA_COOKIE_SUBJECT_TAG$jaCookieKey"

    :0 fhw
    *  JA_COOKIE_AUTO_KEY ?? yes
    | $FORMAIL -I "Subject: $jaCookieSubject $jaCookieKey"

    #   Add extra header as well to message that go past the next one

    :0 fhw
    | $FORMAIL -A "$JA_COOKIE_HEADER $jaCookieKey"

    :0 hbw c: $JA_COOKIE_CACHE$LOCKEXT
    | ( $FORMAIL -rk -b                                                     \
        -A "X-Loop: $JA_COOKIE_XLOOP";                                      \
        echo "You Authentication key is: $jaCookieKey";                     \
        echo "$JA_COOKIE_MSG";                                              \
        ) | $SENDMAIL $SENDMAIL_FLAGS

}

dummy = "pm-jacookie.rc: end: $ERROR"

# pm-store.rc ends here