mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 02:44:21 +02:00
Adding sni_challenge verification
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#Quick script to compile/load sni_support
|
||||||
|
#Will change to something more appropriate in the future
|
||||||
|
|
||||||
|
#Modify python path
|
||||||
|
|
||||||
|
swig -python sni_support.i
|
||||||
|
gcc -fpic -I/home/james/virtualenvs/chocolate/include/python2.7 -c sni_support_wrap.c sni_support.c
|
||||||
|
gcc -shared sni_support_wrap.o sni_support.o -o _sni_support.so
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/objects.h>
|
||||||
|
#include "sni_support.h"
|
||||||
|
|
||||||
|
void set_sni_ext(SSL *ctx, char *servername) {
|
||||||
|
SSL_set_tlsext_host_name(ctx, servername);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_nid(X509_EXTENSION *ext) {
|
||||||
|
return OBJ_obj2nid(X509_EXTENSION_get_object(ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
binary_data_t get_unknown_value(X509_EXTENSION *ext) {
|
||||||
|
binary_data_t result;
|
||||||
|
result.size = ext->value->length;
|
||||||
|
result.data = (unsigned char *)ext->value->data;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef SNI_SUPPORT_H
|
||||||
|
#define SNI_SUPPORT_H
|
||||||
|
|
||||||
|
typedef struct binary_data {
|
||||||
|
int size;
|
||||||
|
unsigned char* data;
|
||||||
|
} binary_data_t;
|
||||||
|
|
||||||
|
void set_sni_ext(SSL *ctx, char *servername);
|
||||||
|
int get_nid(X509_EXTENSION *ext);
|
||||||
|
binary_data_t get_unknown_value(X509_EXTENSION *ext);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
%module sni_support
|
||||||
|
%{
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include "sni_support.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%typemap(out) binary_data_t {
|
||||||
|
$result = PyString_FromStringAndSize($1.data,$1.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
%include "sni_support.h"
|
||||||
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import M2Crypto
|
||||||
|
import sni_support
|
||||||
|
import hmac
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
S_SIZE = 20
|
||||||
|
|
||||||
|
def check(one, two, three, four, five):
|
||||||
|
print "done"
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def byteToHex(byteStr):
|
||||||
|
return ''.join(["%02X" % ord(x) for x in byteStr]).strip()
|
||||||
|
|
||||||
|
def check_challenge_value(ext_value, sharedSecret):
|
||||||
|
s = ext_value[0:S_SIZE]
|
||||||
|
mac = ext_value[S_SIZE:]
|
||||||
|
expected_mac = hmac.new(sharedSecret, str(s), hashlib.sha256).digest()
|
||||||
|
|
||||||
|
#print "s: ", byteToHex(s)
|
||||||
|
#print "mac: ", byteToHex(mac)
|
||||||
|
#print "expected_mac: ", byteToHex(expected_mac)
|
||||||
|
#print type(mac)
|
||||||
|
#print type(expected_mac)
|
||||||
|
|
||||||
|
if mac == expected_mac:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def verify_challenge(address, sharedSecret, encryptedValue):
|
||||||
|
sni_name = byteToHex(encryptedValue[0]) + ".com"
|
||||||
|
|
||||||
|
context = M2Crypto.SSL.Context()
|
||||||
|
context.set_allow_unknown_ca(True)
|
||||||
|
context.set_verify(M2Crypto.SSL.verify_none, 4)
|
||||||
|
|
||||||
|
conn = M2Crypto.SSL.Connection(context)
|
||||||
|
sni_support.set_sni_ext(conn.ssl, sni_name)
|
||||||
|
conn.connect((address, 443))
|
||||||
|
|
||||||
|
cert_chain = conn.get_peer_cert_chain()
|
||||||
|
|
||||||
|
#Ensure certificate chain form is correct
|
||||||
|
if len(cert_chain) != 1:
|
||||||
|
return False, "Incorrect number of certificates in chain"
|
||||||
|
|
||||||
|
for i in range(0,cert_chain[0].get_ext_count()):
|
||||||
|
ext = cert_chain[0].get_ext_at(i)
|
||||||
|
|
||||||
|
if sni_support.get_nid(ext.x509_ext) == 0:
|
||||||
|
|
||||||
|
valid = check_challenge_value(sni_support.get_unknown_value(ext.x509_ext), sharedSecret)
|
||||||
|
if valid:
|
||||||
|
return True, "Challenge completed successfully"
|
||||||
|
else:
|
||||||
|
return False, "Certificate extension does not check out"
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
#Testing the example sni_challenge
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
|
||||||
|
testkey = RSA.importKey(open("/home/james/Documents/apache_choc/testing.key").read())
|
||||||
|
|
||||||
|
#the second parameter is ignored
|
||||||
|
#https://www.dlitz.net/software/pycrypto/api/current/
|
||||||
|
encryptedValue = testkey.encrypt('0x12345678', 0)
|
||||||
|
valid, response = verify_challenge("127.0.0.1", '0x12345678', encryptedValue)
|
||||||
|
print response
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user