]],[[]])
AC_CONFIG_FILES([Makefile src/Makefile lib/Makefile lib/libgnutls-config \
-lib/gnutls.h doc/Makefile src/x509/Makefile src/srp/Makefile ])
+lib/gnutls.h doc/Makefile src/x509/Makefile src/srp/Makefile doc/tex/Makefile])
AC_OUTPUT
+++ /dev/null
-<html>
-<body>
-
-<a name="introduction"> </a>
-<h2>Introduction</h2>
-
-<p>
-gnuTLS is a library which implements the <B>TLS 1.0</b> and <b>SSL 3.0</b> protocols.
-TLS stands for 'Transport Layer Security' and is the sucessor of SSL (Secure Sockets Layer).
-<b>TLS 1.0</b> is described is <i>RFC 2246</i> and is an Internet protocol (thus it's mostly used over TCP/IP),
-that provides confidentiality, and authentication layers.
-</p>
-
-<p>
-Confidentiality is provided by using symmetric encryption algorithms like <b>3DES</b>, <b>AES</b>, or
-stream algorithms like <b>ARCFOUR</b>. A symmetric encryption algorithm uses a single (secret) key
-to encrypt and decrypt data.
-</p>
-
-<p>
-The following authentication schemas are supported in gnuTLS:
-<ul>
-<li>x509 Public Key Infrastructure</li>
-<li>Anonymous authentication</li>
-<li>SRP authentication</li>
-</ul>
-
-</p>
-
-<a name="x509_client_example"> </a>
-<h2>x509 Client example</h2>
-
-<p>
-Let's assume now that we want to create a client which communicates
-with servers using the x509 authentication schema. The following client
-is a very simple TLS client, it does not support session resuming nor
-anything other fancy features.
-
-<xmp>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <gnutls.h>
-
-#define MAX_BUF 1024
-#define CRLFILE "crl.pem"
-#define CAFILE "ca.pem"
-#define SA struct sockaddr
-#define MSG "GET / HTTP/1.0\r\n\r\n"
-
-int main()
-{
- const char* PORT = "443";
- const char* SERVER = "127.0.0.1";
- int err, ret;
- int sd, ii;
- struct sockaddr_in sa;
- GNUTLS_STATE state;
- char buffer[MAX_BUF+1];
- X509PKI_CLIENT_CREDENTIALS xcred;
-
- if (gnutls_global_init() < 0) {
- fprintf(stderr, "global state initialization error\n");
- exit(1);
- }
-
-
- /* X509 stuff */
- if (gnutls_allocate_x509_client_sc( &xcred, 0) < 0) { /* no client private key */
- fprintf(stderr, "memory error\n");
- exit(1);
- }
-
- /* set's the trusted cas file
- */
- gnutls_set_x509_client_trust( xcred, CAFILE, CRLFILE);
-
- /* connects to server
- */
- sd = socket(AF_INET, SOCK_STREAM, 0);
-
- memset(&sa, '\0', sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_port = htons(atoi(PORT));
- inet_pton( AF_INET, SERVER, &sa.sin_addr);
-
- err = connect(sd, (SA *) & sa, sizeof(sa));
-
- /* Initiate TLS state
- */
- gnutls_init(&state, GNUTLS_CLIENT);
-
- /* allow both SSL3 and TLS1
- */
- gnutls_set_protocol_priority( state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
-
- /* allow only ARCFOUR and 3DES ciphers
- * (3DES has the highest priority)
- */
- gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, 0);
-
- /* only allow null compression
- */
- gnutls_set_compression_priority( state, GNUTLS_NULL_COMPRESSION, 0);
-
- /* use GNUTLS_KX_RSA
- */
- gnutls_set_kx_priority( state, GNUTLS_KX_RSA, 0);
-
- /* allow the usage of both SHA and MD5
- */
- gnutls_set_mac_priority( state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0);
-
-
- /* put the x509 credentials to the current state
- */
- gnutls_set_cred( state, GNUTLS_X509PKI, xcred);
-
- /* This should be the CN in the server's
- * certificate.
- */
- gnutls_x509_set_cn( state, "www.host.com");
-
-
- /* Perform the TLS handshake
- */
- ret = gnutls_handshake(sd, state);
-
- if (ret < 0) {
- fprintf(stderr, "*** Handshake failed\n");
- gnutls_perror(ret);
- goto end;
- } else {
- printf("- Handshake was completed\n");
- }
-
- gnutls_write( sd, state, MSG, strlen(MSG));
-
- ret = gnutls_read(sd, state, buffer, MAX_BUF);
- if (gnutls_is_fatal_error(ret) == 1 || ret==0) {
- if (ret == 0) {
- printf("- Peer has closed the GNUTLS connection\n");
- goto end;
- } else {
- fprintf(stderr, "*** Received corrupted data(%d) - server has terminated the connection abnormally\n",
- ret);
- goto end;
- }
- } else {
- if (ret==GNUTLS_E_WARNING_ALERT_RECEIVED || ret==GNUTLS_E_FATAL_ALERT_RECEIVED)
- printf("* Received alert [%d]\n", gnutls_get_last_alert(state));
- if (ret==GNUTLS_E_GOT_HELLO_REQUEST)
- printf("* Received HelloRequest message (server asked to rehandshake)\n");
- }
-
- if (ret > 0) {
- printf("- Received %d bytes: ", ret);
- for (ii=0;ii<ret;ii++) {
- fputc(buffer[ii], stdout);
- }
- fputs("\n", stdout);
- }
-
-
- gnutls_bye(sd, state, 0);
-
- end:
-
- shutdown( sd, SHUT_RDWR); /* no more receptions */
- close(sd);
-
- gnutls_deinit( state);
-
- gnutls_free_x509_client_sc( xcred);
-
- gnutls_global_deinit();
-
- return 0;
-}
-
-
-</xmp>
-
-</p>
-
-
-<a name="functions"> </a>
-<h2>Function reference</h2>
-
-<p>
-All functions return >=0 if everything is ok, or a negative value in case
-of a failure. Failure is not always fatal.
-</p>
-
-EXTRA_DIST = TODO gnutls-api.html ASN1.readme.txt
+EXTRA_DIST = TODO ASN1.readme.txt
+SUBDIRS = tex
-gnutls-api: gnutls-api.html
-gnutls-api.html: API-template.html
- @cat API-template.html > gnutls-api.html
- @scripts/gdoc -html ../lib/*.c >> gnutls-api.html
- @echo "</body></html>" >> gnutls-api.html
$type_param, "<tt><b>\$1</b></tt>" );
$blankline_html = "<p>";
+%highlights_tex = ( $type_constant, "{\\it \$1}",
+ $type_func, "{\\bf \$1}",
+ $type_struct, "{\\it \$1}",
+ $type_param, "{\\bf \$1}" );
+$blankline_tex = "\\par";
+
# sgml, docbook format
%highlights_sgml = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
$type_func, "<function>\$1</function>",
sub usage {
- print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
+ print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -tex ]\n";
print " [ -function funcname [ -function funcname ...] ]\n";
print " c source file(s) > outputfile\n";
exit 1;
$output_mode = "man";
%highlights = %highlights_man;
$blankline = $blankline_man;
+ } elsif ($cmd eq "-tex") {
+ $output_mode = "tex";
+ %highlights = %highlights_tex;
+ $blankline = $blankline_tex;
} elsif ($cmd eq "-text") {
$output_mode = "text";
%highlights = %highlights_text;
print "<hr>\n";
}
+# output in tex
+sub output_tex {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ print "\n\n\\subsection{". $args{'function'} . "}\n";
+
+ print "{\\it ".$args{'functiontype'}."}\n";
+ print "{\\bf ".$args{'function'}."}\n";
+ print "(\n";
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "{\\it ".$args{'parametertypes'}{$parameter}."} {\\bf ".$parameter."}\n";
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ", ";
+ }
+ }
+ print ")\n";
+
+ print "\n\\large{Arguments}\n";
+ print "\\begin{itemize}\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "\\item {\\it ".$args{'parametertypes'}{$parameter}."} {\\bf ".$parameter."}\n";
+ print "\n";
+ output_highlight($args{'parameters'}{$parameter});
+ }
+ print "\\end{itemize}\n";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "\\large{$section}\n";
+ print "\\begin{rmfamily}\n";
+ output_highlight($args{'sections'}{$section});
+ print "\\end{rmfamily}\n";
+ }
+ print "\n";
+}
+
# output in sgml DocBook
sub output_sgml {
--- /dev/null
+EXTRA_DIST = TODO gnutls-api.tex gnutls.tex gnutls.ps gnutls.html ASN1.readme.txt \
+ ex1.tex ex2.tex ex3.tex
+
+gnutls-api: gnutls.html gnutls.ps
+gnutls-api.tex:
+ @echo "\\newpage" > gnutls-api.tex
+ @echo "\\section{Function Reference}" >> gnutls-api.tex
+ @../scripts/gdoc -tex ../../lib/*.c >> gnutls-api.tex
+
+gnutls.ps: gnutls.tex gnutls-api.tex
+ latex gnutls.tex
+ dvips gnutls.dvi -o gnutls.ps
+
+gnutls.html: gnutls.tex gnutls-api.tex
+ latex2html gnutls.tex
--- /dev/null
+\begin{verbatim}
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <gnutls.h>
+
+#define MAX_BUF 1024
+#define CRLFILE "crl.pem"
+#define CAFILE "ca.pem"
+#define SA struct sockaddr
+#define MSG "GET / HTTP/1.0\r\n\r\n"
+
+int main()
+{
+ const char *PORT = "443";
+ const char *SERVER = "127.0.0.1";
+ int err, ret;
+ int sd, ii;
+ struct sockaddr_in sa;
+ GNUTLS_STATE state;
+ char buffer[MAX_BUF + 1];
+ X509PKI_CLIENT_CREDENTIALS xcred;
+ /* variables used in session resuming */
+ int t;
+ char *session;
+ char *session_id;
+ int session_size;
+ int session_id_size;
+ char *tmp_session_id;
+ int tmp_session_id_size;
+
+ if (gnutls_global_init() < 0) {
+ fprintf(stderr, "global state initialization error\n");
+ exit(1);
+ }
+ /* X509 stuff */
+ if (gnutls_allocate_x509_client_sc(&xcred, 0) < 0) { /* no client private key */
+ fprintf(stderr, "memory error\n");
+ exit(1);
+ }
+ gnutls_set_x509_client_trust(xcred, CAFILE, CRLFILE);
+
+ for (t = 0; t < 2; t++) { /* connect 2 times to the server */
+
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+ memset(&sa, '\0', sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(atoi(PORT));
+ inet_pton(AF_INET, SERVER, &sa.sin_addr);
+
+ err = connect(sd, (SA *) & sa, sizeof(sa));
+ if (err < 0) {
+ fprintf(stderr, "Connect error");
+ exit(1);
+ }
+ gnutls_init(&state, GNUTLS_CLIENT);
+ gnutls_set_protocol_priority(state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
+ gnutls_set_cipher_priority(state, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, 0);
+ gnutls_set_compression_priority(state, GNUTLS_NULL_COMPRESSION, 0);
+ gnutls_set_kx_priority(state, GNUTLS_KX_RSA, 0);
+ gnutls_set_mac_priority(state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0);
+
+
+ gnutls_set_cred(state, GNUTLS_X509PKI, xcred);
+ gnutls_x509_set_cn(state, "www.host.com");
+
+
+ if (t > 0) { /* if this is not the first time we connect */
+ gnutls_set_current_session(state, session, session_size);
+ free(session);
+ }
+ /* Perform the TLS handshake
+ */
+ ret = gnutls_handshake(sd, state);
+
+ if (ret < 0) {
+ fprintf(stderr, "*** Handshake failed\n");
+ gnutls_perror(ret);
+ goto end;
+ } else {
+ printf("- Handshake was completed\n");
+ }
+
+ if (t == 0) { /* the first time we connect */
+ /* get the session data size */
+ gnutls_get_current_session(state, NULL, &session_size);
+ session = malloc(session_size);
+
+ /* put session data to the session variable */
+ gnutls_get_current_session(state, session, &session_size);
+
+ /* keep the current session ID. This is only needed
+ * in order to check if the server actually resumed this
+ * connection.
+ */
+ gnutls_get_current_session_id(state, NULL, &session_id_size);
+ session_id = malloc(session_id_size);
+ gnutls_get_current_session_id(state, session_id, &session_id_size);
+
+ } else { /* the second time we connect */
+
+ /* check if we actually resumed the previous session */
+ gnutls_get_current_session_id(state, NULL, &tmp_session_id_size);
+ tmp_session_id = malloc(tmp_session_id_size);
+ gnutls_get_current_session_id(state, tmp_session_id, &tmp_session_id_size);
+
+ if (memcmp(tmp_session_id, session_id, session_id_size) == 0) {
+ printf("- Previous session was resumed\n");
+ } else {
+ fprintf(stderr, "*** Previous session was NOT resumed\n");
+ }
+ free(tmp_session_id);
+ free(session_id);
+ }
+
+ /* This function is defined in a previous example
+ */
+ print_info(state);
+
+ gnutls_write(sd, state, MSG, strlen(MSG));
+
+ ret = gnutls_read(sd, state, buffer, MAX_BUF);
+ if (gnutls_is_fatal_error(ret) == 1 || ret == 0) {
+ if (ret == 0) {
+ printf("- Peer has closed the GNUTLS connection\n");
+ goto end;
+ } else {
+ fprintf(stderr, "*** Received corrupted data(%d) - server has terminated the connection abnormally\n",
+ ret);
+ goto end;
+ }
+ } else {
+ if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
+ printf("* Received alert [%d]\n", gnutls_get_last_alert(state));
+ if (ret == GNUTLS_E_GOT_HELLO_REQUEST)
+ printf("* Received HelloRequest message (server asked to rehandshake)\n");
+ }
+
+ if (ret > 0) {
+ printf("- Received %d bytes: ", ret);
+ for (ii = 0; ii < ret; ii++) {
+ fputc(buffer[ii], stdout);
+ }
+ fputs("\n", stdout);
+ }
+ gnutls_bye(sd, state, 0);
+
+ end:
+
+ shutdown(sd, SHUT_RDWR); /* no more receptions */
+ close(sd);
+
+ gnutls_deinit(state);
+
+ } /* for() */
+
+ gnutls_free_x509_client_sc(xcred);
+
+ gnutls_global_deinit();
+
+ return 0;
+}
+
+\end{verbatim}
--- /dev/null
+\begin{verbatim}
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <gnutls.h>
+
+#define MAX_BUF 1024
+#define CRLFILE "crl.pem"
+#define CAFILE "ca.pem"
+#define SA struct sockaddr
+#define MSG "GET / HTTP/1.0\r\n\r\n"
+
+int main()
+{
+ const char *PORT = "443";
+ const char *SERVER = "127.0.0.1";
+ int err, ret;
+ int sd, ii;
+ struct sockaddr_in sa;
+ GNUTLS_STATE state;
+ char buffer[MAX_BUF + 1];
+ X509PKI_CLIENT_CREDENTIALS xcred;
+
+ if (gnutls_global_init() < 0) {
+ fprintf(stderr, "global state initialization error\n");
+ exit(1);
+ }
+ /* X509 stuff */
+ if (gnutls_allocate_x509_client_sc(&xcred, 0) < 0) { /* no client private key */
+ fprintf(stderr, "memory error\n");
+ exit(1);
+ }
+ /* set's the trusted cas file
+ */
+ gnutls_set_x509_client_trust(xcred, CAFILE, CRLFILE);
+
+ /* connects to server
+ */
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+
+ memset(&sa, '\0', sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(atoi(PORT));
+ inet_pton(AF_INET, SERVER, &sa.sin_addr);
+
+ err = connect(sd, (SA *) & sa, sizeof(sa));
+ if (err < 0) {
+ fprintf(stderr, "Connect error\n");
+ exit(1);
+ }
+ /* Initialize TLS state
+ */
+ gnutls_init(&state, GNUTLS_CLIENT);
+
+ /* allow both SSL3 and TLS1
+ */
+ gnutls_set_protocol_priority(state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
+
+ /* allow only ARCFOUR and 3DES ciphers
+ * (3DES has the highest priority)
+ */
+ gnutls_set_cipher_priority(state, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, 0);
+
+ /* only allow null compression
+ */
+ gnutls_set_compression_priority(state, GNUTLS_NULL_COMPRESSION, 0);
+
+ /* use GNUTLS_KX_RSA
+ */
+ gnutls_set_kx_priority(state, GNUTLS_KX_RSA, 0);
+
+ /* allow the usage of both SHA and MD5
+ */
+ gnutls_set_mac_priority(state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0);
+
+
+ /* put the x509 credentials to the current state
+ */
+ gnutls_set_cred(state, GNUTLS_X509PKI, xcred);
+
+ /* This should be the CN in the server's
+ * certificate.
+ */
+ gnutls_x509_set_cn(state, "www.host.com");
+
+
+ /* Perform the TLS handshake
+ */
+ ret = gnutls_handshake(sd, state);
+
+ if (ret < 0) {
+ fprintf(stderr, "*** Handshake failed\n");
+ gnutls_perror(ret);
+ goto end;
+ } else {
+ printf("- Handshake was completed\n");
+ }
+
+ gnutls_write(sd, state, MSG, strlen(MSG));
+
+ ret = gnutls_read(sd, state, buffer, MAX_BUF);
+ if (gnutls_is_fatal_error(ret) == 1 || ret == 0) {
+ if (ret == 0) {
+ printf("- Peer has closed the GNUTLS connection\n");
+ goto end;
+ } else {
+ fprintf(stderr, "*** Received corrupted data(%d) - server has terminated the connection abnormally\n",
+ ret);
+ goto end;
+ }
+ } else {
+ if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
+ printf("* Received alert [%d]\n", gnutls_get_last_alert(state));
+ if (ret == GNUTLS_E_GOT_HELLO_REQUEST)
+ printf("* Received HelloRequest message (server asked to rehandshake)\n");
+ }
+
+ if (ret > 0) {
+ printf("- Received %d bytes: ", ret);
+ for (ii = 0; ii < ret; ii++) {
+ fputc(buffer[ii], stdout);
+ }
+ fputs("\n", stdout);
+ }
+ gnutls_bye(sd, state, 0);
+
+ end:
+
+ shutdown(sd, SHUT_RDWR); /* no more receptions */
+ close(sd);
+
+ gnutls_deinit(state);
+
+ gnutls_free_x509_client_sc(xcred);
+
+ gnutls_global_deinit();
+
+ return 0;
+}
+
+\end{verbatim}
--- /dev/null
+\begin {verbatim}
+
+int print_info(GNUTLS_STATE state)
+{
+ const char *tmp;
+ const X509PKI_CLIENT_AUTH_INFO *x509_info;
+
+ /* print the key exchange's algorithm name
+ */
+ tmp = gnutls_kx_get_name(gnutls_get_current_kx(state));
+ printf("- Key Exchange: %s\n", tmp);
+
+ /* in case of X509 PKI
+ */
+ if (gnutls_get_auth_info_type(state) == GNUTLS_X509PKI) {
+ x509_info = gnutls_get_auth_info(state);
+ if (x509_info != NULL) {
+ switch (x509_info->peer_certificate_status) {
+ case GNUTLS_CERT_NOT_TRUSTED:
+ printf("- Peer's X509 Certificate was NOT verified\n");
+ break;
+ case GNUTLS_CERT_EXPIRED:
+ printf("- Peer's X509 Certificate was verified but is expired\n");
+ break;
+ case GNUTLS_CERT_TRUSTED:
+ printf("- Peer's X509 Certificate was verified\n");
+ break;
+ case GNUTLS_CERT_WRONG_CN:
+ /* the server's name
+ * is set by using the gnutls_set_x509_cn() function.
+ */
+ printf("- Peer's X509 Certificate was verified but it does not match the server's name\n");
+ break;
+ case GNUTLS_CERT_INVALID:
+ default:
+ printf("- Peer's X509 Certificate was invalid\n");
+ break;
+
+ }
+ }
+ }
+ printf(" - Certificate info:\n");
+ printf(" - Certificate version: #%d\n", x509_info->peer_certificate_version);
+
+ PRINT_DN(peer_dn);
+
+ printf(" - Certificate Issuer's info:\n");
+ PRINT_DN(issuer_dn);
+
+
+ tmp = gnutls_version_get_name(gnutls_get_current_version(state));
+ printf("- Version: %s\n", tmp);
+
+ tmp = gnutls_compression_get_name(gnutls_get_current_compression_method(state));
+ printf("- Compression: %s\n", tmp);
+
+ tmp = gnutls_cipher_get_name(gnutls_get_current_cipher(state));
+ printf("- Cipher: %s\n", tmp);
+
+ tmp = gnutls_mac_get_name(gnutls_get_current_mac_algorithm(state));
+ printf("- MAC: %s\n", tmp);
+
+ return 0;
+}
+
+\end{verbatim}
--- /dev/null
+\documentclass{article}
+\begin{document}
+
+\oddsidemargin=0pt
+\marginparsep = 0pt
+\marginparwidth=0pt
+\textwidth=6cm
+
+\title{Transport Layer Security}
+\author{Nikos Mavroyanopoulos}
+\maketitle
+
+\section{Introduction}
+\par
+gnuTLS is a library which implements the {\bf TLS 1.0} and {\bf SSL 3.0} protocols.
+TLS stands for 'Transport Layer Security' and is the sucessor of SSL (Secure Sockets Layer).
+{\bf TLS 1.0} is described is {\it RFC 2246} and is an Internet protocol (thus it's mostly used over TCP/IP),
+that provides confidentiality, and authentication layers.
+
+\subsection{Confidentiality}
+\par
+Confidentiality is provided by using symmetric encryption algorithms like {\bf 3DES}, {\bf AES}, or
+stream algorithms like {\bf ARCFOUR}. A symmetric encryption algorithm uses a single (secret) key
+to encrypt and decrypt data.
+
+\subsection{Authentication}
+\par
+The following authentication schemas are supported in gnuTLS:
+\begin{enumerate}
+ \item X509 Public Key Infrastructure
+ \item Anonymous authentication
+ \item SRP authentication
+\end{enumerate}
+
+
+
+\section{X509 Client Examples}
+
+Let's assume now that we want to create a client which communicates
+with servers using the X509 authentication schema. The following client
+is a very simple TLS client, it does not support session resuming nor
+any other fancy features.
+
+\subsection{Simple Client example}
+\input{ex2}
+
+\subsection{Getting peer's information}
+\par The above example was the simplest form of a client, it didn't even check
+the result of the peer's certificate verification function (ie. if we have
+an authenticated connection. The following function does check the peer's X509
+Certificate, and prints some information about the current state.
+\par
+This function should be called after a successful \begin{verbatim}gnutls_handshake()\end{verbatim}.
+
+\input{ex3}
+
+\subsection{Resuming Sessions}
+\par
+The \begin{verbatim}gnutls_handshake()\end{verbatim} function, is expensive since
+a lot of calculations are performed. In order to support many fast connections to
+the same server a client may use session resuming. {\bf Session resuming} is a
+feature of the {\bf TLS} protocol which allows a client to connect to a server,
+after a successful handshake, without the expensive calculations (ie. use the previously
+established keys). {\bf gnuTLS} supports this feature, and this example illustrates a
+typical use of it. (This is a modification of the simple client example)
+
+\par
+Keep in mind that sessions are expired after some time (for security reasons), thus
+it may be normal for a server not to resume a session even if you requested that.
+
+\input{ex1}
+
+
+\include{gnutls-api}
+
+\end{document}
+
*/
ssize_t _gnutls_send_change_cipher_spec(SOCKET cd, GNUTLS_STATE state)
{
- char data[1] = { GNUTLS_TYPE_CHANGE_CIPHER_SPEC };
+ opaque data[1] = { GNUTLS_TYPE_CHANGE_CIPHER_SPEC };
#ifdef HANDSHAKE_DEBUG
fprintf(stderr, "Record: Sending ChangeCipherSpec\n");
#ifdef RECORD_DEBUG
fprintf(stderr, "Record: ChangeCipherSpec Packet was received\n");
#endif
+
gnutls_free(ciphertext);
- gnutls_free(tmpdata);
if (tmplen!=sizeofdata) { /* sizeofdata should be 1 */
gnutls_assert();
+ gnutls_free(tmpdata);
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
memcpy( data, tmpdata, sizeofdata);
+ gnutls_free(tmpdata);
return tmplen;
}