rkerberos 0.2.1 → 0.2.3
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 +28 -8
- data/MANIFEST.md +24 -16
- data/Rakefile +4 -1
- data/ext/rkerberos/ccache.c +98 -1
- data/ext/rkerberos/config.c +10 -7
- data/ext/rkerberos/context.c +6 -0
- data/ext/rkerberos/extconf.rb +16 -3
- data/ext/rkerberos/kadm5.c +97 -45
- data/ext/rkerberos/keytab.c +247 -106
- data/ext/rkerberos/keytab_entry.c +2 -1
- data/ext/rkerberos/principal.c +28 -0
- data/ext/rkerberos/rkerberos.c +91 -13
- data/rkerberos.gemspec +1 -1
- data/spec/config_spec.rb +29 -7
- data/spec/context_spec.rb +6 -7
- data/spec/credentials_cache_spec.rb +79 -12
- data/spec/kadm5_spec.rb +57 -16
- data/spec/krb5_keytab_spec.rb +200 -4
- data/spec/krb5_spec.rb +81 -9
- data/spec/policy_spec.rb +8 -7
- data/spec/principal_spec.rb +18 -0
- data/spec/spec_helper.rb +34 -0
- metadata +3 -2
data/ext/rkerberos/kadm5.c
CHANGED
|
@@ -8,6 +8,8 @@ VALUE cKadm5PrincipalNotFoundException;
|
|
|
8
8
|
|
|
9
9
|
// Prototype
|
|
10
10
|
static VALUE rkadm5_close(VALUE);
|
|
11
|
+
static void free_tl_data(krb5_tl_data *);
|
|
12
|
+
static void free_db_args(char**);
|
|
11
13
|
char** parse_db_args(VALUE v_db_args);
|
|
12
14
|
void add_db_args(kadm5_principal_ent_rec*, char**);
|
|
13
15
|
void add_tl_data(krb5_int16 *, krb5_tl_data **,
|
|
@@ -18,11 +20,13 @@ void add_tl_data(krb5_int16 *, krb5_tl_data **,
|
|
|
18
20
|
static void rkadm5_typed_free(void *ptr) {
|
|
19
21
|
if (!ptr) return;
|
|
20
22
|
RUBY_KADM5 *k = (RUBY_KADM5 *)ptr;
|
|
23
|
+
if (k->handle)
|
|
24
|
+
kadm5_destroy(k->handle);
|
|
21
25
|
if (k->princ)
|
|
22
26
|
krb5_free_principal(k->ctx, k->princ);
|
|
23
27
|
if (k->ctx)
|
|
24
28
|
krb5_free_context(k->ctx);
|
|
25
|
-
|
|
29
|
+
free_db_args(k->db_args);
|
|
26
30
|
free(k);
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -72,6 +76,7 @@ static VALUE rkadm5_initialize(VALUE self, VALUE v_opts){
|
|
|
72
76
|
char* pass = NULL;
|
|
73
77
|
char* keytab = NULL;
|
|
74
78
|
char* service = NULL;
|
|
79
|
+
char default_keytab_name[MAX_KEYTAB_NAME_LEN];
|
|
75
80
|
krb5_error_code kerror;
|
|
76
81
|
|
|
77
82
|
TypedData_Get_Struct(self, RUBY_KADM5, &rkadm5_data_type, ptr);
|
|
@@ -126,14 +131,12 @@ static VALUE rkadm5_initialize(VALUE self, VALUE v_opts){
|
|
|
126
131
|
// The docs say I can use NULL to get the default, but reality appears to be otherwise.
|
|
127
132
|
if(RTEST(v_keytab)){
|
|
128
133
|
if(TYPE(v_keytab) == T_TRUE){
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
kerror = krb5_kt_default_name(ptr->ctx, default_name, MAX_KEYTAB_NAME_LEN);
|
|
134
|
+
kerror = krb5_kt_default_name(ptr->ctx, default_keytab_name, MAX_KEYTAB_NAME_LEN);
|
|
132
135
|
|
|
133
136
|
if(kerror)
|
|
134
137
|
rb_raise(cKrb5Exception, "krb5_kt_default_name: %s", error_message(kerror));
|
|
135
138
|
|
|
136
|
-
keytab =
|
|
139
|
+
keytab = default_keytab_name;
|
|
137
140
|
}
|
|
138
141
|
else{
|
|
139
142
|
Check_Type(v_keytab, T_STRING);
|
|
@@ -206,6 +209,11 @@ static VALUE rkadm5_set_password(VALUE self, VALUE v_user, VALUE v_pass){
|
|
|
206
209
|
if(!ptr->ctx)
|
|
207
210
|
rb_raise(cKadm5Exception, "no context has been established");
|
|
208
211
|
|
|
212
|
+
if(ptr->princ){
|
|
213
|
+
krb5_free_principal(ptr->ctx, ptr->princ);
|
|
214
|
+
ptr->princ = NULL;
|
|
215
|
+
}
|
|
216
|
+
|
|
209
217
|
kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
|
|
210
218
|
|
|
211
219
|
if(kerror)
|
|
@@ -239,6 +247,11 @@ static VALUE rkadm5_set_pwexpire(VALUE self, VALUE v_user, VALUE v_pwexpire){
|
|
|
239
247
|
if(!ptr->ctx)
|
|
240
248
|
rb_raise(cKadm5Exception, "no context has been established");
|
|
241
249
|
|
|
250
|
+
if(ptr->princ){
|
|
251
|
+
krb5_free_principal(ptr->ctx, ptr->princ);
|
|
252
|
+
ptr->princ = NULL;
|
|
253
|
+
}
|
|
254
|
+
|
|
242
255
|
kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
|
|
243
256
|
|
|
244
257
|
if(kerror)
|
|
@@ -258,6 +271,8 @@ static VALUE rkadm5_set_pwexpire(VALUE self, VALUE v_user, VALUE v_pwexpire){
|
|
|
258
271
|
ent.pw_expiration=pwexpire;
|
|
259
272
|
kerror = kadm5_modify_principal(ptr->handle, &ent, KADM5_PW_EXPIRATION);
|
|
260
273
|
|
|
274
|
+
kadm5_free_principal_ent(ptr->handle, &ent);
|
|
275
|
+
|
|
261
276
|
if(kerror)
|
|
262
277
|
rb_raise(cKadm5Exception, "kadm5_set_pwexpire: %s", error_message(kerror));
|
|
263
278
|
|
|
@@ -300,22 +315,28 @@ static VALUE rkadm5_create_principal(int argc, VALUE* argv, VALUE self){
|
|
|
300
315
|
|
|
301
316
|
db_args = parse_db_args(v_db_args);
|
|
302
317
|
add_db_args(&princ, db_args);
|
|
303
|
-
|
|
318
|
+
free_db_args(db_args);
|
|
304
319
|
|
|
305
320
|
if(!ptr->ctx)
|
|
306
321
|
rb_raise(cKadm5Exception, "no context has been established");
|
|
307
322
|
|
|
308
323
|
kerror = krb5_parse_name(ptr->ctx, user, &princ.principal);
|
|
309
324
|
|
|
310
|
-
if(kerror)
|
|
325
|
+
if(kerror){
|
|
326
|
+
free_tl_data(princ.tl_data);
|
|
311
327
|
rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
|
|
328
|
+
}
|
|
312
329
|
|
|
313
330
|
kerror = kadm5_create_principal(ptr->handle, &princ, mask, pass);
|
|
314
331
|
|
|
315
|
-
if(kerror)
|
|
332
|
+
if(kerror){
|
|
333
|
+
krb5_free_principal(ptr->ctx, princ.principal);
|
|
334
|
+
free_tl_data(princ.tl_data);
|
|
316
335
|
rb_raise(cKadm5Exception, "kadm5_create_principal: %s", error_message(kerror));
|
|
336
|
+
}
|
|
317
337
|
|
|
318
338
|
krb5_free_principal(ptr->ctx, princ.principal);
|
|
339
|
+
free_tl_data(princ.tl_data);
|
|
319
340
|
|
|
320
341
|
return self;
|
|
321
342
|
}
|
|
@@ -337,6 +358,11 @@ static VALUE rkadm5_delete_principal(VALUE self, VALUE v_user){
|
|
|
337
358
|
if(!ptr->ctx)
|
|
338
359
|
rb_raise(cKadm5Exception, "no context has been established");
|
|
339
360
|
|
|
361
|
+
if(ptr->princ){
|
|
362
|
+
krb5_free_principal(ptr->ctx, ptr->princ);
|
|
363
|
+
ptr->princ = NULL;
|
|
364
|
+
}
|
|
365
|
+
|
|
340
366
|
kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
|
|
341
367
|
|
|
342
368
|
if(kerror)
|
|
@@ -364,16 +390,16 @@ static VALUE rkadm5_close(VALUE self){
|
|
|
364
390
|
RUBY_KADM5* ptr;
|
|
365
391
|
TypedData_Get_Struct(self, RUBY_KADM5, &rkadm5_data_type, ptr);
|
|
366
392
|
|
|
393
|
+
if(ptr->handle)
|
|
394
|
+
kadm5_destroy(ptr->handle);
|
|
395
|
+
|
|
367
396
|
if(ptr->princ)
|
|
368
397
|
krb5_free_principal(ptr->ctx, ptr->princ);
|
|
369
398
|
|
|
370
399
|
if(ptr->ctx)
|
|
371
400
|
krb5_free_context(ptr->ctx);
|
|
372
401
|
|
|
373
|
-
|
|
374
|
-
kadm5_destroy(ptr->handle);
|
|
375
|
-
|
|
376
|
-
free(ptr->db_args);
|
|
402
|
+
free_db_args(ptr->db_args);
|
|
377
403
|
|
|
378
404
|
ptr->db_args = NULL;
|
|
379
405
|
ptr->ctx = NULL;
|
|
@@ -405,10 +431,10 @@ static VALUE create_principal_from_entry(VALUE v_name, RUBY_KADM5* ptr, kadm5_pr
|
|
|
405
431
|
if(ent->last_failed)
|
|
406
432
|
rb_iv_set(v_principal, "@last_failed", rb_time_new(ent->last_failed, 0));
|
|
407
433
|
|
|
408
|
-
if(ent->
|
|
434
|
+
if(ent->last_pwd_change)
|
|
409
435
|
rb_iv_set(v_principal, "@last_password_change", rb_time_new(ent->last_pwd_change, 0));
|
|
410
436
|
|
|
411
|
-
if(ent->
|
|
437
|
+
if(ent->last_success)
|
|
412
438
|
rb_iv_set(v_principal, "@last_success", rb_time_new(ent->last_success, 0));
|
|
413
439
|
|
|
414
440
|
rb_iv_set(v_principal, "@max_life", LONG2FIX(ent->max_life));
|
|
@@ -421,10 +447,13 @@ static VALUE create_principal_from_entry(VALUE v_name, RUBY_KADM5* ptr, kadm5_pr
|
|
|
421
447
|
char* mod_name;
|
|
422
448
|
kerror = krb5_unparse_name(ptr->ctx, ent->mod_name, &mod_name);
|
|
423
449
|
|
|
424
|
-
if(kerror)
|
|
450
|
+
if(kerror){
|
|
451
|
+
kadm5_free_principal_ent(ptr->handle, ent);
|
|
425
452
|
rb_raise(cKadm5Exception, "krb5_unparse_name: %s", error_message(kerror));
|
|
453
|
+
}
|
|
426
454
|
|
|
427
455
|
rb_iv_set(v_principal, "@mod_name", rb_str_new2(mod_name));
|
|
456
|
+
krb5_free_unparsed_name(ptr->ctx, mod_name);
|
|
428
457
|
}
|
|
429
458
|
|
|
430
459
|
if(ent->pw_expiration)
|
|
@@ -433,6 +462,8 @@ static VALUE create_principal_from_entry(VALUE v_name, RUBY_KADM5* ptr, kadm5_pr
|
|
|
433
462
|
if(ent->policy)
|
|
434
463
|
rb_iv_set(v_principal, "@policy", rb_str_new2(ent->policy));
|
|
435
464
|
|
|
465
|
+
kadm5_free_principal_ent(ptr->handle, ent);
|
|
466
|
+
|
|
436
467
|
return v_principal;
|
|
437
468
|
}
|
|
438
469
|
|
|
@@ -464,6 +495,11 @@ static VALUE rkadm5_find_principal(VALUE self, VALUE v_user){
|
|
|
464
495
|
if(!ptr->ctx)
|
|
465
496
|
rb_raise(cKadm5Exception, "no context has been established");
|
|
466
497
|
|
|
498
|
+
if(ptr->princ){
|
|
499
|
+
krb5_free_principal(ptr->ctx, ptr->princ);
|
|
500
|
+
ptr->princ = NULL;
|
|
501
|
+
}
|
|
502
|
+
|
|
467
503
|
kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
|
|
468
504
|
|
|
469
505
|
if(kerror)
|
|
@@ -520,6 +556,11 @@ static VALUE rkadm5_get_principal(VALUE self, VALUE v_user){
|
|
|
520
556
|
if(!ptr->ctx)
|
|
521
557
|
rb_raise(cKadm5Exception, "no context has been established");
|
|
522
558
|
|
|
559
|
+
if(ptr->princ){
|
|
560
|
+
krb5_free_principal(ptr->ctx, ptr->princ);
|
|
561
|
+
ptr->princ = NULL;
|
|
562
|
+
}
|
|
563
|
+
|
|
523
564
|
kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
|
|
524
565
|
|
|
525
566
|
if(kerror)
|
|
@@ -609,7 +650,7 @@ static VALUE rkadm5_create_policy(VALUE self, VALUE v_policy){
|
|
|
609
650
|
|
|
610
651
|
if(RTEST(v_history_num)){
|
|
611
652
|
mask |= KADM5_PW_HISTORY_NUM;
|
|
612
|
-
ent.
|
|
653
|
+
ent.pw_history_num = NUM2LONG(v_history_num);
|
|
613
654
|
}
|
|
614
655
|
|
|
615
656
|
kerror = kadm5_create_policy(ptr->handle, &ent, mask);
|
|
@@ -694,6 +735,8 @@ static VALUE rkadm5_get_policy(VALUE self, VALUE v_name){
|
|
|
694
735
|
v_arg[0] = v_hash;
|
|
695
736
|
|
|
696
737
|
v_policy = rb_class_new_instance(1, v_arg, cKadm5Policy);
|
|
738
|
+
|
|
739
|
+
kadm5_free_policy_ent(ptr->handle, &ent);
|
|
697
740
|
}
|
|
698
741
|
|
|
699
742
|
return v_policy;
|
|
@@ -749,6 +792,8 @@ static VALUE rkadm5_find_policy(VALUE self, VALUE v_name){
|
|
|
749
792
|
v_arg[0] = v_hash;
|
|
750
793
|
|
|
751
794
|
v_policy = rb_class_new_instance(1, v_arg, cKadm5Policy);
|
|
795
|
+
|
|
796
|
+
kadm5_free_policy_ent(ptr->handle, &ent);
|
|
752
797
|
}
|
|
753
798
|
|
|
754
799
|
return v_policy;
|
|
@@ -906,15 +951,14 @@ static VALUE rkadm5_get_principals(int argc, VALUE* argv, VALUE self){
|
|
|
906
951
|
* KADM5_PRIV_ADD (0x02) => "ADD"
|
|
907
952
|
* KADM5_PRIV_MODIFY (0x04) => "MODIFY"
|
|
908
953
|
* KADM5_PRIV_DELETE (0x08) => "DELETE"
|
|
954
|
+
*
|
|
909
955
|
*/
|
|
910
956
|
static VALUE rkadm5_get_privs(int argc, VALUE* argv, VALUE self){
|
|
911
957
|
RUBY_KADM5* ptr;
|
|
912
958
|
VALUE v_return = Qnil;
|
|
913
959
|
VALUE v_strings = Qfalse;
|
|
914
960
|
kadm5_ret_t kerror;
|
|
915
|
-
unsigned int i;
|
|
916
961
|
long privs;
|
|
917
|
-
int result = 0;
|
|
918
962
|
|
|
919
963
|
TypedData_Get_Struct(self, RUBY_KADM5, &rkadm5_data_type, ptr);
|
|
920
964
|
|
|
@@ -928,31 +972,17 @@ static VALUE rkadm5_get_privs(int argc, VALUE* argv, VALUE self){
|
|
|
928
972
|
if(RTEST(v_strings)){
|
|
929
973
|
v_return = rb_ary_new();
|
|
930
974
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
break;
|
|
940
|
-
case KADM5_PRIV_MODIFY:
|
|
941
|
-
rb_ary_push(v_return, rb_str_new2("MODIFY"));
|
|
942
|
-
break;
|
|
943
|
-
case KADM5_PRIV_DELETE:
|
|
944
|
-
rb_ary_push(v_return, rb_str_new2("DELETE"));
|
|
945
|
-
break;
|
|
946
|
-
default:
|
|
947
|
-
rb_ary_push(v_return, rb_str_new2("UNKNOWN"));
|
|
948
|
-
};
|
|
949
|
-
}
|
|
975
|
+
if(privs & KADM5_PRIV_GET)
|
|
976
|
+
rb_ary_push(v_return, rb_str_new2("GET"));
|
|
977
|
+
if(privs & KADM5_PRIV_ADD)
|
|
978
|
+
rb_ary_push(v_return, rb_str_new2("ADD"));
|
|
979
|
+
if(privs & KADM5_PRIV_MODIFY)
|
|
980
|
+
rb_ary_push(v_return, rb_str_new2("MODIFY"));
|
|
981
|
+
if(privs & KADM5_PRIV_DELETE)
|
|
982
|
+
rb_ary_push(v_return, rb_str_new2("DELETE"));
|
|
950
983
|
}
|
|
951
984
|
else{
|
|
952
|
-
|
|
953
|
-
result |= (privs & 1 << i);
|
|
954
|
-
}
|
|
955
|
-
v_return = INT2FIX(result);
|
|
985
|
+
v_return = LONG2FIX(privs);
|
|
956
986
|
}
|
|
957
987
|
|
|
958
988
|
return v_return;
|
|
@@ -987,13 +1017,16 @@ static VALUE rkadm5_randkey_principal(VALUE self, VALUE v_user){
|
|
|
987
1017
|
|
|
988
1018
|
kerror = kadm5_randkey_principal(ptr->handle, princ, &keys, &n_keys);
|
|
989
1019
|
|
|
990
|
-
if(kerror)
|
|
1020
|
+
if(kerror){
|
|
1021
|
+
krb5_free_principal(ptr->ctx, princ);
|
|
991
1022
|
rb_raise(cKadm5Exception, "kadm5_randkey_principal: %s (%li)", error_message(kerror), kerror);
|
|
1023
|
+
}
|
|
992
1024
|
|
|
993
1025
|
for(i = 0; i < n_keys; i++)
|
|
994
1026
|
krb5_free_keyblock_contents(ptr->ctx, &keys[i]);
|
|
995
1027
|
|
|
996
1028
|
free(keys);
|
|
1029
|
+
krb5_free_principal(ptr->ctx, princ);
|
|
997
1030
|
|
|
998
1031
|
return INT2NUM(n_keys);
|
|
999
1032
|
}
|
|
@@ -1008,17 +1041,17 @@ char** parse_db_args(VALUE v_db_args){
|
|
|
1008
1041
|
switch(TYPE(v_db_args)){
|
|
1009
1042
|
case T_STRING:
|
|
1010
1043
|
db_args = (char **) malloc(2 * sizeof(char *));
|
|
1011
|
-
db_args[0] = StringValueCStr(v_db_args);
|
|
1044
|
+
db_args[0] = strdup(StringValueCStr(v_db_args));
|
|
1012
1045
|
db_args[1] = NULL;
|
|
1013
1046
|
break;
|
|
1014
1047
|
case T_ARRAY:
|
|
1015
1048
|
// Multiple arguments
|
|
1016
1049
|
array_length = RARRAY_LEN(v_db_args);
|
|
1017
|
-
db_args = (char **) malloc(array_length * sizeof(char *)
|
|
1050
|
+
db_args = (char **) malloc((array_length + 1) * sizeof(char *));
|
|
1018
1051
|
for(long i = 0; i < array_length; ++i){
|
|
1019
1052
|
VALUE elem = rb_ary_entry(v_db_args, i);
|
|
1020
1053
|
Check_Type(elem, T_STRING);
|
|
1021
|
-
db_args[i] = StringValueCStr(elem);
|
|
1054
|
+
db_args[i] = strdup(StringValueCStr(elem));
|
|
1022
1055
|
}
|
|
1023
1056
|
db_args[array_length] = NULL;
|
|
1024
1057
|
break;
|
|
@@ -1031,6 +1064,16 @@ char** parse_db_args(VALUE v_db_args){
|
|
|
1031
1064
|
return db_args;
|
|
1032
1065
|
}
|
|
1033
1066
|
|
|
1067
|
+
/**
|
|
1068
|
+
* Free a NULL-terminated array of strings returned by parse_db_args.
|
|
1069
|
+
*/
|
|
1070
|
+
static void free_db_args(char** db_args){
|
|
1071
|
+
if(!db_args) return;
|
|
1072
|
+
for(int i = 0; db_args[i] != NULL; i++)
|
|
1073
|
+
free(db_args[i]);
|
|
1074
|
+
free(db_args);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1034
1077
|
/**
|
|
1035
1078
|
* Add parsed db-args to principal entry
|
|
1036
1079
|
*/
|
|
@@ -1046,6 +1089,15 @@ void add_db_args(kadm5_principal_ent_rec* entry, char** db_args){
|
|
|
1046
1089
|
/**
|
|
1047
1090
|
* Source code taken from kadmin source code at https://github.com/krb5/krb5/blob/master/src/kadmin/cli/kadmin.c
|
|
1048
1091
|
*/
|
|
1092
|
+
static void free_tl_data(krb5_tl_data *tl){
|
|
1093
|
+
while(tl){
|
|
1094
|
+
krb5_tl_data *next = tl->tl_data_next;
|
|
1095
|
+
free(tl->tl_data_contents);
|
|
1096
|
+
free(tl);
|
|
1097
|
+
tl = next;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1049
1101
|
void add_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap,
|
|
1050
1102
|
krb5_int16 tl_type, krb5_ui_2 len, krb5_octet *contents){
|
|
1051
1103
|
krb5_tl_data* tl_data;
|