Skip to content

Commit bea6e54

Browse files
committed
Make ssl work on windows
1 parent 03ba022 commit bea6e54

File tree

5 files changed

+81
-3
lines changed

5 files changed

+81
-3
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/ssl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@
158158

159159

160160
if sys.platform == "win32":
161-
from _ssl import enum_certificates, enum_crls
161+
from _ssl import enum_certificates #, enum_crls
162162

163163
from socket import socket, AF_INET, SOCK_STREAM, create_connection
164164
from socket import SOL_SOCKET, SO_TYPE

vm/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,11 @@ libz-sys = "1.0"
101101

102102
[target.'cfg(windows)'.dependencies]
103103
winreg = "0.7"
104+
schannel = "0.1"
104105

105106
[target."cfg(windows)".dependencies.winapi]
106107
version = "0.3"
107-
features = ["winsock2", "handleapi", "ws2def", "std", "winbase"]
108+
features = ["winsock2", "handleapi", "ws2def", "std", "winbase", "wincrypt"]
108109

109110
[target.'cfg(target_arch = "wasm32")'.dependencies]
110111
wasm-bindgen = "0.2"

vm/src/obj/objset.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,17 @@ macro_rules! multi_args_frozenset {
631631

632632
#[pyimpl(flags(BASETYPE))]
633633
impl PyFrozenSet {
634+
pub fn from_iter(
635+
vm: &VirtualMachine,
636+
it: impl IntoIterator<Item = PyObjectRef>,
637+
) -> PyResult<Self> {
638+
let mut inner = PySetInner::default();
639+
for elem in it {
640+
inner.add(&elem, vm)?;
641+
}
642+
Ok(Self { inner })
643+
}
644+
634645
#[pyslot]
635646
fn tp_new(
636647
cls: PyClassRef,

vm/src/stdlib/ssl.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,46 @@ fn obj2py(obj: &Asn1ObjectRef) -> PyNid {
106106
)
107107
}
108108

109+
#[cfg(windows)]
110+
fn ssl_enum_certificates(store_name: PyStringRef, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
111+
use crate::obj::objset::PyFrozenSet;
112+
use schannel::{cert_context::ValidUses, cert_store::CertStore, RawPointer};
113+
use winapi::um::wincrypt;
114+
// TODO: check every store for it, not just 2 of them:
115+
// https://github.com/python/cpython/blob/3.8/Modules/_ssl.c#L5603-L5610
116+
let open_fns = [CertStore::open_current_user, CertStore::open_local_machine];
117+
let stores = open_fns
118+
.iter()
119+
.filter_map(|open| open(store_name.as_str()).ok())
120+
.collect::<Vec<_>>();
121+
let certs = stores.iter().map(|s| s.certs()).flatten().map(|c| {
122+
let cert = vm.ctx.new_bytes(c.to_der().to_owned());
123+
let enc_type = unsafe {
124+
let ptr = c.as_ptr() as wincrypt::PCCERT_CONTEXT;
125+
(*ptr).dwCertEncodingType
126+
};
127+
let enc_type = match enc_type {
128+
wincrypt::X509_ASN_ENCODING => vm.new_str("x509_asn".to_owned()),
129+
wincrypt::PKCS_7_ASN_ENCODING => vm.new_str("pkcs_7_asn".to_owned()),
130+
other => vm.new_int(other),
131+
};
132+
let usage = match c.valid_uses()? {
133+
ValidUses::All => vm.new_bool(true),
134+
ValidUses::Oids(oids) => {
135+
PyFrozenSet::from_iter(vm, oids.into_iter().map(|oid| vm.new_str(oid)))
136+
.unwrap()
137+
.into_ref(vm)
138+
.into_object()
139+
}
140+
};
141+
Ok(vm.ctx.new_tuple(vec![cert, enc_type, usage]))
142+
});
143+
let certs = certs
144+
.collect::<Result<Vec<_>, _>>()
145+
.map_err(|e| super::os::convert_io_error(vm, e))?;
146+
Ok(vm.ctx.new_list(certs))
147+
}
148+
109149
#[derive(FromArgs)]
110150
struct Txt2ObjArgs {
111151
#[pyarg(positional_or_keyword)]
@@ -518,7 +558,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
518558
&vm.ctx.types.type_type,
519559
&vm.ctx.exceptions.os_error,
520560
);
521-
py_module!(vm, "_ssl", {
561+
let module = py_module!(vm, "_ssl", {
522562
"_SSLContext" => PySslContext::make_class(ctx),
523563
"_SSLSocket" => PySslSocket::make_class(ctx),
524564
"SSLError" => ssl_error,
@@ -570,5 +610,20 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
570610
"ALERT_DESCRIPTION_DECODE_ERROR" => ctx.new_int(sys::SSL_AD_DECODE_ERROR),
571611
"ALERT_DESCRIPTION_ILLEGAL_PARAMETER" => ctx.new_int(sys::SSL_AD_ILLEGAL_PARAMETER),
572612
"ALERT_DESCRIPTION_UNRECOGNIZED_NAME" => ctx.new_int(sys::SSL_AD_UNRECOGNIZED_NAME),
613+
});
614+
615+
extend_module_platform_specific(&module, vm);
616+
617+
module
618+
}
619+
620+
#[cfg(windows)]
621+
fn extend_module_platform_specific(module: &PyObjectRef, vm: &VirtualMachine) {
622+
let ctx = &vm.ctx;
623+
extend_module!(vm, module, {
624+
"enum_certificates" => ctx.new_function(ssl_enum_certificates),
573625
})
574626
}
627+
628+
#[cfg(not(windows))]
629+
fn extend_module_platform_specific(_module: &PyObjectRef, _vm: &VirtualMachine) {}

0 commit comments

Comments
 (0)