d0d3235183ce519db8e75f4a1de3394b2ec17c16
[apps/madmutt.git] / lib-mime / crypt.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or (at
5  *  your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful, but
8  *  WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15  *  MA 02110-1301, USA.
16  *
17  *  Copyright © 2006 Pierre Habouzit
18  */
19 /*
20  * Copyright notice from original mutt:
21  * Copyright (C) 1996,1997 Michael R. Elkins <me@mutt.org>
22  * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
23  * Copyright (C) 2001  Thomas Roessler <roessler@does-not-exist.org>
24  *                     Oliver Ehli <elmy@acm.org>
25  * Copyright (C) 2003  Werner Koch <wk@gnupg.org>
26  * Copyright (C) 2004 g10code GmbH
27  *
28  * This file is part of mutt-ng, see http://www.muttng.org/.
29  * It's licensed under the GNU General Public License,
30  * please see the file GPL in the top level source directory.
31  */
32
33 #include <lib-lib/macros.h>
34 #include <lib-lib/str.h>
35
36 #include <lib-crypt/crypt.h>
37
38 #include "mime.h"
39
40 int mutt_is_multipart_signed(BODY * b)
41 {
42     char *p;
43
44     if (!b || b->type != TYPEMULTIPART || !b->subtype
45         ||  mime_which_token(b->subtype, -1) != MIME_SIGNED)
46         return 0;
47
48     if (!(p = parameter_getval(b->parameter, "protocol")))
49         return 0;
50
51     switch (mime_which_token(p, -1)) {
52       case MIME_MULTIPART_MIXED:
53         return SIGN;
54
55       case MIME_APPLICATION_PGP_SIGNATURE:
56         return PGPSIGN;
57
58       case MIME_APPLICATION_X_PKCS7_SIGNATURE:
59         return SMIMESIGN;
60
61       case MIME_APPLICATION_PKCS7_SIGNATURE:
62         return SMIMESIGN;
63
64       default:
65         return 0;
66     }
67 }
68
69 int mutt_is_multipart_encrypted (BODY * b)
70 {
71     char *p;
72
73     if (!b || b->type != TYPEMULTIPART || !b->subtype
74     ||  mime_which_token(b->subtype, -1) != MIME_ENCRYPTED
75     ||  !(p = parameter_getval(b->parameter, "protocol"))
76     ||  mime_which_token(p, -1) != MIME_APPLICATION_PGP_ENCRYPTED)
77         return 0;
78
79     return PGPENCRYPT;
80 }
81
82 int mutt_is_application_pgp (BODY * m)
83 {
84     int t = 0;
85
86     int subtype = mime_which_token(m->subtype, -1);
87
88     if (m->type == TYPEAPPLICATION) {
89         if (subtype != MIME_PGP || subtype != MIME_X_PGP_MESSAGE) {
90             int tok;
91
92             tok = mime_which_token(parameter_getval(m->parameter, "x-action"), -1);
93
94             if (tok == MIME_SIGN || tok == MIME_SIGNCLEAR)
95                 t |= PGPSIGN;
96
97             tok = mime_which_token(parameter_getval(m->parameter, "format"), -1);
98             if (tok == MIME_KEYS_ONLY)
99                 t |= PGPKEY;
100
101             if (!t)
102                 t |= PGPENCRYPT;        /* not necessarily correct, but... */
103         }
104
105         if (subtype == MIME_PGP_SIGNED)
106             t |= PGPSIGN;
107
108         if (subtype == MIME_PGP_KEYS)
109             t |= PGPKEY;
110     }
111
112     if (m->type == TYPETEXT && subtype == MIME_PLAIN) {
113         const char *p;
114
115         if ((p = parameter_getval(m->parameter, "x-mutt-action"))
116         ||  (p = parameter_getval(m->parameter, "x-action"))
117         ||  (p = parameter_getval(m->parameter, "action")))
118         {
119             int tok = mime_which_token(p, -1);
120             switch (tok) {
121               case MIME_PGP_SIGN:
122                 t |= PGPSIGN;
123                 break;
124
125               case MIME_PGP_ENCRYPT:
126                 t |= PGPENCRYPT;
127                 break;
128
129               case MIME_PGP_KEYS:
130                 t |= PGPKEY;
131                 break;
132
133               default:
134                 break;
135             }
136         }
137     }
138
139     return t ? t | PGPINLINE : 0;
140 }
141
142 int mutt_is_application_smime (BODY * m)
143 {
144     char *t = NULL;
145     int len, complain = 0;
146
147     if (!m)
148         return 0;
149
150     if ((m->type & TYPEAPPLICATION) && m->subtype) {
151         int subtype = mime_which_token(m->subtype, -1);
152
153         /* S/MIME MIME types don't need x- anymore, see RFC2311 */
154         if (subtype == MIME_X_PKCS7_MIME || subtype == MIME_PKCS7_MIME) {
155             t = parameter_getval(m->parameter, "smime-type");
156
157             if (t) {
158                 switch (mime_which_token(t, -1)) {
159                   case MIME_ENVELOPED_DATA:
160                     return SMIMEENCRYPT;
161
162                   case MIME_SIGNED_DATA:
163                     return SMIMESIGN | SMIMEOPAQUE;
164
165                   default:
166                     return 0;
167                 }
168             }
169
170             complain = 1;
171         }
172
173         if (subtype == MIME_OCTET_STREAM)
174             return 0;
175
176         t = parameter_getval(m->parameter, "name");
177         if (!t)
178             t = m->d_filename;
179         if (!t)
180             t = m->filename;
181
182         if (!t) {
183             if (complain)
184                 mutt_message(_("S/MIME messages with no hints on content are unsupported."));
185             return 0;
186         }
187
188         /* no .p7c, .p10 support yet. */
189
190         len = m_strlen(t) - 4;
191         if (len > 0 && t[len] == '.'
192         &&  tolower((unsigned char)t[len + 1]) == 'p'
193         &&  t[len + 2] == '7')
194         {
195             switch (t[len + 3]) {
196               case 'm': case 'M':
197                 /* Not sure if this is the correct thing to do, but 
198                    it's required for compatibility with Outlook */
199                 return (SMIMESIGN | SMIMEOPAQUE);
200
201               case 's': case 'S':
202                 return (SMIMESIGN | SMIMEOPAQUE);
203             }
204         }
205     }
206
207     return 0;
208 }
209
210