1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate */
5*7c478bd9Sstevel@tonic-gate
6*7c478bd9Sstevel@tonic-gate /* GSSAPI SASL plugin
7*7c478bd9Sstevel@tonic-gate * Leif Johansson
8*7c478bd9Sstevel@tonic-gate * Rob Siemborski (SASL v2 Conversion)
9*7c478bd9Sstevel@tonic-gate * $Id: gssapi.c,v 1.75 2003/07/02 13:13:42 rjs3 Exp $
10*7c478bd9Sstevel@tonic-gate */
11*7c478bd9Sstevel@tonic-gate /*
12*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
15*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions
16*7c478bd9Sstevel@tonic-gate * are met:
17*7c478bd9Sstevel@tonic-gate *
18*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
19*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
20*7c478bd9Sstevel@tonic-gate *
21*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
22*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in
23*7c478bd9Sstevel@tonic-gate * the documentation and/or other materials provided with the
24*7c478bd9Sstevel@tonic-gate * distribution.
25*7c478bd9Sstevel@tonic-gate *
26*7c478bd9Sstevel@tonic-gate * 3. The name "Carnegie Mellon University" must not be used to
27*7c478bd9Sstevel@tonic-gate * endorse or promote products derived from this software without
28*7c478bd9Sstevel@tonic-gate * prior written permission. For permission or any other legal
29*7c478bd9Sstevel@tonic-gate * details, please contact
30*7c478bd9Sstevel@tonic-gate * Office of Technology Transfer
31*7c478bd9Sstevel@tonic-gate * Carnegie Mellon University
32*7c478bd9Sstevel@tonic-gate * 5000 Forbes Avenue
33*7c478bd9Sstevel@tonic-gate * Pittsburgh, PA 15213-3890
34*7c478bd9Sstevel@tonic-gate * (412) 268-4387, fax: (412) 268-7395
35*7c478bd9Sstevel@tonic-gate * tech-transfer@andrew.cmu.edu
36*7c478bd9Sstevel@tonic-gate *
37*7c478bd9Sstevel@tonic-gate * 4. Redistributions of any form whatsoever must retain the following
38*7c478bd9Sstevel@tonic-gate * acknowledgment:
39*7c478bd9Sstevel@tonic-gate * "This product includes software developed by Computing Services
40*7c478bd9Sstevel@tonic-gate * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
41*7c478bd9Sstevel@tonic-gate *
42*7c478bd9Sstevel@tonic-gate * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
43*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
44*7c478bd9Sstevel@tonic-gate * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
45*7c478bd9Sstevel@tonic-gate * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46*7c478bd9Sstevel@tonic-gate * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
47*7c478bd9Sstevel@tonic-gate * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
48*7c478bd9Sstevel@tonic-gate * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49*7c478bd9Sstevel@tonic-gate */
50*7c478bd9Sstevel@tonic-gate
51*7c478bd9Sstevel@tonic-gate #include <config.h>
52*7c478bd9Sstevel@tonic-gate
53*7c478bd9Sstevel@tonic-gate #ifdef HAVE_GSSAPI_H
54*7c478bd9Sstevel@tonic-gate #include <gssapi.h>
55*7c478bd9Sstevel@tonic-gate #else
56*7c478bd9Sstevel@tonic-gate #include <gssapi/gssapi.h>
57*7c478bd9Sstevel@tonic-gate #endif
58*7c478bd9Sstevel@tonic-gate
59*7c478bd9Sstevel@tonic-gate #ifdef WIN32
60*7c478bd9Sstevel@tonic-gate # include <winsock.h>
61*7c478bd9Sstevel@tonic-gate
62*7c478bd9Sstevel@tonic-gate # ifndef R_OK
63*7c478bd9Sstevel@tonic-gate # define R_OK 04
64*7c478bd9Sstevel@tonic-gate # endif
65*7c478bd9Sstevel@tonic-gate /* we also need io.h for access() prototype */
66*7c478bd9Sstevel@tonic-gate # include <io.h>
67*7c478bd9Sstevel@tonic-gate #else
68*7c478bd9Sstevel@tonic-gate # include <sys/param.h>
69*7c478bd9Sstevel@tonic-gate # include <sys/socket.h>
70*7c478bd9Sstevel@tonic-gate # include <netinet/in.h>
71*7c478bd9Sstevel@tonic-gate # include <arpa/inet.h>
72*7c478bd9Sstevel@tonic-gate # include <netdb.h>
73*7c478bd9Sstevel@tonic-gate #endif /* WIN32 */
74*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
75*7c478bd9Sstevel@tonic-gate #include <stdio.h>
76*7c478bd9Sstevel@tonic-gate #include <sasl.h>
77*7c478bd9Sstevel@tonic-gate #include <saslutil.h>
78*7c478bd9Sstevel@tonic-gate #include <saslplug.h>
79*7c478bd9Sstevel@tonic-gate
80*7c478bd9Sstevel@tonic-gate #include "plugin_common.h"
81*7c478bd9Sstevel@tonic-gate
82*7c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H
83*7c478bd9Sstevel@tonic-gate #include <unistd.h>
84*7c478bd9Sstevel@tonic-gate #endif
85*7c478bd9Sstevel@tonic-gate
86*7c478bd9Sstevel@tonic-gate #include <errno.h>
87*7c478bd9Sstevel@tonic-gate
88*7c478bd9Sstevel@tonic-gate #ifdef WIN32
89*7c478bd9Sstevel@tonic-gate /* This must be after sasl.h */
90*7c478bd9Sstevel@tonic-gate # include "saslgssapi.h"
91*7c478bd9Sstevel@tonic-gate #endif /* WIN32 */
92*7c478bd9Sstevel@tonic-gate
93*7c478bd9Sstevel@tonic-gate /***************************** Common Section *****************************/
94*7c478bd9Sstevel@tonic-gate
95*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
96*7c478bd9Sstevel@tonic-gate static const char plugin_id[] = "$Id: gssapi.c,v 1.75 2003/07/02 13:13:42 rjs3 Exp $";
97*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
98*7c478bd9Sstevel@tonic-gate
99*7c478bd9Sstevel@tonic-gate static const char * GSSAPI_BLANK_STRING = "";
100*7c478bd9Sstevel@tonic-gate
101*7c478bd9Sstevel@tonic-gate #ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
102*7c478bd9Sstevel@tonic-gate extern gss_OID gss_nt_service_name;
103*7c478bd9Sstevel@tonic-gate #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
104*7c478bd9Sstevel@tonic-gate #endif
105*7c478bd9Sstevel@tonic-gate
106*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
107*7c478bd9Sstevel@tonic-gate static int
108*7c478bd9Sstevel@tonic-gate get_oid(const sasl_utils_t *utils, gss_OID *oid);
109*7c478bd9Sstevel@tonic-gate #ifdef GSSAPI_PROTECT
110*7c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(global_mutex);
111*7c478bd9Sstevel@tonic-gate #endif /* GSSAPI_PROTECT */
112*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
113*7c478bd9Sstevel@tonic-gate
114*7c478bd9Sstevel@tonic-gate /* GSSAPI SASL Mechanism by Leif Johansson <leifj@matematik.su.se>
115*7c478bd9Sstevel@tonic-gate * inspired by the kerberos mechanism and the gssapi_server and
116*7c478bd9Sstevel@tonic-gate * gssapi_client from the heimdal distribution by Assar Westerlund
117*7c478bd9Sstevel@tonic-gate * <assar@sics.se> and Johan Danielsson <joda@pdc.kth.se>.
118*7c478bd9Sstevel@tonic-gate * See the configure.in file for details on dependencies.
119*7c478bd9Sstevel@tonic-gate * Heimdal can be obtained from http://www.pdc.kth.se/heimdal
120*7c478bd9Sstevel@tonic-gate *
121*7c478bd9Sstevel@tonic-gate * Important contributions from Sam Hartman <hartmans@fundsxpress.com>.
122*7c478bd9Sstevel@tonic-gate */
123*7c478bd9Sstevel@tonic-gate
124*7c478bd9Sstevel@tonic-gate typedef struct context {
125*7c478bd9Sstevel@tonic-gate int state;
126*7c478bd9Sstevel@tonic-gate
127*7c478bd9Sstevel@tonic-gate gss_ctx_id_t gss_ctx;
128*7c478bd9Sstevel@tonic-gate gss_name_t client_name;
129*7c478bd9Sstevel@tonic-gate gss_name_t server_name;
130*7c478bd9Sstevel@tonic-gate gss_cred_id_t server_creds;
131*7c478bd9Sstevel@tonic-gate sasl_ssf_t limitssf, requiressf; /* application defined bounds, for the
132*7c478bd9Sstevel@tonic-gate server */
133*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
134*7c478bd9Sstevel@tonic-gate gss_cred_id_t client_creds;
135*7c478bd9Sstevel@tonic-gate gss_OID mech_oid;
136*7c478bd9Sstevel@tonic-gate int use_authid;
137*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
138*7c478bd9Sstevel@tonic-gate const sasl_utils_t *utils;
139*7c478bd9Sstevel@tonic-gate
140*7c478bd9Sstevel@tonic-gate /* layers buffering */
141*7c478bd9Sstevel@tonic-gate char *buffer;
142*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
143*7c478bd9Sstevel@tonic-gate unsigned bufsize;
144*7c478bd9Sstevel@tonic-gate #else
145*7c478bd9Sstevel@tonic-gate int bufsize;
146*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
147*7c478bd9Sstevel@tonic-gate char sizebuf[4];
148*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
149*7c478bd9Sstevel@tonic-gate unsigned cursize;
150*7c478bd9Sstevel@tonic-gate unsigned size;
151*7c478bd9Sstevel@tonic-gate #else
152*7c478bd9Sstevel@tonic-gate int cursize;
153*7c478bd9Sstevel@tonic-gate int size;
154*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
155*7c478bd9Sstevel@tonic-gate unsigned needsize;
156*7c478bd9Sstevel@tonic-gate
157*7c478bd9Sstevel@tonic-gate char *encode_buf; /* For encoding/decoding mem management */
158*7c478bd9Sstevel@tonic-gate char *decode_buf;
159*7c478bd9Sstevel@tonic-gate char *decode_once_buf;
160*7c478bd9Sstevel@tonic-gate unsigned encode_buf_len;
161*7c478bd9Sstevel@tonic-gate unsigned decode_buf_len;
162*7c478bd9Sstevel@tonic-gate unsigned decode_once_buf_len;
163*7c478bd9Sstevel@tonic-gate buffer_info_t *enc_in_buf;
164*7c478bd9Sstevel@tonic-gate
165*7c478bd9Sstevel@tonic-gate char *out_buf; /* per-step mem management */
166*7c478bd9Sstevel@tonic-gate unsigned out_buf_len;
167*7c478bd9Sstevel@tonic-gate
168*7c478bd9Sstevel@tonic-gate char *authid; /* hold the authid between steps - server */
169*7c478bd9Sstevel@tonic-gate const char *user; /* hold the userid between steps - client */
170*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
171*7c478bd9Sstevel@tonic-gate const char *client_authid;
172*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
173*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
174*7c478bd9Sstevel@tonic-gate void *h;
175*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
176*7c478bd9Sstevel@tonic-gate } context_t;
177*7c478bd9Sstevel@tonic-gate
178*7c478bd9Sstevel@tonic-gate enum {
179*7c478bd9Sstevel@tonic-gate SASL_GSSAPI_STATE_AUTHNEG = 1,
180*7c478bd9Sstevel@tonic-gate SASL_GSSAPI_STATE_SSFCAP = 2,
181*7c478bd9Sstevel@tonic-gate SASL_GSSAPI_STATE_SSFREQ = 3,
182*7c478bd9Sstevel@tonic-gate SASL_GSSAPI_STATE_AUTHENTICATED = 4
183*7c478bd9Sstevel@tonic-gate };
184*7c478bd9Sstevel@tonic-gate
185*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
186*7c478bd9Sstevel@tonic-gate /* sasl_gss_log only logs gss_display_status() error string */
187*7c478bd9Sstevel@tonic-gate #define sasl_gss_log(x,y,z) sasl_gss_seterror_(text,y,z,1)
188*7c478bd9Sstevel@tonic-gate #define sasl_gss_seterror(x,y,z) sasl_gss_seterror_(text,y,z,0)
189*7c478bd9Sstevel@tonic-gate static void
sasl_gss_seterror_(const context_t * text,OM_uint32 maj,OM_uint32 min,int logonly)190*7c478bd9Sstevel@tonic-gate sasl_gss_seterror_(const context_t *text, OM_uint32 maj, OM_uint32 min,
191*7c478bd9Sstevel@tonic-gate int logonly)
192*7c478bd9Sstevel@tonic-gate #else
193*7c478bd9Sstevel@tonic-gate static void
194*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min)
195*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate OM_uint32 maj_stat, min_stat;
198*7c478bd9Sstevel@tonic-gate gss_buffer_desc msg;
199*7c478bd9Sstevel@tonic-gate OM_uint32 msg_ctx;
200*7c478bd9Sstevel@tonic-gate int ret;
201*7c478bd9Sstevel@tonic-gate char *out = NULL;
202*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
203*7c478bd9Sstevel@tonic-gate unsigned len, curlen = 0;
204*7c478bd9Sstevel@tonic-gate const sasl_utils_t *utils = text->utils;
205*7c478bd9Sstevel@tonic-gate char *prefix = dgettext(TEXT_DOMAIN, "GSSAPI Error: ");
206*7c478bd9Sstevel@tonic-gate #else
207*7c478bd9Sstevel@tonic-gate size_t len, curlen = 0;
208*7c478bd9Sstevel@tonic-gate const char prefix[] = "GSSAPI Error: ";
209*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
210*7c478bd9Sstevel@tonic-gate
211*7c478bd9Sstevel@tonic-gate if(!utils) return;
212*7c478bd9Sstevel@tonic-gate
213*7c478bd9Sstevel@tonic-gate len = sizeof(prefix);
214*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(utils, &out, &curlen, 256);
215*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) return;
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate strcpy(out, prefix);
218*7c478bd9Sstevel@tonic-gate
219*7c478bd9Sstevel@tonic-gate msg_ctx = 0;
220*7c478bd9Sstevel@tonic-gate while (1) {
221*7c478bd9Sstevel@tonic-gate maj_stat = gss_display_status(&min_stat, maj,
222*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
223*7c478bd9Sstevel@tonic-gate GSS_C_GSS_CODE, text->mech_oid,
224*7c478bd9Sstevel@tonic-gate #else
225*7c478bd9Sstevel@tonic-gate GSS_C_GSS_CODE, GSS_C_NULL_OID,
226*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
227*7c478bd9Sstevel@tonic-gate &msg_ctx, &msg);
228*7c478bd9Sstevel@tonic-gate if(GSS_ERROR(maj_stat)) {
229*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
230*7c478bd9Sstevel@tonic-gate if (logonly) {
231*7c478bd9Sstevel@tonic-gate utils->log(text->utils->conn, SASL_LOG_FAIL,
232*7c478bd9Sstevel@tonic-gate "GSSAPI Failure: (could not get major error message)");
233*7c478bd9Sstevel@tonic-gate } else {
234*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
235*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
236*7c478bd9Sstevel@tonic-gate utils->seterror(utils->conn, 0,
237*7c478bd9Sstevel@tonic-gate gettext("GSSAPI Failure "
238*7c478bd9Sstevel@tonic-gate "(could not get major error message)"));
239*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
240*7c478bd9Sstevel@tonic-gate }
241*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
242*7c478bd9Sstevel@tonic-gate #else
243*7c478bd9Sstevel@tonic-gate utils->seterror(utils->conn, 0,
244*7c478bd9Sstevel@tonic-gate "GSSAPI Failure "
245*7c478bd9Sstevel@tonic-gate "(could not get major error message)");
246*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
247*7c478bd9Sstevel@tonic-gate }
248*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
249*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
250*7c478bd9Sstevel@tonic-gate utils->free(out);
251*7c478bd9Sstevel@tonic-gate return;
252*7c478bd9Sstevel@tonic-gate }
253*7c478bd9Sstevel@tonic-gate
254*7c478bd9Sstevel@tonic-gate len += len + msg.length;
255*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(utils, &out, &curlen, len);
256*7c478bd9Sstevel@tonic-gate
257*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) {
258*7c478bd9Sstevel@tonic-gate utils->free(out);
259*7c478bd9Sstevel@tonic-gate return;
260*7c478bd9Sstevel@tonic-gate }
261*7c478bd9Sstevel@tonic-gate
262*7c478bd9Sstevel@tonic-gate strcat(out, msg.value);
263*7c478bd9Sstevel@tonic-gate
264*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, &msg);
265*7c478bd9Sstevel@tonic-gate
266*7c478bd9Sstevel@tonic-gate if (!msg_ctx)
267*7c478bd9Sstevel@tonic-gate break;
268*7c478bd9Sstevel@tonic-gate }
269*7c478bd9Sstevel@tonic-gate
270*7c478bd9Sstevel@tonic-gate /* Now get the minor status */
271*7c478bd9Sstevel@tonic-gate
272*7c478bd9Sstevel@tonic-gate len += 2;
273*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(utils, &out, &curlen, len);
274*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) {
275*7c478bd9Sstevel@tonic-gate utils->free(out);
276*7c478bd9Sstevel@tonic-gate return;
277*7c478bd9Sstevel@tonic-gate }
278*7c478bd9Sstevel@tonic-gate
279*7c478bd9Sstevel@tonic-gate strcat(out, " (");
280*7c478bd9Sstevel@tonic-gate
281*7c478bd9Sstevel@tonic-gate msg_ctx = 0;
282*7c478bd9Sstevel@tonic-gate while (1) {
283*7c478bd9Sstevel@tonic-gate maj_stat = gss_display_status(&min_stat, min,
284*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
285*7c478bd9Sstevel@tonic-gate GSS_C_MECH_CODE, text->mech_oid,
286*7c478bd9Sstevel@tonic-gate #else
287*7c478bd9Sstevel@tonic-gate GSS_C_MECH_CODE, GSS_C_NULL_OID,
288*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
289*7c478bd9Sstevel@tonic-gate &msg_ctx, &msg);
290*7c478bd9Sstevel@tonic-gate if(GSS_ERROR(maj_stat)) {
291*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
292*7c478bd9Sstevel@tonic-gate if (logonly) {
293*7c478bd9Sstevel@tonic-gate utils->log(text->utils->conn, SASL_LOG_FAIL,
294*7c478bd9Sstevel@tonic-gate "GSSAPI Failure: (could not get minor error message)");
295*7c478bd9Sstevel@tonic-gate } else {
296*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
297*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
298*7c478bd9Sstevel@tonic-gate utils->seterror(utils->conn, 0,
299*7c478bd9Sstevel@tonic-gate gettext("GSSAPI Failure "
300*7c478bd9Sstevel@tonic-gate "(could not get minor error message)"));
301*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
302*7c478bd9Sstevel@tonic-gate }
303*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
304*7c478bd9Sstevel@tonic-gate #else
305*7c478bd9Sstevel@tonic-gate utils->seterror(utils->conn, 0,
306*7c478bd9Sstevel@tonic-gate "GSSAPI Failure "
307*7c478bd9Sstevel@tonic-gate "(could not get minor error message)");
308*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
309*7c478bd9Sstevel@tonic-gate }
310*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
311*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
312*7c478bd9Sstevel@tonic-gate utils->free(out);
313*7c478bd9Sstevel@tonic-gate return;
314*7c478bd9Sstevel@tonic-gate }
315*7c478bd9Sstevel@tonic-gate
316*7c478bd9Sstevel@tonic-gate len += len + msg.length;
317*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(utils, &out, &curlen, len);
318*7c478bd9Sstevel@tonic-gate
319*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) {
320*7c478bd9Sstevel@tonic-gate utils->free(out);
321*7c478bd9Sstevel@tonic-gate return;
322*7c478bd9Sstevel@tonic-gate }
323*7c478bd9Sstevel@tonic-gate
324*7c478bd9Sstevel@tonic-gate strcat(out, msg.value);
325*7c478bd9Sstevel@tonic-gate
326*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, &msg);
327*7c478bd9Sstevel@tonic-gate
328*7c478bd9Sstevel@tonic-gate if (!msg_ctx)
329*7c478bd9Sstevel@tonic-gate break;
330*7c478bd9Sstevel@tonic-gate }
331*7c478bd9Sstevel@tonic-gate
332*7c478bd9Sstevel@tonic-gate len += 1;
333*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(utils, &out, &curlen, len);
334*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) {
335*7c478bd9Sstevel@tonic-gate utils->free(out);
336*7c478bd9Sstevel@tonic-gate return;
337*7c478bd9Sstevel@tonic-gate }
338*7c478bd9Sstevel@tonic-gate
339*7c478bd9Sstevel@tonic-gate strcat(out, ")");
340*7c478bd9Sstevel@tonic-gate
341*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
342*7c478bd9Sstevel@tonic-gate if (logonly) {
343*7c478bd9Sstevel@tonic-gate utils->log(text->utils->conn, SASL_LOG_FAIL, out);
344*7c478bd9Sstevel@tonic-gate } else {
345*7c478bd9Sstevel@tonic-gate utils->seterror(utils->conn, 0, out);
346*7c478bd9Sstevel@tonic-gate }
347*7c478bd9Sstevel@tonic-gate #else
348*7c478bd9Sstevel@tonic-gate utils->seterror(utils->conn, 0, out);
349*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
350*7c478bd9Sstevel@tonic-gate utils->free(out);
351*7c478bd9Sstevel@tonic-gate }
352*7c478bd9Sstevel@tonic-gate
353*7c478bd9Sstevel@tonic-gate static int
sasl_gss_encode(void * context,const struct iovec * invec,unsigned numiov,const char ** output,unsigned * outputlen,int privacy)354*7c478bd9Sstevel@tonic-gate sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov,
355*7c478bd9Sstevel@tonic-gate const char **output, unsigned *outputlen, int privacy)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate context_t *text = (context_t *)context;
358*7c478bd9Sstevel@tonic-gate OM_uint32 maj_stat, min_stat;
359*7c478bd9Sstevel@tonic-gate gss_buffer_t input_token, output_token;
360*7c478bd9Sstevel@tonic-gate gss_buffer_desc real_input_token, real_output_token;
361*7c478bd9Sstevel@tonic-gate int ret;
362*7c478bd9Sstevel@tonic-gate struct buffer_info *inblob, bufinfo;
363*7c478bd9Sstevel@tonic-gate
364*7c478bd9Sstevel@tonic-gate if(!output) return SASL_BADPARAM;
365*7c478bd9Sstevel@tonic-gate
366*7c478bd9Sstevel@tonic-gate if(numiov > 1) {
367*7c478bd9Sstevel@tonic-gate ret = _plug_iovec_to_buf(text->utils, invec, numiov, &text->enc_in_buf);
368*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) return ret;
369*7c478bd9Sstevel@tonic-gate inblob = text->enc_in_buf;
370*7c478bd9Sstevel@tonic-gate } else {
371*7c478bd9Sstevel@tonic-gate bufinfo.data = invec[0].iov_base;
372*7c478bd9Sstevel@tonic-gate bufinfo.curlen = invec[0].iov_len;
373*7c478bd9Sstevel@tonic-gate inblob = &bufinfo;
374*7c478bd9Sstevel@tonic-gate }
375*7c478bd9Sstevel@tonic-gate
376*7c478bd9Sstevel@tonic-gate if (text->state != SASL_GSSAPI_STATE_AUTHENTICATED) return SASL_NOTDONE;
377*7c478bd9Sstevel@tonic-gate
378*7c478bd9Sstevel@tonic-gate input_token = &real_input_token;
379*7c478bd9Sstevel@tonic-gate
380*7c478bd9Sstevel@tonic-gate real_input_token.value = inblob->data;
381*7c478bd9Sstevel@tonic-gate real_input_token.length = inblob->curlen;
382*7c478bd9Sstevel@tonic-gate
383*7c478bd9Sstevel@tonic-gate output_token = &real_output_token;
384*7c478bd9Sstevel@tonic-gate output_token->value = NULL;
385*7c478bd9Sstevel@tonic-gate output_token->length = 0;
386*7c478bd9Sstevel@tonic-gate
387*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
388*7c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&global_mutex) < 0)
389*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
390*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
391*7c478bd9Sstevel@tonic-gate maj_stat = gss_wrap (&min_stat,
392*7c478bd9Sstevel@tonic-gate text->gss_ctx,
393*7c478bd9Sstevel@tonic-gate privacy,
394*7c478bd9Sstevel@tonic-gate GSS_C_QOP_DEFAULT,
395*7c478bd9Sstevel@tonic-gate input_token,
396*7c478bd9Sstevel@tonic-gate NULL,
397*7c478bd9Sstevel@tonic-gate output_token);
398*7c478bd9Sstevel@tonic-gate
399*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat))
400*7c478bd9Sstevel@tonic-gate {
401*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
402*7c478bd9Sstevel@tonic-gate if (output_token->value)
403*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
404*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
405*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
406*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
407*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
408*7c478bd9Sstevel@tonic-gate }
409*7c478bd9Sstevel@tonic-gate
410*7c478bd9Sstevel@tonic-gate if (output_token->value && output) {
411*7c478bd9Sstevel@tonic-gate int len;
412*7c478bd9Sstevel@tonic-gate
413*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(text->utils, &(text->encode_buf),
414*7c478bd9Sstevel@tonic-gate &(text->encode_buf_len), output_token->length + 4);
415*7c478bd9Sstevel@tonic-gate
416*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) {
417*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
418*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
419*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
420*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
421*7c478bd9Sstevel@tonic-gate return ret;
422*7c478bd9Sstevel@tonic-gate }
423*7c478bd9Sstevel@tonic-gate
424*7c478bd9Sstevel@tonic-gate len = htonl(output_token->length);
425*7c478bd9Sstevel@tonic-gate memcpy(text->encode_buf, &len, 4);
426*7c478bd9Sstevel@tonic-gate memcpy(text->encode_buf + 4, output_token->value, output_token->length);
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate
429*7c478bd9Sstevel@tonic-gate if (outputlen) {
430*7c478bd9Sstevel@tonic-gate *outputlen = output_token->length + 4;
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate
433*7c478bd9Sstevel@tonic-gate *output = text->encode_buf;
434*7c478bd9Sstevel@tonic-gate
435*7c478bd9Sstevel@tonic-gate if (output_token->value)
436*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
437*7c478bd9Sstevel@tonic-gate
438*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
439*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
440*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
441*7c478bd9Sstevel@tonic-gate
442*7c478bd9Sstevel@tonic-gate return SASL_OK;
443*7c478bd9Sstevel@tonic-gate }
444*7c478bd9Sstevel@tonic-gate
gssapi_privacy_encode(void * context,const struct iovec * invec,unsigned numiov,const char ** output,unsigned * outputlen)445*7c478bd9Sstevel@tonic-gate static int gssapi_privacy_encode(void *context, const struct iovec *invec,
446*7c478bd9Sstevel@tonic-gate unsigned numiov, const char **output,
447*7c478bd9Sstevel@tonic-gate unsigned *outputlen)
448*7c478bd9Sstevel@tonic-gate {
449*7c478bd9Sstevel@tonic-gate return sasl_gss_encode(context,invec,numiov,output,outputlen,1);
450*7c478bd9Sstevel@tonic-gate }
451*7c478bd9Sstevel@tonic-gate
gssapi_integrity_encode(void * context,const struct iovec * invec,unsigned numiov,const char ** output,unsigned * outputlen)452*7c478bd9Sstevel@tonic-gate static int gssapi_integrity_encode(void *context, const struct iovec *invec,
453*7c478bd9Sstevel@tonic-gate unsigned numiov, const char **output,
454*7c478bd9Sstevel@tonic-gate unsigned *outputlen)
455*7c478bd9Sstevel@tonic-gate {
456*7c478bd9Sstevel@tonic-gate return sasl_gss_encode(context,invec,numiov,output,outputlen,0);
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate
459*7c478bd9Sstevel@tonic-gate #define myMIN(a,b) (((a) < (b)) ? (a) : (b))
460*7c478bd9Sstevel@tonic-gate
gssapi_decode_once(void * context,const char ** input,unsigned * inputlen,char ** output,unsigned * outputlen)461*7c478bd9Sstevel@tonic-gate static int gssapi_decode_once(void *context,
462*7c478bd9Sstevel@tonic-gate const char **input, unsigned *inputlen,
463*7c478bd9Sstevel@tonic-gate char **output, unsigned *outputlen)
464*7c478bd9Sstevel@tonic-gate {
465*7c478bd9Sstevel@tonic-gate context_t *text = (context_t *) context;
466*7c478bd9Sstevel@tonic-gate OM_uint32 maj_stat, min_stat;
467*7c478bd9Sstevel@tonic-gate gss_buffer_t input_token, output_token;
468*7c478bd9Sstevel@tonic-gate gss_buffer_desc real_input_token, real_output_token;
469*7c478bd9Sstevel@tonic-gate int result;
470*7c478bd9Sstevel@tonic-gate unsigned diff;
471*7c478bd9Sstevel@tonic-gate
472*7c478bd9Sstevel@tonic-gate if (text->state != SASL_GSSAPI_STATE_AUTHENTICATED) {
473*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
474*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, gettext("GSSAPI Failure"));
475*7c478bd9Sstevel@tonic-gate #else
476*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, "GSSAPI Failure");
477*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
478*7c478bd9Sstevel@tonic-gate return SASL_NOTDONE;
479*7c478bd9Sstevel@tonic-gate }
480*7c478bd9Sstevel@tonic-gate
481*7c478bd9Sstevel@tonic-gate /* first we need to extract a packet */
482*7c478bd9Sstevel@tonic-gate if (text->needsize > 0) {
483*7c478bd9Sstevel@tonic-gate /* how long is it? */
484*7c478bd9Sstevel@tonic-gate int tocopy = myMIN(text->needsize, *inputlen);
485*7c478bd9Sstevel@tonic-gate
486*7c478bd9Sstevel@tonic-gate memcpy(text->sizebuf + 4 - text->needsize, *input, tocopy);
487*7c478bd9Sstevel@tonic-gate text->needsize -= tocopy;
488*7c478bd9Sstevel@tonic-gate *input += tocopy;
489*7c478bd9Sstevel@tonic-gate *inputlen -= tocopy;
490*7c478bd9Sstevel@tonic-gate
491*7c478bd9Sstevel@tonic-gate if (text->needsize == 0) {
492*7c478bd9Sstevel@tonic-gate /* got the entire size */
493*7c478bd9Sstevel@tonic-gate memcpy(&text->size, text->sizebuf, 4);
494*7c478bd9Sstevel@tonic-gate text->size = ntohl(text->size);
495*7c478bd9Sstevel@tonic-gate text->cursize = 0;
496*7c478bd9Sstevel@tonic-gate
497*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
498*7c478bd9Sstevel@tonic-gate if (text->size > 0xFFFFFF) {
499*7c478bd9Sstevel@tonic-gate text->utils->log(text->utils->conn, SASL_LOG_ERR,
500*7c478bd9Sstevel@tonic-gate "Illegal size in sasl_gss_decode_once");
501*7c478bd9Sstevel@tonic-gate #else
502*7c478bd9Sstevel@tonic-gate if (text->size > 0xFFFFFF || text->size <= 0) {
503*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, "Illegal size in sasl_gss_decode_once");
504*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
505*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate
508*7c478bd9Sstevel@tonic-gate if (text->bufsize < text->size + 5) {
509*7c478bd9Sstevel@tonic-gate result = _plug_buf_alloc(text->utils, &text->buffer,
510*7c478bd9Sstevel@tonic-gate &(text->bufsize), text->size+5);
511*7c478bd9Sstevel@tonic-gate if(result != SASL_OK) return result;
512*7c478bd9Sstevel@tonic-gate }
513*7c478bd9Sstevel@tonic-gate }
514*7c478bd9Sstevel@tonic-gate if (*inputlen == 0) {
515*7c478bd9Sstevel@tonic-gate /* need more data ! */
516*7c478bd9Sstevel@tonic-gate *outputlen = 0;
517*7c478bd9Sstevel@tonic-gate *output = NULL;
518*7c478bd9Sstevel@tonic-gate
519*7c478bd9Sstevel@tonic-gate return SASL_OK;
520*7c478bd9Sstevel@tonic-gate }
521*7c478bd9Sstevel@tonic-gate }
522*7c478bd9Sstevel@tonic-gate
523*7c478bd9Sstevel@tonic-gate diff = text->size - text->cursize;
524*7c478bd9Sstevel@tonic-gate
525*7c478bd9Sstevel@tonic-gate if (*inputlen < diff) {
526*7c478bd9Sstevel@tonic-gate /* ok, let's queue it up; not enough data */
527*7c478bd9Sstevel@tonic-gate memcpy(text->buffer + text->cursize, *input, *inputlen);
528*7c478bd9Sstevel@tonic-gate text->cursize += *inputlen;
529*7c478bd9Sstevel@tonic-gate *inputlen = 0;
530*7c478bd9Sstevel@tonic-gate *outputlen = 0;
531*7c478bd9Sstevel@tonic-gate *output = NULL;
532*7c478bd9Sstevel@tonic-gate return SASL_OK;
533*7c478bd9Sstevel@tonic-gate } else {
534*7c478bd9Sstevel@tonic-gate memcpy(text->buffer + text->cursize, *input, diff);
535*7c478bd9Sstevel@tonic-gate *input += diff;
536*7c478bd9Sstevel@tonic-gate *inputlen -= diff;
537*7c478bd9Sstevel@tonic-gate }
538*7c478bd9Sstevel@tonic-gate
539*7c478bd9Sstevel@tonic-gate input_token = &real_input_token;
540*7c478bd9Sstevel@tonic-gate real_input_token.value = text->buffer;
541*7c478bd9Sstevel@tonic-gate real_input_token.length = text->size;
542*7c478bd9Sstevel@tonic-gate
543*7c478bd9Sstevel@tonic-gate output_token = &real_output_token;
544*7c478bd9Sstevel@tonic-gate output_token->value = NULL;
545*7c478bd9Sstevel@tonic-gate output_token->length = 0;
546*7c478bd9Sstevel@tonic-gate
547*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
548*7c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&global_mutex) < 0)
549*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
550*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
551*7c478bd9Sstevel@tonic-gate
552*7c478bd9Sstevel@tonic-gate maj_stat = gss_unwrap (&min_stat,
553*7c478bd9Sstevel@tonic-gate text->gss_ctx,
554*7c478bd9Sstevel@tonic-gate input_token,
555*7c478bd9Sstevel@tonic-gate output_token,
556*7c478bd9Sstevel@tonic-gate NULL,
557*7c478bd9Sstevel@tonic-gate NULL);
558*7c478bd9Sstevel@tonic-gate
559*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat))
560*7c478bd9Sstevel@tonic-gate {
561*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
562*7c478bd9Sstevel@tonic-gate if (output_token->value)
563*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
564*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
565*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
566*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
567*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
568*7c478bd9Sstevel@tonic-gate }
569*7c478bd9Sstevel@tonic-gate
570*7c478bd9Sstevel@tonic-gate if (outputlen)
571*7c478bd9Sstevel@tonic-gate *outputlen = output_token->length;
572*7c478bd9Sstevel@tonic-gate
573*7c478bd9Sstevel@tonic-gate if (output_token->value) {
574*7c478bd9Sstevel@tonic-gate if (output) {
575*7c478bd9Sstevel@tonic-gate result = _plug_buf_alloc(text->utils, &text->decode_once_buf,
576*7c478bd9Sstevel@tonic-gate &text->decode_once_buf_len,
577*7c478bd9Sstevel@tonic-gate *outputlen);
578*7c478bd9Sstevel@tonic-gate if(result != SASL_OK) {
579*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
580*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
581*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
582*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
583*7c478bd9Sstevel@tonic-gate return result;
584*7c478bd9Sstevel@tonic-gate }
585*7c478bd9Sstevel@tonic-gate *output = text->decode_once_buf;
586*7c478bd9Sstevel@tonic-gate memcpy(*output, output_token->value, *outputlen);
587*7c478bd9Sstevel@tonic-gate }
588*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
589*7c478bd9Sstevel@tonic-gate }
590*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
591*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
592*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
593*7c478bd9Sstevel@tonic-gate
594*7c478bd9Sstevel@tonic-gate /* reset for the next packet */
595*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
596*7c478bd9Sstevel@tonic-gate text->size = -1;
597*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
598*7c478bd9Sstevel@tonic-gate text->needsize = 4;
599*7c478bd9Sstevel@tonic-gate
600*7c478bd9Sstevel@tonic-gate return SASL_OK;
601*7c478bd9Sstevel@tonic-gate }
602*7c478bd9Sstevel@tonic-gate
603*7c478bd9Sstevel@tonic-gate static int gssapi_decode(void *context,
604*7c478bd9Sstevel@tonic-gate const char *input, unsigned inputlen,
605*7c478bd9Sstevel@tonic-gate const char **output, unsigned *outputlen)
606*7c478bd9Sstevel@tonic-gate {
607*7c478bd9Sstevel@tonic-gate context_t *text = (context_t *) context;
608*7c478bd9Sstevel@tonic-gate int ret;
609*7c478bd9Sstevel@tonic-gate
610*7c478bd9Sstevel@tonic-gate ret = _plug_decode(text->utils, context, input, inputlen,
611*7c478bd9Sstevel@tonic-gate &text->decode_buf, &text->decode_buf_len, outputlen,
612*7c478bd9Sstevel@tonic-gate gssapi_decode_once);
613*7c478bd9Sstevel@tonic-gate
614*7c478bd9Sstevel@tonic-gate *output = text->decode_buf;
615*7c478bd9Sstevel@tonic-gate
616*7c478bd9Sstevel@tonic-gate return ret;
617*7c478bd9Sstevel@tonic-gate }
618*7c478bd9Sstevel@tonic-gate
619*7c478bd9Sstevel@tonic-gate static context_t *gss_new_context(const sasl_utils_t *utils)
620*7c478bd9Sstevel@tonic-gate {
621*7c478bd9Sstevel@tonic-gate context_t *ret;
622*7c478bd9Sstevel@tonic-gate
623*7c478bd9Sstevel@tonic-gate ret = utils->malloc(sizeof(context_t));
624*7c478bd9Sstevel@tonic-gate if(!ret) return NULL;
625*7c478bd9Sstevel@tonic-gate
626*7c478bd9Sstevel@tonic-gate memset(ret,0,sizeof(context_t));
627*7c478bd9Sstevel@tonic-gate ret->utils = utils;
628*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
629*7c478bd9Sstevel@tonic-gate ret->gss_ctx = GSS_C_NO_CONTEXT;
630*7c478bd9Sstevel@tonic-gate ret->client_name = GSS_C_NO_NAME;
631*7c478bd9Sstevel@tonic-gate ret->server_name = GSS_C_NO_NAME;
632*7c478bd9Sstevel@tonic-gate ret->server_creds = GSS_C_NO_CREDENTIAL;
633*7c478bd9Sstevel@tonic-gate ret->client_creds = GSS_C_NO_CREDENTIAL;
634*7c478bd9Sstevel@tonic-gate if (get_oid(utils, &ret->mech_oid) != SASL_OK) {
635*7c478bd9Sstevel@tonic-gate utils->free(ret);
636*7c478bd9Sstevel@tonic-gate return (NULL);
637*7c478bd9Sstevel@tonic-gate }
638*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
639*7c478bd9Sstevel@tonic-gate
640*7c478bd9Sstevel@tonic-gate ret->needsize = 4;
641*7c478bd9Sstevel@tonic-gate
642*7c478bd9Sstevel@tonic-gate return ret;
643*7c478bd9Sstevel@tonic-gate }
644*7c478bd9Sstevel@tonic-gate
645*7c478bd9Sstevel@tonic-gate static void sasl_gss_free_context_contents(context_t *text)
646*7c478bd9Sstevel@tonic-gate {
647*7c478bd9Sstevel@tonic-gate OM_uint32 maj_stat, min_stat;
648*7c478bd9Sstevel@tonic-gate
649*7c478bd9Sstevel@tonic-gate if (!text) return;
650*7c478bd9Sstevel@tonic-gate
651*7c478bd9Sstevel@tonic-gate if (text->gss_ctx != GSS_C_NO_CONTEXT) {
652*7c478bd9Sstevel@tonic-gate maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
653*7c478bd9Sstevel@tonic-gate text->gss_ctx = GSS_C_NO_CONTEXT;
654*7c478bd9Sstevel@tonic-gate }
655*7c478bd9Sstevel@tonic-gate
656*7c478bd9Sstevel@tonic-gate if (text->client_name != GSS_C_NO_NAME) {
657*7c478bd9Sstevel@tonic-gate maj_stat = gss_release_name(&min_stat,&text->client_name);
658*7c478bd9Sstevel@tonic-gate text->client_name = GSS_C_NO_NAME;
659*7c478bd9Sstevel@tonic-gate }
660*7c478bd9Sstevel@tonic-gate
661*7c478bd9Sstevel@tonic-gate if (text->server_name != GSS_C_NO_NAME) {
662*7c478bd9Sstevel@tonic-gate maj_stat = gss_release_name(&min_stat,&text->server_name);
663*7c478bd9Sstevel@tonic-gate text->server_name = GSS_C_NO_NAME;
664*7c478bd9Sstevel@tonic-gate }
665*7c478bd9Sstevel@tonic-gate
666*7c478bd9Sstevel@tonic-gate if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
667*7c478bd9Sstevel@tonic-gate maj_stat = gss_release_cred(&min_stat, &text->server_creds);
668*7c478bd9Sstevel@tonic-gate text->server_creds = GSS_C_NO_CREDENTIAL;
669*7c478bd9Sstevel@tonic-gate }
670*7c478bd9Sstevel@tonic-gate
671*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
672*7c478bd9Sstevel@tonic-gate if ( text->client_creds != GSS_C_NO_CREDENTIAL) {
673*7c478bd9Sstevel@tonic-gate maj_stat = gss_release_cred(&min_stat, &text->client_creds);
674*7c478bd9Sstevel@tonic-gate text->client_creds = GSS_C_NO_CREDENTIAL;
675*7c478bd9Sstevel@tonic-gate }
676*7c478bd9Sstevel@tonic-gate
677*7c478bd9Sstevel@tonic-gate /*
678*7c478bd9Sstevel@tonic-gate * Note that the oid returned by rpc_gss_mech_to_oid should not
679*7c478bd9Sstevel@tonic-gate * be released
680*7c478bd9Sstevel@tonic-gate */
681*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
682*7c478bd9Sstevel@tonic-gate
683*7c478bd9Sstevel@tonic-gate if (text->out_buf) {
684*7c478bd9Sstevel@tonic-gate text->utils->free(text->out_buf);
685*7c478bd9Sstevel@tonic-gate text->out_buf = NULL;
686*7c478bd9Sstevel@tonic-gate }
687*7c478bd9Sstevel@tonic-gate
688*7c478bd9Sstevel@tonic-gate if (text->encode_buf) {
689*7c478bd9Sstevel@tonic-gate text->utils->free(text->encode_buf);
690*7c478bd9Sstevel@tonic-gate text->encode_buf = NULL;
691*7c478bd9Sstevel@tonic-gate }
692*7c478bd9Sstevel@tonic-gate
693*7c478bd9Sstevel@tonic-gate if (text->decode_buf) {
694*7c478bd9Sstevel@tonic-gate text->utils->free(text->decode_buf);
695*7c478bd9Sstevel@tonic-gate text->decode_buf = NULL;
696*7c478bd9Sstevel@tonic-gate }
697*7c478bd9Sstevel@tonic-gate
698*7c478bd9Sstevel@tonic-gate if (text->decode_once_buf) {
699*7c478bd9Sstevel@tonic-gate text->utils->free(text->decode_once_buf);
700*7c478bd9Sstevel@tonic-gate text->decode_once_buf = NULL;
701*7c478bd9Sstevel@tonic-gate }
702*7c478bd9Sstevel@tonic-gate
703*7c478bd9Sstevel@tonic-gate if (text->enc_in_buf) {
704*7c478bd9Sstevel@tonic-gate if(text->enc_in_buf->data) text->utils->free(text->enc_in_buf->data);
705*7c478bd9Sstevel@tonic-gate text->utils->free(text->enc_in_buf);
706*7c478bd9Sstevel@tonic-gate text->enc_in_buf = NULL;
707*7c478bd9Sstevel@tonic-gate }
708*7c478bd9Sstevel@tonic-gate
709*7c478bd9Sstevel@tonic-gate if (text->buffer) {
710*7c478bd9Sstevel@tonic-gate text->utils->free(text->buffer);
711*7c478bd9Sstevel@tonic-gate text->buffer = NULL;
712*7c478bd9Sstevel@tonic-gate }
713*7c478bd9Sstevel@tonic-gate
714*7c478bd9Sstevel@tonic-gate if (text->authid) { /* works for both client and server */
715*7c478bd9Sstevel@tonic-gate text->utils->free(text->authid);
716*7c478bd9Sstevel@tonic-gate text->authid = NULL;
717*7c478bd9Sstevel@tonic-gate }
718*7c478bd9Sstevel@tonic-gate }
719*7c478bd9Sstevel@tonic-gate
720*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
721*7c478bd9Sstevel@tonic-gate
722*7c478bd9Sstevel@tonic-gate #ifdef HAVE_RPC_GSS_MECH_TO_OID
723*7c478bd9Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
724*7c478bd9Sstevel@tonic-gate #endif /* HAVE_RPC_GSS_MECH_TO_OID */
725*7c478bd9Sstevel@tonic-gate
726*7c478bd9Sstevel@tonic-gate static int
727*7c478bd9Sstevel@tonic-gate get_oid(const sasl_utils_t *utils, gss_OID *oid)
728*7c478bd9Sstevel@tonic-gate {
729*7c478bd9Sstevel@tonic-gate #ifdef HAVE_RPC_GSS_MECH_TO_OID
730*7c478bd9Sstevel@tonic-gate static gss_OID_desc kerb_v5 =
731*7c478bd9Sstevel@tonic-gate {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
732*7c478bd9Sstevel@tonic-gate /* 1.2.840.113554.1.2.2 */
733*7c478bd9Sstevel@tonic-gate *oid = &kerb_v5;
734*7c478bd9Sstevel@tonic-gate #endif /* HAVE_RPC_GSS_MECH_TO_OID */
735*7c478bd9Sstevel@tonic-gate return (SASL_OK);
736*7c478bd9Sstevel@tonic-gate }
737*7c478bd9Sstevel@tonic-gate
738*7c478bd9Sstevel@tonic-gate static int
739*7c478bd9Sstevel@tonic-gate add_mech_to_set(context_t *text, gss_OID_set *desired_mechs)
740*7c478bd9Sstevel@tonic-gate {
741*7c478bd9Sstevel@tonic-gate OM_uint32 maj_stat, min_stat;
742*7c478bd9Sstevel@tonic-gate
743*7c478bd9Sstevel@tonic-gate maj_stat = gss_create_empty_oid_set(&min_stat, desired_mechs);
744*7c478bd9Sstevel@tonic-gate
745*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
746*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
747*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
748*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
749*7c478bd9Sstevel@tonic-gate }
750*7c478bd9Sstevel@tonic-gate
751*7c478bd9Sstevel@tonic-gate maj_stat = gss_add_oid_set_member(&min_stat, text->mech_oid, desired_mechs);
752*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
753*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
754*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
755*7c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min_stat, desired_mechs);
756*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
757*7c478bd9Sstevel@tonic-gate }
758*7c478bd9Sstevel@tonic-gate return SASL_OK;
759*7c478bd9Sstevel@tonic-gate }
760*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
761*7c478bd9Sstevel@tonic-gate
762*7c478bd9Sstevel@tonic-gate static void gssapi_common_mech_dispose(void *conn_context,
763*7c478bd9Sstevel@tonic-gate const sasl_utils_t *utils)
764*7c478bd9Sstevel@tonic-gate {
765*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
766*7c478bd9Sstevel@tonic-gate if (conn_context == NULL)
767*7c478bd9Sstevel@tonic-gate return;
768*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
769*7c478bd9Sstevel@tonic-gate convert_prompt(utils, &((context_t *)conn_context)->h, NULL);
770*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
771*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
772*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
773*7c478bd9Sstevel@tonic-gate (void) LOCK_MUTEX(&global_mutex);
774*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
775*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents((context_t *)(conn_context));
776*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
777*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
778*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
779*7c478bd9Sstevel@tonic-gate utils->free(conn_context);
780*7c478bd9Sstevel@tonic-gate }
781*7c478bd9Sstevel@tonic-gate
782*7c478bd9Sstevel@tonic-gate /***************************** Server Section *****************************/
783*7c478bd9Sstevel@tonic-gate
784*7c478bd9Sstevel@tonic-gate static int
785*7c478bd9Sstevel@tonic-gate gssapi_server_mech_new(void *glob_context __attribute__((unused)),
786*7c478bd9Sstevel@tonic-gate sasl_server_params_t *params,
787*7c478bd9Sstevel@tonic-gate const char *challenge __attribute__((unused)),
788*7c478bd9Sstevel@tonic-gate unsigned challen __attribute__((unused)),
789*7c478bd9Sstevel@tonic-gate void **conn_context)
790*7c478bd9Sstevel@tonic-gate {
791*7c478bd9Sstevel@tonic-gate context_t *text;
792*7c478bd9Sstevel@tonic-gate
793*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
794*7c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&global_mutex) < 0)
795*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
796*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
797*7c478bd9Sstevel@tonic-gate text = gss_new_context(params->utils);
798*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
799*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
800*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
801*7c478bd9Sstevel@tonic-gate if (text == NULL) {
802*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
803*7c478bd9Sstevel@tonic-gate MEMERROR(params->utils);
804*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
805*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
806*7c478bd9Sstevel@tonic-gate }
807*7c478bd9Sstevel@tonic-gate
808*7c478bd9Sstevel@tonic-gate text->gss_ctx = GSS_C_NO_CONTEXT;
809*7c478bd9Sstevel@tonic-gate text->client_name = GSS_C_NO_NAME;
810*7c478bd9Sstevel@tonic-gate text->server_name = GSS_C_NO_NAME;
811*7c478bd9Sstevel@tonic-gate text->server_creds = GSS_C_NO_CREDENTIAL;
812*7c478bd9Sstevel@tonic-gate text->state = SASL_GSSAPI_STATE_AUTHNEG;
813*7c478bd9Sstevel@tonic-gate
814*7c478bd9Sstevel@tonic-gate *conn_context = text;
815*7c478bd9Sstevel@tonic-gate
816*7c478bd9Sstevel@tonic-gate return SASL_OK;
817*7c478bd9Sstevel@tonic-gate }
818*7c478bd9Sstevel@tonic-gate
819*7c478bd9Sstevel@tonic-gate static int
820*7c478bd9Sstevel@tonic-gate gssapi_server_mech_step(void *conn_context,
821*7c478bd9Sstevel@tonic-gate sasl_server_params_t *params,
822*7c478bd9Sstevel@tonic-gate const char *clientin,
823*7c478bd9Sstevel@tonic-gate unsigned clientinlen,
824*7c478bd9Sstevel@tonic-gate const char **serverout,
825*7c478bd9Sstevel@tonic-gate unsigned *serveroutlen,
826*7c478bd9Sstevel@tonic-gate sasl_out_params_t *oparams)
827*7c478bd9Sstevel@tonic-gate {
828*7c478bd9Sstevel@tonic-gate context_t *text = (context_t *)conn_context;
829*7c478bd9Sstevel@tonic-gate gss_buffer_t input_token, output_token;
830*7c478bd9Sstevel@tonic-gate gss_buffer_desc real_input_token, real_output_token;
831*7c478bd9Sstevel@tonic-gate OM_uint32 maj_stat, min_stat;
832*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
833*7c478bd9Sstevel@tonic-gate OM_uint32 max_input_size;
834*7c478bd9Sstevel@tonic-gate gss_OID_set desired_mechs = GSS_C_NULL_OID_SET;
835*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
836*7c478bd9Sstevel@tonic-gate gss_buffer_desc name_token;
837*7c478bd9Sstevel@tonic-gate int ret;
838*7c478bd9Sstevel@tonic-gate
839*7c478bd9Sstevel@tonic-gate input_token = &real_input_token;
840*7c478bd9Sstevel@tonic-gate output_token = &real_output_token;
841*7c478bd9Sstevel@tonic-gate output_token->value = NULL; output_token->length = 0;
842*7c478bd9Sstevel@tonic-gate input_token->value = NULL; input_token->length = 0;
843*7c478bd9Sstevel@tonic-gate
844*7c478bd9Sstevel@tonic-gate if(!serverout) {
845*7c478bd9Sstevel@tonic-gate PARAMERROR(text->utils);
846*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM;
847*7c478bd9Sstevel@tonic-gate }
848*7c478bd9Sstevel@tonic-gate
849*7c478bd9Sstevel@tonic-gate *serverout = NULL;
850*7c478bd9Sstevel@tonic-gate *serveroutlen = 0;
851*7c478bd9Sstevel@tonic-gate
852*7c478bd9Sstevel@tonic-gate switch (text->state) {
853*7c478bd9Sstevel@tonic-gate
854*7c478bd9Sstevel@tonic-gate case SASL_GSSAPI_STATE_AUTHNEG:
855*7c478bd9Sstevel@tonic-gate if (text->server_name == GSS_C_NO_NAME) { /* only once */
856*7c478bd9Sstevel@tonic-gate name_token.length = strlen(params->service) + 1 + strlen(params->serverFQDN);
857*7c478bd9Sstevel@tonic-gate name_token.value = (char *)params->utils->malloc((name_token.length + 1) * sizeof(char));
858*7c478bd9Sstevel@tonic-gate if (name_token.value == NULL) {
859*7c478bd9Sstevel@tonic-gate MEMERROR(text->utils);
860*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
861*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
862*7c478bd9Sstevel@tonic-gate }
863*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
864*7c478bd9Sstevel@tonic-gate snprintf(name_token.value, name_token.length + 1,
865*7c478bd9Sstevel@tonic-gate "%s@%s", params->service, params->serverFQDN);
866*7c478bd9Sstevel@tonic-gate #else
867*7c478bd9Sstevel@tonic-gate sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
868*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
869*7c478bd9Sstevel@tonic-gate
870*7c478bd9Sstevel@tonic-gate maj_stat = gss_import_name (&min_stat,
871*7c478bd9Sstevel@tonic-gate &name_token,
872*7c478bd9Sstevel@tonic-gate GSS_C_NT_HOSTBASED_SERVICE,
873*7c478bd9Sstevel@tonic-gate &text->server_name);
874*7c478bd9Sstevel@tonic-gate
875*7c478bd9Sstevel@tonic-gate params->utils->free(name_token.value);
876*7c478bd9Sstevel@tonic-gate name_token.value = NULL;
877*7c478bd9Sstevel@tonic-gate
878*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
879*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
880*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
881*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
882*7c478bd9Sstevel@tonic-gate }
883*7c478bd9Sstevel@tonic-gate
884*7c478bd9Sstevel@tonic-gate if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
885*7c478bd9Sstevel@tonic-gate maj_stat = gss_release_cred(&min_stat, &text->server_creds);
886*7c478bd9Sstevel@tonic-gate text->server_creds = GSS_C_NO_CREDENTIAL;
887*7c478bd9Sstevel@tonic-gate }
888*7c478bd9Sstevel@tonic-gate
889*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
890*7c478bd9Sstevel@tonic-gate if (text->mech_oid != GSS_C_NULL_OID) {
891*7c478bd9Sstevel@tonic-gate ret = add_mech_to_set(text, &desired_mechs);
892*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK)
893*7c478bd9Sstevel@tonic-gate return (ret);
894*7c478bd9Sstevel@tonic-gate }
895*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
896*7c478bd9Sstevel@tonic-gate
897*7c478bd9Sstevel@tonic-gate maj_stat = gss_acquire_cred(&min_stat,
898*7c478bd9Sstevel@tonic-gate text->server_name,
899*7c478bd9Sstevel@tonic-gate GSS_C_INDEFINITE,
900*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
901*7c478bd9Sstevel@tonic-gate desired_mechs,
902*7c478bd9Sstevel@tonic-gate #else
903*7c478bd9Sstevel@tonic-gate GSS_C_NO_OID_SET,
904*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
905*7c478bd9Sstevel@tonic-gate GSS_C_ACCEPT,
906*7c478bd9Sstevel@tonic-gate &text->server_creds,
907*7c478bd9Sstevel@tonic-gate NULL,
908*7c478bd9Sstevel@tonic-gate NULL);
909*7c478bd9Sstevel@tonic-gate
910*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
911*7c478bd9Sstevel@tonic-gate if (desired_mechs != GSS_C_NULL_OID_SET) {
912*7c478bd9Sstevel@tonic-gate OM_uint32 min_stat2;
913*7c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min_stat2, &desired_mechs);
914*7c478bd9Sstevel@tonic-gate }
915*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
916*7c478bd9Sstevel@tonic-gate
917*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
918*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
919*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
920*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
921*7c478bd9Sstevel@tonic-gate }
922*7c478bd9Sstevel@tonic-gate }
923*7c478bd9Sstevel@tonic-gate
924*7c478bd9Sstevel@tonic-gate if (clientinlen) {
925*7c478bd9Sstevel@tonic-gate real_input_token.value = (void *)clientin;
926*7c478bd9Sstevel@tonic-gate real_input_token.length = clientinlen;
927*7c478bd9Sstevel@tonic-gate }
928*7c478bd9Sstevel@tonic-gate
929*7c478bd9Sstevel@tonic-gate maj_stat =
930*7c478bd9Sstevel@tonic-gate gss_accept_sec_context(&min_stat,
931*7c478bd9Sstevel@tonic-gate &(text->gss_ctx),
932*7c478bd9Sstevel@tonic-gate text->server_creds,
933*7c478bd9Sstevel@tonic-gate input_token,
934*7c478bd9Sstevel@tonic-gate GSS_C_NO_CHANNEL_BINDINGS,
935*7c478bd9Sstevel@tonic-gate &text->client_name,
936*7c478bd9Sstevel@tonic-gate NULL,
937*7c478bd9Sstevel@tonic-gate output_token,
938*7c478bd9Sstevel@tonic-gate NULL,
939*7c478bd9Sstevel@tonic-gate NULL,
940*7c478bd9Sstevel@tonic-gate NULL);
941*7c478bd9Sstevel@tonic-gate
942*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
943*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
944*7c478bd9Sstevel@tonic-gate /* log the local error info, set a more generic error */
945*7c478bd9Sstevel@tonic-gate sasl_gss_log(text->utils, maj_stat, min_stat);
946*7c478bd9Sstevel@tonic-gate text->utils->seterror(text->utils->conn, SASL_NOLOG,
947*7c478bd9Sstevel@tonic-gate gettext("GSSAPI Failure: accept security context error"));
948*7c478bd9Sstevel@tonic-gate if (output_token->value) {
949*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
950*7c478bd9Sstevel@tonic-gate }
951*7c478bd9Sstevel@tonic-gate #else
952*7c478bd9Sstevel@tonic-gate if (output_token->value) {
953*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
954*7c478bd9Sstevel@tonic-gate }
955*7c478bd9Sstevel@tonic-gate text->utils->seterror(text->utils->conn, SASL_NOLOG, "GSSAPI Failure: gss_accept_sec_context");
956*7c478bd9Sstevel@tonic-gate text->utils->log(NULL, SASL_LOG_DEBUG, "GSSAPI Failure: gss_accept_sec_context");
957*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
958*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
959*7c478bd9Sstevel@tonic-gate return SASL_BADAUTH;
960*7c478bd9Sstevel@tonic-gate }
961*7c478bd9Sstevel@tonic-gate
962*7c478bd9Sstevel@tonic-gate if (serveroutlen)
963*7c478bd9Sstevel@tonic-gate *serveroutlen = output_token->length;
964*7c478bd9Sstevel@tonic-gate if (output_token->value) {
965*7c478bd9Sstevel@tonic-gate if (serverout) {
966*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(text->utils, &(text->out_buf),
967*7c478bd9Sstevel@tonic-gate &(text->out_buf_len), *serveroutlen);
968*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) {
969*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
970*7c478bd9Sstevel@tonic-gate return ret;
971*7c478bd9Sstevel@tonic-gate }
972*7c478bd9Sstevel@tonic-gate memcpy(text->out_buf, output_token->value, *serveroutlen);
973*7c478bd9Sstevel@tonic-gate *serverout = text->out_buf;
974*7c478bd9Sstevel@tonic-gate }
975*7c478bd9Sstevel@tonic-gate
976*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
977*7c478bd9Sstevel@tonic-gate } else {
978*7c478bd9Sstevel@tonic-gate /* No output token, send an empty string */
979*7c478bd9Sstevel@tonic-gate *serverout = GSSAPI_BLANK_STRING;
980*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
981*7c478bd9Sstevel@tonic-gate serveroutlen = 0;
982*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
983*7c478bd9Sstevel@tonic-gate }
984*7c478bd9Sstevel@tonic-gate
985*7c478bd9Sstevel@tonic-gate
986*7c478bd9Sstevel@tonic-gate if (maj_stat == GSS_S_COMPLETE) {
987*7c478bd9Sstevel@tonic-gate /* Switch to ssf negotiation */
988*7c478bd9Sstevel@tonic-gate text->state = SASL_GSSAPI_STATE_SSFCAP;
989*7c478bd9Sstevel@tonic-gate }
990*7c478bd9Sstevel@tonic-gate
991*7c478bd9Sstevel@tonic-gate return SASL_CONTINUE;
992*7c478bd9Sstevel@tonic-gate
993*7c478bd9Sstevel@tonic-gate case SASL_GSSAPI_STATE_SSFCAP: {
994*7c478bd9Sstevel@tonic-gate unsigned char sasldata[4];
995*7c478bd9Sstevel@tonic-gate gss_buffer_desc name_token;
996*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
997*7c478bd9Sstevel@tonic-gate gss_buffer_desc name_without_realm;
998*7c478bd9Sstevel@tonic-gate gss_name_t without = NULL;
999*7c478bd9Sstevel@tonic-gate int equal;
1000*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1001*7c478bd9Sstevel@tonic-gate
1002*7c478bd9Sstevel@tonic-gate name_token.value = NULL;
1003*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1004*7c478bd9Sstevel@tonic-gate name_without_realm.value = NULL;
1005*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1006*7c478bd9Sstevel@tonic-gate
1007*7c478bd9Sstevel@tonic-gate /* We ignore whatever the client sent us at this stage */
1008*7c478bd9Sstevel@tonic-gate
1009*7c478bd9Sstevel@tonic-gate maj_stat = gss_display_name (&min_stat,
1010*7c478bd9Sstevel@tonic-gate text->client_name,
1011*7c478bd9Sstevel@tonic-gate &name_token,
1012*7c478bd9Sstevel@tonic-gate NULL);
1013*7c478bd9Sstevel@tonic-gate
1014*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1015*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1016*7c478bd9Sstevel@tonic-gate if (name_without_realm.value)
1017*7c478bd9Sstevel@tonic-gate params->utils->free(name_without_realm.value);
1018*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1019*7c478bd9Sstevel@tonic-gate
1020*7c478bd9Sstevel@tonic-gate if (name_token.value)
1021*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, &name_token);
1022*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1023*7c478bd9Sstevel@tonic-gate if (without)
1024*7c478bd9Sstevel@tonic-gate gss_release_name(&min_stat, &without);
1025*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1026*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1027*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, gettext("GSSAPI Failure"));
1028*7c478bd9Sstevel@tonic-gate #else
1029*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, "GSSAPI Failure");
1030*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1031*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1032*7c478bd9Sstevel@tonic-gate return SASL_BADAUTH;
1033*7c478bd9Sstevel@tonic-gate }
1034*7c478bd9Sstevel@tonic-gate
1035*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1036*7c478bd9Sstevel@tonic-gate /* If the id contains a realm get the identifier for the user
1037*7c478bd9Sstevel@tonic-gate without the realm and see if it's the same id (i.e.
1038*7c478bd9Sstevel@tonic-gate tmartin == tmartin@ANDREW.CMU.EDU. If this is the case we just want
1039*7c478bd9Sstevel@tonic-gate to return the id (i.e. just "tmartin" */
1040*7c478bd9Sstevel@tonic-gate if (strchr((char *) name_token.value, (int) '@') != NULL) {
1041*7c478bd9Sstevel@tonic-gate /* NOTE: libc malloc, as it is freed below by a gssapi internal
1042*7c478bd9Sstevel@tonic-gate * function! */
1043*7c478bd9Sstevel@tonic-gate name_without_realm.value = malloc(strlen(name_token.value)+1);
1044*7c478bd9Sstevel@tonic-gate if (name_without_realm.value == NULL) {
1045*7c478bd9Sstevel@tonic-gate MEMERROR(text->utils);
1046*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
1047*7c478bd9Sstevel@tonic-gate }
1048*7c478bd9Sstevel@tonic-gate
1049*7c478bd9Sstevel@tonic-gate strcpy(name_without_realm.value, name_token.value);
1050*7c478bd9Sstevel@tonic-gate
1051*7c478bd9Sstevel@tonic-gate /* cut off string at '@' */
1052*7c478bd9Sstevel@tonic-gate (strchr(name_without_realm.value,'@'))[0] = '\0';
1053*7c478bd9Sstevel@tonic-gate
1054*7c478bd9Sstevel@tonic-gate name_without_realm.length = strlen( (char *) name_without_realm.value );
1055*7c478bd9Sstevel@tonic-gate
1056*7c478bd9Sstevel@tonic-gate maj_stat = gss_import_name (&min_stat,
1057*7c478bd9Sstevel@tonic-gate &name_without_realm,
1058*7c478bd9Sstevel@tonic-gate /* Solaris 8/9 gss_import_name doesn't accept GSS_C_NULL_OID here,
1059*7c478bd9Sstevel@tonic-gate so use GSS_C_NT_USER_NAME instead if available. */
1060*7c478bd9Sstevel@tonic-gate #ifdef HAVE_GSS_C_NT_USER_NAME
1061*7c478bd9Sstevel@tonic-gate GSS_C_NT_USER_NAME,
1062*7c478bd9Sstevel@tonic-gate #else
1063*7c478bd9Sstevel@tonic-gate GSS_C_NULL_OID,
1064*7c478bd9Sstevel@tonic-gate #endif
1065*7c478bd9Sstevel@tonic-gate &without);
1066*7c478bd9Sstevel@tonic-gate
1067*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1068*7c478bd9Sstevel@tonic-gate params->utils->free(name_without_realm.value);
1069*7c478bd9Sstevel@tonic-gate if (name_token.value)
1070*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, &name_token);
1071*7c478bd9Sstevel@tonic-gate if (without)
1072*7c478bd9Sstevel@tonic-gate gss_release_name(&min_stat, &without);
1073*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, "GSSAPI Failure");
1074*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1075*7c478bd9Sstevel@tonic-gate return SASL_BADAUTH;
1076*7c478bd9Sstevel@tonic-gate }
1077*7c478bd9Sstevel@tonic-gate
1078*7c478bd9Sstevel@tonic-gate maj_stat = gss_compare_name(&min_stat,
1079*7c478bd9Sstevel@tonic-gate text->client_name,
1080*7c478bd9Sstevel@tonic-gate without,
1081*7c478bd9Sstevel@tonic-gate &equal);
1082*7c478bd9Sstevel@tonic-gate
1083*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1084*7c478bd9Sstevel@tonic-gate params->utils->free(name_without_realm.value);
1085*7c478bd9Sstevel@tonic-gate if (name_token.value)
1086*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, &name_token);
1087*7c478bd9Sstevel@tonic-gate if (without)
1088*7c478bd9Sstevel@tonic-gate gss_release_name(&min_stat, &without);
1089*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, "GSSAPI Failure");
1090*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1091*7c478bd9Sstevel@tonic-gate return SASL_BADAUTH;
1092*7c478bd9Sstevel@tonic-gate }
1093*7c478bd9Sstevel@tonic-gate
1094*7c478bd9Sstevel@tonic-gate gss_release_name(&min_stat,&without);
1095*7c478bd9Sstevel@tonic-gate } else {
1096*7c478bd9Sstevel@tonic-gate equal = 0;
1097*7c478bd9Sstevel@tonic-gate }
1098*7c478bd9Sstevel@tonic-gate
1099*7c478bd9Sstevel@tonic-gate if (equal) {
1100*7c478bd9Sstevel@tonic-gate text->authid = strdup(name_without_realm.value);
1101*7c478bd9Sstevel@tonic-gate
1102*7c478bd9Sstevel@tonic-gate if (text->authid == NULL) {
1103*7c478bd9Sstevel@tonic-gate MEMERROR(params->utils);
1104*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
1105*7c478bd9Sstevel@tonic-gate }
1106*7c478bd9Sstevel@tonic-gate } else {
1107*7c478bd9Sstevel@tonic-gate text->authid = strdup(name_token.value);
1108*7c478bd9Sstevel@tonic-gate
1109*7c478bd9Sstevel@tonic-gate if (text->authid == NULL) {
1110*7c478bd9Sstevel@tonic-gate MEMERROR(params->utils);
1111*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
1112*7c478bd9Sstevel@tonic-gate }
1113*7c478bd9Sstevel@tonic-gate }
1114*7c478bd9Sstevel@tonic-gate #else
1115*7c478bd9Sstevel@tonic-gate {
1116*7c478bd9Sstevel@tonic-gate ret = _plug_strdup(params->utils, name_token.value,
1117*7c478bd9Sstevel@tonic-gate &text->authid, NULL);
1118*7c478bd9Sstevel@tonic-gate }
1119*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1120*7c478bd9Sstevel@tonic-gate
1121*7c478bd9Sstevel@tonic-gate if (name_token.value)
1122*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, &name_token);
1123*7c478bd9Sstevel@tonic-gate
1124*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1125*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK)
1126*7c478bd9Sstevel@tonic-gate return (ret);
1127*7c478bd9Sstevel@tonic-gate #else
1128*7c478bd9Sstevel@tonic-gate if (name_without_realm.value)
1129*7c478bd9Sstevel@tonic-gate params->utils->free(name_without_realm.value);
1130*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1131*7c478bd9Sstevel@tonic-gate
1132*7c478bd9Sstevel@tonic-gate
1133*7c478bd9Sstevel@tonic-gate /* we have to decide what sort of encryption/integrity/etc.,
1134*7c478bd9Sstevel@tonic-gate we support */
1135*7c478bd9Sstevel@tonic-gate if (params->props.max_ssf < params->external_ssf) {
1136*7c478bd9Sstevel@tonic-gate text->limitssf = 0;
1137*7c478bd9Sstevel@tonic-gate } else {
1138*7c478bd9Sstevel@tonic-gate text->limitssf = params->props.max_ssf - params->external_ssf;
1139*7c478bd9Sstevel@tonic-gate }
1140*7c478bd9Sstevel@tonic-gate if (params->props.min_ssf < params->external_ssf) {
1141*7c478bd9Sstevel@tonic-gate text->requiressf = 0;
1142*7c478bd9Sstevel@tonic-gate } else {
1143*7c478bd9Sstevel@tonic-gate text->requiressf = params->props.min_ssf - params->external_ssf;
1144*7c478bd9Sstevel@tonic-gate }
1145*7c478bd9Sstevel@tonic-gate
1146*7c478bd9Sstevel@tonic-gate /* build up our security properties token */
1147*7c478bd9Sstevel@tonic-gate if (params->props.maxbufsize > 0xFFFFFF) {
1148*7c478bd9Sstevel@tonic-gate /* make sure maxbufsize isn't too large */
1149*7c478bd9Sstevel@tonic-gate /* maxbufsize = 0xFFFFFF */
1150*7c478bd9Sstevel@tonic-gate sasldata[1] = sasldata[2] = sasldata[3] = 0xFF;
1151*7c478bd9Sstevel@tonic-gate } else {
1152*7c478bd9Sstevel@tonic-gate sasldata[1] = (params->props.maxbufsize >> 16) & 0xFF;
1153*7c478bd9Sstevel@tonic-gate sasldata[2] = (params->props.maxbufsize >> 8) & 0xFF;
1154*7c478bd9Sstevel@tonic-gate sasldata[3] = (params->props.maxbufsize >> 0) & 0xFF;
1155*7c478bd9Sstevel@tonic-gate }
1156*7c478bd9Sstevel@tonic-gate sasldata[0] = 0;
1157*7c478bd9Sstevel@tonic-gate if(text->requiressf != 0 && !params->props.maxbufsize) {
1158*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1159*7c478bd9Sstevel@tonic-gate params->utils->log(params->utils->conn, SASL_LOG_ERR,
1160*7c478bd9Sstevel@tonic-gate "GSSAPI needs a security layer but one is forbidden");
1161*7c478bd9Sstevel@tonic-gate #else
1162*7c478bd9Sstevel@tonic-gate params->utils->seterror(params->utils->conn, 0,
1163*7c478bd9Sstevel@tonic-gate "GSSAPI needs a security layer but one is forbidden");
1164*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1165*7c478bd9Sstevel@tonic-gate return SASL_TOOWEAK;
1166*7c478bd9Sstevel@tonic-gate }
1167*7c478bd9Sstevel@tonic-gate
1168*7c478bd9Sstevel@tonic-gate if (text->requiressf == 0) {
1169*7c478bd9Sstevel@tonic-gate sasldata[0] |= 1; /* authentication */
1170*7c478bd9Sstevel@tonic-gate }
1171*7c478bd9Sstevel@tonic-gate if (text->requiressf <= 1 && text->limitssf >= 1
1172*7c478bd9Sstevel@tonic-gate && params->props.maxbufsize) {
1173*7c478bd9Sstevel@tonic-gate sasldata[0] |= 2;
1174*7c478bd9Sstevel@tonic-gate }
1175*7c478bd9Sstevel@tonic-gate if (text->requiressf <= 56 && text->limitssf >= 56
1176*7c478bd9Sstevel@tonic-gate && params->props.maxbufsize) {
1177*7c478bd9Sstevel@tonic-gate sasldata[0] |= 4;
1178*7c478bd9Sstevel@tonic-gate }
1179*7c478bd9Sstevel@tonic-gate
1180*7c478bd9Sstevel@tonic-gate real_input_token.value = (void *)sasldata;
1181*7c478bd9Sstevel@tonic-gate real_input_token.length = 4;
1182*7c478bd9Sstevel@tonic-gate
1183*7c478bd9Sstevel@tonic-gate maj_stat = gss_wrap(&min_stat,
1184*7c478bd9Sstevel@tonic-gate text->gss_ctx,
1185*7c478bd9Sstevel@tonic-gate 0, /* Just integrity checking here */
1186*7c478bd9Sstevel@tonic-gate GSS_C_QOP_DEFAULT,
1187*7c478bd9Sstevel@tonic-gate input_token,
1188*7c478bd9Sstevel@tonic-gate NULL,
1189*7c478bd9Sstevel@tonic-gate output_token);
1190*7c478bd9Sstevel@tonic-gate
1191*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1192*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1193*7c478bd9Sstevel@tonic-gate if (output_token->value)
1194*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1195*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1196*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1197*7c478bd9Sstevel@tonic-gate }
1198*7c478bd9Sstevel@tonic-gate
1199*7c478bd9Sstevel@tonic-gate
1200*7c478bd9Sstevel@tonic-gate if (serveroutlen)
1201*7c478bd9Sstevel@tonic-gate *serveroutlen = output_token->length;
1202*7c478bd9Sstevel@tonic-gate if (output_token->value) {
1203*7c478bd9Sstevel@tonic-gate if (serverout) {
1204*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(text->utils, &(text->out_buf),
1205*7c478bd9Sstevel@tonic-gate &(text->out_buf_len), *serveroutlen);
1206*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) {
1207*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1208*7c478bd9Sstevel@tonic-gate return ret;
1209*7c478bd9Sstevel@tonic-gate }
1210*7c478bd9Sstevel@tonic-gate memcpy(text->out_buf, output_token->value, *serveroutlen);
1211*7c478bd9Sstevel@tonic-gate *serverout = text->out_buf;
1212*7c478bd9Sstevel@tonic-gate }
1213*7c478bd9Sstevel@tonic-gate
1214*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1215*7c478bd9Sstevel@tonic-gate }
1216*7c478bd9Sstevel@tonic-gate
1217*7c478bd9Sstevel@tonic-gate /* Wait for ssf request and authid */
1218*7c478bd9Sstevel@tonic-gate text->state = SASL_GSSAPI_STATE_SSFREQ;
1219*7c478bd9Sstevel@tonic-gate
1220*7c478bd9Sstevel@tonic-gate return SASL_CONTINUE;
1221*7c478bd9Sstevel@tonic-gate }
1222*7c478bd9Sstevel@tonic-gate
1223*7c478bd9Sstevel@tonic-gate case SASL_GSSAPI_STATE_SSFREQ: {
1224*7c478bd9Sstevel@tonic-gate int layerchoice;
1225*7c478bd9Sstevel@tonic-gate
1226*7c478bd9Sstevel@tonic-gate real_input_token.value = (void *)clientin;
1227*7c478bd9Sstevel@tonic-gate real_input_token.length = clientinlen;
1228*7c478bd9Sstevel@tonic-gate
1229*7c478bd9Sstevel@tonic-gate maj_stat = gss_unwrap(&min_stat,
1230*7c478bd9Sstevel@tonic-gate text->gss_ctx,
1231*7c478bd9Sstevel@tonic-gate input_token,
1232*7c478bd9Sstevel@tonic-gate output_token,
1233*7c478bd9Sstevel@tonic-gate NULL,
1234*7c478bd9Sstevel@tonic-gate NULL);
1235*7c478bd9Sstevel@tonic-gate
1236*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1237*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1238*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1239*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1240*7c478bd9Sstevel@tonic-gate }
1241*7c478bd9Sstevel@tonic-gate
1242*7c478bd9Sstevel@tonic-gate layerchoice = (int)(((char *)(output_token->value))[0]);
1243*7c478bd9Sstevel@tonic-gate if (layerchoice == 1 && text->requiressf == 0) { /* no encryption */
1244*7c478bd9Sstevel@tonic-gate oparams->encode = NULL;
1245*7c478bd9Sstevel@tonic-gate oparams->decode = NULL;
1246*7c478bd9Sstevel@tonic-gate oparams->mech_ssf = 0;
1247*7c478bd9Sstevel@tonic-gate } else if (layerchoice == 2 && text->requiressf <= 1 &&
1248*7c478bd9Sstevel@tonic-gate text->limitssf >= 1) { /* integrity */
1249*7c478bd9Sstevel@tonic-gate oparams->encode=&gssapi_integrity_encode;
1250*7c478bd9Sstevel@tonic-gate oparams->decode=&gssapi_decode;
1251*7c478bd9Sstevel@tonic-gate oparams->mech_ssf=1;
1252*7c478bd9Sstevel@tonic-gate } else if (layerchoice == 4 && text->requiressf <= 56 &&
1253*7c478bd9Sstevel@tonic-gate text->limitssf >= 56) { /* privacy */
1254*7c478bd9Sstevel@tonic-gate oparams->encode = &gssapi_privacy_encode;
1255*7c478bd9Sstevel@tonic-gate oparams->decode = &gssapi_decode;
1256*7c478bd9Sstevel@tonic-gate oparams->mech_ssf = 56;
1257*7c478bd9Sstevel@tonic-gate } else {
1258*7c478bd9Sstevel@tonic-gate /* not a supported encryption layer */
1259*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1260*7c478bd9Sstevel@tonic-gate text->utils->log(text->utils->conn, SASL_LOG_ERR,
1261*7c478bd9Sstevel@tonic-gate "protocol violation: client requested invalid layer");
1262*7c478bd9Sstevel@tonic-gate #else
1263*7c478bd9Sstevel@tonic-gate SETERROR(text->utils,
1264*7c478bd9Sstevel@tonic-gate "protocol violation: client requested invalid layer");
1265*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1266*7c478bd9Sstevel@tonic-gate /* Mark that we attempted negotiation */
1267*7c478bd9Sstevel@tonic-gate oparams->mech_ssf = 2;
1268*7c478bd9Sstevel@tonic-gate if (output_token->value)
1269*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1270*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1271*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1272*7c478bd9Sstevel@tonic-gate }
1273*7c478bd9Sstevel@tonic-gate
1274*7c478bd9Sstevel@tonic-gate if (output_token->length > 4) {
1275*7c478bd9Sstevel@tonic-gate int ret;
1276*7c478bd9Sstevel@tonic-gate
1277*7c478bd9Sstevel@tonic-gate ret = params->canon_user(params->utils->conn,
1278*7c478bd9Sstevel@tonic-gate ((char *) output_token->value) + 4,
1279*7c478bd9Sstevel@tonic-gate (output_token->length - 4) * sizeof(char),
1280*7c478bd9Sstevel@tonic-gate SASL_CU_AUTHZID, oparams);
1281*7c478bd9Sstevel@tonic-gate
1282*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) {
1283*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1284*7c478bd9Sstevel@tonic-gate return ret;
1285*7c478bd9Sstevel@tonic-gate }
1286*7c478bd9Sstevel@tonic-gate
1287*7c478bd9Sstevel@tonic-gate ret = params->canon_user(params->utils->conn,
1288*7c478bd9Sstevel@tonic-gate text->authid,
1289*7c478bd9Sstevel@tonic-gate 0, /* strlen(text->authid) */
1290*7c478bd9Sstevel@tonic-gate SASL_CU_AUTHID, oparams);
1291*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) {
1292*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1293*7c478bd9Sstevel@tonic-gate return ret;
1294*7c478bd9Sstevel@tonic-gate }
1295*7c478bd9Sstevel@tonic-gate } else if(output_token->length == 4) {
1296*7c478bd9Sstevel@tonic-gate /* null authzid */
1297*7c478bd9Sstevel@tonic-gate int ret;
1298*7c478bd9Sstevel@tonic-gate
1299*7c478bd9Sstevel@tonic-gate ret = params->canon_user(params->utils->conn,
1300*7c478bd9Sstevel@tonic-gate text->authid,
1301*7c478bd9Sstevel@tonic-gate 0, /* strlen(text->authid) */
1302*7c478bd9Sstevel@tonic-gate SASL_CU_AUTHZID | SASL_CU_AUTHID,
1303*7c478bd9Sstevel@tonic-gate oparams);
1304*7c478bd9Sstevel@tonic-gate
1305*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) {
1306*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1307*7c478bd9Sstevel@tonic-gate return ret;
1308*7c478bd9Sstevel@tonic-gate }
1309*7c478bd9Sstevel@tonic-gate } else {
1310*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1311*7c478bd9Sstevel@tonic-gate text->utils->log(text->utils->conn, SASL_LOG_ERR,
1312*7c478bd9Sstevel@tonic-gate "token too short");
1313*7c478bd9Sstevel@tonic-gate #else
1314*7c478bd9Sstevel@tonic-gate SETERROR(text->utils,
1315*7c478bd9Sstevel@tonic-gate "token too short");
1316*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1317*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1318*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1319*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1320*7c478bd9Sstevel@tonic-gate }
1321*7c478bd9Sstevel@tonic-gate
1322*7c478bd9Sstevel@tonic-gate /* No matter what, set the rest of the oparams */
1323*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf =
1324*7c478bd9Sstevel@tonic-gate (((unsigned char *) output_token->value)[1] << 16) |
1325*7c478bd9Sstevel@tonic-gate (((unsigned char *) output_token->value)[2] << 8) |
1326*7c478bd9Sstevel@tonic-gate (((unsigned char *) output_token->value)[3] << 0);
1327*7c478bd9Sstevel@tonic-gate
1328*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1329*7c478bd9Sstevel@tonic-gate if (oparams->mech_ssf) {
1330*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf -= 4; /* Allow for 4 byte tag */
1331*7c478bd9Sstevel@tonic-gate maj_stat = gss_wrap_size_limit(&min_stat,
1332*7c478bd9Sstevel@tonic-gate text->gss_ctx,
1333*7c478bd9Sstevel@tonic-gate oparams->mech_ssf > 1,
1334*7c478bd9Sstevel@tonic-gate GSS_C_QOP_DEFAULT,
1335*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf,
1336*7c478bd9Sstevel@tonic-gate &max_input_size);
1337*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1338*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1339*7c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&min_stat, output_token);
1340*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1341*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
1342*7c478bd9Sstevel@tonic-gate }
1343*7c478bd9Sstevel@tonic-gate
1344*7c478bd9Sstevel@tonic-gate /*
1345*7c478bd9Sstevel@tonic-gate * gss_wrap_size_limit will return very big sizes for
1346*7c478bd9Sstevel@tonic-gate * small input values
1347*7c478bd9Sstevel@tonic-gate */
1348*7c478bd9Sstevel@tonic-gate if (max_input_size < oparams->maxoutbuf)
1349*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf = max_input_size;
1350*7c478bd9Sstevel@tonic-gate else {
1351*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf = 0;
1352*7c478bd9Sstevel@tonic-gate }
1353*7c478bd9Sstevel@tonic-gate }
1354*7c478bd9Sstevel@tonic-gate #else
1355*7c478bd9Sstevel@tonic-gate if (oparams->mech_ssf) {
1356*7c478bd9Sstevel@tonic-gate /* xxx this is probably too big */
1357*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf -= 50;
1358*7c478bd9Sstevel@tonic-gate }
1359*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1360*7c478bd9Sstevel@tonic-gate
1361*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1362*7c478bd9Sstevel@tonic-gate
1363*7c478bd9Sstevel@tonic-gate text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
1364*7c478bd9Sstevel@tonic-gate
1365*7c478bd9Sstevel@tonic-gate oparams->doneflag = 1;
1366*7c478bd9Sstevel@tonic-gate
1367*7c478bd9Sstevel@tonic-gate return SASL_OK;
1368*7c478bd9Sstevel@tonic-gate }
1369*7c478bd9Sstevel@tonic-gate
1370*7c478bd9Sstevel@tonic-gate default:
1371*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1372*7c478bd9Sstevel@tonic-gate params->utils->log(text->utils->conn, SASL_LOG_ERR,
1373*7c478bd9Sstevel@tonic-gate "Invalid GSSAPI server step %d", text->state);
1374*7c478bd9Sstevel@tonic-gate #else
1375*7c478bd9Sstevel@tonic-gate params->utils->log(NULL, SASL_LOG_ERR,
1376*7c478bd9Sstevel@tonic-gate "Invalid GSSAPI server step %d\n", text->state);
1377*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1378*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1379*7c478bd9Sstevel@tonic-gate }
1380*7c478bd9Sstevel@tonic-gate
1381*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1382*7c478bd9Sstevel@tonic-gate return SASL_FAIL; /* should never get here */
1383*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1384*7c478bd9Sstevel@tonic-gate }
1385*7c478bd9Sstevel@tonic-gate
1386*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
1387*7c478bd9Sstevel@tonic-gate static int
1388*7c478bd9Sstevel@tonic-gate _gssapi_server_mech_step(void *conn_context,
1389*7c478bd9Sstevel@tonic-gate sasl_server_params_t *params,
1390*7c478bd9Sstevel@tonic-gate const char *clientin,
1391*7c478bd9Sstevel@tonic-gate unsigned clientinlen,
1392*7c478bd9Sstevel@tonic-gate const char **serverout,
1393*7c478bd9Sstevel@tonic-gate unsigned *serveroutlen,
1394*7c478bd9Sstevel@tonic-gate sasl_out_params_t *oparams)
1395*7c478bd9Sstevel@tonic-gate {
1396*7c478bd9Sstevel@tonic-gate int ret;
1397*7c478bd9Sstevel@tonic-gate
1398*7c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&global_mutex) < 0)
1399*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
1400*7c478bd9Sstevel@tonic-gate
1401*7c478bd9Sstevel@tonic-gate ret = gssapi_server_mech_step(conn_context, params, clientin, clientinlen,
1402*7c478bd9Sstevel@tonic-gate serverout, serveroutlen, oparams);
1403*7c478bd9Sstevel@tonic-gate
1404*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
1405*7c478bd9Sstevel@tonic-gate return (ret);
1406*7c478bd9Sstevel@tonic-gate }
1407*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
1408*7c478bd9Sstevel@tonic-gate
1409*7c478bd9Sstevel@tonic-gate static sasl_server_plug_t gssapi_server_plugins[] =
1410*7c478bd9Sstevel@tonic-gate {
1411*7c478bd9Sstevel@tonic-gate {
1412*7c478bd9Sstevel@tonic-gate "GSSAPI", /* mech_name */
1413*7c478bd9Sstevel@tonic-gate 56, /* max_ssf */
1414*7c478bd9Sstevel@tonic-gate SASL_SEC_NOPLAINTEXT
1415*7c478bd9Sstevel@tonic-gate | SASL_SEC_NOACTIVE
1416*7c478bd9Sstevel@tonic-gate | SASL_SEC_NOANONYMOUS
1417*7c478bd9Sstevel@tonic-gate | SASL_SEC_MUTUAL_AUTH, /* security_flags */
1418*7c478bd9Sstevel@tonic-gate SASL_FEAT_WANT_CLIENT_FIRST
1419*7c478bd9Sstevel@tonic-gate | SASL_FEAT_ALLOWS_PROXY, /* features */
1420*7c478bd9Sstevel@tonic-gate NULL, /* glob_context */
1421*7c478bd9Sstevel@tonic-gate &gssapi_server_mech_new, /* mech_new */
1422*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
1423*7c478bd9Sstevel@tonic-gate &_gssapi_server_mech_step, /* mech_step */
1424*7c478bd9Sstevel@tonic-gate #else
1425*7c478bd9Sstevel@tonic-gate &gssapi_server_mech_step, /* mech_step */
1426*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
1427*7c478bd9Sstevel@tonic-gate &gssapi_common_mech_dispose, /* mech_dispose */
1428*7c478bd9Sstevel@tonic-gate NULL, /* mech_free */
1429*7c478bd9Sstevel@tonic-gate NULL, /* setpass */
1430*7c478bd9Sstevel@tonic-gate NULL, /* user_query */
1431*7c478bd9Sstevel@tonic-gate NULL, /* idle */
1432*7c478bd9Sstevel@tonic-gate NULL, /* mech_avail */
1433*7c478bd9Sstevel@tonic-gate NULL /* spare */
1434*7c478bd9Sstevel@tonic-gate }
1435*7c478bd9Sstevel@tonic-gate };
1436*7c478bd9Sstevel@tonic-gate
1437*7c478bd9Sstevel@tonic-gate int gssapiv2_server_plug_init(
1438*7c478bd9Sstevel@tonic-gate #ifndef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
1439*7c478bd9Sstevel@tonic-gate const sasl_utils_t *utils __attribute__((unused)),
1440*7c478bd9Sstevel@tonic-gate #else
1441*7c478bd9Sstevel@tonic-gate const sasl_utils_t *utils,
1442*7c478bd9Sstevel@tonic-gate #endif
1443*7c478bd9Sstevel@tonic-gate int maxversion,
1444*7c478bd9Sstevel@tonic-gate int *out_version,
1445*7c478bd9Sstevel@tonic-gate sasl_server_plug_t **pluglist,
1446*7c478bd9Sstevel@tonic-gate int *plugcount)
1447*7c478bd9Sstevel@tonic-gate {
1448*7c478bd9Sstevel@tonic-gate #ifdef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
1449*7c478bd9Sstevel@tonic-gate const char *keytab = NULL;
1450*7c478bd9Sstevel@tonic-gate char keytab_path[1024];
1451*7c478bd9Sstevel@tonic-gate unsigned int rl;
1452*7c478bd9Sstevel@tonic-gate #endif
1453*7c478bd9Sstevel@tonic-gate
1454*7c478bd9Sstevel@tonic-gate if (maxversion < SASL_SERVER_PLUG_VERSION) {
1455*7c478bd9Sstevel@tonic-gate return SASL_BADVERS;
1456*7c478bd9Sstevel@tonic-gate }
1457*7c478bd9Sstevel@tonic-gate
1458*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1459*7c478bd9Sstevel@tonic-gate #ifdef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
1460*7c478bd9Sstevel@tonic-gate /* unfortunately, we don't check for readability of keytab if it's
1461*7c478bd9Sstevel@tonic-gate the standard one, since we don't know where it is */
1462*7c478bd9Sstevel@tonic-gate
1463*7c478bd9Sstevel@tonic-gate /* FIXME: This code is broken */
1464*7c478bd9Sstevel@tonic-gate
1465*7c478bd9Sstevel@tonic-gate utils->getopt(utils->getopt_context, "GSSAPI", "keytab", &keytab, &rl);
1466*7c478bd9Sstevel@tonic-gate if (keytab != NULL) {
1467*7c478bd9Sstevel@tonic-gate if (access(keytab, R_OK) != 0) {
1468*7c478bd9Sstevel@tonic-gate utils->log(NULL, SASL_LOG_ERR,
1469*7c478bd9Sstevel@tonic-gate "Could not find keytab file: %s: %m",
1470*7c478bd9Sstevel@tonic-gate keytab, errno);
1471*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1472*7c478bd9Sstevel@tonic-gate }
1473*7c478bd9Sstevel@tonic-gate
1474*7c478bd9Sstevel@tonic-gate if(strlen(keytab) > 1024) {
1475*7c478bd9Sstevel@tonic-gate utils->log(NULL, SASL_LOG_ERR,
1476*7c478bd9Sstevel@tonic-gate "path to keytab is > 1024 characters");
1477*7c478bd9Sstevel@tonic-gate return SASL_BUFOVER;
1478*7c478bd9Sstevel@tonic-gate }
1479*7c478bd9Sstevel@tonic-gate
1480*7c478bd9Sstevel@tonic-gate strncpy(keytab_path, keytab, 1024);
1481*7c478bd9Sstevel@tonic-gate
1482*7c478bd9Sstevel@tonic-gate gsskrb5_register_acceptor_identity(keytab_path);
1483*7c478bd9Sstevel@tonic-gate }
1484*7c478bd9Sstevel@tonic-gate #endif
1485*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1486*7c478bd9Sstevel@tonic-gate
1487*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1488*7c478bd9Sstevel@tonic-gate /*
1489*7c478bd9Sstevel@tonic-gate * Let libsasl know that we are a "Sun" plugin so that privacy
1490*7c478bd9Sstevel@tonic-gate * and integrity will be allowed.
1491*7c478bd9Sstevel@tonic-gate */
1492*7c478bd9Sstevel@tonic-gate REG_PLUG("GSSAPI", gssapi_server_plugins);
1493*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1494*7c478bd9Sstevel@tonic-gate
1495*7c478bd9Sstevel@tonic-gate *out_version = SASL_SERVER_PLUG_VERSION;
1496*7c478bd9Sstevel@tonic-gate *pluglist = gssapi_server_plugins;
1497*7c478bd9Sstevel@tonic-gate *plugcount = 1;
1498*7c478bd9Sstevel@tonic-gate
1499*7c478bd9Sstevel@tonic-gate return SASL_OK;
1500*7c478bd9Sstevel@tonic-gate }
1501*7c478bd9Sstevel@tonic-gate
1502*7c478bd9Sstevel@tonic-gate /***************************** Client Section *****************************/
1503*7c478bd9Sstevel@tonic-gate
1504*7c478bd9Sstevel@tonic-gate static int gssapi_client_mech_new(void *glob_context __attribute__((unused)),
1505*7c478bd9Sstevel@tonic-gate sasl_client_params_t *params,
1506*7c478bd9Sstevel@tonic-gate void **conn_context)
1507*7c478bd9Sstevel@tonic-gate {
1508*7c478bd9Sstevel@tonic-gate context_t *text;
1509*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1510*7c478bd9Sstevel@tonic-gate const char *use_authid = NULL;
1511*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1512*7c478bd9Sstevel@tonic-gate
1513*7c478bd9Sstevel@tonic-gate /* holds state are in */
1514*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
1515*7c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&global_mutex) < 0)
1516*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
1517*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
1518*7c478bd9Sstevel@tonic-gate text = gss_new_context(params->utils);
1519*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
1520*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
1521*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
1522*7c478bd9Sstevel@tonic-gate if (text == NULL) {
1523*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1524*7c478bd9Sstevel@tonic-gate MEMERROR(params->utils);
1525*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1526*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
1527*7c478bd9Sstevel@tonic-gate }
1528*7c478bd9Sstevel@tonic-gate
1529*7c478bd9Sstevel@tonic-gate text->state = SASL_GSSAPI_STATE_AUTHNEG;
1530*7c478bd9Sstevel@tonic-gate text->gss_ctx = GSS_C_NO_CONTEXT;
1531*7c478bd9Sstevel@tonic-gate text->client_name = GSS_C_NO_NAME;
1532*7c478bd9Sstevel@tonic-gate text->server_creds = GSS_C_NO_CREDENTIAL;
1533*7c478bd9Sstevel@tonic-gate
1534*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1535*7c478bd9Sstevel@tonic-gate params->utils->getopt(params->utils->getopt_context,
1536*7c478bd9Sstevel@tonic-gate "GSSAPI", "use_authid", &use_authid, NULL);
1537*7c478bd9Sstevel@tonic-gate text->use_authid = (use_authid != NULL) &&
1538*7c478bd9Sstevel@tonic-gate (*use_authid == 'y' || *use_authid == 'Y' || *use_authid == '1');
1539*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1540*7c478bd9Sstevel@tonic-gate
1541*7c478bd9Sstevel@tonic-gate *conn_context = text;
1542*7c478bd9Sstevel@tonic-gate
1543*7c478bd9Sstevel@tonic-gate return SASL_OK;
1544*7c478bd9Sstevel@tonic-gate }
1545*7c478bd9Sstevel@tonic-gate
1546*7c478bd9Sstevel@tonic-gate static int gssapi_client_mech_step(void *conn_context,
1547*7c478bd9Sstevel@tonic-gate sasl_client_params_t *params,
1548*7c478bd9Sstevel@tonic-gate const char *serverin,
1549*7c478bd9Sstevel@tonic-gate unsigned serverinlen,
1550*7c478bd9Sstevel@tonic-gate sasl_interact_t **prompt_need,
1551*7c478bd9Sstevel@tonic-gate const char **clientout,
1552*7c478bd9Sstevel@tonic-gate unsigned *clientoutlen,
1553*7c478bd9Sstevel@tonic-gate sasl_out_params_t *oparams)
1554*7c478bd9Sstevel@tonic-gate {
1555*7c478bd9Sstevel@tonic-gate context_t *text = (context_t *)conn_context;
1556*7c478bd9Sstevel@tonic-gate gss_buffer_t input_token, output_token;
1557*7c478bd9Sstevel@tonic-gate gss_buffer_desc real_input_token, real_output_token;
1558*7c478bd9Sstevel@tonic-gate OM_uint32 maj_stat, min_stat;
1559*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1560*7c478bd9Sstevel@tonic-gate OM_uint32 max_input_size;
1561*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1562*7c478bd9Sstevel@tonic-gate gss_buffer_desc name_token;
1563*7c478bd9Sstevel@tonic-gate int ret;
1564*7c478bd9Sstevel@tonic-gate OM_uint32 req_flags, out_req_flags;
1565*7c478bd9Sstevel@tonic-gate input_token = &real_input_token;
1566*7c478bd9Sstevel@tonic-gate output_token = &real_output_token;
1567*7c478bd9Sstevel@tonic-gate output_token->value = NULL;
1568*7c478bd9Sstevel@tonic-gate input_token->value = NULL;
1569*7c478bd9Sstevel@tonic-gate input_token->length = 0;
1570*7c478bd9Sstevel@tonic-gate
1571*7c478bd9Sstevel@tonic-gate *clientout = NULL;
1572*7c478bd9Sstevel@tonic-gate *clientoutlen = 0;
1573*7c478bd9Sstevel@tonic-gate
1574*7c478bd9Sstevel@tonic-gate switch (text->state) {
1575*7c478bd9Sstevel@tonic-gate
1576*7c478bd9Sstevel@tonic-gate case SASL_GSSAPI_STATE_AUTHNEG:
1577*7c478bd9Sstevel@tonic-gate /* try to get the userid */
1578*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1579*7c478bd9Sstevel@tonic-gate if (text->user == NULL ||
1580*7c478bd9Sstevel@tonic-gate (text->use_authid && text->client_authid == NULL)) {
1581*7c478bd9Sstevel@tonic-gate int auth_result = SASL_OK;
1582*7c478bd9Sstevel@tonic-gate int user_result = SASL_OK;
1583*7c478bd9Sstevel@tonic-gate
1584*7c478bd9Sstevel@tonic-gate if (text->use_authid && text->client_authid == NULL) {
1585*7c478bd9Sstevel@tonic-gate auth_result = _plug_get_authid(params->utils,
1586*7c478bd9Sstevel@tonic-gate &text->client_authid,
1587*7c478bd9Sstevel@tonic-gate prompt_need);
1588*7c478bd9Sstevel@tonic-gate
1589*7c478bd9Sstevel@tonic-gate if ((auth_result != SASL_OK) &&
1590*7c478bd9Sstevel@tonic-gate (auth_result != SASL_INTERACT)) {
1591*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1592*7c478bd9Sstevel@tonic-gate return auth_result;
1593*7c478bd9Sstevel@tonic-gate }
1594*7c478bd9Sstevel@tonic-gate }
1595*7c478bd9Sstevel@tonic-gate if (text->user == NULL) {
1596*7c478bd9Sstevel@tonic-gate user_result = _plug_get_userid(params->utils, &text->user,
1597*7c478bd9Sstevel@tonic-gate prompt_need);
1598*7c478bd9Sstevel@tonic-gate
1599*7c478bd9Sstevel@tonic-gate if ((user_result != SASL_OK) &&
1600*7c478bd9Sstevel@tonic-gate (user_result != SASL_INTERACT)) {
1601*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1602*7c478bd9Sstevel@tonic-gate return user_result;
1603*7c478bd9Sstevel@tonic-gate }
1604*7c478bd9Sstevel@tonic-gate }
1605*7c478bd9Sstevel@tonic-gate #else
1606*7c478bd9Sstevel@tonic-gate if (text->user == NULL) {
1607*7c478bd9Sstevel@tonic-gate int user_result = SASL_OK;
1608*7c478bd9Sstevel@tonic-gate
1609*7c478bd9Sstevel@tonic-gate user_result = _plug_get_userid(params->utils, &text->user,
1610*7c478bd9Sstevel@tonic-gate prompt_need);
1611*7c478bd9Sstevel@tonic-gate
1612*7c478bd9Sstevel@tonic-gate if ((user_result != SASL_OK) && (user_result != SASL_INTERACT)) {
1613*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1614*7c478bd9Sstevel@tonic-gate return user_result;
1615*7c478bd9Sstevel@tonic-gate }
1616*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1617*7c478bd9Sstevel@tonic-gate
1618*7c478bd9Sstevel@tonic-gate /* free prompts we got */
1619*7c478bd9Sstevel@tonic-gate if (prompt_need && *prompt_need) {
1620*7c478bd9Sstevel@tonic-gate params->utils->free(*prompt_need);
1621*7c478bd9Sstevel@tonic-gate *prompt_need = NULL;
1622*7c478bd9Sstevel@tonic-gate }
1623*7c478bd9Sstevel@tonic-gate
1624*7c478bd9Sstevel@tonic-gate /* if there are prompts not filled in */
1625*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1626*7c478bd9Sstevel@tonic-gate if ((user_result == SASL_INTERACT) ||
1627*7c478bd9Sstevel@tonic-gate (auth_result == SASL_INTERACT)) {
1628*7c478bd9Sstevel@tonic-gate /* make the prompt list */
1629*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1630*7c478bd9Sstevel@tonic-gate int result = _plug_make_prompts(params->utils, &text->h,
1631*7c478bd9Sstevel@tonic-gate prompt_need,
1632*7c478bd9Sstevel@tonic-gate user_result == SASL_INTERACT ?
1633*7c478bd9Sstevel@tonic-gate convert_prompt(params->utils, &text->h,
1634*7c478bd9Sstevel@tonic-gate gettext("Please enter your authorization name"))
1635*7c478bd9Sstevel@tonic-gate : NULL, NULL,
1636*7c478bd9Sstevel@tonic-gate auth_result == SASL_INTERACT ?
1637*7c478bd9Sstevel@tonic-gate convert_prompt(params->utils, &text->h,
1638*7c478bd9Sstevel@tonic-gate gettext("Please enter your authentication name"))
1639*7c478bd9Sstevel@tonic-gate : NULL, NULL,
1640*7c478bd9Sstevel@tonic-gate NULL, NULL,
1641*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL,
1642*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL);
1643*7c478bd9Sstevel@tonic-gate #else
1644*7c478bd9Sstevel@tonic-gate int result = _plug_make_prompts(params->utils, prompt_need,
1645*7c478bd9Sstevel@tonic-gate user_result == SASL_INTERACT ?
1646*7c478bd9Sstevel@tonic-gate "Please enter your authorization name"
1647*7c478bd9Sstevel@tonic-gate : NULL, NULL,
1648*7c478bd9Sstevel@tonic-gate auth_result == SASL_INTERACT ?
1649*7c478bd9Sstevel@tonic-gate "Please enter your authentication name"
1650*7c478bd9Sstevel@tonic-gate : NULL, NULL,
1651*7c478bd9Sstevel@tonic-gate NULL, NULL,
1652*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL,
1653*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL);
1654*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1655*7c478bd9Sstevel@tonic-gate
1656*7c478bd9Sstevel@tonic-gate if (result != SASL_OK) return result;
1657*7c478bd9Sstevel@tonic-gate
1658*7c478bd9Sstevel@tonic-gate return SASL_INTERACT;
1659*7c478bd9Sstevel@tonic-gate }
1660*7c478bd9Sstevel@tonic-gate #else
1661*7c478bd9Sstevel@tonic-gate if (user_result == SASL_INTERACT) {
1662*7c478bd9Sstevel@tonic-gate /* make the prompt list */
1663*7c478bd9Sstevel@tonic-gate int result =
1664*7c478bd9Sstevel@tonic-gate _plug_make_prompts(params->utils, prompt_need,
1665*7c478bd9Sstevel@tonic-gate user_result == SASL_INTERACT ?
1666*7c478bd9Sstevel@tonic-gate "Please enter your authorization name" : NULL, NULL,
1667*7c478bd9Sstevel@tonic-gate NULL, NULL,
1668*7c478bd9Sstevel@tonic-gate NULL, NULL,
1669*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL,
1670*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL);
1671*7c478bd9Sstevel@tonic-gate if (result != SASL_OK) return result;
1672*7c478bd9Sstevel@tonic-gate
1673*7c478bd9Sstevel@tonic-gate return SASL_INTERACT;
1674*7c478bd9Sstevel@tonic-gate }
1675*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1676*7c478bd9Sstevel@tonic-gate }
1677*7c478bd9Sstevel@tonic-gate
1678*7c478bd9Sstevel@tonic-gate if (text->server_name == GSS_C_NO_NAME) { /* only once */
1679*7c478bd9Sstevel@tonic-gate name_token.length = strlen(params->service) + 1 + strlen(params->serverFQDN);
1680*7c478bd9Sstevel@tonic-gate name_token.value = (char *)params->utils->malloc((name_token.length + 1) * sizeof(char));
1681*7c478bd9Sstevel@tonic-gate if (name_token.value == NULL) {
1682*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1683*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
1684*7c478bd9Sstevel@tonic-gate }
1685*7c478bd9Sstevel@tonic-gate if (params->serverFQDN == NULL
1686*7c478bd9Sstevel@tonic-gate || strlen(params->serverFQDN) == 0) {
1687*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1688*7c478bd9Sstevel@tonic-gate text->utils->log(text->utils->conn, SASL_LOG_ERR,
1689*7c478bd9Sstevel@tonic-gate "GSSAPI Failure: no serverFQDN");
1690*7c478bd9Sstevel@tonic-gate #else
1691*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, "GSSAPI Failure: no serverFQDN");
1692*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1693*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1694*7c478bd9Sstevel@tonic-gate }
1695*7c478bd9Sstevel@tonic-gate
1696*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1697*7c478bd9Sstevel@tonic-gate snprintf(name_token.value, name_token.length + 1,
1698*7c478bd9Sstevel@tonic-gate "%s@%s", params->service, params->serverFQDN);
1699*7c478bd9Sstevel@tonic-gate #else
1700*7c478bd9Sstevel@tonic-gate sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
1701*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1702*7c478bd9Sstevel@tonic-gate
1703*7c478bd9Sstevel@tonic-gate maj_stat = gss_import_name (&min_stat,
1704*7c478bd9Sstevel@tonic-gate &name_token,
1705*7c478bd9Sstevel@tonic-gate GSS_C_NT_HOSTBASED_SERVICE,
1706*7c478bd9Sstevel@tonic-gate &text->server_name);
1707*7c478bd9Sstevel@tonic-gate
1708*7c478bd9Sstevel@tonic-gate params->utils->free(name_token.value);
1709*7c478bd9Sstevel@tonic-gate name_token.value = NULL;
1710*7c478bd9Sstevel@tonic-gate
1711*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1712*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1713*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1714*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1715*7c478bd9Sstevel@tonic-gate }
1716*7c478bd9Sstevel@tonic-gate }
1717*7c478bd9Sstevel@tonic-gate
1718*7c478bd9Sstevel@tonic-gate if (serverinlen == 0)
1719*7c478bd9Sstevel@tonic-gate input_token = GSS_C_NO_BUFFER;
1720*7c478bd9Sstevel@tonic-gate
1721*7c478bd9Sstevel@tonic-gate if (serverinlen) {
1722*7c478bd9Sstevel@tonic-gate real_input_token.value = (void *)serverin;
1723*7c478bd9Sstevel@tonic-gate real_input_token.length = serverinlen;
1724*7c478bd9Sstevel@tonic-gate }
1725*7c478bd9Sstevel@tonic-gate else if (text->gss_ctx != GSS_C_NO_CONTEXT ) {
1726*7c478bd9Sstevel@tonic-gate /* This can't happen under GSSAPI: we have a non-null context
1727*7c478bd9Sstevel@tonic-gate * and no input from the server. However, thanks to Imap,
1728*7c478bd9Sstevel@tonic-gate * which discards our first output, this happens all the time.
1729*7c478bd9Sstevel@tonic-gate * Throw away the context and try again. */
1730*7c478bd9Sstevel@tonic-gate maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
1731*7c478bd9Sstevel@tonic-gate text->gss_ctx = GSS_C_NO_CONTEXT;
1732*7c478bd9Sstevel@tonic-gate }
1733*7c478bd9Sstevel@tonic-gate
1734*7c478bd9Sstevel@tonic-gate /* Setup req_flags properly */
1735*7c478bd9Sstevel@tonic-gate req_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG;
1736*7c478bd9Sstevel@tonic-gate if(params->props.max_ssf > params->external_ssf) {
1737*7c478bd9Sstevel@tonic-gate /* We are requesting a security layer */
1738*7c478bd9Sstevel@tonic-gate req_flags |= GSS_C_INTEG_FLAG;
1739*7c478bd9Sstevel@tonic-gate if(params->props.max_ssf - params->external_ssf > 56) {
1740*7c478bd9Sstevel@tonic-gate /* We want to try for privacy */
1741*7c478bd9Sstevel@tonic-gate req_flags |= GSS_C_CONF_FLAG;
1742*7c478bd9Sstevel@tonic-gate }
1743*7c478bd9Sstevel@tonic-gate }
1744*7c478bd9Sstevel@tonic-gate
1745*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1746*7c478bd9Sstevel@tonic-gate if (text->use_authid && text->client_creds == GSS_C_NO_CREDENTIAL) {
1747*7c478bd9Sstevel@tonic-gate gss_OID_set desired_mechs = GSS_C_NULL_OID_SET;
1748*7c478bd9Sstevel@tonic-gate gss_buffer_desc name_token;
1749*7c478bd9Sstevel@tonic-gate
1750*7c478bd9Sstevel@tonic-gate name_token.length = strlen(text->client_authid);
1751*7c478bd9Sstevel@tonic-gate name_token.value = (char *)text->client_authid;
1752*7c478bd9Sstevel@tonic-gate
1753*7c478bd9Sstevel@tonic-gate maj_stat = gss_import_name (&min_stat,
1754*7c478bd9Sstevel@tonic-gate &name_token,
1755*7c478bd9Sstevel@tonic-gate #ifdef HAVE_GSS_C_NT_USER_NAME
1756*7c478bd9Sstevel@tonic-gate GSS_C_NT_USER_NAME,
1757*7c478bd9Sstevel@tonic-gate #else
1758*7c478bd9Sstevel@tonic-gate GSS_C_NULL_OID,
1759*7c478bd9Sstevel@tonic-gate #endif
1760*7c478bd9Sstevel@tonic-gate &text->client_name);
1761*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1762*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1763*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1764*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1765*7c478bd9Sstevel@tonic-gate }
1766*7c478bd9Sstevel@tonic-gate
1767*7c478bd9Sstevel@tonic-gate if (text->mech_oid != GSS_C_NULL_OID) {
1768*7c478bd9Sstevel@tonic-gate ret = add_mech_to_set(text, &desired_mechs);
1769*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK)
1770*7c478bd9Sstevel@tonic-gate return (ret);
1771*7c478bd9Sstevel@tonic-gate }
1772*7c478bd9Sstevel@tonic-gate
1773*7c478bd9Sstevel@tonic-gate maj_stat = gss_acquire_cred(&min_stat,
1774*7c478bd9Sstevel@tonic-gate text->client_name,
1775*7c478bd9Sstevel@tonic-gate GSS_C_INDEFINITE,
1776*7c478bd9Sstevel@tonic-gate desired_mechs,
1777*7c478bd9Sstevel@tonic-gate GSS_C_INITIATE,
1778*7c478bd9Sstevel@tonic-gate &text->client_creds,
1779*7c478bd9Sstevel@tonic-gate NULL,
1780*7c478bd9Sstevel@tonic-gate NULL);
1781*7c478bd9Sstevel@tonic-gate
1782*7c478bd9Sstevel@tonic-gate if (desired_mechs != GSS_C_NULL_OID_SET) {
1783*7c478bd9Sstevel@tonic-gate OM_uint32 min_stat2;
1784*7c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min_stat2, &desired_mechs);
1785*7c478bd9Sstevel@tonic-gate }
1786*7c478bd9Sstevel@tonic-gate
1787*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1788*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1789*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1790*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1791*7c478bd9Sstevel@tonic-gate }
1792*7c478bd9Sstevel@tonic-gate }
1793*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1794*7c478bd9Sstevel@tonic-gate
1795*7c478bd9Sstevel@tonic-gate maj_stat = gss_init_sec_context(&min_stat,
1796*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1797*7c478bd9Sstevel@tonic-gate text->client_creds,
1798*7c478bd9Sstevel@tonic-gate #else
1799*7c478bd9Sstevel@tonic-gate GSS_C_NO_CREDENTIAL,
1800*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1801*7c478bd9Sstevel@tonic-gate &text->gss_ctx,
1802*7c478bd9Sstevel@tonic-gate text->server_name,
1803*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1804*7c478bd9Sstevel@tonic-gate text->mech_oid,
1805*7c478bd9Sstevel@tonic-gate #else
1806*7c478bd9Sstevel@tonic-gate GSS_C_NO_OID,
1807*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1808*7c478bd9Sstevel@tonic-gate req_flags,
1809*7c478bd9Sstevel@tonic-gate 0,
1810*7c478bd9Sstevel@tonic-gate GSS_C_NO_CHANNEL_BINDINGS,
1811*7c478bd9Sstevel@tonic-gate input_token,
1812*7c478bd9Sstevel@tonic-gate NULL,
1813*7c478bd9Sstevel@tonic-gate output_token,
1814*7c478bd9Sstevel@tonic-gate &out_req_flags,
1815*7c478bd9Sstevel@tonic-gate NULL);
1816*7c478bd9Sstevel@tonic-gate
1817*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1818*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1819*7c478bd9Sstevel@tonic-gate if (output_token->value)
1820*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1821*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1822*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1823*7c478bd9Sstevel@tonic-gate }
1824*7c478bd9Sstevel@tonic-gate
1825*7c478bd9Sstevel@tonic-gate *clientoutlen = output_token->length;
1826*7c478bd9Sstevel@tonic-gate
1827*7c478bd9Sstevel@tonic-gate if (output_token->value) {
1828*7c478bd9Sstevel@tonic-gate if (clientout) {
1829*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(text->utils, &(text->out_buf),
1830*7c478bd9Sstevel@tonic-gate &(text->out_buf_len), *clientoutlen);
1831*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) {
1832*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1833*7c478bd9Sstevel@tonic-gate return ret;
1834*7c478bd9Sstevel@tonic-gate }
1835*7c478bd9Sstevel@tonic-gate memcpy(text->out_buf, output_token->value, *clientoutlen);
1836*7c478bd9Sstevel@tonic-gate *clientout = text->out_buf;
1837*7c478bd9Sstevel@tonic-gate }
1838*7c478bd9Sstevel@tonic-gate
1839*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1840*7c478bd9Sstevel@tonic-gate }
1841*7c478bd9Sstevel@tonic-gate
1842*7c478bd9Sstevel@tonic-gate if (maj_stat == GSS_S_COMPLETE) {
1843*7c478bd9Sstevel@tonic-gate maj_stat = gss_inquire_context(&min_stat,
1844*7c478bd9Sstevel@tonic-gate text->gss_ctx,
1845*7c478bd9Sstevel@tonic-gate &text->client_name,
1846*7c478bd9Sstevel@tonic-gate NULL, /* targ_name */
1847*7c478bd9Sstevel@tonic-gate NULL, /* lifetime */
1848*7c478bd9Sstevel@tonic-gate NULL, /* mech */
1849*7c478bd9Sstevel@tonic-gate NULL, /* flags */
1850*7c478bd9Sstevel@tonic-gate NULL, /* local init */
1851*7c478bd9Sstevel@tonic-gate NULL); /* open */
1852*7c478bd9Sstevel@tonic-gate
1853*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1854*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1855*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1856*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1857*7c478bd9Sstevel@tonic-gate }
1858*7c478bd9Sstevel@tonic-gate
1859*7c478bd9Sstevel@tonic-gate name_token.length = 0;
1860*7c478bd9Sstevel@tonic-gate maj_stat = gss_display_name(&min_stat,
1861*7c478bd9Sstevel@tonic-gate text->client_name,
1862*7c478bd9Sstevel@tonic-gate &name_token,
1863*7c478bd9Sstevel@tonic-gate NULL);
1864*7c478bd9Sstevel@tonic-gate
1865*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1866*7c478bd9Sstevel@tonic-gate if (name_token.value)
1867*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, &name_token);
1868*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1869*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, gettext("GSSAPI Failure"));
1870*7c478bd9Sstevel@tonic-gate #else
1871*7c478bd9Sstevel@tonic-gate SETERROR(text->utils, "GSSAPI Failure");
1872*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1873*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1874*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1875*7c478bd9Sstevel@tonic-gate }
1876*7c478bd9Sstevel@tonic-gate
1877*7c478bd9Sstevel@tonic-gate if (text->user && text->user[0]) {
1878*7c478bd9Sstevel@tonic-gate ret = params->canon_user(params->utils->conn,
1879*7c478bd9Sstevel@tonic-gate text->user, 0,
1880*7c478bd9Sstevel@tonic-gate SASL_CU_AUTHZID, oparams);
1881*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK)
1882*7c478bd9Sstevel@tonic-gate ret = params->canon_user(params->utils->conn,
1883*7c478bd9Sstevel@tonic-gate name_token.value, 0,
1884*7c478bd9Sstevel@tonic-gate SASL_CU_AUTHID, oparams);
1885*7c478bd9Sstevel@tonic-gate } else {
1886*7c478bd9Sstevel@tonic-gate ret = params->canon_user(params->utils->conn,
1887*7c478bd9Sstevel@tonic-gate name_token.value, 0,
1888*7c478bd9Sstevel@tonic-gate SASL_CU_AUTHID | SASL_CU_AUTHZID,
1889*7c478bd9Sstevel@tonic-gate oparams);
1890*7c478bd9Sstevel@tonic-gate }
1891*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, &name_token);
1892*7c478bd9Sstevel@tonic-gate
1893*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) return ret;
1894*7c478bd9Sstevel@tonic-gate
1895*7c478bd9Sstevel@tonic-gate /* Switch to ssf negotiation */
1896*7c478bd9Sstevel@tonic-gate text->state = SASL_GSSAPI_STATE_SSFCAP;
1897*7c478bd9Sstevel@tonic-gate }
1898*7c478bd9Sstevel@tonic-gate
1899*7c478bd9Sstevel@tonic-gate return SASL_CONTINUE;
1900*7c478bd9Sstevel@tonic-gate
1901*7c478bd9Sstevel@tonic-gate case SASL_GSSAPI_STATE_SSFCAP: {
1902*7c478bd9Sstevel@tonic-gate sasl_security_properties_t *secprops = &(params->props);
1903*7c478bd9Sstevel@tonic-gate unsigned int alen, external = params->external_ssf;
1904*7c478bd9Sstevel@tonic-gate sasl_ssf_t need, allowed;
1905*7c478bd9Sstevel@tonic-gate char serverhas, mychoice;
1906*7c478bd9Sstevel@tonic-gate
1907*7c478bd9Sstevel@tonic-gate real_input_token.value = (void *) serverin;
1908*7c478bd9Sstevel@tonic-gate real_input_token.length = serverinlen;
1909*7c478bd9Sstevel@tonic-gate
1910*7c478bd9Sstevel@tonic-gate maj_stat = gss_unwrap(&min_stat,
1911*7c478bd9Sstevel@tonic-gate text->gss_ctx,
1912*7c478bd9Sstevel@tonic-gate input_token,
1913*7c478bd9Sstevel@tonic-gate output_token,
1914*7c478bd9Sstevel@tonic-gate NULL,
1915*7c478bd9Sstevel@tonic-gate NULL);
1916*7c478bd9Sstevel@tonic-gate
1917*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1918*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1919*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1920*7c478bd9Sstevel@tonic-gate if (output_token->value)
1921*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
1922*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1923*7c478bd9Sstevel@tonic-gate }
1924*7c478bd9Sstevel@tonic-gate
1925*7c478bd9Sstevel@tonic-gate /* taken from kerberos.c */
1926*7c478bd9Sstevel@tonic-gate if (secprops->min_ssf > (56 + external)) {
1927*7c478bd9Sstevel@tonic-gate return SASL_TOOWEAK;
1928*7c478bd9Sstevel@tonic-gate } else if (secprops->min_ssf > secprops->max_ssf) {
1929*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM;
1930*7c478bd9Sstevel@tonic-gate }
1931*7c478bd9Sstevel@tonic-gate
1932*7c478bd9Sstevel@tonic-gate /* need bits of layer -- sasl_ssf_t is unsigned so be careful */
1933*7c478bd9Sstevel@tonic-gate if (secprops->max_ssf >= external) {
1934*7c478bd9Sstevel@tonic-gate allowed = secprops->max_ssf - external;
1935*7c478bd9Sstevel@tonic-gate } else {
1936*7c478bd9Sstevel@tonic-gate allowed = 0;
1937*7c478bd9Sstevel@tonic-gate }
1938*7c478bd9Sstevel@tonic-gate if (secprops->min_ssf >= external) {
1939*7c478bd9Sstevel@tonic-gate need = secprops->min_ssf - external;
1940*7c478bd9Sstevel@tonic-gate } else {
1941*7c478bd9Sstevel@tonic-gate /* good to go */
1942*7c478bd9Sstevel@tonic-gate need = 0;
1943*7c478bd9Sstevel@tonic-gate }
1944*7c478bd9Sstevel@tonic-gate
1945*7c478bd9Sstevel@tonic-gate /* bit mask of server support */
1946*7c478bd9Sstevel@tonic-gate serverhas = ((char *)output_token->value)[0];
1947*7c478bd9Sstevel@tonic-gate
1948*7c478bd9Sstevel@tonic-gate /* if client didn't set use strongest layer available */
1949*7c478bd9Sstevel@tonic-gate if (allowed >= 56 && need <= 56 && (serverhas & 4)) {
1950*7c478bd9Sstevel@tonic-gate /* encryption */
1951*7c478bd9Sstevel@tonic-gate oparams->encode = &gssapi_privacy_encode;
1952*7c478bd9Sstevel@tonic-gate oparams->decode = &gssapi_decode;
1953*7c478bd9Sstevel@tonic-gate oparams->mech_ssf = 56;
1954*7c478bd9Sstevel@tonic-gate mychoice = 4;
1955*7c478bd9Sstevel@tonic-gate } else if (allowed >= 1 && need <= 1 && (serverhas & 2)) {
1956*7c478bd9Sstevel@tonic-gate /* integrity */
1957*7c478bd9Sstevel@tonic-gate oparams->encode = &gssapi_integrity_encode;
1958*7c478bd9Sstevel@tonic-gate oparams->decode = &gssapi_decode;
1959*7c478bd9Sstevel@tonic-gate oparams->mech_ssf = 1;
1960*7c478bd9Sstevel@tonic-gate mychoice = 2;
1961*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1962*7c478bd9Sstevel@tonic-gate } else if (need == 0 && (serverhas & 1)) {
1963*7c478bd9Sstevel@tonic-gate #else
1964*7c478bd9Sstevel@tonic-gate } else if (need <= 0 && (serverhas & 1)) {
1965*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1966*7c478bd9Sstevel@tonic-gate /* no layer */
1967*7c478bd9Sstevel@tonic-gate oparams->encode = NULL;
1968*7c478bd9Sstevel@tonic-gate oparams->decode = NULL;
1969*7c478bd9Sstevel@tonic-gate oparams->mech_ssf = 0;
1970*7c478bd9Sstevel@tonic-gate mychoice = 1;
1971*7c478bd9Sstevel@tonic-gate } else {
1972*7c478bd9Sstevel@tonic-gate /* there's no appropriate layering for us! */
1973*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1974*7c478bd9Sstevel@tonic-gate return SASL_TOOWEAK;
1975*7c478bd9Sstevel@tonic-gate }
1976*7c478bd9Sstevel@tonic-gate
1977*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf =
1978*7c478bd9Sstevel@tonic-gate (((unsigned char *) output_token->value)[1] << 16) |
1979*7c478bd9Sstevel@tonic-gate (((unsigned char *) output_token->value)[2] << 8) |
1980*7c478bd9Sstevel@tonic-gate (((unsigned char *) output_token->value)[3] << 0);
1981*7c478bd9Sstevel@tonic-gate
1982*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1983*7c478bd9Sstevel@tonic-gate if (oparams->mech_ssf > 0) {
1984*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf -= 4; /* Space for 4 byte length header */
1985*7c478bd9Sstevel@tonic-gate maj_stat = gss_wrap_size_limit(&min_stat,
1986*7c478bd9Sstevel@tonic-gate text->gss_ctx,
1987*7c478bd9Sstevel@tonic-gate oparams->mech_ssf > 1,
1988*7c478bd9Sstevel@tonic-gate GSS_C_QOP_DEFAULT,
1989*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf,
1990*7c478bd9Sstevel@tonic-gate &max_input_size);
1991*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
1992*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
1993*7c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&min_stat, output_token);
1994*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
1995*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
1996*7c478bd9Sstevel@tonic-gate }
1997*7c478bd9Sstevel@tonic-gate
1998*7c478bd9Sstevel@tonic-gate /*
1999*7c478bd9Sstevel@tonic-gate * This is a workaround for a Solaris bug where
2000*7c478bd9Sstevel@tonic-gate * gss_wrap_size_limit may return very big sizes for
2001*7c478bd9Sstevel@tonic-gate * small input values
2002*7c478bd9Sstevel@tonic-gate */
2003*7c478bd9Sstevel@tonic-gate if (max_input_size < oparams->maxoutbuf)
2004*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf = max_input_size;
2005*7c478bd9Sstevel@tonic-gate else {
2006*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf = 0;
2007*7c478bd9Sstevel@tonic-gate }
2008*7c478bd9Sstevel@tonic-gate }
2009*7c478bd9Sstevel@tonic-gate #else
2010*7c478bd9Sstevel@tonic-gate if(oparams->mech_ssf) {
2011*7c478bd9Sstevel@tonic-gate /* xxx probably too large */
2012*7c478bd9Sstevel@tonic-gate oparams->maxoutbuf -= 50;
2013*7c478bd9Sstevel@tonic-gate }
2014*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2015*7c478bd9Sstevel@tonic-gate
2016*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
2017*7c478bd9Sstevel@tonic-gate
2018*7c478bd9Sstevel@tonic-gate /* oparams->user is always set, due to canon_user requirements.
2019*7c478bd9Sstevel@tonic-gate * Make sure the client actually requested it though, by checking
2020*7c478bd9Sstevel@tonic-gate * if our context was set.
2021*7c478bd9Sstevel@tonic-gate */
2022*7c478bd9Sstevel@tonic-gate if (text->user && text->user[0])
2023*7c478bd9Sstevel@tonic-gate alen = strlen(oparams->user);
2024*7c478bd9Sstevel@tonic-gate else
2025*7c478bd9Sstevel@tonic-gate alen = 0;
2026*7c478bd9Sstevel@tonic-gate
2027*7c478bd9Sstevel@tonic-gate input_token->length = 4 + alen;
2028*7c478bd9Sstevel@tonic-gate input_token->value =
2029*7c478bd9Sstevel@tonic-gate (char *)params->utils->malloc((input_token->length + 1)*sizeof(char));
2030*7c478bd9Sstevel@tonic-gate if (input_token->value == NULL) {
2031*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
2032*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
2033*7c478bd9Sstevel@tonic-gate }
2034*7c478bd9Sstevel@tonic-gate
2035*7c478bd9Sstevel@tonic-gate if (alen)
2036*7c478bd9Sstevel@tonic-gate memcpy((char *)input_token->value+4,oparams->user,alen);
2037*7c478bd9Sstevel@tonic-gate
2038*7c478bd9Sstevel@tonic-gate /* build up our security properties token */
2039*7c478bd9Sstevel@tonic-gate if (params->props.maxbufsize > 0xFFFFFF) {
2040*7c478bd9Sstevel@tonic-gate /* make sure maxbufsize isn't too large */
2041*7c478bd9Sstevel@tonic-gate /* maxbufsize = 0xFFFFFF */
2042*7c478bd9Sstevel@tonic-gate ((unsigned char *)input_token->value)[1] = 0xFF;
2043*7c478bd9Sstevel@tonic-gate ((unsigned char *)input_token->value)[2] = 0xFF;
2044*7c478bd9Sstevel@tonic-gate ((unsigned char *)input_token->value)[3] = 0xFF;
2045*7c478bd9Sstevel@tonic-gate } else {
2046*7c478bd9Sstevel@tonic-gate ((unsigned char *)input_token->value)[1] =
2047*7c478bd9Sstevel@tonic-gate (params->props.maxbufsize >> 16) & 0xFF;
2048*7c478bd9Sstevel@tonic-gate ((unsigned char *)input_token->value)[2] =
2049*7c478bd9Sstevel@tonic-gate (params->props.maxbufsize >> 8) & 0xFF;
2050*7c478bd9Sstevel@tonic-gate ((unsigned char *)input_token->value)[3] =
2051*7c478bd9Sstevel@tonic-gate (params->props.maxbufsize >> 0) & 0xFF;
2052*7c478bd9Sstevel@tonic-gate }
2053*7c478bd9Sstevel@tonic-gate ((unsigned char *)input_token->value)[0] = mychoice;
2054*7c478bd9Sstevel@tonic-gate
2055*7c478bd9Sstevel@tonic-gate maj_stat = gss_wrap (&min_stat,
2056*7c478bd9Sstevel@tonic-gate text->gss_ctx,
2057*7c478bd9Sstevel@tonic-gate 0, /* Just integrity checking here */
2058*7c478bd9Sstevel@tonic-gate GSS_C_QOP_DEFAULT,
2059*7c478bd9Sstevel@tonic-gate input_token,
2060*7c478bd9Sstevel@tonic-gate NULL,
2061*7c478bd9Sstevel@tonic-gate output_token);
2062*7c478bd9Sstevel@tonic-gate
2063*7c478bd9Sstevel@tonic-gate params->utils->free(input_token->value);
2064*7c478bd9Sstevel@tonic-gate input_token->value = NULL;
2065*7c478bd9Sstevel@tonic-gate
2066*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj_stat)) {
2067*7c478bd9Sstevel@tonic-gate sasl_gss_seterror(text->utils, maj_stat, min_stat);
2068*7c478bd9Sstevel@tonic-gate if (output_token->value)
2069*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
2070*7c478bd9Sstevel@tonic-gate sasl_gss_free_context_contents(text);
2071*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
2072*7c478bd9Sstevel@tonic-gate }
2073*7c478bd9Sstevel@tonic-gate
2074*7c478bd9Sstevel@tonic-gate if (clientoutlen)
2075*7c478bd9Sstevel@tonic-gate *clientoutlen = output_token->length;
2076*7c478bd9Sstevel@tonic-gate if (output_token->value) {
2077*7c478bd9Sstevel@tonic-gate if (clientout) {
2078*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(text->utils, &(text->out_buf),
2079*7c478bd9Sstevel@tonic-gate &(text->out_buf_len), *clientoutlen);
2080*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) {
2081*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
2082*7c478bd9Sstevel@tonic-gate return ret;
2083*7c478bd9Sstevel@tonic-gate }
2084*7c478bd9Sstevel@tonic-gate memcpy(text->out_buf, output_token->value, *clientoutlen);
2085*7c478bd9Sstevel@tonic-gate *clientout = text->out_buf;
2086*7c478bd9Sstevel@tonic-gate }
2087*7c478bd9Sstevel@tonic-gate
2088*7c478bd9Sstevel@tonic-gate gss_release_buffer(&min_stat, output_token);
2089*7c478bd9Sstevel@tonic-gate }
2090*7c478bd9Sstevel@tonic-gate
2091*7c478bd9Sstevel@tonic-gate text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
2092*7c478bd9Sstevel@tonic-gate
2093*7c478bd9Sstevel@tonic-gate oparams->doneflag = 1;
2094*7c478bd9Sstevel@tonic-gate
2095*7c478bd9Sstevel@tonic-gate return SASL_OK;
2096*7c478bd9Sstevel@tonic-gate }
2097*7c478bd9Sstevel@tonic-gate
2098*7c478bd9Sstevel@tonic-gate default:
2099*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2100*7c478bd9Sstevel@tonic-gate params->utils->log(params->utils->conn, SASL_LOG_ERR,
2101*7c478bd9Sstevel@tonic-gate "Invalid GSSAPI client step %d", text->state);
2102*7c478bd9Sstevel@tonic-gate #else
2103*7c478bd9Sstevel@tonic-gate params->utils->log(NULL, SASL_LOG_ERR,
2104*7c478bd9Sstevel@tonic-gate "Invalid GSSAPI client step %d\n", text->state);
2105*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2106*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
2107*7c478bd9Sstevel@tonic-gate }
2108*7c478bd9Sstevel@tonic-gate
2109*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
2110*7c478bd9Sstevel@tonic-gate return SASL_FAIL; /* should never get here */
2111*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
2112*7c478bd9Sstevel@tonic-gate }
2113*7c478bd9Sstevel@tonic-gate
2114*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2115*7c478bd9Sstevel@tonic-gate static const unsigned long gssapi_required_prompts[] = {
2116*7c478bd9Sstevel@tonic-gate #else
2117*7c478bd9Sstevel@tonic-gate static const long gssapi_required_prompts[] = {
2118*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2119*7c478bd9Sstevel@tonic-gate SASL_CB_LIST_END
2120*7c478bd9Sstevel@tonic-gate };
2121*7c478bd9Sstevel@tonic-gate
2122*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
2123*7c478bd9Sstevel@tonic-gate static int _gssapi_client_mech_step(void *conn_context,
2124*7c478bd9Sstevel@tonic-gate sasl_client_params_t *params,
2125*7c478bd9Sstevel@tonic-gate const char *serverin,
2126*7c478bd9Sstevel@tonic-gate unsigned serverinlen,
2127*7c478bd9Sstevel@tonic-gate sasl_interact_t **prompt_need,
2128*7c478bd9Sstevel@tonic-gate const char **clientout,
2129*7c478bd9Sstevel@tonic-gate unsigned *clientoutlen,
2130*7c478bd9Sstevel@tonic-gate sasl_out_params_t *oparams)
2131*7c478bd9Sstevel@tonic-gate {
2132*7c478bd9Sstevel@tonic-gate int ret;
2133*7c478bd9Sstevel@tonic-gate
2134*7c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&global_mutex) < 0)
2135*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
2136*7c478bd9Sstevel@tonic-gate
2137*7c478bd9Sstevel@tonic-gate ret = gssapi_client_mech_step(conn_context, params, serverin, serverinlen,
2138*7c478bd9Sstevel@tonic-gate prompt_need, clientout, clientoutlen, oparams);
2139*7c478bd9Sstevel@tonic-gate
2140*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&global_mutex);
2141*7c478bd9Sstevel@tonic-gate return (ret);
2142*7c478bd9Sstevel@tonic-gate }
2143*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
2144*7c478bd9Sstevel@tonic-gate
2145*7c478bd9Sstevel@tonic-gate static sasl_client_plug_t gssapi_client_plugins[] =
2146*7c478bd9Sstevel@tonic-gate {
2147*7c478bd9Sstevel@tonic-gate {
2148*7c478bd9Sstevel@tonic-gate "GSSAPI", /* mech_name */
2149*7c478bd9Sstevel@tonic-gate 56, /* max_ssf */
2150*7c478bd9Sstevel@tonic-gate SASL_SEC_NOPLAINTEXT
2151*7c478bd9Sstevel@tonic-gate | SASL_SEC_NOACTIVE
2152*7c478bd9Sstevel@tonic-gate | SASL_SEC_NOANONYMOUS
2153*7c478bd9Sstevel@tonic-gate | SASL_SEC_MUTUAL_AUTH, /* security_flags */
2154*7c478bd9Sstevel@tonic-gate SASL_FEAT_WANT_CLIENT_FIRST
2155*7c478bd9Sstevel@tonic-gate | SASL_FEAT_ALLOWS_PROXY, /* features */
2156*7c478bd9Sstevel@tonic-gate gssapi_required_prompts, /* required_prompts */
2157*7c478bd9Sstevel@tonic-gate NULL, /* glob_context */
2158*7c478bd9Sstevel@tonic-gate &gssapi_client_mech_new, /* mech_new */
2159*7c478bd9Sstevel@tonic-gate #if defined _SUN_SDK_ && defined GSSAPI_PROTECT
2160*7c478bd9Sstevel@tonic-gate &_gssapi_client_mech_step, /* mech_step */
2161*7c478bd9Sstevel@tonic-gate #else
2162*7c478bd9Sstevel@tonic-gate &gssapi_client_mech_step, /* mech_step */
2163*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ && GSSAPI_PROTECT */
2164*7c478bd9Sstevel@tonic-gate &gssapi_common_mech_dispose, /* mech_dispose */
2165*7c478bd9Sstevel@tonic-gate NULL, /* mech_free */
2166*7c478bd9Sstevel@tonic-gate NULL, /* idle */
2167*7c478bd9Sstevel@tonic-gate NULL, /* spare */
2168*7c478bd9Sstevel@tonic-gate NULL /* spare */
2169*7c478bd9Sstevel@tonic-gate }
2170*7c478bd9Sstevel@tonic-gate };
2171*7c478bd9Sstevel@tonic-gate
2172*7c478bd9Sstevel@tonic-gate int gssapiv2_client_plug_init(const sasl_utils_t *utils __attribute__((unused)),
2173*7c478bd9Sstevel@tonic-gate int maxversion,
2174*7c478bd9Sstevel@tonic-gate int *out_version,
2175*7c478bd9Sstevel@tonic-gate sasl_client_plug_t **pluglist,
2176*7c478bd9Sstevel@tonic-gate int *plugcount)
2177*7c478bd9Sstevel@tonic-gate {
2178*7c478bd9Sstevel@tonic-gate if (maxversion < SASL_CLIENT_PLUG_VERSION) {
2179*7c478bd9Sstevel@tonic-gate SETERROR(utils, "Version mismatch in GSSAPI");
2180*7c478bd9Sstevel@tonic-gate return SASL_BADVERS;
2181*7c478bd9Sstevel@tonic-gate }
2182*7c478bd9Sstevel@tonic-gate
2183*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
2184*7c478bd9Sstevel@tonic-gate /*
2185*7c478bd9Sstevel@tonic-gate * Let libsasl know that we are a "Sun" plugin so that privacy
2186*7c478bd9Sstevel@tonic-gate * and integrity will be allowed.
2187*7c478bd9Sstevel@tonic-gate */
2188*7c478bd9Sstevel@tonic-gate REG_PLUG("GSSAPI", gssapi_client_plugins);
2189*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
2190*7c478bd9Sstevel@tonic-gate
2191*7c478bd9Sstevel@tonic-gate *out_version = SASL_CLIENT_PLUG_VERSION;
2192*7c478bd9Sstevel@tonic-gate *pluglist = gssapi_client_plugins;
2193*7c478bd9Sstevel@tonic-gate *plugcount = 1;
2194*7c478bd9Sstevel@tonic-gate
2195*7c478bd9Sstevel@tonic-gate return SASL_OK;
2196*7c478bd9Sstevel@tonic-gate }
2197