2 * Copyright (C) 2000,2001,2002 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * GNUTLS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
30 #include "../lib/gnutls.h"
45 #define SA struct sockaddr
46 #define ERR(err,s) if (err==-1) {perror(s);return(1);}
48 #define GERR(ret) fprintf(stderr, "* Error: %s\n", gnutls_strerror(ret))
50 /* global stuff here */
52 char *hostname
= NULL
;
66 char *x509_crlfile
= NULL
;
69 int protocol_priority
[16] = { GNUTLS_TLS1
, GNUTLS_SSL3
, 0 };
71 { GNUTLS_KX_RSA
, GNUTLS_KX_DHE_DSS
, GNUTLS_KX_DHE_RSA
, GNUTLS_KX_SRP
,
74 int cipher_priority
[16] =
75 { GNUTLS_CIPHER_RIJNDAEL_128_CBC
, GNUTLS_CIPHER_3DES_CBC
,
76 GNUTLS_CIPHER_ARCFOUR
, 0
78 int comp_priority
[16] = { GNUTLS_COMP_ZLIB
, GNUTLS_COMP_NULL
, 0 };
79 int mac_priority
[16] = { GNUTLS_MAC_SHA
, GNUTLS_MAC_MD5
, 0 };
80 int cert_type_priority
[16] = { GNUTLS_CRT_X509
, GNUTLS_CRT_OPENPGP
, 0 };
82 /* end of global stuff */
84 #define MAX(X,Y) (X >= Y ? X : Y);
85 #define DEFAULT_X509_CAFILE "x509/ca.pem"
86 #define DEFAULT_X509_KEYFILE2 "x509/clikey-dsa.pem"
87 #define DEFAULT_X509_CERTFILE2 "x509/clicert-dsa.pem"
89 #define DEFAULT_X509_KEYFILE "x509/clikey.pem"
90 #define DEFAULT_X509_CERTFILE "x509/clicert.pem"
92 #define DEFAULT_PGP_KEYFILE "openpgp/cli_sec.asc"
93 #define DEFAULT_PGP_CERTFILE "openpgp/cli_pub.asc"
94 #define DEFAULT_PGP_KEYRING "openpgp/cli_ring.gpg"
96 #define DEFAULT_SRP_USERNAME "test"
97 #define DEFAULT_SRP_PASSWD "test"
99 static int cert_callback(GNUTLS_STATE state
,
100 const gnutls_datum
* client_certs
, int ncerts
,
101 const gnutls_datum
* req_ca_cert
, int nreqs
)
104 if (client_certs
== NULL
) {
105 return 0; /* means the we will only be called again
106 * if the library cannot determine which
107 * certificate to send
111 /* here we should prompt the user and ask him
112 * which certificate to choose. Too bored to
113 * implement that. --nmav
115 for (i
= 0; i
< ncerts
; i
++) {
116 fprintf(stderr
, "%s.", client_cert
->common_name
);
117 fprintf(stderr
, "%s\n", issuer_cert
->common_name
);
119 for (i
= 0; i
< nreqs
; i
++) {
120 fprintf(stderr
, "%s.", req_ca_cert
->common_name
);
122 fprintf(stderr
, "\n");
126 return -1; /* send no certificate to the peer */
130 static void gaa_parser(int argc
, char **argv
);
132 int main(int argc
, char **argv
)
136 struct sockaddr_in sa
;
138 char buffer
[MAX_BUF
+ 1];
141 int session_size
, alert
;
143 char *tmp_session_id
;
144 int tmp_session_id_size
;
149 GNUTLS_SRP_CLIENT_CREDENTIALS cred
;
150 GNUTLS_ANON_CLIENT_CREDENTIALS anon_cred
;
151 GNUTLS_CERTIFICATE_CLIENT_CREDENTIALS xcred
;
152 struct hostent
*server_host
;
154 gaa_parser(argc
, argv
);
156 signal(SIGPIPE
, SIG_IGN
);
158 if (gnutls_global_init() < 0) {
159 fprintf(stderr
, "global state initialization error\n");
163 printf("Resolving '%s'...\n", hostname
);
164 /* get server name */
165 server_host
= gethostbyname(hostname
);
166 if (server_host
== NULL
) {
167 fprintf(stderr
, "Cannot resolve %s\n", hostname
);
172 if (gnutls_certificate_allocate_sc(&xcred
) < 0) { /* space for 2 certificates */
173 fprintf(stderr
, "memory error\n");
177 if (x509_cafile
!= NULL
) {
179 gnutls_certificate_set_x509_trust_file(xcred
, x509_cafile
,
182 fprintf(stderr
, "Error setting the x509 trust file\n");
186 if (x509_certfile
!= NULL
) {
188 gnutls_certificate_set_x509_key_file(xcred
, x509_certfile
,
191 fprintf(stderr
, "Error setting the x509 key files ('%s', '%s')\n",
192 x509_certfile
, x509_keyfile
);
196 if (pgp_certfile
!= NULL
) {
198 gnutls_certificate_set_openpgp_key_file(xcred
, pgp_certfile
,
201 fprintf(stderr
, "Error setting the x509 key files ('%s', '%s'\n",
202 pgp_certfile
, pgp_keyfile
);
206 if (pgp_keyring
!= NULL
) {
208 gnutls_certificate_set_openpgp_keyring_file(xcred
, pgp_keyring
);
210 fprintf(stderr
, "Error setting the OpenPGP keyring file\n");
214 if (pgp_trustdb
!= NULL
) {
215 gnutls_certificate_set_openpgp_trustdb(xcred
, pgp_trustdb
);
217 /* gnutls_certificate_client_callback_func( xcred, cert_callback); */
220 if (srp_username
!=NULL
) {
221 if (gnutls_srp_allocate_client_sc(&cred
) < 0) {
222 fprintf(stderr
, "memory error\n");
225 gnutls_srp_set_client_cred(cred
, srp_username
, srp_passwd
);
229 if (gnutls_anon_allocate_client_sc(&anon_cred
) < 0) {
230 fprintf(stderr
, "memory error\n");
234 sd
= socket(AF_INET
, SOCK_STREAM
, 0);
237 memset(&sa
, '\0', sizeof(sa
));
238 sa
.sin_family
= AF_INET
;
239 sa
.sin_port
= htons(port
);
241 sa
.sin_addr
.s_addr
= *((unsigned int *) server_host
->h_addr
);
243 inet_ntop(AF_INET
, &sa
.sin_addr
, buffer
, MAX_BUF
);
244 fprintf(stderr
, "Connecting to '%s:%d'...\n", buffer
, port
);
246 err
= connect(sd
, (SA
*) & sa
, sizeof(sa
));
249 for (i
= 0; i
< 2; i
++) {
250 gnutls_init(&state
, GNUTLS_CLIENT
);
253 gnutls_session_set_data(state
, session
, session_size
);
257 gnutls_cipher_set_priority(state
, cipher_priority
);
258 gnutls_compression_set_priority(state
, comp_priority
);
259 gnutls_kx_set_priority(state
, kx_priority
);
260 gnutls_protocol_set_priority(state
, protocol_priority
);
261 gnutls_mac_set_priority(state
, mac_priority
);
262 gnutls_cert_type_set_priority(state
, cert_type_priority
);
264 gnutls_dh_set_prime_bits(state
, 1024);
266 gnutls_cred_set(state
, GNUTLS_CRD_ANON
, anon_cred
);
267 if (srp_username
!=NULL
)
268 gnutls_cred_set(state
, GNUTLS_CRD_SRP
, cred
);
269 gnutls_cred_set(state
, GNUTLS_CRD_CERTIFICATE
, xcred
);
271 /* send the fingerprint */
272 if (fingerprint
!= 0)
273 gnutls_openpgp_send_key(state
, GNUTLS_OPENPGP_KEY_FINGERPRINT
);
275 /* use the max record size extension */
276 if (record_max_size
> 0) {
277 if (gnutls_record_set_max_size(state
, record_max_size
) < 0) {
278 fprintf(stderr
, "Cannot set the maximum record size to %d.\n",
284 /* This TLS extension may break old implementations.
286 gnutls_transport_set_ptr(state
, sd
);
288 ret
= gnutls_handshake(state
);
289 } while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
292 if (ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
293 || ret
== GNUTLS_E_FATAL_ALERT_RECEIVED
) {
294 alert
= gnutls_alert_get(state
);
295 printf("*** Received alert [%d]: %s\n",
296 alert
, gnutls_alert_get_name(alert
));
298 fprintf(stderr
, "*** Handshake has failed\n");
300 gnutls_deinit(state
);
303 printf("- Handshake was completed\n");
306 if (i
== 1) { /* resume */
307 /* check if we actually resumed the previous session */
309 gnutls_session_get_id(state
, NULL
, &tmp_session_id_size
);
310 tmp_session_id
= malloc(tmp_session_id_size
);
311 gnutls_session_get_id(state
, tmp_session_id
,
312 &tmp_session_id_size
);
314 if (memcmp(tmp_session_id
, session_id
, session_id_size
) == 0) {
315 printf("- Previous session was resumed\n");
317 fprintf(stderr
, "*** Previous session was NOT resumed\n");
319 free(tmp_session_id
);
325 if (resume
!= 0 && i
== 0) {
327 gnutls_session_get_data(state
, NULL
, &session_size
);
328 session
= malloc(session_size
);
329 gnutls_session_get_data(state
, session
, &session_size
);
331 gnutls_session_get_id(state
, NULL
, &session_id_size
);
332 session_id
= malloc(session_id_size
);
333 gnutls_session_get_id(state
, session_id
, &session_id_size
);
335 /* print some information */
338 printf("- Disconnecting\n");
340 ret
= gnutls_bye(state
, GNUTLS_SHUT_RDWR
);
341 } while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
343 shutdown(sd
, SHUT_WR
);
346 gnutls_deinit(state
);
349 ("\n\n- Connecting again- trying to resume previous session\n");
350 sd
= socket(AF_INET
, SOCK_STREAM
, 0);
353 err
= connect(sd
, (SA
*) & sa
, sizeof(sa
));
361 /* print some information */
364 printf("\n- Simple Client Mode:\n\n");
368 FD_SET(fileno(stdin
), &rset
);
371 maxfd
= MAX(fileno(stdin
), sd
);
374 select(maxfd
+ 1, &rset
, NULL
, NULL
, &tv
);
376 if (FD_ISSET(sd
, &rset
)) {
377 bzero(buffer
, MAX_BUF
+ 1);
379 ret
= gnutls_record_recv(state
, buffer
, MAX_BUF
);
380 } while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
381 /* remove new line */
383 if (gnutls_error_is_fatal(ret
) == 1 || ret
== 0) {
385 printf("- Peer has closed the GNUTLS connection\n");
389 "*** Received corrupted data(%d) - server has terminated the connection abnormally\n",
394 if (ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
395 || ret
== GNUTLS_E_FATAL_ALERT_RECEIVED
)
396 printf("* Received alert [%d]\n", gnutls_alert_get(state
));
397 if (ret
== GNUTLS_E_REHANDSHAKE
) {
398 /* There is a race condition here. If application
399 * data is sent after the rehandshake request,
400 * the server thinks we ignored his request.
401 * This is a bad design of this client.
403 printf("* Received rehandshake request\n");
404 /* gnutls_alert_send( state, GNUTLS_AL_WARNING, GNUTLS_A_NO_RENEGOTIATION); */
407 ret
= gnutls_handshake(state
);
408 } while (ret
== GNUTLS_E_AGAIN
409 || ret
== GNUTLS_E_INTERRUPTED
);
412 printf("* Rehandshake was performed\n");
414 printf("* Rehandshake Failed [%d]\n", ret
);
418 printf("- Received[%d]: ", ret
);
419 for (ii
= 0; ii
< ret
; ii
++) {
420 fputc(buffer
[ii
], stdout
);
429 if (FD_ISSET(fileno(stdin
), &rset
)) {
430 if (fgets(buffer
, MAX_BUF
, stdin
) == NULL
) {
432 ret
= gnutls_bye(state
, GNUTLS_SHUT_WR
);
433 } while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
438 ret
= gnutls_record_send(state
, buffer
, strlen(buffer
));
439 } while (ret
== GNUTLS_E_AGAIN
|| ret
== GNUTLS_E_INTERRUPTED
);
441 printf("- Sent: %d bytes\n", ret
);
449 ret
= gnutls_bye(state
, GNUTLS_SHUT_RDWR
);
450 while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
452 shutdown(sd
, SHUT_RDWR
); /* no more receptions */
455 gnutls_deinit(state
);
457 if (srp_username
!=NULL
)
458 gnutls_srp_free_client_sc(cred
);
459 gnutls_certificate_free_sc(xcred
);
460 gnutls_anon_free_client_sc(anon_cred
);
462 gnutls_global_deinit();
470 void gaa_parser(int argc
, char **argv
)
474 if (gaa(argc
, argv
, &info
) != -1) {
476 "Error in the arguments. Use the --help or -h parameters to get more information.\n");
480 resume
= info
.resume
;
482 record_max_size
= info
.record_size
;
483 fingerprint
= info
.fingerprint
;
486 if (info
.x509_certfile
!= NULL
)
487 x509_certfile
= info
.x509_certfile
;
489 x509_certfile
= DEFAULT_X509_CERTFILE
;
491 if (info
.x509_keyfile
!= NULL
)
492 x509_keyfile
= info
.x509_keyfile
;
494 x509_keyfile
= DEFAULT_X509_KEYFILE
;
496 if (info
.x509_cafile
!= NULL
)
497 x509_cafile
= info
.x509_certfile
;
499 x509_cafile
= DEFAULT_X509_CAFILE
;
501 if (info
.pgp_certfile
!= NULL
)
502 pgp_certfile
= info
.pgp_certfile
;
504 pgp_certfile
= DEFAULT_PGP_CERTFILE
;
506 if (info
.pgp_keyfile
!= NULL
)
507 pgp_keyfile
= info
.pgp_keyfile
;
509 pgp_keyfile
= DEFAULT_PGP_KEYFILE
;
511 if (info
.srp_passwd
!= NULL
)
512 srp_passwd
= info
.srp_passwd
;
514 srp_passwd
= DEFAULT_SRP_PASSWD
;
516 if (info
.srp_username
!= NULL
)
517 srp_username
= info
.srp_username
;
519 srp_username
= DEFAULT_SRP_USERNAME
;
521 srp_username
= info
.srp_username
;
522 srp_passwd
= info
.srp_passwd
;
523 x509_cafile
= info
.x509_certfile
;
524 x509_keyfile
= info
.x509_keyfile
;
525 x509_certfile
= info
.x509_certfile
;
526 pgp_keyfile
= info
.pgp_keyfile
;
527 pgp_certfile
= info
.pgp_certfile
;
531 pgp_keyring
= info
.pgp_keyring
;
532 pgp_trustdb
= info
.pgp_trustdb
;
534 if (info
.nrest_args
== 0)
535 hostname
= "localhost";
537 hostname
= info
.rest_args
[0];
539 if (info
.proto
!= NULL
&& info
.nproto
> 0) {
540 for (j
= i
= 0; i
< info
.nproto
; i
++) {
541 if (strncasecmp(info
.proto
[i
], "SSL", 3) == 0)
542 protocol_priority
[j
++] = GNUTLS_SSL3
;
543 if (strncasecmp(info
.proto
[i
], "TLS", 3) == 0)
544 protocol_priority
[j
++] = GNUTLS_TLS1
;
546 protocol_priority
[j
] = 0;
549 if (info
.ciphers
!= NULL
&& info
.nciphers
> 0) {
550 for (j
= i
= 0; i
< info
.nciphers
; i
++) {
551 if (strncasecmp(info
.ciphers
[i
], "RIJ", 3) == 0)
552 cipher_priority
[j
++] = GNUTLS_CIPHER_RIJNDAEL_128_CBC
;
553 if (strncasecmp(info
.ciphers
[i
], "TWO", 3) == 0)
554 cipher_priority
[j
++] = GNUTLS_CIPHER_TWOFISH_128_CBC
;
555 if (strncasecmp(info
.ciphers
[i
], "3DE", 3) == 0)
556 cipher_priority
[j
++] = GNUTLS_CIPHER_3DES_CBC
;
557 if (strncasecmp(info
.ciphers
[i
], "ARC", 3) == 0)
558 cipher_priority
[j
++] = GNUTLS_CIPHER_ARCFOUR
;
560 cipher_priority
[j
] = 0;
563 if (info
.macs
!= NULL
&& info
.nmacs
> 0) {
564 for (j
= i
= 0; i
< info
.nmacs
; i
++) {
565 if (strncasecmp(info
.macs
[i
], "MD5", 3) == 0)
566 mac_priority
[j
++] = GNUTLS_MAC_MD5
;
567 if (strncasecmp(info
.macs
[i
], "SHA", 3) == 0)
568 mac_priority
[j
++] = GNUTLS_MAC_SHA
;
573 if (info
.ctype
!= NULL
&& info
.nctype
> 0) {
574 for (j
= i
= 0; i
< info
.nctype
; i
++) {
575 if (strncasecmp(info
.ctype
[i
], "OPE", 3) == 0)
576 cert_type_priority
[j
++] = GNUTLS_CRT_OPENPGP
;
577 if (strncasecmp(info
.ctype
[i
], "X", 1) == 0)
578 cert_type_priority
[j
++] = GNUTLS_CRT_X509
;
580 cert_type_priority
[j
] = 0;
583 if (info
.kx
!= NULL
&& info
.nkx
> 0) {
584 for (j
= i
= 0; i
< info
.nkx
; i
++) {
585 if (strncasecmp(info
.kx
[i
], "SRP", 3) == 0)
586 kx_priority
[j
++] = GNUTLS_KX_SRP
;
587 if (strncasecmp(info
.kx
[i
], "RSA", 3) == 0)
588 kx_priority
[j
++] = GNUTLS_KX_RSA
;
589 if (strncasecmp(info
.kx
[i
], "DHE_RSA", 7) == 0)
590 kx_priority
[j
++] = GNUTLS_KX_DHE_RSA
;
591 if (strncasecmp(info
.kx
[i
], "DHE_DSS", 7) == 0)
592 kx_priority
[j
++] = GNUTLS_KX_DHE_DSS
;
593 if (strncasecmp(info
.kx
[i
], "ANON", 4) == 0)
594 kx_priority
[j
++] = GNUTLS_KX_ANON_DH
;
599 if (info
.comp
!= NULL
&& info
.ncomp
> 0) {
600 for (j
= i
= 0; i
< info
.ncomp
; i
++) {
601 if (strncasecmp(info
.comp
[i
], "NUL", 3) == 0)
602 comp_priority
[j
++] = GNUTLS_COMP_NULL
;
603 if (strncasecmp(info
.comp
[i
], "ZLI", 1) == 0)
604 comp_priority
[j
++] = GNUTLS_COMP_ZLIB
;
606 comp_priority
[j
] = 0;