00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 # include "config.h"
00025 #endif
00026
00027
00028 #include "gs2.h"
00029
00030
00031 #include <stdlib.h>
00032
00033
00034 #include <string.h>
00035
00036 #include "gss-extra.h"
00037 #include "gs2helper.h"
00038 #include "mechtools.h"
00039
00040 struct _Gsasl_gs2_server_state
00041 {
00042
00043 int step;
00044 gss_name_t client;
00045 gss_cred_id_t cred;
00046 gss_ctx_id_t context;
00047 gss_OID mech_oid;
00048 struct gss_channel_bindings_struct cb;
00049 };
00050 typedef struct _Gsasl_gs2_server_state _Gsasl_gs2_server_state;
00051
00052
00053
00054 static int
00055 gs2_get_cred (Gsasl_session * sctx, _Gsasl_gs2_server_state * state)
00056 {
00057 OM_uint32 maj_stat, min_stat;
00058 gss_buffer_desc bufdesc;
00059 const char *service = gsasl_property_get (sctx, GSASL_SERVICE);
00060 const char *hostname = gsasl_property_get (sctx, GSASL_HOSTNAME);
00061 gss_name_t server;
00062 gss_OID_set_desc oid_set;
00063 gss_OID_set actual_mechs;
00064 int present;
00065
00066 if (!service)
00067 return GSASL_NO_SERVICE;
00068 if (!hostname)
00069 return GSASL_NO_HOSTNAME;
00070
00071 bufdesc.length = asprintf ((char **) &bufdesc.value, "%s@%s",
00072 service, hostname);
00073 if (bufdesc.length <= 0 || bufdesc.value == NULL)
00074 return GSASL_MALLOC_ERROR;
00075
00076 maj_stat = gss_import_name (&min_stat, &bufdesc,
00077 GSS_C_NT_HOSTBASED_SERVICE, &server);
00078 free (bufdesc.value);
00079 if (GSS_ERROR (maj_stat))
00080 return GSASL_GSSAPI_IMPORT_NAME_ERROR;
00081
00082
00083
00084 oid_set.count = 1;
00085 oid_set.elements = state->mech_oid;
00086
00087 maj_stat = gss_acquire_cred (&min_stat, server, 0,
00088 &oid_set, GSS_C_ACCEPT,
00089 &state->cred, &actual_mechs, NULL);
00090 gss_release_name (&min_stat, &server);
00091 if (GSS_ERROR (maj_stat))
00092 return GSASL_GSSAPI_ACQUIRE_CRED_ERROR;
00093
00094
00095
00096
00097 maj_stat = gss_test_oid_set_member (&min_stat, state->mech_oid,
00098 actual_mechs, &present);
00099 if (GSS_ERROR (maj_stat))
00100 {
00101 gss_release_oid_set (&min_stat, &actual_mechs);
00102 return GSASL_GSSAPI_TEST_OID_SET_MEMBER_ERROR;
00103 }
00104
00105 maj_stat = gss_release_oid_set (&min_stat, &actual_mechs);
00106 if (GSS_ERROR (maj_stat))
00107 return GSASL_GSSAPI_RELEASE_OID_SET_ERROR;
00108
00109 if (!present)
00110 return GSASL_GSSAPI_ACQUIRE_CRED_ERROR;
00111
00112 return GSASL_OK;
00113 }
00114
00115
00116
00117 int
00118 _gsasl_gs2_server_start (Gsasl_session * sctx, void **mech_data)
00119 {
00120 _Gsasl_gs2_server_state *state;
00121 int res;
00122
00123 state = (_Gsasl_gs2_server_state *) malloc (sizeof (*state));
00124 if (state == NULL)
00125 return GSASL_MALLOC_ERROR;
00126
00127 res = gs2_get_oid (sctx, &state->mech_oid);
00128 if (res != GSASL_OK)
00129 {
00130 free (state);
00131 return res;
00132 }
00133
00134 res = gs2_get_cred (sctx, state);
00135 if (res != GSASL_OK)
00136 {
00137 free (state);
00138 return res;
00139 }
00140
00141 state->step = 0;
00142 state->context = GSS_C_NO_CONTEXT;
00143 state->client = NULL;
00144
00145
00146
00147
00148 state->cb.initiator_addrtype = 0;
00149 state->cb.initiator_address.length = 0;
00150 state->cb.initiator_address.value = NULL;
00151 state->cb.acceptor_addrtype = 0;
00152 state->cb.acceptor_address.length = 0;
00153 state->cb.acceptor_address.value = NULL;
00154 state->cb.application_data.length = 0;
00155 state->cb.application_data.value = NULL;
00156
00157 *mech_data = state;
00158
00159 return GSASL_OK;
00160 }
00161
00162
00163
00164
00165
00166 int
00167 _gsasl_gs2_server_step (Gsasl_session * sctx,
00168 void *mech_data,
00169 const char *input, size_t input_len,
00170 char **output, size_t * output_len)
00171 {
00172 _Gsasl_gs2_server_state *state = mech_data;
00173 gss_buffer_desc bufdesc1, bufdesc2;
00174 OM_uint32 maj_stat, min_stat;
00175 gss_buffer_desc client_name;
00176 gss_OID mech_type;
00177 int res;
00178 OM_uint32 ret_flags;
00179 int free_bufdesc1 = 0;
00180
00181 *output = NULL;
00182 *output_len = 0;
00183 bufdesc1.value = input;
00184 bufdesc1.length = input_len;
00185
00186 switch (state->step)
00187 {
00188 case 0:
00189 if (input_len == 0)
00190 {
00191 res = GSASL_NEEDS_MORE;
00192 break;
00193 }
00194 state->step++;
00195
00196
00197 case 1:
00198 {
00199 char *authzid;
00200 size_t headerlen;
00201
00202 res = _gsasl_parse_gs2_header (input, input_len,
00203 &authzid, &headerlen);
00204 if (res != GSASL_OK)
00205 return res;
00206
00207 if (authzid)
00208 {
00209 gsasl_property_set (sctx, GSASL_AUTHZID, authzid);
00210 free (authzid);
00211 }
00212
00213 state->cb.application_data.value = input;
00214 state->cb.application_data.length = headerlen;
00215
00216 bufdesc2.value = input + headerlen;
00217 bufdesc2.length = input_len - headerlen;
00218
00219 maj_stat = gss_encapsulate_token (&bufdesc2, state->mech_oid,
00220 &bufdesc1);
00221 if (GSS_ERROR (maj_stat))
00222 return GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR;
00223
00224 free_bufdesc1 = 1;
00225 }
00226 state->step++;
00227
00228
00229 case 2:
00230 if (state->client)
00231 {
00232 gss_release_name (&min_stat, &state->client);
00233 state->client = GSS_C_NO_NAME;
00234 }
00235
00236 maj_stat = gss_accept_sec_context (&min_stat,
00237 &state->context,
00238 state->cred,
00239 &bufdesc1,
00240 &state->cb,
00241 &state->client,
00242 &mech_type,
00243 &bufdesc2, &ret_flags, NULL, NULL);
00244 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
00245 return GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR;
00246
00247 if (maj_stat == GSS_S_COMPLETE)
00248 {
00249 state->step++;
00250
00251 if (!(ret_flags & GSS_C_MUTUAL_FLAG))
00252 return GSASL_MECHANISM_PARSE_ERROR;
00253
00254 maj_stat = gss_display_name (&min_stat, state->client,
00255 &client_name, &mech_type);
00256 if (GSS_ERROR (maj_stat))
00257 return GSASL_GSSAPI_DISPLAY_NAME_ERROR;
00258
00259 gsasl_property_set_raw (sctx, GSASL_GSSAPI_DISPLAY_NAME,
00260 client_name.value, client_name.length);
00261
00262 res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_GSSAPI);
00263 }
00264 else
00265 res = GSASL_NEEDS_MORE;
00266
00267 if (free_bufdesc1)
00268 {
00269 maj_stat = gss_release_buffer (&min_stat, &bufdesc1);
00270 if (GSS_ERROR (maj_stat))
00271 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00272 }
00273
00274 *output = malloc (bufdesc2.length);
00275 if (!*output)
00276 return GSASL_MALLOC_ERROR;
00277 memcpy (*output, bufdesc2.value, bufdesc2.length);
00278 *output_len = bufdesc2.length;
00279
00280 maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
00281 if (GSS_ERROR (maj_stat))
00282 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00283 break;
00284
00285 default:
00286 res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
00287 break;
00288 }
00289
00290 return res;
00291 }
00292
00293
00294
00295 void
00296 _gsasl_gs2_server_finish (Gsasl_session * sctx, void *mech_data)
00297 {
00298 _Gsasl_gs2_server_state *state = mech_data;
00299 OM_uint32 min_stat;
00300
00301 if (!state)
00302 return;
00303
00304 if (state->context != GSS_C_NO_CONTEXT)
00305 gss_delete_sec_context (&min_stat, &state->context, GSS_C_NO_BUFFER);
00306
00307 if (state->cred != GSS_C_NO_CREDENTIAL)
00308 gss_release_cred (&min_stat, &state->cred);
00309
00310 if (state->client != GSS_C_NO_NAME)
00311 gss_release_name (&min_stat, &state->client);
00312
00313 free (state);
00314 }