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.
@@ -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
- {NULL, rkrb5_princ_typed_free, rkrb5_princ_typed_size,},
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 self, VALUE v_name){
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
- kerror = krb5_init_context(&ptr->ctx);
54
- if(kerror)
55
- rb_raise(cKrb5Exception, "krb5_init_context failed: %s", error_message(kerror));
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