// carddav-sslverify.cpp - CardDAV Object - SSL verification subroutines. // // (c) 2012-2015 Xestia Software Development. // // This file is part of Xestia Address Book. // // Xestia Address Book is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by the // Free Software Foundation, version 3 of the license. // // Xestia Address Book is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with Xestia Address Book. If not, see #include "carddav.h" #include "../version.h" #include #include #include #include #include #include #include #include "../vcard/vcard.h" #include "../common/dirs.h" CURLcode CardDAV::SSLVerifyTest(){ // Verify the SSL information. PageData.Clear(); PageHeader.Clear(); SSLStatus = TRUE; AuthPassed = TRUE; AbortConnection = FALSE; CURL *conn; CURL *connssldata; CURLcode conncode = CURLE_OK; wxString ServerAddressURL; wxString ServerAuth; wxString ServerAddressSSL; wxString ServerAddressNormal; conn = curl_easy_init(); wxString Data1; wxString Data2; ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/"); ServerAddressSSL = wxT("https://") + ServerAddressURL; if (ServerSSL){ union { struct curl_slist *certdata; struct curl_certinfo *certinfo; } ptr; ptr.certdata = NULL; // Setup two initial connections and attempt to get the certificate data. curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(conn, CURLOPT_CERTINFO, 1); curl_easy_setopt(conn, CURLOPT_VERBOSE, 1L); curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, curlerrbuffer); curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader); #if defined(__APPLE__) || defined(__WIN32__) SetConnectionObject(conn); #else if (ServerAccount != ""){ wxString ServerCertFilename = GetAccountDir(ServerAccount, TRUE); if (wxFile::Exists(ServerCertFilename) == TRUE){ curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2); curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8)); } } #endif conncode = (curl_easy_perform(conn)); // Check if the SSL certificate is valid or self-signed or some other // error occured. if (conncode == CURLE_OK){ // Connection is OK. Do nothing. *ServerResult = TRUE; #if !defined(__APPLE__) && !defined(__WIN32__) VerifyCertCollection = BuildSSLCollection(conn); #endif } else if (conncode == CURLE_SSL_CACERT || conncode == CURLE_SSL_CONNECT_ERROR || conncode == CURLE_PEER_FAILED_VERIFICATION){ connssldata = curl_easy_init(); // Retry but get the certificates without peer/host verification. curl_easy_setopt(connssldata, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8)); curl_easy_setopt(connssldata, CURLOPT_CERTINFO, 1); curl_easy_setopt(connssldata, CURLOPT_VERBOSE, 1L); curl_easy_setopt(connssldata, CURLOPT_ERRORBUFFER, curlerrbuffer); curl_easy_setopt(connssldata, CURLOPT_WRITEFUNCTION, WritebackFunc); curl_easy_setopt(connssldata, CURLOPT_WRITEDATA, &PageData); curl_easy_setopt(connssldata, CURLOPT_WRITEHEADER, &PageHeader); curl_easy_setopt(connssldata, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(connssldata, CURLOPT_SSL_VERIFYHOST, 0L); #if defined(__APPLE__) || defined(__WIN32__) SetConnectionObject(connssldata); #endif CURLcode certfetchcode; certfetchcode = (curl_easy_perform(connssldata)); #if !defined(__APPLE__) && !defined(__WIN32__) VerifyCertCollection = BuildSSLCollection(connssldata); if (certfetchcode == CURLE_OK){ curl_easy_getinfo(connssldata, CURLINFO_CERTINFO, &ptr.certdata); VerifyCertCollection = BuildSSLCollection(connssldata); } else { conncode = certfetchcode; } #endif *ServerResult = FALSE; } else { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(conncode)); ErrorMessage = wxString::Format(wxT("%s"), curl_easy_strerror(conncode)); *ServerResult = FALSE; } } curl_easy_cleanup(conn); return conncode; }