2010/05/07

property python

gnutls を使って SSL な server から証明書を取りたい話

gnutls python でサーバーの証明書は取ってきていましたが
python-gnutls にはその上の証明書を取る関数がありませんでした
で、とりあえずソース見てみると connection.py に
    @property
def peer_certificate(self):
if gnutls_certificate_type_get(self._c_object) != GNUTLS_CRT_X509:
return None
list_size = c_uint()
cert_list = gnutls_certificate_get_peers(self._c_object, byref(list_size))
if list_size.value == 0:
return None
cert = cert_list[0]
return X509Certificate(string_at(cert.data, cert.size), X509_FMT_DER)
とありました。
サーバの提示する証明書全部取って、頭だけ出している!!

で、何か decorator 付いてるけどその辺り慣れていないのでググりました
Pythonでプロパティ - crazy()for(;;)you();
なるほど! () を省略したいんだな!!

というわけで書いてみました
from gnutls.connection import (
ClientSession, GNUTLS_CRT_X509, X509Certificate, X509_FMT_DER,
byref, c_uint, string_at,
gnutls_certificate_type_get, gnutls_certificate_get_peers,
)

def peer_certificate_chain(self):
if gnutls_certificate_type_get(self._c_object) != GNUTLS_CRT_X509:
return []
list_size = c_uint()
cert_list = gnutls_certificate_get_peers(self._c_object, byref(list_size))
ders = []
for i in range(list_size.value):
cert = cert_list[i]
ders.append(X509Certificate(string_at(cert.data, cert.size), X509_FMT_DER))
return ders

ClientSession.peer_certificate_chain = property(peer_certificate_chain)

if __name__ == '__main__':
import socket
from gnutls import connection

cred = connection.X509Credentials()
sock = socket.socket()
session = connection.ClientSession(sock, cred)

session.connect(('www.google.com', 443))
session.handshake()

for i in session.peer_certificate_chain:
print("%s <- %s" % (i.subject, i.issuer))
で、動かすと
$ python chain.py
C=US,ST=California,L=Mountain View,O=Google Inc,CN=www.google.com <- C=ZA,O=Thawte Consulting (Pty) Ltd.,CN=Thawte SGC CA
C=ZA,O=Thawte Consulting (Pty) Ltd.,CN=Thawte SGC CA <- C=US,O=VeriSign\, Inc.,OU=Class 3 Public Primary Certification Authority
$
うん、動いた

でも場当たりでメソッド足したりだなんて Python 的と言えないのでは?
と悩んだりもしました
う〜ん

0 件のコメント:

コメントを投稿