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 #ifdef HAVE_LIBGSS
00037 # include <gss.h>
00038 #elif HAVE_GSSAPI_H
00039 # include <gssapi.h>
00040 #else
00041 # ifdef HAVE_GSSAPI_GSSAPI_H
00042 # include <gssapi/gssapi.h>
00043 # endif
00044 # ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
00045 # include <gssapi/gssapi_generic.h>
00046 # endif
00047 #endif
00048
00049 #include "gs2parser.h"
00050
00051 struct _gsasl_gs2_client_state
00052 {
00053 int step;
00054 gss_name_t service;
00055 gss_ctx_id_t context;
00056 gss_qop_t qop;
00057 };
00058 typedef struct _gsasl_gs2_client_state _gsasl_gs2_client_state;
00059
00060 int
00061 _gsasl_gs2_client_start (Gsasl_session * sctx, void **mech_data)
00062 {
00063 _gsasl_gs2_client_state *state;
00064
00065 state = (_gsasl_gs2_client_state *) malloc (sizeof (*state));
00066 if (state == NULL)
00067 return GSASL_MALLOC_ERROR;
00068
00069 state->context = GSS_C_NO_CONTEXT;
00070 state->service = GSS_C_NO_NAME;
00071 state->step = 0;
00072 state->qop = GSASL_QOP_AUTH;
00073
00074 *mech_data = state;
00075
00076 return GSASL_OK;
00077 }
00078
00079 int
00080 _gsasl_gs2_client_step (Gsasl_session * sctx,
00081 void *mech_data,
00082 const char *input, size_t input_len,
00083 char **output, size_t * output_len)
00084 {
00085 _gsasl_gs2_client_state *state = mech_data;
00086 char clientwrap[4];
00087 gss_qop_t serverqop;
00088 gss_buffer_desc bufdesc, bufdesc2;
00089 gss_buffer_t buf = GSS_C_NO_BUFFER;
00090 OM_uint32 maj_stat, min_stat;
00091 int conf_state;
00092 int res;
00093 const char *p;
00094 OM_uint32 ret_flags;
00095 struct gs2_token tok = { NULL, 0, NULL, 0 };
00096
00097 if (state->service == NULL)
00098 {
00099 const char *service, *hostname;
00100
00101 service = gsasl_property_get (sctx, GSASL_SERVICE);
00102 if (!service)
00103 return GSASL_NO_SERVICE;
00104
00105 hostname = gsasl_property_get (sctx, GSASL_HOSTNAME);
00106 if (!hostname)
00107 return GSASL_NO_HOSTNAME;
00108
00109
00110
00111 bufdesc.length = strlen (service) + 1 + strlen (hostname) + 1;
00112 bufdesc.value = malloc (bufdesc.length);
00113 if (bufdesc.value == NULL)
00114 return GSASL_MALLOC_ERROR;
00115
00116 sprintf (bufdesc.value, "%s@%s", service, hostname);
00117
00118 maj_stat = gss_import_name (&min_stat, &bufdesc,
00119 GSS_C_NT_HOSTBASED_SERVICE,
00120 &state->service);
00121 free (bufdesc.value);
00122 if (GSS_ERROR (maj_stat))
00123 return GSASL_GSSAPI_IMPORT_NAME_ERROR;
00124 }
00125
00126 switch (state->step)
00127 {
00128 case 1:
00129 res = gs2_parser (input, input_len, &tok);
00130 if (res < 0)
00131 return GSASL_MECHANISM_PARSE_ERROR;
00132
00133 bufdesc.length = tok.context_length;
00134 bufdesc.value = (void *) tok.context_token;
00135 buf = &bufdesc;
00136
00137
00138 case 0:
00139 bufdesc2.length = 0;
00140 bufdesc2.value = NULL;
00141 maj_stat = gss_init_sec_context (&min_stat,
00142 GSS_C_NO_CREDENTIAL,
00143 &state->context,
00144 state->service,
00145 GSS_C_NO_OID,
00146 GSS_C_MUTUAL_FLAG |
00147 GSS_C_REPLAY_FLAG |
00148 GSS_C_SEQUENCE_FLAG |
00149 GSS_C_INTEG_FLAG |
00150 GSS_C_CONF_FLAG,
00151 0,
00152 GSS_C_NO_CHANNEL_BINDINGS,
00153 buf, NULL, &bufdesc2,
00154 &ret_flags, NULL);
00155 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
00156 return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
00157
00158 if ((ret_flags & GSS_C_PROT_READY_FLAG) || (maj_stat == GSS_S_COMPLETE))
00159 {
00160 puts ("prot_ready");
00161
00162
00163 }
00164 else if (tok.wrap_length > 0)
00165 {
00166
00167
00168 return GSASL_MECHANISM_PARSE_ERROR;
00169 }
00170
00171 res = gs2_encode (bufdesc2.value, bufdesc2.length,
00172 NULL, 0, output, output_len);
00173 if (res < 0)
00174 return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
00175
00176 if (maj_stat == GSS_S_COMPLETE)
00177 state->step = 2;
00178 else
00179 state->step = 1;
00180
00181 maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
00182 if (GSS_ERROR (maj_stat))
00183 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00184
00185 res = GSASL_NEEDS_MORE;
00186 break;
00187
00188 case 2:
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 bufdesc.length = input_len;
00205 bufdesc.value = (void *) input;
00206 maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc,
00207 &bufdesc2, &conf_state, &serverqop);
00208 if (GSS_ERROR (maj_stat))
00209 return GSASL_GSSAPI_UNWRAP_ERROR;
00210
00211 if (bufdesc2.length != 4)
00212 return GSASL_MECHANISM_PARSE_ERROR;
00213
00214 memcpy (clientwrap, bufdesc2.value, 4);
00215
00216 maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
00217 if (GSS_ERROR (maj_stat))
00218 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00219
00220 #if 0
00221
00222 if (cb_qop)
00223 state->qop = cb_qop (sctx, serverqop);
00224
00225 if ((state->qop & serverqop) == 0)
00226
00227 return GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR;
00228 #endif
00229
00230
00231
00232 p = gsasl_property_get (sctx, GSASL_AUTHID);
00233 if (!p)
00234 return GSASL_NO_AUTHID;
00235
00236 bufdesc.length = 4 + strlen (p);
00237 bufdesc.value = malloc (bufdesc.length);
00238 if (!bufdesc.value)
00239 return GSASL_MALLOC_ERROR;
00240
00241 {
00242 char *q = bufdesc.value;
00243 q[0] = state->qop;
00244 memcpy (q + 1, clientwrap + 1, 3);
00245 memcpy (q + 4, p, strlen (p));
00246 }
00247
00248 maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT,
00249 &bufdesc, &conf_state, &bufdesc2);
00250 free (bufdesc.value);
00251 if (GSS_ERROR (maj_stat))
00252 return GSASL_GSSAPI_WRAP_ERROR;
00253
00254 *output_len = bufdesc2.length;
00255 *output = malloc (bufdesc2.length);
00256 if (!*output)
00257 return GSASL_MALLOC_ERROR;
00258
00259 memcpy (*output, bufdesc2.value, bufdesc2.length);
00260
00261 maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
00262 if (GSS_ERROR (maj_stat))
00263 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00264
00265 state->step++;
00266 res = GSASL_OK;
00267 break;
00268
00269 default:
00270 res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
00271 break;
00272 }
00273
00274 return res;
00275 }
00276
00277 void
00278 _gsasl_gs2_client_finish (Gsasl_session * sctx, void *mech_data)
00279 {
00280 _gsasl_gs2_client_state *state = mech_data;
00281 OM_uint32 maj_stat, min_stat;
00282
00283 if (!state)
00284 return;
00285
00286 if (state->service != GSS_C_NO_NAME)
00287 maj_stat = gss_release_name (&min_stat, &state->service);
00288 if (state->context != GSS_C_NO_CONTEXT)
00289 maj_stat = gss_delete_sec_context (&min_stat, &state->context,
00290 GSS_C_NO_BUFFER);
00291
00292 free (state);
00293 }
00294
00295 int
00296 _gsasl_gs2_client_encode (Gsasl_session * sctx,
00297 void *mech_data,
00298 const char *input, size_t input_len,
00299 char **output, size_t * output_len)
00300 {
00301 _gsasl_gs2_client_state *state = mech_data;
00302 OM_uint32 min_stat, maj_stat;
00303 gss_buffer_desc foo;
00304 gss_buffer_t input_message_buffer = &foo;
00305 gss_buffer_desc output_message_buffer;
00306
00307 foo.length = input_len;
00308 foo.value = (void *) input;
00309
00310 if (state && state->step == 3 &&
00311 state->qop & (GSASL_QOP_AUTH_INT | GSASL_QOP_AUTH_CONF))
00312 {
00313 maj_stat = gss_wrap (&min_stat,
00314 state->context,
00315 state->qop & GSASL_QOP_AUTH_CONF ? 1 : 0,
00316 GSS_C_QOP_DEFAULT,
00317 input_message_buffer,
00318 NULL, &output_message_buffer);
00319 if (GSS_ERROR (maj_stat))
00320 return GSASL_GSSAPI_WRAP_ERROR;
00321 *output_len = output_message_buffer.length;
00322 *output = malloc (input_len);
00323 if (!*output)
00324 {
00325 maj_stat = gss_release_buffer (&min_stat, &output_message_buffer);
00326 return GSASL_MALLOC_ERROR;
00327 }
00328 memcpy (*output, output_message_buffer.value,
00329 output_message_buffer.length);
00330
00331 maj_stat = gss_release_buffer (&min_stat, &output_message_buffer);
00332 if (GSS_ERROR (maj_stat))
00333 {
00334 free (*output);
00335 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00336 }
00337 }
00338 else
00339 {
00340 *output_len = input_len;
00341 *output = malloc (input_len);
00342 if (!*output)
00343 return GSASL_MALLOC_ERROR;
00344 memcpy (*output, input, input_len);
00345 }
00346
00347 return GSASL_OK;
00348 }
00349
00350 int
00351 _gsasl_gs2_client_decode (Gsasl_session * sctx,
00352 void *mech_data,
00353 const char *input, size_t input_len,
00354 char **output, size_t * output_len)
00355 {
00356 _gsasl_gs2_client_state *state = mech_data;
00357 OM_uint32 min_stat, maj_stat;
00358 gss_buffer_desc foo;
00359 gss_buffer_t input_message_buffer = &foo;
00360 gss_buffer_desc output_message_buffer;
00361
00362 foo.length = input_len;
00363 foo.value = (void *) input;
00364
00365 if (state && state->step == 3 &&
00366 state->qop & (GSASL_QOP_AUTH_INT | GSASL_QOP_AUTH_CONF))
00367 {
00368 maj_stat = gss_unwrap (&min_stat,
00369 state->context,
00370 input_message_buffer,
00371 &output_message_buffer, NULL, NULL);
00372 if (GSS_ERROR (maj_stat))
00373 return GSASL_GSSAPI_UNWRAP_ERROR;
00374 *output_len = output_message_buffer.length;
00375 *output = malloc (input_len);
00376 if (!*output)
00377 {
00378 maj_stat = gss_release_buffer (&min_stat, &output_message_buffer);
00379 return GSASL_MALLOC_ERROR;
00380 }
00381 memcpy (*output, output_message_buffer.value,
00382 output_message_buffer.length);
00383
00384 maj_stat = gss_release_buffer (&min_stat, &output_message_buffer);
00385 if (GSS_ERROR (maj_stat))
00386 {
00387 free (*output);
00388 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00389 }
00390 }
00391 else
00392 {
00393 *output_len = input_len;
00394 *output = malloc (input_len);
00395 if (!*output)
00396 return GSASL_MALLOC_ERROR;
00397 memcpy (*output, input, input_len);
00398 }
00399
00400 return GSASL_OK;
00401 }