Coverage Report

Created: 2023-11-19 06:12

/src/p11-kit/p11-kit/uri.c
Line
Count
Source (jump to first uncovered line)
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
0
#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 *
163
strip_whitespace (const char *value)
164
0
{
165
0
  size_t length = strlen (value);
166
0
  char *at, *pos;
167
0
  char *key;
168
169
0
  key = malloc (length + 1);
170
0
  return_val_if_fail (key != NULL, NULL);
171
172
0
  memcpy (key, value, length);
173
0
  key[length] = '\0';
174
175
  /* Do we have any whitespace? Strip it out. */
176
0
  if (strcspn (key, P11_URL_WHITESPACE) != length) {
177
0
    for (at = key, pos = key; pos != key + length + 1; ++pos) {
178
0
      if (!strchr (P11_URL_WHITESPACE, *pos))
179
0
        *(at++) = *pos;
180
0
    }
181
0
    *at = '\0';
182
0
  }
183
184
0
  return key;
185
0
}
186
187
static bool
188
match_struct_string (const unsigned char *inuri, const unsigned char *real,
189
                     size_t length)
190
0
{
191
0
  assert (inuri);
192
0
  assert (real);
193
0
  assert (length > 0);
194
195
  /* NULL matches anything */
196
0
  if (inuri[0] == 0)
197
0
    return true;
198
199
0
  return memcmp (inuri, real, length) == 0 ? true : false;
200
0
}
201
202
static bool
203
match_struct_version (CK_VERSION const *inuri, CK_VERSION const *real)
204
0
{
205
  /* This matches anything */
206
0
  if (inuri->major == (CK_BYTE)-1 && inuri->minor == (CK_BYTE)-1)
207
0
    return true;
208
209
0
  return memcmp (inuri, real, sizeof (CK_VERSION)) == 0 ? true : false;
210
0
}
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
229
p11_kit_uri_get_module_info (P11KitUri *uri)
230
0
{
231
0
  return_val_if_fail (uri != NULL, NULL);
232
0
  return &uri->module;
233
0
}
234
235
int
236
p11_match_uri_module_info (CK_INFO const *one,
237
                           CK_INFO const *two)
238
0
{
239
0
  return (match_struct_string (one->libraryDescription,
240
0
                               two->libraryDescription,
241
0
                               sizeof (one->libraryDescription)) &&
242
0
          match_struct_string (one->manufacturerID,
243
0
                               two->manufacturerID,
244
0
                               sizeof (one->manufacturerID)) &&
245
0
          match_struct_version (&one->libraryVersion,
246
0
                                &two->libraryVersion));
247
0
}
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
264
p11_kit_uri_match_module_info (const P11KitUri *uri, const CK_INFO *info)
265
0
{
266
0
  return_val_if_fail (uri != NULL, 0);
267
0
  return_val_if_fail (info != NULL, 0);
268
269
0
  if (uri->unrecognized)
270
0
    return 0;
271
272
0
  return p11_match_uri_module_info (&uri->module, info);
273
0
}
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
292
p11_kit_uri_get_slot_info (P11KitUri *uri)
293
0
{
294
0
  return_val_if_fail (uri != NULL, NULL);
295
0
  return &uri->slot;
296
0
}
297
298
int
299
p11_match_uri_slot_info (CK_SLOT_INFO const *one,
300
                         CK_SLOT_INFO const *two)
301
0
{
302
0
  return (match_struct_string (one->slotDescription,
303
0
             two->slotDescription,
304
0
             sizeof (one->slotDescription)) &&
305
0
    match_struct_string (one->manufacturerID,
306
0
             two->manufacturerID,
307
0
             sizeof (one->manufacturerID)));
308
0
}
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
326
p11_kit_uri_match_slot_info (const P11KitUri *uri, const CK_SLOT_INFO *slot_info)
327
0
{
328
0
  return_val_if_fail (uri != NULL, 0);
329
0
  return_val_if_fail (slot_info != NULL, 0);
330
331
0
  if (uri->unrecognized)
332
0
    return 0;
333
334
0
  return p11_match_uri_slot_info (&uri->slot, slot_info);
335
0
}
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
346
p11_kit_uri_get_slot_id (P11KitUri *uri)
347
0
{
348
0
  return_val_if_fail (uri != NULL, (CK_SLOT_ID)-1);
349
0
  return uri->slot_id;
350
0
}
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
360
p11_kit_uri_set_slot_id (P11KitUri  *uri,
361
       CK_SLOT_ID  slot_id)
362
0
{
363
0
  return_if_fail (uri != NULL);
364
0
  uri->slot_id = slot_id;
365
0
}
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
384
p11_kit_uri_get_token_info (P11KitUri *uri)
385
0
{
386
0
  return_val_if_fail (uri != NULL, NULL);
387
0
  return &uri->token;
388
0
}
389
390
int
391
p11_match_uri_token_info (CK_TOKEN_INFO const *one,
392
                          CK_TOKEN_INFO const *two)
