c++stringopensslsubject-alternative-name

How to extract ip address from subject_alt_name field from OpenSSL certificates using API(not openssl commands) in C


My requirement is to extract ip address from openSSL certificates using OpenSSL API functions(not openSSL primitive commands). I can use ASN1_STRING_data() to extract san field details, but how do i print the ip address from it.What is the data type of the ip address field

I am fetching common name and san field from certificates following the below code flow.I am able to fetch the common name, but having troubles with the SAN field

Using openssl api for C , was able to fetch the common name field but not the SAN ip field

common_name(X509* server_cert) 
{


   X509_NAME *subject_name = X509_get_subject_name((X509 *)server_cert);

int common_name_loc = X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);

  X509_NAME_ENTRY *common_name_entry = 
X509_NAME_get_entry(X509_get_subject_name((X509 *) server_cert), common_name_loc);

ASN1_STRING *common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);        

char *common_name_str = (char *) ASN1_STRING_data(common_name_asn1);
}



san_field(X509 *cert)
{

    STACK_OF(GENERAL_NAME) *san_names = NULL;
    // Try to extract the names within the SAN extension from the certificate
san_names = static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i((X509 *)cert, NID_subject_alt_name, NULL, NULL));

    san_names_nb = sk_GENERAL_NAME_num(san_names);
    // Check each name within the extension
    for (i=0; i<san_names_nb; i++) 
{
       const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);
    if (current_name->type == GEN_IPADD)
    {
    const char* ip_addrezz = reinterpret_cast<char*> 
        (ASN1_STRING_data(current_name->d.iPAddress));

        print ---------->ip_addrezz //issue here

    }
}   
}

How to extract SAN ip field from certificate
How to print the ip address extracted from SAN field of certificate/what is the data type of the ip field
Am i going in correct direction

Solution

  • As i recently also stumbled upon this and i would like to document the answer that suited best for me (i hope i got the point of this question right): RFC5280 - Subject Alternative Name states, that iPAddress is

    stored in the octet string in "network byte order"

    When the subjectAltName extension contains an iPAddress, the address
    MUST be stored in the octet string in "network byte order", as
    specified in [RFC791].  The least significant bit (LSB) of each octet
    is the LSB of the corresponding byte in the network address.  For IP
    version 4, as specified in [RFC791], the octet string MUST contain
    exactly four octets.  For IP version 6, as specified in
    [RFC2460], the octet string MUST contain exactly sixteen octets.
    

    Which in turn means, for an IPv4 address, you might use something like

    std::stringstream ip{};
    ip << (int)ip_addrezz[0] << '.' << (int)ip_addrezz[1] << '.' << (int)ip_addrezz[2] << '.' << (int)ip_addrezz[3]
    return ip.str();
    

    to print it.

    I also found this post really helpful (the code above is copied from there).