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