393
0
{
394
0
  return (match_struct_string (one->label,
395
0
                               two->label,
396
0
                               sizeof (one->label)) &&
397
0
          match_struct_string (one->manufacturerID,
398
0
                               two->manufacturerID,
399
0
                               sizeof (one->manufacturerID)) &&
400
0
          match_struct_string (one->model,
401
0
                               two->model,
402
0
                               sizeof (one->model)) &&
403
0
          match_struct_string (one->serialNumber,
404
0
                               two->serialNumber,
405
0
                               sizeof (one->serialNumber)));
406
0
}
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
424
p11_kit_uri_match_token_info (const P11KitUri *uri, const CK_TOKEN_INFO *token_info)
425
0
{
426
0
  return_val_if_fail (uri != NULL, 0);
427
0
  return_val_if_fail (token_info != NULL, 0);
428
429
0
  if (uri->unrecognized)
430
0
    return 0;
431
432
0
  return p11_match_uri_token_info (&uri->token, token_info);
433
0
}
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
446
p11_kit_uri_get_attribute (P11KitUri *uri, CK_ATTRIBUTE_TYPE attr_type)
447
0
{
448
0
  return_val_if_fail (uri != NULL, NULL);
449
450
0
  if (uri->attrs == NULL)
451
0
    return NULL;
452
453
0
  return p11_attrs_find (uri->attrs, attr_type);
454
0
}
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
469
p11_kit_uri_set_attribute (P11KitUri *uri, CK_ATTRIBUTE_PTR attr)
470
0
{
471
0
  return_val_if_fail (uri != NULL, P11_KIT_URI_UNEXPECTED);
472
473
0
  uri->attrs = p11_attrs_buildn (uri->attrs, attr, 1);
474
0
  return_val_if_fail (uri->attrs != NULL, P11_KIT_URI_UNEXPECTED);
475
476
0
  return P11_KIT_URI_OK;
477
0
}
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
492
p11_kit_uri_clear_attribute (P11KitUri *uri, CK_ATTRIBUTE_TYPE attr_type)
493
0
{
494
0
  return_val_if_fail (uri != NULL, P11_KIT_URI_UNEXPECTED);
495
496
0
  if (attr_type != CKA_CLASS &&
497
0
      attr_type != CKA_LABEL &&
498
0
      attr_type != CKA_ID)
499
0
    return P11_KIT_URI_NOT_FOUND;
500
501
0
  if (uri->attrs)
502
0
    p11_attrs_remove (uri->attrs, attr_type);
503
504
0
  return P11_KIT_URI_OK;
505
0
}
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
519
p11_kit_uri_get_attributes (P11KitUri *uri, CK_ULONG_PTR n_attrs)
520
0
{
521
0
  static const CK_ATTRIBUTE terminator = { CKA_INVALID, NULL, 0UL };
522
523
0
  return_val_if_fail (uri != NULL, NULL);
524
525
0
  if (!uri->attrs) {
526
0
    if (n_attrs)
527
0
      *n_attrs = 0;
528
0
    return (CK_ATTRIBUTE_PTR)&terminator;
529
0
  }
530
531
0
  if (n_attrs)
532
0
    *n_attrs = p11_attrs_count (uri->attrs);
533
0
  return uri->attrs;
534
0
}
535
536
int
537
p11_kit_uri_set_attributes (P11KitUri *uri, CK_ATTRIBUTE_PTR attrs,
538
                            CK_ULONG n_attrs)
539
0
{
540
0
  CK_ULONG i;
541
0
  int ret;
542
543
0
  return_val_if_fail (uri != NULL, P11_KIT_URI_UNEXPECTED);
544
545
0
  p11_kit_uri_clear_attributes (uri);
546
547
0
  for (i = 0; i < n_attrs; i++) {
548
0
    ret = p11_kit_uri_set_attribute (uri, &attrs[i]);
549
0
    if (ret != P11_KIT_URI_OK && ret != P11_KIT_URI_NOT_FOUND)
550
0
      return ret;
551
0
  }
552
553
0
  return P11_KIT_URI_OK;
554
0
}
555
556
void
557
p11_kit_uri_clear_attributes (P11KitUri *uri)
558
0
{
559
0
  return_if_fail (uri != NULL);
560
561
0
  p11_attrs_free (uri->attrs);
562
0
  uri->attrs = NULL;
563
0
}
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
581
p11_kit_uri_match_attributes (const P11KitUri *uri, const CK_ATTRIBUTE *attrs,
582
                              CK_ULONG n_attrs)
583
0
{
584
0
  CK_ATTRIBUTE *attr;
585
0
  CK_ULONG i;
586
587
0
  return_val_if_fail (uri != NULL, 0);
588
0
  return_val_if_fail (attrs != NULL || n_attrs == 0, 0);
589
590
0
  if (uri->unrecognized)
591
0
    return 0;
592
593
0
  for (i = 0; i < n_attrs; i++) {
594
0
    if (attrs[i].type != CKA_CLASS &&
595
0
        attrs[i].type != CKA_LABEL &&
596
0
        attrs[i].type != CKA_ID)
597
0
      continue;
598
0
    attr = NULL;
599
0
    if (uri->attrs)
600
0
      attr = p11_attrs_find (uri->attrs, attrs[i].type);
601
0
    if (!attr)
602
0
      continue;
603
0
    if (!p11_attr_equal (attr, attrs + i))
604
0
      return 0;
605
0
  }
606
607
0
  return 1;
608
0
}
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
622
p11_kit_uri_set_unrecognized (P11KitUri *uri, int unrecognized)
623
0
{
624
0
  return_if_fail (uri != NULL);
625
0
  uri->unrecognized = unrecognized ? true : false;
626
0
}
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
641
p11_kit_uri_any_unrecognized (P11KitUri *uri)
642
0
{
643
0
  return_val_if_fail (uri != NULL, 1);
644
0
  return uri->unrecognized;
645
0
}
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*
657
p11_kit_uri_get_pin_value (const P11KitUri *uri)
658
0
{
659
0
  return_val_if_fail (uri != NULL, NULL);
660
0
  return uri->pin_value;
661
0
}
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
672
p11_kit_uri_set_pin_value (P11KitUri *uri, const char *pin)
673
0
{
674
0
  return_if_fail (uri != NULL);
675
0
  free (uri->pin_value);
676
0
  uri->pin_value = pin ? strdup (pin) : NULL;
677
0
}
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*
690
p11_kit_uri_get_pin_source (const P11KitUri *uri)
691
0
{
692
0
  return_val_if_fail (uri != NULL, NULL);
693
0
  return uri->pin_source;
694
0
}
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*
703
p11_kit_uri_get_pinfile (const P11KitUri *uri)
704
0
{
705
0
  return_val_if_fail (uri != NULL, NULL);
706
0
  return p11_kit_uri_get_pin_source (uri);
707
0
}
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
718
p11_kit_uri_set_pin_source (P11KitUri *uri, const char *pin_source)
719
0
{
720
0
  return_if_fail (uri != NULL);
721
0
  free (uri->pin_source);
722
0
  uri->pin_source = pin_source ? strdup (pin_source) : NULL;
723
0
}
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
733
p11_kit_uri_set_pinfile (P11KitUri *uri, const char *pinfile)
734
0
{
735
0
  return_if_fail (uri != NULL);
736
0
  p11_kit_uri_set_pin_source (uri, pinfile);
737
0
}
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*
750
p11_kit_uri_get_module_name (const P11KitUri *uri)
751
0
{
752
0
  return_val_if_fail (uri != NULL, NULL);
753
0
  return uri->module_name;
754
0
}
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
765
p11_kit_uri_set_module_name (P11KitUri *uri, const char *name)
766
0
{
767
0
  return_if_fail (uri != NULL);
768
0
  free (uri->module_name);
769
0
  uri->module_name = name ? strdup (name) : NULL;
770
0
}
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*
782
p11_kit_uri_get_module_path (const P11KitUri *uri)
783
0
{
784
0
  return_val_if_fail (uri != NULL, NULL);
785
0
  return uri->module_path;
786
0
}
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
797
p11_kit_uri_set_module_path (P11KitUri *uri, const char *path)
798
0
{
799
0
  return_if_fail (uri != NULL);
800
0
  free (uri->module_path);
801
0
  uri->module_path = path ? strdup (path) : NULL;
802
0
}
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*
816
p11_kit_uri_get_vendor_query (const P11KitUri *uri, const char *name)
817
0
{
818
0
  size_t i;
819
820
0
  return_val_if_fail (uri != NULL, NULL);
821
822
0
  for (i = 0; i < uri->qattrs->num; i++) {
823
0
    Attribute *attr = uri->qattrs->elem[i];
824
0
    if (strcmp (attr->name, name) == 0)
825
0
      return attr->value;
826
0
  }
827
0
  return NULL;
828
0
}
829
830
static void
831
free_attribute (Attribute *attr)
832
0
{
833
0
  free (attr->name);
834
0
  free (attr->value);
835
0
  free (attr);
836
0
}
837
838
static bool
839
insert_attribute (p11_array *attrs, char *name, char *value)
840
0
{
841
0
  Attribute *attr;
842
0
  size_t i;
843
844
0
  return_val_if_fail (attrs != NULL, false);
845
0
  return_val_if_fail (name != NULL, false);
846
0
  return_val_if_fail (value != NULL, false);
847
848
0
  for (i = 0; i < attrs->num; i++) {
849
0
    attr = attrs->elem[i];
850
0
    if (strcmp (attr->name, (char *)name) > 0)
851
0
      break;
852
0
  }
853
854
0
  attr = calloc (1, sizeof (Attribute));
855
0
  return_val_if_fail (attr, false);
856
857
0
  attr->name = name;
858
0
  attr->value = value;
859
860
0
  return p11_array_insert (attrs, i, attr);
861
0
}
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
876
p11_kit_uri_set_vendor_query (P11KitUri *uri, const char *name,
877
            const char *value)
878
0
{
879
0
  Attribute *attr;
880
0
  size_t i;
881
882
0
  return_val_if_fail (uri != NULL, 0);
883
0
  return_val_if_fail (name != NULL, 0);
884
885
0
  for (i = 0; i < uri->qattrs->num; i++) {
886
0
    attr = uri->qattrs->elem[i];
887
0
    if (strcmp (attr->name, name) == 0)
888
0
      break;
889
0
  }
890
0
  if (i == uri->qattrs->num) {
891
0
    if (value == NULL)
892
0
      return 0;
893
0
    return insert_attribute (uri->qattrs,
894
0
           strdup (name), strdup (value));
895
0
  }
896
0
  if (value == NULL)
897
0
    p11_array_remove (uri->qattrs, i);
898
0
  else {
899
0
    free (attr->value);
900
0
    attr->value = strdup (value);
901
0
  }
902
903
0
  return 1;
904
0
}
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*
917
p11_kit_uri_new (void)
918
0
{
919
0
  P11KitUri *uri;
920
921
0
  uri = calloc (1, sizeof (P11KitUri));
922
0
  return_val_if_fail (uri != NULL, NULL);
923
924
  /* So that it matches anything */
925
0
  uri->module.libraryVersion.major = (CK_BYTE)-1;
926
0
  uri->module.libraryVersion.minor = (CK_BYTE)-1;
927
0
  uri->slot_id = (CK_SLOT_ID)-1;
928
0
  uri->qattrs = p11_array_new ((p11_destroyer)free_attribute);
929
930
0
  return uri;
931
0
}
932
933
enum uri_sep {
934
  sep_path = '\0',
935
  sep_pattr = ';',
936
  sep_query = '?',
937
  sep_qattr = '&',
938
};
939
940
static void
941
format_name_equals (p11_buffer *buffer,
942
                    enum uri_sep *sep,
943
                    const char *name)
944
0
{
945
0
  if (*sep) {
946
0
    char c = *sep;
947
0
    p11_buffer_add (buffer, &c, 1);
948
0
  }
949
0
  p11_buffer_add (buffer, name, -1);
950
0
  p11_buffer_add (buffer, "=", 1);
951
952
0
  if (*sep == sep_path)
953
0
    *sep = sep_pattr;
954
0
  else if (*sep == sep_query)
955
0
    *sep = sep_qattr;
956
0
}
957
958
static bool
959
format_raw_string (p11_buffer *buffer,
960
                   enum uri_sep *sep,
961
                   const char *name,
962
                   const char *value)
963
0
{
964
  /* Not set */
965
0
  if (!value)
966
0
    return true;
967
968
0
  format_name_equals (buffer, sep, name);
969
0
  p11_buffer_add (buffer, value, -1);
970
971
0
  return p11_buffer_ok (buffer);
972
0
}
973
974
static bool
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
0
{
982
  /* Not set */
983
0
  if (!value)
984
0
    return true;
985
986
0
  format_name_equals (buffer, sep, name);
987
0
  p11_url_encode (value, value + n_value, force ? "" : P11_URL_VERBATIM, buffer);
988
989
0
  return p11_buffer_ok (buffer);
990
0
}
991
992
993
static bool
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
0
{
1000
0
  size_t len;
1001
1002
  /* Not set */
1003
0
  if (!value[0])
1004
0
    return true;
1005
1006
0
  len = p11_kit_space_strlen (value, value_max);
1007
0
  return format_encode_string (buffer, sep, name, value, len, false);
1008
0
}
1009
1010
static bool
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
0
{
1017
0
  /* Not set */;
1018
0
  if (attr == NULL)
1019
0
    return true;
1020
1021
0
  return format_encode_string (buffer, sep, name,
1022
0
                               attr->pValue, attr->ulValueLen,
1023
0
                               force);
1024
0
}
1025
1026
static bool
1027
format_attribute_class (p11_buffer *buffer,
1028
                        enum uri_sep *sep,
1029
                        const char *name,
1030
                        CK_ATTRIBUTE_PTR attr)
