diff options
| author | william <william@25tandclement.com> | 2014-09-19 20:02:38 -0700 |
|---|---|---|
| committer | william <william@25tandclement.com> | 2014-09-19 20:02:38 -0700 |
| commit | ad0549dfa0396f495cddbc8c83b37013c0d9ce15 (patch) | |
| tree | aa4fca223f18222bf43a990e8b437a8bd5fb58b2 /src | |
| parent | 3c27b8f14a31e14dc4037803f0892445b8581a70 (diff) | |
| download | luaossl-ad0549dfa0396f495cddbc8c83b37013c0d9ce15.tar.gz luaossl-ad0549dfa0396f495cddbc8c83b37013c0d9ce15.tar.bz2 luaossl-ad0549dfa0396f495cddbc8c83b37013c0d9ce15.zip | |
fix issue with loading public and private keys concurrently, fix issue in pusherror when no OpenSSL errors are actually defined, and because OpenSSL doesn't define its FOO_free routines to accept NULL--even though most or all do handle NULL properly--don't pass them NULL
Diffstat (limited to 'src')
| -rw-r--r-- | src/openssl.c | 196 |
1 files changed, 140 insertions, 56 deletions
diff --git a/src/openssl.c b/src/openssl.c index 8efb348..1aab2ca 100644 --- a/src/openssl.c +++ b/src/openssl.c | |||
| @@ -236,6 +236,9 @@ static const char *pusherror(lua_State *L, const char *fun) { | |||
| 236 | int line; | 236 | int line; |
| 237 | char txt[256]; | 237 | char txt[256]; |
| 238 | 238 | ||
| 239 | if (!ERR_peek_error()) | ||
| 240 | return lua_pushstring(L, "oops: no OpenSSL errors set"); | ||
| 241 | |||
| 239 | code = ERR_get_error_line(&path, &line); | 242 | code = ERR_get_error_line(&path, &line); |
| 240 | 243 | ||
| 241 | if ((file = strrchr(path, '/'))) | 244 | if ((file = strrchr(path, '/'))) |
| @@ -686,8 +689,10 @@ static void bn_prepops(lua_State *L, BIGNUM **r, BIGNUM **a, BIGNUM **b, _Bool c | |||
| 686 | static int ctx__gc(lua_State *L) { | 689 | static int ctx__gc(lua_State *L) { |
| 687 | BN_CTX **ctx = lua_touserdata(L, 1); | 690 | BN_CTX **ctx = lua_touserdata(L, 1); |
| 688 | 691 | ||
| 689 | BN_CTX_free(*ctx); | 692 | if (*ctx) { |
| 690 | *ctx = NULL; | 693 | BN_CTX_free(*ctx); |
| 694 | *ctx = NULL; | ||
| 695 | } | ||
| 691 | 696 | ||
| 692 | return 0; | 697 | return 0; |
| 693 | } /* ctx__gc() */ | 698 | } /* ctx__gc() */ |
| @@ -837,8 +842,10 @@ static int bn__le(lua_State *L) { | |||
| 837 | static int bn__gc(lua_State *L) { | 842 | static int bn__gc(lua_State *L) { |
| 838 | BIGNUM **ud = luaL_checkudata(L, 1, BIGNUM_CLASS); | 843 | BIGNUM **ud = luaL_checkudata(L, 1, BIGNUM_CLASS); |
| 839 | 844 | ||
| 840 | BN_free(*ud); | 845 | if (*ud) { |
| 841 | *ud = NULL; | 846 | BN_free(*ud); |
| 847 | *ud = NULL; | ||
| 848 | } | ||
| 842 | 849 | ||
| 843 | return 0; | 850 | return 0; |
| 844 | } /* bn__gc() */ | 851 | } /* bn__gc() */ |
| @@ -901,8 +908,10 @@ int luaopen__openssl_bignum(lua_State *L) { | |||
| 901 | static int bio__gc(lua_State *L) { | 908 | static int bio__gc(lua_State *L) { |
| 902 | BIO **bio = lua_touserdata(L, 1); | 909 | BIO **bio = lua_touserdata(L, 1); |
| 903 | 910 | ||
| 904 | BIO_free(*bio); | 911 | if (*bio) { |
| 905 | *bio = NULL; | 912 | BIO_free(*bio); |
| 913 | *bio = NULL; | ||
| 914 | } | ||
| 906 | 915 | ||
| 907 | return 0; | 916 | return 0; |
| 908 | } /* bio__gc() */ | 917 | } /* bio__gc() */ |
| @@ -1080,18 +1089,19 @@ creat: | |||
| 1080 | } /* switch() */ | 1089 | } /* switch() */ |
| 1081 | } else if (lua_isstring(L, 1)) { | 1090 | } else if (lua_isstring(L, 1)) { |
| 1082 | int type = optencoding(L, 2, "*", X509_ANY|X509_PEM|X509_DER); | 1091 | int type = optencoding(L, 2, "*", X509_ANY|X509_PEM|X509_DER); |
| 1083 | int ispub = -1; | 1092 | int pubonly = 0, prvtonly = 0; |
| 1084 | const char *opt, *data; | 1093 | const char *opt, *data; |
| 1085 | size_t len; | 1094 | size_t len; |
| 1086 | BIO *bio; | 1095 | BIO *bio; |
| 1087 | int ok = 0; | 1096 | EVP_PKEY *pub = NULL, *prvt = NULL; |
| 1097 | int goterr = 0; | ||
| 1088 | 1098 | ||
| 1089 | /* check if specified publickey or privatekey */ | 1099 | /* check if specified publickey or privatekey */ |
| 1090 | if ((opt = luaL_optstring(L, 3, NULL))) { | 1100 | if ((opt = luaL_optstring(L, 3, NULL))) { |
| 1091 | if (xtolower(opt[0]) == 'p' && xtolower(opt[1]) == 'u') { | 1101 | if (xtolower(opt[0]) == 'p' && xtolower(opt[1]) == 'u') { |
| 1092 | ispub = 1; | 1102 | pubonly = 1; |
| 1093 | } else if (xtolower(opt[0]) == 'p' && xtolower(opt[1]) == 'r') { | 1103 | } else if (xtolower(opt[0]) == 'p' && xtolower(opt[1]) == 'r') { |
| 1094 | ispub = 0; | 1104 | prvtonly = 1; |
| 1095 | } else { | 1105 | } else { |
| 1096 | return luaL_argerror(L, 3, lua_pushfstring(L, "invalid option %s", opt)); | 1106 | return luaL_argerror(L, 3, lua_pushfstring(L, "invalid option %s", opt)); |
| 1097 | } | 1107 | } |
| @@ -1103,42 +1113,85 @@ creat: | |||
| 1103 | return throwssl(L, "pkey.new"); | 1113 | return throwssl(L, "pkey.new"); |
| 1104 | 1114 | ||
| 1105 | if (type == X509_PEM || type == X509_ANY) { | 1115 | if (type == X509_PEM || type == X509_ANY) { |
| 1106 | if (ispub == 1 || ispub == -1) { | 1116 | if (!prvtonly && !pub) { |
| 1107 | ok = !!(*ud = PEM_read_bio_PUBKEY(bio, NULL, 0, "")); | 1117 | /* |
| 1108 | 1118 | * BIO_reset is a rewind for read-only | |
| 1109 | if (ok || (type == X509_PEM && ispub == 1)) | 1119 | * memory buffers. See mem_ctrl in |
| 1110 | goto done; | 1120 | * crypto/bio/bss_mem.c of OpenSSL source. |
| 1121 | */ | ||
| 1122 | BIO_reset(bio); | ||
| 1123 | |||
| 1124 | if (!(pub = PEM_read_bio_PUBKEY(bio, NULL, 0, ""))) | ||
| 1125 | goterr = 1; | ||
| 1111 | } | 1126 | } |
| 1112 | 1127 | ||
| 1113 | if (ispub == 0 || ispub == -1) { | 1128 | if (!pubonly && !prvt) { |
| 1114 | ok = !!(*ud = PEM_read_bio_PrivateKey(bio, NULL, 0, "")); | 1129 | BIO_reset(bio); |
| 1115 | 1130 | ||
| 1116 | if (ok || (type == X509_PEM && ispub == 0)) | 1131 | if (!(prvt = PEM_read_bio_PrivateKey(bio, NULL, 0, ""))) |
| 1117 | goto done; | 1132 | goterr = 1; |
| 1118 | } | 1133 | } |
| 1119 | } | 1134 | } |
| 1120 | 1135 | ||
| 1121 | if (type == X509_DER || type == X509_ANY) { | 1136 | if (type == X509_DER || type == X509_ANY) { |
| 1122 | if (ispub == 1 || ispub == -1) { | 1137 | if (!prvtonly && !pub) { |
| 1123 | ok = !!(*ud = d2i_PUBKEY_bio(bio, NULL)); | 1138 | BIO_reset(bio); |
| 1124 | 1139 | ||
| 1125 | if (ok || (type == X509_DER && ispub == 1)) | 1140 | if (!(pub = d2i_PUBKEY_bio(bio, NULL))) |
| 1126 | goto done; | 1141 | goterr = 1; |
| 1127 | } | 1142 | } |
| 1128 | 1143 | ||
| 1129 | if (ispub == 0 || ispub == -1) { | 1144 | if (!pubonly && !prvt) { |
| 1130 | ok = !!(*ud = d2i_PrivateKey_bio(bio, NULL)); | 1145 | BIO_reset(bio); |
| 1131 | 1146 | ||
| 1132 | if (ok || (type == X509_DER && ispub == 0)) | 1147 | if (!(prvt = d2i_PrivateKey_bio(bio, NULL))) |
| 1133 | goto done; | 1148 | goterr = 1; |
| 1134 | } | 1149 | } |
| 1135 | } | 1150 | } |
| 1136 | 1151 | ||
| 1152 | if (prvt) { | ||
| 1153 | #if 0 | ||
| 1154 | /* TODO: Determine if this is necessary. */ | ||
| 1155 | if (pub && EVP_PKEY_missing_parameters(prvt)) { | ||
| 1156 | if (!EVP_PKEY_copy_parameters(prvt, pub)) { | ||
| 1157 | /* | ||
| 1158 | * NOTE: It's not necessarily true | ||
| 1159 | * that any internal errors were | ||
| 1160 | * set. But we fixed pusherror() to | ||
| 1161 | * handle that situation. | ||
| 1162 | */ | ||
| 1163 | goterr = 1; | ||
| 1164 | |||
| 1165 | goto done; | ||
| 1166 | } | ||
| 1167 | } | ||
| 1168 | #endif | ||
| 1169 | |||
| 1170 | *ud = prvt; | ||
| 1171 | prvt = NULL; | ||
| 1172 | } else if (pub) { | ||
| 1173 | *ud = pub; | ||
| 1174 | pub = NULL; | ||
| 1175 | } | ||
| 1137 | done: | 1176 | done: |
| 1138 | BIO_free(bio); | 1177 | BIO_free(bio); |
| 1139 | 1178 | ||
| 1140 | if (!ok) | 1179 | if (pub) |
| 1141 | return throwssl(L, "pkey.new"); | 1180 | EVP_PKEY_free(pub); |
| 1181 | |||
| 1182 | if (prvt) | ||
| 1183 | EVP_PKEY_free(prvt); | ||
| 1184 | |||
| 1185 | if (!*ud) { | ||
| 1186 | if (goterr) | ||
| 1187 | return throwssl(L, "pkey.new"); | ||
| 1188 | |||
| 1189 | /* we should never get here */ | ||
| 1190 | return luaL_error(L, "failed to load key for some unexpected reason"); | ||
| 1191 | } else if (goterr) { | ||
| 1192 | /* clean up our mess from testing input formats */ | ||
| 1193 | ERR_clear_error(); | ||
| 1194 | } | ||
| 1142 | } else { | 1195 | } else { |
| 1143 | return luaL_error(L, "%s: unknown key initializer", lua_typename(L, lua_type(L, 1))); | 1196 | return luaL_error(L, "%s: unknown key initializer", lua_typename(L, lua_type(L, 1))); |
| 1144 | } | 1197 | } |
| @@ -1223,7 +1276,7 @@ static int pk_setPrivateKey(lua_State *L) { | |||
| 1223 | lua_pushboolean(L, 1); | 1276 | lua_pushboolean(L, 1); |
| 1224 | 1277 | ||
| 1225 | return 1; | 1278 | return 1; |
| 1226 | } /* pk_setPrivateKEY() */ | 1279 | } /* pk_setPrivateKey() */ |
| 1227 | 1280 | ||
| 1228 | 1281 | ||
| 1229 | static int pk_sign(lua_State *L) { | 1282 | static int pk_sign(lua_State *L) { |
| @@ -1408,8 +1461,10 @@ static int pk__tostring(lua_State *L) { | |||
| 1408 | static int pk__gc(lua_State *L) { | 1461 | static int pk__gc(lua_State *L) { |
| 1409 | EVP_PKEY **ud = luaL_checkudata(L, 1, PKEY_CLASS); | 1462 | EVP_PKEY **ud = luaL_checkudata(L, 1, PKEY_CLASS); |
| 1410 | 1463 | ||
| 1411 | EVP_PKEY_free(*ud); | 1464 | if (*ud) { |
| 1412 | *ud = NULL; | 1465 | EVP_PKEY_free(*ud); |
| 1466 | *ud = NULL; | ||
| 1467 | } | ||
| 1413 | 1468 | ||
| 1414 | return 0; | 1469 | return 0; |
| 1415 | } /* pk__gc() */ | 1470 | } /* pk__gc() */ |
| @@ -1614,8 +1669,10 @@ static int xn__pairs(lua_State *L) { | |||
| 1614 | static int xn__gc(lua_State *L) { | 1669 | static int xn__gc(lua_State *L) { |
| 1615 | X509_NAME **ud = luaL_checkudata(L, 1, X509_NAME_CLASS); | 1670 | X509_NAME **ud = luaL_checkudata(L, 1, X509_NAME_CLASS); |
| 1616 | 1671 | ||
| 1617 | X509_NAME_free(*ud); | 1672 | if (*ud) { |
| 1618 | *ud = NULL; | 1673 | X509_NAME_free(*ud); |
| 1674 | *ud = NULL; | ||
| 1675 | } | ||
| 1619 | 1676 | ||
| 1620 | return 0; | 1677 | return 0; |
| 1621 | } /* xn__gc() */ | 1678 | } /* xn__gc() */ |
| @@ -1881,8 +1938,10 @@ static int gn__pairs(lua_State *L) { | |||
| 1881 | static int gn__gc(lua_State *L) { | 1938 | static int gn__gc(lua_State *L) { |
| 1882 | GENERAL_NAMES **ud = luaL_checkudata(L, 1, X509_GENS_CLASS); | 1939 | GENERAL_NAMES **ud = luaL_checkudata(L, 1, X509_GENS_CLASS); |
| 1883 | 1940 | ||
| 1884 | sk_GENERAL_NAME_pop_free(*ud, GENERAL_NAME_free); | 1941 | if (*ud) { |
| 1885 | *ud = NULL; | 1942 | sk_GENERAL_NAME_pop_free(*ud, GENERAL_NAME_free); |
| 1943 | *ud = NULL; | ||
| 1944 | } | ||
| 1886 | 1945 | ||
| 1887 | return 0; | 1946 | return 0; |
| 1888 | } /* gn__gc() */ | 1947 | } /* gn__gc() */ |
| @@ -1979,8 +2038,10 @@ static int xe_interpose(lua_State *L) { | |||
| 1979 | static int xe__gc(lua_State *L) { | 2038 | static int xe__gc(lua_State *L) { |
| 1980 | X509_EXTENSION **ud = luaL_checkudata(L, 1, X509_EXT_CLASS); | 2039 | X509_EXTENSION **ud = luaL_checkudata(L, 1, X509_EXT_CLASS); |
| 1981 | 2040 | ||
| 1982 | X509_EXTENSION_free(*ud); | 2041 | if (*ud) { |
| 1983 | *ud = NULL; | 2042 | X509_EXTENSION_free(*ud); |
| 2043 | *ud = NULL; | ||
| 2044 | } | ||
| 1984 | 2045 | ||
| 1985 | return 0; | 2046 | return 0; |
| 1986 | } /* xe__gc() */ | 2047 | } /* xe__gc() */ |
| @@ -2899,8 +2960,10 @@ static int xc__tostring(lua_State *L) { | |||
| 2899 | static int xc__gc(lua_State *L) { | 2960 | static int xc__gc(lua_State *L) { |
| 2900 | X509 **ud = luaL_checkudata(L, 1, X509_CERT_CLASS); | 2961 | X509 **ud = luaL_checkudata(L, 1, X509_CERT_CLASS); |
| 2901 | 2962 | ||
| 2902 | X509_free(*ud); | 2963 | if (*ud) { |
| 2903 | *ud = NULL; | 2964 | X509_free(*ud); |
| 2965 | *ud = NULL; | ||
| 2966 | } | ||
| 2904 | 2967 | ||
| 2905 | return 0; | 2968 | return 0; |
| 2906 | } /* xc__gc() */ | 2969 | } /* xc__gc() */ |
| @@ -3130,8 +3193,10 @@ static int xr__tostring(lua_State *L) { | |||
| 3130 | static int xr__gc(lua_State *L) { | 3193 | static int xr__gc(lua_State *L) { |
| 3131 | X509_REQ **ud = luaL_checkudata(L, 1, X509_CSR_CLASS); | 3194 | X509_REQ **ud = luaL_checkudata(L, 1, X509_CSR_CLASS); |
| 3132 | 3195 | ||
| 3133 | X509_REQ_free(*ud); | 3196 | if (*ud) { |
| 3134 | *ud = NULL; | 3197 | X509_REQ_free(*ud); |
| 3198 | *ud = NULL; | ||
| 3199 | } | ||
| 3135 | 3200 | ||
| 3136 | return 0; | 3201 | return 0; |
| 3137 | } /* xr__gc() */ | 3202 | } /* xr__gc() */ |
| @@ -3459,8 +3524,10 @@ static int xx__tostring(lua_State *L) { | |||
| 3459 | static int xx__gc(lua_State *L) { | 3524 | static int xx__gc(lua_State *L) { |
| 3460 | X509_CRL **ud = luaL_checkudata(L, 1, X509_CRL_CLASS); | 3525 | X509_CRL **ud = luaL_checkudata(L, 1, X509_CRL_CLASS); |
| 3461 | 3526 | ||
| 3462 | X509_CRL_free(*ud); | 3527 | if (*ud) { |
| 3463 | *ud = NULL; | 3528 | X509_CRL_free(*ud); |
| 3529 | *ud = NULL; | ||
| 3530 | } | ||
| 3464 | 3531 | ||
| 3465 | return 0; | 3532 | return 0; |
| 3466 | } /* xx__gc() */ | 3533 | } /* xx__gc() */ |
| @@ -3625,8 +3692,10 @@ static int xl__pairs(lua_State *L) { | |||
| 3625 | static int xl__gc(lua_State *L) { | 3692 | static int xl__gc(lua_State *L) { |
| 3626 | STACK_OF(X509) **chain = luaL_checkudata(L, 1, X509_CHAIN_CLASS); | 3693 | STACK_OF(X509) **chain = luaL_checkudata(L, 1, X509_CHAIN_CLASS); |
| 3627 | 3694 | ||
| 3628 | sk_X509_pop_free(*chain, X509_free); | 3695 | if (*chain) { |
| 3629 | *chain = NULL; | 3696 | sk_X509_pop_free(*chain, X509_free); |
| 3697 | *chain = NULL; | ||
| 3698 | } | ||
| 3630 | 3699 | ||
| 3631 | return 0; | 3700 | return 0; |
| 3632 | } /* xl__gc() */ | 3701 | } /* xl__gc() */ |
| @@ -3788,8 +3857,10 @@ static int xs_verify(lua_State *L) { | |||
| 3788 | static int xs__gc(lua_State *L) { | 3857 | static int xs__gc(lua_State *L) { |
| 3789 | X509_STORE **ud = luaL_checkudata(L, 1, X509_STORE_CLASS); | 3858 | X509_STORE **ud = luaL_checkudata(L, 1, X509_STORE_CLASS); |
| 3790 | 3859 | ||
| 3791 | X509_STORE_free(*ud); | 3860 | if (*ud) { |
| 3792 | *ud = NULL; | 3861 | X509_STORE_free(*ud); |
| 3862 | *ud = NULL; | ||
| 3863 | } | ||
| 3793 | 3864 | ||
| 3794 | return 0; | 3865 | return 0; |
| 3795 | } /* xs__gc() */ | 3866 | } /* xs__gc() */ |
| @@ -3857,8 +3928,10 @@ static int stx_add(lua_State *L) { | |||
| 3857 | static int stx__gc(lua_State *L) { | 3928 | static int stx__gc(lua_State *L) { |
| 3858 | X509_STORE **ud = luaL_checkudata(L, 1, X509_STORE_CLASS); | 3929 | X509_STORE **ud = luaL_checkudata(L, 1, X509_STORE_CLASS); |
| 3859 | 3930 | ||
| 3860 | X509_STORE_free(*ud); | 3931 | if (*ud) { |
| 3861 | *ud = NULL; | 3932 | X509_STORE_free(*ud); |
| 3933 | *ud = NULL; | ||
| 3934 | } | ||
| 3862 | 3935 | ||
| 3863 | return 0; | 3936 | return 0; |
| 3864 | } /* stx__gc() */ | 3937 | } /* stx__gc() */ |
| @@ -3975,8 +4048,10 @@ static int p12__tostring(lua_State *L) { | |||
| 3975 | static int p12__gc(lua_State *L) { | 4048 | static int p12__gc(lua_State *L) { |
| 3976 | PKCS12 **ud = luaL_checkudata(L, 1, PKCS12_CLASS); | 4049 | PKCS12 **ud = luaL_checkudata(L, 1, PKCS12_CLASS); |
| 3977 | 4050 | ||
| 3978 | PKCS12_free(*ud); | 4051 | if (*ud) { |
| 3979 | *ud = NULL; | 4052 | PKCS12_free(*ud); |
| 4053 | *ud = NULL; | ||
| 4054 | } | ||
| 3980 | 4055 | ||
| 3981 | return 0; | 4056 | return 0; |
| 3982 | } /* p12__gc() */ | 4057 | } /* p12__gc() */ |
| @@ -4153,6 +4228,11 @@ static int sx_setPrivateKey(lua_State *L) { | |||
| 4153 | /* | 4228 | /* |
| 4154 | * NOTE: No easy way to dup the key, but a shared reference should | 4229 | * NOTE: No easy way to dup the key, but a shared reference should |
| 4155 | * be okay as keys are less mutable than certificates. | 4230 | * be okay as keys are less mutable than certificates. |
| 4231 | * | ||
| 4232 | * FIXME: SSL_CTX_use_PrivateKey will return true even if the | ||
| 4233 | * EVP_PKEY object has no private key. Instead, we'll just get a | ||
| 4234 | * segfault during the SSL handshake. We need to check that a | ||
| 4235 | * private key is actually defined in the object. | ||
| 4156 | */ | 4236 | */ |
| 4157 | if (!SSL_CTX_use_PrivateKey(ctx, key)) | 4237 | if (!SSL_CTX_use_PrivateKey(ctx, key)) |
| 4158 | return throwssl(L, "ssl.context:setPrivateKey"); | 4238 | return throwssl(L, "ssl.context:setPrivateKey"); |
| @@ -4224,8 +4304,10 @@ static int sx_setEphemeralKey(lua_State *L) { | |||
| 4224 | static int sx__gc(lua_State *L) { | 4304 | static int sx__gc(lua_State *L) { |
| 4225 | SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS); | 4305 | SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS); |
| 4226 | 4306 | ||
| 4227 | SSL_CTX_free(*ud); | 4307 | if (*ud) { |
| 4228 | *ud = NULL; | 4308 | SSL_CTX_free(*ud); |
| 4309 | *ud = NULL; | ||
| 4310 | } | ||
| 4229 | 4311 | ||
| 4230 | return 0; | 4312 | return 0; |
| 4231 | } /* sx__gc() */ | 4313 | } /* sx__gc() */ |
| @@ -4446,8 +4528,10 @@ static int ssl_setHostName(lua_State *L) { | |||
| 4446 | static int ssl__gc(lua_State *L) { | 4528 | static int ssl__gc(lua_State *L) { |
| 4447 | SSL **ud = luaL_checkudata(L, 1, SSL_CLASS); | 4529 | SSL **ud = luaL_checkudata(L, 1, SSL_CLASS); |
| 4448 | 4530 | ||
| 4449 | SSL_free(*ud); | 4531 | if (*ud) { |
| 4450 | *ud = NULL; | 4532 | SSL_free(*ud); |
| 4533 | *ud = NULL; | ||
| 4534 | } | ||
| 4451 | 4535 | ||
| 4452 | return 0; | 4536 | return 0; |
| 4453 | } /* ssl__gc() */ | 4537 | } /* ssl__gc() */ |
