Improved PKCS7 support
[gnutls.git] / src / serv.c
blob2e1ef86ee5415b73d137e1377fc9d5a74d7fae40
1 /*
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
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include "../lib/gnutls.h"
31 #include "common.h"
32 #include <signal.h>
33 #include "serv-gaa.h"
36 /* konqueror cannot handle sending the page in multiple
37 * pieces.
39 /* global stuff */
40 static char http_buffer[16 * 1024];
41 static int generate = 0;
42 static int http = 0;
43 static int port = 0;
45 char *srp_passwd;
46 char *srp_passwd_conf;
47 char *pgp_keyring;
48 char *pgp_trustdb;
49 char *pgp_keyserver;
50 char *pgp_keyfile;
51 char *pgp_certfile;
52 char *x509_keyfile;
53 char *x509_certfile;
54 char *x509_cafile;
55 char *x509_crlfile = NULL;
57 /* end of globals */
59 /* This is a sample TCP echo server.
60 * This will behave as an http server if any argument in the
61 * command line is present
65 #define SA struct sockaddr
66 #define ERR(err,s) if(err==-1) {perror(s);return(1);}
67 #define MAX_BUF 1024
69 #define HTTP_BEGIN "HTTP/1.0 200 OK\n" \
70 "Content-Type: text/html\n" \
71 "\n" \
72 "<HTML><BODY>\n" \
73 "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" \
74 "GNUTLS</a></H1>\n\n"
76 #define HTTP_END "</BODY></HTML>\n\n"
78 #define RENEGOTIATE
80 /* These are global */
81 GNUTLS_SRP_SERVER_CREDENTIALS srp_cred;
82 GNUTLS_ANON_SERVER_CREDENTIALS dh_cred;
83 GNUTLS_CERTIFICATE_SERVER_CREDENTIALS cert_cred;
86 #define DEFAULT_PRIME_BITS 1024
88 /* we use primes up to 1024 in this server.
89 * otherwise we should add them here.
91 static int prime_nums[] = { 768, 1024, 0 };
93 GNUTLS_DH_PARAMS dh_params;
95 static int generate_dh_primes(void)
97 gnutls_datum prime, generator;
98 int i = 0;
100 if (gnutls_dh_params_init(&dh_params) < 0) {
101 fprintf(stderr, "Error in dh parameter initialization\n");
102 exit(1);
105 do {
106 /* Generate Diffie Hellman parameters - for use with DHE
107 * kx algorithms. These should be discarded and regenerated
108 * once a day, once a week or once a month. Depends on the
109 * security requirements.
111 printf
112 ("Generating Diffie Hellman parameters [%d]. Please wait...",
113 prime_nums[i]);
114 fflush(stdout);
116 if (gnutls_dh_params_generate(&prime, &generator, prime_nums[i]) < 0) {
117 fprintf(stderr, "Error in prime generation\n");
118 exit(1);
121 if (gnutls_dh_params_set
122 (dh_params, prime, generator, prime_nums[i]) < 0) {
123 fprintf(stderr, "Error in prime replacement\n");
124 exit(1);
126 free(prime.data);
127 free(generator.data);
129 } while (prime_nums[++i] != 0);
131 return 0;
134 int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
135 int kx_priority[16] =
136 { GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP,
137 GNUTLS_KX_ANON_DH, 0
139 int cipher_priority[16] =
140 { GNUTLS_CIPHER_RIJNDAEL_128_CBC, GNUTLS_CIPHER_3DES_CBC,
141 GNUTLS_CIPHER_ARCFOUR, 0
143 int comp_priority[16] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
144 int mac_priority[16] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
145 int cert_type_priority[16] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
147 GNUTLS_STATE initialize_state(void)
149 GNUTLS_STATE state;
150 int ret;
152 gnutls_init(&state, GNUTLS_SERVER);
153 if ((ret = gnutls_db_set_name(state, "gnutls-rsm.db")) < 0)
154 fprintf(stderr,
155 "*** DB error (%d). Resuming will not be possible.\n\n",
156 ret);
158 /* null cipher is here only for debuging
159 * purposes.
161 gnutls_cipher_set_priority(state, cipher_priority);
162 gnutls_compression_set_priority(state, comp_priority);
163 gnutls_kx_set_priority(state, kx_priority);
164 gnutls_protocol_set_priority(state, protocol_priority);
165 gnutls_mac_set_priority(state, mac_priority);
166 gnutls_cert_type_set_priority(state, cert_type_priority);
168 gnutls_dh_set_prime_bits(state, DEFAULT_PRIME_BITS);
170 gnutls_cred_set(state, GNUTLS_CRD_ANON, dh_cred);
171 gnutls_cred_set(state, GNUTLS_CRD_SRP, srp_cred);
172 gnutls_cred_set(state, GNUTLS_CRD_CERTIFICATE, cert_cred);
174 gnutls_mac_set_priority(state, mac_priority);
176 gnutls_certificate_server_set_request(state, GNUTLS_CERT_REQUEST);
178 return state;
181 /* Creates html with the current state information.
183 #define tmp2 &http_buffer[strlen(http_buffer)]
184 void peer_print_info(GNUTLS_STATE state)
186 const char *tmp;
187 unsigned char sesid[32];
188 int sesid_size, i;
190 /* print session_id */
191 gnutls_session_get_id(state, sesid, &sesid_size);
192 sprintf(tmp2, "\n<p>Session ID: <i>");
193 for (i = 0; i < sesid_size; i++)
194 sprintf(tmp2, "%.2X", sesid[i]);
195 sprintf(tmp2, "</i></p>\n");
197 /* Here unlike print_info() we use the kx algorithm to distinguish
198 * the functions to call.
201 /* print srp specific data */
202 if (gnutls_kx_get(state) == GNUTLS_KX_SRP) {
203 sprintf(tmp2, "<p>Connected as user '%s'.</p>\n",
204 gnutls_srp_server_get_username(state));
207 if (gnutls_kx_get(state) == GNUTLS_KX_ANON_DH) {
208 sprintf(tmp2,
209 "<p> Connect using anonymous DH (prime of %d bits)</p>\n",
210 gnutls_dh_get_prime_bits(state));
213 /* print state information */
214 strcat(http_buffer, "<P>\n");
216 tmp = gnutls_protocol_get_name(gnutls_protocol_get_version(state));
217 sprintf(tmp2, "Protocol version: <b>%s</b><br>\n", tmp);
219 if (gnutls_auth_get_type(state) == GNUTLS_CRD_CERTIFICATE) {
220 tmp = gnutls_cert_type_get_name(gnutls_cert_type_get(state));
221 sprintf(tmp2, "Certificate Type: <b>%s</b><br>\n", tmp);
224 tmp = gnutls_kx_get_name(gnutls_kx_get(state));
225 sprintf(tmp2, "Key Exchange: <b>%s</b><br>\n", tmp);
227 if (gnutls_kx_get(state) == GNUTLS_KX_DHE_RSA
228 || gnutls_kx_get(state) == GNUTLS_KX_DHE_DSS) {
229 sprintf(tmp2,
230 "Ephemeral DH using prime of <b>%d</b> bits.<br>\n",
231 gnutls_dh_get_prime_bits(state));
234 tmp = gnutls_compression_get_name(gnutls_compression_get(state));
235 sprintf(tmp2, "Compression: <b>%s</b><br>\n", tmp);
237 tmp = gnutls_cipher_get_name(gnutls_cipher_get(state));
238 sprintf(tmp2, "Cipher: <b>%s</b><br>\n", tmp);
240 tmp = gnutls_mac_get_name(gnutls_mac_get(state));
241 sprintf(tmp2, "MAC: <b>%s</b><br>\n", tmp);
243 strcat(http_buffer, "</P>\n");
245 return;
248 /* actually something like readline.
249 * if rnl!=1 then reads an http request in the form REQ\n\n
251 int read_request(GNUTLS_STATE state, char *data, int data_size, int rnl)
253 int n, rc, nl = 0;
254 char c, *ptr, p1 = 0, p2 = 0;
256 ptr = data;
257 for (n = 1; n < data_size; n++) {
258 do {
259 rc = gnutls_record_recv(state, &c, 1);
260 } while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
262 if (rc == 1) {
263 *ptr++ = c;
264 if (c == '\n' && rnl == 1)
265 break;
267 if (c == '\n' && p1 == '\r' && p2 == '\n') {
268 nl++;
269 if (nl == 1)
270 break;
272 p2 = p1;
273 p1 = c;
275 } else if (rc == 0) {
276 if (n == 1)
277 return 0;
278 else
279 break;
280 } else {
281 return rc;
285 *ptr = 0;
286 return n;
290 void check_alert(GNUTLS_STATE state, int ret)
292 int last_alert;
294 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED
295 || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
296 last_alert = gnutls_alert_get(state);
297 if (last_alert == GNUTLS_A_NO_RENEGOTIATION &&
298 ret == GNUTLS_E_WARNING_ALERT_RECEIVED)
299 printf
300 ("* Received NO_RENEGOTIATION alert. Client Does not support renegotiation.\n");
301 else
302 printf("* Received alert '%d'.\n", ret);
306 static void gaa_parser(int argc, char **argv);
308 int main(int argc, char **argv)
310 int err, listen_sd, i;
311 int sd, ret;
312 struct sockaddr_in sa_serv;
313 struct sockaddr_in sa_cli;
314 int client_len;
315 char topbuf[512];
316 GNUTLS_STATE state;
317 char buffer[MAX_BUF + 1];
318 int optval = 1;
319 char name[256];
321 signal(SIGPIPE, SIG_IGN);
323 gaa_parser(argc, argv);
325 if (http == 1) {
326 strcpy(name, "HTTP Server");
327 } else {
328 strcpy(name, "Echo Server");
331 if (gnutls_global_init() < 0) {
332 fprintf(stderr, "global state initialization error\n");
333 exit(1);
336 /* Note that servers must generate parameters for
337 * Diffie Hellman. See gnutls_dh_params_generate(), and
338 * gnutls_dh_params_set().
340 if (generate != 0)
341 generate_dh_primes();
343 if (gnutls_certificate_allocate_sc(&cert_cred) < 0) {
344 fprintf(stderr, "memory error\n");
345 exit(1);
348 if (x509_cafile != NULL)
349 if (gnutls_certificate_set_x509_trust_file
350 (cert_cred, x509_cafile, x509_crlfile, GNUTLS_X509_FMT_DER) < 0) {
351 fprintf(stderr, "Error reading '%s'\n", x509_cafile);
352 exit(1);
355 if (pgp_keyring != NULL) {
356 ret =
357 gnutls_certificate_set_openpgp_keyring_file(cert_cred, pgp_keyring);
358 if (ret < 0) {
359 fprintf(stderr, "Error setting the OpenPGP keyring file\n");
363 if (pgp_trustdb != NULL) {
364 gnutls_certificate_set_openpgp_trustdb(cert_cred, pgp_trustdb);
367 if (pgp_certfile != NULL)
368 if (gnutls_certificate_set_openpgp_key_file
369 (cert_cred, pgp_certfile, pgp_keyfile) < 0) {
370 fprintf(stderr,
371 "Error while reading the OpenPGP key pair ('%s', '%s')\n",
372 pgp_certfile, pgp_keyfile);
375 gnutls_certificate_set_openpgp_keyserver(cert_cred, pgp_keyserver, 0);
377 if (x509_certfile != NULL)
378 if (gnutls_certificate_set_x509_key_file
379 (cert_cred, x509_certfile, x509_keyfile, GNUTLS_X509_FMT_DER) < 0) {
380 fprintf(stderr,
381 "Error reading '%s' or '%s'\n", x509_certfile,
382 x509_keyfile);
383 exit(1);
386 if (generate != 0)
387 if (gnutls_certificate_set_dh_params(cert_cred, dh_params) < 0) {
388 fprintf(stderr, "Error while setting DH parameters\n");
389 exit(1);
392 /* this is a password file (created with the included srpcrypt utility)
393 * Read README.crypt prior to using SRP.
395 gnutls_srp_allocate_server_sc(&srp_cred);
396 gnutls_srp_set_server_cred_file(srp_cred, srp_passwd, srp_passwd_conf);
398 gnutls_anon_allocate_server_sc(&dh_cred);
399 if (generate != 0)
400 gnutls_anon_set_server_dh_params(dh_cred, dh_params);
402 listen_sd = socket(AF_INET, SOCK_STREAM, 0);
403 ERR(listen_sd, "socket");
405 memset(&sa_serv, '\0', sizeof(sa_serv));
406 sa_serv.sin_family = AF_INET;
407 sa_serv.sin_addr.s_addr = INADDR_ANY;
408 sa_serv.sin_port = htons(port); /* Server Port number */
410 setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
411 err = bind(listen_sd, (SA *) & sa_serv, sizeof(sa_serv));
412 ERR(err, "bind");
413 err = listen(listen_sd, 1024);
414 ERR(err, "listen");
416 printf("%s ready. Listening to port '%d'.\n\n", name, port);
418 client_len = sizeof(sa_cli);
420 for (;;) {
421 state = initialize_state();
423 sd = accept(listen_sd, (SA *) & sa_cli, &client_len);
425 printf("- connection from %s, port %d\n",
426 inet_ntop(AF_INET, &sa_cli.sin_addr, topbuf,
427 sizeof(topbuf)), ntohs(sa_cli.sin_port));
430 gnutls_transport_set_ptr(state, sd);
431 do {
432 ret = gnutls_handshake(state);
433 } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
435 if (ret < 0) {
436 close(sd);
437 gnutls_deinit(state);
438 fprintf(stderr,
439 "*** Handshake has failed (%s)\n\n",
440 gnutls_strerror(ret));
441 check_alert(state, ret);
442 continue;
444 printf("- Handshake was completed\n");
446 print_info(state);
448 i = 0;
449 for (;;) {
450 bzero(buffer, MAX_BUF + 1);
451 ret = read_request(state, buffer, MAX_BUF, (http == 0) ? 1 : 2);
453 if (gnutls_error_is_fatal(ret) == 1 || ret == 0) {
454 fflush(stdout);
455 if (ret == 0) {
456 printf("\n- Peer has closed the GNUTLS connection\n");
457 fflush(stdout);
458 break;
459 } else {
460 fprintf(stderr,
461 "\n*** Received corrupted data(%d). Closing the connection.\n\n",
462 ret);
463 break;
468 if (ret > 0) {
469 if (http == 0) {
470 printf("* Read %d bytes from client.\n", strlen(buffer));
471 do {
472 ret = gnutls_record_send(state, buffer, strlen(buffer));
473 } while (ret ==
474 GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
475 printf("* Wrote %d bytes to client.\n", ret);
476 } else {
477 strcpy(http_buffer, HTTP_BEGIN);
478 peer_print_info(state);
479 strcat(http_buffer, HTTP_END);
480 do {
481 ret =
482 gnutls_record_send(state,
483 http_buffer, strlen(http_buffer));
484 } while (ret ==
485 GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
487 printf("- Served request. Closing connection.\n");
488 break;
491 i++;
492 #ifdef RENEGOTIATE
493 if (i == 20) {
494 do {
495 ret = gnutls_rehandshake(state);
496 } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
498 printf("* Requesting rehandshake.\n");
499 /* continue handshake proccess */
500 do {
501 ret = gnutls_handshake(state);
502 } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
503 printf("* Rehandshake returned %d\n", ret);
505 #endif
507 check_alert(state, ret);
509 if (http != 0) {
510 break; /* close the connection */
513 printf("\n");
514 do {
515 ret = gnutls_bye(state, GNUTLS_SHUT_WR);
516 } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
517 /* do not wait for
518 * the peer to close the connection.
520 close(sd);
521 gnutls_deinit(state);
524 close(listen_sd);
526 gnutls_certificate_free_sc(cert_cred);
527 gnutls_srp_free_server_sc(srp_cred);
528 gnutls_anon_free_server_sc(dh_cred);
530 gnutls_global_deinit();
532 return 0;
536 #define DEFAULT_X509_KEYFILE "x509/key.pem"
537 #define DEFAULT_X509_CERTFILE "x509/cert.pem"
539 #define DEFAULT_X509_KEYFILE2 "x509/key-dsa.pem"
540 #define DEFAULT_X509_CERTFILE2 "x509/cert-dsa.pem"
542 #define DEFAULT_PGP_KEYFILE "openpgp/sec.asc"
543 #define DEFAULT_PGP_CERTFILE "openpgp/pub.asc"
545 #define DEFAULT_X509_CAFILE "x509/ca.pem"
546 #define DEFAULT_X509_CRLFILE NULL;
548 #define DEFAULT_SRP_PASSWD "srp/tpasswd"
549 #define DEFAULT_SRP_PASSWD_CONF "srp/tpasswd.conf"
551 #undef DEBUG
553 static gaainfo info;
554 void gaa_parser(int argc, char **argv)
556 int i, j;
558 if (gaa(argc, argv, &info) != -1) {
559 fprintf(stderr,
560 "Error in the arguments. Use the --help or -h parameters to get more information.\n");
561 exit(1);
564 if (info.http == 0)
565 http = 0;
566 else
567 http = 1;
569 if (info.generate == 0)
570 generate = 0;
571 else
572 generate = 1;
574 port = info.port;
576 #ifdef DEBUG
577 if (info.x509_certfile != NULL)
578 x509_certfile = info.x509_certfile;
579 else
580 x509_certfile = DEFAULT_X509_CERTFILE;
582 if (info.x509_keyfile != NULL)
583 x509_keyfile = info.x509_keyfile;
584 else
585 x509_keyfile = DEFAULT_X509_KEYFILE;
587 if (info.x509_cafile != NULL)
588 x509_cafile = info.x509_certfile;
589 else
590 x509_cafile = DEFAULT_X509_CAFILE;
592 if (info.pgp_certfile != NULL)
593 pgp_certfile = info.pgp_certfile;
594 else
595 pgp_certfile = DEFAULT_PGP_CERTFILE;
597 if (info.pgp_keyfile != NULL)
598 pgp_keyfile = info.pgp_keyfile;
599 else
600 pgp_keyfile = DEFAULT_PGP_KEYFILE;
602 if (info.srp_passwd != NULL)
603 srp_passwd = info.srp_passwd;
604 else
605 srp_passwd = DEFAULT_SRP_PASSWD;
607 if (info.srp_passwd_conf != NULL)
608 srp_passwd_conf = info.srp_passwd_conf;
609 else
610 srp_passwd_conf = DEFAULT_SRP_PASSWD_CONF;
611 #else
612 x509_certfile = info.x509_certfile;
613 x509_keyfile = info.x509_keyfile;
614 x509_cafile = info.x509_cafile;
615 pgp_certfile = info.pgp_certfile;
616 pgp_keyfile = info.pgp_keyfile;
617 srp_passwd = info.srp_passwd;
618 srp_passwd_conf = info.srp_passwd_conf;
619 #endif
621 pgp_keyserver = info.pgp_keyserver;
622 pgp_keyring = info.pgp_keyring;
623 pgp_trustdb = info.pgp_trustdb;
625 if (info.proto != NULL && info.nproto > 0) {
626 for (j = i = 0; i < info.nproto; i++) {
627 if (strncasecmp(info.proto[i], "SSL", 3) == 0)
628 protocol_priority[j++] = GNUTLS_SSL3;
629 if (strncasecmp(info.proto[i], "TLS", 3) == 0)
630 protocol_priority[j++] = GNUTLS_TLS1;
632 protocol_priority[j] = 0;
635 if (info.ciphers != NULL && info.nciphers > 0) {
636 for (j = i = 0; i < info.nciphers; i++) {
637 if (strncasecmp(info.ciphers[i], "RIJ", 3) == 0)
638 cipher_priority[j++] = GNUTLS_CIPHER_RIJNDAEL_128_CBC;
639 if (strncasecmp(info.ciphers[i], "TWO", 3) == 0)
640 cipher_priority[j++] = GNUTLS_CIPHER_TWOFISH_128_CBC;
641 if (strncasecmp(info.ciphers[i], "3DE", 3) == 0)
642 cipher_priority[j++] = GNUTLS_CIPHER_3DES_CBC;
643 if (strncasecmp(info.ciphers[i], "ARC", 3) == 0)
644 cipher_priority[j++] = GNUTLS_CIPHER_ARCFOUR;
646 cipher_priority[j] = 0;
649 if (info.macs != NULL && info.nmacs > 0) {
650 for (j = i = 0; i < info.nmacs; i++) {
651 if (strncasecmp(info.macs[i], "MD5", 3) == 0)
652 mac_priority[j++] = GNUTLS_MAC_MD5;
653 if (strncasecmp(info.macs[i], "SHA", 3) == 0)
654 mac_priority[j++] = GNUTLS_MAC_SHA;
656 mac_priority[j] = 0;
659 if (info.ctype != NULL && info.nctype > 0) {
660 for (j = i = 0; i < info.nctype; i++) {
661 if (strncasecmp(info.ctype[i], "OPE", 3) == 0)
662 cert_type_priority[j++] = GNUTLS_CRT_OPENPGP;
663 if (strncasecmp(info.ctype[i], "X", 1) == 0)
664 cert_type_priority[j++] = GNUTLS_CRT_X509;
666 cert_type_priority[j] = 0;
669 if (info.kx != NULL && info.nkx > 0) {
670 for (j = i = 0; i < info.nkx; i++) {
671 if (strncasecmp(info.kx[i], "SRP", 3) == 0)
672 kx_priority[j++] = GNUTLS_KX_SRP;
673 if (strncasecmp(info.kx[i], "RSA", 3) == 0)
674 kx_priority[j++] = GNUTLS_KX_RSA;
675 if (strncasecmp(info.kx[i], "DHE_RSA", 7) == 0)
676 kx_priority[j++] = GNUTLS_KX_DHE_RSA;
677 if (strncasecmp(info.kx[i], "DHE_DSS", 7) == 0)
678 kx_priority[j++] = GNUTLS_KX_DHE_DSS;
679 if (strncasecmp(info.kx[i], "ANON", 4) == 0)
680 kx_priority[j++] = GNUTLS_KX_ANON_DH;
682 kx_priority[j] = 0;
685 if (info.comp != NULL && info.ncomp > 0) {
686 for (j = i = 0; i < info.ncomp; i++) {
687 if (strncasecmp(info.comp[i], "NUL", 3) == 0)
688 comp_priority[j++] = GNUTLS_COMP_NULL;
689 if (strncasecmp(info.comp[i], "ZLI", 1) == 0)
690 comp_priority[j++] = GNUTLS_COMP_ZLIB;
692 comp_priority[j] = 0;