Skip to content

Instantly share code, notes, and snippets.

@Zensey
Created January 25, 2025 13:44
Show Gist options
  • Save Zensey/d3c2d7102c06a8ba5035a019646603d2 to your computer and use it in GitHub Desktop.
Save Zensey/d3c2d7102c06a8ba5035a019646603d2 to your computer and use it in GitHub Desktop.
Dump server certificate
#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