1031
0
{
1032
0
  CK_OBJECT_CLASS klass;
1033
0
  const char *value;
1034
1035
0
  /* Not set */;
1036
0
  if (attr == NULL)
1037
0
    return true;
1038
1039
0
  klass = *((CK_OBJECT_CLASS*)attr->pValue);
1040
0
  switch (klass) {
1041
0
  case CKO_DATA:
1042
0
    value = "data";
1043
0
    break;
1044
0
  case CKO_SECRET_KEY:
1045
0
    value = "secret-key";
1046
0
    break;
1047
0
  case CKO_CERTIFICATE:
1048
0
    value = "cert";
1049
0
    break;
1050
0
  case CKO_PUBLIC_KEY:
1051
0
    value = "public";
1052
0
    break;
1053
0
  case CKO_PRIVATE_KEY:
1054
0
    value = "private";
1055
0
    break;
1056
0
  default:
1057
0
    return true;
1058
0
  }
1059
1060
0
  return format_raw_string (buffer, sep, name, value);
1061
0
}
1062
1063
static bool
1064
format_struct_version (p11_buffer *buffer,
1065
                       enum uri_sep *sep,
1066
                       const char *name,
1067
                       CK_VERSION_PTR version)
1068
0
{
1069
0
  char buf[64];
1070
1071
  /* Not set */
1072
0
  if (version->major == (CK_BYTE)-1 && version->minor == (CK_BYTE)-1)
1073
0
    return true;
1074
1075
0
  snprintf (buf, sizeof (buf), "%d.%d",
1076
0
            (int)version->major, (int)version->minor);
1077
0
  return format_raw_string (buffer, sep, name, buf);
1078
0
}
1079
1080
static bool
1081
format_ulong (p11_buffer *buffer,
1082
        enum uri_sep *sep,
1083
        const char *name,
1084
        CK_ULONG value)
1085
0
{
1086
0
  char buf[64];
1087
1088
  /* Not set */
1089
0
  if (value == (CK_ULONG)-1)
1090
0
    return true;
1091
1092
0
  snprintf (buf, sizeof (buf), "%lu", value);
1093
0
  return format_raw_string (buffer, sep, name, buf);
1094
0
}
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
1125
p11_kit_uri_format (P11KitUri *uri, P11KitUriType uri_type, char **string)
1126
0
{
1127
0
  p11_buffer buffer;
1128
0
  enum uri_sep sep = sep_path;
1129
0
  size_t i;
1130
1131
0
  return_val_if_fail (uri != NULL, P11_KIT_URI_UNEXPECTED);
1132
0
  return_val_if_fail (string != NULL, P11_KIT_URI_UNEXPECTED);
1133
1134
0
  if (!p11_buffer_init_null (&buffer, 64))
1135
0
    return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1136
1137
0
  p11_buffer_add (&buffer, P11_KIT_URI_SCHEME, P11_KIT_URI_SCHEME_LEN);
1138
0
  p11_buffer_add (&buffer, ":", 1);
1139
1140
0
  if ((uri_type & P11_KIT_URI_FOR_MODULE) == P11_KIT_URI_FOR_MODULE) {
1141
0
    if (!format_struct_string (&buffer, &sep, "library-description",
1142
0
                               uri->module.libraryDescription,
1143
0
                               sizeof (uri->module.libraryDescription)) ||
1144
0
        !format_struct_string (&buffer, &sep, "library-manufacturer",
1145
0
                               uri->module.manufacturerID,
1146
0
                               sizeof (uri->module.manufacturerID))) {
1147
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1148
0
    }
1149
0
  }
1150
1151
0
  if ((uri_type & P11_KIT_URI_FOR_MODULE_WITH_VERSION) == P11_KIT_URI_FOR_MODULE_WITH_VERSION) {
1152
0
    if (!format_struct_version (&buffer, &sep, "library-version",
1153
0
                                &uri->module.libraryVersion)) {
1154
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1155
0
    }
1156
0
  }
1157
1158
0
  if ((uri_type & P11_KIT_URI_FOR_SLOT) == P11_KIT_URI_FOR_SLOT) {
1159
0
    if (!format_struct_string (&buffer, &sep, "slot-description",
1160
0
                               uri->slot.slotDescription,
1161
0
                               sizeof (uri->slot.slotDescription)) ||
1162
0
        !format_struct_string (&buffer, &sep, "slot-manufacturer",
1163
0
                               uri->slot.manufacturerID,
1164
0
                               sizeof (uri->slot.manufacturerID)) ||
1165
0
        !format_ulong (&buffer, &sep, "slot-id",
1166
0
           uri->slot_id)) {
1167
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1168
0
    }
1169
0
  }
1170
1171
0
  if ((uri_type & P11_KIT_URI_FOR_TOKEN) == P11_KIT_URI_FOR_TOKEN) {
1172
0
    if (!format_struct_string (&buffer, &sep, "model",
1173
0
                               uri->token.model,
1174
0
                               sizeof (uri->token.model)) ||
1175
0
        !format_struct_string (&buffer, &sep, "manufacturer",
1176
0
                               uri->token.manufacturerID,
1177
0
                               sizeof (uri->token.manufacturerID)) ||
1178
0
        !format_struct_string (&buffer, &sep, "serial",
1179
0
                               uri->token.serialNumber,
1180
0
                               sizeof (uri->token.serialNumber)) ||
1181
0
        !format_struct_string (&buffer, &sep, "token",
1182
0
                               uri->token.label,
1183
0
                               sizeof (uri->token.label))) {
1184
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1185
0
    }
1186
0
  }
1187
1188
0
  if ((uri_type & P11_KIT_URI_FOR_OBJECT) == P11_KIT_URI_FOR_OBJECT) {
1189
0
    if (!format_attribute_string (&buffer, &sep, "id",
1190
0
                                  p11_kit_uri_get_attribute (uri, CKA_ID),
1191
0
                                  true) ||
1192
0
        !format_attribute_string (&buffer, &sep, "object",
1193
0
                                  p11_kit_uri_get_attribute (uri, CKA_LABEL),
1194
0
                                  false)) {
1195
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1196
0
    }
1197
1198
0
    if (!format_attribute_class (&buffer, &sep, "type",
1199
0
                                 p11_kit_uri_get_attribute (uri, CKA_CLASS))) {
1200
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1201
0
    }
1202
0
  }
1203
1204
0
  sep = sep_query;
1205
1206
0
  if (uri->pin_source) {
1207
0
    if (!format_encode_string (&buffer, &sep, "pin-source",
1208
0
                               (const unsigned char*)uri->pin_source,
1209
0
                               strlen (uri->pin_source), 0)) {
1210
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1211
0
    }
1212
0
  }
1213
1214
0
  if (uri->pin_value) {
1215
0
    if (!format_encode_string (&buffer, &sep, "pin-value",
1216
0
                               (const unsigned char*)uri->pin_value,
1217
0
                               strlen (uri->pin_value), 0)) {
1218
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1219
0
    }
1220
0
  }
1221
1222
0
  if (uri->module_name) {
1223
0
    if (!format_encode_string (&buffer, &sep, "module-name",
1224
0
                               (const unsigned char*)uri->module_name,
1225
0
                               strlen (uri->module_name), 0)) {
1226
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1227
0
    }
1228
0
  }
1229
1230
0
  if (uri->module_path) {
1231
0
    if (!format_encode_string (&buffer, &sep, "module-path",
1232
0
                               (const unsigned char*)uri->module_path,
1233
0
                               strlen (uri->module_path), 0)) {
1234
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1235
0
    }
1236
0
  }
1237
1238
0
  for (i = 0; i < uri->qattrs->num; i++) {
1239
0
    Attribute *attr = uri->qattrs->elem[i];
1240
0
    if (!format_encode_string (&buffer, &sep, attr->name,
1241
0
             (const unsigned char *) attr->value,
1242
0
             strlen (attr->value), 0)) {
1243
0
      return_val_if_reached (P11_KIT_URI_UNEXPECTED);
1244
0
    }
1245
0
  }
1246
1247
0
  return_val_if_fail (p11_buffer_ok (&buffer), P11_KIT_URI_UNEXPECTED);
1248
0
  *string = p11_buffer_steal (&buffer, NULL);
1249
0
  return P11_KIT_URI_OK;
1250
0
}
1251
1252
static bool
1253
str_range_equal (const char *input, const char *start, const char *end)
1254
0
{
1255
0
  return strlen (input) == end - start &&
1256
0
    memcmp (input, start, end - start) == 0;
1257
0
}
1258
1259
static int
1260
parse_string_attribute (const char *name_start, const char *name_end,
1261
      const char *start, const char *end,
1262
      P11KitUri *uri)
