|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /* 00002 * $Id: ossl.c 27440 2010-04-22 08:21:01Z nobu $ 00003 * 'OpenSSL for Ruby' project 00004 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> 00005 * All rights reserved. 00006 */ 00007 /* 00008 * This program is licenced under the same licence as Ruby. 00009 * (See the file 'LICENCE'.) 00010 */ 00011 #include "ossl.h" 00012 #include <stdarg.h> /* for ossl_raise */ 00013 00014 /* 00015 * String to HEXString conversion 00016 */ 00017 int 00018 string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len) 00019 { 00020 static const char hex[]="0123456789abcdef"; 00021 int i, len = 2 * buf_len; 00022 00023 if (buf_len < 0 || len < buf_len) { /* PARANOIA? */ 00024 return -1; 00025 } 00026 if (!hexbuf) { /* if no buf, return calculated len */ 00027 if (hexbuf_len) { 00028 *hexbuf_len = len; 00029 } 00030 return len; 00031 } 00032 if (!(*hexbuf = OPENSSL_malloc(len + 1))) { 00033 return -1; 00034 } 00035 for (i = 0; i < buf_len; i++) { 00036 (*hexbuf)[2 * i] = hex[((unsigned char)buf[i]) >> 4]; 00037 (*hexbuf)[2 * i + 1] = hex[buf[i] & 0x0f]; 00038 } 00039 (*hexbuf)[2 * i] = '\0'; 00040 00041 if (hexbuf_len) { 00042 *hexbuf_len = len; 00043 } 00044 return len; 00045 } 00046 00047 /* 00048 * Data Conversion 00049 */ 00050 STACK_OF(X509) * 00051 ossl_x509_ary2sk0(VALUE ary) 00052 { 00053 STACK_OF(X509) *sk; 00054 VALUE val; 00055 X509 *x509; 00056 int i; 00057 00058 Check_Type(ary, T_ARRAY); 00059 sk = sk_X509_new_null(); 00060 if (!sk) ossl_raise(eOSSLError, NULL); 00061 00062 for (i = 0; i < RARRAY_LEN(ary); i++) { 00063 val = rb_ary_entry(ary, i); 00064 if (!rb_obj_is_kind_of(val, cX509Cert)) { 00065 sk_X509_pop_free(sk, X509_free); 00066 ossl_raise(eOSSLError, "object not X509 cert in array"); 00067 } 00068 x509 = DupX509CertPtr(val); /* NEED TO DUP */ 00069 sk_X509_push(sk, x509); 00070 } 00071 return sk; 00072 } 00073 00074 STACK_OF(X509) * 00075 ossl_protect_x509_ary2sk(VALUE ary, int *status) 00076 { 00077 return (STACK_OF(X509)*)rb_protect((VALUE(*)_((VALUE)))ossl_x509_ary2sk0, 00078 ary, status); 00079 } 00080 00081 STACK_OF(X509) * 00082 ossl_x509_ary2sk(VALUE ary) 00083 { 00084 STACK_OF(X509) *sk; 00085 int status = 0; 00086 00087 sk = ossl_protect_x509_ary2sk(ary, &status); 00088 if(status) rb_jump_tag(status); 00089 00090 return sk; 00091 } 00092 00093 #define OSSL_IMPL_SK2ARY(name, type) \ 00094 VALUE \ 00095 ossl_##name##_sk2ary(STACK_OF(type) *sk) \ 00096 { \ 00097 type *t; \ 00098 int i, num; \ 00099 VALUE ary; \ 00100 \ 00101 if (!sk) { \ 00102 OSSL_Debug("empty sk!"); \ 00103 return Qnil; \ 00104 } \ 00105 num = sk_##type##_num(sk); \ 00106 if (num < 0) { \ 00107 OSSL_Debug("items in sk < -1???"); \ 00108 return rb_ary_new(); \ 00109 } \ 00110 ary = rb_ary_new2(num); \ 00111 \ 00112 for (i=0; i<num; i++) { \ 00113 t = sk_##type##_value(sk, i); \ 00114 rb_ary_push(ary, ossl_##name##_new(t)); \ 00115 } \ 00116 return ary; \ 00117 } 00118 OSSL_IMPL_SK2ARY(x509, X509) 00119 OSSL_IMPL_SK2ARY(x509crl, X509_CRL) 00120 00121 static VALUE 00122 ossl_str_new(int size) 00123 { 00124 return rb_str_new(0, size); 00125 } 00126 00127 VALUE 00128 ossl_buf2str(char *buf, int len) 00129 { 00130 VALUE str; 00131 int status = 0; 00132 00133 str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status); 00134 if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len); 00135 OPENSSL_free(buf); 00136 if(status) rb_jump_tag(status); 00137 00138 return str; 00139 } 00140 00141 /* 00142 * our default PEM callback 00143 */ 00144 static VALUE 00145 ossl_pem_passwd_cb0(VALUE flag) 00146 { 00147 VALUE pass; 00148 00149 pass = rb_yield(flag); 00150 SafeStringValue(pass); 00151 00152 return pass; 00153 } 00154 00155 int 00156 ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd) 00157 { 00158 int len, status = 0; 00159 VALUE rflag, pass; 00160 00161 if (pwd || !rb_block_given_p()) 00162 return PEM_def_callback(buf, max_len, flag, pwd); 00163 00164 while (1) { 00165 /* 00166 * when the flag is nonzero, this passphrase 00167 * will be used to perform encryption; otherwise it will 00168 * be used to perform decryption. 00169 */ 00170 rflag = flag ? Qtrue : Qfalse; 00171 pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status); 00172 if (status) return -1; /* exception was raised. */ 00173 len = RSTRING_LEN(pass); 00174 if (len < 4) { /* 4 is OpenSSL hardcoded limit */ 00175 rb_warning("password must be longer than 4 bytes"); 00176 continue; 00177 } 00178 if (len > max_len) { 00179 rb_warning("password must be shorter then %d bytes", max_len-1); 00180 continue; 00181 } 00182 memcpy(buf, RSTRING_PTR(pass), len); 00183 break; 00184 } 00185 return len; 00186 } 00187 00188 /* 00189 * Verify callback 00190 */ 00191 int ossl_verify_cb_idx; 00192 00193 VALUE 00194 ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args) 00195 { 00196 return rb_funcall(args->proc, rb_intern("call"), 2, 00197 args->preverify_ok, args->store_ctx); 00198 } 00199 00200 int 00201 ossl_verify_cb(int ok, X509_STORE_CTX *ctx) 00202 { 00203 VALUE proc, rctx, ret; 00204 struct ossl_verify_cb_args args; 00205 int state = 0; 00206 00207 proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx); 00208 if ((void*)proc == 0) 00209 proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx); 00210 if ((void*)proc == 0) 00211 return ok; 00212 if (!NIL_P(proc)) { 00213 rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, 00214 (VALUE)ctx, &state); 00215 ret = Qfalse; 00216 if (!state) { 00217 args.proc = proc; 00218 args.preverify_ok = ok ? Qtrue : Qfalse; 00219 args.store_ctx = rctx; 00220 ret = rb_ensure(ossl_call_verify_cb_proc, (VALUE)&args, 00221 ossl_x509stctx_clear_ptr, rctx); 00222 } 00223 if (ret == Qtrue) { 00224 X509_STORE_CTX_set_error(ctx, X509_V_OK); 00225 ok = 1; 00226 } 00227 else{ 00228 if (X509_STORE_CTX_get_error(ctx) == X509_V_OK) { 00229 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED); 00230 } 00231 ok = 0; 00232 } 00233 } 00234 00235 return ok; 00236 } 00237 00238 /* 00239 * main module 00240 */ 00241 VALUE mOSSL; 00242 00243 /* 00244 * OpenSSLError < StandardError 00245 */ 00246 VALUE eOSSLError; 00247 00248 /* 00249 * Convert to DER string 00250 */ 00251 ID ossl_s_to_der; 00252 00253 VALUE 00254 ossl_to_der(VALUE obj) 00255 { 00256 VALUE tmp; 00257 00258 tmp = rb_funcall(obj, ossl_s_to_der, 0); 00259 StringValue(tmp); 00260 00261 return tmp; 00262 } 00263 00264 VALUE 00265 ossl_to_der_if_possible(VALUE obj) 00266 { 00267 if(rb_respond_to(obj, ossl_s_to_der)) 00268 return ossl_to_der(obj); 00269 return obj; 00270 } 00271 00272 /* 00273 * Errors 00274 */ 00275 static VALUE 00276 ossl_make_error(VALUE exc, const char *fmt, va_list args) 00277 { 00278 char buf[BUFSIZ]; 00279 const char *msg; 00280 long e; 00281 int len = 0; 00282 00283 #ifdef HAVE_ERR_PEEK_LAST_ERROR 00284 e = ERR_peek_last_error(); 00285 #else 00286 e = ERR_peek_error(); 00287 #endif 00288 if (fmt) { 00289 len = vsnprintf(buf, BUFSIZ, fmt, args); 00290 } 00291 if (len < BUFSIZ && e) { 00292 if (dOSSL == Qtrue) /* FULL INFO */ 00293 msg = ERR_error_string(e, NULL); 00294 else 00295 msg = ERR_reason_error_string(e); 00296 len += snprintf(buf+len, BUFSIZ-len, "%s%s", (len ? ": " : ""), msg); 00297 } 00298 if (dOSSL == Qtrue){ /* show all errors on the stack */ 00299 while ((e = ERR_get_error()) != 0){ 00300 rb_warn("error on stack: %s", ERR_error_string(e, NULL)); 00301 } 00302 } 00303 ERR_clear_error(); 00304 00305 if(len > BUFSIZ) len = strlen(buf); 00306 return rb_exc_new(exc, buf, len); 00307 } 00308 00309 void 00310 ossl_raise(VALUE exc, const char *fmt, ...) 00311 { 00312 va_list args; 00313 VALUE err; 00314 va_start(args, fmt); 00315 err = ossl_make_error(exc, fmt, args); 00316 va_end(args); 00317 rb_exc_raise(err); 00318 } 00319 00320 VALUE 00321 ossl_exc_new(VALUE exc, const char *fmt, ...) 00322 { 00323 va_list args; 00324 VALUE err; 00325 va_start(args, fmt); 00326 err = ossl_make_error(exc, fmt, args); 00327 va_end(args); 00328 return err; 00329 } 00330 00331 /* 00332 * call-seq: 00333 * OpenSSL.errors -> [String...] 00334 * 00335 * See any remaining errors held in queue. 00336 * 00337 * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation. 00338 */ 00339 VALUE 00340 ossl_get_errors() 00341 { 00342 VALUE ary; 00343 long e; 00344 00345 ary = rb_ary_new(); 00346 while ((e = ERR_get_error()) != 0){ 00347 rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL))); 00348 } 00349 00350 return ary; 00351 } 00352 00353 /* 00354 * Debug 00355 */ 00356 VALUE dOSSL; 00357 00358 #if !defined(HAVE_VA_ARGS_MACRO) 00359 void 00360 ossl_debug(const char *fmt, ...) 00361 { 00362 va_list args; 00363 00364 if (dOSSL == Qtrue) { 00365 fprintf(stderr, "OSSL_DEBUG: "); 00366 va_start(args, fmt); 00367 vfprintf(stderr, fmt, args); 00368 va_end(args); 00369 fprintf(stderr, " [CONTEXT N/A]\n"); 00370 } 00371 } 00372 #endif 00373 00374 /* 00375 * call-seq: 00376 * OpenSSL.debug -> true | false 00377 */ 00378 static VALUE 00379 ossl_debug_get(VALUE self) 00380 { 00381 return dOSSL; 00382 } 00383 00384 /* 00385 * call-seq: 00386 * OpenSSL.debug = boolean -> boolean 00387 * 00388 * Turns on or off CRYPTO_MEM_CHECK. 00389 * Also shows some debugging message on stderr. 00390 */ 00391 static VALUE 00392 ossl_debug_set(VALUE self, VALUE val) 00393 { 00394 VALUE old = dOSSL; 00395 dOSSL = val; 00396 00397 if (old != dOSSL) { 00398 if (dOSSL == Qtrue) { 00399 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 00400 fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n"); 00401 } else if (old == Qtrue) { 00402 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); 00403 fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n"); 00404 } 00405 } 00406 return val; 00407 } 00408 00409 /* 00410 * OSSL library init 00411 */ 00412 void 00413 Init_openssl() 00414 { 00415 /* 00416 * Init timezone info 00417 */ 00418 #if 0 00419 tzset(); 00420 #endif 00421 00422 /* 00423 * Init all digests, ciphers 00424 */ 00425 /* CRYPTO_malloc_init(); */ 00426 /* ENGINE_load_builtin_engines(); */ 00427 OpenSSL_add_ssl_algorithms(); 00428 OpenSSL_add_all_algorithms(); 00429 ERR_load_crypto_strings(); 00430 SSL_load_error_strings(); 00431 00432 /* 00433 * FIXME: 00434 * On unload do: 00435 */ 00436 #if 0 00437 CONF_modules_unload(1); 00438 destroy_ui_method(); 00439 EVP_cleanup(); 00440 ENGINE_cleanup(); 00441 CRYPTO_cleanup_all_ex_data(); 00442 ERR_remove_state(0); 00443 ERR_free_strings(); 00444 #endif 00445 00446 /* 00447 * Init main module 00448 */ 00449 mOSSL = rb_define_module("OpenSSL"); 00450 00451 /* 00452 * Constants 00453 */ 00454 rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION)); 00455 rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT)); 00456 rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); 00457 00458 /* 00459 * Generic error, 00460 * common for all classes under OpenSSL module 00461 */ 00462 eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError); 00463 00464 /* 00465 * Verify callback Proc index for ext-data 00466 */ 00467 if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0) 00468 ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); 00469 00470 /* 00471 * Init debug core 00472 */ 00473 dOSSL = Qfalse; 00474 rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0); 00475 rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1); 00476 rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0); 00477 00478 /* 00479 * Get ID of to_der 00480 */ 00481 ossl_s_to_der = rb_intern("to_der"); 00482 00483 /* 00484 * Init components 00485 */ 00486 Init_ossl_bn(); 00487 Init_ossl_cipher(); 00488 Init_ossl_config(); 00489 Init_ossl_digest(); 00490 Init_ossl_hmac(); 00491 Init_ossl_ns_spki(); 00492 Init_ossl_pkcs12(); 00493 Init_ossl_pkcs7(); 00494 Init_ossl_pkcs5(); 00495 Init_ossl_pkey(); 00496 Init_ossl_rand(); 00497 Init_ossl_ssl(); 00498 Init_ossl_x509(); 00499 Init_ossl_ocsp(); 00500 Init_ossl_engine(); 00501 Init_ossl_asn1(); 00502 } 00503 00504 #if defined(OSSL_DEBUG) 00505 /* 00506 * Check if all symbols are OK with 'make LDSHARED=gcc all' 00507 */ 00508 int 00509 main(int argc, char *argv[]) 00510 { 00511 return 0; 00512 } 00513 #endif /* OSSL_DEBUG */ 00514 00515
1.7.3