1 /************************************************************************************
2 Copyright (C) 2014 MariaDB Corporation Ab
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with this library; if not see <http://www.gnu.org/licenses>
16 or write to the Free Software Foundation, Inc.,
17 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
18
19 *************************************************************************************/
20 #include "ma_schannel.h"
21 #include "schannel_certs.h"
22 #include <string.h>
23
24 extern my_bool ma_tls_initialized;
25 char tls_library_version[] = "Schannel";
26
27 #define PROT_SSL3 1
28 #define PROT_TLS1_0 2
29 #define PROT_TLS1_2 4
30 #define PROT_TLS1_3 8
31
32 static struct
33 {
34 DWORD cipher_id;
35 DWORD protocol;
36 const char *iana_name;
37 const char *openssl_name;
38 ALG_ID algs[4]; /* exchange, encryption, hash, signature */
39 }
40 cipher_map[] =
41 {
42 {
43 0x0002,
44 PROT_TLS1_0 | PROT_TLS1_2 | PROT_SSL3,
45 "TLS_RSA_WITH_NULL_SHA", "NULL-SHA",
46 { CALG_RSA_KEYX, 0, CALG_SHA1, CALG_RSA_SIGN }
47 },
48 {
49 0x0004,
50 PROT_TLS1_0 | PROT_TLS1_2 | PROT_SSL3,
51 "TLS_RSA_WITH_RC4_128_MD5", "RC4-MD5",
52 { CALG_RSA_KEYX, CALG_RC4, CALG_MD5, CALG_RSA_SIGN }
53 },
54 {
55 0x0005,
56 PROT_TLS1_0 | PROT_TLS1_2 | PROT_SSL3,
57 "TLS_RSA_WITH_RC4_128_SHA", "RC4-SHA",
58 { CALG_RSA_KEYX, CALG_RC4, CALG_SHA1, CALG_RSA_SIGN }
59 },
60 {
61 0x000A,
62 PROT_SSL3,
63 "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "DES-CBC3-SHA",
64 {CALG_RSA_KEYX, CALG_3DES, CALG_SHA1, CALG_DSS_SIGN}
65 },
66 {
67 0x0013,
68 PROT_TLS1_0 | PROT_TLS1_2 | PROT_SSL3,
69 "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "EDH-DSS-DES-CBC3-SHA",
70 { CALG_DH_EPHEM, CALG_3DES, CALG_SHA1, CALG_DSS_SIGN }
71 },
72 {
73 0x002F,
74 PROT_SSL3 | PROT_TLS1_0 | PROT_TLS1_2,
75 "TLS_RSA_WITH_AES_128_CBC_SHA", "AES128-SHA",
76 { CALG_RSA_KEYX, CALG_AES_128, CALG_SHA, CALG_RSA_SIGN}
77 },
78 {
79 0x0032,
80 PROT_TLS1_0 | PROT_TLS1_2,
81 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "DHE-DSS-AES128-SHA",
82 { CALG_DH_EPHEM, CALG_AES_128, CALG_SHA1, CALG_RSA_SIGN }
83 },
84 {
85 0x0033,
86 PROT_TLS1_0 | PROT_TLS1_2,
87 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "DHE-RSA-AES128-SHA",
88 { CALG_DH_EPHEM, CALG_AES_128, CALG_SHA1, CALG_RSA_SIGN }
89 },
90 {
91 0x0035,
92 PROT_TLS1_0 | PROT_TLS1_2,
93 "TLS_RSA_WITH_AES_256_CBC_SHA", "AES256-SHA",
94 { CALG_RSA_KEYX, CALG_AES_256, CALG_SHA1, CALG_RSA_SIGN }
95 },
96 {
97 0x0038,
98 PROT_TLS1_0 | PROT_TLS1_2,
99 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "DHE-DSS-AES256-SHA",
100 { CALG_DH_EPHEM, CALG_AES_256, CALG_SHA1, CALG_DSS_SIGN }
101 },
102 {
103 0x0039,
104 PROT_TLS1_0 | PROT_TLS1_2,
105 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "DHE-RSA-AES256-SHA",
106 { CALG_DH_EPHEM, CALG_AES_256, CALG_SHA1, CALG_RSA_SIGN }
107 },
108 {
109 0x003B,
110 PROT_TLS1_2,
111 "TLS_RSA_WITH_NULL_SHA256", "NULL-SHA256",
112 { CALG_RSA_KEYX, 0, CALG_SHA_256, CALG_RSA_SIGN }
113 },
114 {
115 0x003C,
116 PROT_TLS1_2,
117 "TLS_RSA_WITH_AES_128_CBC_SHA256", "AES128-SHA256",
118 { CALG_RSA_KEYX, CALG_AES_128, CALG_SHA_256, CALG_RSA_SIGN }
119 },
120 {
121 0x003D,
122 PROT_TLS1_2,
123 "TLS_RSA_WITH_AES_256_CBC_SHA256", "AES256-SHA256",
124 { CALG_RSA_KEYX, CALG_AES_256, CALG_SHA_256, CALG_RSA_SIGN }
125 },
126 {
127 0x0040,
128 PROT_TLS1_2,
129 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "DHE-DSS-AES128-SHA256",
130 { CALG_DH_EPHEM, CALG_AES_128, CALG_SHA_256, CALG_DSS_SIGN }
131 },
132 {
133 0x009C,
134 PROT_TLS1_2,
135 "TLS_RSA_WITH_AES_128_GCM_SHA256", "AES128-GCM-SHA256",
136 { CALG_RSA_KEYX, CALG_AES_128, CALG_SHA_256, CALG_RSA_SIGN }
137 },
138 {
139 0x009D,
140 PROT_TLS1_2,
141 "TLS_RSA_WITH_AES_256_GCM_SHA384", "AES256-GCM-SHA384",
142 { CALG_RSA_KEYX, CALG_AES_256, CALG_SHA_384, CALG_RSA_SIGN }
143 },
144 {
145 0x009E,
146 PROT_TLS1_2,
147 "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "DHE-RSA-AES128-GCM-SHA256",
148 { CALG_DH_EPHEM, CALG_AES_128, CALG_SHA_256, CALG_RSA_SIGN }
149 },
150 {
151 0x009F,
152 PROT_TLS1_2,
153 "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "DHE-RSA-AES256-GCM-SHA384",
154 { CALG_DH_EPHEM, CALG_AES_256, CALG_SHA_384, CALG_RSA_SIGN }
155 },
156 {
157 0xC027,
158 PROT_TLS1_2,
159 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "ECDHE-RSA-AES128-SHA256",
160 { CALG_ECDH, CALG_AES_128, CALG_SHA_256, CALG_RSA_SIGN }
161 },
162 {
163 0xC028,
164 PROT_TLS1_2,
165 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "ECDHE-RSA-AES256-SHA384",
166 { CALG_ECDH, CALG_AES_256, CALG_SHA_384, CALG_RSA_SIGN }
167 }
168 };
169
170 #define MAX_ALG_ID 50
171
172 extern void ma_schannel_set_sec_error(MARIADB_PVIO *pvio, DWORD ErrorNo);
173
174 /*
175 Initializes SSL and allocate global
176 context SSL_context
177
178 SYNOPSIS
179 ma_tls_start
180
181 RETURN VALUES
182 0 success
183 1 error
184 */
ma_tls_start(char * errmsg,size_t errmsg_len)185 int ma_tls_start(char *errmsg, size_t errmsg_len)
186 {
187 ma_tls_initialized = TRUE;
188 return 0;
189 }
190
191 /*
192 Release SSL and free resources
193 Will be automatically executed by
194 mysql_server_end() function
195
196 SYNOPSIS
197 ma_tls_end()
198 void
199
200 RETURN VALUES
201 void
202 */
ma_tls_end()203 void ma_tls_end()
204 {
205 return;
206 }
207
208 /* {{{ static int ma_tls_set_client_certs(MARIADB_TLS *ctls) */
ma_tls_set_client_certs(MARIADB_TLS * ctls,const CERT_CONTEXT ** cert_ctx)209 static int ma_tls_set_client_certs(MARIADB_TLS *ctls,const CERT_CONTEXT **cert_ctx)
210 {
211 MYSQL *mysql= ctls->pvio->mysql;
212 char *certfile= mysql->options.ssl_cert,
213 *keyfile= mysql->options.ssl_key;
214 MARIADB_PVIO *pvio= ctls->pvio;
215 char errmsg[256];
216
217 if (!certfile && keyfile)
218 certfile= keyfile;
219 if (!keyfile && certfile)
220 keyfile= certfile;
221
222 if (!certfile)
223 return 0;
224
225 *cert_ctx = schannel_create_cert_context(certfile, keyfile, errmsg, sizeof(errmsg));
226 if (!*cert_ctx)
227 {
228 pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: %s", errmsg);
229 return 1;
230 }
231
232 return 0;
233 }
234 /* }}} */
235
236 /* {{{ void *ma_tls_init(MARIADB_TLS *ctls, MYSQL *mysql) */
ma_tls_init(MYSQL * mysql)237 void *ma_tls_init(MYSQL *mysql)
238 {
239 SC_CTX *sctx = (SC_CTX *)LocalAlloc(LMEM_ZEROINIT, sizeof(SC_CTX));
240 if (sctx)
241 {
242 SecInvalidateHandle(&sctx->CredHdl);
243 SecInvalidateHandle(&sctx->hCtxt);
244 }
245 return sctx;
246 }
247 /* }}} */
248
249
250 /*
251 Maps between openssl suite names and schannel alg_ids.
252 Every suite has 4 algorithms (for exchange, encryption, hash and signing).
253
254 The input string is a set of suite names (openssl), separated
255 by ':'
256
257 The output is written into the array 'arr' of size 'arr_size'
258 The function returns number of elements written to the 'arr'.
259 */
260
261 static struct _tls_version {
262 const char *tls_version;
263 DWORD protocol;
264 } tls_version[]= {
265 {"TLSv1.0", PROT_TLS1_0},
266 {"TLSv1.2", PROT_TLS1_2},
267 {"TLSv1.3", PROT_TLS1_3},
268 {"SSLv3", PROT_SSL3}
269 };
270
271 /* The following list was produced with OpenSSL 1.1.1j
272 by executing `openssl ciphers -V`. */
273 static struct {
274 DWORD dwCipherSuite;
275 const char *openssl_name;
276 } openssl_ciphers[] = {
277 {0x002F, "AES128-SHA"},
278 {0x0033, "DHE-RSA-AES128-SHA"},
279 {0x0035, "AES256-SHA"},
280 {0x0039, "DHE-RSA-AES256-SHA"},
281 {0x003C, "AES128-SHA256"},
282 {0x003D, "AES256-SHA256"},
283 {0x0067, "DHE-RSA-AES128-SHA256"},
284 {0x006B, "DHE-RSA-AES256-SHA256"},
285 {0x008C, "PSK-AES128-CBC-SHA"},
286 {0x008D, "PSK-AES256-CBC-SHA"},
287 {0x0090, "DHE-PSK-AES128-CBC-SHA"},
288 {0x0091, "DHE-PSK-AES256-CBC-SHA"},
289 {0x0094, "RSA-PSK-AES128-CBC-SHA"},
290 {0x0095, "RSA-PSK-AES256-CBC-SHA"},
291 {0x009C, "AES128-GCM-SHA256"},
292 {0x009D, "AES256-GCM-SHA384"},
293 {0x009E, "DHE-RSA-AES128-GCM-SHA256"},
294 {0x009F, "DHE-RSA-AES256-GCM-SHA384"},
295 {0x00A8, "PSK-AES128-GCM-SHA256"},
296 {0x00A9, "PSK-AES256-GCM-SHA384"},
297 {0x00AA, "DHE-PSK-AES128-GCM-SHA256"},
298 {0x00AB, "DHE-PSK-AES256-GCM-SHA384"},
299 {0x00AC, "RSA-PSK-AES128-GCM-SHA256"},
300 {0x00AD, "RSA-PSK-AES256-GCM-SHA384"},
301 {0x00AE, "PSK-AES128-CBC-SHA256"},
302 {0x00AF, "PSK-AES256-CBC-SHA384"},
303 {0x00B2, "DHE-PSK-AES128-CBC-SHA256"},
304 {0x00B3, "DHE-PSK-AES256-CBC-SHA384"},
305 {0x00B6, "RSA-PSK-AES128-CBC-SHA256"},
306 {0x00B7, "RSA-PSK-AES256-CBC-SHA384"},
307 {0x1301, "TLS_AES_128_GCM_SHA256"},
308 {0x1302, "TLS_AES_256_GCM_SHA384"},
309 {0x1303, "TLS_CHACHA20_POLY1305_SHA256"},
310 {0xC009, "ECDHE-ECDSA-AES128-SHA"},
311 {0xC00A, "ECDHE-ECDSA-AES256-SHA"},
312 {0xC013, "ECDHE-RSA-AES128-SHA"},
313 {0xC014, "ECDHE-RSA-AES256-SHA"},
314 {0xC01D, "SRP-AES-128-CBC-SHA"},
315 {0xC01E, "SRP-RSA-AES-128-CBC-SHA"},
316 {0xC020, "SRP-AES-256-CBC-SHA"},
317 {0xC021, "SRP-RSA-AES-256-CBC-SHA"},
318 {0xC023, "ECDHE-ECDSA-AES128-SHA256"},
319 {0xC024, "ECDHE-ECDSA-AES256-SHA384"},
320 {0xC027, "ECDHE-RSA-AES128-SHA256"},
321 {0xC028, "ECDHE-RSA-AES256-SHA384"},
322 {0xC02B, "ECDHE-ECDSA-AES128-GCM-SHA256"},
323 {0xC02C, "ECDHE-ECDSA-AES256-GCM-SHA384"},
324 {0xC02F, "ECDHE-RSA-AES128-GCM-SHA256"},
325 {0xC030, "ECDHE-RSA-AES256-GCM-SHA384"},
326 {0xC035, "ECDHE-PSK-AES128-CBC-SHA"},
327 {0xC036, "ECDHE-PSK-AES256-CBC-SHA"},
328 {0xC037, "ECDHE-PSK-AES128-CBC-SHA256"},
329 {0xC038, "ECDHE-PSK-AES256-CBC-SHA384"},
330 {0xCCA8, "ECDHE-RSA-CHACHA20-POLY1305"},
331 {0xCCA9, "ECDHE-ECDSA-CHACHA20-POLY1305"},
332 {0xCCAA, "DHE-RSA-CHACHA20-POLY1305"},
333 {0xCCAB, "PSK-CHACHA20-POLY1305"},
334 {0xCCAC, "ECDHE-PSK-CHACHA20-POLY1305"},
335 {0xCCAD, "DHE-PSK-CHACHA20-POLY1305"},
336 {0xCCAE, "RSA-PSK-CHACHA20-POLY1305"}
337 };
338
set_cipher(char * cipher_str,DWORD protocol,ALG_ID * arr,size_t arr_size)339 static size_t set_cipher(char * cipher_str, DWORD protocol, ALG_ID *arr , size_t arr_size)
340 {
341 char *token = strtok(cipher_str, ":");
342 size_t pos = 0;
343
344 while (token)
345 {
346 size_t i;
347
348 for(i = 0; i < sizeof(cipher_map)/sizeof(cipher_map[0]) ; i++)
349 {
350 if((pos + 4 < arr_size && strcmp(cipher_map[i].openssl_name, token) == 0) ||
351 (cipher_map[i].protocol <= protocol))
352 {
353 memcpy(arr + pos, cipher_map[i].algs, sizeof(ALG_ID)* 4);
354 pos += 4;
355 break;
356 }
357 }
358 token = strtok(NULL, ":");
359 }
360 return pos;
361 }
362
ma_tls_connect(MARIADB_TLS * ctls)363 my_bool ma_tls_connect(MARIADB_TLS *ctls)
364 {
365 MYSQL *mysql;
366 SCHANNEL_CRED Cred = {0};
367 MARIADB_PVIO *pvio;
368 my_bool rc= 1;
369 SC_CTX *sctx;
370 SECURITY_STATUS sRet;
371 ALG_ID AlgId[MAX_ALG_ID];
372 size_t i;
373 DWORD protocol = 0;
374 int verify_certs;
375 const CERT_CONTEXT* cert_context = NULL;
376
377 if (!ctls)
378 return 1;
379
380 pvio= ctls->pvio;
381 sctx= (SC_CTX *)ctls->ssl;
382 if (!pvio || !sctx)
383 return 1;
384
385 mysql= pvio->mysql;
386 if (!mysql)
387 return 1;
388
389 /* Set cipher */
390 if (mysql->options.ssl_cipher)
391 {
392
393 /* check if a protocol was specified as a cipher:
394 * In this case don't allow cipher suites which belong to newer protocols
395 * Please note: There are no cipher suites for TLS1.1
396 */
397 for (i = 0; i < sizeof(tls_version) / sizeof(tls_version[0]); i++)
398 {
399 if (!_stricmp(mysql->options.ssl_cipher, tls_version[i].tls_version))
400 protocol |= tls_version[i].protocol;
401 }
402 memset(AlgId, 0, sizeof(AlgId));
403 Cred.cSupportedAlgs = (DWORD)set_cipher(mysql->options.ssl_cipher, protocol, AlgId, MAX_ALG_ID);
404 if (Cred.cSupportedAlgs)
405 {
406 Cred.palgSupportedAlgs = AlgId;
407 }
408 else if (!protocol)
409 {
410 ma_schannel_set_sec_error(pvio, SEC_E_ALGORITHM_MISMATCH);
411 goto end;
412 }
413 }
414
415 Cred.dwVersion= SCHANNEL_CRED_VERSION;
416
417 Cred.dwFlags = SCH_CRED_NO_SERVERNAME_CHECK | SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION;
418
419 if (mysql->options.extension && mysql->options.extension->tls_version)
420 {
421 if (strstr(mysql->options.extension->tls_version, "TLSv1.0"))
422 Cred.grbitEnabledProtocols|= SP_PROT_TLS1_0_CLIENT;
423 if (strstr(mysql->options.extension->tls_version, "TLSv1.1"))
424 Cred.grbitEnabledProtocols|= SP_PROT_TLS1_1_CLIENT;
425 if (strstr(mysql->options.extension->tls_version, "TLSv1.2"))
426 Cred.grbitEnabledProtocols|= SP_PROT_TLS1_2_CLIENT;
427 }
428 if (!Cred.grbitEnabledProtocols)
429 Cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
430
431
432 if (ma_tls_set_client_certs(ctls, &cert_context))
433 goto end;
434
435 if (cert_context)
436 {
437 Cred.cCreds = 1;
438 Cred.paCred = &cert_context;
439 }
440 sRet= AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND,
441 NULL, &Cred, NULL, NULL, &sctx->CredHdl, NULL);
442 if (sRet)
443 {
444 ma_schannel_set_sec_error(pvio, sRet);
445 goto end;
446 }
447 if (ma_schannel_client_handshake(ctls) != SEC_E_OK)
448 goto end;
449
450 verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath ||
451 (mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT);
452
453 if (verify_certs)
454 {
455 if (!ma_schannel_verify_certs(ctls, (mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT)))
456 goto end;
457 }
458
459 rc = 0;
460
461 end:
462 if (cert_context)
463 schannel_free_cert_context(cert_context);
464 return rc;
465 }
466
ma_tls_read(MARIADB_TLS * ctls,const uchar * buffer,size_t length)467 ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
468 {
469 SC_CTX *sctx= (SC_CTX *)ctls->ssl;
470 MARIADB_PVIO *pvio= ctls->pvio;
471 DWORD dlength= 0;
472 SECURITY_STATUS status = ma_schannel_read_decrypt(pvio, &sctx->hCtxt, &dlength, (uchar *)buffer, (DWORD)length);
473 if (status == SEC_I_CONTEXT_EXPIRED)
474 return 0; /* other side shut down the connection. */
475 if (status == SEC_I_RENEGOTIATE)
476 return -1; /* Do not handle renegotiate yet */
477
478 return (status == SEC_E_OK)? (ssize_t)dlength : -1;
479 }
480
ma_tls_write(MARIADB_TLS * ctls,const uchar * buffer,size_t length)481 ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
482 {
483 MARIADB_PVIO *pvio= ctls->pvio;
484 ssize_t rc, wlength= 0;
485 ssize_t remain= length;
486
487 while (remain > 0)
488 {
489 if ((rc= ma_schannel_write_encrypt(pvio, (uchar *)buffer + wlength, remain)) <= 0)
490 return rc;
491 wlength+= rc;
492 remain-= rc;
493 }
494 return length;
495 }
496
497 /* {{{ my_bool ma_tls_close(MARIADB_PVIO *pvio) */
ma_tls_close(MARIADB_TLS * ctls)498 my_bool ma_tls_close(MARIADB_TLS *ctls)
499 {
500 SC_CTX *sctx= (SC_CTX *)ctls->ssl;
501
502 if (sctx)
503 {
504 LocalFree(sctx->IoBuffer);
505
506 if (SecIsValidHandle(&sctx->CredHdl))
507 FreeCredentialHandle(&sctx->CredHdl);
508
509 if (SecIsValidHandle(&sctx->hCtxt))
510 DeleteSecurityContext(&sctx->hCtxt);
511 }
512 LocalFree(sctx);
513 return 0;
514 }
515 /* }}} */
516
ma_tls_verify_server_cert(MARIADB_TLS * ctls)517 int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
518 {
519 /* Done elsewhere */
520 return 0;
521 }
522
cipher_name(const SecPkgContext_CipherInfo * CipherInfo)523 static const char *cipher_name(const SecPkgContext_CipherInfo *CipherInfo)
524 {
525 size_t i;
526
527 for(i = 0; i < sizeof(openssl_ciphers)/sizeof(openssl_ciphers[0]) ; i++)
528 {
529 if (CipherInfo->dwCipherSuite == openssl_ciphers[i].dwCipherSuite)
530 return openssl_ciphers[i].openssl_name;
531 }
532 return "";
533 };
534
ma_tls_get_cipher(MARIADB_TLS * ctls)535 const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
536 {
537 SecPkgContext_CipherInfo CipherInfo = { SECPKGCONTEXT_CIPHERINFO_V1 };
538 SECURITY_STATUS sRet;
539 SC_CTX *sctx;
540
541 if (!ctls || !ctls->ssl)
542 return NULL;
543
544 sctx= (SC_CTX *)ctls->ssl;
545 sRet= QueryContextAttributesA(&sctx->hCtxt, SECPKG_ATTR_CIPHER_INFO, (PVOID)&CipherInfo);
546
547 if (sRet != SEC_E_OK)
548 return NULL;
549
550 return cipher_name(&CipherInfo);
551 }
552
ma_tls_get_finger_print(MARIADB_TLS * ctls,char * fp,unsigned int len)553 unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
554 {
555 SC_CTX *sctx= (SC_CTX *)ctls->ssl;
556 PCCERT_CONTEXT pRemoteCertContext = NULL;
557 if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext) != SEC_E_OK)
558 return 0;
559 CertGetCertificateContextProperty(pRemoteCertContext, CERT_HASH_PROP_ID, fp, (DWORD *)&len);
560 CertFreeCertificateContext(pRemoteCertContext);
561 return len;
562 }
563