rkerberos 0.2.3 → 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.
- checksums.yaml +4 -4
- data/CHANGES.md +15 -0
- data/EXAMPLES.md +1015 -0
- data/MANIFEST.md +17 -12
- data/README.md +5 -5
- data/ext/rkerberos/ccache.c +101 -26
- data/ext/rkerberos/config.c +53 -7
- data/ext/rkerberos/context.c +70 -7
- data/ext/rkerberos/kadm5.c +280 -87
- data/ext/rkerberos/keytab.c +210 -64
- data/ext/rkerberos/policy.c +25 -23
- data/ext/rkerberos/principal.c +108 -10
- data/ext/rkerberos/rkerberos.c +229 -28
- data/ext/rkerberos/rkerberos.h +8 -0
- data/rkerberos.gemspec +10 -7
- data/spec/config_spec.rb +33 -0
- data/spec/context_spec.rb +51 -0
- data/spec/credentials_cache_spec.rb +79 -26
- data/spec/kadm5_spec.rb +278 -5
- data/spec/krb5_keytab_spec.rb +224 -20
- data/spec/krb5_spec.rb +131 -20
- data/spec/policy_spec.rb +4 -0
- data/spec/principal_spec.rb +90 -10
- metadata +9 -8
data/ext/rkerberos/kadm5.c
CHANGED
|
@@ -17,6 +17,13 @@ void add_tl_data(krb5_int16 *, krb5_tl_data **,
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
// TypedData functions for RUBY_KADM5
|
|
20
|
+
static void rkadm5_typed_mark(void *ptr) {
|
|
21
|
+
if (!ptr) return;
|
|
22
|
+
RUBY_KADM5 *k = (RUBY_KADM5 *)ptr;
|
|
23
|
+
if (k->rb_context != Qnil)
|
|
24
|
+
rb_gc_mark(k->rb_context);
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
static void rkadm5_typed_free(void *ptr) {
|
|
21
28
|
if (!ptr) return;
|
|
22
29
|
RUBY_KADM5 *k = (RUBY_KADM5 *)ptr;
|
|
@@ -24,7 +31,7 @@ static void rkadm5_typed_free(void *ptr) {
|
|
|
24
31
|
kadm5_destroy(k->handle);
|
|
25
32
|
if (k->princ)
|
|
26
33
|
krb5_free_principal(k->ctx, k->princ);
|
|
27
|
-
if (k->ctx)
|
|
34
|
+
if (k->ctx && k->rb_context == Qnil)
|
|
28
35
|
krb5_free_context(k->ctx);
|
|
29
36
|
free_db_args(k->db_args);
|
|
30
37
|
free(k);
|
|
@@ -36,7 +43,7 @@ static size_t rkadm5_typed_size(const void *ptr) {
|
|
|
36
43
|
|
|
37
44
|
static const rb_data_type_t rkadm5_data_type = {
|
|
38
45
|
"RUBY_KADM5",
|
|
39
|
-
{
|
|
46
|
+
{rkadm5_typed_mark, rkadm5_typed_free, rkadm5_typed_size,},
|
|
40
47
|
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
|
|
41
48
|
};
|
|
42
49
|
|
|
@@ -44,34 +51,48 @@ static const rb_data_type_t rkadm5_data_type = {
|
|
|
44
51
|
static VALUE rkadm5_allocate(VALUE klass){
|
|
45
52
|
RUBY_KADM5* ptr = ALLOC(RUBY_KADM5);
|
|
46
53
|
memset(ptr, 0, sizeof(RUBY_KADM5));
|
|
54
|
+
ptr->rb_context = Qnil;
|
|
47
55
|
return TypedData_Wrap_Struct(klass, &rkadm5_data_type, ptr);
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
/*
|
|
51
59
|
* call-seq:
|
|
52
|
-
* Kerberos::Kadm5.new(:
|
|
53
|
-
* Kerberos::Kadm5.new(:
|
|
54
|
-
* Kerberos::Kadm5.new(:
|
|
60
|
+
* Kerberos::Kadm5.new(principal: 'name', password: 'xxxxx')
|
|
61
|
+
* Kerberos::Kadm5.new(principal: 'name', keytab: '/path/to/your/keytab')
|
|
62
|
+
* Kerberos::Kadm5.new(principal: 'name', keytab: true)
|
|
63
|
+
* Kerberos::Kadm5.new(principal: 'name', ccache: ccache_object)
|
|
55
64
|
*
|
|
56
|
-
* Creates and returns a new Kerberos::Kadm5 object.
|
|
57
|
-
*
|
|
58
|
-
*
|
|
65
|
+
* Creates and returns a new Kerberos::Kadm5 object. Keyword arguments allow
|
|
66
|
+
* you to specify a principal and a password, a keytab file, or a credentials
|
|
67
|
+
* cache.
|
|
59
68
|
*
|
|
60
69
|
* If you pass a string as the :keytab value it will attempt to use that file
|
|
61
70
|
* for the keytab. If you pass true as the value it will attempt to use the
|
|
62
71
|
* default keytab file, typically /etc/krb5.keytab.
|
|
63
72
|
*
|
|
73
|
+
* If you pass a Kerberos::Krb5::CredentialsCache object as the :ccache value,
|
|
74
|
+
* it will authenticate using the credentials stored in that cache via
|
|
75
|
+
* kadm5_init_with_creds.
|
|
76
|
+
*
|
|
64
77
|
* You may also pass the :service option to specify the service name. The
|
|
65
78
|
* default is kadmin/admin.
|
|
66
79
|
*
|
|
67
80
|
* There is also a :db_args option, which is a single string or array of strings
|
|
68
81
|
* containing options usually passed to kadmin with the -x switch. For a list of
|
|
69
|
-
* available options, see the kadmin manpage
|
|
82
|
+
* available options, see the kadmin manpage.
|
|
83
|
+
*
|
|
84
|
+
* Only one of :password, :keytab, or :ccache may be specified.
|
|
70
85
|
*
|
|
71
86
|
*/
|
|
72
|
-
static VALUE rkadm5_initialize(VALUE
|
|
87
|
+
static VALUE rkadm5_initialize(int argc, VALUE* argv, VALUE self){
|
|
73
88
|
RUBY_KADM5* ptr;
|
|
74
|
-
VALUE v_principal, v_password, v_keytab, v_service, v_db_args;
|
|
89
|
+
VALUE v_opts, v_principal, v_password, v_keytab, v_service, v_db_args, v_context, v_ccache;
|
|
90
|
+
ID kw_table[7] = {
|
|
91
|
+
rb_intern("principal"), rb_intern("password"), rb_intern("keytab"),
|
|
92
|
+
rb_intern("ccache"), rb_intern("service"), rb_intern("db_args"),
|
|
93
|
+
rb_intern("context")
|
|
94
|
+
};
|
|
95
|
+
VALUE kw_vals[7];
|
|
75
96
|
char* user;
|
|
76
97
|
char* pass = NULL;
|
|
77
98
|
char* keytab = NULL;
|
|
@@ -80,35 +101,59 @@ static VALUE rkadm5_initialize(VALUE self, VALUE v_opts){
|
|
|
80
101
|
krb5_error_code kerror;
|
|
81
102
|
|
|
82
103
|
TypedData_Get_Struct(self, RUBY_KADM5, &rkadm5_data_type, ptr);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
rb_scan_args(argc, argv, "0:", &v_opts);
|
|
105
|
+
|
|
106
|
+
if(NIL_P(v_opts))
|
|
107
|
+
v_opts = rb_hash_new();
|
|
108
|
+
|
|
109
|
+
rb_get_kwargs(v_opts, kw_table, 0, 7, kw_vals);
|
|
110
|
+
v_principal = kw_vals[0] == Qundef ? Qnil : kw_vals[0];
|
|
111
|
+
v_password = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
|
|
112
|
+
v_keytab = kw_vals[2] == Qundef ? Qnil : kw_vals[2];
|
|
113
|
+
v_ccache = kw_vals[3] == Qundef ? Qnil : kw_vals[3];
|
|
114
|
+
v_service = kw_vals[4] == Qundef ? Qnil : kw_vals[4];
|
|
115
|
+
v_db_args = kw_vals[5] == Qundef ? Qnil : kw_vals[5];
|
|
116
|
+
v_context = kw_vals[6] == Qundef ? Qnil : kw_vals[6];
|
|
117
|
+
|
|
118
|
+
// Validate mutual exclusivity
|
|
119
|
+
{
|
|
120
|
+
int auth_count = 0;
|
|
121
|
+
if(RTEST(v_password)) auth_count++;
|
|
122
|
+
if(RTEST(v_keytab)) auth_count++;
|
|
123
|
+
if(RTEST(v_ccache)) auth_count++;
|
|
124
|
+
|
|
125
|
+
if(auth_count > 1)
|
|
126
|
+
rb_raise(rb_eArgError, "only one of password, keytab, or ccache may be specified");
|
|
127
|
+
|
|
128
|
+
if(auth_count == 0)
|
|
129
|
+
rb_raise(rb_eArgError, "one of password, keytab, or ccache must be specified");
|
|
130
|
+
}
|
|
103
131
|
|
|
132
|
+
// Principal must be specified if using a password
|
|
104
133
|
if(RTEST(v_password)){
|
|
134
|
+
if(NIL_P(v_principal))
|
|
135
|
+
rb_raise(rb_eArgError, "principal must be specified");
|
|
136
|
+
|
|
105
137
|
Check_Type(v_password, T_STRING);
|
|
138
|
+
Check_Type(v_principal, T_STRING);
|
|
139
|
+
|
|
106
140
|
pass = StringValueCStr(v_password);
|
|
107
141
|
}
|
|
108
142
|
|
|
109
|
-
|
|
110
|
-
|
|
143
|
+
if(RTEST(v_ccache) && NIL_P(v_principal)){
|
|
144
|
+
if(NIL_P(v_principal))
|
|
145
|
+
v_principal = rb_funcall(v_ccache, rb_intern("principal"), 0);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// For a keytab use the first entry's principal
|
|
149
|
+
if(RTEST(v_keytab) && NIL_P(v_principal)) {
|
|
150
|
+
VALUE v_enum, v_first;
|
|
151
|
+
v_enum = rb_funcall(v_keytab, rb_intern("each"), 0);
|
|
152
|
+
v_first = rb_funcall(v_enum, rb_intern("first"), 0);
|
|
153
|
+
v_principal = rb_iv_get(v_first, "@principal");
|
|
154
|
+
}
|
|
111
155
|
|
|
156
|
+
user = StringValueCStr(v_principal);
|
|
112
157
|
if(NIL_P(v_service)){
|
|
113
158
|
service = (char *) "kadmin/admin";
|
|
114
159
|
}
|
|
@@ -117,16 +162,31 @@ static VALUE rkadm5_initialize(VALUE self, VALUE v_opts){
|
|
|
117
162
|
service = StringValueCStr(v_service);
|
|
118
163
|
}
|
|
119
164
|
|
|
120
|
-
v_db_args = rb_hash_aref2(v_opts, rb_str_new_cstr("db_args"));
|
|
121
|
-
if (NIL_P(v_db_args)) v_db_args = rb_hash_aref2(v_opts, ID2SYM(rb_intern("db_args")));
|
|
122
165
|
ptr->db_args = parse_db_args(v_db_args);
|
|
123
166
|
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
167
|
+
// Initialize or borrow the context
|
|
168
|
+
if(!NIL_P(v_context)){
|
|
169
|
+
RUBY_KRB5_CONTEXT* ctx_ptr;
|
|
127
170
|
|
|
128
|
-
|
|
129
|
-
|
|
171
|
+
if(!rb_obj_is_kind_of(v_context, cKrb5Context))
|
|
172
|
+
rb_raise(rb_eTypeError, "context must be a Kerberos::Krb5::Context object");
|
|
173
|
+
|
|
174
|
+
TypedData_Get_Struct(v_context, RUBY_KRB5_CONTEXT, &rkrb5_context_data_type, ctx_ptr);
|
|
175
|
+
|
|
176
|
+
if(!ctx_ptr->ctx)
|
|
177
|
+
rb_raise(cKrb5Exception, "context is closed");
|
|
178
|
+
|
|
179
|
+
ptr->ctx = ctx_ptr->ctx;
|
|
180
|
+
ptr->rb_context = v_context;
|
|
181
|
+
}
|
|
182
|
+
else{
|
|
183
|
+
kerror = krb5_init_context(&ptr->ctx);
|
|
184
|
+
|
|
185
|
+
if(kerror)
|
|
186
|
+
rb_raise(cKadm5Exception, "krb5_init_context: %s", error_message(kerror));
|
|
187
|
+
|
|
188
|
+
ptr->rb_context = Qnil;
|
|
189
|
+
}
|
|
130
190
|
|
|
131
191
|
// The docs say I can use NULL to get the default, but reality appears to be otherwise.
|
|
132
192
|
if(RTEST(v_keytab)){
|
|
@@ -176,8 +236,31 @@ static VALUE rkadm5_initialize(VALUE self, VALUE v_opts){
|
|
|
176
236
|
if(kerror)
|
|
177
237
|
rb_raise(cKadm5Exception, "kadm5_init_with_skey: %s", error_message(kerror));
|
|
178
238
|
}
|
|
179
|
-
else{
|
|
180
|
-
|
|
239
|
+
else if(RTEST(v_ccache)){
|
|
240
|
+
RUBY_KRB5_CCACHE* cc_ptr;
|
|
241
|
+
|
|
242
|
+
if(!rb_obj_is_kind_of(v_ccache, cKrb5CCache))
|
|
243
|
+
rb_raise(rb_eTypeError, "ccache must be a Kerberos::Krb5::CredentialsCache object");
|
|
244
|
+
|
|
245
|
+
TypedData_Get_Struct(v_ccache, RUBY_KRB5_CCACHE, &rkrb5_ccache_data_type, cc_ptr);
|
|
246
|
+
|
|
247
|
+
if(!cc_ptr->ccache)
|
|
248
|
+
rb_raise(cKrb5Exception, "credentials cache is closed or destroyed");
|
|
249
|
+
|
|
250
|
+
kerror = kadm5_init_with_creds(
|
|
251
|
+
ptr->ctx,
|
|
252
|
+
user,
|
|
253
|
+
cc_ptr->ccache,
|
|
254
|
+
service,
|
|
255
|
+
NULL,
|
|
256
|
+
KADM5_STRUCT_VERSION,
|
|
257
|
+
KADM5_API_VERSION_3,
|
|
258
|
+
ptr->db_args,
|
|
259
|
+
&ptr->handle
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
if(kerror)
|
|
263
|
+
rb_raise(cKadm5Exception, "kadm5_init_with_creds: %s", error_message(kerror));
|
|
181
264
|
}
|
|
182
265
|
|
|
183
266
|
if(rb_block_given_p()){
|
|
@@ -281,36 +364,65 @@ static VALUE rkadm5_set_pwexpire(VALUE self, VALUE v_user, VALUE v_pwexpire){
|
|
|
281
364
|
|
|
282
365
|
/*
|
|
283
366
|
* call-seq:
|
|
284
|
-
* kadm5.create_principal(name
|
|
285
|
-
* kadm5.create_principal(principal)
|
|
367
|
+
* kadm5.create_principal(name:, password:, db_args: nil)
|
|
368
|
+
* kadm5.create_principal(principal:, password:, db_args: nil)
|
|
369
|
+
*
|
|
370
|
+
* Creates a new principal with an initial password of +password+.
|
|
371
|
+
*
|
|
372
|
+
* The principal may be specified either as a +name+ string or as a
|
|
373
|
+
* +principal+ object (a Kerberos::Krb5::Principal). When a Principal
|
|
374
|
+
* object is provided, any non-nil writable attributes on that object
|
|
375
|
+
* are forwarded to the KDC:
|
|
376
|
+
*
|
|
377
|
+
* * +policy+
|
|
378
|
+
* * +expire_time+
|
|
379
|
+
* * +password_expiration+
|
|
380
|
+
* * +max_life+
|
|
381
|
+
* * +max_renewable_life+
|
|
382
|
+
* * +attributes+
|
|
286
383
|
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
* in the add_principal section.
|
|
291
|
-
*--
|
|
292
|
-
* TODO: Allow a Principal object to be passed in as an argument.
|
|
384
|
+
* +db_args+ is an optional string or array of strings containing options
|
|
385
|
+
* that are usually passed to add_principal with the -x option. For a
|
|
386
|
+
* list of options, see the kadmin manpage, in the add_principal section.
|
|
293
387
|
*/
|
|
294
388
|
static VALUE rkadm5_create_principal(int argc, VALUE* argv, VALUE self){
|
|
295
389
|
RUBY_KADM5* ptr;
|
|
296
|
-
char* user;
|
|
297
390
|
char* pass;
|
|
298
391
|
char** db_args;
|
|
299
392
|
int mask;
|
|
300
393
|
kadm5_principal_ent_rec princ;
|
|
301
394
|
krb5_error_code kerror;
|
|
302
|
-
VALUE
|
|
395
|
+
VALUE v_opts, v_name, v_principal, v_pass, v_db_args;
|
|
396
|
+
ID kw_table[4] = { rb_intern("name"), rb_intern("principal"), rb_intern("password"), rb_intern("db_args") };
|
|
397
|
+
VALUE kw_vals[4];
|
|
303
398
|
|
|
304
399
|
TypedData_Get_Struct(self, RUBY_KADM5, &rkadm5_data_type, ptr);
|
|
305
400
|
|
|
306
|
-
rb_scan_args(argc, argv, "
|
|
307
|
-
|
|
401
|
+
rb_scan_args(argc, argv, "0:", &v_opts);
|
|
402
|
+
|
|
403
|
+
if(NIL_P(v_opts))
|
|
404
|
+
v_opts = rb_hash_new();
|
|
405
|
+
|
|
406
|
+
rb_get_kwargs(v_opts, kw_table, 0, 4, kw_vals);
|
|
407
|
+
v_name = kw_vals[0] == Qundef ? Qnil : kw_vals[0];
|
|
408
|
+
v_principal = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
|
|
409
|
+
v_pass = kw_vals[2] == Qundef ? Qnil : kw_vals[2];
|
|
410
|
+
v_db_args = kw_vals[3] == Qundef ? Qnil : kw_vals[3];
|
|
411
|
+
|
|
412
|
+
if(NIL_P(v_pass))
|
|
413
|
+
rb_raise(rb_eArgError, "password: is required");
|
|
414
|
+
|
|
308
415
|
Check_Type(v_pass, T_STRING);
|
|
309
416
|
|
|
417
|
+
if(NIL_P(v_name) && NIL_P(v_principal))
|
|
418
|
+
rb_raise(rb_eArgError, "name: or principal: is required");
|
|
419
|
+
|
|
420
|
+
if(RTEST(v_name) && RTEST(v_principal))
|
|
421
|
+
rb_raise(rb_eArgError, "name: and principal: are mutually exclusive");
|
|
422
|
+
|
|
310
423
|
memset(&princ, 0, sizeof(princ));
|
|
311
424
|
|
|
312
425
|
mask = KADM5_PRINCIPAL | KADM5_TL_DATA;
|
|
313
|
-
user = StringValueCStr(v_user);
|
|
314
426
|
pass = StringValueCStr(v_pass);
|
|
315
427
|
|
|
316
428
|
db_args = parse_db_args(v_db_args);
|
|
@@ -320,11 +432,80 @@ static VALUE rkadm5_create_principal(int argc, VALUE* argv, VALUE self){
|
|
|
320
432
|
if(!ptr->ctx)
|
|
321
433
|
rb_raise(cKadm5Exception, "no context has been established");
|
|
322
434
|
|
|
323
|
-
|
|
435
|
+
// Determine the principal name and populate mask from the principal object
|
|
436
|
+
if(RTEST(v_principal)){
|
|
437
|
+
VALUE v_princ_name, v_policy, v_expire, v_pw_expire, v_max_life, v_max_renew, v_attrs;
|
|
324
438
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
439
|
+
if(!rb_obj_is_kind_of(v_principal, cKrb5Principal))
|
|
440
|
+
rb_raise(rb_eTypeError, "principal: must be a Kerberos::Krb5::Principal object");
|
|
441
|
+
|
|
442
|
+
v_princ_name = rb_iv_get(v_principal, "@principal");
|
|
443
|
+
|
|
444
|
+
if(NIL_P(v_princ_name))
|
|
445
|
+
rb_raise(rb_eArgError, "principal object has no name set");
|
|
446
|
+
|
|
447
|
+
Check_Type(v_princ_name, T_STRING);
|
|
448
|
+
|
|
449
|
+
kerror = krb5_parse_name(ptr->ctx, StringValueCStr(v_princ_name), &princ.principal);
|
|
450
|
+
|
|
451
|
+
if(kerror){
|
|
452
|
+
free_tl_data(princ.tl_data);
|
|
453
|
+
rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Forward optional attributes from the Principal object
|
|
457
|
+
v_policy = rb_iv_get(v_principal, "@policy");
|
|
458
|
+
|
|
459
|
+
if(RTEST(v_policy)){
|
|
460
|
+
Check_Type(v_policy, T_STRING);
|
|
461
|
+
princ.policy = StringValueCStr(v_policy);
|
|
462
|
+
mask |= KADM5_POLICY;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
v_expire = rb_iv_get(v_principal, "@expire_time");
|
|
466
|
+
|
|
467
|
+
if(RTEST(v_expire)){
|
|
468
|
+
princ.princ_expire_time = (krb5_timestamp)NUM2LONG(rb_funcall(v_expire, rb_intern("to_i"), 0));
|
|
469
|
+
mask |= KADM5_PRINC_EXPIRE_TIME;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
v_pw_expire = rb_iv_get(v_principal, "@password_expiration");
|
|
473
|
+
|
|
474
|
+
if(RTEST(v_pw_expire)){
|
|
475
|
+
princ.pw_expiration = (krb5_timestamp)NUM2LONG(rb_funcall(v_pw_expire, rb_intern("to_i"), 0));
|
|
476
|
+
mask |= KADM5_PW_EXPIRATION;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
v_max_life = rb_iv_get(v_principal, "@max_life");
|
|
480
|
+
|
|
481
|
+
if(RTEST(v_max_life)){
|
|
482
|
+
princ.max_life = NUM2LONG(v_max_life);
|
|
483
|
+
mask |= KADM5_MAX_LIFE;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
v_max_renew = rb_iv_get(v_principal, "@max_renewable_life");
|
|
487
|
+
|
|
488
|
+
if(RTEST(v_max_renew)){
|
|
489
|
+
princ.max_renewable_life = NUM2LONG(v_max_renew);
|
|
490
|
+
mask |= KADM5_MAX_RLIFE;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
v_attrs = rb_iv_get(v_principal, "@attributes");
|
|
494
|
+
|
|
495
|
+
if(RTEST(v_attrs)){
|
|
496
|
+
princ.attributes = NUM2LONG(v_attrs);
|
|
497
|
+
mask |= KADM5_ATTRIBUTES;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
else{
|
|
501
|
+
Check_Type(v_name, T_STRING);
|
|
502
|
+
|
|
503
|
+
kerror = krb5_parse_name(ptr->ctx, StringValueCStr(v_name), &princ.principal);
|
|
504
|
+
|
|
505
|
+
if(kerror){
|
|
506
|
+
free_tl_data(princ.tl_data);
|
|
507
|
+
rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
|
|
508
|
+
}
|
|
328
509
|
}
|
|
329
510
|
|
|
330
511
|
kerror = kadm5_create_principal(ptr->handle, &princ, mask, pass);
|
|
@@ -396,7 +577,7 @@ static VALUE rkadm5_close(VALUE self){
|
|
|
396
577
|
if(ptr->princ)
|
|
397
578
|
krb5_free_principal(ptr->ctx, ptr->princ);
|
|
398
579
|
|
|
399
|
-
if(ptr->ctx)
|
|
580
|
+
if(ptr->ctx && ptr->rb_context == Qnil)
|
|
400
581
|
krb5_free_context(ptr->ctx);
|
|
401
582
|
|
|
402
583
|
free_db_args(ptr->db_args);
|
|
@@ -405,6 +586,7 @@ static VALUE rkadm5_close(VALUE self){
|
|
|
405
586
|
ptr->ctx = NULL;
|
|
406
587
|
ptr->princ = NULL;
|
|
407
588
|
ptr->handle = NULL;
|
|
589
|
+
ptr->rb_context = Qnil;
|
|
408
590
|
|
|
409
591
|
return self;
|
|
410
592
|
}
|
|
@@ -413,11 +595,11 @@ static VALUE rkadm5_close(VALUE self){
|
|
|
413
595
|
static VALUE create_principal_from_entry(VALUE v_name, RUBY_KADM5* ptr, kadm5_principal_ent_rec* ent){
|
|
414
596
|
krb5_error_code kerror;
|
|
415
597
|
VALUE v_principal;
|
|
416
|
-
VALUE
|
|
598
|
+
VALUE v_opts = rb_hash_new();
|
|
417
599
|
|
|
418
|
-
|
|
600
|
+
rb_hash_aset(v_opts, ID2SYM(rb_intern("name")), v_name);
|
|
419
601
|
|
|
420
|
-
v_principal =
|
|
602
|
+
v_principal = rb_class_new_instance_kw(1, &v_opts, cKrb5Principal, RB_PASS_KEYWORDS);
|
|
421
603
|
|
|
422
604
|
rb_iv_set(v_principal, "@attributes", LONG2FIX(ent->attributes));
|
|
423
605
|
rb_iv_set(v_principal, "@aux_attributes", INT2FIX(ent->aux_attributes));
|
|
@@ -596,28 +778,39 @@ static VALUE rkadm5_get_principal(VALUE self, VALUE v_user){
|
|
|
596
778
|
* Example:
|
|
597
779
|
*
|
|
598
780
|
* # Using a Policy object
|
|
599
|
-
* policy = Kerberos::Kadm5::Policy.new(:
|
|
781
|
+
* policy = Kerberos::Kadm5::Policy.new(name: 'test', min_length: 5)
|
|
600
782
|
* kadm5.create_policy(policy)
|
|
601
783
|
*
|
|
602
|
-
* # Using
|
|
603
|
-
* kadm5.create_policy(:
|
|
784
|
+
* # Using keywords
|
|
785
|
+
* kadm5.create_policy(name: 'test', min_length: 5)
|
|
604
786
|
*/
|
|
605
|
-
static VALUE rkadm5_create_policy(VALUE
|
|
787
|
+
static VALUE rkadm5_create_policy(int argc, VALUE* argv, VALUE self){
|
|
606
788
|
RUBY_KADM5* ptr;
|
|
607
789
|
kadm5_ret_t kerror;
|
|
608
790
|
kadm5_policy_ent_rec ent;
|
|
609
791
|
long mask = KADM5_POLICY;
|
|
792
|
+
VALUE v_policy, v_kwargs;
|
|
610
793
|
VALUE v_name, v_min_classes, v_min_life, v_max_life, v_min_length, v_history_num;
|
|
611
794
|
|
|
612
795
|
TypedData_Get_Struct(self, RUBY_KADM5, &rkadm5_data_type, ptr);
|
|
613
796
|
|
|
614
|
-
|
|
615
|
-
|
|
797
|
+
rb_scan_args(argc, argv, "01:", &v_policy, &v_kwargs);
|
|
798
|
+
|
|
799
|
+
if(!NIL_P(v_kwargs)){
|
|
616
800
|
VALUE v_args[1];
|
|
617
|
-
|
|
618
|
-
|
|
801
|
+
if(!NIL_P(v_policy))
|
|
802
|
+
rb_raise(rb_eArgError, "provide a Policy object or keyword arguments, not both");
|
|
803
|
+
|
|
804
|
+
v_args[0] = v_kwargs;
|
|
805
|
+
v_policy = rb_class_new_instance_kw(1, v_args, cKadm5Policy, RB_PASS_KEYWORDS);
|
|
619
806
|
}
|
|
620
807
|
|
|
808
|
+
if(NIL_P(v_policy))
|
|
809
|
+
rb_raise(rb_eArgError, "a Policy object or policy keywords are required");
|
|
810
|
+
|
|
811
|
+
if(!rb_obj_is_kind_of(v_policy, cKadm5Policy))
|
|
812
|
+
rb_raise(rb_eTypeError, "expected a Kerberos::Kadm5::Policy object or policy keywords");
|
|
813
|
+
|
|
621
814
|
v_name = rb_iv_get(v_policy, "@policy");
|
|
622
815
|
v_min_classes = rb_iv_get(v_policy, "@min_classes");
|
|
623
816
|
v_min_length = rb_iv_get(v_policy, "@min_length");
|
|
@@ -725,16 +918,16 @@ static VALUE rkadm5_get_policy(VALUE self, VALUE v_name){
|
|
|
725
918
|
VALUE v_arg[1];
|
|
726
919
|
VALUE v_hash = rb_hash_new();
|
|
727
920
|
|
|
728
|
-
rb_hash_aset(v_hash,
|
|
729
|
-
rb_hash_aset(v_hash,
|
|
730
|
-
rb_hash_aset(v_hash,
|
|
731
|
-
rb_hash_aset(v_hash,
|
|
732
|
-
rb_hash_aset(v_hash,
|
|
733
|
-
rb_hash_aset(v_hash,
|
|
921
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("name")), rb_str_new2(ent.policy));
|
|
922
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("min_life")), LONG2FIX(ent.pw_min_life));
|
|
923
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("max_life")), LONG2FIX(ent.pw_max_life));
|
|
924
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("min_length")), LONG2FIX(ent.pw_min_length));
|
|
925
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("min_classes")), LONG2FIX(ent.pw_min_classes));
|
|
926
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("history_num")), LONG2FIX(ent.pw_history_num));
|
|
734
927
|
|
|
735
928
|
v_arg[0] = v_hash;
|
|
736
929
|
|
|
737
|
-
v_policy =
|
|
930
|
+
v_policy = rb_class_new_instance_kw(1, v_arg, cKadm5Policy, RB_PASS_KEYWORDS);
|
|
738
931
|
|
|
739
932
|
kadm5_free_policy_ent(ptr->handle, &ent);
|
|
740
933
|
}
|
|
@@ -782,16 +975,16 @@ static VALUE rkadm5_find_policy(VALUE self, VALUE v_name){
|
|
|
782
975
|
VALUE v_arg[1];
|
|
783
976
|
VALUE v_hash = rb_hash_new();
|
|
784
977
|
|
|
785
|
-
rb_hash_aset(v_hash,
|
|
786
|
-
rb_hash_aset(v_hash,
|
|
787
|
-
rb_hash_aset(v_hash,
|
|
788
|
-
rb_hash_aset(v_hash,
|
|
789
|
-
rb_hash_aset(v_hash,
|
|
790
|
-
rb_hash_aset(v_hash,
|
|
978
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("name")), rb_str_new2(ent.policy));
|
|
979
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("min_life")), LONG2FIX(ent.pw_min_life));
|
|
980
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("max_life")), LONG2FIX(ent.pw_max_life));
|
|
981
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("min_length")), LONG2FIX(ent.pw_min_length));
|
|
982
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("min_classes")), LONG2FIX(ent.pw_min_classes));
|
|
983
|
+
rb_hash_aset(v_hash, ID2SYM(rb_intern("history_num")), LONG2FIX(ent.pw_history_num));
|
|
791
984
|
|
|
792
985
|
v_arg[0] = v_hash;
|
|
793
986
|
|
|
794
|
-
v_policy =
|
|
987
|
+
v_policy = rb_class_new_instance_kw(1, v_arg, cKadm5Policy, RB_PASS_KEYWORDS);
|
|
795
988
|
|
|
796
989
|
kadm5_free_policy_ent(ptr->handle, &ent);
|
|
797
990
|
}
|
|
@@ -1137,12 +1330,12 @@ void Init_kadm5(void){
|
|
|
1137
1330
|
|
|
1138
1331
|
// Initialization Method
|
|
1139
1332
|
|
|
1140
|
-
rb_define_method(cKadm5, "initialize", rkadm5_initialize, 1);
|
|
1333
|
+
rb_define_method(cKadm5, "initialize", rkadm5_initialize, -1);
|
|
1141
1334
|
|
|
1142
1335
|
// Instance Methods
|
|
1143
1336
|
|
|
1144
1337
|
rb_define_method(cKadm5, "close", rkadm5_close, 0);
|
|
1145
|
-
rb_define_method(cKadm5, "create_policy", rkadm5_create_policy, 1);
|
|
1338
|
+
rb_define_method(cKadm5, "create_policy", rkadm5_create_policy, -1);
|
|
1146
1339
|
rb_define_method(cKadm5, "create_principal", rkadm5_create_principal, -1);
|
|
1147
1340
|
rb_define_method(cKadm5, "delete_policy", rkadm5_delete_policy, 1);
|
|
1148
1341
|
rb_define_method(cKadm5, "delete_principal", rkadm5_delete_principal, 1);
|