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.
data/MANIFEST.md CHANGED
@@ -1,24 +1,29 @@
1
1
  * CHANGES.md
2
+ * EXAMPLES.md
3
+ * Gemfile
4
+ * LICENSE
2
5
  * rkerberos.gemspec
3
6
  * MANIFEST.md
4
7
  * Rakefile
5
- * README
6
- * ext/ccache.c
7
- * ext/context.c
8
- * ext/extconf.rb
9
- * ext/kadm5.c
10
- * ext/keytab.c
11
- * ext/keytab_entry.c
12
- * ext/rkerberos.c
13
- * ext/rkerberos.h
14
- * ext/policy.c
15
- * ext/principal.c
8
+ * README.md
9
+ * ext/rkerberos/ccache.c
10
+ * ext/rkerberos/config.c
11
+ * ext/rkerberos/context.c
12
+ * ext/rkerberos/extconf.rb
13
+ * ext/rkerberos/kadm5.c
14
+ * ext/rkerberos/keytab.c
15
+ * ext/rkerberos/keytab_entry.c
16
+ * ext/rkerberos/policy.c
17
+ * ext/rkerberos/principal.c
18
+ * ext/rkerberos/rkerberos.c
19
+ * ext/rkerberos/rkerberos.h
16
20
  * spec/config_spec.rb
17
21
  * spec/context_spec.rb
18
- * spec/credentials_spec.rb
22
+ * spec/credentials_cache_spec.rb
19
23
  * spec/kadm5_spec.rb
20
24
  * spec/keytab_entry_spec.rb
21
25
  * spec/krb5_keytab_spec.rb
22
26
  * spec/krb5_spec.rb
23
27
  * spec/policy_spec.rb
24
28
  * spec/principal_spec.rb
29
+ * spec/spec_helper.rb
data/README.md CHANGED
@@ -18,17 +18,17 @@ puts krb.get_permitted_enctypes.keys.join(',')
18
18
 
19
19
  # Credentials cache
20
20
  cc = Kerberos::Krb5::CredentialsCache.new
21
- krb.verify_init_creds(nil, nil, cc)
21
+ krb.verify_init_creds(ccache: cc)
22
22
  puts cc.primary_principal
23
23
 
24
24
  # Keytab
25
25
  kt_name = Kerberos::Krb5::Keytab.new.default_name # e.g. "FILE:/etc/krb5.keytab"
26
- krb.get_init_creds_keytab('host/server.example.com', kt_name)
27
- krb.get_init_creds_keytab('host/server.example.com', kt_name, nil, cc) # or write to cache
26
+ krb.get_init_creds_keytab(principal: 'host/server.example.com', keytab: kt_name)
27
+ krb.get_init_creds_keytab(principal: 'host/server.example.com', keytab: kt_name, ccache: cc) # or write to cache
28
28
 
29
29
  # Admin
30
30
  Kerberos::Kadm5.new(principal: ENV['KRB5_ADMIN_PRINCIPAL'], password: ENV['KRB5_ADMIN_PASSWORD']) do |kadmin|
31
- kadmin.create_principal('newuser@EXAMPLE.COM', 'initialpass')
31
+ kadmin.create_principal(name: 'newuser@EXAMPLE.COM', password: 'initialpass')
32
32
  kadmin.set_password('newuser@EXAMPLE.COM', 'betterpass')
33
33
  kadmin.delete_principal('newuser@EXAMPLE.COM')
34
34
  end
@@ -79,7 +79,7 @@ ctx.close
79
79
  # Testing
80
80
 
81
81
  ## Prerequisites
82
- - Ruby 3.4 or later
82
+ - Ruby 3.2 or later
83
83
  - Docker or Podman
84
84
  - docker-compose or podman-compose
85
85
 
@@ -4,6 +4,13 @@ VALUE cKrb5CCache;
4
4
 
5
5
 
6
6
  // TypedData functions for RUBY_KRB5_CCACHE
