Blame doc/examples/ex-verify-ssh.c

Packit Service 4684c1
/* This example code is placed in the public domain. */
Packit Service 4684c1
Packit Service 4684c1
#ifdef HAVE_CONFIG_H
Packit Service 4684c1
#include <config.h>
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
#include <stdio.h>
Packit Service 4684c1
#include <stdlib.h>
Packit Service 4684c1
#include <string.h>
Packit Service 4684c1
#include <gnutls/gnutls.h>
Packit Service 4684c1
#include <gnutls/x509.h>
Packit Service 4684c1
#include <assert.h>
Packit Service 4684c1
#include "examples.h"
Packit Service 4684c1
Packit Service 4684c1
#define CHECK(x) assert((x)>=0)
Packit Service 4684c1
Packit Service 4684c1
/* This function will verify the peer's certificate, check
Packit Service 4684c1
 * if the hostname matches. In addition it will perform an
Packit Service 4684c1
 * SSH-style authentication, where ultimately trusted keys
Packit Service 4684c1
 * are only the keys that have been seen before.
Packit Service 4684c1
 */
Packit Service 4684c1
int _ssh_verify_certificate_callback(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
        unsigned int status;
Packit Service 4684c1
        const gnutls_datum_t *cert_list;
Packit Service 4684c1
        unsigned int cert_list_size;
Packit Service 4684c1
        int ret, type;
Packit Service 4684c1
        gnutls_datum_t out;
Packit Service 4684c1
        const char *hostname;
Packit Service 4684c1
Packit Service 4684c1
        /* read hostname */
Packit Service 4684c1
        hostname = gnutls_session_get_ptr(session);
Packit Service 4684c1
Packit Service 4684c1
        /* This verification function uses the trusted CAs in the credentials
Packit Service 4684c1
         * structure. So you must have installed one or more CA certificates.
Packit Service 4684c1
         */
Packit Service 4684c1
        CHECK(gnutls_certificate_verify_peers3(session, hostname, &status));
Packit Service 4684c1
Packit Service 4684c1
        type = gnutls_certificate_type_get(session);
Packit Service 4684c1
Packit Service 4684c1
        CHECK(gnutls_certificate_verification_status_print(status,
Packit Service 4684c1
                                                           type, &out, 0));
Packit Service 4684c1
        printf("%s", out.data);
Packit Service 4684c1
Packit Service 4684c1
        gnutls_free(out.data);
Packit Service 4684c1
Packit Service 4684c1
        if (status != 0)        /* Certificate is not trusted */
Packit Service 4684c1
                return GNUTLS_E_CERTIFICATE_ERROR;
Packit Service 4684c1
Packit Service 4684c1
        /* Do SSH verification */
Packit Service 4684c1
        cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
Packit Service 4684c1
        if (cert_list == NULL) {
Packit Service 4684c1
                printf("No certificate was found!\n");
Packit Service 4684c1
                return GNUTLS_E_CERTIFICATE_ERROR;
Packit Service 4684c1
        }
Packit Service 4684c1
Packit Service 4684c1
        /* service may be obtained alternatively using getservbyport() */
Packit Service 4684c1
        ret = gnutls_verify_stored_pubkey(NULL, NULL, hostname, "https",
Packit Service 4684c1
                                          type, &cert_list[0], 0);
Packit Service 4684c1
        if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND) {
Packit Service 4684c1
                printf("Host %s is not known.", hostname);
Packit Service 4684c1
                if (status == 0)
Packit Service 4684c1
                        printf("Its certificate is valid for %s.\n",
Packit Service 4684c1
                               hostname);
Packit Service 4684c1
Packit Service 4684c1
                /* the certificate must be printed and user must be asked on
Packit Service 4684c1
                 * whether it is trustworthy. --see gnutls_x509_crt_print() */
Packit Service 4684c1
Packit Service 4684c1
                /* if not trusted */
Packit Service 4684c1
                return GNUTLS_E_CERTIFICATE_ERROR;
Packit Service 4684c1
        } else if (ret == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
Packit Service 4684c1
                printf
Packit Service 4684c1
                    ("Warning: host %s is known but has another key associated.",
Packit Service 4684c1
                     hostname);
Packit Service 4684c1
                printf
Packit Service 4684c1
                    ("It might be that the server has multiple keys, or you are under attack\n");
Packit Service 4684c1
                if (status == 0)
Packit Service 4684c1
                        printf("Its certificate is valid for %s.\n",
Packit Service 4684c1
                               hostname);
Packit Service 4684c1
Packit Service 4684c1
                /* the certificate must be printed and user must be asked on
Packit Service 4684c1
                 * whether it is trustworthy. --see gnutls_x509_crt_print() */
Packit Service 4684c1
Packit Service 4684c1
                /* if not trusted */
Packit Service 4684c1
                return GNUTLS_E_CERTIFICATE_ERROR;
Packit Service 4684c1
        } else if (ret < 0) {
Packit Service 4684c1
                printf("gnutls_verify_stored_pubkey: %s\n",
Packit Service 4684c1
                       gnutls_strerror(ret));
Packit Service 4684c1
                return ret;
Packit Service 4684c1
        }
Packit Service 4684c1
Packit Service 4684c1
        /* user trusts the key -> store it */
Packit Service 4684c1
        if (ret != 0) {
Packit Service 4684c1
                CHECK(gnutls_store_pubkey(NULL, NULL, hostname, "https",
Packit Service 4684c1
                                          type, &cert_list[0], 0, 0));
Packit Service 4684c1
        }
Packit Service 4684c1
Packit Service 4684c1
        /* notify gnutls to continue handshake normally */
Packit Service 4684c1
        return 0;
Packit Service 4684c1
}