LCOV - code coverage report
Current view: top level - zxid - zxidwsc.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 168 351 47.9 %
Date: 2010-12-19 Functions: 10 13 76.9 %
Branches: 134 391 34.3 %

           Branch data     Line data    Source code
       1                 :            : /* zxidwsc.c  -  Handwritten nitty-gritty functions for Liberty ID-WSF Web Services Client
       2                 :            :  * Copyright (c) 2009-2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 2007-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: zxidwsc.c,v 1.19 2010-01-08 02:10:09 sampo Exp $
      10                 :            :  *
      11                 :            :  * 7.1.2007,  created --Sampo
      12                 :            :  * 7.10.2008, added documentation --Sampo
      13                 :            :  * 7.1.2010,  added WSC signing --Sampo
      14                 :            :  * 31.5.2010, added WSC sig validation and PDP calls --Sampo
      15                 :            :  */
      16                 :            : 
      17                 :            : #include "platform.h"  /* needed on Win32 for pthread_mutex_lock() et al. */
      18                 :            : 
      19                 :            : #include "errmac.h"
      20                 :            : #include "zxid.h"
      21                 :            : #include "zxidpriv.h"
      22                 :            : #include "zxidutil.h"
      23                 :            : #include "zxidconf.h"
      24                 :            : #include "saml2.h"
      25                 :            : #include "wsf.h"
      26                 :            : #include "c/zx-const.h"
      27                 :            : #include "c/zx-ns.h"
      28                 :            : #include "c/zx-data.h"
      29                 :            : #include "c/zx-e-data.h"
      30                 :            : 
      31                 :            : /*() WSC response validation work horse. This check the ID-WSF [SOAPbind2] specified
      32                 :            :  * criteria, as well as additional criteria and calls PDP, if configured.
      33                 :            :  *
      34                 :            :  * cf:: ZXID configuration object, see zxid_new_conf()
      35                 :            :  * ses:: Session object, used for attributes passed to az, and for recording errors
      36                 :            :  * az_cred:: (Optional) Additional authorization credentials or
      37                 :            :  *     attributes, query string format. These credentials will be populated
      38                 :            :  *     to the attribute pool in addition to the ones obtained from token and
      39                 :            :  *     other sources. Then a PDP is called to get an authorization
      40                 :            :  *     decision (matching obligations we support to those in the request,
      41                 :            :  *     and obligations pleged by caller to those we insist on). See
      42                 :            :  *     also PEPMAP configuration option. This implements generalized
      43                 :            :  *     (application independent) Responder In PEP. To implement
      44                 :            :  *     application dependent PEP features you should call zxid_az() directly.
      45                 :            :  * env:: Entire SOAP envelope as a data structure
      46                 :            :  * enve:: SOAP envelope as string
      47                 :            :  * return:: 1 on success, 0 on validation failure. Exact reason of the failure is
      48                 :            :  *     available from ses->curflt and ses->curstatus.
      49                 :            :  *
      50                 :            :  * See also: zxid_wsp_validate() */
      51                 :            : 
      52                 :            : /* Called by:  zxid_call_epr, zxid_wsc_valid_resp */
      53                 :            : static int zxid_wsc_valid_re_env(zxid_conf* cf, zxid_ses* ses, const char* az_cred, struct zx_e_Envelope_s* env, const char* enve)
      54                 :         20 : {
      55                 :         20 :   int n_refs = 0;
      56                 :            :   struct zxsig_ref refs[ZXID_N_WSF_SIGNED_HEADERS];
      57                 :            :   struct timeval ourts;
      58                 :         20 :   struct timeval srcts = {0,501000};
      59                 :            :   zxid_entity* wsc_meta;
      60                 :            :   struct zx_wsse_Security_s* sec;
      61                 :            :   struct zx_e_Header_s* hdr;
      62                 :            :   struct zx_str* issuer;
      63                 :            :   struct zx_str* logpath;
      64                 :            :   struct zx_str* relto;
      65                 :            :   struct zx_str ss;
      66                 :            :   zxid_cgi cgi;
      67                 :            : 
      68                 :         20 :   GETTIMEOFDAY(&ourts, 0);
      69                 :         20 :   zxid_set_fault(cf, ses, 0);
      70                 :         20 :   zxid_set_tas3_status(cf, ses, 0);
      71                 :            :   
      72         [ -  + ]:         20 :   if (!env) {
      73         [ #  # ]:          0 :     ERR("No <e:Envelope> found. enve(%s)", STRNULLCHK(enve));
      74                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No SOAP Envelope found.", "IDStarMsgNotUnderstood", 0, 0, 0));
      75                 :          0 :     return 0;
      76                 :            :   }
      77                 :         20 :   hdr = env->Header;
      78         [ -  + ]:         20 :   if (!hdr) {
      79                 :          0 :     ERR("No <e:Header> found. %d", 0);
      80                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No SOAP Header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
      81                 :          0 :     return 0;
      82                 :            :   }
      83   [ +  -  +  -  :         20 :   if (!ZX_SIMPLE_ELEM_CHK(hdr->MessageID)) {
          +  -  +  -  +  
                -  -  + ]
      84                 :          0 :     ERR("No <a:MessageID> found. %d", 0);
      85                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No MessageID header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
      86                 :          0 :     return 0;
      87                 :            :   }
      88   [ +  -  +  -  :         20 :   relto = ZX_GET_CONTENT(hdr->RelatesTo);
                   +  - ]
      89   [ +  -  +  - ]:         40 :   if (relto && relto->len) {
      90         [ +  - ]:         20 :     if (ses->wsc_msgid) {
      91   [ +  -  +  - ]:         40 :       if (strlen(ses->wsc_msgid) == relto->len
      92                 :            :           && !memcmp(ses->wsc_msgid, relto->s, relto->len)) {
      93   [ +  +  -  + ]:         20 :         D("RelatesTo check OK %d",1);
      94                 :            :       } else {
      95                 :            :         /* N.B. [SOAPBinding2] p.27, ll.818-822 indicates RelatesTo checking as SHOULD. */
      96         [ #  # ]:          0 :         if (cf->relto_fatal) {
      97                 :          0 :           ERR("<a:RelatesTo> (%.*s) does not match request msgid(%s).", relto->len, relto->s, ses->wsc_msgid);
      98                 :          0 :           zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "RelatesTo in response does not match request MessageID.", "InvalidRefToMsgID", 0, 0, 0));
      99                 :          0 :           return 0;
     100                 :            :         } else {
     101                 :          0 :           INFO("<a:RelatesTo> (%.*s) does not match request msgid(%s), but configured to ignore this error (RELTO_FATAL=0).", relto->len, relto->s, ses->wsc_msgid);
     102                 :            :         }
     103                 :            :       }
     104                 :            :     } else {
     105                 :          0 :       INFO("Session does not have wsc_msgid. Skipping <a:RelatesTo> check. %d",0);
     106                 :            :     }
     107                 :            :   } else {
     108         [ #  # ]:          0 :     if (cf->relto_fatal) {
     109                 :          0 :       ERR("No <a:RelatesTo> found. %d", 0);
     110                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No RelatesTo header found in reply.", "IDStarMsgNotUnderstood", 0, 0, 0));
     111                 :          0 :       return 0;
     112                 :            :     } else {
     113                 :          0 :       INFO("No <a:RelatesTo> found, but configured to ignore this (RELTO_FATAL=0). %d", 0);
     114   [ #  #  #  #  :          0 :       D("No RelTo OK enve(%s)", STRNULLCHK(enve));
                   #  # ]
     115                 :            :     }
     116                 :            :   }
     117                 :            : 
     118   [ +  -  -  +  :         20 :   if (!hdr->Sender || !hdr->Sender->providerID && !hdr->Sender->affiliationID) {
                   #  # ]
     119                 :          0 :     ERR("No <b:Sender> found (or missing providerID or affiliationID). %p", hdr->Sender);
     120                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No b:Sender header found (or missing providerID or affiliationID).", "IDStarMsgNotUnderstood", 0, 0, 0));
     121                 :          0 :     return 0;
     122                 :            :   }
     123                 :         20 :   issuer = &hdr->Sender->providerID->g;
     124                 :            :   
     125                 :            :   /* Validate message signature (*** add Issuer trusted check, CA validation, etc.) */
     126                 :            :   
     127         [ -  + ]:         20 :   if (!(sec = hdr->Security)) {
     128                 :          0 :     ERR("No <wsse:Security> found. %d", 0);
     129                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No wsse:Security header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
     130                 :          0 :     return 0;
     131                 :            :   }
     132                 :            : 
     133   [ +  -  +  -  :         20 :   if (!sec->Signature || !sec->Signature->SignedInfo || !sec->Signature->SignedInfo->Reference) {
                   -  + ]
     134                 :          0 :     ses->sigres = ZXSIG_NO_SIG;
     135         [ #  # ]:          0 :     if (cf->wsp_nosig_fatal) {
     136                 :          0 :       ERR("No Security/Signature found. %p", sec->Signature);
     137                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No wsse:Security/ds:Signature found.", TAS3_STATUS_NOSIG, 0, 0, 0));
     138                 :          0 :       return 0;
     139                 :            :     } else {
     140                 :          0 :       INFO("No Security/Signature found, but configured to ignore this problem (WSP_NOSIG_FATAL=0). %p", sec->Signature);
     141                 :            :     }
     142                 :            :   }
     143                 :            :   
     144                 :         20 :   wsc_meta = zxid_get_ent_ss(cf, issuer);
     145         [ -  + ]:         20 :   if (!wsc_meta) {
     146                 :          0 :     ses->sigres = ZXSIG_NO_SIG;
     147         [ #  # ]:          0 :     if (cf->nosig_fatal) {
     148                 :          0 :       INFO("Unable to find SAML metadata for Sender(%.*s), but configured to ignore this problem (NOSIG_FATAL=0).", issuer->len, issuer->s);
     149                 :            :     } else {
     150                 :          0 :       ERR("Unable to find SAML metadata for Sender(%.*s).", issuer->len, issuer->s);
     151                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "No unable to find SAML metadata for sender.", "ProviderIDNotValid", 0, 0, 0));
     152                 :          0 :       return 0;
     153                 :            :     }
     154                 :            :   }
     155                 :            : 
     156                 :         20 :   ZERO(refs, sizeof(refs));
     157                 :         20 :   n_refs = zxid_hunt_sig_parts(cf, n_refs, refs, sec->Signature->SignedInfo->Reference, hdr, env->Body);
     158                 :            :   /* *** Consider adding BDY and STR */
     159         [ +  - ]:         20 :   ses->sigres = zxsig_validate(cf->ctx, wsc_meta?wsc_meta->sign_cert:0, sec->Signature, n_refs, refs);
     160                 :         20 :   zxid_sigres_map(ses->sigres, &cgi.sigval, &cgi.sigmsg);
     161   [ +  -  -  + ]:         20 :   if (cf->sig_fatal && ses->sigres) {
     162                 :          0 :     ERR("Fail due to failed message signature sigres=%d", ses->sigres);
     163                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "Message signature did not validate.", TAS3_STATUS_BADSIG, 0, 0, 0));
     164                 :          0 :     return 0;
     165                 :            :   }
     166                 :            : 
     167         [ -  + ]:         20 :   if (!zxid_timestamp_chk(cf, ses, sec->Timestamp, &ourts, &srcts, TAS3_PEP_RS_IN, "e:Server"))
     168                 :          0 :     return 0;
     169                 :            : 
     170         [ +  - ]:         20 :   if (hdr->UsageDirective) {
     171   [ +  -  +  -  :         40 :     if (hdr->UsageDirective->Obligation && ZX_GET_CONTENT(hdr->UsageDirective->Obligation->AttributeAssignment)) {
             +  -  +  - ]
     172   [ +  -  +  -  :         20 :       ses->rcvd_usagedir = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(hdr->UsageDirective->Obligation->AttributeAssignment));
                   +  - ]
     173   [ +  +  -  + ]:         20 :       D("Found TAS3 UsageDirective with obligation(%s)", ses->rcvd_usagedir);
     174   [ #  #  #  #  :          0 :     } else if (ZX_GET_CONTENT(hdr->UsageDirective)) {
                   #  # ]
     175   [ #  #  #  #  :          0 :       ses->rcvd_usagedir = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(hdr->UsageDirective));
                   #  # ]
     176   [ #  #  #  # ]:          0 :       D("Found unknown UsageDirective(%s)", ses->rcvd_usagedir);
     177                 :            :     } else {
     178                 :          0 :       ERR("UsageDirective empty or not understood. %p", hdr->UsageDirective->Dict);
     179                 :            :     }
     180                 :            :   }
     181                 :            : 
     182                 :         20 :   zxid_ses_to_pool(cf, ses);
     183                 :         20 :   zxid_snarf_eprs_from_ses(cf, ses);  /* Harvest attributes and bootstrap(s) */
     184                 :            : 
     185   [ -  +  #  #  :         20 :   if (hdr->Status && hdr->Status->code
          #  #  #  #  #  
                      # ]
     186                 :            :       && (hdr->Status->code->g.len != 2
     187                 :            :           || hdr->Status->code->g.s[0] != 'O'
     188                 :            :           || hdr->Status->code->g.s[1] != 'K')) {
     189                 :          0 :     ERR("TAS3 or app level error code(%.*s)", hdr->Status->code->g.len, hdr->Status->code->g.s);
     190                 :          0 :     return 0;
     191                 :            :   }
     192                 :            :   
     193                 :            :   /* Call Rs-In PDP */
     194                 :            :   
     195         [ -  + ]:         20 :   if (!zxid_localpdp(cf, ses)) {
     196                 :          0 :     ERR("RSIN4 Deny by local PDP %d",0);
     197                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Client", "Response denied by WSC local policy", TAS3_STATUS_DENY, 0, 0, 0));
     198                 :          0 :     return 0;
     199   [ +  -  +  - ]:         20 :   } else if (cf->pdp_url && *cf->pdp_url) {
     200                 :            :     //zxid_add_attr_to_pool(cf, ses, "Action", zx_dup_str(cf->ctx, "access"));
     201         [ -  + ]:         20 :     if (!zxid_pep_az_soap_pepmap(cf, 0, ses, cf->pdp_url, cf->pepmap_rsin)) {
     202                 :          0 :       ERR("RSIN4 Deny %d", 0);
     203                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Client", "Response denied by WSC policy at PDP", TAS3_STATUS_DENY, 0, 0, 0));
     204                 :          0 :       return 0;
     205                 :            :     }
     206                 :            :   }
     207                 :            :   
     208                 :            :   /* *** execute (or store for future execution) the obligations. */
     209                 :            :   
     210                 :         20 :   ss.s = (char*)enve;
     211                 :         20 :   ss.len = strlen(enve);
     212   [ +  -  +  -  :         20 :   logpath = zxlog_path(cf, issuer, ZX_GET_CONTENT(hdr->MessageID),
                   +  - ]
     213                 :            :                        ZXLOG_RELY_DIR, ZXLOG_MSG_KIND, 1);
     214         [ -  + ]:         20 :   if (zxlog_dup_check(cf, logpath, "validate response")) {
     215         [ #  # ]:          0 :     if (cf->dup_msg_fatal) {
     216                 :          0 :       zxlog_blob(cf, cf->log_rely_msg, logpath, &ss, "validate response dup err");
     217                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Server", "Duplicate Message.", "DuplicateMsg", 0, 0, 0));
     218                 :          0 :       return 0;
     219                 :            :     } else {
     220                 :          0 :       INFO("Duplicate message detected, but configured to ignore this (DUP_MSG_FATAL=0). %d",0);
     221                 :            :     }
     222                 :            :   }
     223                 :         20 :   zxlog_blob(cf, cf->log_rely_msg, logpath, &ss, "validate response");
     224   [ +  +  +  -  :         20 :   zxlog(cf, &ourts, &srcts, 0, issuer, 0, ses->a7n?&ses->a7n->ID->g:0, ZX_GET_CONTENT(ses->nameid), "N", "K", "VALID", logpath->s, 0);
             +  -  +  + ]
     225                 :         20 :   return 1;
     226                 :            : }
     227                 :            : 
     228                 :            : /*() Prepare some headers for WSC call */
     229                 :            : 
     230                 :            : /* Called by:  zxid_wsc_call */
     231                 :            : static int zxid_wsc_prep(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr, struct zx_e_Envelope_s* env)
     232                 :         38 : {
     233                 :            :   zxid_tok* tok;
     234                 :            :   struct zx_e_Header_s* hdr;
     235         [ -  + ]:         38 :   if (!zxid_wsf_decor(cf, ses, env, 0))
     236                 :          0 :     return 0;
     237                 :         38 :   hdr = env->Header;
     238                 :            : 
     239   [ +  -  -  +  :         38 :   if (ses->call_tgttok || ses->call_invoktok && epr && epr->Metadata && epr->Metadata->SecurityContext && epr->Metadata->SecurityContext->Token) {
          #  #  #  #  #  
                #  #  # ]
     240         [ #  # ]:          0 :     if (ses->call_tgttok) {
     241   [ #  #  #  # ]:          0 :       D("TargetIdentity: Explicit specification of ses->call_tgttok %d",0);
     242                 :          0 :       tok = ses->call_tgttok;
     243                 :            :     } else {
     244   [ #  #  #  # ]:          0 :       D("TargetIdentity: Using token from EPR due to specification of ses->call_invoktok %d",0);
     245                 :          0 :       tok = epr->Metadata->SecurityContext->Token;
     246                 :            :     }
     247                 :          0 :     hdr->TargetIdentity = zx_NEW_b_TargetIdentity(cf->ctx, &hdr->gg);
     248                 :          0 :     hdr->TargetIdentity->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->TargetIdentity->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     249                 :          0 :     hdr->TargetIdentity->actor = zx_ref_attr(cf->ctx, &hdr->TargetIdentity->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     250         [ #  # ]:          0 :     if (tok->EncryptedAssertion) {
     251                 :          0 :       ZX_ADD_KID(hdr->TargetIdentity, EncryptedAssertion, tok->EncryptedAssertion);
     252         [ #  # ]:          0 :     } else if (tok->Assertion) {
     253                 :          0 :       ZX_ADD_KID(hdr->TargetIdentity, Assertion, tok->Assertion);
     254                 :            :     } else {
     255                 :          0 :       ERR("No <sa:EncryptedAssertion> or <sa:Assertion> found in <sec:Token> %p", tok);
     256                 :            :     }
     257                 :            :   } /* else this is just implied by the sec mech */
     258                 :            : 
     259                 :            : #if 1
     260                 :            :   /* Mandatory for a request. */
     261                 :         38 :   hdr->ReplyTo = zx_NEW_a_ReplyTo(cf->ctx, &hdr->gg);
     262                 :            :   /*hdr->ReplyTo->Address = zxid_mk_addr(cf, zx_strf(cf->ctx, "%s?o=P", cf->url));*/
     263                 :         38 :   hdr->ReplyTo->Address = zxid_mk_addr(cf, &hdr->ReplyTo->gg, zx_dup_str(cf->ctx, A_ANON));
     264                 :         38 :   hdr->ReplyTo->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->ReplyTo->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     265                 :         38 :   hdr->ReplyTo->actor = zx_ref_attr(cf->ctx, &hdr->ReplyTo->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     266                 :            : #endif
     267                 :            : 
     268                 :         38 :   hdr->To = zx_NEW_a_To(cf->ctx, &hdr->gg);
     269   [ +  -  +  -  :         38 :   zx_add_content(cf->ctx, &hdr->To->gg, ZX_GET_CONTENT(epr->Address));
                   +  - ]
     270                 :         38 :   hdr->To->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->To->gg, zx_e_mustUnderstand_ATTR,XML_TRUE);
     271                 :         38 :   hdr->To->actor = zx_ref_attr(cf->ctx, &hdr->To->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     272                 :            : 
     273                 :            : #if 0
     274                 :            :   /* Omission means to use same address as ReplyTo */
     275                 :            :   hdr->FaultTo = zx_NEW_a_FaultTo(cf->ctx, &hdr->gg);
     276                 :            :   hdr->FaultTo->Address = zx_mk_addr(cf->ctx, &hdr->FaultTo->gg, zx_strf(cf->ctx, "%s?o=P", cf->url));
     277                 :            :   hdr->FaultTo->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->FaultTo->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     278                 :            :   hdr->FaultTo->actor = zx_ref_attr(cf->ctx, &hdr->FaultTo->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     279                 :            : #endif
     280                 :            : 
     281                 :         38 :   zxid_attach_sol1_usage_directive(cf, ses, env, TAS3_PLEDGE, cf->wsc_localpdp_obl_pledge);
     282                 :         38 :   zx_reverse_elem_lists(&hdr->gg);
     283                 :         38 :   return 1;
     284                 :            : }
     285                 :            : 
     286                 :            : /* Called by:  zxid_wsc_prep_secmech x2 */
     287                 :            : static void zxid_choose_sectok(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr, struct zx_wsse_Security_s* sec)
     288                 :         38 : {
     289                 :            :   zxid_tok* tok;
     290         [ -  + ]:         38 :   if (ses->call_invoktok) {
     291   [ #  #  #  # ]:          0 :     D("Security Token: Explicit specification of ses->call_invoktok %d",0);
     292                 :          0 :     tok = ses->call_invoktok;
     293                 :            :   } else {
     294   [ +  -  +  -  :         76 :     if (epr && epr->Metadata && epr->Metadata->SecurityContext && epr->Metadata->SecurityContext->Token) {
             +  -  +  - ]
     295   [ +  +  -  + ]:         38 :       D("Security Token: Using token from EPR Metadata %d",0);
     296                 :         38 :       tok = epr->Metadata->SecurityContext->Token;
     297                 :            :     } else {
     298                 :          0 :       ERR("Security Token: No SecurityContext in EPR Metadata %p",epr);
     299                 :          0 :       return;
     300                 :            :     }
     301                 :            :   }
     302         [ +  - ]:         38 :   if (tok->EncryptedAssertion) {
     303                 :         38 :     sec->EncryptedAssertion = tok->EncryptedAssertion;
     304                 :         38 :     zx_add_kid_before(&sec->gg, zx_wsu_Timestamp_ELEM, &sec->EncryptedAssertion->gg);
     305         [ #  # ]:          0 :   } else if (tok->Assertion) {
     306                 :          0 :     sec->Assertion = tok->Assertion;
     307                 :          0 :     zx_add_kid_before(&sec->gg, zx_wsu_Timestamp_ELEM, &sec->Assertion->gg);
     308                 :            :   } else
     309                 :          0 :     ERR("No <sa:EncryptedAssertion> or <sa:Assertion> found in <sec:Token> %p", tok);
     310                 :            : }
     311                 :            : 
     312                 :            : /*() Perform security mechanism related processing for a WSC call */
     313                 :            : 
     314                 :            : /* Called by:  zxid_wsc_call */
     315                 :            : static int zxid_wsc_prep_secmech(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr, struct zx_e_Envelope_s* env)
     316                 :         38 : {
     317                 :            :   int secmech;
     318                 :            :   struct zx_wsse_Security_s* sec;
     319                 :            :   struct zx_wsse_SecurityTokenReference_s* str;
     320                 :            :   struct zx_e_Header_s* hdr;
     321                 :            :   
     322   [ +  -  -  + ]:         38 :   if (!epr || !env) {
     323                 :          0 :     ERR("MUST supply epr %p and envelope as arguments", epr);
     324                 :          0 :     return 0;
     325                 :            :   }
     326                 :            : 
     327                 :         38 :   hdr = env->Header;
     328                 :         38 :   zx_add_content(cf->ctx, &hdr->MessageID->gg, zxid_mk_id(cf, "urn:M", ZXID_ID_BITS));
     329                 :         38 :   sec = hdr->Security;
     330   [ +  -  +  -  :         38 :   if (!sec || !sec->Timestamp || !sec->Timestamp->Created) {
                   -  + ]
     331                 :          0 :     ERR("MUST supply wsse:Security and Timestamp %p", sec);
     332                 :          0 :     return 0;
     333                 :            :   }
     334                 :         38 :   zx_add_content(cf->ctx, &sec->Timestamp->Created->gg, zxid_date_time(cf, time(0)));
     335                 :            :     
     336                 :            :   /* Clear away any credentials from previous iteration, if any. *** clear kids list, too */
     337                 :         38 :   sec->Signature = 0;
     338                 :         38 :   sec->BinarySecurityToken = 0;
     339                 :         38 :   sec->SecurityTokenReference = 0;
     340                 :         38 :   sec->Assertion = 0;
     341                 :         38 :   sec->EncryptedAssertion = 0;
     342                 :         38 :   sec->sa11_Assertion = 0;
     343                 :         38 :   sec->ff12_Assertion = 0;
     344                 :            :     
     345                 :            :   /* Sign all Headers that have Id set. See wsc_sign_sec_mech() */
     346                 :         38 :   secmech = zxid_map_sec_mech(epr);
     347   [ -  +  -  -  :         38 :   switch (secmech) {
                   -  - ]
     348                 :            :   case ZXID_SEC_MECH_NULL:
     349   [ #  #  #  # ]:          0 :     D("secmech null %d", secmech);
     350                 :          0 :     break;
     351                 :            :   case ZXID_SEC_MECH_BEARER:
     352                 :         38 :     zxid_choose_sectok(cf, ses, epr, sec);
     353                 :         38 :     str = sec->SecurityTokenReference = zx_NEW_wsse_SecurityTokenReference(cf->ctx, 0);
     354                 :         38 :     zx_add_kid_before(&sec->gg, zx_wsu_Timestamp_ELEM, &str->gg);
     355                 :         38 :     str->KeyIdentifier = zx_NEW_wsse_KeyIdentifier(cf->ctx, &str->gg);
     356                 :         38 :     str->KeyIdentifier->ValueType = zx_ref_attr(cf->ctx, &str->KeyIdentifier->gg, zx_ValueType_ATTR, SAMLID_TOK_PROFILE);
     357         [ -  + ]:         38 :     if (sec->Assertion)
     358                 :          0 :       zx_add_content(cf->ctx, &str->KeyIdentifier->gg, &sec->Assertion->ID->g);
     359                 :            :     /* *** In case of encrypted assertion, how is the KeyIdentifier populated? */
     360                 :            :     
     361                 :         38 :     zxid_wsf_sign(cf, cf->wsc_sign, sec, str, hdr, env->Body);
     362   [ +  +  -  + ]:         38 :     D("secmech bearer %d", secmech);
     363                 :         38 :     break;
     364                 :            :   case ZXID_SEC_MECH_SAML:
     365                 :          0 :     zxid_choose_sectok(cf, ses, epr, sec);
     366                 :            :     /* *** Sign SEC, MID, TO, ACT (if any) */
     367                 :          0 :     zxid_wsf_sign(cf, cf->wsc_sign, sec, 0, hdr, env->Body);
     368   [ #  #  #  # ]:          0 :     D("secmech saml hok %d", secmech);
     369                 :          0 :     break;
     370                 :            :   case ZXID_SEC_MECH_X509:
     371                 :            :     /* *** Sign SEC, MID, TO, ACT (if any) */
     372                 :          0 :     zxid_wsf_sign(cf, cf->wsc_sign, sec, 0, hdr, env->Body);
     373   [ #  #  #  # ]:          0 :     D("secmech x509 %d", secmech);
     374                 :          0 :     break;
     375                 :            :   case ZXID_SEC_MECH_PEERS:
     376                 :            :     /* *** ? */
     377   [ #  #  #  # ]:          0 :     D("secmech peers %d", secmech);
     378                 :          0 :     break;
     379                 :            :   default:
     380                 :          0 :     ERR("Unknown secmech %d", secmech);
     381                 :          0 :     return 0;
     382                 :            :   }
     383                 :         38 :   return 1;
     384                 :            : }
     385                 :            : 
     386                 :            : /*(i) zxid_wsc_call() implements the main low level ID-WSF web service call
     387                 :            :  * logic, including preparation of SOAP headers, use of sec mech (e.g.
     388                 :            :  * preparation of wsse:Security header and signing of appropriate components
     389                 :            :  * of the message), and sequencing of the call. In particular, it is
     390                 :            :  * possible that WSP requests user interaction and thus the caller web
     391                 :            :  * application will need to perform a redirect and then later call this
     392                 :            :  * function again to continue the web service call after interaction.
     393                 :            :  *
     394                 :            :  * env (rather than Body) is taken as argument so that caller can prepare
     395                 :            :  * additional SOAP headers at will before calling this function. This function
     396                 :            :  * will add Liberty ID-WSF specific SOAP headers. */
     397                 :            : 
     398                 :            : /* Called by:  main x9, zxid_call_epr, zxid_get_epr, zxid_map_identity_token, zxid_nidmap_identity_token */
     399                 :            : struct zx_e_Envelope_s* zxid_wsc_call(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr, struct zx_e_Envelope_s* env, char** ret_enve)
     400                 :         37 : {
     401                 :            :   int i, res;
     402                 :            :   struct zx_str* code;
     403                 :            :   struct zx_str* str;
     404                 :            :   struct zx_str* actor;
     405                 :            :   struct zx_root_s* root;
     406                 :            :   struct zx_e_Fault_s* flt;
     407                 :            : 
     408                 :         37 :   D_INDENT("wsc_call: ");
     409                 :            :   
     410         [ -  + ]:         37 :   if (!zxid_wsc_prep(cf, ses, epr, env)) {
     411                 :          0 :     D_DEDENT("wsc_call: ");
     412                 :          0 :     return 0;
     413                 :            :   }
     414                 :            :   
     415         [ +  - ]:         37 :   for (i=0; i < cf->max_soap_retry; ++i) {
     416         [ -  + ]:         37 :     if (!zxid_wsc_prep_secmech(cf, ses, epr, env)) {
     417                 :          0 :       D_DEDENT("wsc_call: ");
     418                 :          0 :       return 0;
     419                 :            :     }
     420   [ +  -  +  -  :         37 :     ses->wsc_msgid = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(env->Header->MessageID));
                   +  - ]
     421                 :            :     
     422   [ +  -  +  -  :         37 :     root = zxid_soap_call_raw(cf, ZX_GET_CONTENT(epr->Address), env, ret_enve);
                   +  - ]
     423   [ +  +  +  -  :         37 :     if (!root || !root->Envelope || !root->Envelope->Body) {
                   -  + ]
     424                 :          2 :       ERR("soap call returned empty or seriously flawed response %p", root);
     425                 :          2 :       D_DEDENT("wsc_call: ");
     426                 :          2 :       return 0;
     427                 :            :     }
     428                 :         35 :     flt = root->Envelope->Body->Fault;
     429         [ -  + ]:         35 :     if (flt) {
     430   [ #  #  #  #  :          0 :       code = ZX_GET_CONTENT(flt->faultcode);
                   #  # ]
     431   [ #  #  #  #  :          0 :       str = ZX_GET_CONTENT(flt->faultstring);
                   #  # ]
     432   [ #  #  #  #  :          0 :       actor = ZX_GET_CONTENT(flt->faultactor);
                   #  # ]
     433   [ #  #  #  #  :          0 :       D("SOAP Fault(%.*s) string(%.*s) actor(%.*s)", code?code->len:1, code?code->s:"?", str?str->len:1, str?str->s:"?", actor?actor->len:1, actor?actor->s:"?");
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     434                 :          0 :       D_DEDENT("wsc_call: ");
     435                 :          0 :       return 0;
     436                 :            :     }
     437                 :            :     
     438                 :            :     //res = zxid_wsf_analyze_result_headers(cf, ret);
     439                 :         35 :     res = ZXID_OK;
     440      [ +  -  - ]:         35 :     switch (res) {
     441                 :            :     case ZXID_OK:
     442                 :         35 :       D_DEDENT("wsc_call: ");
     443                 :         35 :       return root->Envelope;
     444                 :            : #if 0
     445                 :            :     case ZXID_NEW_CRED:
     446                 :            :       break;
     447                 :            :     case ZXID_EP_MOVE:  // ***
     448                 :            :       break;
     449                 :            :     case ZXID_EP_UPDATE:
     450                 :            :       break;
     451                 :            : #endif
     452                 :            :     case ZXID_REDIR_OK:
     453   [ #  #  #  # ]:          0 :       D("Redirection requested (e.g. Interaction Service) %d", 0);
     454                 :          0 :       D_DEDENT("wsc_call: ");
     455                 :          0 :       return (void*)ZXID_REDIR_OK;
     456                 :            :     default:
     457                 :          0 :       ERR("Unknown result code: %d", res);
     458                 :          0 :       D_DEDENT("wsc_call: ");
     459                 :          0 :       return 0;
     460                 :            :     }
     461                 :            :   }
     462                 :          0 :   ERR("Number of soap call retries exhausted max_soap_retry=%d", cf->max_soap_retry);
     463                 :          0 :   D_DEDENT("wsc_call: ");
     464                 :          0 :   return 0;
     465                 :            : }
     466                 :            : 
     467                 :            : static char zx_env_body_open[]  = "<e:Envelope xmlns:e=\""zx_xmlns_e"\"><e:Header></e:Header><e:Body>";
     468                 :            : static char zx_env_body_close[] = "</e:Body></e:Envelope>";
     469                 :            : #if 0
     470                 :            : static char zx_env_open[]  = "<e:Envelope xmlns:e=\""zx_xmlns_e"\"><e:Header></e:Header>";
     471                 :            : static char zx_env_close[] = "</e:Envelope>";
     472                 :            : #endif
     473                 :            : 
     474                 :            : /*() Convenience helper function to parse SOAP Envelope input string.
     475                 :            :  * If the specified envelope is incomplete, it is completed.
     476                 :            :  *
     477                 :            :  * If the string starts by "<e:Envelope", then string
     478                 :            :  * should be a complete SOAP envelope including <e:Header> and <e:Body> parts.
     479                 :            :  * If the string starts by "<e:Body", then the <e:Envelope> and <e:Header> are
     480                 :            :  * automatically added. If the string starts by neither of the above (be
     481                 :            :  * careful to use the "e:" as namespace prefix), then it is assumed to be the
     482                 :            :  * payload content of the <e:Body> and the rest of the SOAP envelope is added.
     483                 :            :  */
     484                 :            : 
     485                 :            : /* Called by:  zxid_call_epr, zxid_wsc_prepare_call, zxid_wsc_valid_resp, zxid_wsp_decorate */
     486                 :            : struct zx_e_Envelope_s* zxid_add_env_if_needed(zxid_conf* cf, const char* enve)
     487                 :         39 : {
     488                 :            :   struct zx_e_Envelope_s* env;
     489                 :            :   struct zx_root_s* r;
     490                 :            : #if 0
     491                 :            : #endif
     492                 :         39 :   r = zx_dec_zx_root(cf->ctx, strlen(enve), enve, "add_env");
     493         [ -  + ]:         39 :   if (!r) {
     494                 :          0 :     ERR("Malformed XML enve(%s)", enve);
     495                 :          0 :     return 0;
     496                 :            :   }
     497                 :         39 :   env = r->Envelope;
     498         [ +  + ]:         39 :   if (env) {
     499         [ -  + ]:          1 :     if (!env->Body)
     500                 :          0 :       env->Body = zx_NEW_e_Body(cf->ctx, &env->gg);
     501         [ -  + ]:          1 :     if (!env->Header)
     502                 :          0 :       env->Header = zx_NEW_e_Header(cf->ctx, &env->gg);
     503         [ -  + ]:         38 :   } else if (r->Body) {
     504                 :          0 :     env = zx_NEW_e_Envelope(cf->ctx,0);
     505                 :          0 :     ZX_ADD_KID(env, Body, r->Body);
     506         [ #  # ]:          0 :     if (r->Header)
     507                 :          0 :       ZX_ADD_KID(env, Header, r->Header);
     508                 :            :     else
     509                 :          0 :       env->Header = zx_NEW_e_Header(cf->ctx, &env->gg);
     510                 :            :   } else { /* Resort to stringwise attempt to add envelope. */
     511                 :         38 :     ZX_FREE(cf->ctx, r);
     512         [ -  + ]:         38 :     if (!memcmp(enve, "<?xml ", sizeof("<?xml ")-1)) {  /* Ignore common, but unnecessary decl. */
     513   [ #  #  #  #  :          0 :       for (enve += sizeof("<?xml "); *enve && !(enve[0] == '?' && enve[1] == '>'); ++enve) ;
                   #  # ]
     514         [ #  # ]:          0 :       if (*enve)
     515                 :          0 :         enve += 2;
     516                 :            :     }
     517                 :            :     /* Must be just payload */
     518                 :         38 :     enve = zx_alloc_sprintf(cf->ctx, 0, "%s%s%s", zx_env_body_open, enve, zx_env_body_close);
     519                 :         38 :     r = zx_dec_zx_root(cf->ctx, strlen(enve), enve, "add_env2");
     520         [ -  + ]:         38 :     if (!r) {
     521                 :          0 :       ERR("Malformed XML enve(%s)", enve);
     522                 :          0 :       return 0;
     523                 :            :     }
     524                 :         38 :     env = r->Envelope;
     525                 :            :   }
     526                 :         39 :   ZX_FREE(cf->ctx, r);
     527         [ -  + ]:         39 :   if (!env)
     528                 :          0 :     ERR("No <e:Envelope> found in input argument. enve(%s)", enve);
     529                 :         39 :   return env;
     530                 :            : }
     531                 :            : 
     532                 :            : /* ----------------------------------------
     533                 :            :  * Simplify writing WSCs */
     534                 :            : 
     535                 :            : /*() Make a SOAP call given XML payload for SOAP <e:Envelope> or <e:Body> content,
     536                 :            :  * specified by the string. Assumes the EPR has already been discovered.
     537                 :            :  * This is sometimes useful in prediscovered or delegated use cases, but
     538                 :            :  * normally you should be using zxid_call() and let the discovery
     539                 :            :  * take its course. */
     540                 :            : 
     541                 :            : /* Called by:  zxid_call, zxid_callf_epr */
     542                 :            : struct zx_str* zxid_call_epr(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr, const char* az_cred, const char* enve)
     543                 :         19 : {
     544                 :            :   char* ret_enve;
     545                 :            :   struct zx_str* ret;
     546                 :            :   struct zx_e_Envelope_s* env;
     547                 :            : 
     548   [ +  -  +  -  :         19 :   if (!cf || !ses || !enve) {
                   -  + ]
     549                 :          0 :     ERR("Missing mandatory arguments ses=%p", ses);
     550                 :          0 :     return 0;
     551                 :            :   }
     552                 :            : 
     553                 :         19 :   D_INDENT("call: ");
     554                 :         19 :   env = zxid_add_env_if_needed(cf, enve);
     555         [ -  + ]:         19 :   if (!env) {
     556                 :          0 :     D_DEDENT("call: ");
     557                 :          0 :     return 0;
     558                 :            :   }
     559                 :            :   
     560                 :            :   /* Call Rq-Out PDP */
     561                 :            :   
     562         [ -  + ]:         19 :   if (!zxid_localpdp(cf, ses)) {
     563                 :          0 :     ERR("RQOUT1 Deny by local PDP %d",0);
     564                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_OUT, "e:Client", "Request denied by WSC local policy", TAS3_STATUS_DENY, 0, 0, 0));
     565                 :          0 :     D_DEDENT("call: ");
     566                 :          0 :     return 0;
     567   [ +  -  +  - ]:         19 :   } else if (cf->pdp_url && *cf->pdp_url) {
     568                 :            :     //zxid_add_attr_to_pool(cf, ses, "Action", zx_dup_str(cf->ctx, "access"));
     569         [ -  + ]:         19 :     if (!zxid_pep_az_soap_pepmap(cf, 0, ses, cf->pdp_url, cf->pepmap_rqout)) {
     570                 :          0 :       ERR("RQOUT1 Deny %d", 0);
     571                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_OUT, "e:Client", "Request denied by WSC policy", TAS3_STATUS_DENY, 0, 0, 0));
     572                 :          0 :       D_DEDENT("call: ");
     573                 :          0 :       return 0;
     574                 :            :     }
     575                 :            :   }
     576                 :            : 
     577                 :            :   /* *** add usage directives */
     578                 :            : 
     579                 :         19 :   env = zxid_wsc_call(cf, ses, epr, env, &ret_enve);
     580         [ -  + ]:         19 :   if (zxid_wsc_valid_re_env(cf, ses, az_cred, env, ret_enve) != 1) {
     581                 :          0 :     D_DEDENT("call: ");
     582                 :          0 :     return 0;
     583                 :            :   }
     584                 :            :   
     585                 :         19 :   ret = zx_easy_enc_elem_opt(cf, &env->gg);
     586                 :         19 :   D_DEDENT("call: ");
     587                 :         19 :   return ret;
     588                 :            : }
     589                 :            : 
     590                 :            : /*() Call web service, printf style. See zxid_call() for more documentation.
     591                 :            :  * Normally you should be calling zxid_callf() instead. */
     592                 :            : 
     593                 :            : /* Called by: */
     594                 :            : struct zx_str* zxid_callf_epr(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr, const char* az_cred, const char* env_f, ...)
     595                 :          0 : {
     596                 :            :   char* s;
     597                 :            :   va_list ap;
     598                 :          0 :   va_start(ap, env_f);
     599                 :          0 :   s = zx_alloc_vasprintf(cf->ctx, 0, env_f, ap);
     600                 :          0 :   va_end(ap);
     601                 :          0 :   return zxid_call_epr(cf, ses, epr, az_cred, s);
     602                 :            : }
     603                 :            : 
     604                 :            : /*(i) Make a SOAP call given XML payload for SOAP <e:Envelope> or <e:Body> content,
     605                 :            :  * specified by the string. This is your WSC work horse for calling almost any kind
     606                 :            :  * of web service. Simple and intuitive specification of XML as string: no need
     607                 :            :  * to build complex data structures.
     608                 :            :  *
     609                 :            :  * If the string starts by "<e:Envelope", then string
     610                 :            :  * should be a complete SOAP envelope including <e:Header> and <e:Body> parts. This
     611                 :            :  * allows caller to specify custom SOAP headers, in addition to the ones
     612                 :            :  * that the underlying zxid_wsc_call() will add. Usually the payload service
     613                 :            :  * will be passed as the contents of the body. If the string starts by
     614                 :            :  * "<e:Body", then the <e:Envelope> and <e:Header> are automatically added. If
     615                 :            :  * the string starts by neither of the above (be careful to use the "e:" as
     616                 :            :  * namespace prefix), then it is assumed to be the payload content of the <e:Body>
     617                 :            :  * and the rest of the SOAP envelope is added.
     618                 :            :  *
     619                 :            :  * cf:: ZXID configuration object, see zxid_new_conf()
     620                 :            :  * ses:: Session object that contains the EPR cache
     621                 :            :  * svctype:: URI (often the namespace URI) specifying the kind of service we
     622                 :            :  *     wish to call. Used for EPR lookup or discovery.
     623                 :            :  * url:: (Optional) If provided, this argument has to match either
     624                 :            :  *     the ProviderID, EntityID, or actual service endpoint URL.
     625                 :            :  * di_opt:: (Optional) Additional discovery options for selecting the
     626                 :            :  *     service, query string format
     627                 :            :  * az_cred:: (Optional) Additional authorization credentials or
     628                 :            :  *     attributes, query string format. These credentials will be populated
     629                 :            :  *     to the attribute pool in addition to the ones obtained from SSO and
     630                 :            :  *     other sources. Then a PDP is called to get an authorization decision
     631                 :            :  *     (as well as obligations we pledge to support). See also PEPMAP
     632                 :            :  *     configuration option. This implementes generalized (application
     633                 :            :  *     independent) Requestor Out and Requestor In PEPs. To implement
     634                 :            :  *     application dependent PEP features you should call zxid_az() directly.
     635                 :            :  * env:: XML payload
     636                 :            :  * return:: SOAP Envelope of the response, as a string. You can parse this
     637                 :            :  *     string to obtain all returned SOAP headers as well as the Body and its
     638                 :            :  *     content. NULL on failure. ses->curflt and/or ses->curstatus contain
     639                 :            :  *     more detailed error information. */
     640                 :            : 
     641                 :            : /* Called by:  zxcall_main, zxid_callf */
     642                 :            : struct zx_str* zxid_call(zxid_conf* cf, zxid_ses* ses, const char* svctype, const char* url, const char* di_opt, const char* az_cred, const char* enve)
     643                 :         20 : {
     644                 :            :   zxid_epr* epr;
     645                 :            : 
     646   [ +  -  -  + ]:         20 :   if (!cf || !ses) {
     647                 :          0 :     ERR("Missing mandatory arguments ses=%p", ses);
     648                 :          0 :     return 0;
     649                 :            :   }
     650                 :            : 
     651                 :         20 :   epr = zxid_get_epr(cf, ses, svctype, url, di_opt, 0 /*Action*/, 1);
     652         [ +  + ]:         20 :   if (!epr) {
     653                 :          1 :     ERR("EPR could not be discovered for svctype(%s)", svctype);
     654                 :          1 :     return 0;
     655                 :            :   }
     656                 :            :   
     657                 :         19 :   return zxid_call_epr(cf, ses, epr, az_cred, enve);
     658                 :            : }
     659                 :            : 
     660                 :            : /*() Call web service, printf style. See zxid_call() for more documentation. */
     661                 :            : 
     662                 :            : /* Called by:  main */
     663                 :            : struct zx_str* zxid_callf(zxid_conf* cf, zxid_ses* ses, const char* svctype, const char* url, const char* di_opt, const char* az_cred, const char* env_f, ...)
     664                 :          0 : {
     665                 :            :   char* s;
     666                 :            :   va_list ap;
     667                 :          0 :   va_start(ap, env_f);
     668                 :          0 :   s = zx_alloc_vasprintf(cf->ctx, 0, env_f, ap);
     669                 :          0 :   va_end(ap);
     670                 :          0 :   return zxid_call(cf, ses, svctype, url, di_opt, az_cred, s);
     671                 :            : }
     672                 :            : 
     673                 :            : /*(i) Prepare a SOAP call given XML payload for SOAP <e:Envelope> or <e:Body> content,
     674                 :            :  * specified by the string. Usually you should use zxid_call(), but if you want
     675                 :            :  * to control the steps yourself or use your own http client, this function
     676                 :            :  * may be useful.
     677                 :            :  *
     678                 :            :  * If the string starts by "<e:Envelope", then string
     679                 :            :  * should be a complete SOAP envelope including <e:Header> and <e:Body> parts. This
     680                 :            :  * allows caller to specify custom SOAP headers, in addition to the ones
     681                 :            :  * that the underlying zxid_wsc_call() will add. Usually the payload service
     682                 :            :  * will be passed as the contents of the body. If the string starts by
     683                 :            :  * "<e:Body", then the <e:Envelope> and <e:Header> are automatically added. If
     684                 :            :  * the string starts by neither of the above (be careful to use the "e:" as
     685                 :            :  * namespace prefix), then it is assumed to be the payload content of the <e:Body>
     686                 :            :  * and the rest of the SOAP envelope is added.
     687                 :            :  *
     688                 :            :  * cf:: ZXID configuration object, see zxid_new_conf()
     689                 :            :  * ses:: Session object that contains the EPR cache
     690                 :            :  * epr:: End point to call. From zxid_get_epr().
     691                 :            :  * az_cred:: (Optional) Additional authorization credentials or
     692                 :            :  *     attributes, query string format. These credentials will be populated
     693                 :            :  *     to the attribute pool in addition to the ones obtained from SSO and
     694                 :            :  *     other sources. Then a PDP is called to get an authorization decision
     695                 :            :  *     (as well as obligations we pledge to support). See also PEPMAP
     696                 :            :  *     configuration option. This implementes generalized (application
     697                 :            :  *     independent) Requestor Out and Requestor In PEPs. To implement
     698                 :            :  *     application dependent PEP features you should call zxid_az() directly.
     699                 :            :  * env:: XML payload as a string
     700                 :            :  * return:: SOAP Envelope ready to be sent to the WSP. You can pass this to HTTP client. */
     701                 :            : 
     702                 :            : /* Called by:  zxid_wsc_prepare_callf */
     703                 :            : struct zx_str* zxid_wsc_prepare_call(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr, const char* az_cred, const char* enve)
     704                 :          1 : {
     705                 :            :   struct zx_str* ret;
     706                 :            :   struct zx_e_Envelope_s* env;
     707                 :            : 
     708   [ +  -  +  -  :          1 :   if (!cf || !ses || !enve) {
                   -  + ]
     709                 :          0 :     ERR("Missing mandatory arguments ses=%p", ses);
     710                 :          0 :     return 0;
     711                 :            :   }
     712                 :          1 :   D_INDENT("prep: ");
     713                 :          1 :   env = zxid_add_env_if_needed(cf, enve);
     714         [ -  + ]:          1 :   if (!env) {
     715                 :          0 :     D_DEDENT("prep: ");
     716                 :          0 :     return 0;
     717                 :            :   }
     718                 :            :   
     719                 :            :   //*** Needs thought and development
     720                 :            : 
     721         [ -  + ]:          1 :   if (!zxid_wsc_prep(cf, ses, epr, env)) {
     722                 :          0 :     D_DEDENT("prep: ");
     723                 :          0 :     return 0;
     724                 :            :   }
     725         [ -  + ]:          1 :   if (!zxid_wsc_prep_secmech(cf, ses, epr, env)) {
     726                 :          0 :     D_DEDENT("prep: ");
     727                 :          0 :     return 0;
     728                 :            :   }
     729   [ +  -  +  -  :          1 :   ses->wsc_msgid = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(env->Header->MessageID));
                   +  - ]
     730                 :            : 
     731                 :            :   /* Call Rq-Out PDP */
     732                 :            :   
     733         [ -  + ]:          1 :   if (!zxid_localpdp(cf, ses)) {
     734                 :          0 :     ERR("RQOUT1 Deny by local PDP %d",0);
     735                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_OUT, "e:Client", "Request denied by WSC local policy", TAS3_STATUS_DENY, 0, 0, 0));
     736                 :          0 :     D_DEDENT("prep: ");
     737                 :          0 :     return 0;
     738   [ +  -  +  - ]:          1 :   } else if (cf->pdp_url && *cf->pdp_url) {
     739                 :            :     //zxid_add_attr_to_pool(cf, ses, "Action", zx_dup_str(cf->ctx, "access"));
     740         [ -  + ]:          1 :     if (!zxid_pep_az_soap_pepmap(cf, 0, ses, cf->pdp_url, cf->pepmap_rqout)) {
     741                 :          0 :       ERR("RQOUT1 Deny %d", 0);
     742                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "Request denied by WSC policy", TAS3_STATUS_DENY, 0, 0, 0));
     743                 :          0 :       D_DEDENT("prep: ");
     744                 :          0 :       return 0;
     745                 :            :     }
     746                 :            :   }
     747                 :            :   
     748                 :            :   /* *** add usage directives */
     749                 :            : 
     750                 :          1 :   ret = zx_easy_enc_elem_opt(cf, &env->gg);
     751                 :          1 :   D_DEDENT("prep: ");
     752                 :          1 :   return ret;
     753                 :            : }
     754                 :            : 
     755                 :            : /*() Prepare a web service call, printf style.
     756                 :            :  * See zxid_wsc_prepare_call() for more documentation. */
     757                 :            : 
     758                 :            : /* Called by: */
     759                 :            : struct zx_str* zxid_wsc_prepare_callf(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr, const char* az_cred, const char* env_f, ...)
     760                 :          0 : {
     761                 :            :   char* s;
     762                 :            :   va_list ap;
     763                 :          0 :   va_start(ap, env_f);
     764                 :          0 :   s = zx_alloc_vasprintf(cf->ctx, 0, env_f, ap);
     765                 :          0 :   va_end(ap);
     766                 :          0 :   return zxid_wsc_prepare_call(cf, ses, epr, az_cred, s);
     767                 :            : }
     768                 :            : 
     769                 :            : /*(i) Validate a response to web service call. Return: 1=valid. */
     770                 :            : 
     771                 :            : /* Called by: */
     772                 :            : int zxid_wsc_valid_resp(zxid_conf* cf, zxid_ses* ses, const char* az_cred, const char* enve)
     773                 :          1 : {
     774                 :            :   int ret;
     775                 :            :   struct zx_e_Envelope_s* env;
     776                 :            : 
     777   [ +  -  +  -  :          1 :   if (!cf || !ses || !enve) {
                   -  + ]
     778                 :          0 :     ERR("Missing mandatory arguments ses=%p enve=%p", ses, enve);
     779                 :          0 :     return 0;
     780                 :            :   }
     781                 :            : 
     782                 :          1 :   D_INDENT("valid: ");
     783                 :          1 :   env = zxid_add_env_if_needed(cf, enve);
     784                 :          1 :   ret = zxid_wsc_valid_re_env(cf, ses, az_cred, env, enve);
     785                 :          1 :   D_DEDENT("valid: ");
     786                 :          1 :   return ret;
     787                 :            : }
     788                 :            : 
     789                 :            : /* EOF  --  zxidwsc.c */

Generated by: LCOV version 1.9