Example #1
0
File: tgs.c Project: Jactry/shishi
/**
 * shishi_tgs_done:
 * @tgs: structure that holds information about AS exchange
 *
 * Deallocate resources associated with TGS exchange.  This should be
 * called by the application when it no longer need to utilize the TGS
 * exchange handle.
 **/
void
shishi_tgs_done (Shishi_tgs * tgs)
{
  shishi_asn1_done (tgs->handle, tgs->tgsreq);
  shishi_asn1_done (tgs->handle, tgs->tgsrep);
  shishi_asn1_done (tgs->handle, tgs->krberror);
  shishi_ap_done (tgs->ap);
  shishi_tkt_done (tgs->tkt);
  free (tgs);
}
Example #2
0
/**
 * shishi_encapreppart:
 * @handle: shishi handle as allocated by shishi_init().
 *
 * This function creates a new EncAPRepPart, populated with some
 * default values.  It uses the current time as returned by the system
 * for the ctime and cusec fields.
 *
 * Return value: Returns the encapreppart or NULL on failure.
 **/
Shishi_asn1
shishi_encapreppart (Shishi * handle)
{
  int res;
  Shishi_asn1 node = NULL;
  struct timeval tv;
  uint32_t seqnr;

  res = gettimeofday (&tv, NULL);
  if (res)
    return NULL;

  node = shishi_asn1_encapreppart (handle);
  if (!node)
    return NULL;

  res = shishi_asn1_write (handle, node, "ctime",
			   shishi_generalize_time (handle, time (NULL)), 0);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_encapreppart_cusec_set (handle, node, tv.tv_usec % 1000000);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "subkey", NULL, 0);
  if (res != SHISHI_OK)
    goto error;

  /*
   * For sequence numbers to adequately support the detection of
   * replays they SHOULD be non-repeating, even across connection
   * boundaries. The initial sequence number SHOULD be random and
   * uniformly distributed across the full space of possible sequence
   * numbers, so that it cannot be guessed by an attacker and so that
   * it and the successive sequence numbers do not repeat other
   * sequences.
   */
  shishi_randomize (handle, 0, &seqnr, sizeof (seqnr));

  /*
   * Implementation note: as noted before, some implementations omit
   * the optional sequence number when its value would be zero.
   * Implementations MAY accept an omitted sequence number when
   * expecting a value of zero, and SHOULD NOT transmit an
   * Authenticator with a initial sequence number of zero.
   */
  if (seqnr == 0)
    seqnr++;

  res = shishi_encapreppart_seqnumber_set (handle, node, seqnr);
  if (res != SHISHI_OK)
    goto error;

  return node;

error:
  shishi_asn1_done (handle, node);
  return NULL;
}
Example #3
0
File: tgs.c Project: Jactry/shishi
/**
 * shishi_tgs_krberror_set:
 * @tgs: structure that holds information about TGS exchange
 * @krberror: krberror to store in TGS.
 *
 * Set the KRB-ERROR in the TGS exchange.
 **/
void
shishi_tgs_krberror_set (Shishi_tgs * tgs, Shishi_asn1 krberror)
{
  if (tgs->krberror)
    shishi_asn1_done (tgs->handle, tgs->krberror);
  tgs->krberror = krberror;
}
Example #4
0
File: tgs.c Project: Jactry/shishi
/**
 * shishi_tgs_req_set:
 * @tgs: structure that holds information about TGS exchange
 * @tgsreq: tgsreq to store in TGS.
 *
 * Set the TGS-REQ in the TGS exchange.
 **/
