Callback at TS_SSL_CERT_HOOK, generate/look up shadow certificates based on SNI/FQDN
| 523 | |
| 524 | /// Callback at TS_SSL_CERT_HOOK, generate/look up shadow certificates based on SNI/FQDN |
| 525 | static int |
| 526 | cert_retriever(TSCont /* contp ATS_UNUSED */, TSEvent /* event ATS_UNUSED */, void *edata) |
| 527 | { |
| 528 | TSVConn ssl_vc = reinterpret_cast<TSVConn>(edata); |
| 529 | TSSslConnection sslobj = TSVConnSslConnectionGet(ssl_vc); |
| 530 | SSL *ssl = reinterpret_cast<SSL *>(sslobj); |
| 531 | const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); |
| 532 | SSL_CTX *ref_ctx = nullptr; |
| 533 | |
| 534 | if (servername == nullptr) { |
| 535 | TSError("[%s] %s: no SNI available", __func__, PLUGIN_NAME); |
| 536 | return TS_ERROR; |
| 537 | } |
| 538 | |
| 539 | bool wontdo = false; |
| 540 | ref_ctx = ssl_list->lookup_and_create(servername, edata, wontdo); |
| 541 | |
| 542 | if (wontdo) { |
| 543 | Dbg(dbg_ctl, "%s: won't generate cert for %s", __func__, servername); |
| 544 | TSVConnReenable(ssl_vc); |
| 545 | return TS_SUCCESS; |
| 546 | } |
| 547 | |
| 548 | if (ref_ctx) { |
| 549 | // Use existing context. |
| 550 | Dbg(dbg_ctl, "%s: reusing existing cert and context for %s", __func__, servername); |
| 551 | SSL_set_SSL_CTX(ssl, ref_ctx); |
| 552 | TSVConnReenable(ssl_vc); |
| 553 | return TS_SUCCESS; |
| 554 | } |
| 555 | |
| 556 | // If no existing context, schedule TASK thread to generate. |
| 557 | Dbg(dbg_ctl, "%s: scheduling thread to generate/retrieve cert for %s", __func__, servername); |
| 558 | TSCont schedule_cont = TSContCreate(shadow_cert_generator, TSMutexCreate()); |
| 559 | TSContDataSet(schedule_cont, const_cast<char *>(servername)); |
| 560 | TSContScheduleOnPool(schedule_cont, 0, TS_THREAD_POOL_TASK); |
| 561 | |
| 562 | return TS_SUCCESS; |
| 563 | } |
| 564 | |
| 565 | void |
| 566 | TSPluginInit(int argc, const char *argv[]) |
nothing calls this directly
no test coverage detected