92bfdfebbc986ddbfa73cb839ed4dcf47fcfeb55
[public/netxms.git] / src / server / core / cert.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2007-2017 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: cert.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24 #include <nxcrypto.h>
25
26 #ifdef _WITH_ENCRYPTION
27
28 // WARNING! this hack works only for d2i_X509(); be careful when adding new code
29 #ifdef OPENSSL_CONST
30 # undef OPENSSL_CONST
31 #endif
32 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
33 # define OPENSSL_CONST const
34 #else
35 # define OPENSSL_CONST
36 #endif
37
38 #if OPENSSL_VERSION_NUMBER < 0x10000000L
39 inline int EVP_PKEY_id(EVP_PKEY *key)
40 {
41 return key->type;
42 }
43 #endif
44
45 /**
46 * Server certificate file information
47 */
48 TCHAR *g_serverCACertificatesPath = NULL;
49 TCHAR g_serverCertificatePath[MAX_PATH] = _T("");
50 TCHAR g_serverCertificateKeyPath[MAX_PATH] = _T("");
51 char g_serverCertificatePassword[MAX_PASSWORD] = "";
52
53 /**
54 * Server certificate
55 */
56 static ObjectRefArray<X509> s_serverCACertificates(8, 8);
57 static X509 *s_serverCertificate = NULL;
58 static EVP_PKEY *s_serverCertificateKey = NULL;
59
60 /**
61 * Trusted CA certificate store
62 */
63 static X509_STORE *s_trustedCertificateStore = NULL;
64 static Mutex s_certificateStoreLock;
65
66 /**
67 * Issue certificate signed with server's certificate
68 */
69 X509 *IssueCertificate(X509_REQ *request, const char *ou, const char *cn, int days)
70 {
71 nxlog_debug(4, _T("IssueCertificate: new certificate request (CN override: %hs, OU override: %hs)"),
72 (cn != NULL) ? cn : "<not set>", (ou != NULL) ? ou : "<not set>");
73
74 X509_NAME *requestSubject = X509_REQ_get_subject_name(request);
75 if (requestSubject == NULL)
76 {
77 nxlog_debug(4, _T("IssueCertificate: cannot get subject from certificate request"));
78 return NULL;
79 }
80
81 X509 *cert = X509_new();
82 if (cert == NULL)
83 {
84 nxlog_debug(4, _T("IssueCertificate: call to X509_new() failed"));
85 return NULL;
86 }
87
88 if (X509_set_version(cert, 2) != 1)
89 {
90 nxlog_debug(4, _T("IssueCertificate: call to X509_set_version() failed"));
91 X509_free(cert);
92 return NULL;
93 }
94
95 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
96 ASN1_INTEGER *serial = ASN1_INTEGER_new();
97 #else
98 ASN1_INTEGER *serial = M_ASN1_INTEGER_new();
99 #endif
100 ASN1_INTEGER_set(serial, 0);
101 int rc = X509_set_serialNumber(cert, serial);
102 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
103 ASN1_INTEGER_free(serial);
104 #else
105 M_ASN1_INTEGER_free(serial);
106 #endif
107 if (rc != 1)
108 {
109 nxlog_debug(4, _T("IssueCertificate: cannot set certificate serial number"));
110 X509_free(cert);
111 return NULL;
112 }
113
114 X509_NAME *subject;
115 if ((cn != NULL) || (ou != NULL))
116 {
117 subject = X509_NAME_dup(requestSubject);
118 if (subject != NULL)
119 {
120 if (ou != NULL)
121 {
122 int idx = X509_NAME_get_index_by_NID(subject, NID_organizationalUnitName, -1);
123 if (idx != -1)
124 X509_NAME_delete_entry(subject, idx);
125 if (!X509_NAME_add_entry_by_txt(subject, "OU", MBSTRING_UTF8, (const BYTE *)ou, -1, -1, 0))
126 nxlog_debug(4, _T("IssueCertificate: X509_NAME_add_entry_by_txt failed for OU=%hs"), ou);
127 }
128 if (cn != NULL)
129 {
130 int idx = X509_NAME_get_index_by_NID(subject, NID_commonName, -1);
131 if (idx != -1)
132 X509_NAME_delete_entry(subject, idx);
133 if (!X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_UTF8, (const BYTE *)cn, -1, -1, 0))
134 nxlog_debug(4, _T("IssueCertificate: X509_NAME_add_entry_by_txt failed for CN=%hs"), cn);
135 }
136 }
137 else
138 {
139 nxlog_debug(4, _T("IssueCertificate: call to X509_NAME_dup() failed"));
140 }
141 }
142 else
143 {
144 subject = requestSubject;
145 }
146
147 if (subject == NULL)
148 {
149 X509_free(cert);
150 return NULL;
151 }
152
153 rc = X509_set_subject_name(cert, subject);
154 if (subject != requestSubject)
155 X509_NAME_free(subject);
156 if (rc != 1)
157 {
158 nxlog_debug(4, _T("IssueCertificate: call to X509_set_subject_name() failed"));
159 X509_free(cert);
160 return NULL;
161 }
162
163 X509_NAME *issuerName = X509_get_subject_name(s_serverCertificate);
164 if (issuerName == NULL)
165 {
166 nxlog_debug(4, _T("IssueCertificate: cannot get CA subject name"));
167 X509_free(cert);
168 return NULL;
169 }
170
171 if (X509_set_issuer_name(cert, issuerName) != 1)
172 {
173 nxlog_debug(4, _T("IssueCertificate: call to X509_set_issuer_name() failed"));
174 X509_free(cert);
175 return NULL;
176 }
177
178 EVP_PKEY *pubkey = X509_REQ_get_pubkey(request);
179 if (pubkey == NULL)
180 {
181 nxlog_debug(4, _T("IssueCertificate: call to X509_REQ_get_pubkey() failed"));
182 X509_free(cert);
183 return NULL;
184 }
185
186 if (X509_REQ_verify(request, pubkey) != 1)
187 {
188 nxlog_debug(4, _T("IssueCertificate: certificate request verification failed"));
189 EVP_PKEY_free(pubkey);
190 X509_free(cert);
191 return NULL;
192 }
193
194 rc = X509_set_pubkey(cert, pubkey);
195 EVP_PKEY_free(pubkey);
196 if (rc != 1)
197 {
198 nxlog_debug(4, _T("IssueCertificate: call to X509_set_pubkey() failed"));
199 X509_free(cert);
200 return NULL;
201 }
202
203 if (X509_gmtime_adj(X509_get_notBefore(cert), 0) == NULL)
204 {
205 nxlog_debug(4, _T("IssueCertificate: cannot set start time"));
206 X509_free(cert);
207 return NULL;
208 }
209
210 if (X509_gmtime_adj(X509_get_notAfter(cert), days * 86400) == NULL)
211 {
212 nxlog_debug(4, _T("IssueCertificate: cannot set end time"));
213 X509_free(cert);
214 return NULL;
215 }
216
217 if (X509_sign(cert, s_serverCertificateKey, EVP_sha256()) == 0)
218 {
219 nxlog_debug(4, _T("IssueCertificate: call to X509_sign() failed"));
220 X509_free(cert);
221 return NULL;
222 }
223
224 char subjectName[1024];
225 X509_NAME_oneline(X509_get_subject_name(cert), subjectName, 1024);
226 nxlog_debug(4, _T("IssueCertificate: new certificate with subject \"%hs\" issued successfully"), subjectName);
227 return cert;
228 }
229
230 /**
231 * Get CN from certificate
232 */
233 bool GetCertificateSubjectField(X509 *cert, int nid, TCHAR *buffer, size_t size)
234 {
235 X509_NAME *subject = X509_get_subject_name(cert);
236 if (subject == NULL)
237 return false;
238
239 int idx = X509_NAME_get_index_by_NID(subject, nid, -1);
240 if (idx == -1)
241 return false;
242
243 X509_NAME_ENTRY *entry = X509_NAME_get_entry(subject, idx);
244 if (entry == NULL)
245 return false;
246
247 ASN1_STRING *data = X509_NAME_ENTRY_get_data(entry);
248 if (data == NULL)
249 return false;
250
251 unsigned char *text;
252 ASN1_STRING_to_UTF8(&text, data);
253 #ifdef UNICODE
254 MultiByteToWideChar(CP_UTF8, 0, (char *)text, -1, buffer, (int)size);
255 #else
256 utf8_to_mb((char *)text, -1, buffer, (int)size);
257 #endif
258 buffer[size - 1] = 0;
259 OPENSSL_free(text);
260 return true;
261 }
262
263 /**
264 * Get CN from certificate
265 */
266 bool GetCertificateCN(X509 *cert, TCHAR *buffer, size_t size)
267 {
268 return GetCertificateSubjectField(cert, NID_commonName, buffer, size);
269 }
270
271 /**
272 * Get OU from certificate
273 */
274 bool GetCertificateOU(X509 *cert, TCHAR *buffer, size_t size)
275 {
276 return GetCertificateSubjectField(cert, NID_organizationalUnitName, buffer, size);
277 }
278
279 /**
280 * Get country name from server certificate
281 */
282 bool GetServerCertificateCountry(TCHAR *buffer, size_t size)
283 {
284 if (s_serverCertificate == NULL)
285 return false;
286 return GetCertificateSubjectField(s_serverCertificate, NID_countryName, buffer, size);
287 }
288
289 /**
290 * Get organization name from server certificate
291 */
292 bool GetServerCertificateOrganization(TCHAR *buffer, size_t size)
293 {
294 if (s_serverCertificate == NULL)
295 return false;
296 return GetCertificateSubjectField(s_serverCertificate, NID_organizationName, buffer, size);
297 }
298
299 /**
300 * Create X509 certificate structure from login message
301 */
302 X509 *CertificateFromLoginMessage(NXCPMessage *pMsg)
303 {
304 UINT32 dwLen;
305 BYTE *pData;
306 OPENSSL_CONST BYTE *p;
307 X509 *pCert = NULL;
308
309 dwLen = pMsg->getFieldAsBinary(VID_CERTIFICATE, NULL, 0);
310 if (dwLen > 0)
311 {
312 pData = (BYTE *)malloc(dwLen);
313 pMsg->getFieldAsBinary(VID_CERTIFICATE, pData, dwLen);
314 p = pData;
315 pCert = d2i_X509(NULL, &p, dwLen);
316 free(pData);
317 }
318 return pCert;
319 }
320
321 /**
322 * Check public key
323 */
324 static BOOL CheckPublicKey(EVP_PKEY *key, const TCHAR *mappingData)
325 {
326 int pkeyLen;
327 unsigned char *ucBuf, *uctempBuf;
328 TCHAR *pkeyText;
329 BOOL valid;
330
331 pkeyLen = i2d_PublicKey(key, NULL);
332 ucBuf = (unsigned char *)malloc(pkeyLen +1);
333 uctempBuf = ucBuf;
334 i2d_PublicKey(key, &uctempBuf);
335
336 pkeyText = (TCHAR *)malloc((pkeyLen * 2 + 1) * sizeof(TCHAR));
337 BinToStr(ucBuf, pkeyLen, pkeyText);
338
339 valid = !_tcscmp(pkeyText, mappingData);
340
341 free(ucBuf);
342 free(pkeyText);
343
344 return valid;
345 }
346
347 /**
348 * Check ciertificate's CN
349 */
350 static BOOL CheckCommonName(X509 *cert, const TCHAR *cn)
351 {
352 TCHAR certCn[256];
353 if (!GetCertificateCN(cert, certCn, 256))
354 return FALSE;
355
356 nxlog_debug(3, _T("Certificate CN=\"%s\", user CN=\"%s\""), certCn, cn);
357 return !_tcsicmp(certCn, cn);
358 }
359
360 /**
361 * Validate user's certificate
362 */
363 BOOL ValidateUserCertificate(X509 *pCert, const TCHAR *pszLogin, BYTE *pChallenge, BYTE *pSignature,
364 UINT32 dwSigLen, int nMappingMethod, const TCHAR *pszMappingData)
365 {
366 BOOL bValid = FALSE;
367
368 char subjectName[1024];
369 X509_NAME_oneline(X509_get_subject_name(pCert), subjectName, 1024);
370 #ifdef UNICODE
371 WCHAR certSubject[1024];
372 MultiByteToWideChar(CP_UTF8, 0, subjectName, -1, certSubject, 1024);
373 #else
374 const char *certSubject = subjectName;
375 #endif
376
377 DbgPrintf(3, _T("Validating certificate \"%s\" for user %s"), certSubject, pszLogin);
378 s_certificateStoreLock.lock();
379
380 if (s_trustedCertificateStore == NULL)
381 {
382 DbgPrintf(3, _T("Cannot validate user certificate because certificate store is not initialized"));
383 s_certificateStoreLock.unlock();
384 return FALSE;
385 }
386
387 // Validate signature
388 EVP_PKEY *pKey = X509_get_pubkey(pCert);
389 if (pKey != NULL)
390 {
391 BYTE hash[SHA1_DIGEST_SIZE];
392 CalculateSHA1Hash(pChallenge, CLIENT_CHALLENGE_SIZE, hash);
393 switch(EVP_PKEY_id(pKey))
394 {
395 case EVP_PKEY_RSA:
396 bValid = RSA_verify(NID_sha1, hash, SHA1_DIGEST_SIZE, pSignature, dwSigLen, EVP_PKEY_get1_RSA(pKey));
397 break;
398 default:
399 DbgPrintf(3, _T("Unknown key type %d in certificate \"%s\" for user %s"), EVP_PKEY_id(pKey), certSubject, pszLogin);
400 break;
401 }
402 }
403
404 // Validate certificate
405 if (bValid)
406 {
407 X509_STORE_CTX *pStore = X509_STORE_CTX_new();
408 if (pStore != NULL)
409 {
410 X509_STORE_CTX_init(pStore, s_trustedCertificateStore, pCert, NULL);
411 bValid = X509_verify_cert(pStore);
412 X509_STORE_CTX_free(pStore);
413 DbgPrintf(3, _T("Certificate \"%s\" for user %s - validation %s"),
414 certSubject, pszLogin, bValid ? _T("successful") : _T("failed"));
415 }
416 else
417 {
418 TCHAR szBuffer[256];
419
420 DbgPrintf(3, _T("X509_STORE_CTX_new() failed: %s"), _ERR_error_tstring(ERR_get_error(), szBuffer));
421 bValid = FALSE;
422 }
423 }
424
425 // Check user mapping
426 if (bValid)
427 {
428 switch(nMappingMethod)
429 {
430 case USER_MAP_CERT_BY_SUBJECT:
431 bValid = !_tcsicmp(certSubject, CHECK_NULL_EX(pszMappingData));
432 break;
433 case USER_MAP_CERT_BY_PUBKEY:
434 bValid = CheckPublicKey(pKey, CHECK_NULL_EX(pszMappingData));
435 break;
436 case USER_MAP_CERT_BY_CN:
437 bValid = CheckCommonName(pCert, ((pszMappingData != NULL) && (*pszMappingData != 0)) ? pszMappingData : pszLogin);
438 break;
439 default:
440 DbgPrintf(3, _T("Invalid certificate mapping method %d for user %s"), nMappingMethod, pszLogin);
441 bValid = FALSE;
442 break;
443 }
444 }
445
446 s_certificateStoreLock.unlock();
447
448 return bValid;
449 }
450
451 /**
452 * Validate agent certificate
453 */
454 bool ValidateAgentCertificate(X509 *cert)
455 {
456 X509_STORE *store = X509_STORE_new();
457 if (store == NULL)
458 {
459 nxlog_debug(3, _T("ValidateAgentCertificate: cannot create certificate store"));
460 }
461
462 for(int i = 0; i < s_serverCACertificates.size(); i++)
463 X509_STORE_add_cert(store, s_serverCACertificates.get(i));
464 X509_STORE_add_cert(store, s_serverCertificate);
465 bool valid = false;
466
467 X509_STORE_CTX *ctx = X509_STORE_CTX_new();
468 if (ctx != NULL)
469 {
470 X509_STORE_CTX_init(ctx, store, cert, NULL);
471 valid = (X509_verify_cert(ctx) == 1);
472 X509_STORE_CTX_free(ctx);
473 }
474 else
475 {
476 TCHAR buffer[256];
477 nxlog_debug(3, _T("ValidateAgentCertificate: X509_STORE_CTX_new() failed: %s"), _ERR_error_tstring(ERR_get_error(), buffer));
478 }
479
480 X509_STORE_free(store);
481 return valid;
482 }
483
484 /**
485 * Reload certificates from database
486 */
487 void ReloadCertificates()
488 {
489 s_certificateStoreLock.lock();
490
491 if (s_trustedCertificateStore != NULL)
492 X509_STORE_free(s_trustedCertificateStore);
493
494 s_trustedCertificateStore = X509_STORE_new();
495 if (s_trustedCertificateStore != NULL)
496 {
497 // Add server's certificate as trusted
498 if (s_serverCertificate != NULL)
499 X509_STORE_add_cert(s_trustedCertificateStore, s_serverCertificate);
500
501 // Add server's CA certificate as trusted
502 for(int i = 0; i < s_serverCACertificates.size(); i++)
503 X509_STORE_add_cert(s_trustedCertificateStore, s_serverCACertificates.get(i));
504
505 TCHAR szBuffer[256];
506 _sntprintf(szBuffer, 256, _T("SELECT cert_data,subject FROM certificates WHERE cert_type=%d"), CERT_TYPE_TRUSTED_CA);
507 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
508 DB_RESULT hResult = DBSelect(hdb, szBuffer);
509 if (hResult != NULL)
510 {
511 int loaded = 0;
512 int count = DBGetNumRows(hResult);
513 for(int i = 0; i < count; i++)
514 {
515 TCHAR *certData = DBGetField(hResult, i, 0, NULL, 0);
516 if (certData != NULL)
517 {
518 size_t len = _tcslen(certData);
519 BYTE *binCert = (BYTE *)malloc(len);
520 StrToBin(certData, binCert, len);
521 free(certData);
522 OPENSSL_CONST BYTE *p = binCert;
523 X509 *cert = d2i_X509(NULL, &p, (long)len);
524 free(binCert);
525 if (cert != NULL)
526 {
527 if (X509_STORE_add_cert(s_trustedCertificateStore, cert))
528 {
529 loaded++;
530 }
531 else
532 {
533 TCHAR subject[256];
534 nxlog_write(MSG_CANNOT_ADD_CERT, EVENTLOG_ERROR_TYPE,
535 "ss", DBGetField(hResult, i, 1, subject, 256),
536 _ERR_error_tstring(ERR_get_error(), szBuffer));
537 }
538 X509_free(cert); // X509_STORE_add_cert increments reference count
539 }
540 else
541 {
542 TCHAR subject[256];
543 nxlog_write(MSG_CANNOT_LOAD_CERT, EVENTLOG_ERROR_TYPE,
544 "ss", DBGetField(hResult, i, 1, subject, 256),
545 _ERR_error_tstring(ERR_get_error(), szBuffer));
546 }
547 }
548 }
549 DBFreeResult(hResult);
550
551 if (loaded > 0)
552 nxlog_write(MSG_CA_CERTIFICATES_LOADED, EVENTLOG_INFORMATION_TYPE, "d", loaded);
553 }
554 DBConnectionPoolReleaseConnection(hdb);
555 }
556 else
557 {
558 TCHAR buffer[256];
559 nxlog_write(MSG_CANNOT_INIT_CERT_STORE, EVENTLOG_ERROR_TYPE, "s", _ERR_error_tstring(ERR_get_error(), buffer));
560 }
561
562 s_certificateStoreLock.unlock();
563 }
564
565 /**
566 * Certificate stuff initialization
567 */
568 void InitCertificates()
569 {
570 ReloadCertificates();
571 }
572
573 /**
574 * Load server certificate
575 */
576 bool LoadServerCertificate(RSA **serverKey)
577 {
578 if (g_serverCertificatePath[0] == 0)
579 {
580 nxlog_write(MSG_SERVER_CERT_NOT_SET, NXLOG_INFO, NULL);
581 return false;
582 }
583
584 // Load server CA certificates
585 TCHAR *curr = g_serverCACertificatesPath;
586 TCHAR *next = _tcschr(curr, _T('\n'));
587 while(next != NULL)
588 {
589 *next = 0;
590
591 FILE *f = _tfopen(curr, _T("r"));
592 if (f == NULL)
593 {
594 nxlog_write(MSG_CANNOT_LOAD_SERVER_CERT, NXLOG_ERROR, "ss", curr, _tcserror(errno));
595 return false;
596 }
597 X509 *cert = PEM_read_X509(f, NULL, NULL, NULL);
598 fclose(f);
599 if (cert == NULL)
600 {
601 TCHAR buffer[1024];
602 nxlog_write(MSG_CANNOT_LOAD_SERVER_CERT, NXLOG_ERROR, "ss", curr, _ERR_error_tstring(ERR_get_error(), buffer));
603 return false;
604 }
605 s_serverCACertificates.add(cert);
606
607 curr = next + 1;
608 next = _tcschr(curr, _T('\n'));
609 }
610
611 // Load server certificate and private key
612 FILE *f = _tfopen(g_serverCertificatePath, _T("r"));
613 if (f == NULL)
614 {
615 nxlog_write(MSG_CANNOT_LOAD_SERVER_CERT, NXLOG_ERROR, "ss", g_serverCertificatePath, _tcserror(errno));
616 return false;
617 }
618
619 DecryptPasswordA("system", g_serverCertificatePassword, g_serverCertificatePassword, MAX_PASSWORD);
620 s_serverCertificate = PEM_read_X509(f, NULL, NULL, g_serverCertificatePassword);
621 if (g_serverCertificateKeyPath[0] != 0)
622 {
623 // Server key is in separate file
624 fclose(f);
625 f = _tfopen(g_serverCertificateKeyPath, _T("r"));
626 if (f == NULL)
627 {
628 nxlog_write(MSG_CANNOT_LOAD_SERVER_CERT, NXLOG_ERROR, "ss", g_serverCertificateKeyPath, _tcserror(errno));
629 return false;
630 }
631 }
632 s_serverCertificateKey = PEM_read_PrivateKey(f, NULL, NULL, g_serverCertificatePassword);
633 fclose(f);
634
635 if ((s_serverCertificate == NULL) || (s_serverCertificateKey == NULL))
636 {
637 TCHAR buffer[1024];
638 nxlog_write(MSG_CANNOT_LOAD_SERVER_CERT, NXLOG_ERROR, "ss", g_serverCertificatePath, _ERR_error_tstring(ERR_get_error(), buffer));
639 return false;
640 }
641
642 RSA *privKey = EVP_PKEY_get1_RSA(s_serverCertificateKey);
643 RSA *pubKey = EVP_PKEY_get1_RSA(X509_get_pubkey(s_serverCertificate));
644 if ((privKey != NULL) && (pubKey != NULL))
645 {
646 // Combine into one key
647 int len = i2d_RSAPublicKey(pubKey, NULL);
648 len += i2d_RSAPrivateKey(privKey, NULL);
649 BYTE *buffer = (BYTE *)malloc(len);
650
651 BYTE *pos = buffer;
652 i2d_RSAPublicKey(pubKey, &pos);
653 i2d_RSAPrivateKey(privKey, &pos);
654
655 *serverKey = RSAKeyFromData(buffer, len, true);
656 free(buffer);
657 }
658
659 return true;
660 }
661
662 #if HAVE_X509_STORE_SET_VERIFY_CB
663
664 /**
665 * Certificate verification callback
666 */
667 static int CertVerifyCallback(int success, X509_STORE_CTX *ctx)
668 {
669 if (!success)
670 {
671 X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
672 int error = X509_STORE_CTX_get_error(ctx);
673 int depth = X509_STORE_CTX_get_error_depth(ctx);
674 char subjectName[1024];
675 X509_NAME_oneline(X509_get_subject_name(cert), subjectName, 1024);
676 nxlog_debug(4, _T("Certificate \"%hs\" verification error %d (%hs) at depth %d"),
677 subjectName, error, X509_verify_cert_error_string(error), depth);
678 }
679 return success;
680 }
681
682 #endif /* HAVE_X509_STORE_SET_VERIFY_CB */
683
684 /**
685 * Setup server-side TLS context
686 */
687 bool SetupServerTlsContext(SSL_CTX *context)
688 {
689 if ((s_serverCertificate == NULL) || (s_serverCertificateKey == NULL))
690 return false;
691
692 X509_STORE *store = X509_STORE_new();
693 if (store == NULL)
694 {
695 nxlog_debug(3, _T("SetupServerTlsContext: cannot create certificate store"));
696 return false;
697 }
698 #if HAVE_X509_STORE_SET_VERIFY_CB
699 X509_STORE_set_verify_cb(store, CertVerifyCallback);
700 #endif
701 X509_STORE_add_cert(store, s_serverCertificate);
702 for(int i = 0; i < s_serverCACertificates.size(); i++)
703 X509_STORE_add_cert(store, s_serverCACertificates.get(i));
704 SSL_CTX_set_cert_store(context, store);
705 SSL_CTX_use_certificate(context, s_serverCertificate);
706 SSL_CTX_use_PrivateKey(context, s_serverCertificateKey);
707 SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
708 return true;
709 }
710
711 #else /* _WITH_ENCRYPTION */
712
713 /**
714 * Stub for certificate initialization
715 */
716 void InitCertificates()
717 {
718 }
719
720 #endif /* _WITH_ENCRYPTION */