LCOV - code coverage report
Current view: top level - zxid - zxidwsp.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 166 279 59.5 %
Date: 2010-12-19 Functions: 6 6 100.0 %
Branches: 109 256 42.6 %

           Branch data     Line data    Source code
       1                 :            : /* zxidwsp.c  -  Handwritten nitty-gritty functions for Liberty ID-WSF Web Services Provider
       2                 :            :  * Copyright (c) 2009-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: zxidwsc.c,v 1.16 2009-11-20 20:27:13 sampo Exp $
      10                 :            :  *
      11                 :            :  * 22.11.2009, created --Sampo
      12                 :            :  * 7.1.2010,   added WSP signing --Sampo
      13                 :            :  * 31.5.2010,  reworked PEPs extensively --Sampo
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "platform.h"  /* needed on Win32 for pthread_mutex_lock() et al. */
      17                 :            : 
      18                 :            : #include "errmac.h"
      19                 :            : #include "zx.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                 :            : 
      30                 :            : #define BOOL_STR_TEST(x) ((x) && (x) != '0')
      31                 :            : 
      32                 :            : /*(i) zxid_wsf_decor() implements the main low level ID-WSF web service call logic, including
      33                 :            :  * preparation of SOAP headers, use of sec mech (e.g. preparation of wsse:Security
      34                 :            :  * header and signing of appropriate compoments of the message), and sequencing
      35                 :            :  * of the call. In particular, it is possible that WSP requests user interaction
      36                 :            :  * and thus the caller web application will need to perform a redirect and then
      37                 :            :  * later call this function again to continue the web service call after interaction.
      38                 :            :  *
      39                 :            :  * env (rather than Body) is taken as argument so that caller can prepare
      40                 :            :  * additional SOAP headers at will before calling this function. This function
      41                 :            :  * will add Liberty ID-WSF specific SOAP headers. */
      42                 :            : 
      43                 :            : /* Called by:  main, zxid_soap_cgi_resp_body, zxid_wsc_prep, zxid_wsp_decorate */
      44                 :            : int zxid_wsf_decor(zxid_conf* cf, zxid_ses* ses, struct zx_e_Envelope_s* env, int is_resp)
      45                 :        191 : {
      46                 :            :   struct zx_wsse_Security_s* sec;
      47                 :            :   struct zx_e_Header_s* hdr;
      48                 :            :   
      49   [ +  -  -  + ]:        191 :   if (!env || !env->Body) {
      50                 :          0 :     ERR("NULL SOAP envelope or body %p", env);
      51                 :          0 :     return 0;
      52                 :            :   }
      53                 :            :   
      54         [ -  + ]:        191 :   if (!env->Header)
      55                 :          0 :     env->Header = zx_NEW_e_Header(cf->ctx, &env->gg);
      56                 :        191 :   hdr = env->Header;
      57                 :            : 
      58                 :            :   /* Populate SOAP headers. */
      59                 :            :   
      60                 :        191 :   hdr->Framework = zx_NEW_sbf_Framework(cf->ctx, &hdr->gg);
      61                 :        191 :   hdr->Framework->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->Framework->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
      62                 :        191 :   hdr->Framework->actor = zx_ref_attr(cf->ctx, &hdr->Framework->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
      63                 :        191 :   hdr->Framework->version = zx_ref_attr(cf->ctx, &hdr->Framework->gg, zx_version_ATTR, "2.0");
      64                 :            : 
      65                 :            : #if 1
      66                 :            :   /* *** Conor claims Sender is not mandatory */
      67                 :        191 :   hdr->Sender = zx_NEW_b_Sender(cf->ctx, &hdr->gg);
      68                 :        191 :   hdr->Sender->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->Sender->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
      69                 :        191 :   hdr->Sender->actor = zx_ref_attr(cf->ctx, &hdr->Sender->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
      70                 :        191 :   hdr->Sender->providerID = zxid_my_ent_id_attr(cf, &hdr->Sender->gg, zx_providerID_ATTR);
      71         [ -  + ]:        191 :   if (cf->affiliation)
      72                 :          0 :     hdr->Sender->affiliationID = zx_ref_attr(cf->ctx, &hdr->Sender->gg, zx_affiliationID_ATTR, cf->affiliation);
      73                 :            : #endif
      74                 :            : 
      75                 :        191 :   hdr->MessageID = zx_NEW_a_MessageID(cf->ctx, &hdr->gg);
      76                 :        191 :   hdr->MessageID->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->MessageID->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
      77                 :        191 :   hdr->MessageID->actor = zx_ref_attr(cf->ctx, &hdr->MessageID->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
      78                 :            : 
      79                 :            : #if 0
      80                 :            :   hdr->Action = zx_NEW_a_Action(cf->ctx, &hdr->gg);
      81                 :            :   zx_add_content(cf->ctx, &hdr->Action->gg, zx_ref_str(cf->ctx, ***));
      82                 :            :   hdr->Action->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->Action->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
      83                 :            :   hdr->Action->actor = zx_ref_attr(cf->ctx, gghdr->Action->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
      84                 :            : #endif
      85                 :            : 
      86                 :            : #if 0
      87                 :            :   hdr->From = zx_NEW_a_From(cf->ctx, &hdr->gg);
      88                 :            :   hdr->From->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->From->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
      89                 :            :   hdr->From->actor = zx_ref_attr(cf->ctx, &hdr->From->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
      90                 :            :   hdr->From->Address = zxid_mk_addr(cf, zx_strf(cf->ctx, "%s?o=P", cf->url));
      91                 :            : #endif
      92                 :            : 
      93                 :            : #if 0
      94                 :            :   hdr->ReferenceParameters = zx_NEW_a_ReferenceParameters(cf->ctx, &hdr->gg);
      95                 :            :   hdr->ReferenceParameters->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->ReferenceParameters->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
      96                 :            :   hdr->ReferenceParameters->actor = zx_ref_attr(cf->ctx, &hdr->ReferenceParameters->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
      97                 :            : #endif
      98                 :            : 
      99                 :            : #if 0
     100                 :            :   hdr->Credentials = zx_NEW_tas3_Credentials(cf->ctx, &hdr->gg);
     101                 :            :   hdr->Credentials->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->Credentials->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     102                 :            :   hdr->Credentials->actor = zx_ref_attr(cf->ctx, &hdr->Credentials->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     103                 :            : #endif
     104                 :            : 
     105                 :            : #if 0
     106                 :            :   /* If you want this header, you should
     107                 :            :    * create it prior to calling zxid_wsc_call() */
     108                 :            :   hdr->UsageDirective = zx_NEW_b_UsageDirective(cf->ctx, &hdr->gg);
     109                 :            :   hdr->UsageDirective->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->UsageDirective->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     110                 :            :   hdr->UsageDirective->actor = zx_ref_attr(cf->ctx, &hdr->UsageDirective->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     111                 :            : #endif
     112                 :            : 
     113                 :            : #if 0
     114                 :            :   /* Interaction or redirection. If you want this header, you should
     115                 :            :    * create it prior to calling zxid_wsc_call() */
     116                 :            :   hdr->UserInteraction = zx_NEW_b_UserInteraction(cf->ctx, &hdr->gg);
     117                 :            :   hdr->UserInteraction->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->UserInteraction->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     118                 :            :   hdr->UserInteraction->actor = zx_ref_attr(cf->ctx, &hdr->UserInteraction->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     119                 :            : #endif
     120                 :            : 
     121   [ +  -  -  + ]:        191 :   if (ses && ses->curstatus) {
     122                 :          0 :     ZX_ADD_KID(hdr, Status, ses->curstatus);
     123                 :            :   }
     124                 :            :   
     125                 :        191 :   sec = hdr->Security = zx_NEW_wsse_Security(cf->ctx, &hdr->gg);
     126                 :        191 :   sec->actor = zx_ref_attr(cf->ctx, &sec->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     127                 :        191 :   sec->mustUnderstand = zx_ref_attr(cf->ctx, &sec->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     128                 :        191 :   sec->Timestamp = zx_NEW_wsu_Timestamp(cf->ctx, &sec->gg);
     129                 :        191 :   sec->Timestamp->Created = zx_NEW_wsu_Created(cf->ctx, &sec->Timestamp->gg);
     130                 :        191 :   zx_reverse_elem_lists(&sec->gg);
     131                 :            : 
     132         [ +  + ]:        191 :   if (is_resp) {
     133                 :        153 :     zx_add_content(cf->ctx, &sec->Timestamp->Created->gg, zxid_date_time(cf, time(0)));
     134                 :        153 :     zx_add_content(cf->ctx, &hdr->MessageID->gg, zxid_mk_id(cf, "urn:M", ZXID_ID_BITS));
     135                 :            :     /* Clear away any credentials from previous iteration. *** clear kids list, too */
     136                 :        153 :     sec->Signature = 0;
     137                 :        153 :     sec->BinarySecurityToken = 0;
     138                 :        153 :     sec->SecurityTokenReference = 0;
     139                 :        153 :     sec->Assertion = 0;
     140                 :        153 :     sec->sa11_Assertion = 0;
     141                 :        153 :     sec->ff12_Assertion = 0;
     142                 :            :     
     143   [ +  -  +  +  :        153 :     if (ses && ses->wsp_msgid && ses->wsp_msgid->len) {
                   +  - ]
     144   [ +  -  -  + ]:         35 :       D("wsp_msgid(%.*s) %p %d %p", ses->wsp_msgid->len, ses->wsp_msgid->s, ses->wsp_msgid, ses->wsp_msgid->len, ses->wsp_msgid->s);
     145                 :         35 :       hdr->RelatesTo = zx_NEW_a_RelatesTo(cf->ctx, &hdr->gg);
     146                 :         35 :       zx_add_content(cf->ctx, &hdr->RelatesTo->gg, ses->wsp_msgid);
     147                 :         35 :       hdr->RelatesTo->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->RelatesTo->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     148                 :         35 :       hdr->RelatesTo->actor = zx_ref_attr(cf->ctx, &hdr->RelatesTo->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     149                 :            :     }
     150                 :            : 
     151                 :        153 :     zxid_attach_sol1_usage_directive(cf, ses, env, TAS3_REQUIRE, cf->wsp_localpdp_obl_emit);
     152                 :        153 :     zxid_wsf_sign(cf, cf->wsp_sign, sec, 0, hdr, env->Body);
     153                 :            :   }
     154                 :        191 :   return 1;
     155                 :            : }
     156                 :            : 
     157                 :            : /* ----------------------------------------
     158                 :            :  * Simplify writing WSPs */
     159                 :            : 
     160                 :            : /*(i) Add ID-WSF (and TAS3) specific headers and signatures to
     161                 :            :  * web service response. Simple and intuitive specification of
     162                 :            :  * XML as string: no need to build complex data structures.
     163                 :            :  *
     164                 :            :  * If the string starts by "<e:Envelope", then string should be
     165                 :            :  * a complete SOAP envelope including <e:Header> and <e:Body> parts. This
     166                 :            :  * allows caller to specify custom SOAP headers, in addition to the ones
     167                 :            :  * that the underlying zxid_wsc_call() will add. Usually the payload service
     168                 :            :  * will be passed as the contents of the body. If the string starts by
     169                 :            :  * "<e:Body", then the <e:Envelope> and <e:Header> are automatically added. If
     170                 :            :  * the string starts by neither of the above (be careful to use the "e:" as
     171                 :            :  * namespace prefix), the it is assumed to be the payload content of
     172                 :            :  * the <e:Body> and the rest of the SOAP envelope is added.
     173                 :            :  *
     174                 :            :  * cf:: ZXID configuration object, see zxid_new_conf()
     175                 :            :  * ses:: Session object that contains the EPR cache
     176                 :            :  * az_cred:: (Optional) Additional authorization credentials or
     177                 :            :  *     attributes, query string format. These credentials will be populated
     178                 :            :  *     to the attribute pool in addition to the ones obtained from token and
     179                 :            :  *     other sources. Then a PDP is called to get an authorization
     180                 :            :  *     decision (generating obligations). See also PEPMAP_RSOUT configuration
     181                 :            :  *     option. This implements generalized (application independent)
     182                 :            :  *     Responder Out PEP. To implement application dependent PEP features
     183                 :            :  *     you should call zxid_az() directly.
     184                 :            :  * env:: XML payload
     185                 :            :  * return:: SOAP Envelope of the response, as a string, ready to be
     186                 :            :  *     sent as HTTP response. */
     187                 :            : 
     188                 :            : /* Called by:  covimp_test, main x9, zxid_wsp_decoratef, zxidwspcgi_parent */
     189                 :            : struct zx_str* zxid_wsp_decorate(zxid_conf* cf, zxid_ses* ses, const char* az_cred, const char* enve)
     190                 :         18 : {
     191                 :            :   struct zx_str* ss;
     192                 :            :   struct zx_e_Envelope_s* env;
     193                 :         18 :   D_INDENT("decor: ");
     194                 :            : 
     195                 :         18 :   env = zxid_add_env_if_needed(cf, enve);
     196         [ -  + ]:         18 :   if (!env) {
     197                 :          0 :     D_DEDENT("decor: ");
     198                 :          0 :     return 0;
     199                 :            :   }
     200                 :            :   
     201                 :            :   //*** Needs thought and development
     202                 :            : 
     203                 :            :   /* Call Rs-Out PDP */
     204                 :            : 
     205         [ -  + ]:         18 :   if (!zxid_localpdp(cf, ses)) {
     206                 :          0 :     ERR("RSOUT3 Deny by local PDP %d",0);
     207                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_OUT, "e:Server", "Response denied by WSP local policy", TAS3_STATUS_DENY, 0, 0, 0));
     208                 :            :     /* Fall through, letting zxid_wsf_decor() pick up the fault and package it as response. */
     209   [ +  +  +  - ]:         18 :   } else if (cf->pdp_url && *cf->pdp_url) {
     210                 :            :     //zxid_add_attr_to_pool(cf, ses, "Action", zx_dup_str(cf->ctx, "access"));
     211         [ -  + ]:         17 :     if (!zxid_pep_az_soap_pepmap(cf, 0, ses, cf->pdp_url, cf->pepmap_rsout)) {
     212                 :          0 :       ERR("RSOUT3 Deny %d", 0);
     213                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_OUT, "e:Server", "Response denied by WSP policy at PDP", TAS3_STATUS_DENY, 0, 0, 0));
     214                 :            :       /* Fall through, letting zxid_wsf_decor() pick up the fault and package it as response. */
     215                 :            :     }
     216                 :            :   }
     217                 :            :   
     218         [ -  + ]:         18 :   if (ses->curflt) {
     219   [ #  #  #  # ]:          0 :     D("Detected curflt, abandoning previous Body content. %d", 0);
     220                 :            :     /* *** LEAK: Should free previous body content */
     221                 :          0 :     env->Body = (struct zx_e_Body_s*)zx_replace_kid(&env->gg, (struct zx_elem_s*)zx_NEW_e_Body(cf->ctx, 0));
     222                 :          0 :     ZX_ADD_KID(env->Body, Fault, ses->curflt);
     223                 :            :   }
     224                 :            :   
     225         [ -  + ]:         18 :   if (!zxid_wsf_decor(cf, ses, env, 1)) {
     226                 :          0 :     ERR("Response decoration failed %p", env);
     227                 :          0 :     D_DEDENT("decor: ");
     228                 :          0 :     return 0;
     229                 :            :   }
     230                 :         18 :   zx_reverse_elem_lists(&env->Header->gg);
     231                 :            :   
     232                 :         18 :   ss = zx_easy_enc_elem_opt(cf, &env->gg);
     233                 :            :   DD("DECOR len=%d envelope(%.*s)", ss->len, ss->len, ss->s);
     234                 :         18 :   D_XML_BLOB(cf, "WSP_DECOR", ss->len, ss->s);
     235                 :         18 :   D_DEDENT("decor: ");
     236                 :         18 :   return ss;
     237                 :            : }
     238                 :            : 
     239                 :            : /*() Create web service response, printf style. See zxid_wsp_decorate() for more documentation. */
     240                 :            : 
     241                 :            : /* Called by:  main */
     242                 :            : struct zx_str* zxid_wsp_decoratef(zxid_conf* cf, zxid_ses* ses, const char* az_cred, const char* env_f, ...)
     243                 :          1 : {
     244                 :            :   char* s;
     245                 :            :   va_list ap;
     246                 :          1 :   va_start(ap, env_f);
     247                 :          1 :   s = zx_alloc_vasprintf(cf->ctx, 0, env_f, ap);
     248                 :          1 :   va_end(ap);
     249                 :          1 :   return zxid_wsp_decorate(cf, ses, az_cred, s);
     250                 :            : }
     251                 :            : 
     252                 :            : /*() Perform necessary validation steps to check either requester or target identity
     253                 :            :  * assertion. Also log the assertion and extract from assertion relevant information
     254                 :            :  * into the session. The two types of assertion are distinguished by lk == "req" or "tgt".
     255                 :            :  * returns 0 on failure and 1 on success.
     256                 :            :  * See zxid_sp_sso_finalize() for similar code.  *** consider factoring out commonality */
     257                 :            : 
     258                 :            : /* Called by:  zxid_wsp_validate_env x2 */
     259                 :            : static int zxid_wsf_validate_a7n(zxid_conf* cf, zxid_ses* ses, zxid_a7n* a7n, const char* lk, struct timeval* srcts)
     260                 :         35 : {
     261                 :            :   struct zx_str* logpath;
     262                 :            :   struct zx_str* a7nss;
     263                 :            :   struct zxsig_ref refs;
     264                 :            :   zxid_nid* nameid;
     265                 :            :   int fmt;
     266                 :            :   struct zx_str* issuer;
     267                 :            :   zxid_entity* idp_meta;
     268                 :            :   zxid_cgi cgi;
     269                 :            :   
     270   [ +  -  -  + ]:         35 :   if (!a7n || !a7n->Subject) {
     271                 :          0 :     ERR("%s: Assertion lacking or does not have Subject. %p", lk, a7n);
     272                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "Assertion does not have Subject.", "IDStarMsgNotUnderstood", 0, lk, 0));
     273                 :          0 :     return 0;
     274                 :            :   }
     275                 :            :   
     276   [ +  -  +  -  :         35 :   issuer = ZX_GET_CONTENT(a7n->Issuer);
                   +  - ]
     277                 :         35 :   nameid = zxid_decrypt_nameid(cf, a7n->Subject->NameID, a7n->Subject->EncryptedID);
     278   [ +  -  +  -  :         35 :   if (!ZX_GET_CONTENT(nameid)) {
                   -  + ]
     279                 :          0 :     ERR("%s: Assertion does not have Subject->NameID. %p", lk, ses->nameid);
     280                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "Assertion does not have Subject->NameID.", "IDStarMsgNotUnderstood", 0, lk, 0));
     281                 :          0 :     return 0;
     282                 :            :   }
     283                 :            :   
     284   [ +  -  -  + ]:         35 :   if (nameid->Format && !memcmp(nameid->Format->g.s, SAML2_TRANSIENT_NID_FMT, nameid->Format->g.len)) {
     285                 :          0 :     fmt = 0;
     286                 :            :   } else {
     287                 :         35 :     fmt = 1;  /* anything nontransient may be a federation */
     288                 :            :   }
     289                 :            : 
     290   [ +  -  -  +  :         35 :   D("A7N received. NID(%s) FMT(%d) SESIX(%s)", STRNULLCHKQ(ses->nid), ses->nidfmt, STRNULLCHK(ses->sesix));
             -  +  -  + ]
     291         [ -  + ]:         35 :   if (!strcmp(lk, "tgt")) {
     292                 :          0 :     ses->tgtnameid = nameid;
     293   [ #  #  #  #  :          0 :     ses->tgt = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(nameid));
                   #  # ]
     294                 :          0 :     ses->tgtfmt = fmt;
     295                 :            :   } else {
     296                 :         35 :     ses->nameid = nameid;
     297   [ +  -  +  -  :         35 :     ses->nid = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(nameid));
                   +  - ]
     298                 :         35 :     ses->nidfmt = fmt;
     299                 :            :   }
     300                 :            :   
     301                 :            :   /* Validate signature (*** add Issuer trusted check, CA validation, etc.) */
     302                 :            :   
     303                 :         35 :   idp_meta = zxid_get_ent_ss(cf, issuer);
     304         [ -  + ]:         35 :   if (!idp_meta) {
     305                 :          0 :     ses->sigres = ZXSIG_NO_SIG;
     306         [ #  # ]:          0 :     if (!cf->nosig_fatal) {
     307                 :          0 :       ERR("%s: Unable to find metadata for Assertion Issuer(%.*s).", lk, issuer->len, issuer->s);
     308                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No unable to find SAML metadata for Assertion Issuer.", "ProviderIDNotValid", 0, lk, 0));
     309                 :          0 :       return 0;
     310                 :            :     } else {
     311                 :          0 :       INFO("%s: Unable to find metadata for Assertion Issuer(%.*s), but configured to ignore this problem (NOSIG_FATAL=0).", lk, issuer->len, issuer->s);
     312                 :            :     }
     313                 :            :   } else {
     314   [ +  -  +  -  :         70 :     if (a7n->Signature && a7n->Signature->SignedInfo && a7n->Signature->SignedInfo->Reference) {
                   +  - ]
     315                 :         35 :       ZERO(&refs, sizeof(refs));
     316                 :         35 :       refs.sref = a7n->Signature->SignedInfo->Reference;
     317                 :         35 :       refs.blob = (struct zx_elem_s*)a7n;
     318                 :         35 :       ses->sigres = zxsig_validate(cf->ctx, idp_meta->sign_cert, a7n->Signature, 1, &refs);
     319                 :         35 :       zxid_sigres_map(ses->sigres, &cgi.sigval, &cgi.sigmsg);
     320                 :            :     } else {
     321   [ #  #  #  # ]:          0 :       if (cf->msg_sig_ok && !ses->sigres) {
     322                 :          0 :         INFO("Assertion without signature accepted due to message level signature (SimpleSign) %d", 0);
     323                 :            :       } else {
     324                 :          0 :         ses->sigres = ZXSIG_NO_SIG;
     325         [ #  # ]:          0 :         if (!cf->nosig_fatal) {
     326         [ #  # ]:          0 :           ERR("Assertion not signed. Sigval(%s) %p", STRNULLCHKNULL(cgi.sigval), a7n->Signature);
     327                 :          0 :           zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "Assertion not signed.", TAS3_STATUS_NOSIG, 0, lk, 0));
     328                 :          0 :           return 0;
     329                 :            :         } else {
     330         [ #  # ]:          0 :           INFO("SSO warn: assertion not signed, but configured to ignore this problem (NOSIG_FATAL=0). Sigval(%s) %p", STRNULLCHKNULL(cgi.sigval), a7n->Signature);
     331                 :            :         }
     332                 :            :       }
     333                 :            :     }
     334                 :            :   }
     335   [ +  -  -  + ]:         35 :   if (cf->sig_fatal && ses->sigres) {
     336                 :          0 :     ERR("Fail due to failed assertion signature sigres=%d", ses->sigres);
     337                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "Assertion signature did not validate.", TAS3_STATUS_BADSIG, 0, lk, 0));
     338                 :          0 :     return 0;
     339                 :            :   }
     340                 :            :   
     341         [ -  + ]:         35 :   if (zxid_validate_cond(cf, &cgi, ses, a7n, zxid_my_ent_id(cf), 0, 0)) {
     342                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "Conditions did not validate.", TAS3_STATUS_BADCOND, 0, lk, 0));
     343                 :          0 :     return 0;
     344                 :            :   }
     345                 :            :   
     346         [ +  - ]:         35 :   if (cf->log_rely_a7n) {
     347                 :            :     DD("Logging... %d", 0);
     348                 :         35 :     logpath = zxlog_path(cf, issuer, &a7n->ID->g, ZXLOG_RELY_DIR, ZXLOG_A7N_KIND, 1);
     349         [ +  - ]:         35 :     if (logpath) {
     350                 :         35 :       ses->sso_a7n_path = ses->tgt_a7n_path = zx_str_to_c(cf->ctx, logpath);
     351                 :         35 :       a7nss = zx_easy_enc_elem_sig(cf, &a7n->gg);
     352         [ +  + ]:         35 :       if (zxlog_dup_check(cf, logpath, "SSO assertion")) {
     353         [ +  + ]:          5 :         if (cf->dup_a7n_fatal) {
     354                 :          4 :           zxlog_blob(cf, cf->log_rely_a7n, logpath, a7nss, "wsp_validade dup err");
     355                 :          4 :           return 0;
     356                 :            :         }
     357                 :            :       }
     358                 :         31 :       zxlog_blob(cf, cf->log_rely_a7n, logpath, a7nss, "wsp_validate");
     359   [ +  -  +  -  :         31 :       zxlog(cf, 0, srcts, ses->ipport, issuer, ses->wsp_msgid, &a7n->ID->g, ZX_GET_CONTENT(nameid), "N", "K", "A7N VALID", logpath->s, lk);
                   +  - ]
     360                 :         31 :       zx_str_free(cf->ctx, a7nss);
     361                 :            :     }
     362                 :            :   }
     363                 :         31 :   return 1;
     364                 :            : }
     365                 :            : 
     366                 :            : /*() Validate SOAP request envelope, specified as data structure
     367                 :            :  *
     368                 :            :  * cf:: ZXID configuration object, see zxid_new_conf()
     369                 :            :  * ses:: Session object that contains the EPR cache
     370                 :            :  * az_cred:: (Optional) Additional authorization credentials or
     371                 :            :  *     attributes, query string format. These credentials will be populated
     372                 :            :  *     to the attribute pool in addition to the ones obtained from token and
     373                 :            :  *     other sources. Then a PDP is called to get an authorization
     374                 :            :  *     decision (matching obligations we support to those in the request,
     375                 :            :  *     and obligations pleged by caller to those we insist on). See
     376                 :            :  *     also PEPMAP configuration option. This implements generalized
     377                 :            :  *     (application independent) Responder In PEP. To implement
     378                 :            :  *     application dependent PEP features you should call zxid_az() directly.
     379                 :            :  * env:: SOAP envelope as data structure
     380                 :            :  * return:: idpnid of target identity of the request (rest of the information
     381                 :            :  *     is populated to the session object, from where it can be retrieved).
     382                 :            :  *     NULL if the validation fails. The target identity is still retrievable
     383                 :            :  *     from the session, should there be desire to process the message despite
     384                 :            :  *     the validation failure.
     385                 :            :  *
     386                 :            :  * See also: zxid_wsc_validate_resp_env() */
     387                 :            : 
     388                 :            : /* Called by:  zxid_sp_soap_dispatch, zxid_wsp_validate */
     389                 :            : char* zxid_wsp_validate_env(zxid_conf* cf, zxid_ses* ses, const char* az_cred, struct zx_e_Envelope_s* env)
     390                 :         37 : {
     391                 :         37 :   int n_refs = 0;
     392                 :            :   struct zxsig_ref refs[ZXID_N_WSF_SIGNED_HEADERS];
     393                 :            :   struct timeval ourts;
     394                 :            :   zxid_entity* wsc_meta;
     395                 :            :   struct zx_e_Header_s* hdr;
     396                 :            :   struct zx_wsse_Security_s* sec;
     397                 :            :   zxid_cgi cgi;
     398                 :            : 
     399                 :         37 :   D_INDENT("valid: ");
     400                 :         37 :   GETTIMEOFDAY(&ourts, 0);
     401                 :         37 :   zxid_set_fault(cf, ses, 0);
     402                 :         37 :   zxid_set_tas3_status(cf, ses, 0);
     403                 :            :   
     404         [ -  + ]:         37 :   if (!env) {
     405                 :          0 :     ERR("No <e:Envelope> found. %d", 0);
     406                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No SOAP Envelope found.", "IDStarMsgNotUnderstood", 0, 0, 0));
     407                 :          0 :     D_DEDENT("valid: ");
     408                 :          0 :     return 0;
     409                 :            :   }
     410                 :            : 
     411                 :         37 :   hdr = env->Header;
     412         [ +  + ]:         37 :   if (!hdr) {
     413                 :          1 :     ERR("No <e:Header> found. %d", 0);
     414                 :          1 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No SOAP Header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
     415                 :          1 :     D_DEDENT("valid: ");
     416                 :          1 :     return 0;
     417                 :            :   }
     418   [ +  -  +  -  :         36 :   if (!ZX_SIMPLE_ELEM_CHK(hdr->MessageID)) {
          +  -  +  -  +  
                -  -  + ]
     419                 :          0 :     ERR("No <a:MessageID> found. %d", 0);
     420                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No MessageID header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
     421                 :          0 :     D_DEDENT("valid: ");
     422                 :          0 :     return 0;
     423                 :            :   }
     424                 :            :   /* Remember MessageID for generating RelatesTo in Response */
     425   [ +  -  +  -  :         36 :   ses->wsp_msgid = zx_dup_zx_str(cf->ctx, ZX_GET_CONTENT(hdr->MessageID));
                   +  - ]
     426                 :            :   DD("wsp_msgid(%.*s) %p %d %p", ses->wsp_msgid->len, ses->wsp_msgid->s, ses->wsp_msgid, ses->wsp_msgid->len, ses->wsp_msgid->s);
     427                 :            :   
     428   [ +  -  -  +  :         36 :   if (!hdr->Sender || !hdr->Sender->providerID && !hdr->Sender->affiliationID) {
                   #  # ]
     429                 :          0 :     ERR("No <b:Sender> found (or missing providerID or affiliationID). %p", hdr->Sender);
     430                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No b:Sender header found (or missing providerID or affiliationID).", "IDStarMsgNotUnderstood", 0, 0, 0));
     431                 :          0 :     D_DEDENT("valid: ");
     432                 :          0 :     return 0;
     433                 :            :   }
     434         [ +  - ]:         36 :   ses->issuer = zx_dup_zx_str(cf->ctx, hdr->Sender->providerID?
     435                 :            :                               &hdr->Sender->providerID->g : &hdr->Sender->affiliationID->g);
     436                 :            :   
     437                 :            :   /* Validate message signature (*** add Issuer trusted check, CA validation, etc.) */
     438                 :            :   
     439         [ -  + ]:         36 :   if (!(sec = hdr->Security)) {
     440                 :          0 :     ERR("No <wsse:Security> found. %d", 0);
     441                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No wsse:Security header found.", "IDStarMsgNotUnderstood", 0, 0, 0));
     442                 :          0 :     D_DEDENT("valid: ");
     443                 :          0 :     return 0;
     444                 :            :   }
     445                 :            : 
     446   [ +  -  +  -  :         36 :   if (!sec->Signature || !sec->Signature->SignedInfo || !sec->Signature->SignedInfo->Reference) {
                   -  + ]
     447                 :          0 :     ses->sigres = ZXSIG_NO_SIG;
     448         [ #  # ]:          0 :     if (cf->wsp_nosig_fatal) {
     449                 :          0 :       ERR("No Security/Signature found. %p", sec->Signature);
     450                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No wsse:Security/ds:Signature found.", TAS3_STATUS_NOSIG, 0, 0, 0));
     451                 :          0 :       D_DEDENT("valid: ");
     452                 :          0 :       return 0;
     453                 :            :     } else {
     454                 :          0 :       INFO("No Security/Signature found, but configured to ignore this problem (NOSIG_FATAL=0). %p", sec->Signature);
     455                 :            :     }
     456                 :            :   }
     457                 :            :   
     458                 :         36 :   wsc_meta = zxid_get_ent_ss(cf, ses->issuer);
     459         [ +  - ]:         36 :   if (wsc_meta) {
     460                 :         36 :     ZERO(refs, sizeof(refs));
     461                 :         36 :     n_refs = zxid_hunt_sig_parts(cf, n_refs, refs, sec->Signature->SignedInfo->Reference, hdr, env->Body);
     462                 :            :     /* *** Consider adding BDY and STR */
     463                 :         36 :     ses->sigres = zxsig_validate(cf->ctx, wsc_meta->sign_cert, sec->Signature, n_refs, refs);
     464                 :         36 :     zxid_sigres_map(ses->sigres, &cgi.sigval, &cgi.sigmsg);
     465   [ +  -  +  + ]:         36 :     if (cf->sig_fatal && ses->sigres) {
     466                 :          1 :       ERR("Fail due to failed message signature sigres=%d", ses->sigres);
     467                 :          1 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "Message signature did not validate.", TAS3_STATUS_BADSIG, 0, 0, 0));
     468                 :          1 :       D_DEDENT("valid: ");
     469                 :          1 :       return 0;
     470                 :            :     }
     471                 :            :   } else {
     472                 :          0 :     ses->sigres = ZXSIG_NO_SIG;
     473         [ #  # ]:          0 :     if (cf->nosig_fatal) {
     474                 :          0 :       INFO("Unable to find SAML metadata for Sender(%.*s), but configured to ignore this problem (NOSIG_FATAL=0).", ses->issuer->len, ses->issuer->s);
     475                 :            :     } else {
     476                 :          0 :       ERR("Unable to find SAML metadata for Sender(%.*s).", ses->issuer->len, ses->issuer->s);
     477                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No unable to find SAML metadata for sender.", "ProviderIDNotValid", 0, 0, 0));
     478                 :          0 :       D_DEDENT("valid: ");
     479                 :          0 :       return 0;
     480                 :            :     }
     481                 :            :   }
     482                 :            : 
     483         [ -  + ]:         35 :   if (!zxid_timestamp_chk(cf, ses, sec->Timestamp, &ourts, &ses->srcts, TAS3_PEP_RQ_IN,"e:Client"))
     484                 :          0 :     return 0;
     485                 :            :   
     486                 :            :   /* Check Requester Identity */
     487                 :            : 
     488                 :         35 :   ses->a7n = zxid_dec_a7n(cf, sec->Assertion, sec->EncryptedAssertion);
     489   [ +  -  +  - ]:         35 :   if (ses->a7n && ses->a7n->Subject) {
     490         [ +  + ]:         35 :     if (!zxid_wsf_validate_a7n(cf, ses, ses->a7n, "req", &ses->srcts)) {
     491                 :          4 :       D_DEDENT("valid: ");
     492                 :          4 :       return 0;
     493                 :            :     }
     494                 :            :   } else {
     495                 :            :     /* *** should there be absolute requirement for a requester assertion to exist? */
     496                 :          0 :     ERR("No Requester <sa:Assertion> found. %p", ses->a7n);
     497                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No assertion found.", TAS3_STATUS_BADCOND, 0, 0, 0));
     498                 :          0 :     D_DEDENT("valid: ");
     499                 :          0 :     return 0;
     500                 :            :   }
     501                 :            : 
     502                 :            :   /* Check Target Identity */
     503                 :            : 
     504         [ -  + ]:         31 :   if (hdr->TargetIdentity) {
     505                 :          0 :     ses->tgta7n = zxid_dec_a7n(cf, hdr->TargetIdentity->Assertion, hdr->TargetIdentity->EncryptedAssertion);
     506   [ #  #  #  # ]:          0 :     if (ses->tgta7n && ses->tgta7n->Subject) {
     507         [ #  # ]:          0 :       if (!zxid_wsf_validate_a7n(cf, ses, ses->a7n, "tgt", &ses->srcts)) {
     508                 :          0 :         D_DEDENT("valid: ");
     509                 :          0 :         return 0;
     510                 :            :       }
     511                 :            :     } else {
     512                 :          0 :       ERR("No TargetIdentity <sa:Assertion> found. %p", ses->tgta7n);
     513                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "No TargetIdentity Assertion found.", TAS3_STATUS_BADCOND, 0, 0, 0));
     514                 :          0 :       D_DEDENT("valid: ");
     515                 :          0 :       return 0;
     516                 :            :     }
     517                 :            :     
     518                 :            :   } else {
     519                 :         31 :     INFO("No explicit TargetIdentity, using requester identity as target identity. %d", 0);
     520                 :         31 :     ses->tgta7n = ses->a7n;
     521                 :         31 :     ses->tgtnameid = ses->nameid;
     522                 :         31 :     ses->tgt = ses->nid;
     523                 :         31 :     ses->tgtfmt = ses->nidfmt;
     524                 :         31 :     ses->tgt_a7n_path = ses->sso_a7n_path;
     525                 :            :   }
     526                 :            : 
     527         [ +  - ]:         31 :   if (hdr->UsageDirective) {
     528   [ +  -  +  -  :         62 :     if (hdr->UsageDirective->Obligation && ZX_GET_CONTENT(hdr->UsageDirective->Obligation->AttributeAssignment)) {
             +  -  +  - ]
     529   [ +  -  +  -  :         31 :       ses->rcvd_usagedir = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(hdr->UsageDirective->Obligation->AttributeAssignment));
                   +  - ]
     530   [ +  -  -  + ]:         31 :       D("Found TAS3 UsageDirective with obligation(%s)", ses->rcvd_usagedir);
     531   [ #  #  #  #  :          0 :     } else if (ZX_GET_CONTENT(hdr->UsageDirective)) {
                   #  # ]
     532   [ #  #  #  #  :          0 :       ses->rcvd_usagedir = zx_str_to_c(cf->ctx, ZX_GET_CONTENT(hdr->UsageDirective));
                   #  # ]
     533   [ #  #  #  # ]:          0 :       D("Found unknown UsageDirective(%s)", ses->rcvd_usagedir);
     534                 :            :     } else {
     535                 :          0 :       ERR("UsageDirective empty or not understood. %p", hdr->UsageDirective->Dict);
     536                 :            :     }
     537                 :            :   }
     538                 :            : 
     539   [ +  -  +  -  :         31 :   if (hdr->UsageDirective && hdr->UsageDirective->Obligation
             +  -  +  - ]
     540                 :            :       && ZX_STR_EQ(&hdr->UsageDirective->Obligation->ObligationId->g, TAS3_SOL1_ENGINE)) {
     541                 :            :     /* *** extract usage directive */
     542                 :            :   }
     543                 :            : 
     544                 :         31 :   zxid_put_ses(cf, ses);
     545                 :         31 :   zxid_ses_to_pool(cf, ses);
     546                 :         31 :   zxid_snarf_eprs_from_ses(cf, ses);  /* Harvest attributes and bootstrap(s) */
     547   [ +  -  +  -  :         31 :   zxid_put_user(cf, &ses->nameid->Format->g, &ses->nameid->NameQualifier->g, &ses->nameid->SPNameQualifier->g, ZX_GET_CONTENT(ses->nameid), 0);
                   +  - ]
     548                 :         31 :   zxlogwsp(cf, ses, "K", "PNEWSES", ses->sid, 0);
     549                 :            :   
     550                 :            :   /* Call Rq-In PDP */
     551                 :            :   
     552         [ -  + ]:         31 :   if (!zxid_localpdp(cf, ses)) {
     553                 :          0 :     ERR("RQIN2 Deny by local PDP %d",0);
     554                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_OUT, "e:Server", "Request denied by WSP local policy", TAS3_STATUS_DENY, 0, 0, 0));
     555                 :            :     /* Fall through, letting zxid_wsf_decor() pick up the fault and package it as response. */
     556   [ +  -  +  + ]:         31 :   } else if (cf->pdp_url && *cf->pdp_url) {
     557                 :            :     //zxid_add_attr_to_pool(cf, ses, "Action", zx_dup_str(cf->ctx, "access"));
     558         [ -  + ]:         13 :     if (!zxid_pep_az_soap_pepmap(cf, 0, ses, cf->pdp_url, cf->pepmap_rqin)) {
     559                 :          0 :       ERR("RQIN2 Deny %d", 0);
     560                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Server", "Request denied by WSP policy", TAS3_STATUS_DENY, 0, 0, 0));
     561                 :          0 :       D_DEDENT("valid: ");
     562                 :          0 :       return 0;
     563                 :            :     }
     564                 :            :   }
     565                 :            :   
     566                 :         31 :   D_DEDENT("valid: ");
     567                 :         31 :   return ses->tgt;
     568                 :            : }
     569                 :            : 
     570                 :            : /*(i) Validate SOAP request (envelope), specified by the string.
     571                 :            :  *
     572                 :            :  * If the string starts by "<e:Envelope", then string
     573                 :            :  * should be a complete SOAP envelope including <e:Header> (and <e:Body>)
     574                 :            :  * parts.
     575                 :            :  *
     576                 :            :  * cf:: ZXID configuration object, see zxid_new_conf()
     577                 :            :  * ses:: Session object that contains the EPR cache
     578                 :            :  * az_cred:: (Optional) Additional authorization credentials or
     579                 :            :  *     attributes, query string format. These credentials will be populated
     580                 :            :  *     to the attribute pool in addition to the ones obtained from token and
     581                 :            :  *     other sources. Then a PDP is called to get an authorization
     582                 :            :  *     decision (matching obligations we support to those in the request,
     583                 :            :  *     and obligations pleged by caller to those we insist on). See
     584                 :            :  *     also PEPMAP configuration option. This implements generalized
     585                 :            :  *     (application independent) Responder In PEP. To implement
     586                 :            :  *     application dependent PEP features you should call zxid_az() directly.
     587                 :            :  * env:: Entire SOAP envelope as a string
     588                 :            :  * return:: idpnid of target identity of the request (rest of the information
     589                 :            :  *     is populated to the session object, from where it can be retrieved).
     590                 :            :  *     NULL if the validation fails. The target identity is still retrievable
     591                 :            :  *     from the session, should there be desire to process the message despite
     592                 :            :  *     the validation failure.
     593                 :            :  *
     594                 :            :  * See also: zxid_wsc_validate_resp_env() */
     595                 :            : 
     596                 :            : /* Called by:  main, zxidwspcgi_main */
     597                 :            : char* zxid_wsp_validate(zxid_conf* cf, zxid_ses* ses, const char* az_cred, const char* enve)
     598                 :         17 : {
     599                 :            :   struct zx_str  ss;
     600                 :            :   char* p;
     601                 :            :   char msg[256];
     602                 :            :   struct zx_str* logpath;
     603                 :            :   struct zx_root_s* r;
     604                 :            : 
     605                 :         17 :   ss.s = (char*)enve;
     606                 :         17 :   ss.len = strlen(enve);
     607                 :         17 :   D_XML_BLOB(cf, "WSP_VALIDATE", ss.len, ss.s);
     608                 :         17 :   r = zx_dec_zx_root(cf->ctx, ss.len, enve, "valid");
     609         [ -  + ]:         17 :   if (!r) {
     610                 :          0 :     zx_format_parse_error(cf->ctx, msg, sizeof(msg), "valid");
     611                 :          0 :     ERR("Malformed XML: %s", msg);
     612                 :            :     /* Squash " to ' because the message will appear in XML attribute value delimited by " */
     613         [ #  # ]:          0 :     for (p = msg; *p; ++p)
     614         [ #  # ]:          0 :       if (*p == '"')
     615                 :          0 :         *p = '\'';
     616                 :          0 :     zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RQ_IN, "e:Client", "Malformed XML", "IDStarMsgNotUnderstood", 0, msg, 0));
     617                 :          0 :     return 0;
     618                 :            :   }
     619                 :         17 :   p = zxid_wsp_validate_env(cf, ses, az_cred, r->Envelope);
     620                 :         17 :   ZX_FREE(cf->ctx, r);
     621                 :            :   
     622                 :         17 :   logpath = zxlog_path(cf, ses->issuer, ses->wsp_msgid, ZXLOG_RELY_DIR, ZXLOG_MSG_KIND, 1);
     623         [ -  + ]:         17 :   if (zxlog_dup_check(cf, logpath, "validate request")) {
     624         [ #  # ]:          0 :     if (cf->dup_msg_fatal) {
     625                 :          0 :       zxlog_blob(cf, cf->log_rely_msg, logpath, &ss, "validate request dup err");
     626                 :          0 :       zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, TAS3_PEP_RS_IN, "e:Client", "Duplicate Message.", "DuplicateMsg", 0, 0, 0));
     627                 :          0 :       D_DEDENT("valid: ");
     628                 :          0 :       return 0;
     629                 :            :     } else {
     630                 :          0 :       INFO("Duplicate message detected, but configured to ignore this (DUP_MSG_FATAL=0). %d",0);
     631                 :            :     }
     632                 :            :   }
     633                 :         17 :   zxlog_blob(cf, cf->log_rely_msg, logpath, &ss, "validate request");
     634                 :         17 :   zxlogwsp(cf, ses, "K", "VALID", logpath->s, 0);
     635                 :         17 :   return p;
     636                 :            : }
     637                 :            : 
     638                 :            : /* EOF  --  zxidwsp.c */

Generated by: LCOV version 1.9