17c478bd9Sstevel@tonic-gate /*
25e01956fSGlenn Barry  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3*cfed4d70SMatt Barden  * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
45e01956fSGlenn Barry  */
55e01956fSGlenn Barry /*
6ab9b2e15Sgtb  * Copyright 2000, 2004  by the Massachusetts Institute of Technology.
77c478bd9Sstevel@tonic-gate  * All Rights Reserved.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
107c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
117c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
127c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
157c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
167c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
177c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
187c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
197c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
207c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
217c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
227c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
237c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
247c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
257c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
267c478bd9Sstevel@tonic-gate  * or implied warranty.
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Copyright 1993 by OpenVision Technologies, Inc.
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, distribute, and sell this software
337c478bd9Sstevel@tonic-gate  * and its documentation for any purpose is hereby granted without fee,
347c478bd9Sstevel@tonic-gate  * provided that the above copyright notice appears in all copies and
357c478bd9Sstevel@tonic-gate  * that both that copyright notice and this permission notice appear in
367c478bd9Sstevel@tonic-gate  * supporting documentation, and that the name of OpenVision not be used
377c478bd9Sstevel@tonic-gate  * in advertising or publicity pertaining to distribution of the software
387c478bd9Sstevel@tonic-gate  * without specific, written prior permission. OpenVision makes no
397c478bd9Sstevel@tonic-gate  * representations about the suitability of this software for any
407c478bd9Sstevel@tonic-gate  * purpose.  It is provided "as is" without express or implied warranty.
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
437c478bd9Sstevel@tonic-gate  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
447c478bd9Sstevel@tonic-gate  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
457c478bd9Sstevel@tonic-gate  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
467c478bd9Sstevel@tonic-gate  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
477c478bd9Sstevel@tonic-gate  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
487c478bd9Sstevel@tonic-gate  * PERFORMANCE OF THIS SOFTWARE.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /*
527c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * All rights reserved.
557c478bd9Sstevel@tonic-gate  *
567c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
577c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
587c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
597c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
607c478bd9Sstevel@tonic-gate  *
617c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
627c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
637c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
647c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
657c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
667c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
677c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
687c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
697c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
707c478bd9Sstevel@tonic-gate  * or implied warranty.
717c478bd9Sstevel@tonic-gate  *
727c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
737c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
747c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
757c478bd9Sstevel@tonic-gate  */
767c478bd9Sstevel@tonic-gate 
77159d09a2SMark Phalan #include "k5-int.h"
78159d09a2SMark Phalan #include "gssapiP_krb5.h"
79ab9b2e15Sgtb #ifdef HAVE_MEMORY_H
807c478bd9Sstevel@tonic-gate #include <memory.h>
81ab9b2e15Sgtb #endif
827c478bd9Sstevel@tonic-gate #include <assert.h>
83159d09a2SMark Phalan #include "auth_con.h"
84ab9b2e15Sgtb #ifdef CFX_EXERCISE
85ab9b2e15Sgtb #define CFX_ACCEPTOR_SUBKEY (time(0) & 1)
86ab9b2e15Sgtb #else
877c478bd9Sstevel@tonic-gate #define CFX_ACCEPTOR_SUBKEY 1
88ab9b2e15Sgtb #endif
895e01956fSGlenn Barry #include <syslog.h>
905e01956fSGlenn Barry #include <locale.h> /* Solaris Kerberos */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  * Decode, decrypt and store the forwarded creds in the local ccache.
947c478bd9Sstevel@tonic-gate  * and populate the callers delegated credential handle if it
957c478bd9Sstevel@tonic-gate  * was provided.
967c478bd9Sstevel@tonic-gate  */
977c478bd9Sstevel@tonic-gate static krb5_error_code
rd_and_store_for_creds(context,auth_context,inbuf,out_cred)987c478bd9Sstevel@tonic-gate rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
997c478bd9Sstevel@tonic-gate     krb5_context context;
1007c478bd9Sstevel@tonic-gate     krb5_auth_context auth_context;
1017c478bd9Sstevel@tonic-gate     krb5_data *inbuf;
1027c478bd9Sstevel@tonic-gate     krb5_gss_cred_id_t *out_cred;
1037c478bd9Sstevel@tonic-gate {
104159d09a2SMark Phalan     krb5_creds ** creds = NULL;
1057c478bd9Sstevel@tonic-gate     krb5_error_code retval;
1067c478bd9Sstevel@tonic-gate     krb5_ccache ccache = NULL;
1077c478bd9Sstevel@tonic-gate     krb5_gss_cred_id_t cred = NULL;
1087c478bd9Sstevel@tonic-gate     krb5_auth_context new_auth_ctx = NULL;
1097c478bd9Sstevel@tonic-gate 	krb5_int32 flags_org;
1107c478bd9Sstevel@tonic-gate 
111159d09a2SMark Phalan     /* Solaris Kerberos */
1127c478bd9Sstevel@tonic-gate     KRB5_LOG0(KRB5_INFO, "rd_and_store_for_creds() start");
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	if ((retval = krb5_auth_con_getflags(context, auth_context, &flags_org)))
1157c478bd9Sstevel@tonic-gate 		return retval;
116159d09a2SMark Phalan 	krb5_auth_con_setflags(context, auth_context,
117159d09a2SMark Phalan 			       0);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	/*
1207c478bd9Sstevel@tonic-gate 	 * By the time krb5_rd_cred is called here (after krb5_rd_req has been
1217c478bd9Sstevel@tonic-gate 	 * called in krb5_gss_accept_sec_context), the "keyblock" field of
1227c478bd9Sstevel@tonic-gate 	 * auth_context contains a pointer to the session key, and the
1237c478bd9Sstevel@tonic-gate 	 * "recv_subkey" field might contain a session subkey.  Either of
1247c478bd9Sstevel@tonic-gate 	 * these (the "recv_subkey" if it isn't NULL, otherwise the
1257c478bd9Sstevel@tonic-gate 	 * "keyblock") might have been used to encrypt the encrypted part of
1267c478bd9Sstevel@tonic-gate 	 * the KRB_CRED message that contains the forwarded credentials.  (The
1277c478bd9Sstevel@tonic-gate 	 * Java Crypto and Security Implementation from the DSTC in Australia
1287c478bd9Sstevel@tonic-gate 	 * always uses the session key.  But apparently it never negotiates a
1297c478bd9Sstevel@tonic-gate 	 * subkey, so this code works fine against a JCSI client.)  Up to the
1307c478bd9Sstevel@tonic-gate 	 * present, though, GSSAPI clients linked against the MIT code (which
1317c478bd9Sstevel@tonic-gate 	 * is almost all GSSAPI clients) don't encrypt the KRB_CRED message at
1327c478bd9Sstevel@tonic-gate 	 * all -- at this level.  So if the first call to krb5_rd_cred fails,
1337c478bd9Sstevel@tonic-gate 	 * we should call it a second time with another auth context freshly
1347c478bd9Sstevel@tonic-gate 	 * created by krb5_auth_con_init.  All of its keyblock fields will be
1357c478bd9Sstevel@tonic-gate 	 * NULL, so krb5_rd_cred will assume that the KRB_CRED message is
1367c478bd9Sstevel@tonic-gate 	 * unencrypted.  (The MIT code doesn't actually send the KRB_CRED
1377c478bd9Sstevel@tonic-gate 	 * message in the clear -- the "authenticator" whose "checksum" ends up
1387c478bd9Sstevel@tonic-gate 	 * containing the KRB_CRED message does get encrypted.)
1397c478bd9Sstevel@tonic-gate 	 */
140159d09a2SMark Phalan     /* Solaris Kerberos */
1417c478bd9Sstevel@tonic-gate     if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))) {
1427c478bd9Sstevel@tonic-gate 	krb5_enctype enctype = ENCTYPE_NULL;
1437c478bd9Sstevel@tonic-gate 	/*
1447c478bd9Sstevel@tonic-gate 	 * If the client is using non-DES enctypes it really ought to
1457c478bd9Sstevel@tonic-gate 	 * send encrypted KRB-CREDs...
1467c478bd9Sstevel@tonic-gate 	 */
1477c478bd9Sstevel@tonic-gate 	if (auth_context->keyblock != NULL)
1487c478bd9Sstevel@tonic-gate 	    enctype = auth_context->keyblock->enctype;
1497c478bd9Sstevel@tonic-gate 	switch (enctype) {
1507c478bd9Sstevel@tonic-gate 	case ENCTYPE_DES_CBC_MD5:
1517c478bd9Sstevel@tonic-gate 	case ENCTYPE_DES_CBC_CRC:
1527c478bd9Sstevel@tonic-gate 	case ENCTYPE_DES3_CBC_SHA1:
1537c478bd9Sstevel@tonic-gate 	    break;
1547c478bd9Sstevel@tonic-gate 	default:
1557c478bd9Sstevel@tonic-gate 	    KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
1567c478bd9Sstevel@tonic-gate 		    "krb5_rd_cred() retval = %d\n", retval);
1577c478bd9Sstevel@tonic-gate 	    goto cleanup;
1587c478bd9Sstevel@tonic-gate 	    /* NOTREACHED */
1597c478bd9Sstevel@tonic-gate 	    break;
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	/* Try to krb5_rd_cred() likely unencrypted KRB-CRED */
1637c478bd9Sstevel@tonic-gate 		if ((retval = krb5_auth_con_init(context, &new_auth_ctx)))
1647c478bd9Sstevel@tonic-gate 			goto cleanup;
1657c478bd9Sstevel@tonic-gate 		krb5_auth_con_setflags(context, new_auth_ctx, 0);
1667c478bd9Sstevel@tonic-gate 		if ((retval = krb5_rd_cred(context, new_auth_ctx, inbuf,
1677c478bd9Sstevel@tonic-gate 					   &creds, NULL))) {
168159d09a2SMark Phalan 			/* Solaris Kerberos */
1697c478bd9Sstevel@tonic-gate 			KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
1707c478bd9Sstevel@tonic-gate 			    "krb5_rd_cred() retval = %d\n", retval);
1717c478bd9Sstevel@tonic-gate 			goto cleanup;
1727c478bd9Sstevel@tonic-gate 		}
1737c478bd9Sstevel@tonic-gate     }
1747c478bd9Sstevel@tonic-gate 
175159d09a2SMark Phalan     if ((retval = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) {
176159d09a2SMark Phalan 	ccache = NULL;
1777c478bd9Sstevel@tonic-gate         goto cleanup;
1787c478bd9Sstevel@tonic-gate     }
1797c478bd9Sstevel@tonic-gate 
180159d09a2SMark Phalan     if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client))) {
181159d09a2SMark Phalan 	/* Solaris Kerberos */
1827c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
1837c478bd9Sstevel@tonic-gate 		"krb5_cc_initialize() retval = %d\n", retval);
1847c478bd9Sstevel@tonic-gate 	goto cleanup;
1857c478bd9Sstevel@tonic-gate     }
1867c478bd9Sstevel@tonic-gate 
187159d09a2SMark Phalan     if ((retval = krb5_cc_store_cred(context, ccache, creds[0]))) {
188159d09a2SMark Phalan 	/* Solaris Kerberos */
1897c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
1907c478bd9Sstevel@tonic-gate 		"krb5_cc_store_cred() retval = %d\n", retval);
1917c478bd9Sstevel@tonic-gate 	goto cleanup;
1927c478bd9Sstevel@tonic-gate     }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate     /* generate a delegated credential handle */
1957c478bd9Sstevel@tonic-gate     if (out_cred) {
1967c478bd9Sstevel@tonic-gate 	/* allocate memory for a cred_t... */
1977c478bd9Sstevel@tonic-gate 	if (!(cred =
1987c478bd9Sstevel@tonic-gate 	      (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
1997c478bd9Sstevel@tonic-gate 	    retval = ENOMEM; /* out of memory? */
2007c478bd9Sstevel@tonic-gate 	    *out_cred = NULL;
2017c478bd9Sstevel@tonic-gate 	    goto cleanup;
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	/* zero it out... */
205159d09a2SMark Phalan 	/* Solaris Kerberos */
2067c478bd9Sstevel@tonic-gate 	(void) memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
2077c478bd9Sstevel@tonic-gate 
208ab9b2e15Sgtb 	retval = k5_mutex_init(&cred->lock);
209ab9b2e15Sgtb 	if (retval) {
210ab9b2e15Sgtb 	    xfree(cred);
211ab9b2e15Sgtb 	    cred = NULL;
212ab9b2e15Sgtb 	    goto cleanup;
213ab9b2e15Sgtb 	}
214ab9b2e15Sgtb 
2157c478bd9Sstevel@tonic-gate 	/* copy the client principle into it... */
216159d09a2SMark Phalan 	if ((retval =
217159d09a2SMark Phalan 	     krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
218159d09a2SMark Phalan 	     /* Solaris Kerberos */
2197c478bd9Sstevel@tonic-gate 	    KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
2207c478bd9Sstevel@tonic-gate 		    "krb5_copy_principal() retval = %d\n", retval);
221ab9b2e15Sgtb 	    k5_mutex_destroy(&cred->lock);
2227c478bd9Sstevel@tonic-gate 	    retval = ENOMEM; /* out of memory? */
2237c478bd9Sstevel@tonic-gate 	    xfree(cred); /* clean up memory on failure */
224159d09a2SMark Phalan 	    cred = NULL;
2257c478bd9Sstevel@tonic-gate 	    goto cleanup;
2267c478bd9Sstevel@tonic-gate 	}
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	cred->usage = GSS_C_INITIATE; /* we can't accept with this */
2297c478bd9Sstevel@tonic-gate 	/* cred->princ already set */
2307c478bd9Sstevel@tonic-gate 	cred->prerfc_mech = 1; /* this cred will work with all three mechs */
2317c478bd9Sstevel@tonic-gate 	cred->rfc_mech = 1;
2327c478bd9Sstevel@tonic-gate 	cred->keytab = NULL; /* no keytab associated with this... */
233159d09a2SMark Phalan 	cred->tgt_expire = creds[0]->times.endtime; /* store the end time */
234ab9b2e15Sgtb 	cred->ccache = ccache; /* the ccache containing the credential */
235ab9b2e15Sgtb 	ccache = NULL; /* cred takes ownership so don't destroy */
2367c478bd9Sstevel@tonic-gate     }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate     /* If there were errors, there might have been a memory leak
2397c478bd9Sstevel@tonic-gate        if (!cred)
2407c478bd9Sstevel@tonic-gate        if ((retval = krb5_cc_close(context, ccache)))
2417c478bd9Sstevel@tonic-gate        goto cleanup;
2427c478bd9Sstevel@tonic-gate     */
2437c478bd9Sstevel@tonic-gate cleanup:
244ab9b2e15Sgtb     if (creds)
2457c478bd9Sstevel@tonic-gate 	krb5_free_tgt_creds(context, creds);
2467c478bd9Sstevel@tonic-gate 
247ab9b2e15Sgtb     if (ccache)
248ab9b2e15Sgtb 	(void)krb5_cc_destroy(context, ccache);
249ab9b2e15Sgtb 
2507c478bd9Sstevel@tonic-gate     if (out_cred)
2517c478bd9Sstevel@tonic-gate 	*out_cred = cred; /* return credential */
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate     if (new_auth_ctx)
2547c478bd9Sstevel@tonic-gate 	krb5_auth_con_free(context, new_auth_ctx);
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate     krb5_auth_con_setflags(context, auth_context, flags_org);
2577c478bd9Sstevel@tonic-gate 
258159d09a2SMark Phalan     /* Solaris Kerberos */
2597c478bd9Sstevel@tonic-gate     KRB5_LOG(KRB5_INFO, "rd_and_store_for_creds() end retval %d", retval);
2607c478bd9Sstevel@tonic-gate     return retval;
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
263ab9b2e15Sgtb /*
264ab9b2e15Sgtb  * SUNW15resync
265ab9b2e15Sgtb  * Most of the logic here left "as is" because of lots of fixes MIT
266ab9b2e15Sgtb  * does not have yet
267ab9b2e15Sgtb  */
2687c478bd9Sstevel@tonic-gate OM_uint32
krb5_gss_accept_sec_context(minor_status,context_handle,verifier_cred_handle,input_token,input_chan_bindings,src_name,mech_type,output_token,ret_flags,time_rec,delegated_cred_handle)269ab9b2e15Sgtb krb5_gss_accept_sec_context(minor_status, context_handle,
2707c478bd9Sstevel@tonic-gate 			    verifier_cred_handle, input_token,
2717c478bd9Sstevel@tonic-gate 			    input_chan_bindings, src_name, mech_type,
2727c478bd9Sstevel@tonic-gate 			    output_token, ret_flags, time_rec,
2737c478bd9Sstevel@tonic-gate 			    delegated_cred_handle)
2747c478bd9Sstevel@tonic-gate      OM_uint32 *minor_status;
2757c478bd9Sstevel@tonic-gate      gss_ctx_id_t *context_handle;
2767c478bd9Sstevel@tonic-gate      gss_cred_id_t verifier_cred_handle;
2777c478bd9Sstevel@tonic-gate      gss_buffer_t input_token;
2787c478bd9Sstevel@tonic-gate      gss_channel_bindings_t input_chan_bindings;
2797c478bd9Sstevel@tonic-gate      gss_name_t *src_name;
2807c478bd9Sstevel@tonic-gate      gss_OID *mech_type;
2817c478bd9Sstevel@tonic-gate      gss_buffer_t output_token;
2827c478bd9Sstevel@tonic-gate      OM_uint32 *ret_flags;
2837c478bd9Sstevel@tonic-gate      OM_uint32 *time_rec;
2847c478bd9Sstevel@tonic-gate      gss_cred_id_t *delegated_cred_handle;
2857c478bd9Sstevel@tonic-gate {
286ab9b2e15Sgtb    krb5_context context;
2877c478bd9Sstevel@tonic-gate    unsigned char *ptr, *ptr2;
288ba7b222eSGlenn Barry    krb5_gss_ctx_id_rec *ctx = 0;
2897c478bd9Sstevel@tonic-gate    char *sptr;
2907c478bd9Sstevel@tonic-gate    long tmp;
2917c478bd9Sstevel@tonic-gate    size_t md5len;
2927c478bd9Sstevel@tonic-gate    int bigend;
2937c478bd9Sstevel@tonic-gate    krb5_gss_cred_id_t cred = 0;
2947c478bd9Sstevel@tonic-gate    krb5_data ap_rep, ap_req;
2957c478bd9Sstevel@tonic-gate    krb5_ap_req *request = NULL;
2967c478bd9Sstevel@tonic-gate    int i;
2977c478bd9Sstevel@tonic-gate    krb5_error_code code;
2987c478bd9Sstevel@tonic-gate    krb5_address addr, *paddr;
2997c478bd9Sstevel@tonic-gate    krb5_authenticator *authdat = 0;
3007c478bd9Sstevel@tonic-gate    krb5_checksum reqcksum;
3015e01956fSGlenn Barry    krb5_principal client_name = NULL;
3025e01956fSGlenn Barry    krb5_principal server_name = NULL;
3037c478bd9Sstevel@tonic-gate    krb5_ui_4 gss_flags = 0;
3047c478bd9Sstevel@tonic-gate    krb5_timestamp now;
3057c478bd9Sstevel@tonic-gate    gss_buffer_desc token;
3067c478bd9Sstevel@tonic-gate    krb5_auth_context auth_context = NULL;
3077c478bd9Sstevel@tonic-gate    krb5_ticket * ticket = NULL;
3087c478bd9Sstevel@tonic-gate    int option_id;
3097c478bd9Sstevel@tonic-gate    krb5_data option;
3107c478bd9Sstevel@tonic-gate    const gss_OID_desc *mech_used = NULL;
3117c478bd9Sstevel@tonic-gate    OM_uint32 major_status = GSS_S_FAILURE;
3127c478bd9Sstevel@tonic-gate    krb5_error krb_error_data;
3137c478bd9Sstevel@tonic-gate    krb5_data scratch;
3147c478bd9Sstevel@tonic-gate    gss_cred_id_t cred_handle = NULL;
3157c478bd9Sstevel@tonic-gate    krb5_gss_cred_id_t deleg_cred = NULL;
3167c478bd9Sstevel@tonic-gate    OM_uint32 saved_ap_options = 0;
317ab9b2e15Sgtb    krb5int_access kaccess;
318ab9b2e15Sgtb    int cred_rcache = 0;
319ba7b222eSGlenn Barry    int no_encap;
320ba7b222eSGlenn Barry    OM_uint32 t_minor_status = 0;
3215e01956fSGlenn Barry    int acquire_fail = 0;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate    KRB5_LOG0(KRB5_INFO,"krb5_gss_accept_sec_context() start");
3247c478bd9Sstevel@tonic-gate 
325a43e85c5SMark Phalan    /* Solaris Kerberos */
326a43e85c5SMark Phalan    memset(&krb_error_data, 0, sizeof(krb_error_data));
327a43e85c5SMark Phalan 
328ab9b2e15Sgtb    code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
329ab9b2e15Sgtb    if (code) {
330ab9b2e15Sgtb        *minor_status = code;
3317c478bd9Sstevel@tonic-gate        return(GSS_S_FAILURE);
332ab9b2e15Sgtb    }
333ab9b2e15Sgtb 
334ab9b2e15Sgtb    code = krb5_gss_init_context(&context);
335ab9b2e15Sgtb    if (code) {
336ab9b2e15Sgtb        *minor_status = code;
337ab9b2e15Sgtb        return GSS_S_FAILURE;
338ab9b2e15Sgtb    }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate    /* set up returns to be freeable */
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate    if (src_name)
3437c478bd9Sstevel@tonic-gate       *src_name = (gss_name_t) NULL;
3447c478bd9Sstevel@tonic-gate    output_token->length = 0;
3457c478bd9Sstevel@tonic-gate    output_token->value = NULL;
3467c478bd9Sstevel@tonic-gate    token.value = 0;
3477c478bd9Sstevel@tonic-gate    reqcksum.contents = 0;
3487c478bd9Sstevel@tonic-gate    ap_req.data = 0;
3497c478bd9Sstevel@tonic-gate    ap_rep.data = 0;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate    if (mech_type)
3527c478bd9Sstevel@tonic-gate       *mech_type = GSS_C_NULL_OID;
3537c478bd9Sstevel@tonic-gate    /* initialize the delegated cred handle to NO_CREDENTIAL for now */
3547c478bd9Sstevel@tonic-gate    if (delegated_cred_handle)
3557c478bd9Sstevel@tonic-gate       *delegated_cred_handle = GSS_C_NO_CREDENTIAL;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate    /*
3587c478bd9Sstevel@tonic-gate     * Context handle must be unspecified.  Actually, it must be
3597c478bd9Sstevel@tonic-gate     * non-established, but currently, accept_sec_context never returns
3607c478bd9Sstevel@tonic-gate     * a non-established context handle.
3617c478bd9Sstevel@tonic-gate     */
3627c478bd9Sstevel@tonic-gate    /*SUPPRESS 29*/
3637c478bd9Sstevel@tonic-gate    if (*context_handle != GSS_C_NO_CONTEXT) {
3647c478bd9Sstevel@tonic-gate       *minor_status = 0;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate        /* Solaris kerberos: the original Solaris code returned GSS_S_NO_CONTEXT
3677c478bd9Sstevel@tonic-gate 	* for this error.  This conflicts somewhat with RFC2743 which states
3687c478bd9Sstevel@tonic-gate 	* GSS_S_NO_CONTEXT should be returned only for sucessor calls following
3697c478bd9Sstevel@tonic-gate 	* GSS_S_CONTINUE_NEEDED status returns.  Note the MIT code doesn't
3707c478bd9Sstevel@tonic-gate 	* return GSS_S_NO_CONTEXT at all.
3717c478bd9Sstevel@tonic-gate 	*/
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate       major_status = GSS_S_NO_CONTEXT;
3747c478bd9Sstevel@tonic-gate       KRB5_LOG0(KRB5_ERR,"krb5_gss_accept_sec_context() "
3757c478bd9Sstevel@tonic-gate 	      "error GSS_S_NO_CONTEXT");
376ab9b2e15Sgtb       goto cleanup;
3777c478bd9Sstevel@tonic-gate    }
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate    /* verify the token's integrity, and leave the token in ap_req.
3807c478bd9Sstevel@tonic-gate       figure out which mech oid was used, and save it */
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate    ptr = (unsigned char *) input_token->value;
3837c478bd9Sstevel@tonic-gate 
384ab9b2e15Sgtb    if (!(code = g_verify_token_header(gss_mech_krb5,
3857c478bd9Sstevel@tonic-gate 				      (uint32_t *)&(ap_req.length),
3867c478bd9Sstevel@tonic-gate 				      &ptr, KG_TOK_CTX_AP_REQ,
3877c478bd9Sstevel@tonic-gate 				      input_token->length, 1))) {
3887c478bd9Sstevel@tonic-gate        mech_used = gss_mech_krb5;
3897c478bd9Sstevel@tonic-gate    } else if ((code == G_WRONG_MECH) &&
39072f0806aSShawn Emery 		!(code = g_verify_token_header(gss_mech_krb5_wrong,
39172f0806aSShawn Emery 						(uint32_t *)&(ap_req.length),
39272f0806aSShawn Emery 						&ptr, KG_TOK_CTX_AP_REQ,
39372f0806aSShawn Emery 						input_token->length, 1))) {
39472f0806aSShawn Emery 	mech_used = gss_mech_krb5_wrong;
39572f0806aSShawn Emery    } else if ((code == G_WRONG_MECH) &&
396ab9b2e15Sgtb 	      !(code = g_verify_token_header(gss_mech_krb5_old,
3977c478bd9Sstevel@tonic-gate 					     (uint32_t *)&(ap_req.length),
3987c478bd9Sstevel@tonic-gate 					     &ptr, KG_TOK_CTX_AP_REQ,
3997c478bd9Sstevel@tonic-gate 					     input_token->length, 1))) {
4007c478bd9Sstevel@tonic-gate        /*
4017c478bd9Sstevel@tonic-gate 	* Previous versions of this library used the old mech_id
4027c478bd9Sstevel@tonic-gate 	* and some broken behavior (wrong IV on checksum
4037c478bd9Sstevel@tonic-gate 	* encryption).  We support the old mech_id for
4047c478bd9Sstevel@tonic-gate 	* compatibility, and use it to decide when to use the
4057c478bd9Sstevel@tonic-gate 	* old behavior.
4067c478bd9Sstevel@tonic-gate 	*/
4077c478bd9Sstevel@tonic-gate        mech_used = gss_mech_krb5_old;
408ba7b222eSGlenn Barry   } else if (code == G_WRONG_TOKID) {
409ba7b222eSGlenn Barry 	major_status = GSS_S_CONTINUE_NEEDED;
410ba7b222eSGlenn Barry         code = KRB5KRB_AP_ERR_MSG_TYPE;
411ba7b222eSGlenn Barry         mech_used = gss_mech_krb5;
412ba7b222eSGlenn Barry         goto fail;
413ba7b222eSGlenn Barry    } else if (code == G_BAD_TOK_HEADER) {
414ba7b222eSGlenn Barry 	/* DCE style not encapsulated */
415ba7b222eSGlenn Barry         ap_req.length = input_token->length;
416ba7b222eSGlenn Barry         ap_req.data = input_token->value;
417ba7b222eSGlenn Barry         mech_used = gss_mech_krb5;
418ba7b222eSGlenn Barry         no_encap = 1;
4197c478bd9Sstevel@tonic-gate    } else {
4207c478bd9Sstevel@tonic-gate 	major_status = GSS_S_DEFECTIVE_TOKEN;
4217c478bd9Sstevel@tonic-gate         goto fail;
4227c478bd9Sstevel@tonic-gate    }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate    sptr = (char *) ptr;
4257c478bd9Sstevel@tonic-gate    TREAD_STR(sptr, ap_req.data, ap_req.length);
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate    /*
4287c478bd9Sstevel@tonic-gate     * Solaris Kerberos:
4297c478bd9Sstevel@tonic-gate     *  We need to decode the request now so that we can get the
4307c478bd9Sstevel@tonic-gate     *  service principal in order to try and acquire a cred for it.
4317c478bd9Sstevel@tonic-gate     *  below in the "handle default cred handle" code block.
4327c478bd9Sstevel@tonic-gate     */
4337c478bd9Sstevel@tonic-gate    if (!krb5_is_ap_req(&ap_req)) {
4347c478bd9Sstevel@tonic-gate        code = KRB5KRB_AP_ERR_MSG_TYPE;
4357c478bd9Sstevel@tonic-gate        goto fail;
4367c478bd9Sstevel@tonic-gate    }
4377c478bd9Sstevel@tonic-gate    /* decode the AP-REQ into request */
4387c478bd9Sstevel@tonic-gate    if ((code = decode_krb5_ap_req(&ap_req, &request))) {
4397c478bd9Sstevel@tonic-gate        if (code == KRB5_BADMSGTYPE)
4407c478bd9Sstevel@tonic-gate            code = KRB5KRB_AP_ERR_BADVERSION;
4417c478bd9Sstevel@tonic-gate        goto fail;
4427c478bd9Sstevel@tonic-gate    }
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate    /* handle default cred handle */
4453dba6097Smp153739    /*
4463dba6097Smp153739     * Solaris Kerberos:
4473dba6097Smp153739     * If there is no princ associated with the cred then treat it the
4483dba6097Smp153739     * the same as GSS_C_NO_CREDENTIAL.
4493dba6097Smp153739     */
4503dba6097Smp153739    if (verifier_cred_handle == GSS_C_NO_CREDENTIAL ||
4513dba6097Smp153739     ((krb5_gss_cred_id_t)verifier_cred_handle)->princ == NULL) {
4527c478bd9Sstevel@tonic-gate        /* Note that we try to acquire a cred for the service principal
4537c478bd9Sstevel@tonic-gate 	* named in the AP-REQ. This allows us to implement option (ii)
4547c478bd9Sstevel@tonic-gate 	* of the recommended behaviour for GSS_Accept_sec_context() as
4557c478bd9Sstevel@tonic-gate 	* described in section 1.1.1.3 of RFC2743.
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	* This is far more useful that option (i), for which we would
4587c478bd9Sstevel@tonic-gate 	* acquire a cred for GSS_C_NO_NAME.
4597c478bd9Sstevel@tonic-gate 	*/
4607c478bd9Sstevel@tonic-gate        /* copy the princ from the ap-req or we'll lose it when we free
4617c478bd9Sstevel@tonic-gate 	  the ap-req */
4627c478bd9Sstevel@tonic-gate        krb5_principal princ;
4637c478bd9Sstevel@tonic-gate        if ((code = krb5_copy_principal(context, request->ticket->server,
4647c478bd9Sstevel@tonic-gate 				       &princ))) {
4657c478bd9Sstevel@tonic-gate            KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
4667c478bd9Sstevel@tonic-gate 	            "krb5_copy_principal() error code %d", code);
4677c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
4687c478bd9Sstevel@tonic-gate 	   goto fail;
4697c478bd9Sstevel@tonic-gate        }
4707c478bd9Sstevel@tonic-gate        /* intern the acceptor name */
4717c478bd9Sstevel@tonic-gate        if (! kg_save_name((gss_name_t) princ)) {
4727c478bd9Sstevel@tonic-gate 	   code = G_VALIDATE_FAILED;
4737c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
4747c478bd9Sstevel@tonic-gate 	   goto fail;
4757c478bd9Sstevel@tonic-gate        }
476ab9b2e15Sgtb        major_status = krb5_gss_acquire_cred((OM_uint32*) &code,
4777c478bd9Sstevel@tonic-gate 					    (gss_name_t) princ,
4787c478bd9Sstevel@tonic-gate 					    GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
4797c478bd9Sstevel@tonic-gate 					    GSS_C_ACCEPT, &cred_handle,
4807c478bd9Sstevel@tonic-gate 					    NULL, NULL);
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate        if (major_status != GSS_S_COMPLETE){
4837c478bd9Sstevel@tonic-gate 	   /* Solaris kerberos: RFC2743 indicate this should be returned if we
4847c478bd9Sstevel@tonic-gate 	    * can't aquire a default cred.
4857c478bd9Sstevel@tonic-gate 	    */
4867c478bd9Sstevel@tonic-gate 	   KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() "
4877c478bd9Sstevel@tonic-gate 		  "krb5_gss_acquire_cred() error"
4887c478bd9Sstevel@tonic-gate 		   "orig major_status = %d, now = GSS_S_NO_CRED\n",
4897c478bd9Sstevel@tonic-gate 		   major_status);
4905e01956fSGlenn Barry 	   acquire_fail = 1;
4917c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_NO_CRED;
4927c478bd9Sstevel@tonic-gate 	   goto fail;
4937c478bd9Sstevel@tonic-gate        }
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate    } else {
4967c478bd9Sstevel@tonic-gate        cred_handle = verifier_cred_handle;
4977c478bd9Sstevel@tonic-gate    }
4987c478bd9Sstevel@tonic-gate 
499ab9b2e15Sgtb    major_status = krb5_gss_validate_cred((OM_uint32*) &code,
5007c478bd9Sstevel@tonic-gate 						 cred_handle);
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate    if (GSS_ERROR(major_status)){
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate        /* Solaris kerberos: RFC2743 indicate GSS_S_NO_CRED should be returned if
5057c478bd9Sstevel@tonic-gate 	* the supplied cred isn't valid.
5067c478bd9Sstevel@tonic-gate 	*/
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate        KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() "
5097c478bd9Sstevel@tonic-gate 	      "krb5_gss_validate_cred() error"
5107c478bd9Sstevel@tonic-gate 	       "orig major_status = %d, now = GSS_S_NO_CRED\n",
5117c478bd9Sstevel@tonic-gate 	       major_status);
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate        major_status = GSS_S_NO_CRED;
5147c478bd9Sstevel@tonic-gate        goto fail;
5157c478bd9Sstevel@tonic-gate    }
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate    cred = (krb5_gss_cred_id_t) cred_handle;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate    /* make sure the supplied credentials are valid for accept */
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate    if ((cred->usage != GSS_C_ACCEPT) &&
5227c478bd9Sstevel@tonic-gate        (cred->usage != GSS_C_BOTH)) {
5237c478bd9Sstevel@tonic-gate        code = 0;
5247c478bd9Sstevel@tonic-gate       KRB5_LOG0(KRB5_ERR,"krb5_gss_accept_sec_context() "
5257c478bd9Sstevel@tonic-gate 	      "error GSS_S_NO_CONTEXT");
5267c478bd9Sstevel@tonic-gate        major_status = GSS_S_NO_CRED;
5277c478bd9Sstevel@tonic-gate        goto fail;
5287c478bd9Sstevel@tonic-gate    }
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate    /* construct the sender_addr */
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate    if ((input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) &&
5337c478bd9Sstevel@tonic-gate        (input_chan_bindings->initiator_addrtype == GSS_C_AF_INET)) {
5347c478bd9Sstevel@tonic-gate        /* XXX is this right? */
5357c478bd9Sstevel@tonic-gate        addr.addrtype = ADDRTYPE_INET;
5367c478bd9Sstevel@tonic-gate        addr.length = input_chan_bindings->initiator_address.length;
5377c478bd9Sstevel@tonic-gate        addr.contents = input_chan_bindings->initiator_address.value;
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate        paddr = &addr;
5407c478bd9Sstevel@tonic-gate    } else {
5417c478bd9Sstevel@tonic-gate        paddr = NULL;
5427c478bd9Sstevel@tonic-gate    }
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate    /* verify the AP_REQ message - setup the auth_context and rcache */
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate    if ((code = krb5_auth_con_init(context, &auth_context))) {
5477c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
5485e01956fSGlenn Barry        save_error_info((OM_uint32)code, context);
549159d09a2SMark Phalan        /* Solaris Kerberos */
5507c478bd9Sstevel@tonic-gate        KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
5517c478bd9Sstevel@tonic-gate 	      "krb5_auth_con_init() error code %d", code);
5527c478bd9Sstevel@tonic-gate        goto fail;
5537c478bd9Sstevel@tonic-gate    }
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate    (void) krb5_auth_con_setflags(context, auth_context,
5567c478bd9Sstevel@tonic-gate                           KRB5_AUTH_CONTEXT_DO_SEQUENCE);
5577c478bd9Sstevel@tonic-gate 
558ab9b2e15Sgtb    if (cred->rcache) {
559ab9b2e15Sgtb        cred_rcache = 1;
560ab9b2e15Sgtb        if ((code = krb5_auth_con_setrcache(context, auth_context, cred->rcache))) {
5617c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
562159d09a2SMark Phalan            /* Solaris Kerberos */
5637c478bd9Sstevel@tonic-gate 	   KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
5647c478bd9Sstevel@tonic-gate 		    "krb5_auth_con_setrcache() error code %d", code);
5657c478bd9Sstevel@tonic-gate 	   goto fail;
5667c478bd9Sstevel@tonic-gate        }
567ab9b2e15Sgtb    }
5687c478bd9Sstevel@tonic-gate    if ((code = krb5_auth_con_setaddrs(context, auth_context, NULL, paddr))) {
5697c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
570159d09a2SMark Phalan        /* Solaris Kerberos */
5717c478bd9Sstevel@tonic-gate        KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
5727c478bd9Sstevel@tonic-gate 	      "krb5_auth_con_setaddrs() error code %d", code);
5737c478bd9Sstevel@tonic-gate        goto fail;
5747c478bd9Sstevel@tonic-gate    }
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate    if ((code = krb5_rd_req_decoded(context, &auth_context, request,
5777c478bd9Sstevel@tonic-gate 			   cred->princ, cred->keytab, NULL, &ticket))) {
5787c478bd9Sstevel@tonic-gate        KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
5797c478bd9Sstevel@tonic-gate 	      "krb5_rd_req() error code %d", code);
5805e01956fSGlenn Barry        if (code == KRB5_KT_KVNONOTFOUND) {
5815e01956fSGlenn Barry 	   char *s_name;
5825e01956fSGlenn Barry 	   if (krb5_unparse_name(context, cred->princ, &s_name) == 0) {
5835e01956fSGlenn Barry 	       krb5_set_error_message(context, KRB5KRB_AP_ERR_BADKEYVER,
5845e01956fSGlenn Barry 				    dgettext(TEXT_DOMAIN,
5855e01956fSGlenn Barry 					    "Key version %d is not available for principal %s"),
5865e01956fSGlenn Barry 				    request->ticket->enc_part.kvno,
5875e01956fSGlenn Barry 				    s_name);
5885e01956fSGlenn Barry 	       krb5_free_unparsed_name(context, s_name);
5895e01956fSGlenn Barry 	   }
5905e01956fSGlenn Barry 	   major_status = GSS_S_DEFECTIVE_CREDENTIAL;
5915e01956fSGlenn Barry 	   code = KRB5KRB_AP_ERR_BADKEYVER;
5925e01956fSGlenn Barry        } else if (code == KRB5_KT_NOTFOUND) {
5935e01956fSGlenn Barry 	   char *s_name;
5945e01956fSGlenn Barry 	   if (krb5_unparse_name(context, cred->princ, &s_name) == 0) {
5955e01956fSGlenn Barry 	       krb5_set_error_message(context, KRB5KRB_AP_ERR_NOKEY,
5965e01956fSGlenn Barry 				    dgettext(TEXT_DOMAIN,
5975e01956fSGlenn Barry 					    "Service key %s not available"),
5985e01956fSGlenn Barry 				    s_name);
5995e01956fSGlenn Barry 	       krb5_free_unparsed_name(context, s_name);
6005e01956fSGlenn Barry 	   }
6017c478bd9Sstevel@tonic-gate            major_status = GSS_S_DEFECTIVE_CREDENTIAL;
6027c478bd9Sstevel@tonic-gate 	   code = KRB5KRB_AP_ERR_NOKEY;
6037c478bd9Sstevel@tonic-gate        }
6047c478bd9Sstevel@tonic-gate        else if (code == KRB5KRB_AP_WRONG_PRINC) {
6057c478bd9Sstevel@tonic-gate            major_status = GSS_S_NO_CRED;
6067c478bd9Sstevel@tonic-gate 	   code = KRB5KRB_AP_ERR_NOT_US;
6077c478bd9Sstevel@tonic-gate        }
6087c478bd9Sstevel@tonic-gate        else if (code == KRB5KRB_AP_ERR_REPEAT)
6097c478bd9Sstevel@tonic-gate            major_status = GSS_S_DUPLICATE_TOKEN;
6107c478bd9Sstevel@tonic-gate        else
6117c478bd9Sstevel@tonic-gate            major_status = GSS_S_FAILURE;
6127c478bd9Sstevel@tonic-gate        goto fail;
6137c478bd9Sstevel@tonic-gate    }
614159d09a2SMark Phalan    krb5_auth_con_setflags(context, auth_context,
615159d09a2SMark Phalan 			  KRB5_AUTH_CONTEXT_DO_SEQUENCE);
6167c478bd9Sstevel@tonic-gate 
6177e0c352dSMark Phalan    /* Solaris Kerberos */
6187e0c352dSMark Phalan    code = krb5_auth_con_getauthenticator(context, auth_context, &authdat);
6197e0c352dSMark Phalan    if (code) {
6207e0c352dSMark Phalan 	   KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
6217e0c352dSMark Phalan 		  "krb5_auth_con_getauthenticator() error code %d", code);
6227e0c352dSMark Phalan 	   major_status = GSS_S_FAILURE;
6237e0c352dSMark Phalan 	   goto fail;
6247e0c352dSMark Phalan    }
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate #if 0
6277c478bd9Sstevel@tonic-gate    /* make sure the necessary parts of the authdat are present */
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate    if ((authdat->authenticator->subkey == NULL) ||
6307c478bd9Sstevel@tonic-gate        (authdat->ticket->enc_part2 == NULL)) {
6317c478bd9Sstevel@tonic-gate 	   code = KG_NO_SUBKEY;
6327c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
6337c478bd9Sstevel@tonic-gate 	   goto fail;
6347c478bd9Sstevel@tonic-gate    }
6357c478bd9Sstevel@tonic-gate #endif
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate    {
6387c478bd9Sstevel@tonic-gate        /* gss krb5 v1 */
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate        /* stash this now, for later. */
641159d09a2SMark Phalan        code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &md5len);
642159d09a2SMark Phalan        if (code) {
643159d09a2SMark Phalan 	   /* Solaris Kerberos */
6447c478bd9Sstevel@tonic-gate 	   KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
6457c478bd9Sstevel@tonic-gate 		  "krb5_c_checksum_length() error code %d", code);
6467c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
6477c478bd9Sstevel@tonic-gate 	   goto fail;
6487c478bd9Sstevel@tonic-gate        }
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate        /* verify that the checksum is correct */
651b429bb60SZdenek Kotala        if (authdat->checksum == NULL) {
652b429bb60SZdenek Kotala           /* missing checksum counts as "inappropriate type" */
653b429bb60SZdenek Kotala           code = KRB5KRB_AP_ERR_INAPP_CKSUM;
654b429bb60SZdenek Kotala           major_status = GSS_S_FAILURE;
655b429bb60SZdenek Kotala           goto fail;
656b429bb60SZdenek Kotala        }
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate        /*
6597c478bd9Sstevel@tonic-gate 	 The checksum may be either exactly 24 bytes, in which case
6607c478bd9Sstevel@tonic-gate 	 no options are specified, or greater than 24 bytes, in which case
6617c478bd9Sstevel@tonic-gate 	 one or more options are specified. Currently, the only valid
6627c478bd9Sstevel@tonic-gate 	 option is KRB5_GSS_FOR_CREDS_OPTION ( = 1 ).
6637c478bd9Sstevel@tonic-gate        */
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate        if ((authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) ||
6667c478bd9Sstevel@tonic-gate 	   (authdat->checksum->length < 24)) {
6677c478bd9Sstevel@tonic-gate 	   code = 0;
6687c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_BAD_BINDINGS;
6697c478bd9Sstevel@tonic-gate 	   goto fail;
6707c478bd9Sstevel@tonic-gate        }
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate        /*
6737c478bd9Sstevel@tonic-gate 	 "Be liberal in what you accept, and
6747c478bd9Sstevel@tonic-gate 	 conservative in what you send"
6757c478bd9Sstevel@tonic-gate 	 -- rfc1123
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	 This code will let this acceptor interoperate with an initiator
6787c478bd9Sstevel@tonic-gate 	 using little-endian or big-endian integer encoding.
6797c478bd9Sstevel@tonic-gate        */
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate        ptr = (unsigned char *) authdat->checksum->contents;
6827c478bd9Sstevel@tonic-gate        bigend = 0;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate        TREAD_INT(ptr, tmp, bigend);
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate        if (tmp != md5len) {
6877c478bd9Sstevel@tonic-gate 	   ptr = (unsigned char *) authdat->checksum->contents;
6887c478bd9Sstevel@tonic-gate 	   bigend = 1;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	   TREAD_INT(ptr, tmp, bigend);
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	   if (tmp != md5len) {
6937c478bd9Sstevel@tonic-gate 	       code = KG_BAD_LENGTH;
6947c478bd9Sstevel@tonic-gate 	       major_status = GSS_S_FAILURE;
6957c478bd9Sstevel@tonic-gate 	       goto fail;
6967c478bd9Sstevel@tonic-gate 	   }
6977c478bd9Sstevel@tonic-gate        }
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate        /* at this point, bigend is set according to the initiator's
7007c478bd9Sstevel@tonic-gate 	  byte order */
7017c478bd9Sstevel@tonic-gate 
702159d09a2SMark Phalan 
7037c478bd9Sstevel@tonic-gate        /*
7047c478bd9Sstevel@tonic-gate           The following section of code attempts to implement the
7057c478bd9Sstevel@tonic-gate           optional channel binding facility as described in RFC2743.
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate           Since this facility is optional channel binding may or may
7087c478bd9Sstevel@tonic-gate           not have been provided by either the client or the server.
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate           If the server has specified input_chan_bindings equal to
7117c478bd9Sstevel@tonic-gate           GSS_C_NO_CHANNEL_BINDINGS then we skip the check.  If
7127c478bd9Sstevel@tonic-gate           the server does provide channel bindings then we compute
7137c478bd9Sstevel@tonic-gate           a checksum and compare against those provided by the
7147c478bd9Sstevel@tonic-gate           client.  If the check fails we test the clients checksum
7157c478bd9Sstevel@tonic-gate           to see whether the client specified GSS_C_NO_CHANNEL_BINDINGS.
7167c478bd9Sstevel@tonic-gate           If either test succeeds we continue without error.
7177c478bd9Sstevel@tonic-gate         */
718159d09a2SMark Phalan        if ((code = kg_checksum_channel_bindings(context,
719159d09a2SMark Phalan 						input_chan_bindings,
7207c478bd9Sstevel@tonic-gate 						&reqcksum, bigend))) {
721159d09a2SMark Phalan 	   /* Solaris Kerberos */
7227c478bd9Sstevel@tonic-gate 	   KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
7237c478bd9Sstevel@tonic-gate 		  "kg_checksum_channel_bindings() error code %d", code);
7247c478bd9Sstevel@tonic-gate 	 major_status = GSS_S_BAD_BINDINGS;
7257c478bd9Sstevel@tonic-gate 	 goto fail;
7267c478bd9Sstevel@tonic-gate        }
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate        TREAD_STR(ptr, ptr2, reqcksum.length);
729159d09a2SMark Phalan 
7307c478bd9Sstevel@tonic-gate        if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS ) {
7317c478bd9Sstevel@tonic-gate            if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
7327c478bd9Sstevel@tonic-gate                xfree(reqcksum.contents);
7337c478bd9Sstevel@tonic-gate                reqcksum.contents = 0;
7347c478bd9Sstevel@tonic-gate 		if ((code = kg_checksum_channel_bindings(context,
7357c478bd9Sstevel@tonic-gate                                                   GSS_C_NO_CHANNEL_BINDINGS,
7367c478bd9Sstevel@tonic-gate                                                   &reqcksum, bigend))) {
7377c478bd9Sstevel@tonic-gate                    major_status = GSS_S_BAD_BINDINGS;
7387c478bd9Sstevel@tonic-gate                    goto fail;
7397c478bd9Sstevel@tonic-gate 		}
7407c478bd9Sstevel@tonic-gate                if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
7417c478bd9Sstevel@tonic-gate                    code = 0;
7427c478bd9Sstevel@tonic-gate                    major_status = GSS_S_BAD_BINDINGS;
7437c478bd9Sstevel@tonic-gate                    goto fail;
7447c478bd9Sstevel@tonic-gate 		}
7457c478bd9Sstevel@tonic-gate            }
746159d09a2SMark Phalan 
7477c478bd9Sstevel@tonic-gate        }
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate        TREAD_INT(ptr, gss_flags, bigend);
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate        /* if the checksum length > 24, there are options to process */
7527c478bd9Sstevel@tonic-gate 
753159d09a2SMark Phalan        if(authdat->checksum->length > 24 && (gss_flags & GSS_C_DELEG_FLAG)) {
754159d09a2SMark Phalan 
7557c478bd9Sstevel@tonic-gate 	   i = authdat->checksum->length - 24;
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	   if (i >= 4) {
758159d09a2SMark Phalan 
7597c478bd9Sstevel@tonic-gate 	       TREAD_INT16(ptr, option_id, bigend);
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	       TREAD_INT16(ptr, option.length, bigend);
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	       i -= 4;
764159d09a2SMark Phalan 
7657c478bd9Sstevel@tonic-gate 	       if (i < option.length || option.length < 0) {
7667c478bd9Sstevel@tonic-gate 		   code = KG_BAD_LENGTH;
7677c478bd9Sstevel@tonic-gate 		   major_status = GSS_S_FAILURE;
7687c478bd9Sstevel@tonic-gate 		   goto fail;
7697c478bd9Sstevel@tonic-gate 	       }
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	       /* have to use ptr2, since option.data is wrong type and
7727c478bd9Sstevel@tonic-gate 		  macro uses ptr as both lvalue and rvalue */
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	       TREAD_STR(ptr, ptr2, option.length);
7757c478bd9Sstevel@tonic-gate 	       option.data = (char *) ptr2;
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	       i -= option.length;
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	       if (option_id != KRB5_GSS_FOR_CREDS_OPTION) {
7807c478bd9Sstevel@tonic-gate 		   major_status = GSS_S_FAILURE;
7817c478bd9Sstevel@tonic-gate 		   goto fail;
7827c478bd9Sstevel@tonic-gate 	       }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 		   /* store the delegated credential */
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 		   code = rd_and_store_for_creds(context, auth_context, &option,
787159d09a2SMark Phalan 						 (delegated_cred_handle) ?
788159d09a2SMark Phalan 						 &deleg_cred : NULL);
7897c478bd9Sstevel@tonic-gate 		   if (code) {
7907c478bd9Sstevel@tonic-gate 		       major_status = GSS_S_FAILURE;
7917c478bd9Sstevel@tonic-gate 		       goto fail;
7927c478bd9Sstevel@tonic-gate 		   }
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	   } /* if i >= 4 */
7957c478bd9Sstevel@tonic-gate 	   /* ignore any additional trailing data, for now */
796159d09a2SMark Phalan #ifdef CFX_EXERCISE
797159d09a2SMark Phalan 	   {
798159d09a2SMark Phalan 	       FILE *f = fopen("/tmp/gsslog", "a");
799159d09a2SMark Phalan 	       if (f) {
800159d09a2SMark Phalan 		   fprintf(f,
801159d09a2SMark Phalan 			   "initial context token with delegation, %d extra bytes\n",
802159d09a2SMark Phalan 			   i);
803159d09a2SMark Phalan 		   fclose(f);
804159d09a2SMark Phalan 	       }
805159d09a2SMark Phalan 	   }
806159d09a2SMark Phalan #endif
807159d09a2SMark Phalan        } else {
808159d09a2SMark Phalan #ifdef CFX_EXERCISE
809159d09a2SMark Phalan 	   {
810159d09a2SMark Phalan 	       FILE *f = fopen("/tmp/gsslog", "a");
811159d09a2SMark Phalan 	       if (f) {
812159d09a2SMark Phalan 		   if (gss_flags & GSS_C_DELEG_FLAG)
813159d09a2SMark Phalan 		       fprintf(f,
814159d09a2SMark Phalan 			       "initial context token, delegation flag but too small\n");
815159d09a2SMark Phalan 		   else
816159d09a2SMark Phalan 		       /* no deleg flag, length might still be too big */
817159d09a2SMark Phalan 		       fprintf(f,
818159d09a2SMark Phalan 			       "initial context token, %d extra bytes\n",
819159d09a2SMark Phalan 			       authdat->checksum->length - 24);
820159d09a2SMark Phalan 		   fclose(f);
821159d09a2SMark Phalan 	       }
822159d09a2SMark Phalan 	   }
823159d09a2SMark Phalan #endif
824159d09a2SMark Phalan        }
825159d09a2SMark Phalan    }
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate    /* create the ctx struct and start filling it in */
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate    if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
8307c478bd9Sstevel@tonic-gate        == NULL) {
8317c478bd9Sstevel@tonic-gate        code = ENOMEM;
8327c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
8337c478bd9Sstevel@tonic-gate        goto fail;
8347c478bd9Sstevel@tonic-gate    }
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate    memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
837ab9b2e15Sgtb    ctx->mech_used = (gss_OID) mech_used;
8387c478bd9Sstevel@tonic-gate    ctx->auth_context = auth_context;
8397c478bd9Sstevel@tonic-gate    ctx->initiate = 0;
8407c478bd9Sstevel@tonic-gate    ctx->gss_flags = (GSS_C_TRANS_FLAG |
8417c478bd9Sstevel@tonic-gate                     ((gss_flags) & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
8427c478bd9Sstevel@tonic-gate                             GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
8437c478bd9Sstevel@tonic-gate                             GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)));
8447c478bd9Sstevel@tonic-gate    ctx->seed_init = 0;
8457c478bd9Sstevel@tonic-gate    ctx->big_endian = bigend;
846ab9b2e15Sgtb    ctx->cred_rcache = cred_rcache;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate    /* Intern the ctx pointer so that delete_sec_context works */
8497c478bd9Sstevel@tonic-gate    if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
8507c478bd9Sstevel@tonic-gate        xfree(ctx);
8517c478bd9Sstevel@tonic-gate        ctx = 0;
8527c478bd9Sstevel@tonic-gate 
853159d09a2SMark Phalan 	/* Solaris Kerberos */
8547c478bd9Sstevel@tonic-gate        KRB5_LOG0(KRB5_ERR, "krb5_gss_accept_sec_context() "
8557c478bd9Sstevel@tonic-gate 	      "kg_save_ctx_id() error");
8567c478bd9Sstevel@tonic-gate        code = G_VALIDATE_FAILED;
8577c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
8587c478bd9Sstevel@tonic-gate        goto fail;
8597c478bd9Sstevel@tonic-gate    }
8607c478bd9Sstevel@tonic-gate 
861ba7b222eSGlenn Barry    /* XXX move this into gss_name_t */
862ba7b222eSGlenn Barry    if ((code = krb5_merge_authdata(context,
863ba7b222eSGlenn Barry 				ticket->enc_part2->authorization_data,
864ba7b222eSGlenn Barry 				authdat->authorization_data,
865ba7b222eSGlenn Barry 				&ctx->authdata))) {
866ba7b222eSGlenn Barry 	major_status = GSS_S_FAILURE;
867ba7b222eSGlenn Barry         goto fail;
868ba7b222eSGlenn Barry    }
869ba7b222eSGlenn Barry 
8707c478bd9Sstevel@tonic-gate    if ((code = krb5_copy_principal(context, cred->princ, &ctx->here))) {
871159d09a2SMark Phalan 	/* Solaris Kerberos */
8727c478bd9Sstevel@tonic-gate        KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
8737c478bd9Sstevel@tonic-gate 	      "krb5_copy_principal() error code %d", code);
8747c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
8757c478bd9Sstevel@tonic-gate        goto fail;
8767c478bd9Sstevel@tonic-gate    }
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate    if ((code = krb5_copy_principal(context, authdat->client, &ctx->there))) {
879159d09a2SMark Phalan 	/* Solaris Kerberos */
8807c478bd9Sstevel@tonic-gate        KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
8817c478bd9Sstevel@tonic-gate 	      "krb5_copy_principal() 2 error code %d", code);
8827c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
8837c478bd9Sstevel@tonic-gate        goto fail;
8847c478bd9Sstevel@tonic-gate    }
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate    if ((code = krb5_auth_con_getrecvsubkey(context, auth_context,
8877c478bd9Sstevel@tonic-gate 					   &ctx->subkey))) {
888159d09a2SMark Phalan 	/* Solaris Kerberos */
8897c478bd9Sstevel@tonic-gate        KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
8907c478bd9Sstevel@tonic-gate 	      "krb5_auth_con_getremotesubkey() error code %d", code);
8917c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
8927c478bd9Sstevel@tonic-gate        goto fail;
8937c478bd9Sstevel@tonic-gate    }
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate    /* use the session key if the subkey isn't present */
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate    if (ctx->subkey == NULL) {
8987c478bd9Sstevel@tonic-gate        if ((code = krb5_auth_con_getkey(context, auth_context,
8997c478bd9Sstevel@tonic-gate 					&ctx->subkey))) {
900159d09a2SMark Phalan 	/* Solaris Kerberos */
9017c478bd9Sstevel@tonic-gate 	   KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
9027c478bd9Sstevel@tonic-gate 		      "krb5_auth_con_getkey() error code %d", code);
9037c478bd9Sstevel@tonic-gate            *minor_status = (OM_uint32) KRB5KDC_ERR_NULL_KEY;
9047c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
9057c478bd9Sstevel@tonic-gate 	   goto fail;
9067c478bd9Sstevel@tonic-gate        }
9077c478bd9Sstevel@tonic-gate    }
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate    if (ctx->subkey == NULL) {
9107c478bd9Sstevel@tonic-gate        /* this isn't a very good error, but it's not clear to me this
9117c478bd9Sstevel@tonic-gate 	  can actually happen */
9127c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
9137c478bd9Sstevel@tonic-gate        code = KRB5KDC_ERR_NULL_KEY;
9147c478bd9Sstevel@tonic-gate        goto fail;
9157c478bd9Sstevel@tonic-gate    }
9167c478bd9Sstevel@tonic-gate 
917159d09a2SMark Phalan     /* Solaris Kerberos */
9187c478bd9Sstevel@tonic-gate    KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() "
9197c478bd9Sstevel@tonic-gate 	   "ctx->subkey->enctype=%d", ctx->subkey->enctype);
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate    ctx->proto = 0;
9227c478bd9Sstevel@tonic-gate    switch(ctx->subkey->enctype) {
9237c478bd9Sstevel@tonic-gate    case ENCTYPE_DES_CBC_MD5:
9247c478bd9Sstevel@tonic-gate    case ENCTYPE_DES_CBC_CRC:
9257c478bd9Sstevel@tonic-gate        ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
9267c478bd9Sstevel@tonic-gate        ctx->signalg = SGN_ALG_DES_MAC_MD5;
9277c478bd9Sstevel@tonic-gate        ctx->cksum_size = 8;
9287c478bd9Sstevel@tonic-gate        ctx->sealalg = SEAL_ALG_DES;
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate        /* fill in the encryption descriptors */
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate        if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
9337c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
9347c478bd9Sstevel@tonic-gate 	   goto fail;
9357c478bd9Sstevel@tonic-gate        }
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate        for (i=0; i<ctx->enc->length; i++)
9387c478bd9Sstevel@tonic-gate 	   /*SUPPRESS 113*/
9397c478bd9Sstevel@tonic-gate 	   ctx->enc->contents[i] ^= 0xf0;
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate        goto copy_subkey_to_seq;
9427c478bd9Sstevel@tonic-gate        break;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate    case ENCTYPE_DES3_CBC_SHA1:
9457c478bd9Sstevel@tonic-gate        ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
9467c478bd9Sstevel@tonic-gate        ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
9477c478bd9Sstevel@tonic-gate        ctx->cksum_size = 20;
9487c478bd9Sstevel@tonic-gate        ctx->sealalg = SEAL_ALG_DES3KD;
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate        /* fill in the encryption descriptors */
9517c478bd9Sstevel@tonic-gate    copy_subkey:
9527c478bd9Sstevel@tonic-gate        if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
9537c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
9547c478bd9Sstevel@tonic-gate 	   goto fail;
9557c478bd9Sstevel@tonic-gate        }
9567c478bd9Sstevel@tonic-gate    copy_subkey_to_seq:
9577c478bd9Sstevel@tonic-gate        if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) {
9587c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
9597c478bd9Sstevel@tonic-gate 	   goto fail;
9607c478bd9Sstevel@tonic-gate        }
9617c478bd9Sstevel@tonic-gate        break;
962159d09a2SMark Phalan 
9637c478bd9Sstevel@tonic-gate    case ENCTYPE_ARCFOUR_HMAC:
9647c478bd9Sstevel@tonic-gate        ctx->signalg = SGN_ALG_HMAC_MD5 ;
9657c478bd9Sstevel@tonic-gate        ctx->cksum_size = 8;
9667c478bd9Sstevel@tonic-gate        ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
9677c478bd9Sstevel@tonic-gate        goto copy_subkey;
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate    default:
9707c478bd9Sstevel@tonic-gate        ctx->signalg = -1;
9717c478bd9Sstevel@tonic-gate        ctx->sealalg = -1;
9727c478bd9Sstevel@tonic-gate        ctx->proto = 1;
973159d09a2SMark Phalan        code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, ctx->subkey->enctype,
9747c478bd9Sstevel@tonic-gate 					    &ctx->cksumtype);
9757c478bd9Sstevel@tonic-gate        if (code)
9767c478bd9Sstevel@tonic-gate 	   goto fail;
9777c478bd9Sstevel@tonic-gate        code = krb5_c_checksum_length(context, ctx->cksumtype,
9787c478bd9Sstevel@tonic-gate 		(size_t *)&ctx->cksum_size);
9797c478bd9Sstevel@tonic-gate        if (code)
9807c478bd9Sstevel@tonic-gate 	   goto fail;
9817c478bd9Sstevel@tonic-gate        ctx->have_acceptor_subkey = 0;
9827c478bd9Sstevel@tonic-gate        goto copy_subkey;
9837c478bd9Sstevel@tonic-gate    }
9847c478bd9Sstevel@tonic-gate 
985159d09a2SMark Phalan     /* Solaris Kerberos */
9867c478bd9Sstevel@tonic-gate    KRB5_LOG1(KRB5_ERR, "accept_sec_context:  subkey enctype = %d proto = %d",
9877c478bd9Sstevel@tonic-gate 	ctx->subkey->enctype, ctx->proto);
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate    ctx->endtime = ticket->enc_part2->times.endtime;
9907c478bd9Sstevel@tonic-gate    ctx->krb_flags = ticket->enc_part2->flags;
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate    krb5_free_ticket(context, ticket); /* Done with ticket */
993159d09a2SMark Phalan 
9947c478bd9Sstevel@tonic-gate    {
9957c478bd9Sstevel@tonic-gate        krb5_ui_4 seq_temp;
9967c478bd9Sstevel@tonic-gate        krb5_auth_con_getremoteseqnumber(context, auth_context,
9977c478bd9Sstevel@tonic-gate 		(krb5_int32 *)&seq_temp);
9987c478bd9Sstevel@tonic-gate        ctx->seq_recv = seq_temp;
9997c478bd9Sstevel@tonic-gate    }
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate    if ((code = krb5_timeofday(context, &now))) {
10027c478bd9Sstevel@tonic-gate        major_status = GSS_S_FAILURE;
10037c478bd9Sstevel@tonic-gate        goto fail;
10047c478bd9Sstevel@tonic-gate    }
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate    if (ctx->endtime < now) {
10077c478bd9Sstevel@tonic-gate        code = 0;
10087c478bd9Sstevel@tonic-gate        major_status = GSS_S_CREDENTIALS_EXPIRED;
10097c478bd9Sstevel@tonic-gate        goto fail;
10107c478bd9Sstevel@tonic-gate    }
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate    g_order_init(&(ctx->seqstate), ctx->seq_recv,
10137c478bd9Sstevel@tonic-gate 		(ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
10147c478bd9Sstevel@tonic-gate 		(ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate    /* at this point, the entire context structure is filled in,
10177c478bd9Sstevel@tonic-gate       so it can be released.  */
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate    /* generate an AP_REP if necessary */
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate    if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
10227c478bd9Sstevel@tonic-gate        unsigned char * ptr3;
10237c478bd9Sstevel@tonic-gate        krb5_ui_4 seq_temp;
10247c478bd9Sstevel@tonic-gate        int cfx_generate_subkey;
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate        if (ctx->proto == 1)
10277c478bd9Sstevel@tonic-gate 	   cfx_generate_subkey = CFX_ACCEPTOR_SUBKEY;
10287c478bd9Sstevel@tonic-gate        else
10297c478bd9Sstevel@tonic-gate 	   cfx_generate_subkey = 0;
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate        if (cfx_generate_subkey) {
10327c478bd9Sstevel@tonic-gate 	   krb5_int32 acflags;
10337c478bd9Sstevel@tonic-gate 	   code = krb5_auth_con_getflags(context, auth_context, &acflags);
10347c478bd9Sstevel@tonic-gate 	   if (code == 0) {
10357c478bd9Sstevel@tonic-gate 	       acflags |= KRB5_AUTH_CONTEXT_USE_SUBKEY;
10367c478bd9Sstevel@tonic-gate 	       code = krb5_auth_con_setflags(context, auth_context, acflags);
10377c478bd9Sstevel@tonic-gate 	   }
10387c478bd9Sstevel@tonic-gate 	   if (code) {
10397c478bd9Sstevel@tonic-gate 	       major_status = GSS_S_FAILURE;
10407c478bd9Sstevel@tonic-gate 	       goto fail;
10417c478bd9Sstevel@tonic-gate 	   }
10427c478bd9Sstevel@tonic-gate        }
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate        if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) {
10457c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
10467c478bd9Sstevel@tonic-gate 	   goto fail;
10477c478bd9Sstevel@tonic-gate        }
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate        krb5_auth_con_getlocalseqnumber(context, auth_context,
10507c478bd9Sstevel@tonic-gate 		(krb5_int32 *)&seq_temp);
10517c478bd9Sstevel@tonic-gate        ctx->seq_send = seq_temp & 0xffffffffL;
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate        if (cfx_generate_subkey) {
10547c478bd9Sstevel@tonic-gate 	   /* Get the new acceptor subkey.  With the code above, there
10557c478bd9Sstevel@tonic-gate 	      should always be one if we make it to this point.  */
10567c478bd9Sstevel@tonic-gate 	   code = krb5_auth_con_getsendsubkey(context, auth_context,
10577c478bd9Sstevel@tonic-gate 					      &ctx->acceptor_subkey);
10587c478bd9Sstevel@tonic-gate 	   if (code != 0) {
10597c478bd9Sstevel@tonic-gate 	       major_status = GSS_S_FAILURE;
10607c478bd9Sstevel@tonic-gate 	       goto fail;
10617c478bd9Sstevel@tonic-gate 	   }
1062159d09a2SMark Phalan 	   code = (*kaccess.krb5int_c_mandatory_cksumtype)(context,
10637c478bd9Sstevel@tonic-gate 						ctx->acceptor_subkey->enctype,
10647c478bd9Sstevel@tonic-gate 						&ctx->acceptor_subkey_cksumtype);
10657c478bd9Sstevel@tonic-gate 	   if (code) {
10667c478bd9Sstevel@tonic-gate 	       major_status = GSS_S_FAILURE;
10677c478bd9Sstevel@tonic-gate 	       goto fail;
10687c478bd9Sstevel@tonic-gate 	   }
10697c478bd9Sstevel@tonic-gate 	   ctx->have_acceptor_subkey = 1;
10707c478bd9Sstevel@tonic-gate        }
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate        /* the reply token hasn't been sent yet, but that's ok. */
10737c478bd9Sstevel@tonic-gate        ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
10747c478bd9Sstevel@tonic-gate        ctx->established = 1;
1075159d09a2SMark Phalan 
1076ab9b2e15Sgtb        token.length = g_token_size(mech_used, ap_rep.length);
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate        if ((token.value = (unsigned char *) xmalloc(token.length))
10797c478bd9Sstevel@tonic-gate 	   == NULL) {
10807c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
10817c478bd9Sstevel@tonic-gate 	   code = ENOMEM;
10827c478bd9Sstevel@tonic-gate 	   goto fail;
10837c478bd9Sstevel@tonic-gate        }
1084159d09a2SMark Phalan        ptr3 = token.value;
1085ab9b2e15Sgtb        g_make_token_header(mech_used, ap_rep.length,
1086159d09a2SMark Phalan 			   &ptr3, KG_TOK_CTX_AP_REP);
10877c478bd9Sstevel@tonic-gate 
1088159d09a2SMark Phalan        TWRITE_STR(ptr3, ap_rep.data, ap_rep.length);
1089159d09a2SMark Phalan 
1090159d09a2SMark Phalan        ctx->established = 1;
1091159d09a2SMark Phalan 
10927c478bd9Sstevel@tonic-gate    } else {
10937c478bd9Sstevel@tonic-gate        token.length = 0;
10947c478bd9Sstevel@tonic-gate        token.value = NULL;
10957c478bd9Sstevel@tonic-gate        ctx->seq_send = ctx->seq_recv;
1096159d09a2SMark Phalan 
10977c478bd9Sstevel@tonic-gate        ctx->established = 1;
1098159d09a2SMark Phalan    }
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate    /* set the return arguments */
11017c478bd9Sstevel@tonic-gate 
11025e01956fSGlenn Barry    /*
11035e01956fSGlenn Barry     * Solaris Kerberos
11045e01956fSGlenn Barry     * Regardless of src_name, get name for error msg if neeeded.
11055e01956fSGlenn Barry     */
11065e01956fSGlenn Barry    if ((code = krb5_copy_principal(context, ctx->there, &client_name))) {
11075e01956fSGlenn Barry 	major_status = GSS_S_FAILURE;
11085e01956fSGlenn Barry 	goto fail;
11095e01956fSGlenn Barry    }
11105e01956fSGlenn Barry    if ((code = krb5_copy_principal(context, ctx->here, &server_name))) {
11117c478bd9Sstevel@tonic-gate 	major_status = GSS_S_FAILURE;
11127c478bd9Sstevel@tonic-gate 	goto fail;
11137c478bd9Sstevel@tonic-gate    }
11147c478bd9Sstevel@tonic-gate    /* intern the src_name */
11155e01956fSGlenn Barry    if (! kg_save_name((gss_name_t) client_name)) {
11167c478bd9Sstevel@tonic-gate 	code = G_VALIDATE_FAILED;
11177c478bd9Sstevel@tonic-gate 	major_status = GSS_S_FAILURE;
11187c478bd9Sstevel@tonic-gate 	goto fail;
11197c478bd9Sstevel@tonic-gate    }
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate    if (time_rec)
11227c478bd9Sstevel@tonic-gate       *time_rec = ctx->endtime - now;
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate    if (ret_flags)
11257c478bd9Sstevel@tonic-gate       *ret_flags = ctx->gss_flags;
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate    *context_handle = (gss_ctx_id_t)ctx;
11287c478bd9Sstevel@tonic-gate    *output_token = token;
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate    if (src_name)
11315e01956fSGlenn Barry       *src_name = (gss_name_t) client_name;
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate    if (delegated_cred_handle && deleg_cred) {
11347c478bd9Sstevel@tonic-gate        if (!kg_save_cred_id((gss_cred_id_t) deleg_cred)) {
1135159d09a2SMark Phalan            /* Solaris Kerberos */
11367c478bd9Sstevel@tonic-gate 	   KRB5_LOG0(KRB5_ERR, "krb5_gss_accept_sec_context() "
11377c478bd9Sstevel@tonic-gate 		      "kg_save_cred_id() error");
11387c478bd9Sstevel@tonic-gate 	   major_status = GSS_S_FAILURE;
11397c478bd9Sstevel@tonic-gate 	   code = (OM_uint32) G_VALIDATE_FAILED;
11407c478bd9Sstevel@tonic-gate 	   goto fail;
11417c478bd9Sstevel@tonic-gate        }
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate        *delegated_cred_handle = (gss_cred_id_t) deleg_cred;
11447c478bd9Sstevel@tonic-gate    }
11457c478bd9Sstevel@tonic-gate 
1146*cfed4d70SMatt Barden    if (server_name)
1147*cfed4d70SMatt Barden 	krb5_free_principal(context, server_name);
1148*cfed4d70SMatt Barden 
11497c478bd9Sstevel@tonic-gate    /* finally! */
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate    *minor_status = 0;
11527c478bd9Sstevel@tonic-gate    major_status = GSS_S_COMPLETE;
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate  fail:
11555e01956fSGlenn Barry    if (mech_type) {
11565e01956fSGlenn Barry 	/*
11575e01956fSGlenn Barry 	 * This needs to be set/returned even on fail so
11585e01956fSGlenn Barry 	 * gss_accept_sec_context() can map_error_oid() the correct
11595e01956fSGlenn Barry 	 * error/oid for later use by gss_display_status().
11605e01956fSGlenn Barry 	 * (needed in CIFS/SPNEGO case)
11615e01956fSGlenn Barry 	 */
11625e01956fSGlenn Barry 	*mech_type = (gss_OID) mech_used;
11635e01956fSGlenn Barry    }
1164ba7b222eSGlenn Barry 
11657c478bd9Sstevel@tonic-gate    if (authdat)
11667c478bd9Sstevel@tonic-gate        krb5_free_authenticator(context, authdat);
1167ab9b2e15Sgtb    /* The ctx structure has the handle of the auth_context */
11687c478bd9Sstevel@tonic-gate    if (auth_context && !ctx) {
1169ab9b2e15Sgtb        if (cred_rcache)
11707c478bd9Sstevel@tonic-gate 	   (void)krb5_auth_con_setrcache(context, auth_context, NULL);
1171ab9b2e15Sgtb 
11727c478bd9Sstevel@tonic-gate        krb5_auth_con_free(context, auth_context);
11737c478bd9Sstevel@tonic-gate    }
11747c478bd9Sstevel@tonic-gate    if (reqcksum.contents)
11757c478bd9Sstevel@tonic-gate        xfree(reqcksum.contents);
11767c478bd9Sstevel@tonic-gate    if (ap_rep.data)
11777c478bd9Sstevel@tonic-gate        xfree(ap_rep.data);
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate    if (request != NULL) {
11807c478bd9Sstevel@tonic-gate 	saved_ap_options = request->ap_options;
11817c478bd9Sstevel@tonic-gate 	krb5_free_ap_req(context, request);
11827c478bd9Sstevel@tonic-gate 	request = NULL;
11837c478bd9Sstevel@tonic-gate    }
11847c478bd9Sstevel@tonic-gate 
1185ab9b2e15Sgtb    if (!GSS_ERROR(major_status) && major_status != GSS_S_CONTINUE_NEEDED) {
1186ab9b2e15Sgtb 	if (!verifier_cred_handle && cred_handle) {
1187ab9b2e15Sgtb 		krb5_gss_release_cred(minor_status, &cred_handle);
1188ab9b2e15Sgtb 	}
1189ab9b2e15Sgtb 
1190ab9b2e15Sgtb 	if (ctx)
1191ab9b2e15Sgtb 	    ctx->k5_context = context;
1192ab9b2e15Sgtb 
1193ab9b2e15Sgtb         return(major_status);
1194ab9b2e15Sgtb    }
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate    /* from here on is the real "fail" code */
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate    if (ctx)
1199ab9b2e15Sgtb        (void) krb5_gss_delete_sec_context(minor_status,
12007c478bd9Sstevel@tonic-gate 					  (gss_ctx_id_t *) &ctx, NULL);
12017c478bd9Sstevel@tonic-gate    if (deleg_cred) { /* free memory associated with the deleg credential */
12027c478bd9Sstevel@tonic-gate        if (deleg_cred->ccache)
12037c478bd9Sstevel@tonic-gate 	   (void)krb5_cc_close(context, deleg_cred->ccache);
12047c478bd9Sstevel@tonic-gate        if (deleg_cred->princ)
12057c478bd9Sstevel@tonic-gate 	   krb5_free_principal(context, deleg_cred->princ);
12067c478bd9Sstevel@tonic-gate        xfree(deleg_cred);
12077c478bd9Sstevel@tonic-gate    }
12087c478bd9Sstevel@tonic-gate    if (token.value)
12097c478bd9Sstevel@tonic-gate        xfree(token.value);
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate    *minor_status = code;
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate    if (saved_ap_options & AP_OPTS_MUTUAL_REQUIRED)
12147c478bd9Sstevel@tonic-gate 	gss_flags |= GSS_C_MUTUAL_FLAG;
12157c478bd9Sstevel@tonic-gate 
1216159d09a2SMark Phalan    if (cred
1217159d09a2SMark Phalan        && ((gss_flags & GSS_C_MUTUAL_FLAG)
1218159d09a2SMark Phalan 	   || (major_status == GSS_S_CONTINUE_NEEDED))) {
12197c478bd9Sstevel@tonic-gate        unsigned int tmsglen;
12207c478bd9Sstevel@tonic-gate        int toktype;
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate        /*
12237c478bd9Sstevel@tonic-gate 	* The client is expecting a response, so we can send an
12247c478bd9Sstevel@tonic-gate 	* error token back
12257c478bd9Sstevel@tonic-gate 	*/
12267c478bd9Sstevel@tonic-gate 
122772f0806aSShawn Emery        /*
122872f0806aSShawn Emery         * Solaris Kerberos: We need to remap error conditions for buggy
122972f0806aSShawn Emery         * Windows clients if the MS_INTEROP env var has been set.
123072f0806aSShawn Emery         */
123172f0806aSShawn Emery        if ((code == KRB5KRB_AP_ERR_BAD_INTEGRITY ||
123272f0806aSShawn Emery 	  code == KRB5KRB_AP_ERR_NOKEY || code == KRB5KRB_AP_ERR_BADKEYVER)
123372f0806aSShawn Emery 	  && krb5_getenv("MS_INTEROP")) {
123472f0806aSShawn Emery            code = KRB5KRB_AP_ERR_MODIFIED;
123572f0806aSShawn Emery 	   major_status = GSS_S_CONTINUE_NEEDED;
123672f0806aSShawn Emery        }
12377c478bd9Sstevel@tonic-gate 
1238ba7b222eSGlenn Barry 	    /*
1239ba7b222eSGlenn Barry 	     * SUNW17PACresync / Solaris Kerberos
1240ba7b222eSGlenn Barry 	     * Set e-data to Windows constant.
1241ba7b222eSGlenn Barry 	     * (verified by MSFT)
1242ba7b222eSGlenn Barry 	     *
1243ba7b222eSGlenn Barry 	     * This facilitates the Windows CIFS client clock skew
1244ba7b222eSGlenn Barry 	     * recovery feature.
1245ba7b222eSGlenn Barry 	     */
124672f0806aSShawn Emery        if (code == KRB5KRB_AP_ERR_SKEW && krb5_getenv("MS_INTEROP")) {
1247ba7b222eSGlenn Barry 	    char *ms_e_data = "\x30\x05\xa1\x03\x02\x01\x02";
1248ba7b222eSGlenn Barry 	    int len = strlen(ms_e_data);
1249ba7b222eSGlenn Barry 
1250ba7b222eSGlenn Barry 	    krb_error_data.e_data.data = malloc(len);
1251ba7b222eSGlenn Barry 	    if (krb_error_data.e_data.data) {
1252ba7b222eSGlenn Barry 		    (void) memcpy(krb_error_data.e_data.data, ms_e_data, len);
1253ba7b222eSGlenn Barry 		    krb_error_data.e_data.length = len;
1254ba7b222eSGlenn Barry 	    }
125572f0806aSShawn Emery 	    major_status = GSS_S_CONTINUE_NEEDED;
1256ba7b222eSGlenn Barry        }
1257ba7b222eSGlenn Barry 
125872f0806aSShawn Emery        code -= ERROR_TABLE_BASE_krb5;
125972f0806aSShawn Emery        if (code < 0 || code > 128)
126072f0806aSShawn Emery 	   code = 60 /* KRB_ERR_GENERIC */;
126172f0806aSShawn Emery 
126272f0806aSShawn Emery        krb_error_data.error = code;
126372f0806aSShawn Emery        (void) krb5_us_timeofday(context, &krb_error_data.stime,
126472f0806aSShawn Emery 				&krb_error_data.susec);
126572f0806aSShawn Emery        krb_error_data.server = cred->princ;
126672f0806aSShawn Emery 
12677c478bd9Sstevel@tonic-gate        code = krb5_mk_error(context, &krb_error_data, &scratch);
12687c478bd9Sstevel@tonic-gate        if (code)
1269ab9b2e15Sgtb            goto cleanup;
12707c478bd9Sstevel@tonic-gate 
12717c478bd9Sstevel@tonic-gate        tmsglen = scratch.length;
12727c478bd9Sstevel@tonic-gate        toktype = KG_TOK_CTX_ERROR;
12737c478bd9Sstevel@tonic-gate 
1274ab9b2e15Sgtb        token.length = g_token_size(mech_used, tmsglen);
12757c478bd9Sstevel@tonic-gate        token.value = (unsigned char *) xmalloc(token.length);
12767c478bd9Sstevel@tonic-gate        if (!token.value)
1277ab9b2e15Sgtb 	  goto cleanup;
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate        ptr = token.value;
1280ab9b2e15Sgtb        g_make_token_header(mech_used, tmsglen, &ptr, toktype);
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate        TWRITE_STR(ptr, scratch.data, scratch.length);
12837c478bd9Sstevel@tonic-gate        xfree(scratch.data);
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate        *output_token = token;
12867c478bd9Sstevel@tonic-gate    }
12877c478bd9Sstevel@tonic-gate 
1288ab9b2e15Sgtb cleanup:
1289a43e85c5SMark Phalan    /* Solaris Kerberos */
1290a43e85c5SMark Phalan    if (krb_error_data.e_data.data != NULL)
1291a43e85c5SMark Phalan         free(krb_error_data.e_data.data);
1292a43e85c5SMark Phalan 
12937c478bd9Sstevel@tonic-gate    if (!verifier_cred_handle && cred_handle) {
1294ba7b222eSGlenn Barry 	krb5_gss_release_cred(&t_minor_status, &cred_handle);
12957c478bd9Sstevel@tonic-gate    }
12965e01956fSGlenn Barry 
12975e01956fSGlenn Barry    /*
12985e01956fSGlenn Barry     * Solaris Kerberos
12995e01956fSGlenn Barry     * Enhance the error message.
13005e01956fSGlenn Barry     */
13015e01956fSGlenn Barry    if (GSS_ERROR(major_status)) {
13025e01956fSGlenn Barry        if (client_name && server_name &&
13035e01956fSGlenn Barry 	 (*minor_status == (OM_uint32)KRB5KRB_AP_ERR_BAD_INTEGRITY)) {
13045e01956fSGlenn Barry 	    char *c_name = NULL;
13055e01956fSGlenn Barry 	    char *s_name = NULL;
13065e01956fSGlenn Barry 	    krb5_error_code cret, sret;
13075e01956fSGlenn Barry 	    cret = krb5_unparse_name(context, (krb5_principal) client_name,
13085e01956fSGlenn Barry 				    &c_name);
13095e01956fSGlenn Barry 	    sret = krb5_unparse_name(context, (krb5_principal) server_name,
13105e01956fSGlenn Barry 				    &s_name);
13115e01956fSGlenn Barry 	    krb5_set_error_message(context, *minor_status,
13125e01956fSGlenn Barry 				dgettext(TEXT_DOMAIN,
13135e01956fSGlenn Barry 					"Decrypt integrity check failed for client '%s' and server '%s'"),
13145e01956fSGlenn Barry 				cret == 0 ? c_name : "unknown",
13155e01956fSGlenn Barry 				sret == 0 ? s_name : "unknown");
13165e01956fSGlenn Barry 	    if (s_name)
13175e01956fSGlenn Barry 		    krb5_free_unparsed_name(context, s_name);
13185e01956fSGlenn Barry 	    if (c_name)
13195e01956fSGlenn Barry 		    krb5_free_unparsed_name(context, c_name);
13205e01956fSGlenn Barry 	    }
13215e01956fSGlenn Barry        /*
13225e01956fSGlenn Barry 	* Solaris Kerberos
13235e01956fSGlenn Barry 	* krb5_gss_acquire_cred() does not take a context arg
13245e01956fSGlenn Barry 	* (and does a save_error_info() itself) so re-calling
13255e01956fSGlenn Barry 	* save_error_info() here is trouble.
13265e01956fSGlenn Barry 	*/
13275e01956fSGlenn Barry        if (!acquire_fail)
13285e01956fSGlenn Barry 	    save_error_info(*minor_status, context);
13295e01956fSGlenn Barry    }
13305e01956fSGlenn Barry    if (client_name) {
13315e01956fSGlenn Barry 	(void) kg_delete_name((gss_name_t) client_name);
13325e01956fSGlenn Barry    }
13335e01956fSGlenn Barry    if (server_name)
13345e01956fSGlenn Barry 	krb5_free_principal(context, server_name);
1335ab9b2e15Sgtb    krb5_free_context(context);
1336ab9b2e15Sgtb 
1337159d09a2SMark Phalan    /* Solaris Kerberos */
13387c478bd9Sstevel@tonic-gate    KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() end, "
13397c478bd9Sstevel@tonic-gate 	      "major_status = %d", major_status);
13407c478bd9Sstevel@tonic-gate    return (major_status);
13417c478bd9Sstevel@tonic-gate }
1342