Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / doc / examples / ex-serv-pgp.c
1 /* This example code is placed in the public domain. */
2
3 #ifdef HAVE_CONFIG_H
4 #include <config.h>
5 #endif
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <errno.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <arpa/inet.h>
13 #include <netinet/in.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <gnutls/gnutls.h>
17 #include <gnutls/openpgp.h>
18
19 #define KEYFILE "secret.asc"
20 #define CERTFILE "public.asc"
21 #define RINGFILE "ring.gpg"
22
23 /* This is a sample TLS 1.0-OpenPGP echo server.
24  */
25
26
27 #define SOCKET_ERR(err,s) if(err==-1) {perror(s);return(1);}
28 #define MAX_BUF 1024
29 #define PORT 5556               /* listen to 5556 port */
30
31 /* These are global */
32 gnutls_dh_params_t dh_params;
33
34 static int generate_dh_params(void)
35 {
36         unsigned int bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH,
37                                                         GNUTLS_SEC_PARAM_LEGACY);
38
39         /* Generate Diffie-Hellman parameters - for use with DHE
40          * kx algorithms. These should be discarded and regenerated
41          * once a day, once a week or once a month. Depending on the
42          * security requirements.
43          */
44         gnutls_dh_params_init(&dh_params);
45         gnutls_dh_params_generate2(dh_params, bits);
46
47         return 0;
48 }
49
50 int main(void)
51 {
52         int err, listen_sd;
53         int sd, ret;
54         struct sockaddr_in sa_serv;
55         struct sockaddr_in sa_cli;
56         socklen_t client_len;
57         char topbuf[512];
58         gnutls_session_t session;
59         gnutls_certificate_credentials_t cred;
60         char buffer[MAX_BUF + 1];
61         int optval = 1;
62         char name[256];
63
64         strcpy(name, "Echo Server");
65
66         if (gnutls_check_version("3.1.4") == NULL) {
67                 fprintf(stderr, "GnuTLS 3.1.4 or later is required for this example\n");
68                 exit(1);
69         }
70
71         /* for backwards compatibility with gnutls < 3.3.0 */
72         gnutls_global_init();
73
74         gnutls_certificate_allocate_credentials(&cred);
75         gnutls_certificate_set_openpgp_keyring_file(cred, RINGFILE,
76                                                     GNUTLS_OPENPGP_FMT_BASE64);
77
78         gnutls_certificate_set_openpgp_key_file(cred, CERTFILE, KEYFILE,
79                                                 GNUTLS_OPENPGP_FMT_BASE64);
80
81         generate_dh_params();
82
83         gnutls_certificate_set_dh_params(cred, dh_params);
84
85         /* Socket operations
86          */
87         listen_sd = socket(AF_INET, SOCK_STREAM, 0);
88         SOCKET_ERR(listen_sd, "socket");
89
90         memset(&sa_serv, '\0', sizeof(sa_serv));
91         sa_serv.sin_family = AF_INET;
92         sa_serv.sin_addr.s_addr = INADDR_ANY;
93         sa_serv.sin_port = htons(PORT); /* Server Port number */
94
95         setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
96                    sizeof(int));
97
98         err =
99             bind(listen_sd, (struct sockaddr *) &sa_serv, sizeof(sa_serv));
100         SOCKET_ERR(err, "bind");
101         err = listen(listen_sd, 1024);
102         SOCKET_ERR(err, "listen");
103
104         printf("%s ready. Listening to port '%d'.\n\n", name, PORT);
105
106         client_len = sizeof(sa_cli);
107         for (;;) {
108                 gnutls_init(&session, GNUTLS_SERVER);
109                 gnutls_priority_set_direct(session,
110                                            "NORMAL:+CTYPE-OPENPGP", NULL);
111
112                 /* request client certificate if any.
113                  */
114                 gnutls_certificate_server_set_request(session,
115                                                       GNUTLS_CERT_REQUEST);
116
117                 sd = accept(listen_sd, (struct sockaddr *) &sa_cli,
118                             &client_len);
119
120                 printf("- connection from %s, port %d\n",
121                        inet_ntop(AF_INET, &sa_cli.sin_addr, topbuf,
122                                  sizeof(topbuf)), ntohs(sa_cli.sin_port));
123
124                 gnutls_transport_set_int(session, sd);
125                 ret = gnutls_handshake(session);
126                 if (ret < 0) {
127                         close(sd);
128                         gnutls_deinit(session);
129                         fprintf(stderr,
130                                 "*** Handshake has failed (%s)\n\n",
131                                 gnutls_strerror(ret));
132                         continue;
133                 }
134                 printf("- Handshake was completed\n");
135
136                 /* see the Getting peer's information example */
137                 /* print_info(session); */
138
139                 for (;;) {
140                         ret = gnutls_record_recv(session, buffer, MAX_BUF);
141
142                         if (ret == 0) {
143                                 printf
144                                     ("\n- Peer has closed the GnuTLS connection\n");
145                                 break;
146                         } else if (ret < 0
147                                    && gnutls_error_is_fatal(ret) == 0) {
148                                 fprintf(stderr, "*** Warning: %s\n",
149                                         gnutls_strerror(ret));
150                         } else if (ret < 0) {
151                                 fprintf(stderr, "\n*** Received corrupted "
152                                         "data(%d). Closing the connection.\n\n",
153                                         ret);
154                                 break;
155                         } else if (ret > 0) {
156                                 /* echo data back to the client
157                                  */
158                                 gnutls_record_send(session, buffer, ret);
159                         }
160                 }
161                 printf("\n");
162                 /* do not wait for the peer to close the connection.
163                  */
164                 gnutls_bye(session, GNUTLS_SHUT_WR);
165
166                 close(sd);
167                 gnutls_deinit(session);
168
169         }
170         close(listen_sd);
171
172         gnutls_certificate_free_credentials(cred);
173
174         gnutls_global_deinit();
175
176         return 0;
177
178 }