Skip to content

Commit 967f4dd

Browse files
committed
2 parents 56d0f60 + 577659a commit 967f4dd

File tree

14 files changed

+707
-37
lines changed

14 files changed

+707
-37
lines changed

docs/library/ussl.rst

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ Functions
1818
Takes a `stream` *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type),
1919
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
2020
an SSL context. Returned object has the usual `stream` interface methods like
21-
``read()``, ``write()``, etc. In MicroPython, the returned object does not expose
22-
socket interface and methods like ``recv()``, ``send()``. In particular, a
21+
``read()``, ``write()``, etc. as well as ``recv()``, ``send()``. In particular, a
2322
server-side SSL socket should be created from a normal socket returned from
2423
:meth:`~usocket.socket.accept()` on a non-SSL listening server socket.
2524

@@ -31,9 +30,14 @@ Functions
3130
- ``ca_certs``: root certificates to use for certificate checking.
3231
- ``server_hostname``: specifies the hostname of the server for verification purposes
3332
as well for SNI (Server Name Identification).
34-
- ``do_handshake``: if True, initiates the TLS handshake and waits for its completion;
35-
if False, proceeds without handshake and performs is with the first write making it
36-
non-blocking if asyncio is used, see git commit 9c7c082.
33+
- ``do_handshake``: determines whether the handshake is done as part of the ``wrap_socket``
34+
or whether it is deferred to be done as part of the initial reads or writes
35+
(there is no ``do_handshake`` method as in CPython).
36+
For blocking sockets doing the handshake immediately is standard. For non-blocking
37+
sockets (i.e. when the *sock* passed into ``wrap_socket`` is in non-blocking mode)
38+
the handshake should generally be deferred because otherwise ``wrap_socket`` blocks
39+
until it completes. Note that in AXTLS the handshake can be deferred until the first
40+
read or write but it then blocks until completion.
3741

3842
Depending on the underlying module implementation in a particular
3943
`MicroPython port`, some or all keyword arguments above may be not supported.

