PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/site/cl+ssl-2008-11-04/conditions.lisp

https://bitbucket.org/nunb/dotsbcl
Lisp | 217 lines | 182 code | 20 blank | 15 comment | 13 complexity | 0fc094aa0960c52f6be2fc0c85ff5595 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  1. ;;; Copyright (C) 2001, 2003 Eric Marsden
  2. ;;; Copyright (C) 2005 David Lichteblau
  3. ;;; "the conditions and ENSURE-SSL-FUNCALL are by Jochen Schmidt."
  4. ;;;
  5. ;;; See LICENSE for details.
  6. (in-package :cl+ssl)
  7. (eval-when (:compile-toplevel :load-toplevel :execute)
  8. (defconstant +ssl-error-none+ 0)
  9. (defconstant +ssl-error-ssl+ 1)
  10. (defconstant +ssl-error-want-read+ 2)
  11. (defconstant +ssl-error-want-write+ 3)
  12. (defconstant +ssl-error-want-x509-lookup+ 4)
  13. (defconstant +ssl-error-syscall+ 5)
  14. (defconstant +ssl-error-zero-return+ 6)
  15. (defconstant +ssl-error-want-connect+ 7))
  16. ;;; Condition hierarchy
  17. ;;;
  18. (defun write-queued-errors (condition stream)
  19. (let ((queue (ssl-error-queue condition)))
  20. (when queue
  21. (write-sequence queue stream))))
  22. (define-condition ssl-error (error)
  23. ((queue :initform nil :initarg :queue :reader ssl-error-queue)))
  24. (define-condition ssl-error/handle (ssl-error)
  25. ((ret :initarg :ret
  26. :reader ssl-error-ret)
  27. (handle :initarg :handle
  28. :reader ssl-error-handle))
  29. (:report (lambda (condition stream)
  30. (format stream "Unspecified error ~A on handle ~A"
  31. (ssl-error-ret condition)
  32. (ssl-error-handle condition))
  33. (write-sequence (ssl-error-queue condition) stream))))
  34. (define-condition ssl-error-initialize (ssl-error)
  35. ((reason :initarg :reason
  36. :reader ssl-error-reason))
  37. (:report (lambda (condition stream)
  38. (format stream "SSL initialization error: ~A"
  39. (ssl-error-reason condition))
  40. (write-queued-errors condition stream))))
  41. (define-condition ssl-error-want-something (ssl-error/handle)
  42. ())
  43. ;;;SSL_ERROR_NONE
  44. (define-condition ssl-error-none (ssl-error/handle)
  45. ()
  46. (:documentation
  47. "The TLS/SSL I/O operation completed. This result code is returned if and
  48. only if ret > 0.")
  49. (:report (lambda (condition stream)
  50. (format stream "The TLS/SSL operation on handle ~A completed. (return code: ~A)"
  51. (ssl-error-handle condition)
  52. (ssl-error-ret condition))
  53. (write-queued-errors condition stream))))
  54. ;; SSL_ERROR_ZERO_RETURN
  55. (define-condition ssl-error-zero-return (ssl-error/handle)
  56. ()
  57. (:documentation
  58. "The TLS/SSL connection has been closed. If the protocol version is SSL 3.0
  59. or TLS 1.0, this result code is returned only if a closure alert has
  60. occurred in the protocol, i.e. if the connection has been closed cleanly.
  61. Note that in this case SSL_ERROR_ZERO_RETURN
  62. does not necessarily indicate that the underlying transport has been
  63. closed.")
  64. (:report (lambda (condition stream)
  65. (format stream "The TLS/SSL connection on handle ~A has been closed. (return code: ~A)"
  66. (ssl-error-handle condition)
  67. (ssl-error-ret condition))
  68. (write-queued-errors condition stream))))
  69. ;; SSL_ERROR_WANT_READ
  70. (define-condition ssl-error-want-read (ssl-error-want-something)
  71. ()
  72. (:documentation
  73. "The operation did not complete; the same TLS/SSL I/O function should be
  74. called again later. If, by then, the underlying BIO has data available for
  75. reading (if the result code is SSL_ERROR_WANT_READ) or allows writing data
  76. (SSL_ERROR_WANT_WRITE), then some TLS/SSL protocol progress will take place,
  77. i.e. at least part of an TLS/SSL record will be read or written. Note that
  78. the retry may again lead to a SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
  79. condition. There is no fixed upper limit for the number of iterations that
  80. may be necessary until progress becomes visible at application protocol
  81. level.")
  82. (:report (lambda (condition stream)
  83. (format stream "The TLS/SSL operation on handle ~A did not complete: It wants a READ. (return code: ~A)"
  84. (ssl-error-handle condition)
  85. (ssl-error-ret condition))
  86. (write-queued-errors condition stream))))
  87. ;; SSL_ERROR_WANT_WRITE
  88. (define-condition ssl-error-want-write (ssl-error-want-something)
  89. ()
  90. (:documentation
  91. "The operation did not complete; the same TLS/SSL I/O function should be
  92. called again later. If, by then, the underlying BIO has data available for
  93. reading (if the result code is SSL_ERROR_WANT_READ) or allows writing data
  94. (SSL_ERROR_WANT_WRITE), then some TLS/SSL protocol progress will take place,
  95. i.e. at least part of an TLS/SSL record will be read or written. Note that
  96. the retry may again lead to a SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
  97. condition. There is no fixed upper limit for the number of iterations that
  98. may be necessary until progress becomes visible at application protocol
  99. level.")
  100. (:report (lambda (condition stream)
  101. (format stream "The TLS/SSL operation on handle ~A did not complete: It wants a WRITE. (return code: ~A)"
  102. (ssl-error-handle condition)
  103. (ssl-error-ret condition))
  104. (write-queued-errors condition stream))))
  105. ;; SSL_ERROR_WANT_CONNECT
  106. (define-condition ssl-error-want-connect (ssl-error-want-something)
  107. ()
  108. (:documentation
  109. "The operation did not complete; the same TLS/SSL I/O function should be
  110. called again later. The underlying BIO was not connected yet to the peer
  111. and the call would block in connect()/accept(). The SSL
  112. function should be called again when the connection is established. These
  113. messages can only appear with a BIO_s_connect() or
  114. BIO_s_accept() BIO, respectively. In order to find out, when
  115. the connection has been successfully established, on many platforms
  116. select() or poll() for writing on the socket file
  117. descriptor can be used.")
  118. (:report (lambda (condition stream)
  119. (format stream "The TLS/SSL operation on handle ~A did not complete: It wants a connect first. (return code: ~A)"
  120. (ssl-error-handle condition)
  121. (ssl-error-ret condition))
  122. (write-queued-errors condition stream))))
  123. ;; SSL_ERROR_WANT_X509_LOOKUP
  124. (define-condition ssl-error-want-x509-lookup (ssl-error-want-something)
  125. ()
  126. (:documentation
  127. "The operation did not complete because an application callback set by
  128. SSL_CTX_set_client_cert_cb() has asked to be called again. The
  129. TLS/SSL I/O function should be called again later. Details depend on the
  130. application.")
  131. (:report (lambda (condition stream)
  132. (format stream "The TLS/SSL operation on handle ~A did not complete: An application callback wants to be called again. (return code: ~A)"
  133. (ssl-error-handle condition)
  134. (ssl-error-ret condition))
  135. (write-queued-errors condition stream))))
  136. ;; SSL_ERROR_SYSCALL
  137. (define-condition ssl-error-syscall (ssl-error/handle)
  138. ((syscall :initarg :syscall))
  139. (:documentation
  140. "Some I/O error occurred. The OpenSSL error queue may contain more
  141. information on the error. If the error queue is empty (i.e. ERR_get_error() returns 0),
  142. ret can be used to find out more about the error: If ret == 0, an EOF was observed that
  143. violates the protocol. If ret == -1, the underlying BIO reported an I/O error (for socket
  144. I/O on Unix systems, consult errno for details).")
  145. (:report (lambda (condition stream)
  146. (if (zerop (err-get-error))
  147. (case (ssl-error-ret condition)
  148. (0 (format stream "An I/O error occurred: An unexpected EOF was observed on handle ~A. (return code: ~A)"
  149. (ssl-error-handle condition)
  150. (ssl-error-ret condition)))
  151. (-1 (format stream "An I/O error occurred in the underlying BIO. (return code: ~A)"
  152. (ssl-error-ret condition)))
  153. (otherwise (format stream "An I/O error occurred: undocumented reason. (return code: ~A)"
  154. (ssl-error-ret condition))))
  155. (format stream "An UNKNOWN I/O error occurred in the underlying BIO. (return code: ~A)"
  156. (ssl-error-ret condition)))
  157. (write-queued-errors condition stream))))
  158. ;; SSL_ERROR_SSL
  159. (define-condition ssl-error-ssl (ssl-error/handle)
  160. ()
  161. (:documentation
  162. "A failure in the SSL library occurred, usually a protocol error. The
  163. OpenSSL error queue contains more information on the error.")
  164. (:report (lambda (condition stream)
  165. (format stream
  166. "A failure in the SSL library occurred on handle ~A. (Return code: ~A)"
  167. (ssl-error-handle condition)
  168. (ssl-error-ret condition))
  169. (write-queued-errors condition stream))))
  170. (defun write-ssl-error-queue (stream)
  171. (format stream "SSL error queue: ~%")
  172. (loop
  173. for error-code = (err-get-error)
  174. until (zerop error-code)
  175. do (format stream "~a~%" (err-error-string error-code (cffi:null-pointer)))))
  176. (defun ssl-signal-error (handle syscall error-code original-error)
  177. (let ((queue (with-output-to-string (s) (write-ssl-error-queue s))))
  178. (if (and (eql error-code #.+ssl-error-syscall+)
  179. (not (zerop original-error)))
  180. (error 'ssl-error-syscall
  181. :handle handle
  182. :ret error-code
  183. :queue queue
  184. :syscall syscall)
  185. (error (case error-code
  186. (#.+ssl-error-none+ 'ssl-error-none)
  187. (#.+ssl-error-ssl+ 'ssl-error-ssl)
  188. (#.+ssl-error-want-read+ 'ssl-error-want-read)
  189. (#.+ssl-error-want-write+ 'ssl-error-want-write)
  190. (#.+ssl-error-want-x509-lookup+ 'ssl-error-want-x509-lookup)
  191. (#.+ssl-error-zero-return+ 'ssl-error-zero-return)
  192. (#.+ssl-error-want-connect+ 'ssl-error-want-connect)
  193. (#.+ssl-error-syscall+ 'ssl-error-zero-return)
  194. (t 'ssl-error/handle))
  195. :handle handle
  196. :ret error-code
  197. :queue queue))))