1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <gnutls/gnutls.h>
#include <gnutls/extra.h>
/* A basic TLS client, with anonymous authentication and TLS/IA handshake.
*/
#define MAX_BUF 1024
#define SA struct sockaddr
#define MSG "GET / HTTP/1.0\r\n\r\n"
extern int tcp_connect (void);
extern void tcp_close (int sd);
int
client_avp (gnutls_session_t session, void *ptr,
const char *last, size_t lastlen,
char **new, size_t *newlen)
{
if (last)
printf ("- received %d bytes AVP: `%.*s'\n",
lastlen, lastlen, last);
else
printf ("- new application phase\n");
*new = gnutls_strdup ("client avp");
if (!*new)
return -1;
*newlen = strlen (*new);
printf ("- sending %d bytes AVP: `%s'\n", *newlen, *new);
gnutls_ia_permute_inner_secret (session, 3, "foo");
return 0;
}
int
main (void)
{
int ret, sd, ii;
gnutls_session_t session;
char buffer[MAX_BUF + 1];
gnutls_anon_client_credentials_t anoncred;
gnutls_ia_client_credentials_t iacred;
/* Need to enable anonymous KX specifically. */
const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
gnutls_global_init ();
gnutls_anon_allocate_client_credentials (&anoncred);
gnutls_ia_allocate_client_credentials (&iacred);
/* Set TLS/IA stuff
*/
gnutls_ia_set_client_avp_function (iacred, client_avp);
/* Initialize TLS session
*/
gnutls_init (&session, GNUTLS_CLIENT);
/* Use default priorities */
gnutls_set_default_priority (session);
gnutls_kx_set_priority (session, kx_prio);
/* put the anonymous and TLS/IA credentials to the current session
*/
gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred);
/* connect to the peer
*/
sd = tcp_connect ();
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
/* Perform the TLS handshake
*/
ret = gnutls_handshake (session);
if (ret < 0)
{
fprintf (stderr, "*** Handshake failed\n");
gnutls_perror (ret);
goto end;
}
else
{
printf ("- Handshake was completed\n");
}
if (!gnutls_ia_handshake_p (session))
{
fprintf (stderr, "*** TLS/IA not negotiated...\n");
goto end;
}
else
{
printf ("- Starting TLS/IA handshake...\n");
ret = gnutls_ia_handshake (session);
if (ret < 0)
{
fprintf (stderr, "*** TLS/IA handshake failed\n");
gnutls_perror (ret);
goto end;
}
else
{
printf ("- TLS/IA Handshake was completed\n");
}
}
gnutls_record_send (session, MSG, strlen (MSG));
ret = gnutls_record_recv (session, buffer, MAX_BUF);
if (ret == 0)
{
printf ("- Peer has closed the TLS connection\n");
goto end;
}
else if (ret < 0)
{
fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
goto end;
}
printf ("- Received %d bytes: ", ret);
for (ii = 0; ii < ret; ii++)
{
fputc (buffer[ii], stdout);
}
fputs ("\n", stdout);
gnutls_bye (session, GNUTLS_SHUT_RDWR);
end:
tcp_close (sd);
gnutls_deinit (session);
gnutls_ia_free_client_credentials (iacred);
gnutls_anon_free_client_credentials (anoncred);
gnutls_global_deinit ();
return 0;
}
|