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