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 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 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 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 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 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