*/
#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#include <libubox/ustream.h>
#include "ustream-ssl.h"
return;
if (__ustream_ssl_connect(us) == U_SSL_OK) {
+
+ /* __ustream_ssl_connect() will also return U_SSL_OK when certificate
+ * verification failed!
+ *
+ * Applications may register a custom .notify_verify_error callback in the
+ * struct ustream_ssl which is called upon verification failures, but there
+ * is no straight forward way for the callback to terminate the connection
+ * initiation right away, e.g. through a true or false return value.
+ *
+ * Instead, existing implementations appear to set .eof field of the underlying
+ * ustream in the hope that this inhibits further operations on the stream.
+ *
+ * Declare this informal behaviour "official" and check for the state of the
+ * .eof member after __ustream_ssl_connect() returned, and do not write the
+ * pending data if it is set to true.
+ */
+
+ if (us->stream.eof)
+ return;
+
us->connected = true;
if (us->notify_connected)
us->notify_connected(us);
+ ustream_write_pending(&us->stream);
}
}
uloop_timeout_cancel(&us->error_timer);
__ustream_ssl_session_free(us->ssl);
+ free(us->peer_cn);
+
us->ctx = NULL;
us->ssl = NULL;
us->conn = NULL;
+ us->peer_cn = NULL;
us->connected = false;
us->error = false;
+ us->valid_cert = false;
+ us->valid_cn = false;
}
static bool ustream_ssl_poll(struct ustream *s)
bool fd_poll;
fd_poll = ustream_poll(us->conn);
- return __ustream_ssl_poll(s) || fd_poll;
+ return __ustream_ssl_poll(us->conn) || fd_poll;
}
static void ustream_ssl_stream_init(struct ustream_ssl *us)
ustream_init_defaults(s);
}
-static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, void *ctx, bool server)
+static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, struct ustream_ssl_ctx *ctx, bool server)
{
us->error_timer.cb = ustream_ssl_error_cb;
us->server = server;
us->conn = conn;
us->ctx = ctx;
+#if defined(HAVE_WOLFSSL) && defined(NO_WOLFSSL_SSLSETIO_SEND_RECV)
+ ustream_set_io(ctx, NULL, conn);
+#endif
us->ssl = __ustream_ssl_session_new(us->ctx);
if (!us->ssl)
return -ENOMEM;
conn->next = &us->stream;
ustream_set_io(ctx, us->ssl, conn);
ustream_ssl_stream_init(us);
+
+ if (us->server_name)
+ __ustream_ssl_set_server_name(us);
+
ustream_ssl_check_conn(us);
return 0;
}
+static int _ustream_ssl_set_peer_cn(struct ustream_ssl *us, const char *name)
+{
+ us->peer_cn = strdup(name);
+ __ustream_ssl_update_peer_cn(us);
+
+ return 0;
+}
+
const struct ustream_ssl_ops ustream_ssl_ops = {
.context_new = __ustream_ssl_context_new,
.context_set_crt_file = __ustream_ssl_set_crt_file,
.context_set_key_file = __ustream_ssl_set_key_file,
+ .context_add_ca_crt_file = __ustream_ssl_add_ca_crt_file,
+ .context_set_ciphers = __ustream_ssl_set_ciphers,
.context_free = __ustream_ssl_context_free,
.init = _ustream_ssl_init,
+ .set_peer_cn = _ustream_ssl_set_peer_cn,
};