LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/x509 - x509_dn.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 204 251 81.3 %
Date: 2020-10-30 04:50:48 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2013-2016 Nikos Mavrogiannopoulos
       3             :  * Copyright (C) 2016 Red Hat, Inc.
       4             :  *
       5             :  * This file is part of GnuTLS.
       6             :  *
       7             :  * The GnuTLS is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public License
       9             :  * as published by the Free Software Foundation; either version 2.1 of
      10             :  * the License, or (at your option) any later version.
      11             :  *
      12             :  * This library is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public License
      18             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      19             :  *
      20             :  */
      21             : 
      22             : /* This file contains functions to handle X.509 certificate generation.
      23             :  */
      24             : 
      25             : #include "gnutls_int.h"
      26             : 
      27             : #include <datum.h>
      28             : #include <global.h>
      29             : #include "errors.h"
      30             : #include <common.h>
      31             : #include <x509.h>
      32             : #include <x509_b64.h>
      33             : #include <c-ctype.h>
      34             : 
      35             : typedef int (*set_dn_func) (void *, const char *oid, unsigned int raw_flag,
      36             :                             const void *name, unsigned int name_size);
      37             : 
      38             : static
      39         121 : int dn_attr_crt_set(set_dn_func f, void *crt, const gnutls_datum_t * name,
      40             :                     const gnutls_datum_t * val, unsigned is_raw)
      41             : {
      42         121 :         char _oid[MAX_OID_SIZE];
      43         121 :         gnutls_datum_t tmp;
      44         121 :         const char *oid;
      45         121 :         int ret;
      46         121 :         unsigned i,j;
      47             : 
      48         121 :         if (name->size == 0 || val->size == 0)
      49           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
      50             : 
      51         121 :         if (c_isdigit(name->data[0]) != 0) {
      52          11 :                 if (name->size >= sizeof(_oid))
      53           0 :                         return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
      54             : 
      55          11 :                 memcpy(_oid, name->data, name->size);
      56          11 :                 _oid[name->size] = 0;
      57             : 
      58          11 :                 oid = _oid;
      59             : 
      60          11 :                 if (gnutls_x509_dn_oid_known(oid) == 0 && !is_raw) {
      61           0 :                         _gnutls_debug_log("Unknown OID: '%s'\n", oid);
      62           0 :                         return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
      63             :                 }
      64             :         } else {
      65         110 :                 oid =
      66         110 :                     _gnutls_ldap_string_to_oid((char *) name->data,
      67             :                                                name->size);
      68             :         }
      69             : 
      70         121 :         if (oid == NULL) {
      71           4 :                 _gnutls_debug_log("Unknown DN attribute: '%.*s'\n",
      72             :                                   (int) name->size, name->data);
      73           4 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
      74             :         }
      75             : 
      76         117 :         if (is_raw) {
      77           3 :                 gnutls_datum_t hex = {val->data+1, val->size-1};
      78             : 
      79           3 :                 ret = gnutls_hex_decode2(&hex, &tmp);
      80           3 :                 if (ret < 0)
      81           1 :                         return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
      82             :         } else {
      83         114 :                 tmp.size = val->size;
      84         114 :                 tmp.data = gnutls_malloc(tmp.size+1);
      85         114 :                 if (tmp.data == NULL) {
      86           0 :                         return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
      87             :                 }
      88             : 
      89             :                 /* unescape */
      90        1218 :                 for (j=i=0;i<tmp.size;i++) {
      91        1105 :                         if (1+j!=val->size && val->data[j] == '\\') {
      92          34 :                                 if (val->data[j+1] == ',' || val->data[j+1] == '#' ||
      93           7 :                                     val->data[j+1] == ' ' || val->data[j+1] == '+' ||
      94           5 :                                     val->data[j+1] == '"' || val->data[j+1] == '<' ||
      95           3 :                                     val->data[j+1] == '>' || val->data[j+1] == ';' ||
      96           1 :                                     val->data[j+1] == '\\' || val->data[j+1] == '=') {
      97          33 :                                         tmp.data[i] = val->data[j+1];
      98          33 :                                         j+=2;
      99          33 :                                         tmp.size--;
     100             :                                 } else {
     101           1 :                                         ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     102           1 :                                         goto fail;
     103             :                                 }
     104             :                         } else {
     105        1071 :                                 tmp.data[i] = val->data[j++];
     106             :                         }
     107             :                 }
     108         113 :                 tmp.data[tmp.size] = 0;
     109             :         }
     110             : 
     111         115 :         ret = f(crt, oid, is_raw, tmp.data, tmp.size);
     112         115 :         if (ret < 0) {
     113           0 :                 gnutls_assert();
     114           0 :                 goto fail;
     115             :         }
     116             : 
     117             :         ret = 0;
     118         116 :  fail:
     119         116 :         gnutls_free(tmp.data);
     120         116 :         return ret;
     121             : }
     122             : 
     123         125 : static int read_attr_and_val(const char **ptr,
     124             :                              gnutls_datum_t *name, gnutls_datum_t *val,
     125             :                              unsigned *is_raw)
     126             : {
     127         125 :         const unsigned char *p = (void *) *ptr;
     128             : 
     129         125 :         *is_raw = 0;
     130             : 
     131             :         /* skip any space */
     132         128 :         while (c_isspace(*p))
     133           3 :                 p++;
     134             : 
     135             :         /* Read the name */
     136         125 :         name->data = (void *) p;
     137         449 :         while (*p != '=' && *p != 0 && !c_isspace(*p))
     138         324 :                 p++;
     139             : 
     140         125 :         name->size = p - name->data;
     141             : 
     142             :         /* skip any space */
     143         145 :         while (c_isspace(*p))
     144          20 :                 p++;
     145             : 
     146         125 :         if (*p != '=')
     147           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     148         125 :         p++;
     149             : 
     150         145 :         while (c_isspace(*p))
     151          20 :                 p++;
     152             : 
     153         125 :         if (*p == '#') {
     154           3 :                 *is_raw = 1;
     155             :         }
     156             : 
     157             :         /* Read value */
     158         125 :         val->data = (void *) p;
     159       26083 :         while (*p != 0 && (*p != ',' || (*p == ',' && *(p - 1) == '\\'))
     160       25958 :                && *p != '\n') {
     161       25958 :                 p++;
     162             :         }
     163         125 :         val->size = p - (val->data);
     164         125 :         *ptr = (void*)p;
     165             : 
     166         125 :         p = val->data;
     167             :         /* check for unescaped '+' - we do not support them */
     168       28254 :         while (*p != 0) {
     169       28130 :                 if (*p == '+' && (*(p - 1) != '\\'))
     170           1 :                         return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     171       28129 :                 p++;
     172             :         }
     173             : 
     174             :         /* remove spaces from the end */
     175         124 :         while(val->size > 0 && c_isspace(val->data[val->size-1])) {
     176           7 :                 if (val->size-2 > 0 && val->data[val->size-2] == '\\')
     177             :                         break;
     178           0 :                 val->size--;
     179             :         }
     180             : 
     181         124 :         if (val->size == 0 || name->size == 0)
     182           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     183             : 
     184             :         return 0;
     185             : }
     186             : 
     187             : typedef struct elem_list_st {
     188             :         gnutls_datum_t name;
     189             :         gnutls_datum_t val;
     190             :         const char *pos;
     191             :         unsigned is_raw;
     192             :         struct elem_list_st *next;
     193             : } elem_list_st;
     194             : 
     195         124 : static int add_new_elem(elem_list_st **head, const gnutls_datum_t *name, const gnutls_datum_t *val, const char *pos, unsigned is_raw)
     196             : {
     197         124 :         elem_list_st *elem = gnutls_malloc(sizeof(*elem));
     198         124 :         if (elem == NULL)
     199           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     200             : 
     201         124 :         memcpy(&elem->name, name, sizeof(*name));
     202         124 :         memcpy(&elem->val, val, sizeof(*val));
     203         124 :         elem->pos = pos;
     204         124 :         elem->is_raw = is_raw;
     205         124 :         elem->next = *head;
     206         124 :         *head = elem;
     207             : 
     208         124 :         return 0;
     209             : }
     210             : 
     211             : static int
     212          45 : crt_set_dn(set_dn_func f, void *crt, const char *dn, const char **err)
     213             : {
     214          45 :         const char *p = dn;
     215          45 :         int ret;
     216          45 :         gnutls_datum_t name, val;
     217          45 :         unsigned is_raw;
     218          45 :         elem_list_st *list = NULL, *plist, *next;
     219             : 
     220          45 :         if (crt == NULL || dn == NULL)
     221           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     222             : 
     223             :         /* We parse the string and set all elements to a linked list in
     224             :          * reverse order. That way we can encode in reverse order,
     225             :          * the way RFC4514 requires. */
     226             : 
     227             :         /* For each element */
     228         169 :         while (*p != 0 && *p != '\n') {
     229         125 :                 if (err)
     230         125 :                         *err = p;
     231             : 
     232         125 :                 is_raw = 0;
     233         125 :                 ret = read_attr_and_val(&p, &name, &val, &is_raw);
     234         125 :                 if (ret < 0) {
     235           1 :                         gnutls_assert();
     236           1 :                         goto fail;
     237             :                 }
     238             : 
     239             :                 /* skip spaces and look for comma */
     240         124 :                 while (c_isspace(*p))
     241           0 :                         p++;
     242             : 
     243         124 :                 ret = add_new_elem(&list, &name, &val, p, is_raw);
     244         124 :                 if (ret < 0) {
     245           0 :                         gnutls_assert();
     246           0 :                         goto fail;
     247             :                 }
     248             : 
     249         124 :                 if (*p != ',' && *p != 0 && *p != '\n') {
     250           0 :                         ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     251           0 :                         goto fail;
     252             :                 }
     253         124 :                 if (*p == ',')
     254          80 :                         p++;
     255             :         }
     256             : 
     257          44 :         plist = list;
     258         159 :         while(plist) {
     259         121 :                 if (err)
     260         121 :                         *err = plist->pos;
     261         121 :                 ret = dn_attr_crt_set(f, crt, &plist->name, &plist->val, plist->is_raw);
     262         121 :                 if (ret < 0)
     263           6 :                         goto fail;
     264             : 
     265         115 :                 plist = plist->next;
     266             :         }
     267             : 
     268             :         ret = 0;
     269          45 : fail:
     270          45 :         plist = list;
     271         169 :         while(plist) {
     272         124 :                 next = plist->next;
     273         124 :                 gnutls_free(plist);
     274         124 :                 plist = next;
     275             :         }
     276             :         return ret;
     277             : }
     278             : 
     279             : 
     280             : /**
     281             :  * gnutls_x509_crt_set_dn:
     282             :  * @crt: a certificate of type #gnutls_x509_crt_t
     283             :  * @dn: a comma separated DN string (RFC4514)
     284             :  * @err: indicates the error position (if any)
     285             :  *
     286             :  * This function will set the DN on the provided certificate.
     287             :  * The input string should be plain ASCII or UTF-8 encoded. On
     288             :  * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
     289             :  *
     290             :  * Note that DNs are not expected to hold DNS information, and thus
     291             :  * no automatic IDNA conversions are attempted when using this function.
     292             :  * If that is required (e.g., store a domain in CN), process the corresponding
     293             :  * input with gnutls_idna_map().
     294             :  *
     295             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     296             :  *   negative error value.
     297             :  **/
     298             : int
     299          22 : gnutls_x509_crt_set_dn(gnutls_x509_crt_t crt, const char *dn,
     300             :                        const char **err)
     301             : {
     302          22 :         return crt_set_dn((set_dn_func) gnutls_x509_crt_set_dn_by_oid, crt,
     303             :                           dn, err);
     304             : }
     305             : 
     306             : /**
     307             :  * gnutls_x509_crt_set_issuer_dn:
     308             :  * @crt: a certificate of type #gnutls_x509_crt_t
     309             :  * @dn: a comma separated DN string (RFC4514)
     310             :  * @err: indicates the error position (if any)
     311             :  *
     312             :  * This function will set the DN on the provided certificate.
     313             :  * The input string should be plain ASCII or UTF-8 encoded. On
     314             :  * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
     315             :  *
     316             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     317             :  *   negative error value.
     318             :  **/
     319             : int
     320           4 : gnutls_x509_crt_set_issuer_dn(gnutls_x509_crt_t crt, const char *dn,
     321             :                               const char **err)
     322             : {
     323           4 :         return crt_set_dn((set_dn_func)
     324             :                           gnutls_x509_crt_set_issuer_dn_by_oid, crt, dn,
     325             :                           err);
     326             : }
     327             : 
     328             : /**
     329             :  * gnutls_x509_crq_set_dn:
     330             :  * @crq: a certificate of type #gnutls_x509_crq_t
     331             :  * @dn: a comma separated DN string (RFC4514)
     332             :  * @err: indicates the error position (if any)
     333             :  *
     334             :  * This function will set the DN on the provided certificate.
     335             :  * The input string should be plain ASCII or UTF-8 encoded. On
     336             :  * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
     337             :  *
     338             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     339             :  *   negative error value.
     340             :  **/
     341             : int
     342           1 : gnutls_x509_crq_set_dn(gnutls_x509_crq_t crq, const char *dn,
     343             :                        const char **err)
     344             : {
     345           1 :         return crt_set_dn((set_dn_func) gnutls_x509_crq_set_dn_by_oid, crq,
     346             :                           dn, err);
     347             : }
     348             : 
     349             : static
     350          36 : int set_dn_by_oid(gnutls_x509_dn_t dn, const char *oid, unsigned int raw_flag, const void *name, unsigned name_size)
     351             : {
     352          36 :         return _gnutls_x509_set_dn_oid(dn->asn, "", oid, raw_flag, name, name_size);
     353             : }
     354             : 
     355             : /**
     356             :  * gnutls_x509_dn_set_str:
     357             :  * @dn: a pointer to DN
     358             :  * @str: a comma separated DN string (RFC4514)
     359             :  * @err: indicates the error position (if any)
     360             :  *
     361             :  * This function will set the DN on the provided DN structure.
     362             :  * The input string should be plain ASCII or UTF-8 encoded. On
     363             :  * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
     364             :  *
     365             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     366             :  *   negative error value.
     367             :  *
     368             :  * Since: 3.5.3
     369             :  **/
     370             : int
     371          18 : gnutls_x509_dn_set_str(gnutls_x509_dn_t dn, const char *str, const char **err)
     372             : {
     373          18 :         if (dn == NULL) {
     374           0 :                 gnutls_assert();
     375           0 :                 return GNUTLS_E_INVALID_REQUEST;
     376             :         }
     377             : 
     378          18 :         return crt_set_dn((set_dn_func) set_dn_by_oid, dn,
     379             :                           str, err);
     380             : }
     381             : 
     382             : /**
     383             :  * gnutls_x509_dn_init:
     384             :  * @dn: the object to be initialized
     385             :  *
     386             :  * This function initializes a #gnutls_x509_dn_t type.
     387             :  *
     388             :  * The object returned must be deallocated using
     389             :  * gnutls_x509_dn_deinit().
     390             :  *
     391             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     392             :  *   negative error value.
     393             :  *
     394             :  * Since: 2.4.0
     395             :  **/
     396        9801 : int gnutls_x509_dn_init(gnutls_x509_dn_t * dn)
     397             : {
     398        9801 :         int result;
     399             : 
     400        9801 :         *dn = gnutls_calloc(1, sizeof(gnutls_x509_dn_st));
     401             : 
     402       19602 :         if ((result =
     403        9801 :              asn1_create_element(_gnutls_get_pkix(),
     404             :                                  "PKIX1.Name", &(*dn)->asn)) != ASN1_SUCCESS) {
     405           0 :                 gnutls_assert();
     406           0 :                 gnutls_free(*dn);
     407           0 :                 return _gnutls_asn2err(result);
     408             :         }
     409             : 
     410             :         return 0;
     411             : }
     412             : 
     413             : /**
     414             :  * gnutls_x509_dn_import:
     415             :  * @dn: the structure that will hold the imported DN
     416             :  * @data: should contain a DER encoded RDN sequence
     417             :  *
     418             :  * This function parses an RDN sequence and stores the result to a
     419             :  * #gnutls_x509_dn_t type. The data must have been initialized
     420             :  * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
     421             :  * decode the DN.
     422             :  *
     423             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     424             :  *   negative error value.
     425             :  *
     426             :  * Since: 2.4.0
     427             :  **/
     428        9783 : int gnutls_x509_dn_import(gnutls_x509_dn_t dn, const gnutls_datum_t * data)
     429             : {
     430        9783 :         int result;
     431        9783 :         char err[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
     432             : 
     433        9783 :         if (data->data == NULL || data->size == 0)
     434           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     435             : 
     436        9783 :         result = _asn1_strict_der_decode(&dn->asn,
     437             :                                    data->data, data->size, err);
     438        9783 :         if (result != ASN1_SUCCESS) {
     439             :                 /* couldn't decode DER */
     440           1 :                 _gnutls_debug_log("ASN.1 Decoding error: %s\n", err);
     441           1 :                 gnutls_assert();
     442           1 :                 return _gnutls_asn2err(result);
     443             :         }
     444             : 
     445             :         return 0;
     446             : }
     447             : 
     448             : /**
     449             :  * gnutls_x509_dn_deinit:
     450             :  * @dn: a DN uint8_t object pointer.
     451             :  *
     452             :  * This function deallocates the DN object as returned by
     453             :  * gnutls_x509_dn_import().
     454             :  *
     455             :  * Since: 2.4.0
     456             :  **/
     457        9801 : void gnutls_x509_dn_deinit(gnutls_x509_dn_t dn)
     458             : {
     459        9801 :         asn1_delete_structure(&dn->asn);
     460        9801 :         gnutls_free(dn);
     461        9801 : }
     462             : 
     463             : /**
     464             :  * gnutls_x509_dn_export:
     465             :  * @dn: Holds the uint8_t DN object
     466             :  * @format: the format of output params. One of PEM or DER.
     467             :  * @output_data: will contain a DN PEM or DER encoded
     468             :  * @output_data_size: holds the size of output_data (and will be
     469             :  *   replaced by the actual size of parameters)
     470             :  *
     471             :  * This function will export the DN to DER or PEM format.
     472             :  *
     473             :  * If the buffer provided is not long enough to hold the output, then
     474             :  * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
     475             :  * will be returned.
     476             :  *
     477             :  * If the structure is PEM encoded, it will have a header
     478             :  * of "BEGIN NAME".
     479             :  *
     480             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     481             :  *   negative error value.
     482             :  **/
     483             : int
     484           2 : gnutls_x509_dn_export(gnutls_x509_dn_t dn,
     485             :                       gnutls_x509_crt_fmt_t format, void *output_data,
     486             :                       size_t * output_data_size)
     487             : {
     488           2 :         if (dn == NULL) {
     489           0 :                 gnutls_assert();
     490           0 :                 return GNUTLS_E_INVALID_REQUEST;
     491             :         }
     492             : 
     493           2 :         return _gnutls_x509_export_int_named(dn->asn, "rdnSequence",
     494             :                                              format, "NAME",
     495             :                                              output_data,
     496             :                                              output_data_size);
     497             : }
     498             : 
     499             : /**
     500             :  * gnutls_x509_dn_export2:
     501             :  * @dn: Holds the uint8_t DN object
     502             :  * @format: the format of output params. One of PEM or DER.
     503             :  * @out: will contain a DN PEM or DER encoded
     504             :  *
     505             :  * This function will export the DN to DER or PEM format.
     506             :  *
     507             :  * The output buffer is allocated using gnutls_malloc().
     508             :  *
     509             :  * If the structure is PEM encoded, it will have a header
     510             :  * of "BEGIN NAME".
     511             :  *
     512             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     513             :  *   negative error value.
     514             :  *
     515             :  * Since: 3.1.3
     516             :  **/
     517             : int
     518          12 : gnutls_x509_dn_export2(gnutls_x509_dn_t dn,
     519             :                        gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
     520             : {
     521          12 :         if (dn == NULL) {
     522           0 :                 gnutls_assert();
     523           0 :                 return GNUTLS_E_INVALID_REQUEST;
     524             :         }
     525             : 
     526          12 :         return _gnutls_x509_export_int_named2(dn->asn, "rdnSequence",
     527             :                                               format, "NAME", out);
     528             : }
     529             : 
     530             : /**
     531             :  * gnutls_x509_dn_get_rdn_ava:
     532             :  * @dn: a pointer to DN
     533             :  * @irdn: index of RDN
     534             :  * @iava: index of AVA.
     535             :  * @ava: Pointer to structure which will hold output information.
     536             :  *
     537             :  * Get pointers to data within the DN. The format of the @ava structure
     538             :  * is shown below.
     539             :  *
     540             :  *  struct gnutls_x509_ava_st {
     541             :  *    gnutls_datum_t oid;
     542             :  *    gnutls_datum_t value;
     543             :  *    unsigned long value_tag;
     544             :  *  };
     545             :  *
     546             :  * The X.509 distinguished name is a sequence of sequences of strings
     547             :  * and this is what the @irdn and @iava indexes model.
     548             :  *
     549             :  * Note that @ava will contain pointers into the @dn structure which
     550             :  * in turns points to the original certificate. Thus you should not
     551             :  * modify any data or deallocate any of those.
     552             :  *
     553             :  * This is a low-level function that requires the caller to do the
     554             :  * value conversions when necessary (e.g. from UCS-2).
     555             :  *
     556             :  * Returns: Returns 0 on success, or an error code.
     557             :  **/
     558             : int
     559           3 : gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn,
     560             :                            int irdn, int iava, gnutls_x509_ava_st * ava)
     561             : {
     562           3 :         ASN1_TYPE rdn, elem;
     563           3 :         ASN1_DATA_NODE vnode;
     564           3 :         long len;
     565           3 :         int lenlen, remlen, ret;
     566           3 :         char rbuf[MAX_NAME_SIZE];
     567           3 :         unsigned char cls;
     568           3 :         const unsigned char *ptr;
     569             : 
     570           3 :         iava++;
     571           3 :         irdn++;                 /* 0->1, 1->2 etc */
     572             : 
     573           3 :         snprintf(rbuf, sizeof(rbuf), "rdnSequence.?%d.?%d", irdn, iava);
     574           3 :         rdn = asn1_find_node(dn->asn, rbuf);
     575           3 :         if (!rdn) {
     576           0 :                 gnutls_assert();
     577           0 :                 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
     578             :         }
     579             : 
     580           3 :         snprintf(rbuf, sizeof(rbuf), "?%d.type", iava);
     581           3 :         elem = asn1_find_node(rdn, rbuf);
     582           3 :         if (!elem) {
     583           0 :                 gnutls_assert();
     584           0 :                 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
     585             :         }
     586             : 
     587           3 :         ret = asn1_read_node_value(elem, &vnode);
     588           3 :         if (ret != ASN1_SUCCESS) {
     589           0 :                 gnutls_assert();
     590           0 :                 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
     591             :         }
     592             : 
     593           3 :         ava->oid.data = (void *) vnode.value;
     594           3 :         ava->oid.size = vnode.value_len;
     595             : 
     596           3 :         snprintf(rbuf, sizeof(rbuf), "?%d.value", iava);
     597           3 :         elem = asn1_find_node(rdn, rbuf);
     598           3 :         if (!elem) {
     599           0 :                 gnutls_assert();
     600           0 :                 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
     601             :         }
     602             : 
     603           3 :         ret = asn1_read_node_value(elem, &vnode);
     604           3 :         if (ret != ASN1_SUCCESS) {
     605           0 :                 gnutls_assert();
     606           0 :                 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
     607             :         }
     608             :         /* The value still has the previous tag's length bytes, plus the
     609             :          * current value's tag and length bytes. Decode them.
     610             :          */
     611             : 
     612           3 :         ptr = vnode.value;
     613           3 :         remlen = vnode.value_len;
     614           3 :         len = asn1_get_length_der(ptr, remlen, &lenlen);
     615           3 :         if (len < 0) {
     616           0 :                 gnutls_assert();
     617           0 :                 return GNUTLS_E_ASN1_DER_ERROR;
     618             :         }
     619             : 
     620           3 :         ptr += lenlen;
     621           3 :         remlen -= lenlen;
     622           3 :         ret =
     623           3 :             asn1_get_tag_der(ptr, remlen, &cls, &lenlen, &ava->value_tag);
     624           3 :         if (ret) {
     625           0 :                 gnutls_assert();
     626           0 :                 return _gnutls_asn2err(ret);
     627             :         }
     628             : 
     629           3 :         ptr += lenlen;
     630           3 :         remlen -= lenlen;
     631             : 
     632             :         {
     633           3 :                 signed long tmp;
     634             : 
     635           3 :                 tmp = asn1_get_length_der(ptr, remlen, &lenlen);
     636           3 :                 if (tmp < 0) {
     637           0 :                         gnutls_assert();
     638           0 :                         return GNUTLS_E_ASN1_DER_ERROR;
     639             :                 }
     640           3 :                 ava->value.size = tmp;
     641             :         }
     642           3 :         ava->value.data = (void *) (ptr + lenlen);
     643             : 
     644           3 :         return 0;
     645             : }
     646             : 
     647             : /**
     648             :  * gnutls_x509_dn_get_str:
     649             :  * @dn: a pointer to DN
     650             :  * @str: a datum that will hold the name
     651             :  *
     652             :  * This function will allocate buffer and copy the name in the provided DN.
     653             :  * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
     654             :  * described in RFC4514. The output string will be ASCII or UTF-8
     655             :  * encoded, depending on the certificate data.
     656             :  *
     657             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     658             :  *   negative error value.
     659             :  *
     660             :  * Since: 3.4.2
     661             :  **/
     662             : int
     663         207 : gnutls_x509_dn_get_str(gnutls_x509_dn_t dn, gnutls_datum_t *str)
     664             : {
     665         207 :         if (dn == NULL) {
     666           0 :                 gnutls_assert();
     667           0 :                 return GNUTLS_E_INVALID_REQUEST;
     668             :         }
     669             : 
     670         207 :         return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, GNUTLS_X509_DN_FLAG_COMPAT);
     671             : }
     672             : 
     673             : /**
     674             :  * gnutls_x509_dn_get_str:
     675             :  * @dn: a pointer to DN
     676             :  * @str: a datum that will hold the name
     677             :  * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
     678             :  *
     679             :  * This function will allocate buffer and copy the name in the provided DN.
     680             :  * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
     681             :  * described in RFC4514. The output string will be ASCII or UTF-8
     682             :  * encoded, depending on the certificate data.
     683             :  *
     684             :  * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
     685             :  * format will match the format output by previous to 3.5.6 versions of GnuTLS
     686             :  * which was not not fully RFC4514-compliant.
     687             :  *
     688             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     689             :  *   negative error value.
     690             :  *
     691             :  * Since: 3.5.7
     692             :  **/
     693             : int
     694        9578 : gnutls_x509_dn_get_str2(gnutls_x509_dn_t dn, gnutls_datum_t *str, unsigned flags)
     695             : {
     696        9578 :         if (dn == NULL) {
     697           0 :                 gnutls_assert();
     698           0 :                 return GNUTLS_E_INVALID_REQUEST;
     699             :         }
     700             : 
     701        9578 :         return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, flags);
     702             : }

Generated by: LCOV version 1.14