|
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 |
}
|