LCOV - code coverage report
Current view: top level - zxid - zxidmeta.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 307 431 71.2 %
Date: 2010-12-19 Functions: 27 32 84.4 %
Branches: 161 390 41.3 %

           Branch data     Line data    Source code
       1                 :            : /* zxidmeta.c  -  Handwritten functions for metadata parsing and generation as well as CoT handling
       2                 :            :  * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
       4                 :            :  * Author: Sampo Kellomaki (sampo@iki.fi)
       5                 :            :  * This is confidential unpublished proprietary source code of the author.
       6                 :            :  * NO WARRANTY, not even implied warranties. Contains trade secrets.
       7                 :            :  * Distribution prohibited unless authorized in writing.
       8                 :            :  * Licensed under Apache License 2.0, see file COPYING.
       9                 :            :  * $Id: zxidmeta.c,v 1.59 2009-11-24 23:53:40 sampo Exp $
      10                 :            :  *
      11                 :            :  * The CoT cache exists both on disk as directory /var/zxid/cot and in
      12                 :            :  * memory as the field cf->cot. The latter is protected by cf->mx lock.
      13                 :            :  * The entities in cache are essentially read only, i.e. once the head
      14                 :            :  * of the list cf->cot has been dereferenced in a thread safe way,
      15                 :            :  * the entity pointers themselves can be passed around threads with
      16                 :            :  * impunity. No locking needed for them.
      17                 :            :  *
      18                 :            :  * 12.8.2006,  created --Sampo
      19                 :            :  * 12.10.2007, mild refactoring to process keys for xenc as well. --Sampo
      20                 :            :  * 13.12.2007, fixed missing KeyDescriptor/@use as seen in CA IdP metadata --Sampo
      21                 :            :  * 14.4.2008,  added SimpleSign --Sampo
      22                 :            :  * 7.10.2008,  added documentation --Sampo
      23                 :            :  * 1.2.2010,   removed arbitrary size limit --Sampo
      24                 :            :  * 12.2.2010,  added pthread locking --Sampo
      25                 :            :  */
      26                 :            : 
      27                 :            : #include "platform.h"  /* for dirent.h */
      28                 :            : 
      29                 :            : #include <fcntl.h>
      30                 :            : #include <string.h>
      31                 :            : #include <stdio.h>
      32                 :            : #include <stdlib.h>
      33                 :            : #include <errno.h>
      34                 :            : #include <sys/types.h>
      35                 :            : #include <sys/stat.h>
      36                 :            : 
      37                 :            : #ifdef USE_OPENSSL
      38                 :            : #include <openssl/sha.h>
      39                 :            : #include <openssl/x509.h>
      40                 :            : #include <openssl/rsa.h>
      41                 :            : #endif
      42                 :            : 
      43                 :            : #include "errmac.h"
      44                 :            : #include "saml2.h"
      45                 :            : #include "zxid.h"
      46                 :            : #include "zxidutil.h"
      47                 :            : #include "zxidconf.h"
      48                 :            : #include "c/zx-const.h"
      49                 :            : #include "c/zx-ns.h"
      50                 :            : #include "c/zx-data.h"
      51                 :            : 
      52                 :            : /* ============== CoT and Metadata of Others ============== */
      53                 :            : 
      54                 :            : /*() Process certificates (public keys) from a metadata for entity.
      55                 :            :  * Since one entity can be both IdP and SP, this function may
      56                 :            :  * be called twice per entity, with different kd argument. */
      57                 :            : 
      58                 :            : /* Called by:  zxid_mk_ent x2 */
      59                 :            : static void zxid_process_keys(zxid_conf* cf, zxid_entity* ent, struct zx_md_KeyDescriptor_s* kd, char* logkey)
      60                 :        985 : {
      61                 :            :   int len;
      62                 :            :   char* pp;
      63                 :            :   char* p;
      64                 :            :   char* e;
      65                 :            :   X509* x;
      66                 :            : 
      67                 :            :   for (;
      68   [ +  -  +  + ]:       3854 :        kd && kd->gg.g.tok == zx_md_KeyDescriptor_ELEM;
      69                 :       1884 :        kd = (struct zx_md_KeyDescriptor_s*)kd->gg.g.n) {
      70   [ +  -  +  -  :       1904 :     if (!kd->KeyInfo || !kd->KeyInfo->X509Data || !ZX_GET_CONTENT(kd->KeyInfo->X509Data->X509Certificate)) {
          +  -  +  -  -  
                      + ]
      71                 :          0 :       ERR("KeyDescriptor for %s missing essential subelements KeyInfo=%p", logkey, kd->KeyInfo);
      72                 :          0 :       return;
      73                 :            :     }
      74   [ +  -  +  -  :       1904 :     p = ZX_GET_CONTENT_S(kd->KeyInfo->X509Data->X509Certificate);
                   +  - ]
      75   [ +  -  +  -  :       1904 :     len = ZX_GET_CONTENT_LEN(kd->KeyInfo->X509Data->X509Certificate);
                   +  - ]
      76                 :       1904 :     e = p + len;
      77                 :       1904 :     pp = ZX_ALLOC(cf->ctx, SIMPLE_BASE64_PESSIMISTIC_DECODE_LEN(e-p));
      78                 :       1904 :     e = unbase64_raw(p, e, pp, zx_std_index_64);
      79                 :       1904 :     x = 0;  /* Forces d2i_X509() to alloc the memory. */
      80   [ +  -  -  + ]:       1904 :     if (!d2i_X509(&x, (const unsigned char**)&pp /* *** compile warning */, e-pp) || !x) {
      81                 :          0 :       ERR("DER decoding of X509 certificate for %s failed. use(%.*s)", logkey, kd->use->g.len, kd->use->g.s);
      82   [ #  #  #  # ]:          0 :       D("Extracted %s base64 form of cert(%.*s)", logkey, len, p);
      83                 :          0 :       return;
      84                 :            :     }
      85         [ +  + ]:       1904 :     if (!kd->use) {
      86                 :         20 :       ent->sign_cert = x;
      87                 :         20 :       ent->enc_cert = x;
      88   [ +  +  -  + ]:         20 :       D("KeyDescriptor is missing use attribute. Assume this certificate can be used for both signing and encryption. %d", 0);
      89                 :         20 :       return;
      90                 :            :     }
      91         [ +  + ]:       1884 :     if (!memcmp("signing", kd->use->g.s, kd->use->g.len)) {
      92                 :        965 :       ent->sign_cert = x;
      93                 :            :       DD("Extracted %s sign cert(%.*s)", logkey, len, p);
      94         [ +  - ]:        919 :     } else if (!memcmp("encryption", kd->use->g.s, kd->use->g.len)) {
      95                 :        919 :       ent->enc_cert = x;
      96                 :            :       DD("Extracted %s enc cert(%.*s)", logkey, len, p);
      97                 :            :     } else {
      98                 :          0 :       ERR("Unknown key use(%.*s)", kd->use->g.len, kd->use->g.s);
      99   [ #  #  #  # ]:          0 :       D("Extracted %s cert(%.*s)", logkey, len, p);
     100                 :            :     }
     101                 :            :   }
     102                 :            : }
     103                 :            : 
     104                 :            : /* Called by:  zxid_parse_meta x2 */
     105                 :            : static zxid_entity* zxid_mk_ent(zxid_conf* cf, struct zx_md_EntityDescriptor_s* ed)
     106                 :        717 : {
     107                 :        717 :   zxid_entity* ent = ZX_ZALLOC(cf->ctx, zxid_entity);
     108                 :        717 :   ent->ed = ed;
     109         [ +  - ]:        717 :   if (!ed->entityID)
     110                 :          0 :     goto bad_md;
     111                 :        717 :   ent->eid = zx_str_to_c(cf->ctx, &ed->entityID->g);
     112                 :        717 :   sha1_safe_base64(ent->sha1_name, ed->entityID->g.len, ent->eid);
     113                 :        717 :   ent->sha1_name[27] = 0;
     114                 :            :   
     115   [ +  +  +  -  :        717 :   if (ed->Organization && ZX_GET_CONTENT(ed->Organization->OrganizationDisplayName))
             +  -  +  - ]
     116   [ +  -  +  -  :        311 :     ent->dpy_name = zx_str_to_c(cf->ctx,ZX_GET_CONTENT(ed->Organization->OrganizationDisplayName));
                   +  - ]
     117                 :            :   
     118         [ +  + ]:        717 :   if (ed->IDPSSODescriptor)
     119                 :        374 :     zxid_process_keys(cf, ent, ed->IDPSSODescriptor->KeyDescriptor, "IDP SSO");
     120         [ +  + ]:        717 :   if (ed->SPSSODescriptor)
     121                 :        611 :     zxid_process_keys(cf, ent, ed->SPSSODescriptor->KeyDescriptor, "SP SSO");
     122                 :            : 
     123                 :        717 :   return ent;
     124                 :          0 :  bad_md:
     125                 :          0 :   ERR("Bad metadata. EntityDescriptor was corrupt. %d", 0);
     126                 :          0 :   zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "B", "BADMD", 0, "");
     127                 :          0 :   return 0;
     128                 :            : }
     129                 :            : 
     130                 :            : /*() Parse Metadata, see [SAML2meta]. This function is quite low level
     131                 :            :  * and assumes it is processing a buffer (which may contain multiple
     132                 :            :  * instances of various metadata).
     133                 :            :  *
     134                 :            :  * cf:: ZXID configuration object, used here mainly for memory allocation
     135                 :            :  * md:: Value-result parameter. Pointer to char pointer pointing to the
     136                 :            :  *     beginning of the metadata. As metadata is scanned and parsed, this
     137                 :            :  *     pointer will be advanced
     138                 :            :  * lim:: End of the metadata buffer
     139                 :            :  * return:: Entity data structure composed from the metadata. If more than
     140                 :            :  *     one EntityDescriptor is found, then a linked list is returned. */
     141                 :            : 
     142                 :            : /* Called by:  zxid_addmd, zxid_get_ent_file, zxid_get_meta, zxid_lscot_line */
     143                 :            : zxid_entity* zxid_parse_meta(zxid_conf* cf, char** md, char* lim)
     144                 :        719 : {
     145                 :            :   zxid_entity* ee;
     146                 :            :   zxid_entity* ent;
     147                 :            :   struct zx_md_EntityDescriptor_s* ed;
     148                 :            :   struct zx_root_s* r;
     149                 :            : 
     150                 :        719 :   r = zx_dec_zx_root(cf->ctx, lim-*md, *md, "parse meta");  /* *** n_decode=5 */
     151                 :        719 :   *md = (char*)cf->ctx->p;
     152         [ -  + ]:        719 :   if (!r)
     153                 :          0 :     return 0;
     154         [ +  + ]:        719 :   if (r->EntityDescriptor) {
     155                 :        717 :     ed = r->EntityDescriptor;
     156                 :        717 :     ZX_FREE(cf->ctx, r);  /* N.B Shallow free only, do not free the descriptor. */
     157                 :        717 :     return zxid_mk_ent(cf, ed);
     158         [ -  + ]:          2 :   } else if (r->EntitiesDescriptor) {
     159         [ #  # ]:          0 :     if (!r->EntitiesDescriptor->EntityDescriptor)
     160                 :          0 :       goto bad_md;
     161                 :          0 :     for (ed = r->EntitiesDescriptor->EntityDescriptor;
     162   [ #  #  #  # ]:          0 :          ed && ed->gg.g.tok == zx_md_EntityDescriptor_ELEM;
     163                 :          0 :          ed = (struct zx_md_EntityDescriptor_s*)ZX_NEXT(ed)) {
     164                 :          0 :       ent = zxid_mk_ent(cf, ed);
     165                 :          0 :       ent->n = ee;
     166                 :          0 :       ee = ent;
     167                 :            :     }
     168                 :          0 :     ZX_FREE(cf->ctx, r->EntitiesDescriptor);
     169                 :          0 :     ZX_FREE(cf->ctx, r);  /* N.B Shallow free only, do not free the descriptors. */
     170                 :          0 :     return ee;
     171                 :            :   }  
     172                 :          2 :  bad_md:
     173                 :          2 :   ERR("Bad metadata. EntityDescriptor could not be found or was corrupt. MD(%.*s) %d chars parsed.", lim-cf->ctx->bas, cf->ctx->bas, *md - cf->ctx->bas);
     174                 :          2 :   zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "B", "BADMD", 0, "chars_parsed(%d)", *md - cf->ctx->bas);
     175                 :          2 :   zx_free_elem(cf->ctx, &r->gg, 0);
     176                 :          2 :   return 0;
     177                 :            : }
     178                 :            : 
     179                 :            : /*() Write metadata of an entity to the Circle of Trust (CoT) cache of
     180                 :            :  * the entity identified by cf. Mainly used by Auto-CoT. */
     181                 :            : 
     182                 :            : /* Called by:  opt x3, zxid_get_ent_ss */
     183                 :            : int zxid_write_ent_to_cache(zxid_conf* cf, zxid_entity* ent)
     184                 :          0 : {
     185                 :            :   struct zx_str* ss;
     186                 :          0 :   fdtype fd = open_fd_from_path(O_CREAT | O_WRONLY | O_TRUNC, 0666, "write_ent_to_cache", 1, "%s" ZXID_COT_DIR "%s", cf->path, ent->sha1_name);
     187         [ #  # ]:          0 :   if (fd == BADFD) {
     188                 :          0 :     perror("open metadata for writing metadata to cache");
     189                 :          0 :     ERR("Failed to open file for writing: sha1_name(%s) to metadata cache", ent->sha1_name);
     190                 :          0 :     return 0;
     191                 :            :   }
     192                 :            :   
     193                 :          0 :   ss = zx_easy_enc_elem_opt(cf, &ent->ed->gg);
     194         [ #  # ]:          0 :   if (!ss)
     195                 :          0 :     return 0;
     196                 :          0 :   write_all_fd(fd, ss->s, ss->len);
     197                 :          0 :   zx_str_free(cf->ctx, ss);
     198                 :          0 :   close_file(fd, (const char*)__FUNCTION__);
     199                 :          0 :   return 1;
     200                 :            : }
     201                 :            : 
     202                 :            : /*() Read metadata from a file.
     203                 :            :  *
     204                 :            :  * Usually the file will be named according to "sha1 name", which
     205                 :            :  * is safe base64 encoded SHA1 digest hash over the EntityID. This
     206                 :            :  * is used to ensure unique file name for each entity. However,
     207                 :            :  * this function will in fact read from any file name supplied.
     208                 :            :  * If the file contains multiple EntityDescriptor elements, they
     209                 :            :  * are all added to the cot. Also EntitiesDesciptor is handled.
     210                 :            :  *
     211                 :            :  * See also zxid_get_ent_cache() which will compute the sha1_name
     212                 :            :  * and then read the metadata. */
     213                 :            : 
     214                 :            : /* Called by:  main x3, test_ibm_cert_problem_enc_dec, zxid_get_ent_by_sha1_name, zxid_get_ent_cache, zxid_load_cot_cache_from_file */
     215                 :            : zxid_entity* zxid_get_ent_file(zxid_conf* cf, char* sha1_name)
     216                 :        925 : {
     217                 :            :   int n, got, siz;
     218                 :            :   fdtype fd;
     219                 :            :   char* md_buf;
     220                 :            :   char* p;
     221                 :        925 :   zxid_entity* first = 0;
     222                 :            :   zxid_entity* ent;
     223                 :            :   zxid_entity* ee;
     224                 :            :   
     225                 :            :   DD("sha1_name(%s)", sha1_name);
     226                 :        925 :   fd = open_fd_from_path(O_RDONLY, 0, "get_ent_file", 1,
     227                 :            :                          "%s" ZXID_COT_DIR "%s", cf->path, sha1_name);
     228         [ +  + ]:        925 :   if (fd == BADFD) {
     229                 :        308 :     perror("open metadata to read");
     230   [ +  +  -  + ]:        308 :     D("No metadata file found for sha1_name(%s)", sha1_name);
     231                 :        308 :     return 0;
     232                 :            :   }
     233                 :        617 :   siz = get_file_size(fd);
     234                 :        617 :   md_buf = ZX_ALLOC(cf->ctx, siz+1);
     235                 :        617 :   n = read_all_fd(fd, md_buf, siz, &got);
     236                 :            :   DD("==========sha1_name(%s)", sha1_name);
     237         [ +  - ]:        617 :   if (n == -1)
     238                 :          0 :     goto readerr;
     239                 :        617 :   close_file(fd, (const char*)__FUNCTION__);
     240                 :            : 
     241                 :            :   DD("md_buf(%.*s) got=%d siz=%d md_buf(%s)", got, md_buf, got, siz, sha1_name);
     242                 :            :   
     243                 :        617 :   p = md_buf;
     244         [ +  + ]:       1851 :   while (p < md_buf+got) {   /* Loop over concatenated descriptors. */
     245                 :        618 :     ent = zxid_parse_meta(cf, &p, md_buf+got);
     246         [ +  + ]:        618 :     if (!first)
     247                 :        617 :       first = ent;
     248                 :            :     DD("++++++++++++sha1_name(%s)", sha1_name);
     249         [ +  + ]:        618 :     if (!ent) {
     250                 :          1 :       ZX_FREE(cf->ctx, md_buf);
     251                 :          1 :       ERR("***** Parsing metadata failed for sha1_name(%s)", sha1_name);
     252                 :          1 :       return first;
     253                 :            :     }
     254   [ -  +  #  # ]:        617 :     LOCK(cf->mx, "add ent to cot");
     255         [ +  + ]:       1851 :     while (ent) {
     256                 :        617 :       ee = ent->n;
     257                 :        617 :       ent->n = cf->cot;
     258                 :        617 :       cf->cot = ent;
     259                 :        617 :       ent = ee;
     260                 :            :     }
     261   [ -  +  #  # ]:        617 :     UNLOCK(cf->mx, "add ent to cot");
     262   [ +  +  +  -  :        617 :     D("GOT META sha1_name(%s) eid(%s)", sha1_name, first?first->eid:"?");
                   -  + ]
     263                 :            :   }
     264                 :        616 :   return first;
     265                 :            : 
     266                 :          0 : readerr:
     267                 :          0 :   perror("read metadata");
     268   [ #  #  #  # ]:          0 :   D("Failed to read metadata for sha1_name(%s)", sha1_name);
     269                 :          0 :   close_file(fd, (const char*)__FUNCTION__);
     270                 :          0 :   return 0;
     271                 :            : }
     272                 :            : 
     273                 :            : /*LOCK_STATIC(zxid_ent_cache_mx);*/
     274                 :            : extern pthread_mutex_t zxid_ent_cache_mx;
     275                 :            : 
     276                 :            : /* Called by:  zxid_get_ent_cache, zxid_load_cot_cache */
     277                 :            : static void zxid_load_cot_cache_from_file(zxid_conf* cf)
     278                 :        702 : {
     279                 :            :   zxid_entity* ee;  
     280         [ +  - ]:        702 :   if (!cf->load_cot_cache)
     281                 :        702 :     return;
     282   [ #  #  #  # ]:          0 :   LOCK(zxid_ent_cache_mx, "get ent from cache");
     283   [ #  #  #  # ]:          0 :   LOCK(cf->mx, "check cot");
     284                 :          0 :   ee = cf->cot;
     285   [ #  #  #  # ]:          0 :   UNLOCK(cf->mx, "check cot");
     286         [ #  # ]:          0 :   if (!ee) {
     287   [ #  #  #  # ]:          0 :     D("Loading cot cache from(%s)", cf->load_cot_cache);
     288                 :          0 :     zxid_get_ent_file(cf, cf->load_cot_cache);
     289   [ #  #  #  # ]:          0 :     D("CoT cache loaded from(%s)", cf->load_cot_cache);
     290                 :            :   }
     291   [ #  #  #  # ]:          0 :   UNLOCK(zxid_ent_cache_mx, "get ent from cache");
     292                 :            : }
     293                 :            : 
     294                 :            : /*() Search cot datastructure by entity id. Failing to find,
     295                 :            :  * compute sha1_name for an entity and then read the metadata from
     296                 :            :  * the CoT metadata cache directory, e.g. /var/zxid/cot */
     297                 :            : 
     298                 :            : /* Called by:  main x5, zxid_get_ent_ss x3 */
     299                 :            : zxid_entity* zxid_get_ent_cache(zxid_conf* cf, struct zx_str* eid)
     300                 :        681 : {
     301                 :            :   zxid_entity* ent;
     302                 :            :   char sha1_name[28];
     303                 :        681 :   zxid_load_cot_cache_from_file(cf);
     304         [ +  + ]:       1950 :   for (ent = cf->cot; ent; ent = ent->n)  /* Check in memory cache. */
     305   [ +  +  +  + ]:       1352 :     if (eid->len == strlen(ent->eid) && !memcmp(eid->s, ent->eid, eid->len)) {
     306   [ +  +  -  + ]:         83 :       D("GOT FROM MEM eid(%s)", ent->eid);
     307                 :         83 :       return ent;
     308                 :            :     }
     309                 :        598 :   sha1_safe_base64(sha1_name, eid->len, eid->s);
     310                 :        598 :   sha1_name[27] = 0;
     311                 :        598 :   return zxid_get_ent_file(cf, sha1_name);
     312                 :            : }
     313                 :            : 
     314                 :            : /*(i) Get metadata for entity, either from cache or network (using WKL), depending
     315                 :            :  * on configuration options. Main work horse for getting entity metadata.
     316                 :            :  *
     317                 :            :  * cf:: ZXID configuration object
     318                 :            :  * eid:: Entity ID whose metadata is desired
     319                 :            :  * return:: Entity data structure, including the metadata */
     320                 :            : 
     321                 :            : /* Called by:  a7n_test, x509_test, zxid_add_fed_tok2epr, zxid_chk_sig, zxid_decode_redir_or_post, zxid_get_ent, zxid_get_ses_idp, zxid_idp_dispatch, zxid_idp_sso, zxid_imreq, zxid_simple_idp_show_an, zxid_slo_resp_redir, zxid_sp_dispatch, zxid_sp_sso_finalize, zxid_ssos_anreq, zxid_wsc_valid_re_env, zxid_wsf_validate_a7n, zxid_wsp_validate_env */
     322                 :            : zxid_entity* zxid_get_ent_ss(zxid_conf* cf, struct zx_str* eid)
     323                 :        528 : {
     324                 :            :   zxid_entity* old_cot;
     325                 :            :   zxid_entity* ent;
     326                 :            :   zxid_entity* ee;
     327                 :        528 :   zxid_entity* match = 0;
     328                 :            :   
     329   [ +  +  -  + ]:        528 :   D("eid(%.*s) path(%.*s) cf->magic=%x, md_cache_first(%d), cot(%p)", eid->len, eid->s, cf->path_len, cf->path, cf->magic, cf->md_cache_first, cf->cot);
     330         [ +  - ]:        528 :   if (cf->md_cache_first) {
     331                 :        528 :     ent = zxid_get_ent_cache(cf, eid);
     332         [ +  + ]:        528 :     if (ent)
     333                 :        375 :       return ent;
     334                 :            :   }
     335                 :            :   
     336         [ +  - ]:        153 :   if (cf->md_fetch) {
     337                 :        153 :     ent = zxid_get_meta_ss(cf, eid);
     338         [ -  + ]:        153 :     if (ent) {
     339   [ #  #  #  # ]:          0 :       LOCK(cf->mx, "read cot");
     340                 :          0 :       old_cot = cf->cot;
     341   [ #  #  #  # ]:          0 :       UNLOCK(cf->mx, "read cot");
     342         [ #  # ]:          0 :       while (ent) {
     343   [ #  #  #  # ]:          0 :         if (eid->len == strlen(ent->eid) && !memcmp(eid->s, ent->eid, eid->len)) {
     344                 :          0 :           match = ent;
     345                 :            :         }
     346                 :            :         /* Check whether entity is already in the cache. */
     347         [ #  # ]:          0 :         if (zxid_get_ent_cache(cf, &ent->ed->entityID->g)) {
     348                 :          0 :           INFO("While fetching metadata for eid(%.*s) got metadata for eid(%s), but the metadata was already in the cache. New metadata ignored.", eid->len, eid->s, ent->eid);
     349                 :          0 :           ent = ent->n;
     350                 :            :         } else {
     351                 :          0 :           INFO("While fetching metadata for eid(%.*s) got metadata for eid(%s). New metadata cached.", eid->len, eid->s, ent->eid);
     352                 :          0 :           ee = ent->n;
     353   [ #  #  #  # ]:          0 :           LOCK(cf->mx, "add fetched ent to cot");
     354                 :          0 :           ent->n = cf->cot;
     355                 :          0 :           cf->cot = ent;
     356   [ #  #  #  # ]:          0 :           UNLOCK(cf->mx, "add fetched ent to cot");
     357                 :          0 :           ent = ee;
     358                 :            :         }
     359                 :            :       }
     360                 :            :       
     361         [ #  # ]:          0 :       if (cf->md_populate_cache) {
     362   [ #  #  #  # ]:          0 :         LOCK(cf->mx, "read cot");
     363                 :          0 :         ent = cf->cot;
     364   [ #  #  #  # ]:          0 :         UNLOCK(cf->mx, "read cot");
     365         [ #  # ]:          0 :         for (; ent != old_cot; ent = ent->n)
     366                 :          0 :           zxid_write_ent_to_cache(cf, ent);
     367                 :            :       }
     368         [ #  # ]:          0 :       if (match)
     369                 :          0 :         return match;
     370                 :            :     }
     371                 :            :   }
     372                 :            :   
     373         [ +  - ]:        153 :   if (cf->md_cache_last) {
     374                 :        153 :     ent = zxid_get_ent_cache(cf, eid);
     375         [ -  + ]:        153 :     if (ent)
     376                 :          0 :       return ent;
     377                 :            :   }
     378   [ +  +  -  + ]:        153 :   D("eid(%.*s) NOT FOUND", eid->len, eid->s);
     379                 :        153 :   zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "B", "NOMD", 0, "eid(%.*s)", eid->len, eid->s);
     380                 :        153 :   return 0;
     381                 :            : }
     382                 :            : 
     383                 :            : /*() Wrapper for zxid_get_ent_ss(), which see. */
     384                 :            : 
     385                 :            : /* Called by:  zxcall_main, zxid_cdc_check x2, zxid_start_sso_url */
     386                 :            : zxid_entity* zxid_get_ent(zxid_conf* cf, char* eid)
     387                 :         24 : {
     388                 :            :   struct zx_str ss;
     389         [ +  + ]:         24 :   if (!eid)
     390                 :          1 :     return 0;
     391                 :         23 :   ss.s = eid;
     392                 :         23 :   ss.len = strlen(eid);
     393                 :            :   DD("eid: (%s)", eid);
     394                 :         23 :   return zxid_get_ent_ss(cf, &ss);
     395                 :            : }
     396                 :            : 
     397                 :            : /*() Given sha1_name, check in memory cache and if not, the disk cache. Do not try net (WKL). */
     398                 :            : 
     399                 :            : /* Called by:  zxid_get_ent_by_succinct_id, zxid_load_cot_cache */
     400                 :            : zxid_entity* zxid_get_ent_by_sha1_name(zxid_conf* cf, char* sha1_name)
     401                 :        417 : {
     402                 :            :   zxid_entity* ent;
     403   [ -  +  #  # ]:        417 :   LOCK(cf->mx, "scan cache by sha1_name");
     404         [ +  + ]:       4230 :   for (ent = cf->cot; ent; ent = ent->n)  /* Check in-memory cache. */
     405         [ +  + ]:       3905 :     if (!strcmp(sha1_name, ent->sha1_name)) {
     406   [ -  +  #  # ]:         92 :       UNLOCK(cf->mx, "scan cache by sha1_name");
     407                 :         92 :       return ent;
     408                 :            :     }
     409   [ -  +  #  # ]:        325 :   UNLOCK(cf->mx, "scan cache by sha1_name");
     410                 :        325 :   ent = zxid_get_ent_file(cf, sha1_name);
     411         [ -  + ]:        325 :   if (!ent)
     412                 :          0 :     zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "B", "NOMD", 0, "sha1_name(%s)", sha1_name);
     413                 :        325 :   return ent;
     414                 :            : }
     415                 :            : 
     416                 :            : /*() In artifact profile concept of "succinct id" appears. If you have one of those,
     417                 :            :  * you canuse this function to fetch the entity metadata. Only in-memory
     418                 :            :  * and disk caches will be tried. No network connection (WKL) will be initiated. */
     419                 :            : 
     420                 :            : /* Called by:  zxid_sp_deref_art */
     421                 :            : zxid_entity* zxid_get_ent_by_succinct_id(zxid_conf* cf, char* raw_succinct_id)
     422                 :          0 : {
     423                 :            :   char sha1_name[28];
     424                 :          0 :   base64_fancy_raw(raw_succinct_id, 20, sha1_name, safe_basis_64, 1<<31, 0, 0, '.');
     425                 :          0 :   sha1_name[27] = 0;
     426                 :          0 :   return zxid_get_ent_by_sha1_name(cf, sha1_name);
     427                 :            : }
     428                 :            : 
     429                 :            : /*() Usually you will want to use the get_ent() methods if you need
     430                 :            :  * only specific entities. Loading the entire cache is expensive and
     431                 :            :  * only useful if you really need to enumerate through all
     432                 :            :  * available entities. This may be the case when rendering login
     433                 :            :  * buttons for all IdPs in a user interface.
     434                 :            :  *
     435                 :            :  * cf:: ZXID configuration object
     436                 :            :  * return:: Linked list of Entity objects (metadata) for CoT partners */
     437                 :            : 
     438                 :            : /* Called by:  main x2, zxid_idp_list_cf_cgi, zxid_mk_idp_list */
     439                 :            : zxid_entity* zxid_load_cot_cache(zxid_conf* cf)
     440                 :         21 : {
     441                 :            :   zxid_entity* ent;
     442                 :            :   struct dirent* de;
     443                 :            :   DIR* dir;
     444                 :            :   char buf[4096];
     445         [ -  + ]:         21 :   if (cf->path_len + sizeof(ZXID_COT_DIR) > sizeof(buf)) {
     446                 :          0 :    ERR("Too long path(%.*s) for config dir. Has %d chars. Max allowed %d. (config problem)",
     447                 :            :         cf->path_len, cf->path, cf->path_len, sizeof(buf) - sizeof(ZXID_COT_DIR));
     448                 :          0 :     return 0;
     449                 :            :   }
     450                 :         21 :   memcpy(buf, cf->path, cf->path_len);
     451                 :         21 :   memcpy(buf + cf->path_len, ZXID_COT_DIR, sizeof(ZXID_COT_DIR));
     452                 :            : 
     453                 :         21 :   zxid_load_cot_cache_from_file(cf);
     454                 :            :   
     455                 :         21 :   dir = opendir(buf);
     456         [ -  + ]:         21 :   if (!dir) {
     457                 :          0 :     perror("opendir for /var/zxid/cot (or other if configured) for loading cot cache");
     458                 :          0 :     ERR("opendir failed path(%s) uid=%d gid=%d", buf, geteuid(), getegid());
     459                 :          0 :     return 0;
     460                 :            :   }
     461                 :            :   
     462         [ +  + ]:        521 :   while (de = readdir(dir))
     463   [ +  +  +  + ]:        479 :     if (de->d_name[0] != '.' && de->d_name[strlen(de->d_name)-1] != '~')
     464                 :        417 :       zxid_get_ent_by_sha1_name(cf, de->d_name);
     465                 :            :   
     466                 :            :   DD("HERE %p", cf);
     467                 :         21 :   closedir(dir);
     468                 :            : 
     469   [ -  +  #  # ]:         21 :   LOCK(cf->mx, "return cot");
     470                 :         21 :   ent = cf->cot;
     471   [ -  +  #  # ]:         21 :   UNLOCK(cf->mx, "return cot");
     472                 :         21 :   return ent;
     473                 :            : }
     474                 :            : 
     475                 :            : /* ============== Our Metadata ============== */
     476                 :            : 
     477                 :            : /*() Generate XML-DSIG key info given X509 certificate. */
     478                 :            : 
     479                 :            : /* Called by:  zxenc_pubkey_enc, zxid_key_desc */
     480                 :            : struct zx_ds_KeyInfo_s* zxid_key_info(zxid_conf* cf, struct zx_elem_s* father, X509* x)
     481                 :        975 : {
     482                 :            :   int len;
     483                 :            :   char* dd;
     484                 :            :   char* d;
     485                 :            :   char* pp;
     486                 :            :   char* p;
     487                 :        975 :   struct zx_ds_KeyInfo_s* ki = zx_NEW_ds_KeyInfo(cf->ctx, father);
     488                 :        975 :   ki->X509Data = zx_NEW_ds_X509Data(cf->ctx, &ki->gg);
     489                 :            : 
     490                 :            : #ifdef USE_OPENSSL
     491                 :            :   /* Build PEM encoding (which is base64 of the DER encoding + header and footer) */
     492                 :            :   
     493                 :        975 :   len = i2d_X509(x, 0);  /* Length of the DER encoding */
     494         [ -  + ]:        975 :   if (len <= 0) {
     495                 :          0 :     ERR("DER encoding certificate failed: %d", len);
     496                 :            :   } else {
     497                 :        975 :     dd = d = ZX_ALLOC(cf->ctx, len);
     498                 :        975 :     i2d_X509(x, (unsigned char**)&d);  /* DER encoding of the cert */
     499                 :        975 :     pp = p = ZX_ALLOC(cf->ctx, (len+4) * 4 / 3 + (len/64) + 6);    
     500                 :        975 :     p = base64_fancy_raw(dd, len, p, std_basis_64, 64, 1, "\n", '=');
     501                 :        975 :     *p = 0;
     502                 :        975 :     ki->X509Data->X509Certificate = zx_ref_len_elem(cf->ctx, &ki->X509Data->gg, zx_ds_X509Certificate_ELEM, p-pp, pp);
     503                 :            :   }
     504                 :            : #else
     505                 :            :   ERR("This copy of zxid was compiled to NOT use OpenSSL. Generating KeyInfo is not supported. Add -DUSE_OPENSSL and recompile. %d", 0);
     506                 :            : #endif
     507                 :        975 :   zx_reverse_elem_lists(&ki->gg);
     508                 :        975 :   return ki;
     509                 :            : }
     510                 :            : 
     511                 :            : /*() Generate key descriptor metadata fragment given X509 certificate [SAML2meta]. */
     512                 :            : 
     513                 :            : /* Called by:  zxid_idp_sso_desc x2, zxid_sp_sso_desc x2 */
     514                 :            : struct zx_md_KeyDescriptor_s* zxid_key_desc(zxid_conf* cf, struct zx_elem_s* father, char* use, X509* x)
     515                 :         18 : {
     516                 :         18 :   struct zx_md_KeyDescriptor_s* kd = zx_NEW_md_KeyDescriptor(cf->ctx, father);
     517                 :         18 :   kd->use = zx_ref_attr(cf->ctx, &kd->gg, zx_use_ATTR, use);
     518                 :         18 :   kd->KeyInfo = zxid_key_info(cf, &kd->gg, x);
     519                 :         18 :   zx_reverse_elem_lists(&kd->gg);
     520                 :         18 :   return kd;
     521                 :            : }
     522                 :            : 
     523                 :            : /*() Generate Artifact Resolution (AR) Descriptor idp metadata fragment [SAML2meta]. */
     524                 :            : 
     525                 :            : /* Called by:  zxid_idp_sso_desc */
     526                 :            : struct zx_md_ArtifactResolutionService_s* zxid_ar_desc(zxid_conf* cf, struct zx_elem_s* father, char* binding, char* loc, char* resp_loc)
     527                 :          0 : {
     528                 :          0 :   struct zx_md_ArtifactResolutionService_s* d = zx_NEW_md_ArtifactResolutionService(cf->ctx,father);
     529                 :          0 :   d->Binding = zx_ref_attr(cf->ctx, &d->gg, zx_Binding_ATTR, binding);
     530                 :          0 :   d->Location = zx_attrf(cf->ctx, &d->gg, zx_Location_ATTR, "%s%s", cf->url, loc);
     531         [ #  # ]:          0 :   if (resp_loc)
     532                 :          0 :     d->ResponseLocation = zx_attrf(cf->ctx, &d->gg, zx_ResponseLocation_ATTR, "%s%s", cf->url, resp_loc);
     533                 :          0 :   zx_reverse_elem_lists(&d->gg);
     534                 :          0 :   return d;
     535                 :            : }
     536                 :            : 
     537                 :            : /*() Generate Single SignOn (SSO) Descriptor idp metadata fragment [SAML2meta]. */
     538                 :            : 
     539                 :            : /* Called by:  zxid_idp_sso_desc */
     540                 :            : struct zx_md_SingleSignOnService_s* zxid_sso_desc(zxid_conf* cf, struct zx_elem_s* father, char* binding, char* loc, char* resp_loc)
     541                 :          2 : {
     542                 :          2 :   struct zx_md_SingleSignOnService_s* d = zx_NEW_md_SingleSignOnService(cf->ctx,father);
     543                 :          2 :   d->Binding = zx_ref_attr(cf->ctx, &d->gg, zx_Binding_ATTR, binding);
     544                 :          2 :   d->Location = zx_attrf(cf->ctx, &d->gg, zx_Location_ATTR, "%s%s", cf->url, loc);
     545         [ -  + ]:          2 :   if (resp_loc)
     546                 :          0 :     d->ResponseLocation = zx_attrf(cf->ctx, &d->gg, zx_ResponseLocation_ATTR, "%s%s", cf->url, resp_loc);
     547                 :          2 :   zx_reverse_elem_lists(&d->gg);
     548                 :          2 :   return d;
     549                 :            : }
     550                 :            : 
     551                 :            : /*() Generate Single Logout (SLO) Descriptor metadata fragment [SAML2meta]. */
     552                 :            : 
     553                 :            : /* Called by:  zxid_idp_sso_desc x2, zxid_sp_sso_desc x2 */
     554                 :            : struct zx_md_SingleLogoutService_s* zxid_slo_desc(zxid_conf* cf, struct zx_elem_s* father, char* binding, char* loc, char* resp_loc)
     555                 :         18 : {
     556                 :         18 :   struct zx_md_SingleLogoutService_s* d = zx_NEW_md_SingleLogoutService(cf->ctx,father);
     557                 :         18 :   d->Binding = zx_ref_attr(cf->ctx, &d->gg, zx_Binding_ATTR, binding);
     558                 :         18 :   d->Location = zx_attrf(cf->ctx, &d->gg, zx_Location_ATTR, "%s%s", cf->url, loc);
     559         [ +  + ]:         18 :   if (resp_loc)
     560                 :          9 :     d->ResponseLocation = zx_attrf(cf->ctx, &d->gg, zx_ResponseLocation_ATTR, "%s%s", cf->url, resp_loc);
     561                 :         18 :   zx_reverse_elem_lists(&d->gg);
     562                 :         18 :   return d;
     563                 :            : }
     564                 :            : 
     565                 :            : /*() Generate Manage Name Id (MNI) Descriptor metadata fragment [SAML2meta]. */
     566                 :            : 
     567                 :            : /* Called by:  zxid_idp_sso_desc x2, zxid_sp_sso_desc x2 */
     568                 :            : struct zx_md_ManageNameIDService_s* zxid_mni_desc(zxid_conf* cf, struct zx_elem_s* father, char* binding, char* loc, char* resp_loc)
     569                 :         14 : {
     570                 :         14 :   struct zx_md_ManageNameIDService_s* d = zx_NEW_md_ManageNameIDService(cf->ctx,father);
     571                 :         14 :   d->Binding = zx_ref_attr(cf->ctx, &d->gg, zx_Binding_ATTR, binding);
     572                 :         14 :   d->Location = zx_attrf(cf->ctx, &d->gg, zx_Location_ATTR, "%s%s", cf->url, loc);
     573         [ +  + ]:         14 :   if (resp_loc)
     574                 :          7 :     d->ResponseLocation = zx_attrf(cf->ctx, &d->gg, zx_ResponseLocation_ATTR, "%s%s", cf->url, resp_loc);
     575                 :         14 :   zx_reverse_elem_lists(&d->gg);
     576                 :         14 :   return d;
     577                 :            : }
     578                 :            : 
     579                 :            : /*() Generate Name ID Mapping Service metadata fragment [SAML2meta]. */
     580                 :            : 
     581                 :            : /* Called by:  zxid_idp_sso_desc */
     582                 :            : struct zx_md_NameIDMappingService_s* zxid_nimap_desc(zxid_conf* cf, struct zx_elem_s* father, char* binding, char* loc, char* resp_loc)
     583                 :          2 : {
     584                 :          2 :   struct zx_md_NameIDMappingService_s* d = zx_NEW_md_NameIDMappingService(cf->ctx,father);
     585                 :          2 :   d->Binding = zx_ref_attr(cf->ctx, &d->gg, zx_Binding_ATTR, binding);
     586                 :          2 :   d->Location = zx_attrf(cf->ctx, &d->gg, zx_Location_ATTR, "%s%s", cf->url, loc);
     587         [ -  + ]:          2 :   if (resp_loc)
     588                 :          0 :     d->ResponseLocation = zx_attrf(cf->ctx, &d->gg, zx_ResponseLocation_ATTR, "%s%s", cf->url, resp_loc);
     589                 :          2 :   zx_reverse_elem_lists(&d->gg);
     590                 :          2 :   return d;
     591                 :            : }
     592                 :            : 
     593                 :            : /*() Generate Assertion Consumer Service (SSO) Descriptor metadata fragment [SAML2meta]. */
     594                 :            : 
     595                 :            : /* Called by:  zxid_sp_sso_desc x5 */
     596                 :            : struct zx_md_AssertionConsumerService_s* zxid_ac_desc(zxid_conf* cf, struct zx_elem_s* father, char* binding, char* loc, char* ix)
     597                 :         35 : {
     598                 :         35 :   struct zx_md_AssertionConsumerService_s* d = zx_NEW_md_AssertionConsumerService(cf->ctx,father);
     599                 :         35 :   d->Binding = zx_ref_attr(cf->ctx, &d->gg, zx_Binding_ATTR, binding);
     600                 :         35 :   d->Location = zx_attrf(cf->ctx, &d->gg, zx_Location_ATTR, "%s%s", cf->url, loc);
     601                 :         35 :   d->index = zx_ref_attr(cf->ctx, &d->gg, zx_index_ATTR, ix);
     602                 :         35 :   zx_reverse_elem_lists(&d->gg);
     603                 :         35 :   return d;
     604                 :            : }
     605                 :            : 
     606                 :            : /*() Generate SP SSO Descriptor metadata fragment [SAML2meta]. */
     607                 :            : 
     608                 :            : /* Called by:  zxid_sp_meta */
     609                 :            : struct zx_md_SPSSODescriptor_s* zxid_sp_sso_desc(zxid_conf* cf, struct zx_elem_s* father)
     610                 :          7 : {
     611                 :          7 :   struct zx_md_SPSSODescriptor_s* sp_ssod = zx_NEW_md_SPSSODescriptor(cf->ctx,father);
     612         [ +  - ]:          7 :   sp_ssod->AuthnRequestsSigned        = zx_ref_attr(cf->ctx, &sp_ssod->gg, zx_AuthnRequestsSigned_ATTR, cf->authn_req_sign?"1":"0");
     613         [ +  - ]:          7 :   sp_ssod->WantAssertionsSigned       = zx_ref_attr(cf->ctx, &sp_ssod->gg, zx_WantAssertionsSigned_ATTR, cf->want_sso_a7n_signed?"1":"0");
     614                 :          7 :   sp_ssod->errorURL                   = zx_attrf(cf->ctx, &sp_ssod->gg, zx_errorURL_ATTR, "%s?o=E", cf->url);
     615                 :          7 :   sp_ssod->protocolSupportEnumeration = zx_ref_attr(cf->ctx, &sp_ssod->gg, zx_protocolSupportEnumeration_ATTR, SAML2_PROTO);
     616                 :            : 
     617   [ -  +  #  # ]:          7 :   LOCK(cf->mx, "read certs for our md");
     618         [ +  + ]:          7 :   if (!cf->enc_cert)
     619                 :          5 :     cf->enc_cert = zxid_read_cert(cf, "enc-nopw-cert.pem");
     620                 :            : 
     621         [ +  + ]:          7 :   if (!cf->sign_cert)
     622                 :          5 :     cf->sign_cert = zxid_read_cert(cf, "sign-nopw-cert.pem");
     623                 :            : 
     624   [ +  -  -  + ]:          7 :   if (!cf->enc_cert || !cf->sign_cert) {
     625   [ #  #  #  # ]:          0 :     UNLOCK(cf->mx, "read certs for our md");
     626                 :          0 :     ERR("Signing or encryption certificate not found (or both are corrupt). %p", cf->enc_cert);
     627                 :            :   } else {
     628                 :          7 :     sp_ssod->KeyDescriptor = zxid_key_desc(cf, &sp_ssod->gg, "encryption", cf->enc_cert);
     629                 :          7 :     sp_ssod->KeyDescriptor = zxid_key_desc(cf, &sp_ssod->gg, "signing", cf->sign_cert);
     630   [ -  +  #  # ]:          7 :     UNLOCK(cf->mx, "read certs for our md");
     631                 :            :   }
     632                 :            : 
     633                 :          7 :   sp_ssod->SingleLogoutService = zxid_slo_desc(cf, &sp_ssod->gg, SAML2_REDIR, "?o=Q", "?o=Q");
     634                 :          7 :   sp_ssod->SingleLogoutService = zxid_slo_desc(cf, &sp_ssod->gg, SAML2_SOAP,  "?o=S", 0);
     635                 :            : 
     636                 :          7 :   sp_ssod->ManageNameIDService = zxid_mni_desc(cf, &sp_ssod->gg, SAML2_REDIR, "?o=Q", "?o=Q");
     637                 :          7 :   sp_ssod->ManageNameIDService = zxid_mni_desc(cf, &sp_ssod->gg, SAML2_SOAP,  "?o=S", 0);
     638                 :            : 
     639                 :          7 :   sp_ssod->NameIDFormat = zx_ref_elem(cf->ctx, &sp_ssod->gg, zx_md_NameIDFormat_ELEM, SAML2_PERSISTENT_NID_FMT);
     640                 :          7 :   sp_ssod->NameIDFormat = zx_ref_elem(cf->ctx, &sp_ssod->gg, zx_md_NameIDFormat_ELEM, SAML2_TRANSIENT_NID_FMT);
     641                 :            : 
     642                 :            :   /* N.B. The index values should not be changed. They are used in
     643                 :            :    * AuthnReq to choose profile using AssertionConsumerServiceIndex */
     644                 :            : 
     645                 :          7 :   sp_ssod->AssertionConsumerService = zxid_ac_desc(cf, &sp_ssod->gg, SAML2_ART, "", "1");
     646                 :          7 :   sp_ssod->AssertionConsumerService = zxid_ac_desc(cf, &sp_ssod->gg, SAML2_POST, "?o=P", "2");
     647                 :          7 :   sp_ssod->AssertionConsumerService = zxid_ac_desc(cf, &sp_ssod->gg, SAML2_SOAP, "?o=S", "3");
     648                 :          7 :   sp_ssod->AssertionConsumerService = zxid_ac_desc(cf, &sp_ssod->gg, SAML2_PAOS, "?o=P", "4");
     649                 :          7 :   sp_ssod->AssertionConsumerService = zxid_ac_desc(cf, &sp_ssod->gg, SAML2_POST_SIMPLE_SIGN, "?o=P", "5");
     650                 :          7 :   zx_reverse_elem_lists(&sp_ssod->gg);
     651                 :          7 :   return sp_ssod;
     652                 :            : }
     653                 :            : 
     654                 :            : /*() Generate IdP SSO Descriptor metadata fragment [SAML2meta]. */
     655                 :            : 
     656                 :            : /* Called by:  zxid_sp_meta */
     657                 :            : struct zx_md_IDPSSODescriptor_s* zxid_idp_sso_desc(zxid_conf* cf, struct zx_elem_s* father)
     658                 :          2 : {
     659                 :          2 :   struct zx_md_IDPSSODescriptor_s* idp_ssod = zx_NEW_md_IDPSSODescriptor(cf->ctx,father);
     660         [ +  - ]:          2 :   idp_ssod->WantAuthnRequestsSigned    = zx_ref_attr(cf->ctx, &idp_ssod->gg, zx_WantAuthnRequestsSigned_ATTR, cf->want_authn_req_signed?"1":"0");
     661                 :          2 :   idp_ssod->errorURL                   = zx_attrf(cf->ctx, &idp_ssod->gg, zx_errorURL_ATTR, "%s?o=E", cf->url);
     662                 :          2 :   idp_ssod->protocolSupportEnumeration = zx_ref_attr(cf->ctx, &idp_ssod->gg, zx_protocolSupportEnumeration_ATTR, SAML2_PROTO);
     663                 :            : 
     664   [ -  +  #  # ]:          2 :   LOCK(cf->mx, "read certs for our md idp");
     665         [ +  - ]:          2 :   if (!cf->enc_cert)
     666                 :          2 :     cf->enc_cert = zxid_read_cert(cf, "enc-nopw-cert.pem");
     667                 :            : 
     668         [ +  - ]:          2 :   if (!cf->sign_cert)
     669                 :          2 :     cf->sign_cert = zxid_read_cert(cf, "sign-nopw-cert.pem");
     670                 :            : 
     671   [ +  -  -  + ]:          2 :   if (!cf->enc_cert || !cf->sign_cert) {
     672   [ #  #  #  # ]:          0 :     UNLOCK(cf->mx, "read certs for our md idp");
     673                 :          0 :     ERR("Signing or encryption certificate not found (or both are corrupt). %p", cf->enc_cert);
     674                 :            :   } else {
     675                 :          2 :     idp_ssod->KeyDescriptor = zxid_key_desc(cf, &idp_ssod->gg, "encryption", cf->enc_cert);
     676                 :          2 :     idp_ssod->KeyDescriptor = zxid_key_desc(cf, &idp_ssod->gg, "signing", cf->sign_cert);
     677   [ -  +  #  # ]:          2 :     UNLOCK(cf->mx, "read certs for our md idp");
     678                 :            :   }
     679                 :            : 
     680                 :            : #if 0
     681                 :            :   /* *** NI */
     682                 :            :   idp_ssod->ArtifactResolutionService = zxid_ar_desc(cf, &idp_ssod->gg, SAML2_SOAP, "?o=S", 0);
     683                 :            : #endif
     684                 :            : 
     685                 :          2 :   idp_ssod->SingleLogoutService = zxid_slo_desc(cf, &idp_ssod->gg, SAML2_REDIR, "?o=Q", "?o=Q");
     686                 :          2 :   idp_ssod->SingleLogoutService = zxid_slo_desc(cf, &idp_ssod->gg, SAML2_SOAP, "?o=S", 0);
     687                 :            : 
     688                 :            : #if 0
     689                 :            :   /* *** NI */
     690                 :            :   idp_ssod->ManageNameIDService = zxid_mni_desc(cf, &idp_ssod->gg, SAML2_REDIR, "?o=Q", "?o=Q");
     691                 :            :   idp_ssod->ManageNameIDService = zxid_mni_desc(cf, &idp_ssod->gg, SAML2_SOAP, "?o=S", 0);
     692                 :            : #endif
     693                 :            : 
     694                 :          2 :   idp_ssod->NameIDFormat = zx_ref_elem(cf->ctx, &idp_ssod->gg, zx_md_NameIDFormat_ELEM, SAML2_PERSISTENT_NID_FMT);
     695                 :          2 :   idp_ssod->NameIDFormat = zx_ref_elem(cf->ctx, &idp_ssod->gg, zx_md_NameIDFormat_ELEM, SAML2_TRANSIENT_NID_FMT);
     696                 :            : 
     697                 :          2 :   idp_ssod->SingleSignOnService = zxid_sso_desc(cf, &idp_ssod->gg, SAML2_REDIR, "?o=F", 0);
     698                 :            : 
     699         [ +  - ]:          2 :   if (cf->imps_ena)
     700                 :          2 :     idp_ssod->NameIDMappingService = zxid_nimap_desc(cf, &idp_ssod->gg, SAML2_SOAP, "?o=S", 0);
     701                 :            :   
     702                 :          2 :   zx_reverse_elem_lists(&idp_ssod->gg);
     703                 :          2 :   return idp_ssod;
     704                 :            : }
     705                 :            : 
     706                 :            : /*() Generate Organization metadata fragment [SAML2meta]. */
     707                 :            : 
     708                 :            : /* Called by:  zxid_sp_meta */
     709                 :            : struct zx_md_Organization_s* zxid_org_desc(zxid_conf* cf, struct zx_elem_s* father)
     710                 :          7 : {
     711                 :          7 :   struct zx_md_Organization_s* org = zx_NEW_md_Organization(cf->ctx,father);
     712                 :          7 :   org->OrganizationName = zx_NEW_md_OrganizationName(cf->ctx, &org->gg);
     713                 :          7 :   org->OrganizationName->lang = zx_ref_attr(cf->ctx, &org->OrganizationName->gg, zx_xml_lang_ATTR, "en");  /* *** config */
     714   [ +  -  +  - ]:         14 :   if (cf->org_name && cf->org_name[0])
     715                 :          7 :     zx_add_content(cf->ctx, &org->OrganizationName->gg, zx_ref_str(cf->ctx, cf->org_name));
     716                 :            :   else
     717         [ #  # ]:          0 :     zx_add_content(cf->ctx, &org->OrganizationName->gg, zx_ref_str(cf->ctx, STRNULLCHKQ(cf->nice_name)));
     718                 :            : 
     719                 :          7 :   org->OrganizationDisplayName = zx_NEW_md_OrganizationDisplayName(cf->ctx, &org->gg);
     720                 :          7 :   org->OrganizationDisplayName->lang = zx_ref_attr(cf->ctx, &org->OrganizationDisplayName->gg, zx_xml_lang_ATTR, "en");  /* *** config */
     721         [ +  - ]:          7 :   zx_add_content(cf->ctx, &org->OrganizationDisplayName->gg, zx_ref_str(cf->ctx, STRNULLCHKQ(cf->nice_name)));
     722                 :            : 
     723                 :          7 :   org->OrganizationURL = zx_NEW_md_OrganizationURL(cf->ctx, &org->gg);
     724                 :          7 :   org->OrganizationURL->lang = zx_ref_attr(cf->ctx, &org->OrganizationURL->gg, zx_xml_lang_ATTR, "en");  /* *** config */
     725   [ +  -  +  - ]:         14 :   if (cf->org_url && cf->org_url[0])
     726                 :          7 :     zx_add_content(cf->ctx, &org->OrganizationURL->gg, zx_ref_str(cf->ctx, cf->org_url));
     727                 :            :   else
     728                 :          0 :     zx_add_content(cf->ctx, &org->OrganizationURL->gg, zx_ref_str(cf->ctx, cf->url));
     729                 :            : 
     730                 :          7 :   zx_reverse_elem_lists(&org->gg);
     731                 :          7 :   return org;
     732                 :            : }
     733                 :            : 
     734                 :            : /*() Generate Contact Person metadata fragment [SAML2meta]. */
     735                 :            : 
     736                 :            : /* Called by:  zxid_sp_meta */
     737                 :            : struct zx_md_ContactPerson_s* zxid_contact_desc(zxid_conf* cf, struct zx_elem_s* father)
     738                 :          7 : {
     739                 :          7 :   struct zx_md_ContactPerson_s* contact = zx_NEW_md_ContactPerson(cf->ctx,father);
     740                 :            : 
     741                 :          7 :   contact->contactType = zx_ref_attr(cf->ctx, &contact->gg, zx_contactType_ATTR, "administrative");  /* *** config */
     742                 :            : 
     743         [ -  + ]:          7 :   if (cf->contact_org) {
     744         [ #  # ]:          0 :     if (cf->contact_org[0])
     745                 :          0 :       contact->Company = zx_ref_elem(cf->ctx, &contact->gg, zx_md_Company_ELEM, cf->contact_org);
     746                 :            :   } else
     747   [ +  -  +  - ]:         14 :     if (cf->org_name && cf->org_name[0])
     748                 :          7 :       contact->Company
     749                 :            :         = zx_ref_elem(cf->ctx, &contact->gg, zx_md_Company_ELEM, cf->org_name);
     750                 :            :     else
     751         [ #  # ]:          0 :       contact->Company
     752                 :            :         = zx_ref_elem(cf->ctx, &contact->gg, zx_md_Company_ELEM, STRNULLCHKQ(cf->nice_name));
     753                 :            : 
     754   [ -  +  #  # ]:          7 :   if (cf->contact_name && cf->contact_name[0])
     755                 :          0 :     contact->SurName = zx_ref_elem(cf->ctx, &contact->gg, zx_md_SurName_ELEM, cf->contact_name);
     756   [ -  +  #  # ]:          7 :   if (cf->contact_email && cf->contact_email[0])
     757                 :          0 :     contact->EmailAddress = zx_ref_elem(cf->ctx, &contact->gg, zx_md_EmailAddress_ELEM, cf->contact_email);
     758   [ -  +  #  # ]:          7 :   if (cf->contact_tel && cf->contact_tel[0])
     759                 :          0 :     contact->TelephoneNumber = zx_ref_elem(cf->ctx, &contact->gg, zx_md_TelephoneNumber_ELEM, cf->contact_tel);
     760                 :            : 
     761                 :          7 :   zx_reverse_elem_lists(&contact->gg);
     762                 :          7 :   return contact;
     763                 :            : }
     764                 :            : 
     765                 :            : /*(i) Primary interface to our own Entity ID. While this would usually be
     766                 :            :  * automatically generated from URL configuration option so as to conform
     767                 :            :  * to the Well Known Location (WKL) metadata exchange convention [SAML2meta],
     768                 :            :  * on some sites the entity ID may be different and thus everybody who
     769                 :            :  * does not know better should use this interface to obtain it.
     770                 :            :  *
     771                 :            :  * cf:: ZXID configuration object, used to compute EntityID and also for memory allocation
     772                 :            :  * return:: Entity ID as zx_str */
     773                 :            : 
     774                 :            : /* Called by:  main x2, zxid_idp_map_nid2uid, zxid_idp_select_zxstr_cf_cgi, zxid_map_bangbang, zxid_mk_subj, zxid_my_issuer, zxid_nidmap_do, zxid_ses_to_pool, zxid_show_conf, zxid_sp_sso_finalize, zxid_wsf_validate_a7n */
     775                 :            : struct zx_str* zxid_my_ent_id(zxid_conf* cf)
     776                 :       1317 : {
     777         [ -  + ]:       1317 :   if (cf->non_standard_entityid) {
     778   [ #  #  #  # ]:          0 :     D("my_entity_id non_standard_entytid(%s)", cf->non_standard_entityid);
     779                 :          0 :     return zx_strf(cf->ctx, "%s", cf->non_standard_entityid);
     780         [ +  + ]:       1317 :   } else if (cf->bare_url_entityid) {
     781   [ +  -  -  + ]:       1070 :     D("my_entity_id bare url(%s)", cf->url);
     782                 :       1070 :     return zx_strf(cf->ctx, "%s", cf->url);
     783                 :            :   } else {
     784   [ +  +  -  + ]:        247 :     D("my_entity_id url(%s)", cf->url);
     785                 :        247 :     return zx_strf(cf->ctx, "%s?o=B", cf->url);
     786                 :            :   }
     787                 :            : }
     788                 :            : 
     789                 :            : /* Called by:  zxid_check_fed, zxid_mk_ecp_Request_hdr, zxid_sp_meta, zxid_wsf_decor */
     790                 :            : struct zx_attr_s* zxid_my_ent_id_attr(zxid_conf* cf, struct zx_elem_s* father, int tok)
     791                 :        199 : {
     792         [ -  + ]:        199 :   if (cf->non_standard_entityid) {
     793   [ #  #  #  # ]:          0 :     D("my_entity_id non_standard_entytid(%s)", cf->non_standard_entityid);
     794                 :          0 :     return zx_attrf(cf->ctx, father, tok, "%s", cf->non_standard_entityid);
     795         [ +  + ]:        199 :   } else if (cf->bare_url_entityid) {
     796   [ +  -  -  + ]:        137 :     D("my_entity_id bare url(%s)", cf->url);
     797                 :        137 :     return zx_attrf(cf->ctx, father, tok, "%s", cf->url);
     798                 :            :   } else {
     799   [ +  +  -  + ]:         62 :     D("my_entity_id url(%s)", cf->url);
     800                 :         62 :     return zx_attrf(cf->ctx, father, tok, "%s?o=B", cf->url);
     801                 :            :   }
     802                 :            : }
     803                 :            : 
     804                 :            : /*() Dynamically determine our Common Domain Cookie (IdP discovery) URL. */
     805                 :            : 
     806                 :            : /* Called by: */
     807                 :            : struct zx_str* zxid_my_cdc_url(zxid_conf* cf)
     808                 :          0 : {
     809                 :          0 :   return zx_strf(cf->ctx, "%s?o=C", cf->cdc_url);
     810                 :            : }
     811                 :            : 
     812                 :            : /*() Generate Issuer value. Issuer is often same as Entity ID, but sometimes
     813                 :            :  * it will be affiliation ID. This function is a low level interface. Usually
     814                 :            :  * you would want to use zxid_my_issuer(). */
     815                 :            : 
     816                 :            : /* Called by:  zxid_my_issuer */
     817                 :            : struct zx_sa_Issuer_s* zxid_issuer(zxid_conf* cf, struct zx_elem_s* father, struct zx_str* nameid, char* affiliation)
     818                 :       1131 : {
     819                 :       1131 :   struct zx_sa_Issuer_s* is = zx_NEW_sa_Issuer(cf->ctx, father);
     820                 :       1131 :   zx_add_content(cf->ctx, &is->gg, nameid);
     821   [ -  +  #  # ]:       1131 :   if (affiliation && affiliation[0])
     822                 :          0 :     is->NameQualifier = zx_ref_attr(cf->ctx, &is->gg, zx_NameQualifier_ATTR, affiliation);
     823                 :            :   /*is->Format = zx_ref_str(cf->ctx, );*/
     824                 :       1131 :   return is;
     825                 :            : }
     826                 :            : 
     827                 :            : /*() Generate Issuer value for our entity. Issuer is often same as Entity ID, but sometimes
     828                 :            :  * it will be affiliation ID. */
     829                 :            : 
     830                 :            : /* Called by:  zxid_mk_a7n, zxid_mk_art_deref, zxid_mk_authn_req, zxid_mk_az, zxid_mk_az_cd1, zxid_mk_ecp_Request_hdr, zxid_mk_logout, zxid_mk_logout_resp, zxid_mk_mni, zxid_mk_mni_resp, zxid_mk_saml_resp */
     831                 :       1131 : struct zx_sa_Issuer_s* zxid_my_issuer(zxid_conf* cf, struct zx_elem_s* father) {
     832                 :       1131 :   return zxid_issuer(cf, father, zxid_my_ent_id(cf), cf->affiliation);
     833                 :            : }
     834                 :            : 
     835                 :            : /*() Generate our SP metadata and return it as a string. */
     836                 :            : 
     837                 :            : /* Called by:  zxid_genmd, zxid_send_sp_meta, zxid_simple_show_meta */
     838                 :            : struct zx_str* zxid_sp_meta(zxid_conf* cf, zxid_cgi* cgi)
     839                 :          7 : {
     840                 :            :   struct zx_md_EntityDescriptor_s* ed;
     841                 :            :   
     842                 :          7 :   ed = zx_NEW_md_EntityDescriptor(cf->ctx,0);
     843                 :          7 :   ed->entityID = zxid_my_ent_id_attr(cf, &ed->gg, zx_entityID_ATTR);
     844         [ +  + ]:          7 :   if (cf->idp_ena)
     845                 :          2 :     ed->IDPSSODescriptor = zxid_idp_sso_desc(cf, &ed->gg);
     846                 :          7 :   ed->SPSSODescriptor = zxid_sp_sso_desc(cf, &ed->gg);
     847                 :          7 :   ed->Organization = zxid_org_desc(cf, &ed->gg);
     848                 :          7 :   ed->ContactPerson = zxid_contact_desc(cf, &ed->gg);
     849                 :          7 :   zx_reverse_elem_lists(&ed->gg);
     850                 :            :   
     851         [ +  - ]:          7 :   if (cf->log_level>0)
     852                 :          7 :     zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "W", "MYMD", 0, 0);
     853                 :          7 :   return zx_easy_enc_elem_opt(cf, &ed->gg);
     854                 :            : }
     855                 :            : 
     856                 :            : /*() Generate our SP metadata and send it to remote partner.
     857                 :            :  *
     858                 :            :  * Limitation:: This function only works with CGI as it will print the
     859                 :            :  *     serialized metadata straight to stdout. There are other
     860                 :            :  *     methods for getting metadat without this limitation, e.g. zxid_sp_meta() */
     861                 :            : 
     862                 :            : /* Called by:  main x2, opt x2 */
     863                 :            : int zxid_send_sp_meta(zxid_conf* cf, zxid_cgi* cgi)
     864                 :          0 : {
     865                 :          0 :   struct zx_str* ss = zxid_sp_meta(cf, cgi);
     866         [ #  # ]:          0 :   if (!ss)
     867                 :          0 :     return 0;
     868                 :            :   //write_all_fd(1, ss->s, ss->len);
     869                 :          0 :   write_all_fd(fileno(stdout), ss->s, ss->len);
     870                 :          0 :   zx_str_free(cf->ctx, ss);
     871                 :          0 :   return 0;
     872                 :            : }
     873                 :            : 
     874                 :            : /* ------- CARML ------- */
     875                 :            : 
     876                 :            : /*() Generate our SP CARML and return it as a string. */
     877                 :            : 
     878                 :            : /* Called by:  zxid_simple_show_carml */
     879                 :            : struct zx_str* zxid_sp_carml(zxid_conf* cf)
     880                 :          1 : {
     881         [ +  - ]:          1 :   if (cf->log_level>0)
     882                 :          1 :     zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "W", "MYCARML", 0, 0);
     883                 :            : 
     884                 :            :   /* *** Much work needed to study CARML spec and to convert need and want to comply */
     885                 :            : 
     886                 :          1 :   return zx_strf(cf->ctx,
     887                 :            : "<carml:ClientAttrReq"
     888                 :            : " AppName=\"ZXID SP\""
     889                 :            : " Description=\"ZXID SP Attribute Needs and Wants\""
     890                 :            : " xmlns:carml=\"urn:igf:client:0.9:carml\">"
     891                 :            : "<carml:DataDefs>"
     892                 :            : 
     893                 :            : "  <carml:Attributes>"
     894                 :            : "  </carml:Attributes>"
     895                 :            : 
     896                 :            : "  <carml:Predicates>"
     897                 :            : "  </carml:Predicates>"
     898                 :            : 
     899                 :            : "  <carml:Roles>"
     900                 :            : "  </carml:Roles>"
     901                 :            : 
     902                 :            : "  <carml:Policies>"
     903                 :            : "  </carml:Policies>"
     904                 :            : 
     905                 :            : "</carml:DataDefs>"
     906                 :            : 
     907                 :            : "<carml:ReadInteraction/>"
     908                 :            : "<carml:FindInteraction/>"
     909                 :            : "<carml:SearchInteraction/>"
     910                 :            : "<carml:CompareInteraction/>"
     911                 :            : "<carml:ModifyInteraction/>"
     912                 :            : "<carml:AddInteraction/>"
     913                 :            : 
     914                 :            : "</carml:ClientAttrReq>"
     915                 :            :                  );
     916                 :            : }
     917                 :            : 
     918                 :            : /* EOF  --  zxidmeta.c */

Generated by: LCOV version 1.9