2012-09-09 14 views
20

Trong Python, ssl.wrap_socket có thể đọc chứng chỉ từ tệp, ssl.wrap_socket yêu cầu chứng chỉ dưới dạng đường dẫn tệp.Cách mở ổ cắm ssl bằng chứng chỉ được lưu trữ trong biến chuỗi trong python

Làm cách nào để bắt đầu kết nối SSL bằng chứng chỉ được đọc từ các biến chuỗi?

Môi trường lưu trữ của tôi không cho phép ghi vào tệp và mô-đun tempfile không hoạt động
Tôi đang sử dụng Python 2.7.
Tôi lưu trữ chứng chỉ bên trong MySQL và đọc dưới dạng chuỗi.

Chỉnh sửa: Tôi đã từ bỏ, điều này về cơ bản là yêu cầu triển khai ssl bằng mã python tinh khiết, điều này vượt quá kiến ​​thức hiện tại của tôi.

+1

Chắc chắn môi trường máy chủ lưu trữ của bạn cho phép bạn lưu trữ chứng chỉ SSL, bằng cách nào đó? ngay cả khi họ muốn tự cung cấp cho họ. – EJP

+0

Tôi đã lưu dữ liệu chứng chỉ trong mysql. mã của tôi cần một ổ cắm ssl đến một máy chủ khác để lấy dữ liệu. Tôi đọc chứng chỉ từ cơ sở dữ liệu, nhưng không biết cách tạo gói ssl. – kaala

+0

Nhìn vào nguồn, ssl.wrap_socket gọi trực tiếp vào mã nguồn gốc (openssl) function SSL_CTX_use_cert_chain_file yêu cầu đường dẫn đến một tệp, vì vậy những gì bạn đang cố gắng làm là không thể. Bạn cần phải ghi chứng chỉ vào một tệp để thao tác này hoạt động. – cnelson

Trả lời

23

Nhìn vào nguồn, ssl.wrap_socket gọi trực tiếp vào mã nguồn gốc (openssl) function SSL_CTX_use_cert_chain_file yêu cầu đường dẫn đến tệp, vì vậy những gì bạn đang cố gắng làm là không thể.

Để tham khảo:

Trong ssl/init py chúng ta thấy:

def wrap_socket(sock, keyfile=None, certfile=None, 
       server_side=False, cert_reqs=CERT_NONE, 
       ssl_version=PROTOCOL_SSLv23, ca_certs=None, 
       do_handshake_on_connect=True): 

    return SSLSocket(sock, keyfile=keyfile, certfile=certfile, 
        server_side=server_side, cert_reqs=cert_reqs, 
        ssl_version=ssl_version, ca_certs=ca_certs, 
        do_handshake_on_connect=do_handshake_on_connect) 

điểm chúng ta đến constructor SSLSocket (đó là trong cùng một tập tin) và chúng ta thấy những điều sau đây xảy ra:

self._sslobj = _ssl2.sslwrap(self._sock, server_side, 
            keyfile, certfile, 
            cert_reqs, ssl_version, ca_certs) 

_ssl2 được thực hiện trong C (_ssl2.c)

Nhìn vào chức năng sslwrap, chúng ta thấy nó tạo ra một đối tượng mới:

return (PyObject *) newPySSLObject(Sock, key_file, cert_file, 
             server_side, verification_mode, 
             protocol, cacerts_file); 

Nhìn vào các nhà xây dựng cho đối tượng đó, chúng tôi cuối cùng đã nhìn thấy:

  ret = SSL_CTX_use_certificate_chain_file(self->ctx, 
                cert_file); 

Đó là chức năng được định nghĩa trong openssl, vì vậy bây giờ chúng ta cần chuyển sang codebase đó.

Trong ssl/ssl_rsa.c chúng tôi cuối cùng đã tìm thấy trong chức năng:

BIO_read_filename(in,file) 

Nếu bạn đào đủ xa vào mã BIO (một phần của openssl), bạn cuối cùng sẽ đi đến một fopen bình thường():

