Index: libabac/abac_id.c
===================================================================
--- libabac/abac_id.c	(revision dfe6b61ee16cecd797cc73a30c11bcf4f7c4fac8)
+++ libabac/abac_id.c	(revision 2e9455f11fea0205b8b4b1306b5d0804cda72e10)
@@ -1,60 +1,73 @@
-
 /**
 **  abac_id.c
 **/
 
-#include <assert.h>
-#include <err.h>
-#include <time.h>
-
-// include the GNU extension of asprintf
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <err.h>
-
-#include "abac_internal.h"
+#include <assert.h>
+#include <time.h>
+
 #include "abac_util.h"
+#include "abac_key.h"
+#include "abac_verifier.h"
+#include "abac_util_cert.h"
 
 static int debug=0;
+
+/* load id into a session when id is being created instead
+   of when id is added into a context */
+static int early_load_id=1;
+
+/* idtypename[idtype] */
+static const char * const _idtypename[] =
+{
+  "badidtype", "keyid"
+};
+static int _idtypename_cnt=1;
+
+
+// abac_id object
+struct _abac_id_t {
+    int idtype;    /* default to string 'keyid' for now */
+    char *keyid; /* sha */
+    char *cn;
+    certificate_t *cert;
+    abac_key_t *key;
+    int refcount;
+};
 
 #define KEY_SUFFIX  "_private.pem"
 #define CERT_SUFFIX "_ID.pem"
 
-extern private_key_t *abac_key_private_key(abac_key_t *ptr);
-extern abac_key_t *abac_key_file_new(char *filename, chunk_t potato);
-extern abac_key_t *abac_key_chunk_new(chunk_t keyblob, chunk_t potato);
-extern chunk_t abac_key_chunk(abac_key_t *);
-
-static int _abac_id_set_cn(abac_id_t *id, char* cn);
-
-//
-// abac_id object
-//
-struct _abac_id_t {
-    int idtype;    /* default to string 'keyid' for now */
-
-    char *keyid; /* sha */
-    char *cn;
-
-    certificate_t *cert;
-    abac_key_t *key;
-
-    int refcount;
-};
-
+
+/* local */
+char *abac_id_keyid(abac_id_t*);
+abac_id_t *abac_id_copy(abac_id_t *id);
 /****************************************************************/
 //
 // Helper functions below
 //
