rkerberos 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +22 -0
- data/EXAMPLES.md +1015 -0
- data/MANIFEST.md +17 -12
- data/README.md +5 -5
- data/ext/rkerberos/ccache.c +105 -26
- data/ext/rkerberos/config.c +59 -10
- data/ext/rkerberos/context.c +76 -7
- data/ext/rkerberos/extconf.rb +16 -3
- data/ext/rkerberos/kadm5.c +301 -96
- data/ext/rkerberos/keytab.c +222 -66
- data/ext/rkerberos/keytab_entry.c +2 -1
- data/ext/rkerberos/policy.c +25 -23
- data/ext/rkerberos/principal.c +136 -10
- data/ext/rkerberos/rkerberos.c +244 -34
- data/ext/rkerberos/rkerberos.h +8 -0
- data/rkerberos.gemspec +10 -7
- data/spec/config_spec.rb +58 -3
- data/spec/context_spec.rb +57 -7
- data/spec/credentials_cache_spec.rb +106 -39
- data/spec/kadm5_spec.rb +292 -17
- data/spec/krb5_keytab_spec.rb +229 -24
- data/spec/krb5_spec.rb +142 -29
- data/spec/policy_spec.rb +12 -7
- data/spec/principal_spec.rb +102 -4
- data/spec/spec_helper.rb +34 -0
- metadata +10 -8
data/ext/rkerberos/principal.c
CHANGED
|
@@ -4,12 +4,19 @@ VALUE cKrb5Principal;
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// TypedData functions for RUBY_KRB5_PRINC
|
|
7
|
+
static void rkrb5_princ_typed_mark(void *ptr) {
|
|
8
|
+
if (!ptr) return;
|
|
9
|
+
RUBY_KRB5_PRINC *p = (RUBY_KRB5_PRINC *)ptr;
|
|
10
|
+
if (p->rb_context != Qnil)
|
|
11
|
+
rb_gc_mark(p->rb_context);
|
|
12
|
+
}
|
|
13
|
+
|
|
7
14
|
static void rkrb5_princ_typed_free(void *ptr) {
|
|
8
15
|
if (!ptr) return;
|
|
9
16
|
RUBY_KRB5_PRINC *p = (RUBY_KRB5_PRINC *)ptr;
|
|
10
17
|
if (p->principal)
|
|
11
18
|
krb5_free_principal(p->ctx, p->principal);
|
|
12
|
-
if (p->ctx)
|
|
19
|
+
if (p->ctx && p->rb_context == Qnil)
|
|
13
20
|
krb5_free_context(p->ctx);
|
|
14
21
|
free(p);
|
|
15
22
|
}
|
|
@@ -20,7 +27,7 @@ static size_t rkrb5_princ_typed_size(const void *ptr) {
|
|
|
20
27
|
|
|
21
28
|
static const rb_data_type_t rkrb5_princ_data_type = {
|
|
22
29
|
"RUBY_KRB5_PRINC",
|
|
23
|
-
{
|
|
30
|
+
{rkrb5_princ_typed_mark, rkrb5_princ_typed_free, rkrb5_princ_typed_size,},
|
|
24
31
|
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
|
|
25
32
|
};
|
|
26
33
|
|
|
@@ -28,43 +35,95 @@ static const rb_data_type_t rkrb5_princ_data_type = {
|
|
|
28
35
|
static VALUE rkrb5_princ_allocate(VALUE klass){
|
|
29
36
|
RUBY_KRB5_PRINC* ptr = ALLOC(RUBY_KRB5_PRINC);
|
|
30
37
|
memset(ptr, 0, sizeof(RUBY_KRB5_PRINC));
|
|
38
|
+
ptr->rb_context = Qnil;
|
|
31
39
|
return TypedData_Wrap_Struct(klass, &rkrb5_princ_data_type, ptr);
|
|
32
40
|
}
|
|
33
41
|
|
|
34
42
|
/*
|
|
35
43
|
* call-seq:
|
|
36
|
-
* Kerberos::Krb5::Principal.new(name)
|
|
44
|
+
* Kerberos::Krb5::Principal.new(name: nil, context: nil)
|
|
37
45
|
*
|
|
38
46
|
* Creates and returns a new Krb5::Principal object. If a block is provided
|
|
39
47
|
* then it yields itself.
|
|
40
48
|
*
|
|
49
|
+
* A principal +name+ may be provided as a keyword argument. If not provided
|
|
50
|
+
* or nil, the principal attribute will be nil.
|
|
51
|
+
*
|
|
52
|
+
* An optional +context+ keyword argument may be provided. If given, it must
|
|
53
|
+
* be a Kerberos::Krb5::Context object and will be used instead of creating
|
|
54
|
+
* a new context via krb5_init_context.
|
|
55
|
+
*
|
|
41
56
|
* Example:
|
|
42
57
|
*
|
|
43
|
-
* principal1 = Kerberos::Krb5::Principal.new('Jon')
|
|
58
|
+
* principal1 = Kerberos::Krb5::Principal.new(name: 'Jon')
|
|
44
59
|
*
|
|
45
|
-
* principal2 = Kerberos::Krb5::Principal.new('Jon') do |pr|
|
|
60
|
+
* principal2 = Kerberos::Krb5::Principal.new(name: 'Jon') do |pr|
|
|
46
61
|
* pr.expire_time = Time.now + 20000
|
|
47
62
|
* end
|
|
63
|
+
*
|
|
64
|
+
* ctx = Kerberos::Krb5::Context.new
|
|
65
|
+
* principal3 = Kerberos::Krb5::Principal.new(name: 'Jon', context: ctx)
|
|
48
66
|
*/
|
|
49
|
-
static VALUE rkrb5_princ_initialize(VALUE
|
|
67
|
+
static VALUE rkrb5_princ_initialize(int argc, VALUE* argv, VALUE self){
|
|
50
68
|
RUBY_KRB5_PRINC* ptr;
|
|
51
69
|
krb5_error_code kerror;
|
|
70
|
+
VALUE v_opts = Qnil;
|
|
71
|
+
VALUE v_name = Qnil;
|
|
72
|
+
VALUE v_context = Qnil;
|
|
73
|
+
ID kw_table[2] = { rb_intern("name"), rb_intern("context") };
|
|
74
|
+
VALUE kw_vals[2];
|
|
75
|
+
|
|
52
76
|
TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
77
|
+
|
|
78
|
+
rb_scan_args(argc, argv, "0:", &v_opts);
|
|
79
|
+
|
|
80
|
+
if(NIL_P(v_opts))
|
|
81
|
+
v_opts = rb_hash_new();
|
|
82
|
+
|
|
83
|
+
rb_get_kwargs(v_opts, kw_table, 0, 2, kw_vals);
|
|
84
|
+
v_name = kw_vals[0] == Qundef ? Qnil : kw_vals[0];
|
|
85
|
+
v_context = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
|
|
86
|
+
|
|
87
|
+
// Initialize or borrow the context
|
|
88
|
+
if(!NIL_P(v_context)){
|
|
89
|
+
RUBY_KRB5_CONTEXT* ctx_ptr;
|
|
90
|
+
|
|
91
|
+
if(!rb_obj_is_kind_of(v_context, cKrb5Context))
|
|
92
|
+
rb_raise(rb_eTypeError, "context must be a Kerberos::Krb5::Context object");
|
|
93
|
+
|
|
94
|
+
TypedData_Get_Struct(v_context, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ctx_ptr);
|
|
95
|
+
|
|
96
|
+
if(!ctx_ptr->ctx)
|
|
97
|
+
rb_raise(cKrb5Exception, "context is closed");
|
|
98
|
+
|
|
99
|
+
ptr->ctx = ctx_ptr->ctx;
|
|
100
|
+
ptr->rb_context = v_context;
|
|
101
|
+
}
|
|
102
|
+
else{
|
|
103
|
+
kerror = krb5_init_context(&ptr->ctx);
|
|
104
|
+
|
|
105
|
+
if(kerror)
|
|
106
|
+
rb_raise(cKrb5Exception, "krb5_init_context failed: %s", error_message(kerror));
|
|
107
|
+
|
|
108
|
+
ptr->rb_context = Qnil;
|
|
109
|
+
}
|
|
110
|
+
|
|
56
111
|
if(NIL_P(v_name)){
|
|
57
112
|
rb_iv_set(self, "@principal", Qnil);
|
|
58
113
|
}
|
|
59
114
|
else{
|
|
60
115
|
char* name;
|
|
61
116
|
Check_Type(v_name, T_STRING);
|
|
117
|
+
|
|
62
118
|
name = StringValueCStr(v_name);
|
|
63
119
|
kerror = krb5_parse_name(ptr->ctx, name, &ptr->principal);
|
|
120
|
+
|
|
64
121
|
if(kerror)
|
|
65
122
|
rb_raise(cKrb5Exception, "krb5_parse_name failed: %s", error_message(kerror));
|
|
123
|
+
|
|
66
124
|
rb_iv_set(self, "@principal", v_name);
|
|
67
125
|
}
|
|
126
|
+
|
|
68
127
|
rb_iv_set(self, "@attributes", Qnil);
|
|
69
128
|
rb_iv_set(self, "@aux_attributes", Qnil);
|
|
70
129
|
rb_iv_set(self, "@expire_time", Qnil);
|
|
@@ -79,8 +138,10 @@ static VALUE rkrb5_princ_initialize(VALUE self, VALUE v_name){
|
|
|
79
138
|
rb_iv_set(self, "@password_expiration", Qnil);
|
|
80
139
|
rb_iv_set(self, "@policy", Qnil);
|
|
81
140
|
rb_iv_set(self, "@kvno", Qnil);
|
|
141
|
+
|
|
82
142
|
if(rb_block_given_p())
|
|
83
143
|
rb_yield(self);
|
|
144
|
+
|
|
84
145
|
return self;
|
|
85
146
|
}
|
|
86
147
|
|
|
@@ -92,7 +153,12 @@ static VALUE rkrb5_princ_initialize(VALUE self, VALUE v_name){
|
|
|
92
153
|
*/
|
|
93
154
|
static VALUE rkrb5_princ_get_realm(VALUE self){
|
|
94
155
|
RUBY_KRB5_PRINC* ptr;
|
|
156
|
+
|
|
95
157
|
TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
|
|
158
|
+
|
|
159
|
+
if(!ptr->principal)
|
|
160
|
+
rb_raise(cKrb5Exception, "no principal has been established");
|
|
161
|
+
|
|
96
162
|
return rb_str_new2(krb5_princ_realm(ptr->ctx, ptr->principal)->data);
|
|
97
163
|
}
|
|
98
164
|
|
|
@@ -104,9 +170,16 @@ static VALUE rkrb5_princ_get_realm(VALUE self){
|
|
|
104
170
|
*/
|
|
105
171
|
static VALUE rkrb5_princ_set_realm(VALUE self, VALUE v_realm){
|
|
106
172
|
RUBY_KRB5_PRINC* ptr;
|
|
173
|
+
|
|
107
174
|
TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
|
|
175
|
+
|
|
176
|
+
if(!ptr->principal)
|
|
177
|
+
rb_raise(cKrb5Exception, "no principal has been established");
|
|
178
|
+
|
|
108
179
|
Check_Type(v_realm, T_STRING);
|
|
180
|
+
|
|
109
181
|
krb5_set_principal_realm(ptr->ctx, ptr->principal, StringValueCStr(v_realm));
|
|
182
|
+
|
|
110
183
|
return v_realm;
|
|
111
184
|
}
|
|
112
185
|
|
|
@@ -120,10 +193,16 @@ static VALUE rkrb5_princ_equal(VALUE self, VALUE v_other){
|
|
|
120
193
|
RUBY_KRB5_PRINC* ptr1;
|
|
121
194
|
RUBY_KRB5_PRINC* ptr2;
|
|
122
195
|
VALUE v_bool = Qfalse;
|
|
196
|
+
|
|
123
197
|
TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr1);
|
|
124
198
|
TypedData_Get_Struct(v_other, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr2);
|
|
199
|
+
|
|
200
|
+
if(!ptr1->principal || !ptr2->principal)
|
|
201
|
+
return Qfalse;
|
|
202
|
+
|
|
125
203
|
if(krb5_principal_compare(ptr1->ctx, ptr1->principal, ptr2->principal))
|
|
126
204
|
v_bool = Qtrue;
|
|
205
|
+
|
|
127
206
|
return v_bool;
|
|
128
207
|
}
|
|
129
208
|
|
|
@@ -205,6 +284,51 @@ static VALUE rkrb5_princ_inspect(VALUE self){
|
|
|
205
284
|
return v_str;
|
|
206
285
|
}
|
|
207
286
|
|
|
287
|
+
/*
|
|
288
|
+
* call-seq:
|
|
289
|
+
* principal.principal_type -> Integer
|
|
290
|
+
*
|
|
291
|
+
* Returns the type of the principal as an integer, e.g.
|
|
292
|
+
* KRB5_NT_PRINCIPAL (1), KRB5_NT_SRV_HST (2), etc.
|
|
293
|
+
*/
|
|
294
|
+
static VALUE rkrb5_princ_get_type(VALUE self){
|
|
295
|
+
RUBY_KRB5_PRINC* ptr;
|
|
296
|
+
|
|
297
|
+
TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
|
|
298
|
+
|
|
299
|
+
if(!ptr->principal)
|
|
300
|
+
rb_raise(cKrb5Exception, "no principal has been established");
|
|
301
|
+
|
|
302
|
+
return INT2FIX(krb5_princ_type(ptr->ctx, ptr->principal));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/*
|
|
306
|
+
* call-seq:
|
|
307
|
+
* principal.components -> Array
|
|
308
|
+
*
|
|
309
|
+
* Returns an array of the component strings that make up this principal
|
|
310
|
+
* name (excluding the realm). For example, "admin/instance@REALM" would
|
|
311
|
+
* return ["admin", "instance"].
|
|
312
|
+
*/
|
|
313
|
+
static VALUE rkrb5_princ_components(VALUE self){
|
|
314
|
+
RUBY_KRB5_PRINC* ptr;
|
|
315
|
+
|
|
316
|
+
TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
|
|
317
|
+
|
|
318
|
+
if(!ptr->principal)
|
|
319
|
+
rb_raise(cKrb5Exception, "no principal has been established");
|
|
320
|
+
|
|
321
|
+
int n = krb5_princ_size(ptr->ctx, ptr->principal);
|
|
322
|
+
VALUE v_array = rb_ary_new_capa(n);
|
|
323
|
+
|
|
324
|
+
for(int i = 0; i < n; i++){
|
|
325
|
+
krb5_data* component = krb5_princ_component(ptr->ctx, ptr->principal, i);
|
|
326
|
+
rb_ary_push(v_array, rb_str_new(component->data, component->length));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return v_array;
|
|
330
|
+
}
|
|
331
|
+
|
|
208
332
|
void Init_principal(void){
|
|
209
333
|
/* The Kerberos::Krb5::Principal class encapsulates a Kerberos principal. */
|
|
210
334
|
cKrb5Principal = rb_define_class_under(cKrb5, "Principal", rb_cObject);
|
|
@@ -215,7 +339,7 @@ void Init_principal(void){
|
|
|
215
339
|
|
|
216
340
|
// Constructor
|
|
217
341
|
|
|
218
|
-
rb_define_method(cKrb5Principal, "initialize", rkrb5_princ_initialize, 1);
|
|
342
|
+
rb_define_method(cKrb5Principal, "initialize", rkrb5_princ_initialize, -1);
|
|
219
343
|
|
|
220
344
|
// Instance Methods
|
|
221
345
|
|
|
@@ -223,6 +347,8 @@ void Init_principal(void){
|
|
|
223
347
|
rb_define_method(cKrb5Principal, "realm", rkrb5_princ_get_realm, 0);
|
|
224
348
|
rb_define_method(cKrb5Principal, "realm=", rkrb5_princ_set_realm, 1);
|
|
225
349
|
rb_define_method(cKrb5Principal, "==", rkrb5_princ_equal, 1);
|
|
350
|
+
rb_define_method(cKrb5Principal, "principal_type", rkrb5_princ_get_type, 0);
|
|
351
|
+
rb_define_method(cKrb5Principal, "components", rkrb5_princ_components, 0);
|
|
226
352
|
|
|
227
353
|
// Attributes
|
|
228
354
|
|