|
gsasl
1.8.0
|
00001 /* client.c --- OPENID20 mechanism, client side. 00002 * Copyright (C) 2011-2012 Simon Josefsson 00003 * 00004 * This file is part of GNU SASL Library. 00005 * 00006 * GNU SASL Library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public License 00008 * as published by the Free Software Foundation; either version 2.1 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * GNU SASL Library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with GNU SASL Library; if not, write to the Free 00018 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 */ 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include "config.h" 00025 #endif 00026 00027 /* Get specification. */ 00028 #include "openid20.h" 00029 00030 /* Get strdup, strlen. */ 00031 #include <string.h> 00032 00033 /* Get calloc, free. */ 00034 #include <stdlib.h> 00035 00036 /* Get bool. */ 00037 #include <stdbool.h> 00038 00039 /* Get _gsasl_gs2_generate_header. */ 00040 #include "mechtools.h" 00041 00042 struct openid20_client_state 00043 { 00044 int step; 00045 }; 00046 00047 int 00048 _gsasl_openid20_client_start (Gsasl_session * sctx, void **mech_data) 00049 { 00050 struct openid20_client_state *state; 00051 00052 state = (struct openid20_client_state *) calloc (sizeof (*state), 1); 00053 if (state == NULL) 00054 return GSASL_MALLOC_ERROR; 00055 00056 *mech_data = state; 00057 00058 return GSASL_OK; 00059 } 00060 00061 int 00062 _gsasl_openid20_client_step (Gsasl_session * sctx, 00063 void *mech_data, 00064 const char *input, size_t input_len, 00065 char **output, size_t * output_len) 00066 { 00067 struct openid20_client_state *state = mech_data; 00068 int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; 00069 00070 switch (state->step) 00071 { 00072 case 0: 00073 { 00074 const char *authzid = gsasl_property_get (sctx, GSASL_AUTHZID); 00075 const char *authid = gsasl_property_get (sctx, GSASL_AUTHID); 00076 00077 if (!authid || !*authid) 00078 return GSASL_NO_AUTHID; 00079 00080 res = _gsasl_gs2_generate_header (false, 'n', NULL, authzid, 00081 strlen (authid), authid, 00082 output, output_len); 00083 if (res != GSASL_OK) 00084 return res; 00085 00086 res = GSASL_NEEDS_MORE; 00087 state->step++; 00088 } 00089 break; 00090 00091 case 1: 00092 { 00093 gsasl_property_set_raw (sctx, GSASL_OPENID20_REDIRECT_URL, 00094 input, input_len); 00095 00096 res = gsasl_callback (NULL, sctx, 00097 GSASL_OPENID20_AUTHENTICATE_IN_BROWSER); 00098 if (res != GSASL_OK) 00099 return res; 00100 00101 *output_len = 1; 00102 *output = strdup ("="); 00103 if (!*output) 00104 return GSASL_MALLOC_ERROR; 00105 00106 res = GSASL_OK; 00107 state->step++; 00108 } 00109 break; 00110 00111 /* This step is optional. The server could have approved 00112 authentication already. Alternatively, it wanted to send 00113 some SREGs or error data and we end up here. */ 00114 case 2: 00115 { 00116 gsasl_property_set_raw (sctx, GSASL_OPENID20_OUTCOME_DATA, 00117 input, input_len); 00118 00119 /* In the case of failures, the response MUST follow this 00120 syntax: 00121 00122 outcome_data = "openid.error" "=" sreg_val *( "," sregp_avp ) 00123 00124 [RFC4422] Section 3.6 explicitly prohibits additional information in 00125 an unsuccessful authentication outcome. Therefore, the openid.error 00126 and openid.error_code are to be sent as an additional challenge in 00127 the event of an unsuccessful outcome. In this case, as the protocol 00128 is lock step, the client will follow with an additional exchange 00129 containing "=", after which the server will respond with an 00130 application-level outcome. 00131 */ 00132 00133 #define ERR_PREFIX "openid.error=" 00134 if (input_len > strlen (ERR_PREFIX) 00135 && strncmp (ERR_PREFIX, input, strlen (ERR_PREFIX)) == 0) 00136 { 00137 *output_len = 1; 00138 *output = strdup ("="); 00139 if (!*output) 00140 return GSASL_MALLOC_ERROR; 00141 00142 res = GSASL_NEEDS_MORE; 00143 } 00144 else 00145 { 00146 *output_len = 0; 00147 *output = NULL; 00148 00149 res = GSASL_OK; 00150 } 00151 00152 state->step++; 00153 } 00154 break; 00155 00156 default: 00157 break; 00158 } 00159 00160 return res; 00161 } 00162 00163 void 00164 _gsasl_openid20_client_finish (Gsasl_session * sctx, void *mech_data) 00165 { 00166 struct openid20_client_state *state = mech_data; 00167 00168 if (!state) 00169 return; 00170 00171 free (state); 00172 }
1.7.6.1