/* * 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; }