Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Altered CardDAV object to accommodate for SSL support for OS X (and other OSes in...
[xestiaab/.git] / source / carddav / carddav-servercontact.cpp
1 // carddav-servercontact.cpp - CardDAV Object - Server Contact subroutines.
2 //
3 // (c) 2012-2015 Xestia Software Development.
4 //
5 // This file is part of Xestia Address Book.
6 //
7 // Xestia Address Book is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by the
9 // Free Software Foundation, version 3 of the license.
10 //
11 // Xestia Address Book is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with Xestia Address Book. If not, see <http://www.gnu.org/licenses/>
19 #include "carddav.h"
20 #include "../version.h"
21 #include <wx/wx.h>
22 #include <wx/tokenzr.h>
23 #include <wx/ffile.h>
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
26 #include <map>
27 #include <thread>
28 #include "../vcard/vcard.h"
29 #include "../common/dirs.h"
31 void CardDAV::GetServerContactData()
32 {
34         // Get the server contact data.
35         
36         PageData.Clear();
37         PageHeader.Clear();
39         SSLStatus = TRUE;
40         AuthPassed = TRUE;
41         AbortConnection = FALSE;
42         
43         wxString ServerCertFilename;
44         bool MatchingCert = FALSE;
46         CURL *conn;
47         CURLcode conncode;
48         wxString ServerAddressURL;
49         wxString ServerAuth;
50         wxString ServerAddressSSL;
51         wxString ServerAddressNormal;
52         
53         conn = curl_easy_init();
54         
55         SetConnectionObject(conn);
56         
57         struct CardDAVCURLPasser {
58         
59                 CardDAV *Data;
60                 bool HeaderMode = TRUE;
61         
62         } CardDAVHeader, CardDAVFooter;
64         CardDAVHeader.Data = this;
65         CardDAVHeader.HeaderMode = TRUE;
66         
67         CardDAVFooter.Data = this;
68         CardDAVFooter.HeaderMode = FALSE;
70         wxString Data1;
71         wxString Data2;
72         
73         ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + ServerFilenameLocation;
74         ServerAddressSSL = wxT("https://") + ServerAddressURL;
75         ServerAddressNormal = wxT("http://") + ServerAddressURL;
76         
77         ServerAuth = ServerUser + wxT(":") + ServerPass;
79         std::map<int,int>::iterator ActIter;
80         struct UploadDataStruc UploadData;
81         
82         ActIter = ActivityListPtr->find((int)ItemIndex);
83         
84         // Try SSL first.
86         if (ServerSSL){
88                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
89                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
90                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
91                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
92                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
93                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);             
94                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
95                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
96                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
97                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
98                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
100 #if defined(__APPLE__)
101                 
102 #else
103                 
104                 ServerCertFilename = GetAccountDir(ServerAccount, TRUE);
106                 if (wxFile::Exists(ServerCertFilename) == TRUE){
107                 
108                         curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
109                         curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
110                         curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
111                 
112                 }
114 #endif
115                 
116                 claconncode = (curl_easy_perform(conn));
118                 // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without
119                 // the local certificate in use.
121                 if (claconncode == CURLE_PEER_FAILED_VERIFICATION){
122                         
123                         curl_easy_cleanup(conn);
124                         conn = curl_easy_init();
125                         
126                         curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
127                         curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
128                         curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
129                         curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
130                         curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
131                         curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);             
132                         curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
133                         curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
134                         curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
135                         curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
136                         curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
137                         
138                         claconncode = (curl_easy_perform(conn));
139                         
140                         // If claconncode is CURLE_OK then delete the certificate file as that
141                         // is no longer needed.
142                         
143                         if (claconncode == CURLE_OK){
144                         
145                                 // Delete the certificate file.
146                                 
147                                 wxRemoveFile(ServerCertFilename);
148                         
149                         }
150                 
151                 }
153                 // Check if it fails with a CURLE_SSL_CACERT then compare
154                 // the certificates as PEM files.
155                 
156 #if defined(__APPLE__)
157                 
158 #else
159                 
160                 if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){
161                 
162                         CURL *sslerrconn;
163                         sslerrconn = curl_easy_init();
164                         CURLcode sslerrconncode;
166                         wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
168                         curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
169                         curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 1L);
170                         curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
171                         curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
172                         curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
173                         curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);               
174                         curl_easy_setopt(sslerrconn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
175                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
176                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
177                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
178                         curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
179                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
180                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYHOST, 0);
181                         curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
182                 
183                         wxString SSLLocalData;
184                         wxString SSLServerData;
185                 
186                         sslerrconncode = (curl_easy_perform(sslerrconn));
187                 
188                         SSLCertCol = BuildSSLCollection(sslerrconn);
189                         std::map<int, SSLCertData>::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0);
190                         std::multimap<wxString,wxString>::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert"));
191                         
192                         wxFFile SSLLocalFile;
193                         
194 #if wxABI_VERSION < 20900
195                         SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r"));
196 #else
197                         SSLLocalFile.Open(ServerCertFilename, wxT("r"));
198 #endif  
199         
200                         // Load the recovery database for tasks not done.
201         
202                         if (SSLLocalFile.IsOpened() == TRUE){
203         
204                                 SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto());
205                 
206         
207                         }
208                         
209                         SSLServerData = SSLDataIter->second;
210                         
211                         if (SSLLocalData == SSLServerData){
212                         
213                                 // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER
214                                 // and CURLOPT_SSL_VERIFYHOST off.
215                         
216                                 curl_easy_cleanup(conn);
217                                 conn = curl_easy_init();
218                                 
219                                 PageData.clear();
220                                 PageHeader.clear();
221                         
222                                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
223                                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
224                                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
225                                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
226                                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
227                                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);             
228                                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
229                                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
230                                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
231                                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
232                                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
233                                 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0);
234                                 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);
235                                                         
236                                 claconncode = (curl_easy_perform(conn));
237                                 
238                                 MatchingCert = TRUE;
239                         
240                         }
241                         
242                         if (MatchingCert == FALSE){
243                 
244                                 claconncode = CURLE_SSL_CACERT;
245                                 return;
246                 
247                         }
248                         
249                         curl_easy_cleanup(sslerrconn);
250                 
251                 }
252                 
253 #endif
254                 
255                 // Sort out SSL error.
256                 
257                 // When SSL cert error occurs, connect again and fetch certificates.
258                 // Display a message to the user explaining that an invalid
259                 // certificate has been given and let the user decide what
260                 // to do next.
262                 if (claconncode == CURLE_OK){
264                 } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){
265                 
266                         CURL *sslerrconn;
267                         sslerrconn = curl_easy_init();
268                         CURLcode sslerrconncode;
269                 
270                         wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
271                 
272                         // Replace conn with sslerrconn!
273                 
274                         curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
275                         curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
276                         curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
277                         curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
278                         curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
279                         curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
280                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
281                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
282                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
283                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
284                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
285                         curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
286                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
287                         curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
288                         
289                         SetConnectionObject(sslerrconn);
290                         
291                         sslerrconncode = (curl_easy_perform(sslerrconn));
293                         SSLCertCol = BuildSSLCollection(sslerrconn);
294                         SSLCertCol.SuccessCode = 1;
296                         return;
297                 
298                 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
299                 
300                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
301                                         curl_easy_strerror(claconncode));
302                         int http_code = 0;
303                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
304                         fprintf(stderr, "Error code was: %d\n", http_code);
305                                         
306                         return;
307                 
308                 } else {
310                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
311                                         curl_easy_strerror(claconncode));
312                         int http_code = 0;
313                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
314                         fprintf(stderr, "Error code was: %d\n", http_code);
316                         return;
318                 }
319                 
320         } else {
321         
322                 // No SSL.
323                 
324                 wxString EmptyString;
325                 
326                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
327                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
328                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
329                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
330                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
331                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);             
332                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
333                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
334                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
335                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
336                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
337                 
338                 PageData.Clear();
339                 PageHeader.Clear();
340                 
341                 conncode = (curl_easy_perform(conn));
343                 if (conncode == CURLE_OK){
345                 } else if (conncode == CURLE_HTTP_RETURNED_ERROR){
346                 
347                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
348                                         curl_easy_strerror(conncode));
349                                         
350                         fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n",
351                                         GetHTTPCode());
352                                         
353                         return;
354                 
355                 } else {
357                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
358                                         curl_easy_strerror(conncode));
359                                 
360                         return;
362                 }
363                 
364         }
365         
366         return;
Xestia Software Development
Yn Maystri
© 2006 - 2019 Xestia Software Development
Software

Xestia Address Book
Xestia Calendar
Development

Xestia Gelforn
Everything else

About
News
Privacy Policy