/*
 * call-seq:
 *   get_init_creds_keytab([principal][,keytab])
 *
 * Call krb5_get_init_creds_keytab() to get credentials based on a keytab.  With no parameters, gets the default principal (probably the username@DEFAULT_REALM) from the default keytab (as configured in /etc/krb5.conf).  With one parameter, get the named principal from the default keytab (as configured in /etc/krb5.conf).  With two parameters, get the named principal from the named keytab.  Returns true on success, raises Krb5Auth::Krb5::Exception on failure.
 */
static VALUE Krb5_get_init_creds_keytab(int argc, VALUE *argv, VALUE self)
{
  VALUE princ_val, keytab_val;
  char *princ;
  char *keytab_name;
  struct ruby_krb5 *kerb;
  krb5_error_code krbret;
  krb5_keytab keytab;

  keytab = NULL;

  rb_scan_args(argc, argv, "02", &princ_val, &keytab_val);

  princ = get_string_or_nil(princ_val);
  keytab_name = get_string_or_nil(keytab_val);

  Data_Get_Struct(self, struct ruby_krb5, kerb);
  if (!kerb) {
    NOSTRUCT_EXCEPT();
    return Qfalse;
  }

  if (keytab_name != NULL) {
    krbret = krb5_kt_resolve(kerb->ctx, keytab_name, &keytab);
    if (krbret) {
      goto failed_keytab;
    }
  }
  // implicit else: if we weren't passed a keytab name, just leave keytab as
  // NULL to use the default

  if (princ != NULL) {
    krbret = krb5_parse_name(kerb->ctx, princ, &kerb->princ);
  }
  else {
    // if we weren't passed a principal, we just get the default principal
    // (which is generally the hostname)
    krbret = krb5_sname_to_principal(kerb->ctx, NULL, NULL, KRB5_NT_SRV_HST,
                                     &kerb->princ);
  }
  if (krbret) {
    goto failed_keytab;
  }

  krbret = krb5_get_init_creds_keytab(kerb->ctx, &kerb->creds, kerb->princ,
                                      keytab, 0, NULL, NULL);
  if (krbret) {
    goto failed_keytab;
  }

  if (keytab)
    krb5_kt_close(kerb->ctx, keytab);

  return Qtrue;

 failed_keytab:
  if (keytab)
    krb5_kt_close(kerb->ctx, keytab);

  Krb5_register_error(krbret);

  // we will never reach here, since Krb5_register_error will rb_raise().  just
  // leave it to shut the compiler up
  return Qfalse;
}