1 /*
2  * This file is part of the Sofia-SIP package
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  *
6  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <string.h>
31 
32 #include "ssl.h"
33 #include "tls.h"
34 
35 typedef int (*IO_HANDLER)(int i);
36 
37 typedef struct __tls_mngr {
38   int         sock;
39   TLS_CONTEXT ctx;
40   IO_HANDLER  handler;
41 } TLS_MNGR;
42 
43 static TLS_MNGR tls_mngr[100] = {{0}};
44 static int mngr_size = 0;
45 static int width = 0;
46 static char *file_prefix = "";
47 static fd_set regifds;
48 static int master_socket = 0;
49 
init_event_mngr(void)50 void init_event_mngr (void)
51 {
52   mngr_size = 0;
53   FD_ZERO (&regifds);
54 }
55 
tls_setblocking(int s,int blocking)56 int tls_setblocking(int s, int blocking)
57 {
58   unsigned mode = fcntl(s, F_GETFL, 0);
59 
60   if (mode < 0)
61      return -1;
62 
63   if (blocking)
64     mode &= ~(O_NDELAY | O_NONBLOCK);
65   else
66     mode |= O_NDELAY | O_NONBLOCK;
67 
68   return fcntl(s, F_SETFL, mode);
69 }
70 
regi_sock(int sock,TLS_CONTEXT ctx,IO_HANDLER handler)71 void regi_sock (int sock, TLS_CONTEXT ctx, IO_HANDLER handler)
72 {
73   FD_SET (sock, &regifds);
74 
75   if (sock + 1 > width)
76     width = sock + 1;
77 
78   tls_mngr[mngr_size].sock = sock;
79   tls_mngr[mngr_size].ctx = ctx;
80   tls_mngr[mngr_size].handler = handler;
81   mngr_size++;
82 
83   tls_setblocking(sock, 0);
84 
85   printf("socket %d registered, ctx = %p, mngr_size = %d, width = %d\n",
86          sock, ctx, mngr_size, width);
87 }
88 
get_width(void)89 int get_width (void)
90 {
91   int i;
92   int lwidth = 1;
93 
94   for (i = 0; i < mngr_size; i++) {
95     if (tls_mngr[i].sock + 1 > lwidth)
96       lwidth = tls_mngr[i].sock + 1;
97   }
98 
99   return lwidth;
100 }
101 
tls_read_buffer(TLS_MNGR mngr,char * buf,int size)102 int tls_read_buffer(TLS_MNGR mngr, char *buf, int size)
103 {
104   int bytes = 0;
105   TLS_CONTEXT ctx = mngr.ctx;
106 
107   do {
108     int ret = tls_read(ctx, buf + bytes, size - bytes);
109     int err = tls_get_error(ctx, ret);
110 
111     printf("tls_read returned %d\n", ret);
112 
113     switch (err) {
114     case SSL_ERROR_NONE:
115       bytes += ret;
116       break;
117 
118     case SSL_ERROR_WANT_READ:
119       printf("ssl error want read\n");
120       return bytes;
121       break;
122 
123     case SSL_ERROR_WANT_WRITE:
124       break;
125 
126     case SSL_ERROR_ZERO_RETURN:
127       printf("shutdown\n");
128       tls_shutdown(ctx);
129       return bytes;
130 
131     case SSL_ERROR_SYSCALL:
132       perror("tls_syscall");
133       tls_shutdown(ctx);
134       FD_CLR(mngr.sock, &regifds);
135       return bytes;
136 
137     default:
138       printf("TLS error code %d\n", err);
139       return bytes;
140     }
141 
142     if (tls_pending(ctx)) {
143       printf("read pending\n");
144     }
145 
146   } while (tls_pending(ctx));
147 
148   printf("normal read %d bytes\n", bytes);
149   return bytes;
150 }
151 
tls_slave_handler(int i)152 int tls_slave_handler(int i)
153 {
154   unsigned char buf[50000];
155   char fname[100];
156   FILE *fp;
157 
158   int bytes = tls_read_buffer(tls_mngr[i], buf, sizeof(buf));
159 
160   printf("buffer read %d bytes\n", bytes);
161 
162   if (bytes > 0) {
163     sprintf(fname, "%s%02d.txt", file_prefix, i);
164     fp = fopen(fname, "a");
165 
166     if (fp == NULL)
167       perror("tls_slave_handler fopen");
168 
169     else {
170       int ret = fwrite(buf, sizeof(char), bytes, fp);
171 
172       if (ret != bytes)
173         perror("tls_slave_handler write");
174 
175       fclose(fp);
176     }
177   }
178 
179   return 0;
180 }
181 
tls_master_handler(int i)182 int tls_master_handler(int i)
183 {
184   TLS_CONTEXT ctx_slave;
185   TLS_ISSUES tls_issues = {0};
186   int         sock;
187 
188   printf("tls_master_handler\n");
189 
190   tls_issues.master_socket = master_socket;
191 
192   sock = init_tls_slave(tls_issues, tls_mngr[i].ctx, &ctx_slave);
193 
194   if (sock < 0) {
195     perror("init_tls_slave");
196     return -1;
197   }
198 
199   regi_sock(sock, ctx_slave, tls_slave_handler);
200 
201   return 0;
202 }
203 
event_mngr()204 int event_mngr ()
205 {
206   struct timeval tv;
207   int            retv;
208   int            i;
209   fd_set readfds;
210 
211   tv.tv_sec = 5;
212   tv.tv_usec = 0;
213 
214   readfds = regifds;
215 
216   retv = select(width, &readfds, NULL, NULL, &tv);
217   printf("select returned %d\n", retv);
218 
219   if (retv > 0) {
220     for (i=0; i < mngr_size; i++) {
221       if (FD_ISSET(tls_mngr[i].sock, &readfds)) {
222         tls_mngr[i].handler(i);
223       }
224     }
225   }
226 
227   if (retv < 0)
228     perror("select");
229 
230   return retv;
231 }
232 
main(int argc,char * argv[])233 int main (int argc, char *argv[])
234 {
235   TLS_ISSUES  tls_issues = {0};
236   TLS_CONTEXT ctx;
237   fd_set readfds;
238 
239   if (argc != 2) {
240     printf("Usage: tls_test_server <file prefix>\n");
241     exit(0);
242   }
243 
244   file_prefix = strdup(argv[1]);
245 
246   init_event_mngr();
247 
248   if (init_tls_master(&master_socket,
249                       tls_issues,
250                       &ctx) < 0) {
251     printf("init_tls_master failed\n");
252     exit (1);
253   }
254 
255   regi_sock(master_socket, ctx, tls_master_handler);
256 
257   for (;;) {
258     readfds = regifds;
259     event_mngr();
260     usleep(100000L);
261   }
262 
263   return 0;
264 }
265