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
|
--[[
Copyright (c) 2022, Vsevolod Stakhov <vsevolod@rspamd.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]--
local argparse = require "argparse"
-- Define command line options
local parser = argparse()
:name "rspamadm cookie"
:description "Produces cookies or message ids"
:help_description_margin(30)
parser:mutex(
parser:option "-k --key"
:description('Key to load')
:argname "<32hex>",
parser:flag "-K --new-key"
:description('Generates a new key')
)
parser:option "-d --domain"
:description('Use specified domain and generate full message id')
:argname "<domain>"
parser:flag "-D --decrypt"
:description('Decrypt cookie instead of encrypting one')
parser:flag "-t --timestamp"
:description('Show cookie timestamp (valid for decrypting only)')
parser:argument "cookie":args "?"
:description('Use specified cookie')
local function gen_cookie(args, key)
local cr = require "rspamd_cryptobox"
if not args.cookie then
return
end
local function encrypt()
if #args.cookie > 31 then
print('cookie too long (>31 characters), cannot encrypt')
os.exit(1)
end
local enc_cookie = cr.encrypt_cookie(key, args.cookie)
if args.domain then
print(string.format('<%s@%s>', enc_cookie, args.domain))
else
print(enc_cookie)
end
end
local function decrypt()
local extracted_cookie = args.cookie:match('^%<?([^@]+)@.*$')
if not extracted_cookie then
-- Assume full message id as a cookie
extracted_cookie = args.cookie
end
local dec_cookie, ts = cr.decrypt_cookie(key, extracted_cookie)
if dec_cookie then
if args.timestamp then
print(string.format('%s %s', dec_cookie, ts))
else
print(dec_cookie)
end
else
print('cannot decrypt cookie')
os.exit(1)
end
end
if args.decrypt then
decrypt()
else
encrypt()
end
end
local function handler(args)
local res = parser:parse(args)
if not (res.key or res['new_key']) then
parser:error('--key or --new-key must be specified')
end
if res.key then
local pattern = { '^' }
for i = 1, 32 do
pattern[i + 1] = '[a-zA-Z0-9]'
end
pattern[34] = '$'
if not res.key:match(table.concat(pattern, '')) then
parser:error('invalid key: ' .. res.key)
end
gen_cookie(res, res.key)
else
local util = require "rspamd_util"
local key = util.random_hex(32)
print(key)
gen_cookie(res, res.key)
end
end
return {
handler = handler,
description = parser._description,
name = 'cookie'
}
|