File indexing completed on 2024-05-05 04:45:24

0001 /*
0002  * Copyright (C) 2005  Justin Karneges <justin@affinix.com>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Lesser General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Lesser General Public
0015  * License along with this library; if not, write to the Free Software
0016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
0017  *
0018  */
0019 
0020 /* mozilla certdata converter.  adapted from the debian ruby script */
0021 
0022 #include <QtCrypto>
0023 
0024 #include <QCoreApplication>
0025 #include <QFile>
0026 #include <QRegularExpression>
0027 #include <QTextStream>
0028 
0029 QStringList splitWithQuotes(const QString &in, char c);
0030 
0031 int main(int argc, char **argv)
0032 {
0033     QCA::Initializer qcaInit;
0034     QCoreApplication app(argc, argv);
0035 
0036     if (argc < 3) {
0037         printf("usage: mozcerts [certdata.txt] [outfile.pem]\n");
0038         return 0;
0039     }
0040 
0041     QFile infile(QString::fromLocal8Bit(argv[1]));
0042     if (!infile.open(QFile::ReadOnly)) {
0043         fprintf(stderr, "Error opening input file\n");
0044         return 1;
0045     }
0046 
0047     QFile outfile(QString::fromLocal8Bit(argv[2]));
0048     if (!outfile.open(QFile::WriteOnly | QFile::Truncate)) {
0049         fprintf(stderr, "Error opening output file\n");
0050         return 1;
0051     }
0052 
0053     int         count = 0;
0054     QString     name;
0055     QTextStream ts(&infile);
0056     while (!ts.atEnd()) {
0057         QString line = ts.readLine();
0058         if (line.startsWith(QLatin1Char('#')))
0059             continue;
0060         line = line.trimmed();
0061         if (line.isEmpty())
0062             continue;
0063 
0064         if (line.startsWith(QLatin1String("CKA_LABEL"))) {
0065             const QStringList list = splitWithQuotes(line, ' ');
0066             if (list.count() != 3)
0067                 continue;
0068 
0069             name = list[2];
0070             // make an output filename based on the name
0071             // outname = name.replace(QRegExp("\\/"), "_")
0072             //  .replace(QRegExp("\\s+"), "_")
0073             //  .replace(QRegExp("[()]"), "=")
0074             //  .replace(QRegExp(","), "_") + ".pem";
0075             continue;
0076         } else if (line == QLatin1String("CKA_VALUE MULTILINE_OCTAL")) {
0077             QByteArray buf;
0078             while (!ts.atEnd()) {
0079                 line = ts.readLine().trimmed();
0080                 if (line == QLatin1String("END"))
0081                     break;
0082                 static const QRegularExpression rx(QStringLiteral("\\\\([0-3][0-7][0-7])"));
0083                 int                             pos   = 0;
0084                 QRegularExpressionMatch         match = rx.match(line, pos);
0085                 while (match.hasMatch()) {
0086                     QString str = match.captured(1);
0087                     uchar   c   = str.toInt(nullptr, 8);
0088                     buf.append(c);
0089                     pos += match.capturedLength();
0090                     match = rx.match(line, pos);
0091                 }
0092             }
0093 
0094             printf(">> [%s], %d bytes\n", qPrintable(name), int(buf.size()));
0095 
0096             QTextStream ts(&outfile);
0097             ts << "-----BEGIN CERTIFICATE-----" << '\n';
0098             QCA::Base64 enc;
0099             enc.setLineBreaksEnabled(true);
0100             enc.setLineBreaksColumn(64);
0101             ts << enc.arrayToString(buf) << '\n';
0102             ts << "-----END CERTIFICATE-----" << '\n';
0103 
0104             ++count;
0105         }
0106     }
0107     printf("Wrote %d certs to [%s]\n", count, argv[2]);
0108 
0109     return 0;
0110 }
0111 
0112 int find_notchar(const QString &str, char c, int offset)
0113 {
0114     for (int n = offset; n < str.length(); ++n) {
0115         if (str[n] != QLatin1Char(c))
0116             return n;
0117     }
0118     return -1;
0119 }
0120 
0121 QStringList splitWithQuotes(const QString &in, char c)
0122 {
0123     QStringList result;
0124     int         at = 0;
0125     if (in[at] == QLatin1Char(c))
0126         at = find_notchar(in, c, at);
0127     while (at != -1) {
0128         bool    quote = false;
0129         int     end;
0130         QString str;
0131         if (in[at] == QLatin1Char('\"')) {
0132             quote = true;
0133             ++at;
0134             end = in.indexOf(QLatin1Char('\"'), at);
0135             if (end == -1)
0136                 break;
0137         } else
0138             end = in.indexOf(QLatin1Char(c), at);
0139 
0140         if (end != -1)
0141             str = in.mid(at, end - at);
0142         else
0143             str = in.mid(at);
0144 
0145         if (!str.isEmpty())
0146             result += str;
0147 
0148         if (quote)
0149             end = in.indexOf(QLatin1Char(c), end);
0150 
0151         if (end != -1)
0152             at = find_notchar(in, c, end);
0153         else
0154             at = -1;
0155     }
0156     return result;
0157 }