Created
January 25, 2025 13:44
-
-
Save Zensey/d3c2d7102c06a8ba5035a019646603d2 to your computer and use it in GitHub Desktop.
Dump server certificate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/socket.h> | |
#include <arpa/inet.h> | |
#include <unistd.h> | |
#include <cstring> | |
#include <iostream> | |
#include <openssl/x509.h> | |
#include <openssl/ssl.h> | |
#include<errno.h> //For errno - the error number | |
#include<netdb.h> //hostent | |
// For details see https://zakird.com/2013/10/13/certificate-parsing-with-openssl | |
#define MAX_LENGTH 1024 | |
void print_certificate(X509* cert) { | |
char subj[MAX_LENGTH+1]; | |
char issuer[MAX_LENGTH+1]; | |
X509_NAME_oneline(X509_get_subject_name(cert), subj, MAX_LENGTH); | |
X509_NAME_oneline(X509_get_issuer_name(cert), issuer, MAX_LENGTH); | |
printf("certificate: %s\n", subj); | |
printf("\tissuer: %s\n\n", issuer); | |
} | |
void print_stack(STACK_OF(X509)* sk) | |
{ | |
unsigned len = sk_X509_num(sk); | |
printf("Begin Certificate Stack:\n"); | |
for(unsigned i=0; i<len; i++) { | |
X509 *cert = sk_X509_value(sk, i); | |
print_certificate(cert); | |
} | |
printf("End Certificate Stack\n"); | |
} | |
int hostname_to_ip(char * hostname , char* ip) | |
{ | |
struct hostent *he; | |
struct in_addr **addr_list; | |
if ( (he = gethostbyname( hostname ) ) == NULL) | |
{ | |
return -1; | |
} | |
addr_list = (struct in_addr **) he->h_addr_list; | |
int i; | |
for(i = 0; addr_list[i] != NULL; i++) | |
{ | |
//Return the first one; | |
strcpy(ip , inet_ntoa(*addr_list[i]) ); | |
return 0; | |
} | |
return -1; | |
} | |
int main(int argc, char **argv) | |
{ | |
SSLeay_add_ssl_algorithms(); | |
SSL_load_error_strings(); | |
SSL_CTX* ctx = SSL_CTX_new (SSLv23_method()); | |
if (ctx == NULL) { | |
std::cout << "Ошибка SSL_CTX_new" << std::endl; | |
return -1; | |
} | |
char *hostname = (char *)"ya.ru"; | |
char ip[100]; | |
int err = hostname_to_ip(hostname , ip); | |
if (err < 0) { | |
std::cout << "Ошибка DNS" << std::endl; | |
return err; | |
} | |
std::cout << hostname << " resolved to " << ip << std::endl; | |
int sd = ::socket (AF_INET, SOCK_STREAM, 0); //create socket | |
if (sd < 0 || ctx == NULL) { | |
std::cout << "Ошибка сокета. " << err << std::endl; | |
return err; | |
} | |
struct sockaddr_in sa; | |
memset (&sa, '\0', sizeof(sa)); | |
sa.sin_family = AF_INET; | |
sa.sin_addr.s_addr = inet_addr (ip); /* Server IP */ | |
sa.sin_port = htons (443); /* Server Port number */ | |
err = ::connect(sd, (struct sockaddr*) &sa, sizeof(sa)); | |
if (err < 0) { | |
std::cout << "Ошибка запроса" << std::endl; | |
return err; | |
} | |
SSL* ssl = SSL_new (ctx); | |
if (ssl == NULL) { | |
std::cout << "Ошибка SSL_new" << std::endl; | |
return -1; | |
} | |
SSL_set_fd(ssl, sd); | |
err = SSL_connect(ssl); | |
if (err < 0) { | |
std::cout << "Ошибка SSL_connect" << std::endl; | |
return err; | |
} | |
X509* server_cert = SSL_get_peer_certificate(ssl); | |
if (server_cert == NULL) { | |
std::cout << "Ошибка SSL_get_peer_certificate" << std::endl; | |
return -1; | |
} | |
STACK_OF(X509) *sk = sk_X509_new_null(); | |
sk_X509_push(sk, server_cert); | |
//print_certificate(server_cert); | |
print_stack(sk); | |
BIO * bio_out = BIO_new_file("./output.pem", "w"); | |
if (bio_out) | |
{ | |
//X509_print(bio_out, server_cert); //parsed | |
if (PEM_write_bio_X509(bio_out, server_cert)) { | |
std::cout << "Сертификат записан" << std::endl; | |
} | |
BIO_free(bio_out); | |
} | |
X509_free (server_cert); | |
SSL_free (ssl); | |
::close (sd); //close socket | |
SSL_CTX_free (ctx); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment