qasn1element.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/network/ssl/qasn1element.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org>-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtNetwork module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40-
41#include "qasn1element_p.h"-
42-
43#include <QtCore/qdatastream.h>-
44#include <QtCore/qdatetime.h>-
45#include <QtCore/qvector.h>-
46#include <QDebug>-
47-
48QT_BEGIN_NAMESPACE-
49-
50typedef QMap<QByteArray, QByteArray> OidNameMap;-
51static OidNameMap createOidMap()-
52{-
53 OidNameMap oids;-
54 // used by unit tests-
55 oids.insert(oids.cend(), QByteArrayLiteral("0.9.2342.19200300.100.1.5"), QByteArrayLiteral("favouriteDrink"));-
56 oids.insert(oids.cend(), QByteArrayLiteral("1.2.840.113549.1.9.1"), QByteArrayLiteral("emailAddress"));-
57 oids.insert(oids.cend(), QByteArrayLiteral("1.3.6.1.5.5.7.1.1"), QByteArrayLiteral("authorityInfoAccess"));-
58 oids.insert(oids.cend(), QByteArrayLiteral("1.3.6.1.5.5.7.48.1"), QByteArrayLiteral("OCSP"));-
59 oids.insert(oids.cend(), QByteArrayLiteral("1.3.6.1.5.5.7.48.2"), QByteArrayLiteral("caIssuers"));-
60 oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.14"), QByteArrayLiteral("subjectKeyIdentifier"));-
61 oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.15"), QByteArrayLiteral("keyUsage"));-
62 oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.17"), QByteArrayLiteral("subjectAltName"));-
63 oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.19"), QByteArrayLiteral("basicConstraints"));-
64 oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.35"), QByteArrayLiteral("authorityKeyIdentifier"));-
65 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.10"), QByteArrayLiteral("O"));-
66 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.11"), QByteArrayLiteral("OU"));-
67 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.12"), QByteArrayLiteral("title"));-
68 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.13"), QByteArrayLiteral("description"));-
69 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.17"), QByteArrayLiteral("postalCode"));-
70 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.3"), QByteArrayLiteral("CN"));-
71 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.4"), QByteArrayLiteral("SN"));-
72 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.41"), QByteArrayLiteral("name"));-
73 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.42"), QByteArrayLiteral("GN"));-
74 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.43"), QByteArrayLiteral("initials"));-
75 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.46"), QByteArrayLiteral("dnQualifier"));-
76 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.5"), QByteArrayLiteral("serialNumber"));-
77 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.6"), QByteArrayLiteral("C"));-
78 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.7"), QByteArrayLiteral("L"));-
79 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.8"), QByteArrayLiteral("ST"));-
80 oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.9"), QByteArrayLiteral("street"));-
81 return oids;-
82}-
83Q_GLOBAL_STATIC_WITH_ARGS(OidNameMap, oidNameMap, (createOidMap()))-
84-
85QAsn1Element::QAsn1Element(quint8 type, const QByteArray &value)-
86 : mType(type)-
87 , mValue(value)-
88{-
89}-
90-
91bool QAsn1Element::read(QDataStream &stream)-
92{-
93 // type-
94 quint8 tmpType;-
95 stream >> tmpType;-
96 if (!tmpType)-
97 return false;-
98-
99 // length-
100 qint64 length = 0;-
101 quint8 first;-
102 stream >> first;-
103 if (first & 0x80) {-
104 // long form-
105 const quint8 bytes = (first & 0x7f);-
106 if (bytes > 7)-
107 return false;-
108-
109 quint8 b;-
110 for (int i = 0; i < bytes; i++) {-
111 stream >> b;-
112 length = (length << 8) | b;-
113 }-
114 } else {-
115 // short form-
116 length = (first & 0x7f);-
117 }-
118-
119 // value-
120 QByteArray tmpValue;-
121 tmpValue.resize(length);-
122 int count = stream.readRawData(tmpValue.data(), tmpValue.size());-
123 if (count != length)-
124 return false;-
125-
126 mType = tmpType;-
127 mValue.swap(tmpValue);-
128 return true;-
129}-
130-
131bool QAsn1Element::read(const QByteArray &data)-
132{-
133 QDataStream stream(data);-
134 return read(stream);-
135}-
136-
137void QAsn1Element::write(QDataStream &stream) const-
138{-
139 // type-
140 stream << mType;-
141-
142 // length-
143 qint64 length = mValue.size();-
144 if (length >= 128) {-
145 // long form-
146 quint8 encodedLength = 0x80;-
147 QByteArray ba;-
148 while (length) {-
149 ba.prepend(quint8((length & 0xff)));-
150 length >>= 8;-
151 encodedLength += 1;-
152 }-
153 stream << encodedLength;-
154 stream.writeRawData(ba.data(), ba.size());-
155 } else {-
156 // short form-
157 stream << quint8(length);-
158 }-
159-
160 // value-
161 stream.writeRawData(mValue.data(), mValue.size());-
162}-
163-
164QAsn1Element QAsn1Element::fromBool(bool val)-
165{-
166 return QAsn1Element(QAsn1Element::BooleanType,-
167 QByteArray(1, val ? 0xff : 0x00));-
168}-
169-
170QAsn1Element QAsn1Element::fromInteger(unsigned int val)-
171{-
172 QAsn1Element elem(QAsn1Element::IntegerType);-
173 while (val > 127) {-
174 elem.mValue.prepend(val & 0xff);-
175 val >>= 8;-
176 }-
177 elem.mValue.prepend(val & 0x7f);-
178 return elem;-
179}-
180-
181QAsn1Element QAsn1Element::fromVector(const QVector<QAsn1Element> &items)-
182{-
183 QAsn1Element seq;-
184 seq.mType = SequenceType;-
185 QDataStream stream(&seq.mValue, QIODevice::WriteOnly);-
186 for (QVector<QAsn1Element>::const_iterator it = items.cbegin(), end = items.cend(); it != end; ++it)-
187 it->write(stream);-
188 return seq;-
189}-
190-
191QAsn1Element QAsn1Element::fromObjectId(const QByteArray &id)-
192{-
193 QAsn1Element elem;-
194 elem.mType = ObjectIdentifierType;-
195 const QList<QByteArray> bits = id.split('.');-
196 Q_ASSERT(bits.size() > 2);-
197 elem.mValue += quint8((bits[0].toUInt() * 40 + bits[1].toUInt()));-
198 for (int i = 2; i < bits.size(); ++i) {
i < bits.size()Description
TRUEevaluated 7 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
2-7
199 char buffer[std::numeric_limits<unsigned int>::digits / 7 + 2];-
200 char *pBuffer = buffer + sizeof(buffer);-
201 *--pBuffer = '\0';-
202 unsigned int node = bits[i].toUInt();-
203 *--pBuffer = quint8((node & 0x7f));-
204 node >>= 7;-
205 while (node) {
nodeDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
FALSEevaluated 7 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
4-7
206 *--pBuffer = quint8(((node & 0x7f) | 0x80));-
207 node >>= 7;-
208 }
executed 4 times by 1 test: end of block
Executed by:
  • tst_qasn1element - unknown status
4
209 elem.mValue += pBuffer;-
210 }
executed 7 times by 1 test: end of block
Executed by:
  • tst_qasn1element - unknown status
7
211 return elem;
executed 2 times by 1 test: return elem;
Executed by:
  • tst_qasn1element - unknown status
2
212}-
213-
214bool QAsn1Element::toBool(bool *ok) const-
215{-
216 if (*this == fromBool(true)) {-
217 if (ok)-
218 *ok = true;-
219 return true;-
220 } else if (*this == fromBool(false)) {-
221 if (ok)-
222 *ok = true;-
223 return false;-
224 } else {-
225 if (ok)-
226 *ok = false;-
227 return false;-
228 }-
229}-
230-
231QDateTime QAsn1Element::toDateTime() const-
232{-
233 if (mValue.endsWith('Z')) {-
234 if (mType == UtcTimeType && mValue.size() == 13)-
235 return QDateTime(QDate(2000 + mValue.mid(0, 2).toInt(),-
236 mValue.mid(2, 2).toInt(),-
237 mValue.mid(4, 2).toInt()),-
238 QTime(mValue.mid(6, 2).toInt(),-
239 mValue.mid(8, 2).toInt(),-
240 mValue.mid(10, 2).toInt()),-
241 Qt::UTC);-
242 else if (mType == GeneralizedTimeType && mValue.size() == 15)-
243 return QDateTime(QDate(mValue.mid(0, 4).toInt(),-
244 mValue.mid(4, 2).toInt(),-
245 mValue.mid(6, 2).toInt()),-
246 QTime(mValue.mid(8, 2).toInt(),-
247 mValue.mid(10, 2).toInt(),-
248 mValue.mid(12, 2).toInt()),-
249 Qt::UTC);-
250 }-
251 return QDateTime();-
252}-
253-
254QMultiMap<QByteArray, QString> QAsn1Element::toInfo() const-
255{-
256 QMultiMap<QByteArray, QString> info;-
257 QAsn1Element elem;-
258 QDataStream issuerStream(mValue);-
259 while (elem.read(issuerStream) && elem.mType == QAsn1Element::SetType) {-
260 QAsn1Element issuerElem;-
261 QDataStream setStream(elem.mValue);-
262 if (issuerElem.read(setStream) && issuerElem.mType == QAsn1Element::SequenceType) {-
263 QVector<QAsn1Element> elems = issuerElem.toVector();-
264 if (elems.size() == 2) {-
265 const QByteArray key = elems.front().toObjectName();-
266 if (!key.isEmpty())-
267 info.insert(key, elems.back().toString());-
268 }-
269 }-
270 }-
271 return info;-
272}-
273-
274qint64 QAsn1Element::toInteger(bool *ok) const-
275{-
276 if (mType != QAsn1Element::IntegerType || mValue.isEmpty()) {-
277 if (ok)-
278 *ok = false;-
279 return 0;-
280 }-
281-
282 // NOTE: negative numbers are not handled-
283 if (mValue.at(0) & 0x80) {-
284 if (ok)-
285 *ok = false;-
286 return 0;-
287 }-
288-
289 qint64 value = mValue.at(0) & 0x7f;-
290 for (int i = 1; i < mValue.size(); ++i)-
291 value = (value << 8) | quint8(mValue.at(i));-
292-
293 if (ok)-
294 *ok = true;-
295 return value;-
296}-
297-
298QVector<QAsn1Element> QAsn1Element::toVector() const-
299{-
300 QVector<QAsn1Element> items;-
301 if (mType == SequenceType) {-
302 QAsn1Element elem;-
303 QDataStream stream(mValue);-
304 while (elem.read(stream))-
305 items << elem;-
306 }-
307 return items;-
308}-
309-
310QByteArray QAsn1Element::toObjectId() const-
311{-
312 QByteArray key;-
313 if (mType == ObjectIdentifierType && !mValue.isEmpty()) {
mType == ObjectIdentifierTypeDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
FALSEnever evaluated
!mValue.isEmpty()Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
FALSEnever evaluated
0-6
314 quint8 b = mValue[.at(0];);-
315 key += QByteArray::number(b / 40) + '.' + QByteArray::number (b % 40);-
316 unsigned int val = 0;-
317 for (int i = 1; i < mValue.size(); ++i) {
i < mValue.size()Description
TRUEevaluated 33 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
FALSEevaluated 6 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
6-33
318 b = mValue[.at(i];);-
319 val = (val << 7) | (b & 0x7f);-
320 if (!(b & 0x80)) {
!(b & 0x80)Description
TRUEevaluated 21 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
FALSEevaluated 12 times by 1 test
Evaluated by:
  • tst_qasn1element - unknown status
12-21
321 key += '.' + QByteArray::number(val);-
322 val = 0;-
323 }
executed 21 times by 1 test: end of block
Executed by:
  • tst_qasn1element - unknown status
21
324 }
executed 33 times by 1 test: end of block
Executed by:
  • tst_qasn1element - unknown status
33
325 }
executed 6 times by 1 test: end of block
Executed by:
  • tst_qasn1element - unknown status
6
326 return key;
executed 6 times by 1 test: return key;
Executed by:
  • tst_qasn1element - unknown status
6
327}-
328-
329QByteArray QAsn1Element::toObjectName() const-
330{-
331 QByteArray key = toObjectId();-
332 return oidNameMap->value(key, key);-
333}-
334-
335QString QAsn1Element::toString() const-
336{-
337 // Detect embedded NULs and reject-
338 if (qstrlen(mValue) < uint(mValue.size()))-
339 return QString();-
340-
341 if (mType == PrintableStringType || mType == TeletexStringType-
342 || mType == Rfc822NameType || mType == DnsNameType-
343 || mType == UniformResourceIdentifierType)-
344 return QString::fromLatin1(mValue, mValue.size());-
345 if (mType == Utf8StringType)-
346 return QString::fromUtf8(mValue, mValue.size());-
347-
348 return QString();-
349}-
350-
351QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9