|
gsasl
1.8.0
|
00001 /* server.c --- SASL mechanism GSSAPI as defined in RFC 4752, server 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_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 /* FIXME: Use asprintf. */ 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 /* fall through */ 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 if (maj_stat == GSS_S_COMPLETE) 00166 state->step++; 00167 00168 if (maj_stat == GSS_S_CONTINUE_NEEDED || bufdesc2.length > 0) 00169 { 00170 *output = malloc (bufdesc2.length); 00171 if (!*output) 00172 return GSASL_MALLOC_ERROR; 00173 memcpy (*output, bufdesc2.value, bufdesc2.length); 00174 *output_len = bufdesc2.length; 00175 } 00176 00177 maj_stat = gss_release_buffer (&min_stat, &bufdesc2); 00178 if (GSS_ERROR (maj_stat)) 00179 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; 00180 00181 if (maj_stat == GSS_S_CONTINUE_NEEDED || *output_len > 0) 00182 { 00183 res = GSASL_NEEDS_MORE; 00184 break; 00185 } 00186 /* fall through */ 00187 00188 case 2: 00189 memset (tmp, 0xFF, 4); 00190 tmp[0] = GSASL_QOP_AUTH; 00191 bufdesc1.length = 4; 00192 bufdesc1.value = tmp; 00193 maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT, 00194 &bufdesc1, NULL, &bufdesc2); 00195 if (GSS_ERROR (maj_stat)) 00196 return GSASL_GSSAPI_WRAP_ERROR; 00197 00198 *output = malloc (bufdesc2.length); 00199 if (!*output) 00200 return GSASL_MALLOC_ERROR; 00201 memcpy (*output, bufdesc2.value, bufdesc2.length); 00202 *output_len = bufdesc2.length; 00203 00204 maj_stat = gss_release_buffer (&min_stat, &bufdesc2); 00205 if (GSS_ERROR (maj_stat)) 00206 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; 00207 00208 state->step++; 00209 res = GSASL_NEEDS_MORE; 00210 break; 00211 00212 case 3: 00213 bufdesc1.value = (void *) input; 00214 bufdesc1.length = input_len; 00215 maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc1, 00216 &bufdesc2, NULL, NULL); 00217 if (GSS_ERROR (maj_stat)) 00218 return GSASL_GSSAPI_UNWRAP_ERROR; 00219 00220 /* [RFC 2222 section 7.2.1]: 00221 The client passes this token to GSS_Unwrap and interprets the 00222 first octet of resulting cleartext as a bit-mask specifying 00223 the security layers supported by the server and the second 00224 through fourth octets as the maximum size output_message to 00225 send to the server. The client then constructs data, with 00226 the first octet containing the bit-mask specifying the 00227 selected security layer, the second through fourth octets 00228 containing in network byte order the maximum size 00229 output_message the client is able to receive, and the 00230 remaining octets containing the authorization identity. The 00231 client passes the data to GSS_Wrap with conf_flag set to 00232 FALSE, and responds with the generated output_message. The 00233 client can then consider the server authenticated. */ 00234 00235 if ((((char *) bufdesc2.value)[0] & GSASL_QOP_AUTH) == 0) 00236 { 00237 /* Integrity or privacy unsupported */ 00238 maj_stat = gss_release_buffer (&min_stat, &bufdesc2); 00239 return GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR; 00240 } 00241 00242 gsasl_property_set_raw (sctx, GSASL_AUTHZID, 00243 (char *) bufdesc2.value + 4, 00244 bufdesc2.length - 4); 00245 00246 maj_stat = gss_display_name (&min_stat, state->client, 00247 &client_name, &mech_type); 00248 if (GSS_ERROR (maj_stat)) 00249 return GSASL_GSSAPI_DISPLAY_NAME_ERROR; 00250 00251 gsasl_property_set_raw (sctx, GSASL_GSSAPI_DISPLAY_NAME, 00252 client_name.value, client_name.length); 00253 00254 maj_stat = gss_release_buffer (&min_stat, &bufdesc2); 00255 if (GSS_ERROR (maj_stat)) 00256 return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; 00257 00258 res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_GSSAPI); 00259 00260 state->step++; 00261 break; 00262 00263 default: 00264 res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; 00265 break; 00266 } 00267 00268 return res; 00269 } 00270 00271 void 00272 _gsasl_gssapi_server_finish (Gsasl_session * sctx, void *mech_data) 00273 { 00274 _Gsasl_gssapi_server_state *state = mech_data; 00275 OM_uint32 min_stat; 00276 00277 if (!state) 00278 return; 00279 00280 if (state->context != GSS_C_NO_CONTEXT) 00281 gss_delete_sec_context (&min_stat, &state->context, GSS_C_NO_BUFFER); 00282 00283 if (state->cred != GSS_C_NO_CREDENTIAL) 00284 gss_release_cred (&min_stat, &state->cred); 00285 00286 if (state->client != GSS_C_NO_NAME) 00287 gss_release_name (&min_stat, &state->client); 00288 00289 free (state); 00290 }
1.7.6.1