/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
*
* $Header:
* 1.14 1995/03/22 22:07:55 jik Exp $
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#include <pthread.h>
#include <thread.h>
#include <syslog.h>
#include <rpc/rpcsec_defs.h>
static void rpc_gss_nextverf();
static bool_t rpc_gss_marshall();
static bool_t rpc_gss_validate();
static bool_t rpc_gss_refresh();
static void rpc_gss_destroy();
static void rpc_gss_destroy_pvt();
static bool_t rpc_gss_seccreate_pvt();
static bool_t validate_seqwin();
/*
* Globals that should have header files but don't.
*/
};
/*
* Private data for RPCSEC_GSS.
*/
typedef struct _rpc_gss_data {
/* validating the sequence window */
} rpc_gss_data;
/*
* Create a context.
*/
AUTH *
char *server_name; /* target server */
char *mech; /* security mechanism */
char *qop; /* requested QOP */
{
/*
* convert ascii strings to GSS values
*/
return (NULL);
}
return (NULL);
}
/*
* convert name to GSS internal type
*/
&target_name);
if (gssstat != GSS_S_COMPLETE) {
return (NULL);
}
/*
* Create AUTH handle. Save the necessary interface information
* so that the client can refresh the handle later if needed.
*/
return (NULL);
}
if (options_req != NULL) {
} else {
}
/*
* Now invoke the real interface that sets up the context from
* the information stashed away in the private data.
*/
if (ap->target_name)
return (NULL);
}
/*
* Make sure that the requested service is supported. In all
* cases, integrity service must be available.
*/
!(ret_flags & GSS_C_CONF_FLAG)) ||
!(ret_flags & GSS_C_INTEG_FLAG)) {
return (NULL);
}
/*
* return option values if requested
*/
if (options_ret != NULL) {
char *s;
else
}
return (auth);
}
/*
* Private interface to create a context. This is the interface
* that's invoked when the context has to be refreshed.
*/
static bool_t
{
/*
* initialize error
*/
/*
* (re)initialize AUTH handle and private data.
*/
/*
* should not change clnt->cl_auth at this time, so save
* old handle
*/
/*
* set state for starting context setup
*/
NULL,
&call_arg,
time_rec);
if (input_token_p != GSS_C_NO_BUFFER) {
}
goto cleanup;
}
/*
* if we got a token, pass it on
*/
timeout);
if (callstat != RPC_SUCCESS) {
goto cleanup;
}
/*
* we have results - note that these need to be freed
*/
free_results = TRUE;
goto cleanup;
/*
* check for ctx_handle
*/
goto cleanup;
goto cleanup;
/*
* check for token
*/
if (*gssstat == GSS_S_COMPLETE)
goto cleanup;
} else if (*gssstat != GSS_S_COMPLETE)
goto cleanup;
/* save the sequence window value; validate later */
}
/*
* results were okay.. continue if necessary
*/
if (*gssstat == GSS_S_CONTINUE_NEEDED)
goto next_token;
/*
* Validate the sequence window - RFC 2203 section 5.2.3.1
*/
if (!validate_seqwin(ap)) {
goto cleanup;
}
/*
* Done! Security context creation is successful.
* Ready for exchanging data.
*/
return (TRUE);
if (free_results)
/*
* if (rpc_createerr.cf_stat == 0)
* rpc_createerr.cf_stat = RPC_AUTHERROR;
*/
if (rpc_createerr.cf_stat == 0) {
}
return (FALSE);
}
/*
* Set service defaults.
*/
char *qop;
{
/*LINTED*/
char *mech;
switch (service) {
case rpc_gss_svc_integrity:
case rpc_gss_svc_privacy:
case rpc_gss_svc_none:
break;
case rpc_gss_svc_default:
break;
default:
return (FALSE);
}
return (FALSE);
return (FALSE);
return (TRUE);
}
/*
* Marshall credentials.
*/
static bool_t
{
/*
* If context has not been set up yet, use NULL handle.
*/
else {
}
return (FALSE);
}
return (FALSE);
return (TRUE);
}
/*
* Marshall verifier. The verifier is the checksum of the RPC header
* up to and including the credential field. The XDR handle that's
* passed in has the header up to and including the credential field
* encoded. A pointer to the transmit buffer is also passed in.
*/
static bool_t
char *buf; /* pointer of send buffer */
{
/*
* If context is not established yet, use NULL verifier.
*/
if (!ap->established) {
}
&out_buf)) != GSS_S_COMPLETE) {
if (major == GSS_S_CONTEXT_EXPIRED) {
}
return (FALSE);
}
return (ret);
}
/*
* Function: rpc_gss_nextverf. Not used.
*/
static void
{
}
/*
* Function: rpc_gss_marshall - not used.
*/
static bool_t
{
return (FALSE);
return (TRUE);
}
/*
* Validate sequence window upon a successful RPCSEC_GSS INIT session.
* The sequence window sent back by the server should be verifiable by
* the verifier which is a checksum of the sequence window.
*/
static bool_t
{
int qop_state = 0;
if (major != GSS_S_COMPLETE)
return (FALSE);
return (TRUE);
}
/*
* Validate RPC response verifier from server. The response verifier
* is the checksum of the request sequence number.
*/
static bool_t
struct opaque_auth *verf;
{
/*LINTED*/
int qop_state;
/*
* If context is not established yet, save the verifier for
* validating the sequence window later at the end of context
* creation session.
*/
if (!ap->established) {
} else {
}
return (TRUE);
}
if (major != GSS_S_COMPLETE)
return (FALSE);
return (TRUE);
}
/*
* Refresh client context. This is necessary sometimes because the
* server will ocassionally destroy contexts based on LRU method, or
* because of expired credentials.
*/
static bool_t
{
/*LINTED*/
/*
* The context needs to be recreated only when the error status
* returned from the server is one of the following:
* RPCSEC_GSS_NOCRED and RPCSEC_GSS_FAILED
* The existing context should not be destroyed unless the above
* error status codes are received or if the context has not
* been set up.
*/
!ap->established) {
/*
* Destroy the context if necessary. Use the same memory
* for the new context since we've already passed a pointer
* to it to the user.
*/
NULL);
}
(void) gss_release_buffer(&minor_stat,
&ap->ctx_handle);
}
/*
* If the context was not already established, don't try to
* recreate it.
*/
if (!ap->established) {
return (FALSE);
}
/*
* Recreate context.
*/
return (TRUE);
else {
return (FALSE);
}
}
return (FALSE);
}
/*
* Destroy a context.
*/
static void
{
/*LINTED*/
}
/*
* Private interface to destroy a context without freeing up
* the memory used by it. We need to do this when a refresh
* fails, for example, so the user will still have a handle.
*/
static void
{
/*LINTED*/
/*
* If we have a server context id, inform server that we are
* destroying the context.
*/
}
/*
* Destroy local GSS context.
*/
}
/*
* Looks like we need to release default credentials if we use it.
* Non-default creds need to be released by user.
*/
/*
* Release any internal name structures.
*/
}
/*
* Free the verifier saved for sequence window checking.
*/
}
}
/*
* Wrap client side data. The encoded header is passed in through
* buf and buflen. The header is up to but not including the
* credential field.
*/
char *buf; /* encoded header */
{
/*LINTED*/
/*
* Reject an invalid context.
*/
return (FALSE);
/*
* If context is established, bump up sequence number.
*/
if (ap->established)
/*
* Create the header in a temporary XDR context and buffer
* before putting it out.
*/
return (FALSE);
/*
* create cred field
*/
return (FALSE);
/*
* create verifier
*/
return (FALSE);
/*
* write out header and destroy temp structures
*/
return (FALSE);
XDR_DESTROY(&xdrs);
/*
* If context is not established, or if neither integrity
* nor privacy is used, just XDR encode data.
*/
}
/*
* Unwrap received data.
*/
{
/*LINTED*/
/*
* If context is not established, of if neither integrity
* nor privacy is used, just XDR encode data.
*/
}
int
int max_tp_unit_len;
{
/*LINTED*/
return (0);
}
void
{
*error = rpc_gss_err;
}
{
if (thr_main())
return (&rpc_gss_err);
return (&rpc_gss_err);
if (tsd)
return (&rpc_gss_err);
}
}
return (tsd);
}