Codebase list sslscan / 2d68197
Update upstream source from tag 'upstream/2.0.15' Update to upstream version '2.0.15' with Debian dir 3d58e4098b8d8d337384db23aa146ca71230c68d Sophie Brun 1 year, 10 months ago
2 changed file(s) with 283 addition(s) and 281 deletion(s). Raw diff Collapse all Expand all
00 Changelog
11 =========
2 Version: 2.0.15
3 Date : 03/07/2022
4 Author : rbsec <[email protected]>
5 Changes: The following are a list of changes
6 > Obtain certificate info even if we can't connect properly
7
28 Version: 2.0.14
39 Date : 23/06/2022
410 Author : rbsec <[email protected]>
19841984 // Report certificate weaknesses (key length and signing algorithm)
19851985 int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)
19861986 {
1987 int cipherStatus = 0;
19881987 int status = true;
19891988 int socketDescriptor = 0;
19901989 int keyBits;
20422041 #endif
20432042
20442043 // Connect SSL over socket
2045 cipherStatus = SSL_connect(ssl);
2046 if (cipherStatus == 1)
2044 SSL_connect(ssl);
2045 // Setup BIO's
2046 if (!xml_to_stdout) {
2047 stdoutBIO = BIO_new(BIO_s_file());
2048 BIO_set_fp(stdoutBIO, stdout, BIO_NOCLOSE);
2049 }
2050 if (options->xmlOutput)
20472051 {
2048 // Setup BIO's
2049 if (!xml_to_stdout) {
2050 stdoutBIO = BIO_new(BIO_s_file());
2051 BIO_set_fp(stdoutBIO, stdout, BIO_NOCLOSE);
2052 }
2053 if (options->xmlOutput)
2054 {
2055 fileBIO = BIO_new(BIO_s_file());
2056 BIO_set_fp(fileBIO, options->xmlOutput, BIO_NOCLOSE);
2057 }
2058
2059 // Get Certificate...
2052 fileBIO = BIO_new(BIO_s_file());
2053 BIO_set_fp(fileBIO, options->xmlOutput, BIO_NOCLOSE);
2054 }
2055
2056 // Get Certificate...
2057 x509Cert = SSL_get_peer_certificate(ssl);
2058 if (x509Cert != NULL)
2059 {
20602060 printf("\n %sSSL Certificate:%s\n", COL_BLUE, RESET);
20612061 printf_xml(" <certificate type=\"short\">\n");
2062 x509Cert = SSL_get_peer_certificate(ssl);
2063 if (x509Cert != NULL)
2062 // Cert Serial No. - Code adapted from OpenSSL's crypto/asn1/t_x509.c
2063 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SERIAL))
20642064 {
2065 // Cert Serial No. - Code adapted from OpenSSL's crypto/asn1/t_x509.c
2066 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SERIAL))
2067 {
2068 BIO *bp;
2069 bp = BIO_new_fp(stdout, BIO_NOCLOSE);
2070 if (options->xmlOutput)
2065 BIO *bp;
2066 bp = BIO_new_fp(stdout, BIO_NOCLOSE);
2067 if (options->xmlOutput)
20712068
20722069 if(NULL != bp)
20732070 BIO_free(bp);
2074 // We don't free the xml_bp because it will be used in the future
2071 // We don't free the xml_bp because it will be used in the future
2072 }
2073
2074 // Signature Algo...
2075 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SIGNAME))
2076 {
2077 printf("Signature Algorithm: ");
2078 X509_get0_signature(NULL, &palg, x509Cert);
2079 X509_ALGOR_get0(&paobj, NULL, NULL, palg);
2080 OBJ_obj2txt(certAlgorithm, sizeof(certAlgorithm), paobj, 0);
2081 strtok(certAlgorithm, "\n");
2082 if (strstr(certAlgorithm, "md5") || strstr(certAlgorithm, "sha1"))
2083 {
2084 printf("%s%s%s\n", COL_RED, certAlgorithm, RESET);
20752085 }
2076
2077 // Signature Algo...
2078 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SIGNAME))
2086 else if (strstr(certAlgorithm, "sha512") || strstr(certAlgorithm, "sha256"))
20792087 {
2080 printf("Signature Algorithm: ");
2081 X509_get0_signature(NULL, &palg, x509Cert);
2082 X509_ALGOR_get0(&paobj, NULL, NULL, palg);
2083 OBJ_obj2txt(certAlgorithm, sizeof(certAlgorithm), paobj, 0);
2084 strtok(certAlgorithm, "\n");
2085 if (strstr(certAlgorithm, "md5") || strstr(certAlgorithm, "sha1"))
2088 printf("%s%s%s\n", COL_GREEN, certAlgorithm, RESET);
2089 }
2090 else
2091 {
2092 printf("%s\n", certAlgorithm);
2093 }
2094
2095 if (options->xmlOutput)
2096 {
2097 printf_xml(" <signature-algorithm>%s</signature-algorithm>\n", certAlgorithm);
2098 }
2099 }
2100
2101 // Public Key...
2102 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_PUBKEY))
2103 {
2104 publicKey = X509_get_pubkey(x509Cert);
2105 if (publicKey == NULL)
2106 {
2107 printf("Public Key: Could not load\n");
2108 printf_xml(" <pk error=\"true\" />\n");
2109 }
2110 else
2111 {
2112 keyBits=EVP_PKEY_bits(publicKey);
2113 switch (EVP_PKEY_id(publicKey))
20862114 {
2087 printf("%s%s%s\n", COL_RED, certAlgorithm, RESET);
2088 }
2089 else if (strstr(certAlgorithm, "sha512") || strstr(certAlgorithm, "sha256"))
2090 {
2091 printf("%s%s%s\n", COL_GREEN, certAlgorithm, RESET);
2092 }
2093 else
2094 {
2095 printf("%s\n", certAlgorithm);
2096 }
2097
2098 if (options->xmlOutput)
2099 {
2100 printf_xml(" <signature-algorithm>%s</signature-algorithm>\n", certAlgorithm);
2101 }
2102 }
2103
2104 // Public Key...
2105 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_PUBKEY))
2106 {
2107 publicKey = X509_get_pubkey(x509Cert);
2108 if (publicKey == NULL)
2109 {
2110 printf("Public Key: Could not load\n");
2111 printf_xml(" <pk error=\"true\" />\n");
2112 }
2113 else
2114 {
2115 keyBits=EVP_PKEY_bits(publicKey);
2116 switch (EVP_PKEY_id(publicKey))
2117 {
2118 case EVP_PKEY_RSA:
2119 if (EVP_PKEY_get1_RSA(publicKey)!=NULL)
2115 case EVP_PKEY_RSA:
2116 if (EVP_PKEY_get1_RSA(publicKey)!=NULL)
2117 {
2118 if (keyBits < 2048 )
21202119 {
2121 if (keyBits < 2048 )
2122 {
2123 printf("RSA Key Strength: %s%d%s\n", COL_RED, keyBits, RESET);
2124 }
2125 else if (keyBits >= 3072 )
2126 {
2127 printf("RSA Key Strength: %s%d%s\n", COL_GREEN, keyBits, RESET);
2128 }
2129 else
2130 {
2131 printf("RSA Key Strength: %d\n", keyBits);
2132 }
2133
2134 printf_xml(" <pk error=\"false\" type=\"RSA\" bits=\"%d\" />\n", keyBits);
2120 printf("RSA Key Strength: %s%d%s\n", COL_RED, keyBits, RESET);
2121 }
2122 else if (keyBits >= 3072 )
2123 {
2124 printf("RSA Key Strength: %s%d%s\n", COL_GREEN, keyBits, RESET);
21352125 }
21362126 else
21372127 {
2138 printf(" RSA Public Key: NULL\n");
2128 printf("RSA Key Strength: %d\n", keyBits);
21392129 }
2140 printf("\n");
2141 break;
2142 case EVP_PKEY_DSA:
2143 if (EVP_PKEY_get1_DSA(publicKey)!=NULL)
2130
2131 printf_xml(" <pk error=\"false\" type=\"RSA\" bits=\"%d\" />\n", keyBits);
2132 }
2133 else
2134 {
2135 printf(" RSA Public Key: NULL\n");
2136 }
2137 printf("\n");
2138 break;
2139 case EVP_PKEY_DSA:
2140 if (EVP_PKEY_get1_DSA(publicKey)!=NULL)
2141 {
2142 // TODO - display key strength
2143 printf_xml(" <pk error=\"false\" type=\"DSA\" />\n");
2144 /* DSA_print(stdoutBIO, publicKey->pkey.dsa, 6); */
2145 }
2146 else
2147 {
2148 printf(" DSA Public Key: NULL\n");
2149 }
2150 break;
2151 case EVP_PKEY_EC:
2152 {
2153 EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(publicKey);
2154 if (ec_key != NULL)
21442155 {
2145 // TODO - display key strength
2146 printf_xml(" <pk error=\"false\" type=\"DSA\" />\n");
2147 /* DSA_print(stdoutBIO, publicKey->pkey.dsa, 6); */
2148 }
2149 else
2150 {
2151 printf(" DSA Public Key: NULL\n");
2152 }
2153 break;
2154 case EVP_PKEY_EC:
2155 {
2156 EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(publicKey);
2157 if (ec_key != NULL)
2158 {
21592156 // We divide by two to get the symmetric key strength equivalent; this
21602157 // ensures consistency with the Server Key Exchange Group section.
21612158 int keyBits = EVP_PKEY_bits(publicKey) / 2;
21642161
21652162
21662163 if (keyBits < 112)
2167 color = COL_RED;
2164 color = COL_RED;
21682165 else if (keyBits < 128)
2169 color = COL_YELLOW;
2166 color = COL_YELLOW;
21702167
21712168 printf("ECC Curve Name: %s\n", ec_group_name);
21722169 printf("ECC Key Strength: %s%d%s\n\n", color, keyBits, RESET);
21732170 printf_xml(" <pk error=\"false\" type=\"EC\" curve_name=\"%s\" bits=\"%d\" />\n", ec_group_name, keyBits);
21742171 EC_KEY_free(ec_key); ec_key = NULL;
2175 }
2176 else
2172 }
2173 else
21772174 printf(" EC Public Key: NULL\n");
2178 }
2179 break;
2180 default:
2181 printf(" Public Key: Unknown\n");
2182 printf_xml(" <pk error=\"true\" type=\"unknown\" />\n");
2183 break;
2175 }
2176 break;
2177 default:
2178 printf(" Public Key: Unknown\n");
2179 printf_xml(" <pk error=\"true\" type=\"unknown\" />\n");
2180 break;
2181 }
2182
2183 EVP_PKEY_free(publicKey);
2184 }
2185 }
2186
2187 // SSL Certificate Issuer...
2188 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_ISSUER))
2189 {
2190 int cnindex;
2191 X509_NAME *subj;
2192 X509_NAME_ENTRY *e;
2193 ASN1_STRING *d;
2194 const char *subject;
2195 const char *issuer;
2196
2197 // Get SSL cert CN
2198 cnindex = -1;
2199 subj = X509_get_subject_name(x509Cert);
2200 cnindex = X509_NAME_get_index_by_NID(subj, NID_commonName, cnindex);
2201
2202 // SSL cert doesn't have a CN, so just print whole thing
2203 if (cnindex == -1)
2204 {
2205 subject = (char *) X509_NAME_oneline(X509_get_subject_name(x509Cert), NULL, 0);
2206 printf("Subject: %s\n", subject);
2207 printf_xml(" <subject><![CDATA[%s]]></subject>\n", subject);
2208
2209 }
2210 else
2211 {
2212 e = X509_NAME_get_entry(subj, cnindex);
2213 d = X509_NAME_ENTRY_get_data(e);
2214 subject = (char *) ASN1_STRING_data(d);
2215 printf("Subject: %s\n", subject);
2216 printf_xml(" <subject><![CDATA[%s]]></subject>\n", subject);
2217 }
2218
2219 // Get certificate altnames if supported
2220 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_EXTENSIONS))
2221 {
2222 if (sk_X509_EXTENSION_num(X509_get0_extensions(x509Cert)) > 0)
2223 {
2224 cnindex = X509_get_ext_by_NID (x509Cert, NID_subject_alt_name, -1);
2225 if (cnindex != -1)
2226 {
2227 extension = X509v3_get_ext(X509_get0_extensions(x509Cert),cnindex);
2228
2229 printf("Altnames: ");
2230 if (!X509V3_EXT_print(stdoutBIO, extension, X509_FLAG_COMPAT, 0))
2231 {
2232 ASN1_STRING_print(stdoutBIO, X509_EXTENSION_get_data(extension));
2233 }
2234 if (options->xmlOutput)
2235 {
2236 printf_xml(" <altnames><![CDATA[");
2237 if (!X509V3_EXT_print(fileBIO, extension, X509_FLAG_COMPAT, 0))
2238 ASN1_STRING_print(fileBIO, X509_EXTENSION_get_data(extension));
2239 }
2240 printf_xml("]]></altnames>\n");
2241 printf("\n");
21842242 }
2185
2186 EVP_PKEY_free(publicKey);
21872243 }
21882244 }
21892245
2190 // SSL Certificate Issuer...
2191 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_ISSUER))
2246 // Get SSL cert issuer
2247 cnindex = -1;
2248 subj = X509_get_issuer_name(x509Cert);
2249 cnindex = X509_NAME_get_index_by_NID(subj, NID_commonName, cnindex);
2250
2251 // Issuer cert doesn't have a CN, so just print whole thing
2252 if (cnindex == -1)
21922253 {
2193 int cnindex;
2194 X509_NAME *subj;
2195 X509_NAME_ENTRY *e;
2196 ASN1_STRING *d;
2197 const char *subject;
2198 const char *issuer;
2199
2200 // Get SSL cert CN
2201 cnindex = -1;
2202 subj = X509_get_subject_name(x509Cert);
2203 cnindex = X509_NAME_get_index_by_NID(subj, NID_commonName, cnindex);
2204
2205 // SSL cert doesn't have a CN, so just print whole thing
2206 if (cnindex == -1)
2254 char *issuer = X509_NAME_oneline(X509_get_issuer_name(x509Cert), NULL, 0);
2255 char *color = "";
2256 int self_signed = 0;
2257
2258 if ((subject != NULL) && (strcmp(subject, issuer) == 0)) {
2259 color = COL_RED;
2260 self_signed = 1;
2261 }
2262 printf("%sIssuer: %s%s", color, issuer, RESET);
2263 printf_xml(" <issuer><![CDATA[%s]]></issuer>\n", issuer);
2264
2265 if (self_signed) {
2266 printf_xml(" <self-signed>true</self-signed>\n");
2267 }
2268 else {
2269 printf_xml(" <self-signed>false</self-signed>\n");
2270 }
2271 }
2272 else
2273 {
2274 e = X509_NAME_get_entry(subj, cnindex);
2275 d = X509_NAME_ENTRY_get_data(e);
2276 issuer = (char *) ASN1_STRING_data(d);
2277
2278 // If issuer is same as hostname we scanned or is *, flag as self-signed
2279 if (
2280 strcmp(issuer, options->host) == 0
2281 || strcmp(issuer, subject) == 0
2282 || strcmp(issuer, "*") == 0
2283 )
22072284 {
2208 subject = (char *) X509_NAME_oneline(X509_get_subject_name(x509Cert), NULL, 0);
2209 printf("Subject: %s\n", subject);
2210 printf_xml(" <subject><![CDATA[%s]]></subject>\n", subject);
2285 printf("Issuer: %s%s%s\n", COL_RED, issuer, RESET);
2286 printf_xml(" <issuer><![CDATA[%s]]></issuer>\n", issuer);
2287 printf_xml(" <self-signed>true</self-signed>\n");
22112288
22122289 }
22132290 else
22142291 {
2215 e = X509_NAME_get_entry(subj, cnindex);
2216 d = X509_NAME_ENTRY_get_data(e);
2217 subject = (char *) ASN1_STRING_data(d);
2218 printf("Subject: %s\n", subject);
2219 printf_xml(" <subject><![CDATA[%s]]></subject>\n", subject);
2220 }
2221
2222 // Get certificate altnames if supported
2223 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_EXTENSIONS))
2224 {
2225 if (sk_X509_EXTENSION_num(X509_get0_extensions(x509Cert)) > 0)
2226 {
2227 cnindex = X509_get_ext_by_NID (x509Cert, NID_subject_alt_name, -1);
2228 if (cnindex != -1)
2229 {
2230 extension = X509v3_get_ext(X509_get0_extensions(x509Cert),cnindex);
2231
2232 printf("Altnames: ");
2233 if (!X509V3_EXT_print(stdoutBIO, extension, X509_FLAG_COMPAT, 0))
2234 {
2235 ASN1_STRING_print(stdoutBIO, X509_EXTENSION_get_data(extension));
2236 }
2237 if (options->xmlOutput)
2238 {
2239 printf_xml(" <altnames><![CDATA[");
2240 if (!X509V3_EXT_print(fileBIO, extension, X509_FLAG_COMPAT, 0))
2241 ASN1_STRING_print(fileBIO, X509_EXTENSION_get_data(extension));
2242 }
2243 printf_xml("]]></altnames>\n");
2244 printf("\n");
2245 }
2246 }
2247 }
2248
2249 // Get SSL cert issuer
2250 cnindex = -1;
2251 subj = X509_get_issuer_name(x509Cert);
2252 cnindex = X509_NAME_get_index_by_NID(subj, NID_commonName, cnindex);
2253
2254 // Issuer cert doesn't have a CN, so just print whole thing
2255 if (cnindex == -1)
2256 {
2257 char *issuer = X509_NAME_oneline(X509_get_issuer_name(x509Cert), NULL, 0);
2258 char *color = "";
2259 int self_signed = 0;
2260
2261 if ((subject != NULL) && (strcmp(subject, issuer) == 0)) {
2262 color = COL_RED;
2263 self_signed = 1;
2264 }
2265 printf("%sIssuer: %s%s", color, issuer, RESET);
2292 printf("Issuer: %s\n", issuer);
22662293 printf_xml(" <issuer><![CDATA[%s]]></issuer>\n", issuer);
2267
2268 if (self_signed) {
2269 printf_xml(" <self-signed>true</self-signed>\n");
2270 }
2271 else {
2272 printf_xml(" <self-signed>false</self-signed>\n");
2273 }
2274 }
2275 else
2276 {
2277 e = X509_NAME_get_entry(subj, cnindex);
2278 d = X509_NAME_ENTRY_get_data(e);
2279 issuer = (char *) ASN1_STRING_data(d);
2280
2281 // If issuer is same as hostname we scanned or is *, flag as self-signed
2282 if (
2283 strcmp(issuer, options->host) == 0
2284 || strcmp(issuer, subject) == 0
2285 || strcmp(issuer, "*") == 0
2286 )
2287 {
2288 printf("Issuer: %s%s%s\n", COL_RED, issuer, RESET);
2289 printf_xml(" <issuer><![CDATA[%s]]></issuer>\n", issuer);
2290 printf_xml(" <self-signed>true</self-signed>\n");
2291
2292 }
2293 else
2294 {
2295 printf("Issuer: %s\n", issuer);
2296 printf_xml(" <issuer><![CDATA[%s]]></issuer>\n", issuer);
2297 printf_xml(" <self-signed>false</self-signed>\n");
2298 }
2294 printf_xml(" <self-signed>false</self-signed>\n");
22992295 }
23002296 }
2301
2302 // Check for certificate expiration
2303 time_t *ptime;
2304 int timediff;
2305 ptime = NULL;
2306
2307 printf("\nNot valid before: ");
2308 timediff = X509_cmp_time(X509_get_notBefore(x509Cert), ptime);
2309 // Certificate isn't valid yet
2297 }
2298
2299 // Check for certificate expiration
2300 time_t *ptime;
2301 int timediff;
2302 ptime = NULL;
2303
2304 printf("\nNot valid before: ");
2305 timediff = X509_cmp_time(X509_get_notBefore(x509Cert), ptime);
2306 // Certificate isn't valid yet
2307 if (timediff > 0)
2308 {
2309 printf("%s", COL_RED);
2310 }
2311 else
2312 {
2313 printf("%s", COL_GREEN);
2314 }
2315 ASN1_TIME_print(stdoutBIO, X509_get_notBefore(x509Cert));
2316 printf("%s", RESET);
2317
2318 if (options->xmlOutput) {
2319 printf_xml(" <not-valid-before>");
2320 ASN1_TIME_print(fileBIO, X509_get_notBefore(x509Cert));
2321 printf_xml("</not-valid-before>\n");
23102322 if (timediff > 0)
23112323 {
2312 printf("%s", COL_RED);
2324 printf_xml(" <not-yet-valid>true</not-yet-valid>\n");
23132325 }
23142326 else
23152327 {
2316 printf("%s", COL_GREEN);
2328 printf_xml(" <not-yet-valid>false</not-yet-valid>\n");
23172329 }
2318 ASN1_TIME_print(stdoutBIO, X509_get_notBefore(x509Cert));
2319 printf("%s", RESET);
2320
2321 if (options->xmlOutput) {
2322 printf_xml(" <not-valid-before>");
2323 ASN1_TIME_print(fileBIO, X509_get_notBefore(x509Cert));
2324 printf_xml("</not-valid-before>\n");
2325 if (timediff > 0)
2326 {
2327 printf_xml(" <not-yet-valid>true</not-yet-valid>\n");
2328 }
2329 else
2330 {
2331 printf_xml(" <not-yet-valid>false</not-yet-valid>\n");
2332 }
2333 }
2334
2335 printf("\nNot valid after: ");
2336 timediff = X509_cmp_time(X509_get_notAfter(x509Cert), ptime);
2337 // Certificate has expired
2330 }
2331
2332 printf("\nNot valid after: ");
2333 timediff = X509_cmp_time(X509_get_notAfter(x509Cert), ptime);
2334 // Certificate has expired
2335 if (timediff < 0)
2336 {
2337 printf("%s", COL_RED);
2338 }
2339 else
2340 {
2341 printf("%s", COL_GREEN);
2342 }
2343 ASN1_TIME_print(stdoutBIO, X509_get_notAfter(x509Cert));
2344 printf("%s", RESET);
2345 if (options->xmlOutput) {
2346 printf_xml(" <not-valid-after>");
2347 ASN1_TIME_print(fileBIO, X509_get_notAfter(x509Cert));
2348 printf_xml("</not-valid-after>\n");
23382349 if (timediff < 0)
23392350 {
2340 printf("%s", COL_RED);
2351 printf_xml(" <expired>true</expired>\n");
23412352 }
23422353 else
23432354 {
2344 printf("%s", COL_GREEN);
2355 printf_xml(" <expired>false</expired>\n");
23452356 }
2346 ASN1_TIME_print(stdoutBIO, X509_get_notAfter(x509Cert));
2347 printf("%s", RESET);
2348 if (options->xmlOutput) {
2349 printf_xml(" <not-valid-after>");
2350 ASN1_TIME_print(fileBIO, X509_get_notAfter(x509Cert));
2351 printf_xml("</not-valid-after>\n");
2352 if (timediff < 0)
2353 {
2354 printf_xml(" <expired>true</expired>\n");
2355 }
2356 else
2357 {
2358 printf_xml(" <expired>false</expired>\n");
2359 }
2360 }
2361 printf("\n");
2362
2363 // Free X509 Certificate...
2364 X509_free(x509Cert);
2365 // This is abusing status a bit, but means that we'll only get the cert once
2366 status = false;
23672357 }
2368
2369 else {
2370 printf(" Unable to parse certificate\n");
2371 }
2372
2373 printf_xml(" </certificate>\n");
2374
2375 // Free BIO
2376 BIO_free(stdoutBIO);
2377 if (options->xmlOutput)
2378 BIO_free(fileBIO);
2379
2380 // Disconnect SSL over socket
2381 SSL_shutdown(ssl);
2358 printf("\n");
2359
2360 // Free X509 Certificate...
2361 X509_free(x509Cert);
2362 // This is abusing status a bit, but means that we'll only get the cert once
2363 status = false;
23822364 }
2365
2366 else {
2367 printf(" Unable to parse certificate\n");
2368 }
2369
2370 printf_xml(" </certificate>\n");
2371
2372 // Free BIO
2373 BIO_free(stdoutBIO);
2374 if (options->xmlOutput)
2375 BIO_free(fileBIO);
2376
2377 // Disconnect SSL over socket
2378 SSL_shutdown(ssl);
23832379 // Free SSL object
23842380 FREE_SSL(ssl);
23852381 }