void
shishi_tgs_req_set (Shishi_tgs * tgs, Shishi_asn1 tgsreq)
{
  if (tgs->tgsreq)
    shishi_asn1_done (tgs->handle, tgs->tgsreq);
  tgs->tgsreq = tgsreq;
}
Example #5
0
Shishi_asn1
shishi_encticketpart (Shishi * handle)
{
  Shishi_asn1 node;
  int res;

  node = shishi_asn1_encticketpart (handle);

  res = shishi_asn1_write (handle, node, "starttime", NULL, 0);
  if (res != SHISHI_OK)
    {
      shishi_asn1_done (handle, node);
      return NULL;
    }

  res = shishi_asn1_write (handle, node, "renew-till", NULL, 0);
  if (res != SHISHI_OK)
    {
      shishi_asn1_done (handle, node);
      return NULL;
    }

  res = shishi_asn1_write (handle, node, "caddr", NULL, 0);
  if (res != SHISHI_OK)
    {
      shishi_asn1_done (handle, node);
      return NULL;
    }

  res = shishi_asn1_write (handle, node, "authorization-data", NULL, 0);
  if (res != SHISHI_OK)
    {
      shishi_asn1_done (handle, node);
      return NULL;
    }

  res = shishi_encticketpart_flags_set (handle, node, 0);
  if (res != SHISHI_OK)
    {
      shishi_asn1_done (handle, node);
      return NULL;
    }

  return node;
}
Example #6
0
File: init.c Project: Jactry/shishi
/**
 * shishi_done:
 * @handle: Shishi handle as allocated by shishi_init().
 *
 * Deallocates the Shishi library handle.  The handle must not be used
 * in any call to a shishi function after an execution of shishi_done().
 *
 * If there is a default #tkts, it is written to the default tkts file.
 * If you do not wish to write the default tkts file, close the
 * default file before calling this function.  It is closed with a
 * simple #shishi_tkts_done(@handle, %NULL).  For related information,
 * see shishi_tkts_default_file_set().
 **/
