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 <stdlib.h>
00029
00030
00031 #include <string.h>
00032
00033
00034 #include "x-gssapi.h"
00035
00036 #ifdef HAVE_LIBGSS
00037 # include <gss.h>
00038 #elif HAVE_GSSAPI_H
00039 # include <gssapi.h>
00040 #elif HAVE_GSSAPI_GSSAPI_H
00041 # include <gssapi/gssapi.h>
00042 #endif
00043
00044 #include "gss-extra.h"
00045
00046 struct _Gsasl_gssapi_server_state
00047 {
00048 int step;
00049 gss_name_t client;
00050 gss_cred_id_t cred;
00051 gss_ctx_id_t context;
00052 };
00053 typedef struct _Gsasl_gssapi_server_state _Gsasl_gssapi_server_state;
00054
00055 int
00056 _gsasl_gssapi_server_start (Gsasl_session * sctx, void **mech_data)
00057 {
00058 _Gsasl_gssapi_server_state *state;
00059 OM_uint32 maj_stat, min_stat;
00060 gss_name_t server;
00061 gss_buffer_desc bufdesc;
00062 const char *service;
00063 const char *hostname;
00064
00065 service = gsasl_property_get (sctx, GSASL_SERVICE);
00066 if (!service)
00067 return GSASL_NO_SERVICE;
00068
00069 hostname = gsasl_property_get (sctx, GSASL_HOSTNAME);
00070 if (!hostname)
00071 return GSASL_NO_HOSTNAME;
00072
00073
00074
00075 bufdesc.length = strlen (service) + strlen ("@") + strlen (hostname) + 1;
00076 bufdesc.value = malloc (bufdesc.length);
00077 if (bufdesc.value == NULL)
00078 return GSASL_MALLOC_ERROR;
00079
00080 sprintf (bufdesc.value, "%s@%s", service, hostname);
00081
00082 state = (_Gsasl_gssapi_server_state *) malloc (sizeof (*state));
00083 if (state == NULL)
00084 {
00085 free (bufdesc.value);
00086 return GSASL_MALLOC_ERROR;
00087 }
00088
00089 maj_stat = gss_import_name (&min_stat, &bufdesc, GSS_C_NT_HOSTBASED_SERVICE,
00090 &server);
00091 free (bufdesc.value);
00092 if (GSS_ERROR (maj_stat))
00093 {
00094 free (state);
00095 return GSASL_GSSAPI_IMPORT_NAME_ERROR;
00096 }
00097
00098 maj_stat = gss_acquire_cred (&min_stat, server, 0,
00099 GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
00100 &state->cred, NULL, NULL);
00101 gss_release_name (&min_stat, &server);
00102
00103 if (GSS_ERROR (maj_stat))
00104 {
00105 free (state);
00106 return GSASL_GSSAPI_ACQUIRE_CRED_ERROR;
00107 }
00108
00109 state->step = 0;
00110 state->context = GSS_C_NO_CONTEXT;
00111 state->client = NULL;
00112 *mech_data = state;
00113
00114 return GSASL_OK;
00115 }
00116
00117 int
00118 _gsasl_gssapi_server_step (Gsasl_session * sctx,
00119 void *mech_data,
00120 const char *input, size_t input_len,
00121 char **output, size_t * output_len)
00122 {
00123 _Gsasl_gssapi_server_state *state = mech_data;
00124 gss_buffer_desc bufdesc1, bufdesc2;
00125 OM_uint32 maj_stat, min_stat;
00126 gss_buffer_desc client_name;
00127 gss_OID mech_type;
00128 char tmp[4];
00129 int res;
00130
00131 *output = NULL;
00132 *output_len = 0;
00133
00134 switch (state->step)
00135 {
00136 case 0:
00137 if (input_len == 0)
00138 {
00139 res = GSASL_NEEDS_MORE;
00140 break;
00141 }
00142 state->step++;
00143
00144
00145 case 1:
00146 bufdesc1.value = (void *) input;
00147 bufdesc1.length = input_len;
00148 if (state->client)
00149 {
00150 gss_release_name (&min_stat, &state->client);
00151 state->client = GSS_C_NO_NAME;
00152 }
00153
00154 maj_stat = gss_accept_sec_context (&min_stat,
00155 &state->context,
00156 state->cred,
00157 &bufdesc1,
00158 GSS_C_NO_CHANNEL_BINDINGS,
00159 &state->client,
00160 &mech_type,
00161 &bufdesc2, NULL, NULL, NULL);
00162 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
00163 return GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR;
00164
00165 *output = malloc (bufdesc2.length);
00166 if (!*output)
00167 return GSASL_MALLOC_ERROR;
00168 memcpy (*output, bufdesc2.value, bufdesc2.length);
00169 *output_len = bufdesc2.length;
00170
00171 maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
00172 if (GSS_ERROR (maj_stat))
00173 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00174
00175 if (maj_stat == GSS_S_COMPLETE)
00176 state->step++;
00177
00178 res = GSASL_NEEDS_MORE;
00179 break;
00180
00181 case 2:
00182 memset (tmp, 0xFF, 4);
00183 tmp[0] = GSASL_QOP_AUTH;
00184 bufdesc1.length = 4;
00185 bufdesc1.value = tmp;
00186 maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT,
00187 &bufdesc1, NULL, &bufdesc2);
00188 if (GSS_ERROR (maj_stat))
00189 return GSASL_GSSAPI_WRAP_ERROR;
00190
00191 *output = malloc (bufdesc2.length);
00192 if (!*output)
00193 return GSASL_MALLOC_ERROR;
00194 memcpy (*output, bufdesc2.value, bufdesc2.length);
00195 *output_len = bufdesc2.length;
00196
00197 maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
00198 if (GSS_ERROR (maj_stat))
00199 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00200
00201 state->step++;
00202 res = GSASL_NEEDS_MORE;
00203 break;
00204
00205 case 3:
00206 bufdesc1.value = (void *) input;
00207 bufdesc1.length = input_len;
00208 maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc1,
00209 &bufdesc2, NULL, NULL);
00210 if (GSS_ERROR (maj_stat))
00211 return GSASL_GSSAPI_UNWRAP_ERROR;
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 if ((((char *) bufdesc2.value)[0] & GSASL_QOP_AUTH) == 0)
00229 {
00230
00231 maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
00232 return GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR;
00233 }
00234
00235 gsasl_property_set_raw (sctx, GSASL_AUTHZID,
00236 (char *) bufdesc2.value + 4,
00237 bufdesc2.length - 4);
00238
00239 maj_stat = gss_display_name (&min_stat, state->client,
00240 &client_name, &mech_type);
00241 if (GSS_ERROR (maj_stat))
00242 return GSASL_GSSAPI_DISPLAY_NAME_ERROR;
00243
00244 gsasl_property_set_raw (sctx, GSASL_GSSAPI_DISPLAY_NAME,
00245 client_name.value, client_name.length);
00246
00247 maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
00248 if (GSS_ERROR (maj_stat))
00249 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;
00250
00251 res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_GSSAPI);
00252
00253 state->step++;
00254 break;
00255
00256 default:
00257 res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
00258 break;
00259 }
00260
00261 return res;
00262 }
00263
00264 void
00265 _gsasl_gssapi_server_finish (Gsasl_session * sctx, void *mech_data)
00266 {
00267 _Gsasl_gssapi_server_state *state = mech_data;
00268 OM_uint32 min_stat;
00269
00270 if (!state)
00271 return;
00272
00273 if (state->context != GSS_C_NO_CONTEXT)
00274 gss_delete_sec_context (&min_stat, &state->context, GSS_C_NO_BUFFER);
00275
00276 if (state->cred != GSS_C_NO_CREDENTIAL)
00277 gss_release_cred (&min_stat, &state->cred);
00278
00279 if (state->client != GSS_C_NO_NAME)
00280 gss_release_name (&min_stat, &state->client);
00281
00282 free (state);
00283 }