1263
0
{
1264
0
  unsigned char *value;
1265
0
  CK_ATTRIBUTE_TYPE type;
1266
0
  size_t length;
1267
1268
0
  assert (name_start <= name_end);
1269
0
  assert (start <= end);
1270
1271
0
  if (str_range_equal ("id", name_start, name_end))
1272
0
    type = CKA_ID;
1273
0
  else if (str_range_equal ("object", name_start, name_end))
1274
0
    type = CKA_LABEL;
1275
0
  else
1276
0
    return 0;
1277
1278
0
  value = p11_url_decode (start, end, P11_URL_WHITESPACE, &length);
1279
0
  if (value == NULL)
1280
0
    return P11_KIT_URI_BAD_ENCODING;
1281
1282
0
  uri->attrs = p11_attrs_take (uri->attrs, type, value, length);
1283
0
  return 1;
1284
0
}
1285
1286
static int
1287
parse_class_attribute (const char *name_start, const char *name_end,
1288
           const char *start, const char *end,
1289
           P11KitUri *uri)
1290
0
{
1291
0
  CK_OBJECT_CLASS klass = 0;
1292
0
  CK_ATTRIBUTE attr;
1293
1294
0
  assert (name_start <= name_end);
1295
0
  assert (start <= end);
1296
1297
0
  if (!str_range_equal ("objecttype", name_start, name_end) &&
1298
0
      !str_range_equal ("object-type", name_start, name_end) &&
1299
0
      !str_range_equal ("type", name_start, name_end))
1300
0
    return 0;
1301
1302
0
  if (str_range_equal ("cert", start, end))
1303
0
    klass = CKO_CERTIFICATE;
1304
0
  else if (str_range_equal ("public", start, end))
1305
0
    klass = CKO_PUBLIC_KEY;
1306
0
  else if (str_range_equal ("private", start, end))
1307
0
    klass = CKO_PRIVATE_KEY;
1308
0
  else if (str_range_equal ("secretkey", start, end))
1309
0
    klass = CKO_SECRET_KEY;
1310
0
  else if (str_range_equal ("secret-key", start, end))
1311
0
    klass = CKO_SECRET_KEY;
1312
0
  else if (str_range_equal ("data", start, end))
1313
0
    klass = CKO_DATA;
1314
0
  else {
1315
0
    uri->unrecognized = true;
1316
0
    return 1;
1317
0
  }
1318
1319
0
  attr.pValue = &klass;
1320
0
  attr.ulValueLen = sizeof (klass);
1321
0
  attr.type = CKA_CLASS;
1322
1323
0
  uri->attrs = p11_attrs_build (uri->attrs, &attr, NULL);
1324
0
  return 1;
1325
0
}
1326
1327
static int
1328
parse_struct_info (unsigned char *where, size_t length, const char *start,
1329
                   const char *end, P11KitUri *uri)
