LCOV - code coverage report
Current view: top level - zxid - zxdecode.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 182 253 71.9 %
Date: 2010-12-19 Functions: 5 5 100.0 %
Branches: 139 287 48.4 %

           Branch data     Line data    Source code
       1                 :            : /* zxdecode.c  -  SAML Decoding tool
       2                 :            :  * Copyright (c) 2008-2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * This is confidential unpublished proprietary source code of the author.
       4                 :            :  * NO WARRANTY, not even implied warranties. Contains trade secrets.
       5                 :            :  * Distribution prohibited unless authorized in writing.
       6                 :            :  * Licensed under Apache License 2.0, see file COPYING.
       7                 :            :  * $Id: zxdecode.c,v 1.8 2009-11-29 12:23:06 sampo Exp $
       8                 :            :  *
       9                 :            :  * 25.11.2008, created --Sampo
      10                 :            :  * 4.10.2010, added -s and ss modes, as well as -i N selector --Sampo
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <string.h>
      14                 :            : #include <stdio.h>
      15                 :            : #include <stdlib.h>
      16                 :            : #include <errno.h>
      17                 :            : #include <sys/types.h>
      18                 :            : #include <sys/stat.h>
      19                 :            : #include <signal.h>
      20                 :            : #include <fcntl.h>
      21                 :            : 
      22                 :            : #include "errmac.h"
      23                 :            : #include "zx.h"
      24                 :            : #include "zxid.h"
      25                 :            : #include "zxidpriv.h"
      26                 :            : #include "zxidutil.h"
      27                 :            : #include "zxidconf.h"
      28                 :            : #include "c/zxidvers.h"
      29                 :            : #include "c/zx-ns.h"
      30                 :            : #include "c/zx-const.h"
      31                 :            : #include "c/zx-data.h"
      32                 :            : 
      33                 :            : char* help =
      34                 :            : "zxdecode  -  Decode SAML Redirect and POST Messages R" ZXID_REL "\n\
      35                 :            : Copyright (c) 2008-2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.\n\
      36                 :            : NO WARRANTY, not even implied warranties. Licensed under Apache License v2.0\n\
      37                 :            : See http://www.apache.org/licenses/LICENSE-2.0\n\
      38                 :            : Send well researched bug reports to the author. Home: zxid.org\n\
      39                 :            : \n\
      40                 :            : Usage: zxdecode [options] <message >decoded\n\
      41                 :            :   -b -B            Prevent or force decode base64 step (default auto detects)\n\
      42                 :            :   -z -Z            Prevent or force inflate step (default auto detects)\n\
      43                 :            :   -i N             Pick Nth detected decodable structure, default: 1=first\n\
      44                 :            :   -s               Enable signature validation step (reads config from -c, see below)\n\
      45                 :            :   -s -s            Only validate hashes (check canon), do not fetch meta or check RSA\n\
      46                 :            :   -c CONF          For -s, optional configuration string (default -c PATH=/var/zxid/)\n\
      47                 :            :                    Most of the configuration is read from /var/zxid/zxid.conf\n\
      48                 :            :   -sha1            Compute sha1 over input and print as base64. For debugging canon.\n\
      49                 :            :   -v               Verbose messages.\n\
      50                 :            :   -q               Be extra quiet.\n\
      51                 :            :   -d               Turn on debugging.\n\
      52                 :            :   -h               This help message\n\
      53                 :            :   --               End of options\n\
      54                 :            : \n\
      55                 :            : Will attempt to detect many layers of encoding. Will hunt for the\n\
      56                 :            : relevant input such as SAMLRequest or SAMLResponse in, e.g., log file.\n";
      57                 :            : 
      58                 :            : int b64_flag = 2;      /* Auto */
      59                 :            : int inflate_flag = 2;  /* Auto */
      60                 :            : int verbose = 1;
      61                 :            : int ix = 1;
      62                 :            : int sig_flag = 0;  /* No sig checking by default. */
      63                 :            : int sha1_flag;
      64                 :            : zxid_conf* cf = 0;
      65                 :            : char buf[256*1024];
      66                 :            : 
      67                 :            : /* Called by:  main x8, zxcall_main, zxcot_main, zxdecode_main */
      68                 :            : static void opt(int* argc, char*** argv, char*** env)
      69                 :         27 : {
      70         [ +  - ]:         27 :   if (*argc <= 1) return;
      71                 :            :   
      72                 :            :   while (1) {
      73                 :        127 :     ++(*argv); --(*argc);
      74                 :            :     
      75   [ +  +  +  - ]:        127 :     if (!(*argc) || ((*argv)[0][0] != '-')) break;  /* normal exit from options loop */
      76                 :            :     
      77   [ +  +  +  +  :        103 :     switch ((*argv)[0][1]) {
          +  +  +  +  +  
                +  +  + ]
      78         [ +  - ]:          2 :     case '-': if ((*argv)[0][2]) break;
      79                 :          2 :       ++(*argv); --(*argc);
      80                 :            :       DD("End of options by --");
      81                 :          2 :       return;  /* -- ends the options */
      82                 :            : 
      83                 :            :     case 'c':
      84         [ +  - ]:         24 :       switch ((*argv)[0][2]) {
      85                 :            :       case '\0':
      86                 :         24 :         ++(*argv); --(*argc);
      87         [ +  - ]:         24 :         if ((*argc) < 1) break;
      88         [ -  + ]:         24 :         if (!cf)
      89                 :          0 :           cf = zxid_new_conf_to_cf(0);
      90                 :         24 :         zxid_parse_conf(cf, (*argv)[0]);
      91                 :         24 :         continue;
      92                 :            :       }
      93                 :          0 :       break;
      94                 :            : 
      95                 :            :     case 'd':
      96         [ +  - ]:          3 :       switch ((*argv)[0][2]) {
      97                 :            :       case '\0':
      98                 :          3 :         ++zx_debug;
      99                 :          3 :         continue;
     100                 :            :       }
     101                 :          0 :       break;
     102                 :            : 
     103                 :            :     case 'i':
     104         [ +  - ]:          3 :       switch ((*argv)[0][2]) {
     105                 :            :       case '\0':
     106                 :          3 :         ++(*argv); --(*argc);
     107         [ +  - ]:          3 :         if ((*argc) < 1) break;
     108                 :          3 :         sscanf((*argv)[0], "%i", &ix);
     109                 :          3 :         continue;
     110                 :            :       }
     111                 :          0 :       break;
     112                 :            : 
     113                 :            :     case 's':
     114      [ +  +  - ]:         39 :       switch ((*argv)[0][2]) {
     115                 :            :       case '\0':
     116                 :         38 :         ++sig_flag;
     117         [ +  + ]:         38 :         if (!cf)
     118                 :         22 :           cf = zxid_new_conf_to_cf(0);
     119                 :         38 :         continue;
     120                 :            :       case 'h':
     121                 :          1 :         ++sha1_flag;
     122                 :          1 :         continue;
     123                 :            :       }
     124                 :          0 :       break;
     125                 :            : 
     126                 :            :     case 'b':
     127         [ +  - ]:          2 :       switch ((*argv)[0][2]) {
     128                 :            :       case '\0':
     129                 :          2 :         b64_flag = 0;
     130                 :          2 :         continue;
     131                 :            :       }
     132                 :          0 :       break;
     133                 :            :     case 'B':
     134         [ +  - ]:          1 :       switch ((*argv)[0][2]) {
     135                 :            :       case '\0':
     136                 :          1 :         b64_flag = 1;
     137                 :          1 :         continue;
     138                 :            :       }
     139                 :          0 :       break;
     140                 :            : 
     141                 :            :     case 'z':
     142         [ +  - ]:          2 :       switch ((*argv)[0][2]) {
     143                 :            :       case '\0':
     144                 :          2 :         inflate_flag = 0;
     145                 :          2 :         continue;
     146                 :            :       }
     147                 :          0 :       break;
     148                 :            :     case 'Z':
     149         [ +  - ]:          1 :       switch ((*argv)[0][2]) {
     150                 :            :       case '\0':
     151                 :          1 :         inflate_flag = 1;
     152                 :          1 :         continue;
     153                 :            :       }
     154                 :          0 :       break;
     155                 :            : 
     156                 :            : #if 0
     157                 :            :     case 'l':
     158                 :            :       switch ((*argv)[0][2]) {
     159                 :            :       case 'i':
     160                 :            :         if (!strcmp((*argv)[0],"-license")) {
     161                 :            :           extern char* license;
     162                 :            :           fprintf(stderr, license);
     163                 :            :           exit(0);
     164                 :            :         }
     165                 :            :         break;
     166                 :            :       }
     167                 :            :       break;
     168                 :            : #endif
     169                 :            : 
     170                 :            :     case 'q':
     171         [ +  - ]:          1 :       switch ((*argv)[0][2]) {
     172                 :            :       case '\0':
     173                 :          1 :         verbose = 0;
     174                 :          1 :         continue;
     175                 :            :       }
     176                 :          0 :       break;
     177                 :            : 
     178                 :            :     case 'v':
     179         [ +  - ]:         24 :       switch ((*argv)[0][2]) {
     180                 :            :       case '\0':
     181                 :         24 :         ++verbose;
     182                 :         24 :         continue;
     183                 :            :       }
     184                 :            :       break;
     185                 :            : 
     186                 :            :     } 
     187                 :            :     /* fall thru means unrecognized flag */
     188         [ +  - ]:          1 :     if (*argc)
     189                 :          1 :       fprintf(stderr, "Unrecognized flag `%s'\n", (*argv)[0]);
     190         [ +  - ]:          1 :     if (verbose>1) {
     191                 :          1 :       printf(help);
     192                 :          1 :       exit(0);
     193                 :            :     }
     194                 :          0 :     fprintf(stderr, help);
     195                 :            :     /*fprintf(stderr, "version=0x%06x rel(%s)\n", zxid_version(), zxid_version_str());*/
     196                 :          0 :     exit(3);
     197                 :        100 :   }
     198                 :            : }
     199                 :            : 
     200                 :            : /* Called by:  sig_validate */
     201                 :            : static int wsse_sec_validate(struct zx_e_Envelope_s* env)
     202                 :          1 : {
     203                 :            :   int ret;
     204                 :          1 :   int n_refs = 0;
     205                 :            :   struct zxsig_ref refs[ZXID_N_WSF_SIGNED_HEADERS];
     206                 :          1 :   struct zx_wsse_Security_s* sec = env->Header->Security;
     207                 :            : 
     208   [ +  -  -  + ]:          1 :   if (!sec || !sec->Signature) {
     209                 :          0 :     ERR("Missing signature on <wsse:Security> %p", sec);
     210                 :          0 :     return 8;
     211                 :            :   }
     212   [ +  -  -  + ]:          1 :   if (!sec->Signature->SignedInfo || !sec->Signature->SignedInfo->Reference) {
     213                 :          0 :     ERR("Malformed signature, missing mandatory SignedInfo(%p) or Reference", sec->Signature->SignedInfo);
     214                 :          0 :     return 9;
     215                 :            :   }
     216                 :            :   
     217                 :          1 :   ZERO(refs, sizeof(refs));
     218                 :          1 :   n_refs = zxid_hunt_sig_parts(cf, n_refs, refs, sec->Signature->SignedInfo->Reference, env->Header, env->Body);
     219                 :            :   /*zx_see_elem_ns(cf->ctx, &refs.pop_seen, &resp->gg); *** */
     220                 :          1 :   ret = zxsig_validate(cf->ctx, 0, sec->Signature, n_refs, refs);
     221         [ -  + ]:          1 :   if (ret == ZXSIG_BAD_CERT) {
     222                 :          0 :     INFO("Canon sha1 of <wsse:Security> verified OK %d", ret);
     223         [ #  # ]:          0 :     if (verbose)
     224                 :          0 :       printf("\nCanon sha1 if <wsse:Security> verified OK %d\n", ret);
     225                 :            :   } else {
     226                 :          1 :     ERR("Response Signature hash validation error. Bad canonicalization? ret=%d",ret);
     227                 :          1 :     return 10;
     228                 :            :   }
     229                 :            : 
     230   [ #  #  #  # ]:          0 :   if (ret && verbose)
     231                 :          0 :     printf("\nSIG Verified OK, zxid_sp_sso_finalize() returned %d\n", ret);
     232         [ #  # ]:          0 :   return ret?0:6;
     233                 :            : }
     234                 :            : 
     235                 :            : /* Called by:  decode */
     236                 :            : static int sig_validate(int len, char* p)
     237                 :         22 : {
     238                 :            :   int ret;
     239                 :            :   zxid_cgi cgi;
     240                 :            :   zxid_ses ses;
     241                 :            :   struct zx_root_s* r;
     242                 :            :   struct zx_sp_Response_s* resp;
     243                 :         22 :   struct zx_ns_s* pop_seen = 0;
     244                 :            :   struct zxsig_ref refs;
     245                 :            :   zxid_a7n* a7n;
     246                 :            :   
     247                 :         22 :   ZERO(&cgi, sizeof(cgi));
     248                 :         22 :   ZERO(&ses, sizeof(ses));
     249                 :            : 
     250                 :         22 :   r = zx_dec_zx_root(cf->ctx, len, p, "decode");
     251         [ -  + ]:         22 :   if (!r) {
     252                 :          0 :     ERR("Failed to parse buf(%.*s)", len, p);
     253                 :          0 :     return 2;
     254                 :            :   }
     255                 :            : 
     256         [ +  + ]:         22 :   if (r->Response)
     257                 :         12 :     resp = r->Response;
     258   [ +  +  +  - ]:         13 :   else if (r->Envelope && r->Envelope->Body) {
     259         [ -  + ]:          4 :     if (r->Envelope->Body->Response)
     260                 :          0 :       resp = r->Envelope->Body->Response;
     261   [ +  +  +  - ]:          7 :     else if (r->Envelope->Body->ArtifactResponse && r->Envelope->Body->ArtifactResponse->Response)
     262                 :          3 :       resp = r->Envelope->Body->ArtifactResponse->Response;
     263   [ +  -  +  - ]:          1 :     else if (r->Envelope->Header && r->Envelope->Header->Security)
     264                 :          1 :       return wsse_sec_validate(r->Envelope);
     265                 :            :     else {
     266                 :          0 :       ERR("<e:Envelope> found, but no <sp:Response> element in it %d",0);
     267                 :          0 :       return 3;
     268                 :            :     }
     269                 :            :   } else {
     270                 :          6 :     a7n = zxid_dec_a7n(cf, r->Assertion, r->EncryptedAssertion);
     271         [ +  - ]:          6 :     if (a7n) {
     272                 :          6 :       INFO("Bare Assertion without Response wrapper detected %p", r->Assertion);
     273                 :          6 :       goto got_a7n;
     274                 :            :     }
     275                 :          0 :     ERR("No <sp:Response>, <sa:Assertion>, or <sa:EncryptedAssertion> found buf(%.*s)", len, p);
     276                 :          0 :     return 3;
     277                 :            :   }
     278                 :            : 
     279                 :            :   /* See zxid_sp_dig_sso_a7n() for similar code. */
     280                 :            :   
     281         [ +  + ]:         15 :   if (sig_flag == 2) {
     282         [ +  - ]:          9 :     if (!resp->Signature) {
     283                 :          9 :       INFO("No signature in Response %d", 0);
     284                 :            :     } else {
     285   [ #  #  #  # ]:          0 :       if (!resp->Signature->SignedInfo || !resp->Signature->SignedInfo->Reference) {
     286                 :          0 :         ERR("Malformed signature, missing mandatory SignedInfo(%p) or Reference", resp->Signature->SignedInfo);
     287                 :          0 :         return 9;
     288                 :            :       }
     289                 :            : 
     290                 :          0 :       ZERO(&refs, sizeof(refs));
     291                 :          0 :       refs.sref = resp->Signature->SignedInfo->Reference;
     292                 :          0 :       refs.blob = &resp->gg;
     293                 :          0 :       refs.pop_seen = pop_seen;
     294                 :          0 :       zx_see_elem_ns(cf->ctx, &refs.pop_seen, &resp->gg);
     295                 :          0 :       ret = zxsig_validate(cf->ctx, 0, resp->Signature, 1, &refs);
     296         [ #  # ]:          0 :       if (ret == ZXSIG_BAD_CERT) {
     297                 :          0 :         INFO("Canon sha1 of Response verified OK %d", ret);
     298         [ #  # ]:          0 :         if (verbose)
     299                 :          0 :           printf("\nCanon sha1 of Response verified OK %d\n", ret);
     300                 :            :       } else {
     301                 :          0 :         ERR("Response Signature hash validation error. Bad canonicalization? ret=%d",ret);
     302         [ #  # ]:          0 :         if (sig_flag < 3)
     303                 :          0 :           return 10;
     304                 :            :       }
     305                 :            :     }
     306                 :            :   } else {
     307         [ -  + ]:          6 :     if (!zxid_chk_sig(cf, &cgi, &ses, &resp->gg, resp->Signature, resp->Issuer, 0, "Response"))
     308                 :          0 :       return 4;
     309                 :            :   }
     310                 :            :   
     311                 :         15 :   a7n = zxid_dec_a7n(cf, resp->Assertion, resp->EncryptedAssertion);
     312         [ -  + ]:         15 :   if (!a7n) {
     313                 :          0 :     ERR("No Assertion found and not anon_ok in SAML Response %d", 0);
     314                 :          0 :     return 5;
     315                 :            :   }
     316                 :         15 :   zx_see_elem_ns(cf->ctx, &pop_seen, &resp->gg);
     317                 :         21 : got_a7n:
     318         [ +  + ]:         21 :   if (sig_flag == 2) {
     319   [ +  -  +  -  :         15 :     if (a7n->Signature && a7n->Signature->SignedInfo && a7n->Signature->SignedInfo->Reference) {
                   +  - ]
     320                 :         15 :       cf->ctx->guard_seen_n.seen_n = &cf->ctx->guard_seen_p;  /* *** should call zx_reset_ctx? */
     321                 :         15 :       cf->ctx->guard_seen_p.seen_p = &cf->ctx->guard_seen_n;
     322                 :         15 :       ZERO(&refs, sizeof(refs));
     323                 :         15 :       refs.sref = a7n->Signature->SignedInfo->Reference;
     324                 :         15 :       refs.blob = &a7n->gg;
     325                 :         15 :       refs.pop_seen = pop_seen;
     326                 :         15 :       zx_see_elem_ns(cf->ctx, &refs.pop_seen, &a7n->gg);
     327                 :         15 :       ret = zxsig_validate(cf->ctx, 0, a7n->Signature, 1, &refs);
     328         [ +  + ]:         15 :       if (ret == ZXSIG_BAD_CERT) {
     329                 :         13 :         INFO("Canon sha1 of Assertion verified OK %d", ret);
     330   [ +  -  +  - ]:         13 :         if (ret && verbose)
     331                 :         13 :           printf("\nCanon sha1 of Assertion verified OK %d\n", ret);
     332                 :         13 :         return 0;
     333                 :            :       }
     334                 :          2 :       ERR("Canon sha1 of Assertion failed to verify ret=%d", ret);
     335                 :          2 :       return 11;
     336                 :            :     } else {
     337                 :          0 :       ERR("Assertion does not contain a signature %p", a7n->Signature);
     338                 :          0 :       return 7;
     339                 :            :     }
     340                 :            :   } else {
     341                 :          6 :     ret = zxid_sp_sso_finalize(cf, &cgi, &ses, a7n, pop_seen);
     342                 :          6 :     INFO("zxid_sp_sso_finalize() returned %d", ret);
     343                 :            :   }
     344   [ +  -  +  - ]:          6 :   if (ret && verbose)
     345                 :          6 :     printf("\nSIG Verified OK, zxid_sp_sso_finalize() returned %d\n", ret);
     346         [ +  - ]:          6 :   return ret?0:6;
     347                 :            : }
     348                 :            : 
     349                 :            : /* Called by:  zxdecode_main x4 */
     350                 :            : static int decode(char* msg, char* q)
     351                 :         23 : {
     352                 :            :   int len;
     353                 :            :   char* p;
     354                 :            :   char* m2;
     355                 :            :   char* p2;
     356                 :            :   
     357                 :         23 :   *q = 0;
     358   [ +  +  -  + ]:         23 :   D("Original Msg(%s) x=%x", msg, *msg);
     359                 :            :   
     360         [ +  + ]:         23 :   if (strchr(msg, '%')) {
     361                 :          4 :     p = p2 = msg;
     362   [ +  +  +  -  :          4 :     URL_DECODE(p, p2, q);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  -  +  
          #  #  #  #  +  
          -  +  -  +  -  
          -  +  -  +  +  
                      + ]
     363                 :          4 :     q = p;
     364                 :          4 :     *q = 0;
     365   [ -  +  #  # ]:          4 :     D("URL Decoded Msg(%s) x=%x", msg, *msg);
     366                 :            :   } else
     367                 :         19 :     p = q;
     368                 :            :   
     369   [ +  -  +  - ]:         23 :   switch (b64_flag) {
     370                 :            :   case 0:
     371   [ +  -  -  + ]:          1 :     D("decode_base64 skipped at user request %d",0);
     372                 :          1 :     break;
     373                 :            :   case 1:
     374   [ #  #  #  # ]:          0 :     D("decode_base64 foreced at user request %d",0);
     375                 :          6 : b64_dec:
     376                 :            :     /* msglen = q - msg; */
     377                 :          6 :     p = unbase64_raw(msg, q, msg, zx_std_index_64);  /* inplace */
     378                 :          6 :     *p = 0;
     379   [ -  +  #  # ]:          6 :     D("Unbase64 Msg(%s) x=%x (n.b. message data may be binary at this point)", msg, *msg);
     380                 :          6 :     break;
     381                 :            :   case 2:
     382         [ +  + ]:         22 :     if (*msg == '<') {
     383   [ -  +  #  # ]:         16 :       D("decode_base64 auto detect no decode due to initial < %p %p", msg, p);
     384                 :            :     } else {
     385   [ -  +  #  # ]:          6 :       D("decode_base64 auto detect decode due to initial 0x%x",*msg);
     386                 :          6 :       goto b64_dec;
     387                 :            :     }
     388                 :            :     break;
     389                 :            :   }
     390                 :            :   
     391   [ +  -  +  - ]:         23 :   switch (inflate_flag) {
     392                 :            :   case 0:
     393   [ +  -  -  + ]:          1 :     D("No decompression by user choice %d",0);
     394                 :          1 :     len = p-msg;
     395                 :          1 :     p = msg;
     396                 :          1 :     break;
     397                 :            :   case 1:
     398   [ #  #  #  # ]:          0 :     D("Decompressing... (force) %d",0);
     399                 :          0 : decompress:
     400                 :          0 :     p = zx_zlib_raw_inflate(0, p-msg, msg, &len);  /* Redir uses compressed payload. */
     401                 :          0 :     break;
     402                 :            :   case 2:
     403                 :            :     /* Skip whitespace in the beginning and end of the payload to help correct POST detection. */
     404         [ +  - ]:         22 :     for (m2 = msg; m2 < p; ++m2)
     405   [ +  -  +  -  :         22 :       if (!ONE_OF_4(*m2, ' ', '\t', '\015', '\012'))
             +  -  +  - ]
     406                 :         22 :         break;
     407         [ +  - ]:         24 :     for (p2 = p-1; m2 < p2; --p2)
     408   [ +  -  +  -  :         24 :       if (!ONE_OF_4(*p2, ' ', '\t', '\015', '\012'))
             +  -  +  + ]
     409                 :         22 :         break;
     410   [ -  +  #  # ]:         22 :     D("Msg_minus_whitespace(%.*s) start=%x end=%x", p2-m2+1, m2, *m2, *p2);
     411                 :            :     
     412   [ +  -  +  - ]:         44 :     if (*m2 == '<' && *p2 == '>') {  /* POST profiles do not compress the payload */
     413                 :         22 :       len = p2 - m2 + 1;
     414                 :         22 :       p = m2;
     415                 :            :     } else {
     416   [ #  #  #  # ]:          0 :       D("Decompressing... (auto) %d",0);
     417                 :          0 :       goto decompress;
     418                 :            :     }
     419                 :            :     break;
     420                 :            :   }
     421                 :         23 :   printf("%.*s", len, p);
     422                 :            :   
     423         [ +  + ]:         23 :   if (sig_flag)
     424                 :         22 :     return sig_validate(len, p);
     425                 :          1 :   return 0;
     426                 :            : }
     427                 :            : 
     428                 :            : #ifndef zxdecode_main
     429                 :            : #define zxdecode_main main
     430                 :            : #endif
     431                 :            : 
     432                 :            : /* Called by: */
     433                 :            : int zxdecode_main(int argc, char** argv, char** env)
     434                 :         27 : {
     435                 :            :   int got;
     436                 :            :   char* pp;
     437                 :            :   char* p;
     438                 :            :   char* q;
     439                 :            :   char* lim;
     440                 :            : 
     441                 :         27 :   strcpy(zx_instance, "\tzxdec");
     442                 :         27 :   opt(&argc, &argv, &env);
     443                 :            : 
     444                 :         26 :   read_all_fd(0, buf, sizeof(buf)-1, &got);
     445                 :         26 :   buf[got] = 0;
     446                 :         26 :   lim = buf+got;
     447                 :            : 
     448         [ +  + ]:         26 :   if (sha1_flag) {
     449                 :          1 :     p = sha1_safe_base64(buf, got, buf);
     450                 :          1 :     *p = 0;
     451                 :          1 :     printf("%s\n", buf);
     452                 :          1 :     return 0;
     453                 :            :   }
     454                 :            : 
     455                 :            :   /* Try to detect relevant input, iterating if -i N was specified.
     456                 :            :    * The detection is supposed to pick SAMLREquest or SAMLResponse from
     457                 :            :    * middle of HTML form, or from log output. Whatever is convenient. */
     458                 :            : 
     459   [ +  -  +  + ]:         26 :   for (pp = buf; pp && pp < lim; pp = p+1) {
     460                 :         24 :     p = strstr(pp, "SAMLRequest=");
     461         [ -  + ]:         24 :     if (p) {
     462         [ #  # ]:          0 :       if (--ix) continue;
     463                 :          0 :       q = strchr(p, '&');
     464         [ #  # ]:          0 :       return decode(p + sizeof("SAMLRequest=")-1, q?q:lim);
     465                 :            :     }
     466                 :         24 :     p = strstr(pp, "SAMLResponse=");
     467         [ +  + ]:         24 :     if (p) {
     468         [ +  - ]:          5 :       if (--ix) continue;
     469                 :          5 :       q = strchr(p, '&');
     470         [ +  + ]:          5 :       return decode(p + sizeof("SAMLResponse=")-1, q?q:lim);
     471                 :            :     }
     472         [ +  + ]:         19 :     if (*pp == '<') {  /* HTML for POST */
     473                 :         16 :       p = strstr(pp, "SAMLRequest");
     474         [ -  + ]:         16 :       if (p) {
     475                 :          0 :         p += sizeof("SAMLRequest")-1;
     476                 :            :       } else {
     477                 :         16 :         p = strstr(pp, "SAMLResponse");
     478         [ -  + ]:         16 :         if (p)
     479                 :          0 :           p += sizeof("SAMLResponse")-1;
     480                 :            :       }
     481         [ -  + ]:         16 :       if (p) {
     482                 :          0 :         p = strstr(p, "value=");
     483         [ #  # ]:          0 :         if (p) {
     484         [ #  # ]:          0 :           if (--ix)     continue;
     485                 :          0 :           p += sizeof("value=")-1;
     486         [ #  # ]:          0 :           if (*p == '"') {
     487                 :          0 :             ++p;
     488                 :          0 :             q = strchr(p, '"');
     489                 :            :           } else {
     490                 :          0 :             q = p+strcspn(p, "\" >");
     491                 :            :           }
     492         [ #  # ]:          0 :           return decode(p, q?q:lim);
     493                 :            :         }
     494                 :            :       }
     495                 :            :     }
     496         [ +  + ]:         19 :     if (--ix) { p = pp; continue; }
     497                 :         18 :     return decode(pp, lim);
     498                 :            :   }
     499                 :          2 :   ERR("Found no SAMLRequest or SAMLResponse to decode %d",2);
     500                 :          2 :   return 1;
     501                 :            : }
     502                 :            : 
     503                 :            : /* EOF  --  zxdecode.c */

Generated by: LCOV version 1.9