LCOV - code coverage report
Current view: top level - zxid - zxidecp.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 55 59 93.2 %
Date: 2010-12-19 Functions: 4 4 100.0 %
Branches: 23 42 54.8 %

           Branch data     Line data    Source code
       1                 :            : /* zxidecp.c  -  Handwritten functions for implementing Enhanced Client Proxy and SP
       2                 :            :  * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 2006-2008 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: zxidecp.c,v 1.10 2008-10-08 03:56:55 sampo Exp $
      10                 :            :  *
      11                 :            :  * 12.8.2006, created --Sampo
      12                 :            :  * 16.1.2007, split from zxidlib.c --Sampo
      13                 :            :  * 7.10.2008, added documentation --Sampo
      14                 :            :  * 14.3.2010, reformed eid presentation --Sampo
      15                 :            :  *
      16                 :            :  * See: zxid_sp_soap_dispatch() in zxidslo.c for handling PAOS response
      17                 :            :  *
      18                 :            :  * If you do not know what PAOS, ECP or LECP means, you should read SAML2 Profiles specification.
      19                 :            :  */
      20                 :            : 
      21                 :            : #include <stdio.h>
      22                 :            : #include <stdlib.h>
      23                 :            : 
      24                 :            : #include "errmac.h"
      25                 :            : #include "zxid.h"
      26                 :            : #include "zxidpriv.h"
      27                 :            : #include "zxidconf.h"
      28                 :            : #include "saml2.h"
      29                 :            : #include "c/zx-const.h"
      30                 :            : #include "c/zx-paos-data.h"
      31                 :            : 
      32                 :            : extern char **environ;
      33                 :            : 
      34                 :            : /*() Generate SOAP headers for use with PAOS carried SAML2 ECP profile AuthnRequest.
      35                 :            :  *
      36                 :            :  * If you do not know what PAOS, ECP or LECP means, you should read [SAML2bind] specification. */
      37                 :            : 
      38                 :            : /* Called by:  zxid_lecp_check */
      39                 :            : static struct zx_paos_Request_s* zxid_mk_paos_Request_hdr(zxid_conf* cf)
      40                 :          1 : {
      41                 :          1 :   struct zx_paos_Request_s* hdr= zx_NEW_paos_Request(cf->ctx,0);
      42                 :          1 :   hdr->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
      43                 :          1 :   hdr->actor   = zx_ref_attr(cf->ctx, &hdr->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
      44                 :          1 :   hdr->service = zx_ref_attr(cf->ctx, &hdr->gg, zx_service_ATTR, SAML2_SSO_ECP);
      45                 :          1 :   hdr->responseConsumerURL = zx_attrf(cf->ctx, &hdr->gg, zx_responseConsumerURL_ATTR, "%s?o=P", cf->url);
      46                 :            :   /*hdr->messageID = zx_ref_str(cf->ctx, "1"); OPTIONAL */
      47                 :          1 :   return hdr;
      48                 :            : }
      49                 :            : 
      50                 :            : /*() Build IDPList of IDPEntry(s) from the IdPs know to us at the moment (our CoT).
      51                 :            :  * Can be used for ECP and IdP proxying.
      52                 :            :  *
      53                 :            :  * cf:: ZXID configuration object, used to locate the CoT directory (PATH
      54                 :            :  *     configuration option) and for memory allocation
      55                 :            :  * binding:: The SSO protocol binding the qualifying IdPs MUST support, or 0 if anything goes
      56                 :            :  * return:: IdP list data structure or 0 on failure */
      57                 :            : 
      58                 :            : /* Called by:  zxid_mk_ecp_Request_hdr */
      59                 :            : static struct zx_sp_IDPList_s* zxid_mk_idp_list(zxid_conf* cf, char* binding)
      60                 :          1 : {
      61                 :            :   zxid_entity* idp;
      62                 :            :   struct zx_md_SingleSignOnService_s* sso_svc;
      63                 :            :   struct zx_sp_IDPList_s* idp_list;
      64                 :            :   struct zx_sp_IDPEntry_s* idp_entry;
      65                 :            : 
      66                 :          1 :   idp = zxid_load_cot_cache(cf);
      67         [ -  + ]:          1 :   if (!idp)
      68                 :          0 :     return 0;
      69                 :            :   
      70                 :          1 :   idp_list = zx_NEW_sp_IDPList(cf->ctx,0);
      71         [ +  + ]:         20 :   for (; idp; idp = idp->n) {
      72   [ -  +  #  # ]:         19 :     D("IDPList consider idp(%s)", idp->eid);
      73         [ +  + ]:         19 :     if (!idp->ed->IDPSSODescriptor)
      74                 :          6 :       continue;
      75                 :         13 :     for (sso_svc = idp->ed->IDPSSODescriptor->SingleSignOnService;
      76   [ +  +  +  + ]:         43 :          sso_svc && sso_svc->gg.g.tok == zx_md_SingleSignOnService_ELEM;
      77                 :         17 :          sso_svc = (struct zx_md_SingleSignOnService_s*)sso_svc->gg.g.n)
      78   [ +  -  +  + ]:         19 :       if (sso_svc->Binding && !memcmp(binding, sso_svc->Binding->g.s, sso_svc->Binding->g.len))
      79                 :          2 :         break;
      80         [ +  + ]:         13 :     if (!sso_svc) {
      81   [ -  +  #  # ]:          7 :       D("Entity(%s) does not have any IdP SSO Service with binding(%s)", idp->eid, binding);
      82                 :          7 :       continue;  /* Not eligible IdP, next one please. */
      83                 :            :     }
      84                 :            :     
      85                 :          6 :     idp_list->IDPEntry = idp_entry = zx_NEW_sp_IDPEntry(cf->ctx, &idp_list->gg);
      86                 :          6 :     idp_entry->ProviderID = zx_ref_attr(cf->ctx, &idp_entry->gg, zx_ProviderID_ATTR, idp->eid);
      87                 :          6 :     idp_entry->Name = zx_ref_attr(cf->ctx, &idp_entry->gg, zx_Name_ATTR, idp->dpy_name);
      88                 :          6 :     idp_entry->Loc = sso_svc->Location;
      89                 :            :   }
      90                 :          1 :   return idp_list;
      91                 :            : }
      92                 :            : 
      93                 :            : /*() Generate headers for use with Liberty ID-FF 1.2 LECP carried AuthnRequest.
      94                 :            :  *
      95                 :            :  * If you do not know what PAOS, ECP or LECP means, you should read [SAML2bind] specification. */
      96                 :            : 
      97                 :            : /* Called by:  zxid_lecp_check */
      98                 :            : static struct zx_ecp_Request_s* zxid_mk_ecp_Request_hdr(zxid_conf* cf)
      99                 :          1 : {
     100                 :          1 :   struct zx_ecp_Request_s* hdr= zx_NEW_ecp_Request(cf->ctx,0);
     101                 :          1 :   hdr->mustUnderstand = zx_ref_attr(cf->ctx, &hdr->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
     102                 :          1 :   hdr->actor = zx_ref_attr(cf->ctx, &hdr->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
     103                 :            :   /*hdr->IsPassive = zx_ref_attr(cf->ctx, &hdr->gg, zx_IsPassive_ATTR, XML_TRUE);  OPTIONAL, default=? */
     104                 :          1 :   hdr->ProviderName = zxid_my_ent_id_attr(cf, &hdr->gg, zx_ProviderName_ATTR);  /* *** Friendly name? */
     105                 :          1 :   hdr->Issuer = zxid_my_issuer(cf, &hdr->gg);
     106                 :          1 :   hdr->IDPList = zxid_mk_idp_list(cf, SAML2_SOAP);
     107                 :          1 :   return hdr;
     108                 :            : }
     109                 :            : 
     110                 :            : /* ============== LECP or ECP ============== */
     111                 :            : 
     112                 :            : /*() Check for ECP indications in HTTP request headers and initiate
     113                 :            :  * PAOS based Single Sign On, i.e AuthnRequest. This is part of the
     114                 :            :  * SAML2 Enhanced Client Proxy profile.
     115                 :            :  *
     116                 :            :  * Limitation:: Current (2008) code only works in CGI environment due to
     117                 :            :  *     reliance on environment variables. (*** fixme)
     118                 :            :  *
     119                 :            :  * If you do not know what PAOS, ECP or LECP means, you should read [SAML2bind] specification. */
     120                 :            : 
     121                 :            : /* Called by:  main x4, zxid_simple_no_ses_cf x2 */
     122                 :            : struct zx_str* zxid_lecp_check(zxid_conf* cf, zxid_cgi* cgi)
     123                 :          8 : {
     124                 :            :   struct zx_e_Envelope_s* se;
     125                 :            :   struct zx_str* env;
     126                 :            :   struct zx_str* req;
     127                 :            :   char* le;
     128                 :            : #if 0
     129                 :            :   char** pp;
     130                 :            :   for (pp = environ; *pp; ++pp)   /* Debug envirnment problems, e.g. mini_httpd does not pass HTTP_PAOS, unless patched. */
     131                 :            :     D("ENV(%s)", *pp);
     132                 :            : #endif
     133                 :            : 
     134                 :          8 :   le = getenv("HTTP_PAOS");
     135         [ +  + ]:          8 :   if (!le) {
     136                 :          7 :     le = getenv("HTTP_LIBERTY_ENABLED");
     137         [ +  - ]:          7 :     if (!le) {
     138   [ +  -  -  + ]:          7 :       D("Neither ECP nor LECP request %d", 0);
     139                 :          7 :       return 0;  /* No ECP/LECP detected, return to normal processing. */
     140                 :            :     }
     141   [ #  #  #  # ]:          0 :     D("LECP detected HTTP_LIBERTY_ENABLED(%s) (*** NOT IMPLEMENTED)", le);
     142                 :            :     /* *** start ID-FF 1.2 LECP processing */
     143                 :          0 :     return 0; /* ars = ...; */
     144                 :            :   }
     145   [ -  +  #  # ]:          1 :   D("ECP detected HTTP_PAOS(%s)", le);
     146         [ -  + ]:          1 :   if (!strstr(le, SAML2_SSO_ECP))
     147                 :          0 :     return 0;
     148                 :            :     
     149                 :            :   /* SAML 2.0 ECP: Create PAOS request to be sent in HTTP response. */
     150                 :            :     
     151                 :          1 :   se = zx_NEW_e_Envelope(cf->ctx,0);
     152                 :          1 :   se->Body = zx_NEW_e_Body(cf->ctx, &se->gg);
     153                 :          1 :   se->Body->AuthnRequest = zxid_mk_authn_req(cf, cgi);
     154                 :          1 :   se->Header = zx_NEW_e_Header(cf->ctx, &se->gg);
     155                 :          1 :   se->Header->Request = zxid_mk_paos_Request_hdr(cf);
     156                 :          1 :   se->Header->ecp_Request = zxid_mk_ecp_Request_hdr(cf);
     157                 :          1 :   env = zx_easy_enc_elem_opt(cf, &se->gg);
     158                 :          1 :   req = zx_strf(cf->ctx,
     159                 :            :                 "Cache-Control: no-cache, no-store, must-revalidate, private" CRLF
     160                 :            :                 "Pragma: no-cache" CRLF
     161                 :            :                 "Content-Type: " PAOS_CONTENT CRLF  /* content type only specified for ECP */
     162                 :            :                 "Content-Length: %d" CRLF2
     163                 :            :                 "%.*s", env->len, env->len, env->s);
     164                 :          1 :   zx_str_free(cf->ctx, env);
     165                 :          1 :   return req;
     166                 :            : }
     167                 :            : 
     168                 :            : /* EOF  --  zxidecp.c */

Generated by: LCOV version 1.9