17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /* GSSAPI SASL plugin
77c478bd9Sstevel@tonic-gate  * Leif Johansson
87c478bd9Sstevel@tonic-gate  * Rob Siemborski (SASL v2 Conversion)
97c478bd9Sstevel@tonic-gate  * $Id: gssapi.c,v 1.75 2003/07/02 13:13:42 rjs3 Exp $
107c478bd9Sstevel@tonic-gate  */
11*55fea89dSDan Cross /*
127c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
157c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
167c478bd9Sstevel@tonic-gate  * are met:
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
19*55fea89dSDan Cross  *    notice, this list of conditions and the following disclaimer.
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
227c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
237c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
247c478bd9Sstevel@tonic-gate  *    distribution.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
277c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
287c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
29*55fea89dSDan Cross  *    details, please contact
307c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
317c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
327c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
337c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
347c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
357c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
387c478bd9Sstevel@tonic-gate  *    acknowledgment:
397c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
407c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
437c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
447c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
457c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
467c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
477c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
487c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #include <config.h>
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #ifdef HAVE_GSSAPI_H
547c478bd9Sstevel@tonic-gate #include <gssapi.h>
557c478bd9Sstevel@tonic-gate #else
567c478bd9Sstevel@tonic-gate #include <gssapi/gssapi.h>
577c478bd9Sstevel@tonic-gate #endif
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #ifdef WIN32
607c478bd9Sstevel@tonic-gate #  include <winsock.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #  ifndef R_OK
637c478bd9Sstevel@tonic-gate #    define R_OK 04
647c478bd9Sstevel@tonic-gate #  endif
657c478bd9Sstevel@tonic-gate /* we also need io.h for access() prototype */
667c478bd9Sstevel@tonic-gate #  include <io.h>
677c478bd9Sstevel@tonic-gate #else
687c478bd9Sstevel@tonic-gate #  include <sys/param.h>
697c478bd9Sstevel@tonic-gate #  include <sys/socket.h>
707c478bd9Sstevel@tonic-gate #  include <netinet/in.h>
717c478bd9Sstevel@tonic-gate #  include <arpa/inet.h>
727c478bd9Sstevel@tonic-gate #  include <netdb.h>
737c478bd9Sstevel@tonic-gate #endif /* WIN32 */
747c478bd9Sstevel@tonic-gate #include <fcntl.h>
757c478bd9Sstevel@tonic-gate #include <stdio.h>
767c478bd9Sstevel@tonic-gate #include <sasl.h>
777c478bd9Sstevel@tonic-gate #include <saslutil.h>
787c478bd9Sstevel@tonic-gate #include <saslplug.h>
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #include "plugin_common.h"
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H
837c478bd9Sstevel@tonic-gate #include <unistd.h>
847c478bd9Sstevel@tonic-gate #endif
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #include <errno.h>
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #ifdef WIN32
897c478bd9Sstevel@tonic-gate /* This must be after sasl.h */
907c478bd9Sstevel@tonic-gate # include "saslgssapi.h"
917c478bd9Sstevel@tonic-gate #endif /* WIN32 */
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate /*****************************  Common Section  *****************************/
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
967c478bd9Sstevel@tonic-gate static const char plugin_id[] = "$Id: gssapi.c,v 1.75 2003/07/02 13:13:42 rjs3 Exp $";
977c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate static const char * GSSAPI_BLANK_STRING = "";
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
1027c478bd9Sstevel@tonic-gate extern gss_OID gss_nt_service_name;
1037c478bd9Sstevel@tonic-gate #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
1047c478bd9Sstevel@tonic-gate #endif
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1077c478bd9Sstevel@tonic-gate static int
1087c478bd9Sstevel@tonic-gate get_oid(const sasl_utils_t *utils, gss_OID *oid);
1097c478bd9Sstevel@tonic-gate #ifdef GSSAPI_PROTECT
1107c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(global_mutex);
1117c478bd9Sstevel@tonic-gate #endif /* GSSAPI_PROTECT */
1127c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate /* GSSAPI SASL Mechanism by Leif Johansson <leifj@matematik.su.se>
1157c478bd9Sstevel@tonic-gate  * inspired by the kerberos mechanism and the gssapi_server and
1167c478bd9Sstevel@tonic-gate  * gssapi_client from the heimdal distribution by Assar Westerlund
117*55fea89dSDan Cross  * <assar@sics.se> and Johan Danielsson <joda@pdc.kth.se>.
1187c478bd9Sstevel@tonic-gate  * See the configure.in file for details on dependencies.
1197c478bd9Sstevel@tonic-gate  * Heimdal can be obtained from http://www.pdc.kth.se/heimdal
1207c478bd9Sstevel@tonic-gate  *
1217c478bd9Sstevel@tonic-gate  * Important contributions from Sam Hartman <hartmans@fundsxpress.com>.
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate typedef struct context {
1257c478bd9Sstevel@tonic-gate     int state;
126*55fea89dSDan Cross 
1277c478bd9Sstevel@tonic-gate     gss_ctx_id_t gss_ctx;
1287c478bd9Sstevel@tonic-gate     gss_name_t   client_name;
1297c478bd9Sstevel@tonic-gate     gss_name_t   server_name;
1307c478bd9Sstevel@tonic-gate     gss_cred_id_t server_creds;
1317c478bd9Sstevel@tonic-gate     sasl_ssf_t limitssf, requiressf; /* application defined bounds, for the
1327c478bd9Sstevel@tonic-gate 					server */
1337c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1347c478bd9Sstevel@tonic-gate     gss_cred_id_t client_creds;
1357c478bd9Sstevel@tonic-gate     gss_OID	mech_oid;
1367c478bd9Sstevel@tonic-gate     int		use_authid;
1377c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1387c478bd9Sstevel@tonic-gate     const sasl_utils_t *utils;
139*55fea89dSDan Cross 
1407c478bd9Sstevel@tonic-gate     /* layers buffering */
1417c478bd9Sstevel@tonic-gate     char *buffer;
1427c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1437c478bd9Sstevel@tonic-gate     unsigned bufsize;
1447c478bd9Sstevel@tonic-gate #else
1457c478bd9Sstevel@tonic-gate     int bufsize;
1467c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1477c478bd9Sstevel@tonic-gate     char sizebuf[4];
1487c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1497c478bd9Sstevel@tonic-gate     unsigned cursize;
1507c478bd9Sstevel@tonic-gate     unsigned size;
1517c478bd9Sstevel@tonic-gate #else
1527c478bd9Sstevel@tonic-gate     int cursize;
1537c478bd9Sstevel@tonic-gate     int size;
1547c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1557c478bd9Sstevel@tonic-gate     unsigned needsize;
156*55fea89dSDan Cross 
1577c478bd9Sstevel@tonic-gate     char *encode_buf;                /* For encoding/decoding mem management */
1587c478bd9Sstevel@tonic-gate     char *decode_buf;
1597c478bd9Sstevel@tonic-gate     char *decode_once_buf;
1607c478bd9Sstevel@tonic-gate     unsigned encode_buf_len;
1617c478bd9Sstevel@tonic-gate     unsigned decode_buf_len;
1627c478bd9Sstevel@tonic-gate     unsigned decode_once_buf_len;
1637c478bd9Sstevel@tonic-gate     buffer_info_t *enc_in_buf;
164*55fea89dSDan Cross 
1657c478bd9Sstevel@tonic-gate     char *out_buf;                   /* per-step mem management */
166*55fea89dSDan Cross     unsigned out_buf_len;
167*55fea89dSDan Cross 
1687c478bd9Sstevel@tonic-gate     char *authid; /* hold the authid between steps - server */
1697c478bd9Sstevel@tonic-gate     const char *user;   /* hold the userid between steps - client */
1707c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1717c478bd9Sstevel@tonic-gate     const char *client_authid;
1727c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1737c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1747c478bd9Sstevel@tonic-gate     void *h;
1757c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1767c478bd9Sstevel@tonic-gate } context_t;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate enum {
1797c478bd9Sstevel@tonic-gate     SASL_GSSAPI_STATE_AUTHNEG = 1,
1807c478bd9Sstevel@tonic-gate     SASL_GSSAPI_STATE_SSFCAP = 2,
1817c478bd9Sstevel@tonic-gate     SASL_GSSAPI_STATE_SSFREQ = 3,
1827c478bd9Sstevel@tonic-gate     SASL_GSSAPI_STATE_AUTHENTICATED = 4
1837c478bd9Sstevel@tonic-gate };
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1867c478bd9Sstevel@tonic-gate /* sasl_gss_log only logs gss_display_status() error string */
1877c478bd9Sstevel@tonic-gate #define sasl_gss_log(x,y,z) sasl_gss_seterror_(text,y,z,1)
1887c478bd9Sstevel@tonic-gate #define sasl_gss_seterror(x,y,z) sasl_gss_seterror_(text,y,z,0)
1897c478bd9Sstevel@tonic-gate static void
sasl_gss_seterror_(const context_t * text,OM_uint32 maj,OM_uint32 min,int logonly)190*55fea89dSDan Cross sasl_gss_seterror_(const context_t *text, OM_uint32 maj, OM_uint32 min,
1917c478bd9Sstevel@tonic-gate 	int logonly)
1927c478bd9Sstevel@tonic-gate #else
1937c478bd9Sstevel@tonic-gate static void
1947c478bd9Sstevel@tonic-gate sasl_gss_seterror(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min)
1957c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate     OM_uint32 maj_stat, min_stat;
1987c478bd9Sstevel@tonic-gate     gss_buffer_desc msg;
1997c478bd9Sstevel@tonic-gate     OM_uint32 msg_ctx;
2007c478bd9Sstevel@tonic-gate     int ret;
2017c478bd9Sstevel@tonic-gate     char *out = NULL;
2027c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2037c478bd9Sstevel@tonic-gate     unsigned len, curlen = 0;
2047c478bd9Sstevel@tonic-gate     const sasl_utils_t *utils = text->utils;
2057c478bd9Sstevel@tonic-gate     char *prefix = dgettext(TEXT_DOMAIN, "GSSAPI Error: ");
2067c478bd9Sstevel@tonic-gate #else
2077c478bd9Sstevel@tonic-gate     size_t len, curlen = 0;
2087c478bd9Sstevel@tonic-gate     const char prefix[] = "GSSAPI Error: ";
2097c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
210*55fea89dSDan Cross 
2117c478bd9Sstevel@tonic-gate     if(!utils) return;
212*55fea89dSDan Cross 
2137c478bd9Sstevel@tonic-gate     len = sizeof(prefix);
2147c478bd9Sstevel@tonic-gate     ret = _plug_buf_alloc(utils, &out, &curlen, 256);
2157c478bd9Sstevel@tonic-gate     if(ret != SASL_OK) return;
216*55fea89dSDan Cross 
2177c478bd9Sstevel@tonic-gate     strcpy(out, prefix);
218*55fea89dSDan Cross 
2197c478bd9Sstevel@tonic-gate     msg_ctx = 0;
2207c478bd9Sstevel@tonic-gate     while (1) {
2217c478bd9Sstevel@tonic-gate 	maj_stat = gss_display_status(&min_stat, maj,
2227c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2237c478bd9Sstevel@tonic-gate 				      GSS_C_GSS_CODE, text->mech_oid,
2247c478bd9Sstevel@tonic-gate #else
2257c478bd9Sstevel@tonic-gate 				      GSS_C_GSS_CODE, GSS_C_NULL_OID,
2267c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2277c478bd9Sstevel@tonic-gate 				      &msg_ctx, &msg);
2287c478bd9Sstevel@tonic-gate 	if(GSS_ERROR(maj_stat)) {
2297c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2307c478bd9Sstevel@tonic-gate 	    if (logonly) {
2317c478bd9Sstevel@tonic-gate 		utils->log(text->utils->conn, SASL_LOG_FAIL,
2327c478bd9Sstevel@tonic-gate 		    "GSSAPI Failure: (could not get major error message)");
2337c478bd9Sstevel@tonic-gate 	    } else {
2347c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2357c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
2367c478bd9Sstevel@tonic-gate 		utils->seterror(utils->conn, 0,
2377c478bd9Sstevel@tonic-gate 				gettext("GSSAPI Failure "
2387c478bd9Sstevel@tonic-gate 				"(could not get major error message)"));
2397c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2407c478bd9Sstevel@tonic-gate 	    }
2417c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2427c478bd9Sstevel@tonic-gate #else
2437c478bd9Sstevel@tonic-gate 	    utils->seterror(utils->conn, 0,
2447c478bd9Sstevel@tonic-gate 			    "GSSAPI Failure "
2457c478bd9Sstevel@tonic-gate 			    "(could not get major error message)");
2467c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2477c478bd9Sstevel@tonic-gate 	    }
2487c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2497c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
2507c478bd9Sstevel@tonic-gate 	    utils->free(out);
2517c478bd9Sstevel@tonic-gate 	    return;
2527c478bd9Sstevel@tonic-gate 	}
253*55fea89dSDan Cross 
2547c478bd9Sstevel@tonic-gate 	len += len + msg.length;
2557c478bd9Sstevel@tonic-gate 	ret = _plug_buf_alloc(utils, &out, &curlen, len);
256*55fea89dSDan Cross 
2577c478bd9Sstevel@tonic-gate 	if(ret != SASL_OK) {
2587c478bd9Sstevel@tonic-gate 	    utils->free(out);
2597c478bd9Sstevel@tonic-gate 	    return;
2607c478bd9Sstevel@tonic-gate 	}
261*55fea89dSDan Cross 
2627c478bd9Sstevel@tonic-gate 	strcat(out, msg.value);
263*55fea89dSDan Cross 
2647c478bd9Sstevel@tonic-gate 	gss_release_buffer(&min_stat, &msg);
265*55fea89dSDan Cross 
2667c478bd9Sstevel@tonic-gate 	if (!msg_ctx)
2677c478bd9Sstevel@tonic-gate 	    break;
2687c478bd9Sstevel@tonic-gate     }
269*55fea89dSDan Cross 
2707c478bd9Sstevel@tonic-gate     /* Now get the minor status */
271*55fea89dSDan Cross 
2727c478bd9Sstevel@tonic-gate     len += 2;
2737c478bd9Sstevel@tonic-gate     ret = _plug_buf_alloc(utils, &out, &curlen, len);
2747c478bd9Sstevel@tonic-gate     if(ret != SASL_OK) {
2757c478bd9Sstevel@tonic-gate 	utils->free(out);
2767c478bd9Sstevel@tonic-gate 	return;
2777c478bd9Sstevel@tonic-gate     }
278*55fea89dSDan Cross 
2797c478bd9Sstevel@tonic-gate     strcat(out, " (");
280*55fea89dSDan Cross 
2817c478bd9Sstevel@tonic-gate     msg_ctx = 0;
2827c478bd9Sstevel@tonic-gate     while (1) {
2837c478bd9Sstevel@tonic-gate 	maj_stat = gss_display_status(&min_stat, min,
2847c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2857c478bd9Sstevel@tonic-gate 				      GSS_C_MECH_CODE, text->mech_oid,
2867c478bd9Sstevel@tonic-gate #else
2877c478bd9Sstevel@tonic-gate 				      GSS_C_MECH_CODE, GSS_C_NULL_OID,
2887c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2897c478bd9Sstevel@tonic-gate 				      &msg_ctx, &msg);
2907c478bd9Sstevel@tonic-gate 	if(GSS_ERROR(maj_stat)) {
2917c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2927c478bd9Sstevel@tonic-gate 	    if (logonly) {
2937c478bd9Sstevel@tonic-gate 		utils->log(text->utils->conn, SASL_LOG_FAIL,
2947c478bd9Sstevel@tonic-gate 		    "GSSAPI Failure: (could not get minor error message)");
2957c478bd9Sstevel@tonic-gate 	    } else {
2967c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2977c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
2987c478bd9Sstevel@tonic-gate 		utils->seterror(utils->conn, 0,
2997c478bd9Sstevel@tonic-gate 				gettext("GSSAPI Failure "
3007c478bd9Sstevel@tonic-gate 				"(could not get minor error message)"));
3017c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
3027c478bd9Sstevel@tonic-gate 	    }
3037c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3047c478bd9Sstevel@tonic-gate #else
3057c478bd9Sstevel@tonic-gate 	    utils->seterror(utils->conn, 0,
3067c478bd9Sstevel@tonic-gate 			    "GSSAPI Failure "
3077c478bd9Sstevel@tonic-gate 			    "(could not get minor error message)");
3087c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
3097c478bd9Sstevel@tonic-gate 	    }
3107c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3117c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
3127c478bd9Sstevel@tonic-gate 	    utils->free(out);
3137c478bd9Sstevel@tonic-gate 	    return;
3147c478bd9Sstevel@tonic-gate 	}
315*55fea89dSDan Cross 
3167c478bd9Sstevel@tonic-gate 	len += len + msg.length;
3177c478bd9Sstevel@tonic-gate 	ret = _plug_buf_alloc(utils, &out, &curlen, len);
318*55fea89dSDan Cross 
3197c478bd9Sstevel@tonic-gate 	if(ret != SASL_OK) {
3207c478bd9Sstevel@tonic-gate 	    utils->free(out);
3217c478bd9Sstevel@tonic-gate 	    return;
3227c478bd9Sstevel@tonic-gate 	}
323*55fea89dSDan Cross 
3247c478bd9Sstevel@tonic-gate 	strcat(out, msg.value);
325*55fea89dSDan Cross 
3267c478bd9Sstevel@tonic-gate 	gss_release_buffer(&min_stat, &msg);
327*55fea89dSDan Cross 
3287c478bd9Sstevel@tonic-gate 	if (!msg_ctx)
3297c478bd9Sstevel@tonic-gate 	    break;
3307c478bd9Sstevel@tonic-gate     }
331*55fea89dSDan Cross 
3327c478bd9Sstevel@tonic-gate     len += 1;
3337c478bd9Sstevel@tonic-gate     ret = _plug_buf_alloc(utils, &out, &curlen, len);
3347c478bd9Sstevel@tonic-gate     if(ret != SASL_OK) {
3357c478bd9Sstevel@tonic-gate 	utils->free(out);
3367c478bd9Sstevel@tonic-gate 	return;
3377c478bd9Sstevel@tonic-gate     }
338*55fea89dSDan Cross 
3397c478bd9Sstevel@tonic-gate     strcat(out, ")");
340*55fea89dSDan Cross 
3417c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
3427c478bd9Sstevel@tonic-gate     if (logonly) {
3437c478bd9Sstevel@tonic-gate 	utils->log(text->utils->conn, SASL_LOG_FAIL, out);
3447c478bd9Sstevel@tonic-gate     } else {
3457c478bd9Sstevel@tonic-gate 	utils->seterror(utils->conn, 0, out);
3467c478bd9Sstevel@tonic-gate     }
3477c478bd9Sstevel@tonic-gate #else
3487c478bd9Sstevel@tonic-gate     utils->seterror(utils->conn, 0, out);
3497c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3507c478bd9Sstevel@tonic-gate     utils->free(out);
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate 
353*55fea89dSDan Cross static int
sasl_gss_encode(void * context,const struct iovec * invec,unsigned numiov,const char ** output,unsigned * outputlen,int privacy)3547c478bd9Sstevel@tonic-gate sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov,
3557c478bd9Sstevel@tonic-gate 		const char **output, unsigned *outputlen, int privacy)
3567c478bd9Sstevel@tonic-gate {
3577c478bd9Sstevel@tonic-gate     context_t *text = (context_t *)context;
3587c478bd9Sstevel@tonic-gate     OM_uint32 maj_stat, min_stat;
3597c478bd9Sstevel@tonic-gate     gss_buffer_t input_token, output_token;
3607c478bd9Sstevel@tonic-gate     gss_buffer_desc real_input_token, real_output_token;
3617c478bd9Sstevel@tonic-gate     int ret;
3627c478bd9Sstevel@tonic-gate     struct buffer_info *inblob, bufinfo;
363*55fea89dSDan Cross 
3647c478bd9Sstevel@tonic-gate     if(!output) return SASL_BADPARAM;
365*55fea89dSDan Cross 
3667c478bd9Sstevel@tonic-gate     if(numiov > 1) {
3677c478bd9Sstevel@tonic-gate 	ret = _plug_iovec_to_buf(text->utils, invec, numiov, &text->enc_in_buf);
3687c478bd9Sstevel@tonic-gate 	if(ret != SASL_OK) return ret;
3697c478bd9Sstevel@tonic-gate 	inblob = text->enc_in_buf;
3707c478bd9Sstevel@tonic-gate     } else {
3717c478bd9Sstevel@tonic-gate 	bufinfo.data = invec[0].iov_base;
3727c478bd9Sstevel@tonic-gate 	bufinfo.curlen = invec[0].iov_len;
3737c478bd9Sstevel@tonic-gate 	inblob = &bufinfo;
3747c478bd9Sstevel@tonic-gate     }
375*55fea89dSDan Cross 
3767c478bd9Sstevel@tonic-gate     if (text->state != SASL_GSSAPI_STATE_AUTHENTICATED) return SASL_NOTDONE;
377*55fea89dSDan Cross 
3787c478bd9Sstevel@tonic-gate     input_token = &real_input_token;
379*55fea89dSDan Cross 
3807c478bd9Sstevel@tonic-gate     real_input_token.value  = inblob->data;
3817c478bd9Sstevel@tonic-gate     real_input_token.length = inblob->curlen;
382*55fea89dSDan Cross 
3837c478bd9Sstevel@tonic-gate     output_token = &real_output_token;
3847c478bd9Sstevel@tonic-gate     output_token->value = NULL;
3857c478bd9Sstevel@tonic-gate     output_token->length = 0;
386*55fea89dSDan Cross 
3877c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
3887c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&global_mutex) < 0)
3897c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
3907c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
3917c478bd9Sstevel@tonic-gate     maj_stat = gss_wrap (&min_stat,
3927c478bd9Sstevel@tonic-gate 			 text->gss_ctx,
3937c478bd9Sstevel@tonic-gate 			 privacy,
3947c478bd9Sstevel@tonic-gate 			 GSS_C_QOP_DEFAULT,
3957c478bd9Sstevel@tonic-gate 			 input_token,
3967c478bd9Sstevel@tonic-gate 			 NULL,
3977c478bd9Sstevel@tonic-gate 			 output_token);
398*55fea89dSDan Cross 
3997c478bd9Sstevel@tonic-gate     if (GSS_ERROR(maj_stat))
4007c478bd9Sstevel@tonic-gate 	{
4017c478bd9Sstevel@tonic-gate 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
4027c478bd9Sstevel@tonic-gate 	    if (output_token->value)
4037c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
4047c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
4057c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&global_mutex);
4067c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
4077c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
4087c478bd9Sstevel@tonic-gate 	}
409*55fea89dSDan Cross 
4107c478bd9Sstevel@tonic-gate     if (output_token->value && output) {
4117c478bd9Sstevel@tonic-gate 	int len;
412*55fea89dSDan Cross 
4137c478bd9Sstevel@tonic-gate 	ret = _plug_buf_alloc(text->utils, &(text->encode_buf),
4147c478bd9Sstevel@tonic-gate 			      &(text->encode_buf_len), output_token->length + 4);
415*55fea89dSDan Cross 
4167c478bd9Sstevel@tonic-gate 	if (ret != SASL_OK) {
4177c478bd9Sstevel@tonic-gate 	    gss_release_buffer(&min_stat, output_token);
4187c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
4197c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&global_mutex);
4207c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
4217c478bd9Sstevel@tonic-gate 	    return ret;
4227c478bd9Sstevel@tonic-gate 	}
423*55fea89dSDan Cross 
4247c478bd9Sstevel@tonic-gate 	len = htonl(output_token->length);
4257c478bd9Sstevel@tonic-gate 	memcpy(text->encode_buf, &len, 4);
4267c478bd9Sstevel@tonic-gate 	memcpy(text->encode_buf + 4, output_token->value, output_token->length);
4277c478bd9Sstevel@tonic-gate     }
428*55fea89dSDan Cross 
4297c478bd9Sstevel@tonic-gate     if (outputlen) {
4307c478bd9Sstevel@tonic-gate 	*outputlen = output_token->length + 4;
4317c478bd9Sstevel@tonic-gate     }
432*55fea89dSDan Cross 
4337c478bd9Sstevel@tonic-gate     *output = text->encode_buf;
434*55fea89dSDan Cross 
4357c478bd9Sstevel@tonic-gate     if (output_token->value)
4367c478bd9Sstevel@tonic-gate 	gss_release_buffer(&min_stat, output_token);
437*55fea89dSDan Cross 
4387c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
4397c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
4407c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate     return SASL_OK;
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate 
gssapi_privacy_encode(void * context,const struct iovec * invec,unsigned numiov,const char ** output,unsigned * outputlen)4457c478bd9Sstevel@tonic-gate static int gssapi_privacy_encode(void *context, const struct iovec *invec,
4467c478bd9Sstevel@tonic-gate 				 unsigned numiov, const char **output,
4477c478bd9Sstevel@tonic-gate 				 unsigned *outputlen)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate     return sasl_gss_encode(context,invec,numiov,output,outputlen,1);
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate 
gssapi_integrity_encode(void * context,const struct iovec * invec,unsigned numiov,const char ** output,unsigned * outputlen)4527c478bd9Sstevel@tonic-gate static int gssapi_integrity_encode(void *context, const struct iovec *invec,
4537c478bd9Sstevel@tonic-gate 				   unsigned numiov, const char **output,
454*55fea89dSDan Cross 				   unsigned *outputlen)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate     return sasl_gss_encode(context,invec,numiov,output,outputlen,0);
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate #define myMIN(a,b) (((a) < (b)) ? (a) : (b))
4607c478bd9Sstevel@tonic-gate 
gssapi_decode_once(void * context,const char ** input,unsigned * inputlen,char ** output,unsigned * outputlen)4617c478bd9Sstevel@tonic-gate static int gssapi_decode_once(void *context,
4627c478bd9Sstevel@tonic-gate 			      const char **input, unsigned *inputlen,
4637c478bd9Sstevel@tonic-gate 			      char **output, unsigned *outputlen)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate     context_t *text = (context_t *) context;
4667c478bd9Sstevel@tonic-gate     OM_uint32 maj_stat, min_stat;
4677c478bd9Sstevel@tonic-gate     gss_buffer_t input_token, output_token;
4687c478bd9Sstevel@tonic-gate     gss_buffer_desc real_input_token, real_output_token;
4697c478bd9Sstevel@tonic-gate     int result;
4707c478bd9Sstevel@tonic-gate     unsigned diff;
471*55fea89dSDan Cross 
4727c478bd9Sstevel@tonic-gate     if (text->state != SASL_GSSAPI_STATE_AUTHENTICATED) {
4737c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
4747c478bd9Sstevel@tonic-gate 	SETERROR(text->utils, gettext("GSSAPI Failure"));
4757c478bd9Sstevel@tonic-gate #else
4767c478bd9Sstevel@tonic-gate 	SETERROR(text->utils, "GSSAPI Failure");
4777c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
4787c478bd9Sstevel@tonic-gate 	return SASL_NOTDONE;
4797c478bd9Sstevel@tonic-gate     }
480*55fea89dSDan Cross 
4817c478bd9Sstevel@tonic-gate     /* first we need to extract a packet */
4827c478bd9Sstevel@tonic-gate     if (text->needsize > 0) {
4837c478bd9Sstevel@tonic-gate 	/* how long is it? */
4847c478bd9Sstevel@tonic-gate 	int tocopy = myMIN(text->needsize, *inputlen);
485*55fea89dSDan Cross 
4867c478bd9Sstevel@tonic-gate 	memcpy(text->sizebuf + 4 - text->needsize, *input, tocopy);
4877c478bd9Sstevel@tonic-gate 	text->needsize -= tocopy;
4887c478bd9Sstevel@tonic-gate 	*input += tocopy;
4897c478bd9Sstevel@tonic-gate 	*inputlen -= tocopy;
490*55fea89dSDan Cross 
4917c478bd9Sstevel@tonic-gate 	if (text->needsize == 0) {
4927c478bd9Sstevel@tonic-gate 	    /* got the entire size */
4937c478bd9Sstevel@tonic-gate 	    memcpy(&text->size, text->sizebuf, 4);
4947c478bd9Sstevel@tonic-gate 	    text->size = ntohl(text->size);
4957c478bd9Sstevel@tonic-gate 	    text->cursize = 0;
496*55fea89dSDan Cross 
4977c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4987c478bd9Sstevel@tonic-gate 	    if (text->size > 0xFFFFFF) {
4997c478bd9Sstevel@tonic-gate 		text->utils->log(text->utils->conn, SASL_LOG_ERR,
5007c478bd9Sstevel@tonic-gate 				 "Illegal size in sasl_gss_decode_once");
5017c478bd9Sstevel@tonic-gate #else
5027c478bd9Sstevel@tonic-gate 	    if (text->size > 0xFFFFFF || text->size <= 0) {
5037c478bd9Sstevel@tonic-gate 		SETERROR(text->utils, "Illegal size in sasl_gss_decode_once");
5047c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5057c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
5067c478bd9Sstevel@tonic-gate 	    }
507*55fea89dSDan Cross 
5087c478bd9Sstevel@tonic-gate 	    if (text->bufsize < text->size + 5) {
5097c478bd9Sstevel@tonic-gate 		result = _plug_buf_alloc(text->utils, &text->buffer,
5107c478bd9Sstevel@tonic-gate 					 &(text->bufsize), text->size+5);
5117c478bd9Sstevel@tonic-gate 		if(result != SASL_OK) return result;
5127c478bd9Sstevel@tonic-gate 	    }
5137c478bd9Sstevel@tonic-gate 	}
5147c478bd9Sstevel@tonic-gate 	if (*inputlen == 0) {
5157c478bd9Sstevel@tonic-gate 	    /* need more data ! */
5167c478bd9Sstevel@tonic-gate 	    *outputlen = 0;
5177c478bd9Sstevel@tonic-gate 	    *output = NULL;
518*55fea89dSDan Cross 
5197c478bd9Sstevel@tonic-gate 	    return SASL_OK;
5207c478bd9Sstevel@tonic-gate 	}
5217c478bd9Sstevel@tonic-gate     }
522*55fea89dSDan Cross 
5237c478bd9Sstevel@tonic-gate     diff = text->size - text->cursize;
524*55fea89dSDan Cross 
5257c478bd9Sstevel@tonic-gate     if (*inputlen < diff) {
5267c478bd9Sstevel@tonic-gate 	/* ok, let's queue it up; not enough data */
5277c478bd9Sstevel@tonic-gate 	memcpy(text->buffer + text->cursize, *input, *inputlen);
5287c478bd9Sstevel@tonic-gate 	text->cursize += *inputlen;
5297c478bd9Sstevel@tonic-gate 	*inputlen = 0;
5307c478bd9Sstevel@tonic-gate 	*outputlen = 0;
5317c478bd9Sstevel@tonic-gate 	*output = NULL;
5327c478bd9Sstevel@tonic-gate 	return SASL_OK;
5337c478bd9Sstevel@tonic-gate     } else {
5347c478bd9Sstevel@tonic-gate 	memcpy(text->buffer + text->cursize, *input, diff);
5357c478bd9Sstevel@tonic-gate 	*input += diff;
5367c478bd9Sstevel@tonic-gate 	*inputlen -= diff;
5377c478bd9Sstevel@tonic-gate     }
538*55fea89dSDan Cross 
539*55fea89dSDan Cross     input_token = &real_input_token;
5407c478bd9Sstevel@tonic-gate     real_input_token.value = text->buffer;
5417c478bd9Sstevel@tonic-gate     real_input_token.length = text->size;
542*55fea89dSDan Cross 
5437c478bd9Sstevel@tonic-gate     output_token = &real_output_token;
5447c478bd9Sstevel@tonic-gate     output_token->value = NULL;
5457c478bd9Sstevel@tonic-gate     output_token->length = 0;
546*55fea89dSDan Cross 
5477c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
5487c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&global_mutex) < 0)
5497c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
5507c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate     maj_stat = gss_unwrap (&min_stat,
5537c478bd9Sstevel@tonic-gate 			   text->gss_ctx,
5547c478bd9Sstevel@tonic-gate 			   input_token,
5557c478bd9Sstevel@tonic-gate 			   output_token,
5567c478bd9Sstevel@tonic-gate 			   NULL,
5577c478bd9Sstevel@tonic-gate 			   NULL);
558*55fea89dSDan Cross 
5597c478bd9Sstevel@tonic-gate     if (GSS_ERROR(maj_stat))
5607c478bd9Sstevel@tonic-gate 	{
5617c478bd9Sstevel@tonic-gate 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
5627c478bd9Sstevel@tonic-gate 	    if (output_token->value)
5637c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
5647c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
5657c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&global_mutex);
5667c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
5677c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
5687c478bd9Sstevel@tonic-gate 	}
569*55fea89dSDan Cross 
5707c478bd9Sstevel@tonic-gate     if (outputlen)
5717c478bd9Sstevel@tonic-gate 	*outputlen = output_token->length;
572*55fea89dSDan Cross 
5737c478bd9Sstevel@tonic-gate     if (output_token->value) {
5747c478bd9Sstevel@tonic-gate 	if (output) {
5757c478bd9Sstevel@tonic-gate 	    result = _plug_buf_alloc(text->utils, &text->decode_once_buf,
5767c478bd9Sstevel@tonic-gate 				     &text->decode_once_buf_len,
5777c478bd9Sstevel@tonic-gate 				     *outputlen);
5787c478bd9Sstevel@tonic-gate 	    if(result != SASL_OK) {
5797c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
5807c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
5817c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&global_mutex);
5827c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
5837c478bd9Sstevel@tonic-gate 		return result;
5847c478bd9Sstevel@tonic-gate 	    }
5857c478bd9Sstevel@tonic-gate 	    *output = text->decode_once_buf;
5867c478bd9Sstevel@tonic-gate 	    memcpy(*output, output_token->value, *outputlen);
5877c478bd9Sstevel@tonic-gate 	}
5887c478bd9Sstevel@tonic-gate 	gss_release_buffer(&min_stat, output_token);
5897c478bd9Sstevel@tonic-gate     }
5907c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
5917c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&global_mutex);
5927c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
593*55fea89dSDan Cross 
5947c478bd9Sstevel@tonic-gate     /* reset for the next packet */
5957c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
5967c478bd9Sstevel@tonic-gate     text->size = -1;
5977c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
5987c478bd9Sstevel@tonic-gate     text->needsize = 4;
599*55fea89dSDan Cross 
6007c478bd9Sstevel@tonic-gate     return SASL_OK;
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate static int gssapi_decode(void *context,
6047c478bd9Sstevel@tonic-gate 			 const char *input, unsigned inputlen,
6057c478bd9Sstevel@tonic-gate 			 const char **output, unsigned *outputlen)
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate     context_t *text = (context_t *) context;
6087c478bd9Sstevel@tonic-gate     int ret;
609*55fea89dSDan Cross 
6107c478bd9Sstevel@tonic-gate     ret = _plug_decode(text->utils, context, input, inputlen,
6117c478bd9Sstevel@tonic-gate 		       &text->decode_buf, &text->decode_buf_len, outputlen,
6127c478bd9Sstevel@tonic-gate 		       gssapi_decode_once);
613*55fea89dSDan Cross 
6147c478bd9Sstevel@tonic-gate     *output = text->decode_buf;
615*55fea89dSDan Cross 
6167c478bd9Sstevel@tonic-gate     return ret;
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate static context_t *gss_new_context(const sasl_utils_t *utils)
6207c478bd9Sstevel@tonic-gate {
6217c478bd9Sstevel@tonic-gate     context_t *ret;
622*55fea89dSDan Cross 
6237c478bd9Sstevel@tonic-gate     ret = utils->malloc(sizeof(context_t));
6247c478bd9Sstevel@tonic-gate     if(!ret) return NULL;
625*55fea89dSDan Cross 
6267c478bd9Sstevel@tonic-gate     memset(ret,0,sizeof(context_t));
6277c478bd9Sstevel@tonic-gate     ret->utils = utils;
6287c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6297c478bd9Sstevel@tonic-gate     ret->gss_ctx = GSS_C_NO_CONTEXT;
6307c478bd9Sstevel@tonic-gate     ret->client_name = GSS_C_NO_NAME;
6317c478bd9Sstevel@tonic-gate     ret->server_name = GSS_C_NO_NAME;
6327c478bd9Sstevel@tonic-gate     ret->server_creds = GSS_C_NO_CREDENTIAL;
6337c478bd9Sstevel@tonic-gate     ret->client_creds = GSS_C_NO_CREDENTIAL;
6347c478bd9Sstevel@tonic-gate     if (get_oid(utils, &ret->mech_oid) != SASL_OK) {
6357c478bd9Sstevel@tonic-gate 	utils->free(ret);
6367c478bd9Sstevel@tonic-gate 	return (NULL);
6377c478bd9Sstevel@tonic-gate     }
6387c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
639*55fea89dSDan Cross 
6407c478bd9Sstevel@tonic-gate     ret->needsize = 4;
641*55fea89dSDan Cross 
6427c478bd9Sstevel@tonic-gate     return ret;
6437c478bd9Sstevel@tonic-gate }
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate static void sasl_gss_free_context_contents(context_t *text)
6467c478bd9Sstevel@tonic-gate {
6474213c2d8SToomas Soome     OM_uint32 min_stat;
648*55fea89dSDan Cross 
6497c478bd9Sstevel@tonic-gate     if (!text) return;
650*55fea89dSDan Cross 
6517c478bd9Sstevel@tonic-gate     if (text->gss_ctx != GSS_C_NO_CONTEXT) {
6524213c2d8SToomas Soome 	(void) gss_delete_sec_context(&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
6537c478bd9Sstevel@tonic-gate 	text->gss_ctx = GSS_C_NO_CONTEXT;
6547c478bd9Sstevel@tonic-gate     }
655*55fea89dSDan Cross 
6567c478bd9Sstevel@tonic-gate     if (text->client_name != GSS_C_NO_NAME) {
6574213c2d8SToomas Soome 	(void) gss_release_name(&min_stat,&text->client_name);
6587c478bd9Sstevel@tonic-gate 	text->client_name = GSS_C_NO_NAME;
6597c478bd9Sstevel@tonic-gate     }
660*55fea89dSDan Cross 
6617c478bd9Sstevel@tonic-gate     if (text->server_name != GSS_C_NO_NAME) {
6624213c2d8SToomas Soome 	(void) gss_release_name(&min_stat,&text->server_name);
6637c478bd9Sstevel@tonic-gate 	text->server_name = GSS_C_NO_NAME;
6647c478bd9Sstevel@tonic-gate     }
665*55fea89dSDan Cross 
6667c478bd9Sstevel@tonic-gate     if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
6674213c2d8SToomas Soome 	(void) gss_release_cred(&min_stat, &text->server_creds);
6687c478bd9Sstevel@tonic-gate 	text->server_creds = GSS_C_NO_CREDENTIAL;
6697c478bd9Sstevel@tonic-gate     }
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6727c478bd9Sstevel@tonic-gate     if ( text->client_creds != GSS_C_NO_CREDENTIAL) {
6734213c2d8SToomas Soome 	(void) gss_release_cred(&min_stat, &text->client_creds);
6747c478bd9Sstevel@tonic-gate 	text->client_creds = GSS_C_NO_CREDENTIAL;
6757c478bd9Sstevel@tonic-gate     }
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate     /*
6787c478bd9Sstevel@tonic-gate      * Note that the oid returned by rpc_gss_mech_to_oid should not
6797c478bd9Sstevel@tonic-gate      * be released
6807c478bd9Sstevel@tonic-gate      */
6817c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
682*55fea89dSDan Cross 
6837c478bd9Sstevel@tonic-gate     if (text->out_buf) {
6847c478bd9Sstevel@tonic-gate 	text->utils->free(text->out_buf);
6857c478bd9Sstevel@tonic-gate 	text->out_buf = NULL;
6867c478bd9Sstevel@tonic-gate     }
687*55fea89dSDan Cross 
6887c478bd9Sstevel@tonic-gate     if (text->encode_buf) {
6897c478bd9Sstevel@tonic-gate 	text->utils->free(text->encode_buf);
6907c478bd9Sstevel@tonic-gate 	text->encode_buf = NULL;
6917c478bd9Sstevel@tonic-gate     }
692*55fea89dSDan Cross 
6937c478bd9Sstevel@tonic-gate     if (text->decode_buf) {
6947c478bd9Sstevel@tonic-gate 	text->utils->free(text->decode_buf);
6957c478bd9Sstevel@tonic-gate 	text->decode_buf = NULL;
6967c478bd9Sstevel@tonic-gate     }
697*55fea89dSDan Cross 
6987c478bd9Sstevel@tonic-gate     if (text->decode_once_buf) {
6997c478bd9Sstevel@tonic-gate 	text->utils->free(text->decode_once_buf);
7007c478bd9Sstevel@tonic-gate 	text->decode_once_buf = NULL;
7017c478bd9Sstevel@tonic-gate     }
702*55fea89dSDan Cross 
7037c478bd9Sstevel@tonic-gate     if (text->enc_in_buf) {
7047c478bd9Sstevel@tonic-gate 	if(text->enc_in_buf->data) text->utils->free(text->enc_in_buf->data);
7057c478bd9Sstevel@tonic-gate 	text->utils->free(text->enc_in_buf);
7067c478bd9Sstevel@tonic-gate 	text->enc_in_buf = NULL;
7077c478bd9Sstevel@tonic-gate     }
708*55fea89dSDan Cross 
7097c478bd9Sstevel@tonic-gate     if (text->buffer) {
7107c478bd9Sstevel@tonic-gate 	text->utils->free(text->buffer);
7117c478bd9Sstevel@tonic-gate 	text->buffer = NULL;
7127c478bd9Sstevel@tonic-gate     }
713*55fea89dSDan Cross 
7147c478bd9Sstevel@tonic-gate     if (text->authid) { /* works for both client and server */
7157c478bd9Sstevel@tonic-gate 	text->utils->free(text->authid);
7167c478bd9Sstevel@tonic-gate 	text->authid = NULL;
7177c478bd9Sstevel@tonic-gate     }
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate #ifdef HAVE_RPC_GSS_MECH_TO_OID
7237c478bd9Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
7247c478bd9Sstevel@tonic-gate #endif /* HAVE_RPC_GSS_MECH_TO_OID */
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate static int
7277c478bd9Sstevel@tonic-gate get_oid(const sasl_utils_t *utils, gss_OID *oid)
7287c478bd9Sstevel@tonic-gate {
7297c478bd9Sstevel@tonic-gate #ifdef HAVE_RPC_GSS_MECH_TO_OID
7307c478bd9Sstevel@tonic-gate     static gss_OID_desc kerb_v5 =
7317c478bd9Sstevel@tonic-gate 	{9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
7327c478bd9Sstevel@tonic-gate 	/* 1.2.840.113554.1.2.2 */
7337c478bd9Sstevel@tonic-gate     *oid = &kerb_v5;
7347c478bd9Sstevel@tonic-gate #endif /* HAVE_RPC_GSS_MECH_TO_OID */
7357c478bd9Sstevel@tonic-gate     return (SASL_OK);
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate static int
7397c478bd9Sstevel@tonic-gate add_mech_to_set(context_t *text, gss_OID_set *desired_mechs)
7407c478bd9Sstevel@tonic-gate {
7417c478bd9Sstevel@tonic-gate     OM_uint32 maj_stat, min_stat;
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate     maj_stat = gss_create_empty_oid_set(&min_stat, desired_mechs);
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate     if (GSS_ERROR(maj_stat)) {
7467c478bd9Sstevel@tonic-gate 	sasl_gss_seterror(text->utils, maj_stat, min_stat);
7477c478bd9Sstevel@tonic-gate 	sasl_gss_free_context_contents(text);
7487c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
7497c478bd9Sstevel@tonic-gate     }
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate     maj_stat = gss_add_oid_set_member(&min_stat, text->mech_oid, desired_mechs);
7527c478bd9Sstevel@tonic-gate     if (GSS_ERROR(maj_stat)) {
7537c478bd9Sstevel@tonic-gate 	sasl_gss_seterror(text->utils, maj_stat, min_stat);
7547c478bd9Sstevel@tonic-gate 	sasl_gss_free_context_contents(text);
7557c478bd9Sstevel@tonic-gate 	(void) gss_release_oid_set(&min_stat, desired_mechs);
7567c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
7577c478bd9Sstevel@tonic-gate     }
7587c478bd9Sstevel@tonic-gate     return SASL_OK;
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate static void gssapi_common_mech_dispose(void *conn_context,
7637c478bd9Sstevel@tonic-gate 				       const sasl_utils_t *utils)
7647c478bd9Sstevel@tonic-gate {
7657c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7667c478bd9Sstevel@tonic-gate     if (conn_context == NULL)
7677c478bd9Sstevel@tonic-gate 	return;
7687c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
7697c478bd9Sstevel@tonic-gate     convert_prompt(utils, &((context_t *)conn_context)->h, NULL);
7707c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
7717c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7727c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
7737c478bd9Sstevel@tonic-gate     (void) LOCK_MUTEX(&global_mutex);
7747c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
7757c478bd9Sstevel@tonic-gate     sasl_gss_free_context_contents((context_t *)(conn_context));
7767c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
7777c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
7787c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
7797c478bd9Sstevel@tonic-gate     utils->free(conn_context);
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate /*****************************  Server Section  *****************************/
7837c478bd9Sstevel@tonic-gate 
784*55fea89dSDan Cross static int
785*55fea89dSDan Cross gssapi_server_mech_new(void *glob_context __attribute__((unused)),
7867c478bd9Sstevel@tonic-gate 		       sasl_server_params_t *params,
787*55fea89dSDan Cross 		       const char *challenge __attribute__((unused)),
7887c478bd9Sstevel@tonic-gate 		       unsigned challen __attribute__((unused)),
7897c478bd9Sstevel@tonic-gate 		       void **conn_context)
7907c478bd9Sstevel@tonic-gate {
7917c478bd9Sstevel@tonic-gate     context_t *text;
792*55fea89dSDan Cross 
7937c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
7947c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&global_mutex) < 0)
7957c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
7967c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
7977c478bd9Sstevel@tonic-gate     text = gss_new_context(params->utils);
7987c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
7997c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
8007c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
8017c478bd9Sstevel@tonic-gate     if (text == NULL) {
8027c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
8037c478bd9Sstevel@tonic-gate 	MEMERROR(params->utils);
8047c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
8057c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
8067c478bd9Sstevel@tonic-gate     }
807*55fea89dSDan Cross 
8087c478bd9Sstevel@tonic-gate     text->gss_ctx = GSS_C_NO_CONTEXT;
8097c478bd9Sstevel@tonic-gate     text->client_name = GSS_C_NO_NAME;
8107c478bd9Sstevel@tonic-gate     text->server_name = GSS_C_NO_NAME;
8117c478bd9Sstevel@tonic-gate     text->server_creds = GSS_C_NO_CREDENTIAL;
8127c478bd9Sstevel@tonic-gate     text->state = SASL_GSSAPI_STATE_AUTHNEG;
813*55fea89dSDan Cross 
8147c478bd9Sstevel@tonic-gate     *conn_context = text;
815*55fea89dSDan Cross 
8167c478bd9Sstevel@tonic-gate     return SASL_OK;
8177c478bd9Sstevel@tonic-gate }
8187c478bd9Sstevel@tonic-gate 
819*55fea89dSDan Cross static int
8207c478bd9Sstevel@tonic-gate gssapi_server_mech_step(void *conn_context,
8217c478bd9Sstevel@tonic-gate 			sasl_server_params_t *params,
8227c478bd9Sstevel@tonic-gate 			const char *clientin,
8237c478bd9Sstevel@tonic-gate 			unsigned clientinlen,
8247c478bd9Sstevel@tonic-gate 			const char **serverout,
8257c478bd9Sstevel@tonic-gate 			unsigned *serveroutlen,
8267c478bd9Sstevel@tonic-gate 			sasl_out_params_t *oparams)
8277c478bd9Sstevel@tonic-gate {
8287c478bd9Sstevel@tonic-gate     context_t *text = (context_t *)conn_context;
8297c478bd9Sstevel@tonic-gate     gss_buffer_t input_token, output_token;
8307c478bd9Sstevel@tonic-gate     gss_buffer_desc real_input_token, real_output_token;
8317c478bd9Sstevel@tonic-gate     OM_uint32 maj_stat, min_stat;
8327c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
8337c478bd9Sstevel@tonic-gate     OM_uint32 max_input_size;
8347c478bd9Sstevel@tonic-gate     gss_OID_set desired_mechs = GSS_C_NULL_OID_SET;
8357c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
8367c478bd9Sstevel@tonic-gate     gss_buffer_desc name_token;
8377c478bd9Sstevel@tonic-gate     int ret;
838*55fea89dSDan Cross 
8397c478bd9Sstevel@tonic-gate     input_token = &real_input_token;
8407c478bd9Sstevel@tonic-gate     output_token = &real_output_token;
8417c478bd9Sstevel@tonic-gate     output_token->value = NULL; output_token->length = 0;
8427c478bd9Sstevel@tonic-gate     input_token->value = NULL; input_token->length = 0;
843*55fea89dSDan Cross 
8447c478bd9Sstevel@tonic-gate     if(!serverout) {
8457c478bd9Sstevel@tonic-gate 	PARAMERROR(text->utils);
8467c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
8477c478bd9Sstevel@tonic-gate     }
848*55fea89dSDan Cross 
8497c478bd9Sstevel@tonic-gate     *serverout = NULL;
850*55fea89dSDan Cross     *serveroutlen = 0;
851*55fea89dSDan Cross 
8527c478bd9Sstevel@tonic-gate     switch (text->state) {
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate     case SASL_GSSAPI_STATE_AUTHNEG:
8557c478bd9Sstevel@tonic-gate 	if (text->server_name == GSS_C_NO_NAME) { /* only once */
8567c478bd9Sstevel@tonic-gate 	    name_token.length = strlen(params->service) + 1 + strlen(params->serverFQDN);
8577c478bd9Sstevel@tonic-gate 	    name_token.value = (char *)params->utils->malloc((name_token.length + 1) * sizeof(char));
8587c478bd9Sstevel@tonic-gate 	    if (name_token.value == NULL) {
8597c478bd9Sstevel@tonic-gate 		MEMERROR(text->utils);
8607c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
8617c478bd9Sstevel@tonic-gate 		return SASL_NOMEM;
8627c478bd9Sstevel@tonic-gate 	    }
8637c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
8647c478bd9Sstevel@tonic-gate 	    snprintf(name_token.value, name_token.length + 1,
8657c478bd9Sstevel@tonic-gate 		"%s@%s", params->service, params->serverFQDN);
8667c478bd9Sstevel@tonic-gate #else
8677c478bd9Sstevel@tonic-gate 	    sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
8687c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
869*55fea89dSDan Cross 
8707c478bd9Sstevel@tonic-gate 	    maj_stat = gss_import_name (&min_stat,
8717c478bd9Sstevel@tonic-gate 					&name_token,
8727c478bd9Sstevel@tonic-gate 					GSS_C_NT_HOSTBASED_SERVICE,
8737c478bd9Sstevel@tonic-gate 					&text->server_name);
874*55fea89dSDan Cross 
8757c478bd9Sstevel@tonic-gate 	    params->utils->free(name_token.value);
8767c478bd9Sstevel@tonic-gate 	    name_token.value = NULL;
877*55fea89dSDan Cross 
8787c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
8797c478bd9Sstevel@tonic-gate 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
8807c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
8817c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
8827c478bd9Sstevel@tonic-gate 	    }
883*55fea89dSDan Cross 
8847c478bd9Sstevel@tonic-gate 	    if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
8857c478bd9Sstevel@tonic-gate 		maj_stat = gss_release_cred(&min_stat, &text->server_creds);
8867c478bd9Sstevel@tonic-gate 		text->server_creds = GSS_C_NO_CREDENTIAL;
8877c478bd9Sstevel@tonic-gate 	    }
888*55fea89dSDan Cross 
8897c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
8907c478bd9Sstevel@tonic-gate 	    if (text->mech_oid != GSS_C_NULL_OID) {
8917c478bd9Sstevel@tonic-gate 		ret = add_mech_to_set(text, &desired_mechs);
8927c478bd9Sstevel@tonic-gate 		if (ret != SASL_OK)
8937c478bd9Sstevel@tonic-gate 		    return (ret);
8947c478bd9Sstevel@tonic-gate 	    }
8957c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
8967c478bd9Sstevel@tonic-gate 
897*55fea89dSDan Cross 	    maj_stat = gss_acquire_cred(&min_stat,
8987c478bd9Sstevel@tonic-gate 					text->server_name,
899*55fea89dSDan Cross 					GSS_C_INDEFINITE,
9007c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
9017c478bd9Sstevel@tonic-gate 					desired_mechs,
9027c478bd9Sstevel@tonic-gate #else
9037c478bd9Sstevel@tonic-gate 					GSS_C_NO_OID_SET,
9047c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
9057c478bd9Sstevel@tonic-gate 					GSS_C_ACCEPT,
906*55fea89dSDan Cross 					&text->server_creds,
907*55fea89dSDan Cross 					NULL,
9087c478bd9Sstevel@tonic-gate 					NULL);
909*55fea89dSDan Cross 
9107c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
9117c478bd9Sstevel@tonic-gate 	    if (desired_mechs != GSS_C_NULL_OID_SET) {
9127c478bd9Sstevel@tonic-gate 		OM_uint32 min_stat2;
9137c478bd9Sstevel@tonic-gate 		(void) gss_release_oid_set(&min_stat2, &desired_mechs);
9147c478bd9Sstevel@tonic-gate 	    }
9157c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
9187c478bd9Sstevel@tonic-gate 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
9197c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
9207c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
9217c478bd9Sstevel@tonic-gate 	    }
9227c478bd9Sstevel@tonic-gate 	}
923*55fea89dSDan Cross 
9247c478bd9Sstevel@tonic-gate 	if (clientinlen) {
9257c478bd9Sstevel@tonic-gate 	    real_input_token.value = (void *)clientin;
9267c478bd9Sstevel@tonic-gate 	    real_input_token.length = clientinlen;
9277c478bd9Sstevel@tonic-gate 	}
928*55fea89dSDan Cross 
9297c478bd9Sstevel@tonic-gate 	maj_stat =
9307c478bd9Sstevel@tonic-gate 	    gss_accept_sec_context(&min_stat,
9317c478bd9Sstevel@tonic-gate 				   &(text->gss_ctx),
9327c478bd9Sstevel@tonic-gate 				   text->server_creds,
9337c478bd9Sstevel@tonic-gate 				   input_token,
9347c478bd9Sstevel@tonic-gate 				   GSS_C_NO_CHANNEL_BINDINGS,
9357c478bd9Sstevel@tonic-gate 				   &text->client_name,
9367c478bd9Sstevel@tonic-gate 				   NULL,
9377c478bd9Sstevel@tonic-gate 				   output_token,
9387c478bd9Sstevel@tonic-gate 				   NULL,
9397c478bd9Sstevel@tonic-gate 				   NULL,
9407c478bd9Sstevel@tonic-gate 				   NULL);
941*55fea89dSDan Cross 
9427c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj_stat)) {
9437c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
9447c478bd9Sstevel@tonic-gate 	    /* log the local error info, set a more generic error */
9457c478bd9Sstevel@tonic-gate 	    sasl_gss_log(text->utils, maj_stat, min_stat);
946*55fea89dSDan Cross 	    text->utils->seterror(text->utils->conn, SASL_NOLOG,
9477c478bd9Sstevel@tonic-gate 		    gettext("GSSAPI Failure: accept security context error"));
9487c478bd9Sstevel@tonic-gate 	    if (output_token->value) {
9497c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
9507c478bd9Sstevel@tonic-gate 	    }
9517c478bd9Sstevel@tonic-gate #else
9527c478bd9Sstevel@tonic-gate 	    if (output_token->value) {
9537c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
9547c478bd9Sstevel@tonic-gate 	    }
9557c478bd9Sstevel@tonic-gate 	    text->utils->seterror(text->utils->conn, SASL_NOLOG, "GSSAPI Failure: gss_accept_sec_context");
9567c478bd9Sstevel@tonic-gate 	    text->utils->log(NULL, SASL_LOG_DEBUG, "GSSAPI Failure: gss_accept_sec_context");
9577c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
9587c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
9597c478bd9Sstevel@tonic-gate 	    return SASL_BADAUTH;
9607c478bd9Sstevel@tonic-gate 	}
961*55fea89dSDan Cross 
9627c478bd9Sstevel@tonic-gate 	if (serveroutlen)
9637c478bd9Sstevel@tonic-gate 	    *serveroutlen = output_token->length;
9647c478bd9Sstevel@tonic-gate 	if (output_token->value) {
9657c478bd9Sstevel@tonic-gate 	    if (serverout) {
9667c478bd9Sstevel@tonic-gate 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
9677c478bd9Sstevel@tonic-gate 				      &(text->out_buf_len), *serveroutlen);
9687c478bd9Sstevel@tonic-gate 		if(ret != SASL_OK) {
9697c478bd9Sstevel@tonic-gate 		    gss_release_buffer(&min_stat, output_token);
9707c478bd9Sstevel@tonic-gate 		    return ret;
9717c478bd9Sstevel@tonic-gate 		}
9727c478bd9Sstevel@tonic-gate 		memcpy(text->out_buf, output_token->value, *serveroutlen);
9737c478bd9Sstevel@tonic-gate 		*serverout = text->out_buf;
9747c478bd9Sstevel@tonic-gate 	    }
975*55fea89dSDan Cross 
9767c478bd9Sstevel@tonic-gate 	    gss_release_buffer(&min_stat, output_token);
9777c478bd9Sstevel@tonic-gate 	} else {
9787c478bd9Sstevel@tonic-gate 	    /* No output token, send an empty string */
9797c478bd9Sstevel@tonic-gate 	    *serverout = GSSAPI_BLANK_STRING;
9807c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
9817c478bd9Sstevel@tonic-gate 	    serveroutlen = 0;
9827c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
9837c478bd9Sstevel@tonic-gate 	}
984*55fea89dSDan Cross 
985*55fea89dSDan Cross 
9867c478bd9Sstevel@tonic-gate 	if (maj_stat == GSS_S_COMPLETE) {
9877c478bd9Sstevel@tonic-gate 	    /* Switch to ssf negotiation */
9887c478bd9Sstevel@tonic-gate 	    text->state = SASL_GSSAPI_STATE_SSFCAP;
9897c478bd9Sstevel@tonic-gate 	}
990*55fea89dSDan Cross 
9917c478bd9Sstevel@tonic-gate 	return SASL_CONTINUE;
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate     case SASL_GSSAPI_STATE_SSFCAP: {
9947c478bd9Sstevel@tonic-gate 	unsigned char sasldata[4];
9957c478bd9Sstevel@tonic-gate 	gss_buffer_desc name_token;
9967c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
9977c478bd9Sstevel@tonic-gate 	gss_buffer_desc name_without_realm;
9987c478bd9Sstevel@tonic-gate 	gss_name_t without = NULL;
9997c478bd9Sstevel@tonic-gate 	int equal;
10007c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1001*55fea89dSDan Cross 
10027c478bd9Sstevel@tonic-gate 	name_token.value = NULL;
10037c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
10047c478bd9Sstevel@tonic-gate 	name_without_realm.value = NULL;
10057c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1006*55fea89dSDan Cross 
10077c478bd9Sstevel@tonic-gate 	/* We ignore whatever the client sent us at this stage */
1008*55fea89dSDan Cross 
10097c478bd9Sstevel@tonic-gate 	maj_stat = gss_display_name (&min_stat,
10107c478bd9Sstevel@tonic-gate 				     text->client_name,
10117c478bd9Sstevel@tonic-gate 				     &name_token,
10127c478bd9Sstevel@tonic-gate 				     NULL);
1013*55fea89dSDan Cross 
10147c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj_stat)) {
10157c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
10167c478bd9Sstevel@tonic-gate 	    if (name_without_realm.value)
10177c478bd9Sstevel@tonic-gate 		params->utils->free(name_without_realm.value);
10187c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1019*55fea89dSDan Cross 
10207c478bd9Sstevel@tonic-gate 	    if (name_token.value)
10217c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, &name_token);
10227c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
10237c478bd9Sstevel@tonic-gate 	    if (without)
10247c478bd9Sstevel@tonic-gate 		gss_release_name(&min_stat, &without);
10257c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
10267c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
10277c478bd9Sstevel@tonic-gate 	    SETERROR(text->utils, gettext("GSSAPI Failure"));
10287c478bd9Sstevel@tonic-gate #else
10297c478bd9Sstevel@tonic-gate 	    SETERROR(text->utils, "GSSAPI Failure");
10307c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
10317c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
10327c478bd9Sstevel@tonic-gate 	    return SASL_BADAUTH;
10337c478bd9Sstevel@tonic-gate 	}
1034*55fea89dSDan Cross 
10357c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
10367c478bd9Sstevel@tonic-gate 	/* If the id contains a realm get the identifier for the user
1037*55fea89dSDan Cross 	   without the realm and see if it's the same id (i.e.
10387c478bd9Sstevel@tonic-gate 	   tmartin == tmartin@ANDREW.CMU.EDU. If this is the case we just want
10397c478bd9Sstevel@tonic-gate 	   to return the id (i.e. just "tmartin" */
10407c478bd9Sstevel@tonic-gate 	if (strchr((char *) name_token.value, (int) '@') != NULL) {
10417c478bd9Sstevel@tonic-gate 	    /* NOTE: libc malloc, as it is freed below by a gssapi internal
10427c478bd9Sstevel@tonic-gate 	     *       function! */
10437c478bd9Sstevel@tonic-gate 	    name_without_realm.value = malloc(strlen(name_token.value)+1);
10447c478bd9Sstevel@tonic-gate 	    if (name_without_realm.value == NULL) {
10457c478bd9Sstevel@tonic-gate 		MEMERROR(text->utils);
10467c478bd9Sstevel@tonic-gate 		return SASL_NOMEM;
10477c478bd9Sstevel@tonic-gate 	    }
1048*55fea89dSDan Cross 
10497c478bd9Sstevel@tonic-gate 	    strcpy(name_without_realm.value, name_token.value);
1050*55fea89dSDan Cross 
10517c478bd9Sstevel@tonic-gate 	    /* cut off string at '@' */
10527c478bd9Sstevel@tonic-gate 	    (strchr(name_without_realm.value,'@'))[0] = '\0';
1053*55fea89dSDan Cross 
10547c478bd9Sstevel@tonic-gate 	    name_without_realm.length = strlen( (char *) name_without_realm.value );
1055*55fea89dSDan Cross 
10567c478bd9Sstevel@tonic-gate 	    maj_stat = gss_import_name (&min_stat,
10577c478bd9Sstevel@tonic-gate 					&name_without_realm,
10587c478bd9Sstevel@tonic-gate 	    /* Solaris 8/9 gss_import_name doesn't accept GSS_C_NULL_OID here,
10597c478bd9Sstevel@tonic-gate 	       so use GSS_C_NT_USER_NAME instead if available.  */
10607c478bd9Sstevel@tonic-gate #ifdef HAVE_GSS_C_NT_USER_NAME
10617c478bd9Sstevel@tonic-gate 					GSS_C_NT_USER_NAME,
10627c478bd9Sstevel@tonic-gate #else
10637c478bd9Sstevel@tonic-gate 					GSS_C_NULL_OID,
10647c478bd9Sstevel@tonic-gate #endif
10657c478bd9Sstevel@tonic-gate 					&without);
1066*55fea89dSDan Cross 
10677c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
10687c478bd9Sstevel@tonic-gate 		params->utils->free(name_without_realm.value);
10697c478bd9Sstevel@tonic-gate 		if (name_token.value)
10707c478bd9Sstevel@tonic-gate 		    gss_release_buffer(&min_stat, &name_token);
10717c478bd9Sstevel@tonic-gate 		if (without)
10727c478bd9Sstevel@tonic-gate 		    gss_release_name(&min_stat, &without);
10737c478bd9Sstevel@tonic-gate 		SETERROR(text->utils, "GSSAPI Failure");
10747c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
10757c478bd9Sstevel@tonic-gate 		return SASL_BADAUTH;
10767c478bd9Sstevel@tonic-gate 	    }
1077*55fea89dSDan Cross 
10787c478bd9Sstevel@tonic-gate 	    maj_stat = gss_compare_name(&min_stat,
10797c478bd9Sstevel@tonic-gate 					text->client_name,
10807c478bd9Sstevel@tonic-gate 					without,
10817c478bd9Sstevel@tonic-gate 					&equal);
1082*55fea89dSDan Cross 
10837c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
10847c478bd9Sstevel@tonic-gate 		params->utils->free(name_without_realm.value);
10857c478bd9Sstevel@tonic-gate 		if (name_token.value)
10867c478bd9Sstevel@tonic-gate 		    gss_release_buffer(&min_stat, &name_token);
10877c478bd9Sstevel@tonic-gate 		if (without)
10887c478bd9Sstevel@tonic-gate 		    gss_release_name(&min_stat, &without);
10897c478bd9Sstevel@tonic-gate 		SETERROR(text->utils, "GSSAPI Failure");
10907c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
10917c478bd9Sstevel@tonic-gate 		return SASL_BADAUTH;
10927c478bd9Sstevel@tonic-gate 	    }
1093*55fea89dSDan Cross 
10947c478bd9Sstevel@tonic-gate 	    gss_release_name(&min_stat,&without);
10957c478bd9Sstevel@tonic-gate 	} else {
10967c478bd9Sstevel@tonic-gate 	    equal = 0;
10977c478bd9Sstevel@tonic-gate 	}
1098*55fea89dSDan Cross 
10997c478bd9Sstevel@tonic-gate 	if (equal) {
11007c478bd9Sstevel@tonic-gate 	    text->authid = strdup(name_without_realm.value);
1101*55fea89dSDan Cross 
11027c478bd9Sstevel@tonic-gate 	    if (text->authid == NULL) {
11037c478bd9Sstevel@tonic-gate 		MEMERROR(params->utils);
11047c478bd9Sstevel@tonic-gate 		return SASL_NOMEM;
11057c478bd9Sstevel@tonic-gate 	    }
11067c478bd9Sstevel@tonic-gate 	} else {
11077c478bd9Sstevel@tonic-gate 	    text->authid = strdup(name_token.value);
1108*55fea89dSDan Cross 
11097c478bd9Sstevel@tonic-gate 	    if (text->authid == NULL) {
11107c478bd9Sstevel@tonic-gate 		MEMERROR(params->utils);
11117c478bd9Sstevel@tonic-gate 		return SASL_NOMEM;
11127c478bd9Sstevel@tonic-gate 	    }
11137c478bd9Sstevel@tonic-gate 	}
11147c478bd9Sstevel@tonic-gate #else
11157c478bd9Sstevel@tonic-gate 	{
11167c478bd9Sstevel@tonic-gate 	    ret = _plug_strdup(params->utils, name_token.value,
11177c478bd9Sstevel@tonic-gate 		&text->authid, NULL);
11187c478bd9Sstevel@tonic-gate 	}
11197c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1120*55fea89dSDan Cross 
11217c478bd9Sstevel@tonic-gate 	if (name_token.value)
11227c478bd9Sstevel@tonic-gate 	    gss_release_buffer(&min_stat, &name_token);
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
11257c478bd9Sstevel@tonic-gate 	if (ret != SASL_OK)
11267c478bd9Sstevel@tonic-gate 	    return (ret);
11277c478bd9Sstevel@tonic-gate #else
11287c478bd9Sstevel@tonic-gate 	if (name_without_realm.value)
11297c478bd9Sstevel@tonic-gate 	    params->utils->free(name_without_realm.value);
11307c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1131*55fea89dSDan Cross 
1132*55fea89dSDan Cross 
11337c478bd9Sstevel@tonic-gate 	/* we have to decide what sort of encryption/integrity/etc.,
11347c478bd9Sstevel@tonic-gate 	   we support */
11357c478bd9Sstevel@tonic-gate 	if (params->props.max_ssf < params->external_ssf) {
11367c478bd9Sstevel@tonic-gate 	    text->limitssf = 0;
11377c478bd9Sstevel@tonic-gate 	} else {
11387c478bd9Sstevel@tonic-gate 	    text->limitssf = params->props.max_ssf - params->external_ssf;
11397c478bd9Sstevel@tonic-gate 	}
11407c478bd9Sstevel@tonic-gate 	if (params->props.min_ssf < params->external_ssf) {
11417c478bd9Sstevel@tonic-gate 	    text->requiressf = 0;
11427c478bd9Sstevel@tonic-gate 	} else {
11437c478bd9Sstevel@tonic-gate 	    text->requiressf = params->props.min_ssf - params->external_ssf;
11447c478bd9Sstevel@tonic-gate 	}
1145*55fea89dSDan Cross 
11467c478bd9Sstevel@tonic-gate 	/* build up our security properties token */
11477c478bd9Sstevel@tonic-gate         if (params->props.maxbufsize > 0xFFFFFF) {
11487c478bd9Sstevel@tonic-gate             /* make sure maxbufsize isn't too large */
11497c478bd9Sstevel@tonic-gate             /* maxbufsize = 0xFFFFFF */
11507c478bd9Sstevel@tonic-gate             sasldata[1] = sasldata[2] = sasldata[3] = 0xFF;
11517c478bd9Sstevel@tonic-gate         } else {
11527c478bd9Sstevel@tonic-gate             sasldata[1] = (params->props.maxbufsize >> 16) & 0xFF;
11537c478bd9Sstevel@tonic-gate             sasldata[2] = (params->props.maxbufsize >> 8) & 0xFF;
11547c478bd9Sstevel@tonic-gate             sasldata[3] = (params->props.maxbufsize >> 0) & 0xFF;
11557c478bd9Sstevel@tonic-gate         }
11567c478bd9Sstevel@tonic-gate 	sasldata[0] = 0;
11577c478bd9Sstevel@tonic-gate 	if(text->requiressf != 0 && !params->props.maxbufsize) {
11587c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
11597c478bd9Sstevel@tonic-gate 	    params->utils->log(params->utils->conn, SASL_LOG_ERR,
11607c478bd9Sstevel@tonic-gate 		"GSSAPI needs a security layer but one is forbidden");
11617c478bd9Sstevel@tonic-gate #else
11627c478bd9Sstevel@tonic-gate 	    params->utils->seterror(params->utils->conn, 0,
11637c478bd9Sstevel@tonic-gate 				    "GSSAPI needs a security layer but one is forbidden");
11647c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
11657c478bd9Sstevel@tonic-gate 	    return SASL_TOOWEAK;
11667c478bd9Sstevel@tonic-gate 	}
1167*55fea89dSDan Cross 
11687c478bd9Sstevel@tonic-gate 	if (text->requiressf == 0) {
11697c478bd9Sstevel@tonic-gate 	    sasldata[0] |= 1; /* authentication */
11707c478bd9Sstevel@tonic-gate 	}
11717c478bd9Sstevel@tonic-gate 	if (text->requiressf <= 1 && text->limitssf >= 1
11727c478bd9Sstevel@tonic-gate 	    && params->props.maxbufsize) {
11737c478bd9Sstevel@tonic-gate 	    sasldata[0] |= 2;
11747c478bd9Sstevel@tonic-gate 	}
11757c478bd9Sstevel@tonic-gate 	if (text->requiressf <= 56 && text->limitssf >= 56
11767c478bd9Sstevel@tonic-gate 	    && params->props.maxbufsize) {
11777c478bd9Sstevel@tonic-gate 	    sasldata[0] |= 4;
11787c478bd9Sstevel@tonic-gate 	}
1179*55fea89dSDan Cross 
11807c478bd9Sstevel@tonic-gate 	real_input_token.value = (void *)sasldata;
11817c478bd9Sstevel@tonic-gate 	real_input_token.length = 4;
1182*55fea89dSDan Cross 
11837c478bd9Sstevel@tonic-gate 	maj_stat = gss_wrap(&min_stat,
11847c478bd9Sstevel@tonic-gate 			    text->gss_ctx,
11857c478bd9Sstevel@tonic-gate 			    0, /* Just integrity checking here */
11867c478bd9Sstevel@tonic-gate 			    GSS_C_QOP_DEFAULT,
11877c478bd9Sstevel@tonic-gate 			    input_token,
11887c478bd9Sstevel@tonic-gate 			    NULL,
11897c478bd9Sstevel@tonic-gate 			    output_token);
1190*55fea89dSDan Cross 
11917c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj_stat)) {
11927c478bd9Sstevel@tonic-gate 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
11937c478bd9Sstevel@tonic-gate 	    if (output_token->value)
11947c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
11957c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
11967c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
11977c478bd9Sstevel@tonic-gate 	}
1198*55fea89dSDan Cross 
1199*55fea89dSDan Cross 
12007c478bd9Sstevel@tonic-gate 	if (serveroutlen)
12017c478bd9Sstevel@tonic-gate 	    *serveroutlen = output_token->length;
12027c478bd9Sstevel@tonic-gate 	if (output_token->value) {
12037c478bd9Sstevel@tonic-gate 	    if (serverout) {
12047c478bd9Sstevel@tonic-gate 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
12057c478bd9Sstevel@tonic-gate 				      &(text->out_buf_len), *serveroutlen);
12067c478bd9Sstevel@tonic-gate 		if(ret != SASL_OK) {
12077c478bd9Sstevel@tonic-gate 		    gss_release_buffer(&min_stat, output_token);
12087c478bd9Sstevel@tonic-gate 		    return ret;
12097c478bd9Sstevel@tonic-gate 		}
12107c478bd9Sstevel@tonic-gate 		memcpy(text->out_buf, output_token->value, *serveroutlen);
12117c478bd9Sstevel@tonic-gate 		*serverout = text->out_buf;
12127c478bd9Sstevel@tonic-gate 	    }
1213*55fea89dSDan Cross 
12147c478bd9Sstevel@tonic-gate 	    gss_release_buffer(&min_stat, output_token);
12157c478bd9Sstevel@tonic-gate 	}
1216*55fea89dSDan Cross 
12177c478bd9Sstevel@tonic-gate 	/* Wait for ssf request and authid */
1218*55fea89dSDan Cross 	text->state = SASL_GSSAPI_STATE_SSFREQ;
1219*55fea89dSDan Cross 
12207c478bd9Sstevel@tonic-gate 	return SASL_CONTINUE;
12217c478bd9Sstevel@tonic-gate     }
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate     case SASL_GSSAPI_STATE_SSFREQ: {
12247c478bd9Sstevel@tonic-gate 	int layerchoice;
1225*55fea89dSDan Cross 
12267c478bd9Sstevel@tonic-gate 	real_input_token.value = (void *)clientin;
12277c478bd9Sstevel@tonic-gate 	real_input_token.length = clientinlen;
1228*55fea89dSDan Cross 
12297c478bd9Sstevel@tonic-gate 	maj_stat = gss_unwrap(&min_stat,
12307c478bd9Sstevel@tonic-gate 			      text->gss_ctx,
12317c478bd9Sstevel@tonic-gate 			      input_token,
12327c478bd9Sstevel@tonic-gate 			      output_token,
12337c478bd9Sstevel@tonic-gate 			      NULL,
12347c478bd9Sstevel@tonic-gate 			      NULL);
1235*55fea89dSDan Cross 
12367c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj_stat)) {
12377c478bd9Sstevel@tonic-gate 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
12387c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
12397c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
12407c478bd9Sstevel@tonic-gate 	}
1241*55fea89dSDan Cross 
12427c478bd9Sstevel@tonic-gate 	layerchoice = (int)(((char *)(output_token->value))[0]);
12437c478bd9Sstevel@tonic-gate 	if (layerchoice == 1 && text->requiressf == 0) { /* no encryption */
12447c478bd9Sstevel@tonic-gate 	    oparams->encode = NULL;
12457c478bd9Sstevel@tonic-gate 	    oparams->decode = NULL;
12467c478bd9Sstevel@tonic-gate 	    oparams->mech_ssf = 0;
12477c478bd9Sstevel@tonic-gate 	} else if (layerchoice == 2 && text->requiressf <= 1 &&
12487c478bd9Sstevel@tonic-gate 		   text->limitssf >= 1) { /* integrity */
12497c478bd9Sstevel@tonic-gate 	    oparams->encode=&gssapi_integrity_encode;
12507c478bd9Sstevel@tonic-gate 	    oparams->decode=&gssapi_decode;
12517c478bd9Sstevel@tonic-gate 	    oparams->mech_ssf=1;
12527c478bd9Sstevel@tonic-gate 	} else if (layerchoice == 4 && text->requiressf <= 56 &&
12537c478bd9Sstevel@tonic-gate 		   text->limitssf >= 56) { /* privacy */
12547c478bd9Sstevel@tonic-gate 	    oparams->encode = &gssapi_privacy_encode;
12557c478bd9Sstevel@tonic-gate 	    oparams->decode = &gssapi_decode;
12567c478bd9Sstevel@tonic-gate 	    oparams->mech_ssf = 56;
12577c478bd9Sstevel@tonic-gate 	} else {
12587c478bd9Sstevel@tonic-gate 	    /* not a supported encryption layer */
12597c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
12607c478bd9Sstevel@tonic-gate 	    text->utils->log(text->utils->conn, SASL_LOG_ERR,
12617c478bd9Sstevel@tonic-gate 		"protocol violation: client requested invalid layer");
12627c478bd9Sstevel@tonic-gate #else
12637c478bd9Sstevel@tonic-gate 	    SETERROR(text->utils,
12647c478bd9Sstevel@tonic-gate 		     "protocol violation: client requested invalid layer");
12657c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
12667c478bd9Sstevel@tonic-gate 	    /* Mark that we attempted negotiation */
12677c478bd9Sstevel@tonic-gate 	    oparams->mech_ssf = 2;
12687c478bd9Sstevel@tonic-gate 	    if (output_token->value)
12697c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
12707c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
12717c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
12727c478bd9Sstevel@tonic-gate 	}
1273*55fea89dSDan Cross 
12747c478bd9Sstevel@tonic-gate 	if (output_token->length > 4) {
12757c478bd9Sstevel@tonic-gate 	    int ret;
1276*55fea89dSDan Cross 
12777c478bd9Sstevel@tonic-gate 	    ret = params->canon_user(params->utils->conn,
12787c478bd9Sstevel@tonic-gate 				     ((char *) output_token->value) + 4,
12797c478bd9Sstevel@tonic-gate 				     (output_token->length - 4) * sizeof(char),
12807c478bd9Sstevel@tonic-gate 				     SASL_CU_AUTHZID, oparams);
1281*55fea89dSDan Cross 
12827c478bd9Sstevel@tonic-gate 	    if (ret != SASL_OK) {
12837c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
12847c478bd9Sstevel@tonic-gate 		return ret;
12857c478bd9Sstevel@tonic-gate 	    }
1286*55fea89dSDan Cross 
12877c478bd9Sstevel@tonic-gate 	    ret = params->canon_user(params->utils->conn,
12887c478bd9Sstevel@tonic-gate 				     text->authid,
12897c478bd9Sstevel@tonic-gate 				     0, /* strlen(text->authid) */
12907c478bd9Sstevel@tonic-gate 				     SASL_CU_AUTHID, oparams);
12917c478bd9Sstevel@tonic-gate 	    if (ret != SASL_OK) {
12927c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
12937c478bd9Sstevel@tonic-gate 		return ret;
12947c478bd9Sstevel@tonic-gate 	    }
12957c478bd9Sstevel@tonic-gate 	} else if(output_token->length == 4) {
12967c478bd9Sstevel@tonic-gate 	    /* null authzid */
12977c478bd9Sstevel@tonic-gate 	    int ret;
1298*55fea89dSDan Cross 
12997c478bd9Sstevel@tonic-gate 	    ret = params->canon_user(params->utils->conn,
13007c478bd9Sstevel@tonic-gate 				     text->authid,
13017c478bd9Sstevel@tonic-gate 				     0, /* strlen(text->authid) */
13027c478bd9Sstevel@tonic-gate 				     SASL_CU_AUTHZID | SASL_CU_AUTHID,
13037c478bd9Sstevel@tonic-gate 				     oparams);
1304*55fea89dSDan Cross 
13057c478bd9Sstevel@tonic-gate 	    if (ret != SASL_OK) {
13067c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
13077c478bd9Sstevel@tonic-gate 		return ret;
1308*55fea89dSDan Cross 	    }
13097c478bd9Sstevel@tonic-gate 	} else {
13107c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13117c478bd9Sstevel@tonic-gate 	    text->utils->log(text->utils->conn, SASL_LOG_ERR,
13127c478bd9Sstevel@tonic-gate 	    		     "token too short");
13137c478bd9Sstevel@tonic-gate #else
13147c478bd9Sstevel@tonic-gate 	    SETERROR(text->utils,
13157c478bd9Sstevel@tonic-gate 		     "token too short");
13167c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
13177c478bd9Sstevel@tonic-gate 	    gss_release_buffer(&min_stat, output_token);
13187c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
13197c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
1320*55fea89dSDan Cross 	}
1321*55fea89dSDan Cross 
13227c478bd9Sstevel@tonic-gate 	/* No matter what, set the rest of the oparams */
13237c478bd9Sstevel@tonic-gate         oparams->maxoutbuf =
13247c478bd9Sstevel@tonic-gate 	    (((unsigned char *) output_token->value)[1] << 16) |
13257c478bd9Sstevel@tonic-gate             (((unsigned char *) output_token->value)[2] << 8) |
13267c478bd9Sstevel@tonic-gate             (((unsigned char *) output_token->value)[3] << 0);
13277c478bd9Sstevel@tonic-gate 
13287c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13297c478bd9Sstevel@tonic-gate 	if (oparams->mech_ssf) {
13307c478bd9Sstevel@tonic-gate 	    oparams->maxoutbuf -= 4;	/* Allow for 4 byte tag */
13317c478bd9Sstevel@tonic-gate 	    maj_stat = gss_wrap_size_limit(&min_stat,
13327c478bd9Sstevel@tonic-gate 					text->gss_ctx,
13337c478bd9Sstevel@tonic-gate 					oparams->mech_ssf > 1,
13347c478bd9Sstevel@tonic-gate 					GSS_C_QOP_DEFAULT,
13357c478bd9Sstevel@tonic-gate 					oparams->maxoutbuf,
13367c478bd9Sstevel@tonic-gate 					&max_input_size);
13377c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
13387c478bd9Sstevel@tonic-gate 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
13397c478bd9Sstevel@tonic-gate 		(void) gss_release_buffer(&min_stat, output_token);
13407c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
13417c478bd9Sstevel@tonic-gate 		return (SASL_FAIL);
13427c478bd9Sstevel@tonic-gate 	    }
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 	    /*
13457c478bd9Sstevel@tonic-gate 	     * gss_wrap_size_limit will return very big sizes for
13467c478bd9Sstevel@tonic-gate 	     * small input values
13477c478bd9Sstevel@tonic-gate 	     */
13487c478bd9Sstevel@tonic-gate 	    if (max_input_size < oparams->maxoutbuf)
13497c478bd9Sstevel@tonic-gate  		oparams->maxoutbuf = max_input_size;
13507c478bd9Sstevel@tonic-gate 	    else {
13517c478bd9Sstevel@tonic-gate 		oparams->maxoutbuf = 0;
13527c478bd9Sstevel@tonic-gate 	    }
13537c478bd9Sstevel@tonic-gate 	}
13547c478bd9Sstevel@tonic-gate #else
13557c478bd9Sstevel@tonic-gate 	if (oparams->mech_ssf) {
13567c478bd9Sstevel@tonic-gate 	    /* xxx this is probably too big */
13577c478bd9Sstevel@tonic-gate 	    oparams->maxoutbuf -= 50;
13587c478bd9Sstevel@tonic-gate 	}
13597c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1360*55fea89dSDan Cross 
13617c478bd9Sstevel@tonic-gate 	gss_release_buffer(&min_stat, output_token);
1362*55fea89dSDan Cross 
13637c478bd9Sstevel@tonic-gate 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
1364*55fea89dSDan Cross 
13657c478bd9Sstevel@tonic-gate 	oparams->doneflag = 1;
1366*55fea89dSDan Cross 
13677c478bd9Sstevel@tonic-gate 	return SASL_OK;
13687c478bd9Sstevel@tonic-gate     }
1369*55fea89dSDan Cross 
13707c478bd9Sstevel@tonic-gate     default:
13717c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13727c478bd9Sstevel@tonic-gate 	params->utils->log(text->utils->conn, SASL_LOG_ERR,
13737c478bd9Sstevel@tonic-gate 			   "Invalid GSSAPI server step %d", text->state);
13747c478bd9Sstevel@tonic-gate #else
13757c478bd9Sstevel@tonic-gate 	params->utils->log(NULL, SASL_LOG_ERR,
13767c478bd9Sstevel@tonic-gate 			   "Invalid GSSAPI server step %d\n", text->state);
13777c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
13787c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
13797c478bd9Sstevel@tonic-gate     }
1380*55fea89dSDan Cross 
13817c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
13827c478bd9Sstevel@tonic-gate     return SASL_FAIL; /* should never get here */
13837c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
13847c478bd9Sstevel@tonic-gate }
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
1387*55fea89dSDan Cross static int
13887c478bd9Sstevel@tonic-gate _gssapi_server_mech_step(void *conn_context,
13897c478bd9Sstevel@tonic-gate 			sasl_server_params_t *params,
13907c478bd9Sstevel@tonic-gate 			const char *clientin,
13917c478bd9Sstevel@tonic-gate 			unsigned clientinlen,
13927c478bd9Sstevel@tonic-gate 			const char **serverout,
13937c478bd9Sstevel@tonic-gate 			unsigned *serveroutlen,
13947c478bd9Sstevel@tonic-gate 			sasl_out_params_t *oparams)
13957c478bd9Sstevel@tonic-gate {
13967c478bd9Sstevel@tonic-gate     int ret;
13977c478bd9Sstevel@tonic-gate 
13987c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&global_mutex) < 0)
13997c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate     ret = gssapi_server_mech_step(conn_context, params, clientin, clientinlen,
14027c478bd9Sstevel@tonic-gate 	serverout, serveroutlen, oparams);
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
14057c478bd9Sstevel@tonic-gate     return (ret);
14067c478bd9Sstevel@tonic-gate }
14077c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
14087c478bd9Sstevel@tonic-gate 
1409*55fea89dSDan Cross static sasl_server_plug_t gssapi_server_plugins[] =
14107c478bd9Sstevel@tonic-gate {
14117c478bd9Sstevel@tonic-gate     {
14127c478bd9Sstevel@tonic-gate 	"GSSAPI",			/* mech_name */
14137c478bd9Sstevel@tonic-gate 	56,				/* max_ssf */
14147c478bd9Sstevel@tonic-gate 	SASL_SEC_NOPLAINTEXT
14157c478bd9Sstevel@tonic-gate 	| SASL_SEC_NOACTIVE
14167c478bd9Sstevel@tonic-gate 	| SASL_SEC_NOANONYMOUS
14177c478bd9Sstevel@tonic-gate 	| SASL_SEC_MUTUAL_AUTH,		/* security_flags */
14187c478bd9Sstevel@tonic-gate 	SASL_FEAT_WANT_CLIENT_FIRST
14197c478bd9Sstevel@tonic-gate 	| SASL_FEAT_ALLOWS_PROXY,	/* features */
14207c478bd9Sstevel@tonic-gate 	NULL,				/* glob_context */
14217c478bd9Sstevel@tonic-gate 	&gssapi_server_mech_new,	/* mech_new */
14227c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
14237c478bd9Sstevel@tonic-gate 	&_gssapi_server_mech_step,	/* mech_step */
14247c478bd9Sstevel@tonic-gate #else
14257c478bd9Sstevel@tonic-gate 	&gssapi_server_mech_step,	/* mech_step */
14267c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
14277c478bd9Sstevel@tonic-gate 	&gssapi_common_mech_dispose,	/* mech_dispose */
14287c478bd9Sstevel@tonic-gate 	NULL,				/* mech_free */
14297c478bd9Sstevel@tonic-gate 	NULL,				/* setpass */
14307c478bd9Sstevel@tonic-gate 	NULL,				/* user_query */
14317c478bd9Sstevel@tonic-gate 	NULL,				/* idle */
14327c478bd9Sstevel@tonic-gate 	NULL,				/* mech_avail */
14337c478bd9Sstevel@tonic-gate 	NULL				/* spare */
14347c478bd9Sstevel@tonic-gate     }
14357c478bd9Sstevel@tonic-gate };
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate int gssapiv2_server_plug_init(
14387c478bd9Sstevel@tonic-gate #ifndef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
14397c478bd9Sstevel@tonic-gate     const sasl_utils_t *utils __attribute__((unused)),
14407c478bd9Sstevel@tonic-gate #else
14417c478bd9Sstevel@tonic-gate     const sasl_utils_t *utils,
1442*55fea89dSDan Cross #endif
14437c478bd9Sstevel@tonic-gate     int maxversion,
14447c478bd9Sstevel@tonic-gate     int *out_version,
14457c478bd9Sstevel@tonic-gate     sasl_server_plug_t **pluglist,
14467c478bd9Sstevel@tonic-gate     int *plugcount)
14477c478bd9Sstevel@tonic-gate {
14487c478bd9Sstevel@tonic-gate #ifdef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
14497c478bd9Sstevel@tonic-gate     const char *keytab = NULL;
14507c478bd9Sstevel@tonic-gate     char keytab_path[1024];
14517c478bd9Sstevel@tonic-gate     unsigned int rl;
14527c478bd9Sstevel@tonic-gate #endif
1453*55fea89dSDan Cross 
14547c478bd9Sstevel@tonic-gate     if (maxversion < SASL_SERVER_PLUG_VERSION) {
14557c478bd9Sstevel@tonic-gate 	return SASL_BADVERS;
14567c478bd9Sstevel@tonic-gate     }
1457*55fea89dSDan Cross 
14587c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
14597c478bd9Sstevel@tonic-gate #ifdef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
14607c478bd9Sstevel@tonic-gate     /* unfortunately, we don't check for readability of keytab if it's
14617c478bd9Sstevel@tonic-gate        the standard one, since we don't know where it is */
1462*55fea89dSDan Cross 
14637c478bd9Sstevel@tonic-gate     /* FIXME: This code is broken */
1464*55fea89dSDan Cross 
14657c478bd9Sstevel@tonic-gate     utils->getopt(utils->getopt_context, "GSSAPI", "keytab", &keytab, &rl);
14667c478bd9Sstevel@tonic-gate     if (keytab != NULL) {
14677c478bd9Sstevel@tonic-gate 	if (access(keytab, R_OK) != 0) {
14687c478bd9Sstevel@tonic-gate 	    utils->log(NULL, SASL_LOG_ERR,
14697c478bd9Sstevel@tonic-gate 		       "Could not find keytab file: %s: %m",
14707c478bd9Sstevel@tonic-gate 		       keytab, errno);
14717c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
14727c478bd9Sstevel@tonic-gate 	}
1473*55fea89dSDan Cross 
14747c478bd9Sstevel@tonic-gate 	if(strlen(keytab) > 1024) {
14757c478bd9Sstevel@tonic-gate 	    utils->log(NULL, SASL_LOG_ERR,
14767c478bd9Sstevel@tonic-gate 		       "path to keytab is > 1024 characters");
14777c478bd9Sstevel@tonic-gate 	    return SASL_BUFOVER;
14787c478bd9Sstevel@tonic-gate 	}
1479*55fea89dSDan Cross 
14807c478bd9Sstevel@tonic-gate 	strncpy(keytab_path, keytab, 1024);
1481*55fea89dSDan Cross 
14827c478bd9Sstevel@tonic-gate 	gsskrb5_register_acceptor_identity(keytab_path);
14837c478bd9Sstevel@tonic-gate     }
14847c478bd9Sstevel@tonic-gate #endif
14857c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1486*55fea89dSDan Cross 
14877c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
14887c478bd9Sstevel@tonic-gate     /*
14897c478bd9Sstevel@tonic-gate      * Let libsasl know that we are a "Sun" plugin so that privacy
14907c478bd9Sstevel@tonic-gate      * and integrity will be allowed.
14917c478bd9Sstevel@tonic-gate      */
14927c478bd9Sstevel@tonic-gate     REG_PLUG("GSSAPI", gssapi_server_plugins);
14937c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate     *out_version = SASL_SERVER_PLUG_VERSION;
14967c478bd9Sstevel@tonic-gate     *pluglist = gssapi_server_plugins;
1497*55fea89dSDan Cross     *plugcount = 1;
1498*55fea89dSDan Cross 
14997c478bd9Sstevel@tonic-gate     return SASL_OK;
15007c478bd9Sstevel@tonic-gate }
15017c478bd9Sstevel@tonic-gate 
15027c478bd9Sstevel@tonic-gate /*****************************  Client Section  *****************************/
15037c478bd9Sstevel@tonic-gate 
1504*55fea89dSDan Cross static int gssapi_client_mech_new(void *glob_context __attribute__((unused)),
15057c478bd9Sstevel@tonic-gate 				  sasl_client_params_t *params,
15067c478bd9Sstevel@tonic-gate 				  void **conn_context)
15077c478bd9Sstevel@tonic-gate {
15087c478bd9Sstevel@tonic-gate     context_t *text;
15097c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
15107c478bd9Sstevel@tonic-gate     const char *use_authid = NULL;
15117c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1512*55fea89dSDan Cross 
15137c478bd9Sstevel@tonic-gate     /* holds state are in */
15147c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
15157c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&global_mutex) < 0)
15167c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
15177c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
15187c478bd9Sstevel@tonic-gate     text = gss_new_context(params->utils);
15197c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
15207c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
15217c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
15227c478bd9Sstevel@tonic-gate     if (text == NULL) {
15237c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
15247c478bd9Sstevel@tonic-gate 	MEMERROR(params->utils);
15257c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
15267c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
15277c478bd9Sstevel@tonic-gate     }
1528*55fea89dSDan Cross 
15297c478bd9Sstevel@tonic-gate     text->state = SASL_GSSAPI_STATE_AUTHNEG;
15307c478bd9Sstevel@tonic-gate     text->gss_ctx = GSS_C_NO_CONTEXT;
15317c478bd9Sstevel@tonic-gate     text->client_name = GSS_C_NO_NAME;
15327c478bd9Sstevel@tonic-gate     text->server_creds = GSS_C_NO_CREDENTIAL;
1533*55fea89dSDan Cross 
15347c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
15357c478bd9Sstevel@tonic-gate     params->utils->getopt(params->utils->getopt_context,
15367c478bd9Sstevel@tonic-gate 			  "GSSAPI", "use_authid", &use_authid, NULL);
15377c478bd9Sstevel@tonic-gate     text->use_authid = (use_authid != NULL) &&
15387c478bd9Sstevel@tonic-gate 	(*use_authid == 'y' || *use_authid == 'Y' || *use_authid == '1');
15397c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1540*55fea89dSDan Cross 
15417c478bd9Sstevel@tonic-gate     *conn_context = text;
1542*55fea89dSDan Cross 
15437c478bd9Sstevel@tonic-gate     return SASL_OK;
15447c478bd9Sstevel@tonic-gate }
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate static int gssapi_client_mech_step(void *conn_context,
15477c478bd9Sstevel@tonic-gate 				   sasl_client_params_t *params,
15487c478bd9Sstevel@tonic-gate 				   const char *serverin,
15497c478bd9Sstevel@tonic-gate 				   unsigned serverinlen,
15507c478bd9Sstevel@tonic-gate 				   sasl_interact_t **prompt_need,
15517c478bd9Sstevel@tonic-gate 				   const char **clientout,
15527c478bd9Sstevel@tonic-gate 				   unsigned *clientoutlen,
15537c478bd9Sstevel@tonic-gate 				   sasl_out_params_t *oparams)
15547c478bd9Sstevel@tonic-gate {
15557c478bd9Sstevel@tonic-gate     context_t *text = (context_t *)conn_context;
15567c478bd9Sstevel@tonic-gate     gss_buffer_t input_token, output_token;
15577c478bd9Sstevel@tonic-gate     gss_buffer_desc real_input_token, real_output_token;
15587c478bd9Sstevel@tonic-gate     OM_uint32 maj_stat, min_stat;
15597c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
15607c478bd9Sstevel@tonic-gate     OM_uint32 max_input_size;
15617c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
15627c478bd9Sstevel@tonic-gate     gss_buffer_desc name_token;
15637c478bd9Sstevel@tonic-gate     int ret;
15647c478bd9Sstevel@tonic-gate     OM_uint32 req_flags, out_req_flags;
15657c478bd9Sstevel@tonic-gate     input_token = &real_input_token;
15667c478bd9Sstevel@tonic-gate     output_token = &real_output_token;
15677c478bd9Sstevel@tonic-gate     output_token->value = NULL;
1568*55fea89dSDan Cross     input_token->value = NULL;
15697c478bd9Sstevel@tonic-gate     input_token->length = 0;
1570*55fea89dSDan Cross 
15717c478bd9Sstevel@tonic-gate     *clientout = NULL;
15727c478bd9Sstevel@tonic-gate     *clientoutlen = 0;
1573*55fea89dSDan Cross 
15747c478bd9Sstevel@tonic-gate     switch (text->state) {
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate     case SASL_GSSAPI_STATE_AUTHNEG:
15777c478bd9Sstevel@tonic-gate 	/* try to get the userid */
15787c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
15797c478bd9Sstevel@tonic-gate 	if (text->user == NULL ||
15807c478bd9Sstevel@tonic-gate 		(text->use_authid && text->client_authid == NULL)) {
15817c478bd9Sstevel@tonic-gate 	    int auth_result = SASL_OK;
15827c478bd9Sstevel@tonic-gate 	    int user_result = SASL_OK;
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 	    if (text->use_authid && text->client_authid == NULL) {
15857c478bd9Sstevel@tonic-gate 		auth_result = _plug_get_authid(params->utils,
15867c478bd9Sstevel@tonic-gate 					       &text->client_authid,
15877c478bd9Sstevel@tonic-gate 					       prompt_need);
1588*55fea89dSDan Cross 
15897c478bd9Sstevel@tonic-gate 		if ((auth_result != SASL_OK) &&
15907c478bd9Sstevel@tonic-gate 			(auth_result != SASL_INTERACT)) {
15917c478bd9Sstevel@tonic-gate 		    sasl_gss_free_context_contents(text);
15927c478bd9Sstevel@tonic-gate 		    return auth_result;
15937c478bd9Sstevel@tonic-gate 		}
15947c478bd9Sstevel@tonic-gate 	    }
15957c478bd9Sstevel@tonic-gate 	    if (text->user == NULL) {
15967c478bd9Sstevel@tonic-gate 		user_result = _plug_get_userid(params->utils, &text->user,
15977c478bd9Sstevel@tonic-gate 					       prompt_need);
1598*55fea89dSDan Cross 
15997c478bd9Sstevel@tonic-gate 		if ((user_result != SASL_OK) &&
16007c478bd9Sstevel@tonic-gate 			(user_result != SASL_INTERACT)) {
16017c478bd9Sstevel@tonic-gate 		    sasl_gss_free_context_contents(text);
16027c478bd9Sstevel@tonic-gate 		    return user_result;
16037c478bd9Sstevel@tonic-gate 		}
16047c478bd9Sstevel@tonic-gate 	    }
16057c478bd9Sstevel@tonic-gate #else
16067c478bd9Sstevel@tonic-gate 	if (text->user == NULL) {
16077c478bd9Sstevel@tonic-gate 	    int user_result = SASL_OK;
1608*55fea89dSDan Cross 
16097c478bd9Sstevel@tonic-gate 	    user_result = _plug_get_userid(params->utils, &text->user,
16107c478bd9Sstevel@tonic-gate 					   prompt_need);
1611*55fea89dSDan Cross 
16127c478bd9Sstevel@tonic-gate 	    if ((user_result != SASL_OK) && (user_result != SASL_INTERACT)) {
16137c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
16147c478bd9Sstevel@tonic-gate 		return user_result;
16157c478bd9Sstevel@tonic-gate 	    }
16167c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1617*55fea89dSDan Cross 
16187c478bd9Sstevel@tonic-gate 	    /* free prompts we got */
16197c478bd9Sstevel@tonic-gate 	    if (prompt_need && *prompt_need) {
16207c478bd9Sstevel@tonic-gate 		params->utils->free(*prompt_need);
16217c478bd9Sstevel@tonic-gate 		*prompt_need = NULL;
16227c478bd9Sstevel@tonic-gate 	    }
1623*55fea89dSDan Cross 
16247c478bd9Sstevel@tonic-gate 	    /* if there are prompts not filled in */
16257c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
16267c478bd9Sstevel@tonic-gate 	    if ((user_result == SASL_INTERACT) ||
16277c478bd9Sstevel@tonic-gate 			(auth_result == SASL_INTERACT)) {
16287c478bd9Sstevel@tonic-gate 		/* make the prompt list */
16297c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
16307c478bd9Sstevel@tonic-gate 		int result = _plug_make_prompts(params->utils, &text->h,
16317c478bd9Sstevel@tonic-gate 			   prompt_need,
16327c478bd9Sstevel@tonic-gate 			   user_result == SASL_INTERACT ?
16337c478bd9Sstevel@tonic-gate 			   convert_prompt(params->utils, &text->h,
16347c478bd9Sstevel@tonic-gate 			    gettext("Please enter your authorization name"))
16357c478bd9Sstevel@tonic-gate 				: NULL, NULL,
16367c478bd9Sstevel@tonic-gate 			   auth_result == SASL_INTERACT ?
16377c478bd9Sstevel@tonic-gate 			   convert_prompt(params->utils, &text->h,
16387c478bd9Sstevel@tonic-gate 			    gettext("Please enter your authentication name"))
16397c478bd9Sstevel@tonic-gate 				: NULL, NULL,
16407c478bd9Sstevel@tonic-gate 			   NULL, NULL,
16417c478bd9Sstevel@tonic-gate 			   NULL, NULL, NULL,
16427c478bd9Sstevel@tonic-gate 			   NULL, NULL, NULL);
16437c478bd9Sstevel@tonic-gate #else
16447c478bd9Sstevel@tonic-gate 		int result = _plug_make_prompts(params->utils, prompt_need,
16457c478bd9Sstevel@tonic-gate 			   user_result == SASL_INTERACT ?
16467c478bd9Sstevel@tonic-gate 			   	"Please enter your authorization name"
16477c478bd9Sstevel@tonic-gate 				: NULL, NULL,
16487c478bd9Sstevel@tonic-gate 			   auth_result == SASL_INTERACT ?
16497c478bd9Sstevel@tonic-gate 			   	"Please enter your authentication name"
16507c478bd9Sstevel@tonic-gate 				: NULL, NULL,
16517c478bd9Sstevel@tonic-gate 			   NULL, NULL,
16527c478bd9Sstevel@tonic-gate 			   NULL, NULL, NULL,
16537c478bd9Sstevel@tonic-gate 			   NULL, NULL, NULL);
16547c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1655*55fea89dSDan Cross 
16567c478bd9Sstevel@tonic-gate 		if (result != SASL_OK) return result;
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 		return SASL_INTERACT;
16597c478bd9Sstevel@tonic-gate 	    }
16607c478bd9Sstevel@tonic-gate #else
16617c478bd9Sstevel@tonic-gate 	    if (user_result == SASL_INTERACT) {
16627c478bd9Sstevel@tonic-gate 		/* make the prompt list */
16637c478bd9Sstevel@tonic-gate 		int result =
16647c478bd9Sstevel@tonic-gate 		    _plug_make_prompts(params->utils, prompt_need,
16657c478bd9Sstevel@tonic-gate 				       user_result == SASL_INTERACT ?
16667c478bd9Sstevel@tonic-gate 				       "Please enter your authorization name" : NULL, NULL,
16677c478bd9Sstevel@tonic-gate 				       NULL, NULL,
16687c478bd9Sstevel@tonic-gate 				       NULL, NULL,
16697c478bd9Sstevel@tonic-gate 				       NULL, NULL, NULL,
16707c478bd9Sstevel@tonic-gate 				       NULL, NULL, NULL);
16717c478bd9Sstevel@tonic-gate 		if (result != SASL_OK) return result;
1672*55fea89dSDan Cross 
16737c478bd9Sstevel@tonic-gate 		return SASL_INTERACT;
16747c478bd9Sstevel@tonic-gate 	    }
16757c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
16767c478bd9Sstevel@tonic-gate 	}
1677*55fea89dSDan Cross 
16787c478bd9Sstevel@tonic-gate 	if (text->server_name == GSS_C_NO_NAME) { /* only once */
16797c478bd9Sstevel@tonic-gate 	    name_token.length = strlen(params->service) + 1 + strlen(params->serverFQDN);
16807c478bd9Sstevel@tonic-gate 	    name_token.value = (char *)params->utils->malloc((name_token.length + 1) * sizeof(char));
16817c478bd9Sstevel@tonic-gate 	    if (name_token.value == NULL) {
16827c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
16837c478bd9Sstevel@tonic-gate 		return SASL_NOMEM;
16847c478bd9Sstevel@tonic-gate 	    }
16857c478bd9Sstevel@tonic-gate 	    if (params->serverFQDN == NULL
16867c478bd9Sstevel@tonic-gate 		|| strlen(params->serverFQDN) == 0) {
16877c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
16887c478bd9Sstevel@tonic-gate 		text->utils->log(text->utils->conn, SASL_LOG_ERR,
16897c478bd9Sstevel@tonic-gate 				 "GSSAPI Failure: no serverFQDN");
16907c478bd9Sstevel@tonic-gate #else
16917c478bd9Sstevel@tonic-gate 		SETERROR(text->utils, "GSSAPI Failure: no serverFQDN");
16927c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
16937c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
16947c478bd9Sstevel@tonic-gate 	    }
1695*55fea89dSDan Cross 
16967c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
16977c478bd9Sstevel@tonic-gate 	    snprintf(name_token.value, name_token.length + 1,
16987c478bd9Sstevel@tonic-gate 		"%s@%s", params->service, params->serverFQDN);
16997c478bd9Sstevel@tonic-gate #else
17007c478bd9Sstevel@tonic-gate 	    sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
17017c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1702*55fea89dSDan Cross 
17037c478bd9Sstevel@tonic-gate 	    maj_stat = gss_import_name (&min_stat,
17047c478bd9Sstevel@tonic-gate 					&name_token,
17057c478bd9Sstevel@tonic-gate 					GSS_C_NT_HOSTBASED_SERVICE,
17067c478bd9Sstevel@tonic-gate 					&text->server_name);
1707*55fea89dSDan Cross 
17087c478bd9Sstevel@tonic-gate 	    params->utils->free(name_token.value);
17097c478bd9Sstevel@tonic-gate 	    name_token.value = NULL;
1710*55fea89dSDan Cross 
17117c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
17127c478bd9Sstevel@tonic-gate 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
17137c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
17147c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
17157c478bd9Sstevel@tonic-gate 	    }
17167c478bd9Sstevel@tonic-gate 	}
1717*55fea89dSDan Cross 
17187c478bd9Sstevel@tonic-gate 	if (serverinlen == 0)
17197c478bd9Sstevel@tonic-gate 	    input_token = GSS_C_NO_BUFFER;
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	if (serverinlen) {
17227c478bd9Sstevel@tonic-gate 	    real_input_token.value = (void *)serverin;
17237c478bd9Sstevel@tonic-gate 	    real_input_token.length = serverinlen;
17247c478bd9Sstevel@tonic-gate 	}
17257c478bd9Sstevel@tonic-gate 	else if (text->gss_ctx != GSS_C_NO_CONTEXT ) {
17267c478bd9Sstevel@tonic-gate 	    /* This can't happen under GSSAPI: we have a non-null context
17277c478bd9Sstevel@tonic-gate 	     * and no input from the server.  However, thanks to Imap,
17287c478bd9Sstevel@tonic-gate 	     * which discards our first output, this happens all the time.
17297c478bd9Sstevel@tonic-gate 	     * Throw away the context and try again. */
17307c478bd9Sstevel@tonic-gate 	    maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
17317c478bd9Sstevel@tonic-gate 	    text->gss_ctx = GSS_C_NO_CONTEXT;
17327c478bd9Sstevel@tonic-gate 	}
1733*55fea89dSDan Cross 
17347c478bd9Sstevel@tonic-gate 	/* Setup req_flags properly */
17357c478bd9Sstevel@tonic-gate 	req_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG;
17367c478bd9Sstevel@tonic-gate 	if(params->props.max_ssf > params->external_ssf) {
17377c478bd9Sstevel@tonic-gate 	    /* We are requesting a security layer */
17387c478bd9Sstevel@tonic-gate 	    req_flags |= GSS_C_INTEG_FLAG;
17397c478bd9Sstevel@tonic-gate 	    if(params->props.max_ssf - params->external_ssf > 56) {
17407c478bd9Sstevel@tonic-gate 		/* We want to try for privacy */
17417c478bd9Sstevel@tonic-gate 		req_flags |= GSS_C_CONF_FLAG;
17427c478bd9Sstevel@tonic-gate 	    }
17437c478bd9Sstevel@tonic-gate 	}
1744*55fea89dSDan Cross 
17457c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
17467c478bd9Sstevel@tonic-gate 	if (text->use_authid && text->client_creds == GSS_C_NO_CREDENTIAL) {
17477c478bd9Sstevel@tonic-gate 	    gss_OID_set desired_mechs = GSS_C_NULL_OID_SET;
17487c478bd9Sstevel@tonic-gate 	    gss_buffer_desc name_token;
17497c478bd9Sstevel@tonic-gate 
17507c478bd9Sstevel@tonic-gate 	    name_token.length = strlen(text->client_authid);
17517c478bd9Sstevel@tonic-gate 	    name_token.value = (char *)text->client_authid;
17527c478bd9Sstevel@tonic-gate 
17537c478bd9Sstevel@tonic-gate 	    maj_stat = gss_import_name (&min_stat,
17547c478bd9Sstevel@tonic-gate 					&name_token,
17557c478bd9Sstevel@tonic-gate #ifdef HAVE_GSS_C_NT_USER_NAME
17567c478bd9Sstevel@tonic-gate 					GSS_C_NT_USER_NAME,
17577c478bd9Sstevel@tonic-gate #else
17587c478bd9Sstevel@tonic-gate 					GSS_C_NULL_OID,
17597c478bd9Sstevel@tonic-gate #endif
17607c478bd9Sstevel@tonic-gate 					&text->client_name);
17617c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
17627c478bd9Sstevel@tonic-gate 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
17637c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
17647c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
17657c478bd9Sstevel@tonic-gate 	    }
17667c478bd9Sstevel@tonic-gate 
17677c478bd9Sstevel@tonic-gate 	    if (text->mech_oid != GSS_C_NULL_OID) {
17687c478bd9Sstevel@tonic-gate 		ret = add_mech_to_set(text, &desired_mechs);
17697c478bd9Sstevel@tonic-gate 		if (ret != SASL_OK)
17707c478bd9Sstevel@tonic-gate 		    return (ret);
17717c478bd9Sstevel@tonic-gate 	    }
17727c478bd9Sstevel@tonic-gate 
1773*55fea89dSDan Cross 	    maj_stat = gss_acquire_cred(&min_stat,
17747c478bd9Sstevel@tonic-gate 					text->client_name,
1775*55fea89dSDan Cross 					GSS_C_INDEFINITE,
17767c478bd9Sstevel@tonic-gate 					desired_mechs,
17777c478bd9Sstevel@tonic-gate 					GSS_C_INITIATE,
1778*55fea89dSDan Cross 					&text->client_creds,
1779*55fea89dSDan Cross 					NULL,
17807c478bd9Sstevel@tonic-gate 					NULL);
17817c478bd9Sstevel@tonic-gate 
17827c478bd9Sstevel@tonic-gate 	    if (desired_mechs != GSS_C_NULL_OID_SET) {
17837c478bd9Sstevel@tonic-gate 		OM_uint32 min_stat2;
17847c478bd9Sstevel@tonic-gate 		(void) gss_release_oid_set(&min_stat2, &desired_mechs);
17857c478bd9Sstevel@tonic-gate 	    }
17867c478bd9Sstevel@tonic-gate 
17877c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
17887c478bd9Sstevel@tonic-gate 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
17897c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
17907c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
17917c478bd9Sstevel@tonic-gate 	    }
17927c478bd9Sstevel@tonic-gate 	}
17937c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 	maj_stat = gss_init_sec_context(&min_stat,
17967c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
17977c478bd9Sstevel@tonic-gate 					text->client_creds,
17987c478bd9Sstevel@tonic-gate #else
17997c478bd9Sstevel@tonic-gate 					GSS_C_NO_CREDENTIAL,
18007c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
18017c478bd9Sstevel@tonic-gate 					&text->gss_ctx,
18027c478bd9Sstevel@tonic-gate 					text->server_name,
18037c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
18047c478bd9Sstevel@tonic-gate 					text->mech_oid,
18057c478bd9Sstevel@tonic-gate #else
18067c478bd9Sstevel@tonic-gate 					GSS_C_NO_OID,
18077c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
18087c478bd9Sstevel@tonic-gate 					req_flags,
18097c478bd9Sstevel@tonic-gate 					0,
18107c478bd9Sstevel@tonic-gate 					GSS_C_NO_CHANNEL_BINDINGS,
18117c478bd9Sstevel@tonic-gate 					input_token,
18127c478bd9Sstevel@tonic-gate 					NULL,
18137c478bd9Sstevel@tonic-gate 					output_token,
18147c478bd9Sstevel@tonic-gate 					&out_req_flags,
18157c478bd9Sstevel@tonic-gate 					NULL);
1816*55fea89dSDan Cross 
18177c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj_stat)) {
18187c478bd9Sstevel@tonic-gate 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
18197c478bd9Sstevel@tonic-gate 	    if (output_token->value)
18207c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
18217c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
18227c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
18237c478bd9Sstevel@tonic-gate 	}
1824*55fea89dSDan Cross 
18257c478bd9Sstevel@tonic-gate 	*clientoutlen = output_token->length;
1826*55fea89dSDan Cross 
18277c478bd9Sstevel@tonic-gate 	if (output_token->value) {
18287c478bd9Sstevel@tonic-gate 	    if (clientout) {
18297c478bd9Sstevel@tonic-gate 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
18307c478bd9Sstevel@tonic-gate 				      &(text->out_buf_len), *clientoutlen);
18317c478bd9Sstevel@tonic-gate 		if(ret != SASL_OK) {
18327c478bd9Sstevel@tonic-gate 		    gss_release_buffer(&min_stat, output_token);
18337c478bd9Sstevel@tonic-gate 		    return ret;
18347c478bd9Sstevel@tonic-gate 		}
18357c478bd9Sstevel@tonic-gate 		memcpy(text->out_buf, output_token->value, *clientoutlen);
18367c478bd9Sstevel@tonic-gate 		*clientout = text->out_buf;
18377c478bd9Sstevel@tonic-gate 	    }
1838*55fea89dSDan Cross 
18397c478bd9Sstevel@tonic-gate 	    gss_release_buffer(&min_stat, output_token);
18407c478bd9Sstevel@tonic-gate 	}
1841*55fea89dSDan Cross 
18427c478bd9Sstevel@tonic-gate 	if (maj_stat == GSS_S_COMPLETE) {
18437c478bd9Sstevel@tonic-gate 	    maj_stat = gss_inquire_context(&min_stat,
18447c478bd9Sstevel@tonic-gate 					   text->gss_ctx,
18457c478bd9Sstevel@tonic-gate 					   &text->client_name,
18467c478bd9Sstevel@tonic-gate 					   NULL,       /* targ_name */
18477c478bd9Sstevel@tonic-gate 					   NULL,       /* lifetime */
18487c478bd9Sstevel@tonic-gate 					   NULL,       /* mech */
18497c478bd9Sstevel@tonic-gate 					   NULL,       /* flags */
18507c478bd9Sstevel@tonic-gate 					   NULL,       /* local init */
18517c478bd9Sstevel@tonic-gate 					   NULL);      /* open */
1852*55fea89dSDan Cross 
18537c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
18547c478bd9Sstevel@tonic-gate 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
18557c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
18567c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
18577c478bd9Sstevel@tonic-gate 	    }
1858*55fea89dSDan Cross 
18597c478bd9Sstevel@tonic-gate 	    name_token.length = 0;
18607c478bd9Sstevel@tonic-gate 	    maj_stat = gss_display_name(&min_stat,
18617c478bd9Sstevel@tonic-gate 					text->client_name,
18627c478bd9Sstevel@tonic-gate 					&name_token,
18637c478bd9Sstevel@tonic-gate 					NULL);
1864*55fea89dSDan Cross 
18657c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
18667c478bd9Sstevel@tonic-gate 		if (name_token.value)
18677c478bd9Sstevel@tonic-gate 		    gss_release_buffer(&min_stat, &name_token);
18687c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
18697c478bd9Sstevel@tonic-gate 		SETERROR(text->utils, gettext("GSSAPI Failure"));
18707c478bd9Sstevel@tonic-gate #else
18717c478bd9Sstevel@tonic-gate 		SETERROR(text->utils, "GSSAPI Failure");
18727c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
18737c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
18747c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
18757c478bd9Sstevel@tonic-gate 	    }
1876*55fea89dSDan Cross 
18777c478bd9Sstevel@tonic-gate 	    if (text->user && text->user[0]) {
18787c478bd9Sstevel@tonic-gate 		ret = params->canon_user(params->utils->conn,
18797c478bd9Sstevel@tonic-gate 					 text->user, 0,
18807c478bd9Sstevel@tonic-gate 					 SASL_CU_AUTHZID, oparams);
1881*55fea89dSDan Cross 		if (ret == SASL_OK)
18827c478bd9Sstevel@tonic-gate 		    ret = params->canon_user(params->utils->conn,
18837c478bd9Sstevel@tonic-gate 					     name_token.value, 0,
18847c478bd9Sstevel@tonic-gate 					     SASL_CU_AUTHID, oparams);
18857c478bd9Sstevel@tonic-gate 	    } else {
18867c478bd9Sstevel@tonic-gate 		ret = params->canon_user(params->utils->conn,
18877c478bd9Sstevel@tonic-gate 					 name_token.value, 0,
18887c478bd9Sstevel@tonic-gate 					 SASL_CU_AUTHID | SASL_CU_AUTHZID,
18897c478bd9Sstevel@tonic-gate 					 oparams);
18907c478bd9Sstevel@tonic-gate 	    }
18917c478bd9Sstevel@tonic-gate 	    gss_release_buffer(&min_stat, &name_token);
1892*55fea89dSDan Cross 
18937c478bd9Sstevel@tonic-gate 	    if (ret != SASL_OK) return ret;
1894*55fea89dSDan Cross 
18957c478bd9Sstevel@tonic-gate 	    /* Switch to ssf negotiation */
18967c478bd9Sstevel@tonic-gate 	    text->state = SASL_GSSAPI_STATE_SSFCAP;
18977c478bd9Sstevel@tonic-gate 	}
1898*55fea89dSDan Cross 
18997c478bd9Sstevel@tonic-gate 	return SASL_CONTINUE;
19007c478bd9Sstevel@tonic-gate 
19017c478bd9Sstevel@tonic-gate     case SASL_GSSAPI_STATE_SSFCAP: {
19027c478bd9Sstevel@tonic-gate 	sasl_security_properties_t *secprops = &(params->props);
19037c478bd9Sstevel@tonic-gate 	unsigned int alen, external = params->external_ssf;
19047c478bd9Sstevel@tonic-gate 	sasl_ssf_t need, allowed;
19057c478bd9Sstevel@tonic-gate 	char serverhas, mychoice;
1906*55fea89dSDan Cross 
19077c478bd9Sstevel@tonic-gate 	real_input_token.value = (void *) serverin;
19087c478bd9Sstevel@tonic-gate 	real_input_token.length = serverinlen;
1909*55fea89dSDan Cross 
19107c478bd9Sstevel@tonic-gate 	maj_stat = gss_unwrap(&min_stat,
19117c478bd9Sstevel@tonic-gate 			      text->gss_ctx,
19127c478bd9Sstevel@tonic-gate 			      input_token,
19137c478bd9Sstevel@tonic-gate 			      output_token,
19147c478bd9Sstevel@tonic-gate 			      NULL,
19157c478bd9Sstevel@tonic-gate 			      NULL);
1916*55fea89dSDan Cross 
19177c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj_stat)) {
19187c478bd9Sstevel@tonic-gate 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
19197c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
19207c478bd9Sstevel@tonic-gate 	    if (output_token->value)
19217c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
19227c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
19237c478bd9Sstevel@tonic-gate 	}
1924*55fea89dSDan Cross 
19257c478bd9Sstevel@tonic-gate 	/* taken from kerberos.c */
19267c478bd9Sstevel@tonic-gate 	if (secprops->min_ssf > (56 + external)) {
19277c478bd9Sstevel@tonic-gate 	    return SASL_TOOWEAK;
19287c478bd9Sstevel@tonic-gate 	} else if (secprops->min_ssf > secprops->max_ssf) {
19297c478bd9Sstevel@tonic-gate 	    return SASL_BADPARAM;
19307c478bd9Sstevel@tonic-gate 	}
1931*55fea89dSDan Cross 
19327c478bd9Sstevel@tonic-gate 	/* need bits of layer -- sasl_ssf_t is unsigned so be careful */
19337c478bd9Sstevel@tonic-gate 	if (secprops->max_ssf >= external) {
19347c478bd9Sstevel@tonic-gate 	    allowed = secprops->max_ssf - external;
19357c478bd9Sstevel@tonic-gate 	} else {
19367c478bd9Sstevel@tonic-gate 	    allowed = 0;
19377c478bd9Sstevel@tonic-gate 	}
19387c478bd9Sstevel@tonic-gate 	if (secprops->min_ssf >= external) {
19397c478bd9Sstevel@tonic-gate 	    need = secprops->min_ssf - external;
19407c478bd9Sstevel@tonic-gate 	} else {
19417c478bd9Sstevel@tonic-gate 	    /* good to go */
19427c478bd9Sstevel@tonic-gate 	    need = 0;
19437c478bd9Sstevel@tonic-gate 	}
1944*55fea89dSDan Cross 
19457c478bd9Sstevel@tonic-gate 	/* bit mask of server support */
19467c478bd9Sstevel@tonic-gate 	serverhas = ((char *)output_token->value)[0];
1947*55fea89dSDan Cross 
19487c478bd9Sstevel@tonic-gate 	/* if client didn't set use strongest layer available */
19497c478bd9Sstevel@tonic-gate 	if (allowed >= 56 && need <= 56 && (serverhas & 4)) {
19507c478bd9Sstevel@tonic-gate 	    /* encryption */
19517c478bd9Sstevel@tonic-gate 	    oparams->encode = &gssapi_privacy_encode;
19527c478bd9Sstevel@tonic-gate 	    oparams->decode = &gssapi_decode;
19537c478bd9Sstevel@tonic-gate 	    oparams->mech_ssf = 56;
19547c478bd9Sstevel@tonic-gate 	    mychoice = 4;
19557c478bd9Sstevel@tonic-gate 	} else if (allowed >= 1 && need <= 1 && (serverhas & 2)) {
19567c478bd9Sstevel@tonic-gate 	    /* integrity */
19577c478bd9Sstevel@tonic-gate 	    oparams->encode = &gssapi_integrity_encode;
19587c478bd9Sstevel@tonic-gate 	    oparams->decode = &gssapi_decode;
19597c478bd9Sstevel@tonic-gate 	    oparams->mech_ssf = 1;
19607c478bd9Sstevel@tonic-gate 	    mychoice = 2;
19617c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
19627c478bd9Sstevel@tonic-gate 	} else if (need == 0 && (serverhas & 1)) {
19637c478bd9Sstevel@tonic-gate #else
19647c478bd9Sstevel@tonic-gate 	} else if (need <= 0 && (serverhas & 1)) {
19657c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
19667c478bd9Sstevel@tonic-gate 	    /* no layer */
19677c478bd9Sstevel@tonic-gate 	    oparams->encode = NULL;
19687c478bd9Sstevel@tonic-gate 	    oparams->decode = NULL;
19697c478bd9Sstevel@tonic-gate 	    oparams->mech_ssf = 0;
19707c478bd9Sstevel@tonic-gate 	    mychoice = 1;
19717c478bd9Sstevel@tonic-gate 	} else {
19727c478bd9Sstevel@tonic-gate 	    /* there's no appropriate layering for us! */
19737c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
19747c478bd9Sstevel@tonic-gate 	    return SASL_TOOWEAK;
19757c478bd9Sstevel@tonic-gate 	}
1976*55fea89dSDan Cross 
19777c478bd9Sstevel@tonic-gate         oparams->maxoutbuf =
19787c478bd9Sstevel@tonic-gate 	    (((unsigned char *) output_token->value)[1] << 16) |
19797c478bd9Sstevel@tonic-gate             (((unsigned char *) output_token->value)[2] << 8) |
19807c478bd9Sstevel@tonic-gate             (((unsigned char *) output_token->value)[3] << 0);
19817c478bd9Sstevel@tonic-gate 
19827c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
19837c478bd9Sstevel@tonic-gate 	if (oparams->mech_ssf > 0) {
19847c478bd9Sstevel@tonic-gate 	    oparams->maxoutbuf -= 4;	/* Space for 4 byte length header */
19857c478bd9Sstevel@tonic-gate 	    maj_stat = gss_wrap_size_limit(&min_stat,
19867c478bd9Sstevel@tonic-gate 					text->gss_ctx,
19877c478bd9Sstevel@tonic-gate 					oparams->mech_ssf > 1,
19887c478bd9Sstevel@tonic-gate 					GSS_C_QOP_DEFAULT,
19897c478bd9Sstevel@tonic-gate 					oparams->maxoutbuf,
19907c478bd9Sstevel@tonic-gate 					&max_input_size);
19917c478bd9Sstevel@tonic-gate 	    if (GSS_ERROR(maj_stat)) {
19927c478bd9Sstevel@tonic-gate 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
19937c478bd9Sstevel@tonic-gate 		(void) gss_release_buffer(&min_stat, output_token);
19947c478bd9Sstevel@tonic-gate 		sasl_gss_free_context_contents(text);
19957c478bd9Sstevel@tonic-gate 		return (SASL_FAIL);
19967c478bd9Sstevel@tonic-gate 	    }
19977c478bd9Sstevel@tonic-gate 
19987c478bd9Sstevel@tonic-gate 	/*
19997c478bd9Sstevel@tonic-gate 	 * This is a workaround for a Solaris bug where
20007c478bd9Sstevel@tonic-gate 	 * gss_wrap_size_limit may return very big sizes for
20017c478bd9Sstevel@tonic-gate 	 * small input values
20027c478bd9Sstevel@tonic-gate 	 */
20037c478bd9Sstevel@tonic-gate 	    if (max_input_size < oparams->maxoutbuf)
20047c478bd9Sstevel@tonic-gate  		oparams->maxoutbuf = max_input_size;
20057c478bd9Sstevel@tonic-gate 	    else {
20067c478bd9Sstevel@tonic-gate 		oparams->maxoutbuf = 0;
20077c478bd9Sstevel@tonic-gate 	    }
20087c478bd9Sstevel@tonic-gate 	}
20097c478bd9Sstevel@tonic-gate #else
20107c478bd9Sstevel@tonic-gate 	if(oparams->mech_ssf) {
20117c478bd9Sstevel@tonic-gate 	    /* xxx probably too large */
20127c478bd9Sstevel@tonic-gate 	    oparams->maxoutbuf -= 50;
20137c478bd9Sstevel@tonic-gate 	}
20147c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2015*55fea89dSDan Cross 
20167c478bd9Sstevel@tonic-gate 	gss_release_buffer(&min_stat, output_token);
2017*55fea89dSDan Cross 
20187c478bd9Sstevel@tonic-gate 	/* oparams->user is always set, due to canon_user requirements.
20197c478bd9Sstevel@tonic-gate 	 * Make sure the client actually requested it though, by checking
20207c478bd9Sstevel@tonic-gate 	 * if our context was set.
20217c478bd9Sstevel@tonic-gate 	 */
20227c478bd9Sstevel@tonic-gate 	if (text->user && text->user[0])
20237c478bd9Sstevel@tonic-gate 	    alen = strlen(oparams->user);
20247c478bd9Sstevel@tonic-gate 	else
20257c478bd9Sstevel@tonic-gate 	    alen = 0;
2026*55fea89dSDan Cross 
20277c478bd9Sstevel@tonic-gate 	input_token->length = 4 + alen;
20287c478bd9Sstevel@tonic-gate 	input_token->value =
20297c478bd9Sstevel@tonic-gate 	    (char *)params->utils->malloc((input_token->length + 1)*sizeof(char));
20307c478bd9Sstevel@tonic-gate 	if (input_token->value == NULL) {
20317c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
20327c478bd9Sstevel@tonic-gate 	    return SASL_NOMEM;
20337c478bd9Sstevel@tonic-gate 	}
2034*55fea89dSDan Cross 
20357c478bd9Sstevel@tonic-gate 	if (alen)
20367c478bd9Sstevel@tonic-gate 	    memcpy((char *)input_token->value+4,oparams->user,alen);
20377c478bd9Sstevel@tonic-gate 
20387c478bd9Sstevel@tonic-gate 	/* build up our security properties token */
20397c478bd9Sstevel@tonic-gate         if (params->props.maxbufsize > 0xFFFFFF) {
20407c478bd9Sstevel@tonic-gate             /* make sure maxbufsize isn't too large */
20417c478bd9Sstevel@tonic-gate             /* maxbufsize = 0xFFFFFF */
20427c478bd9Sstevel@tonic-gate             ((unsigned char *)input_token->value)[1] = 0xFF;
20437c478bd9Sstevel@tonic-gate             ((unsigned char *)input_token->value)[2] = 0xFF;
20447c478bd9Sstevel@tonic-gate             ((unsigned char *)input_token->value)[3] = 0xFF;
20457c478bd9Sstevel@tonic-gate         } else {
2046*55fea89dSDan Cross             ((unsigned char *)input_token->value)[1] =
20477c478bd9Sstevel@tonic-gate                 (params->props.maxbufsize >> 16) & 0xFF;
2048*55fea89dSDan Cross             ((unsigned char *)input_token->value)[2] =
20497c478bd9Sstevel@tonic-gate                 (params->props.maxbufsize >> 8) & 0xFF;
2050*55fea89dSDan Cross             ((unsigned char *)input_token->value)[3] =
20517c478bd9Sstevel@tonic-gate                 (params->props.maxbufsize >> 0) & 0xFF;
20527c478bd9Sstevel@tonic-gate         }
20537c478bd9Sstevel@tonic-gate 	((unsigned char *)input_token->value)[0] = mychoice;
2054*55fea89dSDan Cross 
20557c478bd9Sstevel@tonic-gate 	maj_stat = gss_wrap (&min_stat,
20567c478bd9Sstevel@tonic-gate 			     text->gss_ctx,
20577c478bd9Sstevel@tonic-gate 			     0, /* Just integrity checking here */
20587c478bd9Sstevel@tonic-gate 			     GSS_C_QOP_DEFAULT,
20597c478bd9Sstevel@tonic-gate 			     input_token,
20607c478bd9Sstevel@tonic-gate 			     NULL,
20617c478bd9Sstevel@tonic-gate 			     output_token);
2062*55fea89dSDan Cross 
20637c478bd9Sstevel@tonic-gate 	params->utils->free(input_token->value);
20647c478bd9Sstevel@tonic-gate 	input_token->value = NULL;
2065*55fea89dSDan Cross 
20667c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj_stat)) {
20677c478bd9Sstevel@tonic-gate 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
20687c478bd9Sstevel@tonic-gate 	    if (output_token->value)
20697c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, output_token);
20707c478bd9Sstevel@tonic-gate 	    sasl_gss_free_context_contents(text);
20717c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
20727c478bd9Sstevel@tonic-gate 	}
2073*55fea89dSDan Cross 
20747c478bd9Sstevel@tonic-gate 	if (clientoutlen)
20757c478bd9Sstevel@tonic-gate 	    *clientoutlen = output_token->length;
20767c478bd9Sstevel@tonic-gate 	if (output_token->value) {
20777c478bd9Sstevel@tonic-gate 	    if (clientout) {
20787c478bd9Sstevel@tonic-gate 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
20797c478bd9Sstevel@tonic-gate 				      &(text->out_buf_len), *clientoutlen);
20807c478bd9Sstevel@tonic-gate 		if (ret != SASL_OK) {
20817c478bd9Sstevel@tonic-gate 		    gss_release_buffer(&min_stat, output_token);
20827c478bd9Sstevel@tonic-gate 		    return ret;
20837c478bd9Sstevel@tonic-gate 		}
20847c478bd9Sstevel@tonic-gate 		memcpy(text->out_buf, output_token->value, *clientoutlen);
20857c478bd9Sstevel@tonic-gate 		*clientout = text->out_buf;
20867c478bd9Sstevel@tonic-gate 	    }
2087*55fea89dSDan Cross 
20887c478bd9Sstevel@tonic-gate 	    gss_release_buffer(&min_stat, output_token);
20897c478bd9Sstevel@tonic-gate 	}
2090*55fea89dSDan Cross 
20917c478bd9Sstevel@tonic-gate 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
2092*55fea89dSDan Cross 
20937c478bd9Sstevel@tonic-gate 	oparams->doneflag = 1;
2094*55fea89dSDan Cross 
20957c478bd9Sstevel@tonic-gate 	return SASL_OK;
20967c478bd9Sstevel@tonic-gate     }
2097*55fea89dSDan Cross 
20987c478bd9Sstevel@tonic-gate     default:
20997c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
21007c478bd9Sstevel@tonic-gate 	params->utils->log(params->utils->conn, SASL_LOG_ERR,
21017c478bd9Sstevel@tonic-gate 			   "Invalid GSSAPI client step %d", text->state);
21027c478bd9Sstevel@tonic-gate #else
21037c478bd9Sstevel@tonic-gate 	params->utils->log(NULL, SASL_LOG_ERR,
21047c478bd9Sstevel@tonic-gate 			   "Invalid GSSAPI client step %d\n", text->state);
21057c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
21067c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
21077c478bd9Sstevel@tonic-gate     }
2108*55fea89dSDan Cross 
21097c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
21107c478bd9Sstevel@tonic-gate     return SASL_FAIL; /* should never get here */
21117c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
21127c478bd9Sstevel@tonic-gate }
21137c478bd9Sstevel@tonic-gate 
21147c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
21157c478bd9Sstevel@tonic-gate static const unsigned long gssapi_required_prompts[] = {
21167c478bd9Sstevel@tonic-gate #else
21177c478bd9Sstevel@tonic-gate static const long gssapi_required_prompts[] = {
21187c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
21197c478bd9Sstevel@tonic-gate     SASL_CB_LIST_END
2120*55fea89dSDan Cross };
21217c478bd9Sstevel@tonic-gate 
21227c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
21237c478bd9Sstevel@tonic-gate static int _gssapi_client_mech_step(void *conn_context,
21247c478bd9Sstevel@tonic-gate 				   sasl_client_params_t *params,
21257c478bd9Sstevel@tonic-gate 				   const char *serverin,
21267c478bd9Sstevel@tonic-gate 				   unsigned serverinlen,
21277c478bd9Sstevel@tonic-gate 				   sasl_interact_t **prompt_need,
21287c478bd9Sstevel@tonic-gate 				   const char **clientout,
21297c478bd9Sstevel@tonic-gate 				   unsigned *clientoutlen,
21307c478bd9Sstevel@tonic-gate 				   sasl_out_params_t *oparams)
21317c478bd9Sstevel@tonic-gate {
21327c478bd9Sstevel@tonic-gate     int ret;
21337c478bd9Sstevel@tonic-gate 
21347c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&global_mutex) < 0)
21357c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
21367c478bd9Sstevel@tonic-gate 
21377c478bd9Sstevel@tonic-gate     ret = gssapi_client_mech_step(conn_context, params, serverin, serverinlen,
21387c478bd9Sstevel@tonic-gate 	prompt_need, clientout, clientoutlen, oparams);
21397c478bd9Sstevel@tonic-gate 
21407c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
21417c478bd9Sstevel@tonic-gate     return (ret);
21427c478bd9Sstevel@tonic-gate }
21437c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
21447c478bd9Sstevel@tonic-gate 
2145*55fea89dSDan Cross static sasl_client_plug_t gssapi_client_plugins[] =
21467c478bd9Sstevel@tonic-gate {
21477c478bd9Sstevel@tonic-gate     {
21487c478bd9Sstevel@tonic-gate 	"GSSAPI",			/* mech_name */
21497c478bd9Sstevel@tonic-gate 	56,				/* max_ssf */
21507c478bd9Sstevel@tonic-gate 	SASL_SEC_NOPLAINTEXT
21517c478bd9Sstevel@tonic-gate 	| SASL_SEC_NOACTIVE
21527c478bd9Sstevel@tonic-gate 	| SASL_SEC_NOANONYMOUS
21537c478bd9Sstevel@tonic-gate 	| SASL_SEC_MUTUAL_AUTH,		/* security_flags */
21547c478bd9Sstevel@tonic-gate 	SASL_FEAT_WANT_CLIENT_FIRST
21557c478bd9Sstevel@tonic-gate 	| SASL_FEAT_ALLOWS_PROXY,	/* features */
21567c478bd9Sstevel@tonic-gate 	gssapi_required_prompts,	/* required_prompts */
21577c478bd9Sstevel@tonic-gate 	NULL,				/* glob_context */
21587c478bd9Sstevel@tonic-gate 	&gssapi_client_mech_new,	/* mech_new */
21597c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
21607c478bd9Sstevel@tonic-gate 	&_gssapi_client_mech_step,	/* mech_step */
21617c478bd9Sstevel@tonic-gate #else
21627c478bd9Sstevel@tonic-gate 	&gssapi_client_mech_step,	/* mech_step */
21637c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
21647c478bd9Sstevel@tonic-gate 	&gssapi_common_mech_dispose,	/* mech_dispose */
21657c478bd9Sstevel@tonic-gate 	NULL,				/* mech_free */
21667c478bd9Sstevel@tonic-gate 	NULL,				/* idle */
21677c478bd9Sstevel@tonic-gate 	NULL,				/* spare */
21687c478bd9Sstevel@tonic-gate 	NULL				/* spare */
21697c478bd9Sstevel@tonic-gate     }
21707c478bd9Sstevel@tonic-gate };
21717c478bd9Sstevel@tonic-gate 
2172*55fea89dSDan Cross int gssapiv2_client_plug_init(const sasl_utils_t *utils __attribute__((unused)),
21737c478bd9Sstevel@tonic-gate 			      int maxversion,
2174*55fea89dSDan Cross 			      int *out_version,
21757c478bd9Sstevel@tonic-gate 			      sasl_client_plug_t **pluglist,
21767c478bd9Sstevel@tonic-gate 			      int *plugcount)
21777c478bd9Sstevel@tonic-gate {
21787c478bd9Sstevel@tonic-gate     if (maxversion < SASL_CLIENT_PLUG_VERSION) {
21797c478bd9Sstevel@tonic-gate 	SETERROR(utils, "Version mismatch in GSSAPI");
21807c478bd9Sstevel@tonic-gate 	return SASL_BADVERS;
21817c478bd9Sstevel@tonic-gate     }
2182*55fea89dSDan Cross 
21837c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
21847c478bd9Sstevel@tonic-gate     /*
21857c478bd9Sstevel@tonic-gate      * Let libsasl know that we are a "Sun" plugin so that privacy
21867c478bd9Sstevel@tonic-gate      * and integrity will be allowed.
21877c478bd9Sstevel@tonic-gate      */
21887c478bd9Sstevel@tonic-gate     REG_PLUG("GSSAPI", gssapi_client_plugins);
21897c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
21907c478bd9Sstevel@tonic-gate 
21917c478bd9Sstevel@tonic-gate     *out_version = SASL_CLIENT_PLUG_VERSION;
21927c478bd9Sstevel@tonic-gate     *pluglist = gssapi_client_plugins;
21937c478bd9Sstevel@tonic-gate     *plugcount = 1;
2194*55fea89dSDan Cross 
21957c478bd9Sstevel@tonic-gate     return SASL_OK;
21967c478bd9Sstevel@tonic-gate }
2197