HTTPS, certificaten en beveiligingsheaders · oefening
Zie verificatie slagen en falen
Je twee contexts hebben de juiste instellingen, en nog geen enkele verbinding heeft ze gebruikt. In deze les zie je ze aan het werk: vier handshakes op deze computer, een die slaagt en drie die de client weigert. Daarna schrijf je de
Lees eerst certs/README.md in je project. Het beschrijft de bestanden in certs/. Een ervan, ca.pem, is een testautoriteit: een uitgever gemaakt voor deze cursus. Geen browser en geen
Houd de hele les één ding in gedachten. Deze handshakes laten zien hoe een client beslist. Ze laten niets zien over een echte website.
Voer het uit
python pl_sec.py tls
Het hulpprogramma start vier keer een kleine listener op deze computer, elke keer met je server_context() en een ander certificaat. Elke keer maakt het verbinding met je client_context("certs/ca.pem") en vraagt het om de naam reading.example:
pl_sec: tls, four handshakes on 127.0.0.1 with your client_context() and server_context()
The name reading.example exists only in the model. Every byte goes to this computer.
--- the client ---
trusts certs/ca.pem only, and expects the name reading.example
--- the server presents certs/reading.pem ---
handshake completed (TLSv1.3); the server said: hello over TLS
--- the server presents certs/unknown-issuer.pem ---
refused: verify_code 20: unable to get local issuer certificate
--- the server presents certs/wrong-name.pem ---
refused: verify_code 62: Hostname mismatch, certificate is not valid for 'reading.example'.
--- the server presents certs/expired.pem ---
refused: verify_code 10: certificate has expired
--- result ---
1 handshake completed and 3 were refused, each before any request was sent
pl_sec: every thread has stopped
pl_sec: tls_failure() is not written yet (Write this function in Lesson 3.), so the failed checks have no name yet
De client verbindt zijn 127.0.0.1, en hij verwacht reading.example. Dat zijn twee aparte dingen. Een client controleert de naam waar hij om vroeg, niet het adres waarmee hij verbinding maakte, en hier wordt de naam nergens opgezocht: het hulpprogramma geeft hem rechtstreeks aan de handshake. Een certificaat kan ook adressen noemen. Het goede certificaat van de cursus noemt 127.0.0.1 naast zijn namen.
Kijk naar het eerste blok. De handshake slaagde, en pas daarna zei de server iets: hello over TLS reisde binnen de versleutelde verbinding. De regel noemt ook de protocolversie waarover de twee contexts het eens werden. Die van jou staan allebei
De drie weigeringen zijn de drie controles uit les 1. unknown-issuer.pem noemt reading.example en zijn datums kloppen, maar zijn uitgever staat niet in certs/ca.pem. wrong-name.pem komt van de juiste uitgever, voor other.example. expired.pem eindigde in 2020. In alle drie de gevallen stopte de client tijdens de handshake, dus de server aan de andere kant kreeg nooit een verzoek.
De client weigerde expired.pem. Hoeveel van een HTTP-verzoek had de server toen bereikt?
De fout is een object
Als een controle faalt, werpt de handshake ssl.SSLCertVerificationError op. De
verify_codeis een getal van OpenSSL, de bibliotheek die het controleren doet.20,62en10in de run hierboven zijn verify codes.verify_messageis een zin voor mensen.
Code die de verbinding maakt, vangt de exception op en leest ze, zoals elk attribuut van een exception:
try:
secure = context.wrap_socket(sock, server_hostname="reading.example")
except ssl.SSLCertVerificationError as error:
print(error.verify_code, error.verify_message)
Beslis op de code en nooit op het bericht. Het bericht is geformuleerd door OpenSSL, en die formulering verandert tussen versies. De getallen komen uit OpenSSL’s eigen
Python heeft geen namen voor deze getallen, dus tls_contexts.py levert ze als drie sets, met een commentaar bij elk getal: ISSUER_CODES, NAME_CODES en DATE_CODES. De sets bevatten meer codes dan de run liet zien. Code 18 is bijvoorbeeld een certificaat dat de houder zelf heeft ondertekend. Die kom je tegen op een ontwikkelmachine, waar mensen zulke certificaten voor zichzelf maken. Code 9 is een certificaat waarvan de periode nog niet is begonnen. Dat faalt op dezelfde controle als een verlopen certificaat; daarom heet die controle hier de datumcontrole en niet “verlopen”.
unknown-issuer.pem noemt reading.example en zijn datums kloppen. Waarom wordt het geweigerd?
De server laat certs/wrong-name.pem zien. Wat geeft tls_failure() terug voor de fout?
Je opdracht
Schrijf tls_failure(error) in tls_contexts.py. De functie leest error.verify_code en geeft een van vier
"issuer"als de code inISSUER_CODESstaat;"name"als hij inNAME_CODESstaat;"date"als hij inDATE_CODESstaat;"other"voor elke andere code.
Voer daarna het scenario opnieuw uit:
python pl_sec.py tls
Elke weigering heeft nu één regel extra eronder, en de laatste regel van de eerste run is verdwenen:
refused: verify_code 20: unable to get local issuer certificate
tls_failure() says: issuer
De andere twee zeggen tls_failure() says: name en tls_failure() says: date.
Wat lieten deze vier handshakes zien over een echte website?
Klik daarna op Check my work. Die roept je functie aan met foutobjecten die hij zelf maakt, voor de codes die je zag en voor codes die je niet zag, dus hij heeft geen handshake nodig. De verbinding heeft nu een geverifieerd ander eind. De volgende les richt zich op de pagina die erover binnenkomt.
Opdracht
Schrijf tls_failure(error) in tls_contexts.py.
erroris eenssl.SSLCertVerificationError. Lees deverify_codeervan.Geef
"issuer"terug als de code inISSUER_CODESstaat,"name"als hij inNAME_CODESstaat,"date"als hij inDATE_CODESstaat, en"other"voor elke andere code.Beslis op
verify_code.verify_messageis een zin voor mensen: de formulering kan tussen OpenSSL-versies veranderen, en hij kan leeg zijn.
Voer python pl_sec.py tls uit in de tls_failure() says: issuer, name of date.
Klik daarna op Check my work. Die roept tls_failure aan met foutobjecten die hij zelf maakt: de drie codes die de run laat zien, zes die hij niet laat zien, en een waarvan het bericht leeg is. Hij doet geen handshake en opent geen verbinding. Niets uit je terminal wordt beoordeeld.