mirror of
https://github.com/certbot/certbot.git
synced 2026-01-26 07:41:33 +03:00
Adding sni_challenge verification
This commit is contained in:
9
ca/sni_challenge/make.sh
Normal file
9
ca/sni_challenge/make.sh
Normal file
@@ -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
|
||||
19
ca/sni_challenge/sni_support.c
Normal file
19
ca/sni_challenge/sni_support.c
Normal file
@@ -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;
|
||||
}
|
||||
13
ca/sni_challenge/sni_support.h
Normal file
13
ca/sni_challenge/sni_support.h
Normal file
@@ -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
|
||||
13
ca/sni_challenge/sni_support.i
Normal file
13
ca/sni_challenge/sni_support.i
Normal file
@@ -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"
|
||||
|
||||
72
ca/sni_challenge/verify_sni_challenge.py
Normal file
72
ca/sni_challenge/verify_sni_challenge.py
Normal file
@@ -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