1330
0
{
1331
0
  unsigned char *value;
1332
0
  size_t value_length;
1333
1334
0
  assert (start <= end);
1335
1336
0
  value = p11_url_decode (start, end, P11_URL_WHITESPACE, &value_length);
1337
0
  if (value == NULL)
1338
0
    return P11_KIT_URI_BAD_ENCODING;
1339
1340
  /* Too long, shouldn't match anything */
1341
0
  if (value_length > length) {
1342
0
    free (value);
1343
0
    uri->unrecognized = true;
1344
0
    return 1;
1345
0
  }
1346
1347
0
  memset (where, ' ', length);
1348
0
  memcpy (where, value, value_length);
1349
1350
0
  free (value);
1351
0
  return 1;
1352
0
}
1353
1354
static int
1355
parse_token_info (const char *name_start, const char *name_end,
1356
      const char *start, const char *end,
1357
      P11KitUri *uri)
1358
0
{
1359
0
  unsigned char *where;
1360
0
  size_t length;
1361
1362
0
  assert (name_start <= name_end);
1363
0
  assert (start <= end);
1364
1365
0
  if (str_range_equal ("model", name_start, name_end)) {
1366
0
    where = uri->token.model;
1367
0
    length = sizeof (uri->token.model);
1368
0
  } else if (str_range_equal ("manufacturer", name_start, name_end)) {
1369
0
    where = uri->token.manufacturerID;
1370
0
    length = sizeof (uri->token.manufacturerID);
1371
0
  } else if (str_range_equal ("serial", name_start, name_end)) {
1372
0
    where = uri->token.serialNumber;
1373
0
    length = sizeof (uri->token.serialNumber);
1374
0
  } else if (str_range_equal ("token", name_start, name_end)) {
1375
0
    where = uri->token.label;
1376
0
    length = sizeof (uri->token.label);
1377
0
  } else {
1378
0
    return 0;
1379
0
  }
1380
1381
0
  return parse_struct_info (where, length, start, end, uri);
1382
0
}
1383
1384
static long
1385
atoin (const char *start, const char *end)
1386
0
{
1387
0
  long ret = 0;
1388
0
  while (start != end) {
1389
0
    if (*start < '0' || *start > '9')
1390
0
      return -1;
1391
0
    ret *= 10;
1392
0
    ret += (*start - '0');
1393
0
    ++start;
1394
0
  }
1395
0
  return ret;
1396
0
}
1397
1398
static int
1399
parse_struct_version (const char *start, const char *end, CK_VERSION_PTR version)
1400
0
{
1401
0
  const char *dot;
1402
0
  int val;
1403
1404
0
  assert (start <= end);
1405
1406
0
  dot = memchr (start, '.', end - start);
1407
0
  if (!dot)
1408
0
    dot = end;
1409
1410
0
  if (dot == start)
1411
0
    return P11_KIT_URI_BAD_VERSION;
1412
0
  val = atoin (start, dot);
1413
0
  if (val < 0 || val >= 255)
1414
0
    return P11_KIT_URI_BAD_VERSION;
1415
0
  version->major = (CK_BYTE)val;
1416
0
  version->minor = 0;
1417
1418
0
  if (dot != end) {
1419
0
    if (dot + 1 == end)
1420
0
      return P11_KIT_URI_BAD_VERSION;
1421
0
    val = atoin (dot + 1, end);
1422
0
    if (val < 0 || val >= 255)
1423
0
      return P11_KIT_URI_BAD_VERSION;
1424
0
    version->minor = (CK_BYTE)val;
1425
0
  }
1426
1427
0
  return 1;
1428
0
}
1429
1430
static int
1431
parse_slot_info (const char *name_start, const char *name_end,
1432
                 const char *start, const char *end,
1433
                 P11KitUri *uri)
1434
0
{
1435
0
  unsigned char *where;
1436
0
  size_t length;
1437
1438
0
  assert (name_start <= name_end);
1439
0
  assert (start <= end);
1440
1441
0
  if (str_range_equal ("slot-description", name_start, name_end)) {
1442
0
    where = uri->slot.slotDescription;
1443
0
    length = sizeof (uri->slot.slotDescription);
1444
0
  } else if (str_range_equal ("slot-manufacturer", name_start, name_end)) {
1445
0
    where = uri->slot.manufacturerID;
1446
0
    length = sizeof (uri->slot.manufacturerID);
1447
0
  } else {
1448
0
    return 0;
1449
0
  }
1450
1451
0
  return parse_struct_info (where, length, start, end, uri);
1452
0
}
1453
1454
static int
1455
parse_slot_id (const char *name_start, const char *name_end,
1456
         const char *start, const char *end,
1457
         P11KitUri *uri)
1458
0
{
1459
0
  assert (name_start <= name_end);
1460
0
  assert (start <= end);
1461
1462
0
  if (str_range_equal ("slot-id", name_start, name_end)) {
1463
0
    long val;
1464
0
    val = atoin (start, end);
1465
0
    if (val < 0)
1466
0
      return P11_KIT_URI_BAD_SYNTAX;
1467
0
    uri->slot_id = (CK_SLOT_ID)val;
1468
0
    return 1;
1469
0
  }
1470
0
  return 0;
1471
0
}
1472
1473
static int
1474
parse_module_version_info (const char *name_start, const char *name_end,
1475
         const char *start, const char *end,
1476
         P11KitUri *uri)
1477
0
{
1478
0
  assert (name_start <= name_end);
1479
0
  assert (start <= end);
1480
1481
0
  if (str_range_equal ("library-version", name_start, name_end))
1482
0
    return parse_struct_version (start, end,
1483
0
                                 &uri->module.libraryVersion);
1484
1485
0
  return 0;
1486
0
}
1487
1488
static int
1489
parse_module_info (const char *name_start, const char *name_end,
1490
       const char *start, const char *end,
1491
       P11KitUri *uri)
1492
0
{
1493
0
  unsigned char *where;
1494
0
  size_t length;
1495
1496
0
  assert (name_start <= name_end);
1497
0
  assert (start <= end);
1498
1499
0
  if (str_range_equal ("library-description", name_start, name_end)) {
1500
0
    where = uri->module.libraryDescription;
1501
0
    length = sizeof (uri->module.libraryDescription);
1502
0
  } else if (str_range_equal ("library-manufacturer", name_start, name_end)) {
1503
0
    where = uri->module.manufacturerID;
1504
0
    length = sizeof (uri->module.manufacturerID);
1505
0
  } else {
1506
0
    return 0;
1507
0
  }
1508
1509
0
  return parse_struct_info (where, length, start, end, uri);
1510
0
}
1511
1512
static int
1513
parse_pin_query (const char *name_start, const char *name_end,
1514
     const char *start, const char *end,
1515
     P11KitUri *uri)
