1 /*
2 * Copyright (C) 2011 Collabora Ltd.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
11 * * Redistributions in binary form must reproduce the
12 * above copyright notice, this list of conditions and
13 * the following disclaimer in the documentation and/or
14 * other materials provided with the distribution.
15 * * The names of contributors to this software may not be
16 * used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 * DAMAGE.
31 *
32 * Author: Stef Walter <stefw@collabora.co.uk>
33 */
34
35 #include "config.h"
36
37 #include "array.h"
38 #include "attrs.h"
39 #include "buffer.h"
40 #define P11_DEBUG_FLAG P11_DEBUG_URI
41 #include "debug.h"
42 #include "message.h"
43 #include "pkcs11.h"
44 #include "private.h"
45 #include "p11-kit.h"
46 #include "uri.h"
47 #include "url.h"
48
49 #include <assert.h>
50 #include <ctype.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54
55 /**
56 * SECTION:p11-kit-uri
57 * @title: URIs
58 * @short_description: Parsing and formatting PKCS\#11 URIs
59 *
60 * PKCS\#11 URIs can be used in configuration files or applications to represent
61 * PKCS\#11 modules, tokens or objects. An example of a URI might be:
62 *
63 * <code><literallayout>
64 * pkcs11:token=The\%20Software\%20PKCS\#11\%20softtoken;
65 * manufacturer=Snake\%20Oil,\%20Inc.;serial=;object=my-certificate;
66 * model=1.0;type=cert;id=\%69\%95\%3e\%5c\%f4\%bd\%ec\%91
67 * </literallayout></code>
68 *
69 * You can use p11_kit_uri_parse() to parse such a URI, and p11_kit_uri_format()
70 * to build one. URIs are represented by the #P11KitUri structure. You can match
71 * a parsed URI against PKCS\#11 tokens with p11_kit_uri_match_token_info()
72 * or attributes with p11_kit_uri_match_attributes().
73 *
74 * Since URIs can represent different sorts of things, when parsing or formatting
75 * a URI a 'context' can be used to indicate which sort of URI is expected.
76 *
77 * URIs have an <code>unrecognized</code> flag. This flag is set during parsing
78 * if any parts of the URI are not recognized. This may be because the part is
79 * from a newer version of the PKCS\#11 spec or because that part was not valid
80 * inside of the desired context used when parsing.
81 */
82
83 /**
84 * P11KitUri:
85 *
86 * A structure representing a PKCS\#11 URI. There are no public fields
87 * visible in this structure. Use the various accessor functions.
88 */
89
90 /**
91 * P11KitUriType:
92 * @P11_KIT_URI_FOR_OBJECT: The URI represents one or more objects
93 * @P11_KIT_URI_FOR_TOKEN: The URI represents one or more tokens
94 * @P11_KIT_URI_FOR_SLOT: The URI represents one or more slots
95 * @P11_KIT_URI_FOR_MODULE: The URI represents one or more modules
96 * @P11_KIT_URI_FOR_MODULE_WITH_VERSION: The URI represents a module with
97 * a specific version.
98 * @P11_KIT_URI_FOR_OBJECT_ON_TOKEN: The URI represents one or more objects
99 * that are present on a specific token.
100 * @P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE: The URI represents one or more
101 * objects that are present on a specific token, being used with a certain
102 * module.
103 * @P11_KIT_URI_FOR_ANY: The URI can represent anything
104 *
105 * A PKCS\#11 URI can represent different kinds of things. This flag is used by
106 * p11_kit_uri_parse() to denote in what context the URI will be used.
107 *
108 * The various types can be combined.
109 */
110
111 /**
112 * P11KitUriResult:
113 * @P11_KIT_URI_OK: Success
114 * @P11_KIT_URI_UNEXPECTED: Unexpected or internal system error
115 * @P11_KIT_URI_BAD_SCHEME: The URI had a bad scheme
116 * @P11_KIT_URI_BAD_ENCODING: The URI had a bad encoding
117 * @P11_KIT_URI_BAD_SYNTAX: The URI had a bad syntax
118 * @P11_KIT_URI_BAD_VERSION: The URI contained a bad version number
119 * @P11_KIT_URI_NOT_FOUND: A requested part of the URI was not found
120 *
121 * Error codes returned by various functions. The functions each clearly state
122 * which error codes they are capable of returning.
123 */
124
125 /**
126 * P11_KIT_URI_NO_MEMORY:
127 *
128 * Unexpected memory allocation failure result. Same as #P11_KIT_URI_UNEXPECTED.
129 */
130
131 /**
132 * P11_KIT_URI_SCHEME:
133 *
134 * String of URI scheme for PKCS\#11 URIs.
135 */
136
137 /**
138 * P11_KIT_URI_SCHEME_LEN:
139 *
140 * Length of %P11_KIT_URI_SCHEME.
141 */
142
143 typedef struct _Attribute {
144 char *name;
145 char *value;
146 } Attribute;
147
148 struct p11_kit_uri {
149 bool unrecognized;
150 CK_INFO module;
151 CK_SLOT_INFO slot;
152 CK_TOKEN_INFO token;
153 CK_ATTRIBUTE *attrs;
154 CK_SLOT_ID slot_id;
155 char *pin_source;
156 char *pin_value;
157 char *module_name;
158 char *module_path;
159 p11_array *qattrs;
160 };
161
162 static char *
strip_whitespace(const char * value)163 strip_whitespace (const char *value)
164 {
165 size_t length = strlen (value);
166 char *at, *pos;
167 char *key;
168
169 key = malloc (length + 1);
170 return_val_if_fail (key != NULL, NULL);
171
172 memcpy (key, value, length);
173 key[length] = '\0';
174
175 /* Do we have any whitespace? Strip it out. */
176 if (strcspn (key, P11_URL_WHITESPACE) != length) {
177 for (at = key, pos = key; pos != key + length + 1; ++pos) {
178 if (!strchr (P11_URL_WHITESPACE, *pos))
179 *(at++) = *pos;
180 }
181 *at = '\0';
182 }
183
184 return key;
185 }
186
187 static bool
match_struct_string(const unsigned char * inuri,const unsigned char * real,size_t length)188 match_struct_string (const unsigned char *inuri, const unsigned char *real,
189 size_t length)
190 {
191 assert (inuri);
192 assert (real);
193 assert (length > 0);
194
195 /* NULL matches anything */
196 if (inuri[0] == 0)
197 return true;
198
199 return memcmp (inuri, real, length) == 0 ? true : false;
200 }
201
202 static bool
match_struct_version(CK_VERSION const * inuri,CK_VERSION const * real)203 match_struct_version (CK_VERSION const *inuri, CK_VERSION const *real)
204 {
205 /* This matches anything */
206 if (inuri->major == (CK_BYTE)-1 && inuri->minor == (CK_BYTE)-1)
207 return true;
208
209 return memcmp (inuri, real, sizeof (CK_VERSION)) == 0 ? true : false;
210 }
211
212 /**
213 * p11_kit_uri_get_module_info:
214 * @uri: the URI
215 *
216 * Get the <code>CK_INFO</code> structure associated with this URI.
217 *
218 * If this is a parsed URI, then the fields corresponding to library parts of
219 * the URI will be filled in. Any library URI parts that were missing will have
220 * their fields filled with zeros.
221 *
222 * If the caller wishes to setup information for building a URI, then relevant
223 * fields should be filled in. Fields that should not appear as parts in the
224 * resulting URI should be filled with zeros.
225 *
226 * Returns: A pointer to the <code>CK_INFO</code> structure.
227 */
228 CK_INFO_PTR
p11_kit_uri_get_module_info(P11KitUri * uri)229 p11_kit_uri_get_module_info (P11KitUri *uri)
230 {
231 return_val_if_fail (uri != NULL, NULL);
232 return &uri->module;
233 }
234
235 int
p11_match_uri_module_info(CK_INFO const * one,CK_INFO const * two)236 p11_match_uri_module_info (CK_INFO const *one,
237 CK_INFO const *two)
238 {
239 return (match_struct_string (one->libraryDescription,
240 two->libraryDescription,
241 sizeof (one->libraryDescription)) &&
242 match_struct_string (one->manufacturerID,
243 two->manufacturerID,
244 sizeof (one->manufacturerID)) &&
245 match_struct_version (&one->libraryVersion,
246 &two->libraryVersion));
247 }
248
249 /**
250 * p11_kit_uri_match_module_info:
251 * @uri: the URI
252 * @info: the structure to match against the URI
253 *
254 * Match a <code>CK_INFO</code> structure against the library parts of this URI.
255 *
256 * Only the fields of the <code>CK_INFO</code> structure that are valid for use
257 * in a URI will be matched. A URI part that was not specified in the URI will
258 * match any value in the structure. If during the URI parsing any unrecognized
259 * parts were encountered then this match will fail.
260 *
261 * Returns: 1 if the URI matches, 0 if not.
262 */
263 int
p11_kit_uri_match_module_info(const P11KitUri * uri,const CK_INFO * info)264 p11_kit_uri_match_module_info (const P11KitUri *uri, const CK_INFO *info)
265 {
266 return_val_if_fail (uri != NULL, 0);
267 return_val_if_fail (info != NULL, 0);
268
269 if (uri->unrecognized)
270 return 0;
271
272 return p11_match_uri_module_info (&uri->module, info);
273 }
274
275 /**
276 * p11_kit_uri_get_slot_info:
277 * @uri: the URI
278 *
279 * Get the <code>CK_SLOT_INFO</code> structure associated with this URI.
280 *
281 * If this is a parsed URI, then the fields corresponding to slot parts of
282 * the URI will be filled in. Any slot URI parts that were missing will have
283 * their fields filled with zeros.
284 *
285 * If the caller wishes to setup information for building a URI, then relevant
286 * fields should be filled in. Fields that should not appear as parts in the
287 * resulting URI should be filled with zeros.
288 *
289 * Returns: A pointer to the <code>CK_INFO</code> structure.
290 */
291 CK_SLOT_INFO_PTR
p11_kit_uri_get_slot_info(P11KitUri * uri)292 p11_kit_uri_get_slot_info (P11KitUri *uri)
293 {
294 return_val_if_fail (uri != NULL, NULL);
295 return &uri->slot;
296 }
297
298 int
p11_match_uri_slot_info(CK_SLOT_INFO const * one,CK_SLOT_INFO const * two)299 p11_match_uri_slot_info (CK_SLOT_INFO const *one,
300 CK_SLOT_INFO const *two)
301 {
302 return (match_struct_string (one->slotDescription,
303 two->slotDescription,
304 sizeof (one->slotDescription)) &&
305 match_struct_string (one->manufacturerID,
306 two->manufacturerID,
307 sizeof (one->manufacturerID)));
308 }
309
310 /**
311 * p11_kit_uri_match_slot_info:
312 * @uri: the URI
313 * @slot_info: the structure to match against the URI
314 *
315 * Match a <code>CK_SLOT_INFO</code> structure against the slot parts of this
316 * URI.
317 *
318 * Only the fields of the <code>CK_SLOT_INFO</code> structure that are valid
319 * for use in a URI will be matched. A URI part that was not specified in the
320 * URI will match any value in the structure. If during the URI parsing any
321 * unrecognized parts were encountered then this match will fail.
322 *
323 * Returns: 1 if the URI matches, 0 if not.
324 */
325 int
p11_kit_uri_match_slot_info(const P11KitUri * uri,const CK_SLOT_INFO * slot_info)326 p11_kit_uri_match_slot_info (const P11KitUri *uri, const CK_SLOT_INFO *slot_info)
327 {
328 return_val_if_fail (uri != NULL, 0);
329 return_val_if_fail (slot_info != NULL, 0);
330
331 if (uri->unrecognized)
332 return 0;
333
334 return p11_match_uri_slot_info (&uri->slot, slot_info);
335 }
336
337 /**
338 * p11_kit_uri_get_slot_id:
339 * @uri: The URI
340 *
341 * Get the 'slot-id' part of the URI.
342 *
343 * Returns: The slot-id or <code>(CK_SLOT_ID)-1</code> if not set.
344 */
345 CK_SLOT_ID
p11_kit_uri_get_slot_id(P11KitUri * uri)346 p11_kit_uri_get_slot_id (P11KitUri *uri)
347 {
348 return_val_if_fail (uri != NULL, (CK_SLOT_ID)-1);
349 return uri->slot_id;
350 }
351
352 /**
353 * p11_kit_uri_set_slot_id:
354 * @uri: The URI
355 * @slot_id: The new slot-id
356 *
357 * Set the 'slot-id' part of the URI.
358 */
359 void
p11_kit_uri_set_slot_id(P11KitUri * uri,CK_SLOT_ID slot_id)360 p11_kit_uri_set_slot_id (P11KitUri *uri,
361 CK_SLOT_ID slot_id)
362 {
363 return_if_fail (uri != NULL);
364 uri->slot_id = slot_id;
365 }
366
367 /**
368 * p11_kit_uri_get_token_info:
369 * @uri: the URI
370 *
371 * Get the <code>CK_TOKEN_INFO</code> structure associated with this URI.
372 *
373 * If this is a parsed URI, then the fields corresponding to token parts of
374 * the URI will be filled in. Any token URI parts that were missing will have
375 * their fields filled with zeros.
376 *
377 * If the caller wishes to setup information for building a URI, then relevant
378 * fields should be filled in. Fields that should not appear as parts in the
379 * resulting URI should be filled with zeros.
380 *
381 * Returns: A pointer to the <code>CK_INFO</code> structure.
382 */
383 CK_TOKEN_INFO_PTR
p11_kit_uri_get_token_info(P11KitUri * uri)384 p11_kit_uri_get_token_info (P11KitUri *uri)
385 {
386 return_val_if_fail (uri != NULL, NULL);
387 return &uri->token;
388 }
389
390 int
p11_match_uri_token_info(CK_TOKEN_INFO const * one,CK_TOKEN_INFO const * two)391 p11_match_uri_token_info (CK_TOKEN_INFO const *one,
392 CK_TOKEN_INFO const *two)
393 {
394 return (match_struct_string (one->label,
395 two->label,
396 sizeof (one->label)) &&
397 match_struct_string (one->manufacturerID,
398 two->manufacturerID,
399 sizeof (one->manufacturerID)) &&
400 match_struct_string (one->model,
401 two->model,
402 sizeof (one->model)) &&
403 match_struct_string (one->serialNumber,
404 two->serialNumber,
405 sizeof (one->serialNumber)));
406 }
407
408 /**
409 * p11_kit_uri_match_token_info:
410 * @uri: the URI
411 * @token_info: the structure to match against the URI
412 *
413 * Match a <code>CK_TOKEN_INFO</code> structure against the token parts of this
414 * URI.
415 *
416 * Only the fields of the <code>CK_TOKEN_INFO</code> structure that are valid
417 * for use in a URI will be matched. A URI part that was not specified in the
418 * URI will match any value in the structure. If during the URI parsing any
419 * unrecognized parts were encountered then this match will fail.
420 *
421 * Returns: 1 if the URI matches, 0 if not.
422 */
423 int
p11_kit_uri_match_token_info(const P11KitUri * uri,const CK_TOKEN_INFO * token_info)424 p11_kit_uri_match_token_info (const P11KitUri *uri, const CK_TOKEN_INFO *token_info)
425 {
426 return_val_if_fail (uri != NULL, 0);
427 return_val_if_fail (token_info != NULL, 0);
428
429 if (uri->unrecognized)
430 return 0;
431
432 return p11_match_uri_token_info (&uri->token, token_info);
433 }
434
435 /**
436 * p11_kit_uri_get_attribute:
437 * @uri: The URI
438 * @attr_type: The attribute type
439 *
440 * Get a pointer to an attribute present in this URI.
441 *
442 * Returns: A pointer to the attribute, or <code>NULL</code> if not present.
443 * The attribute is owned by the URI and should not be freed.
444 */
445 CK_ATTRIBUTE_PTR
p11_kit_uri_get_attribute(P11KitUri * uri,CK_ATTRIBUTE_TYPE attr_type)446 p11_kit_uri_get_attribute (P11KitUri *uri, CK_ATTRIBUTE_TYPE attr_type)
447 {
448 return_val_if_fail (uri != NULL, NULL);
449
450 if (uri->attrs == NULL)
451 return NULL;
452
453 return p11_attrs_find (uri->attrs, attr_type);
454 }
455
456 /**
457 * p11_kit_uri_set_attribute:
458 * @uri: The URI
459 * @attr: The attribute to set
460 *
461 * Set an attribute on the URI.
462 *
463 * Only attributes that map to parts in a PKCS\#11 URI will be accepted.
464 *
465 * Returns: %P11_KIT_URI_OK if the attribute was successfully set.
466 * %P11_KIT_URI_NOT_FOUND if the attribute was not valid for a URI.
467 */
468 int
p11_kit_uri_set_attribute(P11KitUri * uri,CK_ATTRIBUTE_PTR attr)469 p11_kit_uri_set_attribute (P11KitUri *uri, CK_ATTRIBUTE_PTR attr)
470 {
471 return_val_if_fail (uri != NULL, P11_KIT_URI_UNEXPECTED);
472
473 uri->attrs = p11_attrs_buildn (uri->attrs, attr, 1);
474 return_val_if_fail (uri->attrs != NULL, P11_KIT_URI_UNEXPECTED);
475
476 return P11_KIT_URI_OK;
477 }
478
479 /**
480 * p11_kit_uri_clear_attribute:
481 * @uri: The URI
482 * @attr_type: The type of the attribute to clear
483 *
484 * Clear an attribute on the URI.
485 *
486 * Only attributes that map to parts in a PKCS\#11 URI will be accepted.
487 *
488 * Returns: %P11_KIT_URI_OK if the attribute was successfully cleared.
489 * %P11_KIT_URI_NOT_FOUND if the attribute was not valid for a URI.
490 */
491 int
p11_kit_uri_clear_attribute(P11KitUri * uri,CK_ATTRIBUTE_TYPE attr_type)492 p11_kit_uri_clear_attribute (P11KitUri *uri, CK_ATTRIBUTE_TYPE attr_type)
493 {
494 return_val_if_fail (uri != NULL, P11_KIT_URI_UNEXPECTED);
495
496 if (attr_type != CKA_CLASS &&
497 attr_type != CKA_LABEL &&
498 attr_type != CKA_ID)
499 return P11_KIT_URI_NOT_FOUND;
500
501 if (uri->attrs)
502 p11_attrs_remove (uri->attrs, attr_type);
503
504 return P11_KIT_URI_OK;
505 }
506
507 /**
508 * p11_kit_uri_get_attribute_types:
509 * @uri: The URI
510 * @n_attrs: A location to store the number of attributes returned.
511 *
512 * Get the attributes present in this URI. The attributes and values are
513 * owned by the URI. If the URI is modified, then the attributes that were
514 * returned from this function will not remain consistent.
515 *
516 * Returns: The attributes for this URI. These are owned by the URI.
517 */
518 CK_ATTRIBUTE_PTR
p11_kit_uri_get_attributes(P11KitUri * uri,CK_ULONG_PTR n_attrs)519 p11_kit_uri_get_attributes (P11KitUri *uri, CK_ULONG_PTR n_attrs)
520 {
521 static const CK_ATTRIBUTE terminator = { CKA_INVALID, NULL, 0UL };
522
523 return_val_if_fail (uri != NULL, NULL);
524
525 if (!uri->attrs) {
526 if (n_attrs)
527 *n_attrs = 0;
528 return (CK_ATTRIBUTE_PTR)&terminator;
529 }
530
531 if (n_attrs)
532 *n_attrs = p11_attrs_count (uri->attrs);
533 return uri->attrs;
534 }
535
536 int
p11_kit_uri_set_attributes(P11KitUri * uri,CK_ATTRIBUTE_PTR attrs,CK_ULONG n_attrs)537 p11_kit_uri_set_attributes (P11KitUri *uri, CK_ATTRIBUTE_PTR attrs,
538 CK_ULONG n_attrs)
539 {
540 CK_ULONG i;
541 int ret;
542
543 return_val_if_fail (uri != NULL, P11_KIT_URI_UNEXPECTED);
544
545 p11_kit_uri_clear_attributes (uri);
546
547 for (i = 0; i < n_attrs; i++) {
548 ret = p11_kit_uri_set_attribute (uri, &attrs[i]);
549 if (ret != P11_KIT_URI_OK && ret != P11_KIT_URI_NOT_FOUND)
550 return ret;
551 }
552
553 return P11_KIT_URI_OK;
554 }
555
556 void
p11_kit_uri_clear_attributes(P11KitUri * uri)557 p11_kit_uri_clear_attributes (P11KitUri *uri)
558 {
559 return_if_fail (uri != NULL);
560
561 p11_attrs_free (uri->attrs);
562 uri->attrs = NULL;
563 }
564
565 /**
566 * p11_kit_uri_match_attributes:
567 * @uri: The URI
568 * @attrs: The attributes to match
569 * @n_attrs: The number of attributes
570 *
571 * Match a attributes against the object parts of this URI.
572 *
573 * Only the attributes that are valid for use in a URI will be matched. A URI
574 * part that was not specified in the URI will match any attribute value. If
575 * during the URI parsing any unrecognized parts were encountered then this
576 * match will fail.
577 *
578 * Returns: 1 if the URI matches, 0 if not.
579 */
580 int
p11_kit_uri_match_attributes(const P11KitUri * uri,const CK_ATTRIBUTE * attrs,CK_ULONG n_attrs)581 p11_kit_uri_match_attributes (const P11KitUri *uri, const CK_ATTRIBUTE *attrs,
582 CK_ULONG n_attrs)
583 {
584 CK_ATTRIBUTE *attr;
585 CK_ULONG i;
586
587 return_val_if_fail (uri != NULL, 0);
588 return_val_if_fail (attrs != NULL || n_attrs == 0, 0);
589
590 if (uri->unrecognized)
591 return 0;
592
593 for (i = 0; i < n_attrs; i++) {
594 if (attrs[i].type != CKA_CLASS &&
595 attrs[i].type != CKA_LABEL &&
596 attrs[i].type != CKA_ID)
597 continue;
598 attr = NULL;
599 if (uri->attrs)
600 attr = p11_attrs_find (uri->attrs, attrs[i].type);
601 if (!attr)
602 continue;
603 if (!p11_attr_equal (attr, attrs + i))
604 return 0;
605 }
606
607 return 1;
608 }
609
610 /**
611 * p11_kit_uri_set_unrecognized:
612 * @uri: The URI
613 * @unrecognized: The new unregognized flag value
614 *
615 * Set the unrecognized flag on this URI.
616 *
617 * The unrecognized flag is automatically set to 1 when during parsing any part
618 * of the URI is unrecognized. If the unrecognized flag is set to 1, then
619 * matching against this URI will always fail.
620 */
621 void
p11_kit_uri_set_unrecognized(P11KitUri * uri,int unrecognized)622 p11_kit_uri_set_unrecognized (P11KitUri *uri, int unrecognized)
623 {
624 return_if_fail (uri != NULL);
625 uri->unrecognized = unrecognized ? true : false;
626 }
627
628 /**
629 * p11_kit_uri_any_unrecognized:
630 * @uri: The URI
631 *
632 * Get the unrecognized flag for this URI.
633 *
634 * The unrecognized flag is automatically set to 1 when during parsing any part
635 * of the URI is unrecognized. If the unrecognized flag is set to 1, then
636 * matching against this URI will always fail.
637 *
638 * Returns: 1 if unrecognized flag is set, 0 otherwise.
639 */
640 int
p11_kit_uri_any_unrecognized(P11KitUri * uri)641 p11_kit_uri_any_unrecognized (P11KitUri *uri)
642 {
643 return_val_if_fail (uri != NULL, 1);
644 return uri->unrecognized;
645 }
646
647 /**
648 * p11_kit_uri_get_pin_value:
649 * @uri: The URI
650 *
651 * Get the 'pin-value' part of the URI. This is used by some applications to
652 * read the PIN for logging into a PKCS\#11 token.
653 *
654 * Returns: The pin-value or %NULL if not present.
655 */
656 const char*
p11_kit_uri_get_pin_value(const P11KitUri * uri)657 p11_kit_uri_get_pin_value (const P11KitUri *uri)
658 {
659 return_val_if_fail (uri != NULL, NULL);
660 return uri->pin_value;
661 }
662
663 /**
664 * p11_kit_uri_set_pin_value:
665 * @uri: The URI
666 * @pin: The new pin-value
667 *
668 * Set the 'pin-value' part of the URI. This is used by some applications to
669 * specify the PIN for logging into a PKCS\#11 token.
670 */
671 void
p11_kit_uri_set_pin_value(P11KitUri * uri,const char * pin)672 p11_kit_uri_set_pin_value (P11KitUri *uri, const char *pin)
673 {
674 return_if_fail (uri != NULL);
675 free (uri->pin_value);
676 uri->pin_value = pin ? strdup (pin) : NULL;
677 }
678
679
680 /**
681 * p11_kit_uri_get_pin_source:
682 * @uri: The URI
683 *
684 * Get the 'pin-source' part of the URI. This is used by some applications to
685 * lookup a PIN for logging into a PKCS\#11 token.
686 *
687 * Returns: The pin-source or %NULL if not present.
688 */
689 const char*
p11_kit_uri_get_pin_source(const P11KitUri * uri)690 p11_kit_uri_get_pin_source (const P11KitUri *uri)
691 {
692 return_val_if_fail (uri != NULL, NULL);
693 return uri->pin_source;
694 }
695
696 /**
697 * p11_kit_uri_get_pinfile:
698 * @uri: The URI
699 *
700 * Deprecated: use p11_kit_uri_get_pin_source().
701 */
702 const char*
p11_kit_uri_get_pinfile(const P11KitUri * uri)703 p11_kit_uri_get_pinfile (const P11KitUri *uri)
704 {
705 return_val_if_fail (uri != NULL, NULL);
706 return p11_kit_uri_get_pin_source (uri);
707 }
708
709 /**
710 * p11_kit_uri_set_pin_source:
711 * @uri: The URI
712 * @pin_source: The new pin-source
713 *
714 * Set the 'pin-source' part of the URI. This is used by some applications to
715 * lookup a PIN for logging into a PKCS\#11 token.
716 */
717 void
p11_kit_uri_set_pin_source(P11KitUri * uri,const char * pin_source)718 p11_kit_uri_set_pin_source (P11KitUri *uri, const char *pin_source)
719 {
720 return_if_fail (uri != NULL);
721 free (uri->pin_source);
722 uri->pin_source = pin_source ? strdup (pin_source) : NULL;
723 }
724
725 /**
726 * p11_kit_uri_set_pinfile:
727 * @uri: The URI
728 * @pinfile: The pinfile
729 *
730 * Deprecated: use p11_kit_uri_set_pin_source().
731 */
732 void
p11_kit_uri_set_pinfile(P11KitUri * uri,const char * pinfile)733 p11_kit_uri_set_pinfile (P11KitUri *uri, const char *pinfile)
734 {
735 return_if_fail (uri != NULL);
736 p11_kit_uri_set_pin_source (uri, pinfile);
737 }
738
739
740 /**
741 * p11_kit_uri_get_module_name:
742 * @uri: The URI
743 *
744 * Get the 'module-name' part of the URI. This is used by some
745 * applications to explicitly specify the name of a PKCS\#11 module.
746 *
747 * Returns: The module-name or %NULL if not present.
748 */
749 const char*
p11_kit_uri_get_module_name(const P11KitUri * uri)750 p11_kit_uri_get_module_name (const P11KitUri *uri)
751 {
752 return_val_if_fail (uri != NULL, NULL);
753 return uri->module_name;
754 }
755
756 /**
757 * p11_kit_uri_set_module_name:
758 * @uri: The URI
759 * @name: The new module-name
760 *
761 * Set the 'module-name' part of the URI. This is used by some
762 * applications to explicitly specify the name of a PKCS\#11 module.
763 */
764 void
p11_kit_uri_set_module_name(P11KitUri * uri,const char * name)765 p11_kit_uri_set_module_name (P11KitUri *uri, const char *name)
766 {
767 return_if_fail (uri != NULL);
768 free (uri->module_name);
769 uri->module_name = name ? strdup (name) : NULL;
770 }
771
772 /**
773 * p11_kit_uri_get_module_path:
774 * @uri: The URI
775 *
776 * Get the 'module-path' part of the URI. This is used by some
777 * applications to explicitly specify the path of a PKCS\#11 module.
778 *
779 * Returns: The module-path or %NULL if not present.
780 */
781 const char*
p11_kit_uri_get_module_path(const P11KitUri * uri)782 p11_kit_uri_get_module_path (const P11KitUri *uri)
783 {
784 return_val_if_fail (uri != NULL, NULL);
785 return uri->module_path;
786 }
787
788 /**
789 * p11_kit_uri_set_module_path:
790 * @uri: The URI
791 * @path: The new module-path
792 *
793 * Set the 'module-path' part of the URI. This is used by some
794 * applications to explicitly specify the path of a PKCS\#11 module.
795 */
796 void
p11_kit_uri_set_module_path(P11KitUri * uri,const char * path)797 p11_kit_uri_set_module_path (P11KitUri *uri, const char *path)
798 {
799 return_if_fail (uri != NULL);
800 free (uri->module_path);
801 uri->module_path = path ? strdup (path) : NULL;
802 }
803
804 /**
805 * p11_kit_uri_get_vendor_query:
806 * @uri: The URI
807 * @name: The name of vendor query
808 *
809 * Get the vendor query part of the URI, identified by @name. This is
810 * used by some applications to explicitly specify the path of a
811 * PKCS\#11 module.
812 *
813 * Returns: The value of vendor query or %NULL if not present.
814 */
815 const char*
p11_kit_uri_get_vendor_query(const P11KitUri * uri,const char * name)816 p11_kit_uri_get_vendor_query (const P11KitUri *uri, const char *name)
817 {
818 size_t i;
819
820 return_val_if_fail (uri != NULL, NULL);
821
822 for (i = 0; i < uri->qattrs->num; i++) {
823 Attribute *attr = uri->qattrs->elem[i];
824 if (strcmp (attr->name, name) == 0)
825 return attr->value;
826 }
827 return NULL;
828 }
829
830 static void
free_attribute(Attribute * attr)831 free_attribute (Attribute *attr)
832 {
833 free (attr->name);
834 free (attr->value);
835 free (attr);
836 }
837
838 static bool
insert_attribute(p11_array * attrs,char * name,char * value)839 insert_attribute (p11_array *attrs, char *name, char *value)
840 {
841 Attribute *attr;
842 size_t i;
843
844 return_val_if_fail (attrs != NULL, false);
845 return_val_if_fail (name != NULL, false);
846 return_val_if_fail (value != NULL, false);
847
848 for (i = 0; i < attrs->num; i++) {
849 attr = attrs->elem[i];
850 if (strcmp (attr->name, (char *)name) > 0)
851 break;
852 }
853
854 attr = calloc (1, sizeof (Attribute));
855 return_val_if_fail (attr, false);
856
857 attr->name = name;
858 attr->value = value;
859
860 return p11_array_insert (attrs, i, attr);
861 }
862
863 /**
864 * p11_kit_uri_set_vendor_query:
865 * @uri: The URI
866 * @name: The name of vendor query
867 * @value: (allow-none): The value of vendor query
868 *
869 * Set the vendor query part of the URI, identified by @name. This is
870 * used by some applications to explicitly specify the path of a
871 * PKCS\#11 module.
872 *
873 * Returns: 1 if the vendor query is set or removed, 0 if not.
874 */
875 int
p11_kit_uri_set_vendor_query(P11KitUri * uri,const char * name,const char * value)876 p11_kit_uri_set_vendor_query (P11KitUri *uri, const char *name,
877 const char *value)
878 {
879 Attribute *attr;
880 size_t i;
881
882 return_val_if_fail (uri != NULL, 0);
883 return_val_if_fail (name != NULL, 0);
884
885 for (i = 0; i < uri->qattrs->num; i++) {
886 attr = uri->qattrs->elem[i];
887 if (strcmp (attr->name, name) == 0)
888 break;
889 }
890 if (i == uri->qattrs->num) {
891 if (value == NULL)
892 return 0;
893 return insert_attribute (uri->qattrs,
894 strdup (name), strdup (value));
895 }
896 if (value == NULL)
897 p11_array_remove (uri->qattrs, i);
898 else {
899 free (attr->value);
900 attr->value = strdup (value);
901 }
902
903 return 1;
904 }
905
906 /**
907 * p11_kit_uri_new:
908 *
909 * Create a new blank PKCS\#11 URI.
910 *
911 * The new URI is in the right state to parse a string into. All relevant fields
912 * are zeroed out. Formatting this URI will produce a valid but empty URI.
913 *
914 * Returns: A newly allocated URI. This should be freed with p11_kit_uri_free().
915 */
916 P11KitUri*
p11_kit_uri_new(void)917 p11_kit_uri_new (void)
918 {
919 P11KitUri *uri;
920
921 uri = calloc (1, sizeof (P11KitUri));
922 return_val_if_fail (uri != NULL, NULL);
923
924 /* So that it matches anything */
925 uri->module.libraryVersion.major = (CK_BYTE)-1;
926 uri->module.libraryVersion.minor = (CK_BYTE)-1;
927 uri->slot_id = (CK_SLOT_ID)-1;
928 uri->qattrs = p11_array_new ((p11_destroyer)free_attribute);
929
930 return uri;
931 }
932
933 enum uri_sep {
934 sep_path = '\0',
935 sep_pattr = ';',
936 sep_query = '?',
937 sep_qattr = '&',
938 };
939
940 static void
format_name_equals(p11_buffer * buffer,enum uri_sep * sep,const char * name)941 format_name_equals (p11_buffer *buffer,
942 enum uri_sep *sep,
943 const char *name)
944 {
945 if (*sep) {
946 char c = *sep;
947 p11_buffer_add (buffer, &c, 1);
948 }
949 p11_buffer_add (buffer, name, -1);
950 p11_buffer_add (buffer, "=", 1);
951
952 if (*sep == sep_path)
953 *sep = sep_pattr;
954 else if (*sep == sep_query)
955 *sep = sep_qattr;
956 }
957
958 static bool
format_raw_string(p11_buffer * buffer,enum uri_sep * sep,const char * name,const char * value)959 format_raw_string (p11_buffer *buffer,
960 enum uri_sep *sep,
961 const char *name,
962 const char *value)
963 {
964 /* Not set */
965 if (!value)
966 return true;
967
968 format_name_equals (buffer, sep, name);
969 p11_buffer_add (buffer, value, -1);
970
971 return p11_buffer_ok (buffer);
972 }
973
974 static bool
format_encode_string(p11_buffer * buffer,enum uri_sep * sep,const char * name,const unsigned char * value,size_t n_value,bool force)975 format_encode_string (p11_buffer *buffer,
976 enum uri_sep *sep,
977 const char *name,
978 const unsigned char *value,
979 size_t n_value,
980 bool force)
981 {
982 /* Not set */
983 if (!value)
984 return true;
985
986 format_name_equals (buffer, sep, name);
987 p11_url_encode (value, value + n_value, force ? "" : P11_URL_VERBATIM, buffer);
988
989 return p11_buffer_ok (buffer);
990 }
991
992
993 static bool
format_struct_string(p11_buffer * buffer,enum uri_sep * sep,const char * name,const unsigned char * value,size_t value_max)994 format_struct_string (p11_buffer *buffer,
995 enum uri_sep *sep,
996 const char *name,
997 const unsigned char *value,
998 size_t value_max)
999 {
1000 size_t len;
1001
1002 /* Not set */
1003 if (!value[0])
1004 return true;
1005
1006 len = p11_kit_space_strlen (value, value_max);
1007 return format_encode_string (buffer, sep, name, value, len, false);
1008 }
1009
1010 static bool
format_attribute_string(p11_buffer * buffer,enum uri_sep * sep,const char * name,CK_ATTRIBUTE_PTR attr,bool force)1011 format_attribute_string (p11_buffer *buffer,
1012 enum uri_sep *sep,
1013 const char *name,
1014 CK_ATTRIBUTE_PTR attr,
1015 bool force)
1016 {
1017 /* Not set */;
1018 if (attr == NULL)
1019 return true;
1020
1021 return format_encode_string (buffer, sep, name,
1022 attr->pValue, attr->ulValueLen,
1023 force);
1024 }
1025
1026 static bool
format_attribute_class(p11_buffer * buffer,enum uri_sep * sep,const char * name,CK_ATTRIBUTE_PTR attr)1027 format_attribute_class (p11_buffer *buffer,
1028 enum uri_sep *sep,
1029 const char *name,
1030 CK_ATTRIBUTE_PTR attr)
1031 {
1032 CK_OBJECT_CLASS klass;
1033 const char *value;
1034
1035 /* Not set */;
1036 if (attr == NULL)
1037 return true;
1038
1039 klass = *((CK_OBJECT_CLASS*)attr->pValue);
1040 switch (klass) {
1041 case CKO_DATA:
1042 value = "data";
1043 break;
1044 case CKO_SECRET_KEY:
1045 value = "secret-key";
1046 break;
1047 case CKO_CERTIFICATE:
1048 value = "cert";
1049 break;
1050 case CKO_PUBLIC_KEY:
1051 value = "public";
1052 break;
1053 case CKO_PRIVATE_KEY:
1054 value = "private";
1055 break;
1056 default:
1057 return true;
1058 }
1059
1060 return format_raw_string (buffer, sep, name, value);
1061 }
1062
1063 static bool
format_struct_version(p11_buffer * buffer,enum uri_sep * sep,const char * name,CK_VERSION_PTR version)1064 format_struct_version (p11_buffer *buffer,
1065 enum uri_sep *sep,
1066 const char *name,
1067 CK_VERSION_PTR version)
1068 {
1069 char buf[64];
1070
1071 /* Not set */
1072 if (version->major == (CK_BYTE)-1 && version->minor == (CK_BYTE)-1)
1073 return true;
1074
1075 snprintf (buf, sizeof (buf), "%d.%d",
1076 (int)version->major, (int)version->minor);
1077 return format_raw_string (buffer, sep, name, buf);
1078 }
1079
1080 static bool
format_ulong(p11_buffer * buffer,enum uri_sep * sep,const char * name,CK_ULONG value)1081 format_ulong (p11_buffer *buffer,
1082 enum uri_sep *sep,
1083 const char *name,
1084 CK_ULONG value)
1085 {
1086 char buf[64];
1087
1088 /* Not set */
1089 if (value == (CK_ULONG)-1)
1090 return true;
1091
1092 snprintf (buf, sizeof (buf), "%lu", value);
1093 return format_raw_string (buffer, sep, name, buf);
1094 }
1095
1096 /**
1097 * p11_kit_uri_format:
1098 * @uri: The URI.
1099 * @uri_type: The type of URI that should be produced.
1100 * @string: Location to store a newly allocated string.
1101 *
1102 * Format a PKCS\#11 URI into a string.
1103 *
1104 * Fields which are zeroed out will not be included in the resulting string.
1105 * Attributes which are not present will also not be included.
1106 *
1107 * The uri_type of URI specified limits the different parts of the resulting
1108 * URI. To format a URI containing all possible information use
1109 * %P11_KIT_URI_FOR_ANY
1110 *
1111 * It's up to the caller to guarantee that the attributes set in @uri are
1112 * those appropriate for inclusion in a URI, specifically:
1113 * <literal>CKA_ID</literal>, <literal>CKA_LABEL</literal>
1114 * and <literal>CKA_CLASS</literal>. The class must be one of
1115 * <literal>CKO_DATA</literal>, <literal>CKO_SECRET_KEY</literal>,
1116 * <literal>CKO_CERTIFICATE</literal>, <literal>CKO_PUBLIC_KEY</literal>,
1117 * <literal>CKO_PRIVATE_KEY</literal>.
1118 *
1119 * The resulting string should be freed with free().
1120 *
1121 * Returns: %P11_KIT_URI_OK if the URI was formatted successfully,
1122 * %P11_KIT_URI_UNEXPECTED if the data in @uri is invalid for a URI.
1123 */
1124 int
p11_kit_uri_format(P11KitUri * uri,P11KitUriType uri_type,char ** string)1125 p11_kit_uri_format (P11KitUri *uri, P11KitUriType uri_type, char **string)
1126 {
1127 p11_buffer buffer;
1128 enum uri_sep sep = sep_path;
1129 size_t i;
1130
1131 return_val_if_fail (uri != NULL, P11_KIT_URI_UNEXPECTED);
1132 return_val_if_fail (string != NULL, P11_KIT_URI_UNEXPECTED);
1133
1134 if (!p11_buffer_init_null (&buffer, 64))
1135 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1136
1137 p11_buffer_add (&buffer, P11_KIT_URI_SCHEME, P11_KIT_URI_SCHEME_LEN);
1138 p11_buffer_add (&buffer, ":", 1);
1139
1140 if ((uri_type & P11_KIT_URI_FOR_MODULE) == P11_KIT_URI_FOR_MODULE) {
1141 if (!format_struct_string (&buffer, &sep, "library-description",
1142 uri->module.libraryDescription,
1143 sizeof (uri->module.libraryDescription)) ||
1144 !format_struct_string (&buffer, &sep, "library-manufacturer",
1145 uri->module.manufacturerID,
1146 sizeof (uri->module.manufacturerID))) {
1147 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1148 }
1149 }
1150
1151 if ((uri_type & P11_KIT_URI_FOR_MODULE_WITH_VERSION) == P11_KIT_URI_FOR_MODULE_WITH_VERSION) {
1152 if (!format_struct_version (&buffer, &sep, "library-version",
1153 &uri->module.libraryVersion)) {
1154 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1155 }
1156 }
1157
1158 if ((uri_type & P11_KIT_URI_FOR_SLOT) == P11_KIT_URI_FOR_SLOT) {
1159 if (!format_struct_string (&buffer, &sep, "slot-description",
1160 uri->slot.slotDescription,
1161 sizeof (uri->slot.slotDescription)) ||
1162 !format_struct_string (&buffer, &sep, "slot-manufacturer",
1163 uri->slot.manufacturerID,
1164 sizeof (uri->slot.manufacturerID)) ||
1165 !format_ulong (&buffer, &sep, "slot-id",
1166 uri->slot_id)) {
1167 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1168 }
1169 }
1170
1171 if ((uri_type & P11_KIT_URI_FOR_TOKEN) == P11_KIT_URI_FOR_TOKEN) {
1172 if (!format_struct_string (&buffer, &sep, "model",
1173 uri->token.model,
1174 sizeof (uri->token.model)) ||
1175 !format_struct_string (&buffer, &sep, "manufacturer",
1176 uri->token.manufacturerID,
1177 sizeof (uri->token.manufacturerID)) ||
1178 !format_struct_string (&buffer, &sep, "serial",
1179 uri->token.serialNumber,
1180 sizeof (uri->token.serialNumber)) ||
1181 !format_struct_string (&buffer, &sep, "token",
1182 uri->token.label,
1183 sizeof (uri->token.label))) {
1184 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1185 }
1186 }
1187
1188 if ((uri_type & P11_KIT_URI_FOR_OBJECT) == P11_KIT_URI_FOR_OBJECT) {
1189 if (!format_attribute_string (&buffer, &sep, "id",
1190 p11_kit_uri_get_attribute (uri, CKA_ID),
1191 true) ||
1192 !format_attribute_string (&buffer, &sep, "object",
1193 p11_kit_uri_get_attribute (uri, CKA_LABEL),
1194 false)) {
1195 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1196 }
1197
1198 if (!format_attribute_class (&buffer, &sep, "type",
1199 p11_kit_uri_get_attribute (uri, CKA_CLASS))) {
1200 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1201 }
1202 }
1203
1204 sep = sep_query;
1205
1206 if (uri->pin_source) {
1207 if (!format_encode_string (&buffer, &sep, "pin-source",
1208 (const unsigned char*)uri->pin_source,
1209 strlen (uri->pin_source), 0)) {
1210 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1211 }
1212 }
1213
1214 if (uri->pin_value) {
1215 if (!format_encode_string (&buffer, &sep, "pin-value",
1216 (const unsigned char*)uri->pin_value,
1217 strlen (uri->pin_value), 0)) {
1218 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1219 }
1220 }
1221
1222 if (uri->module_name) {
1223 if (!format_encode_string (&buffer, &sep, "module-name",
1224 (const unsigned char*)uri->module_name,
1225 strlen (uri->module_name), 0)) {
1226 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1227 }
1228 }
1229
1230 if (uri->module_path) {
1231 if (!format_encode_string (&buffer, &sep, "module-path",
1232 (const unsigned char*)uri->module_path,
1233 strlen (uri->module_path), 0)) {
1234 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1235 }
1236 }
1237
1238 for (i = 0; i < uri->qattrs->num; i++) {
1239 Attribute *attr = uri->qattrs->elem[i];
1240 if (!format_encode_string (&buffer, &sep, attr->name,
1241 (const unsigned char *) attr->value,
1242 strlen (attr->value), 0)) {
1243 return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1244 }
1245 }
1246
1247 return_val_if_fail (p11_buffer_ok (&buffer), P11_KIT_URI_UNEXPECTED);
1248 *string = p11_buffer_steal (&buffer, NULL);
1249 return P11_KIT_URI_OK;
1250 }
1251
1252 static bool
str_range_equal(const char * input,const char * start,const char * end)1253 str_range_equal (const char *input, const char *start, const char *end)
1254 {
1255 return strlen (input) == end - start &&
1256 memcmp (input, start, end - start) == 0;
1257 }
1258
1259 static int
parse_string_attribute(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1260 parse_string_attribute (const char *name_start, const char *name_end,
1261 const char *start, const char *end,
1262 P11KitUri *uri)
1263 {
1264 unsigned char *value;
1265 CK_ATTRIBUTE_TYPE type;
1266 size_t length;
1267
1268 assert (name_start <= name_end);
1269 assert (start <= end);
1270
1271 if (str_range_equal ("id", name_start, name_end))
1272 type = CKA_ID;
1273 else if (str_range_equal ("object", name_start, name_end))
1274 type = CKA_LABEL;
1275 else
1276 return 0;
1277
1278 value = p11_url_decode (start, end, P11_URL_WHITESPACE, &length);
1279 if (value == NULL)
1280 return P11_KIT_URI_BAD_ENCODING;
1281
1282 uri->attrs = p11_attrs_take (uri->attrs, type, value, length);
1283 return 1;
1284 }
1285
1286 static int
parse_class_attribute(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1287 parse_class_attribute (const char *name_start, const char *name_end,
1288 const char *start, const char *end,
1289 P11KitUri *uri)
1290 {
1291 CK_OBJECT_CLASS klass = 0;
1292 CK_ATTRIBUTE attr;
1293
1294 assert (name_start <= name_end);
1295 assert (start <= end);
1296
1297 if (!str_range_equal ("objecttype", name_start, name_end) &&
1298 !str_range_equal ("object-type", name_start, name_end) &&
1299 !str_range_equal ("type", name_start, name_end))
1300 return 0;
1301
1302 if (str_range_equal ("cert", start, end))
1303 klass = CKO_CERTIFICATE;
1304 else if (str_range_equal ("public", start, end))
1305 klass = CKO_PUBLIC_KEY;
1306 else if (str_range_equal ("private", start, end))
1307 klass = CKO_PRIVATE_KEY;
1308 else if (str_range_equal ("secretkey", start, end))
1309 klass = CKO_SECRET_KEY;
1310 else if (str_range_equal ("secret-key", start, end))
1311 klass = CKO_SECRET_KEY;
1312 else if (str_range_equal ("data", start, end))
1313 klass = CKO_DATA;
1314 else {
1315 uri->unrecognized = true;
1316 return 1;
1317 }
1318
1319 attr.pValue = &klass;
1320 attr.ulValueLen = sizeof (klass);
1321 attr.type = CKA_CLASS;
1322
1323 uri->attrs = p11_attrs_build (uri->attrs, &attr, NULL);
1324 return 1;
1325 }
1326
1327 static int
parse_struct_info(unsigned char * where,size_t length,const char * start,const char * end,P11KitUri * uri)1328 parse_struct_info (unsigned char *where, size_t length, const char *start,
1329 const char *end, P11KitUri *uri)
1330 {
1331 unsigned char *value;
1332 size_t value_length;
1333
1334 assert (start <= end);
1335
1336 value = p11_url_decode (start, end, P11_URL_WHITESPACE, &value_length);
1337 if (value == NULL)
1338 return P11_KIT_URI_BAD_ENCODING;
1339
1340 /* Too long, shouldn't match anything */
1341 if (value_length > length) {
1342 free (value);
1343 uri->unrecognized = true;
1344 return 1;
1345 }
1346
1347 memset (where, ' ', length);
1348 memcpy (where, value, value_length);
1349
1350 free (value);
1351 return 1;
1352 }
1353
1354 static int
parse_token_info(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1355 parse_token_info (const char *name_start, const char *name_end,
1356 const char *start, const char *end,
1357 P11KitUri *uri)
1358 {
1359 unsigned char *where;
1360 size_t length;
1361
1362 assert (name_start <= name_end);
1363 assert (start <= end);
1364
1365 if (str_range_equal ("model", name_start, name_end)) {
1366 where = uri->token.model;
1367 length = sizeof (uri->token.model);
1368 } else if (str_range_equal ("manufacturer", name_start, name_end)) {
1369 where = uri->token.manufacturerID;
1370 length = sizeof (uri->token.manufacturerID);
1371 } else if (str_range_equal ("serial", name_start, name_end)) {
1372 where = uri->token.serialNumber;
1373 length = sizeof (uri->token.serialNumber);
1374 } else if (str_range_equal ("token", name_start, name_end)) {
1375 where = uri->token.label;
1376 length = sizeof (uri->token.label);
1377 } else {
1378 return 0;
1379 }
1380
1381 return parse_struct_info (where, length, start, end, uri);
1382 }
1383
1384 static long
atoin(const char * start,const char * end)1385 atoin (const char *start, const char *end)
1386 {
1387 long ret = 0;
1388 while (start != end) {
1389 if (*start < '0' || *start > '9')
1390 return -1;
1391 ret *= 10;
1392 ret += (*start - '0');
1393 ++start;
1394 }
1395 return ret;
1396 }
1397
1398 static int
parse_struct_version(const char * start,const char * end,CK_VERSION_PTR version)1399 parse_struct_version (const char *start, const char *end, CK_VERSION_PTR version)
1400 {
1401 const char *dot;
1402 int val;
1403
1404 assert (start <= end);
1405
1406 dot = memchr (start, '.', end - start);
1407 if (!dot)
1408 dot = end;
1409
1410 if (dot == start)
1411 return P11_KIT_URI_BAD_VERSION;
1412 val = atoin (start, dot);
1413 if (val < 0 || val >= 255)
1414 return P11_KIT_URI_BAD_VERSION;
1415 version->major = (CK_BYTE)val;
1416 version->minor = 0;
1417
1418 if (dot != end) {
1419 if (dot + 1 == end)
1420 return P11_KIT_URI_BAD_VERSION;
1421 val = atoin (dot + 1, end);
1422 if (val < 0 || val >= 255)
1423 return P11_KIT_URI_BAD_VERSION;
1424 version->minor = (CK_BYTE)val;
1425 }
1426
1427 return 1;
1428 }
1429
1430 static int
parse_slot_info(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1431 parse_slot_info (const char *name_start, const char *name_end,
1432 const char *start, const char *end,
1433 P11KitUri *uri)
1434 {
1435 unsigned char *where;
1436 size_t length;
1437
1438 assert (name_start <= name_end);
1439 assert (start <= end);
1440
1441 if (str_range_equal ("slot-description", name_start, name_end)) {
1442 where = uri->slot.slotDescription;
1443 length = sizeof (uri->slot.slotDescription);
1444 } else if (str_range_equal ("slot-manufacturer", name_start, name_end)) {
1445 where = uri->slot.manufacturerID;
1446 length = sizeof (uri->slot.manufacturerID);
1447 } else {
1448 return 0;
1449 }
1450
1451 return parse_struct_info (where, length, start, end, uri);
1452 }
1453
1454 static int
parse_slot_id(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1455 parse_slot_id (const char *name_start, const char *name_end,
1456 const char *start, const char *end,
1457 P11KitUri *uri)
1458 {
1459 assert (name_start <= name_end);
1460 assert (start <= end);
1461
1462 if (str_range_equal ("slot-id", name_start, name_end)) {
1463 long val;
1464 val = atoin (start, end);
1465 if (val < 0)
1466 return P11_KIT_URI_BAD_SYNTAX;
1467 uri->slot_id = (CK_SLOT_ID)val;
1468 return 1;
1469 }
1470 return 0;
1471 }
1472
1473 static int
parse_module_version_info(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1474 parse_module_version_info (const char *name_start, const char *name_end,
1475 const char *start, const char *end,
1476 P11KitUri *uri)
1477 {
1478 assert (name_start <= name_end);
1479 assert (start <= end);
1480
1481 if (str_range_equal ("library-version", name_start, name_end))
1482 return parse_struct_version (start, end,
1483 &uri->module.libraryVersion);
1484
1485 return 0;
1486 }
1487
1488 static int
parse_module_info(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1489 parse_module_info (const char *name_start, const char *name_end,
1490 const char *start, const char *end,
1491 P11KitUri *uri)
1492 {
1493 unsigned char *where;
1494 size_t length;
1495
1496 assert (name_start <= name_end);
1497 assert (start <= end);
1498
1499 if (str_range_equal ("library-description", name_start, name_end)) {
1500 where = uri->module.libraryDescription;
1501 length = sizeof (uri->module.libraryDescription);
1502 } else if (str_range_equal ("library-manufacturer", name_start, name_end)) {
1503 where = uri->module.manufacturerID;
1504 length = sizeof (uri->module.manufacturerID);
1505 } else {
1506 return 0;
1507 }
1508
1509 return parse_struct_info (where, length, start, end, uri);
1510 }
1511
1512 static int
parse_pin_query(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1513 parse_pin_query (const char *name_start, const char *name_end,
1514 const char *start, const char *end,
1515 P11KitUri *uri)
1516 {
1517 unsigned char *value;
1518
1519 assert (name_start <= name_end);
1520 assert (start <= end);
1521
1522 if (str_range_equal ("pinfile", name_start, name_end) ||
1523 str_range_equal ("pin-source", name_start, name_end)) {
1524 value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1525 if (value == NULL)
1526 return P11_KIT_URI_BAD_ENCODING;
1527 free (uri->pin_source);
1528 uri->pin_source = (char*)value;
1529 return 1;
1530 } else if (str_range_equal ("pin-value", name_start, name_end)) {
1531 value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1532 if (value == NULL)
1533 return P11_KIT_URI_BAD_ENCODING;
1534 free (uri->pin_value);
1535 uri->pin_value = (char*)value;
1536 return 1;
1537 }
1538
1539 return 0;
1540 }
1541
1542 static int
parse_module_query(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1543 parse_module_query (const char *name_start, const char *name_end,
1544 const char *start, const char *end,
1545 P11KitUri *uri)
1546 {
1547 unsigned char *value;
1548
1549 assert (name_start <= name_end);
1550 assert (start <= end);
1551
1552 if (str_range_equal ("module-name", name_start, name_end)) {
1553 value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1554 if (value == NULL)
1555 return P11_KIT_URI_BAD_ENCODING;
1556 free (uri->module_name);
1557 uri->module_name = (char*)value;
1558 return 1;
1559 } else if (str_range_equal ("module-path", name_start, name_end)) {
1560 value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1561 if (value == NULL)
1562 return P11_KIT_URI_BAD_ENCODING;
1563 free (uri->module_path);
1564 uri->module_path = (char*)value;
1565 return 1;
1566 }
1567
1568 return 0;
1569 }
1570
1571 static int
parse_vendor_query(const char * name_start,const char * name_end,const char * start,const char * end,P11KitUri * uri)1572 parse_vendor_query (const char *name_start, const char *name_end,
1573 const char *start, const char *end,
1574 P11KitUri *uri)
1575 {
1576 char *name;
1577 unsigned char *value;
1578
1579 assert (name_start <= name_end);
1580 assert (start <= end);
1581
1582 name = malloc (name_end - name_start + 1);
1583 if (name == NULL)
1584 return P11_KIT_URI_BAD_ENCODING;
1585 memcpy (name, name_start, name_end - name_start);
1586 name[name_end - name_start] = '\0';
1587
1588 /* Limit the characters in NAME, according to the specification. */
1589 if (strspn (name, "abcdefghijklmnopqrstuvwxyz0123456789-_") !=
1590 name_end - name_start) {
1591 free (name);
1592 return P11_KIT_URI_UNEXPECTED;
1593 }
1594
1595 value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1596 if (value == NULL) {
1597 free (name);
1598 return P11_KIT_URI_BAD_ENCODING;
1599 }
1600
1601 if (!insert_attribute (uri->qattrs, name, (char *)value)) {
1602 free (name);
1603 free (value);
1604 return P11_KIT_URI_UNEXPECTED;
1605 }
1606
1607 return 0;
1608 }
1609
1610 /**
1611 * p11_kit_uri_parse:
1612 * @string: The string to parse
1613 * @uri_type: The type of URI that is expected
1614 * @uri: The blank URI to parse the values into
1615 *
1616 * Parse a PKCS\#11 URI string.
1617 *
1618 * PKCS\#11 URIs can represent tokens, objects or modules. The uri_type argument
1619 * allows the caller to specify what type of URI is expected and the sorts of
1620 * things the URI should match. %P11_KIT_URI_FOR_ANY can be used to parse a URI
1621 * for any context. It's then up to the caller to make sense of the way that
1622 * it is used.
1623 *
1624 * If the PKCS\#11 URI contains unrecognized URI parts or parts not applicable
1625 * to the specified context, then the unrecognized flag will be set. This will
1626 * prevent the URI from matching using the various match functions.
1627 *
1628 * Returns: %P11_KIT_URI_OK if the URI was parsed successfully.
1629 * %P11_KIT_URI_BAD_SCHEME if this was not a PKCS\#11 URI.
1630 * %P11_KIT_URI_BAD_SYNTAX if the URI syntax was bad.
1631 * %P11_KIT_URI_BAD_VERSION if a version number was bad.
1632 * %P11_KIT_URI_BAD_ENCODING if the URI encoding was invalid.
1633 */
1634 int
p11_kit_uri_parse(const char * string,P11KitUriType uri_type,P11KitUri * uri)1635 p11_kit_uri_parse (const char *string, P11KitUriType uri_type,
1636 P11KitUri *uri)
1637 {
1638 const char *spos, *epos;
1639 int ret;
1640 size_t length, i;
1641 char *allocated = NULL;
1642
1643 assert (string);
1644 assert (uri);
1645
1646 /* If STRING contains any whitespace, create a copy of the
1647 * string and strip it out */
1648 length = strcspn (string, P11_URL_WHITESPACE);
1649 if (strspn (string + length, P11_URL_WHITESPACE) > 0) {
1650 allocated = strip_whitespace (string);
1651 return_val_if_fail (allocated != NULL, P11_KIT_URI_UNEXPECTED);
1652 string = allocated;
1653 }
1654
1655 epos = strchr (string, ':');
1656 if (epos == NULL) {
1657 free (allocated);
1658 return P11_KIT_URI_BAD_SCHEME;
1659 }
1660 if (epos - string != P11_KIT_URI_SCHEME_LEN) {
1661 free (allocated);
1662 return P11_KIT_URI_BAD_SCHEME;
1663 }
1664 for (i = 0; i < P11_KIT_URI_SCHEME_LEN; i++)
1665 if (p11_ascii_tolower (string[i]) != P11_KIT_URI_SCHEME[i])
1666 break;
1667 if (i != P11_KIT_URI_SCHEME_LEN) {
1668 free (allocated);
1669 return P11_KIT_URI_BAD_SCHEME;
1670 }
1671
1672 string = epos + 1;
1673
1674 /* Clear everything out */
1675 memset (&uri->module, 0, sizeof (uri->module));
1676 memset (&uri->token, 0, sizeof (uri->token));
1677 p11_attrs_free (uri->attrs);
1678 uri->attrs = NULL;
1679 uri->module.libraryVersion.major = (CK_BYTE)-1;
1680 uri->module.libraryVersion.minor = (CK_BYTE)-1;
1681 uri->unrecognized = 0;
1682 uri->slot_id = (CK_SLOT_ID)-1;
1683 free (uri->pin_source);
1684 uri->pin_source = NULL;
1685 free (uri->pin_value);
1686 uri->pin_value = NULL;
1687 free (uri->module_name);
1688 uri->module_name = NULL;
1689 free (uri->module_path);
1690 uri->module_path = NULL;
1691 p11_array_clear (uri->qattrs);
1692
1693 /* Parse the path. */
1694 for (;;) {
1695 spos = string + strcspn (string, ";?");
1696 if (spos == string)
1697 break;
1698
1699 epos = strchr (string, '=');
1700 if (epos == NULL || epos == string || epos >= spos) {
1701 free (allocated);
1702 return P11_KIT_URI_BAD_SYNTAX;
1703 }
1704
1705 ret = 0;
1706 if ((uri_type & P11_KIT_URI_FOR_OBJECT) == P11_KIT_URI_FOR_OBJECT)
1707 ret = parse_string_attribute (string, epos, epos + 1, spos, uri);
1708 if (ret == 0 && (uri_type & P11_KIT_URI_FOR_OBJECT) == P11_KIT_URI_FOR_OBJECT)
1709 ret = parse_class_attribute (string, epos, epos + 1, spos, uri);
1710 if (ret == 0 && (uri_type & P11_KIT_URI_FOR_TOKEN) == P11_KIT_URI_FOR_TOKEN)
1711 ret = parse_token_info (string, epos, epos + 1, spos, uri);
1712 if (ret == 0 && (uri_type & P11_KIT_URI_FOR_SLOT) == P11_KIT_URI_FOR_SLOT)
1713 ret = parse_slot_info (string, epos, epos + 1, spos, uri);
1714 if (ret == 0 && (uri_type & P11_KIT_URI_FOR_SLOT) == P11_KIT_URI_FOR_SLOT)
1715 ret = parse_slot_id (string, epos, epos + 1, spos, uri);
1716 if (ret == 0 && (uri_type & P11_KIT_URI_FOR_MODULE) == P11_KIT_URI_FOR_MODULE)
1717 ret = parse_module_info (string, epos, epos + 1, spos, uri);
1718 if (ret == 0 && (uri_type & P11_KIT_URI_FOR_MODULE_WITH_VERSION) == P11_KIT_URI_FOR_MODULE_WITH_VERSION)
1719 ret = parse_module_version_info (string, epos, epos + 1, spos, uri);
1720 /* Accept 'pin-source' and 'pin-value' in path
1721 * attributes for backward compatibility. */
1722 if (ret == 0)
1723 ret = parse_pin_query (string, epos, epos + 1, spos, uri);
1724
1725 if (ret < 0) {
1726 free (allocated);
1727 return ret;
1728 }
1729 if (ret == 0)
1730 uri->unrecognized = true;
1731
1732 string = spos;
1733 if (*spos == '\0')
1734 break;
1735 if (*spos == '?')
1736 break;
1737 string++;
1738 }
1739
1740 /* Parse the query. */
1741 for (;;) {
1742 if (*string == '\0')
1743 break;
1744 string++;
1745 spos = strchr (string, '&');
1746 if (spos == NULL) {
1747 spos = string + strlen (string);
1748 assert (*spos == '\0');
1749 if (spos == string)
1750 break;
1751 }
1752
1753 epos = strchr (string, '=');
1754 if (epos == NULL || spos == string || epos == string || epos >= spos) {
1755 free (allocated);
1756 return P11_KIT_URI_BAD_SYNTAX;
1757 }
1758
1759 ret = parse_pin_query (string, epos, epos + 1, spos, uri);
1760 if (ret == 0)
1761 ret = parse_module_query (string, epos, epos + 1, spos, uri);
1762 if (ret == 0)
1763 ret = parse_vendor_query (string, epos, epos + 1, spos, uri);
1764 if (ret < 0) {
1765 free (allocated);
1766 return ret;
1767 }
1768
1769 string = spos;
1770 }
1771
1772 free (allocated);
1773 return P11_KIT_URI_OK;
1774 }
1775
1776 /**
1777 * p11_kit_uri_free:
1778 * @uri: The URI
1779 *
1780 * Free a PKCS\#11 URI.
1781 */
1782 void
p11_kit_uri_free(P11KitUri * uri)1783 p11_kit_uri_free (P11KitUri *uri)
1784 {
1785 if (!uri)
1786 return;
1787
1788 p11_attrs_free (uri->attrs);
1789 free (uri->pin_source);
1790 free (uri->pin_value);
1791 free (uri->module_name);
1792 free (uri->module_path);
1793 p11_array_free (uri->qattrs);
1794 free (uri);
1795 }
1796
1797 /**
1798 * p11_kit_uri_message:
1799 * @code: The error code
1800 *
1801 * Lookup a message for the uri error code. These codes are the P11_KIT_URI_XXX
1802 * error codes that can be returned from p11_kit_uri_parse() or
1803 * p11_kit_uri_format(). As a special case %NULL, will be returned for
1804 * %P11_KIT_URI_OK.
1805 *
1806 * Returns: The message for the error code. This string is owned by the p11-kit
1807 * library.
1808 */
1809 const char*
p11_kit_uri_message(int code)1810 p11_kit_uri_message (int code)
1811 {
1812 switch (code) {
1813 case P11_KIT_URI_OK:
1814 return NULL;
1815 case P11_KIT_URI_UNEXPECTED:
1816 return "Unexpected or internal system error";
1817 case P11_KIT_URI_BAD_SCHEME:
1818 return "URI scheme must be 'pkcs11:'";
1819 case P11_KIT_URI_BAD_ENCODING:
1820 return "URI encoding invalid or corrupted";
1821 case P11_KIT_URI_BAD_SYNTAX:
1822 return "URI syntax is invalid";
1823 case P11_KIT_URI_BAD_VERSION:
1824 return "URI version component is invalid";
1825 case P11_KIT_URI_NOT_FOUND:
1826 return "The URI component was not found";
1827 default:
1828 p11_debug ("unknown error code: %d", code);
1829 return "Unknown error";
1830 }
1831 }
1832