Last active
August 29, 2015 14:12
-
-
Save Asmod4n/28e9902421642096a4d0 to your computer and use it in GitHub Desktop.
SecureBuffer for mruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <sodium.h> | |
#include <mruby.h> | |
#include <mruby/data.h> | |
#include <mruby/class.h> | |
#include <mruby/string.h> | |
#include <mruby/array.h> | |
#include "picohttpparser.h" | |
static mrb_value | |
pico_parse(mrb_state *mrb, mrb_value self) | |
{ | |
mrb_int i; | |
char *request; | |
mrb_int request_len; | |
mrb_value block; | |
int ret; | |
const char *method; | |
size_t method_len; | |
const char *path; | |
size_t path_len; | |
int minor_version; | |
size_t num_headers = 32; | |
struct phr_header headers[num_headers]; | |
mrb_value yield_array, headers_array, body; | |
i = mrb_get_args(mrb, "s&", &request, &request_len, &block); | |
ret = phr_parse_request(request, request_len, | |
&method, &method_len, &path, &path_len, &minor_version, headers, | |
&num_headers, 0); | |
yield_array = mrb_ary_new_capa(mrb, 5); | |
mrb_ary_set(mrb, yield_array, 0, mrb_str_new_static(mrb, method, method_len)); | |
mrb_ary_set(mrb, yield_array, 1, mrb_str_new_static(mrb, path, path_len)); | |
mrb_ary_set(mrb, yield_array, 2, mrb_fixnum_value(minor_version)); | |
headers_array = mrb_ary_new_capa(mrb, (mrb_int)num_headers); | |
for(i=0;i != num_headers;i++) { | |
mrb_value tmp = mrb_ary_new_capa(mrb, 2); | |
mrb_ary_set(mrb, tmp, 0, | |
mrb_str_new_static(mrb, headers[i].name, headers[i].name_len)); | |
mrb_ary_set(mrb, tmp, 1, | |
mrb_str_new_static(mrb, headers[i].value, headers[i].value_len)); | |
mrb_ary_set(mrb, headers_array, i, tmp); | |
} | |
mrb_ary_set(mrb, yield_array, 3, headers_array); | |
body = mrb_str_new_static(mrb, request + ret, request_len - ret); | |
mrb_ary_set(mrb, yield_array, 4, body); | |
return mrb_yield(mrb, block, yield_array); | |
} | |
static mrb_value | |
mrb_sodium_init(mrb_state *mrb, mrb_value self) | |
{ | |
if (sodium_init () == -1) { | |
mrb_raise(mrb, E_RUNTIME_ERROR, "Could nit initalize libsodium"); | |
} else { | |
return mrb_true_value(); | |
} | |
} | |
typedef struct { | |
void *ptr; | |
mrb_int size; | |
} secret_buffer_t; | |
static void | |
secret_buffer_free(mrb_state *mrb, void *p) | |
{ | |
secret_buffer_t *buffer; | |
buffer = (secret_buffer_t *) p; | |
if (sodium_mprotect_readonly (buffer->ptr) == 0) | |
sodium_free(buffer->ptr); | |
} | |
static const struct mrb_data_type secret_buffer_type = { | |
"$i_secret_buffer", secret_buffer_free, | |
}; | |
static mrb_value | |
secret_buffer_init(mrb_state *mrb, mrb_value self) | |
{ | |
secret_buffer_t *buffer; | |
mrb_int size; | |
buffer = (secret_buffer_t *) DATA_PTR(self); | |
if(buffer) | |
mrb_free(mrb, buffer); | |
mrb_data_init(self, NULL, &secret_buffer_type); | |
mrb_get_args(mrb, "i", &size); | |
if (size >= 0) { | |
buffer = (secret_buffer_t *) mrb_calloc(mrb, 1, sizeof(buffer)); | |
buffer->ptr = sodium_malloc ((size_t)size); | |
if (buffer->ptr == NULL) { | |
mrb->out_of_memory = TRUE; | |
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); | |
} else { | |
buffer->size = size; | |
mrb_data_init(self, buffer, &secret_buffer_type); | |
} | |
} else { | |
mrb_raise(mrb, E_RANGE_ERROR, "size musn't be negative"); | |
} | |
return self; | |
} | |
static mrb_value | |
secret_buffer_ptr(mrb_state *mrb, mrb_value self) | |
{ | |
secret_buffer_t *buffer; | |
buffer = (secret_buffer_t *) DATA_PTR(self); | |
return mrb_cptr_value(mrb, buffer->ptr); | |
} | |
static mrb_value | |
secret_buffer_size(mrb_state *mrb, mrb_value self) | |
{ | |
secret_buffer_t *buffer; | |
buffer = (secret_buffer_t *) DATA_PTR(self); | |
return mrb_fixnum_value(buffer->size); | |
} | |
static mrb_value | |
secret_buffer_noaccess(mrb_state *mrb, mrb_value self) | |
{ | |
secret_buffer_t *buffer; | |
int rc; | |
buffer = (secret_buffer_t *) DATA_PTR(self); | |
rc = sodium_mprotect_noaccess (buffer->ptr); | |
if (rc == 0) | |
return mrb_true_value(); | |
else | |
return mrb_false_value(); | |
} | |
static mrb_value | |
secret_buffer_readonly(mrb_state *mrb, mrb_value self) | |
{ | |
secret_buffer_t *buffer; | |
int rc; | |
buffer = (secret_buffer_t *) DATA_PTR(self); | |
rc = sodium_mprotect_readonly (buffer->ptr); | |
if (rc == 0) | |
return mrb_true_value(); | |
else | |
return mrb_false_value(); | |
} | |
static mrb_value | |
secret_buffer_readwrite(mrb_state *mrb, mrb_value self) | |
{ | |
secret_buffer_t *buffer; | |
int rc; | |
buffer = (secret_buffer_t *) DATA_PTR(self); | |
rc = sodium_mprotect_readwrite (buffer->ptr); | |
if (rc == 0) | |
return mrb_true_value(); | |
else | |
return mrb_false_value(); | |
} | |
static mrb_value | |
mrb_randombytes_random(mrb_state *mrb, mrb_value self) | |
{ | |
uint32_t ran; | |
ran = randombytes_random (); | |
if (ran > MRB_INT_MAX) | |
return mrb_float_value(mrb, ran); | |
else | |
return mrb_fixnum_value(ran); | |
} | |
static mrb_value | |
mrb_randombytes_uniform(mrb_state *mrb, mrb_value self) | |
{ | |
mrb_float upper_bound; | |
uint32_t ran; | |
mrb_get_args(mrb, "f", &upper_bound); | |
if (upper_bound >= 0 && upper_bound <= UINT32_MAX) { | |
ran = randombytes_uniform ((uint32_t)upper_bound); | |
if (ran > MRB_INT_MAX) | |
return mrb_float_value(mrb, ran); | |
else | |
return mrb_fixnum_value(ran); | |
} else { | |
mrb_raise(mrb, E_RANGE_ERROR, "upper_bound is out of range"); | |
} | |
} | |
static mrb_value | |
mrb_randombytes_buf(mrb_state *mrb, mrb_value self) | |
{ | |
mrb_value buf_obj; | |
void *buf; | |
mrb_int size; | |
mrb_get_args(mrb, "o", &buf_obj); | |
switch (mrb_type(buf_obj)) { | |
case MRB_TT_STRING: | |
buf = RSTRING_PTR(buf_obj); | |
size = RSTRING_LEN(buf_obj); | |
break; | |
case MRB_TT_DATA: | |
if (DATA_TYPE(buf_obj) == &secret_buffer_type) { | |
secret_buffer_t *buffer; | |
buffer = (secret_buffer_t *) DATA_PTR(buf_obj); | |
buf = buffer->ptr; | |
size = buffer->size; | |
} | |
else | |
mrb_raise(mrb, E_TYPE_ERROR, "only works with Strings or SecureBuffers"); | |
break; | |
default: | |
mrb_raise(mrb, E_TYPE_ERROR, "only works with Strings or SecureBuffers"); | |
} | |
randombytes_buf(buf, (size_t)size); | |
return buf_obj; | |
} | |
void | |
mrb_c_extension_example_gem_init(mrb_state* mrb) { | |
struct RClass *sodium_class; | |
sodium_class = mrb_define_module(mrb, "Sodium"); | |
mrb_define_module_function(mrb, sodium_class, "init", mrb_sodium_init, MRB_ARGS_NONE()); | |
struct RClass *secret_buffer_class; | |
secret_buffer_class = mrb_define_class_under(mrb, sodium_class, "SecretBuffer", mrb->object_class); | |
MRB_SET_INSTANCE_TT(secret_buffer_class, MRB_TT_DATA); | |
mrb_define_method(mrb, secret_buffer_class, "initialize", secret_buffer_init, MRB_ARGS_REQ(1)); | |
mrb_define_method(mrb, secret_buffer_class, "ptr", secret_buffer_ptr, MRB_ARGS_NONE()); | |
mrb_define_method(mrb, secret_buffer_class, "size", secret_buffer_size, MRB_ARGS_NONE()); | |
mrb_define_method(mrb, secret_buffer_class, "noaccess", secret_buffer_noaccess, MRB_ARGS_NONE()); | |
mrb_define_method(mrb, secret_buffer_class, "readonly", secret_buffer_readonly, MRB_ARGS_NONE()); | |
mrb_define_method(mrb, secret_buffer_class, "readwrite", secret_buffer_readwrite, MRB_ARGS_NONE()); | |
struct RClass *random_bytes_class; | |
random_bytes_class = mrb_define_module(mrb, "RandomBytes"); | |
mrb_define_module_function(mrb, random_bytes_class, "random", mrb_randombytes_random, MRB_ARGS_NONE()); | |
mrb_define_module_function(mrb, random_bytes_class, "uniform", mrb_randombytes_uniform, MRB_ARGS_REQ(1)); | |
mrb_define_module_function(mrb, random_bytes_class, "buf", mrb_randombytes_buf, MRB_ARGS_REQ(1)); | |
mrb_define_module_function(mrb, random_bytes_class, "parse", pico_parse, MRB_ARGS_REQ(2)); | |
} | |
void | |
mrb_c_extension_example_gem_final(mrb_state* mrb) { | |
/* finalizer */ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment