|
gsasl
1.8.0
|
00001 /* server.c --- OPENID20 mechanism, server 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 _gsasl_parse_gs2_header. */ 00037 #include "mechtools.h" 00038 00039 struct openid20_server_state 00040 { 00041 int step; 00042 int allow_error_step; 00043 }; 00044 00045 int 00046 _gsasl_openid20_server_start (Gsasl_session * sctx, void **mech_data) 00047 { 00048 struct openid20_server_state *state; 00049 00050 state = (struct openid20_server_state *) calloc (sizeof (*state), 1); 00051 if (state == NULL) 00052 return GSASL_MALLOC_ERROR; 00053 00054 *mech_data = state; 00055 00056 return GSASL_OK; 00057 } 00058 00059 int 00060 _gsasl_openid20_server_step (Gsasl_session * sctx, 00061 void *mech_data, 00062 const char *input, size_t input_len, 00063 char **output, size_t * output_len) 00064 { 00065 struct openid20_server_state *state = mech_data; 00066 int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; 00067 00068 *output_len = 0; 00069 *output = NULL; 00070 00071 switch (state->step) 00072 { 00073 case 0: 00074 { 00075 const char *p; 00076 char *authzid; 00077 size_t headerlen; 00078 00079 if (input_len == 0) 00080 return GSASL_NEEDS_MORE; 00081 00082 res = _gsasl_parse_gs2_header (input, input_len, 00083 &authzid, &headerlen); 00084 if (res != GSASL_OK) 00085 return res; 00086 00087 if (authzid) 00088 { 00089 gsasl_property_set (sctx, GSASL_AUTHZID, authzid); 00090 free (authzid); 00091 } 00092 00093 input += headerlen; 00094 input_len -= headerlen; 00095 00096 gsasl_property_set_raw (sctx, GSASL_AUTHID, input, input_len); 00097 00098 p = gsasl_property_get (sctx, GSASL_OPENID20_REDIRECT_URL); 00099 if (!p || !*p) 00100 return GSASL_NO_OPENID20_REDIRECT_URL; 00101 00102 *output_len = strlen (p); 00103 *output = malloc (*output_len); 00104 if (!*output) 00105 return GSASL_MALLOC_ERROR; 00106 00107 memcpy (*output, p, *output_len); 00108 00109 res = GSASL_NEEDS_MORE; 00110 state->step++; 00111 break; 00112 } 00113 00114 case 1: 00115 { 00116 const char *outcome_data; 00117 00118 if (!(input_len == 1 && *input == '=')) 00119 return GSASL_MECHANISM_PARSE_ERROR; 00120 00121 res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_OPENID20); 00122 if (res != GSASL_OK) 00123 { 00124 *output = strdup ("openid.error=fail"); 00125 if (!*output) 00126 return GSASL_MALLOC_ERROR; 00127 *output_len = strlen (*output); 00128 00129 /* [RFC4422] Section 3.6 explicitly prohibits additional 00130 information in an unsuccessful authentication outcome. 00131 Therefore, the openid.error and openid.error_code are 00132 to be sent as an additional challenge in the event of 00133 an unsuccessful outcome. In this case, as the protocol 00134 is lock step, the client will follow with an additional 00135 exchange containing "=", after which the server will 00136 respond with an application-level outcome. */ 00137 00138 state->allow_error_step = 1; 00139 state->step++; 00140 return GSASL_NEEDS_MORE; 00141 } 00142 00143 outcome_data = gsasl_property_get (sctx, GSASL_OPENID20_OUTCOME_DATA); 00144 if (outcome_data) 00145 { 00146 *output = strdup (outcome_data); 00147 if (!*output) 00148 return GSASL_MALLOC_ERROR; 00149 *output_len = strlen (*output); 00150 } 00151 else 00152 { 00153 *output = NULL; 00154 *output_len = 0; 00155 } 00156 00157 res = GSASL_OK; 00158 state->step++; 00159 } 00160 break; 00161 00162 case 2: 00163 { 00164 /* We only get here when the previous step signalled an error 00165 to the client. */ 00166 00167 if (!state->allow_error_step) 00168 return GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; 00169 00170 if (!(input_len == 1 && *input == '=')) 00171 return GSASL_MECHANISM_PARSE_ERROR; 00172 00173 res = GSASL_AUTHENTICATION_ERROR; 00174 state->step++; 00175 } 00176 break; 00177 00178 default: 00179 break; 00180 } 00181 00182 return res; 00183 } 00184 00185 void 00186 _gsasl_openid20_server_finish (Gsasl_session * sctx, void *mech_data) 00187 { 00188 struct openid20_server_state *state = mech_data; 00189 00190 if (!state) 00191 return; 00192 00193 free (state); 00194 }
1.7.6.1