+ if (!session->sess || !user)
+ return;
+
+ unsigned int status;
+ const gnutls_datum_t* cert_list;
+ int ret;
+ unsigned int cert_list_size;
+ gnutls_x509_crt_t cert;
+ char name[MAXBUF];
+ unsigned char digest[MAXBUF];
+ size_t digest_size = sizeof(digest);
+ size_t name_size = sizeof(name);
+ ssl_cert* certinfo = new ssl_cert;
+
+ user->Extend("ssl_cert",certinfo);
+
+ /* This verification function uses the trusted CAs in the credentials
+ * structure. So you must have installed one or more CA certificates.
+ */
+ ret = gnutls_certificate_verify_peers2(session->sess, &status);
+
+ if (ret < 0)
+ {
+ certinfo->data.insert(std::make_pair("error",std::string(gnutls_strerror(ret))));
+ return;
+ }
+
+ if (status & GNUTLS_CERT_INVALID)
+ {
+ certinfo->data.insert(std::make_pair("invalid",ConvToStr(1)));
+ }
+ else
+ {
+ certinfo->data.insert(std::make_pair("invalid",ConvToStr(0)));
+ }
+ if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+ {
+ certinfo->data.insert(std::make_pair("unknownsigner",ConvToStr(1)));
+ }
+ else
+ {
+ certinfo->data.insert(std::make_pair("unknownsigner",ConvToStr(0)));
+ }
+ if (status & GNUTLS_CERT_REVOKED)
+ {
+ certinfo->data.insert(std::make_pair("revoked",ConvToStr(1)));
+ }
+ else
+ {
+ certinfo->data.insert(std::make_pair("revoked",ConvToStr(0)));
+ }
+ if (status & GNUTLS_CERT_SIGNER_NOT_CA)
+ {
+ certinfo->data.insert(std::make_pair("trusted",ConvToStr(0)));
+ }
+ else
+ {
+ certinfo->data.insert(std::make_pair("trusted",ConvToStr(1)));
+ }
+
+ /* Up to here the process is the same for X.509 certificates and
+ * OpenPGP keys. From now on X.509 certificates are assumed. This can
+ * be easily extended to work with openpgp keys as well.
+ */
+ if (gnutls_certificate_type_get(session->sess) != GNUTLS_CRT_X509)
+ {
+ certinfo->data.insert(std::make_pair("error","No X509 keys sent"));
+ return;
+ }
+
+ ret = gnutls_x509_crt_init(&cert);
+ if (ret < 0)
+ {
+ certinfo->data.insert(std::make_pair("error",gnutls_strerror(ret)));
+ return;
+ }
+
+ cert_list_size = 0;
+ cert_list = gnutls_certificate_get_peers(session->sess, &cert_list_size);
+ if (cert_list == NULL)
+ {
+ certinfo->data.insert(std::make_pair("error","No certificate was found"));
+ return;
+ }
+
+ /* This is not a real world example, since we only check the first
+ * certificate in the given chain.
+ */
+
+ ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
+ if (ret < 0)
+ {
+ certinfo->data.insert(std::make_pair("error",gnutls_strerror(ret)));
+ return;
+ }
+
+ gnutls_x509_crt_get_dn(cert, name, &name_size);
+
+ certinfo->data.insert(std::make_pair("dn",name));
+
+ gnutls_x509_crt_get_issuer_dn(cert, name, &name_size);
+
+ certinfo->data.insert(std::make_pair("issuer",name));
+
+ if ((ret = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, digest, &digest_size)) < 0)
+ {
+ certinfo->data.insert(std::make_pair("error",gnutls_strerror(ret)));
+ }
+ else
+ {
+ certinfo->data.insert(std::make_pair("fingerprint",irc::hex(digest, digest_size)));
+ }
+
+ /* Beware here we do not check for errors.
+ */
+ if ((gnutls_x509_crt_get_expiration_time(cert) < time(0)) || (gnutls_x509_crt_get_activation_time(cert) > time(0)))
+ {
+ certinfo->data.insert(std::make_pair("error","Not activated, or expired certificate"));
+ }
+
+ gnutls_x509_crt_deinit(cert);
+
+ return;