1516
0
{
1517
0
  unsigned char *value;
1518
1519
0
  assert (name_start <= name_end);
1520
0
  assert (start <= end);
1521
1522
0
  if (str_range_equal ("pinfile", name_start, name_end) ||
1523
0
      str_range_equal ("pin-source", name_start, name_end)) {
1524
0
    value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1525
0
    if (value == NULL)
1526
0
      return P11_KIT_URI_BAD_ENCODING;
1527
0
    free (uri->pin_source);
1528
0
    uri->pin_source = (char*)value;
1529
0
    return 1;
1530
0
  } else if (str_range_equal ("pin-value", name_start, name_end)) {
1531
0
    value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1532
0
    if (value == NULL)
1533
0
      return P11_KIT_URI_BAD_ENCODING;
1534
0
    free (uri->pin_value);
1535
0
    uri->pin_value = (char*)value;
1536
0
    return 1;
1537
0
  }
1538
1539
0
  return 0;
1540
0
}
1541
1542
static int
1543
parse_module_query (const char *name_start, const char *name_end,
1544
        const char *start, const char *end,
1545
        P11KitUri *uri)
1546
0
{
1547
0
  unsigned char *value;
1548
1549
0
  assert (name_start <= name_end);
1550
0
  assert (start <= end);
1551
1552
0
  if (str_range_equal ("module-name", name_start, name_end)) {
1553
0
    value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1554
0
    if (value == NULL)
1555
0
      return P11_KIT_URI_BAD_ENCODING;
1556
0
    free (uri->module_name);
1557
0
    uri->module_name = (char*)value;
1558
0
    return 1;
1559
0
  } else if (str_range_equal ("module-path", name_start, name_end)) {
1560
0
    value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1561
0
    if (value == NULL)
1562
0
      return P11_KIT_URI_BAD_ENCODING;
1563
0
    free (uri->module_path);
1564
0
    uri->module_path = (char*)value;
1565
0
    return 1;
1566
0
  }
1567
1568
0
  return 0;
1569
0
}
1570
1571
static int
1572
parse_vendor_query (const char *name_start, const char *name_end,
1573
        const char *start, const char *end,
1574
        P11KitUri *uri)
1575
0
{
1576
0
  char *name;
1577
0
  unsigned char *value;
1578
1579
0
  assert (name_start <= name_end);
1580
0
  assert (start <= end);
1581
1582
0
  name = malloc (name_end - name_start + 1);
1583
0
  if (name == NULL)
1584
0
    return P11_KIT_URI_BAD_ENCODING;
1585
0
  memcpy (name, name_start, name_end - name_start);
1586
0
  name[name_end - name_start] = '\0';
1587
1588
  /* Limit the characters in NAME, according to the specification.  */
1589
0
  if (strspn (name, "abcdefghijklmnopqrstuvwxyz0123456789-_") !=
1590
0
      name_end - name_start) {
1591
0
    free (name);
1592
0
    return P11_KIT_URI_UNEXPECTED;
1593
0
  }
1594
1595
0
  value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
1596
0
  if (value == NULL) {
1597
0
    free (name);
1598
0
    return P11_KIT_URI_BAD_ENCODING;
1599
0
  }
1600
1601
0
  if (!insert_attribute (uri->qattrs, name, (char *)value)) {
1602
0
    free (name);
1603
0
    free (value);
1604
0
    return P11_KIT_URI_UNEXPECTED;
1605
0
  }
1606
1607
0
  return 0;
1608
0
}
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
1635
p11_kit_uri_parse (const char *string, P11KitUriType uri_type,
1636
                   P11KitUri *uri)
