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 (®ifds);
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, ®ifds);
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, ®ifds);
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