Remove demos/tunala
This has been unmaintained for a long time. If it's still of interest to anyone, it can be obtained easily enough by reverting this commit. (It could join other demo code in some other repository, perhaps.) In any case we don't want it taking up space in the baseline source package, so <snip>. Signed-off-by: Geoff Thorpe <geoff@openssl.org>
This commit is contained in:
parent
7a2b54509c
commit
ceea4bf047
19 changed files with 0 additions and 2818 deletions
|
@ -1,4 +0,0 @@
|
|||
tunala
|
||||
|
||||
*.flc
|
||||
semantic.cache
|
|
@ -1,84 +0,0 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 2 (0x2)
|
||||
Signature Algorithm: md5WithRSAEncryption
|
||||
Issuer: C=NZ, L=Wellington, O=Really Irresponsible Authorisation Authority (RIAA), OU=Cert-stamping, CN=Jackov al-Trades/Email=none@fake.domain
|
||||
Validity
|
||||
Not Before: Jan 16 05:19:30 2002 GMT
|
||||
Not After : Jan 14 05:19:30 2012 GMT
|
||||
Subject: C=NZ, L=Auckland, O=Mordor, OU=SSL grunt things, CN=tunala-client/Email=client@fake.domain
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public Key: (1024 bit)
|
||||
Modulus (1024 bit):
|
||||
00:b0:d3:56:5c:c8:7f:fb:f4:95:9d:04:84:4f:82:
|
||||
b7:a2:75:5c:81:48:8c:56:5d:52:ee:38:e1:5c:c8:
|
||||
9a:70:8e:72:f2:00:1c:17:ef:df:b7:06:59:82:04:
|
||||
f1:f6:49:11:12:a6:4d:cb:1e:ed:ac:59:1c:4a:d0:
|
||||
3d:de:e6:f2:8d:cd:39:c2:0f:e0:46:2f:db:cb:9f:
|
||||
47:f7:56:e7:f8:16:5f:68:71:fb:3a:e3:ab:d2:e5:
|
||||
05:b7:da:65:61:fe:6d:30:e4:12:a8:b5:c1:71:24:
|
||||
6b:aa:80:05:41:17:a0:8b:6e:8b:e6:04:cf:85:7b:
|
||||
2a:ac:a1:79:7d:f4:96:6e:77
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
Netscape Comment:
|
||||
OpenSSL Generated Certificate
|
||||
X509v3 Subject Key Identifier:
|
||||
F8:43:CB:4F:4D:4F:BC:6E:52:1A:FD:F9:7B:E1:12:3F:A7:A3:BA:93
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:49:FB:45:72:12:C4:CC:E1:45:A1:D3:08:9E:95:C4:2C:6D:55:3F:17
|
||||
DirName:/C=NZ/L=Wellington/O=Really Irresponsible Authorisation Authority (RIAA)/OU=Cert-stamping/CN=Jackov al-Trades/Email=none@fake.domain
|
||||
serial:00
|
||||
|
||||
Signature Algorithm: md5WithRSAEncryption
|
||||
8f:5f:0e:43:da:9d:61:43:7e:03:38:9a:e6:50:9d:42:e8:95:
|
||||
34:49:75:ec:04:8d:5c:85:99:94:70:a0:e7:1f:1e:a0:8b:0f:
|
||||
d6:e2:cb:f7:35:d9:96:72:bd:a6:e9:8d:4e:b1:e2:ac:97:7f:
|
||||
2f:70:01:9d:aa:04:bc:d4:01:2b:63:77:a5:de:63:3c:a8:f5:
|
||||
f2:72:af:ec:11:12:c0:d4:70:cf:71:a6:fb:e9:1d:b3:27:07:
|
||||
aa:f2:b1:f3:87:d6:ab:8b:ce:c2:08:1b:3c:f9:ba:ff:77:71:
|
||||
86:09:ef:9e:4e:04:06:63:44:e9:93:20:90:c7:2d:50:c6:50:
|
||||
f8:66
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID9TCCA16gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBtDELMAkGA1UEBhMCTlox
|
||||
EzARBgNVBAcTCldlbGxpbmd0b24xPDA6BgNVBAoTM1JlYWxseSBJcnJlc3BvbnNp
|
||||
YmxlIEF1dGhvcmlzYXRpb24gQXV0aG9yaXR5IChSSUFBKTEWMBQGA1UECxMNQ2Vy
|
||||
dC1zdGFtcGluZzEZMBcGA1UEAxMQSmFja292IGFsLVRyYWRlczEfMB0GCSqGSIb3
|
||||
DQEJARYQbm9uZUBmYWtlLmRvbWFpbjAeFw0wMjAxMTYwNTE5MzBaFw0xMjAxMTQw
|
||||
NTE5MzBaMIGHMQswCQYDVQQGEwJOWjERMA8GA1UEBxMIQXVja2xhbmQxDzANBgNV
|
||||
BAoTBk1vcmRvcjEZMBcGA1UECxMQU1NMIGdydW50IHRoaW5nczEWMBQGA1UEAxMN
|
||||
dHVuYWxhLWNsaWVudDEhMB8GCSqGSIb3DQEJARYSY2xpZW50QGZha2UuZG9tYWlu
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw01ZcyH/79JWdBIRPgreidVyB
|
||||
SIxWXVLuOOFcyJpwjnLyABwX79+3BlmCBPH2SRESpk3LHu2sWRxK0D3e5vKNzTnC
|
||||
D+BGL9vLn0f3Vuf4Fl9ocfs646vS5QW32mVh/m0w5BKotcFxJGuqgAVBF6CLbovm
|
||||
BM+FeyqsoXl99JZudwIDAQABo4IBQDCCATwwCQYDVR0TBAIwADAsBglghkgBhvhC
|
||||
AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFPhD
|
||||
y09NT7xuUhr9+XvhEj+no7qTMIHhBgNVHSMEgdkwgdaAFEn7RXISxMzhRaHTCJ6V
|
||||
xCxtVT8XoYG6pIG3MIG0MQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2VsbGluZ3Rv
|
||||
bjE8MDoGA1UEChMzUmVhbGx5IElycmVzcG9uc2libGUgQXV0aG9yaXNhdGlvbiBB
|
||||
dXRob3JpdHkgKFJJQUEpMRYwFAYDVQQLEw1DZXJ0LXN0YW1waW5nMRkwFwYDVQQD
|
||||
ExBKYWNrb3YgYWwtVHJhZGVzMR8wHQYJKoZIhvcNAQkBFhBub25lQGZha2UuZG9t
|
||||
YWluggEAMA0GCSqGSIb3DQEBBAUAA4GBAI9fDkPanWFDfgM4muZQnULolTRJdewE
|
||||
jVyFmZRwoOcfHqCLD9biy/c12ZZyvabpjU6x4qyXfy9wAZ2qBLzUAStjd6XeYzyo
|
||||
9fJyr+wREsDUcM9xpvvpHbMnB6rysfOH1quLzsIIGzz5uv93cYYJ755OBAZjROmT
|
||||
IJDHLVDGUPhm
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXgIBAAKBgQCw01ZcyH/79JWdBIRPgreidVyBSIxWXVLuOOFcyJpwjnLyABwX
|
||||
79+3BlmCBPH2SRESpk3LHu2sWRxK0D3e5vKNzTnCD+BGL9vLn0f3Vuf4Fl9ocfs6
|
||||
46vS5QW32mVh/m0w5BKotcFxJGuqgAVBF6CLbovmBM+FeyqsoXl99JZudwIDAQAB
|
||||
AoGAU4chbqbPvkclPYzaq2yGLlneHrwUft+KwzlfS6L/QVgo+CQRIUWQmjaHpaGM
|
||||
YtjVFcg1S1QK1bUqZjTEZT0XKhfbYmqW8yYTfbcDEbnY7esoYlvIlW8qRlPRlTBE
|
||||
utKrtZafmVhLgoNawYGD0aLZofPqpYjbGUlrC7nrem2vNJECQQDVLD3Qb+OlEMET
|
||||
73ApnJhYsK3e+G2LTrtjrS8y5zS4+Xv61XUqvdV7ogzRl0tpvSAmMOItVyoYadkB
|
||||
S3xSIWX9AkEA1Fm1FhkQSZwGG5rf4c6gMN71jJ6JE3/kocdVa0sUjRevIupo4XQ2
|
||||
Vkykxi84MRP8cfHqyjewq7Ozv3op2MGWgwJBAKemsb66IJjzAkaBav7u70nhOf0/
|
||||
+Dc1Zl7QF2y7NVW8sGrnccx5m+ot2lMD4AV6/kvK6jaqdKrapBZGnbGiHqkCQQDI
|
||||
T1r33mqz1R8Z2S2Jtzz6/McKf930a/dC+GLGVEutkILf39lRmytKmv/wB0jtWtoO
|
||||
rlJ5sLDSNzC+1cE1u997AkEAu3IrtGmLKiuS6kDj6W47m+iiTIsuSJtTJb1SbUaK
|
||||
fIoBNFxbvJYW6rUU9+PxpMRaEhzh5s24/jBOE+mlb17mRQ==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -1,84 +0,0 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 1 (0x1)
|
||||
Signature Algorithm: md5WithRSAEncryption
|
||||
Issuer: C=NZ, L=Wellington, O=Really Irresponsible Authorisation Authority (RIAA), OU=Cert-stamping, CN=Jackov al-Trades/Email=none@fake.domain
|
||||
Validity
|
||||
Not Before: Jan 16 05:14:06 2002 GMT
|
||||
Not After : Jan 14 05:14:06 2012 GMT
|
||||
Subject: C=NZ, L=Wellington, O=Middle Earth, OU=SSL dev things, CN=tunala-server/Email=server@fake.domain
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public Key: (1024 bit)
|
||||
Modulus (1024 bit):
|
||||
00:a9:3e:62:87:97:13:6b:de:8f:bc:1d:0a:3f:65:
|
||||
0c:f9:76:a3:53:ce:97:30:27:0d:c6:df:72:1f:8d:
|
||||
5a:ce:58:23:6a:65:e5:e3:72:1a:8d:7f:fe:90:01:
|
||||
ea:42:f1:9f:6e:7b:0a:bd:eb:52:15:7b:f4:3d:9c:
|
||||
4e:db:74:29:2b:d1:81:9d:b9:9e:18:2b:87:e1:da:
|
||||
50:20:3c:59:6c:c9:83:3e:2c:11:0b:78:1e:03:f4:
|
||||
56:3a:db:95:6a:75:33:85:a9:7b:cc:3c:4a:67:96:
|
||||
f2:24:b2:a0:cb:2e:cc:52:18:16:6f:44:d9:29:64:
|
||||
07:2e:fb:56:cc:7c:dc:a2:d7
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
Netscape Comment:
|
||||
OpenSSL Generated Certificate
|
||||
X509v3 Subject Key Identifier:
|
||||
70:AC:7A:B5:6E:97:C2:82:AF:11:9E:32:CB:8D:48:49:93:B7:DC:22
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:49:FB:45:72:12:C4:CC:E1:45:A1:D3:08:9E:95:C4:2C:6D:55:3F:17
|
||||
DirName:/C=NZ/L=Wellington/O=Really Irresponsible Authorisation Authority (RIAA)/OU=Cert-stamping/CN=Jackov al-Trades/Email=none@fake.domain
|
||||
serial:00
|
||||
|
||||
Signature Algorithm: md5WithRSAEncryption
|
||||
2e:cb:a3:cd:6d:a8:9d:d1:dc:e5:f0:e0:27:7e:4b:5a:90:a8:
|
||||
85:43:f0:05:f7:04:43:d7:5f:d1:a5:8f:5c:58:eb:fc:da:c6:
|
||||
7c:e0:0b:2b:98:72:95:f6:79:48:96:7a:fa:0c:6b:09:ec:c6:
|
||||
8c:91:74:45:9f:8f:0f:16:78:e3:66:14:fa:1e:f4:f0:23:ec:
|
||||
cd:a9:52:77:20:4d:c5:05:2c:52:b6:7b:f3:42:33:fd:90:1f:
|
||||
3e:88:6f:9b:23:61:c8:80:3b:e6:57:84:2e:f7:26:c7:35:ed:
|
||||
00:8b:08:30:9b:aa:21:83:b6:6d:b8:7c:8a:9b:2a:ef:79:3d:
|
||||
96:31
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID+zCCA2SgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBtDELMAkGA1UEBhMCTlox
|
||||
EzARBgNVBAcTCldlbGxpbmd0b24xPDA6BgNVBAoTM1JlYWxseSBJcnJlc3BvbnNp
|
||||
YmxlIEF1dGhvcmlzYXRpb24gQXV0aG9yaXR5IChSSUFBKTEWMBQGA1UECxMNQ2Vy
|
||||
dC1zdGFtcGluZzEZMBcGA1UEAxMQSmFja292IGFsLVRyYWRlczEfMB0GCSqGSIb3
|
||||
DQEJARYQbm9uZUBmYWtlLmRvbWFpbjAeFw0wMjAxMTYwNTE0MDZaFw0xMjAxMTQw
|
||||
NTE0MDZaMIGNMQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2VsbGluZ3RvbjEVMBMG
|
||||
A1UEChMMTWlkZGxlIEVhcnRoMRcwFQYDVQQLEw5TU0wgZGV2IHRoaW5nczEWMBQG
|
||||
A1UEAxMNdHVuYWxhLXNlcnZlcjEhMB8GCSqGSIb3DQEJARYSc2VydmVyQGZha2Uu
|
||||
ZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpPmKHlxNr3o+8HQo/
|
||||
ZQz5dqNTzpcwJw3G33IfjVrOWCNqZeXjchqNf/6QAepC8Z9uewq961IVe/Q9nE7b
|
||||
dCkr0YGduZ4YK4fh2lAgPFlsyYM+LBELeB4D9FY625VqdTOFqXvMPEpnlvIksqDL
|
||||
LsxSGBZvRNkpZAcu+1bMfNyi1wIDAQABo4IBQDCCATwwCQYDVR0TBAIwADAsBglg
|
||||
hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
|
||||
BBYEFHCserVul8KCrxGeMsuNSEmTt9wiMIHhBgNVHSMEgdkwgdaAFEn7RXISxMzh
|
||||
RaHTCJ6VxCxtVT8XoYG6pIG3MIG0MQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2Vs
|
||||
bGluZ3RvbjE8MDoGA1UEChMzUmVhbGx5IElycmVzcG9uc2libGUgQXV0aG9yaXNh
|
||||
dGlvbiBBdXRob3JpdHkgKFJJQUEpMRYwFAYDVQQLEw1DZXJ0LXN0YW1waW5nMRkw
|
||||
FwYDVQQDExBKYWNrb3YgYWwtVHJhZGVzMR8wHQYJKoZIhvcNAQkBFhBub25lQGZh
|
||||
a2UuZG9tYWluggEAMA0GCSqGSIb3DQEBBAUAA4GBAC7Lo81tqJ3R3OXw4Cd+S1qQ
|
||||
qIVD8AX3BEPXX9Glj1xY6/zaxnzgCyuYcpX2eUiWevoMawnsxoyRdEWfjw8WeONm
|
||||
FPoe9PAj7M2pUncgTcUFLFK2e/NCM/2QHz6Ib5sjYciAO+ZXhC73Jsc17QCLCDCb
|
||||
qiGDtm24fIqbKu95PZYx
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQCpPmKHlxNr3o+8HQo/ZQz5dqNTzpcwJw3G33IfjVrOWCNqZeXj
|
||||
chqNf/6QAepC8Z9uewq961IVe/Q9nE7bdCkr0YGduZ4YK4fh2lAgPFlsyYM+LBEL
|
||||
eB4D9FY625VqdTOFqXvMPEpnlvIksqDLLsxSGBZvRNkpZAcu+1bMfNyi1wIDAQAB
|
||||
AoGANCwqHZhiAU/TyW6+WPqivEhpYw19p/dyFMuPF9DwnEmpaUROUQY8z0AUznn4
|
||||
qHhp6Jn/nrprTHowucl0ucweYIYVxZoUiUDFpxdFUbzMdFvo6HcyV1Pe4Rt81HaY
|
||||
KYWrTZ6PaPtN65hLms8NhPEdGcGAFlY1owYv4QNGq2bU1JECQQDd32LM0NSfyGmK
|
||||
4ziajqGcvzK9NO2XyV/nJsGlJZNgMh2zm1t7yR28l/6Q2uyU49cCN+2aYULZCAfs
|
||||
taNvxBspAkEAw0alNub+xj2AVQvaxOB1sGfKzsJjHCzKIxUXn/tJi3j0+2asmkBZ
|
||||
Umx1MWr9jKQBnCMciCRUbnMEZiElOxCN/wJAfAeQl6Z19gx206lJzzzEo3dOye54
|
||||
k02DSxijT8q9pBzf9bN3ZK987BybtiZr8p+bZiYVsSOF1wViSLURdD1QYQJAIaMU
|
||||
qH1n24wShBPTrmAfxbBLTgxL+Dl65Eoo1KT7iSvfv0JzbuqwuDL4iPeuD0DdCiE+
|
||||
M/FWHeRwGIuTFzaFzwJBANKwx0jZS/h093w9g0Clw6UzeA1P5VcAt9y+qMC9hO3c
|
||||
4KXwIxQAt9yRaFLpiIR9do5bjjKNnMguf3aO/XRSDQM=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -1,24 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIID9zCCA2CgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtDELMAkGA1UEBhMCTlox
|
||||
EzARBgNVBAcTCldlbGxpbmd0b24xPDA6BgNVBAoTM1JlYWxseSBJcnJlc3BvbnNp
|
||||
YmxlIEF1dGhvcmlzYXRpb24gQXV0aG9yaXR5IChSSUFBKTEWMBQGA1UECxMNQ2Vy
|
||||
dC1zdGFtcGluZzEZMBcGA1UEAxMQSmFja292IGFsLVRyYWRlczEfMB0GCSqGSIb3
|
||||
DQEJARYQbm9uZUBmYWtlLmRvbWFpbjAeFw0wMjAxMTYwNTA5NTlaFw0xMjAxMTQw
|
||||
NTA5NTlaMIG0MQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2VsbGluZ3RvbjE8MDoG
|
||||
A1UEChMzUmVhbGx5IElycmVzcG9uc2libGUgQXV0aG9yaXNhdGlvbiBBdXRob3Jp
|
||||
dHkgKFJJQUEpMRYwFAYDVQQLEw1DZXJ0LXN0YW1waW5nMRkwFwYDVQQDExBKYWNr
|
||||
b3YgYWwtVHJhZGVzMR8wHQYJKoZIhvcNAQkBFhBub25lQGZha2UuZG9tYWluMIGf
|
||||
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7QdDfFIrJn3X24hKmpkyk3TG0Ivxd
|
||||
K2wWmDPXq1wjr8lUTwrA6hM5Ba9N36jLieWpXhviLOWu9DBza5GmtgCuXloATKTC
|
||||
94xOdKHlciTVujG3wDlLDB5e710Kar84nnj6VueL1RyZ0bmP5PANa4mbGW9Tqc7J
|
||||
CkBTTW2y9d0SgQIDAQABo4IBFTCCAREwHQYDVR0OBBYEFEn7RXISxMzhRaHTCJ6V
|
||||
xCxtVT8XMIHhBgNVHSMEgdkwgdaAFEn7RXISxMzhRaHTCJ6VxCxtVT8XoYG6pIG3
|
||||
MIG0MQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2VsbGluZ3RvbjE8MDoGA1UEChMz
|
||||
UmVhbGx5IElycmVzcG9uc2libGUgQXV0aG9yaXNhdGlvbiBBdXRob3JpdHkgKFJJ
|
||||
QUEpMRYwFAYDVQQLEw1DZXJ0LXN0YW1waW5nMRkwFwYDVQQDExBKYWNrb3YgYWwt
|
||||
VHJhZGVzMR8wHQYJKoZIhvcNAQkBFhBub25lQGZha2UuZG9tYWluggEAMAwGA1Ud
|
||||
EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAYQo95V/NY+eKxYxkhibZiUQygph+
|
||||
gTfgbDG20MsnH6+8//w5ArHauFCgDrf0P2VyACgq+N4pBTWFGaAaLwbjKy9HCe2E
|
||||
j9C91tO1CqDS4MJkDB5AP13FTkK6fP1ZCiTQranOAp3DlGWTTWsFVyW5kVfQ9diS
|
||||
ZOyJZ9Fit5XM2X0=
|
||||
-----END CERTIFICATE-----
|
|
@ -1,107 +0,0 @@
|
|||
There are two ways to build this code;
|
||||
|
||||
(1) Manually
|
||||
|
||||
(2) Using all-singing all-dancing (all-confusing) autotools, ie. autoconf,
|
||||
automake, and their little friends (autoheader, etc).
|
||||
|
||||
=================
|
||||
Building Manually
|
||||
=================
|
||||
|
||||
There is a basic "Makefile" in this directory that gets moved out of the way and
|
||||
ignored when building with autoconf et al. This Makefile is suitable for
|
||||
building tunala on Linux using gcc. Any other platform probably requires some
|
||||
tweaking. Here are the various bits you might need to do if you want to build
|
||||
this way and the default Makefile isn't sufficient;
|
||||
|
||||
* Compiler: Edit the "CC" definition in Makefile
|
||||
|
||||
* Headers, features: tunala.h controls what happens in the non-autoconf world.
|
||||
It, by default, assumes the system has *everything* (except autoconf's
|
||||
"config.h") so if a target system is missing something it must define the
|
||||
appropriate "NO_***" symbols in CFLAGS. These include;
|
||||
|
||||
- NO_HAVE_UNISTD_H, NO_HAVE_FCNTL_H, NO_HAVE_LIMITS_H
|
||||
Indicates the compiling system doesn't have (or need) these header files.
|
||||
- NO_HAVE_STRSTR, NO_HAVE_STRTOUL
|
||||
Indicates the compiling system doesn't have these functions. Replacements
|
||||
are compiled and used in breakage.c
|
||||
- NO_HAVE_SELECT, NO_HAVE_SOCKET
|
||||
Pointless symbols - these indicate select() and/or socket() are missing in
|
||||
which case the program won't compile anyway.
|
||||
|
||||
If you want to specify any of these, add them with "-D" prefixed to each in
|
||||
the CFLAGS definition in Makefile.
|
||||
|
||||
* Compilation flags: edit DEBUG_FLAGS and/or CFLAGS directly to control the
|
||||
flags passed to the compiler. This can also be used to change the degree of
|
||||
optimisation.
|
||||
|
||||
* Linker flags: some systems (eg. Solaris) require extra linker flags such as;
|
||||
-ldl, -lsocket, -lnsl, etc. If unsure, bring up the man page for whichever
|
||||
function is "undefined" when the linker fails - that usually indicates what
|
||||
you need to add. Make changes to the LINK_FLAGS symbol.
|
||||
|
||||
* Linker command: if a different linker syntax or even a different program is
|
||||
required to link, edit the linker line directly in the "tunala:" target
|
||||
definition - it currently assumes the "CC" (compiler) program is used to link.
|
||||
|
||||
======================
|
||||
Building Automagically
|
||||
======================
|
||||
|
||||
Automagic building is handled courtesy of autoconf, automake, etc. There are in
|
||||
fact two steps required to build, and only the first has to be done on a system
|
||||
with these tools installed (and if I was prepared to bloat out the CVS
|
||||
repository, I could store these extra files, but I'm not).
|
||||
|
||||
First step: "autogunk.sh"
|
||||
-------------------------
|
||||
|
||||
The "./autogunk.sh" script will call all the necessary autotool commands to
|
||||
create missing files and run automake and autoconf. The result is that a
|
||||
"./configure" script should be generated and a "Makefile.in" generated from the
|
||||
supplied "Makefile.am". NB: This script also moves the "manual" Makefile (see
|
||||
above) out of the way and calls it "Makefile.plain" - the "ungunk" script
|
||||
reverses this to leave the directory it was previously.
|
||||
|
||||
Once "ungunk" has been run, the resulting directory should be able to build on
|
||||
other systems without autoconf, automake, or libtool. Which is what the second
|
||||
step describes;
|
||||
|
||||
Second step: "./configure"
|
||||
--------------------------
|
||||
|
||||
The second step is to run the generated "./configure" script to create a
|
||||
config.h header for your system and to generate a "Makefile" (generated from
|
||||
"Makefile.in") tweaked to compile on your system. This is the standard sort of
|
||||
thing you see in GNU packages, for example, and the standard tricks also work.
|
||||
Eg. to override "configure"'s choice of compiler, set the CC environment
|
||||
variable prior to running configure, eg.
|
||||
|
||||
CC=gcc ./configure
|
||||
|
||||
would cause "gcc" to be used even if there is an otherwise preferable (to
|
||||
autoconf) native compiler on your system.
|
||||
|
||||
After this run "make" and it should build the "tunala" executable.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
- Some versions of autoconf (or automake?) generate a Makefile syntax that gives
|
||||
trouble to some "make" programs on some systems (eg. OpenBSD). If this
|
||||
happens, either build 'Manually' (see above) or use "gmake" instead of "make".
|
||||
I don't like this either but like even less the idea of sifting into all the
|
||||
script magic crud that's involved.
|
||||
|
||||
- On a solaris system I tried, the "configure" script specified some broken
|
||||
compiler flags in the resulting Makefile that don't even get echoed to
|
||||
stdout/err when the error happens (evil!). If this happens, go into the
|
||||
generated Makefile, find the two affected targets ("%.o:" and "%.lo"), and
|
||||
remove the offending hidden option in the $(COMPILE) line all the sludge after
|
||||
the two first lines of script (ie. after the "echo" and the "COMPILE" lines).
|
||||
NB: This will probably only function if "--disable-shared" was used, otherwise
|
||||
who knows what would result ...
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
# Edit these to suit
|
||||
#
|
||||
# Oh yeah, and please read the README too.
|
||||
|
||||
|
||||
SSL_HOMEDIR=../..
|
||||
SSL_INCLUDEDIR=$(SSL_HOMEDIR)/include
|
||||
SSL_LIBDIR=$(SSL_HOMEDIR)
|
||||
|
||||
RM=rm -f
|
||||
CC=gcc
|
||||
DEBUG_FLAGS=-g -ggdb3 -Wall -Wshadow
|
||||
INCLUDE_FLAGS=-I$(SSL_INCLUDEDIR)
|
||||
CFLAGS=$(DEBUG_FLAGS) $(INCLUDE_FLAGS) -DNO_CONFIG_H
|
||||
COMPILE=$(CC) $(CFLAGS) -c
|
||||
|
||||
# Edit, particularly the "-ldl" if not building with "dlfcn" support
|
||||
LINK_FLAGS=-L$(SSL_LIBDIR) -lssl -lcrypto -ldl
|
||||
|
||||
SRCS=buffer.c cb.c ip.c sm.c tunala.c breakage.c
|
||||
OBJS=buffer.o cb.o ip.o sm.o tunala.o breakage.o
|
||||
|
||||
TARGETS=tunala
|
||||
|
||||
default: $(TARGETS)
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS) $(TARGETS) *.bak core
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) $<
|
||||
|
||||
tunala: $(OBJS)
|
||||
$(CC) -o tunala $(OBJS) $(LINK_FLAGS)
|
||||
|
||||
# Extra dependencies, should really use makedepend
|
||||
buffer.o: buffer.c tunala.h
|
||||
cb.o: cb.c tunala.h
|
||||
ip.o: ip.c tunala.h
|
||||
sm.o: sm.c tunala.h
|
||||
tunala.o: tunala.c tunala.h
|
|
@ -1,7 +0,0 @@
|
|||
# Our includes come from the OpenSSL build-tree we're in
|
||||
INCLUDES = -I$(top_builddir)/../../include
|
||||
|
||||
bin_PROGRAMS = tunala
|
||||
|
||||
tunala_SOURCES = tunala.c buffer.c cb.c ip.c sm.c breakage.c
|
||||
tunala_LDADD = -L$(top_builddir)/../.. -lssl -lcrypto
|
|
@ -1,233 +0,0 @@
|
|||
This is intended to be an example of a state-machine driven SSL application. It
|
||||
acts as an SSL tunneler (functioning as either the server or client half,
|
||||
depending on command-line arguments). *PLEASE* read the comments in tunala.h
|
||||
before you treat this stuff as anything more than a curiosity - YOU HAVE BEEN
|
||||
WARNED!! There, that's the draconian bit out of the way ...
|
||||
|
||||
|
||||
Why "tunala"??
|
||||
--------------
|
||||
|
||||
I thought I asked you to read tunala.h?? :-)
|
||||
|
||||
|
||||
Show me
|
||||
-------
|
||||
|
||||
If you want to simply see it running, skip to the end and see some example
|
||||
command-line arguments to demonstrate with.
|
||||
|
||||
|
||||
Where to look and what to do?
|
||||
-----------------------------
|
||||
|
||||
The code is split up roughly coinciding with the detaching of an "abstract" SSL
|
||||
state machine (which is the purpose of all this) and its surrounding application
|
||||
specifics. This is primarily to make it possible for me to know when I could cut
|
||||
corners and when I needed to be rigorous (or at least maintain the pretense as
|
||||
such :-).
|
||||
|
||||
Network stuff:
|
||||
|
||||
Basically, the network part of all this is what is supposed to be abstracted out
|
||||
of the way. The intention is to illustrate one way to stick OpenSSL's mechanisms
|
||||
inside a little memory-driven sandbox and operate it like a pure state-machine.
|
||||
So, the network code is inside both ip.c (general utility functions and gory
|
||||
IPv4 details) and tunala.c itself, which takes care of application specifics
|
||||
like the main select() loop. The connectivity between the specifics of this
|
||||
application (TCP/IP tunneling and the associated network code) and the
|
||||
underlying abstract SSL state machine stuff is through the use of the "buffer_t"
|
||||
type, declared in tunala.h and implemented in buffer.c.
|
||||
|
||||
State machine:
|
||||
|
||||
Which leaves us, generally speaking, with the abstract "state machine" code left
|
||||
over and this is sitting inside sm.c, with declarations inside tunala.h. As can
|
||||
be seen by the definition of the state_machine_t structure and the associated
|
||||
functions to manipulate it, there are the 3 OpenSSL "handles" plus 4 buffer_t
|
||||
structures dealing with IO on both the encrypted and unencrypted sides ("dirty"
|
||||
and "clean" respectively). The "SSL" handle is what facilitates the reading and
|
||||
writing of the unencrypted (tunneled) data. The two "BIO" handles act as the
|
||||
read and write channels for encrypted tunnel traffic - in other applications
|
||||
these are often socket BIOs so that the OpenSSL framework operates with the
|
||||
network layer directly. In this example, those two BIOs are memory BIOs
|
||||
(BIO_s_mem()) so that the sending and receiving of the tunnel traffic stays
|
||||
within the state-machine, and we can handle where this gets send to (or read
|
||||
from) ourselves.
|
||||
|
||||
|
||||
Why?
|
||||
----
|
||||
|
||||
If you take a look at the "state_machine_t" section of tunala.h and the code in
|
||||
sm.c, you will notice that nothing related to the concept of 'transport' is
|
||||
involved. The binding to TCP/IP networking occurs in tunala.c, specifically
|
||||
within the "tunala_item_t" structure that associates a state_machine_t object
|
||||
with 4 file-descriptors. The way to best see where the bridge between the
|
||||
outside world (TCP/IP reads, writes, select()s, file-descriptors, etc) and the
|
||||
state machine is, is to examine the "tunala_item_io()" function in tunala.c.
|
||||
This is currently around lines 641-732 but of course could be subject to change.
|
||||
|
||||
|
||||
And...?
|
||||
-------
|
||||
|
||||
Well, although that function is around 90 lines of code, it could easily have
|
||||
been a lot less only I was trying to address an easily missed "gotcha" (item (2)
|
||||
below). The main() code that drives the select/accept/IO loop initialises new
|
||||
tunala_item_t structures when connections arrive, and works out which
|
||||
file-descriptors go where depending on whether we're an SSL client or server
|
||||
(client --> accepted connection is clean and proxied is dirty, server -->
|
||||
accepted connection is dirty and proxied is clean). What that tunala_item_io()
|
||||
function is attempting to do is 2 things;
|
||||
|
||||
(1) Perform all reads and writes on the network directly into the
|
||||
state_machine_t's buffers (based on a previous select() result), and only
|
||||
then allow the abstact state_machine_t to "churn()" using those buffers.
|
||||
This will cause the SSL machine to consume as much input data from the two
|
||||
"IN" buffers as possible, and generate as much output data into the two
|
||||
"OUT" buffers as possible. Back up in the main() function, the next main
|
||||
loop loop will examine these output buffers and select() for writability
|
||||
on the corresponding sockets if the buffers are non-empty.
|
||||
|
||||
(2) Handle the complicated tunneling-specific issue of cascading "close"s.
|
||||
This is the reason for most of the complexity in the logic - if one side
|
||||
of the tunnel is closed, you can't simply close the other side and throw
|
||||
away the whole thing - (a) there may still be outgoing data on the other
|
||||
side of the tunnel that hasn't been sent yet, (b) the close (or things
|
||||
happening during the close) may cause more data to be generated that needs
|
||||
sending on the other side. Of course, this logic is complicated yet futher
|
||||
by the fact that it's different depending on which side closes first :-)
|
||||
state_machine_close_clean() will indicate to the state machine that the
|
||||
unencrypted side of the tunnel has closed, so any existing outgoing data
|
||||
needs to be flushed, and the SSL stream needs to be closed down using the
|
||||
appropriate shutdown sequence. state_machine_close_dirty() is simpler
|
||||
because it indicates that the SSL stream has been disconnected, so all
|
||||
that remains before closing the other side is to flush out anything that
|
||||
remains and wait for it to all be sent.
|
||||
|
||||
Anyway, with those things in mind, the code should be a little easier to follow
|
||||
in terms of "what is *this* bit supposed to achieve??!!".
|
||||
|
||||
|
||||
How might this help?
|
||||
--------------------
|
||||
|
||||
Well, the reason I wrote this is that there seemed to be rather a flood of
|
||||
questions of late on the openssl-dev and openssl-users lists about getting this
|
||||
whole IO logic thing sorted out, particularly by those who were trying to either
|
||||
use non-blocking IO, or wanted SSL in an environment where "something else" was
|
||||
handling the network already and they needed to operate in memory only. This
|
||||
code is loosely based on some other stuff I've been working on, although that
|
||||
stuff is far more complete, far more dependant on a whole slew of other
|
||||
network/framework code I don't want to incorporate here, and far harder to look
|
||||
at for 5 minutes and follow where everything is going. I will be trying over
|
||||
time to suck in a few things from that into this demo in the hopes it might be
|
||||
more useful, and maybe to even make this demo usable as a utility of its own.
|
||||
Possible things include:
|
||||
|
||||
* controlling multiple processes/threads - this can be used to combat
|
||||
latencies and get passed file-descriptor limits on some systems, and it uses
|
||||
a "controller" process/thread that maintains IPC links with the
|
||||
processes/threads doing the real work.
|
||||
|
||||
* cert verification rules - having some say over which certs get in or out :-)
|
||||
|
||||
* control over SSL protocols and cipher suites
|
||||
|
||||
* A few other things you can already do in s_client and s_server :-)
|
||||
|
||||
* Support (and control over) session resuming, particularly when functioning
|
||||
as an SSL client.
|
||||
|
||||
If you have a particular environment where this model might work to let you "do
|
||||
SSL" without having OpenSSL be aware of the transport, then you should find you
|
||||
could use the state_machine_t structure (or your own variant thereof) and hook
|
||||
it up to your transport stuff in much the way tunala.c matches it up with those
|
||||
4 file-descriptors. The state_machine_churn(), state_machine_close_clean(), and
|
||||
state_machine_close_dirty() functions are the main things to understand - after
|
||||
that's done, you just have to ensure you're feeding and bleeding the 4
|
||||
state_machine buffers in a logical fashion. This state_machine loop handles not
|
||||
only handshakes and normal streaming, but also renegotiates - there's no special
|
||||
handling required beyond keeping an eye on those 4 buffers and keeping them in
|
||||
sync with your outer "loop" logic. Ie. if one of the OUT buffers is not empty,
|
||||
you need to find an opportunity to try and forward its data on. If one of the IN
|
||||
buffers is not full, you should keep an eye out for data arriving that should be
|
||||
placed there.
|
||||
|
||||
This approach could hopefully also allow you to run the SSL protocol in very
|
||||
different environments. As an example, you could support encrypted event-driven
|
||||
IPC where threads/processes pass messages to each other inside an SSL layer;
|
||||
each IPC-message's payload would be in fact the "dirty" content, and the "clean"
|
||||
payload coming out of the tunnel at each end would be the real intended message.
|
||||
Likewise, this could *easily* be made to work across unix domain sockets, or
|
||||
even entirely different network/comms protocols.
|
||||
|
||||
This is also a quick and easy way to do VPN if you (and the remote network's
|
||||
gateway) support virtual network devices that are encapsulted in a single
|
||||
network connection, perhaps PPP going through an SSL tunnel?
|
||||
|
||||
|
||||
Suggestions
|
||||
-----------
|
||||
|
||||
Please let me know if you find this useful, or if there's anything wrong or
|
||||
simply too confusing about it. Patches are also welcome, but please attach a
|
||||
description of what it changes and why, and "diff -urN" format is preferred.
|
||||
Mail to geoff@openssl.org should do the trick.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
Here is an example of how to use "tunala" ...
|
||||
|
||||
First, it's assumed that OpenSSL has already built, and that you are building
|
||||
inside the ./demos/tunala/ directory. If not - please correct the paths and
|
||||
flags inside the Makefile. Likewise, if you want to tweak the building, it's
|
||||
best to try and do so in the makefile (eg. removing the debug flags and adding
|
||||
optimisation flags).
|
||||
|
||||
Secondly, this code has mostly only been tested on Linux. However, some
|
||||
autoconf/etc support has been added and the code has been compiled on openbsd
|
||||
and solaris using that.
|
||||
|
||||
Thirdly, if you are Win32, you probably need to do some *major* rewriting of
|
||||
ip.c to stand a hope in hell. Good luck, and please mail me the diff if you do
|
||||
this, otherwise I will take a look at another time. It can certainly be done,
|
||||
but it's very non-POSIXy.
|
||||
|
||||
See the INSTALL document for details on building.
|
||||
|
||||
Now, if you don't have an executable "tunala" compiled, go back to "First,...".
|
||||
Rinse and repeat.
|
||||
|
||||
Inside one console, try typing;
|
||||
|
||||
(i) ./tunala -listen localhost:8080 -proxy localhost:8081 -cacert CA.pem \
|
||||
-cert A-client.pem -out_totals -v_peer -v_strict
|
||||
|
||||
In another console, type;
|
||||
|
||||
(ii) ./tunala -listen localhost:8081 -proxy localhost:23 -cacert CA.pem \
|
||||
-cert A-server.pem -server 1 -out_totals -v_peer -v_strict
|
||||
|
||||
Now if you open another console and "telnet localhost 8080", you should be
|
||||
tunneled through to the telnet service on your local machine (if it's running -
|
||||
you could change it to port "22" and tunnel ssh instead if you so desired). When
|
||||
you logout of the telnet session, the tunnel should cleanly shutdown and show
|
||||
you some traffic stats in both consoles. Feel free to experiment. :-)
|
||||
|
||||
Notes:
|
||||
|
||||
- the format for the "-listen" argument can skip the host part (eg. "-listen
|
||||
8080" is fine). If you do, the listening socket will listen on all interfaces
|
||||
so you can connect from other machines for example. Using the "localhost"
|
||||
form listens only on 127.0.0.1 so you can only connect locally (unless, of
|
||||
course, you've set up weird stuff with your networking in which case probably
|
||||
none of the above applies).
|
||||
|
||||
- ./tunala -? gives you a list of other command-line options, but tunala.c is
|
||||
also a good place to look :-)
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This script tries to follow the "GNU way" w.r.t. the autobits.
|
||||
# This does of course generate a number of irritating files.
|
||||
# Try to get over it (I am getting there myself).
|
||||
|
||||
# This should generate any missing crud, and then run autoconf which should turn
|
||||
# configure.in into a "./configure" script and "Makefile.am" into a
|
||||
# "Makefile.in". Then running "./configure" should turn "Makefile.in" into
|
||||
# "Makefile" and should generate the config.h containing your systems various
|
||||
# settings. I know ... what a hassle ...
|
||||
|
||||
# Also, sometimes these autobits things generate bizarre output (looking like
|
||||
# errors). So I direct everything "elsewhere" ...
|
||||
|
||||
(aclocal
|
||||
autoheader
|
||||
libtoolize --copy --force
|
||||
automake --foreign --add-missing --copy
|
||||
autoconf) 1> /dev/null 2>&1
|
||||
|
||||
# Move the "no-autotools" Makefile out of the way
|
||||
if test ! -f Makefile.plain; then
|
||||
mv Makefile Makefile.plain
|
||||
fi
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This script tries to clean up as much as is possible from whatever diabolical
|
||||
# mess has been left in the directory thanks to autoconf, automake, and their
|
||||
# friends.
|
||||
|
||||
if test -f Makefile.plain; then
|
||||
if test -f Makefile; then
|
||||
make distclean
|
||||
fi
|
||||
mv Makefile.plain Makefile
|
||||
else
|
||||
make clean
|
||||
fi
|
||||
|
||||
rm -f aclocal.m4 config.* configure install-sh \
|
||||
missing mkinstalldirs stamp-h.* Makefile.in \
|
||||
ltconfig ltmain.sh depcomp
|
||||
rm -rf autom4te.cache
|
|
@ -1,66 +0,0 @@
|
|||
#include "tunala.h"
|
||||
|
||||
int int_strtoul(const char *str, unsigned long *val)
|
||||
{
|
||||
#ifdef HAVE_STRTOUL
|
||||
char *tmp;
|
||||
unsigned long ret = strtoul(str, &tmp, 10);
|
||||
if((str == tmp) || (*tmp != '\0'))
|
||||
/* The value didn't parse cleanly */
|
||||
return 0;
|
||||
if(ret == ULONG_MAX)
|
||||
/* We hit a limit */
|
||||
return 0;
|
||||
*val = ret;
|
||||
return 1;
|
||||
#else
|
||||
char buf[2];
|
||||
unsigned long ret = 0;
|
||||
buf[1] = '\0';
|
||||
if(str == '\0')
|
||||
/* An empty string ... */
|
||||
return 0;
|
||||
while(*str != '\0') {
|
||||
/* We have to multiply 'ret' by 10 before absorbing the next
|
||||
* digit. If this will overflow, catch it now. */
|
||||
if(ret && (((ULONG_MAX + 10) / ret) < 10))
|
||||
return 0;
|
||||
ret *= 10;
|
||||
if(!isdigit(*str))
|
||||
return 0;
|
||||
buf[0] = *str;
|
||||
ret += atoi(buf);
|
||||
str++;
|
||||
}
|
||||
*val = ret;
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRSTR
|
||||
char *int_strstr(const char *haystack, const char *needle)
|
||||
{
|
||||
const char *sub_haystack = haystack, *sub_needle = needle;
|
||||
unsigned int offset = 0;
|
||||
if(!needle)
|
||||
return haystack;
|
||||
if(!haystack)
|
||||
return NULL;
|
||||
while((*sub_haystack != '\0') && (*sub_needle != '\0')) {
|
||||
if(sub_haystack[offset] == sub_needle) {
|
||||
/* sub_haystack is still a candidate */
|
||||
offset++;
|
||||
sub_needle++;
|
||||
} else {
|
||||
/* sub_haystack is no longer a possibility */
|
||||
sub_haystack++;
|
||||
offset = 0;
|
||||
sub_needle = needle;
|
||||
}
|
||||
}
|
||||
if(*sub_haystack == '\0')
|
||||
/* Found nothing */
|
||||
return NULL;
|
||||
return sub_haystack;
|
||||
}
|
||||
#endif
|
|
@ -1,205 +0,0 @@
|
|||
#include "tunala.h"
|
||||
|
||||
#ifndef NO_BUFFER
|
||||
|
||||
void buffer_init(buffer_t *buf)
|
||||
{
|
||||
buf->used = 0;
|
||||
buf->total_in = buf->total_out = 0;
|
||||
}
|
||||
|
||||
void buffer_close(buffer_t *buf)
|
||||
{
|
||||
/* Our data is static - nothing needs "release", just reset it */
|
||||
buf->used = 0;
|
||||
}
|
||||
|
||||
/* Code these simple ones in compact form */
|
||||
unsigned int buffer_used(buffer_t *buf) {
|
||||
return buf->used; }
|
||||
unsigned int buffer_unused(buffer_t *buf) {
|
||||
return (MAX_DATA_SIZE - buf->used); }
|
||||
int buffer_full(buffer_t *buf) {
|
||||
return (buf->used == MAX_DATA_SIZE ? 1 : 0); }
|
||||
int buffer_notfull(buffer_t *buf) {
|
||||
return (buf->used < MAX_DATA_SIZE ? 1 : 0); }
|
||||
int buffer_empty(buffer_t *buf) {
|
||||
return (buf->used == 0 ? 1 : 0); }
|
||||
int buffer_notempty(buffer_t *buf) {
|
||||
return (buf->used > 0 ? 1 : 0); }
|
||||
unsigned long buffer_total_in(buffer_t *buf) {
|
||||
return buf->total_in; }
|
||||
unsigned long buffer_total_out(buffer_t *buf) {
|
||||
return buf->total_out; }
|
||||
|
||||
/* These 3 static (internal) functions don't adjust the "total" variables as
|
||||
* it's not sure when they're called how it should be interpreted. Only the
|
||||
* higher-level "buffer_[to|from]_[fd|SSL|BIO]" functions should alter these
|
||||
* values. */
|
||||
#if 0 /* To avoid "unused" warnings */
|
||||
static unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned int added = MAX_DATA_SIZE - buf->used;
|
||||
if(added > size)
|
||||
added = size;
|
||||
if(added == 0)
|
||||
return 0;
|
||||
memcpy(buf->data + buf->used, ptr, added);
|
||||
buf->used += added;
|
||||
buf->total_in += added;
|
||||
return added;
|
||||
}
|
||||
|
||||
static unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap)
|
||||
{
|
||||
unsigned int moved, tomove = from->used;
|
||||
if((int)tomove > cap)
|
||||
tomove = cap;
|
||||
if(tomove == 0)
|
||||
return 0;
|
||||
moved = buffer_adddata(to, from->data, tomove);
|
||||
if(moved == 0)
|
||||
return 0;
|
||||
buffer_takedata(from, NULL, moved);
|
||||
return moved;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned int taken = buf->used;
|
||||
if(taken > size)
|
||||
taken = size;
|
||||
if(taken == 0)
|
||||
return 0;
|
||||
if(ptr)
|
||||
memcpy(ptr, buf->data, taken);
|
||||
buf->used -= taken;
|
||||
/* Do we have to scroll? */
|
||||
if(buf->used > 0)
|
||||
memmove(buf->data, buf->data + taken, buf->used);
|
||||
return taken;
|
||||
}
|
||||
|
||||
#ifndef NO_IP
|
||||
|
||||
int buffer_from_fd(buffer_t *buf, int fd)
|
||||
{
|
||||
int toread = buffer_unused(buf);
|
||||
if(toread == 0)
|
||||
/* Shouldn't be called in this case! */
|
||||
abort();
|
||||
toread = read(fd, buf->data + buf->used, toread);
|
||||
if(toread > 0) {
|
||||
buf->used += toread;
|
||||
buf->total_in += toread;
|
||||
}
|
||||
return toread;
|
||||
}
|
||||
|
||||
int buffer_to_fd(buffer_t *buf, int fd)
|
||||
{
|
||||
int towrite = buffer_used(buf);
|
||||
if(towrite == 0)
|
||||
/* Shouldn't be called in this case! */
|
||||
abort();
|
||||
towrite = write(fd, buf->data, towrite);
|
||||
if(towrite > 0) {
|
||||
buffer_takedata(buf, NULL, towrite);
|
||||
buf->total_out += towrite;
|
||||
}
|
||||
return towrite;
|
||||
}
|
||||
|
||||
#endif /* !defined(NO_IP) */
|
||||
|
||||
#ifndef NO_OPENSSL
|
||||
|
||||
static void int_ssl_check(SSL *s, int ret)
|
||||
{
|
||||
int e = SSL_get_error(s, ret);
|
||||
switch(e) {
|
||||
/* These seem to be harmless and already "dealt with" by our
|
||||
* non-blocking environment. NB: "ZERO_RETURN" is the clean
|
||||
* "error" indicating a successfully closed SSL tunnel. We let
|
||||
* this happen because our IO loop should not appear to have
|
||||
* broken on this condition - and outside the IO loop, the
|
||||
* "shutdown" state is checked. */
|
||||
case SSL_ERROR_NONE:
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
return;
|
||||
/* These seem to be indications of a genuine error that should
|
||||
* result in the SSL tunnel being regarded as "dead". */
|
||||
case SSL_ERROR_SYSCALL:
|
||||
case SSL_ERROR_SSL:
|
||||
SSL_set_app_data(s, (char *)1);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* For any other errors that (a) exist, and (b) crop up - we need to
|
||||
* interpret what to do with them - so "politely inform" the caller that
|
||||
* the code needs updating here. */
|
||||
abort();
|
||||
}
|
||||
|
||||
void buffer_from_SSL(buffer_t *buf, SSL *ssl)
|
||||
{
|
||||
int ret;
|
||||
if(!ssl || buffer_full(buf))
|
||||
return;
|
||||
ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf));
|
||||
if(ret > 0) {
|
||||
buf->used += ret;
|
||||
buf->total_in += ret;
|
||||
}
|
||||
if(ret < 0)
|
||||
int_ssl_check(ssl, ret);
|
||||
}
|
||||
|
||||
void buffer_to_SSL(buffer_t *buf, SSL *ssl)
|
||||
{
|
||||
int ret;
|
||||
if(!ssl || buffer_empty(buf))
|
||||
return;
|
||||
ret = SSL_write(ssl, buf->data, buf->used);
|
||||
if(ret > 0) {
|
||||
buffer_takedata(buf, NULL, ret);
|
||||
buf->total_out += ret;
|
||||
}
|
||||
if(ret < 0)
|
||||
int_ssl_check(ssl, ret);
|
||||
}
|
||||
|
||||
void buffer_from_BIO(buffer_t *buf, BIO *bio)
|
||||
{
|
||||
int ret;
|
||||
if(!bio || buffer_full(buf))
|
||||
return;
|
||||
ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf));
|
||||
if(ret > 0) {
|
||||
buf->used += ret;
|
||||
buf->total_in += ret;
|
||||
}
|
||||
}
|
||||
|
||||
void buffer_to_BIO(buffer_t *buf, BIO *bio)
|
||||
{
|
||||
int ret;
|
||||
if(!bio || buffer_empty(buf))
|
||||
return;
|
||||
ret = BIO_write(bio, buf->data, buf->used);
|
||||
if(ret > 0) {
|
||||
buffer_takedata(buf, NULL, ret);
|
||||
buf->total_out += ret;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !defined(NO_OPENSSL) */
|
||||
|
||||
#endif /* !defined(NO_BUFFER) */
|
|
@ -1,162 +0,0 @@
|
|||
#include "tunala.h"
|
||||
|
||||
#ifndef NO_OPENSSL
|
||||
|
||||
/* For callbacks generating output, here are their file-descriptors. */
|
||||
static FILE *fp_cb_ssl_info = NULL;
|
||||
static FILE *fp_cb_ssl_verify = NULL;
|
||||
/* Output level:
|
||||
* 0 = nothing,
|
||||
* 1 = minimal, just errors,
|
||||
* 2 = minimal, all steps,
|
||||
* 3 = detail, all steps */
|
||||
static unsigned int cb_ssl_verify_level = 1;
|
||||
|
||||
/* Other static rubbish (to mirror s_cb.c where required) */
|
||||
static int int_verify_depth = 10;
|
||||
|
||||
/* This function is largely borrowed from the one used in OpenSSL's "s_client"
|
||||
* and "s_server" utilities. */
|
||||
void cb_ssl_info(const SSL *s, int where, int ret)
|
||||
{
|
||||
const char *str1, *str2;
|
||||
int w;
|
||||
|
||||
if(!fp_cb_ssl_info)
|
||||
return;
|
||||
|
||||
w = where & ~SSL_ST_MASK;
|
||||
str1 = (w & SSL_ST_CONNECT ? "SSL_connect" : (w & SSL_ST_ACCEPT ?
|
||||
"SSL_accept" : "undefined")),
|
||||
str2 = SSL_state_string_long(s);
|
||||
|
||||
if (where & SSL_CB_LOOP)
|
||||
fprintf(fp_cb_ssl_info, "(%s) %s\n", str1, str2);
|
||||
else if (where & SSL_CB_EXIT) {
|
||||
if (ret == 0)
|
||||
fprintf(fp_cb_ssl_info, "(%s) failed in %s\n", str1, str2);
|
||||
/* In a non-blocking model, we get a few of these "error"s simply because we're
|
||||
* calling "reads" and "writes" on the state-machine that are virtual NOPs
|
||||
* simply to avoid wasting the time seeing if we *should* call them. Removing
|
||||
* this case makes the "-out_state" output a lot easier on the eye. */
|
||||
#if 0
|
||||
else if (ret < 0)
|
||||
fprintf(fp_cb_ssl_info, "%s:error in %s\n", str1, str2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void cb_ssl_info_set_output(FILE *fp)
|
||||
{
|
||||
fp_cb_ssl_info = fp;
|
||||
}
|
||||
|
||||
static const char *int_reason_no_issuer = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT";
|
||||
static const char *int_reason_not_yet = "X509_V_ERR_CERT_NOT_YET_VALID";
|
||||
static const char *int_reason_before = "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD";
|
||||
static const char *int_reason_expired = "X509_V_ERR_CERT_HAS_EXPIRED";
|
||||
static const char *int_reason_after = "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD";
|
||||
|
||||
/* Stolen wholesale from apps/s_cb.c :-) And since then, mutilated ... */
|
||||
int cb_ssl_verify(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
char buf1[256]; /* Used for the subject name */
|
||||
char buf2[256]; /* Used for the issuer name */
|
||||
const char *reason = NULL; /* Error reason (if any) */
|
||||
X509 *err_cert;
|
||||
int err, depth;
|
||||
|
||||
if(!fp_cb_ssl_verify || (cb_ssl_verify_level == 0))
|
||||
return ok;
|
||||
err_cert = X509_STORE_CTX_get_current_cert(ctx);
|
||||
err = X509_STORE_CTX_get_error(ctx);
|
||||
depth = X509_STORE_CTX_get_error_depth(ctx);
|
||||
|
||||
buf1[0] = buf2[0] = '\0';
|
||||
/* Fill buf1 */
|
||||
X509_NAME_oneline(X509_get_subject_name(err_cert), buf1, 256);
|
||||
/* Fill buf2 */
|
||||
X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf2, 256);
|
||||
switch (ctx->error) {
|
||||
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
|
||||
reason = int_reason_no_issuer;
|
||||
break;
|
||||
case X509_V_ERR_CERT_NOT_YET_VALID:
|
||||
reason = int_reason_not_yet;
|
||||
break;
|
||||
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
|
||||
reason = int_reason_before;
|
||||
break;
|
||||
case X509_V_ERR_CERT_HAS_EXPIRED:
|
||||
reason = int_reason_expired;
|
||||
break;
|
||||
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
|
||||
reason = int_reason_after;
|
||||
break;
|
||||
}
|
||||
|
||||
if((cb_ssl_verify_level == 1) && ok)
|
||||
return ok;
|
||||
fprintf(fp_cb_ssl_verify, "chain-depth=%d, ", depth);
|
||||
if(reason)
|
||||
fprintf(fp_cb_ssl_verify, "error=%s\n", reason);
|
||||
else
|
||||
fprintf(fp_cb_ssl_verify, "error=%d\n", err);
|
||||
if(cb_ssl_verify_level < 3)
|
||||
return ok;
|
||||
fprintf(fp_cb_ssl_verify, "--> subject = %s\n", buf1);
|
||||
fprintf(fp_cb_ssl_verify, "--> issuer = %s\n", buf2);
|
||||
if(!ok)
|
||||
fprintf(fp_cb_ssl_verify,"--> verify error:num=%d:%s\n",err,
|
||||
X509_verify_cert_error_string(err));
|
||||
fprintf(fp_cb_ssl_verify, "--> verify return:%d\n",ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void cb_ssl_verify_set_output(FILE *fp)
|
||||
{
|
||||
fp_cb_ssl_verify = fp;
|
||||
}
|
||||
|
||||
void cb_ssl_verify_set_depth(unsigned int verify_depth)
|
||||
{
|
||||
int_verify_depth = verify_depth;
|
||||
}
|
||||
|
||||
void cb_ssl_verify_set_level(unsigned int level)
|
||||
{
|
||||
if(level < 4)
|
||||
cb_ssl_verify_level = level;
|
||||
}
|
||||
|
||||
RSA *cb_generate_tmp_rsa(SSL *s, int is_export, int keylength)
|
||||
{
|
||||
/* TODO: Perhaps make it so our global key can be generated on-the-fly
|
||||
* after certain intervals? */
|
||||
static RSA *rsa_tmp = NULL;
|
||||
BIGNUM *bn = NULL;
|
||||
int ok = 1;
|
||||
if(!rsa_tmp) {
|
||||
ok = 0;
|
||||
if(!(bn = BN_new()))
|
||||
goto end;
|
||||
if(!BN_set_word(bn, RSA_F4))
|
||||
goto end;
|
||||
if(!(rsa_tmp = RSA_new()))
|
||||
goto end;
|
||||
if(!RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL))
|
||||
goto end;
|
||||
ok = 1;
|
||||
}
|
||||
end:
|
||||
if(bn)
|
||||
BN_free(bn);
|
||||
if(!ok) {
|
||||
RSA_free(rsa_tmp);
|
||||
rsa_tmp = NULL;
|
||||
}
|
||||
return rsa_tmp;
|
||||
}
|
||||
|
||||
#endif /* !defined(NO_OPENSSL) */
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(tunala.c)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
AM_INIT_AUTOMAKE(tunala, 0.0.1-dev)
|
||||
|
||||
dnl Checks for programs. (Though skip libtool)
|
||||
AC_PROG_CC
|
||||
dnl AC_PROG_LIBTOOL
|
||||
dnl AM_PROG_LIBTOOL
|
||||
|
||||
dnl Checks for libraries.
|
||||
AC_CHECK_LIB(dl, dlopen)
|
||||
AC_CHECK_LIB(z, inflate)
|
||||
AC_CHECK_LIB(socket, socket)
|
||||
AC_CHECK_LIB(nsl, gethostbyname)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(fcntl.h limits.h unistd.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS(strstr strtoul)
|
||||
AC_CHECK_FUNCS(select socket)
|
||||
AC_CHECK_FUNCS(dlopen)
|
||||
|
||||
AC_OUTPUT(Makefile)
|
|
@ -1,146 +0,0 @@
|
|||
#include "tunala.h"
|
||||
|
||||
#ifndef NO_IP
|
||||
|
||||
#define IP_LISTENER_BACKLOG 511 /* So if it gets masked by 256 or some other
|
||||
such value it'll still be respectable */
|
||||
|
||||
/* Any IP-related initialisations. For now, this means blocking SIGPIPE */
|
||||
int ip_initialise(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
if(sigaction(SIGPIPE, &sa, NULL) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ip_create_listener_split(const char *ip, unsigned short port)
|
||||
{
|
||||
struct sockaddr_in in_addr;
|
||||
int fd = -1;
|
||||
int reuseVal = 1;
|
||||
|
||||
/* Create the socket */
|
||||
if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
|
||||
goto err;
|
||||
/* Set the SO_REUSEADDR flag - servers act weird without it */
|
||||
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuseVal),
|
||||
sizeof(reuseVal)) != 0)
|
||||
goto err;
|
||||
/* Prepare the listen address stuff */
|
||||
in_addr.sin_family = AF_INET;
|
||||
memcpy(&in_addr.sin_addr.s_addr, ip, 4);
|
||||
in_addr.sin_port = htons(port);
|
||||
/* Bind to the required port/address/interface */
|
||||
if(bind(fd, (struct sockaddr *)&in_addr, sizeof(struct sockaddr_in)) != 0)
|
||||
goto err;
|
||||
/* Start "listening" */
|
||||
if(listen(fd, IP_LISTENER_BACKLOG) != 0)
|
||||
goto err;
|
||||
return fd;
|
||||
err:
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ip_create_connection_split(const char *ip, unsigned short port)
|
||||
{
|
||||
struct sockaddr_in in_addr;
|
||||
int flags, fd = -1;
|
||||
|
||||
/* Create the socket */
|
||||
if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
|
||||
goto err;
|
||||
/* Make it non-blocking */
|
||||
if(((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
|
||||
(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0))
|
||||
goto err;
|
||||
/* Prepare the connection address stuff */
|
||||
in_addr.sin_family = AF_INET;
|
||||
memcpy(&in_addr.sin_addr.s_addr, ip, 4);
|
||||
in_addr.sin_port = htons(port);
|
||||
/* Start a connect (non-blocking, in all likelihood) */
|
||||
if((connect(fd, (struct sockaddr *)&in_addr,
|
||||
sizeof(struct sockaddr_in)) != 0) &&
|
||||
(errno != EINPROGRESS))
|
||||
goto err;
|
||||
return fd;
|
||||
err:
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char all_local_ip[] = {0x00,0x00,0x00,0x00};
|
||||
|
||||
int ip_parse_address(const char *address, const char **parsed_ip,
|
||||
unsigned short *parsed_port, int accept_all_ip)
|
||||
{
|
||||
char buf[256];
|
||||
struct hostent *lookup;
|
||||
unsigned long port;
|
||||
const char *ptr = strstr(address, ":");
|
||||
const char *ip = all_local_ip;
|
||||
|
||||
if(!ptr) {
|
||||
/* We assume we're listening on all local interfaces and have
|
||||
* only specified a port. */
|
||||
if(!accept_all_ip)
|
||||
return 0;
|
||||
ptr = address;
|
||||
goto determine_port;
|
||||
}
|
||||
if((ptr - address) > 255)
|
||||
return 0;
|
||||
memset(buf, 0, 256);
|
||||
memcpy(buf, address, ptr - address);
|
||||
ptr++;
|
||||
if((lookup = gethostbyname(buf)) == NULL) {
|
||||
/* Spit a message to differentiate between lookup failures and
|
||||
* bad strings. */
|
||||
fprintf(stderr, "hostname lookup for '%s' failed\n", buf);
|
||||
return 0;
|
||||
}
|
||||
ip = lookup->h_addr_list[0];
|
||||
determine_port:
|
||||
if(strlen(ptr) < 1)
|
||||
return 0;
|
||||
if(!int_strtoul(ptr, &port) || (port > 65535))
|
||||
return 0;
|
||||
*parsed_ip = ip;
|
||||
*parsed_port = (unsigned short)port;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ip_create_listener(const char *address)
|
||||
{
|
||||
const char *ip;
|
||||
unsigned short port;
|
||||
|
||||
if(!ip_parse_address(address, &ip, &port, 1))
|
||||
return -1;
|
||||
return ip_create_listener_split(ip, port);
|
||||
}
|
||||
|
||||
int ip_create_connection(const char *address)
|
||||
{
|
||||
const char *ip;
|
||||
unsigned short port;
|
||||
|
||||
if(!ip_parse_address(address, &ip, &port, 0))
|
||||
return -1;
|
||||
return ip_create_connection_split(ip, port);
|
||||
}
|
||||
|
||||
int ip_accept_connection(int listen_fd)
|
||||
{
|
||||
return accept(listen_fd, NULL, NULL);
|
||||
}
|
||||
|
||||
#endif /* !defined(NO_IP) */
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
#include "tunala.h"
|
||||
|
||||
#ifndef NO_TUNALA
|
||||
|
||||
void state_machine_init(state_machine_t *machine)
|
||||
{
|
||||
machine->ssl = NULL;
|
||||
machine->bio_intossl = machine->bio_fromssl = NULL;
|
||||
buffer_init(&machine->clean_in);
|
||||
buffer_init(&machine->clean_out);
|
||||
buffer_init(&machine->dirty_in);
|
||||
buffer_init(&machine->dirty_out);
|
||||
}
|
||||
|
||||
void state_machine_close(state_machine_t *machine)
|
||||
{
|
||||
if(machine->ssl)
|
||||
SSL_free(machine->ssl);
|
||||
/* SSL_free seems to decrement the reference counts already so doing this goes
|
||||
* kaboom. */
|
||||
#if 0
|
||||
if(machine->bio_intossl)
|
||||
BIO_free(machine->bio_intossl);
|
||||
if(machine->bio_fromssl)
|
||||
BIO_free(machine->bio_fromssl);
|
||||
#endif
|
||||
buffer_close(&machine->clean_in);
|
||||
buffer_close(&machine->clean_out);
|
||||
buffer_close(&machine->dirty_in);
|
||||
buffer_close(&machine->dirty_out);
|
||||
state_machine_init(machine);
|
||||
}
|
||||
|
||||
buffer_t *state_machine_get_buffer(state_machine_t *machine, sm_buffer_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case SM_CLEAN_IN:
|
||||
return &machine->clean_in;
|
||||
case SM_CLEAN_OUT:
|
||||
return &machine->clean_out;
|
||||
case SM_DIRTY_IN:
|
||||
return &machine->dirty_in;
|
||||
case SM_DIRTY_OUT:
|
||||
return &machine->dirty_out;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Should never get here */
|
||||
abort();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSL *state_machine_get_SSL(state_machine_t *machine)
|
||||
{
|
||||
return machine->ssl;
|
||||
}
|
||||
|
||||
int state_machine_set_SSL(state_machine_t *machine, SSL *ssl, int is_server)
|
||||
{
|
||||
if(machine->ssl)
|
||||
/* Shouldn't ever be set twice */
|
||||
abort();
|
||||
machine->ssl = ssl;
|
||||
/* Create the BIOs to handle the dirty side of the SSL */
|
||||
if((machine->bio_intossl = BIO_new(BIO_s_mem())) == NULL)
|
||||
abort();
|
||||
if((machine->bio_fromssl = BIO_new(BIO_s_mem())) == NULL)
|
||||
abort();
|
||||
/* Hook up the BIOs on the dirty side of the SSL */
|
||||
SSL_set_bio(machine->ssl, machine->bio_intossl, machine->bio_fromssl);
|
||||
if(is_server)
|
||||
SSL_set_accept_state(machine->ssl);
|
||||
else
|
||||
SSL_set_connect_state(machine->ssl);
|
||||
/* If we're the first one to generate traffic - do it now otherwise we
|
||||
* go into the next select empty-handed and our peer will not send data
|
||||
* but will similarly wait for us. */
|
||||
return state_machine_churn(machine);
|
||||
}
|
||||
|
||||
/* Performs the data-IO loop and returns zero if the machine should close */
|
||||
int state_machine_churn(state_machine_t *machine)
|
||||
{
|
||||
unsigned int loop;
|
||||
if(machine->ssl == NULL) {
|
||||
if(buffer_empty(&machine->clean_out))
|
||||
/* Time to close this state-machine altogether */
|
||||
return 0;
|
||||
else
|
||||
/* Still buffered data on the clean side to go out */
|
||||
return 1;
|
||||
}
|
||||
/* Do this loop twice to cover any dependencies about which precise
|
||||
* order of reads and writes is required. */
|
||||
for(loop = 0; loop < 2; loop++) {
|
||||
buffer_to_SSL(&machine->clean_in, machine->ssl);
|
||||
buffer_to_BIO(&machine->dirty_in, machine->bio_intossl);
|
||||
buffer_from_SSL(&machine->clean_out, machine->ssl);
|
||||
buffer_from_BIO(&machine->dirty_out, machine->bio_fromssl);
|
||||
}
|
||||
/* We close on the SSL side if the info callback noticed some problems
|
||||
* or an SSL shutdown was underway and shutdown traffic had all been
|
||||
* sent. */
|
||||
if(SSL_get_app_data(machine->ssl) || (SSL_get_shutdown(machine->ssl) &&
|
||||
buffer_empty(&machine->dirty_out))) {
|
||||
/* Great, we can seal off the dirty side completely */
|
||||
if(!state_machine_close_dirty(machine))
|
||||
return 0;
|
||||
}
|
||||
/* Either the SSL is alive and well, or the closing process still has
|
||||
* outgoing data waiting to be sent */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Called when the clean side of the SSL has lost its connection */
|
||||
int state_machine_close_clean(state_machine_t *machine)
|
||||
{
|
||||
/* Well, first thing to do is null out the clean-side buffers - they're
|
||||
* no use any more. */
|
||||
buffer_close(&machine->clean_in);
|
||||
buffer_close(&machine->clean_out);
|
||||
/* And start an SSL shutdown */
|
||||
if(machine->ssl)
|
||||
SSL_shutdown(machine->ssl);
|
||||
/* This is an "event", so flush the SSL of any generated traffic */
|
||||
state_machine_churn(machine);
|
||||
if(buffer_empty(&machine->dirty_in) &&
|
||||
buffer_empty(&machine->dirty_out))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Called when the dirty side of the SSL has lost its connection. This is pretty
|
||||
* terminal as all that can be left to do is send any buffered output on the
|
||||
* clean side - after that, we're done. */
|
||||
int state_machine_close_dirty(state_machine_t *machine)
|
||||
{
|
||||
buffer_close(&machine->dirty_in);
|
||||
buffer_close(&machine->dirty_out);
|
||||
buffer_close(&machine->clean_in);
|
||||
if(machine->ssl)
|
||||
SSL_free(machine->ssl);
|
||||
machine->ssl = NULL;
|
||||
machine->bio_intossl = machine->bio_fromssl = NULL;
|
||||
if(buffer_empty(&machine->clean_out))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* !defined(NO_TUNALA) */
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
HTTP="localhost:8080"
|
||||
CLIENT_PORT="9020"
|
||||
SERVER_PORT="9021"
|
||||
|
||||
sub_test ()
|
||||
{
|
||||
echo "STARTING - $VER $CIPHER"
|
||||
./tunala -listen localhost:$CLIENT_PORT -proxy localhost:$SERVER_PORT \
|
||||
-cacert CA.pem -cert A-client.pem -server 0 \
|
||||
-dh_special standard -v_peer -v_strict \
|
||||
$VER -cipher $CIPHER 1> tc1.txt 2> tc2.txt &
|
||||
./tunala -listen localhost:$SERVER_PORT -proxy $HTTP \
|
||||
-cacert CA.pem -cert A-server.pem -server 1 \
|
||||
-dh_special standard -v_peer -v_strict \
|
||||
$VER -cipher $CIPHER 1> ts1.txt 2> ts2.txt &
|
||||
# Wait for the servers to be listening before starting the wget test
|
||||
DONE="no"
|
||||
while [ "$DONE" != "yes" ]; do
|
||||
L1=`netstat -a | egrep "LISTEN[\t ]*$" | grep ":$CLIENT_PORT"`
|
||||
L2=`netstat -a | egrep "LISTEN[\t ]*$" | grep ":$SERVER_PORT"`
|
||||
if [ "x$L1" != "x" ]; then
|
||||
DONE="yes"
|
||||
elif [ "x$L2" != "x" ]; then
|
||||
DONE="yes"
|
||||
else
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
HTML=`wget -O - -T 1 http://localhost:$CLIENT_PORT 2> /dev/null | grep "<HTML>"`
|
||||
if [ "x$HTML" != "x" ]; then
|
||||
echo "OK - $CIPHER ($VER)"
|
||||
else
|
||||
echo "FAIL - $CIPHER ($VER)"
|
||||
killall tunala
|
||||
exit 1
|
||||
fi
|
||||
killall tunala
|
||||
# Wait for the servers to stop before returning - otherwise the next
|
||||
# test my fail to start ... (fscking race conditions)
|
||||
DONE="yes"
|
||||
while [ "$DONE" != "no" ]; do
|
||||
L1=`netstat -a | egrep "LISTEN[\t ]*$" | grep ":$CLIENT_PORT"`
|
||||
L2=`netstat -a | egrep "LISTEN[\t ]*$" | grep ":$SERVER_PORT"`
|
||||
if [ "x$L1" != "x" ]; then
|
||||
DONE="yes"
|
||||
elif [ "x$L2" != "x" ]; then
|
||||
DONE="yes"
|
||||
else
|
||||
DONE="no"
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
}
|
||||
|
||||
run_test ()
|
||||
{
|
||||
(sub_test 1> /dev/null) || exit 1
|
||||
}
|
||||
|
||||
run_ssl_test ()
|
||||
{
|
||||
killall tunala 1> /dev/null 2> /dev/null
|
||||
echo ""
|
||||
echo "Starting all $PRETTY tests"
|
||||
if [ "$PRETTY" != "SSLv2" ]; then
|
||||
if [ "$PRETTY" != "SSLv3" ]; then
|
||||
export VER="-no_ssl2 -no_ssl3"
|
||||
export OSSL="-tls1"
|
||||
else
|
||||
export VER="-no_ssl2 -no_tls1"
|
||||
export OSSL="-ssl3"
|
||||
fi
|
||||
else
|
||||
export VER="-no_ssl3 -no_tls1"
|
||||
export OSSL="-ssl2"
|
||||
fi
|
||||
LIST="`../../apps/openssl ciphers $OSSL | sed -e 's/:/ /g'`"
|
||||
#echo "$LIST"
|
||||
for i in $LIST; do \
|
||||
DSS=`echo "$i" | grep "DSS"`
|
||||
if [ "x$DSS" != "x" ]; then
|
||||
echo "---- skipping $i (no DSA cert/keys) ----"
|
||||
else
|
||||
export CIPHER=$i
|
||||
run_test
|
||||
echo "SUCCESS: $i"
|
||||
fi
|
||||
done;
|
||||
}
|
||||
|
||||
# Welcome the user
|
||||
echo "Tests will assume an http server running at $HTTP"
|
||||
|
||||
# TLSv1 test
|
||||
export PRETTY="TLSv1"
|
||||
run_ssl_test
|
||||
|
||||
# SSLv3 test
|
||||
export PRETTY="SSLv3"
|
||||
run_ssl_test
|
||||
|
||||
# SSLv2 test
|
||||
export PRETTY="SSLv2"
|
||||
run_ssl_test
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,215 +0,0 @@
|
|||
/* Tunala ("Tunneler with a New Zealand accent")
|
||||
*
|
||||
* Written by Geoff Thorpe, but endorsed/supported by noone. Please use this is
|
||||
* if it's useful or informative to you, but it's only here as a scratchpad for
|
||||
* ideas about how you might (or might not) program with OpenSSL. If you deploy
|
||||
* this is in a mission-critical environment, and have not read, understood,
|
||||
* audited, and modified this code to your satisfaction, and the result is that
|
||||
* all hell breaks loose and you are looking for a new employer, then it proves
|
||||
* nothing except perhaps that Darwinism is alive and well. Let's just say, *I*
|
||||
* don't use this in a mission-critical environment, so it would be stupid for
|
||||
* anyone to assume that it is solid and/or tested enough when even its author
|
||||
* doesn't place that much trust in it. You have been warned.
|
||||
*
|
||||
* With thanks to Cryptographic Appliances, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _TUNALA_H
|
||||
#define _TUNALA_H
|
||||
|
||||
/* pull in autoconf fluff */
|
||||
#ifndef NO_CONFIG_H
|
||||
#include "config.h"
|
||||
#else
|
||||
/* We don't have autoconf, we have to set all of these unless a tweaked Makefile
|
||||
* tells us not to ... */
|
||||
/* headers */
|
||||
#ifndef NO_HAVE_SELECT
|
||||
#define HAVE_SELECT
|
||||
#endif
|
||||
#ifndef NO_HAVE_SOCKET
|
||||
#define HAVE_SOCKET
|
||||
#endif
|
||||
#ifndef NO_HAVE_UNISTD_H
|
||||
#define HAVE_UNISTD_H
|
||||
#endif
|
||||
#ifndef NO_HAVE_FCNTL_H
|
||||
#define HAVE_FCNTL_H
|
||||
#endif
|
||||
#ifndef NO_HAVE_LIMITS_H
|
||||
#define HAVE_LIMITS_H
|
||||
#endif
|
||||
/* features */
|
||||
#ifndef NO_HAVE_STRSTR
|
||||
#define HAVE_STRSTR
|
||||
#endif
|
||||
#ifndef NO_HAVE_STRTOUL
|
||||
#define HAVE_STRTOUL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SELECT) || !defined(HAVE_SOCKET)
|
||||
#error "can't build without some network basics like select() and socket()"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifndef NO_SYSTEM_H
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#endif /* !defined(NO_SYSTEM_H) */
|
||||
|
||||
#ifndef NO_OPENSSL
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/ssl.h>
|
||||
#endif /* !defined(NO_OPENSSL) */
|
||||
|
||||
#ifndef OPENSSL_NO_BUFFER
|
||||
/* This is the generic "buffer" type that is used when feeding the
|
||||
* state-machine. It's basically a FIFO with respect to the "adddata" &
|
||||
* "takedata" type functions that operate on it. */
|
||||
#define MAX_DATA_SIZE 16384
|
||||
typedef struct _buffer_t {
|
||||
unsigned char data[MAX_DATA_SIZE];
|
||||
unsigned int used;
|
||||
/* Statistical values - counts the total number of bytes read in and
|
||||
* read out (respectively) since "buffer_init()" */
|
||||
unsigned long total_in, total_out;
|
||||
} buffer_t;
|
||||
|
||||
/* Initialise a buffer structure before use */
|
||||
void buffer_init(buffer_t *buf);
|
||||
/* Cleanup a buffer structure - presently not needed, but if buffer_t is
|
||||
* converted to using dynamic allocation, this would be required - so should be
|
||||
* called to protect against an explosion of memory leaks later if the change is
|
||||
* made. */
|
||||
void buffer_close(buffer_t *buf);
|
||||
|
||||
/* Basic functions to manipulate buffers */
|
||||
|
||||
unsigned int buffer_used(buffer_t *buf); /* How much data in the buffer */
|
||||
unsigned int buffer_unused(buffer_t *buf); /* How much space in the buffer */
|
||||
int buffer_full(buffer_t *buf); /* Boolean, is it full? */
|
||||
int buffer_notfull(buffer_t *buf); /* Boolean, is it not full? */
|
||||
int buffer_empty(buffer_t *buf); /* Boolean, is it empty? */
|
||||
int buffer_notempty(buffer_t *buf); /* Boolean, is it not empty? */
|
||||
unsigned long buffer_total_in(buffer_t *buf); /* Total bytes written to buffer */
|
||||
unsigned long buffer_total_out(buffer_t *buf); /* Total bytes read from buffer */
|
||||
|
||||
#if 0 /* Currently used only within buffer.c - better to expose only
|
||||
* higher-level functions anyway */
|
||||
/* Add data to the tail of the buffer, returns the amount that was actually
|
||||
* added (so, you need to check if return value is less than size) */
|
||||
unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
|
||||
unsigned int size);
|
||||
|
||||
/* Take data from the front of the buffer (and scroll the rest forward). If
|
||||
* "ptr" is NULL, this just removes data off the front of the buffer. Return
|
||||
* value is the amount actually removed (can be less than size if the buffer has
|
||||
* too little data). */
|
||||
unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
|
||||
unsigned int size);
|
||||
|
||||
/* Flushes as much data as possible out of the "from" buffer into the "to"
|
||||
* buffer. Return value is the amount moved. The amount moved can be restricted
|
||||
* to a maximum by specifying "cap" - setting it to -1 means no limit. */
|
||||
unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap);
|
||||
#endif
|
||||
|
||||
#ifndef NO_IP
|
||||
/* Read or write between a file-descriptor and a buffer */
|
||||
int buffer_from_fd(buffer_t *buf, int fd);
|
||||
int buffer_to_fd(buffer_t *buf, int fd);
|
||||
#endif /* !defined(NO_IP) */
|
||||
|
||||
#ifndef NO_OPENSSL
|
||||
/* Read or write between an SSL or BIO and a buffer */
|
||||
void buffer_from_SSL(buffer_t *buf, SSL *ssl);
|
||||
void buffer_to_SSL(buffer_t *buf, SSL *ssl);
|
||||
void buffer_from_BIO(buffer_t *buf, BIO *bio);
|
||||
void buffer_to_BIO(buffer_t *buf, BIO *bio);
|
||||
|
||||
/* Callbacks */
|
||||
void cb_ssl_info(const SSL *s, int where, int ret);
|
||||
void cb_ssl_info_set_output(FILE *fp); /* Called if output should be sent too */
|
||||
int cb_ssl_verify(int ok, X509_STORE_CTX *ctx);
|
||||
void cb_ssl_verify_set_output(FILE *fp);
|
||||
void cb_ssl_verify_set_depth(unsigned int verify_depth);
|
||||
void cb_ssl_verify_set_level(unsigned int level);
|
||||
RSA *cb_generate_tmp_rsa(SSL *s, int is_export, int keylength);
|
||||
#endif /* !defined(NO_OPENSSL) */
|
||||
#endif /* !defined(OPENSSL_NO_BUFFER) */
|
||||
|
||||
#ifndef NO_TUNALA
|
||||
#ifdef OPENSSL_NO_BUFFER
|
||||
#error "TUNALA section of tunala.h requires BUFFER support"
|
||||
#endif
|
||||
typedef struct _state_machine_t {
|
||||
SSL *ssl;
|
||||
BIO *bio_intossl;
|
||||
BIO *bio_fromssl;
|
||||
buffer_t clean_in, clean_out;
|
||||
buffer_t dirty_in, dirty_out;
|
||||
} state_machine_t;
|
||||
typedef enum {
|
||||
SM_CLEAN_IN, SM_CLEAN_OUT,
|
||||
SM_DIRTY_IN, SM_DIRTY_OUT
|
||||
} sm_buffer_t;
|
||||
void state_machine_init(state_machine_t *machine);
|
||||
void state_machine_close(state_machine_t *machine);
|
||||
buffer_t *state_machine_get_buffer(state_machine_t *machine, sm_buffer_t type);
|
||||
SSL *state_machine_get_SSL(state_machine_t *machine);
|
||||
int state_machine_set_SSL(state_machine_t *machine, SSL *ssl, int is_server);
|
||||
/* Performs the data-IO loop and returns zero if the machine should close */
|
||||
int state_machine_churn(state_machine_t *machine);
|
||||
/* Is used to handle closing conditions - namely when one side of the tunnel has
|
||||
* closed but the other should finish flushing. */
|
||||
int state_machine_close_clean(state_machine_t *machine);
|
||||
int state_machine_close_dirty(state_machine_t *machine);
|
||||
#endif /* !defined(NO_TUNALA) */
|
||||
|
||||
#ifndef NO_IP
|
||||
/* Initialise anything related to the networking. This includes blocking pesky
|
||||
* SIGPIPE signals. */
|
||||
int ip_initialise(void);
|
||||
/* ip is the 4-byte ip address (eg. 127.0.0.1 is {0x7F,0x00,0x00,0x01}), port is
|
||||
* the port to listen on (host byte order), and the return value is the
|
||||
* file-descriptor or -1 on error. */
|
||||
int ip_create_listener_split(const char *ip, unsigned short port);
|
||||
/* Same semantics as above. */
|
||||
int ip_create_connection_split(const char *ip, unsigned short port);
|
||||
/* Converts a string into the ip/port before calling the above */
|
||||
int ip_create_listener(const char *address);
|
||||
int ip_create_connection(const char *address);
|
||||
/* Just does a string conversion on its own. NB: If accept_all_ip is non-zero,
|
||||
* then the address string could be just a port. Ie. it's suitable for a
|
||||
* listening address but not a connecting address. */
|
||||
int ip_parse_address(const char *address, const char **parsed_ip,
|
||||
unsigned short *port, int accept_all_ip);
|
||||
/* Accepts an incoming connection through the listener. Assumes selects and
|
||||
* what-not have deemed it an appropriate thing to do. */
|
||||
int ip_accept_connection(int listen_fd);
|
||||
#endif /* !defined(NO_IP) */
|
||||
|
||||
/* These functions wrap up things that can be portability hassles. */
|
||||
int int_strtoul(const char *str, unsigned long *val);
|
||||
#ifdef HAVE_STRSTR
|
||||
#define int_strstr strstr
|
||||
#else
|
||||
char *int_strstr(const char *haystack, const char *needle);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(_TUNALA_H) */
|
Loading…
Reference in a new issue