Line data Source code
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 :
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 324 : _gpgme_sig_notation_free (gpgme_sig_notation_t notation)
41 : {
42 324 : if (notation->name)
43 216 : free (notation->name);
44 :
45 324 : if (notation->value)
46 324 : free (notation->value);
47 :
48 324 : free (notation);
49 324 : }
50 :
51 :
52 : /* Set the flags of NOTATION to FLAGS. */
53 : static void
54 324 : 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 324 : notation->human_readable = flags & GPGME_SIG_NOTATION_HUMAN_READABLE ? 1 : 0;
60 324 : notation->critical = flags & GPGME_SIG_NOTATION_CRITICAL ? 1 : 0;
61 :
62 324 : notation->flags = flags;
63 324 : }
64 :
65 :
66 : /* Create a new, empty signature notation data object. */
67 : gpgme_error_t
68 324 : _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 324 : gpgme_error_t err = 0;
74 : gpgme_sig_notation_t notation;
75 :
76 : /* Currently, we require all notations to be human-readable. */
77 324 : if (name && !(flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
78 0 : return gpg_error (GPG_ERR_INV_VALUE);
79 :
80 324 : notation = calloc (1, sizeof (*notation));
81 324 : if (!notation)
82 0 : return gpg_error_from_syserror ();
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 324 : if (name)
88 : {
89 : /* We add a trailing '\0' for stringification in the good
90 : case. */
91 6 : notation->name = malloc (name_len + 1);
92 6 : if (!notation->name)
93 : {
94 0 : err = gpg_error_from_syserror ();
95 0 : goto err;
96 : }
97 :
98 6 : memcpy (notation->name, name, name_len);
99 6 : notation->name[name_len] = '\0';
100 6 : notation->name_len = name_len;
101 : }
102 :
103 324 : if (value)
104 : {
105 : /* We add a trailing '\0' for stringification in the good
106 : case. */
107 9 : notation->value = malloc (value_len + 1);
108 9 : if (!notation->value)
109 : {
110 0 : err = gpg_error_from_syserror ();
111 0 : goto err;
112 : }
113 :
114 9 : memcpy (notation->value, value, value_len);
115 9 : notation->value[value_len] = '\0';
116 9 : notation->value_len = value_len;
117 : }
118 :
119 324 : sig_notation_set_flags (notation, flags);
120 :
121 324 : *notationp = notation;
122 324 : return 0;
123 :
124 : err:
125 0 : _gpgme_sig_notation_free (notation);
126 0 : return err;
127 : }
128 :
129 :
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 0 : _gpgme_parse_notation (gpgme_sig_notation_t *notationp,
142 : int type, int pkflags, int len, char *data)
143 : {
144 : gpgme_error_t err;
145 0 : char *name = NULL;
146 0 : int name_len = 0;
147 0 : char *value = NULL;
148 0 : int value_len = 0;
149 0 : 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 0 : if (type != 20 && type != 26)
156 : {
157 0 : *notationp = NULL;
158 0 : return 0;
159 : }
160 :
161 : /* A few simple sanity checks. */
162 0 : if (len > strlen (data))
163 0 : 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 0 : if (type == 20 && len < 4 + 2 + 2)
169 0 : return trace_gpg_error (GPG_ERR_INV_ENGINE);
170 :
171 0 : err = _gpgme_decode_percent_string (data, &decoded_data, 0, 1);
172 0 : if (err)
173 0 : return err;
174 0 : bdata = (unsigned char *) decoded_data;
175 :
176 : /* Flags common to notation data and policy URL. */
177 0 : if (pkflags & GNUPG_SPK_CRITICAL)
178 0 : 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 0 : 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 0 : chr = *bdata;
218 0 : bdata++;
219 :
220 0 : if (chr & RFC2440_SPK20_FLAG1_HUMAN_READABLE)
221 0 : flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
222 :
223 : /* The second, third and four octet of flags are unused. */
224 0 : bdata++;
225 0 : bdata++;
226 0 : bdata++;
227 :
228 0 : name_len = RFC2440_GET_WORD (bdata);
229 0 : bdata += 2;
230 :
231 0 : value_len = RFC2440_GET_WORD (bdata);
232 0 : bdata += 2;
233 :
234 : /* Small sanity check. */
235 0 : if (4 + 2 + 2 + name_len + value_len > len)
236 : {
237 0 : free (decoded_data);
238 0 : return trace_gpg_error (GPG_ERR_INV_ENGINE);
239 : }
240 :
241 0 : name = (char *) bdata;
242 0 : bdata += name_len;
243 :
244 0 : value = (char *) bdata;
245 : }
246 : else
247 : {
248 : /* Type is 26. */
249 :
250 : /* NAME is NULL, name_len is 0. */
251 :
252 0 : value = (char *) bdata;
253 0 : value_len = strlen (value);
254 : }
255 :
256 0 : err = _gpgme_sig_notation_create (notationp, name, name_len,
257 : value, value_len, flags);
258 :
259 0 : free (decoded_data);
260 0 : return err;
261 : }
|