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

/ruby-1.8.7/ext/openssl/ossl_ssl_session.c

http://github.com/replit/emscripted-ruby
C | 298 lines | 185 code | 60 blank | 53 comment | 26 complexity | 379a34d3247487203e944897c60f52d7 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, AGPL-3.0
  1. /*
  2. * Copyright (C) 2004-2007 Technorama Ltd. <oss-ruby@technorama.net>
  3. */
  4. #include "ossl.h"
  5. #define GetSSLSession(obj, sess) do { \
  6. Data_Get_Struct(obj, SSL_SESSION, sess); \
  7. if (!sess) { \
  8. ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
  9. } \
  10. } while (0)
  11. #define SafeGetSSLSession(obj, sess) do { \
  12. OSSL_Check_Kind(obj, cSSLSession); \
  13. GetSSLSession(obj, sess); \
  14. } while (0)
  15. VALUE cSSLSession;
  16. static VALUE eSSLSession;
  17. static VALUE ossl_ssl_session_alloc(VALUE klass)
  18. {
  19. return Data_Wrap_Struct(klass, 0, SSL_SESSION_free, NULL);
  20. }
  21. /*
  22. * call-seq:
  23. * Session.new(SSLSocket | string) => session
  24. *
  25. * === Parameters
  26. * +SSLSocket+ is an OpenSSL::SSL::SSLSocket
  27. * +string+ must be a DER or PEM encoded Session.
  28. */
  29. static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
  30. {
  31. SSL_SESSION *ctx = NULL;
  32. VALUE obj;
  33. unsigned char *p;
  34. if (RDATA(self)->data)
  35. ossl_raise(eSSLSession, "SSL Session already initialized");
  36. if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
  37. SSL *ssl;
  38. Data_Get_Struct(arg1, SSL, ssl);
  39. if ((ctx = SSL_get1_session(ssl)) == NULL)
  40. ossl_raise(eSSLSession, "no session available");
  41. } else {
  42. BIO *in = ossl_obj2bio(arg1);
  43. ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
  44. if (!ctx) {
  45. BIO_reset(in);
  46. ctx = d2i_SSL_SESSION_bio(in, NULL);
  47. }
  48. BIO_free(in);
  49. if (!ctx)
  50. ossl_raise(rb_eArgError, "unknown type");
  51. }
  52. /* should not happen */
  53. if (ctx == NULL)
  54. ossl_raise(eSSLSession, "ctx not set - internal error");
  55. RDATA(self)->data = ctx;
  56. return self;
  57. }
  58. /*
  59. * call-seq:
  60. * session1 == session2 -> boolean
  61. *
  62. */
  63. static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
  64. {
  65. SSL_SESSION *ctx1, *ctx2;
  66. GetSSLSession(val1, ctx1);
  67. SafeGetSSLSession(val2, ctx2);
  68. switch (SSL_SESSION_cmp(ctx1, ctx2)) {
  69. case 0: return Qtrue;
  70. default: return Qfalse;
  71. }
  72. }
  73. /*
  74. * call-seq:
  75. * session.time -> Time
  76. *
  77. */
  78. static VALUE ossl_ssl_session_get_time(VALUE self)
  79. {
  80. SSL_SESSION *ctx;
  81. time_t t;
  82. GetSSLSession(self, ctx);
  83. t = SSL_SESSION_get_time(ctx);
  84. if (t == 0)
  85. return Qnil;
  86. return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
  87. }
  88. /*
  89. * call-seq:
  90. * session.timeout -> integer
  91. *
  92. * How long until the session expires in seconds.
  93. *
  94. */
  95. static VALUE ossl_ssl_session_get_timeout(VALUE self)
  96. {
  97. SSL_SESSION *ctx;
  98. time_t t;
  99. GetSSLSession(self, ctx);
  100. t = SSL_SESSION_get_timeout(ctx);
  101. return ULONG2NUM(t);
  102. }
  103. #define SSLSESSION_SET_TIME(func) \
  104. static VALUE ossl_ssl_session_set_##func(VALUE self, VALUE time_v) \
  105. { \
  106. SSL_SESSION *ctx; \
  107. time_t t; \
  108. \
  109. GetSSLSession(self, ctx); \
  110. \
  111. if (rb_obj_is_instance_of(time_v, rb_cTime)) { \
  112. time_v = rb_funcall(time_v, rb_intern("to_i"), 0); \
  113. } else if (FIXNUM_P(time_v)) { \
  114. ; \
  115. } else { \
  116. rb_raise(rb_eArgError, "unknown type"); \
  117. } \
  118. \
  119. t = NUM2ULONG(time_v); \
  120. \
  121. SSL_SESSION_set_##func(ctx, t); \
  122. \
  123. return ossl_ssl_session_get_##func(self); \
  124. }
  125. SSLSESSION_SET_TIME(time)
  126. SSLSESSION_SET_TIME(timeout)
  127. #ifdef HAVE_SSL_SESSION_GET_ID
  128. /*
  129. * call-seq:
  130. * session.id -> aString
  131. *
  132. * Returns the Session ID.
  133. */
  134. static VALUE ossl_ssl_session_get_id(VALUE self)
  135. {
  136. SSL_SESSION *ctx;
  137. const unsigned char *p = NULL;
  138. unsigned int i = 0;
  139. GetSSLSession(self, ctx);
  140. p = SSL_SESSION_get_id(ctx, &i);
  141. return rb_str_new((const char *) p, i);
  142. }
  143. #endif
  144. /*
  145. * call-seq:
  146. * session.to_der -> aString
  147. *
  148. * Returns an ASN1 encoded String that contains the Session object.
  149. */
  150. static VALUE ossl_ssl_session_to_der(VALUE self)
  151. {
  152. SSL_SESSION *ctx;
  153. unsigned char buf[1024*10], *p;
  154. int len;
  155. GetSSLSession(self, ctx);
  156. p = buf;
  157. len = i2d_SSL_SESSION(ctx, &p);
  158. if (len <= 0)
  159. ossl_raise(eSSLSession, "i2d_SSL_SESSION");
  160. else if (len >= sizeof(buf))
  161. ossl_raise(eSSLSession, "i2d_SSL_SESSION too large");
  162. return rb_str_new((const char *) p, len);
  163. }
  164. /*
  165. * call-seq:
  166. * session.to_pem -> String
  167. *
  168. * Returns a PEM encoded String that contains the Session object.
  169. */
  170. static VALUE ossl_ssl_session_to_pem(VALUE self)
  171. {
  172. SSL_SESSION *ctx;
  173. BIO *out;
  174. BUF_MEM *buf;
  175. VALUE str;
  176. int i;
  177. GetSSLSession(self, ctx);
  178. if (!(out = BIO_new(BIO_s_mem()))) {
  179. ossl_raise(eSSLSession, "BIO_s_mem()");
  180. }
  181. if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
  182. BIO_free(out);
  183. ossl_raise(eSSLSession, "SSL_SESSION_print()");
  184. }
  185. BIO_get_mem_ptr(out, &buf);
  186. str = rb_str_new(buf->data, buf->length);
  187. BIO_free(out);
  188. return str;
  189. }
  190. /*
  191. * call-seq:
  192. * session.to_text -> String
  193. *
  194. * Shows everything in the Session object.
  195. */
  196. static VALUE ossl_ssl_session_to_text(VALUE self)
  197. {
  198. SSL_SESSION *ctx;
  199. BIO *out;
  200. BUF_MEM *buf;
  201. VALUE str;
  202. GetSSLSession(self, ctx);
  203. if (!(out = BIO_new(BIO_s_mem()))) {
  204. ossl_raise(eSSLSession, "BIO_s_mem()");
  205. }
  206. if (!SSL_SESSION_print(out, ctx)) {
  207. BIO_free(out);
  208. ossl_raise(eSSLSession, "SSL_SESSION_print()");
  209. }
  210. BIO_get_mem_ptr(out, &buf);
  211. str = rb_str_new(buf->data, buf->length);
  212. BIO_free(out);
  213. return str;
  214. }
  215. void Init_ossl_ssl_session(void)
  216. {
  217. #if 0 /* let rdoc know about mOSSL */
  218. mOSSL = rb_define_module("OpenSSL");
  219. mSSL = rb_define_module_under(mOSSL, "SSL");
  220. #endif
  221. cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
  222. eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
  223. rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
  224. rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
  225. rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
  226. rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
  227. rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
  228. rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
  229. rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
  230. #ifdef HAVE_SSL_SESSION_GET_ID
  231. rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
  232. #else
  233. rb_undef_method(cSSLSession, "id");
  234. #endif
  235. rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
  236. rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
  237. rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
  238. }