2011-09-21 4 views
2

Je dois échanger des données avec le serveur qui nécessite un certificat local (fichier .crt). J'essaie ceci:QNetworkRequest avec certificat local ssl

loginRequest = QNetworkRequest(QUrl("https://somesite.com/login")); 

QSslConfiguration sslConf = loginRequest.sslConfiguration(); 
QList<QSslCertificate> certs = QSslCertificate::fromPath(Preferences::certificatePath()); 
qDebug() << certs.first().issuerInfo(QSslCertificate::Organization); // prints name 
sslConf.setLocalCertificate(certs.first()); 
qDebug() << "is valid " << sslConf.localCertificate().isValid(); // true 
qDebug() << "is null " << sslConf.localCertificate().isNull(); // false 
qDebug() << "protocol " << sslConf.protocol(); // 0 
sslConf.setProtocol(QSsl::SslV3); // i also tried Qssl::AnyProtocol 
qDebug() << "protocol " << sslConf.protocol(); // 0 

// if i uncomment these i expect everithing to work 
//QSslConfiguration::setDefaultConfiguration(sslConf); 
//QSslSocket::addDefaultCaCertificate(certs.first()); 
//loginRequest.setSslConfiguration(sslConf); 

QObject::connect(connectionManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(printSslErrors2(QNetworkReply*,QList<QSslError>))); 

m_reply = connectionManager->get(loginRequest); 
QObject::connect(m_reply, SIGNAL(readyRead()), this, SLOT(getCookie())); 
QObject::connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(printSslErrors(QList<QSslError>))); 

Lorsque ce code exécute j'ai les messages suivants dans Wireshark (filtre: tcp & & ssl & & ip.addr == my_addr):

Client Hello 
ServerHello, Certificate 
Server Key Exchange, Certificate request, Server Hello Done 
Alert (level: Warning, Description: no certificate), client key exchange, change cipher spec, encrypted handshake message 
Alert (level: Fatal, Description: Handshake failure) 

Cela devrait - le code pour appliquer le certificat est commenté, mais la chose étrange - je ne reçois aucune erreur SSL de mon QNetworkAccessManager et QNetworkReply (slots printSslErrors et printSslErrors2).

Si je décommenter l'une de ces 3 lignes:

//QSslConfiguration::setDefaultConfiguration(sslConf); 
//QSslSocket::addDefaultCaCertificate(certs.first()); 
//loginRequest.setSslConfiguration(sslConf); 

Je ne reçois rien dans Wireshark (quelques SYN, ACK et FIN messages tcp, mais pas le trafic HTTP ou ssl). En outre, il n'y a toujours pas d'erreurs de QNetworkAccessManager et QNetworkReply, donc je n'ai aucune idie ce qui ne va pas.

Y at-il une chance de faire Qt accepter mon certificat local ou peut-être il ya une partie 3d orientée qt-lib pour m'aider? P.S .: btw-ssl et https ont bien fonctionné il y a quelques jours, avant que le serveur ne soit modifié pour exiger des certificats côté client.

P.P.S .: le certificat est auto-signé si cela fait une différence. J'ai aussi essayé de 'l'installer' (le fichier p12) dans le système et à la fois Chrome et IE7 sont capables de l'utiliser et de communiquer avec le serveur.

Répondre

0

SOLUTION Partie I: Je résolu la plupart du temps ce (le manque de connexion), il y avait 2 raisons:

1er - le serveur apache réellement besoin clé privée (pour une raison inconnue, a jugé [ ici] [1]), comment ajouter la clé privée:

QFile x(Preferences::certificateKeyPath()); 
x.open(QIODevice::ReadOnly); 
pKey = QSslKey(x.readAll(),QSsl::Rsa); 
QSslError error1(QSslError::SelfSignedCertificate, certs.first()); 
QSslError error2(QSslError::CertificateUntrusted, certs.first()); 
QList<QSslError> expectedSslErrors; 
expectedSslErrors.append(error1); 
expectedSslErrors.append(error2); 

2d - le certificat que j'avais était pas très 'bon'. Je ne sais pas ce que cela signifie vraiment ou pourquoi cela ne fonctionnait pas, mais quand j'ai reçu un nouveau certificat de l'administrateur du serveur et ajouté la clé privée, la poignée de main a réussi.

Je ne sais toujours pas comment attraper sslErrors (par exemple pour montrer l'utilisateur que son certificat ne fonctionne pas), mais il est un bon début

SOLUTION, Partie II:

Résolu la dernière une partie de la question (kina a woraround).Il semble que QNetworkReply n'émette pas SslErrors est un bug (ou du moins il ne fonctionne pas tout le temps ou pour tous les sites web), trouvé [dans Qt bug tracker] [2]. Et la solution de contournement aussi à partir de là: sinse nous ne pouvons pas obtenir SslErrors, nous devons essayer et obtenir smth else - [erreur] [3], par exemple. Il ne donne pas d'informations détaillées sur ce qui s'est réellement passé, mais mieux que rien. Pour moi le code d'erreur 6 - "le protocole SSL/TLS a échoué et le canal crypté n'a pas pu être établi Le signal sslErrors() aurait dû être émis." est parfait (je ne garde rien d'autre):

QObject::connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleSslErrors(QNetworkReply::NetworkError))); 

La partie importante: si l'utilisateur a certificat incorrect et/ou clé - le signal est emited. Mais il est également émis si le certificat et la clé sont corrects. Il semble que l'authentification ne soit toujours pas parfaite, mais vous pouvez facilement l'arrêter avec

QObject :: connect (m_reply, SIGNAL (sslErrors (QList)), ceci, SLOT (printSslErrors (QList)));

Conclusion il semble qu'ils ont fixé un grand nombre de bugs SSL dans Qt 4.8, donc j'espère que la libération sera bientôt

1

Plan complet dans l'obscurité et part du principe que Qt peut en fait signaler une erreur mais que vous n'obtenez pas le signal.

Vous vous connectez les signaux de votre connectionManager à this avez-vous inclus la Q_OBJECT macro dans l'en-tête this?

Examinez également la sortie lorsque vous exécutez votre application car Qt peut signaler des problèmes de connexion des signaux/emplacements si c'est effectivement le cas ici.

+0

1. Ceci est un QMainWindow, il obtient le signal de bouton de connexion (celui-ci commence connexion séquence) donc je ne vois pas pourquoi d'autres signaux pourraient être ignorés 2. Il n'y a pas d'erreurs avec les signaux/slots. Tbh la seule erreur que je sais (qui est rapportée dans la fenêtre de sortie applicatiion) est sur le signal et le slot n'existe pas ou a des paramètres erronés – DarkWalker

+0

C'est bon si vous obtenez d'autres signaux dans votre classe QMainWindow. La vérification de la macro Q_OBJECT est la première chose que je fais quand j'ai des problèmes. J'espère que vous traquerez le vrai problème. – Matthew