Coverage Report

Created: 2026-08-28 07:25

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.27k
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.27k
  return out == nullptr || BIO_write(out, buf, len) == len;
29
1.27k
}
30
31
// do_indent prints `indent` spaces to `out`.
32
417
static int do_indent(BIO *out, int indent) {
33
417
  for (int i = 0; i < indent; i++) {
34
0
    if (!maybe_write(out, " ", 1)) {
35
0
      return 0;
36
0
    }
37
0
  }
38
417
  return 1;
39
417
}
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
161
                      unsigned long flags) {
46
161
  int prev = -1, orflags;
47
161
  int outlen, len;
48
161
  const char *sep_dn, *sep_mv, *sep_eq;
49
161
  int sep_dn_len, sep_mv_len, sep_eq_len;
50
161
  if (indent < 0) {
51
0
    indent = 0;
52
0
  }
53
161
  outlen = indent;
54
161
  if (!do_indent(out, indent)) {
55
0
    return -1;
56
0
  }
57
161
  switch (flags & XN_FLAG_SEP_MASK) {
58
0
    case XN_FLAG_SEP_MULTILINE:
59
0
      sep_dn = "\n";
60
0
      sep_dn_len = 1;
61
0
      sep_mv = " + ";
62
0
      sep_mv_len = 3;
63
0
      break;
64
65
0
    case XN_FLAG_SEP_COMMA_PLUS:
66
0
      sep_dn = ",";
67
0
      sep_dn_len = 1;
68
0
      sep_mv = "+";
69
0
      sep_mv_len = 1;
70
0
      indent = 0;
71
0
      break;
72
73
161
    case XN_FLAG_SEP_CPLUS_SPC:
74
161
      sep_dn = ", ";
75
161
      sep_dn_len = 2;
76
161
      sep_mv = " + ";
77
161
      sep_mv_len = 3;
78
161
      indent = 0;
79
161
      break;
80
81
0
    case XN_FLAG_SEP_SPLUS_SPC:
82
0
      sep_dn = "; ";
83
0
      sep_dn_len = 2;
84
0
      sep_mv = " + ";
85
0
      sep_mv_len = 3;
86
0
      indent = 0;
87
0
      break;
88
89
0
    default:
90
0
      return -1;
91
161
  }
92
93
161
  if (flags & XN_FLAG_SPC_EQ) {
94
161
    sep_eq = " = ";
95
161
    sep_eq_len = 3;
96
161
  } else {
97
0
    sep_eq = "=";
98
0
    sep_eq_len = 1;
99
0
  }
100
101
161
  int cnt = X509_NAME_entry_count(n);
102
637
  for (int i = 0; i < cnt; i++) {
103
476
    const X509_NAME_ENTRY *ent;
104
476
    if (flags & XN_FLAG_DN_REV) {
105
0
      ent = X509_NAME_get_entry(n, cnt - i - 1);
106
476
    } else {
107
476
      ent = X509_NAME_get_entry(n, i);
108
476
    }
109
476
    if (prev != -1) {
110
325
      if (prev == X509_NAME_ENTRY_set(ent)) {
111
69
        if (!maybe_write(out, sep_mv, sep_mv_len)) {
112
0
          return -1;
113
0
        }
114
69
        outlen += sep_mv_len;
115
256
      } else {
116
256
        if (!maybe_write(out, sep_dn, sep_dn_len)) {
117
0
          return -1;
118
0
        }
119
256
        outlen += sep_dn_len;
120
256
        if (!do_indent(out, indent)) {
121
0
          return -1;
122
0
        }
123
256
        outlen += indent;
124
256
      }
125
325
    }
126
476
    prev = X509_NAME_ENTRY_set(ent);
127
476
    const ASN1_OBJECT *fn = X509_NAME_ENTRY_get_object(ent);
128
476
    const ASN1_STRING *val = X509_NAME_ENTRY_get_data(ent);
129
476
    assert((flags & XN_FLAG_FN_MASK) == XN_FLAG_FN_SN);
130
    // Print the short name if available, otherwise serialize the OID.
131
476
    char objtmp[80];
132
476
    const char *objbuf = nullptr;
133
476
    int fn_nid = OBJ_obj2nid(fn);
134
476
    if (fn_nid != NID_undef) {
135
112
      objbuf = OBJ_nid2sn(fn_nid);
136
112
    }
137
476
    if (objbuf == nullptr) {
138
364
      OBJ_obj2txt(objtmp, sizeof(objtmp), fn, /*always_return_oid=*/1);
139
364
      objbuf = objtmp;
140
364
    }
141
476
    int objlen = strlen(objbuf);
142
476
    if (!maybe_write(out, objbuf, objlen) ||
143
476
        !maybe_write(out, sep_eq, sep_eq_len)) {
144
0
      return -1;
145
0
    }
146
476
    outlen += objlen + sep_eq_len;
147
    // If the field name is unknown then fix up the DER dump flag. We
148
    // might want to limit this further so it will DER dump on anything
149
    // other than a few 'standard' fields.
150
476
    if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) {
151
0
      orflags = ASN1_STRFLGS_DUMP_ALL;
152
476
    } else {
153
476
      orflags = 0;
154
476
    }
155
156
476
    len = ASN1_STRING_print_ex(out, val, flags | orflags);
157
476
    if (len < 0) {
158
0
      return -1;
159
0
    }
160
476
    outlen += len;
161
476
  }
162
161
  return outlen;
163
161
}
164
165
int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
166
5.88k
                       unsigned long flags) {
167
5.88k
  if (flags == XN_FLAG_COMPAT) {
168
5.72k
    return X509_NAME_print(out, nm, indent);
169
5.72k
  }
170
161
  return do_name_ex(out, nm, indent, flags);
171
5.88k
}
172
173
int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
174
0
                          unsigned long flags) {
175
0
  BIO *bio = nullptr;
176
0
  if (fp != nullptr) {
177
    // If `fp` is NULL, this function returns the number of bytes without
178
    // writing.
179
0
    bio = BIO_new_fp(fp, BIO_NOCLOSE);
180
0
    if (bio == nullptr) {
181
0
      return -1;
182
0
    }
183
0
  }
184
0
  int ret = X509_NAME_print_ex(bio, nm, indent, flags);
185
0
  BIO_free(bio);
186
0
  return ret;
187
0
}