-static char *_get_keyid(certificate_t *cert) {
-    // get the keyid
-    x509_t *x509 = (x509_t *)cert;
-    chunk_t keyid = x509->get_subjectKeyIdentifier(x509);
-    chunk_t string = chunk_to_hex(keyid, NULL, 0);
-    return (char *)string.ptr;
-}
-
-static char *_create_dn(char *cn) {
-
+int abac_idtype_lookup(char *type)
+{
+    int i;
+    for (i = 1; i <= _idtypename_cnt ; i++)
+        if(strcmp(type,_idtypename[i])==0)
+            return i;
+    return 0;
+}
+
+char *abac_idtype_string(int i)
+{
+    if(i > _idtypename_cnt) {
+        printf("bad idtypename idx %d\n", i);
+        panic("abac_idtype_string: went out of range on idtypename");
+    }
+    return (char*) _idtypename[i];
+}
+
+
+static char *_create_dn(char *cn)
+{
 #define DN "cn="
 
@@ -64,4 +77,51 @@
 
     return dn;
+}
+
+void abac_id_dump_from_id(abac_id_t *id)
+{
+    fprintf(stderr,"abac_id_dump_id: \n");
+    fprintf(stderr,"idtype: %d\n",id->idtype); 
+    fprintf(stderr,"keyid: %s\n",id->keyid);
+    fprintf(stderr,"cn: %s\n", id->cn);
+    fprintf(stderr,"refcount: %d\n",id->refcount);
+    if(id->key !=NULL) fprintf(stderr,"has private key\n");
+    if(id->cert !=NULL) fprintf(stderr,"has cert\n");
+}
+
+void abac_id_dump_from_cert(certificate_t *cert)
+{
+    char *ret;
+    fprintf(stderr,"abac_id_dump_from_cert: \n");
+    int rv = asprintf(&ret, "%Y", cert->get_issuer(cert));
+    fprintf(stderr,"issuer: %s\n",ret);
+    fprintf(stderr,"keyid: %s\n",cert_get_keyid(cert));
+}
+
+
+/**
+ *
+ * Preload ID into sessions' master list before being
+ * loaded into some context
+ *
+**/
+
+static int _add_into_id_credentials(abac_id_t *id)
+{
+    char *keyid=abac_id_keyid(id);
+    abac_id_credential_t *idcred=abac_id_credential_lookup(keyid);
+    if(idcred !=NULL) {
+       if(debug) fprintf(stderr,"_add_into_id_credentials: something in there for %s\n",keyid);
+       idcred=abac_id_credential_dup(idcred);
+       } else {
+          if(debug) fprintf(stderr,"_add_into_id_credentials: adding %s\n",keyid);
+          if(early_load_id) {
+             /* this id needed to be deep copyed, because it is going into our
+                session id credential list */
+             abac_id_t *nid = abac_id_copy(id);
+             idcred=abac_id_credential_new(nid);
+             abac_add_id_cred(idcred);
+          }
+    }
 }
 
@@ -76,6 +136,8 @@
     libabac_init();
 
-    identification_t *id = identification_create_from_string(dn_string);
-    if (id == NULL)
+    DEBUG_PRINTF("\n_generate_cert: id cert for cn(%s)with dn(%s)\n", cn, dn_string);
+
+    identification_t *iden = identification_create_from_string(dn_string);
+    if (iden == NULL)
         errx(1, "couldn't create ID from DN %s", dn_string);
     free(dn_string);
@@ -107,5 +169,5 @@
         BUILD_SIGNING_KEY, private,
         BUILD_PUBLIC_KEY, public,
-        BUILD_SUBJECT, id,
+        BUILD_SUBJECT, iden,
         BUILD_NOT_BEFORE_TIME, not_before,
         BUILD_NOT_AFTER_TIME, not_after,
@@ -119,5 +181,5 @@
         errx(1, "couldn't build cert :(");
 
-    DESTROY_IF(id);
+    DESTROY_IF(iden);
     DESTROY_IF(public);
     DESTROY_IF(private);
@@ -127,4 +189,10 @@
 }
 
+/* from libstrongswan, chunk.h
+chunk_t chunk_from_base64(chunk_t base64, char *buf);
+chunk_t chunk_to_base64(chunk_t chunk, char *buf);
+    chunk_t b64 = chunk_to_base64(chunk, NULL);
+    chunk_t chk = chunk_from_base64(base64, NULL); 
+*/
 #define BYTES_PER_LINE 64
 
@@ -242,10 +310,12 @@
 }
 
