~ubuntu-branches/ubuntu/wily/qca2/wily-proposed

« back to all changes in this revision

Viewing changes to src/qca_default.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2007-10-27 18:51:54 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071027185154-4ir9ys3h2q9fofrw
Tags: 2.0.0-2
Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2003-2005  Justin Karneges <justin@affinix.com>
 
2
 * Copyright (C) 2003-2007  Justin Karneges <justin@affinix.com>
3
3
 * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
4
4
 *
5
5
 * This library is free software; you can redistribute it and/or
22
22
 
23
23
#include <QMutex>
24
24
#include <QHash>
 
25
#include "qca_textfilter.h"
 
26
#include "qca_cert.h"
25
27
#include "qcaprovider.h"
26
28
 
27
29
#ifndef QCA_NO_SYSTEMSTORE
28
30
# include "qca_systemstore.h"
29
31
#endif
30
32
 
 
33
#define FRIENDLY_NAMES
 
34
 
31
35
namespace QCA {
32
36
 
33
37
class DefaultShared
129
133
  ghost@aladdin.com
130
134
 
131
135
 */
132
 
/* $Id: qca_default.cpp 681693 2007-06-29 21:34:01Z infiniti $ */
 
136
/* $Id: qca_default.cpp 697168 2007-08-07 01:46:20Z infiniti $ */
133
137
/*
134
138
  Independent implementation of MD5 (RFC 1321).
135
139
 
782
786
//----------------------------------------------------------------------------
783
787
// DefaultKeyStoreEntry
784
788
//----------------------------------------------------------------------------
 
789
 
 
790
// this escapes colons, commas, and newlines.  colons and commas so that they
 
791
//   are available as delimiters, and newlines so that our output can be a
 
792
//   single line of text.
785
793
static QString escape_string(const QString &in)
786
794
{
787
795
        QString out;
793
801
                        out += "\\c";
794
802
                else if(in[n] == ',')
795
803
                        out += "\\o";
 
804
                else if(in[n] == '\n')
 
805
                        out += "\\n";
796
806
                else
797
807
                        out += in[n];
798
808
        }
799
809
        return out;
800
810
}
801
811
 
802
 
static QString unescape_string(const QString &in)
 
812
static bool unescape_string(const QString &in, QString *_out)
803
813
{
804
814
        QString out;
805
815
        for(int n = 0; n < in.length(); ++n)
806
816
        {
807
817
                if(in[n] == '\\')
808
818
                {
809
 
                        if(n + 1 < in.length())
810
 
                        {
811
 
                                if(in[n + 1] == '\\')
812
 
                                        out += '\\';
813
 
                                else if(in[n + 1] == 'c')
814
 
                                        out += ':';
815
 
                                else if(in[n + 1] == 'o')
816
 
                                        out += ',';
817
 
                                ++n;
818
 
                        }
 
819
                        if(n + 1 >= in.length())
 
820
                                return false;
 
821
 
 
822
                        if(in[n + 1] == '\\')
 
823
                                out += '\\';
 
824
                        else if(in[n + 1] == 'c')
 
825
                                out += ':';
 
826
                        else if(in[n + 1] == 'o')
 
827
                                out += ',';
 
828
                        else if(in[n + 1] == 'n')
 
829
                                out += '\n';
 
830
                        else
 
831
                                return false;
 
832
                        ++n;
819
833
                }
820
834
                else
821
835
                        out += in[n];
822
836
        }
823
 
        return out;
824
 
}
825
 
 
826
 
static QString makeId(const QString &storeId, const QString &storeName, const QString &entryId, const QString &entryName, const QString &entryType, const QString &pem)
 
837
        *_out = out;
 
838
        return true;
 
839
}
 
840
 
 
841
static QString escape_stringlist(const QStringList &in)
 
842
{
 
843
        QStringList list;
 
844
        for(int n = 0; n < in.count(); ++n)
 
845
                list += escape_string(in[n]);
 
846
        return list.join(":");
 
847
}
 
848
 
 
849
static bool unescape_stringlist(const QString &in, QStringList *_out)
827
850
{
828
851
        QStringList out;
829
 
        out += escape_string("qca_def");
830
 
        out += escape_string(storeId);
831
 
        out += escape_string(storeName);
832
 
        out += escape_string(entryId);
833
 
        out += escape_string(entryName);
834
 
        out += escape_string(entryType);
835
 
        out += escape_string(pem);
836
 
        return out.join(":");
837
 
}
838
 
 
839
 
static bool parseId(const QString &in, QString *storeId, QString *storeName, QString *entryId, QString *entryName, QString *entryType, QString *pem)
840
 
{
841
852
        QStringList list = in.split(':');
 
853
        for(int n = 0; n < list.count(); ++n)
 
854
        {
 
855
                QString str;
 
856
                if(!unescape_string(list[n], &str))
 
857
                        return false;
 
858
                out += str;
 
859
        }
 
860
        *_out = out;
 
861
        return true;
 
862
}
 
863
 
 
864
// serialization format is a colon separated list of 7 escaped strings
 
865
//  0 - "qca_def_1" (header)
 
866
//  1 - store id
 
867
//  2 - store name
 
868
//  3 - entry id
 
869
//  4 - entry name
 
870
//  5 - entry type (e.g. "cert")
 
871
//  6 - string encoding of object (e.g. DER encoded in Base64)
 
872
static QString entry_serialize(const QString &storeId, const QString &storeName, const QString &entryId, const QString &entryName, const QString &entryType, const QString &data)
 
873
{
 
874
        QStringList out;
 
875
        out += "qca_def";
 
876
        out += storeId;
 
877
        out += storeName;
 
878
        out += entryId;
 
879
        out += entryName;
 
880
        out += entryType;
 
881
        out += data;
 
882
        return escape_stringlist(out);
 
883
}
 
884
 
 
885
static bool entry_deserialize(const QString &in, QString *storeId, QString *storeName, QString *entryId, QString *entryName, QString *entryType, QString *data)
 
886
{
 
887
        QStringList list;
 
888
        if(!unescape_stringlist(in, &list))
 
889
                return false;
842
890
        if(list.count() != 7)
843
891
                return false;
844
 
        QString header = unescape_string(list[0]);
845
 
        if(header != "qca_def")
 
892
        if(list[0] != "qca_def")
846
893
                return false;
847
 
        *storeId   = unescape_string(list[1]);
848
 
        *storeName = unescape_string(list[2]);
849
 
        *entryId   = unescape_string(list[3]);
850
 
        *entryName = unescape_string(list[4]);
851
 
        *entryType = unescape_string(list[5]);
852
 
        *pem       = unescape_string(list[6]);
 
894
        *storeId   = list[1];
 
895
        *storeName = list[2];
 
896
        *entryId   = list[3];
 
897
        *entryName = list[4];
 
898
        *entryType = list[5];
 
899
        *data      = list[6];
853
900
        return true;
854
901
}
855
902
 
856
903
class DefaultKeyStoreEntry : public KeyStoreEntryContext
857
904
{
858
905
public:
859
 
        KeyStoreEntry::Type item_type;
860
 
        QString item_id, _storeId, _storeName;
 
906
        KeyStoreEntry::Type _type;
 
907
        QString _id, _name, _storeId, _storeName;
861
908
        Certificate _cert;
862
909
        CRL _crl;
863
 
        QString item_save;
864
 
 
865
 
        QString item_name;
 
910
        mutable QString _serialized;
866
911
 
867
912
        DefaultKeyStoreEntry(const Certificate &cert, const QString &storeId, const QString &storeName, Provider *p) : KeyStoreEntryContext(p)
868
913
        {
 
914
                _type = KeyStoreEntry::TypeCertificate;
869
915
                _storeId = storeId;
870
916
                _storeName = storeName;
871
917
                _cert = cert;
872
 
                item_type = KeyStoreEntry::TypeCertificate;
873
918
        }
874
919
 
875
920
        DefaultKeyStoreEntry(const CRL &crl, const QString &storeId, const QString &storeName, Provider *p) : KeyStoreEntryContext(p)
876
921
        {
 
922
                _type = KeyStoreEntry::TypeCRL;
877
923
                _storeId = storeId;
878
924
                _storeName = storeName;
879
925
                _crl = crl;
880
 
                item_type = KeyStoreEntry::TypeCRL;
881
 
        }
882
 
 
883
 
        DefaultKeyStoreEntry(const DefaultKeyStoreEntry &from) : KeyStoreEntryContext(from)
884
 
        {
885
 
        }
886
 
 
887
 
        ~DefaultKeyStoreEntry()
888
 
        {
889
926
        }
890
927
 
891
928
        virtual Provider::Context *clone() const
895
932
 
896
933
        virtual KeyStoreEntry::Type type() const
897
934
        {
898
 
                return item_type;
 
935
                return _type;
899
936
        }
900
937
 
901
938
        virtual QString id() const
902
939
        {
903
 
                return item_id;
 
940
                return _id;
904
941
        }
905
942
 
906
943
        virtual QString name() const
907
944
        {
908
 
                return item_name;
909
 
        }
910
 
 
911
 
        QString makeName() const
912
 
        {
913
 
                // use the common name, else orgname
914
 
                if(item_type == KeyStoreEntry::TypeCertificate)
915
 
                {
916
 
                        QString str = _cert.commonName();
917
 
                        if(str.isEmpty())
918
 
                                str = _cert.subjectInfo().value(Organization);
919
 
                        return str;
920
 
                }
921
 
                else
922
 
                        return _crl.issuerInfo().value(CommonName);
 
945
                return _name;
923
946
        }
924
947
 
925
948
        virtual QString storeId() const
944
967
 
945
968
        virtual QString serialize() const
946
969
        {
947
 
                return item_save;
 
970
                if(_serialized.isEmpty())
 
971
                {
 
972
                        QString typestr;
 
973
                        QString datastr;
 
974
 
 
975
                        if(_type == KeyStoreEntry::TypeCertificate)
 
976
                        {
 
977
                                typestr = "cert";
 
978
                                datastr = Base64().arrayToString(_cert.toDER());
 
979
                        }
 
980
                        else
 
981
                        {
 
982
                                typestr = "crl";
 
983
                                datastr = Base64().arrayToString(_crl.toDER());
 
984
                        }
 
985
 
 
986
                        _serialized = entry_serialize(_storeId, _storeName, _id, _name, typestr, datastr);
 
987
                }
 
988
 
 
989
                return _serialized;
 
990
        }
 
991
 
 
992
        static DefaultKeyStoreEntry *deserialize(const QString &in, Provider *provider)
 
993
        {
 
994
                QString storeId, storeName, id, name, typestr, datastr;
 
995
 
 
996
                if(entry_deserialize(in, &storeId, &storeName, &id, &name, &typestr, &datastr))
 
997
                {
 
998
                        QByteArray data = Base64().stringToArray(datastr).toByteArray();
 
999
                        DefaultKeyStoreEntry *c;
 
1000
 
 
1001
                        if(typestr == "cert")
 
1002
                        {
 
1003
                                Certificate cert = Certificate::fromDER(data);
 
1004
                                if(cert.isNull())
 
1005
                                        return 0;
 
1006
                                c = new DefaultKeyStoreEntry(cert, storeId, storeName, provider);
 
1007
                        }
 
1008
                        else if(typestr == "crl")
 
1009
                        {
 
1010
                                CRL crl = CRL::fromDER(data);
 
1011
                                if(crl.isNull())
 
1012
                                        return 0;
 
1013
                                c = new DefaultKeyStoreEntry(crl, storeId, storeName, provider);
 
1014
                        }
 
1015
                        else
 
1016
                                return 0;
 
1017
 
 
1018
                        c->_id = id;
 
1019
                        c->_name = name;
 
1020
                        c->_serialized = in;
 
1021
                        return c;
 
1022
                }
 
1023
                return 0;
 
1024
        }
 
1025
 
 
1026
        QString simpleId() const
 
1027
        {
 
1028
                if(_type == KeyStoreEntry::TypeCertificate)
 
1029
                        return QString::number(qHash(_cert.toDER()));
 
1030
                else
 
1031
                        return QString::number(qHash(_crl.toDER()));
 
1032
        }
 
1033
 
 
1034
        QString simpleName() const
 
1035
        {
 
1036
                // use the common name, else orgname
 
1037
                if(_type == KeyStoreEntry::TypeCertificate)
 
1038
                {
 
1039
                        QString str = _cert.commonName();
 
1040
                        if(str.isEmpty())
 
1041
                                str = _cert.subjectInfo().value(Organization);
 
1042
                        return str;
 
1043
                }
 
1044
                else
 
1045
                        return _crl.issuerInfo().value(CommonName);
948
1046
        }
949
1047
};
950
1048
 
955
1053
{
956
1054
        Q_OBJECT
957
1055
public:
958
 
        bool ready;
 
1056
        bool x509_supported;
959
1057
        DefaultShared *shared;
960
1058
 
961
1059
        DefaultKeyStoreList(Provider *p, DefaultShared *_shared) : KeyStoreListContext(p), shared(_shared)
973
1071
 
974
1072
        virtual void start()
975
1073
        {
976
 
                ready = false;
 
1074
                x509_supported = false;
977
1075
 
978
 
#ifndef QCA_NO_SYSTEMSTORE
979
 
                if(qca_have_systemstore() &&
980
 
                   isSupported("cert") &&
981
 
                   isSupported("crl"))
982
 
                {
983
 
                        ready = true;
984
 
                }
985
 
#endif
986
1076
                QMetaObject::invokeMethod(this, "busyEnd", Qt::QueuedConnection);
987
1077
        }
988
1078
 
989
1079
        virtual QList<int> keyStores()
990
1080
        {
 
1081
                if(!x509_supported)
 
1082
                {
 
1083
                        if(isSupported("cert") && isSupported("crl"))
 
1084
                                x509_supported = true;
 
1085
                }
 
1086
 
 
1087
                bool have_systemstore = false;
 
1088
#ifndef QCA_NO_SYSTEMSTORE
 
1089
                if(shared->use_system())
 
1090
                        have_systemstore = qca_have_systemstore();
 
1091
#endif
 
1092
 
991
1093
                QList<int> list;
992
 
                if(ready || !shared->roots_file().isEmpty())
 
1094
 
 
1095
                // system store only shows up if the OS store is available or
 
1096
                //   there is a configured store file
 
1097
                if(x509_supported && (have_systemstore || !shared->roots_file().isEmpty()))
993
1098
                        list += 0;
 
1099
 
994
1100
                return list;
995
1101
        }
996
1102
 
1024
1130
                QList<Certificate> certs;
1025
1131
                QList<CRL> crls;
1026
1132
 
1027
 
                if(ready && shared->use_system())
 
1133
                if(shared->use_system())
1028
1134
                {
1029
1135
                        CertificateCollection col;
1030
1136
#ifndef QCA_NO_SYSTEMSTORE
1042
1148
                        crls += col.crls();
1043
1149
                }
1044
1150
 
1045
 
                //QStringList names = makeFriendlyNames(certs);
1046
 
                int n;
1047
 
                for(n = 0; n < certs.count(); ++n)
 
1151
#ifdef FRIENDLY_NAMES
 
1152
                QStringList names = makeFriendlyNames(certs);
 
1153
#endif
 
1154
                for(int n = 0; n < certs.count(); ++n)
1048
1155
                {
1049
1156
                        DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(certs[n], storeId(0), name(0), provider());
1050
 
                        //c->item_id = QString::number(n);
1051
 
                        QString ename = c->makeName();
1052
 
                        //QString ename = names[n];
1053
 
                        QString eid = QString::number(qHash(certs[n].toDER()));
1054
 
                        c->item_name = ename;
1055
 
                        c->item_id = eid;
1056
 
                        c->item_save = makeId(storeId(0), name(0), eid, ename, "cert", certs[n].toPEM());
 
1157
                        c->_id = c->simpleId();
 
1158
#ifdef FRIENDLY_NAMES
 
1159
                        c->_name = names[n];
 
1160
#else
 
1161
                        c->_name = c->simpleName();
 
1162
#endif
1057
1163
                        out.append(c);
1058
1164
                }
1059
 
                for(n = 0; n < crls.count(); ++n)
 
1165
 
 
1166
                for(int n = 0; n < crls.count(); ++n)
1060
1167
                {
1061
1168
                        DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(crls[n], storeId(0), name(0), provider());
1062
 
                        QString ename = c->makeName();
1063
 
                        QString eid = QString::number(qHash(certs[n].toDER()));
1064
 
                        c->item_name = ename;
1065
 
                        c->item_id = eid;
1066
 
                        c->item_save = makeId(storeId(0), name(0), eid, ename, "crl", crls[n].toPEM());
 
1169
                        c->_id = c->simpleId();
 
1170
                        c->_name = c->simpleName();
1067
1171
                        out.append(c);
1068
1172
                }
1069
1173
 
1070
1174
                return out;
1071
1175
        }
1072
1176
 
1073
 
        // TODO
1074
1177
        virtual KeyStoreEntryContext *entryPassive(const QString &serialized)
1075
1178
        {
1076
 
                QString storeId, storeName, eid, ename, etype, pem;
1077
 
                if(parseId(serialized, &storeId, &storeName, &eid, &ename, &etype, &pem))
1078
 
                {
1079
 
                        if(etype == "cert")
1080
 
                        {
1081
 
                                Certificate cert = Certificate::fromPEM(pem);
1082
 
                                if(cert.isNull())
1083
 
                                        return 0;
1084
 
                                DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(cert, storeId, storeName, provider());
1085
 
                                c->item_name = ename;
1086
 
                                c->item_id = eid;
1087
 
                                c->item_save = serialized;
1088
 
                                return c;
1089
 
                        }
1090
 
                        else if(etype == "crl")
1091
 
                        {
1092
 
                                CRL crl = CRL::fromPEM(pem);
1093
 
                                if(crl.isNull())
1094
 
                                        return 0;
1095
 
                                DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(crl, storeId, storeName, provider());
1096
 
                                c->item_name = ename;
1097
 
                                c->item_id = eid;
1098
 
                                c->item_save = serialized;
1099
 
                                return c;
1100
 
                        }
1101
 
                }
1102
 
                return 0;
 
1179
                return DefaultKeyStoreEntry::deserialize(serialized, provider());
1103
1180
        }
1104
1181
};
1105
1182
 
1106
1183
//----------------------------------------------------------------------------
1107
1184
// DefaultProvider
1108
1185
//----------------------------------------------------------------------------
 
1186
static bool unescape_config_stringlist(const QString &in, QStringList *_out)
 
1187
{
 
1188
        QStringList out;
 
1189
        QStringList list = in.split(',');
 
1190
        for(int n = 0; n < list.count(); ++n)
 
1191
        {
 
1192
                QString str;
 
1193
                if(!unescape_string(list[n], &str))
 
1194
                        return false;
 
1195
                out += str.trimmed();
 
1196
        }
 
1197
        *_out = out;
 
1198
        return true;
 
1199
}
 
1200
 
1109
1201
class DefaultProvider : public Provider
1110
1202
{
1111
1203
public:
1178
1270
                QString skip_plugins_str = config["skip_plugins"].toString();
1179
1271
                QString plugin_priorities_str = config["plugin_priorities"].toString();
1180
1272
 
1181
 
                QStringList skip_plugins = skip_plugins_str.split(",");
1182
 
                for(int n = 0; n < skip_plugins.count(); ++n)
1183
 
                {
1184
 
                        QString &s = skip_plugins[n];
1185
 
                        s = unescape_string(s).trimmed();
1186
 
                }
1187
 
 
1188
 
                QStringList plugin_priorities = plugin_priorities_str.split(",");
 
1273
                QStringList tmp;
 
1274
 
 
1275
                QStringList skip_plugins;
 
1276
                if(unescape_config_stringlist(skip_plugins_str, &tmp))
 
1277
                        skip_plugins = tmp;
 
1278
 
 
1279
                QStringList plugin_priorities;
 
1280
                if(unescape_config_stringlist(plugin_priorities_str, &tmp))
 
1281
                        plugin_priorities = tmp;
 
1282
 
1189
1283
                for(int n = 0; n < plugin_priorities.count(); ++n)
1190
1284
                {
1191
1285
                        QString &s = plugin_priorities[n];
1192
 
                        s = unescape_string(s).trimmed();
1193
1286
 
1194
1287
                        // make sure the entry ends with ":number"
1195
1288
                        int x = s.indexOf(':');