LCOV - code coverage report
Current view: top level - zxid - zxidslo.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 42 95 44.2 %
Date: 2010-12-19 Functions: 3 5 60.0 %
Branches: 37 150 24.7 %

           Branch data     Line data    Source code
       1                 :            : /* zxidslo.c  -  Handwritten functions for implementing Single LogOut logic for SP
       2                 :            :  * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 2006-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: zxidslo.c,v 1.42 2010-01-08 02:10:09 sampo Exp $
      10                 :            :  *
      11                 :            :  * 12.8.2006,  created --Sampo
      12                 :            :  * 12.10.2007, tweaked for signing SLO and MNI --Sampo
      13                 :            :  * 14.4.2008,  added SimpleSign --Sampo
      14                 :            :  * 7.10.2008,  added documentation --Sampo
      15                 :            :  * 12.2.2010,  added locking to lazy loading --Sampo
      16                 :            :  */
      17                 :            : 
      18                 :            : #include "platform.h"  /* needed on Win32 for pthread_mutex_lock() et al. */
      19                 :            : 
      20                 :            : #include "errmac.h"
      21                 :            : #include "zxid.h"
      22                 :            : #include "zxidpriv.h"
      23                 :            : #include "zxidconf.h"
      24                 :            : #include "saml2.h"
      25                 :            : #include "c/zx-const.h"
      26                 :            : #include "c/zx-ns.h"
      27                 :            : #include "c/zx-data.h"
      28                 :            : 
      29                 :            : /* ============== Single Logout ============== */
      30                 :            : 
      31                 :            : /*(i) SOAP client for sending Single Logout to IdP. The SOAP call is made
      32                 :            :  * using CURL HTTP Client and will block until response is received.
      33                 :            :  *
      34                 :            :  * return:: 1 if successful. 0 upon failure. */
      35                 :            : 
      36                 :            : /* Called by:  zxid_mgmt, zxid_simple_ses_active_cf */
      37                 :            : int zxid_sp_slo_soap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses)
      38                 :          0 : {
      39                 :            :   X509* sign_cert;
      40                 :            :   EVP_PKEY* sign_pkey;
      41                 :            : 
      42                 :          0 :   zxid_get_ses_sso_a7n(cf, ses);  
      43         [ #  # ]:          0 :   if (ses->a7n) {
      44                 :            :     struct zxsig_ref refs;
      45                 :            :     struct zx_root_s* r;
      46                 :            :     struct zx_e_Body_s* body;
      47                 :            :     struct zx_str* ses_ix;
      48                 :            :     zxid_entity* idp_meta;
      49                 :            :     
      50         [ #  # ]:          0 :     ses_ix = ses->a7n->AuthnStatement?&ses->a7n->AuthnStatement->SessionIndex->g:0;
      51         [ #  # ]:          0 :     if (cf->log_level>0)
      52   [ #  #  #  #  :          0 :       zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "W", "SLOSOAP", ses->sid, "sesix(%.*s)", ses_ix?ses_ix->len:1, ses_ix?ses_ix->s:"?");
          #  #  #  #  #  
                      # ]
      53                 :            :     
      54                 :          0 :     idp_meta = zxid_get_ses_idp(cf, ses);
      55         [ #  # ]:          0 :     if (!idp_meta)
      56                 :          0 :       return 0;
      57                 :            :     
      58                 :          0 :     body = zx_NEW_e_Body(cf->ctx,0);
      59                 :          0 :     body->LogoutRequest = zxid_mk_logout(cf, zxid_get_user_nameid(cf, ses->nameid), ses_ix, idp_meta);
      60         [ #  # ]:          0 :     if (cf->sso_soap_sign) {
      61                 :          0 :       ZERO(&refs, sizeof(refs));
      62                 :          0 :       refs.id = &body->LogoutRequest->ID->g;
      63                 :          0 :       refs.canon = zx_easy_enc_elem_sig(cf, &body->LogoutRequest->gg);
      64         [ #  # ]:          0 :       if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert slo")) {
      65                 :          0 :         body->LogoutRequest->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
      66                 :          0 :         zx_add_kid_after_sa_Issuer(&body->LogoutRequest->gg, &body->LogoutRequest->Signature->gg);
      67                 :            :       }
      68                 :          0 :       zx_str_free(cf->ctx, refs.canon);
      69                 :            :     }
      70                 :          0 :     r = zxid_idp_soap(cf, cgi, ses, idp_meta, ZXID_SLO_SVC, body);
      71         [ #  # ]:          0 :     if (!zxid_saml_ok(cf, cgi, r->Envelope->Body->LogoutResponse->Status, "LogoutResp"))
      72                 :          0 :       return 0;
      73                 :          0 :     return 1;
      74                 :            :   }
      75         [ #  # ]:          0 :   if (ses->a7n11) {
      76                 :          0 :     ERR("Not implemented, SAML 1.1 assetion %d", 0);
      77                 :            :   }
      78         [ #  # ]:          0 :   if (ses->a7n12) {
      79                 :          0 :     ERR("Not implemented, ID-FF 1.2 type SAML 1.1 assetion %d", 0);
      80                 :            :   }
      81                 :          0 :   ERR("Session sid(%s) lacks SSO assertion.", ses->sid);
      82                 :          0 :   return 0;
      83                 :            : }
      84                 :            : 
      85                 :            : /*(i) Send Single Logout to IdP using redirect binding. This function
      86                 :            :  * generates the URL encapsulating the request. You need to pass this
      87                 :            :  * URL to the appropriate function in your environment to provoke
      88                 :            :  * an HTTP 302 redirect.
      89                 :            :  *
      90                 :            :  * cf:: ZXID config object, also used for memory allocation
      91                 :            :  * cgi:: Data parsed from POST or query string. Provides parameters to determine
      92                 :            :  *     details of the SLO request
      93                 :            :  * ses:: Session object. Used to determine session index (~ses_ix~) and name id, among others
      94                 :            :  * return:: location string if successful. "* ERR" upon failure. */
      95                 :            : 
      96                 :            : /* Called by:  zxid_mgmt, zxid_simple_ses_active_cf */
      97                 :            : struct zx_str* zxid_sp_slo_redir(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses)
      98                 :          2 : {
      99                 :          2 :   zxid_get_ses_sso_a7n(cf, ses);
     100         [ +  - ]:          2 :   if (ses->a7n) {
     101                 :            :     struct zx_sp_LogoutRequest_s* r;
     102                 :            :     struct zx_str* rs;
     103                 :            :     struct zx_str* loc;
     104                 :            :     zxid_entity* idp_meta;
     105                 :            :     struct zx_str* ses_ix;
     106                 :            : 
     107         [ +  - ]:          2 :     ses_ix = ses->a7n->AuthnStatement?&ses->a7n->AuthnStatement->SessionIndex->g:0;
     108         [ +  - ]:          2 :     if (cf->log_level>0)
     109   [ +  -  +  -  :          2 :       zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "W", "SLOREDIR", ses->sid, "sesix(%.*s)", ses_ix?ses_ix->len:1, ses_ix?ses_ix->s:"?");
          +  -  +  -  +  
                      - ]
     110                 :            :     
     111                 :          2 :     idp_meta = zxid_get_ses_idp(cf, ses);
     112         [ -  + ]:          2 :     if (!idp_meta)
     113                 :          0 :       return zx_dup_str(cf->ctx, "* ERR");
     114                 :            : 
     115                 :          2 :     loc = zxid_idp_loc(cf, cgi, ses, idp_meta, ZXID_SLO_SVC, SAML2_REDIR);
     116         [ -  + ]:          2 :     if (!loc)
     117                 :          0 :       return zx_dup_str(cf->ctx, "* ERR");
     118                 :          2 :     r = zxid_mk_logout(cf, zxid_get_user_nameid(cf, ses->nameid), ses_ix, idp_meta);
     119                 :          2 :     r->Destination = zx_ref_len_attr(cf->ctx, &r->gg, zx_Destination_ATTR, loc->len, loc->s);
     120                 :          2 :     rs = zx_easy_enc_elem_opt(cf, &r->gg);
     121   [ +  -  -  + ]:          2 :     D("SLO(%.*s)", rs->len, rs->s);
     122                 :          2 :     return zxid_saml2_redir(cf, loc, rs, 0);
     123                 :            :   }
     124         [ #  # ]:          0 :   if (ses->a7n11) {
     125                 :          0 :     ERR("Not implemented, SAML 1.1 assetion %d", 0);
     126                 :            :   }
     127         [ #  # ]:          0 :   if (ses->a7n12) {
     128                 :          0 :     ERR("Not implemented, ID-FF 1.2 type SAML 1.1 assetion %d", 0);
     129                 :            :   }
     130                 :          0 :   ERR("Session sid(%s) lacks SSO assertion.", ses->sid);
     131                 :          0 :   return zx_dup_str(cf->ctx, "* ERR");
     132                 :            : }
     133                 :            : 
     134                 :            : /*() Generate SLO Response, SP or IdP variant. The actual session invalidation must be
     135                 :            :  * done somewhere else, i.e. this is just the final protocol phase of the SLO. */
     136                 :            : 
     137                 :            : /* Called by:  zxid_idp_dispatch, zxid_sp_dispatch */
     138                 :            : struct zx_str* zxid_slo_resp_redir(zxid_conf* cf, zxid_cgi* cgi, struct zx_sp_LogoutRequest_s* req)
     139                 :          2 : {
     140                 :            :   struct zx_sp_LogoutResponse_s* res;
     141                 :            :   zxid_entity* meta;
     142                 :            :   struct zx_str* loc;
     143                 :            :   struct zx_str* ss;
     144                 :            :   struct zx_str* ss2;
     145                 :            : 
     146   [ +  -  +  -  :          2 :   meta = zxid_get_ent_ss(cf, ZX_GET_CONTENT(req->Issuer));
                   +  - ]
     147                 :          2 :   loc = zxid_idp_loc_raw(cf, cgi, meta, ZXID_SLO_SVC, SAML2_REDIR, 0);
     148         [ +  - ]:          2 :   if (!loc)
     149                 :          2 :     loc = zxid_sp_loc_raw(cf, cgi, meta, ZXID_SLO_SVC, SAML2_REDIR, 0);
     150         [ -  + ]:          2 :   if (!loc)
     151                 :          0 :     return zx_dup_str(cf->ctx, "* ERR");  /* *** consider sending error page */
     152                 :            : 
     153                 :          2 :   zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "W", "SLORESREDIR", 0, "");
     154                 :            : 
     155                 :          2 :   res = zxid_mk_logout_resp(cf, zxid_OK(cf, 0), &req->ID->g);
     156                 :          2 :   res->Destination = zx_ref_len_attr(cf->ctx, &res->gg, zx_Destination_ATTR, loc->len, loc->s);
     157                 :          2 :   ss = zx_easy_enc_elem_opt(cf, &res->gg);
     158                 :          2 :   ss2 = zxid_saml2_resp_redir(cf, loc, ss, cgi->rs);
     159                 :            :   /*zx_str_free(cf->ctx, loc); Do NOT free loc as it is still referenced by the metadata. */
     160                 :          2 :   zx_str_free(cf->ctx, ss);
     161                 :          2 :   return ss2;
     162                 :            : }
     163                 :            : 
     164                 :            : /*() Process SP SLO request. */
     165                 :            : 
     166                 :            : /* Called by:  zxid_idp_dispatch, zxid_sp_dispatch, zxid_sp_soap_dispatch */
     167                 :            : int zxid_sp_slo_do(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_sp_LogoutRequest_s* req)
     168                 :          0 : {
     169   [ #  #  #  #  :          0 :   struct zx_str* sesix = ZX_GET_CONTENT(req->SessionIndex);
                   #  # ]
     170                 :            : 
     171         [ #  # ]:          0 :   if (!zxid_chk_sig(cf, cgi, ses, &req->gg, req->Signature, req->Issuer, 0, "LogoutRequest"))
     172                 :          0 :     return 0;
     173                 :            : 
     174         [ #  # ]:          0 :   if (cf->log_level>0)
     175   [ #  #  #  #  :          0 :     zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), cgi->sigval, "K", "SLO", ses->sid, "sesix(%.*s)", sesix?sesix->len:1, sesix?sesix->s:"?");
          #  #  #  #  #  
                      # ]
     176                 :            :   
     177                 :          0 :   req->NameID = zxid_decrypt_nameid(cf, req->NameID, req->EncryptedID);
     178   [ #  #  #  #  :          0 :   if (!ZX_GET_CONTENT(req->NameID)) {
                   #  # ]
     179                 :          0 :     ERR("SLO failed: request does not have NameID. %p", req->NameID);
     180                 :          0 :     return 0;
     181                 :            :   }
     182   [ #  #  #  #  :          0 :   zxid_find_ses(cf, ses, sesix, ZX_GET_CONTENT(req->NameID));
                   #  # ]
     183                 :          0 :   zxid_del_ses(cf, ses);
     184                 :          0 :   return 1;
     185                 :            : }
     186                 :            : 
     187                 :            : /*() Process IdP SLO request. The IdP SLO Requests are complicated by the need
     188                 :            :  * to log the user out of other SPs as well, if they belong to same session.
     189                 :            :  * Part of the complication is figuring out what constitutes "same session".
     190                 :            :  * Finally, the redirect profiles may be "hairy" to handle if some SP does
     191                 :            :  * not collaborate in the SLO. For SOAP similar problem exists, but it should be
     192                 :            :  * manageable. */
     193                 :            : 
     194                 :            : /* Called by:  zxid_idp_dispatch, zxid_idp_soap_dispatch, zxid_sp_dispatch */
     195                 :            : int zxid_idp_slo_do(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_sp_LogoutRequest_s* req)
     196                 :          2 : {
     197   [ +  -  +  -  :          2 :   struct zx_str* sesix = ZX_GET_CONTENT(req->SessionIndex);
                   +  - ]
     198         [ +  - ]:          2 :   if (sesix)
     199   [ +  -  +  -  :          2 :     sesix = zxid_psobj_dec(cf, ZX_GET_CONTENT(req->Issuer), "ZS", sesix);
                   +  - ]
     200                 :            :   
     201         [ -  + ]:          2 :   if (!zxid_chk_sig(cf, cgi, ses, &req->gg, req->Signature, req->Issuer, 0, "LogoutRequest"))
     202                 :          0 :     return 0;
     203                 :            :   
     204         [ +  - ]:          2 :   if (cf->log_level>0)
     205   [ -  +  -  +  :          2 :     zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), cgi->sigval, "K", "ISLO", ses->sid, "sesix(%.*s)", sesix?sesix->len:1, sesix?sesix->s:"?");
          -  +  #  #  #  
                      # ]
     206         [ +  - ]:          2 :   if (cf->loguser)
     207   [ -  +  -  +  :          2 :     zxlogusr(cf, ses->uid, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), cgi->sigval, "K", "ISLO", ses->sid, "sesix(%.*s)", sesix?sesix->len:1, sesix?sesix->s:"?");
          -  +  #  #  #  
                      # ]
     208                 :            : 
     209                 :          2 :   req->NameID = zxid_decrypt_nameid(cf, req->NameID, req->EncryptedID);
     210   [ +  -  +  -  :          2 :   if (!ZX_GET_CONTENT(req->NameID)) {
                   -  + ]
     211   [ #  #  #  # ]:          0 :     INFO("SLO: request does not have NameID. %p sesix(%.*s)", req->NameID, sesix?sesix->len:0, sesix?sesix->s:"");
     212                 :            :   }
     213         [ +  - ]:          2 :   if (zxid_find_ses(cf, ses, sesix, 0 /*ZX_GET_CONTENT(req->NameID)*/))
     214                 :          2 :     zxid_del_ses(cf, ses);
     215                 :          2 :   return 1;
     216                 :            : }
     217                 :            : 
     218                 :            : /* EOF  --  zxidslo.c */

Generated by: LCOV version 1.9