fp=fopen(ptr,p); 

Vì vậy, có vẻ như nó đang được viết. Nó phải ở trong một tập tin có thể mở được bằng fopen của C().

Ngoài ra, vì thư viện ssl của python nhanh chóng nhảy vào C, tôi không thấy một vị trí rõ ràng ngay lập tức để monkeypatch trong một workaround hoặc.

+1

Khá nhiều hy vọng cho một hack bẩn ... – domenukk

-1

Bạn có thể xử lý các chuỗi như tệp với StringIO.

+1

StringIO này không làm việc dưới ssl.wrap_socket, yêu cầu một chuỗi như là đường dẫn tệp. Ngoại lệ: TypeError ('phải chuỗi hoặc Không, không dụ',) Traceback: Traceback (gần đây nhất gọi cuối cùng): File "/data1/www/htdocs/705/pty/1/pty.py ", dòng 23, trong kết nối self.push.connect (self.gateway) Tệp" /usr/local/sae/python/lib/python2.7/ssl.py ", dòng 331, trong kết nối self._real_connect (addr, False) Tệp "/usr/local/sae/python/lib/python2.7/ssl.py", dòng 314, trong _real_connect self.ca_certs, self.ciphers) LoạiError: phải là chuỗi hoặc Không , không phải trường hợp – kaala

+1

Vì vậy, nó có một đường dẫn tập tin và không phải là một đối tượng tập tin –

5

nhanh nhìn mặc dù nguồn mô-đun ssl khẳng định những gì bạn muốn không được hỗ trợ bởi các API: http://code.google.com/codesearch#2T6lfGELm_A/trunk/Modules/_ssl.c&q=sslwrap&type=cs

Mà không phải là để nói nó là không thể, bạn có thể tạo một ống tên, nuôi một đầu từ Python và đặt tên tệp cho mô-đun ssl.

Để sử dụng đơn giản hơn, kém an toàn hơn, hãy đổ chứng chỉ từ bộ nhớ sang tệp mkstemp() 'd.

Bạn thậm chí có thể gắn kết khối lượng FUSE và chặn tệp gọi lại.

Cuối cùng, sử dụng ctypes để hack tại ngữ cảnh ssl khi chạy và tải cert/ket từ bộ đệm theo công thức C Read certificate files from memory instead of a file using OpenSSL Những thứ như thế này đã được thực hiện trước đó, nhưng nó không dành cho những người yếu tim.

Có vẻ như bạn đang cố gắng thoát ra khỏi ví dụ: công cụ ứng dụng "tù", có lẽ nó chỉ là không thể?

Nếu bạn không cầu kỳ về triển khai ssl, bạn có thể sử dụng M2Crypto, TLS Lite, pyOpenSSL hoặc cái gì khác. Trước đó là python tinh khiết, bạn chắc chắn có thể hack nó để sử dụng các chứng chỉ/khóa trong bộ nhớ.

+0

Ống được đặt tên về cơ bản là một tệp tạm thời, phải không? Ý tưởng rất hay. Tôi nghĩ rằng việc sử dụng M2Crypto hoặc một cái gì đó tương tự sẽ là cách tiếp cận tốt nhất sau đó. – domenukk

+0

có tạo tên được đặt tên yêu cầu phải ghi sự cho phép trên hệ thống tập tin –

+0

Ngay cả sau khi đã nối vào 'load_verify_locations' của' ssl._ssl._SSLContext' bằng cách sử dụng ctypes hackery, tất cả hàm đó nhận được là một đối tượng 'ssl.SSLContext' và nó là một bí ẩn đối với tôi để sử dụng điều đó để truy cập đúng vị trí bộ nhớ đã được cấp phát cho lớp cha bên dưới 'PySSLContext', để tôi có thể lấy con trỏ tới thành viên' ctx' của kiểu 'SL_CTX *'. Có ai có bất kỳ con trỏ (chữ)? – josch