Coverage Report

Created: 2026-02-16 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/x509/name_print.cc
Line
Count
Source
1
// Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/x509.h>
16
17
#include <assert.h>
18
#include <inttypes.h>
19
#include <string.h>
20
21
#include <openssl/asn1.h>
22
#include <openssl/bio.h>
23
#include <openssl/obj.h>
24
25
26
1.04k
static int maybe_write(BIO *out, const void *buf, int len) {
27
  // If |out| is NULL, ignore the output but report the length.
28
1.04k
  return out == nullptr || BIO_write(out, buf, len) == len;
29
1.04k
}
30
31
// do_indent prints |indent| spaces to |out|.
32
351
static int do_indent(BIO *out, int indent) {
33
351
  for (int i = 0; i < indent; i++) {
34
0
    if (!maybe_write(out, " ", 1)) {
35
0
      return 0;
36
0
    }
37
0
  }
38
351
  return 1;
39
351
}
40
41
#define FN_WIDTH_LN 25
42
#define FN_WIDTH_SN 10
43
44
static int do_name_ex(BIO *out, const X509_NAME *n, int indent,
45
135
                      unsigned long flags) {
46
135
  int prev = -1, orflags;
47
135
  char objtmp[80];
48
135
  const char *objbuf;
49
135
  int outlen, len;
50
135
  const char *sep_dn, *sep_mv, *sep_eq;
51
135
  int sep_dn_len, sep_mv_len, sep_eq_len;
52
135
  if (indent < 0) {
53
0
    indent = 0;
54
0
  }
55
135
  outlen = indent;
56
135
  if (!do_indent(out, indent)) {
57
0
    return -1;
58
0
  }
59
135
  switch (flags & XN_FLAG_SEP_MASK) {
60
0
    case XN_FLAG_SEP_MULTILINE:
61
0
      sep_dn = "\n";
62
0
      sep_dn_len = 1;
63
0
      sep_mv = " + ";
64
0
      sep_mv_len = 3;
65
0
      break;
66
67
0
    case XN_FLAG_SEP_COMMA_PLUS:
68
0
      sep_dn = ",";
69
0
      sep_dn_len = 1;
70
0
      sep_mv = "+";
71
0
      sep_mv_len = 1;
72
0
      indent = 0;
73
0
      break;
74
75
135
    case XN_FLAG_SEP_CPLUS_SPC:
76
135
      sep_dn = ", ";
77
135
      sep_dn_len = 2;
78
135
      sep_mv = " + ";
79
135
      sep_mv_len = 3;
80
135
      indent = 0;
81
135
      break;
82
83
0
    case XN_FLAG_SEP_SPLUS_SPC:
84
0
      sep_dn = "; ";
85
0
      sep_dn_len = 2;
86
0
      sep_mv = " + ";
87
0
      sep_mv_len = 3;
88
0
      indent = 0;
89
0
      break;
90
91
0
    default:
92
0
      return -1;
93
135
  }
94
95
135
  if (flags & XN_FLAG_SPC_EQ) {
96
135
    sep_eq = " = ";
97
135
    sep_eq_len = 3;
98
135
  } else {
99
0
    sep_eq = "=";
100
0
    sep_eq_len = 1;
101
0
  }
102
103
135
  int cnt = X509_NAME_entry_count(n);
104
525
  for (int i = 0; i < cnt; i++) {
105
390
    const X509_NAME_ENTRY *ent;
106
390
    if (flags & XN_FLAG_DN_REV) {
107
0
      ent = X509_NAME_get_entry(n, cnt - i - 1);
108
390
    } else {
109
390
      ent = X509_NAME_get_entry(n, i);
110
390
    }
111
390
    if (prev != -1) {
112
269
      if (prev == X509_NAME_ENTRY_set(ent)) {
113
53
        if (!maybe_write(out, sep_mv, sep_mv_len)) {
114
0
          return -1;
115
0
        }
116
53
        outlen += sep_mv_len;
117
216
      } else {
118
216
        if (!maybe_write(out, sep_dn, sep_dn_len)) {
119
0
          return -1;
120
0
        }
121
216
        outlen += sep_dn_len;
122
216
        if (!do_indent(out, indent)) {
123
0
          return -1;
124
0
        }
125
216
        outlen += indent;
126
216
      }
127
269
    }
128
390
    prev = X509_NAME_ENTRY_set(ent);
129
390
    const ASN1_OBJECT *fn = X509_NAME_ENTRY_get_object(ent);
130
390
    const ASN1_STRING *val = X509_NAME_ENTRY_get_data(ent);
131
390
    assert((flags & XN_FLAG_FN_MASK) == XN_FLAG_FN_SN);
132
390
    int fn_nid = OBJ_obj2nid(fn);
133
390
    if (fn_nid == NID_undef) {
134
257
      OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1);
135
257
      objbuf = objtmp;
136
257
    } else {
137
133
      objbuf = OBJ_nid2sn(fn_nid);
138
133
    }
139
390
    int objlen = strlen(objbuf);
140
390
    if (!maybe_write(out, objbuf, objlen) ||
141
390
        !maybe_write(out, sep_eq, sep_eq_len)) {
142
0
      return -1;
143
0
    }
144
390
    outlen += objlen + sep_eq_len;
145
    // If the field name is unknown then fix up the DER dump flag. We
146
    // might want to limit this further so it will DER dump on anything
147
    // other than a few 'standard' fields.
148
390
    if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) {
149
0
      orflags = ASN1_STRFLGS_DUMP_ALL;
150
390
    } else {
151
390
      orflags = 0;
152
390
    }
153
154
390
    len = ASN1_STRING_print_ex(out, val, flags | orflags);
155
390
    if (len < 0) {
156
0
      return -1;
157
0
    }
158
390
    outlen += len;
159
390
  }
160
135
  return outlen;
161
135
}
162
163
int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
164
5.67k
                       unsigned long flags) {
165
5.67k
  if (flags == XN_FLAG_COMPAT) {
166
5.54k
    return X509_NAME_print(out, nm, indent);
167
5.54k
  }
168
135
  return do_name_ex(out, nm, indent, flags);
169
5.67k
}
170
171
int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
172
0
                          unsigned long flags) {
173
0
  BIO *bio = nullptr;
174
0
  if (fp != nullptr) {
175
    // If |fp| is NULL, this function returns the number of bytes without
176
    // writing.
177
0
    bio = BIO_new_fp(fp, BIO_NOCLOSE);
178
0
    if (bio == nullptr) {
179
0
      return -1;
180
0
    }
181
0
  }
182
0
  int ret = X509_NAME_print_ex(bio, nm, indent, flags);
183
0
  BIO_free(bio);
184
0
  return ret;
185
0
}