3 Minimal MatrixSSL Helper
4 Copyright (C) 2006-2009 Jonathan Zarate
6 Licensed under GNU GPL v2 or later.
16 #include <sys/socket.h>
23 #include "../matrixssl/matrixSsl.h"
29 #define _dprintf(args...) do { } while(0)
30 // #define _dprintf cprintf
35 sslBuf_t inbuf
; // buffer for decoded data
36 sslBuf_t insock
; // buffer for recv() data
37 sslBuf_t outsock
; // buffer for send() data
42 static sslKeys_t
*keys
;
46 inline int sb_used(sslBuf_t
*b
)
48 return b
->end
- b
->start
;
51 inline int sb_unused(sslBuf_t
*b
)
53 return (b
->buf
+ b
->size
) - b
->end
;
56 static void sb_free(sslBuf_t
*b
)
59 b
->start
= b
->end
= b
->buf
= NULL
;
63 // - expects ->buf to be valid or NULL
64 // - malloc error is fatal
65 static int sb_alloc(sslBuf_t
*b
, int size
)
70 if ((p
= malloc(size
)) == NULL
) {
71 syslog(LOG_CRIT
, "Not enough memory");
74 b
->start
= b
->end
= b
->buf
= p
;
79 // - expects ->buf to be valid or NULL
80 // - malloc error is fatal
81 static int sb_realloc(sslBuf_t
*b
, int size
)
85 if ((p
= realloc(b
->buf
, size
)) == NULL
) {
86 syslog(LOG_CRIT
, "Not enough memory");
89 b
->start
= p
+ (b
->start
- b
->buf
);
90 b
->end
= p
+ (b
->end
- b
->buf
);
96 static void sb_pack(sslBuf_t
*b
)
100 if (b
->start
== b
->end
) {
101 b
->start
= b
->end
= b
->buf
;
105 memmove(b
->buf
, b
->start
, n
);
111 static int sb_read(sslBuf_t
*b
, unsigned char *buf
, int len
)
114 n
= min(sb_used(b
), len
);
115 memcpy(buf
, b
->start
, n
);
117 if (b
->start
== b
->end
) b
->start
= b
->end
= b
->buf
;
122 // -----------------------------------------------------------------------------
125 static ssize_t
mssl_read(void *cookie
, char *buf
, size_t len
)
127 mssl_cookie_t
*kuki
= cookie
;
129 unsigned char err
, alevel
, adesc
;
132 _dprintf("%s\n", __FUNCTION__
);
134 if (kuki
->inbuf
.buf
) {
135 if (kuki
->inbuf
.start
< kuki
->inbuf
.end
) {
136 r
= sb_read(&kuki
->inbuf
, buf
, len
);
137 _dprintf("sb_read r=%d\n", r
);
140 sb_free(&kuki
->inbuf
);
143 sb_pack(&kuki
->insock
);
145 if (kuki
->insock
.start
== kuki
->insock
.end
) {
149 while ((r
= recv(kuki
->sd
, kuki
->insock
.end
, sb_unused(&kuki
->insock
), 0)) == -1) {
150 if (errno
!= EINTR
) {
151 _dprintf("recv failed errno=%d\n", errno
);
159 kuki
->insock
.end
+= r
;
162 sb_alloc(&kuki
->inbuf
, len
);
165 _dprintf("DECODE\n");
171 switch (matrixSslDecode(kuki
->ssl
, &kuki
->insock
, &kuki
->inbuf
, &err
, &alevel
, &adesc
)) {
173 _dprintf("SSL_SUCCESS\n");
175 case SSL_PROCESS_DATA
:
176 _dprintf("SSL_PROCESS_DATA\n");
178 r
= sb_used(&kuki
->inbuf
);
179 _dprintf(" r = %d len = %d\n", r
, len
);
181 memcpy(buf
, kuki
->inbuf
.start
, r
);
182 kuki
->inbuf
.start
+= r
;
184 case SSL_SEND_RESPONSE
:
185 _dprintf("SSL_SEND_RESPONSE\n");
186 _dprintf("send %d\n", sb_used(&kuki
->inbuf
));
188 while ((r
= send(kuki
->sd
, kuki
->inbuf
.start
, sb_used(&kuki
->inbuf
), MSG_NOSIGNAL
)) == -1) {
189 if (errno
!= EINTR
) {
190 _dprintf("send error\n");
194 kuki
->inbuf
.start
+= r
;
195 if (kuki
->inbuf
.start
!= kuki
->inbuf
.end
) _dprintf("inbuf.start != inbuf.end\n");
196 kuki
->inbuf
.start
= kuki
->inbuf
.end
= kuki
->inbuf
.buf
;
199 _dprintf("ssl error %d\n", err
);
201 if (kuki
->inbuf
.start
< kuki
->inbuf
.end
) {
202 send(kuki
->sd
, kuki
->inbuf
.start
, sb_used(&kuki
->inbuf
), MSG_NOSIGNAL
);
207 _dprintf("SSL_ALERT\n");
209 if (adesc
== SSL_ALERT_CLOSE_NOTIFY
) {
214 _dprintf("ssl closing on alert level=%d desc=%d\n", alevel
, adesc
);
218 _dprintf("SSL_PARTIAL insock.size=%d %d\n", kuki
->insock
.size
, SSL_MAX_BUF_SIZE
);
220 if ((kuki
->insock
.start
== kuki
->insock
.buf
) && (kuki
->insock
.end
== (kuki
->insock
.buf
+ kuki
->insock
.size
))) {
221 if (kuki
->insock
.size
> SSL_MAX_BUF_SIZE
) return -1;
222 sb_realloc(&kuki
->insock
, kuki
->insock
.size
* 2);
225 if (kuki
->inbuf
.start
!= kuki
->inbuf
.end
) {
226 _dprintf("!! inbuf.start != inbuf.end\n");
229 sb_free(&kuki
->inbuf
);
232 _dprintf("SSL_FULL\n");
234 sb_alloc(&kuki
->inbuf
, kuki
->inbuf
.size
* 2);
241 static ssize_t
mssl_write(void *cookie
, const char *buf
, size_t len
)
243 mssl_cookie_t
*kuki
= cookie
;
247 _dprintf("%s\n", __FUNCTION__
);
250 sb_pack(&kuki
->outsock
);
251 if (buf
== NULL
) goto PUMP
;
254 switch (matrixSslEncode(kuki
->ssl
, (unsigned char *)buf
, len
, &kuki
->outsock
)) {
257 _dprintf("SSL_ERROR\n");
260 if (kuki
->outsock
.size
> SSL_MAX_BUF_SIZE
) {
262 _dprintf("outsock.size > max\n");
265 sb_realloc(&kuki
->outsock
, kuki
->outsock
.size
* 2);
270 while ((r
= send(kuki
->sd
, kuki
->outsock
.start
, sb_used(&kuki
->outsock
), MSG_NOSIGNAL
)) == -1) {
271 if (errno
!= EINTR
) {
272 _dprintf("send error %d\n", errno
);
276 kuki
->outsock
.start
+= r
;
279 if (kuki
->outsock
.start
< kuki
->outsock
.end
) {
280 _dprintf("start < end\n");
287 static int mssl_seek(void *cookie
, __offmax_t
*pos
, int whence
)
289 _dprintf("%s()\n", __FUNCTION__
);
294 static int mssl_close(void *cookie
)
296 mssl_cookie_t
*kuki
= cookie
;
298 _dprintf("%s()\n", __FUNCTION__
);
303 if (kuki
->outsock
.buf
) {
304 mssl_write(kuki
, NULL
, 0);
306 kuki
->outsock
.start
= kuki
->outsock
.end
= kuki
->outsock
.buf
;
307 matrixSslEncodeClosureAlert(kuki
->ssl
, &kuki
->outsock
);
308 fcntl(kuki
->sd
, F_SETFL
, fcntl(kuki
->sd
, F_GETFL
) | O_NONBLOCK
);
309 send(kuki
->sd
, kuki
->outsock
.start
, sb_used(&kuki
->outsock
), MSG_NOSIGNAL
);
312 matrixSslDeleteSession(kuki
->ssl
);
315 sb_free(&kuki
->inbuf
);
316 sb_free(&kuki
->insock
);
317 sb_free(&kuki
->outsock
);
323 static int cert_valid(sslCertInfo_t
*cert
, void *arg
)
325 // note: no validation!
326 return SSL_ALLOW_ANON_CONNECTION
;
329 static const cookie_io_functions_t mssl
= {
330 mssl_read
, mssl_write
, mssl_seek
, mssl_close
333 static FILE *_ssl_fopen(int sd
, int client
)
335 unsigned char buf
[1024];
341 _dprintf("%s()\n", __FUNCTION__
);
343 if ((kuki
= calloc(1, sizeof(*kuki
))) == NULL
) {
349 if (matrixSslNewSession(&kuki
->ssl
, keys
, NULL
, client
? 0 : SSL_FLAGS_SERVER
) < 0) {
350 _dprintf("%s: matrixSslNewSession failed\n", __FUNCTION__
);
354 sb_alloc(&kuki
->insock
, 1024);
355 sb_alloc(&kuki
->outsock
, 2048);
358 matrixSslSetCertValidator(kuki
->ssl
, cert_valid
, NULL
);
360 n
= matrixSslEncodeClientHello(kuki
->ssl
, &kuki
->outsock
, 0);
362 _dprintf("%s: matrixSslEncodeClientHello failed\n", __FUNCTION__
);
365 if (mssl_write(kuki
, NULL
, 0) <= 0) {
366 _dprintf("%s: error while writing HELLO\n", __FUNCTION__
);
372 r
= mssl_read(kuki
, buf
, sizeof(buf
));
375 _dprintf("%s: end reached\n", __FUNCTION__
);
379 if (matrixSslHandshakeIsComplete(kuki
->ssl
) == 0) {
380 _dprintf("%s: =0 goto more\n", __FUNCTION__
);
383 if ((f
= fopencookie(kuki
, "r+", mssl
)) == NULL
) {
384 _dprintf("%s: fopencookie failed\n", __FUNCTION__
);
390 _dprintf("%s: read error r=%d errno=%d\n", __FUNCTION__
, r
, errno
);
398 FILE *ssl_server_fopen(int sd
)
400 _dprintf("%s()\n", __FUNCTION__
);
401 return _ssl_fopen(sd
, 0);
404 FILE *ssl_client_fopen(int sd
)
406 _dprintf("%s()\n", __FUNCTION__
);
407 return _ssl_fopen(sd
, 1);
410 int ssl_init(char *cert
, char *priv
)
412 if (matrixSslOpen() < 0) {
413 _dprintf("matrixSslOpen failed");
416 if (matrixSslReadKeys(&keys
, cert
, priv
, NULL
, NULL
) < 0) {
418 _dprintf("matrixSslReadKeys failed");