Bump copyright years
[smime-smtp-proxy.git] / smime-smtp-filter
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 # Copyright 2008-2010 Joachim Breitner
5
6 # Licensed under the EUPL, Version 1.0 or – as soon they
7 # will be approved by the European Commission - subsequent
8 # versions of the EUPL (the "Licence");
9 # you may not use this work except in compliance with the
10 # Licence.
11 # You may obtain a copy of the Licence at:
12
13 # http://ec.europa.eu/idabc/7330l5
14
15 # Unless required by applicable law or agreed to in
16 # writing, software distributed under the Licence is
17 # distributed on an "AS IS" BASIS,
18 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
19 # express or implied.
20 # See the Licence for the specific language governing
21 # permissions and limitations under the Licence.
22
23
24 """An smime signing filter to be used with proxsmtp
25
26 Usage: %(program)s --keyfile file.pem
27
28 Options:
29
30     --keyfile file.pem
31     -k file.pem
32         Loads the key and certificate from the given file.
33
34     -h, --help
35         Displays this help message
36 """
37
38 import getopt, sys
39
40 from M2Crypto import BIO, SMIME, X509
41
42 program = sys.argv[0]
43
44 def usage(code, msg=''):
45     print >> sys.stderr, __doc__ % globals()
46     if msg:
47         print >> sys.stderr, msg
48     sys.exit(code)
49
50 class Options:
51     keyfile = None
52
53 def parseargs():
54     global DEBUGSTREAM
55     try:
56         opts, args = getopt.getopt(
57             sys.argv[1:], 'hVk:',
58             ['keyfile=','help','version'])
59     except getopt.error, e:
60         usage(1, e)
61
62     options = Options()
63     for opt, arg in opts:
64         if opt in ('-h', '--help'):
65             usage(0)
66         #elif opt in ('-V', '--version'):
67         #    print >> sys.stderr, __version__
68         #    sys.exit(0)
69         elif opt in ('-k', '--keyfile'):
70             options.keyfile = arg
71         elif opt in ('-d', '--debug'):
72             DEBUGSTREAM = sys.stderr
73
74     if options.keyfile is None:
75         usage(1, 'Missing required parameter: keyfile')
76
77     return options
78
79 if __name__ == '__main__':
80     options = parseargs()
81
82     header = ""
83     body = ""
84     last_header_to = "header"
85     for line in sys.stdin:
86         if line[0] == '\t':
87             # header continuation (rfc2822)
88             if last_header_to == "header":
89                 header += line    
90             elif last_header_to == "nothing":
91                 pass
92             elif last_header_to == "body":
93                 body += line
94
95         elif line == '\r\n':
96             break
97
98         # some headers have to be moved to the body or stripped
99         elif   line.lower().startswith(("content-type: ",
100                                       "content-transfer-encoding: ")):
101             last_header_to = "body"
102             body += line
103         elif line.lower().startswith("mime-version: "):
104             last_header_to = "nothing"
105             pass
106         else:
107             last_header_to = "header"
108             header += line
109
110     if body != "":
111         body += "\r\n"
112
113     for line in sys.stdin:
114         body += line
115
116     msg_bio = BIO.MemoryBuffer(body) 
117     s = SMIME.SMIME()
118
119     s.load_key(options.keyfile)
120     #p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT)
121     p7 = s.sign(msg_bio)
122     
123     msg_bio = BIO.MemoryBuffer(body) 
124     out = BIO.MemoryBuffer()
125     s.write(out, p7, msg_bio) #, SMIME.PKCS7_TEXT)
126
127     sys.stdout.write(header)
128     # Convert all line endings to \r\n
129     for line in out.read().splitlines():
130         sys.stdout.write(line)
131         sys.stdout.write('\r\n')
132
133
134