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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a969c8a989d5d310bd6906a8023acdd1bd511524cdf85e1b8df35b9e51a424e
4
- data.tar.gz: 8792c83e657bd1ddc3da150a2989906050ea48bc2631a2de9e95fe5a8983f2c1
3
+ metadata.gz: 10c43a653634532f7c52f8156f9ea2c9b5646d9bdff60866f8dde301c1abe5e7
4
+ data.tar.gz: 99021863b149758d3231938481736878027ad99ef8b4056d3d994e0b0a8dbffb
5
5
  SHA512:
6
- metadata.gz: 41e50b69c30e64a0ca78548cb189ad6627b41b951abb906caac1e27d2746afbd81df6b96e1cbb1910b1b0c535c5fddd752e5246ff4eab16af860e1797b599374
7
- data.tar.gz: 1b3a230983ff08f515412a0bf2055f1152c8e3d757cda4d017d2ec72a53210c077a4874117a0d56256b42535b83d5495c4ec0e315d02cf2e6be9220384d0ac8f
6
+ metadata.gz: c74926903cdbbcafe0e756189b0e5b53308fc30f4808d090d8091e92941c28f9c7e4629f61c9fb30df130990574bec809f42cfccee9d75d9b697e27e5654889f
7
+ data.tar.gz: 798be63f34c776a54d1ea54556edc36d965ac0149b7a04414f37b16db3439f8ea1dc8ae7d0f64a0c826c3f80d7cdea0818f5c519a2a77bac0495fa3cb4a44317
data/CHANGES.md ADDED
@@ -0,0 +1,59 @@
1
+ # 0.2.2 - 3-Mar-2026
2
+ * Added custom .dup methods for CredentialsCache and Keytab.
3
+ * Added the keytab_name and keytab_type methods to Keytab.
4
+ * Added the cache_name, cache_type and principal methods to CredentialsCache.
5
+ * The Keytab#get_entry method now properly honors the vno and encoding type arguments.
6
+ * Fixed the max_life and max_rlife attributes in Config.
7
+ * Fixed the get_privileges method in Kadm5.
8
+ * Fixed the change_password method in Kadm5 and added specs for it. Previously it would
9
+ generally always return true because it wasn't considering KDC failures, only raw
10
+ function failures.
11
+ * Heaps of memory leak fixes. Get it? Heaps? Right, I'll see myself out.
12
+ * Converted the CHANGES and MANIFEST files to markdown.
13
+
14
+ # 0.2.1 - 1-Mar-2026
15
+ * Added the verify_init_creds and an authenticate! methods.
16
+ * The Context constructor now accepts optional :secure and/or :profile arguments
17
+ for different types of contexts.
18
+ * Minor fix for the CredentialsCache constructor.
19
+ * Minor fix for the get_init_creds_keytab method.
20
+ * Fixed a mistake in an rb_funcall in the Policy class (thanks Ondřej Gajdušek).
21
+ * Update gemspec so that releases don't include Docker related files (thanks Ondřej Gajdušek).
22
+ * Add a spec:compose task for convenience.
23
+ * The rake-compiler gem is now a development dependency, not a runtime
24
+ dependency (thanks Ondřej Gajdušek).
25
+
26
+ # 0.2.0 - 14-Feb-2026
27
+ * Added Docker and Podman support for running tests in isolated environments with Kerberos and OpenLDAP services.
28
+ * Updated documentation with modern testing and development workflows, including container-based instructions.
29
+ * Improved compatibility for Ruby 3.4 and later.
30
+ * Enhanced build and test automation using docker-compose and podman-compose.
31
+ * Various bug fixes, code cleanups, and test improvements.
32
+
33
+ # 0.1.5 - 17-Oct-2016
34
+ * Fix build error on Ruby 2.0.0/2.1 with CFLAGS concatenation
35
+
36
+ # 0.1.4 - 14-Oct-2016
37
+ * Implement db_args functionality in kadmin (fixes #8)
38
+ * Fix a double-free error when setting the realm for a principal
39
+ * Fix an error in policy creation that would sometimes cause a communication failure
40
+ * Set C99 as the C Standard and fix all compiler warnings at this level
41
+
42
+ # 0.1.3 - 07-Sep-2013
43
+ * Add optional 'service' argument to get_init_creds_password (fixes #3)
44
+ * Artistic License 2.0 text now included (fixes #2)
45
+
46
+ # 0.1.2 - 24-Jun-2013
47
+ * Fix kadm5clnt build issue on EL6
48
+ * Remove admin_keytab references for krb5 1.11
49
+ * Add Gemfile
50
+ * Replace deprecated Config with RbConfig (Ruby 2)
51
+
52
+ # 0.1.1 - 08-May-2013
53
+ * Add credential cache argument to get_init_creds_keytab
54
+ * Fixed invalid VALUE declarations affecting non-gcc compilers
55
+ * Add OS X install instructions
56
+
57
+ # 0.1.0 - 28-Apr-2011
58
+ * Initial release. This is effectively a re-release of my own custom branch
59
+ of the krb5-auth library, with some minor changes.
data/MANIFEST.md ADDED
@@ -0,0 +1,24 @@
1
+ * CHANGES.md
2
+ * rkerberos.gemspec
3
+ * MANIFEST.md
4
+ * 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
16
+ * spec/config_spec.rb
17
+ * spec/context_spec.rb
18
+ * spec/credentials_spec.rb
19
+ * spec/kadm5_spec.rb
20
+ * spec/keytab_entry_spec.rb
21
+ * spec/krb5_keytab_spec.rb
22
+ * spec/krb5_spec.rb
23
+ * spec/policy_spec.rb
24
+ * spec/principal_spec.rb
data/README.md CHANGED
@@ -1,5 +1,44 @@
1
+ [![Ruby](https://github.com/rkerberos/rkerberos/actions/workflows/ci.yml/badge.svg)](https://github.com/rkerberos/rkerberos/actions/workflows/ci.yml)
2
+
1
3
  # Description
2
- The rkerberos library provides a Ruby interface for Kerberos.
4
+ The rkerberos library provides a Ruby interface for Kerberos.
5
+
6
+ ## Code synopsis
7
+
8
+ Some basic usage:
9
+
10
+ ```ruby
11
+ require 'rkerberos'
12
+
13
+ # Client
14
+ krb = Kerberos::Krb5.new
15
+ puts krb.default_realm
16
+ puts krb.default_principal
17
+ puts krb.get_permitted_enctypes.keys.join(',')
18
+
19
+ # Credentials cache
20
+ cc = Kerberos::Krb5::CredentialsCache.new
21
+ krb.verify_init_creds(nil, nil, cc)
22
+ puts cc.primary_principal
23
+
24
+ # Keytab
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
28
+
29
+ # Admin
30
+ Kerberos::Kadm5.new(principal: ENV['KRB5_ADMIN_PRINCIPAL'], password: ENV['KRB5_ADMIN_PASSWORD']) do |kadmin|
31
+ kadmin.create_principal('newuser@EXAMPLE.COM', 'initialpass')
32
+ kadmin.set_password('newuser@EXAMPLE.COM', 'betterpass')
33
+ kadmin.delete_principal('newuser@EXAMPLE.COM')
34
+ end
35
+
36
+ # Contexts
37
+ ctx = Kerberos::Krb5::Context.new # standard context
38
+ ctx = Kerberos::Krb5::Context.new(profile: '/etc/krb5.conf') # or use a profile
39
+ ctx = Kerberos::Krb5::Context.new(secure: true) # or use a secure context
40
+ ctx.close
41
+ ```
3
42
 
4
43
  # Requirements
5
44
 
@@ -91,6 +130,19 @@ If you make changes to the Ruby code or C extensions:
91
130
  podman-compose run --rm rkerberos-test
92
131
  ```
93
132
 
133
+ Alternatively, you can just run containerized tests via the `spec:compose`
134
+ Rake task. This task runs the same containerized workflow used above and
135
+ prefers `podman-compose` with a `docker-compose` fallback.
136
+
137
+ ```bash
138
+ # build image and run RSpec inside the test container
139
+ rake spec:compose
140
+ # skip the build step by passing a positional or named argument:
141
+ # (equivalent forms)
142
+ rake spec:compose[true]
143
+ rake "spec:compose[fast=true]"
144
+ ```
145
+
94
146
  The test environment includes:
95
147
  - MIT Kerberos KDC (Key Distribution Center)
96
148
  - OpenLDAP server for directory services
@@ -112,8 +164,8 @@ The test environment includes:
112
164
 
113
165
  # Authors
114
166
  * Daniel Berger
115
- * Dominic Cleal (maintainer)
116
- * Simon Levermann (maintainer)
167
+ * Dominic Cleal
168
+ * Simon Levermann
117
169
 
118
170
  # License
119
171
  rkerberos is distributed under the Artistic-2.0 license.
data/Rakefile CHANGED
@@ -77,6 +77,41 @@ RSpec::Core::RakeTask.new(:spec) do |t|
77
77
  t.pattern = 'spec/**/*_spec.rb'
78
78
  end
79
79
 
80
+ # Run specs inside the project container using podman-compose (or docker-compose).
81
+ namespace :spec do
82
+ desc 'Build test image and run RSpec inside container (podman-compose or docker-compose)'
83
+ task :compose, [:fast] do |t, args|
84
+ # allow either positional or named argument (e.g. "fast=true")
85
+ fast = args[:fast]
86
+ if fast && fast.include?("=")
87
+ k,v = fast.split("=",2)
88
+ fast = v if k == 'fast'
89
+ end
90
+ fast = true if fast == 'true'
91
+
92
+ compose = `which podman-compose`.strip
93
+ compose = 'docker-compose' if compose.empty?
94
+
95
+ if fast
96
+ puts "Using #{compose} to run containerized specs (fast)..."
97
+ else
98
+ puts "Using #{compose} to run containerized specs..."
99
+ end
100
+
101
+ FileUtils.rm_rf('Gemfile.lock')
102
+ begin
103
+ unless fast
104
+ sh "#{compose} build --no-cache kerberos-kdc"
105
+ sh "#{compose} build --no-cache rkerberos-test"
106
+ end
107
+ sh "#{compose} run --rm rkerberos-test"
108
+ ensure
109
+ # redirect stderr so missing-container messages don't appear
110
+ sh "#{compose} down -v 2>/dev/null" rescue nil
111
+ end
112
+ end
113
+ end
114
+
80
115
  # Clean up afterwards
81
116
  Rake::Task[:spec].enhance do
82
117
  Rake::Task[:clean].invoke
@@ -57,10 +57,17 @@ static VALUE rkrb5_ccache_initialize(int argc, VALUE* argv, VALUE self){
57
57
 
58
58
  rb_scan_args(argc, argv, "02", &v_principal, &v_name);
59
59
 
60
- // Convert the principal name to a principal object
61
- if(RTEST(v_principal)){
60
+ if(RTEST(v_principal))
62
61
  Check_Type(v_principal, T_STRING);
63
62
 
63
+ // Initialize the context
64
+ kerror = krb5_init_context(&ptr->ctx);
65
+
66
+ if(kerror)
67
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
68
+
69
+ // Convert the principal name to a principal object
70
+ if(RTEST(v_principal)){
64
71
  kerror = krb5_parse_name(
65
72
  ptr->ctx,
66
73
  StringValueCStr(v_principal),
@@ -71,12 +78,6 @@ static VALUE rkrb5_ccache_initialize(int argc, VALUE* argv, VALUE self){
71
78
  rb_raise(cKrb5Exception, "krb5_parse_name: %s", error_message(kerror));
72
79
  }
73
80
 
74
- // Initialize the context
75
- kerror = krb5_init_context(&ptr->ctx);
76
-
77
- if(kerror)
78
- rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
79
-
80
81
  // Set the credentials cache using the default cache if no name is provided
81
82
  if(NIL_P(v_name)){
82
83
  kerror = krb5_cc_default(ptr->ctx, &ptr->ccache);
@@ -156,6 +157,40 @@ static VALUE rkrb5_ccache_default_name(VALUE self){
156
157
  return rb_str_new2(krb5_cc_default_name(ptr->ctx));
157
158
  }
158
159
 
160
+ // Wrapper for krb5_cc_get_name; returns the actual ccache name.
161
+ static VALUE rkrb5_ccache_get_name(VALUE self){
162
+ RUBY_KRB5_CCACHE* ptr;
163
+ const char *name;
164
+
165
+ TypedData_Get_Struct(self, RUBY_KRB5_CCACHE, &rkrb5_ccache_data_type, ptr);
166
+
167
+ if(!ptr->ctx)
168
+ rb_raise(cKrb5Exception, "no context has been established");
169
+
170
+ name = krb5_cc_get_name(ptr->ctx, ptr->ccache);
171
+ if(!name)
172
+ rb_raise(cKrb5Exception, "krb5_cc_get_name returned NULL");
173
+
174
+ return rb_str_new2(name);
175
+ }
176
+
177
+ // Wrapper for krb5_cc_get_type; returns the cache type string.
178
+ static VALUE rkrb5_ccache_get_type(VALUE self){
179
+ RUBY_KRB5_CCACHE* ptr;
180
+ const char *type;
181
+
182
+ TypedData_Get_Struct(self, RUBY_KRB5_CCACHE, &rkrb5_ccache_data_type, ptr);
183
+
184
+ if(!ptr->ctx)
185
+ rb_raise(cKrb5Exception, "no context has been established");
186
+
187
+ type = krb5_cc_get_type(ptr->ctx, ptr->ccache);
188
+ if(!type)
189
+ rb_raise(cKrb5Exception, "krb5_cc_get_type returned NULL");
190
+
191
+ return rb_str_new2(type);
192
+ }
193
+
159
194
  /*
160
195
  * call-seq:
161
196
  * ccache.primary_principal
@@ -172,6 +207,11 @@ static VALUE rkrb5_ccache_primary_principal(VALUE self){
172
207
  if(!ptr->ctx)
173
208
  rb_raise(cKrb5Exception, "no context has been established");
174
209
 
210
+ if(ptr->principal){
211
+ krb5_free_principal(ptr->ctx, ptr->principal);
212
+ ptr->principal = NULL;
213
+ }
214
+
175
215
  kerror = krb5_cc_get_principal(ptr->ctx, ptr->ccache, &ptr->principal);
176
216
 
177
217
  if(kerror)
@@ -182,7 +222,15 @@ static VALUE rkrb5_ccache_primary_principal(VALUE self){
182
222
  if(kerror)
183
223
  rb_raise(cKrb5Exception, "krb5_unparse_name: %s", error_message(kerror));
184
224
 
185
- return rb_str_new2(name);
225
+ VALUE v_name = rb_str_new2(name);
226
+ krb5_free_unparsed_name(ptr->ctx, name);
227
+
228
+ return v_name;
229
+ }
230
+
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);
186
234
  }
187
235
 
188
236
  /*
@@ -236,6 +284,47 @@ static VALUE rkrb5_ccache_destroy(VALUE self){
236
284
  return v_bool;
237
285
  }
238
286
 
287
+ // Duplicate the credentials cache object.
288
+ // call-seq:
289
+ // ccache.dup -> new_ccache
290
+ //
291
+ // Returns a new Kerberos::Krb5::CredentialsCache that references the
292
+ // same underlying cache data. The new object has its own krb5 context so
293
+ // that closing one cache does not affect the other.
294
+ static VALUE rkrb5_ccache_dup(VALUE self){
295
+ RUBY_KRB5_CCACHE *ptr, *newptr;
296
+ krb5_error_code kerror;
297
+ VALUE newobj;
298
+
299
+ TypedData_Get_Struct(self, RUBY_KRB5_CCACHE, &rkrb5_ccache_data_type, ptr);
300
+
301
+ if(!ptr->ctx)
302
+ rb_raise(cKrb5Exception, "no context has been established");
303
+
304
+ // allocate new ruby object and struct
305
+ newobj = rkrb5_ccache_allocate(CLASS_OF(self));
306
+ TypedData_Get_Struct(newobj, RUBY_KRB5_CCACHE, &rkrb5_ccache_data_type, newptr);
307
+
308
+ // initialize a fresh context for the duplicate
309
+ kerror = krb5_init_context(&newptr->ctx);
310
+ if(kerror){
311
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
312
+ }
313
+
314
+ // perform ccache duplication using the new context
315
+ kerror = krb5_cc_dup(newptr->ctx, ptr->ccache, &newptr->ccache);
316
+ if(kerror){
317
+ krb5_free_context(newptr->ctx);
318
+ newptr->ctx = NULL;
319
+ rb_raise(cKrb5Exception, "krb5_cc_dup: %s", error_message(kerror));
320
+ }
321
+
322
+ // principal is not copied; let callers query primary_principal on each
323
+ newptr->principal = NULL;
324
+
325
+ return newobj;
326
+ }
327
+
239
328
  void Init_ccache(void){
240
329
  /* The Kerberos::Krb5::CredentialsCache class encapsulates a Kerberos credentials cache. */
241
330
  cKrb5CCache = rb_define_class_under(cKrb5, "CredentialsCache", rb_cObject);
@@ -249,8 +338,13 @@ void Init_ccache(void){
249
338
  // Instance Methods
250
339
  rb_define_method(cKrb5CCache, "close", rkrb5_ccache_close, 0);
251
340
  rb_define_method(cKrb5CCache, "default_name", rkrb5_ccache_default_name, 0);
341
+ rb_define_method(cKrb5CCache, "cache_name", rkrb5_ccache_get_name, 0);
342
+ rb_define_method(cKrb5CCache, "cache_type", rkrb5_ccache_get_type, 0);
252
343
  rb_define_method(cKrb5CCache, "destroy", rkrb5_ccache_destroy, 0);
253
344
  rb_define_method(cKrb5CCache, "primary_principal", rkrb5_ccache_primary_principal, 0);
345
+ rb_define_method(cKrb5CCache, "principal", rkrb5_ccache_principal, 0);
346
+ rb_define_method(cKrb5CCache, "dup", rkrb5_ccache_dup, 0);
347
+ rb_define_alias(cKrb5CCache, "clone", "dup");
254
348
 
255
349
  // Aliases
256
350
  rb_define_alias(cKrb5CCache, "delete", "destroy");
@@ -263,12 +263,12 @@ static VALUE rkadm5_config_inspect(VALUE self){
263
263
  rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@mkey_from_kbd")));
264
264
  rb_str_buf_cat2(v_str, " ");
265
265
 
266
- rb_str_buf_cat2(v_str, "maxlife=");
267
- rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@maxlife")));
266
+ rb_str_buf_cat2(v_str, "max_life=");
267
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@max_life")));
268
268
  rb_str_buf_cat2(v_str, " ");
269
269
 
270
- rb_str_buf_cat2(v_str, "maxrlife=");
271
- rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@maxrlife")));
270
+ rb_str_buf_cat2(v_str, "max_rlife=");
271
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@max_rlife")));
272
272
  rb_str_buf_cat2(v_str, " ");
273
273
 
274
274
  rb_str_buf_cat2(v_str, "num_keysalts=");
@@ -1,5 +1,7 @@
1
1
  #include <rkerberos.h>
2
2
 
3
+ #include <profile.h>
4
+
3
5
  VALUE cKrb5Context;
4
6
 
5
7
  // Free function for the Kerberos::Krb5::Context class.
@@ -51,23 +53,76 @@ static VALUE rkrb5_context_close(VALUE self){
51
53
 
52
54
  /*
53
55
  * call-seq:
54
- * Kerberos::Context.new
56
+ * Kerberos::Context.new(options = {})
55
57
  *
56
58
  * Creates and returns a new Kerberos::Context object.
57
59
  *
58
- * This class is not typically instantiated directly, but is used internally
59
- * by the krb5-auth library.
60
+ * The options hash may be one or both of the following keys:
61
+ *
62
+ * :secure => true|false # Use config files only, ignore env variables
63
+ * :profile => '/path/to/krb5.conf' # Use the specified profile file
60
64
  */
61
- static VALUE rkrb5_context_initialize(VALUE self){
65
+ static VALUE rkrb5_context_initialize(int argc, VALUE *argv, VALUE self){
62
66
  RUBY_KRB5_CONTEXT* ptr;
67
+ VALUE v_opts;
68
+ VALUE v_secure, v_profile;
63
69
  krb5_error_code kerror;
64
70
 
65
71
  TypedData_Get_Struct(self, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ptr);
66
72
 
67
- kerror = krb5_init_context(&ptr->ctx);
73
+ rb_scan_args(argc, argv, "01", &v_opts);
74
+
75
+ // Default behavior is a normal context that may respect environment.
76
+ if (NIL_P(v_opts)) {
77
+ kerror = krb5_init_context(&ptr->ctx);
78
+ if(kerror)
79
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
80
+
81
+ return self;
82
+ }
83
+
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
+
89
+ /*
90
+ * If a profile path is supplied, load it via profile_init_path() and
91
+ * create a context from that profile. The KRB5_INIT_CONTEXT_SECURE flag
92
+ * is used when the :secure option is truthy.
93
+ */
94
+ if (!NIL_P(v_profile)){
95
+ Check_Type(v_profile, T_STRING);
96
+
97
+ const char *profile_path = StringValueCStr(v_profile);
98
+ profile_t profile = NULL;
99
+ long pres = profile_init_path(profile_path, &profile);
100
+
101
+ if(pres != 0)
102
+ rb_raise(cKrb5Exception, "profile_init_path: %ld", pres);
103
+
104
+ krb5_flags flags = RTEST(v_secure) ? KRB5_INIT_CONTEXT_SECURE : 0;
105
+ kerror = krb5_init_context_profile(profile, flags, &ptr->ctx);
106
+
107
+ profile_release(profile);
108
+
109
+ if(kerror)
110
+ rb_raise(cKrb5Exception, "krb5_init_context_profile: %s", error_message(kerror));
111
+
112
+ return self;
113
+ }
68
114
 
69
- if(kerror)
70
- rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
115
+ // No profile given, choose secure or normal init.
116
+ if (RTEST(v_secure)){
117
+ kerror = krb5_init_secure_context(&ptr->ctx);
118
+ if(kerror)
119
+ rb_raise(cKrb5Exception, "krb5_init_secure_context: %s", error_message(kerror));
120
+ }
121
+ else{
122
+ kerror = krb5_init_context(&ptr->ctx);
123
+ if(kerror)
124
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
125
+ }
71
126
 
72
127
  return self;
73
128
  }
@@ -80,7 +135,7 @@ void Init_context(void){
80
135
  rb_define_alloc_func(cKrb5Context, rkrb5_context_allocate);
81
136
 
82
137
  // Constructor
83
- rb_define_method(cKrb5Context, "initialize", rkrb5_context_initialize, 0);
138
+ rb_define_method(cKrb5Context, "initialize", rkrb5_context_initialize, -1);
84
139
 
85
140
  // Instance Methods
86
141
  rb_define_method(cKrb5Context, "close", rkrb5_context_close, 0);