--- /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 = "5556";
+ 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);
+
+
+ /* 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.txt gnutls-api.html ASN1.readme.txt
+EXTRA_DIST = TODO gnutls-api.html ASN1.readme.txt
-gnutls-api: gnutls-api.html gnutls-api.txt
-gnutls-api.html:
- @scripts/gdoc -html ../lib/*.c > gnutls-api.html
-gnutls-api.txt:
- @scripts/gdoc -text ../lib/*.c > gnutls-api.txt
+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
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
- print "<h2>Function</h2>\n";
+ print "\n\n<a name=\"". $args{'function'} . "\"> </a><h2>Function</h2>\n";
print "<i>".$args{'functiontype'}."</i>\n";
print "<b>".$args{'function'}."</b>\n";
int gnutls_global_init();
void gnutls_global_deinit();
-void gnutls_set_recv_func( ssize_t (*recv_func)(SOCKET, void*, size_t, int));
-void gnutls_set_send_func( ssize_t (*send_func)(SOCKET, const void*, size_t, int));
+typedef ssize_t (*RECV_FUNC)(SOCKET, void*, size_t,int);
+typedef ssize_t (*SEND_FUNC)(SOCKET, const void*, size_t,int);
+
+RECV_FUNC _gnutls_recv_func;
+SEND_FUNC _gnutls_send_func;
+
+void gnutls_global_set_send_func( SEND_FUNC send_func);
+void gnutls_global_set_recv_func( RECV_FUNC recv_func);
/* error codes appended here */
typedef struct gnutls_error_entry gnutls_error_entry;
static gnutls_error_entry error_algorithms[] = {
+ GNUTLS_ERROR_ENTRY( GNUTLS_E_SUCCESS, 0),
GNUTLS_ERROR_ENTRY( GNUTLS_E_MAC_FAILED, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_CIPHER, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_CIPHER_SUITE, 1),
int gnutls_is_fatal_error(int error)
{
int ret = 0;
+
GNUTLS_ERROR_ALG_LOOP(ret = p->fatal);
return ret;
}
+#define GNUTLS_E_SUCCESS 0
#define GNUTLS_E_MAC_FAILED -1
#define GNUTLS_E_UNKNOWN_CIPHER -2
#define GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM -3
extern const static_asn pkix_asn1_tab[];
static void* old_sig_handler;
-ssize_t (*_gnutls_recv_func)( SOCKET, void*, size_t, int);
-ssize_t (*_gnutls_send_func)( SOCKET,const void*, size_t, int);
+
+typedef ssize_t (*RECV_FUNC)(SOCKET, void*, size_t,int);
+typedef ssize_t (*SEND_FUNC)(SOCKET, const void*, size_t,int);
+
+RECV_FUNC _gnutls_recv_func;
+SEND_FUNC _gnutls_send_func;
static node_asn *PKIX1_ASN;
static node_asn *PKCS1_ASN;
}
/**
- * gnutls_set_recv_func - This function sets the recv() function
- * @(*recv_func): it's a recv(2) like function
+ * gnutls_global_set_recv_func - This function sets the recv() function
+ * @recv_func: it's a recv(2) like function
*
* This is the function were you set the recv() function gnutls
* is going to use. Normaly you may not use this function since
* called once and after gnutls_global_init().
*
**/
-void gnutls_set_recv_func( ssize_t (*recv_func)(SOCKET,void*,size_t,int)) {
+void gnutls_global_set_recv_func( RECV_FUNC recv_func) {
_gnutls_recv_func = recv_func;
}
/**
- * gnutls_set_send_func - This function sets the send() function
- * @(*send_func): it's a send(2) like function
+ * gnutls_global_set_send_func - This function sets the send() function
+ * @send_func: it's a send(2) like function
*
* This is the function were you set the send() function gnutls
* is going to use. Normaly you may not use this function since
* a front end to this function. This function should be
* called once and after gnutls_global_init().
**/
-void gnutls_set_send_func( ssize_t (*send_func)(SOCKET, const void*,size_t,int)) {
+void gnutls_global_set_send_func( SEND_FUNC send_func) {
_gnutls_send_func = send_func;
}
int init)
{
int ret = 0;
+ char ch;
ret =
gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC, -1,
- NULL, 0, 0);
+ &ch, 1, 0);
if (ret < 0) {
ERR("recv ChangeCipherSpec", ret);
gnutls_assert();
#define BUFFERS_DEBUG
#define RECORD_DEBUG
#define HANDSHAKE_DEBUG
-#define DEBUG
*/
+#define DEBUG
+
#define SOCKET int
#define LIST ...
if (state->gnutls_internals.valid_connection == VALID_FALSE || sizeofdata==0) {
return 0; /* EOF */
-/* return GNUTLS_E_INVALID_SESSION; */
}
/* in order for GNUTLS_E_AGAIN to be returned the socket
#endif
gnutls_free(ciphertext);
gnutls_free(tmpdata);
- if (tmplen!=1) {
+
+ if (tmplen!=sizeofdata) { /* sizeofdata should be 1 */
gnutls_assert();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
- return 0;
+ memcpy( data, tmpdata, sizeofdata);
+
+ return tmplen;
}
#ifdef RECORD_DEBUG
return ret;
}
-#ifdef DEBUG
-fprintf(stderr, "digest_size: %s\n", _gnutls_bin2hex(digest,digest_size));
-#endif
-
gnutls_free_datum( &decrypted);
if (digest_size != gnutls_hash_get_algo_len(hash)) {
hd = gnutls_hash_init( hash);
gnutls_hash( hd, text->data, text->size);
gnutls_hash_deinit( hd, md);
-#ifdef DEBUG
- fprintf(stderr, "cmd: %s\n", _gnutls_bin2hex(md, 16));
-#endif
+
if (memcmp( md, digest, digest_size)!=0) {
gnutls_assert();
return GNUTLS_E_PK_SIGNATURE_FAILED;
return GNUTLS_CERT_TRUSTED;
}
#ifdef DEBUG
-fprintf(stderr, "PK: %d\n", issuer->subject_pk_algorithm);
+ fprintf(stderr, "PK: %d\n", issuer->subject_pk_algorithm);
#endif
gnutls_assert();