rkerberos 0.2.0 → 0.2.2

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.
@@ -7,7 +7,7 @@ VALUE cKrb5Keytab, cKrb5KeytabException;
7
7
  void rkrb5_keytab_typed_free(void *ptr) {
8
8
  if (!ptr) return;
9
9
  RUBY_KRB5_KEYTAB *kt = (RUBY_KRB5_KEYTAB *)ptr;
10
- if (kt->keytab)
10
+ if (kt->keytab && kt->ctx)
11
11
  krb5_kt_close(kt->ctx, kt->keytab);
12
12
  if (kt->ctx)
13
13
  krb5_free_cred_contents(kt->ctx, &kt->creds);
@@ -35,6 +35,56 @@ VALUE rkrb5_keytab_allocate(VALUE klass){
35
35
 
36
36
  // Allocation function for the Kerberos::Krb5::Keytab class.
37
37
 
38
+ // Struct for rb_ensure in each()
39
+ typedef struct {
40
+ krb5_context ctx;
41
+ krb5_keytab keytab;
42
+ krb5_kt_cursor cursor;
43
+ int cursor_active;
44
+ } keytab_each_arg;
45
+
46
+ static VALUE rkrb5_keytab_each_body(VALUE arg){
47
+ keytab_each_arg* ea = (keytab_each_arg*)arg;
48
+ krb5_keytab_entry entry;
49
+ krb5_error_code kerror;
50
+ char* principal;
51
+ VALUE v_kt_entry;
52
+
53
+ while((kerror = krb5_kt_next_entry(ea->ctx, ea->keytab, &entry, &ea->cursor)) == 0){
54
+ krb5_unparse_name(ea->ctx, entry.principal, &principal);
55
+
56
+ v_kt_entry = rb_class_new_instance(0, NULL, cKrb5KtEntry);
57
+
58
+ rb_iv_set(v_kt_entry, "@principal", rb_str_new2(principal));
59
+ rb_iv_set(v_kt_entry, "@timestamp", rb_time_new(entry.timestamp, 0));
60
+ rb_iv_set(v_kt_entry, "@vno", INT2FIX(entry.vno));
61
+ rb_iv_set(v_kt_entry, "@key", INT2FIX(entry.key.enctype));
62
+
63
+ krb5_free_unparsed_name(ea->ctx, principal);
64
+ krb5_kt_free_entry(ea->ctx, &entry);
65
+
66
+ rb_yield(v_kt_entry);
67
+ }
68
+
69
+ ea->cursor_active = 0;
70
+
71
+ kerror = krb5_kt_end_seq_get(ea->ctx, ea->keytab, &ea->cursor);
72
+
73
+ if(kerror)
74
+ rb_raise(cKrb5Exception, "krb5_kt_end_seq_get: %s", error_message(kerror));
75
+
76
+ return Qnil;
77
+ }
78
+
79
+ static VALUE rkrb5_keytab_each_ensure(VALUE arg){
80
+ keytab_each_arg* ea = (keytab_each_arg*)arg;
81
+
82
+ if(ea->cursor_active)
83
+ krb5_kt_end_seq_get(ea->ctx, ea->keytab, &ea->cursor);
84
+
85
+ return Qnil;
86
+ }
87
+
38
88
  /*
39
89
  * call-seq:
40
90
  *
@@ -46,48 +96,22 @@ VALUE rkrb5_keytab_allocate(VALUE klass){
46
96
  */
47
97
  static VALUE rkrb5_keytab_each(VALUE self){
48
98
  RUBY_KRB5_KEYTAB* ptr;
49
- VALUE v_kt_entry;
50
99
  krb5_error_code kerror;
51
- krb5_kt_cursor cursor;
52
- krb5_keytab_entry entry;
53
- char* principal;
100
+ keytab_each_arg ea;
54
101
 
55
102
  TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
56
103
 
57
- kerror = krb5_kt_start_seq_get(
58
- ptr->ctx,
59
- ptr->keytab,
60
- &cursor
61
- );
104
+ ea.ctx = ptr->ctx;
105
+ ea.keytab = ptr->keytab;
106
+
107
+ kerror = krb5_kt_start_seq_get(ea.ctx, ea.keytab, &ea.cursor);
62
108
 
63
109
  if(kerror)
64
110
  rb_raise(cKrb5Exception, "krb5_kt_start_seq_get: %s", error_message(kerror));
65
111
 
66
- while((kerror = krb5_kt_next_entry(ptr->ctx, ptr->keytab, &entry, &cursor)) == 0){
67
- krb5_unparse_name(ptr->ctx, entry.principal, &principal);
68
-
69
- v_kt_entry = rb_class_new_instance(0, NULL, cKrb5KtEntry);
70
-
71
- rb_iv_set(v_kt_entry, "@principal", rb_str_new2(principal));
72
- rb_iv_set(v_kt_entry, "@timestamp", rb_time_new(entry.timestamp, 0));
73
- rb_iv_set(v_kt_entry, "@vno", INT2FIX(entry.vno));
74
- rb_iv_set(v_kt_entry, "@key", INT2FIX(entry.key.enctype));
75
-
76
- rb_yield(v_kt_entry);
77
-
78
- free(principal);
79
-
80
- krb5_kt_free_entry(ptr->ctx, &entry);
81
- }
82
-
83
- kerror = krb5_kt_end_seq_get(
84
- ptr->ctx,
85
- ptr->keytab,
86
- &cursor
87
- );
112
+ ea.cursor_active = 1;
88
113
 
89
- if(kerror)
90
- rb_raise(cKrb5Exception, "krb5_kt_end_seq_get: %s", error_message(kerror));
114
+ rb_ensure(rkrb5_keytab_each_body, (VALUE)&ea, rkrb5_keytab_each_ensure, (VALUE)&ea);
91
115
 
92
116
  return self;
93
117
  }
@@ -130,6 +154,11 @@ static VALUE rkrb5_keytab_close(VALUE self){
130
154
 
131
155
  TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
132
156
 
157
+ if(ptr->keytab && ptr->ctx){
158
+ krb5_kt_close(ptr->ctx, ptr->keytab);
159
+ ptr->keytab = NULL;
160
+ }
161
+
133
162
  if(ptr->ctx)
134
163
  krb5_free_cred_contents(ptr->ctx, &ptr->creds);
135
164
 
@@ -241,8 +270,8 @@ static VALUE rkrb5_keytab_add_entry(int argc, VALUE* argv, VALUE self){
241
270
  * call-seq:
242
271
  * keytab.get_entry(principal, vno = 0, encoding_type = nil)
243
272
  *
244
- * Searches the keytab by +principal+, +vno+ and +encoding_type+. If the
245
- * +vno+ is zero (the default), then the first entry that matches +principal+
273
+ * Searches the keytab by +principal+, +vno+ (version number) and +encoding_type+.
274
+ * If the +vno+ is zero (the default), then the first entry that matches +principal+
246
275
  * is returned.
247
276
  *
248
277
  * Returns a Kerberos::Krb5::KeytabEntry object if the entry is found.
@@ -269,10 +298,17 @@ static VALUE rkrb5_keytab_get_entry(int argc, VALUE* argv, VALUE self){
269
298
  kerror = krb5_parse_name(ptr->ctx, name, &principal);
270
299
 
271
300
  if(kerror)
272
- rb_raise(cKrb5Exception, "krb5_unparse_name: %s", error_message(kerror));
301
+ rb_raise(cKrb5Exception, "krb5_parse_name: %s", error_message(kerror));
302
+
303
+ if(NIL_P(v_vno))
304
+ vno = 0;
305
+ else
306
+ vno = NUM2INT(v_vno);
273
307
 
274
- vno = 0;
275
- enctype = 0;
308
+ if(NIL_P(v_enctype))
309
+ enctype = 0;
310
+ else
311
+ enctype = NUM2INT(v_enctype);
276
312
 
277
313
  kerror = krb5_kt_get_entry(
278
314
  ptr->ctx,
@@ -283,6 +319,8 @@ static VALUE rkrb5_keytab_get_entry(int argc, VALUE* argv, VALUE self){
283
319
  &entry
284
320
  );
285
321
 
322
+ krb5_free_principal(ptr->ctx, principal);
323
+
286
324
  if(kerror)
287
325
  rb_raise(cKrb5Exception, "krb5_kt_get_entry: %s", error_message(kerror));
288
326
 
@@ -298,6 +336,93 @@ static VALUE rkrb5_keytab_get_entry(int argc, VALUE* argv, VALUE self){
298
336
  return v_entry;
299
337
  }
300
338
 
339
+ /*
340
+ * call-seq:
341
+ * keytab.keytab_name
342
+ *
343
+ * Return the name associated with the open keytab. This returns the canonical
344
+ * type:residual string used internally by the library. It will usually be the
345
+ * same as the +name+ method, but could be different.
346
+ */
347
+ static VALUE rkrb5_keytab_get_name(VALUE self){
348
+ RUBY_KRB5_KEYTAB* ptr;
349
+ krb5_error_code kerror;
350
+ char name[MAX_KEYTAB_NAME_LEN];
351
+
352
+ TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
353
+
354
+ if(!ptr->ctx)
355
+ rb_raise(cKrb5Exception, "no context has been established");
356
+
357
+ kerror = krb5_kt_get_name(ptr->ctx, ptr->keytab, name, MAX_KEYTAB_NAME_LEN);
358
+
359
+ if(kerror)
360
+ rb_raise(cKrb5Exception, "krb5_kt_get_name: %s", error_message(kerror));
361
+
362
+ return rb_str_new2(name);
363
+ }
364
+
365
+ /*
366
+ * call-seq:
367
+ * keytab.keytab_type
368
+ *
369
+ * Return the keytab type portion, e.g. "FILE". Raises an error if nil.
370
+ */
371
+ static VALUE rkrb5_keytab_get_type(VALUE self){
372
+ RUBY_KRB5_KEYTAB* ptr;
373
+ const char *type;
374
+
375
+ TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
376
+
377
+ if(!ptr->ctx)
378
+ rb_raise(cKrb5Exception, "no context has been established");
379
+
380
+ type = krb5_kt_get_type(ptr->ctx, ptr->keytab);
381
+
382
+ if(!type)
383
+ rb_raise(cKrb5Exception, "krb5_kt_get_type returned NULL");
384
+
385
+ return rb_str_new2(type);
386
+ }
387
+
388
+ /*
389
+ * call-seq:
390
+ * keytab.dup -> new_keytab
391
+ *
392
+ * Duplicate the keytab object so that both handles may be closed
393
+ * independently. Underlying data is shared by the krb5 library; the
394
+ * new Ruby object receives a fresh context.
395
+ */
396
+ static VALUE rkrb5_keytab_dup(VALUE self){
397
+ RUBY_KRB5_KEYTAB *ptr, *newptr;
398
+ krb5_error_code kerror;
399
+ VALUE newobj;
400
+
401
+ TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
402
+
403
+ if(!ptr->ctx)
404
+ rb_raise(cKrb5Exception, "no context has been established");
405
+
406
+ newobj = rkrb5_keytab_allocate(CLASS_OF(self));
407
+ TypedData_Get_Struct(newobj, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, newptr);
408
+
409
+ kerror = krb5_init_context(&newptr->ctx);
410
+ if(kerror){
411
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
412
+ }
413
+
414
+ kerror = krb5_kt_dup(newptr->ctx, ptr->keytab, &newptr->keytab);
415
+ if(kerror){
416
+ krb5_free_context(newptr->ctx);
417
+ newptr->ctx = NULL;
418
+ rb_raise(cKrb5Exception, "krb5_kt_dup: %s", error_message(kerror));
419
+ }
420
+
421
+ rb_iv_set(newobj, "@name", rb_iv_get(self, "@name"));
422
+
423
+ return newobj;
424
+ }
425
+
301
426
  /*
302
427
  * call-seq:
303
428
  * Kerberos::Krb5::Keytab.new(name = nil)
@@ -362,6 +487,62 @@ static VALUE rkrb5_keytab_initialize(int argc, VALUE* argv, VALUE self){
362
487
 
363
488
  // Singleton Methods
364
489
 
490
+ // Struct for rb_ensure in foreach()
491
+ typedef struct {
492
+ krb5_context ctx;
493
+ krb5_keytab keytab;
494
+ krb5_kt_cursor cursor;
495
+ int cursor_active;
496
+ } keytab_foreach_arg;
497
+
498
+ static VALUE rkrb5_s_keytab_foreach_body(VALUE arg){
499
+ keytab_foreach_arg* fa = (keytab_foreach_arg*)arg;
500
+ krb5_keytab_entry entry;
501
+ krb5_error_code kerror;
502
+ char* principal;
503
+ VALUE v_kt_entry;
504
+
505
+ while((kerror = krb5_kt_next_entry(fa->ctx, fa->keytab, &entry, &fa->cursor)) == 0){
506
+ krb5_unparse_name(fa->ctx, entry.principal, &principal);
507
+
508
+ v_kt_entry = rb_class_new_instance(0, NULL, cKrb5KtEntry);
509
+
510
+ rb_iv_set(v_kt_entry, "@principal", rb_str_new2(principal));
511
+ rb_iv_set(v_kt_entry, "@timestamp", rb_time_new(entry.timestamp, 0));
512
+ rb_iv_set(v_kt_entry, "@vno", INT2FIX(entry.vno));
513
+ rb_iv_set(v_kt_entry, "@key", INT2FIX(entry.key.enctype));
514
+
515
+ krb5_free_unparsed_name(fa->ctx, principal);
516
+ krb5_kt_free_entry(fa->ctx, &entry);
517
+
518
+ rb_yield(v_kt_entry);
519
+ }
520
+
521
+ fa->cursor_active = 0;
522
+
523
+ kerror = krb5_kt_end_seq_get(fa->ctx, fa->keytab, &fa->cursor);
524
+
525
+ if(kerror)
526
+ rb_raise(cKrb5Exception, "krb5_kt_end_seq_get: %s", error_message(kerror));
527
+
528
+ return Qnil;
529
+ }
530
+
531
+ static VALUE rkrb5_s_keytab_foreach_ensure(VALUE arg){
532
+ keytab_foreach_arg* fa = (keytab_foreach_arg*)arg;
533
+
534
+ if(fa->cursor_active)
535
+ krb5_kt_end_seq_get(fa->ctx, fa->keytab, &fa->cursor);
536
+
537
+ if(fa->keytab)
538
+ krb5_kt_close(fa->ctx, fa->keytab);
539
+
540
+ if(fa->ctx)
541
+ krb5_free_context(fa->ctx);
542
+
543
+ return Qnil;
544
+ }
545
+
365
546
  /*
366
547
  * call-seq:
367
548
  * Kerberos::Krb5::Keytab.foreach(keytab = nil){ |entry|
@@ -374,31 +555,26 @@ static VALUE rkrb5_keytab_initialize(int argc, VALUE* argv, VALUE self){
374
555
  * If no +keytab+ is provided, then the default keytab is used.
375
556
  */
376
557
  static VALUE rkrb5_s_keytab_foreach(int argc, VALUE* argv, VALUE klass){
377
- VALUE v_kt_entry;
378
558
  VALUE v_keytab_name;
379
559
  krb5_error_code kerror;
380
- krb5_kt_cursor cursor;
381
- krb5_keytab keytab;
382
- krb5_keytab_entry entry;
383
- krb5_context context;
384
- char* principal;
560
+ keytab_foreach_arg fa;
385
561
  char keytab_name[MAX_KEYTAB_NAME_LEN];
386
562
 
563
+ memset(&fa, 0, sizeof(fa));
564
+
387
565
  rb_scan_args(argc, argv, "01", &v_keytab_name);
388
566
 
389
- kerror = krb5_init_context(&context);
567
+ kerror = krb5_init_context(&fa.ctx);
390
568
 
391
569
  if(kerror)
392
570
  rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
393
571
 
394
572
  // Use the default keytab name if one isn't provided.
395
573
  if(NIL_P(v_keytab_name)){
396
- kerror = krb5_kt_default_name(context, keytab_name, MAX_KEYTAB_NAME_LEN);
574
+ kerror = krb5_kt_default_name(fa.ctx, keytab_name, MAX_KEYTAB_NAME_LEN);
397
575
 
398
576
  if(kerror){
399
- if(context)
400
- krb5_free_context(context);
401
-
577
+ krb5_free_context(fa.ctx);
402
578
  rb_raise(cKrb5Exception, "krb5_kt_default_name: %s", error_message(kerror));
403
579
  }
404
580
  }
@@ -408,73 +584,24 @@ static VALUE rkrb5_s_keytab_foreach(int argc, VALUE* argv, VALUE klass){
408
584
  keytab_name[MAX_KEYTAB_NAME_LEN - 1] = '\0';
409
585
  }
410
586
 
411
- kerror = krb5_kt_resolve(
412
- context,
413
- keytab_name,
414
- &keytab
415
- );
587
+ kerror = krb5_kt_resolve(fa.ctx, keytab_name, &fa.keytab);
416
588
 
417
589
  if(kerror){
418
- if(context)
419
- krb5_free_context(context);
420
-
590
+ krb5_free_context(fa.ctx);
421
591
  rb_raise(cKrb5Exception, "krb5_kt_resolve: %s", error_message(kerror));
422
592
  }
423
593
 
424
- kerror = krb5_kt_start_seq_get(
425
- context,
426
- keytab,
427
- &cursor
428
- );
594
+ kerror = krb5_kt_start_seq_get(fa.ctx, fa.keytab, &fa.cursor);
429
595
 
430
596
  if(kerror){
431
- if(context)
432
- krb5_free_context(context);
433
-
434
- if(keytab)
435
- krb5_kt_close(context, keytab);
436
-
597
+ krb5_kt_close(fa.ctx, fa.keytab);
598
+ krb5_free_context(fa.ctx);
437
599
  rb_raise(cKrb5Exception, "krb5_kt_start_seq_get: %s", error_message(kerror));
438
600
  }
439
601
 
440
- while((kerror = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
441
- krb5_unparse_name(context, entry.principal, &principal);
442
-
443
- v_kt_entry = rb_class_new_instance(0, NULL, cKrb5KtEntry);
444
-
445
- rb_iv_set(v_kt_entry, "@principal", rb_str_new2(principal));
446
- rb_iv_set(v_kt_entry, "@timestamp", rb_time_new(entry.timestamp, 0));
447
- rb_iv_set(v_kt_entry, "@vno", INT2FIX(entry.vno));
448
- rb_iv_set(v_kt_entry, "@key", INT2FIX(entry.key.enctype));
449
-
450
- rb_yield(v_kt_entry);
451
-
452
- free(principal);
453
-
454
- krb5_kt_free_entry(context, &entry);
455
- }
456
-
457
- kerror = krb5_kt_end_seq_get(
458
- context,
459
- keytab,
460
- &cursor
461
- );
462
-
463
- if(kerror){
464
- if(context)
465
- krb5_free_context(context);
466
-
467
- if(keytab)
468
- krb5_kt_close(context, keytab);
469
-
470
- rb_raise(cKrb5Exception, "krb5_kt_end_seq_get: %s", error_message(kerror));
471
- }
472
-
473
- if(keytab)
474
- krb5_kt_close(context, keytab);
602
+ fa.cursor_active = 1;
475
603
 
476
- if(context)
477
- krb5_free_context(context);
604
+ rb_ensure(rkrb5_s_keytab_foreach_body, (VALUE)&fa, rkrb5_s_keytab_foreach_ensure, (VALUE)&fa);
478
605
 
479
606
  return Qnil;
480
607
  }
@@ -504,6 +631,10 @@ void Init_keytab(void){
504
631
  rb_define_method(cKrb5Keytab, "close", rkrb5_keytab_close, 0);
505
632
  rb_define_method(cKrb5Keytab, "each", rkrb5_keytab_each, 0);
506
633
  rb_define_method(cKrb5Keytab, "get_entry", rkrb5_keytab_get_entry, -1);
634
+ rb_define_method(cKrb5Keytab, "keytab_name", rkrb5_keytab_get_name, 0);
635
+ rb_define_method(cKrb5Keytab, "keytab_type", rkrb5_keytab_get_type, 0);
636
+ rb_define_method(cKrb5Keytab, "dup", rkrb5_keytab_dup, 0);
637
+ rb_define_alias(cKrb5Keytab, "clone", "dup");
507
638
 
508
639
  // TODO: Move these into Kadm5 and/or figure out how to set the vno properly.
509
640
  // rb_define_method(cKrb5Keytab, "add_entry", rkrb5_keytab_add_entry, -1);
@@ -59,7 +59,7 @@ static VALUE rkadm5_policy_init(VALUE self, VALUE v_options){
59
59
 
60
60
  Check_Type(v_options, T_HASH);
61
61
 
62
- if(RTEST(rb_funcall(v_options, rb_intern("empty?"), 0, 0)))
62
+ if(RTEST(rb_funcall(v_options, rb_intern("empty?"), 0)))
63
63
  rb_raise(rb_eArgError, "no policy options provided");
64
64
 
65
65
  v_name = rb_hash_aref2(v_options, rb_str_new_cstr("name"));