rkerberos 0.2.3 → 0.3.1
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 +30 -0
- data/EXAMPLES.md +1015 -0
- data/MANIFEST.md +17 -12
- data/README.md +17 -6
- data/ext/rkerberos/ccache.c +99 -26
- data/ext/rkerberos/config.c +62 -10
- data/ext/rkerberos/context.c +132 -14
- data/ext/rkerberos/kadm5.c +332 -116
- data/ext/rkerberos/keytab.c +230 -79
- data/ext/rkerberos/policy.c +25 -23
- data/ext/rkerberos/principal.c +139 -11
- data/ext/rkerberos/rkerberos.c +269 -52
- data/ext/rkerberos/rkerberos.h +14 -0
- data/rkerberos.gemspec +10 -7
- data/spec/config_spec.rb +41 -0
- data/spec/context_spec.rb +96 -0
- data/spec/credentials_cache_spec.rb +82 -26
- data/spec/kadm5_spec.rb +319 -5
- data/spec/krb5_keytab_spec.rb +275 -20
- data/spec/krb5_spec.rb +186 -21
- data/spec/policy_spec.rb +4 -0
- data/spec/principal_spec.rb +116 -10
- metadata +9 -8
data/ext/rkerberos/keytab.c
CHANGED
|
@@ -4,6 +4,13 @@ VALUE cKrb5Keytab, cKrb5KeytabException;
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// TypedData functions for RUBY_KRB5_KEYTAB
|
|
7
|
+
static void rkrb5_keytab_typed_mark(void *ptr) {
|
|
8
|
+
if (!ptr) return;
|
|
9
|
+
RUBY_KRB5_KEYTAB *kt = (RUBY_KRB5_KEYTAB *)ptr;
|
|
10
|
+
if (kt->rb_context != Qnil)
|
|
11
|
+
rb_gc_mark(kt->rb_context);
|
|
12
|
+
}
|
|
13
|
+
|
|
7
14
|
void rkrb5_keytab_typed_free(void *ptr) {
|
|
8
15
|
if (!ptr) return;
|
|
9
16
|
RUBY_KRB5_KEYTAB *kt = (RUBY_KRB5_KEYTAB *)ptr;
|
|
@@ -11,8 +18,10 @@ void rkrb5_keytab_typed_free(void *ptr) {
|
|
|
11
18
|
krb5_kt_close(kt->ctx, kt->keytab);
|
|
12
19
|
if (kt->ctx)
|
|
13
20
|
krb5_free_cred_contents(kt->ctx, &kt->creds);
|
|
14
|
-
if (kt->ctx)
|
|
21
|
+
if (kt->ctx && kt->rb_context == Qnil)
|
|
15
22
|
krb5_free_context(kt->ctx);
|
|
23
|
+
else if (kt->rb_context != Qnil)
|
|
24
|
+
rkrb5_context_release(kt->rb_context);
|
|
16
25
|
free(kt);
|
|
17
26
|
}
|
|
18
27
|
|
|
@@ -23,13 +32,14 @@ size_t rkrb5_keytab_typed_size(const void *ptr) {
|
|
|
23
32
|
// Must NOT be static so it is exported
|
|
24
33
|
const rb_data_type_t rkrb5_keytab_data_type = {
|
|
25
34
|
"RUBY_KRB5_KEYTAB",
|
|
26
|
-
{
|
|
35
|
+
{rkrb5_keytab_typed_mark, rkrb5_keytab_typed_free, rkrb5_keytab_typed_size,},
|
|
27
36
|
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
|
|
28
37
|
};
|
|
29
38
|
|
|
30
39
|
VALUE rkrb5_keytab_allocate(VALUE klass){
|
|
31
40
|
RUBY_KRB5_KEYTAB* ptr = ALLOC(RUBY_KRB5_KEYTAB);
|
|
32
41
|
memset(ptr, 0, sizeof(RUBY_KRB5_KEYTAB));
|
|
42
|
+
ptr->rb_context = Qnil;
|
|
33
43
|
return TypedData_Wrap_Struct(klass, &rkrb5_keytab_data_type, ptr);
|
|
34
44
|
}
|
|
35
45
|
|
|
@@ -46,7 +56,7 @@ typedef struct {
|
|
|
46
56
|
static VALUE rkrb5_keytab_each_body(VALUE arg){
|
|
47
57
|
keytab_each_arg* ea = (keytab_each_arg*)arg;
|
|
48
58
|
krb5_keytab_entry entry;
|
|
49
|
-
krb5_error_code kerror;
|
|
59
|
+
krb5_error_code kerror, iteration_error;
|
|
50
60
|
char* principal;
|
|
51
61
|
VALUE v_kt_entry;
|
|
52
62
|
|
|
@@ -71,9 +81,13 @@ static VALUE rkrb5_keytab_each_body(VALUE arg){
|
|
|
71
81
|
rb_yield(v_kt_entry);
|
|
72
82
|
}
|
|
73
83
|
|
|
74
|
-
|
|
84
|
+
iteration_error = kerror;
|
|
75
85
|
|
|
76
86
|
kerror = krb5_kt_end_seq_get(ea->ctx, ea->keytab, &ea->cursor);
|
|
87
|
+
ea->cursor_active = 0;
|
|
88
|
+
|
|
89
|
+
if(iteration_error != KRB5_KT_END)
|
|
90
|
+
rb_raise(cKrb5Exception, "krb5_kt_next_entry: %s", error_message(iteration_error));
|
|
77
91
|
|
|
78
92
|
if(kerror)
|
|
79
93
|
rb_raise(cKrb5Exception, "krb5_kt_end_seq_get: %s", error_message(kerror));
|
|
@@ -106,6 +120,9 @@ static VALUE rkrb5_keytab_each(VALUE self){
|
|
|
106
120
|
|
|
107
121
|
TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
|
|
108
122
|
|
|
123
|
+
if(!ptr->ctx || !ptr->keytab)
|
|
124
|
+
rb_raise(cKrb5Exception, "keytab is closed");
|
|
125
|
+
|
|
109
126
|
ea.ctx = ptr->ctx;
|
|
110
127
|
ea.keytab = ptr->keytab;
|
|
111
128
|
|
|
@@ -136,6 +153,9 @@ static VALUE rkrb5_keytab_default_name(VALUE self){
|
|
|
136
153
|
|
|
137
154
|
TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
|
|
138
155
|
|
|
156
|
+
if(!ptr->ctx)
|
|
157
|
+
rb_raise(cKrb5Exception, "no context has been established");
|
|
158
|
+
|
|
139
159
|
kerror = krb5_kt_default_name(ptr->ctx, default_name, MAX_KEYTAB_NAME_LEN);
|
|
140
160
|
|
|
141
161
|
if(kerror)
|
|
@@ -167,109 +187,192 @@ static VALUE rkrb5_keytab_close(VALUE self){
|
|
|
167
187
|
if(ptr->ctx)
|
|
168
188
|
krb5_free_cred_contents(ptr->ctx, &ptr->creds);
|
|
169
189
|
|
|
170
|
-
if(ptr->ctx)
|
|
190
|
+
if(ptr->ctx && ptr->rb_context == Qnil)
|
|
171
191
|
krb5_free_context(ptr->ctx);
|
|
192
|
+
else if(ptr->rb_context != Qnil)
|
|
193
|
+
rkrb5_context_release(ptr->rb_context);
|
|
172
194
|
|
|
173
195
|
ptr->ctx = NULL;
|
|
196
|
+
ptr->rb_context = Qnil;
|
|
174
197
|
|
|
175
198
|
return Qtrue;
|
|
176
199
|
}
|
|
177
200
|
|
|
178
201
|
/*
|
|
179
|
-
|
|
202
|
+
* call-seq:
|
|
203
|
+
* keytab.add_entry(principal:, password:, vno: 1, enctype: 18)
|
|
204
|
+
*
|
|
205
|
+
* Add a new entry to the keytab for the given +principal+ string.
|
|
206
|
+
*
|
|
207
|
+
* A key is derived from +password+ (and the principal-based salt) using
|
|
208
|
+
* +krb5_c_string_to_key+, so the resulting key will match what the KDC
|
|
209
|
+
* would generate for the same password.
|
|
210
|
+
*
|
|
211
|
+
* Options:
|
|
212
|
+
* principal:: A Kerberos principal name string (required).
|
|
213
|
+
* password:: The password used to derive the key (required).
|
|
214
|
+
* vno:: Key version number (default 1).
|
|
215
|
+
* enctype:: Encryption type as an integer (default 18,
|
|
216
|
+
* aes256-cts-hmac-sha1-96).
|
|
217
|
+
*
|
|
218
|
+
* Returns +self+.
|
|
219
|
+
*/
|
|
220
|
+
static VALUE rkrb5_keytab_add_entry(int argc, VALUE* argv, VALUE self){
|
|
180
221
|
RUBY_KRB5_KEYTAB* ptr;
|
|
181
222
|
krb5_error_code kerror;
|
|
182
223
|
krb5_keytab_entry entry;
|
|
183
|
-
|
|
184
|
-
VALUE
|
|
224
|
+
krb5_data pwd_data, salt;
|
|
225
|
+
VALUE v_opts, v_principal, v_password, v_vno, v_enctype;
|
|
226
|
+
ID kw_table[4] = { rb_intern("principal"), rb_intern("password"), rb_intern("vno"), rb_intern("enctype") };
|
|
227
|
+
VALUE kw_vals[4];
|
|
185
228
|
|
|
186
229
|
TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
|
|
187
230
|
|
|
188
|
-
|
|
231
|
+
if(!ptr->ctx)
|
|
232
|
+
rb_raise(cKrb5Exception, "no context has been established");
|
|
189
233
|
|
|
190
|
-
|
|
234
|
+
rb_scan_args(argc, argv, "0:", &v_opts);
|
|
191
235
|
|
|
192
|
-
|
|
236
|
+
if(NIL_P(v_opts))
|
|
237
|
+
v_opts = rb_hash_new();
|
|
193
238
|
|
|
194
|
-
|
|
195
|
-
|
|
239
|
+
rb_get_kwargs(v_opts, kw_table, 2, 2, kw_vals);
|
|
240
|
+
v_principal = kw_vals[0];
|
|
241
|
+
v_password = kw_vals[1];
|
|
242
|
+
v_vno = kw_vals[2] == Qundef ? Qnil : kw_vals[2];
|
|
243
|
+
v_enctype = kw_vals[3] == Qundef ? Qnil : kw_vals[3];
|
|
244
|
+
|
|
245
|
+
Check_Type(v_principal, T_STRING);
|
|
246
|
+
Check_Type(v_password, T_STRING);
|
|
247
|
+
|
|
248
|
+
memset(&entry, 0, sizeof(entry));
|
|
196
249
|
|
|
197
|
-
|
|
250
|
+
entry.vno = NIL_P(v_vno) ? 1 : NUM2INT(v_vno);
|
|
251
|
+
entry.key.enctype = NIL_P(v_enctype) ? ENCTYPE_AES256_CTS_HMAC_SHA1_96 : NUM2INT(v_enctype);
|
|
252
|
+
|
|
253
|
+
kerror = krb5_parse_name(ptr->ctx, StringValueCStr(v_principal), &entry.principal);
|
|
198
254
|
|
|
199
255
|
if(kerror)
|
|
200
256
|
rb_raise(cKrb5Exception, "krb5_parse_name: %s", error_message(kerror));
|
|
201
257
|
|
|
202
|
-
|
|
203
|
-
entry.vno = 0;
|
|
204
|
-
else
|
|
205
|
-
entry.vno = NUM2INT(v_vno);
|
|
258
|
+
entry.timestamp = time(NULL);
|
|
206
259
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
else
|
|
210
|
-
entry.key.enctype = NUM2INT(v_enctype);
|
|
260
|
+
// Derive the salt from the principal
|
|
261
|
+
kerror = krb5_principal2salt(ptr->ctx, entry.principal, &salt);
|
|
211
262
|
|
|
212
|
-
|
|
263
|
+
if(kerror){
|
|
264
|
+
krb5_free_principal(ptr->ctx, entry.principal);
|
|
265
|
+
rb_raise(cKrb5Exception, "krb5_principal2salt: %s", error_message(kerror));
|
|
266
|
+
}
|
|
213
267
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
);
|
|
268
|
+
// Derive key from password + salt
|
|
269
|
+
pwd_data.data = StringValuePtr(v_password);
|
|
270
|
+
pwd_data.length = (unsigned int)RSTRING_LEN(v_password);
|
|
271
|
+
|
|
272
|
+
kerror = krb5_c_string_to_key(ptr->ctx, entry.key.enctype, &pwd_data, &salt, &entry.key);
|
|
273
|
+
|
|
274
|
+
krb5_free_data_contents(ptr->ctx, &salt);
|
|
275
|
+
|
|
276
|
+
if(kerror){
|
|
277
|
+
krb5_free_principal(ptr->ctx, entry.principal);
|
|
278
|
+
rb_raise(cKrb5Exception, "krb5_c_string_to_key: %s", error_message(kerror));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
kerror = krb5_kt_add_entry(ptr->ctx, ptr->keytab, &entry);
|
|
282
|
+
|
|
283
|
+
krb5_free_keyblock_contents(ptr->ctx, &entry.key);
|
|
284
|
+
krb5_free_principal(ptr->ctx, entry.principal);
|
|
219
285
|
|
|
220
286
|
if(kerror)
|
|
221
|
-
rb_raise(cKrb5KeytabException, "
|
|
287
|
+
rb_raise(cKrb5KeytabException, "krb5_kt_add_entry: %s", error_message(kerror));
|
|
222
288
|
|
|
223
289
|
return self;
|
|
224
290
|
}
|
|
225
291
|
|
|
226
|
-
|
|
292
|
+
/*
|
|
293
|
+
* call-seq:
|
|
294
|
+
* keytab.remove_entry(principal:, vno: 0, enctype: 0)
|
|
295
|
+
*
|
|
296
|
+
* Remove entries from the keytab that match the given +principal+ string,
|
|
297
|
+
* +vno+, and +enctype+.
|
|
298
|
+
*
|
|
299
|
+
* A +vno+ of 0 (the default) matches any version number.
|
|
300
|
+
* An +enctype+ of 0 (the default) matches any encryption type.
|
|
301
|
+
*
|
|
302
|
+
* When both +vno+ and +enctype+ are 0 (the defaults), all entries for
|
|
303
|
+
* the +principal+ are removed.
|
|
304
|
+
*
|
|
305
|
+
* Options:
|
|
306
|
+
* principal:: A Kerberos principal name string (required).
|
|
307
|
+
* vno:: Key version number to match, 0 for any (default 0).
|
|
308
|
+
* enctype:: Encryption type to match, 0 for any (default 0).
|
|
309
|
+
*
|
|
310
|
+
* Returns +self+.
|
|
311
|
+
*/
|
|
312
|
+
static VALUE rkrb5_keytab_remove_entry(int argc, VALUE* argv, VALUE self){
|
|
227
313
|
RUBY_KRB5_KEYTAB* ptr;
|
|
228
314
|
krb5_error_code kerror;
|
|
229
|
-
krb5_keytab_entry
|
|
230
|
-
|
|
231
|
-
|
|
315
|
+
krb5_keytab_entry found_entry;
|
|
316
|
+
krb5_principal match_princ;
|
|
317
|
+
krb5_kvno match_vno;
|
|
318
|
+
krb5_enctype match_enctype;
|
|
319
|
+
int removed = 0;
|
|
320
|
+
VALUE v_opts, v_principal, v_vno, v_enctype;
|
|
321
|
+
ID kw_table[3] = { rb_intern("principal"), rb_intern("vno"), rb_intern("enctype") };
|
|
322
|
+
VALUE kw_vals[3];
|
|
232
323
|
|
|
233
324
|
TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
|
|
234
325
|
|
|
235
|
-
|
|
326
|
+
if(!ptr->ctx)
|
|
327
|
+
rb_raise(cKrb5Exception, "no context has been established");
|
|
236
328
|
|
|
237
|
-
|
|
329
|
+
rb_scan_args(argc, argv, "0:", &v_opts);
|
|
238
330
|
|
|
239
|
-
|
|
331
|
+
if(NIL_P(v_opts))
|
|
332
|
+
v_opts = rb_hash_new();
|
|
240
333
|
|
|
241
|
-
|
|
242
|
-
|
|
334
|
+
rb_get_kwargs(v_opts, kw_table, 1, 2, kw_vals);
|
|
335
|
+
v_principal = kw_vals[0];
|
|
336
|
+
v_vno = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
|
|
337
|
+
v_enctype = kw_vals[2] == Qundef ? Qnil : kw_vals[2];
|
|
338
|
+
|
|
339
|
+
Check_Type(v_principal, T_STRING);
|
|
243
340
|
|
|
244
|
-
|
|
341
|
+
match_vno = NIL_P(v_vno) ? 0 : NUM2INT(v_vno);
|
|
342
|
+
match_enctype = NIL_P(v_enctype) ? 0 : NUM2INT(v_enctype);
|
|
343
|
+
|
|
344
|
+
kerror = krb5_parse_name(ptr->ctx, StringValueCStr(v_principal), &match_princ);
|
|
245
345
|
|
|
246
346
|
if(kerror)
|
|
247
347
|
rb_raise(cKrb5Exception, "krb5_parse_name: %s", error_message(kerror));
|
|
248
348
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
entry.key.enctype = NUM2INT(v_enctype);
|
|
349
|
+
// Retrieve the full entry via krb5_kt_get_entry and then pass the
|
|
350
|
+
// complete struct to krb5_kt_remove_entry so all fields match exactly.
|
|
351
|
+
// Loop to remove every matching entry when vno/enctype are wildcards.
|
|
352
|
+
while(1){
|
|
353
|
+
kerror = krb5_kt_get_entry(
|
|
354
|
+
ptr->ctx, ptr->keytab, match_princ,
|
|
355
|
+
match_vno, match_enctype, &found_entry
|
|
356
|
+
);
|
|
258
357
|
|
|
259
|
-
|
|
358
|
+
if(kerror){
|
|
359
|
+
krb5_free_principal(ptr->ctx, match_princ);
|
|
360
|
+
if(removed)
|
|
361
|
+
return self;
|
|
362
|
+
rb_raise(cKrb5KeytabException, "krb5_kt_remove_entry: %s", error_message(kerror));
|
|
363
|
+
}
|
|
260
364
|
|
|
261
|
-
|
|
262
|
-
ptr->ctx,
|
|
263
|
-
ptr->keytab,
|
|
264
|
-
&entry
|
|
265
|
-
);
|
|
365
|
+
kerror = krb5_kt_remove_entry(ptr->ctx, ptr->keytab, &found_entry);
|
|
366
|
+
krb5_kt_free_entry(ptr->ctx, &found_entry);
|
|
266
367
|
|
|
267
|
-
|
|
268
|
-
|
|
368
|
+
if(kerror){
|
|
369
|
+
krb5_free_principal(ptr->ctx, match_princ);
|
|
370
|
+
rb_raise(cKrb5KeytabException, "krb5_kt_remove_entry: %s", error_message(kerror));
|
|
371
|
+
}
|
|
269
372
|
|
|
270
|
-
|
|
373
|
+
removed = 1;
|
|
374
|
+
}
|
|
271
375
|
}
|
|
272
|
-
*/
|
|
273
376
|
|
|
274
377
|
/*
|
|
275
378
|
* call-seq:
|
|
@@ -295,26 +398,22 @@ static VALUE rkrb5_keytab_get_entry(int argc, VALUE* argv, VALUE self){
|
|
|
295
398
|
|
|
296
399
|
TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
|
|
297
400
|
|
|
401
|
+
if(!ptr->ctx || !ptr->keytab)
|
|
402
|
+
rb_raise(cKrb5Exception, "keytab is closed");
|
|
403
|
+
|
|
298
404
|
rb_scan_args(argc, argv, "12", &v_principal, &v_vno, &v_enctype);
|
|
299
405
|
|
|
300
406
|
Check_Type(v_principal, T_STRING);
|
|
301
407
|
name = StringValueCStr(v_principal);
|
|
302
408
|
|
|
409
|
+
vno = NIL_P(v_vno) ? 0 : NUM2INT(v_vno);
|
|
410
|
+
enctype = NIL_P(v_enctype) ? 0 : NUM2INT(v_enctype);
|
|
411
|
+
|
|
303
412
|
kerror = krb5_parse_name(ptr->ctx, name, &principal);
|
|
304
413
|
|
|
305
414
|
if(kerror)
|
|
306
415
|
rb_raise(cKrb5Exception, "krb5_parse_name: %s", error_message(kerror));
|
|
307
416
|
|
|
308
|
-
if(NIL_P(v_vno))
|
|
309
|
-
vno = 0;
|
|
310
|
-
else
|
|
311
|
-
vno = NUM2INT(v_vno);
|
|
312
|
-
|
|
313
|
-
if(NIL_P(v_enctype))
|
|
314
|
-
enctype = 0;
|
|
315
|
-
else
|
|
316
|
-
enctype = NUM2INT(v_enctype);
|
|
317
|
-
|
|
318
417
|
kerror = krb5_kt_get_entry(
|
|
319
418
|
ptr->ctx,
|
|
320
419
|
ptr->keytab,
|
|
@@ -430,7 +529,7 @@ static VALUE rkrb5_keytab_dup(VALUE self){
|
|
|
430
529
|
|
|
431
530
|
/*
|
|
432
531
|
* call-seq:
|
|
433
|
-
* Kerberos::Krb5::Keytab.new(name
|
|
532
|
+
* Kerberos::Krb5::Keytab.new(name: nil, context: nil)
|
|
434
533
|
*
|
|
435
534
|
* Creates and returns a new Kerberos::Krb5::Keytab object. This initializes
|
|
436
535
|
* the context and keytab for future method calls on that object.
|
|
@@ -439,28 +538,56 @@ static VALUE rkrb5_keytab_dup(VALUE self){
|
|
|
439
538
|
* name is used. If a +name+ is provided it must be in the form 'type:residual'
|
|
440
539
|
* where 'type' is a type known to the Kerberos library.
|
|
441
540
|
*
|
|
541
|
+
* An optional +context+ keyword argument may be provided. If given, it must
|
|
542
|
+
* be a Kerberos::Krb5::Context object and will be used instead of creating
|
|
543
|
+
* a new context via krb5_init_context.
|
|
544
|
+
*
|
|
442
545
|
* Examples:
|
|
443
546
|
*
|
|
444
547
|
* # Using the default keytab
|
|
445
548
|
* keytab = Kerberos::Krb5::Keytab.new
|
|
446
549
|
*
|
|
447
550
|
* # Using an explicit keytab
|
|
448
|
-
* keytab = Kerberos::Krb5::Keytab.new('FILE:/etc/krb5.keytab')
|
|
551
|
+
* keytab = Kerberos::Krb5::Keytab.new(name: 'FILE:/etc/krb5.keytab')
|
|
552
|
+
*
|
|
553
|
+
* # Using a custom context
|
|
554
|
+
* ctx = Kerberos::Krb5::Context.new
|
|
555
|
+
* keytab = Kerberos::Krb5::Keytab.new(name: 'FILE:/etc/krb5.keytab', context: ctx)
|
|
449
556
|
*/
|
|
450
557
|
static VALUE rkrb5_keytab_initialize(int argc, VALUE* argv, VALUE self){
|
|
451
558
|
RUBY_KRB5_KEYTAB* ptr;
|
|
452
559
|
krb5_error_code kerror;
|
|
453
560
|
char keytab_name[MAX_KEYTAB_NAME_LEN];
|
|
454
561
|
VALUE v_keytab_name = Qnil;
|
|
562
|
+
VALUE v_opts = Qnil;
|
|
563
|
+
VALUE v_context = Qnil;
|
|
564
|
+
ID kw_table[2] = { rb_intern("name"), rb_intern("context") };
|
|
565
|
+
VALUE kw_vals[2];
|
|
455
566
|
|
|
456
567
|
TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
|
|
457
568
|
|
|
458
|
-
rb_scan_args(argc, argv, "
|
|
569
|
+
rb_scan_args(argc, argv, "0:", &v_opts);
|
|
459
570
|
|
|
460
|
-
|
|
571
|
+
if(NIL_P(v_opts))
|
|
572
|
+
v_opts = rb_hash_new();
|
|
461
573
|
|
|
462
|
-
|
|
463
|
-
|
|
574
|
+
rb_get_kwargs(v_opts, kw_table, 0, 2, kw_vals);
|
|
575
|
+
v_keytab_name = kw_vals[0] == Qundef ? Qnil : kw_vals[0];
|
|
576
|
+
v_context = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
|
|
577
|
+
|
|
578
|
+
// Initialize or borrow the context
|
|
579
|
+
if(!NIL_P(v_context)){
|
|
580
|
+
ptr->ctx = rkrb5_context_borrow(v_context);
|
|
581
|
+
ptr->rb_context = v_context;
|
|
582
|
+
}
|
|
583
|
+
else{
|
|
584
|
+
kerror = krb5_init_context(&ptr->ctx);
|
|
585
|
+
|
|
586
|
+
if(kerror)
|
|
587
|
+
rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
|
|
588
|
+
|
|
589
|
+
ptr->rb_context = Qnil;
|
|
590
|
+
}
|
|
464
591
|
|
|
465
592
|
// Use the default keytab name if one isn't provided.
|
|
466
593
|
if(NIL_P(v_keytab_name)){
|
|
@@ -503,7 +630,7 @@ typedef struct {
|
|
|
503
630
|
static VALUE rkrb5_s_keytab_foreach_body(VALUE arg){
|
|
504
631
|
keytab_foreach_arg* fa = (keytab_foreach_arg*)arg;
|
|
505
632
|
krb5_keytab_entry entry;
|
|
506
|
-
krb5_error_code kerror;
|
|
633
|
+
krb5_error_code kerror, iteration_error;
|
|
507
634
|
char* principal;
|
|
508
635
|
VALUE v_kt_entry;
|
|
509
636
|
|
|
@@ -528,9 +655,13 @@ static VALUE rkrb5_s_keytab_foreach_body(VALUE arg){
|
|
|
528
655
|
rb_yield(v_kt_entry);
|
|
529
656
|
}
|
|
530
657
|
|
|
531
|
-
|
|
658
|
+
iteration_error = kerror;
|
|
532
659
|
|
|
533
660
|
kerror = krb5_kt_end_seq_get(fa->ctx, fa->keytab, &fa->cursor);
|
|
661
|
+
fa->cursor_active = 0;
|
|
662
|
+
|
|
663
|
+
if(iteration_error != KRB5_KT_END)
|
|
664
|
+
rb_raise(cKrb5Exception, "krb5_kt_next_entry: %s", error_message(iteration_error));
|
|
534
665
|
|
|
535
666
|
if(kerror)
|
|
536
667
|
rb_raise(cKrb5Exception, "krb5_kt_end_seq_get: %s", error_message(kerror));
|
|
@@ -616,6 +747,26 @@ static VALUE rkrb5_s_keytab_foreach(int argc, VALUE* argv, VALUE klass){
|
|
|
616
747
|
return Qnil;
|
|
617
748
|
}
|
|
618
749
|
|
|
750
|
+
/*
|
|
751
|
+
* call-seq:
|
|
752
|
+
* keytab.have_content? -> true or false
|
|
753
|
+
*
|
|
754
|
+
* Returns true if the keytab exists and contains entries, false otherwise.
|
|
755
|
+
*/
|
|
756
|
+
static VALUE rkrb5_keytab_have_content(VALUE self){
|
|
757
|
+
RUBY_KRB5_KEYTAB* ptr;
|
|
758
|
+
krb5_error_code kerror;
|
|
759
|
+
|
|
760
|
+
TypedData_Get_Struct(self, RUBY_KRB5_KEYTAB, &rkrb5_keytab_data_type, ptr);
|
|
761
|
+
|
|
762
|
+
if(!ptr->ctx)
|
|
763
|
+
rb_raise(cKrb5Exception, "no context has been established");
|
|
764
|
+
|
|
765
|
+
kerror = krb5_kt_have_content(ptr->ctx, ptr->keytab);
|
|
766
|
+
|
|
767
|
+
return kerror ? Qfalse : Qtrue;
|
|
768
|
+
}
|
|
769
|
+
|
|
619
770
|
void Init_keytab(void){
|
|
620
771
|
/* The Kerberos::Krb5::Keytab class encapsulates a Kerberos keytab. */
|
|
621
772
|
cKrb5Keytab = rb_define_class_under(cKrb5, "Keytab", rb_cObject);
|
|
@@ -644,11 +795,11 @@ void Init_keytab(void){
|
|
|
644
795
|
rb_define_method(cKrb5Keytab, "keytab_name", rkrb5_keytab_get_name, 0);
|
|
645
796
|
rb_define_method(cKrb5Keytab, "keytab_type", rkrb5_keytab_get_type, 0);
|
|
646
797
|
rb_define_method(cKrb5Keytab, "dup", rkrb5_keytab_dup, 0);
|
|
798
|
+
rb_define_method(cKrb5Keytab, "have_content?", rkrb5_keytab_have_content, 0);
|
|
647
799
|
rb_define_alias(cKrb5Keytab, "clone", "dup");
|
|
648
800
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
// rb_define_method(cKrb5Keytab, "remove_entry", rkrb5_keytab_remove_entry, -1);
|
|
801
|
+
rb_define_method(cKrb5Keytab, "add_entry", rkrb5_keytab_add_entry, -1);
|
|
802
|
+
rb_define_method(cKrb5Keytab, "remove_entry", rkrb5_keytab_remove_entry, -1);
|
|
652
803
|
|
|
653
804
|
// Accessors
|
|
654
805
|
|
data/ext/rkerberos/policy.c
CHANGED
|
@@ -32,12 +32,12 @@ static VALUE rkadm5_policy_allocate(VALUE klass){
|
|
|
32
32
|
|
|
33
33
|
/*
|
|
34
34
|
* call-seq:
|
|
35
|
-
* Kerberos::Kadm5::Policy.new(
|
|
35
|
+
* Kerberos::Kadm5::Policy.new(name:, min_life: nil, max_life: nil,
|
|
36
|
+
* min_length: nil, min_classes: nil, history_num: nil)
|
|
36
37
|
*
|
|
37
|
-
* Returns a new policy object using
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* Kadm5.create_policy method.
|
|
38
|
+
* Returns a new policy object using the keyword arguments you choose to pass.
|
|
39
|
+
* This does NOT actually create the policy within Kerberos. To do that pass
|
|
40
|
+
* your Policy object to the Kadm5.create_policy method.
|
|
41
41
|
*
|
|
42
42
|
* The possible options are:
|
|
43
43
|
*
|
|
@@ -50,32 +50,34 @@ static VALUE rkadm5_policy_allocate(VALUE klass){
|
|
|
50
50
|
*
|
|
51
51
|
* If you do not provide a :name then an ArgumentError will be raised.
|
|
52
52
|
*/
|
|
53
|
-
static VALUE rkadm5_policy_init(VALUE
|
|
53
|
+
static VALUE rkadm5_policy_init(int argc, VALUE* argv, VALUE self){
|
|
54
54
|
RUBY_KADM5_POLICY* ptr;
|
|
55
|
+
VALUE v_options;
|
|
55
56
|
VALUE v_name, v_minlife, v_maxlife, v_minlength;
|
|
56
57
|
VALUE v_minclasses, v_historynum;
|
|
58
|
+
ID kw_table[6] = {
|
|
59
|
+
rb_intern("name"), rb_intern("min_life"), rb_intern("max_life"),
|
|
60
|
+
rb_intern("min_length"), rb_intern("min_classes"), rb_intern("history_num")
|
|
61
|
+
};
|
|
62
|
+
VALUE kw_vals[6];
|
|
57
63
|
|
|
58
64
|
TypedData_Get_Struct(self, RUBY_KADM5_POLICY, &rkadm5_policy_data_type, ptr);
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
rb_scan_args(argc, argv, "0:", &v_options);
|
|
61
67
|
|
|
62
|
-
if(
|
|
63
|
-
|
|
68
|
+
if(NIL_P(v_options))
|
|
69
|
+
v_options = rb_hash_new();
|
|
64
70
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
rb_get_kwargs(v_options, kw_table, 1, 5, kw_vals);
|
|
72
|
+
v_name = kw_vals[0];
|
|
73
|
+
v_minlife = kw_vals[1] == Qundef ? Qnil : kw_vals[1];
|
|
74
|
+
v_maxlife = kw_vals[2] == Qundef ? Qnil : kw_vals[2];
|
|
75
|
+
v_minlength = kw_vals[3] == Qundef ? Qnil : kw_vals[3];
|
|
76
|
+
v_minclasses = kw_vals[4] == Qundef ? Qnil : kw_vals[4];
|
|
77
|
+
v_historynum = kw_vals[5] == Qundef ? Qnil : kw_vals[5];
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
else{
|
|
76
|
-
ptr->policy.policy = StringValueCStr(v_name);
|
|
77
|
-
rb_iv_set(self, "@policy", v_name);
|
|
78
|
-
}
|
|
79
|
+
ptr->policy.policy = StringValueCStr(v_name);
|
|
80
|
+
rb_iv_set(self, "@policy", v_name);
|
|
79
81
|
|
|
80
82
|
if(!NIL_P(v_minlife)){
|
|
81
83
|
ptr->policy.pw_min_life = NUM2LONG(v_minlife);
|
|
@@ -171,7 +173,7 @@ void Init_policy(void){
|
|
|
171
173
|
|
|
172
174
|
// Initialization Function
|
|
173
175
|
|
|
174
|
-
rb_define_method(cKadm5Policy, "initialize", rkadm5_policy_init, 1);
|
|
176
|
+
rb_define_method(cKadm5Policy, "initialize", rkadm5_policy_init, -1);
|
|
175
177
|
|
|
176
178
|
// Instance methods
|
|
177
179
|
|