pkcs11uri.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "pkcs11.h"
  5. #include "pkcs11uri.h"
  6. #include "plarena.h"
  7. #include "prprf.h"
  8. #include "secport.h"
  9. /* Character sets used in the ABNF rules in RFC7512. */
  10. #define PK11URI_DIGIT "0123456789"
  11. #define PK11URI_ALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  12. #define PK11URI_HEXDIG PK11URI_DIGIT "abcdefABCDEF"
  13. #define PK11URI_UNRESERVED PK11URI_ALPHA PK11URI_DIGIT "-._~"
  14. #define PK11URI_RES_AVAIL ":[]@!$'()*+,="
  15. #define PK11URI_PATH_RES_AVAIL PK11URI_RES_AVAIL "&"
  16. #define PK11URI_QUERY_RES_AVAIL PK11URI_RES_AVAIL "/?|"
  17. #define PK11URI_ATTR_NM_CHAR PK11URI_ALPHA PK11URI_DIGIT "-_"
  18. #define PK11URI_PCHAR PK11URI_UNRESERVED PK11URI_PATH_RES_AVAIL
  19. #define PK11URI_QCHAR PK11URI_UNRESERVED PK11URI_QUERY_RES_AVAIL
  20. /* Path attributes defined in RFC7512. */
  21. static const char *pattr_names[] = {
  22. PK11URI_PATTR_TOKEN,
  23. PK11URI_PATTR_MANUFACTURER,
  24. PK11URI_PATTR_SERIAL,
  25. PK11URI_PATTR_MODEL,
  26. PK11URI_PATTR_LIBRARY_MANUFACTURER,
  27. PK11URI_PATTR_LIBRARY_DESCRIPTION,
  28. PK11URI_PATTR_LIBRARY_VERSION,
  29. PK11URI_PATTR_OBJECT,
  30. PK11URI_PATTR_TYPE,
  31. PK11URI_PATTR_ID,
  32. PK11URI_PATTR_SLOT_MANUFACTURER,
  33. PK11URI_PATTR_SLOT_DESCRIPTION,
  34. PK11URI_PATTR_SLOT_ID
  35. };
  36. /* Query attributes defined in RFC7512. */
  37. static const char *qattr_names[] = {
  38. PK11URI_QATTR_PIN_SOURCE,
  39. PK11URI_QATTR_PIN_VALUE,
  40. PK11URI_QATTR_MODULE_NAME,
  41. PK11URI_QATTR_MODULE_PATH
  42. };
  43. struct PK11URIBufferStr {
  44. PLArenaPool *arena;
  45. char *data;
  46. size_t size;
  47. size_t allocated;
  48. };
  49. typedef struct PK11URIBufferStr PK11URIBuffer;
  50. struct PK11URIAttributeListEntryStr {
  51. char *name;
  52. char *value;
  53. };
  54. typedef struct PK11URIAttributeListEntryStr PK11URIAttributeListEntry;
  55. struct PK11URIAttributeListStr {
  56. PLArenaPool *arena;
  57. PK11URIAttributeListEntry *attrs;
  58. size_t num_attrs;
  59. };
  60. typedef struct PK11URIAttributeListStr PK11URIAttributeList;
  61. struct PK11URIStr {
  62. PLArenaPool *arena;
  63. PK11URIAttributeList pattrs;
  64. PK11URIAttributeList vpattrs;
  65. PK11URIAttributeList qattrs;
  66. PK11URIAttributeList vqattrs;
  67. };
  68. #define PK11URI_ARENA_SIZE 1024
  69. typedef int (*PK11URIAttributeCompareNameFunc)(const char *a, const char *b);
  70. /* This belongs in secport.h */
  71. #define PORT_ArenaGrowArray(poolp, oldptr, type, oldnum, newnum) \
  72. (type *)PORT_ArenaGrow((poolp), (oldptr), \
  73. (oldnum) * sizeof(type), (newnum) * sizeof(type))
  74. #define PORT_ReallocArray(oldptr, type, newnum) \
  75. (type *)PORT_Realloc((oldptr), (newnum) * sizeof(type))
  76. /* Functions for resizable buffer. */
  77. static SECStatus
  78. pk11uri_AppendBuffer(PK11URIBuffer *buffer, const unsigned char *data,
  79. size_t size)
  80. {
  81. /* Check overflow. */
  82. if (buffer->size + size < buffer->size)
  83. return SECFailure;
  84. if (buffer->size + size > buffer->allocated) {
  85. size_t allocated = buffer->allocated * 2 + size;
  86. if (allocated < buffer->allocated)
  87. return SECFailure;
  88. if (buffer->arena)
  89. buffer->data = PORT_ArenaGrow(buffer->arena, buffer->data,
  90. buffer->allocated, allocated);
  91. else
  92. buffer->data = PORT_Realloc(buffer->data, allocated);
  93. if (buffer->data == NULL)
  94. return SECFailure;
  95. buffer->allocated = allocated;
  96. }
  97. memcpy(&buffer->data[buffer->size], data, size);
  98. buffer->size += size;
  99. return SECSuccess;
  100. }
  101. static void
  102. pk11uri_InitBuffer(PK11URIBuffer *buffer, PLArenaPool *arena)
  103. {
  104. memset(buffer, 0, sizeof(PK11URIBuffer));
  105. buffer->arena = arena;
  106. }
  107. static void
  108. pk11uri_DestroyBuffer(PK11URIBuffer *buffer)
  109. {
  110. if (buffer->arena == NULL) {
  111. PORT_Free(buffer->data);
  112. }
  113. }
  114. /* URI encoding functions. */
  115. static char *
  116. pk11uri_Escape(PLArenaPool *arena, const char *value, size_t length,
  117. const char *available)
  118. {
  119. PK11URIBuffer buffer;
  120. const char *p;
  121. unsigned char buf[4];
  122. char *result = NULL;
  123. SECStatus ret;
  124. pk11uri_InitBuffer(&buffer, arena);
  125. for (p = value; p < value + length; p++) {
  126. if (strchr(available, *p) == NULL) {
  127. if (PR_snprintf((char *)buf, sizeof(buf), "%%%02X", *p) == (PRUint32)-1) {
  128. goto fail;
  129. }
  130. ret = pk11uri_AppendBuffer(&buffer, buf, 3);
  131. if (ret != SECSuccess) {
  132. goto fail;
  133. }
  134. } else {
  135. ret = pk11uri_AppendBuffer(&buffer, (const unsigned char *)p, 1);
  136. if (ret != SECSuccess) {
  137. goto fail;
  138. }
  139. }
  140. }
  141. buf[0] = '\0';
  142. ret = pk11uri_AppendBuffer(&buffer, buf, 1);
  143. if (ret != SECSuccess) {
  144. goto fail;
  145. }
  146. /* Steal the memory allocated in buffer. */
  147. result = buffer.data;
  148. buffer.data = NULL;
  149. fail:
  150. pk11uri_DestroyBuffer(&buffer);
  151. return result;
  152. }
  153. static char *
  154. pk11uri_Unescape(PLArenaPool *arena, const char *value, size_t length)
  155. {
  156. PK11URIBuffer buffer;
  157. const char *p;
  158. unsigned char buf[1];
  159. char *result = NULL;
  160. SECStatus ret;
  161. pk11uri_InitBuffer(&buffer, arena);
  162. for (p = value; p < value + length; p++) {
  163. if (*p == '%') {
  164. int c;
  165. size_t i;
  166. p++;
  167. for (c = 0, i = 0; i < 2; i++) {
  168. int h = *(p + i);
  169. if ('0' <= h && h <= '9') {
  170. c = (c << 4) | (h - '0');
  171. } else if ('a' <= h && h <= 'f') {
  172. c = (c << 4) | (h - 'a' + 10);
  173. } else if ('A' <= h && h <= 'F') {
  174. c = (c << 4) | (h - 'A' + 10);
  175. } else {
  176. break;
  177. }
  178. }
  179. if (i != 2) {
  180. goto fail;
  181. }
  182. p++;
  183. buf[0] = c;
  184. } else {
  185. buf[0] = *p;
  186. }
  187. ret = pk11uri_AppendBuffer(&buffer, buf, 1);
  188. if (ret != SECSuccess) {
  189. goto fail;
  190. }
  191. }
  192. buf[0] = '\0';
  193. ret = pk11uri_AppendBuffer(&buffer, buf, 1);
  194. if (ret != SECSuccess) {
  195. goto fail;
  196. }
  197. result = buffer.data;
  198. buffer.data = NULL;
  199. fail:
  200. pk11uri_DestroyBuffer(&buffer);
  201. return result;
  202. }
  203. /* Functions for manipulating attributes array. */
  204. /* Compare two attribute names by the array index in attr_names. Both
  205. * attribute names must be present in attr_names, otherwise it is a
  206. * programming error. */
  207. static int
  208. pk11uri_CompareByPosition(const char *a, const char *b,
  209. const char **attr_names, size_t num_attr_names)
  210. {
  211. size_t i, j;
  212. for (i = 0; i < num_attr_names; i++) {
  213. if (strcmp(a, attr_names[i]) == 0) {
  214. break;
  215. }
  216. }
  217. PR_ASSERT(i < num_attr_names);
  218. for (j = 0; j < num_attr_names; j++) {
  219. if (strcmp(b, attr_names[j]) == 0) {
  220. break;
  221. }
  222. }
  223. PR_ASSERT(j < num_attr_names);
  224. return i - j;
  225. }
  226. /* Those pk11uri_Compare{Path,Query}AttributeName functions are used
  227. * to reorder attributes when inserting. */
  228. static int
  229. pk11uri_ComparePathAttributeName(const char *a, const char *b)
  230. {
  231. return pk11uri_CompareByPosition(a, b, pattr_names, PR_ARRAY_SIZE(pattr_names));
  232. }
  233. static int
  234. pk11uri_CompareQueryAttributeName(const char *a, const char *b)
  235. {
  236. return pk11uri_CompareByPosition(a, b, qattr_names, PR_ARRAY_SIZE(qattr_names));
  237. }
  238. static SECStatus
  239. pk11uri_InsertToAttributeList(PK11URIAttributeList *attrs,
  240. char *name, char *value,
  241. PK11URIAttributeCompareNameFunc compare_name,
  242. PRBool allow_duplicate)
  243. {
  244. size_t i;
  245. if (attrs->arena) {
  246. attrs->attrs = PORT_ArenaGrowArray(attrs->arena, attrs->attrs,
  247. PK11URIAttributeListEntry,
  248. attrs->num_attrs,
  249. attrs->num_attrs + 1);
  250. } else {
  251. attrs->attrs = PORT_ReallocArray(attrs->attrs,
  252. PK11URIAttributeListEntry,
  253. attrs->num_attrs + 1);
  254. }
  255. if (attrs->attrs == NULL) {
  256. return SECFailure;
  257. }
  258. for (i = 0; i < attrs->num_attrs; i++) {
  259. if (!allow_duplicate && strcmp(name, attrs->attrs[i].name) == 0) {
  260. return SECFailure;
  261. }
  262. if (compare_name(name, attrs->attrs[i].name) < 0) {
  263. memmove(&attrs->attrs[i + 1], &attrs->attrs[i],
  264. sizeof(PK11URIAttributeListEntry) * (attrs->num_attrs - i));
  265. break;
  266. }
  267. }
  268. attrs->attrs[i].name = name;
  269. attrs->attrs[i].value = value;
  270. attrs->num_attrs++;
  271. return SECSuccess;
  272. }
  273. static SECStatus
  274. pk11uri_InsertToAttributeListEscaped(PK11URIAttributeList *attrs,
  275. const char *name, size_t name_size,
  276. const char *value, size_t value_size,
  277. PK11URIAttributeCompareNameFunc compare_name,
  278. PRBool allow_duplicate)
  279. {
  280. char *name_copy = NULL, *value_copy = NULL;
  281. SECStatus ret;
  282. if (attrs->arena) {
  283. name_copy = PORT_ArenaNewArray(attrs->arena, char, name_size + 1);
  284. } else {
  285. name_copy = PORT_Alloc(name_size + 1);
  286. }
  287. if (name_copy == NULL) {
  288. goto fail;
  289. }
  290. memcpy(name_copy, name, name_size);
  291. name_copy[name_size] = '\0';
  292. value_copy = pk11uri_Unescape(attrs->arena, value, value_size);
  293. if (value_copy == NULL) {
  294. goto fail;
  295. }
  296. ret = pk11uri_InsertToAttributeList(attrs, name_copy, value_copy, compare_name,
  297. allow_duplicate);
  298. if (ret != SECSuccess) {
  299. goto fail;
  300. }
  301. return ret;
  302. fail:
  303. if (attrs->arena == NULL) {
  304. PORT_Free(name_copy);
  305. PORT_Free(value_copy);
  306. }
  307. return SECFailure;
  308. }
  309. static void
  310. pk11uri_InitAttributeList(PK11URIAttributeList *attrs, PLArenaPool *arena)
  311. {
  312. memset(attrs, 0, sizeof(PK11URIAttributeList));
  313. attrs->arena = arena;
  314. }
  315. static void
  316. pk11uri_DestroyAttributeList(PK11URIAttributeList *attrs)
  317. {
  318. if (attrs->arena == NULL) {
  319. size_t i;
  320. for (i = 0; i < attrs->num_attrs; i++) {
  321. PORT_Free(attrs->attrs[i].name);
  322. PORT_Free(attrs->attrs[i].value);
  323. }
  324. PORT_Free(attrs->attrs);
  325. }
  326. }
  327. static SECStatus
  328. pk11uri_AppendAttributeListToBuffer(PK11URIBuffer *buffer,
  329. PK11URIAttributeList *attrs,
  330. int separator,
  331. const char *unescaped)
  332. {
  333. size_t i;
  334. SECStatus ret;
  335. for (i = 0; i < attrs->num_attrs; i++) {
  336. unsigned char sep[1];
  337. char *escaped;
  338. PK11URIAttributeListEntry *attr = &attrs->attrs[i];
  339. if (i > 0) {
  340. sep[0] = separator;
  341. ret = pk11uri_AppendBuffer(buffer, sep, 1);
  342. if (ret != SECSuccess) {
  343. return ret;
  344. }
  345. }
  346. ret = pk11uri_AppendBuffer(buffer, (unsigned char *)attr->name,
  347. strlen(attr->name));
  348. if (ret != SECSuccess) {
  349. return ret;
  350. }
  351. sep[0] = '=';
  352. ret = pk11uri_AppendBuffer(buffer, sep, 1);
  353. if (ret != SECSuccess) {
  354. return ret;
  355. }
  356. escaped = pk11uri_Escape(buffer->arena, attr->value, strlen(attr->value),
  357. unescaped);
  358. if (escaped == NULL) {
  359. return ret;
  360. }
  361. ret = pk11uri_AppendBuffer(buffer, (unsigned char *)escaped,
  362. strlen(escaped));
  363. if (buffer->arena == NULL) {
  364. PORT_Free(escaped);
  365. }
  366. if (ret != SECSuccess) {
  367. return ret;
  368. }
  369. }
  370. return SECSuccess;
  371. }
  372. /* Creation of PK11URI object. */
  373. static PK11URI *
  374. pk11uri_AllocURI(void)
  375. {
  376. PLArenaPool *arena;
  377. PK11URI *result;
  378. arena = PORT_NewArena(PK11URI_ARENA_SIZE);
  379. if (arena == NULL) {
  380. return NULL;
  381. }
  382. result = PORT_ArenaZAlloc(arena, sizeof(PK11URI));
  383. if (result == NULL) {
  384. PORT_FreeArena(arena, PR_FALSE);
  385. return NULL;
  386. }
  387. result->arena = arena;
  388. pk11uri_InitAttributeList(&result->pattrs, arena);
  389. pk11uri_InitAttributeList(&result->vpattrs, arena);
  390. pk11uri_InitAttributeList(&result->qattrs, arena);
  391. pk11uri_InitAttributeList(&result->vqattrs, arena);
  392. return result;
  393. }
  394. static SECStatus
  395. pk11uri_InsertAttributes(PK11URIAttributeList *dest_attrs,
  396. PK11URIAttributeList *dest_vattrs,
  397. const PK11URIAttribute *attrs,
  398. size_t num_attrs,
  399. const char **attr_names,
  400. size_t num_attr_names,
  401. PK11URIAttributeCompareNameFunc compare_name,
  402. PRBool allow_duplicate,
  403. PRBool vendor_allow_duplicate)
  404. {
  405. SECStatus ret;
  406. size_t i;
  407. for (i = 0; i < num_attrs; i++) {
  408. char *name, *value;
  409. const char *p;
  410. size_t j;
  411. p = attrs[i].name;
  412. /* The attribute must not be empty. */
  413. if (*p == '\0') {
  414. return SECFailure;
  415. }
  416. /* Check that the name doesn't contain invalid character. */
  417. for (; *p != '\0'; p++) {
  418. if (strchr(PK11URI_ATTR_NM_CHAR, *p) == NULL) {
  419. return SECFailure;
  420. }
  421. }
  422. name = PORT_ArenaStrdup(dest_attrs->arena, attrs[i].name);
  423. if (name == NULL) {
  424. return SECFailure;
  425. }
  426. value = PORT_ArenaStrdup(dest_attrs->arena, attrs[i].value);
  427. if (value == NULL) {
  428. return SECFailure;
  429. }
  430. for (j = 0; j < num_attr_names; j++) {
  431. if (strcmp(name, attr_names[j]) == 0) {
  432. break;
  433. }
  434. }
  435. if (j < num_attr_names) {
  436. /* Named attribute. */
  437. ret = pk11uri_InsertToAttributeList(dest_attrs,
  438. name, value,
  439. compare_name,
  440. allow_duplicate);
  441. if (ret != SECSuccess) {
  442. return ret;
  443. }
  444. } else {
  445. /* Vendor attribute. */
  446. ret = pk11uri_InsertToAttributeList(dest_vattrs,
  447. name, value,
  448. strcmp,
  449. vendor_allow_duplicate);
  450. if (ret != SECSuccess) {
  451. return ret;
  452. }
  453. }
  454. }
  455. return SECSuccess;
  456. }
  457. PK11URI *
  458. PK11URI_CreateURI(const PK11URIAttribute *pattrs,
  459. size_t num_pattrs,
  460. const PK11URIAttribute *qattrs,
  461. size_t num_qattrs)
  462. {
  463. PK11URI *result;
  464. SECStatus ret;
  465. result = pk11uri_AllocURI();
  466. ret = pk11uri_InsertAttributes(&result->pattrs, &result->vpattrs,
  467. pattrs, num_pattrs,
  468. pattr_names, PR_ARRAY_SIZE(pattr_names),
  469. pk11uri_ComparePathAttributeName,
  470. PR_FALSE, PR_FALSE);
  471. if (ret != SECSuccess) {
  472. goto fail;
  473. }
  474. ret = pk11uri_InsertAttributes(&result->qattrs, &result->vqattrs,
  475. qattrs, num_qattrs,
  476. qattr_names, PR_ARRAY_SIZE(qattr_names),
  477. pk11uri_CompareQueryAttributeName,
  478. PR_FALSE, PR_TRUE);
  479. if (ret != SECSuccess) {
  480. goto fail;
  481. }
  482. return result;
  483. fail:
  484. PK11URI_DestroyURI(result);
  485. return NULL;
  486. }
  487. /* Parsing. */
  488. static SECStatus
  489. pk11uri_ParseAttributes(const char **string,
  490. const char *stop_chars,
  491. int separator,
  492. const char *accept_chars,
  493. const char **attr_names, size_t num_attr_names,
  494. PK11URIAttributeList *attrs,
  495. PK11URIAttributeList *vattrs,
  496. PK11URIAttributeCompareNameFunc compare_name,
  497. PRBool allow_duplicate,
  498. PRBool vendor_allow_duplicate)
  499. {
  500. const char *p = *string;
  501. for (; *p != '\0'; p++) {
  502. const char *name_start, *name_end, *value_start, *value_end;
  503. size_t name_length, value_length, i;
  504. SECStatus ret;
  505. if (strchr(stop_chars, *p) != NULL) {
  506. break;
  507. }
  508. for (name_start = p; *p != '=' && *p != '\0'; p++) {
  509. if (strchr(PK11URI_ATTR_NM_CHAR, *p) != NULL)
  510. continue;
  511. return SECFailure;
  512. }
  513. if (*p == '\0') {
  514. return SECFailure;
  515. }
  516. name_end = p++;
  517. /* The attribute name must not be empty. */
  518. if (name_end == name_start) {
  519. return SECFailure;
  520. }
  521. for (value_start = p; *p != separator && *p != '\0'; p++) {
  522. if (strchr(stop_chars, *p) != NULL) {
  523. break;
  524. }
  525. if (strchr(accept_chars, *p) != NULL) {
  526. continue;
  527. }
  528. if (*p == '%') {
  529. const char ch2 = *++p;
  530. if (strchr(PK11URI_HEXDIG, ch2) != NULL) {
  531. const char ch3 = *++p;
  532. if (strchr(PK11URI_HEXDIG, ch3) != NULL)
  533. continue;
  534. }
  535. }
  536. return SECFailure;
  537. }
  538. value_end = p;
  539. name_length = name_end - name_start;
  540. value_length = value_end - value_start;
  541. for (i = 0; i < num_attr_names; i++) {
  542. if (name_length == strlen(attr_names[i]) &&
  543. memcmp(name_start, attr_names[i], name_length) == 0) {
  544. break;
  545. }
  546. }
  547. if (i < num_attr_names) {
  548. /* Named attribute. */
  549. ret = pk11uri_InsertToAttributeListEscaped(attrs,
  550. name_start, name_length,
  551. value_start, value_length,
  552. compare_name,
  553. allow_duplicate);
  554. if (ret != SECSuccess) {
  555. return ret;
  556. }
  557. } else {
  558. /* Vendor attribute. */
  559. ret = pk11uri_InsertToAttributeListEscaped(vattrs,
  560. name_start, name_length,
  561. value_start, value_length,
  562. strcmp,
  563. vendor_allow_duplicate);
  564. if (ret != SECSuccess) {
  565. return ret;
  566. }
  567. }
  568. if (*p == '?' || *p == '\0') {
  569. break;
  570. }
  571. }
  572. *string = p;
  573. return SECSuccess;
  574. }
  575. PK11URI *
  576. PK11URI_ParseURI(const char *string)
  577. {
  578. PK11URI *result;
  579. const char *p = string;
  580. SECStatus ret;
  581. if (PORT_Strncasecmp("pkcs11:", p, 7) != 0) {
  582. return NULL;
  583. }
  584. p += 7;
  585. result = pk11uri_AllocURI();
  586. if (result == NULL) {
  587. return NULL;
  588. }
  589. /* Parse the path component and its attributes. */
  590. ret = pk11uri_ParseAttributes(&p, "?", ';', PK11URI_PCHAR,
  591. pattr_names, PR_ARRAY_SIZE(pattr_names),
  592. &result->pattrs, &result->vpattrs,
  593. pk11uri_ComparePathAttributeName,
  594. PR_FALSE, PR_FALSE);
  595. if (ret != SECSuccess) {
  596. goto fail;
  597. }
  598. /* Parse the query component and its attributes. */
  599. if (*p == '?') {
  600. p++;
  601. ret = pk11uri_ParseAttributes(&p, "", '&', PK11URI_QCHAR,
  602. qattr_names, PR_ARRAY_SIZE(qattr_names),
  603. &result->qattrs, &result->vqattrs,
  604. pk11uri_CompareQueryAttributeName,
  605. PR_FALSE, PR_TRUE);
  606. if (ret != SECSuccess) {
  607. goto fail;
  608. }
  609. }
  610. return result;
  611. fail:
  612. PK11URI_DestroyURI(result);
  613. return NULL;
  614. }
  615. /* Formatting. */
  616. char *
  617. PK11URI_FormatURI(PLArenaPool *arena, PK11URI *uri)
  618. {
  619. PK11URIBuffer buffer;
  620. SECStatus ret;
  621. char *result = NULL;
  622. pk11uri_InitBuffer(&buffer, arena);
  623. ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"pkcs11:", 7);
  624. if (ret != SECSuccess)
  625. goto fail;
  626. ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->pattrs, ';', PK11URI_PCHAR);
  627. if (ret != SECSuccess) {
  628. goto fail;
  629. }
  630. if (uri->pattrs.num_attrs > 0 && uri->vpattrs.num_attrs > 0) {
  631. ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)";", 1);
  632. if (ret != SECSuccess) {
  633. goto fail;
  634. }
  635. }
  636. ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->vpattrs, ';',
  637. PK11URI_PCHAR);
  638. if (ret != SECSuccess) {
  639. goto fail;
  640. }
  641. if (uri->qattrs.num_attrs > 0 || uri->vqattrs.num_attrs > 0) {
  642. ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"?", 1);
  643. if (ret != SECSuccess) {
  644. goto fail;
  645. }
  646. }
  647. ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->qattrs, '&', PK11URI_QCHAR);
  648. if (ret != SECSuccess) {
  649. goto fail;
  650. }
  651. if (uri->qattrs.num_attrs > 0 && uri->vqattrs.num_attrs > 0) {
  652. ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"&", 1);
  653. if (ret != SECSuccess) {
  654. goto fail;
  655. }
  656. }
  657. ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->vqattrs, '&',
  658. PK11URI_QCHAR);
  659. if (ret != SECSuccess) {
  660. goto fail;
  661. }
  662. ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"\0", 1);
  663. if (ret != SECSuccess) {
  664. goto fail;
  665. }
  666. result = buffer.data;
  667. buffer.data = NULL;
  668. fail:
  669. pk11uri_DestroyBuffer(&buffer);
  670. return result;
  671. }
  672. /* Deallocating. */
  673. void
  674. PK11URI_DestroyURI(PK11URI *uri)
  675. {
  676. pk11uri_DestroyAttributeList(&uri->pattrs);
  677. pk11uri_DestroyAttributeList(&uri->vpattrs);
  678. pk11uri_DestroyAttributeList(&uri->qattrs);
  679. pk11uri_DestroyAttributeList(&uri->vqattrs);
  680. PORT_FreeArena(uri->arena, PR_FALSE);
  681. }
  682. /* Accessors. */
  683. static const char *
  684. pk11uri_GetAttribute(PK11URIAttributeList *attrs,
  685. PK11URIAttributeList *vattrs,
  686. const char *name)
  687. {
  688. size_t i;
  689. for (i = 0; i < attrs->num_attrs; i++) {
  690. if (strcmp(name, attrs->attrs[i].name) == 0) {
  691. return attrs->attrs[i].value;
  692. }
  693. }
  694. for (i = 0; i < vattrs->num_attrs; i++) {
  695. if (strcmp(name, vattrs->attrs[i].name) == 0) {
  696. return vattrs->attrs[i].value;
  697. }
  698. }
  699. return NULL;
  700. }
  701. const char *
  702. PK11URI_GetPathAttribute(PK11URI *uri, const char *name)
  703. {
  704. return pk11uri_GetAttribute(&uri->pattrs, &uri->vpattrs, name);
  705. }
  706. const char *
  707. PK11URI_GetQueryAttribute(PK11URI *uri, const char *name)
  708. {
  709. return pk11uri_GetAttribute(&uri->qattrs, &uri->vqattrs, name);
  710. }