rkerberos 0.2.3 → 0.3.1

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.
@@ -4,13 +4,22 @@ 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);
21
+ else if (p->rb_context != Qnil)
22
+ rkrb5_context_release(p->rb_context);
14
23
  free(p);
15
24
  }
16
25
 
@@ -20,7 +29,7 @@ static size_t rkrb5_princ_typed_size(const void *ptr) {
20
29
 
21
30
  static const rb_data_type_t rkrb5_princ_data_type = {
22
31
  "RUBY_KRB5_PRINC",
23
- {NULL, rkrb5_princ_typed_free, rkrb5_princ_typed_size,},
32
+ {rkrb5_princ_typed_mark, rkrb5_princ_typed_free, rkrb5_princ_typed_size,},
24
33
  NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
25
34
  };
26
35
 
@@ -28,34 +37,68 @@ static const rb_data_type_t rkrb5_princ_data_type = {
28
37
  static VALUE rkrb5_princ_allocate(VALUE klass){
29
38
  RUBY_KRB5_PRINC* ptr = ALLOC(RUBY_KRB5_PRINC);
30
39
  memset(ptr, 0, sizeof(RUBY_KRB5_PRINC));
40
+ ptr->rb_context = Qnil;
31
41
  return TypedData_Wrap_Struct(klass, &rkrb5_princ_data_type, ptr);
32
42
  }
33
43
 
34
44
  /*
35
45
  * call-seq:
36
- * Kerberos::Krb5::Principal.new(name)
46
+ * Kerberos::Krb5::Principal.new(name: nil, context: nil)
37
47
  *
38
48
  * Creates and returns a new Krb5::Principal object. If a block is provided
39
49
  * then it yields itself.
40
50
  *
51
+ * A principal +name+ may be provided as a keyword argument. If not provided
52
+ * or nil, the principal attribute will be nil.
53
+ *
54
+ * An optional +context+ keyword argument may be provided. If given, it must
55
+ * be a Kerberos::Krb5::Context object and will be used instead of creating
56
+ * a new context via krb5_init_context.
57
+ *
41
58
  * Example:
42
59
  *
43
- * principal1 = Kerberos::Krb5::Principal.new('Jon')
60
+ * principal1 = Kerberos::Krb5::Principal.new(name: 'Jon')
44
61
  *
45
- * principal2 = Kerberos::Krb5::Principal.new('Jon') do |pr|
62
+ * principal2 = Kerberos::Krb5::Principal.new(name: 'Jon') do |pr|
46
63
  * pr.expire_time = Time.now + 20000
47
64
  * end
65
+ *
66
+ * ctx = Kerberos::Krb5::Context.new
67
+ * principal3 = Kerberos::Krb5::Principal.new(name: 'Jon', context: ctx)
48
68
  */
49
- static VALUE rkrb5_princ_initialize(VALUE self, VALUE v_name){
69
+ static VALUE rkrb5_princ_initialize(int argc, VALUE* argv, VALUE self){
50
70
  RUBY_KRB5_PRINC* ptr;
51
71
  krb5_error_code kerror;
72
+ VALUE v_opts = Qnil;
73
+ VALUE v_name = Qnil;
74
+ VALUE v_context = Qnil;
75
+ ID kw_table[2] = { rb_intern("name"), rb_intern("context") };
76
+ VALUE kw_vals[2];
52
77
 
53
78
  TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
54
79
 
55
- kerror = krb5_init_context(&ptr->ctx);
80
+ rb_scan_args(argc, argv, "0:", &v_opts);
81
+
82
+ if(NIL_P(v_opts))
83
+ v_opts = rb_hash_new();
56
84
 
57
- if(kerror)
58
- rb_raise(cKrb5Exception, "krb5_init_context failed: %s", error_message(kerror));
85
+ rb_get_kwargs(v_opts, kw_table, 0, 2, kw_vals);
86
+ v_name = kw_vals[0] == Qundef ? Qnil : kw_vals[0];
87
+ v_context = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
88
+
89
+ // Initialize or borrow the context
90
+ if(!NIL_P(v_context)){
91
+ ptr->ctx = rkrb5_context_borrow(v_context);
92
+ ptr->rb_context = v_context;
93
+ }
94
+ else{
95
+ kerror = krb5_init_context(&ptr->ctx);
96
+
97
+ if(kerror)
98
+ rb_raise(cKrb5Exception, "krb5_init_context failed: %s", error_message(kerror));
99
+
100
+ ptr->rb_context = Qnil;
101
+ }
59
102
 
60
103
  if(NIL_P(v_name)){
61
104
  rb_iv_set(self, "@principal", Qnil);
@@ -94,6 +137,36 @@ static VALUE rkrb5_princ_initialize(VALUE self, VALUE v_name){
94
137
  return self;
95
138
  }
96
139
 
140
+ /*
141
+ * call-seq:
142
+ * principal.close
143
+ *
144
+ * Releases the principal and its Kerberos context lease. Once closed, the
145
+ * principal cannot be reused.
146
+ */
147
+ static VALUE rkrb5_princ_close(VALUE self){
148
+ RUBY_KRB5_PRINC* ptr;
149
+
150
+ TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
151
+
152
+ if(!ptr->ctx)
153
+ return self;
154
+
155
+ if(ptr->principal)
156
+ krb5_free_principal(ptr->ctx, ptr->principal);
157
+
158
+ if(ptr->rb_context == Qnil)
159
+ krb5_free_context(ptr->ctx);
160
+ else
161
+ rkrb5_context_release(ptr->rb_context);
162
+
163
+ ptr->ctx = NULL;
164
+ ptr->principal = NULL;
165
+ ptr->rb_context = Qnil;
166
+
167
+ return self;
168
+ }
169
+
97
170
  /*
98
171
  * call-seq:
99
172
  * principal.realm
@@ -102,13 +175,16 @@ static VALUE rkrb5_princ_initialize(VALUE self, VALUE v_name){
102
175
  */
103
176
  static VALUE rkrb5_princ_get_realm(VALUE self){
104
177
  RUBY_KRB5_PRINC* ptr;
178
+ krb5_data* realm;
105
179
 
106
180
  TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
107
181
 
108
182
  if(!ptr->principal)
109
183
  rb_raise(cKrb5Exception, "no principal has been established");
110
184
 
111
- return rb_str_new2(krb5_princ_realm(ptr->ctx, ptr->principal)->data);
185
+ realm = krb5_princ_realm(ptr->ctx, ptr->principal);
186
+
187
+ return rb_str_new(realm->data, realm->length);
112
188
  }
113
189
 
114
190
  /*
@@ -144,6 +220,10 @@ static VALUE rkrb5_princ_equal(VALUE self, VALUE v_other){
144
220
  VALUE v_bool = Qfalse;
145
221
 
146
222
  TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr1);
223
+
224
+ if(!rb_obj_is_kind_of(v_other, cKrb5Principal))
225
+ return Qfalse;
226
+
147
227
  TypedData_Get_Struct(v_other, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr2);
148
228
 
149
229
  if(!ptr1->principal || !ptr2->principal)
@@ -233,6 +313,51 @@ static VALUE rkrb5_princ_inspect(VALUE self){
233
313
  return v_str;
234
314
  }
235
315
 
316
+ /*
317
+ * call-seq:
318
+ * principal.principal_type -> Integer
319
+ *
320
+ * Returns the type of the principal as an integer, e.g.
321
+ * KRB5_NT_PRINCIPAL (1), KRB5_NT_SRV_HST (2), etc.
322
+ */
323
+ static VALUE rkrb5_princ_get_type(VALUE self){
324
+ RUBY_KRB5_PRINC* ptr;
325
+
326
+ TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
327
+
328
+ if(!ptr->principal)
329
+ rb_raise(cKrb5Exception, "no principal has been established");
330
+
331
+ return INT2FIX(krb5_princ_type(ptr->ctx, ptr->principal));
332
+ }
333
+
334
+ /*
335
+ * call-seq:
336
+ * principal.components -> Array
337
+ *
338
+ * Returns an array of the component strings that make up this principal
339
+ * name (excluding the realm). For example, "admin/instance@REALM" would
340
+ * return ["admin", "instance"].
341
+ */
342
+ static VALUE rkrb5_princ_components(VALUE self){
343
+ RUBY_KRB5_PRINC* ptr;
344
+
345
+ TypedData_Get_Struct(self, RUBY_KRB5_PRINC, &rkrb5_princ_data_type, ptr);
346
+
347
+ if(!ptr->principal)
348
+ rb_raise(cKrb5Exception, "no principal has been established");
349
+
350
+ int n = krb5_princ_size(ptr->ctx, ptr->principal);
351
+ VALUE v_array = rb_ary_new_capa(n);
352
+
353
+ for(int i = 0; i < n; i++){
354
+ krb5_data* component = krb5_princ_component(ptr->ctx, ptr->principal, i);
355
+ rb_ary_push(v_array, rb_str_new(component->data, component->length));
356
+ }
357
+
358
+ return v_array;
359
+ }
360
+
236
361
  void Init_principal(void){
237
362
  /* The Kerberos::Krb5::Principal class encapsulates a Kerberos principal. */
238
363
  cKrb5Principal = rb_define_class_under(cKrb5, "Principal", rb_cObject);
@@ -243,7 +368,7 @@ void Init_principal(void){
243
368
 
244
369
  // Constructor
245
370
 
246
- rb_define_method(cKrb5Principal, "initialize", rkrb5_princ_initialize, 1);
371
+ rb_define_method(cKrb5Principal, "initialize", rkrb5_princ_initialize, -1);
247
372
 
248
373
  // Instance Methods
249
374
 
@@ -251,6 +376,9 @@ void Init_principal(void){
251
376
  rb_define_method(cKrb5Principal, "realm", rkrb5_princ_get_realm, 0);
252
377
  rb_define_method(cKrb5Principal, "realm=", rkrb5_princ_set_realm, 1);
253
378
  rb_define_method(cKrb5Principal, "==", rkrb5_princ_equal, 1);
379
+ rb_define_method(cKrb5Principal, "principal_type", rkrb5_princ_get_type, 0);
380
+ rb_define_method(cKrb5Principal, "components", rkrb5_princ_components, 0);
381
+ rb_define_method(cKrb5Principal, "close", rkrb5_princ_close, 0);
254
382
 
255
383
  // Attributes
256
384