summaryrefslogtreecommitdiff
path: root/ext/openssl/ossl_config.c
blob: f721bb90b1627a370f5d8d1bd5821e51ab843439 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
 * $Id$
 * 'OpenSSL for Ruby' project
 * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
 * All rights reserved.
 */
/*
 * This program is licenced under the same licence as Ruby.
 * (See the file 'LICENCE'.)
 */
#include "ossl.h"

#define WrapConfig(klass, obj, conf) do { \
    if (!conf) { \
	ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
    } \
    obj = Data_Wrap_Struct(klass, 0, NCONF_free, conf); \
} while (0)

#define GetConfig(obj, conf) do { \
    Data_Get_Struct(obj, CONF, conf); \
    if (!conf) { \
	ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
    } \
} while (0)

/*
 * Classes
 */
VALUE cConfig;
VALUE eConfigError;

/* 
 * Public 
 */

/*
 * Private
 */
static VALUE
ossl_config_s_load(int argc, VALUE *argv, VALUE klass)
{
    CONF *conf;
    long err_line = -1;
    char *filename;
    VALUE path, obj;

    if (rb_scan_args(argc, argv, "01", &path) == 1) {
	SafeStringValue(path);
	filename = BUF_strdup(RSTRING(path)->ptr);
    }
    else {
	if (!(filename = CONF_get1_default_config_file())) {
	    ossl_raise(eConfigError, NULL);
	}
    }
    if (!(conf = NCONF_new(NULL))) {
	OPENSSL_free(filename);
	ossl_raise(eConfigError, NULL);
    }
    OSSL_Debug("Loading file: %s", filename);

    if (!NCONF_load(conf, filename, &err_line)) {
	char tmp[255];

	memcpy(tmp, filename, strlen(filename)>=sizeof(tmp)?sizeof(tmp):strlen(filename));
	tmp[sizeof(tmp)-1] = '\0';
	OPENSSL_free(filename);
	
	if (err_line <= 0) {
	    ossl_raise(eConfigError, "wrong config file (%s)", tmp);
	} else {
	    ossl_raise(eConfigError, "error on line %ld in config file \"%s\"",
		       err_line, tmp);
	}
    }
    OPENSSL_free(filename);
    WrapConfig(klass, obj, conf);
    
    return obj;
}

static VALUE
ossl_config_get_value(int argc, VALUE *argv, VALUE self)
{
    CONF *conf;
    VALUE section, item;
    char *sect = NULL, *str;
	
    GetConfig(self, conf);

    if (rb_scan_args(argc, argv, "11", &section, &item) == 1) {
	item = section;
    } else if (!NIL_P(section)) {
	sect = StringValuePtr(section);
    }
    if (!(str = NCONF_get_string(conf, sect, StringValuePtr(item)))) {
	ossl_raise(eConfigError, NULL);
    }
    return rb_str_new2(str);
}

/*
 * Get all numbers as strings - use str.to_i to convert
 * long number = CONF_get_number(confp->config, sect, StringValuePtr(item));
 */

static VALUE
ossl_config_get_section(VALUE self, VALUE section)
{
    CONF *conf;
    STACK_OF(CONF_VALUE) *sk;
    CONF_VALUE *entry;
    int i, entries;
    VALUE hash;

    GetConfig(self, conf);
	
    if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) {
	ossl_raise(eConfigError, NULL);
    }
    hash = rb_hash_new();
    
    if ((entries = sk_CONF_VALUE_num(sk)) < 0) {
	OSSL_Debug("# of items in section is < 0?!?");
	return hash;
    }
    for (i=0; i<entries; i++) {
	entry = sk_CONF_VALUE_value(sk, i);		
	rb_hash_aset(hash, rb_str_new2(entry->name), rb_str_new2(entry->value));
    }
    return hash;
}

/*
 * INIT
 */
void
Init_ossl_config()
{
    eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);

    cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
	
    rb_define_singleton_method(cConfig, "load", ossl_config_s_load, -1);
    rb_define_alias(CLASS_OF(cConfig), "new", "load");

    rb_define_method(cConfig, "value", ossl_config_get_value, -1);
    rb_define_method(cConfig, "section", ossl_config_get_section, 1);
    rb_define_alias(cConfig, "[]", "section");
}