Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
a5771c21fd12f716fabe29871a7696e07cb2cf68
[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;   
53         conn = curl_easy_init();
54         
55         struct CardDAVCURLPasser {
56         
57                 CardDAV *Data;
58                 bool HeaderMode = TRUE;
59         
60         } CardDAVHeader, CardDAVFooter;
62         CardDAVHeader.Data = this;
63         CardDAVHeader.HeaderMode = TRUE;
64         
65         CardDAVFooter.Data = this;
66         CardDAVFooter.HeaderMode = FALSE;
68         wxString Data1;
69         wxString Data2;
70         
71         ServerAddressURL = ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/") + ServerPrefix + ServerFilenameLocation;
72         ServerAddressSSL = wxT("https://") + ServerAddressURL;
73         ServerAddressNormal = wxT("http://") + ServerAddressURL;
74         
75         ServerAuth = ServerUser + wxT(":") + ServerPass;
77         std::map<int,int>::iterator ActIter;
78         struct UploadDataStruc UploadData;
79         
80         ActIter = ActivityListPtr->find((int)ItemIndex);
81         
82         // Try SSL first.
84         if (ServerSSL){
86                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
87                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
88                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
89                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
90                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
91                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);             
92                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
93                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
94                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
95                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
96                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
98                 ServerCertFilename = GetAccountDir(ServerAccount, TRUE);
100                 if (wxFile::Exists(ServerCertFilename) == TRUE){
101                 
102                         curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 1);
103                         curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 2);
104                         curl_easy_setopt(conn, CURLOPT_CAINFO, (const char*)ServerCertFilename.mb_str(wxConvUTF8));
105                 
106                 }
108                 claconncode = (curl_easy_perform(conn));
110                 // If CURLE_PEER_FAILED_VERIFICATION is returned, retry without
111                 // the local certificate in use.
113                 if (claconncode == CURLE_PEER_FAILED_VERIFICATION){
114                         
115                         curl_easy_cleanup(conn);
116                         conn = curl_easy_init();
117                         
118                         curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
119                         curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
120                         curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
121                         curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
122                         curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
123                         curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);             
124                         curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
125                         curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
126                         curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
127                         curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
128                         curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
129                         
130                         claconncode = (curl_easy_perform(conn));
131                         
132                         // If claconncode is CURLE_OK then delete the certificate file as that
133                         // is no longer needed.
134                         
135                         if (claconncode == CURLE_OK){
136                         
137                                 // Delete the certificate file.
138                                 
139                                 wxRemoveFile(ServerCertFilename);
140                         
141                         }
142                 
143                 }
145                 // Check if it fails with a CURLE_SSL_CACERT then compare
146                 // the certificates as PEM files.
147                 
148                 if (claconncode == CURLE_SSL_CACERT && wxFile::Exists(ServerCertFilename) == TRUE){
149                 
150                         CURL *sslerrconn;
151                         sslerrconn = curl_easy_init();
152                         CURLcode sslerrconncode;
154                         wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
156                         curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
157                         curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 1L);
158                         curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
159                         curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
160                         curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
161                         curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);               
162                         curl_easy_setopt(sslerrconn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
163                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
164                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
165                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
166                         curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
167                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
168                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYHOST, 0);
169                         curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
170                 
171                         wxString SSLLocalData;
172                         wxString SSLServerData;
173                 
174                         sslerrconncode = (curl_easy_perform(sslerrconn));
175                 
176                         SSLCertCol = BuildSSLCollection(sslerrconn);
177                         std::map<int, SSLCertData>::iterator SSLCDIter = SSLCertCol.SSLCollection.find(0);
178                         std::multimap<wxString,wxString>::iterator SSLDataIter = SSLCDIter->second.CertData.find(wxT("Cert"));
179                         
180                         wxFFile SSLLocalFile;
181                         
182 #if wxABI_VERSION < 20900
183                         SSLLocalFile.Open(ServerCertFilename.c_str(), wxT("r"));
184 #else
185                         SSLLocalFile.Open(ServerCertFilename, wxT("r"));
186 #endif  
187         
188                         // Load the recovery database for tasks not done.
189         
190                         if (SSLLocalFile.IsOpened() == TRUE){
191         
192                                 SSLLocalFile.ReadAll(&SSLLocalData, wxConvAuto());
193                 
194         
195                         }
196                         
197                         SSLServerData = SSLDataIter->second;
198                         
199                         if (SSLLocalData == SSLServerData){
200                         
201                                 // Server key matches with local key so retry with CURLOPT_SSL_VERIFYPEER
202                                 // and CURLOPT_SSL_VERIFYHOST off.
203                         
204                                 curl_easy_cleanup(conn);
205                                 conn = curl_easy_init();
206                                 
207                                 PageData.clear();
208                                 PageHeader.clear();
209                         
210                                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressSSL.mb_str(wxConvUTF8));
211                                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
212                                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
213                                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
214                                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
215                                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);             
216                                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
217                                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
218                                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
219                                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
220                                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
221                                 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYHOST, 0);
222                                 curl_easy_setopt(conn, CURLOPT_SSL_VERIFYPEER, 0);
223                                                         
224                                 claconncode = (curl_easy_perform(conn));
225                                 
226                                 MatchingCert = TRUE;
227                         
228                         }
229                         
230                         if (MatchingCert == FALSE){
231                 
232                                 claconncode = CURLE_SSL_CACERT;
233                                 return;
234                 
235                         }
236                         
237                         curl_easy_cleanup(sslerrconn);
238                 
239                 }
240                 
241                 // Sort out SSL error.
242                 
243                 // When SSL cert error occurs, connect again and fetch certificates.
244                 // Display a message to the user explaining that an invalid
245                 // certificate has been given and let the user decide what
246                 // to do next.
248                 if (claconncode == CURLE_OK){
250                 } else if (claconncode == CURLE_SSL_CACERT || claconncode == CURLE_PEER_FAILED_VERIFICATION){
251                 
252                         CURL *sslerrconn;
253                         sslerrconn = curl_easy_init();
254                         CURLcode sslerrconncode;
255                 
256                         wxString ServerAddressOnly = wxT("https://") + ServerAddress + wxT(":") + wxString::Format(wxT("%i"), ServerPort) + wxT("/");
257                 
258                         // Replace conn with sslerrconn!
259                 
260                         curl_easy_setopt(sslerrconn, CURLOPT_URL, (const char*)ServerAddressOnly.mb_str(wxConvUTF8));
261                         curl_easy_setopt(sslerrconn, CURLOPT_NOPROGRESS, 0);
262                         curl_easy_setopt(sslerrconn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
263                         curl_easy_setopt(sslerrconn, CURLOPT_TIMEOUT, 60);
264                         curl_easy_setopt(sslerrconn, CURLOPT_FAILONERROR, TRUE);
265                         curl_easy_setopt(sslerrconn, CURLOPT_USERAGENT, XSDAB_USERAGENT);
266                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEFUNCTION, WritebackFunc);
267                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEDATA, &PageData);
268                         curl_easy_setopt(sslerrconn, CURLOPT_WRITEHEADER, &PageHeader);
269                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSDATA, this);
270                         curl_easy_setopt(sslerrconn, CURLOPT_PROGRESSFUNCTION, ProgressFunc);
271                         curl_easy_setopt(sslerrconn, CURLOPT_NOSIGNAL, 1);
272                         curl_easy_setopt(sslerrconn, CURLOPT_SSL_VERIFYPEER, 0);
273                         curl_easy_setopt(sslerrconn, CURLOPT_CERTINFO, 1);
274                                         
275                         sslerrconncode = (curl_easy_perform(sslerrconn));
277                         SSLCertCol = BuildSSLCollection(sslerrconn);
278                         SSLCertCol.SuccessCode = 1;
280                         return;
281                 
282                 } else if (claconncode == CURLE_HTTP_RETURNED_ERROR){
283                 
284                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
285                                         curl_easy_strerror(claconncode));
286                         int http_code = 0;
287                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
288                         fprintf(stderr, "Error code was: %d\n", http_code);
289                                         
290                         return;
291                 
292                 } else {
294                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
295                                         curl_easy_strerror(claconncode));
296                         int http_code = 0;
297                         curl_easy_getinfo(conn, CURLINFO_RESPONSE_CODE, &http_code);
298                         fprintf(stderr, "Error code was: %d\n", http_code);
300                         return;
302                 }
303                 
304         } else {
305         
306                 // No SSL.
307                 
308                 wxString EmptyString;
309                 
310                 curl_easy_setopt(conn, CURLOPT_URL, (const char*)ServerAddressNormal.mb_str(wxConvUTF8));
311                 curl_easy_setopt(conn, CURLOPT_NOPROGRESS, 1L);
312                 curl_easy_setopt(conn, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
313                 curl_easy_setopt(conn, CURLOPT_TIMEOUT, 60);
314                 curl_easy_setopt(conn, CURLOPT_FAILONERROR, TRUE);
315                 curl_easy_setopt(conn, CURLOPT_USERAGENT, XSDAB_USERAGENT);             
316                 curl_easy_setopt(conn, CURLOPT_USERPWD, (const char*)ServerAuth.mb_str(wxConvUTF8));
317                 curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, WritebackFunc);
318                 curl_easy_setopt(conn, CURLOPT_WRITEDATA, &PageData);
319                 curl_easy_setopt(conn, CURLOPT_WRITEHEADER, &PageHeader);
320                 curl_easy_setopt(conn, CURLOPT_NOSIGNAL, 1);
321                 
322                 PageData.Clear();
323                 PageHeader.Clear();
324                 
325                 conncode = (curl_easy_perform(conn));
327                 if (conncode == CURLE_OK){
329                 } else if (conncode == CURLE_HTTP_RETURNED_ERROR){
330                 
331                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
332                                         curl_easy_strerror(conncode));
333                                         
334                         fprintf(stderr, "curl_easy_perform() HTTP code was: %i\n",
335                                         GetHTTPCode());
336                                         
337                         return;
338                 
339                 } else {
341                         fprintf(stderr, "curl_easy_perform() failed: %s\n",
342                                         curl_easy_strerror(conncode));
343                                 
344                         return;
346                 }
347                 
348         }
349         
350         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