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 "sslheaders.h"
20 #include "tscore/TestBox.h"
21 #include <cstdio>
22 #include <cstdarg>
23 #include <openssl/ssl.h>
24 #include <openssl/bio.h>
25 #include <openssl/pem.h>
26 
27 char *
_TSstrdup(const char * str,int64_t length,const char *)28 _TSstrdup(const char *str, int64_t length, const char *)
29 {
30   if (length == -1) {
31     return strdup(str);
32   } else {
33     return strndup(str, length);
34   }
35 }
36 
37 void
_TSfree(void * ptr)38 _TSfree(void *ptr)
39 {
40   free(ptr);
41 }
42 
43 void
TSDebug(const char * tag,const char * fmt,...)44 TSDebug(const char *tag, const char *fmt, ...)
45 {
46   va_list args;
47 
48   fprintf(stderr, "%s", tag);
49   va_start(args, fmt);
50   vfprintf(stderr, fmt, args);
51   va_end(args);
52   fprintf(stderr, "\n");
53 }
54 
55 void
TSError(const char * fmt,...)56 TSError(const char *fmt, ...)
57 {
58   va_list args;
59 
60   va_start(args, fmt);
61   vfprintf(stderr, fmt, args);
62   va_end(args);
63   fprintf(stderr, "\n");
64 }
65 
REGRESSION_TEST(ParseExpansion)66 REGRESSION_TEST(ParseExpansion)(RegressionTest *t, int /* atype ATS_UNUSED */, int *pstatus)
67 {
68   TestBox box(t, pstatus);
69 
70 #define EXPECT_TRUE(expression, _name, _scope, _field)                                                                            \
71   do {                                                                                                                            \
72     SslHdrExpansion exp;                                                                                                          \
73     box.check(SslHdrParseExpansion(expression, exp) == true, "'%s' failed (expected success)", (expression));                     \
74     box.check(strcmp(exp.name.c_str(), _name) == 0, "'%s' expected name %s, received %s", (expression), (_name),                  \
75               exp.name.c_str());                                                                                                  \
76     box.check(exp.scope == (_scope), "'%s' expected scope 0x%x (%s), received 0x%x", (expression), (_scope), #_scope, exp.scope); \
77     box.check(exp.field == (_field), "'%s' expected field 0x%x (%s), received 0x%x", (expression), (_field), #_field, exp.field); \
78   } while (0)
79 
80 #define EXPECT_FALSE(expression)                                                                                  \
81   do {                                                                                                            \
82     SslHdrExpansion exp;                                                                                          \
83     box.check(SslHdrParseExpansion(expression, exp) == false, "'%s' succeeded (expected failure)", (expression)); \
84   } while (0)
85 
86   box = REGRESSION_TEST_PASSED;
87 
88   EXPECT_FALSE("");
89   EXPECT_FALSE("missing-certificate-selector");
90   EXPECT_FALSE("missing-field-selector=");
91   EXPECT_FALSE("missing-field-selector=client");
92   EXPECT_FALSE("missing-field-selector=client.");
93 
94   EXPECT_TRUE("ssl-client-cert=client.certificate", "ssl-client-cert", SSL_HEADERS_SCOPE_CLIENT, SSL_HEADERS_FIELD_CERTIFICATE);
95   EXPECT_TRUE("ssl-server-signature=server.signature", "ssl-server-signature", SSL_HEADERS_SCOPE_SERVER,
96               SSL_HEADERS_FIELD_SIGNATURE);
97 
98   EXPECT_TRUE("certificate=server.certificate", "certificate", SSL_HEADERS_SCOPE_SERVER, SSL_HEADERS_FIELD_CERTIFICATE);
99   EXPECT_TRUE("subject=server.subject", "subject", SSL_HEADERS_SCOPE_SERVER, SSL_HEADERS_FIELD_SUBJECT);
100   EXPECT_TRUE("issuer=server.issuer", "issuer", SSL_HEADERS_SCOPE_SERVER, SSL_HEADERS_FIELD_ISSUER);
101   EXPECT_TRUE("serial=server.serial", "serial", SSL_HEADERS_SCOPE_SERVER, SSL_HEADERS_FIELD_SERIAL);
102   EXPECT_TRUE("signature=server.signature", "signature", SSL_HEADERS_SCOPE_SERVER, SSL_HEADERS_FIELD_SIGNATURE);
103   EXPECT_TRUE("notbefore=server.notbefore", "notbefore", SSL_HEADERS_SCOPE_SERVER, SSL_HEADERS_FIELD_NOTBEFORE);
104   EXPECT_TRUE("notafter=server.notafter", "notafter", SSL_HEADERS_SCOPE_SERVER, SSL_HEADERS_FIELD_NOTAFTER);
105 
106 #undef EXPECT_FALSE
107 #undef EXPECT_TRUE
108 }
109 
110 // Certificate:
111 //     Data:
112 //         Version: 3 (0x2)
113 //         Serial Number: 16125629757001825863 (0xdfc9bed3a58ffe47)
114 //     Signature Algorithm: sha1WithRSAEncryption
115 //         Issuer: CN=test.sslheaders.trafficserver.apache.org
116 //         Validity
117 //             Not Before: Jul 23 17:51:08 2014 GMT
118 //             Not After : May 12 17:51:08 2017 GMT
119 //         Subject: CN=test.sslheaders.trafficserver.apache.org
120 //         Subject Public Key Info:
121 //             Public Key Algorithm: rsaEncryption
122 //                 Public-Key: (1024 bit)
123 //                 Modulus:
124 //                     00:cd:ba:29:dc:57:9e:a2:30:0d:44:ed:2b:3d:06:
125 //                     53:6f:46:65:1d:57:70:27:e5:2e:af:5c:73:ff:85:
126 //                     74:95:4d:28:fe:de:8d:08:ed:eb:3f:da:7a:01:33:
127 //                     b5:26:5d:64:c1:18:d8:dc:41:8c:c1:79:df:d0:22:
128 //                     fa:8c:f6:9e:50:e0:1e:e4:28:54:db:d7:10:4e:97:
129 //                     81:14:dc:b1:e5:f5:fc:f3:87:16:d9:30:07:36:30:
130 //                     75:b9:5f:cf:9e:09:1e:8a:e8:80:6e:e6:c4:6e:2d:
131 //                     33:ef:21:98:60:eb:7f:df:7e:13:49:4c:89:b2:5b:
132 //                     6f:9e:1f:c8:2e:54:67:77:f1
133 //                 Exponent: 65537 (0x10001)
134 //         X509v3 extensions:
135 //             X509v3 Subject Alternative Name:
136 //                 DNS:test.sslheaders.trafficserver.apache.org
137 //     Signature Algorithm: sha1WithRSAEncryption
138 //          26:b2:1d:1c:39:7b:48:9e:8c:d9:22:80:b0:11:93:d6:91:5a:
139 //          2c:b4:58:59:14:75:f7:e1:cb:08:e7:38:ac:44:1a:f7:d9:1a:
140 //          43:50:3c:53:7e:d1:21:e4:ee:b0:26:f1:29:73:b4:e2:04:95:
141 //          2b:f1:ff:2f:43:07:29:f8:21:e4:b0:d9:a5:3a:cd:98:99:51:
142 //          23:e2:f5:2b:60:f3:fb:56:bf:d3:2f:39:25:3f:27:b0:87:68:
143 //          79:16:b9:86:df:05:30:4d:0e:89:1f:a8:5b:6a:63:75:09:ec:
144 //          f9:fe:eb:26:d2:d9:16:73:c2:64:a3:8a:74:fc:1a:09:44:df:
145 //          42:51
146 
147 // Given a PEM formatted object, remove the newlines to get what we would
148 // see in a HTTP header.
149 static char *
make_pem_header(const char * pem)150 make_pem_header(const char *pem)
151 {
152   char *hdr;
153   char *ptr;
154   unsigned remain;
155 
156   hdr = ptr = strdup(pem);
157   remain    = strlen(hdr);
158 
159   for (char *nl; (nl = static_cast<char *>(memchr(ptr, '\n', remain))); ptr = nl) {
160     *nl = ' ';
161     remain -= nl - ptr;
162   }
163 
164   return hdr;
165 }
166 
REGRESSION_TEST(ParseX509Fields)167 REGRESSION_TEST(ParseX509Fields)(RegressionTest *t, int /* atype ATS_UNUSED */, int *pstatus)
168 {
169   // A self-signed certificate for CN=test.sslheaders.trafficserver.apache.org.
170   static const char *test_certificate = "-----BEGIN CERTIFICATE-----\n"
171                                         "MIICGzCCAYSgAwIBAgIJAN/JvtOlj/5HMA0GCSqGSIb3DQEBBQUAMDMxMTAvBgNV\n"
172                                         "BAMMKHRlc3Quc3NsaGVhZGVycy50cmFmZmljc2VydmVyLmFwYWNoZS5vcmcwHhcN\n"
173                                         "MTQwNzIzMTc1MTA4WhcNMTcwNTEyMTc1MTA4WjAzMTEwLwYDVQQDDCh0ZXN0LnNz\n"
174                                         "bGhlYWRlcnMudHJhZmZpY3NlcnZlci5hcGFjaGUub3JnMIGfMA0GCSqGSIb3DQEB\n"
175                                         "AQUAA4GNADCBiQKBgQDNuincV56iMA1E7Ss9BlNvRmUdV3An5S6vXHP/hXSVTSj+\n"
176                                         "3o0I7es/2noBM7UmXWTBGNjcQYzBed/QIvqM9p5Q4B7kKFTb1xBOl4EU3LHl9fzz\n"
177                                         "hxbZMAc2MHW5X8+eCR6K6IBu5sRuLTPvIZhg63/ffhNJTImyW2+eH8guVGd38QID\n"
178                                         "AQABozcwNTAzBgNVHREELDAqgih0ZXN0LnNzbGhlYWRlcnMudHJhZmZpY3NlcnZl\n"
179                                         "ci5hcGFjaGUub3JnMA0GCSqGSIb3DQEBBQUAA4GBACayHRw5e0iejNkigLARk9aR\n"
180                                         "Wiy0WFkUdffhywjnOKxEGvfZGkNQPFN+0SHk7rAm8SlztOIElSvx/y9DByn4IeSw\n"
181                                         "2aU6zZiZUSPi9Stg8/tWv9MvOSU/J7CHaHkWuYbfBTBNDokfqFtqY3UJ7Pn+6ybS\n"
182                                         "2RZzwmSjinT8GglE30JR\n"
183                                         "-----END CERTIFICATE-----\n";
184 #if 0
185   "-----BEGIN RSA PRIVATE KEY-----"
186   "MIICXgIBAAKBgQDNuincV56iMA1E7Ss9BlNvRmUdV3An5S6vXHP/hXSVTSj+3o0I"
187   "7es/2noBM7UmXWTBGNjcQYzBed/QIvqM9p5Q4B7kKFTb1xBOl4EU3LHl9fzzhxbZ"
188   "MAc2MHW5X8+eCR6K6IBu5sRuLTPvIZhg63/ffhNJTImyW2+eH8guVGd38QIDAQAB"
189   "AoGBAJLTO48DhbbxHndD4SkTe7aeAgpX3jbK7W/ARxVldNgdkpWb1gI6czxGO+7h"
190   "rXatDvx1NEi2C7QFvEN6w2CZnlCIEYLdC3JPA9qQXD66vHSVttNqwLHezm+tf3Ci"
191   "DgPoSWABHJbDc/TFHjeVDvzkGJ/x0E6CO8lMvvDRbzjcNRoBAkEA80ulSvbCpZHL"
192   "aTqMwB/djvEFyrlyDyD8WkJewkL2q7HRWimNTAU+AsYftzn9kVaIHcVC3x1T47bB"
193   "qP1yEn+eoQJBANh4TtlZOEX6ykm4KqrCQXzOU5sp3m0RmqzYGQ3g8+8X8VTHjduw"
194   "OoJ/vJo6peluh0JalDbdSkCHU0OiILYD51ECQEoEP3s46yq32ixfVaa1ixALn3l3"
195   "RY34uQ00l+N9v9GoPUqyzXvNNHpfkBKMH+pxauOzuY5rO7RRS0WAJY4fKUECQQCd"
196   "R6R6lTGm3tYVhAM0OJoeVUc3yM78Tjsk9IoXpGd4Q9wrriYrBbstUCQ3pv8fQRhz"
197   "pJ5l0pj9k5Vy4ZyEwwdRAkEA3WViCDYe+uxeXcJxqiRHFoGm7YvkqcpBk9UQaWiz"
198   "d9D304LUJ+dfMHNUmhBe/HKG35VU8dG5/0E9vkQyz99zCw=="
199   "-----END RSA PRIVATE KEY-----"
200   ;
201 #endif
202 
203   TestBox box(t, pstatus);
204 
205   box = REGRESSION_TEST_PASSED;
206 
207   BIO *exp   = BIO_new(BIO_s_mem());
208   BIO *bio   = BIO_new_mem_buf((void *)test_certificate, -1);
209   X509 *x509 = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
210 
211   box.check(x509 != nullptr, "failed to load the test certificate");
212 
213 #define EXPECT_FIELD(_field, _value)                                                                                    \
214   do {                                                                                                                  \
215     long len;                                                                                                           \
216     char *ptr;                                                                                                          \
217     SslHdrExpandX509Field(exp, x509, _field);                                                                           \
218     len = BIO_get_mem_data(exp, &ptr);                                                                                  \
219     box.check(strncmp(_value, ptr, len) == 0, "expected '%s' for %s, received '%.*s'", _value, #_field, (int)len, ptr); \
220   } while (0)
221 
222   // Munge the PEM certificate to what we expect in the HTTP header.
223   char *certhdr = make_pem_header(test_certificate);
224 
225   EXPECT_FIELD(SSL_HEADERS_FIELD_NONE, "");
226   EXPECT_FIELD(SSL_HEADERS_FIELD_CERTIFICATE, certhdr);
227   EXPECT_FIELD(SSL_HEADERS_FIELD_SUBJECT, "CN = test.sslheaders.trafficserver.apache.org");
228   EXPECT_FIELD(SSL_HEADERS_FIELD_ISSUER, "CN = test.sslheaders.trafficserver.apache.org");
229   EXPECT_FIELD(SSL_HEADERS_FIELD_SERIAL, "DFC9BED3A58FFE47");
230   EXPECT_FIELD(SSL_HEADERS_FIELD_SIGNATURE, "26B21D1C397B489E8CD92280B01193D6915A"
231                                             "2CB458591475F7E1CB08E738AC441AF7D91A"
232                                             "43503C537ED121E4EEB026F12973B4E20495"
233                                             "2BF1FF2F430729F821E4B0D9A53ACD989951"
234                                             "23E2F52B60F3FB56BFD32F39253F27B08768"
235                                             "7916B986DF05304D0E891FA85B6A637509EC"
236                                             "F9FEEB26D2D91673C264A38A74FC1A0944DF"
237                                             "4251");
238 
239   EXPECT_FIELD(SSL_HEADERS_FIELD_NOTBEFORE, "Jul 23 17:51:08 2014 GMT");
240   EXPECT_FIELD(SSL_HEADERS_FIELD_NOTAFTER, "May 12 17:51:08 2017 GMT");
241 
242 #undef EXPECT_FIELD
243 
244   BIO_free(exp);
245   BIO_free(bio);
246   free(certhdr);
247 }
248 
249 int
main(int argc,const char ** argv)250 main(int argc, const char **argv)
251 {
252   SSL_library_init();
253   return RegressionTest::main(argc, argv, REGRESSION_TEST_QUICK);
254 }
255