#!/usr/local/bin/php-cgi
<?php
/*
 * Copyright (c) 2003-2011
 * Distributed Systems Software.  All rights reserved.
 * See the file LICENSE for redistribution information.
 *
 * $Id: demo_card_defs.php 2529 2011-09-23 22:19:51Z brachman $
 */

/*
 * This is a prototype implementation of the callback web service for
 * dacs_managed_infocard.
 * Internal DACS admin credentials are sent for authorization.
 *
 * Arguments:
 *   DACS_IDENTITY:     DACS identity requesting an InfoCard
 *   CARD_ID:           unique ID (a URL) assigned to the new InfoCard
 *   CARD_VERSION:      version number assigned to the new InfoCard
 *   DACS_JURISDICTION: name of jurisdiction acting as IP/STS
 *   DACS_FEDERATION:   DACS_JURISDICTION is in this federation
 *
 * At minimum, this program needs to do three things:
 * 0) If there is already a mapping from DACS_IDENTITY to any card,
 *    delete the mapping
 * 1) Create a mapping from CARD_ID to DACS_IDENTITY and vice versa
 * 2) Emit a description of the claims to be associated with the new
 *    managed InfoCard (and which a companion program must be prepared to
 *    fill)
 *
 * Output is an XML document:
 * <!ELEMENT card_defs (claim_def)*>
 * <!ATTLIST claim_defs
 *   card_name    CDATA   #IMPLIED
 *   card_error   CDATA   #IMPLIED
 * >
 * <!ELEMENT claim_def EMPTY>
 * <!ATTLIST claim_def
 *   type         CDATA   #REQUIRED
 *   name         CDATA   #REQUIRED
 *   label        CDATA   #REQUIRED
 *   description  CDATA   #REQUIRED
 * >
 *
 * If an error occurs, the card_error attribute must be present and
 * its value can be an error message; e.g.,
 * <card_defs card_error="Could not open database">
 * </card_defs>
 *
 * The normal output looks like:
 * <?xml version="1.0"?>
 * <card_defs card_version="1">
 * <claim_def type="<TYPE>" name="<NAME>" label="<LABEL>" description="<DESC>"/>
 *  ...
 * </card_defs>
 * where:
 *   <TYPE> is the word "standard" or "dacs", or a URI (the URI is not
 *   dereferenced); this establishes a namespace for <NAME> - "standard"
 *   and "dacs" are just short, convenient identifiers for URIs
 *     "standard" is http://schemas.xmlsoap.org/ws/2005/05/identity/claims
 *     "dacs" is http://dacs.dss.ca/claims
 *   <NAME> is a unique (relative to <TYPE>) name for this claim
 *   consisting of alphanumerics and underscores (not beginning with a digit)
 *   <LABEL> is a short (fewer than 15 chars) descriptive blurb that the
 *   Identity Selector will display to identify the claim
 *   (the ic:DisplayTag element in the InfoCard)
 *   <DESC> is a longer descriptive blurb
 *   (the ic:Description element in the InfoCard)
 *
 * Note that this must not define the PPID because it is handled specially
 * within the IP/STS.
 */

/*
 * Configuration - change as desired
 */
$dbfile = "/tmp/defs.db";
$debugfile = "/tmp/defs.log";

/* Set non-zero to enable logging debug info */
$debug = 0;

$db = FALSE;
$fp = FALSE;

/*
 * Return an error message.
 * This assumes that no other output has been emitted.
 */
function fatal($errmsg)
{

  print "<?xml version='1.0' encoding='US-ASCII'?>\n";
  print "<card_defs card_error='" . $errmsg . "'>\n";
  print "</card_defs>\n";

  if ($fp != FALSE) {
    fclose($fp);
  }

  if ($db != FALSE) {
    dba_close($db);
  }

  exit(0);
}

Header('Content-Type: text/xml');

$identity = $_POST['DACS_IDENTITY'];
$card_id = $_POST['CARD_ID'];
$card_version = $_POST['CARD_VERSION'];
$jurisdiction_name = $_POST['DACS_JURISDICTION'];
$federation_name = $_POST['DACS_FEDERATION'];

list($fed, $junk, $jur, $uname) = split(":", $identity, 4);

if ($debug) {
  if (!($fp = fopen($debugfile, 'a+'))) {
      return;
  }
  fprintf($fp, "DACS_IDENTITY=$identity\n");
  fprintf($fp, "CARD_ID=$card_id\n");
  fprintf($fp, "CARD_VERSION=$card_version\n");
  fprintf($fp, "DACS_JURISDICTION=$jurisdiction_name\n");
  fprintf($fp, "DACS_FEDERATION=$federation_name\n");
  fprintf($fp, "uname=$uname\n");
  fclose($fp);
}

/* Open for create/write and lock. */
$db = dba_open($dbfile, "cd", "db4");
if ($db == FALSE) {
  fatal("Cannot open database");
}

/*
 * If this identity already has a card, invalidate the card by deleting
 * the mappings.
 */
if (($old_card_id = dba_fetch($identity, $db)) != FALSE) {
  if (dba_delete($identity, $db) == FALSE) {
    fatal("Cannot delete existing record for $identity");
  }
  if (dba_delete($old_card_id, $db) == FALSE) {
    fatal("Cannot delete existing record for $old_card_id");
  }
}

/*
 * Map the DACS identity to the CardId
 */
if (dba_replace($identity, $card_id, $db) == FALSE) {
  fatal("Cannot store new record for $identity");
}

/*
 * Map the CardId to the DACS identity
 */
if (dba_replace($card_id, $identity, $db) == FALSE) {
  fatal("Cannot store new record for $card_id");
}

if (dba_sync($db) == FALSE) {
  fatal("dba_sync() failed");
}

dba_close($db);

/*
 * Last thing... emit the card's claim definitions
 */
print "<?xml version='1.0' encoding='US-ASCII'?>\n";
print "<card_defs>\n";

/*
 * This should probably be an array with type/name/label/description fields
 */
print "<claim_def type='dacs' name='dacs_identity' label='DACS Identity' description='The user%27s DACS identity' />\n";

print "</card_defs>\n";

exit(0);
?>
