pylibtls - Python bindings for libtls
Project description
pylibtls
About
Developed initially in september 2021 on FreeBSD 13.0 with LibreSSL 3.3.3 with API Version 20200120.
The aim is to just wrap the API as thinly as possible. A few principles:
stris encoded using default encoding (just callingencode())- Epochs are converted to UTC datetime
- Return code
-1is made intoTLSError - Returned
1s and0s are cast toboolean - Returned strings are converted with
decode() tls_read()andtls_write()expectsbytesthough- The order of the functions defined matches that of libtls.h
- Argument names are not always pythonic but matches that of libtls.h
Background
I always thought it was a bit of a mistake for LibreSSL to be an drop-in replacement for OpenSSL. I just wanted to use libtls and be done with it. But since LibreSSL always replaced OpenSSL and that always seemed to be problematic I looked for ways to install just libtls, but to no awail. Until April 18, 2021 when version 3.3.2 of LibreSSL was released.
From the release notes (way down):
Added '--enable-libtls-only' build option, which builds and installs a statically-linked libtls, skipping libcrypto and libssl. This is useful for systems that ship with OpenSSL but wish to also package libtls.
YEY!
Some time after it was made a flavor of the FreeBSD LibreSSL port. So now I finally had it! So I started looking for Python wrappers for it. I found python-libtls by Vinay Sajip. Last update in 2017, looked abandoned, so I made a new one.
Getting started
Getting libtls
First thing is getting libtls somehow. If you already have LibreSSL you should be good to go. Otherwise hope the ‑‑enable‑libtls‑only build flag is used somehow in whatever package thingamajig you're using:
- FreeBSD got the forementioned port
- MacOS got nothing (yet...)
- Gentoo got libtls ported to OpenSSL (ewww...)
There's an env variable you can use to specify the path to libtls if ctypes is unable to find it automagically and that's PYLIBTLS_LIBTLS_PATH.
Getting pylibtls
Once I get it up on PyPi you can just use:
$> pip install pylibtls
and
import tls
But right now your only option is to clone this repo and work your way from there. Godspeed!
Usage
Oh the fun part!
Functions are named the same so tls_init() is tls.tls_init() and so on. Constants from header file are just tls.TLS_A_CONSTANT.
from tls import (tls_config_new, tls_client, tls_configure, tls_connect, tls_write,
tls_read, tls_config_free, tls_close, tls_free)
cfg = tls_config_new()
ctx = tls_client()
tls_configure(ctx, cfg)
host = 'www.openbsd.org'
tls_connect(ctx, host, 443)
query = "HEAD / HTTP/1.0\r\nHost: {}\r\n\r\n".format(host)
tls_write(ctx, query.encode())
r = tls_read(ctx)
print(r.decode())
tls_config_free(cfg)
tls_close(ctx)
tls_free(ctx)
The full monty
from tls import *
print('Version:', TLS_API)
cfg = tls_config_new()
tls_config_set_ca_file(cfg, "/etc/ssl/cert.pem")
print(tls_default_ca_cert_file())
tls_config_set_protocols(cfg, TLS_PROTOCOL_TLSv1_2)
ctx = tls_client()
tls_configure(ctx, cfg)
host = 'www.openbsd.org'
print('host:', host)
print('connect_socket')
tls_connect(ctx, host, 443)
print("Cert provided:", tls_peer_cert_provided(ctx))
print("Hash (SHA256):", tls_peer_cert_hash(ctx))
print("Issuer:", tls_peer_cert_issuer(ctx))
print("Subject:", tls_peer_cert_subject(ctx))
print("NotBefore (UTC):", tls_peer_cert_notbefore(ctx))
print("NotAfter (UTC):", tls_peer_cert_notafter(ctx))
print("ALPN:", tls_conn_alpn_selected(ctx))
print("Cipher:", tls_conn_cipher(ctx))
print("Servername:", tls_conn_servername(ctx))
print("Resumed:", tls_conn_session_resumed(ctx))
print("TLS Version:", tls_conn_version(ctx))
print("OCSP URL:", tls_peer_ocsp_url(ctx))
print("OCSP result:", tls_peer_ocsp_result(ctx))
if tls_peer_ocsp_result(ctx) is not None:
print("OCSP Response Status:", TLS_OCSP_RESPONSE[tls_peer_ocsp_response_status(ctx)])
print("OCSP Cert Status:", TLS_OCSP_CERT[tls_peer_ocsp_cert_status(ctx)])
print("OCSP CRL Reason:", TLS_CRL_REASON[tls_peer_ocsp_crl_reason(ctx)])
print("OCSP revocation:", tls_peer_ocsp_revocation_time(ctx))
print("OCSP this update:", tls_peer_ocsp_this_update(ctx))
print("OCSP next update:", tls_peer_ocsp_next_update(ctx))
print()
query = "HEAD / HTTP/1.0\r\nHost: {}\r\n\r\n".format(host)
print('tls_write', query)
r = tls_write(ctx, query.encode())
print(r, 'bytes')
print('read')
r = tls_read(ctx)
print(len(r), 'bytes')
print(r.decode())
tls_config_free(cfg)
tls_close(ctx)
tls_free(ctx)
This is using the extra dicts I put in for reverse lookup of values-to-name: TLS_OCSP_RESPONSE, TLS_OCSP_CERT and TLS_CRL_REASON. They require that OCSP stapling is active on the server in question. In the example, it is.
Documentation
None yet, apart from this README. See the OpenBSD documentation for reference. It should get you up and running somewhat.
Status
2021-10-08
First pushed to GitHub (A bit nervous). Most of the API implemented. Only client functionality tested. No local OCSP-stuff (getting the staple file is HARD). Only tested on FreeBSD. Should work fine on Linux at least. No libtls-only brew Formulae so MacOS is out (might be next project). Windows seems to be a sad chapter in general. Vinay stranded here more or less.
TODO
- All
mem-functions that read stuff from memory loaded withtls_load_file() - Callbacks versions of
tls_accept()andtls_connect() - File descriptor versions of the same
-
tls_peer_cert_chain_pem() -
asserta few things here and there
Acknowledgments
- python-libtls and python-gnutls for inspiration
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pylibtls-0.1.1.tar.gz.
File metadata
- Download URL: pylibtls-0.1.1.tar.gz
- Upload date:
- Size: 11.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.25.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a993c711e3775234f81eab0a45cebe6dcd27884d65ed455ae32d3ce1641d834c
|
|
| MD5 |
91e3486b347c875d332d9b21c91af120
|
|
| BLAKE2b-256 |
65526d5d7980023dc6af619e175f5e0a409c243c7b57a6a22a1a79a8bb8ea23f
|
File details
Details for the file pylibtls-0.1.1-py2.py3-none-any.whl.
File metadata
- Download URL: pylibtls-0.1.1-py2.py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.25.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c56e20c681fa98d50adac00e71d6736da35630bb825603b1c0d19865ce9e2fba
|
|
| MD5 |
b5b4376e91a076091871bcd45c743d25
|
|
| BLAKE2b-256 |
31d2ce4e61514a47a14b7f39a5c2e41648c31a96b80488dfaa8ff36e39ec8290
|