int bud_config_select_sni_context(SSL* s, int* ad, void* arg) { bud_config_t* config; bud_context_t* ctx; const char* servername; config = arg; servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); /* No servername - no context selection */ if (servername == NULL) return SSL_TLSEXT_ERR_OK; /* Async SNI */ ctx = SSL_get_ex_data(s, kBudSSLSNIIndex); /* Normal SNI */ if (ctx == NULL) ctx = bud_config_select_context(config, servername, strlen(servername)); if (ctx != NULL) { SSL_set_SSL_CTX(s, ctx->ctx); if (!SSL_set_ex_data(s, kBudSSLSNIIndex, ctx)) return SSL_TLSEXT_ERR_ALERT_FATAL; } return SSL_TLSEXT_ERR_OK; }
bud_error_t bud_client_ocsp_stapling(bud_client_t* client) { bud_config_t* config; bud_context_t* context; bud_error_t err; const char* id; size_t id_size; config = client->config; if (client->sni_ctx.ctx != NULL) { /* Async SNI success */ context = &client->sni_ctx; } else if (client->hello.servername_len != 0) { /* Matching context */ context = bud_config_select_context(config, client->hello.servername, client->hello.servername_len); } else { /* Default context */ context = &config->contexts[0]; } /* Cache context to prevent second search in OpenSSL's callback */ if (!SSL_set_ex_data(client->ssl, kBudSSLSNIIndex, context)) { err = bud_error(kBudErrStaplingSetData); goto fatal; } id = bud_context_get_ocsp_id(context, &id_size); /* Certificate has no OCSP id */ if (id == NULL) return bud_ok(); /* Request backend for cached respose first */ client->stapling_cache_req = bud_http_get(config->stapling.pool, config->stapling.query_fmt, id, id_size, bud_client_stapling_cache_req_cb, &err); client->stapling_cache_req->data = client; if (!bud_is_ok(err)) goto fatal; client->hello_parse = kBudProgressRunning; return bud_ok(); fatal: return err; }