Trace the use of GPG_ERR_INV_ENGINE.
[gpgme.git] / src / sig-notation.c
1 /* sig-notation.c - Signature notation data support.
2    Copyright (C) 2005 g10 Code GmbH
3
4    This file is part of GPGME.
5
6    GPGME is free software; you can redistribute it and/or modify it
7    under the terms of the GNU Lesser General Public License as
8    published by the Free Software Foundation; either version 2.1 of
9    the License, or (at your option) any later version.
10
11    GPGME is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28
29 #include "gpgme.h"
30 #include "util.h"
31 #include "context.h"
32 #include "ops.h"
33 #include "debug.h"
34
35 \f
36 /* Free the signature notation object and all associated resources.
37    The object must already be removed from any linked list as the next
38    pointer is ignored.  */
39 void
40 _gpgme_sig_notation_free (gpgme_sig_notation_t notation)
41 {
42   if (notation->name)
43     free (notation->name);
44
45   if (notation->value)
46     free (notation->value);
47
48   free (notation);
49 }
50
51 \f
52 /* Set the flags of NOTATION to FLAGS.  */
53 static void
54 sig_notation_set_flags (gpgme_sig_notation_t notation,
55                         gpgme_sig_notation_flags_t flags)
56 {
57   /* We copy the flags into individual bits to make them easier
58      accessible individually for the user.  */
59   notation->human_readable = flags & GPGME_SIG_NOTATION_HUMAN_READABLE ? 1 : 0;
60   notation->critical = flags & GPGME_SIG_NOTATION_CRITICAL ? 1 : 0;
61
62   notation->flags = flags;
63 }
64
65
66 /* Create a new, empty signature notation data object.  */
67 gpgme_error_t
68 _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp,
69                             const char *name, int name_len,
70                             const char *value, int value_len,
71                             gpgme_sig_notation_flags_t flags)
72 {
73   gpgme_error_t err = 0;
74   gpgme_sig_notation_t notation;
75
76   /* Currently, we require all notations to be human-readable.  */
77   if (name && !(flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
78     return gpg_error (GPG_ERR_INV_VALUE);
79
80   notation = calloc (1, sizeof (*notation));
81   if (!notation)
82     return gpg_error_from_errno (errno);
83
84   /* This is critical.  We want to reliably identify policy URLs by
85      using a NULL pointer for NAME.  So all notations must have a NAME
86      string, even if it is empty.  */
87   if (name)
88     {
89       /* We add a trailing '\0' for stringification in the good
90          case.  */
91       notation->name = malloc (name_len + 1);
92       if (!notation->name)
93         {
94           err = gpg_error_from_errno (errno);
95           goto err;
96         }
97
98       memcpy (notation->name, name, name_len);
99       notation->name[name_len] = '\0';
100       notation->name_len = name_len;
101     }
102
103   if (value)
104     {
105       /* We add a trailing '\0' for stringification in the good
106          case.  */
107       notation->value = malloc (value_len + 1);
108       if (!notation->value)
109         {
110           err = gpg_error_from_errno (errno);
111           goto err;
112         }
113
114       memcpy (notation->value, value, value_len);
115       notation->value[value_len] = '\0';
116       notation->value_len = value_len;
117     }
118
119   sig_notation_set_flags (notation, flags);
120
121   *notationp = notation;
122   return 0;
123
124  err:
125   _gpgme_sig_notation_free (notation);
126   return err;
127 }
128
129 \f
130 /* GnuPG subpacket flags.  */
131
132 /* This subpacket data is part of the hashed data.  */
133 #define GNUPG_SPK_HASHED        0x01
134
135 /* This subpacket is marked critical.  */
136 #define GNUPG_SPK_CRITICAL      0x02
137
138 /* Parse a notation or policy URL subpacket.  If the packet type is
139    not known, return no error but NULL in NOTATION.  */
140 gpgme_error_t
141 _gpgme_parse_notation (gpgme_sig_notation_t *notationp,
142                        int type, int pkflags, int len, char *data)
143 {
144   gpgme_error_t err;
145   char *name = NULL;
146   int name_len = 0;
147   char *value = NULL;
148   int value_len = 0;
149   gpgme_sig_notation_flags_t flags = 0;
150   char *decoded_data;
151   unsigned char *bdata;
152
153   /* Type 20: Notation data.  */
154   /* Type 26: Policy URL.  */
155   if (type != 20 && type != 26)
156     {
157       *notationp = NULL;
158       return 0;
159     }
160
161   /* A few simple sanity checks.  */
162   if (len > strlen (data))
163     return trace_gpg_error (GPG_ERR_INV_ENGINE);
164
165   /* See below for the format of a notation subpacket.  It has at
166      least four octets of flags and two times two octets of length
167      information.  */
168   if (type == 20 && len < 4 + 2 + 2)
169     return trace_gpg_error (GPG_ERR_INV_ENGINE);
170
171   err = _gpgme_decode_percent_string (data, &decoded_data, 0, 1);
172   if (err)
173     return err;
174   bdata = (unsigned char *) decoded_data;
175
176   /* Flags common to notation data and policy URL.  */
177   if (pkflags & GNUPG_SPK_CRITICAL)
178     flags |= GPGME_SIG_NOTATION_CRITICAL;
179
180   /* This information is relevant in parsing multi-octet numbers below:
181
182      3.1. Scalar numbers
183
184      Scalar numbers are unsigned, and are always stored in big-endian
185      format.  Using n[k] to refer to the kth octet being interpreted,
186      the value of a two-octet scalar is ((n[0] << 8) + n[1]).  The
187      value of a four-octet scalar is ((n[0] << 24) + (n[1] << 16) +
188      (n[2] << 8) + n[3]).
189
190      From RFC2440: OpenPGP Message Format.  Copyright (C) The Internet
191      Society (1998).  All Rights Reserved.  */
192 #define RFC2440_GET_WORD(chr) ((((int)((unsigned char *)(chr))[0]) << 8) \
193                                + ((int)((unsigned char *)(chr))[1]))
194
195   if (type == 20)
196     {
197       /* 5.2.3.15. Notation Data
198
199          (4 octets of flags, 2 octets of name length (M),
200          2 octets of value length (N), M octets of name data,
201          N octets of value data)
202
203          [...] The "flags" field holds four octets of flags.
204          All undefined flags MUST be zero. Defined flags are:
205
206          First octet: 0x80 = human-readable. [...]
207          Other octets:  none.
208
209          From RFC2440: OpenPGP Message Format.  Copyright (C) The
210          Internet Society (1998).  All Rights Reserved.  */
211
212       int chr;
213
214       /* First octet of flags.  */
215 #define RFC2440_SPK20_FLAG1_HUMAN_READABLE 0x80
216
217       chr = *bdata;
218       bdata++;
219
220       if (chr & RFC2440_SPK20_FLAG1_HUMAN_READABLE)
221         flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
222
223       /* The second, third and four octet of flags are unused.  */
224       bdata++;
225       bdata++;
226       bdata++;
227
228       name_len = RFC2440_GET_WORD (bdata);
229       bdata += 2;
230
231       value_len = RFC2440_GET_WORD (bdata);
232       bdata += 2;
233
234       /* Small sanity check.  */
235       if (4 + 2 + 2 + name_len + value_len > len)
236         {
237           free (decoded_data);
238           return trace_gpg_error (GPG_ERR_INV_ENGINE);
239         }
240
241       name = (char *) bdata;
242       bdata += name_len;
243
244       value = (char *) bdata;
245     }
246   else
247     {
248       /* Type is 26.  */
249
250       /* NAME is NULL, name_len is 0.  */
251
252       value = (char *) bdata;
253       value_len = strlen (value);
254     }
255
256   err = _gpgme_sig_notation_create (notationp, name, name_len,
257                                     value, value_len, flags);
258
259   free (decoded_data);
260   return err;
261 }