LCOV - code coverage report
Current view: top level - zxid - zxiddi.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 91 151 60.3 %
Date: 2010-12-19 Functions: 2 2 100.0 %
Branches: 103 266 38.7 %

           Branch data     Line data    Source code
       1                 :            : /* zxiddi.c  -  Discovery Server
       2                 :            :  * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 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: zxiddi.c,v 1.2 2009-11-24 23:53:40 sampo Exp $
      10                 :            :  *
      11                 :            :  * 15.11.2009, created --Sampo
      12                 :            :  *
      13                 :            :  * See also zxidepr.c for discovery client code.
      14                 :            :  *
      15                 :            :  *   zxcot -e http://idp.tas3.pt:8081/zxididp?o=S 'Discovery Svc' \
      16                 :            :  *     http://idp.tas3.pt:8081/zxididp?o=B urn:liberty:disco:2006-08 \
      17                 :            :  *   | zxcot -bs /var/zxid/idpdimd
      18                 :            :  */
      19                 :            : 
      20                 :            : #include "platform.h"  /* for dirent.h */
      21                 :            : #include "errmac.h"
      22                 :            : #include "zxid.h"
      23                 :            : #include "zxidpriv.h"
      24                 :            : #include "zxidutil.h"
      25                 :            : #include "zxidconf.h"
      26                 :            : #include "saml2.h"
      27                 :            : #include "wsf.h"
      28                 :            : #include "c/zx-const.h"
      29                 :            : #include "c/zx-ns.h"
      30                 :            : #include "c/zx-data.h"
      31                 :            : 
      32                 :            : /*() Recover end user's identity: uid at IdP. This is actually done via "self federation"
      33                 :            :  * that was created when token for accessing discovery was issued.
      34                 :            :  * Returns 1 on success, 0 on failure. */
      35                 :            : 
      36                 :            : /* Called by:  zxid_di_query, zxid_imreq, zxid_ps_addent_invite, zxid_ps_resolv_id, zxid_ssos_anreq */
      37                 :            : int zxid_idp_map_nid2uid(zxid_conf* cf, int len, char* uid, zxid_nid* nameid, struct zx_lu_Status_s** stp)
      38                 :         18 : {
      39                 :            :   struct zx_str* affil;
      40                 :            :   char sp_name_buf[1024];
      41         [ -  + ]:         18 :   if (!nameid) {
      42                 :          0 :     ERR("Missing nameid %d",0);
      43                 :          0 :     return 0;
      44                 :            :   }
      45                 :            : 
      46         [ +  - ]:         18 :   affil = nameid->SPNameQualifier ? &nameid->SPNameQualifier->g : zxid_my_ent_id(cf);
      47                 :         18 :   zxid_nice_sha1(cf, sp_name_buf, sizeof(sp_name_buf), affil, affil, 7);
      48   [ +  -  +  -  :         18 :   len = read_all(len-1, uid, "idp_map_nid2uid", 1, "%s" ZXID_NID_DIR "%s/%.*s", cf->path, sp_name_buf, ZX_GET_CONTENT_LEN(nameid), ZX_GET_CONTENT_S(nameid));
          +  -  +  -  +  
                -  +  - ]
      49         [ -  + ]:         18 :   if (!len) {
      50   [ #  #  #  #  :          0 :     ERR("Can not find reverse mapping for SP,SHA1(%s) nid(%.*s)", sp_name_buf, ZX_GET_CONTENT_LEN(nameid), ZX_GET_CONTENT_S(nameid));
          #  #  #  #  #  
                #  #  # ]
      51         [ #  # ]:          0 :     if (stp)
      52                 :          0 :       *stp = zxid_mk_lu_Status(cf, 0, "Fail", 0, 0, 0);
      53                 :          0 :     return 0;
      54                 :            :   }
      55                 :         18 :   return 1;
      56                 :            : }
      57                 :            : 
      58                 :            : /*() Server side Discovery Service Query processing. See also zxid_gen_bootstraps() */
      59                 :            : 
      60                 :            : /* Called by:  zxid_sp_soap_dispatch */
      61                 :            : struct zx_di_QueryResponse_s* zxid_di_query(zxid_conf* cf,zxid_ses* ses,struct zx_di_Query_s* req)
      62                 :         17 : {
      63                 :            :   struct zx_di_RequestedService_s* rs;
      64                 :         17 :   struct zx_di_QueryResponse_s* resp = zx_NEW_di_QueryResponse(cf->ctx,0);
      65                 :            :   struct zx_root_s* r;
      66                 :         17 :   int len, epr_len, match, n_discovered = 0;
      67                 :            :   char logop[8];
      68                 :            :   char uid[ZXID_MAX_USER];
      69                 :            :   char mdpath[ZXID_MAX_BUF];
      70                 :            :   char path[ZXID_MAX_BUF];
      71                 :            :   char* epr_buf;
      72                 :            :   DIR* dir;
      73                 :            :   struct dirent* de;
      74                 :            :   struct zx_elem_s* el;
      75                 :         17 :   struct zx_a_Metadata_s* md = 0;  
      76                 :            :   struct zx_str* ss;
      77                 :            :   struct zx_str* tt;
      78                 :         17 :   struct zx_str* addr = 0;  
      79                 :         17 :   zxid_epr* epr = 0;
      80                 :         17 :   D_INDENT("di_query: ");
      81                 :         17 :   ses->uid = uid;
      82                 :            :   
      83         [ -  + ]:         17 :   if (!zxid_idp_map_nid2uid(cf, sizeof(uid), uid, ses->tgtnameid, &resp->Status)) {
      84                 :          0 :     D_DEDENT("di_query: ");
      85                 :          0 :     return resp;
      86                 :            :   }
      87                 :         17 :   name_from_path(mdpath, sizeof(mdpath), "%sdimd", cf->path);
      88                 :            : 
      89                 :            :   /* Work through all requests */
      90                 :            : 
      91                 :         17 :   for (rs = req->RequestedService;
      92   [ +  +  +  - ]:         51 :        rs && rs->gg.g.tok == zx_di_RequestedService_ELEM;
      93                 :         17 :        rs = (struct zx_di_RequestedService_s*)ZX_NEXT(rs)) {
      94                 :            : 
      95                 :            :     /* Look for all entities providing service */
      96                 :            : 
      97   [ +  -  +  -  :         17 :     if (ZX_SIMPLE_ELEM_CHK(rs->ServiceType)) {
          +  -  +  -  +  
                -  +  - ]
      98                 :            :       /* *** proper handling of discovering simultaneously multiple service types? */
      99                 :            :     } else {
     100   [ #  #  #  # ]:          0 :       D("%d: No specific service type given. Looking for all. %p", n_discovered, rs->ServiceType);
     101                 :          0 :       len = 0;
     102                 :          0 :       path[0] = 0;
     103                 :            :     }
     104                 :            : 
     105   [ +  -  -  + ]:         17 :     D("%d: Looking for service metadata in dir(%s)", n_discovered, mdpath);
     106                 :         17 :     dir = opendir(mdpath);
     107         [ -  + ]:         17 :     if (!dir) {
     108                 :          0 :       perror("opendir to find service metadata");
     109                 :          0 :       ERR("Opening service metadata directory failed path(%s)", mdpath);
     110                 :          0 :       resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "Fail", 0, 0, 0);
     111                 :          0 :       D_DEDENT("di_query: ");
     112                 :          0 :       return resp;
     113                 :            :     }
     114                 :            :     
     115                 :            :     /* Work through all available providers, filtering out insuitable ones. */
     116                 :            :     
     117         [ +  + ]:        323 :     while (de = readdir(dir)) {
     118   [ +  -  -  + ]:        289 :       D("%d: Considering file(%s)", n_discovered, de->d_name);
     119                 :            : 
     120         [ +  - ]:        289 :       if (de->d_name[strlen(de->d_name)-1] == '~')  /* Ignore backups from hand edited EPRs. */
     121                 :          0 :         continue;
     122                 :            :       
     123                 :            :       /* Filter file name by service type */
     124                 :            :       
     125                 :        289 :       for (el = rs->ServiceType;
     126   [ +  -  +  + ]:        594 :            el && el->g.tok == zx_di_ServiceType_ELEM;
     127                 :         16 :            el = (struct zx_elem_s*)el->g.n) {
     128   [ +  -  +  -  :        289 :         ss = ZX_GET_CONTENT(el);
                   +  - ]
     129   [ +  -  +  - ]:        289 :         if (!ss || !ss->len)
     130                 :            :           continue;
     131                 :        289 :         len = MIN(ss->len, sizeof(path)-1);
     132                 :        289 :         memcpy(path, ss->s, len);
     133                 :        289 :         path[len] = 0;
     134                 :        289 :         zxid_fold_svc(path, len);
     135   [ +  +  -  + ]:        289 :         if (memcmp(de->d_name, path, len) || de->d_name[len] != ',') {
     136   [ +  -  -  + ]:        273 :           D("%d:     rejected due to prefix(%s) file(%s)", n_discovered, path, de->d_name);
     137                 :        273 :           goto next_file;
     138                 :            :         }
     139                 :            :       }
     140                 :            :       
     141                 :            :       /* Probable enough, read and parse EPR so we can continue examination. */
     142                 :            : 
     143                 :         16 :       epr_buf = read_all_alloc(cf->ctx, "find_svcmd", 1, &epr_len, "%s/%s", mdpath, de->d_name);
     144         [ -  + ]:         16 :       if (!epr_buf)
     145                 :          0 :         continue;
     146                 :            :       
     147                 :         16 :       r = zx_dec_zx_root(cf->ctx, epr_len, epr_buf, "diq epr");
     148         [ -  + ]:         16 :       if (!r) {
     149                 :          0 :         ERR("Failed to XML parse epr_buf(%.*s) file(%s)", epr_len, epr_buf, de->d_name);
     150                 :          0 :         ZX_FREE(cf->ctx, epr_buf);
     151                 :          0 :         continue;
     152                 :            :       }
     153                 :            :       /* *** add ID-WSF 1.1 handling */
     154                 :         16 :       epr = r->EndpointReference;
     155                 :         16 :       ZX_FREE(cf->ctx, r);
     156   [ +  -  -  + ]:         16 :       if (!epr || !epr->Metadata) {
     157                 :          0 :         ERR("No EPR or missing <Metadata>. epr_buf(%.*s) file(%s)", epr_len, epr_buf, de->d_name);
     158                 :          0 :         ZX_FREE(cf->ctx, epr_buf);
     159                 :          0 :         continue;
     160                 :            :       }
     161   [ +  -  +  -  :         16 :       if (!ZX_SIMPLE_ELEM_CHK(epr->Address)) {
          +  -  +  -  +  
                -  -  + ]
     162                 :          0 :         ERR("EPR missing <Address>. epr_buf(%.*s) file(%s)", epr_len, epr_buf, de->d_name);
     163                 :          0 :         ZX_FREE(cf->ctx, epr_buf);
     164                 :          0 :         continue;
     165                 :            :       }
     166   [ +  -  +  -  :         16 :       addr = ZX_GET_CONTENT(epr->Address);
                   +  - ]
     167                 :         16 :       md = epr->Metadata;
     168                 :            : 
     169                 :            :       /* Filter by service type */
     170                 :            :       
     171                 :         16 :       match = 1;
     172                 :         16 :       for (el = rs->ServiceType;
     173   [ +  -  +  - ]:         32 :            el && el->g.tok == zx_di_ServiceType_ELEM;
     174                 :          0 :            el = (struct zx_elem_s*)el->g.n) {
     175   [ +  -  +  -  :         16 :         ss = ZX_GET_CONTENT(el);
                   +  - ]
     176   [ +  -  +  - ]:         16 :         if (!ss || !ss->len)
     177                 :            :           continue;
     178                 :         16 :         match = 0;
     179   [ +  -  +  -  :         16 :         tt = ZX_GET_CONTENT(md->ServiceType);
                   +  - ]
     180   [ +  -  -  + ]:         16 :         if (!tt || !tt->len) {
     181                 :          0 :           INFO("EPR missing ServiceType. Rejected. epr_buf(%.*s) file(%s)", epr_len, epr_buf, de->d_name);
     182                 :          0 :           ZX_FREE(cf->ctx, epr_buf);
     183                 :          0 :           goto next_file;
     184                 :            :         }
     185   [ +  -  -  + ]:         16 :         if (ss->len != tt->len || memcmp(ss->s, tt->s, ss->len)) {
     186   [ #  #  #  # ]:          0 :           D("%d: Internal svctype(%.*s) does not match desired(%.*s)", n_discovered, tt->len, tt->s, ss->len, ss->s);
     187                 :          0 :           continue;
     188                 :            :         }
     189   [ +  -  -  + ]:         16 :         D("%d: ServiceType matches. file(%s)", n_discovered, de->d_name);
     190                 :         16 :         match = 1;
     191                 :         16 :         break;
     192                 :            :       }
     193         [ -  + ]:         16 :       if (!match) {
     194   [ #  #  #  # ]:          0 :           D("%d: Rejected due to ServiceType. file(%s)", n_discovered, de->d_name);
     195                 :          0 :           ZX_FREE(cf->ctx, epr_buf);
     196                 :          0 :           goto next_file;
     197                 :            :       }
     198                 :            : 
     199                 :            :       /* Filter by provider id */
     200                 :            :       
     201                 :         16 :       for (el = rs->ProviderID;
     202   [ +  +  +  - ]:         32 :            el && el->g.tok == zx_di_ProviderID_ELEM;
     203                 :          0 :            el = (struct zx_elem_s*)el->g.n) {
     204   [ +  -  +  -  :          1 :         ss = ZX_GET_CONTENT(el);
                   +  - ]
     205   [ +  -  +  - ]:          1 :         if (!ss || !ss->len)
     206                 :            :           continue;
     207                 :          1 :         match = 0;
     208   [ +  -  +  -  :          1 :         tt = ZX_GET_CONTENT(md->ProviderID);
                   +  - ]
     209   [ +  -  -  + ]:          1 :         if (!tt || !tt->len) {
     210                 :          0 :           INFO("EPR missing ProviderID. epr_buf(%.*s) file(%s)", epr_len, epr_buf, de->d_name);
     211                 :          0 :           break;
     212                 :            :         }
     213   [ +  -  -  + ]:          1 :         if (ss->len != tt->len || memcmp(ss->s, tt->s, ss->len)) {
     214   [ #  #  #  # ]:          0 :           D("%d: ProviderID(%.*s) does not match desired(%.*s)", n_discovered, tt->len, tt->s, ss->len, ss->s);
     215                 :          0 :           continue;
     216                 :            :         }
     217   [ +  -  -  + ]:          1 :         D("%d: ProviderID matches. file(%s)", n_discovered, de->d_name);
     218                 :          1 :         match = 1;
     219                 :          1 :         break;
     220                 :            :       }
     221                 :            : #if 1
     222                 :            :       /* TAS3 extension: allow matching by the Address (URL) as well */
     223         [ -  + ]:         16 :       if (!match) {
     224                 :          0 :         for (el = rs->ProviderID;
     225   [ #  #  #  # ]:          0 :              el && el->g.tok == zx_di_ProviderID_ELEM;
     226                 :          0 :              el = (struct zx_elem_s*)el->g.n) {
     227   [ #  #  #  #  :          0 :           ss = ZX_GET_CONTENT(el);
                   #  # ]
     228   [ #  #  #  # ]:          0 :           if (!ss || !ss->len)
     229                 :            :             continue;
     230                 :          0 :           match = 0;
     231   [ #  #  #  # ]:          0 :           if (ss->len != addr->len || memcmp(ss->s, addr->s, ss->len)) {
     232   [ #  #  #  # ]:          0 :             D("%d: Address(%.*s) does not match desired(%.*s)", n_discovered, addr->len, addr->s, ss->len, ss->s);
     233                 :          0 :             continue;
     234                 :            :           }
     235   [ #  #  #  # ]:          0 :           D("%d: Address matches. file(%s)", n_discovered, de->d_name);
     236                 :          0 :           match = 1;
     237                 :          0 :           break;
     238                 :            :         }
     239                 :            :       }
     240                 :            : #endif
     241         [ -  + ]:         16 :       if (!match) {
     242   [ #  #  #  # ]:          0 :         D("%d: Rejected due to ProviderID. file(%s)", n_discovered, de->d_name);
     243                 :          0 :         ZX_FREE(cf->ctx, epr_buf);
     244                 :          0 :         goto next_file;
     245                 :            :       }
     246                 :            : 
     247                 :            :       /* *** Check Options */
     248                 :            : 
     249                 :            :       /* *** Check Framework */
     250                 :            : 
     251                 :            :       /* *** Check Action */
     252                 :            : 
     253                 :            : #if 0
     254                 :            :       /* Call Trust and Privacy Negotiation (TrustBuilder), Andreas. */
     255                 :            :       systemf("./tpn-client.sh %s %s %s", idpnid, "urn:idhrxml:cv:update", host);
     256                 :            : #endif
     257                 :         16 :       ++n_discovered;
     258   [ +  -  -  + ]:         16 :       D("%d: DISCOVERED EPR url(%.*s)", n_discovered, addr->len, addr->s);
     259         [ -  + ]:         16 :       if (!zxid_add_fed_tok2epr(cf, ses, epr, 1, logop)) {
     260                 :          0 :         ZX_FREE(cf->ctx, epr_buf);
     261                 :          0 :         goto next_file;
     262                 :            :       }
     263                 :            : 
     264                 :         16 :       zx_add_kid(&resp->gg, &epr->gg);
     265         [ +  - ]:         16 :       if (!resp->EndpointReference)
     266                 :         16 :         resp->EndpointReference = epr;
     267                 :            : 
     268                 :         16 :       zxlogwsp(cf, ses, "K", logop, uid, 0);
     269                 :            : 
     270   [ -  +  #  #  :         16 :       if (rs->resultsType && rs->resultsType->g.s
             #  #  #  # ]
     271                 :            :           && (!memcmp(rs->resultsType->g.s, "only-one", rs->resultsType->g.len)
     272                 :            :               || !memcmp(rs->resultsType->g.s, "best", rs->resultsType->g.len))) {
     273   [ #  #  #  # ]:          0 :         D("only-one or best requested (%.*s)", rs->resultsType->g.len, rs->resultsType->g.s);
     274                 :          0 :         break;
     275                 :            :       }
     276                 :            :       
     277                 :        306 : next_file:
     278                 :            :       continue;
     279                 :            :     }
     280                 :            :     
     281                 :         17 :     closedir(dir);
     282                 :            :   }
     283   [ +  -  +  -  :         17 :   ss = ZX_GET_CONTENT(req->RequestedService->ServiceType);
                   +  - ]
     284   [ +  -  +  -  :         17 :   D("TOTAL discovered %d svctype(%.*s)", n_discovered, ss?ss->len:0, ss?ss->s:"");
             +  -  -  + ]
     285   [ +  -  +  - ]:         17 :   zxlogwsp(cf, ses, "K", "DIOK", 0, "%.*s n=%d", ss?ss->len:1, ss?ss->s:"-", n_discovered);
     286                 :         17 :   resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "OK", 0, 0, 0);  /* last is first */
     287                 :         17 :   D_DEDENT("di_query: ");
     288                 :         17 :   return resp;
     289                 :            : }
     290                 :            : 
     291                 :            : /* EOF  --  zxiddi.c */

Generated by: LCOV version 1.9