* This callback function is executed when the TLS Application-Layer * Protocol Negotiation Extension (ALPN, RFC 7301) is triggered by the Client * Hello, giving a list of desired protocol names (in descending preference) * to the server. * The callback has to select a protocol name or return an error if none of * the clients preferences is supported. * The selected protocol does not have to
| 2527 | * characters (not null-terminated), followed by the next protocol name. |
| 2528 | */ |
| 2529 | int ssl_callback_alpn_select(SSL *ssl, |
| 2530 | const unsigned char **out, unsigned char *outlen, |
| 2531 | const unsigned char *in, unsigned int inlen, |
| 2532 | void *arg) |
| 2533 | { |
| 2534 | conn_rec *c = (conn_rec*)SSL_get_app_data(ssl); |
| 2535 | SSLConnRec *sslconn; |
| 2536 | apr_array_header_t *client_protos; |
| 2537 | const char *proposed; |
| 2538 | size_t len; |
| 2539 | int i; |
| 2540 | |
| 2541 | /* If the connection object is not available, |
| 2542 | * then there's nothing for us to do. */ |
| 2543 | if (c == NULL) { |
| 2544 | return SSL_TLSEXT_ERR_OK; |
| 2545 | } |
| 2546 | sslconn = myConnConfig(c); |
| 2547 | |
| 2548 | if (inlen == 0) { |
| 2549 | /* someone tries to trick us? */ |
| 2550 | ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02837) |
| 2551 | "ALPN client protocol list empty"); |
| 2552 | return SSL_TLSEXT_ERR_ALERT_FATAL; |
| 2553 | } |
| 2554 | |
| 2555 | client_protos = apr_array_make(c->pool, 0, sizeof(char *)); |
| 2556 | for (i = 0; i < inlen; /**/) { |
| 2557 | unsigned int plen = in[i++]; |
| 2558 | if (plen + i > inlen) { |
| 2559 | /* someone tries to trick us? */ |
| 2560 | ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02838) |
| 2561 | "ALPN protocol identifier too long"); |
| 2562 | return SSL_TLSEXT_ERR_ALERT_FATAL; |
| 2563 | } |
| 2564 | APR_ARRAY_PUSH(client_protos, char *) = |
| 2565 | apr_pstrndup(c->pool, (const char *)in+i, plen); |
| 2566 | i += plen; |
| 2567 | } |
| 2568 | |
| 2569 | /* The order the callbacks are invoked from TLS extensions is, unfortunately |
| 2570 | * not defined and older openssl versions do call ALPN selection before |
| 2571 | * they callback the SNI. We need to make sure that we know which vhost |
| 2572 | * we are dealing with so we respect the correct protocols. |
| 2573 | */ |
| 2574 | init_vhost(c, ssl, NULL); |
| 2575 | |
| 2576 | proposed = ap_select_protocol(c, NULL, sslconn->server, client_protos); |
| 2577 | if (!proposed) { |
| 2578 | proposed = ap_get_protocol(c); |
| 2579 | } |
| 2580 | |
| 2581 | len = strlen(proposed); |
| 2582 | if (len > 255) { |
| 2583 | ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02840) |
| 2584 | "ALPN negotiated protocol name too long"); |
| 2585 | return SSL_TLSEXT_ERR_ALERT_FATAL; |
| 2586 | } |
nothing calls this directly
no test coverage detected