7
+ static void rkrb5_ccache_typed_mark(void *ptr) {
8
+ if (!ptr) return;
9
+ RUBY_KRB5_CCACHE *c = (RUBY_KRB5_CCACHE *)ptr;
10
+ if (c->rb_context != Qnil)
11
+ rb_gc_mark(c->rb_context);
12
+ }
13
+
7
14
  static void rkrb5_ccache_typed_free(void *ptr) {
8
15
  if (!ptr) return;
9
16
  RUBY_KRB5_CCACHE *c = (RUBY_KRB5_CCACHE *)ptr;
@@ -11,7 +18,7 @@ static void rkrb5_ccache_typed_free(void *ptr) {
11
18
  krb5_cc_close(c->ctx, c->ccache);
12
19
  if (c->principal)
13
20
  krb5_free_principal(c->ctx, c->principal);
14
- if (c->ctx)
21
+ if (c->ctx && c->rb_context == Qnil)
15
22
  krb5_free_context(c->ctx);
16
23
  free(c);
17
24
  }
@@ -22,7 +29,7 @@ static size_t rkrb5_ccache_typed_size(const void *ptr) {
22
29
 
23
30
  const rb_data_type_t rkrb5_ccache_data_type = {
24
31
  "RUBY_KRB5_CCACHE",
25
- {NULL, rkrb5_ccache_typed_free, rkrb5_ccache_typed_size,},
32
+ {rkrb5_ccache_typed_mark, rkrb5_ccache_typed_free, rkrb5_ccache_typed_size,},
26
33
  NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
27
34
  };
28
35
 
@@ -30,20 +37,28 @@ const rb_data_type_t rkrb5_ccache_data_type = {
30
37
  static VALUE rkrb5_ccache_allocate(VALUE klass){
31
38
  RUBY_KRB5_CCACHE* ptr = ALLOC(RUBY_KRB5_CCACHE);
32
39
  memset(ptr, 0, sizeof(RUBY_KRB5_CCACHE));
40
+ ptr->rb_context = Qnil;
33
41
  return TypedData_Wrap_Struct(klass, &rkrb5_ccache_data_type, ptr);
34
42
  }
35
43
 
36
44
  /*
37
45
  * call-seq:
38
- * Kerberos::CredentialsCache.new(principal = nil, cache_name = nil)
46
+ * Kerberos::CredentialsCache.new(principal: nil, cache_name: nil, context: nil)
47
+ *
48
+ * Creates and returns a new Kerberos::CredentialsCache object. Accepts the
49
+ * following keyword arguments:
50
+ *
51
+ * - +principal+: A string principal name. If specified, the credentials cache
52
+ * is created or refreshed with this as the primary principal. If a cache
53
+ * already exists, its contents are destroyed. May also be an object that
54
+ * responds to the `.principal` method.
39
55
  *
40
- * Creates and returns a new Kerberos::CredentialsCache object. If cache_name
41
- * is specified, then that cache is used, which must be in "type:residual"
42
- * format, where 'type' is a type known to Kerberos (typically 'FILE').
56
+ * - +cache_name+: The name of the credentials cache to use, which must be in
57
+ * "type:residual" format, where 'type' is a type known to Kerberos
58
+ * (typically 'FILE'). If omitted, the default cache is used.
43
59
  *
44
- * If a +principal+ is specified, then it creates or refreshes the credentials
45
- * cache with the primary principal set to +principal+. If the credentials
46
- * cache already exists, its contents are destroyed.
60
+ * - +context+: A Kerberos::Krb5::Context object. If provided, that context is
61
+ * used instead of creating a new one via krb5_init_context.
47
62
  *
48
63
  * Note that the principal's credentials are not set via the constructor.
49
64
  * It merely creates the cache and sets the default principal.
@@ -51,23 +66,55 @@ static VALUE rkrb5_ccache_allocate(VALUE klass){
51
66
  static VALUE rkrb5_ccache_initialize(int argc, VALUE* argv, VALUE self){
52
67
  RUBY_KRB5_CCACHE* ptr;
53
68
  krb5_error_code kerror;
54
- VALUE v_principal, v_name;
69
+ VALUE v_opts, v_principal, v_name, v_context;
70
+ ID kw_table[3] = { rb_intern("principal"), rb_intern("cache_name"), rb_intern("context") };
71
+ VALUE kw_vals[3];
55
72
 
56
73
  TypedData_Get_Struct(self, RUBY_KRB5_CCACHE, &rkrb5_ccache_data_type, ptr);
57
74
 
58
- rb_scan_args(argc, argv, "02", &v_principal, &v_name);
75
+ rb_scan_args(argc, argv, "0:", &v_opts);
76
+
77
+ if(NIL_P(v_opts))
78
+ v_opts = rb_hash_new();
79
+
80
+ rb_get_kwargs(v_opts, kw_table, 0, 3, kw_vals);
81
+ v_principal = kw_vals[0] == Qundef ? Qnil : kw_vals[0];
82
+ v_name = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
83
+ v_context = kw_vals[2] == Qundef ? Qnil : kw_vals[2];
84
+
85
+ if(!NIL_P(v_principal)){
86
+ if(rb_respond_to(v_principal, rb_intern("principal")))
87
+ v_principal = rb_funcall(v_principal, rb_intern("principal"), 0);
59
88
 
60
- if(RTEST(v_principal))
61
89
  Check_Type(v_principal, T_STRING);
90
+ }
62
91
 
63
- // Initialize the context
64
- kerror = krb5_init_context(&ptr->ctx);
92
+ // Initialize or borrow the context
93
+ if(!NIL_P(v_context)){
94
+ RUBY_KRB5_CONTEXT* ctx_ptr;
65
95
 
66
- if(kerror)
67
- rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
96
+ if(!rb_obj_is_kind_of(v_context, cKrb5Context))
97
+ rb_raise(rb_eTypeError, "context must be a Kerberos::Krb5::Context object");
98
+
99
+ TypedData_Get_Struct(v_context, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ctx_ptr);
100
+
101
+ if(!ctx_ptr->ctx)
102
+ rb_raise(cKrb5Exception, "context is closed");
103
+
104
+ ptr->ctx = ctx_ptr->ctx;
105
+ ptr->rb_context = v_context;
106
+ }
107
+ else{
108
+ kerror = krb5_init_context(&ptr->ctx);
109
+
110
+ if(kerror)
111
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
112
+
113
+ ptr->rb_context = Qnil;
114
+ }
68
115
 
69
116
  // Convert the principal name to a principal object
70
- if(RTEST(v_principal)){
117
+ if(!NIL_P(v_principal)){
71
118
  kerror = krb5_parse_name(
72
119
  ptr->ctx,
73
120
  StringValueCStr(v_principal),
@@ -127,12 +174,13 @@ static VALUE rkrb5_ccache_close(VALUE self){
127
174
  if(ptr->principal)
128
175
  krb5_free_principal(ptr->ctx, ptr->principal);
129
176
 
130
- if(ptr->ctx)
177
+ if(ptr->ctx && ptr->rb_context == Qnil)
131
178
  krb5_free_context(ptr->ctx);
132
179
 
133
180
  ptr->ccache = NULL;
134
181
  ptr->ctx = NULL;
135
182
  ptr->principal = NULL;
183
+ ptr->rb_context = Qnil;
136
184
 
137
185
  return self;
138
186
  }
@@ -228,11 +276,6 @@ static VALUE rkrb5_ccache_primary_principal(VALUE self){
228
276
  return v_name;
229
277
  }
230
278
 
231
- // Simple wrapper around krb5_cc_get_principal returning a principal name string.
232
- static VALUE rkrb5_ccache_principal(VALUE self){
233
- return rkrb5_ccache_primary_principal(self);
234
- }
235
-
236
279
  /*
237
280
  * call-seq:
238
281
  * ccache.destroy
@@ -264,9 +307,14 @@ static VALUE rkrb5_ccache_destroy(VALUE self){
264
307
  if(ptr->principal)
265
308
  krb5_free_principal(ptr->ctx, ptr->principal);
266
309
 
267
- if(ptr->ctx)
310
+ if(ptr->ctx && ptr->rb_context == Qnil)
268
311
  krb5_free_context(ptr->ctx);
269
312
 
313
+ ptr->ccache = NULL;
314
+ ptr->ctx = NULL;
315
+ ptr->principal = NULL;
316
+ ptr->rb_context = Qnil;
317
+
270
318
  rb_raise(cKrb5Exception, "krb5_cc_destroy: %s", error_message(kerror));
271
319
  }
272
320
  }
@@ -274,12 +322,13 @@ static VALUE rkrb5_ccache_destroy(VALUE self){
274
322
  if(ptr->principal)
275
323
  krb5_free_principal(ptr->ctx, ptr->principal);
276
324
 
277
- if(ptr->ctx)
325
+ if(ptr->ctx && ptr->rb_context == Qnil)
278
326
  krb5_free_context(ptr->ctx);
279
327
 
280
328
  ptr->ccache = NULL;
281
329
  ptr->ctx = NULL;
282
330
  ptr->principal = NULL;
331
+ ptr->rb_context = Qnil;
283
332
 
284
333
  return v_bool;
285
334
  }
@@ -325,6 +374,35 @@ static VALUE rkrb5_ccache_dup(VALUE self){
325
374
  return newobj;
326
375
  }
327
376
 
377
+ /*
378
+ * call-seq:
379
+ * ccache.full_name -> String
380
+ *
381
+ * Returns the full name of the credential cache, including the type prefix,
382
+ * e.g. "FILE:/tmp/krb5cc_1000".
383
+ */
384
+ static VALUE rkrb5_ccache_full_name(VALUE self){
385
+ RUBY_KRB5_CCACHE* ptr;
386
+ char *full_name;
387
+ krb5_error_code kerror;
388
+ VALUE result;
389
+
390
+ TypedData_Get_Struct(self, RUBY_KRB5_CCACHE, &rkrb5_ccache_data_type, ptr);
391
+
392
+ if(!ptr->ctx)
393
+ rb_raise(cKrb5Exception, "no context has been established");
394
+
395
+ kerror = krb5_cc_get_full_name(ptr->ctx, ptr->ccache, &full_name);
396
+
397
+ if(kerror)
398
+ rb_raise(cKrb5Exception, "krb5_cc_get_full_name: %s", error_message(kerror));
399
+
400
+ result = rb_str_new2(full_name);
401
+ krb5_free_string(ptr->ctx, full_name);
402
+
403
+ return result;
404
+ }
405
+
328
406
  void Init_ccache(void){
329
407
  /* The Kerberos::Krb5::CredentialsCache class encapsulates a Kerberos credentials cache. */
330
408
  cKrb5CCache = rb_define_class_under(cKrb5, "CredentialsCache", rb_cObject);
@@ -342,10 +420,11 @@ void Init_ccache(void){
342
420
  rb_define_method(cKrb5CCache, "cache_type", rkrb5_ccache_get_type, 0);
343
421
  rb_define_method(cKrb5CCache, "destroy", rkrb5_ccache_destroy, 0);
344
422
  rb_define_method(cKrb5CCache, "primary_principal", rkrb5_ccache_primary_principal, 0);
345
- rb_define_method(cKrb5CCache, "principal", rkrb5_ccache_principal, 0);
423
+ rb_define_method(cKrb5CCache, "full_name", rkrb5_ccache_full_name, 0);
346
424
  rb_define_method(cKrb5CCache, "dup", rkrb5_ccache_dup, 0);
347
425
  rb_define_alias(cKrb5CCache, "clone", "dup");
348
426
 
349
427
  // Aliases
350
428
  rb_define_alias(cKrb5CCache, "delete", "destroy");
429
+ rb_define_alias(cKrb5CCache, "principal", "primary_principal");
351
430
  }
@@ -1,3 +1,4 @@
1
+ #ifdef HAVE_KADM5_ADMIN_H
1
2
  #include <rkerberos.h>
2
3
 
3
4
  VALUE cKadm5Config;
@@ -5,12 +6,21 @@ VALUE cKeySalt;
5
6
 
6
7
 
7
8
  // TypedData functions for RUBY_KADM5_CONFIG
9
+ static void rkadm5_config_typed_mark(void *ptr) {
10
+ if (!ptr) return;
11
+ RUBY_KADM5_CONFIG *c = (RUBY_KADM5_CONFIG *)ptr;
12
+ if (c->rb_context != Qnil)
13
+ rb_gc_mark(c->rb_context);
14
+ }
15
+
8
16
  static void rkadm5_config_typed_free(void *ptr) {
9
17
  if (!ptr) return;
10
18
  RUBY_KADM5_CONFIG *c = (RUBY_KADM5_CONFIG *)ptr;
11
- kadm5_free_config_params(c->ctx, &c->config);
12
- if (c->ctx)
13
- krb5_free_context(c->ctx);
19
+ if (c->ctx) {
20
+ kadm5_free_config_params(c->ctx, &c->config);
21
+ if (c->rb_context == Qnil)
22
+ krb5_free_context(c->ctx);
23
+ }
14
24
  free(c);
15
25
  }
16
26
 
@@ -20,7 +30,7 @@ static size_t rkadm5_config_typed_size(const void *ptr) {
20
30
 
21
31
  const rb_data_type_t rkadm5_config_data_type = {
22
32
  "RUBY_KADM5_CONFIG",
23
- {NULL, rkadm5_config_typed_free, rkadm5_config_typed_size,},
33
+ {rkadm5_config_typed_mark, rkadm5_config_typed_free, rkadm5_config_typed_size,},
24
34
  NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
25
35
  };
26
36
 
@@ -28,6 +38,7 @@ const rb_data_type_t rkadm5_config_data_type = {
28
38
  static VALUE rkadm5_config_allocate(VALUE klass){
29
39
  RUBY_KADM5_CONFIG* ptr = ALLOC(RUBY_KADM5_CONFIG);
30
40
  memset(ptr, 0, sizeof(RUBY_KADM5_CONFIG));
41
+ ptr->rb_context = Qnil;
31
42
  return TypedData_Wrap_Struct(klass, &rkadm5_config_data_type, ptr);
32
43
  }
33
44
 
@@ -41,23 +52,60 @@ static VALUE rkeysalt_new(krb5_enctype enctype, krb5_int32 salttype){
41
52
  }
42
53
 
43
54
  /*
55
+ * call-seq:
56
+ * Kerberos::Kadm5::Config.new(context: nil)
57
+ *
44
58
  * Returns a Kerberos::Kadm5::Config object. This object contains Kerberos
45
59
  * admin configuration.
46
60
  *
61
+ * Accepts the following keyword argument:
62
+ *
63
+ * - +context+: A Kerberos::Krb5::Context object. If provided, that context is
64
+ * used instead of creating a new one via krb5_init_context.
65
+ *
47
66
  * Note that the returned object is frozen. Changes made to the Kerberos
48
67
  * admin configuration options after the call will not be reflected in this
49
68
  * object.
50
69
  */
51
- static VALUE rkadm5_config_initialize(VALUE self){
70
+ static VALUE rkadm5_config_initialize(int argc, VALUE* argv, VALUE self){
52
71
  RUBY_KADM5_CONFIG* ptr;
53
72
  krb5_error_code kerror;
73
+ VALUE v_opts, v_context;
74
+ ID kw_table[1] = { rb_intern("context") };
75
+ VALUE kw_vals[1];
54
76
 
55
77
  TypedData_Get_Struct(self, RUBY_KADM5_CONFIG, &rkadm5_config_data_type, ptr);
56
78
 
57
- kerror = krb5_init_context(&ptr->ctx);
79
+ rb_scan_args(argc, argv, "0:", &v_opts);
58
80
 
59
- if(kerror)
60
- rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
81
+ if(NIL_P(v_opts))
82
+ v_opts = rb_hash_new();
83
+
84
+ rb_get_kwargs(v_opts, kw_table, 0, 1, kw_vals);
85
+ v_context = kw_vals[0] == Qundef ? Qnil : kw_vals[0];
86
+
87
+ if(!NIL_P(v_context)){
88
+ RUBY_KRB5_CONTEXT* ctx_ptr;
89
+
90
+ if(!rb_obj_is_kind_of(v_context, cKrb5Context))
91
+ rb_raise(rb_eTypeError, "context must be a Kerberos::Krb5::Context object");
92
+
93
+ TypedData_Get_Struct(v_context, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ctx_ptr);
94
+
95
+ if(!ctx_ptr->ctx)
96
+ rb_raise(cKrb5Exception, "context is closed");
97
+
98
+ ptr->ctx = ctx_ptr->ctx;
99
+ ptr->rb_context = v_context;
100
+ }
101
+ else{
102
+ kerror = krb5_init_context(&ptr->ctx);
103
+
104
+ if(kerror)
105
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
106
+
107
+ ptr->rb_context = Qnil;
108
+ }
61
109
 
62
110
  kerror = kadm5_get_config_params(
63
111
  ptr->ctx,
@@ -298,7 +346,7 @@ void Init_config(void){
298
346
 
299
347
  // Initializer
300
348
 
301
- rb_define_method(cKadm5Config, "initialize", rkadm5_config_initialize, 0);
349
+ rb_define_method(cKadm5Config, "initialize", rkadm5_config_initialize, -1);
302
350
 
303
351
  // Methods
304
352
 
@@ -332,4 +380,5 @@ void Init_config(void){
332
380
  cKeySalt = rb_define_class_under(cKadm5, "KeySalt", rb_cObject);
333
381
  rb_define_attr(cKeySalt, "enctype", 1, 0);
334
382
  rb_define_attr(cKeySalt, "salttype", 1, 0);
335
- }
383
+ }
384
+ #endif
@@ -53,24 +53,28 @@ static VALUE rkrb5_context_close(VALUE self){
53
53
 
54
54
  /*
55
55
  * call-seq:
56
- * Kerberos::Context.new(options = {})
56
+ * Kerberos::Krb5::Context.new(secure: false, profile: nil)
57
57
  *
58
58
  * Creates and returns a new Kerberos::Context object.
59
59
  *
60
- * The options hash may be one or both of the following keys:
60
+ * The following keyword arguments are supported:
61
61
  *
62
62
  * :secure => true|false # Use config files only, ignore env variables
63
63
  * :profile => '/path/to/krb5.conf' # Use the specified profile file
64
+ *
65
+ * Note that the profile option may not be supported on your platform.
64
66
  */
65
67
  static VALUE rkrb5_context_initialize(int argc, VALUE *argv, VALUE self){
66
68
  RUBY_KRB5_CONTEXT* ptr;
67
69
  VALUE v_opts;
68
70
  VALUE v_secure, v_profile;
71
+ ID kw_table[2] = { rb_intern("secure"), rb_intern("profile") };
72
+ VALUE kw_vals[2];
69
73
  krb5_error_code kerror;
70
74
 
71
75
  TypedData_Get_Struct(self, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ptr);
72
76
 
73
- rb_scan_args(argc, argv, "01", &v_opts);
77
+ rb_scan_args(argc, argv, "0:", &v_opts);
74
78
 
75
79
  // Default behavior is a normal context that may respect environment.
76
80
  if (NIL_P(v_opts)) {
@@ -81,10 +85,9 @@ static VALUE rkrb5_context_initialize(int argc, VALUE *argv, VALUE self){
81
85
  return self;
82
86
  }
83
87
 
84
- Check_Type(v_opts, T_HASH);
85
-
86
- v_secure = rb_hash_aref2(v_opts, ID2SYM(rb_intern("secure")));
87
- v_profile = rb_hash_aref2(v_opts, ID2SYM(rb_intern("profile")));
88
+ rb_get_kwargs(v_opts, kw_table, 0, 2, kw_vals);
89
+ v_secure = kw_vals[0] == Qundef ? Qfalse : kw_vals[0];
90
+ v_profile = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
88
91
 
89
92
  /*
90
93
  * If a profile path is supplied, load it via profile_init_path() and
@@ -92,6 +95,9 @@ static VALUE rkrb5_context_initialize(int argc, VALUE *argv, VALUE self){
92
95
  * is used when the :secure option is truthy.
93
96
  */
94
97
  if (!NIL_P(v_profile)){
98
+ #ifndef HAVE_PROFILE_INIT_PATH
99
+ rb_raise(rb_eArgError, "profile option not supported on this platform");
100
+ #else
95
101
  Check_Type(v_profile, T_STRING);
96
102
 
97
103
  const char *profile_path = StringValueCStr(v_profile);
@@ -110,6 +116,7 @@ static VALUE rkrb5_context_initialize(int argc, VALUE *argv, VALUE self){
110
116
  rb_raise(cKrb5Exception, "krb5_init_context_profile: %s", error_message(kerror));
111
117
 
112
118
  return self;
119
+ #endif
113
120
  }
114
121
 
115
122
  // No profile given, choose secure or normal init.
@@ -127,6 +134,66 @@ static VALUE rkrb5_context_initialize(int argc, VALUE *argv, VALUE self){
127
134
  return self;
128
135
  }
129
136
 
137
+ /*
138
+ * call-seq:
139
+ * context.default_realm -> String
140
+ *
141
+ * Returns the default realm from this context.
142
+ */
143
+ static VALUE rkrb5_context_default_realm(VALUE self){
144
+ RUBY_KRB5_CONTEXT* ptr;
145
+ char* realm;
146
+ krb5_error_code kerror;
147
+
148
+ TypedData_Get_Struct(self, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ptr);
149
+
150
+ if(!ptr->ctx)
151
+ rb_raise(cKrb5Exception, "no context has been established");
152
+
153
+ kerror = krb5_get_default_realm(ptr->ctx, &realm);
154
+
155
+ if(kerror)
156
+ rb_raise(cKrb5Exception, "krb5_get_default_realm: %s", error_message(kerror));
157
+
158
+ VALUE v_realm = rb_str_new2(realm);
159
+ krb5_free_default_realm(ptr->ctx, realm);
160
+
161
+ return v_realm;
162
+ }
163
+
164
+ /*
165
+ * call-seq:
166
+ * context.default_realm = realm
167
+ *
168
+ * Sets the default realm for this context. If +realm+ is nil the default
169
+ * from krb5.conf is restored.
170
+ */
171
+ static VALUE rkrb5_context_set_default_realm(VALUE self, VALUE v_realm){
172
+ RUBY_KRB5_CONTEXT* ptr;
173
+ char* realm;
174
+ krb5_error_code kerror;
175
+
176
+ TypedData_Get_Struct(self, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ptr);
177
+
178
+ if(!ptr->ctx)
179
+ rb_raise(cKrb5Exception, "no context has been established");
180
+
181
+ if(NIL_P(v_realm)){
182
+ realm = NULL;
183
+ }
184
+ else{
185
+ Check_Type(v_realm, T_STRING);
186
+ realm = StringValueCStr(v_realm);
187
+ }
188
+
189
+ kerror = krb5_set_default_realm(ptr->ctx, realm);
190
+
191
+ if(kerror)
192
+ rb_raise(cKrb5Exception, "krb5_set_default_realm: %s", error_message(kerror));
193
+
194
+ return v_realm;
195
+ }
196
+
130
197
  void Init_context(void){
131
198
  /* The Kerberos::Krb5::Context class encapsulates a Kerberos context. */
132
199
  cKrb5Context = rb_define_class_under(cKrb5, "Context", rb_cObject);
@@ -139,4 +206,6 @@ void Init_context(void){
139
206
 
140
207
  // Instance Methods
141
208
  rb_define_method(cKrb5Context, "close", rkrb5_context_close, 0);
209
+ rb_define_method(cKrb5Context, "default_realm", rkrb5_context_default_realm, 0);
210
+ rb_define_method(cKrb5Context, "default_realm=", rkrb5_context_set_default_realm, 1);
142
211
  }
@@ -14,8 +14,19 @@ else
14
14
  else
15
15
  dir_config('rkerberos', '/usr/local')
16
16
  end
17
+
18
+ if File::ALT_SEPARATOR
19
+ kfw_dir = ENV['KRB5_DIR'] || 'C:/Program Files/MIT/Kerberos'
20
+ kfw_inc = ENV['KRB5_INCLUDE'] || File.join(kfw_dir, 'include')
21
+ kfw_lib = ENV['KRB5_LIB'] || File.join(kfw_dir, 'lib')
22
+ $INCFLAGS << " -I\"#{kfw_inc}\""
23
+ $LDFLAGS << " -L\"#{kfw_lib}\""
24
+ end
25
+
17
26
  have_header('krb5.h')
18
- have_library('krb5')
27
+
28
+ have_library('krb5') || have_library('krb5_64')
29
+ have_library('comerr') || have_library('comerr64')
19
30
  end
20
31
 
21
32
  pkg_config('com_err') || have_library('com_err')
@@ -26,8 +37,10 @@ end
26
37
 
27
38
  if pkg_config('kdb5') || have_library('kdb5')
28
39
  have_header('kdb.h')
29
- else
30
- raise 'kdb5 library not found'
40
+ end
41
+
42
+ if have_header('profile.h')
43
+ have_func('profile_init_path')
31
44
  end
32
45
 
33
46
  create_makefile('rkerberos')