|
gsasl
1.8.0
|
00001 /* client.c --- SASL mechanism GSSAPI as defined in RFC 4752, client side. 00002 * Copyright (C) 2002-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 malloc, free. */ 00028 #include <stdlib.h> 00029 00030 /* Get memcpy, strlen. */ 00031 #include <string.h> 00032 00033 /* Get specification. */ 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_client_state 00047 { 00048 int step; 00049 gss_name_t service; 00050 gss_ctx_id_t context; 00051 gss_qop_t qop; 00052 }; 00053 typedef struct _Gsasl_gssapi_client_state _Gsasl_gssapi_client_state; 00054 00055 int 00056 _gsasl_gssapi_client_start (Gsasl_session * sctx, void **mech_data) 00057 { 00058 _Gsasl_gssapi_client_state *state; 00059 00060 state = (_Gsasl_gssapi_client_state *) malloc (sizeof (*state)); 00061 if (state == NULL) 00062 return GSASL_MALLOC_ERROR; 00063 00064 state->context = GSS_C_NO_CONTEXT; 00065 state->service = GSS_C_NO_NAME; 00066 state->step = 0; 00067 state->qop = GSASL_QOP_AUTH; /* FIXME: Should be GSASL_QOP_AUTH_CONF. */ 00068 00069 *mech_data = state; 00070 00071 return GSASL_OK; 00072 } 00073 00074 int 00075 _gsasl_gssapi_client_step (Gsasl_session * sctx, 00076 void *mech_data, 00077 const char *input, size_t input_len, 00078 char **output, size_t * output_len) 00079 { 00080 _Gsasl_gssapi_client_state *state = mech_data; 00081 char clientwrap[4]; 00082 gss_qop_t serverqop; 00083 gss_buffer_desc bufdesc, bufdesc2; 00084 gss_buffer_t buf = GSS_C_NO_BUFFER; 00085 OM_uint32 maj_stat, min_stat; 00086 int conf_state; 00087 int res; 00088 const char *p; 00089 00090 if (state->service == NULL) 00091 { 00092 const char *service, *hostname; 00093 00094 service = gsasl_property_get (sctx, GSASL_SERVICE); 00095 if (!service) 00096 return GSASL_NO_SERVICE; 00097 00098 hostname = gsasl_property_get (sctx, GSASL_HOSTNAME); 00099 if (!hostname) 00100 return GSASL_NO_HOSTNAME; 00101 00102 /* FIXME: Use asprintf. */ 00103 00104 bufdesc.length = strlen (service) + 1 + strlen (hostname) + 1; 00105 bufdesc.value = malloc (bufdesc.length); 00106 if (bufdesc.value == NULL) 00107 return GSASL_MALLOC_ERROR; 00108 00109 sprintf (bufdesc.value, "%s@%s", service, hostname); 00110 00111 maj_stat = gss_import_name (&min_stat, &bufdesc, 00112 GSS_C_NT_HOSTBASED_SERVICE, 00113 &state->service); 00114 free (bufdesc.value); 00115 if (GSS_ERROR (maj_stat)) 00116 return GSASL_GSSAPI_IMPORT_NAME_ERROR; 00117 } 00118 00119 switch (state->step) 00120 { 00121 case 1: 00122 bufdesc.length = input_len; 00123 bufdesc.value = (void *) input; 00124 buf = &bufdesc; 00125 /* fall through */ 00126 00127 case 0: 00128 bufdesc2.length = 0; 00129 bufdesc2.value = NULL; 00130 maj_stat = gss_init_sec_context (&min_stat, 00131 GSS_C_NO_CREDENTIAL, 00132 &state->context, 00133 state->service, 00134 GSS_C_NO_OID, 00135 GSS_C_MUTUAL_FLAG | 00136 GSS_C_REPLAY_FLAG | 00137 GSS_C_SEQUENCE_FLAG | 00138 GSS_C_INTEG_FLAG | 00139 GSS_C_CONF_FLAG, 00140 0, 00141 GSS_C_NO_CHANNEL_BINDINGS, 00142 buf, NULL, &bufdesc2, NULL, NULL); 00143 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) 00144 return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR; 00145 00146 *output_len = bufdesc2.length; 00147 *output = malloc (*output_len); 00148 if (!*output) 00149 return GSASL_MALLOC_ERROR; 00150 memcpy (*output, bufdesc2.value, bufdesc2.length); 00151 00152 if (maj_stat == GSS_S_COMPLETE) 00153 state->step = 2; 00154 else 00155 state->step = 1; 00156 00157 maj_stat = gss_release_buffer (&min_stat, &bufdesc2); 00158 if (maj_stat != GSS_S_COMPLETE) 00159 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; 00160 00161 res = GSASL_NEEDS_MORE; 00162 break; 00163 00164 case 2: 00165 /* [RFC 2222 section 7.2.1]: 00166 The client passes this token to GSS_Unwrap and interprets the 00167 first octet of resulting cleartext as a bit-mask specifying 00168 the security layers supported by the server and the second 00169 through fourth octets as the maximum size output_message to 00170 send to the server. The client then constructs data, with 00171 the first octet containing the bit-mask specifying the 00172 selected security layer, the second through fourth octets 00173 containing in network byte order the maximum size 00174 output_message the client is able to receive, and the 00175 remaining octets containing the authorization identity. The 00176 client passes the data to GSS_Wrap with conf_flag set to 00177 FALSE, and responds with the generated output_message. The 00178 client can then consider the server authenticated. */ 00179 00180 bufdesc.length = input_len; 00181 bufdesc.value = (void *) input; 00182 maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc, 00183 &bufdesc2, &conf_state, &serverqop); 00184 if (GSS_ERROR (maj_stat)) 00185 return GSASL_GSSAPI_UNWRAP_ERROR; 00186 00187 if (bufdesc2.length != 4) 00188 return GSASL_MECHANISM_PARSE_ERROR; 00189 00190 memcpy (clientwrap, bufdesc2.value, 4); 00191 00192 maj_stat = gss_release_buffer (&min_stat, &bufdesc2); 00193 if (GSS_ERROR (maj_stat)) 00194 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; 00195 00196 #if 0 00197 /* FIXME: Fix qop. */ 00198 if (cb_qop) 00199 state->qop = cb_qop (sctx, serverqop); 00200 00201 if ((state->qop & serverqop) == 0) 00202 /* Server does not support what user wanted. */ 00203 return GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR; 00204 #endif 00205 00206 /* FIXME: Fix maxbuf. */ 00207 00208 p = gsasl_property_get (sctx, GSASL_AUTHID); 00209 if (!p) 00210 return GSASL_NO_AUTHID; 00211 00212 bufdesc.length = 4 + strlen (p); 00213 bufdesc.value = malloc (bufdesc.length); 00214 if (!bufdesc.value) 00215 return GSASL_MALLOC_ERROR; 00216 00217 { 00218 char *q = bufdesc.value; 00219 q[0] = state->qop; 00220 memcpy (q + 1, clientwrap + 1, 3); 00221 memcpy (q + 4, p, strlen (p)); 00222 } 00223 00224 maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT, 00225 &bufdesc, &conf_state, &bufdesc2); 00226 free (bufdesc.value); 00227 if (GSS_ERROR (maj_stat)) 00228 return GSASL_GSSAPI_WRAP_ERROR; 00229 00230 *output_len = bufdesc2.length; 00231 *output = malloc (bufdesc2.length); 00232 if (!*output) 00233 return GSASL_MALLOC_ERROR; 00234 00235 memcpy (*output, bufdesc2.value, bufdesc2.length); 00236 00237 maj_stat = gss_release_buffer (&min_stat, &bufdesc2); 00238 if (GSS_ERROR (maj_stat)) 00239 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; 00240 00241 state->step++; 00242 res = GSASL_OK; 00243 break; 00244 00245 default: 00246 res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; 00247 break; 00248 } 00249 00250 return res; 00251 } 00252 00253 void 00254 _gsasl_gssapi_client_finish (Gsasl_session * sctx, void *mech_data) 00255 { 00256 _Gsasl_gssapi_client_state *state = mech_data; 00257 OM_uint32 maj_stat, min_stat; 00258 00259 if (!state) 00260 return; 00261 00262 if (state->service != GSS_C_NO_NAME) 00263 maj_stat = gss_release_name (&min_stat, &state->service); 00264 if (state->context != GSS_C_NO_CONTEXT) 00265 maj_stat = gss_delete_sec_context (&min_stat, &state->context, 00266 GSS_C_NO_BUFFER); 00267 00268 free (state); 00269 } 00270 00271 int 00272 _gsasl_gssapi_client_encode (Gsasl_session * sctx, 00273 void *mech_data, 00274 const char *input, size_t input_len, 00275 char **output, size_t * output_len) 00276 { 00277 _Gsasl_gssapi_client_state *state = mech_data; 00278 OM_uint32 min_stat, maj_stat; 00279 gss_buffer_desc foo; 00280 gss_buffer_t input_message_buffer = &foo; 00281 gss_buffer_desc output_message_buffer; 00282 00283 foo.length = input_len; 00284 foo.value = (void *) input; 00285 00286 if (state && state->step == 3 && 00287 state->qop & (GSASL_QOP_AUTH_INT | GSASL_QOP_AUTH_CONF)) 00288 { 00289 maj_stat = gss_wrap (&min_stat, 00290 state->context, 00291 state->qop & GSASL_QOP_AUTH_CONF ? 1 : 0, 00292 GSS_C_QOP_DEFAULT, 00293 input_message_buffer, 00294 NULL, &output_message_buffer); 00295 if (GSS_ERROR (maj_stat)) 00296 return GSASL_GSSAPI_WRAP_ERROR; 00297 *output_len = output_message_buffer.length; 00298 *output = malloc (input_len); 00299 if (!*output) 00300 { 00301 maj_stat = gss_release_buffer (&min_stat, &output_message_buffer); 00302 return GSASL_MALLOC_ERROR; 00303 } 00304 memcpy (*output, output_message_buffer.value, 00305 output_message_buffer.length); 00306 00307 maj_stat = gss_release_buffer (&min_stat, &output_message_buffer); 00308 if (GSS_ERROR (maj_stat)) 00309 { 00310 free (*output); 00311 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; 00312 } 00313 } 00314 else 00315 { 00316 *output_len = input_len; 00317 *output = malloc (input_len); 00318 if (!*output) 00319 return GSASL_MALLOC_ERROR; 00320 memcpy (*output, input, input_len); 00321 } 00322 00323 return GSASL_OK; 00324 } 00325 00326 int 00327 _gsasl_gssapi_client_decode (Gsasl_session * sctx, 00328 void *mech_data, 00329 const char *input, size_t input_len, 00330 char **output, size_t * output_len) 00331 { 00332 _Gsasl_gssapi_client_state *state = mech_data; 00333 OM_uint32 min_stat, maj_stat; 00334 gss_buffer_desc foo; 00335 gss_buffer_t input_message_buffer = &foo; 00336 gss_buffer_desc output_message_buffer; 00337 00338 foo.length = input_len; 00339 foo.value = (void *) input; 00340 00341 if (state && state->step == 3 && 00342 state->qop & (GSASL_QOP_AUTH_INT | GSASL_QOP_AUTH_CONF)) 00343 { 00344 maj_stat = gss_unwrap (&min_stat, 00345 state->context, 00346 input_message_buffer, 00347 &output_message_buffer, NULL, NULL); 00348 if (GSS_ERROR (maj_stat)) 00349 return GSASL_GSSAPI_UNWRAP_ERROR; 00350 *output_len = output_message_buffer.length; 00351 *output = malloc (input_len); 00352 if (!*output) 00353 { 00354 maj_stat = gss_release_buffer (&min_stat, &output_message_buffer); 00355 return GSASL_MALLOC_ERROR; 00356 } 00357 memcpy (*output, output_message_buffer.value, 00358 output_message_buffer.length); 00359 00360 maj_stat = gss_release_buffer (&min_stat, &output_message_buffer); 00361 if (GSS_ERROR (maj_stat)) 00362 { 00363 free (*output); 00364 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; 00365 } 00366 } 00367 else 00368 { 00369 *output_len = input_len; 00370 *output = malloc (input_len); 00371 if (!*output) 00372 return GSASL_MALLOC_ERROR; 00373 memcpy (*output, input, input_len); 00374 } 00375 00376 return GSASL_OK; 00377 }
1.7.6.1