void
shishi_done (Shishi * handle)
{
  int rc;

  if (handle->tkts)
    {
      shishi_tkts_to_file (handle->tkts, shishi_tkts_default_file (handle));
      shishi_tkts_done (&handle->tkts);
    }

  shishi_principal_default_set (handle, NULL);
  shishi_tkts_default_file_set (handle, NULL);

#ifdef USE_STARTTLS
  rc = _shishi_tls_done (handle);
  if (rc != SHISHI_OK)
    shishi_warn (handle, "Cannot deinitialize TLS library");
#endif

  if (handle->realminfos)
    {
      size_t i, j;

      for (i = 0; i < handle->nrealminfos; i++)
	{
	  /* XXX free each address */

	  free (handle->realminfos[i].kdcaddresses);
	  free (handle->realminfos[i].name);

	  for (j = 0; j < handle->realminfos[i].nserverwildcards; j++)
	    free (handle->realminfos[i].serverwildcards[j]);
	}
    }

  free (handle->default_realm);
  free (handle->usercfgfile);
  free (handle->hostkeysdefaultfile);
  free (handle->clientkdcetypes);
  free (handle->authorizationtypes);
  free (handle->stringprocess);
  free (handle->userdirectory);

  if (handle->asn1)
    shishi_asn1_done (handle, handle->asn1);

  free (handle);
}
Example #7
0
void
test (Shishi * handle)
{
  Shishi_asn1 req, rep;
  char *reqder, *repder;
  size_t reqderlen, repderlen;
  int rc;
  uint32_t nonce;

  if (!base64_decode_alloc (asreq, strlen (asreq), &reqder, &reqderlen))
    fail ("base64 req\n");

  if (!base64_decode_alloc (asreppart, strlen (asreppart), &repder, &repderlen))
    fail ("base64 rep\n");

  req = shishi_der2asn1_asreq (handle, reqder, reqderlen);
  if (!req)
    fail ("der2asn1 req\n");

  rep = shishi_der2asn1_encasreppart (handle, repder, repderlen);
  if (!rep)
    fail ("der2asn1 rep\n");

  if (debug)
    {
      shishi_kdcreq_print (handle, stdout, req);
      shishi_enckdcreppart_print (handle, stdout, rep);
    }

  /* Read and check req */

  rc = shishi_asn1_read_uint32 (handle, req, "req-body.nonce", &nonce);
  if (rc)
    fail ("shishi_asn1_read_uint32\n");

  printf ("req nonce: %x\n", nonce);

  if (nonce != 0x09575283)
    fail ("nonce mismatch low\n");

  rc = shishi_kdcreq_nonce (handle, req, &nonce);
  if (rc)
    fail ("shishi_kdcreq_nonce\n");

  printf ("req nonce: %x\n", nonce);

  if (nonce != 0x09575283)
    fail ("nonce mismatch high");

  /* Read and check rep */

  rc = shishi_asn1_read_uint32 (handle, rep, "nonce", &nonce);
  if (rc)
    fail ("read rep uint32");

  printf ("old rep nonce: %x\n", nonce);

  if (nonce != 0x7fffffff)
    fail ("nonce mismatch high");

  /* Copy nonce. */

  rc = shishi_kdc_copy_nonce (handle, req, rep);
  if (rc)
    fail ("shishi_kdc_copy_nonce\n");

  /* Read and check rep */

  rc = shishi_asn1_read_uint32 (handle, rep, "nonce", &nonce);
  if (rc)
    fail ("read rep uint32");

  printf ("new rep nonce: %x\n", nonce);

  if (nonce != 0x09575283)
    fail ("nonce mismatch high");

  free (reqder);
  free (repder);

  shishi_asn1_done (handle, req);
  shishi_asn1_done (handle, rep);
}
Example #8
0
static Shishi_asn1
_shishi_kdcreq (Shishi * handle, int as)
{
    int res;
    Shishi_asn1 node;
    const char *servicebuf[3];
    uint32_t nonce;

    if (as)
        node = shishi_asn1_asreq (handle);
    else
        node = shishi_asn1_tgsreq (handle);
    if (!node)
        return NULL;

    res = shishi_asn1_write (handle, node, "pvno",
                             SHISHI_KDCREQ_DEFAULT_PVNO,
                             SHISHI_KDCREQ_DEFAULT_PVNO_LEN);
    if (res != SHISHI_OK)
        goto error;

    if (as)
        res = shishi_asn1_write (handle, node, "msg-type",
                                 SHISHI_AS_REQ_DEFAULT_MSG_TYPE,
                                 SHISHI_AS_REQ_DEFAULT_MSG_TYPE_LEN);
    else
        res = shishi_asn1_write (handle, node, "msg-type",
                                 SHISHI_TGS_REQ_DEFAULT_MSG_TYPE,
                                 SHISHI_TGS_REQ_DEFAULT_MSG_TYPE_LEN);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "req-body.kdc-options",
                             SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS,
                             SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS_LEN);
    if (res != SHISHI_OK)
        goto error;

    if (as)
        res = shishi_kdcreq_set_cname (handle, node, SHISHI_NT_PRINCIPAL,
                                       shishi_principal_default (handle));
    else
        res = shishi_asn1_write (handle, node, "req-body.cname", NULL, 0);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_kdcreq_set_realm (handle, node, shishi_realm_default (handle));
    if (res != SHISHI_OK)
        goto error;

    servicebuf[0] = "krbtgt";
    servicebuf[1] = shishi_realm_default (handle);
    servicebuf[2] = NULL;
    res = shishi_kdcreq_set_sname (handle, node,
                                   SHISHI_NT_PRINCIPAL, servicebuf);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "req-body.sname.name-type",
                             SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE,
                             SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE_LEN);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "req-body.till",
                             shishi_generalize_time (handle,
                                     time (NULL) +
                                     handle->ticketlife), 0);
    if (res != SHISHI_OK)
        goto error;

    shishi_randomize (handle, 0, &nonce, sizeof (nonce));
    nonce &= 0x7FFFFFFF;		/* XXX fix _libtasn1_convert_integer. */
    res = shishi_kdcreq_nonce_set (handle, node, nonce);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_kdcreq_set_etype (handle, node, handle->clientkdcetypes,
                                   handle->nclientkdcetypes);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node, "req-body.addresses", NULL, 0);
    if (res != SHISHI_OK)
        goto error;

    res = shishi_asn1_write (handle, node,
                             "req-body.enc-authorization-data", NULL, 0);
    if (res != SHISHI_OK)
        goto error;

    res =
        shishi_asn1_write (handle, node, "req-body.additional-tickets", NULL, 0);
    if (res != SHISHI_OK)
        goto error;

    return node;

error:
    shishi_asn1_done (handle, node);
    return NULL;
}
Example #9
0
/**
 * shishi_apreq_get_ticket:
 * @handle: shishi handle as allocated by shishi_init().
 * @apreq: AP-REQ variable to get ticket from.
 * @ticket: output variable to hold extracted ticket.
 *
 * Extract ticket from AP-REQ.
 *
 * Return value: Returns SHISHI_OK iff successful.
 **/
