/** Imports a PEM-formatted X.509 certificate from the specified file. * @param filename Filename to import from. Format is PEM * * @return A newly allocated Certificate structure of the x509_gnutls scheme */ static PurpleCertificate * x509_import_from_file(const gchar * filename) { PurpleCertificate *crt; /* Certificate being constructed */ gchar *buf; /* Used to load the raw file data */ gsize buf_sz; /* Size of the above */ gnutls_datum_t dt; /* Struct to pass down to GnuTLS */ purple_debug_info("gnutls", "Attempting to load X.509 certificate from %s\n", filename); /* Next, we'll simply yank the entire contents of the file into memory */ /* TODO: Should I worry about very large files here? */ g_return_val_if_fail( g_file_get_contents(filename, &buf, &buf_sz, NULL /* No error checking for now */ ), NULL); /* Load the datum struct */ dt.data = (unsigned char *) buf; dt.size = buf_sz; /* Perform the conversion; files should be in PEM format */ crt = x509_import_from_datum(dt, GNUTLS_X509_FMT_PEM); /* Cleanup */ g_free(buf); return crt; }
static GList * ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc) { PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); PurpleCertificate *prvcrt = NULL; /* List of Certificate instances to return */ GList * peer_certs = NULL; /* List of raw certificates as given by GnuTLS */ const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0; unsigned int i; /* This should never, ever happen. */ g_return_val_if_fail( gnutls_certificate_type_get (gnutls_data->session) == GNUTLS_CRT_X509, NULL); /* Get the certificate list from GnuTLS */ /* TODO: I am _pretty sure_ this doesn't block or do other exciting things */ cert_list = gnutls_certificate_get_peers(gnutls_data->session, &cert_list_size); /* Convert each certificate to a Certificate and append it to the list */ for (i = 0; i < cert_list_size; i++) { PurpleCertificate * newcrt = x509_import_from_datum(cert_list[i], GNUTLS_X509_FMT_DER); /* Append is somewhat inefficient on linked lists, but is easy to read. If someone complains, I'll change it. TODO: Is anyone complaining? (Maybe elb?) */ /* only append if previous cert was actually signed by this one. * Thanks Microsoft. */ if ((prvcrt == NULL) || x509_certificate_signed_by(prvcrt, newcrt)) { peer_certs = g_list_append(peer_certs, newcrt); prvcrt = newcrt; } else { x509_destroy_certificate(newcrt); purple_debug_error("gnutls", "Dropping further peer certificates " "because the chain is broken!\n"); break; } } /* cert_list doesn't need free()-ing */ return peer_certs; }
/** Imports a number of PEM-formatted X.509 certificates from the specified file. * @param filename Filename to import from. Format is PEM * * @return A newly allocated GSList of Certificate structures of the x509_gnutls scheme */ static GSList * x509_importcerts_from_file(const gchar * filename) { PurpleCertificate *crt; /* Certificate being constructed */ gchar *buf; /* Used to load the raw file data */ gchar *begin, *end; GSList *crts = NULL; gsize buf_sz; /* Size of the above */ gnutls_datum_t dt; /* Struct to pass down to GnuTLS */ purple_debug_info("gnutls", "Attempting to load X.509 certificates from %s\n", filename); /* Next, we'll simply yank the entire contents of the file into memory */ /* TODO: Should I worry about very large files here? */ g_return_val_if_fail( g_file_get_contents(filename, &buf, &buf_sz, NULL /* No error checking for now */ ), NULL); begin = buf; while((end = strstr(begin, "-----END CERTIFICATE-----")) != NULL) { end += sizeof("-----END CERTIFICATE-----")-1; /* Load the datum struct */ dt.data = (unsigned char *) begin; dt.size = (end-begin); /* Perform the conversion; files should be in PEM format */ crt = x509_import_from_datum(dt, GNUTLS_X509_FMT_PEM); if (crt != NULL) { crts = g_slist_prepend(crts, crt); } begin = end; } /* Cleanup */ g_free(buf); return crts; }
static GList * ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc) { PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); /* List of Certificate instances to return */ GList * peer_certs = NULL; /* List of raw certificates as given by GnuTLS */ const gnutls_datum *cert_list; unsigned int cert_list_size = 0; unsigned int i; /* This should never, ever happen. */ g_return_val_if_fail( gnutls_certificate_type_get (gnutls_data->session) == GNUTLS_CRT_X509, NULL); /* Get the certificate list from GnuTLS */ /* TODO: I am _pretty sure_ this doesn't block or do other exciting things */ cert_list = gnutls_certificate_get_peers(gnutls_data->session, &cert_list_size); /* Convert each certificate to a Certificate and append it to the list */ for (i = 0; i < cert_list_size; i++) { PurpleCertificate * newcrt = x509_import_from_datum(cert_list[i], GNUTLS_X509_FMT_DER); /* Append is somewhat inefficient on linked lists, but is easy to read. If someone complains, I'll change it. TODO: Is anyone complaining? (Maybe elb?) */ peer_certs = g_list_append(peer_certs, newcrt); } /* cert_list doesn't need free()-ing */ return peer_certs; }