1 /* zxidcdc.c  -  Handwritten functions for Common Domain Cookie handling at SP
2  * Copyright (c) 2010-2011 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: zxidcdc.c,v 1.5 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  */
15 
16 #include <string.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include "platform.h"
20 #include "errmac.h"
21 #include "zxid.h"
22 #include "zxidpriv.h"
23 #include "zxidutil.h"
24 #include "zxidconf.h"
25 
26 /* ============== CDC ============== */
27 
28 /*() Read Common Domain Cookie and formulate HTTP redirection to pass it back.
29  *
30  * The SAML CDC is a standards based method for SSO IdP discovery. */
31 
32 /* Called by:  covimp_test, main x2, zxid_simple_no_ses_cf */
zxid_cdc_read(zxid_conf * cf,zxid_cgi * cgi)33 struct zx_str* zxid_cdc_read(zxid_conf* cf, zxid_cgi* cgi)
34 {
35   char* p;
36   char* cdc = 0;
37   char* cookie = getenv("HTTP_COOKIE");
38   char* host = getenv("HTTP_HOST");
39   if (cookie) {
40     D("CDC(%s) host(%s)", cookie, host);
41     cdc = strstr(cookie, "_saml_idp");
42     if (!cdc)
43       cdc = strstr(cookie, "_liberty_idp");
44     if (cdc) {
45       cdc = strchr(cdc, '=');
46       if (cdc) {
47 	D("cdc(%s)", cdc);
48 	if (cdc[1] == '"') {
49 	  cdc += 2;
50 	  p = strchr(cdc, '"');
51 	  if (p)
52 	    *p = 0;
53 	  else
54 	    cdc = 0;
55 	} else
56 	  ++cdc;
57       }
58     } else {
59       ERR("Malformed CDC(%s)", cookie);
60     }
61   } else {
62     D("No CDC _saml_idp in CGI environment host(%s)", STRNULLCHK(host));
63   }
64   D("Location: %s?o=E&c=%s\r\n\r\n", cf->burl, cdc?cdc:"(missing)");
65   /* *** should prepare AuthnReq and redirect directly to the IdP (if any). */
66   return zx_strf(cf->ctx, "Location: %s?o=E&c=%s\r\n\r\n", cf->burl, cdc?cdc:"");
67 }
68 
69 /*() Process second part of Common Domain Cookie redirection.
70  * See zxid_cdc_read() for first part.
71  *
72  * The SAML CDC is a standards based method for SSO IdP discovery. */
73 
74 /* Called by:  covimp_test, main x2, zxid_simple_no_ses_cf */
zxid_cdc_check(zxid_conf * cf,zxid_cgi * cgi)75 int zxid_cdc_check(zxid_conf* cf, zxid_cgi* cgi)
76 {
77   int len;
78   zxid_entity* ent;
79   char* p;
80   char* q;
81   char eid[ZXID_MAX_EID];
82 #if 0
83   char* idp_eid;
84   if (!cgi->cdc) return 0;
85   for (idp_eid = strtok(cgi->cdc, " "); idp_eid; idp_eid = strtok(0, " ")) {
86     if (!(ent = zxid_get_ent(cf, idp_eid)))
87       continue;
88     switch (cf->cdc_choice) {
89     case ZXID_CDC_CHOICE_ALWAYS_FIRST:  /* Do not offer UI, always pick first on CDC list. */
90       break;
91     case ZXID_CDC_CHOICE_ALWAYS_LAST:   /* Do not offer UI, always pick last on CDC list. */
92       /* *** How to detect "lastness" in strtok() list? */
93       break;
94     case ZXID_CDC_CHOICE_ALWAYS_ONLY:   /* If CDC has only one IdP, always pick it. */
95       /* *** How to detect "onlyness" in strtok() list? */
96       break;
97     case ZXID_CDC_CHOICE_UI_PREF:       /* Offer UI with the CDC designated IdPs first. */
98       /* *** */
99       break;
100     case ZXID_CDC_CHOICE_UI_NOPREF:     /* Offer UI. Do not give preference to CDC IdPs. */
101       /* *** */
102       break;
103     default: NEVER("Bad CDC choice(%d)\n", cf->cdc_choice);
104     }
105   }
106 #else
107 
108   for (q = cgi->cdc; q; q = p ? p+1 : 0) {
109     p = strchr(q, ' ');
110     len = p ? p-q : strlen(q);
111 
112     if (SIMPLE_BASE64_PESSIMISTIC_DECODE_LEN(len) > sizeof(eid)-1) {
113       ERR("EntityID len=%d larger than built in limit=%d. Base64 len=%d", SIMPLE_BASE64_PESSIMISTIC_DECODE_LEN(len), (int)sizeof(eid)-1, len);
114       continue;
115     }
116     q = unbase64_raw(q, q + len, eid, zx_std_index_64);
117     *q = 0;
118 
119     ent = zxid_get_ent(cf, eid);
120     if (!ent) {
121       ERR("eid(%s) not in CoT", eid);  /* *** Change this to offer login button anyway so new IdP can join CoT using WKL */
122       continue;
123     }
124     D("Adding entity(%s) to cgi->idp_list", eid);
125     ent->n_cdc = cgi->idp_list;
126     cgi->idp_list = ent;
127   }
128 #endif
129   return 0;
130 }
131 
132 /* EOF  --  zxidcdc.c */
133