/*
* call-seq:
* list_cache([cache_name]) -> array
*
* Call krb5_cc_next_cred to fetch credentials from a cachefile. With no parameters, it fetches the credentials in the default cachefile. With one parameter, it fetches the credentials in the named cachefile. Returns a list of Krb5Auth::Krb5::Cred objects on success, raises Krb5Auth::Krb5::Exception on failure.
*/
static VALUE Krb5_list_cache_creds(int argc, VALUE *argv, VALUE self)
{
struct ruby_krb5 *kerb;
krb5_error_code krbret;
char *cache_name;
krb5_ccache cc;
krb5_cc_cursor cur;
krb5_creds creds;
char *name;
char *sname;
krb5_ticket *tkt;
VALUE result;
VALUE line;
if (argc == 0) {
cache_name = NULL;
}
else if (argc == 1) {
Check_Type(argv[0], T_STRING);
cache_name = STR2CSTR(argv[0]);
}
else {
rb_raise(rb_eRuntimeError, "Invalid arguments");
}
Data_Get_Struct(self, struct ruby_krb5, kerb);
if (!kerb) {
NOSTRUCT_EXCEPT();
return Qfalse;
}
if (cache_name == NULL) {
krbret = krb5_cc_default(kerb->ctx, &cc);
}
else {
krbret = krb5_cc_resolve(kerb->ctx, cache_name, &cc);
}
if (krbret) {
goto cache_fail_raise;
}
krbret = krb5_cc_start_seq_get(kerb->ctx, cc, &cur);
if (krbret) {
goto cache_fail_close;
}
result = rb_ary_new();
while (!(krbret = krb5_cc_next_cred(kerb->ctx, cc, &cur, &creds))) {
krbret = krb5_unparse_name(kerb->ctx, creds.client, &name);
if (krbret) {
krb5_free_cred_contents(kerb->ctx, &creds);
break;
}
krbret = krb5_unparse_name(kerb->ctx, creds.server, &sname);
if (krbret) {
free(name);
krb5_free_cred_contents(kerb->ctx, &creds);
break;
}
krbret = krb5_decode_ticket(&creds.ticket, &tkt);
if (krbret) {
free(sname);
free(name);
krb5_free_cred_contents(kerb->ctx, &creds);
break;
}
line = rb_class_new_instance(0, NULL, cCred);
rb_iv_set(line, "@client", rb_str_new2(name));
rb_iv_set(line, "@server", rb_str_new2(sname));
rb_iv_set(line, "@starttime", INT2NUM(creds.times.starttime));
rb_iv_set(line, "@authtime", INT2NUM(creds.times.authtime));
rb_iv_set(line, "@endtime", INT2NUM(creds.times.endtime));
rb_iv_set(line, "@ticket_flags", INT2NUM(creds.ticket_flags));
rb_iv_set(line, "@cred_enctype", INT2NUM(creds.keyblock.enctype));
rb_iv_set(line, "@ticket_enctype", INT2NUM(tkt->enc_part.enctype));
rb_ary_push(result, line);
krb5_free_ticket(kerb->ctx, tkt);
free(sname);
free(name);
krb5_free_cred_contents(kerb->ctx, &creds);
}
if (krbret != KRB5_CC_END) {
// FIXME: do we need to free up "result" here? There will be no
// references to it, so I think the garbage collector will pick it up,
// but I'm not sure.
goto cache_fail_close;
}
krbret = krb5_cc_end_seq_get(kerb->ctx, cc, &cur);
krb5_cc_close(kerb->ctx, cc);
return result;
cache_fail_close:
krb5_cc_close(kerb->ctx, cc);
cache_fail_raise:
Krb5_register_error(krbret);
return Qfalse;
}