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.
@@ -25,6 +25,13 @@ VALUE rb_hash_aref2(VALUE v_hash, VALUE v_key){
25
25
 
26
26
 
27
27
  // TypedData functions for RUBY_KRB5
28
+ static void rkrb5_typed_mark(void *ptr) {
29
+ if (!ptr) return;
30
+ RUBY_KRB5 *r = (RUBY_KRB5 *)ptr;
31
+ if (r->rb_context != Qnil)
32
+ rb_gc_mark(r->rb_context);
33
+ }
34
+
28
35
  static void rkrb5_typed_free(void *ptr) {
29
36
  if (!ptr) return;
30
37
  RUBY_KRB5 *r = (RUBY_KRB5 *)ptr;
@@ -34,7 +41,7 @@ static void rkrb5_typed_free(void *ptr) {
34
41
  krb5_free_cred_contents(r->ctx, &r->creds);
35
42
  if (r->princ)
36
43
  krb5_free_principal(r->ctx, r->princ);
37
- if (r->ctx)
44
+ if (r->ctx && r->rb_context == Qnil)
38
45
  krb5_free_context(r->ctx);
39
46
  free(r);
40
47
  }
@@ -43,9 +50,9 @@ static size_t rkrb5_typed_size(const void *ptr) {
43
50
  return sizeof(RUBY_KRB5);
44
51
  }
45
52
 
46
- static const rb_data_type_t rkrb5_data_type = {
53
+ const rb_data_type_t rkrb5_data_type = {
47
54
  "RUBY_KRB5",
48
- {NULL, rkrb5_typed_free, rkrb5_typed_size,},
55
+ {rkrb5_typed_mark, rkrb5_typed_free, rkrb5_typed_size,},
49
56
  NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
50
57
  };
51
58
 
@@ -53,26 +60,63 @@ static const rb_data_type_t rkrb5_data_type = {
53
60
  static VALUE rkrb5_allocate(VALUE klass){
54
61
  RUBY_KRB5* ptr = ALLOC(RUBY_KRB5);
55
62
  memset(ptr, 0, sizeof(RUBY_KRB5));
63
+ ptr->rb_context = Qnil;
56
64
  return TypedData_Wrap_Struct(klass, &rkrb5_data_type, ptr);
57
65
  }
58
66
 
59
67
  /*
60
68
  * call-seq:
61
- * Kerberos::Krb5.new
69
+ * Kerberos::Krb5.new(context: nil)
62
70
  *
63
71
  * Creates and returns a new Kerberos::Krb5 object. This initializes the
64
72
  * context for future method calls on that object.
73
+ *
74
+ * If a +context+ keyword argument is provided, it must be a
75
+ * Kerberos::Krb5::Context object. The context will be borrowed rather than
76
+ * creating a new one internally via krb5_init_context. The caller is
77
+ * responsible for keeping the Context object alive for the lifetime of
78
+ * this Krb5 instance.
79
+ *
80
+ * A block form is also supported. If a block is given, the object is
81
+ * yielded to the block and automatically closed when the block returns.
65
82
  */
66
- static VALUE rkrb5_initialize(VALUE self){
83
+ static VALUE rkrb5_initialize(int argc, VALUE* argv, VALUE self){
67
84
  RUBY_KRB5* ptr;
85
+ VALUE v_opts, v_context;
86
+ ID kw_table[1] = { rb_intern("context") };
87
+ VALUE kw_vals[1];
68
88
  krb5_error_code kerror;
69
89
 
70
90
  TypedData_Get_Struct(self, RUBY_KRB5, &rkrb5_data_type, ptr);
71
91
 
72
- kerror = krb5_init_context(&ptr->ctx);
92
+ rb_scan_args(argc, argv, "0:", &v_opts);
73
93
 
74
- if(kerror)
75
- rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
94
+ if(NIL_P(v_opts))
95
+ v_opts = rb_hash_new();
96
+
97
+ rb_get_kwargs(v_opts, kw_table, 0, 1, kw_vals);
98
+ v_context = kw_vals[0] == Qundef ? Qnil : kw_vals[0];
99
+
100
+ if(!NIL_P(v_context)){
101
+ RUBY_KRB5_CONTEXT* ctx_ptr;
102
+
103
+ if(!rb_obj_is_kind_of(v_context, cKrb5Context))
104
+ rb_raise(rb_eTypeError, "context must be a Kerberos::Krb5::Context object");
105
+
106
+ TypedData_Get_Struct(v_context, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ctx_ptr);
107
+
108
+ if(!ctx_ptr->ctx)
109
+ rb_raise(cKrb5Exception, "context is closed");
110
+
111
+ ptr->ctx = ctx_ptr->ctx;
112
+ ptr->rb_context = v_context;
113
+ }
114
+ else{
115
+ kerror = krb5_init_context(&ptr->ctx);
116
+
117
+ if(kerror)
118
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
119
+ }
76
120
 
77
121
  if(rb_block_given_p()){
78
122
  rb_ensure(rb_yield, self, rkrb5_close, self);
@@ -140,7 +184,7 @@ static VALUE rkrb5_set_default_realm(int argc, VALUE* argv, VALUE self){
140
184
  }
141
185
 
142
186
  /* call-seq:
143
- * krb5.get_init_creds_keytab(principal = nil, keytab = nil, service = nil, ccache = nil)
187
+ * krb5.get_init_creds_keytab(principal: nil, keytab: nil, service: nil, ccache: nil)
144
188
  *
145
189
  * Acquire credentials for +principal+ from +keytab+ using +service+. If
146
190
  * no principal is specified, then a principal is derived from the service
@@ -154,7 +198,10 @@ static VALUE rkrb5_set_default_realm(int argc, VALUE* argv, VALUE self){
154
198
  */
155
199
  static VALUE rkrb5_get_init_creds_keytab(int argc, VALUE* argv, VALUE self){
156
200
  RUBY_KRB5* ptr;
157
- VALUE v_user, v_keytab_name, v_service, v_ccache;
201
+ VALUE v_user = Qnil, v_keytab_name = Qnil, v_service = Qnil, v_ccache = Qnil;
202
+ VALUE v_kwargs = Qnil;
203
+ ID kw_table[4] = { rb_intern("principal"), rb_intern("keytab"), rb_intern("service"), rb_intern("ccache") };
204
+ VALUE kw_vals[4];
158
205
  char* user;
159
206
  char* service;
160
207
  char keytab_name[MAX_KEYTAB_NAME_LEN];
@@ -181,18 +228,36 @@ static VALUE rkrb5_get_init_creds_keytab(int argc, VALUE* argv, VALUE self){
181
228
  krb5_free_cred_contents(ptr->ctx, &ptr->creds);
182
229
  memset(&ptr->creds, 0, sizeof(ptr->creds));
183
230
 
231
+ rb_scan_args(argc, argv, "0:", &v_kwargs);
232
+
233
+ if(NIL_P(v_kwargs))
234
+ v_kwargs = rb_hash_new();
235
+
236
+ rb_get_kwargs(v_kwargs, kw_table, 0, 4, kw_vals);
237
+ if(kw_vals[0] != Qundef) v_user = kw_vals[0];
238
+ if(kw_vals[1] != Qundef) v_keytab_name = kw_vals[1];
239
+ if(kw_vals[2] != Qundef) v_service = kw_vals[2];
240
+ if(kw_vals[3] != Qundef) v_ccache = kw_vals[3];
241
+
242
+ // Validate argument types before allocating opt, so type errors don't leak it.
243
+ if(!NIL_P(v_user))
244
+ Check_Type(v_user, T_STRING);
245
+
246
+ if(!NIL_P(v_keytab_name))
247
+ Check_Type(v_keytab_name, T_STRING);
248
+
249
+ if(!NIL_P(v_service))
250
+ Check_Type(v_service, T_STRING);
251
+
184
252
  kerror = krb5_get_init_creds_opt_alloc(ptr->ctx, &opt);
185
253
  if(kerror)
186
254
  rb_raise(cKrb5Exception, "krb5_get_init_creds_opt_alloc: %s", error_message(kerror));
187
255
 
188
- rb_scan_args(argc, argv, "04", &v_user, &v_keytab_name, &v_service, &v_ccache);
189
-
190
256
  // We need the service information for later.
191
257
  if(NIL_P(v_service)){
192
258
  service = NULL;
193
259
  }
194
260
  else{
195
- Check_Type(v_service, T_STRING);
196
261
  service = StringValueCStr(v_service);
197
262
  }
198
263
 
@@ -212,7 +277,6 @@ static VALUE rkrb5_get_init_creds_keytab(int argc, VALUE* argv, VALUE self){
212
277
  }
213
278
  }
214
279
  else{
215
- Check_Type(v_user, T_STRING);
216
280
  user = StringValueCStr(v_user);
217
281
 
218
282
  kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
@@ -233,7 +297,6 @@ static VALUE rkrb5_get_init_creds_keytab(int argc, VALUE* argv, VALUE self){
233
297
  }
234
298
  }
235
299
  else{
236
- Check_Type(v_keytab_name, T_STRING);
237
300
  strncpy(keytab_name, StringValueCStr(v_keytab_name), MAX_KEYTAB_NAME_LEN - 1);
238
301
  keytab_name[MAX_KEYTAB_NAME_LEN - 1] = '\0';
239
302
  }
@@ -293,7 +356,7 @@ static VALUE rkrb5_get_init_creds_keytab(int argc, VALUE* argv, VALUE self){
293
356
  *
294
357
  * Example:
295
358
  *
296
- * krb5.get_init_creds_password('foo', 'XXXXXX') # Authenticate 'foo' user
359
+ * krb5.get_init_creds_password(principal: 'foo', password: 'XXXXXX') # Authenticate 'foo' user
297
360
  * krb5.change_password('XXXXXX', 'YYYYYY') # Change password for 'foo'
298
361
  */
299
362
  static VALUE rkrb5_change_password(VALUE self, VALUE v_old, VALUE v_new){
@@ -371,19 +434,26 @@ static VALUE rkrb5_change_password(VALUE self, VALUE v_old, VALUE v_new){
371
434
 
372
435
  /*
373
436
  * call-seq:
374
- * krb5.get_init_creds_password(user, password, service = nil)
437
+ * krb5.get_init_creds_password(principal: nil, password: nil, service: nil, ccache: nil)
375
438
  *
376
- * Authenticates the credentials of +user+ using +password+ against +service+,
439
+ * Authenticates the credentials of +principal+ using +password+ against +service+,
377
440
  * and has the effect of setting the principal and context internally. This method
378
441
  * must typically be called before using other methods.
442
+ *
443
+ * When +ccache+ is given, the acquired credentials will be written into the
444
+ * provided Kerberos::Krb5::CredentialsCache.
379
445
  */
380
446
  static VALUE rkrb5_get_init_creds_passwd(int argc, VALUE* argv, VALUE self){
381
447
  RUBY_KRB5* ptr;
382
- VALUE v_user, v_pass, v_service;
448
+ VALUE v_user = Qnil, v_pass = Qnil, v_service = Qnil, v_ccache = Qnil;
449
+ VALUE v_kwargs = Qnil;
450
+ ID kw_table[4] = { rb_intern("principal"), rb_intern("password"), rb_intern("service"), rb_intern("ccache") };
451
+ VALUE kw_vals[4];
383
452
  char* user;
384
453
  char* pass;
385
454
  char* service;
386
455
  krb5_error_code kerror;
456
+ krb5_get_init_creds_opt* opt = NULL;
387
457
 
388
458
  TypedData_Get_Struct(self, RUBY_KRB5, &rkrb5_data_type, ptr);
389
459
 
@@ -399,7 +469,19 @@ static VALUE rkrb5_get_init_creds_passwd(int argc, VALUE* argv, VALUE self){
399
469
  krb5_free_cred_contents(ptr->ctx, &ptr->creds);
400
470
  memset(&ptr->creds, 0, sizeof(ptr->creds));
401
471
 
402
- rb_scan_args(argc, argv, "21", &v_user, &v_pass, &v_service);
472
+ rb_scan_args(argc, argv, "0:", &v_kwargs);
473
+
474
+ if(NIL_P(v_kwargs))
475
+ v_kwargs = rb_hash_new();
476
+
477
+ rb_get_kwargs(v_kwargs, kw_table, 0, 4, kw_vals);
478
+ if(kw_vals[0] != Qundef) v_user = kw_vals[0];
479
+ if(kw_vals[1] != Qundef) v_pass = kw_vals[1];
480
+ if(kw_vals[2] != Qundef) v_service = kw_vals[2];
481
+ if(kw_vals[3] != Qundef) v_ccache = kw_vals[3];
482
+
483
+ if(NIL_P(v_user) || NIL_P(v_pass))
484
+ rb_raise(rb_eArgError, "principal and password are required");
403
485
 
404
486
  Check_Type(v_user, T_STRING);
405
487
  Check_Type(v_pass, T_STRING);
@@ -419,6 +501,21 @@ static VALUE rkrb5_get_init_creds_passwd(int argc, VALUE* argv, VALUE self){
419
501
  if(kerror)
420
502
  rb_raise(cKrb5Exception, "krb5_parse_name: %s", error_message(kerror));
421
503
 
504
+ if(!NIL_P(v_ccache)){
505
+ RUBY_KRB5_CCACHE* ccptr;
506
+ TypedData_Get_Struct(v_ccache, RUBY_KRB5_CCACHE, &rkrb5_ccache_data_type, ccptr);
507
+
508
+ kerror = krb5_get_init_creds_opt_alloc(ptr->ctx, &opt);
509
+ if(kerror)
510
+ rb_raise(cKrb5Exception, "krb5_get_init_creds_opt_alloc: %s", error_message(kerror));
511
+
512
+ kerror = krb5_get_init_creds_opt_set_out_ccache(ptr->ctx, opt, ccptr->ccache);
513
+ if(kerror){
514
+ krb5_get_init_creds_opt_free(ptr->ctx, opt);
515
+ rb_raise(cKrb5Exception, "krb5_get_init_creds_opt_set_out_ccache: %s", error_message(kerror));
516
+ }
517
+ }
518
+
422
519
  kerror = krb5_get_init_creds_password(
423
520
  ptr->ctx,
424
521
  &ptr->creds,
@@ -428,9 +525,12 @@ static VALUE rkrb5_get_init_creds_passwd(int argc, VALUE* argv, VALUE self){
428
525
  NULL,
429
526
  0,
430
527
  service,
431
- NULL
528
+ opt
432
529
  );
433
530
 
531
+ if(opt)
532
+ krb5_get_init_creds_opt_free(ptr->ctx, opt);
533
+
434
534
  if(kerror)
435
535
  rb_raise(cKrb5Exception, "krb5_get_init_creds_password: %s", error_message(kerror));
436
536
 
@@ -439,7 +539,7 @@ static VALUE rkrb5_get_init_creds_passwd(int argc, VALUE* argv, VALUE self){
439
539
 
440
540
  /*
441
541
  * call-seq:
442
- * krb5.authenticate!(user, password, service = nil)
542
+ * krb5.authenticate!(principal:, password:, service: nil)
443
543
  *
444
544
  * Convenience method that: acquires initial credentials via password and
445
545
  * immediately verifies those credentials using `verify_init_creds` with
@@ -451,7 +551,9 @@ static VALUE rkrb5_get_init_creds_passwd(int argc, VALUE* argv, VALUE self){
451
551
  */
452
552
  static VALUE rkrb5_authenticate_bang(int argc, VALUE* argv, VALUE self){
453
553
  RUBY_KRB5* ptr;
454
- VALUE v_user, v_pass, v_service;
554
+ VALUE v_kwargs, v_user, v_pass, v_service;
555
+ ID kw_table[3] = { rb_intern("principal"), rb_intern("password"), rb_intern("service") };
556
+ VALUE kw_vals[3];
455
557
  char* user;
456
558
  char* pass;
457
559
  char* service;
@@ -472,8 +574,15 @@ static VALUE rkrb5_authenticate_bang(int argc, VALUE* argv, VALUE self){
472
574
  krb5_free_cred_contents(ptr->ctx, &ptr->creds);
473
575
  memset(&ptr->creds, 0, sizeof(ptr->creds));
474
576
 
475
- // Require user and password, optional service
476
- rb_scan_args(argc, argv, "21", &v_user, &v_pass, &v_service);
577
+ rb_scan_args(argc, argv, "0:", &v_kwargs);
578
+
579
+ if(NIL_P(v_kwargs))
580
+ v_kwargs = rb_hash_new();
581
+
582
+ rb_get_kwargs(v_kwargs, kw_table, 2, 1, kw_vals);
583
+ v_user = kw_vals[0];
584
+ v_pass = kw_vals[1];
585
+ v_service = kw_vals[2] == Qundef ? Qnil : kw_vals[2];
477
586
 
478
587
  Check_Type(v_user, T_STRING);
479
588
  Check_Type(v_pass, T_STRING);
@@ -573,11 +682,12 @@ static VALUE rkrb5_close(VALUE self){
573
682
  if(ptr->princ)
574
683
  krb5_free_principal(ptr->ctx, ptr->princ);
575
684
 
576
- if(ptr->ctx)
685
+ if(ptr->ctx && ptr->rb_context == Qnil)
577
686
  krb5_free_context(ptr->ctx);
578
687
 
579
688
  ptr->ctx = NULL;
580
689
  ptr->princ = NULL;
690
+ ptr->rb_context = Qnil;
581
691
 
582
692
  return Qtrue;
583
693
  }
@@ -678,8 +788,10 @@ static VALUE rkrb5_get_permitted_enctypes(VALUE self){
678
788
  v_enctypes = rb_hash_new();
679
789
 
680
790
  for(i = 0; ktypes[i]; i++){
681
- if(krb5_enctype_to_string(ktypes[i], encoding, 128)){
682
- rb_raise(cKrb5Exception, "krb5_enctype_to_string: %s", error_message(kerror));
791
+ krb5_error_code enc_err = krb5_enctype_to_string(ktypes[i], encoding, 128);
792
+ if(enc_err){
793
+ krb5_free_enctypes(ptr->ctx, ktypes);
794
+ rb_raise(cKrb5Exception, "krb5_enctype_to_string: %s", error_message(enc_err));
683
795
  }
684
796
  rb_hash_aset(v_enctypes, INT2FIX(ktypes[i]), rb_str_new2(encoding));
685
797
  }
@@ -692,7 +804,7 @@ static VALUE rkrb5_get_permitted_enctypes(VALUE self){
692
804
 
693
805
  /*
694
806
  * call-seq:
695
- * krb5.verify_init_creds(server = nil, keytab = nil, ccache = nil)
807
+ * krb5.verify_init_creds(server: nil, keytab: nil, ccache: nil)
696
808
  *
697
809
  * Verifies the initial credentials currently stored in the internal
698
810
  * credentials structure. Optionally a server principal string, a
@@ -702,7 +814,10 @@ static VALUE rkrb5_get_permitted_enctypes(VALUE self){
702
814
  */
703
815
  static VALUE rkrb5_verify_init_creds(int argc, VALUE* argv, VALUE self){
704
816
  RUBY_KRB5* ptr;
705
- VALUE v_server, v_keytab, v_ccache;
817
+ VALUE v_server = Qnil, v_keytab = Qnil, v_ccache = Qnil;
818
+ VALUE v_kwargs = Qnil;
819
+ ID kw_table[3] = { rb_intern("server"), rb_intern("keytab"), rb_intern("ccache") };
820
+ VALUE kw_vals[3];
706
821
  krb5_error_code kerror;
707
822
  krb5_principal server_princ = NULL;
708
823
  RUBY_KRB5_KEYTAB* ktptr = NULL;
@@ -710,7 +825,15 @@ static VALUE rkrb5_verify_init_creds(int argc, VALUE* argv, VALUE self){
710
825
  krb5_keytab keytab = NULL;
711
826
  krb5_ccache *ccache_ptr = NULL;
712
827
 
713
- rb_scan_args(argc, argv, "03", &v_server, &v_keytab, &v_ccache);
828
+ rb_scan_args(argc, argv, "0:", &v_kwargs);
829
+
830
+ if(NIL_P(v_kwargs))
831
+ v_kwargs = rb_hash_new();
832
+
833
+ rb_get_kwargs(v_kwargs, kw_table, 0, 3, kw_vals);
834
+ if(kw_vals[0] != Qundef) v_server = kw_vals[0];
835
+ if(kw_vals[1] != Qundef) v_keytab = kw_vals[1];
836
+ if(kw_vals[2] != Qundef) v_ccache = kw_vals[2];
714
837
 
715
838
  TypedData_Get_Struct(self, RUBY_KRB5, &rkrb5_data_type, ptr);
716
839
 
@@ -772,6 +895,83 @@ static VALUE rkrb5_verify_init_creds(int argc, VALUE* argv, VALUE self){
772
895
  return Qtrue;
773
896
  }
774
897
 
898
+ /*
899
+ * call-seq:
900
+ * krb5.get_host_realm(hostname) -> Array
901
+ *
902
+ * Returns an array of realm names associated with +hostname+.
903
+ * Uses the Kerberos library's host-to-realm mapping (krb5.conf
904
+ * [domain_realm] section, DNS lookups, etc.).
905
+ */
906
+ static VALUE rkrb5_get_host_realm(VALUE self, VALUE v_host){
907
+ RUBY_KRB5* ptr;
908
+ char** realms;
909
+ char** p;
910
+ krb5_error_code kerror;
911
+
912
+ TypedData_Get_Struct(self, RUBY_KRB5, &rkrb5_data_type, ptr);
913
+
914
+ if(!ptr->ctx)
915
+ rb_raise(cKrb5Exception, "no context has been established");
916
+
917
+ Check_Type(v_host, T_STRING);
918
+
919
+ kerror = krb5_get_host_realm(ptr->ctx, StringValueCStr(v_host), &realms);
920
+
921
+ if(kerror)
922
+ rb_raise(cKrb5Exception, "krb5_get_host_realm: %s", error_message(kerror));
923
+
924
+ VALUE v_array = rb_ary_new();
925
+
926
+ for(p = realms; p && *p; p++)
927
+ rb_ary_push(v_array, rb_str_new2(*p));
928
+
929
+ krb5_free_host_realm(ptr->ctx, realms);
930
+
931
+ return v_array;
932
+ }
933
+
934
+ /*
935
+ * call-seq:
936
+ * krb5.expand_hostname(hostname) -> String
937
+ *
938
+ * Canonicalizes +hostname+ by performing a forward DNS lookup followed
939
+ * by a reverse lookup, returning the canonical hostname.
940
+ */
941
+ static VALUE rkrb5_expand_hostname(VALUE self, VALUE v_host){
942
+ RUBY_KRB5* ptr;
943
+ char* canonical;
944
+ krb5_error_code kerror;
945
+
946
+ TypedData_Get_Struct(self, RUBY_KRB5, &rkrb5_data_type, ptr);
947
+
948
+ if(!ptr->ctx)
949
+ rb_raise(cKrb5Exception, "no context has been established");
950
+
951
+ Check_Type(v_host, T_STRING);
952
+
953
+ kerror = krb5_expand_hostname(ptr->ctx, StringValueCStr(v_host), &canonical);
954
+
955
+ if(kerror)
956
+ rb_raise(cKrb5Exception, "krb5_expand_hostname: %s", error_message(kerror));
957
+
958
+ VALUE v_result = rb_str_new2(canonical);
959
+ krb5_free_string(ptr->ctx, canonical);
960
+
961
+ return v_result;
962
+ }
963
+
964
+ /*
965
+ * call-seq:
966
+ * Kerberos::Krb5.thread_safe?
967
+ *
968
+ * Returns true if the Kerberos library was built with multithread support,
969
+ * false otherwise.
970
+ */
971
+ static VALUE rkrb5_s_thread_safe(VALUE klass){
972
+ return krb5_is_thread_safe() ? Qtrue : Qfalse;
973
+ }
974
+
775
975
  void Init_rkerberos(void){
776
976
  mKerberos = rb_define_module("Kerberos");
777
977
  cKrb5 = rb_define_class_under(mKerberos, "Krb5", rb_cObject);
@@ -781,7 +981,10 @@ void Init_rkerberos(void){
781
981
  rb_define_alloc_func(cKrb5, rkrb5_allocate);
782
982
 
783
983
  // Initializers
784
- rb_define_method(cKrb5, "initialize", rkrb5_initialize, 0);
984
+ rb_define_method(cKrb5, "initialize", rkrb5_initialize, -1);
985
+
986
+ // Singleton Methods
987
+ rb_define_singleton_method(cKrb5, "thread_safe?", rkrb5_s_thread_safe, 0);
785
988
 
786
989
  // Krb5 Methods
787
990
  rb_define_method(cKrb5, "authenticate!", rkrb5_authenticate_bang, -1);
@@ -794,13 +997,20 @@ void Init_rkerberos(void){
794
997
  rb_define_method(cKrb5, "get_permitted_enctypes", rkrb5_get_permitted_enctypes, 0);
795
998
  rb_define_method(cKrb5, "set_default_realm", rkrb5_set_default_realm, -1);
796
999
  rb_define_method(cKrb5, "verify_init_creds", rkrb5_verify_init_creds, -1);
1000
+ rb_define_method(cKrb5, "get_host_realm", rkrb5_get_host_realm, 1);
1001
+ rb_define_method(cKrb5, "expand_hostname", rkrb5_expand_hostname, 1);
797
1002
 
798
1003
  // Aliases
799
1004
  rb_define_alias(cKrb5, "default_realm", "get_default_realm");
1005
+ rb_define_alias(cKrb5, "default_realm=", "set_default_realm");
800
1006
  rb_define_alias(cKrb5, "default_principal", "get_default_principal");
1007
+ rb_define_alias(cKrb5, "host_realm", "get_host_realm");
1008
+ rb_define_alias(cKrb5, "init_creds_password", "get_init_creds_password");
1009
+ rb_define_alias(cKrb5, "init_creds_keytab", "get_init_creds_keytab");
1010
+ rb_define_alias(cKrb5, "permitted_enctypes", "get_permitted_enctypes");
801
1011
 
802
- /* 0.2.1: The version of the custom rkerberos library */
803
- rb_define_const(cKrb5, "VERSION", rb_str_new2("0.2.2"));
1012
+ /* 0.3.0: The version of the custom rkerberos library */
1013
+ rb_define_const(cKrb5, "VERSION", rb_str_new2("0.3.0"));
804
1014
 
805
1015
  // Encoding type constants
806
1016
 
@@ -8,6 +8,8 @@
8
8
 
9
9
  // Make the context data type visible to other C files
10
10
  extern const rb_data_type_t rkrb5_context_data_type;
11
+ // Make the Krb5 data type visible to other C files
12
+ extern const rb_data_type_t rkrb5_data_type;
11
13
  // Make the config data type visible to other C files
12
14
  extern const rb_data_type_t rkadm5_config_data_type;
13
15
 
@@ -67,6 +69,7 @@ typedef struct {
67
69
  krb5_creds creds;
68
70
  krb5_principal princ;
69
71
  krb5_keytab keytab;
72
+ VALUE rb_context;
70
73
  } RUBY_KRB5;
71
74
 
72
75
  // Kerberos::Context
@@ -81,6 +84,7 @@ typedef struct {
81
84
  krb5_principal princ;
82
85
  void* handle;
83
86
  char** db_args;
87
+ VALUE rb_context; // Ruby Context object when borrowed, Qnil if ctx is owned
84
88
  } RUBY_KADM5;
85
89
 
86
90
  // Kerberos::Krb5::Keytab::Entry
@@ -96,23 +100,27 @@ typedef struct {
96
100
  krb5_context ctx;
97
101
  krb5_creds creds;
98
102
  krb5_keytab keytab;
103
+ VALUE rb_context; // Ruby Context object when borrowed, Qnil if ctx is owned
99
104
  } RUBY_KRB5_KEYTAB;
100
105
 
101
106
  typedef struct {
102
107
  krb5_context ctx;
103
108
  krb5_principal principal;
109
+ VALUE rb_context; // Ruby Context object when borrowed, Qnil if ctx is owned
104
110
  } RUBY_KRB5_PRINC;
105
111
 
106
112
  typedef struct {
107
113
  krb5_context ctx;
108
114
  krb5_ccache ccache;
109
115
  krb5_principal principal;
116
+ VALUE rb_context; // Ruby Context object when borrowed, Qnil if ctx is owned
110
117
  } RUBY_KRB5_CCACHE;
111
118
 
112
119
  #ifdef HAVE_KADM5_ADMIN_H
113
120
  typedef struct {
114
121
  krb5_context ctx;
115
122
  kadm5_config_params config;
123
+ VALUE rb_context; // Ruby Context object when borrowed, Qnil if ctx is owned
116
124
  } RUBY_KADM5_CONFIG;
117
125
 
118
126
  typedef struct {
data/rkerberos.gemspec CHANGED
@@ -2,15 +2,18 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'rkerberos'
5
- spec.version = '0.2.2'
5
+ spec.version = '0.3.0'
6
6
  spec.authors = ['Daniel Berger', 'Dominic Cleal', 'Simon Levermann']
7
7
  spec.license = 'Artistic-2.0'
8
8
  spec.email = ['djberg96@gmail.com', 'dominic@cleal.org', 'simon-rubygems@slevermann.de']
9
- spec.homepage = 'http://github.com/rkerberos/rkerberos'
10
- spec.summary = 'A Ruby interface for the the Kerberos library'
9
+ spec.homepage = 'https://github.com/rkerberos/rkerberos'
10
+ spec.summary = 'A Ruby interface for the Kerberos library'
11
+ spec.required_ruby_version = '>= 3.2'
11
12
  spec.test_files = Dir['spec/**/*_spec.rb']
12
13
  spec.extensions = ['ext/rkerberos/extconf.rb']
13
- spec.files = Dir['**/*'].grep_v(%r{\A(?:\.git|docker|Dockerfile)})
14
+ spec.files = Dir['**/*']
15
+ .select { |file| File.file?(file) }
16
+ .grep_v(%r{\A(?:\.git|docker|Dockerfile|Gemfile\.lock\z|tmp(?:/|\z))|\.gem\z})
14
17
 
15
18
  spec.add_development_dependency('rake-compiler')
16
19
  spec.add_development_dependency('rspec', '>= 3.0')
@@ -22,13 +25,13 @@ Gem::Specification.new do |spec|
22
25
  EOF
23
26
 
24
27
  spec.metadata = {
25
- 'homepage_uri' => 'https://github.com/rkerberos/rkerberos',
26
28
  'bug_tracker_uri' => 'https://github.com/rkerberos/rkerberos/issues',
27
- 'changelog_uri' => 'https://github.com/rkerberos/rkerberos/blob/main/CHANGES.md',
29
+ 'changelog_uri' => 'https://github.com/rkerberos/rkerberos/blob/master/CHANGES.md',
28
30
  'documentation_uri' => 'https://github.com/rkerberos/rkerberos/wiki',
31
+ 'homepage_uri' => 'https://github.com/rkerberos/rkerberos',
29
32
  'source_code_uri' => 'https://github.com/rkerberos/rkerberos',
30
33
  'wiki_uri' => 'https://github.com/rkerberos/rkerberos/wiki',
31
- 'github_repo' => 'https://github.com/djberg96/rkerberos',
34
+ 'github_repo' => 'https://github.com/rkerberos/rkerberos',
32
35
  'funding_uri' => 'https://github.com/sponsors/rkerberos',
33
36
  'rubygems_mfa_required' => 'true'
34
37
  }