1178825Sdfr/* 2178825Sdfr * Copyright (c) 2006 Kungliga Tekniska H�gskolan 3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden). 4178825Sdfr * All rights reserved. 5178825Sdfr * 6178825Sdfr * Redistribution and use in source and binary forms, with or without 7178825Sdfr * modification, are permitted provided that the following conditions 8178825Sdfr * are met: 9178825Sdfr * 10178825Sdfr * 1. Redistributions of source code must retain the above copyright 11178825Sdfr * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 14178825Sdfr * notice, this list of conditions and the following disclaimer in the 15178825Sdfr * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors 18178825Sdfr * may be used to endorse or promote products derived from this software 19178825Sdfr * without specific prior written permission. 20178825Sdfr * 21178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31178825Sdfr * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "ntlm/ntlm.h" 35178825Sdfr 36178825SdfrRCSID("$Id: init_sec_context.c 22382 2007-12-30 12:13:17Z lha $"); 37178825Sdfr 38178825Sdfrstatic int 39178825Sdfrfrom_file(const char *fn, const char *target_domain, 40178825Sdfr char **username, struct ntlm_buf *key) 41178825Sdfr{ 42178825Sdfr char *str, buf[1024]; 43178825Sdfr FILE *f; 44178825Sdfr 45178825Sdfr f = fopen(fn, "r"); 46178825Sdfr if (f == NULL) 47178825Sdfr return ENOENT; 48178825Sdfr 49178825Sdfr while (fgets(buf, sizeof(buf), f) != NULL) { 50178825Sdfr char *d, *u, *p; 51178825Sdfr buf[strcspn(buf, "\r\n")] = '\0'; 52178825Sdfr if (buf[0] == '#') 53178825Sdfr continue; 54178825Sdfr str = NULL; 55178825Sdfr d = strtok_r(buf, ":", &str); 56178825Sdfr if (d && strcasecmp(target_domain, d) != 0) 57178825Sdfr continue; 58178825Sdfr u = strtok_r(NULL, ":", &str); 59178825Sdfr p = strtok_r(NULL, ":", &str); 60178825Sdfr if (u == NULL || p == NULL) 61178825Sdfr continue; 62178825Sdfr 63178825Sdfr *username = strdup(u); 64178825Sdfr 65178825Sdfr heim_ntlm_nt_key(p, key); 66178825Sdfr 67178825Sdfr memset(buf, 0, sizeof(buf)); 68178825Sdfr fclose(f); 69178825Sdfr return 0; 70178825Sdfr } 71178825Sdfr memset(buf, 0, sizeof(buf)); 72178825Sdfr fclose(f); 73178825Sdfr return ENOENT; 74178825Sdfr} 75178825Sdfr 76178825Sdfrstatic int 77178825Sdfrget_user_file(const ntlm_name target_name, 78178825Sdfr char **username, struct ntlm_buf *key) 79178825Sdfr{ 80178825Sdfr const char *fn; 81178825Sdfr 82178825Sdfr if (issuid()) 83178825Sdfr return ENOENT; 84178825Sdfr 85178825Sdfr fn = getenv("NTLM_USER_FILE"); 86178825Sdfr if (fn == NULL) 87178825Sdfr return ENOENT; 88178825Sdfr if (from_file(fn, target_name->domain, username, key) == 0) 89178825Sdfr return 0; 90178825Sdfr 91178825Sdfr return ENOENT; 92178825Sdfr} 93178825Sdfr 94178825Sdfr/* 95178825Sdfr * Pick up the ntlm cred from the default krb5 credential cache. 96178825Sdfr */ 97178825Sdfr 98178825Sdfrstatic int 99178825Sdfrget_user_ccache(const ntlm_name name, char **username, struct ntlm_buf *key) 100178825Sdfr{ 101178825Sdfr krb5_principal client; 102178825Sdfr krb5_context context = NULL; 103178825Sdfr krb5_error_code ret; 104178825Sdfr krb5_ccache id = NULL; 105178825Sdfr krb5_creds mcreds, creds; 106178825Sdfr 107178825Sdfr *username = NULL; 108178825Sdfr key->length = 0; 109178825Sdfr key->data = NULL; 110178825Sdfr 111178825Sdfr memset(&creds, 0, sizeof(creds)); 112178825Sdfr memset(&mcreds, 0, sizeof(mcreds)); 113178825Sdfr 114178825Sdfr ret = krb5_init_context(&context); 115178825Sdfr if (ret) 116178825Sdfr return ret; 117178825Sdfr 118178825Sdfr ret = krb5_cc_default(context, &id); 119178825Sdfr if (ret) 120178825Sdfr goto out; 121178825Sdfr 122178825Sdfr ret = krb5_cc_get_principal(context, id, &client); 123178825Sdfr if (ret) 124178825Sdfr goto out; 125178825Sdfr 126178825Sdfr ret = krb5_unparse_name_flags(context, client, 127178825Sdfr KRB5_PRINCIPAL_UNPARSE_NO_REALM, 128178825Sdfr username); 129178825Sdfr if (ret) 130178825Sdfr goto out; 131178825Sdfr 132178825Sdfr ret = krb5_make_principal(context, &mcreds.server, 133178825Sdfr krb5_principal_get_realm(context, client), 134178825Sdfr "@ntlm-key", name->domain, NULL); 135178825Sdfr krb5_free_principal(context, client); 136178825Sdfr if (ret) 137178825Sdfr goto out; 138178825Sdfr 139178825Sdfr mcreds.session.keytype = ENCTYPE_ARCFOUR_HMAC_MD5; 140178825Sdfr ret = krb5_cc_retrieve_cred(context, id, KRB5_TC_MATCH_KEYTYPE, 141178825Sdfr &mcreds, &creds); 142178825Sdfr if (ret) { 143178825Sdfr char *s = krb5_get_error_message(context, ret); 144178825Sdfr krb5_free_error_string(context, s); 145178825Sdfr goto out; 146178825Sdfr } 147178825Sdfr 148178825Sdfr key->data = malloc(creds.session.keyvalue.length); 149178825Sdfr if (key->data == NULL) 150178825Sdfr goto out; 151178825Sdfr key->length = creds.session.keyvalue.length; 152178825Sdfr memcpy(key->data, creds.session.keyvalue.data, key->length); 153178825Sdfr 154178825Sdfr krb5_free_cred_contents(context, &creds); 155178825Sdfr 156178825Sdfr return 0; 157178825Sdfr 158178825Sdfrout: 159178825Sdfr if (*username) { 160178825Sdfr free(*username); 161178825Sdfr *username = NULL; 162178825Sdfr } 163178825Sdfr krb5_free_cred_contents(context, &creds); 164178825Sdfr if (mcreds.server) 165178825Sdfr krb5_free_principal(context, mcreds.server); 166178825Sdfr if (id) 167178825Sdfr krb5_cc_close(context, id); 168178825Sdfr if (context) 169178825Sdfr krb5_free_context(context); 170178825Sdfr 171178825Sdfr return ret; 172178825Sdfr} 173178825Sdfr 174178825Sdfrint 175178825Sdfr_gss_ntlm_get_user_cred(const ntlm_name target_name, 176178825Sdfr ntlm_cred *rcred) 177178825Sdfr{ 178178825Sdfr ntlm_cred cred; 179178825Sdfr int ret; 180178825Sdfr 181178825Sdfr cred = calloc(1, sizeof(*cred)); 182178825Sdfr if (cred == NULL) 183178825Sdfr return ENOMEM; 184178825Sdfr 185178825Sdfr ret = get_user_file(target_name, &cred->username, &cred->key); 186178825Sdfr if (ret) 187178825Sdfr ret = get_user_ccache(target_name, &cred->username, &cred->key); 188178825Sdfr if (ret) { 189178825Sdfr free(cred); 190178825Sdfr return ret; 191178825Sdfr } 192178825Sdfr 193178825Sdfr cred->domain = strdup(target_name->domain); 194178825Sdfr *rcred = cred; 195178825Sdfr 196178825Sdfr return ret; 197178825Sdfr} 198178825Sdfr 199178825Sdfrstatic int 200178825Sdfr_gss_copy_cred(ntlm_cred from, ntlm_cred *to) 201178825Sdfr{ 202178825Sdfr *to = calloc(1, sizeof(*to)); 203178825Sdfr if (*to == NULL) 204178825Sdfr return ENOMEM; 205178825Sdfr (*to)->username = strdup(from->username); 206178825Sdfr if ((*to)->username == NULL) { 207178825Sdfr free(*to); 208178825Sdfr return ENOMEM; 209178825Sdfr } 210178825Sdfr (*to)->domain = strdup(from->domain); 211178825Sdfr if ((*to)->domain == NULL) { 212178825Sdfr free((*to)->username); 213178825Sdfr free(*to); 214178825Sdfr return ENOMEM; 215178825Sdfr } 216178825Sdfr (*to)->key.data = malloc(from->key.length); 217178825Sdfr if ((*to)->key.data == NULL) { 218178825Sdfr free((*to)->domain); 219178825Sdfr free((*to)->username); 220178825Sdfr free(*to); 221178825Sdfr return ENOMEM; 222178825Sdfr } 223178825Sdfr memcpy((*to)->key.data, from->key.data, from->key.length); 224178825Sdfr (*to)->key.length = from->key.length; 225178825Sdfr 226178825Sdfr return 0; 227178825Sdfr} 228178825Sdfr 229178825SdfrOM_uint32 230178825Sdfr_gss_ntlm_init_sec_context 231178825Sdfr (OM_uint32 * minor_status, 232178825Sdfr const gss_cred_id_t initiator_cred_handle, 233178825Sdfr gss_ctx_id_t * context_handle, 234178825Sdfr const gss_name_t target_name, 235178825Sdfr const gss_OID mech_type, 236178825Sdfr OM_uint32 req_flags, 237178825Sdfr OM_uint32 time_req, 238178825Sdfr const gss_channel_bindings_t input_chan_bindings, 239178825Sdfr const gss_buffer_t input_token, 240178825Sdfr gss_OID * actual_mech_type, 241178825Sdfr gss_buffer_t output_token, 242178825Sdfr OM_uint32 * ret_flags, 243178825Sdfr OM_uint32 * time_rec 244178825Sdfr ) 245178825Sdfr{ 246178825Sdfr ntlm_ctx ctx; 247178825Sdfr ntlm_name name = (ntlm_name)target_name; 248178825Sdfr 249178825Sdfr *minor_status = 0; 250178825Sdfr 251178825Sdfr if (ret_flags) 252178825Sdfr *ret_flags = 0; 253178825Sdfr if (time_rec) 254178825Sdfr *time_rec = 0; 255178825Sdfr if (actual_mech_type) 256178825Sdfr *actual_mech_type = GSS_C_NO_OID; 257178825Sdfr 258178825Sdfr if (*context_handle == GSS_C_NO_CONTEXT) { 259178825Sdfr struct ntlm_type1 type1; 260178825Sdfr struct ntlm_buf data; 261178825Sdfr uint32_t flags = 0; 262178825Sdfr int ret; 263178825Sdfr 264178825Sdfr ctx = calloc(1, sizeof(*ctx)); 265178825Sdfr if (ctx == NULL) { 266178825Sdfr *minor_status = EINVAL; 267178825Sdfr return GSS_S_FAILURE; 268178825Sdfr } 269178825Sdfr *context_handle = (gss_ctx_id_t)ctx; 270178825Sdfr 271178825Sdfr if (initiator_cred_handle != GSS_C_NO_CREDENTIAL) { 272178825Sdfr ntlm_cred cred = (ntlm_cred)initiator_cred_handle; 273178825Sdfr ret = _gss_copy_cred(cred, &ctx->client); 274178825Sdfr } else 275178825Sdfr ret = _gss_ntlm_get_user_cred(name, &ctx->client); 276178825Sdfr 277178825Sdfr if (ret) { 278178825Sdfr _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); 279178825Sdfr *minor_status = ret; 280178825Sdfr return GSS_S_FAILURE; 281178825Sdfr } 282178825Sdfr 283178825Sdfr if (req_flags & GSS_C_CONF_FLAG) 284178825Sdfr flags |= NTLM_NEG_SEAL; 285178825Sdfr if (req_flags & GSS_C_INTEG_FLAG) 286178825Sdfr flags |= NTLM_NEG_SIGN; 287178825Sdfr else 288178825Sdfr flags |= NTLM_NEG_ALWAYS_SIGN; 289178825Sdfr 290178825Sdfr flags |= NTLM_NEG_UNICODE; 291178825Sdfr flags |= NTLM_NEG_NTLM; 292178825Sdfr flags |= NTLM_NEG_NTLM2_SESSION; 293178825Sdfr flags |= NTLM_NEG_KEYEX; 294178825Sdfr 295178825Sdfr memset(&type1, 0, sizeof(type1)); 296178825Sdfr 297178825Sdfr type1.flags = flags; 298178825Sdfr type1.domain = name->domain; 299178825Sdfr type1.hostname = NULL; 300178825Sdfr type1.os[0] = 0; 301178825Sdfr type1.os[1] = 0; 302178825Sdfr 303178825Sdfr ret = heim_ntlm_encode_type1(&type1, &data); 304178825Sdfr if (ret) { 305178825Sdfr _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); 306178825Sdfr *minor_status = ret; 307178825Sdfr return GSS_S_FAILURE; 308178825Sdfr } 309178825Sdfr 310178825Sdfr output_token->value = data.data; 311178825Sdfr output_token->length = data.length; 312178825Sdfr 313178825Sdfr return GSS_S_CONTINUE_NEEDED; 314178825Sdfr } else { 315178825Sdfr krb5_error_code ret; 316178825Sdfr struct ntlm_type2 type2; 317178825Sdfr struct ntlm_type3 type3; 318178825Sdfr struct ntlm_buf data; 319178825Sdfr 320178825Sdfr ctx = (ntlm_ctx)*context_handle; 321178825Sdfr 322178825Sdfr data.data = input_token->value; 323178825Sdfr data.length = input_token->length; 324178825Sdfr 325178825Sdfr ret = heim_ntlm_decode_type2(&data, &type2); 326178825Sdfr if (ret) { 327178825Sdfr _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); 328178825Sdfr *minor_status = ret; 329178825Sdfr return GSS_S_FAILURE; 330178825Sdfr } 331178825Sdfr 332178825Sdfr ctx->flags = type2.flags; 333178825Sdfr 334178825Sdfr /* XXX check that type2.targetinfo matches `target_name� */ 335178825Sdfr /* XXX check verify targetinfo buffer */ 336178825Sdfr 337178825Sdfr memset(&type3, 0, sizeof(type3)); 338178825Sdfr 339178825Sdfr type3.username = ctx->client->username; 340178825Sdfr type3.flags = type2.flags; 341178825Sdfr type3.targetname = type2.targetname; 342178825Sdfr type3.ws = rk_UNCONST("workstation"); 343178825Sdfr 344178825Sdfr /* 345178825Sdfr * NTLM Version 1 if no targetinfo buffer. 346178825Sdfr */ 347178825Sdfr 348178825Sdfr if (1 || type2.targetinfo.length == 0) { 349178825Sdfr struct ntlm_buf sessionkey; 350178825Sdfr 351178825Sdfr if (type2.flags & NTLM_NEG_NTLM2_SESSION) { 352178825Sdfr unsigned char nonce[8]; 353178825Sdfr 354178825Sdfr if (RAND_bytes(nonce, sizeof(nonce)) != 1) { 355178825Sdfr _gss_ntlm_delete_sec_context(minor_status, 356178825Sdfr context_handle, NULL); 357178825Sdfr *minor_status = EINVAL; 358178825Sdfr return GSS_S_FAILURE; 359178825Sdfr } 360178825Sdfr 361178825Sdfr ret = heim_ntlm_calculate_ntlm2_sess(nonce, 362178825Sdfr type2.challange, 363178825Sdfr ctx->client->key.data, 364178825Sdfr &type3.lm, 365178825Sdfr &type3.ntlm); 366178825Sdfr } else { 367178825Sdfr ret = heim_ntlm_calculate_ntlm1(ctx->client->key.data, 368178825Sdfr ctx->client->key.length, 369178825Sdfr type2.challange, 370178825Sdfr &type3.ntlm); 371178825Sdfr 372178825Sdfr } 373178825Sdfr if (ret) { 374178825Sdfr _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); 375178825Sdfr *minor_status = ret; 376178825Sdfr return GSS_S_FAILURE; 377178825Sdfr } 378178825Sdfr 379178825Sdfr ret = heim_ntlm_build_ntlm1_master(ctx->client->key.data, 380178825Sdfr ctx->client->key.length, 381178825Sdfr &sessionkey, 382178825Sdfr &type3.sessionkey); 383178825Sdfr if (ret) { 384178825Sdfr if (type3.lm.data) 385178825Sdfr free(type3.lm.data); 386178825Sdfr if (type3.ntlm.data) 387178825Sdfr free(type3.ntlm.data); 388178825Sdfr _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); 389178825Sdfr *minor_status = ret; 390178825Sdfr return GSS_S_FAILURE; 391178825Sdfr } 392178825Sdfr 393178825Sdfr ret = krb5_data_copy(&ctx->sessionkey, 394178825Sdfr sessionkey.data, sessionkey.length); 395178825Sdfr free(sessionkey.data); 396178825Sdfr if (ret) { 397178825Sdfr if (type3.lm.data) 398178825Sdfr free(type3.lm.data); 399178825Sdfr if (type3.ntlm.data) 400178825Sdfr free(type3.ntlm.data); 401178825Sdfr _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); 402178825Sdfr *minor_status = ret; 403178825Sdfr return GSS_S_FAILURE; 404178825Sdfr } 405178825Sdfr ctx->status |= STATUS_SESSIONKEY; 406178825Sdfr 407178825Sdfr } else { 408178825Sdfr struct ntlm_buf sessionkey; 409178825Sdfr unsigned char ntlmv2[16]; 410178825Sdfr struct ntlm_targetinfo ti; 411178825Sdfr 412178825Sdfr /* verify infotarget */ 413178825Sdfr 414178825Sdfr ret = heim_ntlm_decode_targetinfo(&type2.targetinfo, 1, &ti); 415178825Sdfr if(ret) { 416178825Sdfr _gss_ntlm_delete_sec_context(minor_status, 417178825Sdfr context_handle, NULL); 418178825Sdfr *minor_status = ret; 419178825Sdfr return GSS_S_FAILURE; 420178825Sdfr } 421178825Sdfr 422178825Sdfr if (ti.domainname && strcmp(ti.domainname, name->domain) != 0) { 423178825Sdfr _gss_ntlm_delete_sec_context(minor_status, 424178825Sdfr context_handle, NULL); 425178825Sdfr *minor_status = EINVAL; 426178825Sdfr return GSS_S_FAILURE; 427178825Sdfr } 428178825Sdfr 429178825Sdfr ret = heim_ntlm_calculate_ntlm2(ctx->client->key.data, 430178825Sdfr ctx->client->key.length, 431178825Sdfr ctx->client->username, 432178825Sdfr name->domain, 433178825Sdfr type2.challange, 434178825Sdfr &type2.targetinfo, 435178825Sdfr ntlmv2, 436178825Sdfr &type3.ntlm); 437178825Sdfr if (ret) { 438178825Sdfr _gss_ntlm_delete_sec_context(minor_status, 439178825Sdfr context_handle, NULL); 440178825Sdfr *minor_status = ret; 441178825Sdfr return GSS_S_FAILURE; 442178825Sdfr } 443178825Sdfr 444178825Sdfr ret = heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2), 445178825Sdfr &sessionkey, 446178825Sdfr &type3.sessionkey); 447178825Sdfr memset(ntlmv2, 0, sizeof(ntlmv2)); 448178825Sdfr if (ret) { 449178825Sdfr _gss_ntlm_delete_sec_context(minor_status, 450178825Sdfr context_handle, NULL); 451178825Sdfr *minor_status = ret; 452178825Sdfr return GSS_S_FAILURE; 453178825Sdfr } 454178825Sdfr 455178825Sdfr ctx->flags |= NTLM_NEG_NTLM2_SESSION; 456178825Sdfr 457178825Sdfr ret = krb5_data_copy(&ctx->sessionkey, 458178825Sdfr sessionkey.data, sessionkey.length); 459178825Sdfr free(sessionkey.data); 460178825Sdfr } 461178825Sdfr 462178825Sdfr if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { 463178825Sdfr ctx->status |= STATUS_SESSIONKEY; 464178825Sdfr _gss_ntlm_set_key(&ctx->u.v2.send, 0, (ctx->flags & NTLM_NEG_KEYEX), 465178825Sdfr ctx->sessionkey.data, 466178825Sdfr ctx->sessionkey.length); 467178825Sdfr _gss_ntlm_set_key(&ctx->u.v2.recv, 1, (ctx->flags & NTLM_NEG_KEYEX), 468178825Sdfr ctx->sessionkey.data, 469178825Sdfr ctx->sessionkey.length); 470178825Sdfr } else { 471178825Sdfr ctx->status |= STATUS_SESSIONKEY; 472178825Sdfr RC4_set_key(&ctx->u.v1.crypto_recv.key, 473178825Sdfr ctx->sessionkey.length, 474178825Sdfr ctx->sessionkey.data); 475178825Sdfr RC4_set_key(&ctx->u.v1.crypto_send.key, 476178825Sdfr ctx->sessionkey.length, 477178825Sdfr ctx->sessionkey.data); 478178825Sdfr } 479178825Sdfr 480178825Sdfr 481178825Sdfr 482178825Sdfr ret = heim_ntlm_encode_type3(&type3, &data); 483178825Sdfr free(type3.sessionkey.data); 484178825Sdfr if (type3.lm.data) 485178825Sdfr free(type3.lm.data); 486178825Sdfr if (type3.ntlm.data) 487178825Sdfr free(type3.ntlm.data); 488178825Sdfr if (ret) { 489178825Sdfr _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); 490178825Sdfr *minor_status = ret; 491178825Sdfr return GSS_S_FAILURE; 492178825Sdfr } 493178825Sdfr 494178825Sdfr output_token->length = data.length; 495178825Sdfr output_token->value = data.data; 496178825Sdfr 497178825Sdfr if (actual_mech_type) 498178825Sdfr *actual_mech_type = GSS_NTLM_MECHANISM; 499178825Sdfr if (ret_flags) 500178825Sdfr *ret_flags = 0; 501178825Sdfr if (time_rec) 502178825Sdfr *time_rec = GSS_C_INDEFINITE; 503178825Sdfr 504178825Sdfr ctx->status |= STATUS_OPEN; 505178825Sdfr 506178825Sdfr return GSS_S_COMPLETE; 507178825Sdfr } 508178825Sdfr} 509