-certificate_t *abac_id_cert(abac_id_t *id) {
+certificate_t *abac_id_cert(abac_id_t *id)
+{
     assert(id != NULL);
     return id->cert;
 }
 
-private_key_t *abac_id_privkey(abac_id_t *id) {
+private_key_t *abac_id_privkey(abac_id_t *id)
+{
     assert(id != NULL);
     if(id->key !=0)
@@ -256,13 +326,27 @@
 abac_key_t *abac_id_keyptr(abac_id_t *id)
 {
+    assert(id!=NULL);
     return id->key;
 }
 
-int abac_id_has_privkey(abac_id_t *id) {
-    if(id->key !=0)
+int abac_id_has_privkey(abac_id_t *id)
+{
+    if(id && id->key !=0)
        return 1;
     return 0;
 }
 
+// convert a chunk to a lowercase binary string
+// malloc's the string
+static char *_chunk_to_string(chunk_t chunk) {
+    int i;
+
+    char *ret = abac_xmalloc(chunk.len * 2 + 1);
+
+    for (i = 0; i < chunk.len; ++i)
+        sprintf(ret + 2 * i, "%02x", chunk.ptr[i]);
+
+    return ret;
+}
 
 /**
@@ -276,5 +360,4 @@
     if(rc) {
         _encode_base64(out, encoding);
-        free(encoding.ptr);
     }
 }
@@ -321,5 +404,6 @@
  * Copy an abac ID. Actually just increases its reference count.
  */
-abac_id_t *abac_id_dup(abac_id_t *id) {
+abac_id_t *abac_id_dup(abac_id_t *id)
+{
     if(id)
         ++id->refcount;
@@ -328,6 +412,9 @@
 
 void abac_id_free(abac_id_t *id) {
+
     if (id == NULL)
         return;
+
+    DEBUG_PRINTF("\nabac_id_free: deleting id with cn(%s)with sha(%s) at(%ld)\n", id->cn, id->keyid, (long)id);
 
     --id->refcount;
@@ -335,10 +422,11 @@
         return;
 
-    if(debug)
-        fprintf(stderr,"making abac_id_free call on (%s)!!!\n", id->cn);
     // free once the reference count reaches 0
     DESTROY_IF(id->cert);
 
-    if(id->key) abac_key_free(id->key);
+    if(id->key) {
+         DEBUG_PRINTF("abac_id_free: deleting id with cn(%s)at(%ld)key(%ld)\n", id->cn, (long)id, (long)id->key);
+         abac_key_free(id->key);
+    }
 
     free(id->keyid);
@@ -384,4 +472,8 @@
 certificate_t *cert)
 {
+if(debug)
+   fprintf(stderr,"abac_id_new, keyid(%s), cn(%s) keyid from cert(%s)\n",
+           keyid,cn, cert_get_keyid(cert));
+
     abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
     id->idtype = idtype;
@@ -391,8 +483,40 @@
     id->key = NULL;
     id->refcount = 1;
-    if(debug) fprintf(stderr,"abac_id_new: made a new id, %ld\n",(long) id);
+    _add_into_id_credentials(id);
     return id;
 }
 
+static certificate_t *_certificate_copy(certificate_t *cert)
+{
+    chunk_t encoding = chunk_empty;
+    int rc=cert->get_encoding(cert,CERT_ASN1_DER,&encoding);
+    certificate_t *ncert = cert_get_id_cert_from_chunk(encoding);
+    return ncert;
+}
+
+/*
+    hard duplicate of an id 
+    This is used by the libabac interface for case the where
+    abac_context_load_id(abac_id_t *id) is called. We want
+    the structure being kept in libabac to be locally held
+    so that we are not subject to destructor being called on
+    the structure by some other system or being called in
+    certain way that is not fully controlled by libabac.
+*/
+abac_id_t *abac_id_copy(abac_id_t *id)
+{
+    assert(id);
+    abac_id_t *nid = abac_xmalloc(sizeof(abac_id_t));
+    nid->idtype = id->idtype;
+    nid->keyid = abac_xstrdup(id->keyid);
+    nid->cn = abac_xstrdup(id->cn);
+    nid->cert = _certificate_copy(id->cert);
+    if(id->key)
+        nid->key = abac_key_copy(id->key); 
+        else nid->key=NULL;
+    nid->refcount = id->refcount+1;
+    return nid;
+}
+
 abac_id_t *abac_id_keyid_new(char *keyid, char *cn, certificate_t *cert)
 {
@@ -400,5 +524,6 @@
 }
 
-static abac_id_t *_abac_id_from_cert(certificate_t *cert) {
+static abac_id_t *_abac_id_from_cert(certificate_t *cert)
+{
     abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
     id->idtype = e_KEYID;
@@ -408,5 +533,5 @@
     id->key = NULL;
 
-    id->keyid = _get_keyid(id->cert);
+    id->keyid = cert_get_keyid(id->cert);
     // get the CN from the cert
     id_part_t type;
@@ -435,5 +560,5 @@
 
     id->refcount = 1;
-
+    _add_into_id_credentials(id);
     return id;
 }
@@ -449,13 +574,7 @@
 
     libabac_init();
-    certificate_t *cert = lib->creds->create(lib->creds,
-        CRED_CERTIFICATE, CERT_X509,
-        BUILD_FROM_FILE, filename,
-        BUILD_X509_FLAG, X509_AA,
-        BUILD_END
-    );
-
-    if (cert == NULL)
-        return NULL;
+    certificate_t *cert = cert_get_id_cert_from_file(filename);
+
+    if (cert == NULL) return NULL;
 
     return _abac_id_from_cert(cert);
@@ -465,16 +584,10 @@
  * Create an ID cert from a chunk.
  */
-abac_id_t *abac_id_from_chunk(abac_chunk_t achunk) {
+abac_id_t *abac_id_from_chunk(abac_chunk_t achunk)
+{
     chunk_t chunk = { .ptr = achunk.ptr, .len = achunk.len };
-
-    certificate_t *cert = lib->creds->create(lib->creds,
-        CRED_CERTIFICATE, CERT_X509,
-        BUILD_BLOB_ASN1_DER, chunk,
-        BUILD_X509_FLAG, X509_AA,
-        BUILD_END
-    );
-
-    if (cert == NULL)
-        return NULL;
+    certificate_t *cert = cert_get_id_cert_from_chunk(chunk);
+
+    if (cert == NULL) return NULL;
 
     return _abac_id_from_cert(cert);
@@ -491,5 +604,5 @@
         return ABAC_ID_GENERATE_INVALID_CN;
 
-    if(debug) fprintf(stderr,"abac_id_generate: generating id with cn(%s)\n",cn);
+    DEBUG_PRINTF("abac_id_generate: generating id with cn(%s)\n",cn);
 
     if (validity < 0)
@@ -506,7 +619,8 @@
     id->key = abac_key_generate();
     id->cert = _generate_cert(id->key, cn, validity);
-    id->keyid = _get_keyid(id->cert);
+    id->keyid = cert_get_keyid(id->cert);
 
     id->refcount = 1;
+    _add_into_id_credentials(id);
 
     *ret = id;
@@ -550,16 +664,29 @@
     id->key = abac_key_file_new(filename,pp);
     id->cert = _generate_cert(id->key, cn, validity);
-    id->keyid = _get_keyid(id->cert);
+    id->keyid = cert_get_keyid(id->cert);
 
     id->refcount = 1;
-
+    _add_into_id_credentials(id);
     *ret = id;
     return ABAC_ID_SUCCESS;
 }
 
+/* special handling, need to update the key of the id copy stored in
+   session's id credential list */
+static void _load_privkey_to_master_list(char *keyid, abac_key_t *key)
+{
+    abac_id_credential_t *idcred=abac_id_credential_lookup(keyid);
+    if(idcred==NULL) {
+        panic(1,"_load_privkey_to_master_list: missing id in masterlist(%s)\n", keyid);
+    }
+    abac_id_t *id=abac_id_credential_id(idcred);
+    id->key = abac_key_copy(key);
+}
+
 int abac_id_load_privkey_file(abac_id_t *ptr, char *keyfile)
 {
     assert(ptr);
     ptr->key=abac_key_file_new(keyfile, chunk_empty);
+    _load_privkey_to_master_list(abac_id_keyid(ptr), ptr->key);
     return 1;
 }
@@ -570,4 +697,5 @@
     chunk_t pp=extract_potato(keyfile,pfile);
     ptr->key=abac_key_file_new(keyfile, pp);
+    _load_privkey_to_master_list(abac_id_keyid(ptr), ptr->key);
     return 1;
 }
@@ -577,6 +705,5 @@
     assert(ptr);
     ptr->key=abac_key_chunk_new(keychunk, chunk_empty);
-    if(debug)
-        print_abac_key("after abac_id_load_privkey_chunk", ptr->key);
+    _load_privkey_to_master_list(abac_id_keyid(ptr), ptr->key);
     return 1;
 }
@@ -587,4 +714,5 @@
     chunk_t pp=extract_potato(NULL,pfile);
     ptr->key=abac_key_chunk_new(keychunk, pp);
+    _load_privkey_to_master_list(abac_id_keyid(ptr), ptr->key);
     return 1;
 }
