LCOV - code coverage report
Current view: top level - zxid - zxidloc.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 37 123 30.1 %
Date: 2010-12-19 Functions: 3 7 42.9 %
Branches: 38 157 24.2 %

           Branch data     Line data    Source code
       1                 :            : /* zxidloc.c  -  Handwritten functions implementing service locator (based on metadata)
       2                 :            :  * Copyright (c) 2006-2008 Symlabs (symlabs@symlabs.com), All Rights Reserved.
       3                 :            :  * Author: Sampo Kellomaki (sampo@iki.fi)
       4                 :            :  * This is confidential unpublished proprietary source code of the author.
       5                 :            :  * NO WARRANTY, not even implied warranties. Contains trade secrets.
       6                 :            :  * Distribution prohibited unless authorized in writing.
       7                 :            :  * Licensed under Apache License 2.0, see file COPYING.
       8                 :            :  * $Id: zxidloc.c,v 1.13 2010-01-08 02:10:09 sampo Exp $
       9                 :            :  *
      10                 :            :  * 12.8.2006, created --Sampo
      11                 :            :  * 16.1.2007, split from zxidlib.c --Sampo
      12                 :            :  * 7.10.2008, added documentation --Sampo
      13                 :            :  */
      14                 :            : 
      15                 :            : #include <string.h>
      16                 :            : #include <stdio.h>
      17                 :            : #include <stdlib.h>
      18                 :            : 
      19                 :            : #include "errmac.h"
      20                 :            : #include "zxid.h"
      21                 :            : #include "zxidutil.h"
      22                 :            : #include "zxidconf.h"
      23                 :            : #include "saml2.h"
      24                 :            : #include "c/zx-data.h"
      25                 :            : 
      26                 :            : /* err_res = "ERR-metadata-does-not-have-url-for-binding";*/
      27                 :            : 
      28                 :            : /* ============== IdP Service Locator ============= */
      29                 :            : 
      30                 :            : /* *** figure out a way to leverage commonality. */
      31                 :            : 
      32                 :            : /*() Raw computation of IdP URL given service type, binding, and whether operation is a
      33                 :            :  * request. See zxid_idp_loc() for full description. */
      34                 :            : 
      35                 :            : /* Called by:  zxid_idp_loc x3, zxid_slo_resp_redir, zxid_sp_dispatch */
      36                 :            : struct zx_str* zxid_idp_loc_raw(zxid_conf* cf, zxid_cgi* cgi,
      37                 :            :                                 zxid_entity* idp_meta, int svc_type, char* binding, int req)
      38                 :          4 : {
      39                 :            :   struct zx_str* loc;
      40                 :            :   struct zx_md_SingleLogoutService_s* slo_svc;
      41                 :            :   struct zx_md_ManageNameIDService_s* mni_svc;
      42                 :            :   
      43   [ +  -  +  -  :          4 :   if (!idp_meta || !idp_meta->eid || !idp_meta->ed->IDPSSODescriptor) {
                   +  + ]
      44   [ +  -  +  - ]:          2 :     ERR("Entity(%s) does not have IdP SSO Descriptor (metadata problem)", idp_meta?STRNULLCHKQ(idp_meta->eid):"-");
      45                 :          2 :     return 0;
      46                 :            :   }
      47                 :            : 
      48      [ +  -  - ]:          2 :   switch (svc_type) {
      49                 :            :   case ZXID_SLO_SVC:
      50                 :          2 :     for (slo_svc = idp_meta->ed->IDPSSODescriptor->SingleLogoutService;
      51   [ +  -  +  - ]:          4 :          slo_svc && slo_svc->gg.g.tok == zx_md_SingleLogoutService_ELEM;
      52                 :          0 :          slo_svc = (struct zx_md_SingleLogoutService_s*)slo_svc->gg.g.n)
      53   [ +  -  +  -  :          2 :       if (slo_svc->Binding  && !memcmp(binding, slo_svc->Binding->g.s, slo_svc->Binding->g.len)
                   +  - ]
      54                 :            :           /*&& svc->index && !memcmp(end_pt_ix, svc->index->s, svc->index->len)*/
      55                 :            :           && slo_svc->Location)
      56                 :          2 :         break;
      57         [ +  - ]:          2 :     if (!slo_svc)
      58                 :          0 :       break;
      59   [ +  -  #  # ]:          2 :     loc = req ? &slo_svc->Location->g : (slo_svc->ResponseLocation ? &slo_svc->ResponseLocation->g : &slo_svc->Location->g);
      60         [ -  + ]:          2 :     if (!loc)
      61                 :          0 :       break;
      62                 :          2 :     return loc;
      63                 :            :   case ZXID_MNI_SVC:
      64                 :          0 :     for (mni_svc = idp_meta->ed->IDPSSODescriptor->ManageNameIDService;
      65   [ #  #  #  # ]:          0 :          mni_svc && mni_svc->gg.g.tok == zx_md_ManageNameIDService_ELEM;
      66                 :          0 :          mni_svc = (struct zx_md_ManageNameIDService_s*)mni_svc->gg.g.n)
      67   [ #  #  #  #  :          0 :       if (mni_svc->Binding  && !memcmp(binding, mni_svc->Binding->g.s, mni_svc->Binding->g.len)
                   #  # ]
      68                 :            :           /*&& svc->index && !memcmp(end_pt_ix, svc->index->s, svc->index->len)*/
      69                 :            :           && mni_svc->Location)
      70                 :          0 :         break;
      71         [ #  # ]:          0 :     if (!mni_svc)
      72                 :          0 :       break;
      73   [ #  #  #  # ]:          0 :     loc = req ? &mni_svc->Location->g : (mni_svc->ResponseLocation ? &mni_svc->ResponseLocation->g : &mni_svc->Location->g);
      74         [ #  # ]:          0 :     if (!loc)
      75                 :          0 :       break;
      76                 :          0 :     return loc;
      77                 :            :   }
      78                 :            : 
      79                 :          0 :   ERR("IdP Entity(%s) does not have any %d service with binding(%s) (metadata problem)", idp_meta->eid, svc_type, binding);
      80                 :          0 :   return 0;
      81                 :            : }
      82                 :            : 
      83                 :            : /*() SAML2 service locator. Given desired service, like SLO or MNI, and possibly binding,
      84                 :            :  * locate the appropriate service descriptor from the IdP metadata.
      85                 :            :  *
      86                 :            :  * cf:: ZXID configuration object, used for preferences and for memory allocation
      87                 :            :  * cgi:: May contain CGI variables that further indicate preference. Often specified
      88                 :            :  *     as 0 (no preference).
      89                 :            :  * ses:: Session object, which may be used to remember historical events, such as
      90                 :            :  *     binding of SSO transaction, that may act as preferences for binding. The
      91                 :            :  *     session MUST have assertion.
      92                 :            :  * idp_meta:: Metadata for the IdP
      93                 :            :  * svc_type:: The desired service, indicated as URN
      94                 :            :  * binding:: preferred binding URN, or 0 if no preference. In that case the built in
      95                 :            :  *     preference is used, or if that is indifferent, then first applicable metadata
      96                 :            :  *     item is picked. If IdP only supports one binding 0 will match that. If nonzero,
      97                 :            :  *     then the IdP metadata MUST have exactly matching entry or else 0 is returned.
      98                 :            :  * return:: URL for accessing the service or 0 upon failure
      99                 :            :  *
     100                 :            :  * *Limitation:* If binding is not specified, it may be ambiguous what binding the returned
     101                 :            :  * URL relates to. Generally the decision will have been taken prior to calling
     102                 :            :  * this function. */
     103                 :            : 
     104                 :            : /* Called by:  zxid_idp_soap, zxid_sp_mni_redir, zxid_sp_slo_redir */
     105                 :            : struct zx_str* zxid_idp_loc(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses,
     106                 :            :                             zxid_entity* idp_meta, int svc_type, char* binding)
     107                 :          2 : {
     108                 :          2 :   zxid_get_ses_sso_a7n(cf, ses);
     109                 :            :   
     110         [ +  - ]:          2 :   if (ses->a7n) {
     111                 :          2 :     return zxid_idp_loc_raw(cf, cgi, idp_meta, svc_type, binding, 1);
     112                 :            :   }
     113         [ #  # ]:          0 :   if (ses->a7n11) {
     114                 :          0 :     ERR("Not implemented: obtaining location from SAML 1.1 assetion %d", 0);
     115                 :            :     //return zxid_idp_loc_raw(cf, cgi, ses->a7n->Issuer, svc_type, binding, 1);
     116                 :            :   }
     117         [ #  # ]:          0 :   if (ses->a7n12) {
     118                 :          0 :     ERR("Not implemented: obtaining location from ID-FF 1.2 type SAML 1.1 assetion %d", 0);
     119                 :            :     //return zxid_idp_loc_raw(cf, cgi, ses->a7n->Issuer, svc_type, binding, 1);
     120                 :            :   }
     121                 :            :   
     122                 :          0 :   ERR("Session sid(%s) appears to lack SSO assertion.", ses->sid);
     123                 :          0 :   return 0;
     124                 :            : }
     125                 :            : 
     126                 :            : /*() Deternine URL for SOAP binding to given service and perform a SOAP call.
     127                 :            :  *
     128                 :            :  * cf:: ZXID configuration object
     129                 :            :  * cgi:: CGI variables that may influence determination of end point. Or 0 if no preference.
     130                 :            :  * ses:: Session information that may influence the choice of the end point. The
     131                 :            :  *     session MUST have asserion.
     132                 :            :  * idp_meta:: Metadata for the IdP
     133                 :            :  * svc_type:: The desired service, indicated as URN
     134                 :            :  * body:: XML data structure for the SOAP call <Body> element payload
     135                 :            :  * return:: XML data structure for Body element of the SOAP call response. */
     136                 :            : 
     137                 :            : /* Called by:  zxid_az_soap, zxid_sp_mni_soap, zxid_sp_slo_soap */
     138                 :            : struct zx_root_s* zxid_idp_soap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses,
     139                 :            :                                 zxid_entity* idp_meta, int svc_type, struct zx_e_Body_s* body)
     140                 :          0 : {
     141                 :            :   struct zx_root_s* r;
     142                 :          0 :   struct zx_str* loc = zxid_idp_loc(cf, cgi, ses, idp_meta, svc_type, SAML2_SOAP);
     143         [ #  # ]:          0 :   if (!loc)
     144                 :          0 :     return 0;
     145                 :          0 :   r = zxid_soap_call_hdr_body(cf, loc, 0, body);
     146                 :          0 :   zx_str_free(cf->ctx, loc);
     147                 :          0 :   return r;
     148                 :            : }
     149                 :            : 
     150                 :            : /* ============== SP Service Locator ============= */
     151                 :            : 
     152                 :            : /* *** figure out a way to leverage commonality. */
     153                 :            : 
     154                 :            : /* Called by:  zxid_idp_sso */
     155                 :            : struct zx_str* zxid_sp_loc_by_index_raw(zxid_conf* cf, zxid_cgi* cgi,
     156                 :            :                                         zxid_entity* sp_meta, int svc_type,
     157                 :            :                                         struct zx_str* ix, int* binding)
     158                 :          0 : {
     159                 :            :   struct zx_str* loc;
     160                 :            :   struct zx_md_AssertionConsumerService_s* acs_svc;
     161                 :            :   
     162   [ #  #  #  #  :          0 :   if (!sp_meta || !sp_meta->eid || !sp_meta->ed->SPSSODescriptor) {
                   #  # ]
     163   [ #  #  #  # ]:          0 :     ERR("Entity(%s) does not have SP SSO Descriptor (metadata problem)", sp_meta?STRNULLCHKQ(sp_meta->eid):"-");
     164                 :          0 :     return 0;
     165                 :            :   }
     166                 :            : 
     167         [ #  # ]:          0 :   switch (svc_type) {
     168                 :            :   case ZXID_ACS_SVC:
     169                 :          0 :     for (acs_svc = sp_meta->ed->SPSSODescriptor->AssertionConsumerService;
     170   [ #  #  #  # ]:          0 :          acs_svc && acs_svc->gg.g.tok == zx_md_AssertionConsumerService_ELEM;
     171                 :          0 :          acs_svc = (struct zx_md_AssertionConsumerService_s*)acs_svc->gg.g.n)
     172   [ #  #  #  #  :          0 :       if (acs_svc->index && ix->len == acs_svc->index->g.len
             #  #  #  # ]
     173                 :            :           && !memcmp(ix->s, acs_svc->index->g.s, ix->len)
     174                 :            :           && acs_svc->Location)
     175                 :          0 :         break;
     176         [ #  # ]:          0 :     if (!acs_svc)
     177                 :          0 :       break;
     178                 :          0 :     loc = &acs_svc->Location->g;
     179         [ #  # ]:          0 :     if (!loc)
     180                 :          0 :       break;
     181                 :          0 :     *binding = zxid_protocol_binding_map_saml2(&acs_svc->Binding->g);
     182                 :          0 :     return loc;
     183                 :            :   }
     184                 :            : 
     185                 :          0 :   ERR("SP Entity(%s) does not have any %d service with index(%.*s) (metadata problem)", sp_meta->eid, svc_type, ix->len, ix->s);
     186                 :          0 :   *binding = 0;
     187                 :          0 :   return 0;
     188                 :            : }
     189                 :            : 
     190                 :            : 
     191                 :            : /*() Raw computation of SP URL given service type, binding, and whether operation is a
     192                 :            :  * request. See zxid_sp_loc() for full description.
     193                 :            :  *
     194                 :            :  * return:: URL for the protocol end point, or 0 on failure */
     195                 :            : 
     196                 :            : /* Called by:  zxid_idp_dispatch, zxid_idp_sso x2, zxid_slo_resp_redir, zxid_sp_loc x3 */
     197                 :            : struct zx_str* zxid_sp_loc_raw(zxid_conf* cf, zxid_cgi* cgi, zxid_entity* sp_meta, int svc_type, char* binding, int req)
     198                 :          7 : {
     199                 :            :   struct zx_str* loc;
     200                 :            :   struct zx_md_SingleLogoutService_s* slo_svc;
     201                 :            :   struct zx_md_ManageNameIDService_s* mni_svc;
     202                 :            :   struct zx_md_AssertionConsumerService_s* acs_svc;
     203                 :            :   
     204   [ +  -  +  -  :          7 :   if (!sp_meta || !sp_meta->eid || !sp_meta->ed->SPSSODescriptor) {
                   -  + ]
     205   [ #  #  #  # ]:          0 :     ERR("Entity(%s) does not have SP SSO Descriptor (metadata problem)", sp_meta?STRNULLCHKQ(sp_meta->eid):"-");
     206                 :          0 :     return 0;
     207                 :            :   }
     208                 :            :   
     209   [ +  -  +  - ]:          7 :   switch (svc_type) {
     210                 :            :   case ZXID_SLO_SVC:
     211                 :          2 :     for (slo_svc = sp_meta->ed->SPSSODescriptor->SingleLogoutService;
     212   [ +  -  +  - ]:          4 :          slo_svc && slo_svc->gg.g.tok == zx_md_SingleLogoutService_ELEM;
     213                 :          0 :          slo_svc = (struct zx_md_SingleLogoutService_s*)slo_svc->gg.g.n)
     214   [ +  -  +  -  :          2 :       if (slo_svc->Binding  && !memcmp(binding, slo_svc->Binding->g.s, slo_svc->Binding->g.len)
                   +  - ]
     215                 :            :           /*&& svc->index && !memcmp(end_pt_ix, svc->index->s, svc->index->len)*/
     216                 :            :           && slo_svc->Location)
     217                 :          2 :         break;
     218         [ +  - ]:          2 :     if (!slo_svc)
     219                 :          0 :       break;
     220   [ -  +  +  - ]:          2 :     loc = req ? &slo_svc->Location->g : (slo_svc->ResponseLocation ? &slo_svc->ResponseLocation->g : &slo_svc->Location->g);
     221         [ -  + ]:          2 :     if (!loc)
     222                 :          0 :       break;
     223                 :          2 :     return loc;
     224                 :            :   case ZXID_MNI_SVC:
     225                 :          0 :     for (mni_svc = sp_meta->ed->SPSSODescriptor->ManageNameIDService;
     226   [ #  #  #  # ]:          0 :          mni_svc && mni_svc->gg.g.tok == zx_md_ManageNameIDService_ELEM;
     227                 :          0 :          mni_svc = (struct zx_md_ManageNameIDService_s*)mni_svc->gg.g.n)
     228   [ #  #  #  #  :          0 :       if (mni_svc->Binding  && !memcmp(binding, mni_svc->Binding->g.s, mni_svc->Binding->g.len)
                   #  # ]
     229                 :            :           /*&& svc->index && !memcmp(end_pt_ix, svc->index->s, svc->index->len)*/
     230                 :            :           && mni_svc->Location)
     231                 :          0 :         break;
     232         [ #  # ]:          0 :     if (!mni_svc)
     233                 :          0 :       break;
     234   [ #  #  #  # ]:          0 :     loc = req ? &mni_svc->Location->g : (mni_svc->ResponseLocation ? &mni_svc->ResponseLocation->g : &mni_svc->Location->g);
     235         [ #  # ]:          0 :     if (!loc)
     236                 :          0 :       break;
     237                 :          0 :     return loc;
     238                 :            :   case ZXID_ACS_SVC:
     239                 :          5 :     for (acs_svc = sp_meta->ed->SPSSODescriptor->AssertionConsumerService;
     240   [ +  -  +  - ]:         25 :          acs_svc && acs_svc->gg.g.tok == zx_md_AssertionConsumerService_ELEM;
     241                 :         15 :          acs_svc = (struct zx_md_AssertionConsumerService_s*)acs_svc->gg.g.n)
     242   [ +  -  +  +  :         20 :       if (acs_svc->Binding  && !memcmp(binding, acs_svc->Binding->g.s, acs_svc->Binding->g.len)
                   +  - ]
     243                 :            :           /*&& svc->index && !memcmp(end_pt_ix, svc->index->s, svc->index->len)*/
     244                 :            :           && acs_svc->Location)
     245                 :          5 :         break;
     246         [ -  + ]:          5 :     if (!acs_svc)
     247                 :          0 :       break;
     248                 :          5 :     loc = &acs_svc->Location->g;
     249         [ -  + ]:          5 :     if (!loc)
     250                 :          0 :       break;
     251                 :          5 :     return loc;
     252                 :            :   }
     253                 :            : 
     254                 :          0 :   ERR("SP Entity(%s) does not have any %d service with binding(%s) (metadata problem)", sp_meta->eid, svc_type, binding);
     255                 :          0 :   return 0;
     256                 :            : }
     257                 :            : 
     258                 :            : /*() SAML2 service locator for SP. Given desired service, like SLO or MNI, and possibly binding,
     259                 :            :  * locate the appropriate service descriptor from the Sp metadata.
     260                 :            :  *
     261                 :            :  * cf:: ZXID configuration object, used for preferences and for memory allocation
     262                 :            :  * cgi:: May contain CGI variables that further indicate preference. Often specified
     263                 :            :  *     as 0 (no preference).
     264                 :            :  * ses:: Session object, which may be used to remember historical events, such as
     265                 :            :  *     binding of SSO transaction, that may act as preferences for binding. The
     266                 :            :  *     session MUST have assertion.
     267                 :            :  * sp_meta:: Metadata for the Sp
     268                 :            :  * svc_type:: The desired service, indicated as URN
     269                 :            :  * binding:: preferred binding URN, or 0 if no preference. In that case the built in
     270                 :            :  *     preference is used, or if that is indifferent, then first applicable metadata
     271                 :            :  *     item is picked. If Sp only supports one binding 0 will match that. If nonzero,
     272                 :            :  *     then the Sp metadata MUST have exactly matching entry or else 0 is returned.
     273                 :            :  * return:: URL for accessing the service or 0 upon failure
     274                 :            :  *
     275                 :            :  * *Limitation:* If binding is not specified, it may be ambiguous what binding the returned
     276                 :            :  * URL relates to. Generally the decision will have been taken prior to calling
     277                 :            :  * this function. */
     278                 :            : 
     279                 :            : /* Called by:  zxid_sp_soap */
     280                 :            : struct zx_str* zxid_sp_loc(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, zxid_entity* sp_meta, int svc_type, char* binding)
     281                 :          0 : {
     282                 :          0 :   zxid_get_ses_sso_a7n(cf, ses);
     283                 :            :   
     284         [ #  # ]:          0 :   if (ses->a7n) {
     285                 :          0 :     return zxid_sp_loc_raw(cf, cgi, sp_meta, svc_type, binding, 1);
     286                 :            :   }
     287         [ #  # ]:          0 :   if (ses->a7n11) {
     288                 :          0 :     ERR("Not implemented: obtaining location from SAML 1.1 assetion %d", 0);
     289                 :            :     //return zxid_sp_loc_raw(cf, cgi, ses->a7n->Issuer, svc_type, binding, 1);
     290                 :            :   }
     291         [ #  # ]:          0 :   if (ses->a7n12) {
     292                 :          0 :     ERR("Not implemented: obtaining location from ID-FF 1.2 type SAML 1.1 assetion %d", 0);
     293                 :            :     //return zxid_sp_loc_raw(cf, cgi, ses->a7n->Issuer, svc_type, binding, 1);
     294                 :            :   }
     295                 :            :   
     296                 :          0 :   ERR("Session sid(%s) appears to lack SSO assertion.", ses->sid);
     297                 :          0 :   return 0;
     298                 :            : }
     299                 :            : 
     300                 :            : /*() Deternine URL for SOAP binding to given service on SP and perform a SOAP call.
     301                 :            :  *
     302                 :            :  * cf:: ZXID configuration object
     303                 :            :  * cgi:: CGI variables that may influence determination of end point. Or 0 if no preference.
     304                 :            :  * ses:: Session information that may influence the choice of the end point. The
     305                 :            :  *     session MUST have asserion.
     306                 :            :  * sp_meta:: Metadata for the Sp
     307                 :            :  * svc_type:: The desired service, indicated as URN
     308                 :            :  * body:: XML data structure for the SOAP call <Body> element payload
     309                 :            :  * return:: XML data structure for Body element of the SOAP call response. */
     310                 :            : 
     311                 :            : /* Called by: */
     312                 :            : struct zx_root_s* zxid_sp_soap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, zxid_entity* sp_meta, int svc_type, struct zx_e_Body_s* body)
     313                 :          0 : {
     314                 :            :   struct zx_root_s* r;
     315                 :          0 :   struct zx_str* loc = zxid_sp_loc(cf, cgi, ses, sp_meta, svc_type, SAML2_SOAP);
     316         [ #  # ]:          0 :   if (!loc)
     317                 :          0 :     return 0;
     318                 :          0 :   r = zxid_soap_call_hdr_body(cf, loc, 0, body);
     319                 :          0 :   zx_str_free(cf->ctx, loc);
     320                 :          0 :   return r;
     321                 :            : }
     322                 :            : 
     323                 :            : /* EOF  --  zxidloc.c */

Generated by: LCOV version 1.9