1637
0
{
1638
0
  const char *spos, *epos;
1639
0
  int ret;
1640
0
  size_t length, i;
1641
0
  char *allocated = NULL;
1642
1643
0
  assert (string);
1644
0
  assert (uri);
1645
1646
  /* If STRING contains any whitespace, create a copy of the
1647
   * string and strip it out */
1648
0
  length = strcspn (string, P11_URL_WHITESPACE);
1649
0
  if (strspn (string + length, P11_URL_WHITESPACE) > 0) {
1650
0
    allocated = strip_whitespace (string);
1651
0
    return_val_if_fail (allocated != NULL, P11_KIT_URI_UNEXPECTED);
1652
0
    string = allocated;
1653
0
  }
1654
1655
0
  epos = strchr (string, ':');
1656
0
  if (epos == NULL) {
1657
0
    free (allocated);
1658
0
    return P11_KIT_URI_BAD_SCHEME;
1659
0
  }
1660
0
  if (epos - string != P11_KIT_URI_SCHEME_LEN) {
1661
0
    free (allocated);
1662
0
    return P11_KIT_URI_BAD_SCHEME;
1663
0
  }
1664
0
  for (i = 0; i < P11_KIT_URI_SCHEME_LEN; i++)
1665
0
    if (p11_ascii_tolower (string[i]) != P11_KIT_URI_SCHEME[i])
1666
0
      break;
1667
0
  if (i != P11_KIT_URI_SCHEME_LEN) {
1668
0
    free (allocated);
1669
0
    return P11_KIT_URI_BAD_SCHEME;
1670
0
  }
1671
1672
0
  string = epos + 1;
1673
1674
  /* Clear everything out */
1675
0
  memset (&uri->module, 0, sizeof (uri->module));
1676
0
  memset (&uri->token, 0, sizeof (uri->token));
1677
0
  p11_attrs_free (uri->attrs);
1678
0
  uri->attrs = NULL;
1679
0
  uri->module.libraryVersion.major = (CK_BYTE)-1;
1680
0
  uri->module.libraryVersion.minor = (CK_BYTE)-1;
1681
0
  uri->unrecognized = 0;
1682
0
  uri->slot_id = (CK_SLOT_ID)-1;
1683
0
  free (uri->pin_source);
1684
0
  uri->pin_source = NULL;
1685
0
  free (uri->pin_value);
1686
0
  uri->pin_value = NULL;
1687
0
  free (uri->module_name);
1688
0
  uri->module_name = NULL;
1689
0
  free (uri->module_path);
1690
0
  uri->module_path = NULL;
1691
0
  p11_array_clear (uri->qattrs);
1692
1693
  /* Parse the path. */
1694
0
  for (;;) {
1695
0
    spos = string + strcspn (string, ";?");
1696
0
    if (spos == string)
1697
0
      break;
1698
1699
0
    epos = strchr (string, '=');
1700
0
    if (epos == NULL || epos == string || epos >= spos) {
1701
0
      free (allocated);
1702
0
      return P11_KIT_URI_BAD_SYNTAX;
1703
0
    }
1704
1705
0
    ret = 0;
1706
0
    if ((uri_type & P11_KIT_URI_FOR_OBJECT) == P11_KIT_URI_FOR_OBJECT)
1707
0
      ret = parse_string_attribute (string, epos, epos + 1, spos, uri);
1708
0
    if (ret == 0 && (uri_type & P11_KIT_URI_FOR_OBJECT) == P11_KIT_URI_FOR_OBJECT)
1709
0
      ret = parse_class_attribute (string, epos, epos + 1, spos, uri);
1710
0
    if (ret == 0 && (uri_type & P11_KIT_URI_FOR_TOKEN) == P11_KIT_URI_FOR_TOKEN)
1711
0
      ret = parse_token_info (string, epos, epos + 1, spos, uri);
1712
0
    if (ret == 0 && (uri_type & P11_KIT_URI_FOR_SLOT) == P11_KIT_URI_FOR_SLOT)
1713
0
      ret = parse_slot_info (string, epos, epos + 1, spos, uri);
1714
0
    if (ret == 0 && (uri_type & P11_KIT_URI_FOR_SLOT) == P11_KIT_URI_FOR_SLOT)
1715
0
      ret = parse_slot_id (string, epos, epos + 1, spos, uri);
1716
0
    if (ret == 0 && (uri_type & P11_KIT_URI_FOR_MODULE) == P11_KIT_URI_FOR_MODULE)
1717
0
      ret = parse_module_info (string, epos, epos + 1, spos, uri);
1718
0
    if (ret == 0 && (uri_type & P11_KIT_URI_FOR_MODULE_WITH_VERSION) == P11_KIT_URI_FOR_MODULE_WITH_VERSION)
1719
0
      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
0
    if (ret == 0)
1723
0
      ret = parse_pin_query (string, epos, epos + 1, spos, uri);
1724
1725
0
    if (ret < 0) {
1726
0
      free (allocated);
1727
0
      return ret;
1728
0
    }
1729
0
    if (ret == 0)
1730
0
      uri->unrecognized = true;
1731
1732
0
    string = spos;
1733
0
    if (*spos == '\0')
1734
0
      break;
1735
0
    if (*spos == '?')
1736
0
      break;
1737
0
    string++;
1738
0
  }
1739
1740
  /* Parse the query. */
1741
0
  for (;;) {
1742
0
    if (*string == '\0')
1743
0
      break;
1744
0
    string++;
1745
0
    spos = strchr (string, '&');
1746
0
    if (spos == NULL) {
1747
0
      spos = string + strlen (string);
1748
0
      assert (*spos == '\0');
1749
0
      if (spos == string)
1750
0
        break;
1751
0
    }
1752
1753
0
    epos = strchr (string, '=');
1754
0
    if (epos == NULL || spos == string || epos == string || epos >= spos) {
1755
0
      free (allocated);
1756
0
      return P11_KIT_URI_BAD_SYNTAX;
1757
0
    }
1758
1759
0
    ret = parse_pin_query (string, epos, epos + 1, spos, uri);
1760
0
    if (ret == 0)
1761
0
      ret = parse_module_query (string, epos, epos + 1, spos, uri);
1762
0
    if (ret == 0)
1763
0
      ret = parse_vendor_query (string, epos, epos + 1, spos, uri);
1764
0
    if (ret < 0) {
1765
0
      free (allocated);
1766
0
      return ret;
1767
0
    }
1768
1769
0
    string = spos;
1770
0
  }
1771
1772
0
  free (allocated);
1773
0
  return P11_KIT_URI_OK;
1774
0
}
1775
1776
/**
1777
 * p11_kit_uri_free:
1778
 * @uri: The URI
1779
 *
1780
 * Free a PKCS\#11 URI.
1781
 */
1782
void
1783
p11_kit_uri_free (P11KitUri *uri)
1784
0
{
1785
0
  if (!uri)
1786
0
    return;
1787
1788
0
  p11_attrs_free (uri->attrs);
1789
0
  free (uri->pin_source);
1790
0
  free (uri->pin_value);
1791
0
  free (uri->module_name);
1792
0
  free (uri->module_path);
1793
0
  p11_array_free (uri->qattrs);
1794
0
  free (uri);
1795
0
}
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*
1810
p11_kit_uri_message (int code)
1811
0
{
1812
0
  switch (code) {
1813
0
  case P11_KIT_URI_OK:
1814
0
    return NULL;
1815
0
  case P11_KIT_URI_UNEXPECTED:
1816
0
    return "Unexpected or internal system error";
1817
0
  case P11_KIT_URI_BAD_SCHEME:
1818
0
    return "URI scheme must be 'pkcs11:'";
1819
0
  case P11_KIT_URI_BAD_ENCODING:
1820
0
    return "URI encoding invalid or corrupted";
1821
0
  case P11_KIT_URI_BAD_SYNTAX:
1822
0
    return "URI syntax is invalid";
1823
0
  case P11_KIT_URI_BAD_VERSION:
1824
0
    return "URI version component is invalid";
1825
0
  case P11_KIT_URI_NOT_FOUND:
1826
0
    return "The URI component was not found";
1827
0
  default:
1828
0
    p11_debug ("unknown error code: %d", code);
1829
0
    return "Unknown error";
1830
0
  }
1831
0
}