/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2011 Bayard G. Bell. All rights reserved.
*/
/*
* A module that implements a dummy security mechanism.
* It's mainly used to test GSS-API application. Multiple tokens
* exchanged during security context establishment can be
* specified through dummy_mech.conf located in /etc.
*/
#include <gssapiP_dummy.h>
#include <gssapi_err_generic.h>
#include <mechglueP.h>
#include <gssapi/kgssapi_defs.h>
#ifdef DUMMY_MECH_DEBUG
/*
* Kernel kgssd module debugging aid. The global variable "dummy_mech_log"
* is a bit mask which allows various types of debugging messages
* to be printed out.
*
* dummy_mech_log & 1 will cause actual failures to be printed.
* dummy_mech_log & 2 will cause informational messages to be
* printed on the client side of kgssd.
* dummy_mech_log & 4 will cause informational messages to be
* printed on the server side of kgssd.
* dummy_mech_log & 8 will cause informational messages to be
* printed on both client and server side of kgssd.
*/
#endif
/* Local defines */
/* private routines for dummy_mechanism */
static int der_length_size(int);
static void der_write_length(unsigned char **, int);
static int der_read_length(unsigned char **, int *);
int toksize);
/* private global variables */
static int dummy_token_nums;
/*
* This OID:
* { iso(1) org(3) internet(6) dod(1) private(4) enterprises(1) sun(42)
* products(2) gssapi(26) mechtypes(1) dummy(2) }
*/
{{10, "\053\006\001\004\001\052\002\032\001\002"},
NULL, /* context */
NULL, /* next */
TRUE, /* uses_kmod */
};
static gss_mechanism
{
dprintf("Entering gss_mech_initialize\n");
if (dummy_token_nums == 0)
dummy_token_nums = 1;
dprintf("Leaving gss_mech_initialize\n");
return (&dummy_mechanism);
}
/*
* Clean up after a failed mod_install()
*/
static void
{
/* Nothing to do */
}
/*
* Module linkage information for the kernel.
*/
extern struct mod_ops mod_miscops;
&mod_miscops, "in-kernel dummy GSS mechanism"
};
(void *)&modlmisc,
};
int
_init()
{
int retval;
mech = gss_mech_initialize();
"dummy GSS mechanism: mechanism already in table.\n");
"table supports kernel operations!\n");
}
/*
* keep us loaded, but let us be unloadable. This
* will give the developer time to trouble shoot
*/
dummy_fini_code = 0;
} else {
}
gss_mech_fini(); /* clean up */
return (retval);
}
int
_fini()
{
if (ret == 0) {
}
return (ret);
}
int
{
}
/*ARGSUSED*/
static OM_uint32
void *context;
int qop_req;
{
dprintf("Entering gss_sign\n");
if (context_handle == GSS_C_NO_CONTEXT)
return (GSS_S_NO_CONTEXT);
dprintf("Leaving gss_sign\n");
return (GSS_S_COMPLETE);
}
/*ARGSUSED*/
static OM_uint32
void *context;
int *qop_state;
{
unsigned char *ptr;
int bodysize;
int err;
dprintf("Entering gss_verify\n");
if (context_handle == GSS_C_NO_CONTEXT)
return (GSS_S_NO_CONTEXT);
/* Check for defective input token. */
&ptr, 0,
token_buffer->length)) {
*minor_status = err;
return (GSS_S_DEFECTIVE_TOKEN);
}
dprintf("Leaving gss_verify\n");
return (GSS_S_COMPLETE);
}
/*ARGSUSED*/
static OM_uint32
void *context;
int conf_req_flag;
int qop_req;
int *conf_state;
{
dprintf("Entering gss_seal\n");
if (context_handle == GSS_C_NO_CONTEXT)
return (GSS_S_NO_CONTEXT);
/* Copy the input message to output message */
if (conf_state)
*conf_state = 1;
dprintf("Leaving gss_seal\n");
return (GSS_S_COMPLETE);
}
/*ARGSUSED*/
static OM_uint32
void *context;
int *conf_state;
int *qop_state;
{
unsigned char *ptr;
int bodysize;
int err;
dprintf("Entering gss_unseal\n");
if (context_handle == GSS_C_NO_CONTEXT)
return (GSS_S_NO_CONTEXT);
&ptr, 0,
*minor_status = err;
return (GSS_S_DEFECTIVE_TOKEN);
}
if (conf_state)
*conf_state = 1;
dprintf("Leaving gss_unseal\n");
return (GSS_S_COMPLETE);
}
/*ARGSUSED*/
void *ct;
{
unsigned char *ptr;
int bodysize;
int err;
/* Assume that we got ctx from the interprocess token. */
dprintf("Entering import_sec_context\n");
&ptr, 0,
interprocess_token->length)) {
*minor_status = err;
return (GSS_S_DEFECTIVE_TOKEN);
}
dprintf("Leaving import_sec_context\n");
return (GSS_S_COMPLETE);
}
/*ARGSUSED*/
static OM_uint32
void *ct;
{
dprintf("Entering delete_sec_context\n");
/* Make the length to 0, so the output token is not sent to peer */
if (output_token) {
output_token->length = 0;
}
if (*context_handle == GSS_C_NO_CONTEXT) {
*minor_status = 0;
return (GSS_S_COMPLETE);
}
dprintf("Leaving delete_sec_context\n");
return (GSS_S_COMPLETE);
}
static int
{
return (1);
return (2);
return (3);
return (4);
else
return (5);
}
static void
{
} else {
}
}
static int
unsigned char **buf;
int *bufsize;
{
unsigned char sf;
int ret;
if (*bufsize < 1)
return (-1);
(*bufsize)--;
if (sf & 0x80) {
return (-1);
if (sf > DUMMY_SIZE_OF_INT)
return (-1);
ret = 0;
(*bufsize)--;
}
} else {
}
return (ret);
}
static int
unsigned int body_size;
{
/* set body_size to sequence contents size */
}
static void
int body_size;
unsigned char **buf;
int tok_type;
{
*(*buf)++ = 0x60;
*(*buf)++ = 0x06;
}
static int
int *body_size;
unsigned char **buf_in;
int tok_type;
int toksize;
{
int seqsize;
int ret = 0;
if ((toksize -= 1) < 0)
return (G_BAD_TOK_HEADER);
if (*buf++ != 0x60)
return (G_BAD_TOK_HEADER);
return (G_BAD_TOK_HEADER);
return (G_BAD_TOK_HEADER);
if ((toksize -= 1) < 0)
return (G_BAD_TOK_HEADER);
if (*buf++ != 0x06)
return (G_BAD_TOK_HEADER);
if ((toksize -= 1) < 0)
return (G_BAD_TOK_HEADER);
return (G_BAD_TOK_HEADER);
ret = G_WRONG_MECH;
/*
* G_WRONG_MECH is not returned immediately because it's more important
* to return G_BAD_TOK_HEADER if the token header is in fact bad
*/
if ((toksize -= 2) < 0)
return (G_BAD_TOK_HEADER);
return (G_BAD_TOK_HEADER);
if (!ret) {
}
return (ret);
}
static gss_buffer_desc
{
int tlen;
unsigned char *t;
unsigned char *ptr;
return (buffer);
}
ptr = t;
return (buffer);
}