| 2350 | |
| 2351 | #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME |
| 2352 | int Server::SSLSwitchCTXByHostname(struct ssl_st* ssl, |
| 2353 | int* al, void* se) { |
| 2354 | (void)al; |
| 2355 | Server* server = reinterpret_cast<Server*>(se); |
| 2356 | const char* hostname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); |
| 2357 | bool strict_sni = server->_options.ssl_options().strict_sni; |
| 2358 | if (hostname == NULL) { |
| 2359 | return strict_sni ? SSL_TLSEXT_ERR_ALERT_FATAL : SSL_TLSEXT_ERR_NOACK; |
| 2360 | } |
| 2361 | |
| 2362 | butil::DoublyBufferedData<CertMaps>::ScopedPtr s; |
| 2363 | if (server->_reload_cert_maps.Read(&s) != 0) { |
| 2364 | return SSL_TLSEXT_ERR_ALERT_FATAL; |
| 2365 | } |
| 2366 | |
| 2367 | std::shared_ptr<SocketSSLContext>* pctx = s->cert_map.seek(hostname); |
| 2368 | if (pctx == NULL) { |
| 2369 | const char* dot = hostname; |
| 2370 | for (; *dot != '\0'; ++dot) { |
| 2371 | if (*dot == '.') { |
| 2372 | ++dot; |
| 2373 | break; |
| 2374 | } |
| 2375 | } |
| 2376 | if (*dot != '\0') { |
| 2377 | pctx = s->wildcard_cert_map.seek(dot); |
| 2378 | } |
| 2379 | } |
| 2380 | if (pctx == NULL) { |
| 2381 | if (strict_sni) { |
| 2382 | return SSL_TLSEXT_ERR_ALERT_FATAL; |
| 2383 | } |
| 2384 | // Use default SSL_CTX which is the current one |
| 2385 | return SSL_TLSEXT_ERR_OK; |
| 2386 | } |
| 2387 | |
| 2388 | // Switch SSL_CTX to the one with correct hostname |
| 2389 | SSL_set_SSL_CTX(ssl, (*pctx)->raw_ctx); |
| 2390 | return SSL_TLSEXT_ERR_OK; |
| 2391 | } |
| 2392 | #endif // SSL_CTRL_SET_TLSEXT_HOSTNAME |
| 2393 | |
| 2394 | } // namespace brpc |