int
shishi_apreq_get_ticket (Shishi * handle,
			 Shishi_asn1 apreq, Shishi_asn1 * ticket)
{
  char *buf;
  char *format;
  size_t buflen, i, n;
  int res;

  /* there's GOT to be an easier way to do this */

  *ticket = shishi_ticket (handle);
  if (!*ticket)
    return SHISHI_ASN1_ERROR;

  res = shishi_asn1_read (handle, apreq, "ticket.tkt-vno", &buf, &buflen);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, *ticket, "tkt-vno", buf, buflen);
  free (buf);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_read (handle, apreq, "ticket.realm", &buf, &buflen);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, *ticket, "realm", buf, buflen);
  free (buf);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_read (handle, apreq, "ticket.sname.name-type",
			  &buf, &buflen);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, *ticket, "sname.name-type", buf, buflen);
  free (buf);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_number_of_elements (handle, apreq,
					"ticket.sname.name-string", &n);
  if (res != SHISHI_OK)
    goto error;

  for (i = 1; i <= n; i++)
    {
      res = shishi_asn1_write (handle, *ticket, "sname.name-string",
			       "NEW", 1);
      if (res != SHISHI_OK)
	goto error;

      asprintf (&format, "ticket.sname.name-string.?%d", i);
      res = shishi_asn1_read (handle, apreq, format, &buf, &buflen);
      free (format);
      if (res != SHISHI_OK)
	goto error;

      asprintf (&format, "sname.name-string.?%d", i);
      res = shishi_asn1_write (handle, *ticket, format, buf, buflen);
      free (format);
      free (buf);
      if (res != SHISHI_OK)
	goto error;
    }

  res = shishi_asn1_read (handle, apreq, "ticket.enc-part.etype",
			  &buf, &buflen);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, *ticket, "enc-part.etype", buf, buflen);
  free (buf);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_read (handle, apreq, "ticket.enc-part.kvno",
			  &buf, &buflen);
  if (res != SHISHI_OK && res != SHISHI_ASN1_NO_ELEMENT)
    goto error;

  if (res == SHISHI_ASN1_NO_ELEMENT)
    res = shishi_asn1_write (handle, *ticket, "enc-part.kvno", NULL, 0);
  else
    {
      res = shishi_asn1_write (handle, *ticket, "enc-part.kvno", buf, buflen);
      free (buf);
    }
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_read (handle, apreq, "ticket.enc-part.cipher",
			  &buf, &buflen);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, *ticket, "enc-part.cipher", buf, buflen);
  free (buf);
  if (res != SHISHI_OK)
    goto error;

  return SHISHI_OK;

error:
  shishi_asn1_done (handle, *ticket);
  return res;
}
Example #10
0
/**
 * shishi_apreq:
 * @handle: shishi handle as allocated by shishi_init().
 *
 * This function creates a new AP-REQ, populated with some default
 * values.
 *
 * Return value: Returns the AP-REQ or NULL on failure.
 **/
