📄 gssapi.c
字号:
#ifdef BUILD_GSSAPI_PLUGIN/* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) * $Id$ *//* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "Carnegie Mellon University" must not be used to * endorse or promote products derived from this software without * prior written permission. For permission or any other legal * details, please contact * Office of Technology Transfer * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, PA 15213-3890 * (412) 268-4387, fax: (412) 268-7395 * tech-transfer@andrew.cmu.edu * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Computing Services * at Carnegie Mellon University (http://www.cmu.edu/computing/)." * * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */#include <stdlib.h>#include <string.h>#include <dlfcn.h>#ifdef HAVE_GSSAPI_H#include <gssapi.h>#else#include <gssapi/gssapi.h>#endif#ifdef WIN32# include <winsock2.h># ifndef R_OK# define R_OK 04# endif/* we also need io.h for access() prototype */# include <io.h>#else# include <sys/param.h># include <sys/socket.h># include <netinet/in.h># include <arpa/inet.h># include <netdb.h>#endif /* WIN32 */#include <fcntl.h>#include <stdio.h>#include <sys/uio.h>#include <sasl.h>#include <saslutil.h>#include <saslplug.h>#include "plugin_common.h"#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <errno.h>/***************************** Common Section *****************************/static const char plugin_id[] = "$Id$";static const char * GSSAPI_BLANK_STRING = "";#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICEextern gss_OID gss_nt_service_name;#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name#endif#ifdef WANT_KERBEROS5_3DES/* Check if CyberSafe flag is defined */#ifdef CSF_GSS_C_DES3_FLAG#define K5_MAX_SSF 112#endif/* Heimdal and MIT use the following */#ifdef GSS_KRB5_CONF_C_QOP_DES3_KD#define K5_MAX_SSF 112#endif#endif#ifndef K5_MAX_SSF/* All Kerberos implementations support DES */#define K5_MAX_SSF 56#endif/* GSSAPI SASL Mechanism by Leif Johansson <leifj@matematik.su.se> * inspired by the kerberos mechanism and the gssapi_server and * gssapi_client from the heimdal distribution by Assar Westerlund * <assar@sics.se> and Johan Danielsson <joda@pdc.kth.se>. * See the configure.in file for details on dependencies. * * Important contributions from Sam Hartman <hartmans@fundsxpress.com>. * * This code was tested with the following distributions of Kerberos: * Heimdal (http://www.pdc.kth.se/heimdal), MIT (http://web.mit.edu/kerberos/www/) * CyberSafe (http://www.cybersafe.com/) and SEAM. */typedef struct context { int state; gss_ctx_id_t gss_ctx; gss_name_t client_name; gss_name_t server_name; gss_cred_id_t server_creds; sasl_ssf_t limitssf, requiressf; /* application defined bounds, for the server */ const sasl_utils_t *utils; /* layers buffering */ decode_context_t decode_context; char *encode_buf; /* For encoding/decoding mem management */ char *decode_buf; char *decode_once_buf; unsigned encode_buf_len; unsigned decode_buf_len; unsigned decode_once_buf_len; buffer_info_t *enc_in_buf; char *out_buf; /* per-step mem management */ unsigned out_buf_len; char *authid; /* hold the authid between steps - server */ const char *user; /* hold the userid between steps - client */} context_t;enum { SASL_GSSAPI_STATE_AUTHNEG = 1, SASL_GSSAPI_STATE_SSFCAP = 2, SASL_GSSAPI_STATE_SSFREQ = 3, SASL_GSSAPI_STATE_AUTHENTICATED = 4};/* sasl_gss_log: only logs status string returned from gss_display_status() */#define sasl_gss_log(x,y,z) sasl_gss_seterror_(x,y,z,1)#define sasl_gss_seterror(x,y,z) sasl_gss_seterror_(x,y,z,0)/* Force use of Kerberos v5 GSSAPI library functions even when linked with GSI GSSAPI libraries. */#ifndef KRB5_LIB_NAME#define KRB5_LIB_NAME "libgssapi_krb5.so"#endif /* KRB5_LIB_NAME */static void *h_krb5lib;static OM_uint32 (*p_krb5_gss_accept_sec_context) (OM_uint32 *, gss_ctx_id_t *, gss_cred_id_t, gss_buffer_t, gss_channel_bindings_t, gss_name_t *, gss_OID *, gss_buffer_t, OM_uint32 *, OM_uint32 *, gss_cred_id_t *);static OM_uint32 (*p_krb5_gss_acquire_cred) (OM_uint32 *, gss_name_t, OM_uint32, gss_OID_set, gss_cred_usage_t, gss_cred_id_t *, gss_OID_set *, OM_uint32 *);static OM_uint32 (*p_krb5_gss_compare_name) (OM_uint32 *, gss_name_t, gss_name_t, int *);static OM_uint32 (*p_krb5_gss_delete_sec_context) (OM_uint32 *, gss_ctx_id_t *, gss_buffer_t);static OM_uint32 (*p_krb5_gss_display_name) (OM_uint32 *, gss_name_t, gss_buffer_t, gss_OID *);static OM_uint32 (*p_krb5_gss_display_status) (OM_uint32 *, OM_uint32, int, gss_OID, OM_uint32 *, gss_buffer_t);static OM_uint32 (*p_krb5_gss_import_name) (OM_uint32 *, gss_buffer_t, gss_OID, gss_name_t *);static OM_uint32 (*p_krb5_gss_init_sec_context) (OM_uint32 *, const gss_cred_id_t, gss_ctx_id_t *, const gss_name_t, const gss_OID, OM_uint32, OM_uint32, const gss_channel_bindings_t, const gss_buffer_t, gss_OID *, gss_buffer_t, OM_uint32 *, OM_uint32 *);static OM_uint32 (*p_krb5_gss_inquire_context) (OM_uint32 *, gss_ctx_id_t, gss_name_t *, gss_name_t *, OM_uint32 *, gss_OID *, OM_uint32 *, int *, int *);static OM_uint32 (*p_krb5_gss_release_buffer)(OM_uint32 *, gss_buffer_t);static OM_uint32 (*p_krb5_gss_release_cred) (OM_uint32 *, gss_cred_id_t *);static OM_uint32 (*p_krb5_gss_release_name)(OM_uint32 *, gss_name_t *);static OM_uint32 (*p_krb5_gss_unwrap) (OM_uint32 *, gss_ctx_id_t, gss_buffer_t, gss_buffer_t, int *, gss_qop_t *);static OM_uint32 (*p_krb5_gss_wrap) (OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, gss_buffer_t, int *, gss_buffer_t);static OM_uint32 (*p_krb5_gss_wrap_size_limit) (OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, OM_uint32, OM_uint32 *);static intsasl_gss_lib_init(const sasl_utils_t *utils){ char *errmsg=NULL, *dlerr=NULL; if (h_krb5lib) return SASL_OK; if ((h_krb5lib = dlopen(KRB5_LIB_NAME, RTLD_LAZY)) == NULL) { errmsg = "Failed to open GSSAPI library"; goto error; }#define SASL_GSS_DLSYM(x) \ p_krb5_ ## x = dlsym(h_krb5lib, #x); \ if (p_krb5_ ## x == NULL) { \ errmsg = "Failed to dlsym(" #x ")"; \ goto error; \ } SASL_GSS_DLSYM(gss_accept_sec_context); SASL_GSS_DLSYM(gss_acquire_cred); SASL_GSS_DLSYM(gss_compare_name); SASL_GSS_DLSYM(gss_delete_sec_context); SASL_GSS_DLSYM(gss_display_name); SASL_GSS_DLSYM(gss_display_status); SASL_GSS_DLSYM(gss_import_name); SASL_GSS_DLSYM(gss_init_sec_context); SASL_GSS_DLSYM(gss_inquire_context); SASL_GSS_DLSYM(gss_release_buffer); SASL_GSS_DLSYM(gss_release_cred); SASL_GSS_DLSYM(gss_release_name); SASL_GSS_DLSYM(gss_unwrap); SASL_GSS_DLSYM(gss_wrap); SASL_GSS_DLSYM(gss_wrap_size_limit); return SASL_OK; error: dlerr = dlerror(); if (dlerr) { char *saslerr; saslerr = malloc(strlen(errmsg)+strlen(dlerr)+3); sprintf(saslerr, "%s: %s", errmsg, dlerr); SETERROR(utils, saslerr); free(saslerr); } else { SETERROR(utils, errmsg); } if (h_krb5lib) { dlclose(h_krb5lib); h_krb5lib = NULL; } return SASL_FAIL;}static voidsasl_gss_seterror_(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min, int logonly){ OM_uint32 maj_stat, min_stat; gss_buffer_desc msg; OM_uint32 msg_ctx; int ret; char *out = NULL; size_t len, curlen = 0; const char prefix[] = "GSSAPI Error: "; if(!utils) return; if (sasl_gss_lib_init(utils) != SASL_OK) return; len = sizeof(prefix); ret = _plug_buf_alloc(utils, &out, &curlen, 256); if(ret != SASL_OK) return; strcpy(out, prefix); msg_ctx = 0; while (1) { maj_stat = (*p_krb5_gss_display_status)(&min_stat, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &msg); if(GSS_ERROR(maj_stat)) { if (logonly) { utils->log(utils->conn, SASL_LOG_FAIL, "GSSAPI Failure: (could not get major error message)"); } else { utils->seterror(utils->conn, 0, "GSSAPI Failure " "(could not get major error message)"); } utils->free(out); return; } len += len + msg.length; ret = _plug_buf_alloc(utils, &out, &curlen, len); if(ret != SASL_OK) { utils->free(out); return; } strcat(out, msg.value); (*p_krb5_gss_release_buffer)(&min_stat, &msg); if (!msg_ctx) break; } /* Now get the minor status */ len += 2; ret = _plug_buf_alloc(utils, &out, &curlen, len); if(ret != SASL_OK) { utils->free(out); return; } strcat(out, " ("); msg_ctx = 0; while (1) { maj_stat = (*p_krb5_gss_display_status)(&min_stat, min, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &msg); if(GSS_ERROR(maj_stat)) { if (logonly) { utils->log(utils->conn, SASL_LOG_FAIL, "GSSAPI Failure: (could not get minor error message)"); } else { utils->seterror(utils->conn, 0, "GSSAPI Failure " "(could not get minor error message)"); } utils->free(out); return; } len += len + msg.length; ret = _plug_buf_alloc(utils, &out, &curlen, len); if(ret != SASL_OK) { utils->free(out); return; } strcat(out, msg.value); (*p_krb5_gss_release_buffer)(&min_stat, &msg); if (!msg_ctx) break; } len += 1; ret = _plug_buf_alloc(utils, &out, &curlen, len); if(ret != SASL_OK) { utils->free(out); return; } strcat(out, ")"); if (logonly) { utils->log(utils->conn, SASL_LOG_FAIL, out); } else { utils->seterror(utils->conn, 0, out); } utils->free(out);}static int sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, const char **output, unsigned *outputlen, int privacy){ context_t *text = (context_t *)context; OM_uint32 maj_stat, min_stat; gss_buffer_t input_token, output_token; gss_buffer_desc real_input_token, real_output_token; int ret; struct buffer_info *inblob, bufinfo; if(!output) return SASL_BADPARAM; if (sasl_gss_lib_init(text->utils) != SASL_OK) return SASL_FAIL; if(numiov > 1) { ret = _plug_iovec_to_buf(text->utils, invec, numiov, &text->enc_in_buf); if(ret != SASL_OK) return ret; inblob = text->enc_in_buf; } else { bufinfo.data = invec[0].iov_base; bufinfo.curlen = invec[0].iov_len; inblob = &bufinfo; } if (text->state != SASL_GSSAPI_STATE_AUTHENTICATED) return SASL_NOTDONE; input_token = &real_input_token; real_input_token.value = inblob->data; real_input_token.length = inblob->curlen; output_token = &real_output_token; output_token->value = NULL; output_token->length = 0; maj_stat = (*p_krb5_gss_wrap) (&min_stat, text->gss_ctx, privacy,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -