1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "tscore/ink_config.h"
20 #include "ts/ts.h"
21 #include "ts/remap.h"
22 #include "utilities.h"
23
24 // Needs special OpenSSL APIs as a global plugin for early CLIENT_HELLO inspection
25 #if TS_USE_HELLO_CB
26
27 std::string_view
getSNI(SSL * ssl)28 getSNI(SSL *ssl)
29 {
30 const char *servername = nullptr;
31 const unsigned char *p;
32 size_t remaining, len = 0;
33
34 // Parse the server name if the get extension call succeeds and there are more than 2 bytes to parse
35 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &p, &remaining) && remaining > 2) {
36 // Parse to get to the name, originally from test/handshake_helper.c in openssl tree
37 /* Extract the length of the supplied list of names. */
38 len = *(p++) << 8;
39 len += *(p++);
40 if (len + 2 == remaining) {
41 remaining = len;
42 /*
43 * The list in practice only has a single element, so we only consider
44 * the first one.
45 */
46 if (*p++ == TLSEXT_NAMETYPE_host_name) {
47 remaining--;
48 /* Now we can finally pull out the byte array with the actual hostname. */
49 if (remaining > 2) {
50 len = *(p++) << 8;
51 len += *(p++);
52 if (len + 2 <= remaining) {
53 servername = reinterpret_cast<const char *>(p);
54 }
55 }
56 }
57 }
58 }
59
60 return std::string_view(servername, servername ? len : 0);
61 }
62
63 #endif
64
65 ///////////////////////////////////////////////////////////////////////////////
66 // Add a header with the delay imposed on this transaction. This can be used
67 // for logging, and other types of metrics.
68 //
69 void
delayHeader(TSHttpTxn txnp,std::string & header,std::chrono::milliseconds delay)70 delayHeader(TSHttpTxn txnp, std::string &header, std::chrono::milliseconds delay)
71 {
72 if (header.size() > 0) {
73 TSMLoc hdr_loc = nullptr;
74 TSMBuffer bufp = nullptr;
75 TSMLoc field_loc = nullptr;
76
77 if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc)) {
78 if (TS_SUCCESS == TSMimeHdrFieldCreateNamed(bufp, hdr_loc, header.c_str(), header.size(), &field_loc)) {
79 if (TS_SUCCESS == TSMimeHdrFieldValueIntSet(bufp, hdr_loc, field_loc, -1, static_cast<int>(delay.count()))) {
80 TSDebug(PLUGIN_NAME, "Added client request header; %s: %d", header.c_str(), static_cast<int>(delay.count()));
81 TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
82 }
83 TSHandleMLocRelease(bufp, hdr_loc, field_loc);
84 }
85 TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
86 }
87 }
88 }
89
90 ///////////////////////////////////////////////////////////////////////////////
91 // Add a header with the delay imposed on this transaction. This can be used
92 // for logging, and other types of metrics.
93 //
94 void
retryAfter(TSHttpTxn txnp,unsigned retry)95 retryAfter(TSHttpTxn txnp, unsigned retry)
96 {
97 if (retry > 0) {
98 TSMLoc hdr_loc = nullptr;
99 TSMBuffer bufp = nullptr;
100 TSMLoc field_loc = nullptr;
101
102 if (TS_SUCCESS == TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc)) {
103 if (TS_SUCCESS == TSMimeHdrFieldCreateNamed(bufp, hdr_loc, "Retry-After", 11, &field_loc)) {
104 if (TS_SUCCESS == TSMimeHdrFieldValueIntSet(bufp, hdr_loc, field_loc, -1, retry)) {
105 TSDebug(PLUGIN_NAME, "Added a Retry-After: %u", retry);
106 TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
107 }
108 TSHandleMLocRelease(bufp, hdr_loc, field_loc);
109 }
110 TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
111 }
112 }
113 }
114