Patrick Williams | b48b7b4 | 2016-08-17 15:04:38 -0500 | [diff] [blame^] | 1 | From 884913e807414a1e06245918dea71243c5fdd0e6 Mon Sep 17 00:00:00 2001 |
| 2 | From: Nicolas Williams <nico@twosigma.com> |
| 3 | Date: Mon, 14 Sep 2015 12:27:52 -0400 |
| 4 | Subject: [PATCH 1/4] Fix SPNEGO context aliasing bugs [CVE-2015-2695] |
| 5 | |
| 6 | The SPNEGO mechanism currently replaces its context handle with the |
| 7 | mechanism context handle upon establishment, under the assumption that |
| 8 | most GSS functions are only called after context establishment. This |
| 9 | assumption is incorrect, and can lead to aliasing violations for some |
| 10 | programs. Maintain the SPNEGO context structure after context |
| 11 | establishment and refer to it in all GSS methods. Add initiate and |
| 12 | opened flags to the SPNEGO context structure for use in |
| 13 | gss_inquire_context() prior to context establishment. |
| 14 | |
| 15 | CVE-2015-2695: |
| 16 | |
| 17 | In MIT krb5 1.5 and later, applications which call |
| 18 | gss_inquire_context() on a partially-established SPNEGO context can |
| 19 | cause the GSS-API library to read from a pointer using the wrong type, |
| 20 | generally causing a process crash. This bug may go unnoticed, because |
| 21 | the most common SPNEGO authentication scenario establishes the context |
| 22 | after just one call to gss_accept_sec_context(). Java server |
| 23 | applications using the native JGSS provider are vulnerable to this |
| 24 | bug. A carefully crafted SPNEGO packet might allow the |
| 25 | gss_inquire_context() call to succeed with attacker-determined |
| 26 | results, but applications should not make access control decisions |
| 27 | based on gss_inquire_context() results prior to context establishment. |
| 28 | |
| 29 | CVSSv2 Vector: AV:N/AC:M/Au:N/C:N/I:N/A:C/E:POC/RL:OF/RC:C |
| 30 | |
| 31 | [ghudson@mit.edu: several bugfixes, style changes, and edge-case |
| 32 | behavior changes; commit message and CVE description] |
| 33 | |
| 34 | ticket: 8244 |
| 35 | target_version: 1.14 |
| 36 | tags: pullup |
| 37 | |
| 38 | Backport upstream commit: |
| 39 | https://github.com/krb5/krb5/commit/b51b33f2bc5d1497ddf5bd107f791c101695000d |
| 40 | |
| 41 | Upstream-Status: Backport |
| 42 | --- |
| 43 | src/lib/gssapi/spnego/gssapiP_spnego.h | 2 + |
| 44 | src/lib/gssapi/spnego/spnego_mech.c | 254 ++++++++++++++++++++++++--------- |
| 45 | 2 files changed, 192 insertions(+), 64 deletions(-) |
| 46 | |
| 47 | diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h |
| 48 | index bc23f56..8e05736 100644 |
| 49 | --- a/src/lib/gssapi/spnego/gssapiP_spnego.h |
| 50 | +++ b/src/lib/gssapi/spnego/gssapiP_spnego.h |
| 51 | @@ -102,6 +102,8 @@ typedef struct { |
| 52 | int firstpass; |
| 53 | int mech_complete; |
| 54 | int nego_done; |
| 55 | + int initiate; |
| 56 | + int opened; |
| 57 | OM_uint32 ctx_flags; |
| 58 | gss_name_t internal_name; |
| 59 | gss_OID actual_mech; |
| 60 | diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c |
| 61 | index f9248ab..3423f22 100644 |
| 62 | --- a/src/lib/gssapi/spnego/spnego_mech.c |
| 63 | +++ b/src/lib/gssapi/spnego/spnego_mech.c |
| 64 | @@ -101,7 +101,7 @@ static OM_uint32 get_negotiable_mechs(OM_uint32 *, spnego_gss_cred_id_t, |
| 65 | gss_cred_usage_t, gss_OID_set *); |
| 66 | static void release_spnego_ctx(spnego_gss_ctx_id_t *); |
| 67 | static void check_spnego_options(spnego_gss_ctx_id_t); |
| 68 | -static spnego_gss_ctx_id_t create_spnego_ctx(void); |
| 69 | +static spnego_gss_ctx_id_t create_spnego_ctx(int); |
| 70 | static int put_mech_set(gss_OID_set mechSet, gss_buffer_t buf); |
| 71 | static int put_input_token(unsigned char **, gss_buffer_t, unsigned int); |
| 72 | static int put_mech_oid(unsigned char **, gss_OID_const, unsigned int); |
| 73 | @@ -439,7 +439,7 @@ check_spnego_options(spnego_gss_ctx_id_t spnego_ctx) |
| 74 | } |
| 75 | |
| 76 | static spnego_gss_ctx_id_t |
| 77 | -create_spnego_ctx(void) |
| 78 | +create_spnego_ctx(int initiate) |
| 79 | { |
| 80 | spnego_gss_ctx_id_t spnego_ctx = NULL; |
| 81 | spnego_ctx = (spnego_gss_ctx_id_t) |
| 82 | @@ -462,6 +462,8 @@ create_spnego_ctx(void) |
| 83 | spnego_ctx->mic_rcvd = 0; |
| 84 | spnego_ctx->mech_complete = 0; |
| 85 | spnego_ctx->nego_done = 0; |
| 86 | + spnego_ctx->opened = 0; |
| 87 | + spnego_ctx->initiate = initiate; |
| 88 | spnego_ctx->internal_name = GSS_C_NO_NAME; |
| 89 | spnego_ctx->actual_mech = GSS_C_NO_OID; |
| 90 | |
| 91 | @@ -627,7 +629,7 @@ init_ctx_new(OM_uint32 *minor_status, |
| 92 | OM_uint32 ret; |
| 93 | spnego_gss_ctx_id_t sc = NULL; |
| 94 | |
| 95 | - sc = create_spnego_ctx(); |
| 96 | + sc = create_spnego_ctx(1); |
| 97 | if (sc == NULL) |
| 98 | return GSS_S_FAILURE; |
| 99 | |
| 100 | @@ -644,10 +646,7 @@ init_ctx_new(OM_uint32 *minor_status, |
| 101 | ret = GSS_S_FAILURE; |
| 102 | goto cleanup; |
| 103 | } |
| 104 | - /* |
| 105 | - * The actual context is not yet determined, set the output |
| 106 | - * context handle to refer to the spnego context itself. |
| 107 | - */ |
| 108 | + |
| 109 | sc->ctx_handle = GSS_C_NO_CONTEXT; |
| 110 | *ctx = (gss_ctx_id_t)sc; |
| 111 | sc = NULL; |
| 112 | @@ -1088,16 +1087,11 @@ cleanup: |
| 113 | } |
| 114 | gss_release_buffer(&tmpmin, &mechtok_out); |
| 115 | if (ret == GSS_S_COMPLETE) { |
| 116 | - /* |
| 117 | - * Now, switch the output context to refer to the |
| 118 | - * negotiated mechanism's context. |
| 119 | - */ |
| 120 | - *context_handle = (gss_ctx_id_t)spnego_ctx->ctx_handle; |
| 121 | + spnego_ctx->opened = 1; |
| 122 | if (actual_mech != NULL) |
| 123 | *actual_mech = spnego_ctx->actual_mech; |
| 124 | if (ret_flags != NULL) |
| 125 | *ret_flags = spnego_ctx->ctx_flags; |
| 126 | - release_spnego_ctx(&spnego_ctx); |
| 127 | } else if (ret != GSS_S_CONTINUE_NEEDED) { |
| 128 | if (spnego_ctx != NULL) { |
| 129 | gss_delete_sec_context(&tmpmin, |
| 130 | @@ -1341,7 +1335,7 @@ acc_ctx_hints(OM_uint32 *minor_status, |
| 131 | if (ret != GSS_S_COMPLETE) |
| 132 | goto cleanup; |
| 133 | |
| 134 | - sc = create_spnego_ctx(); |
| 135 | + sc = create_spnego_ctx(0); |
| 136 | if (sc == NULL) { |
| 137 | ret = GSS_S_FAILURE; |
| 138 | goto cleanup; |
| 139 | @@ -1423,7 +1417,7 @@ acc_ctx_new(OM_uint32 *minor_status, |
| 140 | gss_release_buffer(&tmpmin, &sc->DER_mechTypes); |
| 141 | assert(mech_wanted != GSS_C_NO_OID); |
| 142 | } else |
| 143 | - sc = create_spnego_ctx(); |
| 144 | + sc = create_spnego_ctx(0); |
| 145 | if (sc == NULL) { |
| 146 | ret = GSS_S_FAILURE; |
| 147 | *return_token = NO_TOKEN_SEND; |
| 148 | @@ -1806,13 +1800,12 @@ cleanup: |
| 149 | ret = GSS_S_FAILURE; |
| 150 | } |
| 151 | if (ret == GSS_S_COMPLETE) { |
| 152 | - *context_handle = (gss_ctx_id_t)sc->ctx_handle; |
| 153 | + sc->opened = 1; |
| 154 | if (sc->internal_name != GSS_C_NO_NAME && |
| 155 | src_name != NULL) { |
| 156 | *src_name = sc->internal_name; |
| 157 | sc->internal_name = GSS_C_NO_NAME; |
| 158 | } |
| 159 | - release_spnego_ctx(&sc); |
| 160 | } else if (ret != GSS_S_CONTINUE_NEEDED) { |
| 161 | if (sc != NULL) { |
| 162 | gss_delete_sec_context(&tmpmin, &sc->ctx_handle, |
| 163 | @@ -2125,8 +2118,13 @@ spnego_gss_unwrap( |
| 164 | gss_qop_t *qop_state) |
| 165 | { |
| 166 | OM_uint32 ret; |
| 167 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 168 | + |
| 169 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 170 | + return (GSS_S_NO_CONTEXT); |
| 171 | + |
| 172 | ret = gss_unwrap(minor_status, |
| 173 | - context_handle, |
| 174 | + sc->ctx_handle, |
| 175 | input_message_buffer, |
| 176 | output_message_buffer, |
| 177 | conf_state, |
| 178 | @@ -2146,8 +2144,13 @@ spnego_gss_wrap( |
| 179 | gss_buffer_t output_message_buffer) |
| 180 | { |
| 181 | OM_uint32 ret; |
| 182 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 183 | + |
| 184 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 185 | + return (GSS_S_NO_CONTEXT); |
| 186 | + |
| 187 | ret = gss_wrap(minor_status, |
| 188 | - context_handle, |
| 189 | + sc->ctx_handle, |
| 190 | conf_req_flag, |
| 191 | qop_req, |
| 192 | input_message_buffer, |
| 193 | @@ -2164,8 +2167,14 @@ spnego_gss_process_context_token( |
| 194 | const gss_buffer_t token_buffer) |
| 195 | { |
| 196 | OM_uint32 ret; |
| 197 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 198 | + |
| 199 | + /* SPNEGO doesn't have its own context tokens. */ |
| 200 | + if (!sc->opened) |
| 201 | + return (GSS_S_DEFECTIVE_TOKEN); |
| 202 | + |
| 203 | ret = gss_process_context_token(minor_status, |
| 204 | - context_handle, |
| 205 | + sc->ctx_handle, |
| 206 | token_buffer); |
| 207 | |
| 208 | return (ret); |
| 209 | @@ -2189,19 +2198,9 @@ spnego_gss_delete_sec_context( |
| 210 | if (*ctx == NULL) |
| 211 | return (GSS_S_COMPLETE); |
| 212 | |
| 213 | - /* |
| 214 | - * If this is still an SPNEGO mech, release it locally. |
| 215 | - */ |
| 216 | - if ((*ctx)->magic_num == SPNEGO_MAGIC_ID) { |
| 217 | - (void) gss_delete_sec_context(minor_status, |
| 218 | - &(*ctx)->ctx_handle, |
| 219 | - output_token); |
| 220 | - (void) release_spnego_ctx(ctx); |
| 221 | - } else { |
| 222 | - ret = gss_delete_sec_context(minor_status, |
| 223 | - context_handle, |
| 224 | - output_token); |
| 225 | - } |
| 226 | + (void) gss_delete_sec_context(minor_status, &(*ctx)->ctx_handle, |
| 227 | + output_token); |
| 228 | + (void) release_spnego_ctx(ctx); |
| 229 | |
| 230 | return (ret); |
| 231 | } |
| 232 | @@ -2213,8 +2212,13 @@ spnego_gss_context_time( |
| 233 | OM_uint32 *time_rec) |
| 234 | { |
| 235 | OM_uint32 ret; |
| 236 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 237 | + |
| 238 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 239 | + return (GSS_S_NO_CONTEXT); |
| 240 | + |
| 241 | ret = gss_context_time(minor_status, |
| 242 | - context_handle, |
| 243 | + sc->ctx_handle, |
| 244 | time_rec); |
| 245 | return (ret); |
| 246 | } |
| 247 | @@ -2226,9 +2230,20 @@ spnego_gss_export_sec_context( |
| 248 | gss_buffer_t interprocess_token) |
| 249 | { |
| 250 | OM_uint32 ret; |
| 251 | + spnego_gss_ctx_id_t sc = *(spnego_gss_ctx_id_t *)context_handle; |
| 252 | + |
| 253 | + /* We don't currently support exporting partially established |
| 254 | + * contexts. */ |
| 255 | + if (!sc->opened) |
| 256 | + return GSS_S_UNAVAILABLE; |
| 257 | + |
| 258 | ret = gss_export_sec_context(minor_status, |
| 259 | - context_handle, |
| 260 | + &sc->ctx_handle, |
| 261 | interprocess_token); |
| 262 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) { |
| 263 | + release_spnego_ctx(&sc); |
| 264 | + *context_handle = GSS_C_NO_CONTEXT; |
| 265 | + } |
| 266 | return (ret); |
| 267 | } |
| 268 | |
| 269 | @@ -2238,11 +2253,12 @@ spnego_gss_import_sec_context( |
| 270 | const gss_buffer_t interprocess_token, |
| 271 | gss_ctx_id_t *context_handle) |
| 272 | { |
| 273 | - OM_uint32 ret; |
| 274 | - ret = gss_import_sec_context(minor_status, |
| 275 | - interprocess_token, |
| 276 | - context_handle); |
| 277 | - return (ret); |
| 278 | + /* |
| 279 | + * Until we implement partial context exports, there are no SPNEGO |
| 280 | + * exported context tokens, only tokens for underlying mechs. So just |
| 281 | + * return an error for now. |
| 282 | + */ |
| 283 | + return GSS_S_UNAVAILABLE; |
| 284 | } |
| 285 | #endif /* LEAN_CLIENT */ |
| 286 | |
| 287 | @@ -2259,16 +2275,48 @@ spnego_gss_inquire_context( |
| 288 | int *opened) |
| 289 | { |
| 290 | OM_uint32 ret = GSS_S_COMPLETE; |
| 291 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 292 | + |
| 293 | + if (src_name != NULL) |
| 294 | + *src_name = GSS_C_NO_NAME; |
| 295 | + if (targ_name != NULL) |
| 296 | + *targ_name = GSS_C_NO_NAME; |
| 297 | + if (lifetime_rec != NULL) |
| 298 | + *lifetime_rec = 0; |
| 299 | + if (mech_type != NULL) |
| 300 | + *mech_type = (gss_OID)gss_mech_spnego; |
| 301 | + if (ctx_flags != NULL) |
| 302 | + *ctx_flags = 0; |
| 303 | + if (locally_initiated != NULL) |
| 304 | + *locally_initiated = sc->initiate; |
| 305 | + if (opened != NULL) |
| 306 | + *opened = sc->opened; |
| 307 | + |
| 308 | + if (sc->ctx_handle != GSS_C_NO_CONTEXT) { |
| 309 | + ret = gss_inquire_context(minor_status, sc->ctx_handle, |
| 310 | + src_name, targ_name, lifetime_rec, |
| 311 | + mech_type, ctx_flags, NULL, NULL); |
| 312 | + } |
| 313 | |
| 314 | - ret = gss_inquire_context(minor_status, |
| 315 | - context_handle, |
| 316 | - src_name, |
| 317 | - targ_name, |
| 318 | - lifetime_rec, |
| 319 | - mech_type, |
| 320 | - ctx_flags, |
| 321 | - locally_initiated, |
| 322 | - opened); |
| 323 | + if (!sc->opened) { |
| 324 | + /* |
| 325 | + * We are still doing SPNEGO negotiation, so report SPNEGO as |
| 326 | + * the OID. After negotiation is complete we will report the |
| 327 | + * underlying mechanism OID. |
| 328 | + */ |
| 329 | + if (mech_type != NULL) |
| 330 | + *mech_type = (gss_OID)gss_mech_spnego; |
| 331 | + |
| 332 | + /* |
| 333 | + * Remove flags we don't support with partially-established |
| 334 | + * contexts. (Change this to keep GSS_C_TRANS_FLAG if we add |
| 335 | + * support for exporting partial SPNEGO contexts.) |
| 336 | + */ |
| 337 | + if (ctx_flags != NULL) { |
| 338 | + *ctx_flags &= ~GSS_C_PROT_READY_FLAG; |
| 339 | + *ctx_flags &= ~GSS_C_TRANS_FLAG; |
| 340 | + } |
| 341 | + } |
| 342 | |
| 343 | return (ret); |
| 344 | } |
| 345 | @@ -2283,8 +2331,13 @@ spnego_gss_wrap_size_limit( |
| 346 | OM_uint32 *max_input_size) |
| 347 | { |
| 348 | OM_uint32 ret; |
| 349 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 350 | + |
| 351 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 352 | + return (GSS_S_NO_CONTEXT); |
| 353 | + |
| 354 | ret = gss_wrap_size_limit(minor_status, |
| 355 | - context_handle, |
| 356 | + sc->ctx_handle, |
| 357 | conf_req_flag, |
| 358 | qop_req, |
| 359 | req_output_size, |
| 360 | @@ -2301,8 +2354,13 @@ spnego_gss_get_mic( |
| 361 | gss_buffer_t message_token) |
| 362 | { |
| 363 | OM_uint32 ret; |
| 364 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 365 | + |
| 366 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 367 | + return (GSS_S_NO_CONTEXT); |
| 368 | + |
| 369 | ret = gss_get_mic(minor_status, |
| 370 | - context_handle, |
| 371 | + sc->ctx_handle, |
| 372 | qop_req, |
| 373 | message_buffer, |
| 374 | message_token); |
| 375 | @@ -2318,8 +2376,13 @@ spnego_gss_verify_mic( |
| 376 | gss_qop_t *qop_state) |
| 377 | { |
| 378 | OM_uint32 ret; |
| 379 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 380 | + |
| 381 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 382 | + return (GSS_S_NO_CONTEXT); |
| 383 | + |
| 384 | ret = gss_verify_mic(minor_status, |
| 385 | - context_handle, |
| 386 | + sc->ctx_handle, |
| 387 | msg_buffer, |
| 388 | token_buffer, |
| 389 | qop_state); |
| 390 | @@ -2334,8 +2397,14 @@ spnego_gss_inquire_sec_context_by_oid( |
| 391 | gss_buffer_set_t *data_set) |
| 392 | { |
| 393 | OM_uint32 ret; |
| 394 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 395 | + |
| 396 | + /* There are no SPNEGO-specific OIDs for this function. */ |
| 397 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 398 | + return (GSS_S_UNAVAILABLE); |
| 399 | + |
| 400 | ret = gss_inquire_sec_context_by_oid(minor_status, |
| 401 | - context_handle, |
| 402 | + sc->ctx_handle, |
| 403 | desired_object, |
| 404 | data_set); |
| 405 | return (ret); |
| 406 | @@ -2404,8 +2473,15 @@ spnego_gss_set_sec_context_option( |
| 407 | const gss_buffer_t value) |
| 408 | { |
| 409 | OM_uint32 ret; |
| 410 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)*context_handle; |
| 411 | + |
| 412 | + /* There are no SPNEGO-specific OIDs for this function, and we cannot |
| 413 | + * construct an empty SPNEGO context with it. */ |
| 414 | + if (sc == NULL || sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 415 | + return (GSS_S_UNAVAILABLE); |
| 416 | + |
| 417 | ret = gss_set_sec_context_option(minor_status, |
| 418 | - context_handle, |
| 419 | + &sc->ctx_handle, |
| 420 | desired_object, |
| 421 | value); |
| 422 | return (ret); |
| 423 | @@ -2422,8 +2498,13 @@ spnego_gss_wrap_aead(OM_uint32 *minor_status, |
| 424 | gss_buffer_t output_message_buffer) |
| 425 | { |
| 426 | OM_uint32 ret; |
| 427 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 428 | + |
| 429 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 430 | + return (GSS_S_NO_CONTEXT); |
| 431 | + |
| 432 | ret = gss_wrap_aead(minor_status, |
| 433 | - context_handle, |
| 434 | + sc->ctx_handle, |
| 435 | conf_req_flag, |
| 436 | qop_req, |
| 437 | input_assoc_buffer, |
| 438 | @@ -2444,8 +2525,13 @@ spnego_gss_unwrap_aead(OM_uint32 *minor_status, |
| 439 | gss_qop_t *qop_state) |
| 440 | { |
| 441 | OM_uint32 ret; |
| 442 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 443 | + |
| 444 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 445 | + return (GSS_S_NO_CONTEXT); |
| 446 | + |
| 447 | ret = gss_unwrap_aead(minor_status, |
| 448 | - context_handle, |
| 449 | + sc->ctx_handle, |
| 450 | input_message_buffer, |
| 451 | input_assoc_buffer, |
| 452 | output_payload_buffer, |
| 453 | @@ -2464,8 +2550,13 @@ spnego_gss_wrap_iov(OM_uint32 *minor_status, |
| 454 | int iov_count) |
| 455 | { |
| 456 | OM_uint32 ret; |
| 457 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 458 | + |
| 459 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 460 | + return (GSS_S_NO_CONTEXT); |
| 461 | + |
| 462 | ret = gss_wrap_iov(minor_status, |
| 463 | - context_handle, |
| 464 | + sc->ctx_handle, |
| 465 | conf_req_flag, |
| 466 | qop_req, |
| 467 | conf_state, |
| 468 | @@ -2483,8 +2574,13 @@ spnego_gss_unwrap_iov(OM_uint32 *minor_status, |
| 469 | int iov_count) |
| 470 | { |
| 471 | OM_uint32 ret; |
| 472 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 473 | + |
| 474 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 475 | + return (GSS_S_NO_CONTEXT); |
| 476 | + |
| 477 | ret = gss_unwrap_iov(minor_status, |
| 478 | - context_handle, |
| 479 | + sc->ctx_handle, |
| 480 | conf_state, |
| 481 | qop_state, |
| 482 | iov, |
| 483 | @@ -2502,8 +2598,13 @@ spnego_gss_wrap_iov_length(OM_uint32 *minor_status, |
| 484 | int iov_count) |
| 485 | { |
| 486 | OM_uint32 ret; |
| 487 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 488 | + |
| 489 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 490 | + return (GSS_S_NO_CONTEXT); |
| 491 | + |
| 492 | ret = gss_wrap_iov_length(minor_status, |
| 493 | - context_handle, |
| 494 | + sc->ctx_handle, |
| 495 | conf_req_flag, |
| 496 | qop_req, |
| 497 | conf_state, |
| 498 | @@ -2520,8 +2621,13 @@ spnego_gss_complete_auth_token( |
| 499 | gss_buffer_t input_message_buffer) |
| 500 | { |
| 501 | OM_uint32 ret; |
| 502 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 503 | + |
| 504 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 505 | + return (GSS_S_UNAVAILABLE); |
| 506 | + |
| 507 | ret = gss_complete_auth_token(minor_status, |
| 508 | - context_handle, |
| 509 | + sc->ctx_handle, |
| 510 | input_message_buffer); |
| 511 | return (ret); |
| 512 | } |
| 513 | @@ -2773,8 +2879,13 @@ spnego_gss_pseudo_random(OM_uint32 *minor_status, |
| 514 | gss_buffer_t prf_out) |
| 515 | { |
| 516 | OM_uint32 ret; |
| 517 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context; |
| 518 | + |
| 519 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 520 | + return (GSS_S_NO_CONTEXT); |
| 521 | + |
| 522 | ret = gss_pseudo_random(minor_status, |
| 523 | - context, |
| 524 | + sc->ctx_handle, |
| 525 | prf_key, |
| 526 | prf_in, |
| 527 | desired_output_len, |
| 528 | @@ -2915,7 +3026,12 @@ spnego_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, |
| 529 | gss_qop_t qop_req, gss_iov_buffer_desc *iov, |
| 530 | int iov_count) |
| 531 | { |
| 532 | - return gss_get_mic_iov(minor_status, context_handle, qop_req, iov, |
| 533 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 534 | + |
| 535 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 536 | + return (GSS_S_NO_CONTEXT); |
| 537 | + |
| 538 | + return gss_get_mic_iov(minor_status, sc->ctx_handle, qop_req, iov, |
| 539 | iov_count); |
| 540 | } |
| 541 | |
| 542 | @@ -2924,7 +3040,12 @@ spnego_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, |
| 543 | gss_qop_t *qop_state, gss_iov_buffer_desc *iov, |
| 544 | int iov_count) |
| 545 | { |
| 546 | - return gss_verify_mic_iov(minor_status, context_handle, qop_state, iov, |
| 547 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 548 | + |
| 549 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 550 | + return (GSS_S_NO_CONTEXT); |
| 551 | + |
| 552 | + return gss_verify_mic_iov(minor_status, sc->ctx_handle, qop_state, iov, |
| 553 | iov_count); |
| 554 | } |
| 555 | |
| 556 | @@ -2933,7 +3054,12 @@ spnego_gss_get_mic_iov_length(OM_uint32 *minor_status, |
| 557 | gss_ctx_id_t context_handle, gss_qop_t qop_req, |
| 558 | gss_iov_buffer_desc *iov, int iov_count) |
| 559 | { |
| 560 | - return gss_get_mic_iov_length(minor_status, context_handle, qop_req, iov, |
| 561 | + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; |
| 562 | + |
| 563 | + if (sc->ctx_handle == GSS_C_NO_CONTEXT) |
| 564 | + return (GSS_S_NO_CONTEXT); |
| 565 | + |
| 566 | + return gss_get_mic_iov_length(minor_status, sc->ctx_handle, qop_req, iov, |
| 567 | iov_count); |
| 568 | } |
| 569 | |
| 570 | -- |
| 571 | 1.9.1 |
| 572 | |