forked from adafruit/circuitpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSSLContext.c
More file actions
210 lines (172 loc) · 8.66 KB
/
Copy pathSSLContext.c
File metadata and controls
210 lines (172 loc) · 8.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <string.h>
#include "extmod/vfs.h"
#include "py/objtuple.h"
#include "py/objlist.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "shared-bindings/ssl/SSLContext.h"
//| class SSLContext:
//| """Settings related to SSL that can be applied to a socket by wrapping it.
//| This is useful to provide SSL certificates to specific connections
//| rather than all of them."""
//|
static mp_obj_t ssl_sslcontext_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
ssl_sslcontext_obj_t *s = mp_obj_malloc(ssl_sslcontext_obj_t, &ssl_sslcontext_type);
common_hal_ssl_sslcontext_construct(s);
return MP_OBJ_FROM_PTR(s);
}
//| def load_cert_chain(self, certfile: str, keyfile: str) -> None:
//| """Load a private key and the corresponding certificate.
//|
//| The certfile string must be the path to a single file in PEM format
//| containing the certificate as well as any number of CA certificates
//| needed to establish the certificate's authenticity. The keyfile string
//| must point to a file containing the private key.
//| """
//|
static void get_file_contents(mp_obj_t name_obj, mp_buffer_info_t *bufinfo) {
mp_obj_t file = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), name_obj, MP_OBJ_NEW_QSTR(MP_QSTR_rb));
mp_obj_t dest[2];
mp_load_method(file, MP_QSTR_read, dest);
mp_obj_t result = mp_call_method_n_kw(0, 0, dest);
mp_get_buffer_raise(result, bufinfo, MP_BUFFER_READ);
}
static mp_obj_t ssl_sslcontext_load_cert_chain(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_certfile, ARG_keyfile };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_certfile, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_keyfile, MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_buffer_info_t cert_buf, key_buf;
get_file_contents(args[ARG_certfile].u_obj, &cert_buf);
if (args[ARG_keyfile].u_obj != mp_const_none) {
get_file_contents(args[ARG_keyfile].u_obj, &key_buf);
} else {
key_buf = cert_buf;
}
common_hal_ssl_sslcontext_load_cert_chain(self, &cert_buf, &key_buf);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_load_cert_chain_obj, 1, ssl_sslcontext_load_cert_chain);
//| def load_verify_locations(
//| self,
//| cafile: Optional[str] = None,
//| capath: Optional[str] = None,
//| cadata: Optional[str] = None,
//| ) -> None:
//| """
//| Load a set of certification authority (CA) certificates used to validate
//| other peers' certificates.
//|
//| :param str cafile: path to a file of contcatenated CA certificates in PEM format. **Not implemented**.
//| :param str capath: path to a directory of CA certificate files in PEM format. **Not implemented**.
//| :param str cadata: A single CA certificate in PEM format. **Limitation**: CPython allows one
//| or more certificates, but this implementation is limited to one.
//| """
//|
static mp_obj_t ssl_sslcontext_load_verify_locations(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_cafile, ARG_capath, ARG_cadata };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_cafile, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_capath, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_cadata, MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (args[ARG_cafile].u_obj != mp_const_none) {
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_cafile);
}
if (args[ARG_capath].u_obj != mp_const_none) {
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_capath);
}
const char *cadata = mp_obj_str_get_str(args[ARG_cadata].u_obj);
common_hal_ssl_sslcontext_load_verify_locations(self, cadata);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_load_verify_locations_obj, 1, ssl_sslcontext_load_verify_locations);
//| def set_default_verify_paths(self) -> None:
//| """Load a set of default certification authority (CA) certificates."""
//|
static mp_obj_t ssl_sslcontext_set_default_verify_paths(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
common_hal_ssl_sslcontext_set_default_verify_paths(self);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_set_default_verify_paths_obj, 1, ssl_sslcontext_set_default_verify_paths);
//| check_hostname: bool
//| """Whether to match the peer certificate's hostname."""
//|
static mp_obj_t ssl_sslcontext_get_check_hostname(mp_obj_t self_in) {
ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(common_hal_ssl_sslcontext_get_check_hostname(self));
}
static MP_DEFINE_CONST_FUN_OBJ_1(ssl_sslcontext_get_check_hostname_obj, ssl_sslcontext_get_check_hostname);
static mp_obj_t ssl_sslcontext_set_check_hostname(mp_obj_t self_in, mp_obj_t value) {
ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_ssl_sslcontext_set_check_hostname(self, mp_obj_is_true(value));
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(ssl_sslcontext_set_check_hostname_obj, ssl_sslcontext_set_check_hostname);
MP_PROPERTY_GETSET(ssl_sslcontext_check_hostname_obj,
(mp_obj_t)&ssl_sslcontext_get_check_hostname_obj,
(mp_obj_t)&ssl_sslcontext_set_check_hostname_obj);
//| def wrap_socket(
//| self,
//| sock: socketpool.Socket,
//| *,
//| server_side: bool = False,
//| server_hostname: Optional[str] = None,
//| ) -> ssl.SSLSocket:
//| """Wraps the socket into a socket-compatible class that handles SSL negotiation.
//| The socket must be of type SOCK_STREAM."""
//|
//|
static mp_obj_t ssl_sslcontext_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_sock, ARG_server_side, ARG_server_hostname };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_sock, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
const char *server_hostname = NULL;
if (args[ARG_server_hostname].u_obj != mp_const_none) {
server_hostname = mp_obj_str_get_str(args[ARG_server_hostname].u_obj);
}
bool server_side = args[ARG_server_side].u_bool;
if (server_side && server_hostname != NULL) {
mp_raise_ValueError(MP_ERROR_TEXT("Server side context cannot have hostname"));
}
mp_obj_t sock_obj = args[ARG_sock].u_obj;
return common_hal_ssl_sslcontext_wrap_socket(self, sock_obj, server_side, server_hostname);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_wrap_socket_obj, 1, ssl_sslcontext_wrap_socket);
static const mp_rom_map_elem_t ssl_sslcontext_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&ssl_sslcontext_wrap_socket_obj) },
{ MP_ROM_QSTR(MP_QSTR_load_cert_chain), MP_ROM_PTR(&ssl_sslcontext_load_cert_chain_obj) },
{ MP_ROM_QSTR(MP_QSTR_load_verify_locations), MP_ROM_PTR(&ssl_sslcontext_load_verify_locations_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_default_verify_paths), MP_ROM_PTR(&ssl_sslcontext_set_default_verify_paths_obj) },
{ MP_ROM_QSTR(MP_QSTR_check_hostname), MP_ROM_PTR(&ssl_sslcontext_check_hostname_obj) },
};
static MP_DEFINE_CONST_DICT(ssl_sslcontext_locals_dict, ssl_sslcontext_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
ssl_sslcontext_type,
MP_QSTR_SSLContext,
MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
make_new, ssl_sslcontext_make_new,
locals_dict, &ssl_sslcontext_locals_dict
);