1/* client.c --- SAML20 mechanism, client side.
2 * Copyright (C) 2010-2012 Simon Josefsson
3 *
4 * This file is part of GNU SASL Library.
5 *
6 * GNU SASL Library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * GNU SASL Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with GNU SASL Library; if not, write to the Free
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27/* Get specification. */
28#include "saml20.h"
29
30/* Get strdup, strlen. */
31#include <string.h>
32
33/* Get free. */
34#include <stdlib.h>
35
36/* Get bool. */
37#include <stdbool.h>
38
39/* Get _gsasl_gs2_generate_header. */
40#include "mechtools.h"
41
42struct saml20_client_state
43{
44 int step;
45};
46
47int
48_gsasl_saml20_client_start (Gsasl_session * sctx, void **mech_data)
49{
50 struct saml20_client_state *state;
51
52 state = (struct saml20_client_state *) calloc (sizeof (*state), 1);
53 if (state == NULL)
54 return GSASL_MALLOC_ERROR;
55
56 *mech_data = state;
57
58 return GSASL_OK;
59}
60
61int
62_gsasl_saml20_client_step (Gsasl_session * sctx,
63 void *mech_data,
64 const char *input, size_t input_len,
65 char **output, size_t * output_len)
66{
67 struct saml20_client_state *state = mech_data;
68 int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
69
70 switch (state->step)
71 {
72 case 0:
73 {
74 const char *authzid = gsasl_property_get (sctx, GSASL_AUTHZID);
75 const char *idp =
76 gsasl_property_get (sctx, GSASL_SAML20_IDP_IDENTIFIER);
77
78 if (!idp || !*idp)
79 return GSASL_NO_SAML20_IDP_IDENTIFIER;
80
81 res = _gsasl_gs2_generate_header (false, 'n', NULL, authzid,
82 strlen (idp), idp,
83 output, output_len);
84 if (res != GSASL_OK)
85 return res;
86
87 res = GSASL_NEEDS_MORE;
88 state->step++;
89 }
90 break;
91
92 case 1:
93 {
94 gsasl_property_set_raw (sctx, GSASL_SAML20_REDIRECT_URL,
95 input, input_len);
96
97 res = gsasl_callback (NULL, sctx,
98 GSASL_SAML20_AUTHENTICATE_IN_BROWSER);
99 if (res != GSASL_OK)
100 return res;
101
102 *output_len = 1;
103 *output = strdup ("=");
104 if (!*output)
105 return GSASL_MALLOC_ERROR;
106
107 res = GSASL_OK;
108 state->step++;
109 }
110 break;
111
112 default:
113 break;
114 }
115
116 return res;
117}
118
119void
120_gsasl_saml20_client_finish (Gsasl_session * sctx, void *mech_data)
121{
122 struct saml20_client_state *state = mech_data;
123
124 if (!state)
125 return;
126
127 free (state);
128}
129