extmod/modussl_axtls.c

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,44 @@ struct ssl_args {
5454

5555
STATIC const mp_obj_type_t ussl_socket_type;
5656

57+
// Table of errors
58+
struct ssl_errs {
59+
int16_t errnum;
60+
const char *errstr;
61+
};
62+
STATIC const struct ssl_errs ssl_error_tab[] = {
63+
{ SSL_NOT_OK, "NOT_OK" },
64+
{ SSL_ERROR_DEAD, "DEAD" },
65+
{ SSL_ERROR_RECORD_OVERFLOW, "RECORD_OVERFLOW" },
66+
{ SSL_ERROR_SOCK_SETUP_FAILURE, "SOCK_SETUP_FAILURE" },
67+
{ SSL_ERROR_INVALID_HANDSHAKE, "INVALID_HANDSHAKE" },
68+
{ SSL_ERROR_INVALID_PROT_MSG, "INVALID_PROT_MSG" },
69+
{ SSL_ERROR_INVALID_HMAC, "INVALID_HMAC" },
70+
{ SSL_ERROR_INVALID_VERSION, "INVALID_VERSION" },
71+
{ SSL_ERROR_UNSUPPORTED_EXTENSION, "UNSUPPORTED_EXTENSION" },
72+
{ SSL_ERROR_INVALID_SESSION, "INVALID_SESSION" },
73+
{ SSL_ERROR_NO_CIPHER, "NO_CIPHER" },
74+
{ SSL_ERROR_INVALID_CERT_HASH_ALG, "INVALID_CERT_HASH_ALG" },
75+
{ SSL_ERROR_BAD_CERTIFICATE, "BAD_CERTIFICATE" },
76+
{ SSL_ERROR_INVALID_KEY, "INVALID_KEY" },
77+
{ SSL_ERROR_FINISHED_INVALID, "FINISHED_INVALID" },
78+
{ SSL_ERROR_NO_CERT_DEFINED, "NO_CERT_DEFINED" },
79+
{ SSL_ERROR_NO_CLIENT_RENOG, "NO_CLIENT_RENOG" },
80+
{ SSL_ERROR_NOT_SUPPORTED, "NOT_SUPPORTED" },
81+
{ 0, 0 },
82+
};
83+
84+
STATIC NORETURN void ussl_raise_error(int err) {
85+
for (int i=0; ssl_error_tab[i].errnum; i++) {
86+
if (ssl_error_tab[i].errnum == err) {
87+
//printf("AXTLS error: SSL_%s\n", ssl_error_tab[i].errstr);
88+
mp_raise_msg_varg(&mp_type_OSError, "AXTLS %d: %s", err, ssl_error_tab[i].errstr);
89+
}
90+
}
91+
mp_raise_msg_varg(&mp_type_OSError, "AXTLS %d", err);
92+
}
93+
94+
5795
STATIC mp_obj_ssl_socket_t *ussl_socket_new(mp_obj_t sock, struct ssl_args *args) {
5896
#if MICROPY_PY_USSL_FINALISER
5997
mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
@@ -104,12 +142,16 @@ STATIC mp_obj_ssl_socket_t *ussl_socket_new(mp_obj_t sock, struct ssl_args *args
104142
o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0, ext);
105143

106144
if (args->do_handshake.u_bool) {
107-
int res = ssl_handshake_status(o->ssl_sock);
108-
109-
if (res != SSL_OK) {
110-
printf("ssl_handshake_status: %d\n", res);
111-
ssl_display_error(res);
112-
mp_raise_OSError(MP_EIO);
145+
int r = ssl_handshake_status(o->ssl_sock);
146+
147+
if (r != SSL_OK) {
148+
ssl_display_error(r);
149+
if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) { // EOF
150+
r = MP_ENOTCONN;
151+
} else if (r == SSL_EAGAIN) {
152+
r = MP_EAGAIN;
153+
}
154+
ussl_raise_error(r);
113155
}
114156
}
115157

@@ -173,6 +215,22 @@ STATIC mp_uint_t ussl_socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int
173215
return size;
174216
}
175217

218+
STATIC mp_obj_t ussl_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
219+
size_t len = mp_obj_get_int(len_in);
220+
vstr_t vstr;
221+
vstr_init_len(&vstr, len);
222+
223+
int errcode;
224+
mp_uint_t ret = ussl_socket_read(self_in, vstr.buf, len, &errcode);
225+
if (ret == MP_STREAM_ERROR) {
226+
mp_raise_OSError(errcode);
227+
}
228+
229+
vstr.len = ret;
230+
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
231+
}
232+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(ussl_socket_recv_obj, ussl_socket_recv);
233+
176234
STATIC mp_uint_t ussl_socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
177235
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
178236

@@ -181,14 +239,43 @@ STATIC mp_uint_t ussl_socket_write(mp_obj_t o_in, const void *buf, mp_uint_t siz
181239
return MP_STREAM_ERROR;
182240
}
183241

184-
mp_int_t r = ssl_write(o->ssl_sock, buf, size);
242+
mp_int_t r;
243+
eagain:
244+
r = ssl_write(o->ssl_sock, buf, size);
245+
if (r == SSL_OK) {
246+
// see comment in read method
247+
if (o->blocking) {
248+
goto eagain;
249+
} else {
250+
r = SSL_EAGAIN;
251+
}
252+
}
185253
if (r < 0) {
254+
if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) {
255+
return 0; // EOF
256+
}
257+
if (r == SSL_EAGAIN) {
258+
r = MP_EAGAIN;
259+
}
186260
*errcode = r;
187261
return MP_STREAM_ERROR;
188262
}
189263
return r;
190264
}
191265

266+
STATIC mp_obj_t ussl_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
267+
mp_buffer_info_t bufinfo;
268+
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
269+
270+
int errcode;
271+
mp_uint_t r = ussl_socket_write(self_in, bufinfo.buf, bufinfo.len, &errcode);
272+
if (r == MP_STREAM_ERROR) {
273+
mp_raise_OSError(errcode);
274+
}
275+
return mp_obj_new_int(r);
276+
}
277+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(ussl_socket_send_obj, ussl_socket_send);
278+
192279
STATIC mp_uint_t ussl_socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
193280
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
194281
if (request == MP_STREAM_CLOSE && self->ssl_sock != NULL) {
@@ -216,7 +303,9 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
216303
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
217304
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
218305
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
306+
{ MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&ussl_socket_recv_obj) },
219307
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
308+
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&ussl_socket_send_obj) },
220309
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&ussl_socket_setblocking_obj) },
221310
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
222311
#if MICROPY_PY_USSL_FINALISER

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy