======Synopsis:====== This document covers how SSL connetions to IRC servers happen. This information was current as of EPIC5-2.1.6. =====Step One -- You connect to an SSL server===== You connect to an irc server doing something like /SERVER irc.example.com:6697:type=irc-ssl This goes through connect()ing to the server, and then doing an SSL_connect() to set up the certificate exchange and TLS negotiation. =====Step Two -- The SSL handshake is completed===== After the SSL_connect() step has completed, we now have a fully functioning TLS socket with an SSL certificate. Before we use the TLS socket, we're supposed to verify we trust the SSL certificate, to ensure we're talking to who we think we are. =====Step Three -- The client watches the certificate verification===== OpenSSL "verifies" the certificate and the client provides a C function to tag along for the ride. The callback function is called every time: - An error is discovered, or - There are no (further) errors in a certificate. Thus, if a certificate is trusted, it will only report "no problems" for each link in the chain. This permits the client to trap and categorize every error that happens - some certificates have multiple problems! There are three buckets the client uses: - Self-signed certificates - Incorrect-hostname certificates - Any other (serious) error The client tracks the "most serious error" (if there is one), using the above priorities. =====Step Four - The client offers you /ON SSL_SERVER_CERT===== The client sets $serverctl(SET SSL_ACCEPT_CERT -1) and then throws /ON SSL_SERVER_CERT. The use of -1 is on purpose so the client can determine whether your /ON handler sets it to 0 or 1. If your handler does a $serverctl(SET SSL_ACCEPT_CERT 0|1) then that is taken as the final disposition of the handling, and nothing further occurs. (ie, it skips the rest of the steps) Parameters of /ON SSL_SERVER_CERT $0 The fd of the socket (Use $serverctl(FROM_SERVER) to get the server refnum) $1 Certificate Subject, url-encoded $2 Certificate Issuer, url-encoded $3 Bits used in the public key $4 OpenSSL error code of the "most serious error" (18 is "Self-signed certificate", 62 is "Hostname mismatch", everything else is irregular/bad) $5 The SSL regime being used (ie, TLSv1.2) $6 The Certificate Hash $7 Was there a hostname mismatch? 0 = no error, 1 = error $8 Was there a self-signed error? 0 = no error, 1 = error $9 Was there another (serious) error? 0 = no other error 1 = other error $10 Was there any error of any kind? 0 = no errors of any kind, 1 = some kind of error =====Step Five -- The client makes a provisional decision===== Next, the client looks at the errors and decides whether it thinks the cert is ok. ^ Description ^ Outcome ^ | Cert has no errors | ACCEPT | | Cert has "self signed" or "wrong hostname" error and /SET ACCEPT_INVALID_SSL_CERT ON | ACCEPT | | Cert has "self signed" or "wrong hostname" error aand /SET ACCEPT_INVALID_SSL_CERT OFF | REJECT | | Cert has any serious error | REJECT | The client sets this provisional value with $serverctl(SET SSL_ACCEPT_CERT 0|1) =====Step Six - The client offers you ON SERVER_SSL_EVAL===== Then, the client hooks /ON SERVER_SSL_EVAL. At this point, all of the information your script needs to make a fully informed decision to accept or overrule the client's choice is available. Your handler is not obligated to make any change, but it certainly can if it wants to Parameters of /ON SERVER_SSL_EVAL $0 The server refnum $1 The "ourname" of the server (what you /server'd to) $2 Was there any error at all? 0 = no errors of any kind 1 = some kind of error $3 Was there a hostname mismatch? 0 = no error, 1 = error $4 Was there a self-signed error? 0 = no error, 1 = error $5 Was there another (serious) error? 0 = no other error, 1 = other error $6 What does the client suggest? 0 = reject certificate, 1 = accept certificate Using $serverctl() to get info about the certificate Use $serverctl(GET ) where is: | SSL_CIPHER | The encryption cipher being used | | SSL_PEM | The certificate (in PEM format) | | SSL_CERT_HASH | The certificate's hash | | SSL_PKEY_BITS | The bits in the public key | | SSL_SUBJECT | Who the cert was issued to | | SSL_SUBJECT_URL | Who the cert was issued to (url-encoded) | | SSL_ISSUER | Who issued the cert | | SSL_ISSUER_URL | Who issued the cert (url-encoded) | | SSL_VERSION | What version of SSL being used (ie, TLSv1.2) | | SSL_SANS | Subject Alternate Names in the cert | | SSL_CHECKHOST_ERROR | Hostname Mismatch error - 0 (no) 1 (yes) | | SSL_SELF_SIGNED_ERROR | Self-signed error - 0 (no) 1 (yes) | | SSL_OTHER_ERROR | Any other (serious) error - 0 (no) 1 (yes) | | SSL_MOST_SERIOUS_ERROR | The OpenSSL error code of the most serious error 18 (self-signed) and 62 (hostname mismatch) are considered non-serious (routine) errors | | SSL_VERIFY_ERROR | Any error at all - 0 (no) 1 (yes) | | SSL_ACCEPT_CERT | Is this cert headed for acceptance? 0 (no) 1 (yes) | To reject the cert: $serverctl(SET SSL_ACCEPT_CERT 0) To accept the cert: $serverctl(SET SSL_ACCEPT_CERT 1) If you don't do anything, the client will do the most reasonable thing =====Step Seven - The client moves forward===== Finally, everyone has had a chance to weigh in. Whatever the value of $serverctl(GET SSL_ACCEPT_CERT) is after all this, is used to accept or reject the SSL connection. ======History:====== This information was current as of EPIC5-2.1.6.