123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "pkcs11.h"
- #include "pkcs11uri.h"
- #include "plarena.h"
- #include "prprf.h"
- #include "secport.h"
- /* Character sets used in the ABNF rules in RFC7512. */
- #define PK11URI_DIGIT "0123456789"
- #define PK11URI_ALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
- #define PK11URI_HEXDIG PK11URI_DIGIT "abcdefABCDEF"
- #define PK11URI_UNRESERVED PK11URI_ALPHA PK11URI_DIGIT "-._~"
- #define PK11URI_RES_AVAIL ":[]@!$'()*+,="
- #define PK11URI_PATH_RES_AVAIL PK11URI_RES_AVAIL "&"
- #define PK11URI_QUERY_RES_AVAIL PK11URI_RES_AVAIL "/?|"
- #define PK11URI_ATTR_NM_CHAR PK11URI_ALPHA PK11URI_DIGIT "-_"
- #define PK11URI_PCHAR PK11URI_UNRESERVED PK11URI_PATH_RES_AVAIL
- #define PK11URI_QCHAR PK11URI_UNRESERVED PK11URI_QUERY_RES_AVAIL
- /* Path attributes defined in RFC7512. */
- static const char *pattr_names[] = {
- PK11URI_PATTR_TOKEN,
- PK11URI_PATTR_MANUFACTURER,
- PK11URI_PATTR_SERIAL,
- PK11URI_PATTR_MODEL,
- PK11URI_PATTR_LIBRARY_MANUFACTURER,
- PK11URI_PATTR_LIBRARY_DESCRIPTION,
- PK11URI_PATTR_LIBRARY_VERSION,
- PK11URI_PATTR_OBJECT,
- PK11URI_PATTR_TYPE,
- PK11URI_PATTR_ID,
- PK11URI_PATTR_SLOT_MANUFACTURER,
- PK11URI_PATTR_SLOT_DESCRIPTION,
- PK11URI_PATTR_SLOT_ID
- };
- /* Query attributes defined in RFC7512. */
- static const char *qattr_names[] = {
- PK11URI_QATTR_PIN_SOURCE,
- PK11URI_QATTR_PIN_VALUE,
- PK11URI_QATTR_MODULE_NAME,
- PK11URI_QATTR_MODULE_PATH
- };
- struct PK11URIBufferStr {
- PLArenaPool *arena;
- char *data;
- size_t size;
- size_t allocated;
- };
- typedef struct PK11URIBufferStr PK11URIBuffer;
- struct PK11URIAttributeListEntryStr {
- char *name;
- char *value;
- };
- typedef struct PK11URIAttributeListEntryStr PK11URIAttributeListEntry;
- struct PK11URIAttributeListStr {
- PLArenaPool *arena;
- PK11URIAttributeListEntry *attrs;
- size_t num_attrs;
- };
- typedef struct PK11URIAttributeListStr PK11URIAttributeList;
- struct PK11URIStr {
- PLArenaPool *arena;
- PK11URIAttributeList pattrs;
- PK11URIAttributeList vpattrs;
- PK11URIAttributeList qattrs;
- PK11URIAttributeList vqattrs;
- };
- #define PK11URI_ARENA_SIZE 1024
- typedef int (*PK11URIAttributeCompareNameFunc)(const char *a, const char *b);
- /* This belongs in secport.h */
- #define PORT_ArenaGrowArray(poolp, oldptr, type, oldnum, newnum) \
- (type *)PORT_ArenaGrow((poolp), (oldptr), \
- (oldnum) * sizeof(type), (newnum) * sizeof(type))
- #define PORT_ReallocArray(oldptr, type, newnum) \
- (type *)PORT_Realloc((oldptr), (newnum) * sizeof(type))
- /* Functions for resizable buffer. */
- static SECStatus
- pk11uri_AppendBuffer(PK11URIBuffer *buffer, const unsigned char *data,
- size_t size)
- {
- /* Check overflow. */
- if (buffer->size + size < buffer->size)
- return SECFailure;
- if (buffer->size + size > buffer->allocated) {
- size_t allocated = buffer->allocated * 2 + size;
- if (allocated < buffer->allocated)
- return SECFailure;
- if (buffer->arena)
- buffer->data = PORT_ArenaGrow(buffer->arena, buffer->data,
- buffer->allocated, allocated);
- else
- buffer->data = PORT_Realloc(buffer->data, allocated);
- if (buffer->data == NULL)
- return SECFailure;
- buffer->allocated = allocated;
- }
- memcpy(&buffer->data[buffer->size], data, size);
- buffer->size += size;
- return SECSuccess;
- }
- static void
- pk11uri_InitBuffer(PK11URIBuffer *buffer, PLArenaPool *arena)
- {
- memset(buffer, 0, sizeof(PK11URIBuffer));
- buffer->arena = arena;
- }
- static void
- pk11uri_DestroyBuffer(PK11URIBuffer *buffer)
- {
- if (buffer->arena == NULL) {
- PORT_Free(buffer->data);
- }
- }
- /* URI encoding functions. */
- static char *
- pk11uri_Escape(PLArenaPool *arena, const char *value, size_t length,
- const char *available)
- {
- PK11URIBuffer buffer;
- const char *p;
- unsigned char buf[4];
- char *result = NULL;
- SECStatus ret;
- pk11uri_InitBuffer(&buffer, arena);
- for (p = value; p < value + length; p++) {
- if (strchr(available, *p) == NULL) {
- if (PR_snprintf((char *)buf, sizeof(buf), "%%%02X", *p) == (PRUint32)-1) {
- goto fail;
- }
- ret = pk11uri_AppendBuffer(&buffer, buf, 3);
- if (ret != SECSuccess) {
- goto fail;
- }
- } else {
- ret = pk11uri_AppendBuffer(&buffer, (const unsigned char *)p, 1);
- if (ret != SECSuccess) {
- goto fail;
- }
- }
- }
- buf[0] = '\0';
- ret = pk11uri_AppendBuffer(&buffer, buf, 1);
- if (ret != SECSuccess) {
- goto fail;
- }
- /* Steal the memory allocated in buffer. */
- result = buffer.data;
- buffer.data = NULL;
- fail:
- pk11uri_DestroyBuffer(&buffer);
- return result;
- }
- static char *
- pk11uri_Unescape(PLArenaPool *arena, const char *value, size_t length)
- {
- PK11URIBuffer buffer;
- const char *p;
- unsigned char buf[1];
- char *result = NULL;
- SECStatus ret;
- pk11uri_InitBuffer(&buffer, arena);
- for (p = value; p < value + length; p++) {
- if (*p == '%') {
- int c;
- size_t i;
- p++;
- for (c = 0, i = 0; i < 2; i++) {
- int h = *(p + i);
- if ('0' <= h && h <= '9') {
- c = (c << 4) | (h - '0');
- } else if ('a' <= h && h <= 'f') {
- c = (c << 4) | (h - 'a' + 10);
- } else if ('A' <= h && h <= 'F') {
- c = (c << 4) | (h - 'A' + 10);
- } else {
- break;
- }
- }
- if (i != 2) {
- goto fail;
- }
- p++;
- buf[0] = c;
- } else {
- buf[0] = *p;
- }
- ret = pk11uri_AppendBuffer(&buffer, buf, 1);
- if (ret != SECSuccess) {
- goto fail;
- }
- }
- buf[0] = '\0';
- ret = pk11uri_AppendBuffer(&buffer, buf, 1);
- if (ret != SECSuccess) {
- goto fail;
- }
- result = buffer.data;
- buffer.data = NULL;
- fail:
- pk11uri_DestroyBuffer(&buffer);
- return result;
- }
- /* Functions for manipulating attributes array. */
- /* Compare two attribute names by the array index in attr_names. Both
- * attribute names must be present in attr_names, otherwise it is a
- * programming error. */
- static int
- pk11uri_CompareByPosition(const char *a, const char *b,
- const char **attr_names, size_t num_attr_names)
- {
- size_t i, j;
- for (i = 0; i < num_attr_names; i++) {
- if (strcmp(a, attr_names[i]) == 0) {
- break;
- }
- }
- PR_ASSERT(i < num_attr_names);
- for (j = 0; j < num_attr_names; j++) {
- if (strcmp(b, attr_names[j]) == 0) {
- break;
- }
- }
- PR_ASSERT(j < num_attr_names);
- return i - j;
- }
- /* Those pk11uri_Compare{Path,Query}AttributeName functions are used
- * to reorder attributes when inserting. */
- static int
- pk11uri_ComparePathAttributeName(const char *a, const char *b)
- {
- return pk11uri_CompareByPosition(a, b, pattr_names, PR_ARRAY_SIZE(pattr_names));
- }
- static int
- pk11uri_CompareQueryAttributeName(const char *a, const char *b)
- {
- return pk11uri_CompareByPosition(a, b, qattr_names, PR_ARRAY_SIZE(qattr_names));
- }
- static SECStatus
- pk11uri_InsertToAttributeList(PK11URIAttributeList *attrs,
- char *name, char *value,
- PK11URIAttributeCompareNameFunc compare_name,
- PRBool allow_duplicate)
- {
- size_t i;
- if (attrs->arena) {
- attrs->attrs = PORT_ArenaGrowArray(attrs->arena, attrs->attrs,
- PK11URIAttributeListEntry,
- attrs->num_attrs,
- attrs->num_attrs + 1);
- } else {
- attrs->attrs = PORT_ReallocArray(attrs->attrs,
- PK11URIAttributeListEntry,
- attrs->num_attrs + 1);
- }
- if (attrs->attrs == NULL) {
- return SECFailure;
- }
- for (i = 0; i < attrs->num_attrs; i++) {
- if (!allow_duplicate && strcmp(name, attrs->attrs[i].name) == 0) {
- return SECFailure;
- }
- if (compare_name(name, attrs->attrs[i].name) < 0) {
- memmove(&attrs->attrs[i + 1], &attrs->attrs[i],
- sizeof(PK11URIAttributeListEntry) * (attrs->num_attrs - i));
- break;
- }
- }
- attrs->attrs[i].name = name;
- attrs->attrs[i].value = value;
- attrs->num_attrs++;
- return SECSuccess;
- }
- static SECStatus
- pk11uri_InsertToAttributeListEscaped(PK11URIAttributeList *attrs,
- const char *name, size_t name_size,
- const char *value, size_t value_size,
- PK11URIAttributeCompareNameFunc compare_name,
- PRBool allow_duplicate)
- {
- char *name_copy = NULL, *value_copy = NULL;
- SECStatus ret;
- if (attrs->arena) {
- name_copy = PORT_ArenaNewArray(attrs->arena, char, name_size + 1);
- } else {
- name_copy = PORT_Alloc(name_size + 1);
- }
- if (name_copy == NULL) {
- goto fail;
- }
- memcpy(name_copy, name, name_size);
- name_copy[name_size] = '\0';
- value_copy = pk11uri_Unescape(attrs->arena, value, value_size);
- if (value_copy == NULL) {
- goto fail;
- }
- ret = pk11uri_InsertToAttributeList(attrs, name_copy, value_copy, compare_name,
- allow_duplicate);
- if (ret != SECSuccess) {
- goto fail;
- }
- return ret;
- fail:
- if (attrs->arena == NULL) {
- PORT_Free(name_copy);
- PORT_Free(value_copy);
- }
- return SECFailure;
- }
- static void
- pk11uri_InitAttributeList(PK11URIAttributeList *attrs, PLArenaPool *arena)
- {
- memset(attrs, 0, sizeof(PK11URIAttributeList));
- attrs->arena = arena;
- }
- static void
- pk11uri_DestroyAttributeList(PK11URIAttributeList *attrs)
- {
- if (attrs->arena == NULL) {
- size_t i;
- for (i = 0; i < attrs->num_attrs; i++) {
- PORT_Free(attrs->attrs[i].name);
- PORT_Free(attrs->attrs[i].value);
- }
- PORT_Free(attrs->attrs);
- }
- }
- static SECStatus
- pk11uri_AppendAttributeListToBuffer(PK11URIBuffer *buffer,
- PK11URIAttributeList *attrs,
- int separator,
- const char *unescaped)
- {
- size_t i;
- SECStatus ret;
- for (i = 0; i < attrs->num_attrs; i++) {
- unsigned char sep[1];
- char *escaped;
- PK11URIAttributeListEntry *attr = &attrs->attrs[i];
- if (i > 0) {
- sep[0] = separator;
- ret = pk11uri_AppendBuffer(buffer, sep, 1);
- if (ret != SECSuccess) {
- return ret;
- }
- }
- ret = pk11uri_AppendBuffer(buffer, (unsigned char *)attr->name,
- strlen(attr->name));
- if (ret != SECSuccess) {
- return ret;
- }
- sep[0] = '=';
- ret = pk11uri_AppendBuffer(buffer, sep, 1);
- if (ret != SECSuccess) {
- return ret;
- }
- escaped = pk11uri_Escape(buffer->arena, attr->value, strlen(attr->value),
- unescaped);
- if (escaped == NULL) {
- return ret;
- }
- ret = pk11uri_AppendBuffer(buffer, (unsigned char *)escaped,
- strlen(escaped));
- if (buffer->arena == NULL) {
- PORT_Free(escaped);
- }
- if (ret != SECSuccess) {
- return ret;
- }
- }
- return SECSuccess;
- }
- /* Creation of PK11URI object. */
- static PK11URI *
- pk11uri_AllocURI(void)
- {
- PLArenaPool *arena;
- PK11URI *result;
- arena = PORT_NewArena(PK11URI_ARENA_SIZE);
- if (arena == NULL) {
- return NULL;
- }
- result = PORT_ArenaZAlloc(arena, sizeof(PK11URI));
- if (result == NULL) {
- PORT_FreeArena(arena, PR_FALSE);
- return NULL;
- }
- result->arena = arena;
- pk11uri_InitAttributeList(&result->pattrs, arena);
- pk11uri_InitAttributeList(&result->vpattrs, arena);
- pk11uri_InitAttributeList(&result->qattrs, arena);
- pk11uri_InitAttributeList(&result->vqattrs, arena);
- return result;
- }
- static SECStatus
- pk11uri_InsertAttributes(PK11URIAttributeList *dest_attrs,
- PK11URIAttributeList *dest_vattrs,
- const PK11URIAttribute *attrs,
- size_t num_attrs,
- const char **attr_names,
- size_t num_attr_names,
- PK11URIAttributeCompareNameFunc compare_name,
- PRBool allow_duplicate,
- PRBool vendor_allow_duplicate)
- {
- SECStatus ret;
- size_t i;
- for (i = 0; i < num_attrs; i++) {
- char *name, *value;
- const char *p;
- size_t j;
- p = attrs[i].name;
- /* The attribute must not be empty. */
- if (*p == '\0') {
- return SECFailure;
- }
- /* Check that the name doesn't contain invalid character. */
- for (; *p != '\0'; p++) {
- if (strchr(PK11URI_ATTR_NM_CHAR, *p) == NULL) {
- return SECFailure;
- }
- }
- name = PORT_ArenaStrdup(dest_attrs->arena, attrs[i].name);
- if (name == NULL) {
- return SECFailure;
- }
- value = PORT_ArenaStrdup(dest_attrs->arena, attrs[i].value);
- if (value == NULL) {
- return SECFailure;
- }
- for (j = 0; j < num_attr_names; j++) {
- if (strcmp(name, attr_names[j]) == 0) {
- break;
- }
- }
- if (j < num_attr_names) {
- /* Named attribute. */
- ret = pk11uri_InsertToAttributeList(dest_attrs,
- name, value,
- compare_name,
- allow_duplicate);
- if (ret != SECSuccess) {
- return ret;
- }
- } else {
- /* Vendor attribute. */
- ret = pk11uri_InsertToAttributeList(dest_vattrs,
- name, value,
- strcmp,
- vendor_allow_duplicate);
- if (ret != SECSuccess) {
- return ret;
- }
- }
- }
- return SECSuccess;
- }
- PK11URI *
- PK11URI_CreateURI(const PK11URIAttribute *pattrs,
- size_t num_pattrs,
- const PK11URIAttribute *qattrs,
- size_t num_qattrs)
- {
- PK11URI *result;
- SECStatus ret;
- result = pk11uri_AllocURI();
- ret = pk11uri_InsertAttributes(&result->pattrs, &result->vpattrs,
- pattrs, num_pattrs,
- pattr_names, PR_ARRAY_SIZE(pattr_names),
- pk11uri_ComparePathAttributeName,
- PR_FALSE, PR_FALSE);
- if (ret != SECSuccess) {
- goto fail;
- }
- ret = pk11uri_InsertAttributes(&result->qattrs, &result->vqattrs,
- qattrs, num_qattrs,
- qattr_names, PR_ARRAY_SIZE(qattr_names),
- pk11uri_CompareQueryAttributeName,
- PR_FALSE, PR_TRUE);
- if (ret != SECSuccess) {
- goto fail;
- }
- return result;
- fail:
- PK11URI_DestroyURI(result);
- return NULL;
- }
- /* Parsing. */
- static SECStatus
- pk11uri_ParseAttributes(const char **string,
- const char *stop_chars,
- int separator,
- const char *accept_chars,
- const char **attr_names, size_t num_attr_names,
- PK11URIAttributeList *attrs,
- PK11URIAttributeList *vattrs,
- PK11URIAttributeCompareNameFunc compare_name,
- PRBool allow_duplicate,
- PRBool vendor_allow_duplicate)
- {
- const char *p = *string;
- for (; *p != '\0'; p++) {
- const char *name_start, *name_end, *value_start, *value_end;
- size_t name_length, value_length, i;
- SECStatus ret;
- if (strchr(stop_chars, *p) != NULL) {
- break;
- }
- for (name_start = p; *p != '=' && *p != '\0'; p++) {
- if (strchr(PK11URI_ATTR_NM_CHAR, *p) != NULL)
- continue;
- return SECFailure;
- }
- if (*p == '\0') {
- return SECFailure;
- }
- name_end = p++;
- /* The attribute name must not be empty. */
- if (name_end == name_start) {
- return SECFailure;
- }
- for (value_start = p; *p != separator && *p != '\0'; p++) {
- if (strchr(stop_chars, *p) != NULL) {
- break;
- }
- if (strchr(accept_chars, *p) != NULL) {
- continue;
- }
- if (*p == '%') {
- const char ch2 = *++p;
- if (strchr(PK11URI_HEXDIG, ch2) != NULL) {
- const char ch3 = *++p;
- if (strchr(PK11URI_HEXDIG, ch3) != NULL)
- continue;
- }
- }
- return SECFailure;
- }
- value_end = p;
- name_length = name_end - name_start;
- value_length = value_end - value_start;
- for (i = 0; i < num_attr_names; i++) {
- if (name_length == strlen(attr_names[i]) &&
- memcmp(name_start, attr_names[i], name_length) == 0) {
- break;
- }
- }
- if (i < num_attr_names) {
- /* Named attribute. */
- ret = pk11uri_InsertToAttributeListEscaped(attrs,
- name_start, name_length,
- value_start, value_length,
- compare_name,
- allow_duplicate);
- if (ret != SECSuccess) {
- return ret;
- }
- } else {
- /* Vendor attribute. */
- ret = pk11uri_InsertToAttributeListEscaped(vattrs,
- name_start, name_length,
- value_start, value_length,
- strcmp,
- vendor_allow_duplicate);
- if (ret != SECSuccess) {
- return ret;
- }
- }
- if (*p == '?' || *p == '\0') {
- break;
- }
- }
- *string = p;
- return SECSuccess;
- }
- PK11URI *
- PK11URI_ParseURI(const char *string)
- {
- PK11URI *result;
- const char *p = string;
- SECStatus ret;
- if (PORT_Strncasecmp("pkcs11:", p, 7) != 0) {
- return NULL;
- }
- p += 7;
- result = pk11uri_AllocURI();
- if (result == NULL) {
- return NULL;
- }
- /* Parse the path component and its attributes. */
- ret = pk11uri_ParseAttributes(&p, "?", ';', PK11URI_PCHAR,
- pattr_names, PR_ARRAY_SIZE(pattr_names),
- &result->pattrs, &result->vpattrs,
- pk11uri_ComparePathAttributeName,
- PR_FALSE, PR_FALSE);
- if (ret != SECSuccess) {
- goto fail;
- }
- /* Parse the query component and its attributes. */
- if (*p == '?') {
- p++;
- ret = pk11uri_ParseAttributes(&p, "", '&', PK11URI_QCHAR,
- qattr_names, PR_ARRAY_SIZE(qattr_names),
- &result->qattrs, &result->vqattrs,
- pk11uri_CompareQueryAttributeName,
- PR_FALSE, PR_TRUE);
- if (ret != SECSuccess) {
- goto fail;
- }
- }
- return result;
- fail:
- PK11URI_DestroyURI(result);
- return NULL;
- }
- /* Formatting. */
- char *
- PK11URI_FormatURI(PLArenaPool *arena, PK11URI *uri)
- {
- PK11URIBuffer buffer;
- SECStatus ret;
- char *result = NULL;
- pk11uri_InitBuffer(&buffer, arena);
- ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"pkcs11:", 7);
- if (ret != SECSuccess)
- goto fail;
- ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->pattrs, ';', PK11URI_PCHAR);
- if (ret != SECSuccess) {
- goto fail;
- }
- if (uri->pattrs.num_attrs > 0 && uri->vpattrs.num_attrs > 0) {
- ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)";", 1);
- if (ret != SECSuccess) {
- goto fail;
- }
- }
- ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->vpattrs, ';',
- PK11URI_PCHAR);
- if (ret != SECSuccess) {
- goto fail;
- }
- if (uri->qattrs.num_attrs > 0 || uri->vqattrs.num_attrs > 0) {
- ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"?", 1);
- if (ret != SECSuccess) {
- goto fail;
- }
- }
- ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->qattrs, '&', PK11URI_QCHAR);
- if (ret != SECSuccess) {
- goto fail;
- }
- if (uri->qattrs.num_attrs > 0 && uri->vqattrs.num_attrs > 0) {
- ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"&", 1);
- if (ret != SECSuccess) {
- goto fail;
- }
- }
- ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->vqattrs, '&',
- PK11URI_QCHAR);
- if (ret != SECSuccess) {
- goto fail;
- }
- ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"\0", 1);
- if (ret != SECSuccess) {
- goto fail;
- }
- result = buffer.data;
- buffer.data = NULL;
- fail:
- pk11uri_DestroyBuffer(&buffer);
- return result;
- }
- /* Deallocating. */
- void
- PK11URI_DestroyURI(PK11URI *uri)
- {
- pk11uri_DestroyAttributeList(&uri->pattrs);
- pk11uri_DestroyAttributeList(&uri->vpattrs);
- pk11uri_DestroyAttributeList(&uri->qattrs);
- pk11uri_DestroyAttributeList(&uri->vqattrs);
- PORT_FreeArena(uri->arena, PR_FALSE);
- }
- /* Accessors. */
- static const char *
- pk11uri_GetAttribute(PK11URIAttributeList *attrs,
- PK11URIAttributeList *vattrs,
- const char *name)
- {
- size_t i;
- for (i = 0; i < attrs->num_attrs; i++) {
- if (strcmp(name, attrs->attrs[i].name) == 0) {
- return attrs->attrs[i].value;
- }
- }
- for (i = 0; i < vattrs->num_attrs; i++) {
- if (strcmp(name, vattrs->attrs[i].name) == 0) {
- return vattrs->attrs[i].value;
- }
- }
- return NULL;
- }
- const char *
- PK11URI_GetPathAttribute(PK11URI *uri, const char *name)
- {
- return pk11uri_GetAttribute(&uri->pattrs, &uri->vpattrs, name);
- }
- const char *
- PK11URI_GetQueryAttribute(PK11URI *uri, const char *name)
- {
- return pk11uri_GetAttribute(&uri->qattrs, &uri->vqattrs, name);
- }
|