summaryrefslogtreecommitdiffstats
path: root/lib/auto-verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/auto-verify.c')
-rw-r--r--lib/auto-verify.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/lib/auto-verify.c b/lib/auto-verify.c
new file mode 100644
index 0000000..c9ec503
--- /dev/null
+++ b/lib/auto-verify.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ *
+ */
+
+#include "gnutls_int.h"
+#include "errors.h"
+#include <auth/cert.h>
+#include <gnutls/gnutls.h>
+
+/* This file implements the client certificate auto verification functionality.
+ */
+
+/* The actual verification callback. */
+static int auto_verify_cb(gnutls_session_t session)
+{
+ unsigned int status;
+ int ret;
+
+ if (session->internals.vc_elements == 0) {
+ ret = gnutls_certificate_verify_peers2(session, &status);
+ } else {
+ ret = gnutls_certificate_verify_peers(session, session->internals.vc_data,
+ session->internals.vc_elements, &status);
+ }
+ if (ret < 0) {
+ return gnutls_assert_val(GNUTLS_E_CERTIFICATE_ERROR);
+ }
+
+ session->internals.vc_status = status;
+
+ if (status != 0) /* Certificate is not trusted */
+ return gnutls_assert_val(GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR);
+
+ /* notify gnutls to continue handshake normally */
+ return 0;
+}
+
+/**
+ * gnutls_session_set_verify_cert:
+ * @session: is a gnutls session
+ * @hostname: is the expected name of the peer; may be %NULL
+ * @flags: flags for certificate verification -- #gnutls_certificate_verify_flags
+ *
+ * This function instructs GnuTLS to verify the peer's certificate
+ * using the provided hostname. If the verification fails the handshake
+ * will also fail with %GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR. In that
+ * case the verification result can be obtained using gnutls_session_get_verify_cert_status().
+ *
+ * The @hostname pointer provided must remain valid for the lifetime
+ * of the session. More precisely it should be available during any subsequent
+ * handshakes. If no hostname is provided, no hostname verification
+ * will be performed. For a more advanced verification function check
+ * gnutls_session_set_verify_cert2().
+ *
+ * If @flags is provided which contain a profile, this function should be
+ * called after any session priority setting functions.
+ *
+ * The gnutls_session_set_verify_cert() function is intended to be used by TLS
+ * clients to verify the server's certificate.
+ *
+ * Since: 3.4.6
+ **/
+void gnutls_session_set_verify_cert(gnutls_session_t session,
+ const char *hostname, unsigned flags)
+{
+ if (hostname) {
+ session->internals.vc_sdata.type = GNUTLS_DT_DNS_HOSTNAME;
+ session->internals.vc_sdata.data = (void*)hostname;
+ session->internals.vc_sdata.size = 0;
+ session->internals.vc_elements = 1;
+ session->internals.vc_data = &session->internals.vc_sdata;
+ } else {
+ session->internals.vc_elements = 0;
+ }
+
+ if (flags) {
+ ADD_PROFILE_VFLAGS(session, flags);
+ }
+
+ gnutls_session_set_verify_function(session, auto_verify_cb);
+}
+
+/**
+ * gnutls_session_set_verify_cert2:
+ * @session: is a gnutls session
+ * @data: an array of typed data
+ * @elements: the number of data elements
+ * @flags: flags for certificate verification -- #gnutls_certificate_verify_flags
+ *
+ * This function instructs GnuTLS to verify the peer's certificate
+ * using the provided typed data information. If the verification fails the handshake
+ * will also fail with %GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR. In that
+ * case the verification result can be obtained using gnutls_session_get_verify_cert_status().
+ *
+ * The acceptable typed data are the same as in gnutls_certificate_verify_peers(),
+ * and once set must remain valid for the lifetime of the session. More precisely
+ * they should be available during any subsequent handshakes.
+ *
+ * If @flags is provided which contain a profile, this function should be
+ * called after any session priority setting functions.
+ *
+ * Since: 3.4.6
+ **/
+void gnutls_session_set_verify_cert2(gnutls_session_t session,
+ gnutls_typed_vdata_st * data,
+ unsigned elements,
+ unsigned flags)
+{
+ session->internals.vc_data = data;
+ session->internals.vc_elements = elements;
+
+ if (flags)
+ session->internals.additional_verify_flags |= flags;
+
+ gnutls_session_set_verify_function(session, auto_verify_cb);
+}
+
+/**
+ * gnutls_session_get_verify_cert_status:
+ * @session: is a gnutls session
+ *
+ * This function returns the status of the verification when initiated
+ * via auto-verification, i.e., by gnutls_session_set_verify_cert2() or
+ * gnutls_session_set_verify_cert(). If no certificate verification
+ * was occurred then the return value would be set to ((unsigned int)-1).
+ *
+ * The certificate verification status is the same as in gnutls_certificate_verify_peers().
+ *
+ * Returns: the certificate verification status.
+ *
+ * Since: 3.4.6
+ **/
+unsigned int gnutls_session_get_verify_cert_status(gnutls_session_t session)
+{
+ return session->internals.vc_status;
+}