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"
31 #include "../libextra/gnutls-extra.h"
37 /* konqueror cannot handle sending the page in multiple
41 static char http_buffer
[16 * 1024];
42 static int generate
= 0;
48 char *srp_passwd_conf
;
57 char *x509_crlfile
= NULL
;
61 /* This is a sample TCP echo server.
62 * This will behave as an http server if any argument in the
63 * command line is present
67 #define SA struct sockaddr
68 #define ERR(err,s) if(err==-1) {perror(s);return(1);}
71 #define HTTP_BEGIN "HTTP/1.0 200 OK\n" \
72 "Content-Type: text/html\n" \
75 "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" \
78 #define HTTP_END "</BODY></HTML>\n\n"
82 /* These are global */
83 GNUTLS_SRP_SERVER_CREDENTIALS srp_cred
;
84 GNUTLS_ANON_SERVER_CREDENTIALS dh_cred
;
85 GNUTLS_CERTIFICATE_SERVER_CREDENTIALS cert_cred
;
88 #define DEFAULT_PRIME_BITS 1024
90 /* we use primes up to 1024 in this server.
91 * otherwise we should add them here.
93 static int prime_nums
[] = { 768, 1024, 0 };
95 GNUTLS_DH_PARAMS dh_params
;
97 static int generate_dh_primes(void)
99 gnutls_datum prime
, generator
;
102 if (gnutls_dh_params_init(&dh_params
) < 0) {
103 fprintf(stderr
, "Error in dh parameter initialization\n");
108 /* Generate Diffie Hellman parameters - for use with DHE
109 * kx algorithms. These should be discarded and regenerated
110 * once a day, once a week or once a month. Depends on the
111 * security requirements.
114 ("Generating Diffie Hellman parameters [%d]. Please wait...",
118 if (gnutls_dh_params_generate(&prime
, &generator
, prime_nums
[i
]) < 0) {
119 fprintf(stderr
, "Error in prime generation\n");
123 if (gnutls_dh_params_set
124 (dh_params
, prime
, generator
, prime_nums
[i
]) < 0) {
125 fprintf(stderr
, "Error in prime replacement\n");
129 free(generator
.data
);
131 } while (prime_nums
[++i
] != 0);
136 int protocol_priority
[16] = { GNUTLS_TLS1
, GNUTLS_SSL3
, 0 };
137 int kx_priority
[16] =
138 { GNUTLS_KX_DHE_DSS
, GNUTLS_KX_RSA
, GNUTLS_KX_DHE_RSA
, GNUTLS_KX_SRP
,
141 int cipher_priority
[16] =
142 { GNUTLS_CIPHER_RIJNDAEL_128_CBC
, GNUTLS_CIPHER_3DES_CBC
,
143 GNUTLS_CIPHER_ARCFOUR
, 0
145 int comp_priority
[16] = { GNUTLS_COMP_ZLIB
, GNUTLS_COMP_NULL
, 0 };
146 int mac_priority
[16] = { GNUTLS_MAC_SHA
, GNUTLS_MAC_MD5
, 0 };
147 int cert_type_priority
[16] = { GNUTLS_CRT_X509
, GNUTLS_CRT_OPENPGP
, 0 };
149 GNUTLS_STATE
initialize_state(void)
154 gnutls_init(&state
, GNUTLS_SERVER
);
155 if ((ret
= gnutls_db_set_name(state
, "gnutls-rsm.db")) < 0)
157 "*** DB error (%d). Resuming will not be possible.\n\n",
160 /* null cipher is here only for debuging
163 gnutls_cipher_set_priority(state
, cipher_priority
);
164 gnutls_compression_set_priority(state
, comp_priority
);
165 gnutls_kx_set_priority(state
, kx_priority
);
166 gnutls_protocol_set_priority(state
, protocol_priority
);
167 gnutls_mac_set_priority(state
, mac_priority
);
168 gnutls_cert_type_set_priority(state
, cert_type_priority
);
170 gnutls_dh_set_prime_bits(state
, DEFAULT_PRIME_BITS
);
172 gnutls_cred_set(state
, GNUTLS_CRD_ANON
, dh_cred
);
173 gnutls_cred_set(state
, GNUTLS_CRD_SRP
, srp_cred
);
174 gnutls_cred_set(state
, GNUTLS_CRD_CERTIFICATE
, cert_cred
);
176 gnutls_mac_set_priority(state
, mac_priority
);
178 gnutls_certificate_server_set_request(state
, GNUTLS_CERT_REQUEST
);
183 /* Creates html with the current state information.
185 #define tmp2 &http_buffer[strlen(http_buffer)]
186 void peer_print_info(GNUTLS_STATE state
)
189 unsigned char sesid
[32];
192 /* print session_id */
193 gnutls_session_get_id(state
, sesid
, &sesid_size
);
194 sprintf(tmp2
, "\n<p>Session ID: <i>");
195 for (i
= 0; i
< sesid_size
; i
++)
196 sprintf(tmp2
, "%.2X", sesid
[i
]);
197 sprintf(tmp2
, "</i></p>\n");
199 /* Here unlike print_info() we use the kx algorithm to distinguish
200 * the functions to call.
203 /* print srp specific data */
204 if (gnutls_kx_get(state
) == GNUTLS_KX_SRP
) {
205 sprintf(tmp2
, "<p>Connected as user '%s'.</p>\n",
206 gnutls_srp_server_get_username(state
));
209 if (gnutls_kx_get(state
) == GNUTLS_KX_ANON_DH
) {
211 "<p> Connect using anonymous DH (prime of %d bits)</p>\n",
212 gnutls_dh_get_prime_bits(state
));
215 /* print state information */
216 strcat(http_buffer
, "<P>\n");
218 tmp
= gnutls_protocol_get_name(gnutls_protocol_get_version(state
));
219 sprintf(tmp2
, "Protocol version: <b>%s</b><br>\n", tmp
);
221 if (gnutls_auth_get_type(state
) == GNUTLS_CRD_CERTIFICATE
) {
222 tmp
= gnutls_cert_type_get_name(gnutls_cert_type_get(state
));
223 sprintf(tmp2
, "Certificate Type: <b>%s</b><br>\n", tmp
);
226 tmp
= gnutls_kx_get_name(gnutls_kx_get(state
));
227 sprintf(tmp2
, "Key Exchange: <b>%s</b><br>\n", tmp
);
229 if (gnutls_kx_get(state
) == GNUTLS_KX_DHE_RSA
230 || gnutls_kx_get(state
) == GNUTLS_KX_DHE_DSS
) {
232 "Ephemeral DH using prime of <b>%d</b> bits.<br>\n",
233 gnutls_dh_get_prime_bits(state
));
236 tmp
= gnutls_compression_get_name(gnutls_compression_get(state
));
237 sprintf(tmp2
, "Compression: <b>%s</b><br>\n", tmp
);
239 tmp
= gnutls_cipher_get_name(gnutls_cipher_get(state
));
240 sprintf(tmp2
, "Cipher: <b>%s</b><br>\n", tmp
);
242 tmp
= gnutls_mac_get_name(gnutls_mac_get(state
));
243 sprintf(tmp2
, "MAC: <b>%s</b><br>\n", tmp
);
245 strcat(http_buffer
, "</P>\n");
250 /* actually something like readline.
251 * if rnl!=1 then reads an http request in the form REQ\n\n
253 int read_request(GNUTLS_STATE state
, char *data
, int data_size
, int rnl
)
256 char c
, *ptr
, p1
= 0, p2
= 0;
259 for (n
= 1; n
< data_size
; n
++) {
261 rc
= gnutls_record_recv(state
, &c
, 1);
262 } while (rc
== GNUTLS_E_INTERRUPTED
|| rc
== GNUTLS_E_AGAIN
);
266 if (c
== '\n' && rnl
== 1)
269 if (c
== '\n' && p1
== '\r' && p2
== '\n') {
277 } else if (rc
== 0) {
292 void check_alert(GNUTLS_STATE state
, int ret
)
296 if (ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
297 || ret
== GNUTLS_E_FATAL_ALERT_RECEIVED
) {
298 last_alert
= gnutls_alert_get(state
);
299 if (last_alert
== GNUTLS_A_NO_RENEGOTIATION
&&
300 ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
)
302 ("* Received NO_RENEGOTIATION alert. Client Does not support renegotiation.\n");
304 printf("* Received alert '%d'.\n", ret
);
308 static void gaa_parser(int argc
, char **argv
);
310 int main(int argc
, char **argv
)
312 int err
, listen_sd
, i
;
314 struct sockaddr_in sa_serv
;
315 struct sockaddr_in sa_cli
;
319 char buffer
[MAX_BUF
+ 1];
323 signal(SIGPIPE
, SIG_IGN
);
325 gaa_parser(argc
, argv
);
328 strcpy(name
, "HTTP Server");
330 strcpy(name
, "Echo Server");
333 if (gnutls_global_init() < 0) {
334 fprintf(stderr
, "global state initialization error\n");
338 if (gnutls_global_init_extra() < 0) {
339 fprintf(stderr
, "global state initialization error\n");
343 /* Note that servers must generate parameters for
344 * Diffie Hellman. See gnutls_dh_params_generate(), and
345 * gnutls_dh_params_set().
348 generate_dh_primes();
350 if (gnutls_certificate_allocate_sc(&cert_cred
) < 0) {
351 fprintf(stderr
, "memory error\n");
355 if (x509_cafile
!= NULL
) {
356 if ((ret
=gnutls_certificate_set_x509_trust_file
357 (cert_cred
, x509_cafile
, x509ctype
)) < 0) {
358 fprintf(stderr
, "Error reading '%s'\n", x509_cafile
);
361 printf("Processed %d CA certificate(s).\n", ret
);
365 if (pgp_keyring
!= NULL
) {
367 gnutls_certificate_set_openpgp_keyring_file(cert_cred
, pgp_keyring
);
369 fprintf(stderr
, "Error setting the OpenPGP keyring file\n");
373 if (pgp_trustdb
!= NULL
) {
374 ret
= gnutls_certificate_set_openpgp_trustdb(cert_cred
, pgp_trustdb
);
376 fprintf(stderr
, "Error setting the OpenPGP trustdb file\n");
380 if (pgp_certfile
!= NULL
)
381 if (gnutls_certificate_set_openpgp_key_file
382 (cert_cred
, pgp_certfile
, pgp_keyfile
) < 0) {
384 "Error while reading the OpenPGP key pair ('%s', '%s')\n",
385 pgp_certfile
, pgp_keyfile
);
388 gnutls_certificate_set_openpgp_keyserver(cert_cred
, pgp_keyserver
, 0);
390 if (x509_certfile
!= NULL
)
391 if (gnutls_certificate_set_x509_key_file
392 (cert_cred
, x509_certfile
, x509_keyfile
, x509ctype
) < 0) {
394 "Error reading '%s' or '%s'\n", x509_certfile
,
400 if (gnutls_certificate_set_dh_params(cert_cred
, dh_params
) < 0) {
401 fprintf(stderr
, "Error while setting DH parameters\n");
405 /* this is a password file (created with the included srpcrypt utility)
406 * Read README.crypt prior to using SRP.
408 gnutls_srp_allocate_server_sc(&srp_cred
);
410 if (srp_passwd
!=NULL
)
411 if ((ret
=gnutls_srp_set_server_cred_file(srp_cred
, srp_passwd
, srp_passwd_conf
)) < 0) {
412 /* only exit is this function is not disabled
414 fprintf(stderr
, "Error while setting SRP parameters\n");
417 gnutls_anon_allocate_server_sc(&dh_cred
);
419 gnutls_anon_set_server_dh_params(dh_cred
, dh_params
);
421 listen_sd
= socket(AF_INET
, SOCK_STREAM
, 0);
422 ERR(listen_sd
, "socket");
424 memset(&sa_serv
, '\0', sizeof(sa_serv
));
425 sa_serv
.sin_family
= AF_INET
;
426 sa_serv
.sin_addr
.s_addr
= INADDR_ANY
;
427 sa_serv
.sin_port
= htons(port
); /* Server Port number */
429 setsockopt(listen_sd
, SOL_SOCKET
, SO_REUSEADDR
, &optval
, sizeof(int));
430 err
= bind(listen_sd
, (SA
*) & sa_serv
, sizeof(sa_serv
));
432 err
= listen(listen_sd
, 1024);
435 printf("%s ready. Listening to port '%d'.\n\n", name
, port
);
437 client_len
= sizeof(sa_cli
);
440 state
= initialize_state();
442 sd
= accept(listen_sd
, (SA
*) & sa_cli
, &client_len
);
444 printf("- connection from %s, port %d\n",
445 inet_ntop(AF_INET
, &sa_cli
.sin_addr
, topbuf
,
446 sizeof(topbuf
)), ntohs(sa_cli
.sin_port
));
449 gnutls_transport_set_ptr(state
, sd
);
451 ret
= gnutls_handshake(state
);
452 } while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
456 gnutls_deinit(state
);
458 "*** Handshake has failed (%s)\n\n",
459 gnutls_strerror(ret
));
460 check_alert(state
, ret
);
463 printf("- Handshake was completed\n");
464 if ( gnutls_session_is_resumed( state
)!=0)
465 printf("*** This is a resumed session\n");
471 bzero(buffer
, MAX_BUF
+ 1);
472 ret
= read_request(state
, buffer
, MAX_BUF
, (http
== 0) ? 1 : 2);
474 if (gnutls_error_is_fatal(ret
) == 1 || ret
== 0) {
477 printf("\n- Peer has closed the GNUTLS connection\n");
482 "\n*** Received corrupted data(%d). Closing the connection.\n\n",
491 printf("* Read %d bytes from client.\n", strlen(buffer
));
493 ret
= gnutls_record_send(state
, buffer
, strlen(buffer
));
495 GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
496 printf("* Wrote %d bytes to client.\n", ret
);
498 strcpy(http_buffer
, HTTP_BEGIN
);
499 peer_print_info(state
);
500 strcat(http_buffer
, HTTP_END
);
503 gnutls_record_send(state
,
504 http_buffer
, strlen(http_buffer
));
506 GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
508 printf("- Served request. Closing connection.\n");
516 ret
= gnutls_rehandshake(state
);
517 } while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
519 printf("* Requesting rehandshake.\n");
520 /* continue handshake proccess */
522 ret
= gnutls_handshake(state
);
523 } while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
524 printf("* Rehandshake returned %d\n", ret
);
528 check_alert(state
, ret
);
531 break; /* close the connection */
536 ret
= gnutls_bye(state
, GNUTLS_SHUT_WR
);
537 } while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
539 * the peer to close the connection.
542 gnutls_deinit(state
);
547 gnutls_certificate_free_sc(cert_cred
);
548 gnutls_srp_free_server_sc(srp_cred
);
549 gnutls_anon_free_server_sc(dh_cred
);
551 gnutls_global_deinit();
557 #define DEFAULT_X509_KEYFILE "x509/key.pem"
558 #define DEFAULT_X509_CERTFILE "x509/cert.pem"
560 #define DEFAULT_X509_KEYFILE2 "x509/key-dsa.pem"
561 #define DEFAULT_X509_CERTFILE2 "x509/cert-dsa.pem"
563 #define DEFAULT_PGP_KEYFILE "openpgp/sec.asc"
564 #define DEFAULT_PGP_CERTFILE "openpgp/pub.asc"
566 #define DEFAULT_X509_CAFILE "x509/ca.pem"
567 #define DEFAULT_X509_CRLFILE NULL;
569 #define DEFAULT_SRP_PASSWD "srp/tpasswd"
570 #define DEFAULT_SRP_PASSWD_CONF "srp/tpasswd.conf"
575 void gaa_parser(int argc
, char **argv
)
579 if (gaa(argc
, argv
, &info
) != -1) {
581 "Error in the arguments. Use the --help or -h parameters to get more information.\n");
590 if (info
.fmtder
== 0)
591 x509ctype
= GNUTLS_X509_FMT_PEM
;
593 x509ctype
= GNUTLS_X509_FMT_DER
;
595 if (info
.generate
== 0)
603 if (info
.x509_certfile
!= NULL
)
604 x509_certfile
= info
.x509_certfile
;
606 x509_certfile
= DEFAULT_X509_CERTFILE
;
608 if (info
.x509_keyfile
!= NULL
)
609 x509_keyfile
= info
.x509_keyfile
;
611 x509_keyfile
= DEFAULT_X509_KEYFILE
;
613 if (info
.x509_cafile
!= NULL
)
614 x509_cafile
= info
.x509_certfile
;
616 x509_cafile
= DEFAULT_X509_CAFILE
;
618 if (info
.pgp_certfile
!= NULL
)
619 pgp_certfile
= info
.pgp_certfile
;
621 pgp_certfile
= DEFAULT_PGP_CERTFILE
;
623 if (info
.pgp_keyfile
!= NULL
)
624 pgp_keyfile
= info
.pgp_keyfile
;
626 pgp_keyfile
= DEFAULT_PGP_KEYFILE
;
628 if (info
.srp_passwd
!= NULL
)
629 srp_passwd
= info
.srp_passwd
;
631 srp_passwd
= DEFAULT_SRP_PASSWD
;
633 if (info
.srp_passwd_conf
!= NULL
)
634 srp_passwd_conf
= info
.srp_passwd_conf
;
636 srp_passwd_conf
= DEFAULT_SRP_PASSWD_CONF
;
638 x509_certfile
= info
.x509_certfile
;
639 x509_keyfile
= info
.x509_keyfile
;
640 x509_cafile
= info
.x509_cafile
;
641 pgp_certfile
= info
.pgp_certfile
;
642 pgp_keyfile
= info
.pgp_keyfile
;
643 srp_passwd
= info
.srp_passwd
;
644 srp_passwd_conf
= info
.srp_passwd_conf
;
647 pgp_keyserver
= info
.pgp_keyserver
;
648 pgp_keyring
= info
.pgp_keyring
;
649 pgp_trustdb
= info
.pgp_trustdb
;
651 if (info
.proto
!= NULL
&& info
.nproto
> 0) {
652 for (j
= i
= 0; i
< info
.nproto
; i
++) {
653 if (strncasecmp(info
.proto
[i
], "SSL", 3) == 0)
654 protocol_priority
[j
++] = GNUTLS_SSL3
;
655 if (strncasecmp(info
.proto
[i
], "TLS", 3) == 0)
656 protocol_priority
[j
++] = GNUTLS_TLS1
;
658 protocol_priority
[j
] = 0;
661 if (info
.ciphers
!= NULL
&& info
.nciphers
> 0) {
662 for (j
= i
= 0; i
< info
.nciphers
; i
++) {
663 if (strncasecmp(info
.ciphers
[i
], "RIJ", 3) == 0)
664 cipher_priority
[j
++] = GNUTLS_CIPHER_RIJNDAEL_128_CBC
;
665 if (strncasecmp(info
.ciphers
[i
], "TWO", 3) == 0)
666 cipher_priority
[j
++] = GNUTLS_CIPHER_TWOFISH_128_CBC
;
667 if (strncasecmp(info
.ciphers
[i
], "3DE", 3) == 0)
668 cipher_priority
[j
++] = GNUTLS_CIPHER_3DES_CBC
;
669 if (strncasecmp(info
.ciphers
[i
], "ARC", 3) == 0)
670 cipher_priority
[j
++] = GNUTLS_CIPHER_ARCFOUR
;
672 cipher_priority
[j
] = 0;
675 if (info
.macs
!= NULL
&& info
.nmacs
> 0) {
676 for (j
= i
= 0; i
< info
.nmacs
; i
++) {
677 if (strncasecmp(info
.macs
[i
], "MD5", 3) == 0)
678 mac_priority
[j
++] = GNUTLS_MAC_MD5
;
679 if (strncasecmp(info
.macs
[i
], "SHA", 3) == 0)
680 mac_priority
[j
++] = GNUTLS_MAC_SHA
;
685 if (info
.ctype
!= NULL
&& info
.nctype
> 0) {
686 for (j
= i
= 0; i
< info
.nctype
; i
++) {
687 if (strncasecmp(info
.ctype
[i
], "OPE", 3) == 0)
688 cert_type_priority
[j
++] = GNUTLS_CRT_OPENPGP
;
689 if (strncasecmp(info
.ctype
[i
], "X", 1) == 0)
690 cert_type_priority
[j
++] = GNUTLS_CRT_X509
;
692 cert_type_priority
[j
] = 0;
695 if (info
.kx
!= NULL
&& info
.nkx
> 0) {
696 for (j
= i
= 0; i
< info
.nkx
; i
++) {
697 if (strncasecmp(info
.kx
[i
], "SRP", 3) == 0)
698 kx_priority
[j
++] = GNUTLS_KX_SRP
;
699 if (strncasecmp(info
.kx
[i
], "RSA", 3) == 0)
700 kx_priority
[j
++] = GNUTLS_KX_RSA
;
701 if (strncasecmp(info
.kx
[i
], "DHE_RSA", 7) == 0)
702 kx_priority
[j
++] = GNUTLS_KX_DHE_RSA
;
703 if (strncasecmp(info
.kx
[i
], "DHE_DSS", 7) == 0)
704 kx_priority
[j
++] = GNUTLS_KX_DHE_DSS
;
705 if (strncasecmp(info
.kx
[i
], "ANON", 4) == 0)
706 kx_priority
[j
++] = GNUTLS_KX_ANON_DH
;
711 if (info
.comp
!= NULL
&& info
.ncomp
> 0) {
712 for (j
= i
= 0; i
< info
.ncomp
; i
++) {
713 if (strncasecmp(info
.comp
[i
], "NUL", 3) == 0)
714 comp_priority
[j
++] = GNUTLS_COMP_NULL
;
715 if (strncasecmp(info
.comp
[i
], "ZLI", 1) == 0)
716 comp_priority
[j
++] = GNUTLS_COMP_ZLIB
;
718 comp_priority
[j
] = 0;
725 void serv_version(void) {
726 fprintf(stderr
, "GNU TLS test server, ");
727 fprintf(stderr
, "version %s.\n", LIBGNUTLS_VERSION
);