diff --git a/Cargo.toml b/Cargo.toml index 557b49a..fae3473 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ +workspace = { members = ["spammer"] } [package] name = "netpong" -version = "0.1.0" +version = "0.2.0" edition = "2021" publish = true authors = ["Christoph J. Scherr "] @@ -17,11 +18,13 @@ anyhow = "1.0.79" clap = "4.4.18" clap-num = "1.0.2" clap-verbosity-flag = "2.1.2" -libpt = { version = "0.3.10", features = ["net"] } +libpt = { version = "0.3.11", features = ["net"] } thiserror = "1.0.56" -threadpool = { version = "1.8.1", optional = true } tokio = { version = "1.35.1", features = ["net", "rt", "macros"] } +rustls-pemfile = "2.0.0" +tokio-rustls = "0.25.0" +webpki-roots = "0.26.0" [features] default = ["server"] -server = ["dep:threadpool"] +server = [] diff --git a/data/Netpong-Test-CA/cacert.pem b/data/Netpong-Test-CA/cacert.pem new file mode 100644 index 0000000..f5c48b9 --- /dev/null +++ b/data/Netpong-Test-CA/cacert.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEFDCCAvygAwIBAgITfl3NbK3jOj2V0yehJ0VkuBWlvDANBgkqhkiG9w0BAQsF +ADCBmTELMAkGA1UEBhMCREUxHTAbBgNVBAgMFEJhZGVuIFfDg8K8cnR0ZW1iZXJn +MREwDwYDVQQHDAhNYW5uaGVpbTEVMBMGA1UECgwMTmV0cG9uZyBUZWFtMR0wGwYD +VQQDDBROZXRwb25nLVRlc3QtQ0EgUm9vdDEiMCAGCSqGSIb3DQEJARYTc29mdHdh +cmVAY3NjaGVyci5kZTAeFw0yNDAxMjQxNDM3NTdaFw0zNDAxMjExNDM3NTdaMIGZ +MQswCQYDVQQGEwJERTEdMBsGA1UECAwUQmFkZW4gV8ODwrxydHRlbWJlcmcxETAP +BgNVBAcMCE1hbm5oZWltMRUwEwYDVQQKDAxOZXRwb25nIFRlYW0xHTAbBgNVBAMM +FE5ldHBvbmctVGVzdC1DQSBSb290MSIwIAYJKoZIhvcNAQkBFhNzb2Z0d2FyZUBj +c2NoZXJyLmRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjc443jjU +YZP4aVC0vD0WRpzC6G50wva3lLX2vOf6x1xAE/sVQ7F3j25s/oUUzHSf4/F4H3rC +R5ZmpyOBiW/1ZuQVb48HxzE7Vh/QQenTUVcPEdZcqf0vLogDzaSrq9uMXvmWHWgQ +IE0yYbEBd2/bE0k530EW5QZpKdUZI6m+Tf6k60Fk65skC4IZ684M6ahB9AQiBY0c +6DzJPN6AV33s6HjHqLJUeWwiEFXx7v/I3Fo81NHnoRZQw9bNel3rRa1Ovn1FIUz3 +rKygXb3/Zcl3TKh2eRXb7bJmG35dh+Cx9OtPlYSiU45w5Kxa7+c1n2H+rDv5QlcH +tsUR2ONDDRG4MwIDAQABo1MwUTAdBgNVHQ4EFgQUj4dOxujhWUGrCG5xJNhrCXM0 +JWEwHwYDVR0jBBgwFoAUj4dOxujhWUGrCG5xJNhrCXM0JWEwDwYDVR0TAQH/BAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcR6c5RMuEqO01TKfzXq0b2J8Rfqxe9WJ +6tgc7/3DatCYkytCq+fucZ2hUg/IxZ8wRpe1UyaK5iLd0kC8ag5RT5pl9ybHnVZZ +DsQNYlal71DaCwId+VhiZpqGVERruln7nBifNDrqbRy9U2da/q7ZoMlxkIOgUiBd +r4Ecv/J6l6LprIIjxGRQ6dC0TN0kDkJ5UFS7IMsM13eDtejA/mfHOamN6Ty0PzaY +HI9IeKzlFz0yzRyaYL/VrpBmiQF1goRpeIfEZw5F09hatkhSgzmV+GcMjTAnIVCU +h/s9q/mFKeWVWUA8endIx+3YXtIdMK6H16DGYNOIyzmc7XwpQkDqvg== +-----END CERTIFICATE----- diff --git a/data/Netpong-Test-CA/index.txt b/data/Netpong-Test-CA/index.txt new file mode 100644 index 0000000..1c22b02 --- /dev/null +++ b/data/Netpong-Test-CA/index.txt @@ -0,0 +1 @@ +V 340121145241Z 00 unknown /C=DE/ST=Baden W\xC3\x83\xC2\xBCrttemberg/O=Netpong Team/CN=localhost diff --git a/data/Netpong-Test-CA/index.txt.attr b/data/Netpong-Test-CA/index.txt.attr new file mode 100644 index 0000000..8f7e63a --- /dev/null +++ b/data/Netpong-Test-CA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/data/Netpong-Test-CA/index.txt.old b/data/Netpong-Test-CA/index.txt.old new file mode 100644 index 0000000..e69de29 diff --git a/data/Netpong-Test-CA/localhost.crt b/data/Netpong-Test-CA/localhost.crt new file mode 100644 index 0000000..a3928c9 --- /dev/null +++ b/data/Netpong-Test-CA/localhost.crt @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 0 (0x0) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, ST=Baden W\xC3\x83\xC2\xBCrttemberg, L=Mannheim, O=Netpong Team, CN=Netpong-Test-CA Root/emailAddress=software@cscherr.de + Validity + Not Before: Jan 24 14:52:41 2024 GMT + Not After : Jan 21 14:52:41 2034 GMT + Subject: C=DE, ST=Baden W\xC3\x83\xC2\xBCrttemberg, O=Netpong Team, CN=localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d5:e6:a4:18:a1:c2:a6:c6:f1:22:d7:c5:66:a6: + 90:68:f6:2f:0e:2f:41:8c:9b:2e:f2:e4:64:9b:e1: + 5f:28:64:4f:ea:a6:b5:68:67:e2:09:93:11:93:3d: + d8:0b:e7:06:50:38:1e:6c:fa:70:2c:32:fb:64:ba: + d3:43:8c:16:b0:78:39:e4:6f:05:da:e1:7b:c0:8c: + e0:79:90:4d:60:85:0e:13:5c:2b:03:a9:38:c9:20: + 48:1b:41:a7:70:95:d2:ae:e9:96:5e:55:d7:a1:9b: + 75:51:de:65:75:7c:0f:1f:71:29:88:6d:ca:82:d5: + 9e:e6:09:78:4a:d3:10:f7:13:69:c8:3e:4e:7e:1f: + 9b:9c:6b:a3:f6:da:2a:65:3d:41:e9:41:62:41:a7: + aa:5e:9e:5a:1b:e9:a0:ca:35:c4:7e:a0:93:48:0c: + cc:54:98:79:4b:97:20:0d:48:9f:9a:fb:24:16:6e: + ba:ad:04:5e:83:0c:a6:da:de:59:6a:29:c0:fd:77: + 3b:d4:d1:f2:a7:a0:a1:64:66:32:52:11:08:5f:17: + 35:14:11:ab:9a:ac:69:df:82:d0:05:7e:78:7e:45: + 20:ea:da:0e:18:3b:22:72:e3:d6:ef:4a:00:aa:2a: + 3d:42:3a:03:ae:6a:e6:cc:2a:fb:6c:eb:e0:13:3e: + ca:1d:a6:92:ed:14:25:a3:c3:d9:03:60:13:48:be: + 32:c4:b3:09:df:68:b5:b3:7f:cd:13:c6:af:e0:49: + d2:91:40:d3:9d:6f:53:a5:08:23:5e:fb:b1:d6:20: + 8f:a0:66:b1:ce:7d:8e:97:79:9c:ec:73:94:ca:60: + 71:48:8e:0f:92:b7:5b:99:83:24:02:13:a3:f3:64: + 92:25:2e:74:00:0d:b6:e4:85:41:95:12:af:93:39: + ed:ed:73:9e:00:a5:c6:1b:8a:3f:19:73:e8:e4:01: + 4a:a4:f5:a6:3c:f8:ee:e3:74:21:fd:ab:53:17:2c: + 72:74:b0:7e:87:23:b5:f2:dd:67:24:d1:8c:8d:75: + 4b:d9:5b:d1:10:55:c0:6b:2d:22:7c:7f:a1:42:15: + 12:4f:fd:70:b3:18:f5:78:a9:56:f7:2f:f2:91:54: + 57:38:9f:11:31:20:dd:79:aa:fb:b6:8d:fc:58:25: + 07:2b:b9:c7:8b:85:e3:39:77:6f:8e:51:fa:9c:6b: + c7:2a:ba:1e:59:28:e9:b8:07:1f:50:bc:89:3e:61: + 55:9a:c5:c6:6d:54:09:9a:96:ec:97:d9:16:5b:4b: + 60:d5:37:bf:9d:ad:72:09:4c:fc:c0:df:05:5c:2a: + 51:92:e2:79:b0:c6:8c:91:26:a9:cb:3d:f9:1e:dd: + 7f:19:e3 + Exponent: 65537 (0x10001) + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 3f:00:bc:70:77:c1:4d:f5:d2:f5:ea:23:7a:1d:ee:90:3a:1e: + 16:3a:2b:25:56:8c:13:78:4e:a1:6c:32:49:68:3e:0e:9a:43: + e1:45:bf:85:a1:36:88:5f:9a:e1:9b:04:40:f8:a4:77:5f:cf: + a3:29:c5:fb:b0:2b:d1:cc:2b:97:04:d1:9e:4d:32:7d:bd:ff: + 49:7b:b1:38:c7:77:be:74:73:2f:f2:e5:f8:af:34:05:f2:5e: + 75:40:2a:d3:8f:d7:4f:aa:17:7d:09:f1:16:3e:1c:f7:e6:e9: + 7a:bb:98:92:83:5a:b4:71:08:97:fc:6e:97:cf:07:73:48:de: + 23:f6:58:06:b4:c9:c9:a7:11:8b:95:50:f0:2e:cb:25:85:b1: + 30:79:6c:61:84:ee:b4:ea:1f:b1:a7:80:c5:09:2c:e3:ae:83: + f8:0a:3c:ef:d1:b8:fb:1e:2e:91:03:21:65:62:fe:fe:a6:c7: + cd:cf:7f:31:d4:99:cf:6e:39:63:df:1a:f2:fd:55:33:22:ef: + a8:26:2f:15:f6:d9:63:a2:ac:bb:f1:bf:e9:c1:c7:88:d1:4f: + d8:19:38:ce:8c:d3:bc:a8:15:32:ba:05:58:74:f5:8c:fa:aa: + 9f:52:42:67:2e:73:57:04:ec:57:ca:6c:a6:f5:f2:84:b5:0d: + 09:09:1a:64 +-----BEGIN CERTIFICATE----- +MIIEZTCCA00CAQAwDQYJKoZIhvcNAQELBQAwgZkxCzAJBgNVBAYTAkRFMR0wGwYD +VQQIDBRCYWRlbiBXw4PCvHJ0dGVtYmVyZzERMA8GA1UEBwwITWFubmhlaW0xFTAT +BgNVBAoMDE5ldHBvbmcgVGVhbTEdMBsGA1UEAwwUTmV0cG9uZy1UZXN0LUNBIFJv +b3QxIjAgBgkqhkiG9w0BCQEWE3NvZnR3YXJlQGNzY2hlcnIuZGUwHhcNMjQwMTI0 +MTQ1MjQxWhcNMzQwMTIxMTQ1MjQxWjBXMQswCQYDVQQGEwJERTEdMBsGA1UECAwU +QmFkZW4gV8ODwrxydHRlbWJlcmcxFTATBgNVBAoMDE5ldHBvbmcgVGVhbTESMBAG +A1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +1eakGKHCpsbxItfFZqaQaPYvDi9BjJsu8uRkm+FfKGRP6qa1aGfiCZMRkz3YC+cG +UDgebPpwLDL7ZLrTQ4wWsHg55G8F2uF7wIzgeZBNYIUOE1wrA6k4ySBIG0GncJXS +rumWXlXXoZt1Ud5ldXwPH3EpiG3KgtWe5gl4StMQ9xNpyD5Ofh+bnGuj9toqZT1B +6UFiQaeqXp5aG+mgyjXEfqCTSAzMVJh5S5cgDUifmvskFm66rQRegwym2t5ZainA +/Xc71NHyp6ChZGYyUhEIXxc1FBGrmqxp34LQBX54fkUg6toOGDsicuPW70oAqio9 +QjoDrmrmzCr7bOvgEz7KHaaS7RQlo8PZA2ATSL4yxLMJ32i1s3/NE8av4EnSkUDT +nW9TpQgjXvux1iCPoGaxzn2Ol3mc7HOUymBxSI4PkrdbmYMkAhOj82SSJS50AA22 +5IVBlRKvkznt7XOeAKXGG4o/GXPo5AFKpPWmPPju43Qh/atTFyxydLB+hyO18t1n +JNGMjXVL2VvREFXAay0ifH+hQhUST/1wsxj1eKlW9y/ykVRXOJ8RMSDdear7to38 +WCUHK7nHi4XjOXdvjlH6nGvHKroeWSjpuAcfULyJPmFVmsXGbVQJmpbsl9kWW0tg +1Te/na1yCUz8wN8FXCpRkuJ5sMaMkSapyz35Ht1/GeMCAwEAATANBgkqhkiG9w0B +AQsFAAOCAQEAPwC8cHfBTfXS9eojeh3ukDoeFjorJVaME3hOoWwySWg+DppD4UW/ +haE2iF+a4ZsEQPikd1/PoynF+7Ar0cwrlwTRnk0yfb3/SXuxOMd3vnRzL/Ll+K80 +BfJedUAq04/XT6oXfQnxFj4c9+bperuYkoNatHEIl/xul88Hc0jeI/ZYBrTJyacR +i5VQ8C7LJYWxMHlsYYTutOofsaeAxQks466D+Ao879G4+x4ukQMhZWL+/qbHzc9/ +MdSZz245Y98a8v1VMyLvqCYvFfbZY6Ksu/G/6cHHiNFP2Bk4zozTvKgVMroFWHT1 +jPqqn1JCZy5zVwTsV8pspvXyhLUNCQkaZA== +-----END CERTIFICATE----- diff --git a/data/Netpong-Test-CA/localhost.csr b/data/Netpong-Test-CA/localhost.csr new file mode 100644 index 0000000..b31028b --- /dev/null +++ b/data/Netpong-Test-CA/localhost.csr @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIE1DCCArwCAQAwgY4xCzAJBgNVBAYTAkRFMR0wGwYDVQQIDBRCYWRlbiBXw4PC +vHJ0dGVtYmVyZzERMA8GA1UEBwwITWFubmhlaW0xFTATBgNVBAoMDE5ldHBvbmcg +VGVhbTESMBAGA1UEAwwJbG9jYWxob3N0MSIwIAYJKoZIhvcNAQkBFhNzb2Z0d2Fy +ZUBjc2NoZXJyLmRlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1eak +GKHCpsbxItfFZqaQaPYvDi9BjJsu8uRkm+FfKGRP6qa1aGfiCZMRkz3YC+cGUDge +bPpwLDL7ZLrTQ4wWsHg55G8F2uF7wIzgeZBNYIUOE1wrA6k4ySBIG0GncJXSrumW +XlXXoZt1Ud5ldXwPH3EpiG3KgtWe5gl4StMQ9xNpyD5Ofh+bnGuj9toqZT1B6UFi +QaeqXp5aG+mgyjXEfqCTSAzMVJh5S5cgDUifmvskFm66rQRegwym2t5ZainA/Xc7 +1NHyp6ChZGYyUhEIXxc1FBGrmqxp34LQBX54fkUg6toOGDsicuPW70oAqio9QjoD +rmrmzCr7bOvgEz7KHaaS7RQlo8PZA2ATSL4yxLMJ32i1s3/NE8av4EnSkUDTnW9T +pQgjXvux1iCPoGaxzn2Ol3mc7HOUymBxSI4PkrdbmYMkAhOj82SSJS50AA225IVB +lRKvkznt7XOeAKXGG4o/GXPo5AFKpPWmPPju43Qh/atTFyxydLB+hyO18t1nJNGM +jXVL2VvREFXAay0ifH+hQhUST/1wsxj1eKlW9y/ykVRXOJ8RMSDdear7to38WCUH +K7nHi4XjOXdvjlH6nGvHKroeWSjpuAcfULyJPmFVmsXGbVQJmpbsl9kWW0tg1Te/ +na1yCUz8wN8FXCpRkuJ5sMaMkSapyz35Ht1/GeMCAwEAAaAAMA0GCSqGSIb3DQEB +CwUAA4ICAQBfGAE9+31BxgHeUbmC96QtOjEhpy5YkONNQWB8M8588NVExV4WBAmj +bqEdGf5/KnDEqEMctzxYt7vSCPT5p1OALAkExWI+tz0uup6pjoKq8Ar9A/Va9tfn +4Bw3Nyvg1LJ55j0dhCCT8APljGhlHV5eVeLuFX4zTXHt+MJj/Laaip/k6J2+PuJk +pRPA/f/A2zswhgrWU/4ovyYB6f8MjJFvh65wlBva1j4Bs9siV5VpNdORswEBVXK+ +4JUvdSabitn3uFWDCnEW+z7xi9Kl5aqo6VmYC6W58k8qJw8PhGODYIgKE0MhBLsd +CrfU9luUOpmrjvczZfkLuuuJxdZClrfW0kWyOlkx1rB9OFDmJVGgm0Px+dTUv53A +MojK3fhVdP2aUzHMrCpkINmpvChRNHKWYPDgBeqHNuMq/qlGXeDPuKGSN3KI3Srk +LhiDOTfRMDYNgi9V8kZywv8iLiHYke2TWDP08baUy190b5MxKr2/BnTNDpTVyx2q +4Cw7PdcvvlQsG/gpWyD93DQ3QNFsO+D4ZX6DyCbOnGFh4ff0w8Gylehp7OCiPbLB +hQrxbLrfZWEe62FrBArdJgF6aawpxycrgjXaapzFQhwaJV3BHQI+ScFrzwHaGnEG +LsSnnt+U6WrGgPuss435JhnB9QUe2hq/DSzuabeIQrpb57BrD57yuA== +-----END CERTIFICATE REQUEST----- diff --git a/data/Netpong-Test-CA/newcerts/00.pem b/data/Netpong-Test-CA/newcerts/00.pem new file mode 100644 index 0000000..a3928c9 --- /dev/null +++ b/data/Netpong-Test-CA/newcerts/00.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 0 (0x0) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, ST=Baden W\xC3\x83\xC2\xBCrttemberg, L=Mannheim, O=Netpong Team, CN=Netpong-Test-CA Root/emailAddress=software@cscherr.de + Validity + Not Before: Jan 24 14:52:41 2024 GMT + Not After : Jan 21 14:52:41 2034 GMT + Subject: C=DE, ST=Baden W\xC3\x83\xC2\xBCrttemberg, O=Netpong Team, CN=localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d5:e6:a4:18:a1:c2:a6:c6:f1:22:d7:c5:66:a6: + 90:68:f6:2f:0e:2f:41:8c:9b:2e:f2:e4:64:9b:e1: + 5f:28:64:4f:ea:a6:b5:68:67:e2:09:93:11:93:3d: + d8:0b:e7:06:50:38:1e:6c:fa:70:2c:32:fb:64:ba: + d3:43:8c:16:b0:78:39:e4:6f:05:da:e1:7b:c0:8c: + e0:79:90:4d:60:85:0e:13:5c:2b:03:a9:38:c9:20: + 48:1b:41:a7:70:95:d2:ae:e9:96:5e:55:d7:a1:9b: + 75:51:de:65:75:7c:0f:1f:71:29:88:6d:ca:82:d5: + 9e:e6:09:78:4a:d3:10:f7:13:69:c8:3e:4e:7e:1f: + 9b:9c:6b:a3:f6:da:2a:65:3d:41:e9:41:62:41:a7: + aa:5e:9e:5a:1b:e9:a0:ca:35:c4:7e:a0:93:48:0c: + cc:54:98:79:4b:97:20:0d:48:9f:9a:fb:24:16:6e: + ba:ad:04:5e:83:0c:a6:da:de:59:6a:29:c0:fd:77: + 3b:d4:d1:f2:a7:a0:a1:64:66:32:52:11:08:5f:17: + 35:14:11:ab:9a:ac:69:df:82:d0:05:7e:78:7e:45: + 20:ea:da:0e:18:3b:22:72:e3:d6:ef:4a:00:aa:2a: + 3d:42:3a:03:ae:6a:e6:cc:2a:fb:6c:eb:e0:13:3e: + ca:1d:a6:92:ed:14:25:a3:c3:d9:03:60:13:48:be: + 32:c4:b3:09:df:68:b5:b3:7f:cd:13:c6:af:e0:49: + d2:91:40:d3:9d:6f:53:a5:08:23:5e:fb:b1:d6:20: + 8f:a0:66:b1:ce:7d:8e:97:79:9c:ec:73:94:ca:60: + 71:48:8e:0f:92:b7:5b:99:83:24:02:13:a3:f3:64: + 92:25:2e:74:00:0d:b6:e4:85:41:95:12:af:93:39: + ed:ed:73:9e:00:a5:c6:1b:8a:3f:19:73:e8:e4:01: + 4a:a4:f5:a6:3c:f8:ee:e3:74:21:fd:ab:53:17:2c: + 72:74:b0:7e:87:23:b5:f2:dd:67:24:d1:8c:8d:75: + 4b:d9:5b:d1:10:55:c0:6b:2d:22:7c:7f:a1:42:15: + 12:4f:fd:70:b3:18:f5:78:a9:56:f7:2f:f2:91:54: + 57:38:9f:11:31:20:dd:79:aa:fb:b6:8d:fc:58:25: + 07:2b:b9:c7:8b:85:e3:39:77:6f:8e:51:fa:9c:6b: + c7:2a:ba:1e:59:28:e9:b8:07:1f:50:bc:89:3e:61: + 55:9a:c5:c6:6d:54:09:9a:96:ec:97:d9:16:5b:4b: + 60:d5:37:bf:9d:ad:72:09:4c:fc:c0:df:05:5c:2a: + 51:92:e2:79:b0:c6:8c:91:26:a9:cb:3d:f9:1e:dd: + 7f:19:e3 + Exponent: 65537 (0x10001) + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 3f:00:bc:70:77:c1:4d:f5:d2:f5:ea:23:7a:1d:ee:90:3a:1e: + 16:3a:2b:25:56:8c:13:78:4e:a1:6c:32:49:68:3e:0e:9a:43: + e1:45:bf:85:a1:36:88:5f:9a:e1:9b:04:40:f8:a4:77:5f:cf: + a3:29:c5:fb:b0:2b:d1:cc:2b:97:04:d1:9e:4d:32:7d:bd:ff: + 49:7b:b1:38:c7:77:be:74:73:2f:f2:e5:f8:af:34:05:f2:5e: + 75:40:2a:d3:8f:d7:4f:aa:17:7d:09:f1:16:3e:1c:f7:e6:e9: + 7a:bb:98:92:83:5a:b4:71:08:97:fc:6e:97:cf:07:73:48:de: + 23:f6:58:06:b4:c9:c9:a7:11:8b:95:50:f0:2e:cb:25:85:b1: + 30:79:6c:61:84:ee:b4:ea:1f:b1:a7:80:c5:09:2c:e3:ae:83: + f8:0a:3c:ef:d1:b8:fb:1e:2e:91:03:21:65:62:fe:fe:a6:c7: + cd:cf:7f:31:d4:99:cf:6e:39:63:df:1a:f2:fd:55:33:22:ef: + a8:26:2f:15:f6:d9:63:a2:ac:bb:f1:bf:e9:c1:c7:88:d1:4f: + d8:19:38:ce:8c:d3:bc:a8:15:32:ba:05:58:74:f5:8c:fa:aa: + 9f:52:42:67:2e:73:57:04:ec:57:ca:6c:a6:f5:f2:84:b5:0d: + 09:09:1a:64 +-----BEGIN CERTIFICATE----- +MIIEZTCCA00CAQAwDQYJKoZIhvcNAQELBQAwgZkxCzAJBgNVBAYTAkRFMR0wGwYD +VQQIDBRCYWRlbiBXw4PCvHJ0dGVtYmVyZzERMA8GA1UEBwwITWFubmhlaW0xFTAT +BgNVBAoMDE5ldHBvbmcgVGVhbTEdMBsGA1UEAwwUTmV0cG9uZy1UZXN0LUNBIFJv +b3QxIjAgBgkqhkiG9w0BCQEWE3NvZnR3YXJlQGNzY2hlcnIuZGUwHhcNMjQwMTI0 +MTQ1MjQxWhcNMzQwMTIxMTQ1MjQxWjBXMQswCQYDVQQGEwJERTEdMBsGA1UECAwU +QmFkZW4gV8ODwrxydHRlbWJlcmcxFTATBgNVBAoMDE5ldHBvbmcgVGVhbTESMBAG +A1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +1eakGKHCpsbxItfFZqaQaPYvDi9BjJsu8uRkm+FfKGRP6qa1aGfiCZMRkz3YC+cG +UDgebPpwLDL7ZLrTQ4wWsHg55G8F2uF7wIzgeZBNYIUOE1wrA6k4ySBIG0GncJXS +rumWXlXXoZt1Ud5ldXwPH3EpiG3KgtWe5gl4StMQ9xNpyD5Ofh+bnGuj9toqZT1B +6UFiQaeqXp5aG+mgyjXEfqCTSAzMVJh5S5cgDUifmvskFm66rQRegwym2t5ZainA +/Xc71NHyp6ChZGYyUhEIXxc1FBGrmqxp34LQBX54fkUg6toOGDsicuPW70oAqio9 +QjoDrmrmzCr7bOvgEz7KHaaS7RQlo8PZA2ATSL4yxLMJ32i1s3/NE8av4EnSkUDT +nW9TpQgjXvux1iCPoGaxzn2Ol3mc7HOUymBxSI4PkrdbmYMkAhOj82SSJS50AA22 +5IVBlRKvkznt7XOeAKXGG4o/GXPo5AFKpPWmPPju43Qh/atTFyxydLB+hyO18t1n +JNGMjXVL2VvREFXAay0ifH+hQhUST/1wsxj1eKlW9y/ykVRXOJ8RMSDdear7to38 +WCUHK7nHi4XjOXdvjlH6nGvHKroeWSjpuAcfULyJPmFVmsXGbVQJmpbsl9kWW0tg +1Te/na1yCUz8wN8FXCpRkuJ5sMaMkSapyz35Ht1/GeMCAwEAATANBgkqhkiG9w0B +AQsFAAOCAQEAPwC8cHfBTfXS9eojeh3ukDoeFjorJVaME3hOoWwySWg+DppD4UW/ +haE2iF+a4ZsEQPikd1/PoynF+7Ar0cwrlwTRnk0yfb3/SXuxOMd3vnRzL/Ll+K80 +BfJedUAq04/XT6oXfQnxFj4c9+bperuYkoNatHEIl/xul88Hc0jeI/ZYBrTJyacR +i5VQ8C7LJYWxMHlsYYTutOofsaeAxQks466D+Ao879G4+x4ukQMhZWL+/qbHzc9/ +MdSZz245Y98a8v1VMyLvqCYvFfbZY6Ksu/G/6cHHiNFP2Bk4zozTvKgVMroFWHT1 +jPqqn1JCZy5zVwTsV8pspvXyhLUNCQkaZA== +-----END CERTIFICATE----- diff --git a/data/Netpong-Test-CA/private/cakey.pem b/data/Netpong-Test-CA/private/cakey.pem new file mode 100644 index 0000000..04e2fdf --- /dev/null +++ b/data/Netpong-Test-CA/private/cakey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCNzjjeONRhk/hp +ULS8PRZGnMLobnTC9reUtfa85/rHXEAT+xVDsXePbmz+hRTMdJ/j8XgfesJHlman +I4GJb/Vm5BVvjwfHMTtWH9BB6dNRVw8R1lyp/S8uiAPNpKur24xe+ZYdaBAgTTJh +sQF3b9sTSTnfQRblBmkp1Rkjqb5N/qTrQWTrmyQLghnrzgzpqEH0BCIFjRzoPMk8 +3oBXfezoeMeoslR5bCIQVfHu/8jcWjzU0eehFlDD1s16XetFrU6+fUUhTPesrKBd +vf9lyXdMqHZ5FdvtsmYbfl2H4LH060+VhKJTjnDkrFrv5zWfYf6sO/lCVwe2xRHY +40MNEbgzAgMBAAECggEAIMO52wqpc8RTPM4zfFzm9TjKRhcjblrADyG+GWbGSGL1 +wUgd4S6zj9X1ZBeOtzDpMqs71JYyJoVHQa4QA5f1TSk9FLIpG2qyKZOfNGOY+m3R +ow7zCSnhSXCO5Gh8a/CF7fngJ/o/457CmdTioFydc0bTktSAvDkvekVtEhLp0C5C +jTxhOYFaSznpLccHVkZtu2hYqSInTLFk3YVBi1qHO8qGbnUCj1PWSxV1wTmu/Ilo +wVw3OFyCoZhjrSN3sjNYpOFJEAV5eb9AUGCum6r+Zo7GNPiM7jDShfRidD8mjcq9 +YDDkInTETHVcmr1U5CByUagDl7//ifaRBoBy5E3GPQKBgQDDKneviwuCGt2y5qbN +PPILMXHwMxja77iDIily7Mg9cbi8Cmq4fcLcPs6SEoMmHHzuAFICrWXjJJ14npfv +PR/UnIqDo95PclsjHe1dou396eqrtNGUBp5c8lt8tZGbLcLdCZMOsKqCdiPTmw1T +vaGnx4GRaQIoOVeW0N8me0J9hQKBgQC6Acr6JP/tD40s04fQb6SBMz+mTiAGPoel +R0crnh6rqb4wvomX5yoT9JRI80+i/aqVtm7COb512nq2CLc4SKSOdVSEHaRTUmOC +lLnImM9rQoP13VEwuGnL7kMv7mNc2sOZl6WHGmAnHS27zDV+e74vUIyjAdqUAUsL +C19SU5nQVwKBgQCbo7pe29wJnbM/gIF1Gy1Lj9r1W0pvDs1uhkfXxszJc2+HRidl +iaVkTxIdm3XLZtyaUNcWG4Itan3KO2+e8nf37f7ojD41zVSw5KTvD4gL/gePd1vL +WJviM8SR55p+zjegXopQJMNV1zErB3PRXGEWlBvYAo4d1dzsARZ0ccfMoQKBgB+Z +AF8f++3Mb4IG6RJqdLqR9yUMLnqBEs/r3NY3BSTKMAndxEfuuAIt0SbXVlbs2paW +KBiMcKNamu/jaSSBipq8qb/LvUd+PnNHSoweEVY6NWqFzy4ElcxTzEwPJgf3DbVA +wpjBzUW3ujYlyYyT/snQ2CM0xGnSEmps4yN8Giv/AoGALsiOvNv/jUNU/RM+OznR +93Q7WsmjZxbPFLAdpiI+Fl8zcERlSGqBKSxQSdeD7Tke5Ywzc/LHqNhTJjnDjJCY +xWzDRe/ALUHCEEc4C6dd5qPmD30T8Fb8fRX6HVFHqT3VKb3KKrpZYvkNY8ihprq6 +iLDnm4a9JQ3aGrzkgV6xxlo= +-----END PRIVATE KEY----- diff --git a/data/Netpong-Test-CA/private/localhost.key b/data/Netpong-Test-CA/private/localhost.key new file mode 100644 index 0000000..9e2a241 --- /dev/null +++ b/data/Netpong-Test-CA/private/localhost.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +nUyPrKRIgMlaQ+VkMxifhq9MzBqyB7I= +-----END PRIVATE KEY----- diff --git a/data/Netpong-Test-CA/serial b/data/Netpong-Test-CA/serial new file mode 100644 index 0000000..8a0f05e --- /dev/null +++ b/data/Netpong-Test-CA/serial @@ -0,0 +1 @@ +01 diff --git a/data/Netpong-Test-CA/serial.old b/data/Netpong-Test-CA/serial.old new file mode 100644 index 0000000..4daddb7 --- /dev/null +++ b/data/Netpong-Test-CA/serial.old @@ -0,0 +1 @@ +00 diff --git a/data/ca.conf b/data/ca.conf new file mode 100644 index 0000000..f83aa0c --- /dev/null +++ b/data/ca.conf @@ -0,0 +1,32 @@ + [ ca ] + default_ca = Netpong-Test-CA # The default ca section + + [ Netpong-Test-CA ] + + dir = ./Netpong-Test-CA # top dir + database = $dir/index.txt # index file. + new_certs_dir = $dir/newcerts # new certs dir + + certificate = $dir/cacert.pem # The CA cert + serial = $dir/serial # serial no file + private_key = $dir/private/cakey.pem# CA private key + RANDFILE = $dir/private/.rand # random number file + + default_days = 3650 # how long to certify for + default_crl_days= 30 # how long before next CRL + default_md = sha256 # md to use + + policy = policy_any # default policy + email_in_dn = no # Don't add the email into cert DN + + name_opt = ca_default # Subject name display option + cert_opt = ca_default # Certificate display option + copy_extensions = none # Don't copy extensions from request + + [ policy_any ] + countryName = optional + stateOrProvinceName = optional + organizationName = optional + organizationalUnitName = optional + commonName = supplied + emailAddress = optional diff --git a/data/just_works/README.md b/data/just_works/README.md new file mode 100644 index 0000000..f7323bb --- /dev/null +++ b/data/just_works/README.md @@ -0,0 +1,27 @@ +Using openssl to generate stuff is an endless hole, that will only make you +frustrated and waste your time. Don't even bother. You have been warned. + +The stuff below is stolen from [here](https://stackoverflow.com/questions/60751795/unable-to-use-self-signed-certificates-with-tokio-rustls). +It just worked, after hours of trying to set up a selfsigned pki with v3 x509 +(rustls decided not to support the regular v1) + +--- + +You probably used a CA certificate as a client certificate. + +Create a CA: + +openssl req -x509 -noenc -subj '/CN=example.com' -newkey rsa -keyout root.key -out root.crt + +Create a certificate signing request (CSR): + +openssl req -noenc -newkey rsa -keyout client.key -out client.csr -subj '/CN=example.com' -addext subjectAltName=DNS:example.com + +Sign it using your CA: + +openssl x509 -req -in client.csr -CA root.crt -CAkey root.key -days 365 -out client.crt -copy_extensions copy + +And then you use the certificate client.crt and the key client.key. And the client should trust your root.crt. + +The addext and copy_extensions flag ensure that they generated key is X509v3, otherwise webpki will start complaining. And subjectAltName is required to prevent rustls from complaining. + diff --git a/data/just_works/root.crt b/data/just_works/root.crt new file mode 100644 index 0000000..a9cfb15 --- /dev/null +++ b/data/just_works/root.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUcD/jxH3qOc8VK/FXAeP6nimT0W4wDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDEyNDE0NTYzMloXDTI0MDIy +MzE0NTYzMlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAmc0kWDjYQ9073nXLsGYN2ovyxOHKjWcREFbuTLp2qf+A +CpK6j+mBFngNNKlTJvQKhrULdUf61WeBwz0zYiExibd4jlGERjzK/5Aj1z+eUKBA +TiwfmvnpHGNvsU2WrfNd9wBjiJV/FB17JDYJZVfiswpbdV+9066fzQ0LImHBj1ON +vcwSPIrxwG3oe+zPGIO9CpQHUEzaMy6S5AUgDHwtiTwQwucu5Up4xM5WA1kVCiMq +Fc9qv84RxhhSOlWbCVeRMZP1qiWzMRs2vGVOfX/D6gL21qHliVLIP2lrs1ISdqM9 +OMCCxMb8MAqtIECxVCm3cNE/YeBaoA7p2JlkY0BB+wIDAQABo1MwUTAdBgNVHQ4E +FgQUKAvw/RZZKZHpaxVLWVlijc+BROwwHwYDVR0jBBgwFoAUKAvw/RZZKZHpaxVL +WVlijc+BROwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAeNmR +fTyPanTRdTYewpJZPRZ1SvROwfzAAwMu6CqMqnH1aLizG2DFNAeHoU+TezvgXb2u +lvuIqNuUdLDTUWIhZkCgL/TQhnKWfAv9jqP2h85TgRCNAzEHYgFtXuHYnTuB4KAg +AAsRsY6r5bTvr/eDBeufOn7+MIbPp795g5ffD6YFv5gRGlKDBudwA2N0upptiZT9 +Vzzf6SdPyskIdtLLA4QeY0lCsqekpd3Bo0fM0D0LgIw4+R+D5iYLUNRCkYqj0ydj +tJQEOdWVKtEdbylYlFF0QFSEAtszOW9yRPbfIY7n84WC2Z9zCYTls8V0sgw9PfMs +P1J2bn37/RNoNykeTA== +-----END CERTIFICATE----- diff --git a/data/just_works/root.key b/data/just_works/root.key new file mode 100644 index 0000000..b5f7133 --- /dev/null +++ b/data/just_works/root.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCZzSRYONhD3Tve +dcuwZg3ai/LE4cqNZxEQVu5Munap/4AKkrqP6YEWeA00qVMm9AqGtQt1R/rVZ4HD +PTNiITGJt3iOUYRGPMr/kCPXP55QoEBOLB+a+ekcY2+xTZat8133AGOIlX8UHXsk +NgllV+KzClt1X73Trp/NDQsiYcGPU429zBI8ivHAbeh77M8Yg70KlAdQTNozLpLk +BSAMfC2JPBDC5y7lSnjEzlYDWRUKIyoVz2q/zhHGGFI6VZsJV5Exk/WqJbMxGza8 +ZU59f8PqAvbWoeWJUsg/aWuzUhJ2oz04wILExvwwCq0gQLFUKbdw0T9h4FqgDunY +mWRjQEH7AgMBAAECggEADkpu8Zmakre4S+PjIMliySdOz/dw9DGa9ss1CkEbLJGW +iqT2m8+lFHrkMzv2g3ySi9C/t06QYorjFkqV/yy5ZyP6mjK92S7l59gzVFlPcwto +3jqgVyyYefBNXQqqERC3bu+E0Bif/bT9j7BLsDR51owEUoQqZcRoicuH+NJfg1sp +ndoLSfS6HTewS0oVAHaXgS02BsBoWCfEmf4G5VXhJvwgRN+QHgrni8bvuXFzoD48 +e+uv+LVMOYaG7bf3jOEun3kdvNtrocEVA5lsc8mIfz6ie/b703p3FsS7FuIrUUqN +raVkvwxBeqeXPf94IBRUuicn+tH0fT9g/Pwsd+zhvQKBgQC1Ku/cKxwguoHFWlwv +17rTmNYAPgEQ8PXai+05LjVBi0ZMKfRJ7jSbV/JZbZy9omGqvqo8w4rLE6uQDEXv +huKYqQP8azp6pav6mX+G/zxHw606QNw12vc98egGCQeOPRUa6O2GK8BZkbJ7OKvF +NQ0Vy0hDDAldzYOTPpGIWXTrfQKBgQDZVGy3Yb+ynB35g0qHpVxN0tLZhe29Vnrb +yyZ5Jpg0tIa1sce9vOF1eYj1W/HlnfNeKiJ4/Qd6SXZjM8MQAvuvwaRf/dsexF49 +WQwTPVro+oDL7OEq/Bj3vjM7AuDs99TuEbqLk6pw+Tsrw1sSGiyNMe5hKxE4bRD4 +4VKxIfks1wKBgQCjD6liZl7jylrBMeplmWtrxlVfVG+LOwZeFbGH1OJUQzIbnWtm +G4O4Cjl0amc4e+4iS4hYNrw2ulahyZos1CAhvYZ77FtvRqx7Wytga1xrT2EcXIKX +6qS8WX436GqniKz1Uo9vQvPW6n9VzxUz4+MKKbS5vBy2FCMIJbnBmprU1QKBgAwp +4XvSCLyiaDsS0hUNeEESz6JFEK1MLcwnbpvRQSuR/wgkTx2beLLufm/dGYjUck6O +5ScIYmbBvdKHjx9SS2vm1qBYwO7T5sJgPYDGKlRn0NWZCHEzcuJKzus6mgQpSs2Y +SGyPczanfFxSrsIwnNW6ObFOi8QwtoZ3df1b/Wo5AoGAFmiDM8D4G3DVkZaKwSgX +6KpyQL2Vl1lyDzFiiBMy7REqy6KruZivmxlFwepkyTFbQt7r3BtWwwEq4teZiPXx +JOdD5MnAUeoR5XvMN064IsLeC9ReTEBWrrh0XciAWTNpfsM0861V3OgX9NQIOXcc +wRZa4TAcJKBJO4+ftFKCi30= +-----END PRIVATE KEY----- diff --git a/data/just_works/test.crt b/data/just_works/test.crt new file mode 100644 index 0000000..07c8b0e --- /dev/null +++ b/data/just_works/test.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDDjCCAfagAwIBAgIUCa25BV6Yb+yazosg/MltJOTnuhUwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDEyNDE0NTcwOVoXDTI1MDEy +MzE0NTcwOVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA8Z284xhdzPP6PfAmmy8TGtITFcRoARqWicOMBFGDuzNy +BKnU5oO/3mEt41C+ZllKgUodyx373WmKylV2l2JTQza2LZPXBVDUf/i4L7TwvqtR +Ia5w//EZ0kfozxTB0WXRutJqbxKizN/yLpzAKNgKYp73x8hOBD7cpKJ/wlZ4qFXq +cR7K+P4/HvTVCyqdnaG/UMVnnRnuOUu1XYPXhaTvsxh7Febxu7lShZeB/oyaaDCR +K9oA6eJV6lAWOqaMLWuHYfma0fjwEgr+tV3IkIVOfAdp91jo1bvgNdfoF1jxMmD5 +v/0DpbkbcpOF8zQ3la+foloyQJuutx4bcj7sRfLMiwIDAQABo1gwVjAUBgNVHREE +DTALgglsb2NhbGhvc3QwHQYDVR0OBBYEFCCuIWcRm+7YgC8qmX87aWFc3l2qMB8G +A1UdIwQYMBaAFCgL8P0WWSmR6WsVS1lZYo3PgUTsMA0GCSqGSIb3DQEBCwUAA4IB +AQAkBR4fl1Vhx1WPCXdnyM5yocCUv3SfbzKJlevOqXWYzjCXUzB3LMqNrjjCcSUA +z42BYfv9cvmKfp5G77M3LEE9sUyKL+epyNBTgh5N/d1xZdITKuHL6c2OCaIHKowg +cP7kxFWFU5QDwYKhhkn6GRYoasS+B0jxCwW+k2pgUKxsMOZMmoBWVJL+MPyPBzV4 +9oeYi50s+8RFAzsjXlHan6me6egbiJIn8DmBrshUG9LJzElPC6n6aixY9Ar0E6hR +O/25jHtFApXWzMsM5CwIRfb0JPMEB46+BUk89km2XYjFqUFp3PIjJz+/AMk07qEP +vykAMiOZ9ZP3XeZryzdLCIfd +-----END CERTIFICATE----- diff --git a/data/just_works/test.csr b/data/just_works/test.csr new file mode 100644 index 0000000..b7b3434 --- /dev/null +++ b/data/just_works/test.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICgDCCAWgCAQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA8Z284xhdzPP6PfAmmy8TGtITFcRoARqWicOMBFGD +uzNyBKnU5oO/3mEt41C+ZllKgUodyx373WmKylV2l2JTQza2LZPXBVDUf/i4L7Tw +vqtRIa5w//EZ0kfozxTB0WXRutJqbxKizN/yLpzAKNgKYp73x8hOBD7cpKJ/wlZ4 +qFXqcR7K+P4/HvTVCyqdnaG/UMVnnRnuOUu1XYPXhaTvsxh7Febxu7lShZeB/oya +aDCRK9oA6eJV6lAWOqaMLWuHYfma0fjwEgr+tV3IkIVOfAdp91jo1bvgNdfoF1jx +MmD5v/0DpbkbcpOF8zQ3la+foloyQJuutx4bcj7sRfLMiwIDAQABoCcwJQYJKoZI +hvcNAQkOMRgwFjAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQAD +ggEBAH5eaWnbsbys+CFHbzzpmXpnZpvCvrkvekJEm/21WAKGfcfl0o6IbyIGXePO +ASdWtiXcHhUIQ6c8V6nNIjP26sJR5Ol5qlPpHY+rP0CfKydwhOiu0Ty2Ceqqk2qV +AMG57tIR0XDNB8s1/cqIWqqX3vO4QEooBZlzY4Cu0HZKgnKNbV1XEjE4P4KbmEq2 +DJUSO0ewqgYHdY227zjWVUFxicVOWiQQ9wLHl1ICBmHYzDiROSWzIswd8IZZvAGw +2+ulMnfEXKr04NN2AKj+DgZLyi7QhRL9MqnBAAGeQqmBVZjhn8dfuHUJFo6+xKe1 +kB/FW9YU50Vt8mMxhwsA4XY0BEo= +-----END CERTIFICATE REQUEST----- diff --git a/data/just_works/test.key b/data/just_works/test.key new file mode 100644 index 0000000..bed5d00 --- /dev/null +++ b/data/just_works/test.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDxnbzjGF3M8/o9 +8CabLxMa0hMVxGgBGpaJw4wEUYO7M3IEqdTmg7/eYS3jUL5mWUqBSh3LHfvdaYrK +VXaXYlNDNrYtk9cFUNR/+LgvtPC+q1EhrnD/8RnSR+jPFMHRZdG60mpvEqLM3/Iu +nMAo2ApinvfHyE4EPtykon/CVnioVepxHsr4/j8e9NULKp2dob9QxWedGe45S7Vd +g9eFpO+zGHsV5vG7uVKFl4H+jJpoMJEr2gDp4lXqUBY6powta4dh+ZrR+PASCv61 +XciQhU58B2n3WOjVu+A11+gXWPEyYPm//QOluRtyk4XzNDeVr5+iWjJAm663Hhty +PuxF8syLAgMBAAECggEAd2wAJvztq/YxSzjuVAiV+E06GqmrwFPscSZCiAXkRvxc +EDsDHHalOJyuyiqoGT1sCnBgPntQ+HSIoY5RYey6+79Il0l530o+5gvAue/EiHFz +1eJ7Pr3kBd/+DZCUZdPeMGl9Ku46omnUMb7PacCyjWFGVixGh2mstAEPhbYoyAZN +TyuGU1GQMtKlGOt9bibvzt/rMZlCZvQyCINOeU//9lGpmilvUbKFIxUzE1SRevXa +a1WZn4KEIphGPOF/dbgWhGMhVuoyaiLGriTsNUtky4dT/6e+IUEus9SkPDnooo18 +ZN3cuNqZKB4IIXrlfBw7bBQQ4XsILVXKq5XAMhvlVQKBgQD2REmOWCkZQvzsTNj2 +CxaOo5LsUqxQK1/eB5tgMf6qQVhodRZ3nMrSZGsGjJJDvRDyc6DtN1saLqr6KWdi +qGFySTA2dcoiSupFp7QqtGA5TARgy+lYh4QOYcUjobmCHH+OJtyzxWV+vsRF/wcI +RE0nbt9PkbN6K33HVUVMKsdxBwKBgQD7KmVrnPsSEygfV1tujf4a3pn1t4rOryej +yUQzd1YDc4QAkCuTZ9e2nMx5eyf57gIqjhFfThxe873a/wtKq9veDFiaBoZyOeL/ +WAaP0YS0hpnOahrtcnaF3C/hvMbiF1Z0CCmIwL9UrxsS5PeC7qlsSObAMqXalPnR +oXBg6xUbXQKBgF6tqknbgxF/O5XthYwyfx2fraDFuBGqW1UVP5sgHXR/Yunl+hlK +Yn+4s5z09lasnZNY+Qm6OoA6aOl8eY7ohW5WzP5jEq9UdfUJoK66YjQlEZnVS4UJ +tK+CzzP/vT5UjoWsUzWaMocj+Hmgrqdy+uaqLZh9v668gcLc+aNq3vqJAoGAL4ec +Xbr9QDRj2Vp8sPUp6wfI9tje6bH3vGTwBRVGL60Cg+DEfkaeaa5Oe4a0z/Ucb9Um +sHRlpgpWGUU+a8kN+H05nxwxARi3Pj74LuslQ8xc+tTVd627hCVg4kUJFev4rkiF +I53mFy5z3yV5OUvUv+sjz6dF/5FFnUgBrjWObvkCgYASOqDXKOhMey2VgrHYCEGJ +VGlYG/NOTSOhvJKeS9LEgi4IaNWwbRSeR94AB749tZKCvz9jin+VJyxZsE/StCoS +Dg8xIC/lrB5S4FVoLUD/cn9k0SSI/AsnISpW21BUZPCwzOM4NDvyf3uGhRZXPOTk +8b+Chcc4BjK6X3oKgt4ztQ== +-----END PRIVATE KEY----- diff --git a/scripts/client.py b/scripts/client.py deleted file mode 100644 index 8aa1142..0000000 --- a/scripts/client.py +++ /dev/null @@ -1,21 +0,0 @@ -import socket - -HOST = "127.0.0.1" -PORT = 9999 - -payload = b"ping\0" - -with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.connect((HOST, PORT)) - while True: - try: - s.sendall(payload) - print("> ping") - except Exception as e: - break - reply = s.recv(1024).decode() - if reply == "": - break - print(f"< {reply}") - print("connection shut down") - diff --git a/scripts/make_cert.sh b/scripts/make_cert.sh new file mode 100755 index 0000000..2dd0782 --- /dev/null +++ b/scripts/make_cert.sh @@ -0,0 +1,5 @@ +#!/bin/bash +mkdir data +echo create ca +# non-interactive and 10 years expiration +openssl req -x509 -nodes -newkey rsa:4096 -keyout data/key.pem -out data/cert.pem -sha256 -days 3650 -subj '/CN=localhost' diff --git a/spammer/Cargo.toml b/spammer/Cargo.toml new file mode 100644 index 0000000..ed89719 --- /dev/null +++ b/spammer/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "spammer" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +threadpool = "1.8.1" diff --git a/spammer/src/main.rs b/spammer/src/main.rs new file mode 100644 index 0000000..a95f16e --- /dev/null +++ b/spammer/src/main.rs @@ -0,0 +1,18 @@ +use threadpool::ThreadPool; +const MAX: usize = 20; +use std::process::Command; + +fn main() { + let pool = ThreadPool::new(MAX); + + loop { + if pool.queued_count() < MAX { + pool.execute(|| { + let mut cmd = Command::new("/usr/bin/python3"); + cmd.args(["../scripts/client.py"]); + let _ = cmd.output().unwrap(); + }); + } + std::thread::sleep(std::time::Duration::from_millis(100)); + } +} diff --git a/src/client/mod.rs b/src/client/mod.rs index 8b13789..10fc9c4 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1 +1,79 @@ +#![cfg(feature = "server")] +use std::{fs::File, io::BufReader, sync::Arc}; +use crate::{common::decode, Config}; + +use anyhow; +use libpt::log::{error, info, trace}; +use rustls_pemfile::certs; +use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::TcpStream, +}; +use tokio_rustls::{ + rustls::{self, pki_types}, + TlsConnector, +}; +use webpki_roots; + +const BUF_SIZE: usize = 512; + +pub struct Client { + cfg: Config, + stream: TcpStream, + connector: TlsConnector, + domain: pki_types::ServerName<'static>, +} + +impl Client { + pub async fn build(cfg: Config) -> anyhow::Result { + let mut root_cert_store = rustls::RootCertStore::empty(); + root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + if cfg.certs.is_some() { + let mut reader = BufReader::new(File::open(cfg.certs.clone().unwrap())?); + for cert in certs(&mut reader) { + trace!("found custom cert: {cert:?}"); + root_cert_store.add(cert?)? + } + } + trace!("root cert store: {root_cert_store:?}"); + let tls_config = rustls::ClientConfig::builder() + .with_root_certificates(root_cert_store) + .with_no_client_auth(); + let connector = TlsConnector::from(Arc::new(tls_config)); + let stream = TcpStream::connect(&cfg.addr).await?; + let domain = match pki_types::ServerName::try_from(cfg.hostname.clone()) { + Ok(domain) => domain, + Err(err) => { + error!("Could not resolve hostname '{}': {err:?}", cfg.hostname); + return Err(err.into()); + } + }; + + Ok(Client { + cfg: cfg.clone(), + stream, + connector, + domain, + }) + } + + pub async fn run(self) -> anyhow::Result<()> { + let mut stream = self.connector.connect(self.domain, self.stream).await?; + let mut buf = [0; BUF_SIZE]; + stream.write_all(b"ping").await?; + info!("> ({}) ping", self.cfg.hostname); + while stream.read(&mut buf).await? > 0 { + let response = decode(&buf)?; + info!("< ({}) {}", self.cfg.hostname, response); + if response == "You win!" { + break; + } + stream.write_all(b"ping").await?; + info!("> ({}) ping", self.cfg.hostname); + // we should wait, so that we don't spam the client + std::thread::sleep(self.cfg.delay); + } + Ok(()) + } +} diff --git a/src/common/args.rs b/src/common/args.rs index 9a53635..3d161f8 100644 --- a/src/common/args.rs +++ b/src/common/args.rs @@ -1,10 +1,10 @@ +use std::path::PathBuf; + use libpt::log::{Level, Logger}; use clap::Parser; use clap_verbosity_flag::{InfoLevel, Verbosity}; -use crate::common::conf::Mode; - /// short about section displayed in help const ABOUT_ROOT: &'static str = r##" Let your hosts play ping pong over the network @@ -46,16 +46,14 @@ pub(crate) struct Cli { #[arg(short, long, default_value_t = false)] pub(crate) server: bool, - // how much threads the server should use - #[cfg(feature = "server")] - #[arg(short, long, default_value_t = 4)] - pub(crate) threads: usize, - - #[arg(short, long, default_value_t = Mode::Tcp, ignore_case = true)] - pub(crate) mode: Mode, - /// Address of the server - pub(crate) addr: std::net::SocketAddr, + pub(crate) host: String, + + #[cfg(feature = "server")] + #[arg(short, long)] + pub key: Option, + #[arg(short, long)] + pub certs: Option, } impl Cli { @@ -72,7 +70,7 @@ impl Cli { } }; if cli.meta { - Logger::init(None, Some(ll)).expect("could not initialize Logger"); + Logger::init(None, Some(ll), true).expect("could not initialize Logger"); } else { // less verbose version Logger::init_mini(Some(ll)).expect("could not initialize Logger"); diff --git a/src/common/conf.rs b/src/common/conf.rs index a860098..f80bd52 100644 --- a/src/common/conf.rs +++ b/src/common/conf.rs @@ -1,65 +1,61 @@ use crate::common::args::Cli; -use clap::ValueEnum; -use std::{fmt::Display, time::Duration}; + +use std::{ + net::{SocketAddr, ToSocketAddrs}, + path::PathBuf, + time::Duration, +}; + +use anyhow::{anyhow, Result}; +use libpt::log::{error, trace}; const DEFAULT_TIMEOUT_LEN: u64 = 5000; // ms const DEFAULT_DELAY_LEN: u64 = 500; // ms const DEFAULT_WIN_AFTER: usize = 20; -#[derive(Debug, Clone, Copy)] -pub enum Mode { - Tcp, -} - -impl ValueEnum for Mode { - fn to_possible_value(&self) -> Option { - Some(match self { - Self::Tcp => clap::builder::PossibleValue::new("tcp"), - }) - } - fn value_variants<'a>() -> &'a [Self] { - &[Self::Tcp] - } - fn from_str(input: &str, ignore_case: bool) -> Result { - let comp: String = if ignore_case { - input.to_lowercase() - } else { - input.to_string() - }; - match comp.as_str() { - "tcp" => return Ok(Self::Tcp), - _ => return Err(format!("\"{input}\" is not a valid mode")), - } - } -} - -impl Display for Mode { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let repr: String = match self { - Self::Tcp => format!("tcp"), - }; - write!(f, "{}", repr) - } -} - +#[derive(Clone)] pub struct Config { pub addr: std::net::SocketAddr, - pub mode: Mode, - pub threads: usize, + pub hostname: String, pub timeout: Duration, pub delay: Duration, + #[cfg(feature = "server")] pub win_after: usize, + #[cfg(feature = "server")] + pub key: Option, + pub certs: Option, } impl Config { - pub fn new(cli: &Cli) -> Self { - Config { - addr: cli.addr.clone(), - mode: cli.mode.clone(), - threads: cli.threads, + pub fn build(cli: &Cli) -> Result { + let addr: SocketAddr = match cli.host.to_socket_addrs() { + Ok(mut addr) => addr.next().unwrap(), + Err(err) => { + error!( + "could not resolve host {:?} to a socket address: {err:?}", + cli.host.clone() + ); + return Err(anyhow!( + "could not resolve host {:?} to a socket address: {err:?}", + cli.host + )); + } + }; + let hostname = match cli.host.split_once(':') { + Some(hostname) => hostname.0.to_string(), + None => return Err(anyhow!("malformatted host (no port specified)")), + }; + trace!("config has resolved the given hostname to: {addr:?}"); + Ok(Config { + addr, + hostname, timeout: Duration::from_millis(DEFAULT_TIMEOUT_LEN), delay: Duration::from_millis(DEFAULT_DELAY_LEN), + #[cfg(feature = "server")] win_after: DEFAULT_WIN_AFTER, - } + #[cfg(feature = "server")] + key: cli.key.clone(), + certs: cli.certs.clone(), + }) } } diff --git a/src/common/mod.rs b/src/common/mod.rs index f4200ec..098dde5 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,2 +1,14 @@ +use std::str::Utf8Error; + pub mod args; pub mod conf; + +#[inline] +pub fn decode(buf: &[u8]) -> Result { + Ok(match std::str::from_utf8(buf) { + Ok(s) => s.to_string(), + Err(err) => return Err(err.into()), + } + .trim_matches(char::from(0)) + .to_string()) +} diff --git a/src/main.rs b/src/main.rs index f0f5acc..5c73f3c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,14 +13,14 @@ mod server; use common::{args::Cli, conf::*}; -use crate::server::Server; +use crate::{client::Client, server::Server}; #[tokio::main] async fn main() -> Result<()> { let cli = Cli::cli_parse(); debug!("dumping cli args:\n{:#?}", cli); - let cfg = Config::new(&cli); + let cfg = Config::build(&cli)?; #[cfg(feature = "server")] if cli.server { @@ -29,5 +29,5 @@ async fn main() -> Result<()> { } // implicit else, so we can work without the server feature info!("starting client"); - Ok(()) + return Client::build(cfg).await?.run().await; } diff --git a/src/server/errors.rs b/src/server/errors.rs index 90dd1f5..7485d1b 100644 --- a/src/server/errors.rs +++ b/src/server/errors.rs @@ -1,4 +1,4 @@ -use std::{fmt::Display, string::FromUtf8Error}; +use std::{fmt::Display, str::Utf8Error}; use anyhow; use thiserror::Error; @@ -11,7 +11,7 @@ pub enum ServerError { Timeout(Elapsed), Anyhow(anyhow::Error), IO(std::io::Error), - Format(FromUtf8Error), + Format(Utf8Error), } impl From for ServerError { @@ -26,8 +26,8 @@ impl From for ServerError { } } -impl From for ServerError { - fn from(value: FromUtf8Error) -> Self { +impl From for ServerError { + fn from(value: Utf8Error) -> Self { Self::Format(value) } } diff --git a/src/server/mod.rs b/src/server/mod.rs index 3e3a021..842ab5a 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,125 +1,189 @@ #![cfg(feature = "server")] -use std::time::Duration; - -use libpt::log::{debug, info, trace, warn}; -use tokio::{ - io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, - net::{TcpListener, TcpStream}, - time::timeout, +use std::{ + fs::File, + net::SocketAddr, + sync::{atomic::AtomicUsize, Arc}, + time::Duration, }; -use crate::common::conf::Config; +use libpt::log::{debug, error, info, trace, warn}; +use rustls::pki_types::{CertificateDer, PrivateKeyDer}; +use rustls_pemfile::{certs, private_key}; +use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::{TcpListener, TcpStream}, + time::{self}, +}; +use tokio_rustls::{rustls, TlsAcceptor}; + +use crate::common::{conf::Config, decode}; pub mod errors; use errors::*; +const BUF_SIZE: usize = 512; + pub struct Server { cfg: Config, - pub timeout: Option, server: TcpListener, + num_peers: AtomicUsize, + acceptor: TlsAcceptor, } impl Server { pub async fn build(cfg: Config) -> anyhow::Result { + let certs = Self::load_certs(cfg.clone())?; + trace!("loaded certs: {:?}", certs); + let key = Self::load_key(cfg.clone())?.expect("bad key?"); + trace!("loaded key: {:?}", key); + let tls_config = rustls::ServerConfig::builder() + .with_no_client_auth() + .with_single_cert(certs, key)?; + let acceptor = TlsAcceptor::from(Arc::new(tls_config)); let server = TcpListener::bind(cfg.addr).await?; - let timeout = Some(Duration::from_secs(5)); + Ok(Server { cfg, - timeout, server, + num_peers: AtomicUsize::new(0), + acceptor, }) } + pub async fn run(self) -> anyhow::Result<()> { + let rc_self = Arc::new(self); + let ref_self = rc_self.clone(); + tokio::spawn(async move { + let mut interval = time::interval(Duration::from_millis(5000)); + loop { + interval.tick().await; + info!( + "status: {} peers", + ref_self + .num_peers + .load(std::sync::atomic::Ordering::Relaxed) + ); + } + }); loop { - let (stream, addr) = match self.server.accept().await { + let (stream, addr) = match rc_self.server.accept().await { Ok(s) => s, Err(err) => { - warn!("could not accept stream: {err:?}"); + warn!("could not accept tcp stream: {err:?}"); continue; } }; - match self.handle_stream(stream).await { - Ok(_) => (), - Err(err) => { - match err { + let ref_self = rc_self.clone(); + // NOTE: we can only start the task now. If we start it before accepting connections + // (so that the task theoretically accepts the connection), we would create endless + // tasks in a loop. + tokio::spawn(async move { + let stream: tokio_rustls::server::TlsStream<_> = + match ref_self.acceptor.accept(stream).await { + Ok(s) => s, + Err(err) => { + warn!("could not accept tls stream: {err}"); + return; + } + }; + ref_self.peer_add(1); + match ref_self.handle_stream(stream, addr).await { + Ok(_) => (), + Err(err) => match err { ServerError::Timeout(_) => { - info!("stream {:?} timed out", addr) + debug!("stream {:?} timed out", addr) } _ => { warn!("error while handling stream: {:?}", err) } - } - continue; - } - }; + }, + }; + ref_self.peer_sub(1); + }); } } - async fn handle_stream(&self, stream: TcpStream) -> Result<()> { - let mut pings: usize = 0; - let addr = match stream.peer_addr() { - Ok(a) => a, - Err(err) => { - debug!("could not get peer address: {:?}", err); - return Err(err.into()); - } - }; - info!("new peer: {:?}", addr); - let mut buf = Vec::new(); - let mut reader = BufReader::new(stream); - let mut len; - loop { - len = match self.read(&mut reader, &mut buf).await { - Ok(len) => len, - Err(err) => { - match err { - ServerError::Timeout(_) => { - info!("peer {:?} timed out", addr) - } - _ => return Err(err), - } - break; - } - }; - trace!("received message: {:X?}", buf); - if len == 0 { - trace!("len is apperently 0: {len:?}"); - break; - } else { - let msg = self.decode(&buf)?; - info!("< {:?} : {}", addr, msg); - if msg.contains("ping") { - pings += 1; - } - if pings < self.cfg.win_after { - reader.write_all(b"pong\0").await?; - info!("> {:?} : pong", addr,); - } else { - reader.write_all(b"you win!\0").await?; - info!("> {:?} : you win!", addr,); - reader.shutdown().await?; - break; - } - buf.clear(); + fn load_key(cfg: Config) -> std::io::Result>> { + if cfg.key.is_none() { + error!("the server needs a key!"); + return Err(std::io::ErrorKind::InvalidInput.into()); + } + let key = private_key(&mut std::io::BufReader::new(File::open( + cfg.key.clone().unwrap(), + )?)); + return key; + } - // we should wait, so that we don't spam the client - std::thread::sleep(self.cfg.delay); + fn load_certs(cfg: Config) -> std::io::Result>> { + if cfg.certs.is_none() { + error!("the server needs at least one certificate!"); + return Err(std::io::ErrorKind::InvalidInput.into()); + } + match certs(&mut std::io::BufReader::new(File::open( + &cfg.certs.clone().unwrap(), + )?)) + .collect::>>>() + { + Ok(v) if !v.is_empty() => Ok(v), + Ok(_) => { + error!("no certs found in provided file {:?}", cfg.certs); + return Err(std::io::ErrorKind::InvalidInput.into()); + } + Err(err) => { + error!("could not load certs: {err:?}"); + return Err(err); } } - info!("disconnected peer: {:?}", addr); + } + + #[inline] + fn peer_add(&self, v: usize) { + self.num_peers.store( + self.num_peers.load(std::sync::atomic::Ordering::Relaxed) + v, + std::sync::atomic::Ordering::Relaxed, + ) + } + + #[inline] + fn peer_sub(&self, v: usize) { + self.num_peers.store( + self.num_peers.load(std::sync::atomic::Ordering::Relaxed) - v, + std::sync::atomic::Ordering::Relaxed, + ) + } + + async fn handle_stream( + &self, + mut stream: tokio_rustls::server::TlsStream, + addr: SocketAddr, + ) -> Result<()> { + let mut buf = [0; BUF_SIZE]; + let mut pings = 0; + debug!("new peer: {:?}", addr); + while stream.read(&mut buf).await? > 0 { + let request = decode(&buf)?; + debug!(pings, "< ({})\n\"{}\"", addr, request); + if request == format!("ping") { + pings += 1; + if pings > self.cfg.win_after { + stream.write_all(b"You win!").await?; + debug!(pings, "> ({})\n\"{}\"", addr, "You win!"); + info!("{} won!", addr); + stream.flush().await?; + stream.shutdown().await?; + break; + } + stream.write_all(b"pong").await?; + debug!(pings, "> ({})\n\"{}\"", addr, "pong"); + } else { + stream.write_all(b"what is the magic word?").await?; + debug!(pings, "> ({})\n\"{}\"", addr, "what is the magic word?"); + stream.flush().await?; + } + // we should wait, so that we don't spam the client + std::thread::sleep(self.cfg.delay); + } + debug!("disconnected peer: {:?}", addr); Ok(()) } - - #[inline] - fn decode(&self, buf: &Vec) -> Result { - Ok(String::from_utf8(buf.clone())?.replace('\n', "\\n")) - } - - #[inline] - async fn read(&self, reader: &mut BufReader, buf: &mut Vec) -> Result { - match timeout(self.cfg.timeout, reader.read_until(0x00, buf)).await? { - Ok(len) => Ok(len), - Err(err) => Err(err.into()), - } - } }