Shishi_asn1
shishi_apreq (Shishi * handle)
{
  Shishi_asn1 node;
  int res;

  node = shishi_asn1_apreq (handle);
  if (!node)
    goto error;

  res = shishi_asn1_write (handle, node, "pvno",
			   SHISHI_APREQ_DEFAULT_PVNO,
			   SHISHI_APREQ_DEFAULT_PVNO_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "msg-type",
			   SHISHI_APREQ_DEFAULT_MSG_TYPE,
			   SHISHI_APREQ_DEFAULT_MSG_TYPE_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "ap-options",
			   SHISHI_APREQ_DEFAULT_AP_OPTIONS,
			   SHISHI_APREQ_DEFAULT_AP_OPTIONS_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "ticket.tkt-vno",
			   SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO,
			   SHISHI_APREQ_DEFAULT_TICKET_TKT_VNO_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "ticket.realm",
			   SHISHI_APREQ_DEFAULT_TICKET_REALM,
			   SHISHI_APREQ_DEFAULT_TICKET_REALM_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "ticket.realm",
			   SHISHI_APREQ_DEFAULT_TICKET_REALM,
			   SHISHI_APREQ_DEFAULT_TICKET_REALM_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "ticket.sname.name-type",
			   SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE,
			   SHISHI_APREQ_DEFAULT_TICKET_SNAME_NAME_TYPE_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "ticket.enc-part.etype",
			   SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE,
			   SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_ETYPE_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "ticket.enc-part.kvno",
			   SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO,
			   SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_KVNO_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "ticket.enc-part.cipher",
			   SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER,
			   SHISHI_APREQ_DEFAULT_TICKET_ENC_PART_CIPHER_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "authenticator.etype",
			   SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE,
			   SHISHI_APREQ_DEFAULT_AUTHENTICATOR_ETYPE_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "authenticator.kvno",
			   SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO,
			   SHISHI_APREQ_DEFAULT_AUTHENTICATOR_KVNO_LEN);
  if (res != SHISHI_OK)
    goto error;

  res = shishi_asn1_write (handle, node, "authenticator.cipher",
			   SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER,
			   SHISHI_APREQ_DEFAULT_AUTHENTICATOR_CIPHER_LEN);
  if (res != SHISHI_OK)
    goto error;

  return node;

error:
  if (node)
    shishi_asn1_done (handle, node);
  return NULL;
}
Example #11
0
void
test (Shishi * handle)
{
  Shishi_asn1 a;
  char *p, *buf, *buf2;
  int res;
  size_t n, m;
  int32_t t;
  uint32_t s;

  /* shishi_authenticator */
  a = shishi_authenticator (handle);
  if (debug)
    printf ("shishi_authenticator () => `%p'.\n", a);
  if (a)
    success ("shishi_authenticator() OK\n");
  else
    fail ("shishi_authenticator() failed\n");

  if (debug)
    shishi_authenticator_print (handle, stdout, a);

  res = shishi_authenticator_remove_subkey (handle, a);
  if (res == SHISHI_OK)
    success ("shishi_authenticator_remove_subkey() OK\n");
  else
    fail ("shishi_authenticator_remove_subkey() failed\n");

  /* shishi_authenticator_seqnumber_get */
  res = shishi_authenticator_seqnumber_get (handle, a, &s);
  if (res == SHISHI_OK)
    success ("shishi_authenticator_seqnumber_get() OK\n");
  else
    fail ("shishi_authenticator_seqnumber_get() failed\n");

  /* shishi_authenticator_seqnumber_set */
  res = shishi_authenticator_seqnumber_set (handle, a, 42);
  if (res == SHISHI_OK)
    success ("shishi_authenticator_seqnumber_set() OK\n");
  else
    fail ("shishi_authenticator_seqnumber_set() failed\n");

  /* shishi_authenticator_seqnumber_get */
  res = shishi_authenticator_seqnumber_get (handle, a, &s);
  if (res == SHISHI_OK && s == 42)
    success ("shishi_authenticator_seqnumber_get() OK\n");
  else
    fail ("shishi_authenticator_seqnumber_get() failed\n");

  /* shishi_authenticator_seqnumber_remove */
  res = shishi_authenticator_seqnumber_remove (handle, a);
  if (res == SHISHI_OK)
    success ("shishi_authenticator_seqnumber_remove() OK\n");
  else
    fail ("shishi_authenticator_seqnumber_remove() failed\n");

  /* shishi_authenticator_set_crealm */
  res = shishi_authenticator_set_crealm (handle, a, "foo");
  if (res == SHISHI_OK)
    success ("shishi_authenticator_set_crealm() OK\n");
  else
    fail ("shishi_authenticator_set_crealm() failed\n");

  /* shishi_authenticator_client_set */
  res = shishi_authenticator_client_set (handle, a, "foo/bar/baz");
  if (res == SHISHI_OK)
    success ("shishi_authenticator_client_set() OK\n");
  else
    fail ("shishi_authenticator_client_set() failed\n");

  /* shishi_authenticator_client */
  res = shishi_authenticator_client (handle, a, &buf, &n);
  if (debug)
    escapeprint (buf, n);
  if (res == SHISHI_OK &&
      n == strlen ("foo/bar/baz") && memcmp (buf, "foo/bar/baz", n) == 0)
    success ("shishi_authenticator_client() OK\n");
  else
    fail ("shishi_authenticator_client() failed\n");
  if (res == SHISHI_OK)
    free (buf);

  /* shishi_authenticator_client_set */
  res = shishi_authenticator_client_set (handle, a, "foo");
  if (res == SHISHI_OK)
    success ("shishi_authenticator_client_set() OK\n");
  else
    fail ("shishi_authenticator_client_set() failed\n");

  /* shishi_authenticator_client */
  res = shishi_authenticator_client (handle, a, &buf, &n);
  if (debug)
    escapeprint (buf, n);
  if (res == SHISHI_OK && n == strlen ("foo") && memcmp (buf, "foo", n) == 0)
    success ("shishi_authenticator_client() OK\n");
  else
    fail ("shishi_authenticator_client() failed\n");
  if (res == SHISHI_OK)
    free (buf);

  /* shishi_authenticator_set_crealm */
  res = shishi_authenticator_set_crealm (handle, a, "bar");
  if (res == SHISHI_OK)
    success ("shishi_authenticator_set_crealm() OK\n");
  else
    fail ("shishi_authenticator_set_crealm() failed\n");

  /* shishi_authenticator_clientrealm */
  res = shishi_authenticator_clientrealm (handle, a, &buf, &n);
  if (debug)
    escapeprint (buf, n);
  if (res == SHISHI_OK &&
      n == strlen ("foo@bar") && memcmp (buf, "foo@bar", n) == 0)
    success ("shishi_authenticator_clientrealm() OK\n");
  else
    fail ("shishi_authenticator_clientrealm() failed\n");
  if (res == SHISHI_OK)
    free (buf);

  /* shishi_authenticator_add_authorizationdata */
  res = shishi_authenticator_add_authorizationdata (handle, a, 42, "baz", 3);
  if (res == SHISHI_OK)
    success ("shishi_authenticator_add_authorizationdata() OK\n");
  else
    fail ("shishi_authenticator_add_authorizationdata() failed\n");

  /* shishi_authenticator_authorizationdata */
  res = shishi_authenticator_authorizationdata (handle, a, &t, &buf, &m, 1);
  if (debug)
    escapeprint (buf, m);
  if (res == SHISHI_OK && t == 42 && m == 3 && memcmp (buf, "baz", 3) == 0)
    success ("shishi_authenticator_authorizationdata() OK\n");
  else
    fail ("shishi_authenticator_authorizationdata() failed\n");
  if (res == SHISHI_OK)
    free (buf);

  /* shishi_authenticator_authorizationdata */
  res = shishi_authenticator_authorizationdata (handle, a, &t, &buf, &m, 2);
  if (res == SHISHI_OK)
    free (buf);
  if (res == SHISHI_OUT_OF_RANGE)
    success ("shishi_authenticator_authorizationdata() OK\n");
  else
    fail ("shishi_authenticator_authorizationdata() failed\n");

  /* shishi_authenticator_remove_cksum */
  res = shishi_authenticator_remove_cksum (handle, a);
  if (res == SHISHI_OK)
    success ("shishi_authenticator_remove_cksum() OK\n");
  else
    fail ("shishi_authenticator_remove_cksum() failed\n");

  /* shishi_asn1_to_der */
  res = shishi_asn1_to_der (handle, a, &buf, &n);
  if (res == SHISHI_OK)
    success ("shishi_asn1_to_der() OK\n");
  else
    n = 0, fail ("shishi_asn1_to_der() failed\n");

  /* shishi_authenticator_to_file */
  res = shishi_authenticator_to_file (handle, a, SHISHI_FILETYPE_TEXT,
				      "authenticator.tmp");
  if (res == SHISHI_OK)
    success ("shishi_authenticator_to_file() OK\n");
  else
    fail ("shishi_authenticator_to_file() failed\n");

  /* shishi_asn1_done */
  shishi_asn1_done (handle, a);
  success ("shishi_asn1_done() OK\n");

  a = NULL;

  /* shishi_authenticator_from_file */
  res = shishi_authenticator_from_file (handle, &a, SHISHI_FILETYPE_TEXT,
					"authenticator.tmp");
  if (res == SHISHI_OK)
    success ("shishi_authenticator_from_file() OK\n");
  else
    fail ("shishi_authenticator_from_file() failed\n");

  if (debug)
    {
      /* shishi_authenticator_print */
      res = shishi_authenticator_print (handle, stdout, a);
      if (res == SHISHI_OK)
	success ("shishi_authenticator_print() OK\n");
      else
	fail ("shishi_authenticator_print() failed\n");
    }

  /* shishi_asn1_to_der */
  res = shishi_asn1_to_der (handle, a, &buf2, &m);
  if (res == SHISHI_OK)
    success ("shishi_asn1_to_der() OK\n");
  else
    n = 0, fail ("shishi_asn1_to_der() failed\n");

  /* Compare DER encodings of authenticators */
  if (n > 0 && m > 0 && n == m && memcmp (buf, buf2, n) == 0)
    success ("DER comparison OK\n");
  else
    fail ("DER comparison failed\n");

  free (buf);
  free (buf2);

  /* shishi_authenticator_cusec_set */
  res = shishi_authenticator_cusec_set (handle, a, 4711);
  if (res == SHISHI_OK)
    success ("shishi_authenticator_cusec_set() OK\n");
  else
    fail ("shishi_authenticator_cusec_set() failed\n");

  /* shishi_authenticator_cusec_get */
  res = shishi_authenticator_cusec_get (handle, a, &s);
  if (debug)
    printf ("shishi_authenticator_cusec_get () => `%d'.\n", t);
  if (res == SHISHI_OK && s == 4711)
    success ("shishi_authenticator_cusec_get() OK\n");
  else
    fail ("shishi_authenticator_cusec_get() failed\n");

  /* shishi_authenticator_ctime_set */
  res = shishi_authenticator_ctime_set (handle, a, "19700101011831Z");
  if (res == SHISHI_OK)
    success ("shishi_authenticator_ctime_set() OK\n");
  else
    fail ("shishi_authenticator_ctime_set() failed\n");

  /* shishi_authenticator_ctime */
  res = shishi_authenticator_ctime (handle, a, &p);
  if (debug)
    escapeprint (p, strlen (p));
  if (res == SHISHI_OK && memcmp (p, "19700101011831Z", 15) == 0)
    success ("shishi_authenticator_ctime() OK\n");
  else
    fail ("shishi_authenticator_ctime() failed\n");
  if (res == SHISHI_OK)
    free (p);

  /* shishi_asn1_to_der */
  res = shishi_asn1_to_der (handle, a, &buf, &n);
  if (res == SHISHI_OK)
    success ("shishi_asn1_to_der() OK\n");
  else
    n = 0, fail ("shishi_asn1_to_der() failed\n");
  if (debug)
    {
      shishi_authenticator_print (handle, stdout, a);
      hexprint (buf, n);
      puts ("");
      hexprint (authenticator, sizeof (authenticator));
      puts ("");
    }
  if (n == sizeof (authenticator) &&
      n == AUTHENTICATOR_LEN && memcmp (authenticator, buf, n) == 0)
    success ("DER comparison OK\n");
  else
    fail ("DER comparison failed\n");

  free (buf);

  /* shishi_authenticator_clear_authorizationdata */
  res = shishi_authenticator_clear_authorizationdata (handle, a);
  if (res == SHISHI_OK)
    success ("shishi_authenticator_clear_authorizationdata() OK\n");
  else
    fail ("shishi_authenticator_clear_authorizationdata() failed\n");

  /* shishi_asn1_to_der */
  res = shishi_asn1_to_der (handle, a, &buf, &n);
  if (res == SHISHI_OK)
    success ("shishi_asn1_to_der() OK\n");
  else
    n = 0, fail ("shishi_asn1_to_der() failed\n");
  if (debug)
    {
      shishi_authenticator_print (handle, stdout, a);
      hexprint (buf, n);
      puts ("");
      hexprint (authenticator2, sizeof (authenticator2));
      puts ("");
    }
  if (n == sizeof (authenticator2) &&
      n == AUTHENTICATOR2_LEN && memcmp (authenticator2, buf, n) == 0)
    success ("DER comparison OK\n");
  else
    fail ("DER comparison failed\n");

  free (buf);

  /* unlink */
  res = unlink ("authenticator.tmp");
  if (res == 0)
    success ("unlink() OK\n");
  else
    fail ("unlink() failed\n");

  /* shishi_asn1_done */
  shishi_asn1_done (handle, a);
  success ("shishi_asn1_done() OK\n");
}