#
# 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
# or http://www.opensolaris.org/os/licensing.
# 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 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# Copyright (c) 2018, Joyent, Inc.
TESTPROG = gssdtest
OUTPUT_OPTION = -I.
PROG= gssd
MANIFEST= gss.xml
GSSD_BASEOBJS = gssd.o gssd_proc.o gssd_generic.o gssd_getuid.o
GSSC_BASEOBJS = gssdtest.o gssd_release_name_and_type.o gssd_clnt_stubs.o \
gssd_handle.o
GD_OBJS = gssd_svc.o
GC_OBJS = gssd_clnt.o
G_OBJS = gssd_xdr.o
GSSDOBJS = $(GSSD_BASEOBJS) $(GD_OBJS) $(G_OBJS)
GSSCOBJS = $(GSSC_BASEOBJS) $(GC_OBJS) $(G_OBJS)
ROBJS = $(GD_OBJS) $(GC_OBJS) $(G_OBJS)
OBJS = $(GSSD_BASEOBJS) $(GD_OBJS) $(GSSC_BASEOBJS) $(GC_OBJS) $(G_OBJS)
SRCS = $(OBJS:.o=.c)
RSRC = $(ROBJS:.o=.c)
RSRC += gssd.h
CLOBBERFILES += $(TESTPROG)
include ../../Makefile.cmd
ROOTMANIFESTDIR= $(ROOTSVCNETWORKRPC)
TEXT_DOMAIN = SUNW_OST_NETRPC
POFILE = $(PROG).po
POFILES = generic.po
#
# Override $ROOTLIB
#
ROOTLIB= $(ROOT)/usr/lib/gss
DIRS= $(ROOTLIB)
CPPFLAGS += -I$(SRC)/uts/common/gssapi/include
CERRWARN += -Wno-unused-variable
CERRWARN += -Wno-implicit-function-declaration
CERRWARN += -Wno-parentheses
CERRWARN += $(CNOWARN_UNINIT)
# Hammerhead: Suppress pointer/int cast warnings in legacy gssd code
CERRWARN += -Wno-pointer-to-int-cast
CERRWARN += -Wno-int-to-pointer-cast
# not linted
SMATCH=off
LDLIBS += -lgss -lnsl
gssd : MAPFILES = $(MAPFILE.INT) $(MAPFILE.NGB)
gssd : LDFLAGS += $(MAPFILES:%=-Wl,-M%)
$(GPROGS) : CPPFLAGS += -DSYSV -DSunOS=50
.KEEP_STATE:
all: $(PROG) $(TESTPROG)
$(ROOTLIB):
$(INS.dir)
$(ROOTLIB)/%: %
$(INS.file)
gssd: $(GSSDOBJS) $$(MAPFILES)
$(LINK.c) $(GSSDOBJS) -o $@ $(LDLIBS)
$(POST_PROCESS)
gssdtest: $(GSSCOBJS)
$(LINK.c) $(GSSCOBJS) -o $@ $(LDLIBS)
$(POST_PROCESS)
GSSDX= $(SRC)/uts/common/gssapi/gssd.x
gssd.x: $(GSSDX)
rm -f $@
cp $(GSSDX) $@
# Hammerhead: pre-generated (rpcgen + GNU cpp truncation bug)
# gssd.h, gssd_clnt.c, gssd_svc.c, gssd_xdr.c are now committed source files.
$(OBJS): gssd.h
install: all $(DIRS) $(ROOTLIBPROG) $(ROOTMANIFEST)
install_h:
clean:
$(RM) $(OBJS) gssd.x
@# Hammerhead: do not delete pre-generated $(RSRC)
check: $(CHKMANIFEST)
include ../../Makefile.targ
$(POFILE): $(DERIVED_FILES) .WAIT $(POFILES)
$(RM) $@
$(CAT) $(POFILES) > $@
generic.po: FRC
$(RM) messages.po
$(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext *.[ch]`
$(SED) "/^domain/d" messages.po > $@
$(RM) messages.po
FRC:
Generic Security Service
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Usermode daemon which assists the kernel when handling gssapi calls.
* It is gssd that actually implements all gssapi calls.
* Some calls, such as gss_sign, are implemented in the kernel on a per
* mechanism basis.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gssd.h"
int gssd_debug = 0; /* enable debugging printfs */
extern void gsscred_set_options(void);
void gssprog_1();
void gssd_setup(char *);
static void usage(void);
static void daemonize_start();
static void daemonize_ready(unsigned char status);
extern int svc_create_local_service();
/* following declarations needed in rpcgen-generated code */
int _rpcpmstart = 0; /* Started by a port monitor ? */
int _rpcfdtype; /* Whether Stream or Datagram ? */
int _rpcsvcdirty; /* Still serving ? */
mutex_t _svcstate_lock = ERRORCHECKMUTEX;
static void
/* LINTED */
catch_hup(int sig_num)
{
sigset_t mask_set; /* used to set a signal masking set. */
sigset_t old_set; /* used to store the old mask set. */
/* re-set the signal handler again to catch_hup, for next time */
(void) signal(SIGHUP, catch_hup);
/* mask any further signals while we're inside the handler. */
(void) sigfillset(&mask_set);
(void) sigprocmask(SIG_SETMASK, &mask_set, &old_set);
gsscred_set_options();
/* let admin know the sighup was caught and conf file re-read */
syslog(LOG_INFO,
"catch_hup: read gsscred.conf opts");
if (gssd_debug)
(void) fprintf(stderr, "catch_hup: read gsscred.conf opts");
(void) sigprocmask(SIG_SETMASK, &old_set, NULL);
}
int
main(int argc, char **argv)
{
register SVCXPRT *transp;
int maxrecsz = RPC_MAXDATASIZE;
extern int optind;
int c;
char mname[FMNAMESZ + 1];
/* set locale and domain for internationalization */
setlocale(LC_ALL, "");
textdomain(TEXT_DOMAIN);
/*
* Take special note that "getuid()" is called here. This call is used
* rather than app_krb5_user_uid(), to ensure gssd(8) is running as
* root.
*/
#ifdef DEBUG
(void) setuid(0); /* DEBUG: set ruid to root */
#endif /* DEBUG */
if (getuid()) {
(void) fprintf(stderr,
gettext("[%s] must be run as root\n"), argv[0]);
#ifdef DEBUG
(void) fprintf(stderr, gettext(" warning only\n"));
#else /* DEBUG */
exit(1);
#endif /* DEBUG */
}
gssd_setup(argv[0]);
while ((c = getopt(argc, argv, "d")) != -1)
switch (c) {
case 'd':
/* turn on debugging */
gssd_debug = 1;
break;
default:
usage();
}
if (optind != argc) {
usage();
}
gsscred_set_options();
(void) signal(SIGHUP, catch_hup);
/*
* Started by inetd if name of module just below stream
* head is either a sockmod or timod.
*/
if (!ioctl(0, I_LOOK, mname) && ((strcmp(mname, "sockmod") == 0) ||
(strcmp(mname, "timod") == 0))) {
char *netid;
struct netconfig *nconf;
openlog("gssd", LOG_PID, LOG_DAEMON);
if ((netid = getenv("NLSPROVIDER")) == NULL) {
netid = "ticotsord";
}
if ((nconf = getnetconfigent(netid)) == NULL) {
syslog(LOG_ERR, gettext("cannot get transport info"));
exit(1);
}
if (strcmp(mname, "sockmod") == 0) {
if (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, "timod")) {
syslog(LOG_ERR,
gettext("could not get the "
"right module"));
exit(1);
}
}
if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
syslog(LOG_ERR,
gettext("unable to set RPC max record size"));
exit(1);
}
/* XXX - is nconf even needed here? */
if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
syslog(LOG_ERR, gettext("cannot create server handle"));
exit(1);
}
/*
* We use a NULL nconf because GSSPROG has already been
* registered with rpcbind.
*/
if (!svc_reg(transp, GSSPROG, GSSVERS, gssprog_1, NULL)) {
syslog(LOG_ERR,
gettext("unable to register "
"(GSSPROG, GSSVERS)"));
exit(1);
}
if (nconf)
freenetconfigent(nconf);
} else {
if (!gssd_debug)
daemonize_start();
openlog("gssd", LOG_PID, LOG_DAEMON);
if (svc_create_local_service(gssprog_1, GSSPROG, GSSVERS,
"netpath", "gssd") == 0) {
syslog(LOG_ERR, gettext("unable to create service"));
exit(1);
}
/* service created, now the daemon parent can exit */
daemonize_ready(0);
}
if (gssd_debug) {
fprintf(stderr,
gettext("gssd start: \n"));
}
svc_run();
abort();
/*NOTREACHED*/
#ifdef lint
return (1);
#endif
}
static void
usage(void)
{
(void) fprintf(stderr, gettext("usage: gssd [-dg]\n"));
exit(1);
}
/*
* Fork, detach from tty, etc...
*/
static int write_pipe_fd = -1;
static
void
daemonize_start()
{
int pipe_fds[2];
unsigned char status = 1;
closefrom(0);
/* Open stdin/out/err, chdir, get a pipe */
if (open("/dev/null", O_RDONLY) < 0 ||
open("/dev/null", O_WRONLY) < 0 || dup(1) < 0 ||
chdir("/") < 0 || pipe(pipe_fds) < 0)
exit(1);
/* For daemonize_ready() */
write_pipe_fd = pipe_fds[1];
switch (fork()) {
case -1:
exit(1);
/* NOTREACHED */
case 0:
break;
default:
/* Wait for child to be ready befor exiting */
(void) close(pipe_fds[1]);
(void) signal(SIGPIPE, SIG_DFL);
(void) read(pipe_fds[0], &status, sizeof (status));
exit(status);
}
(void) close(pipe_fds[0]);
(void) setsid();
}
static
void
daemonize_ready(unsigned char status)
{
if (write_pipe_fd == -1)
return;
(void) write(write_pipe_fd, &status, sizeof (status));
(void) close(write_pipe_fd);
write_pipe_fd = -1;
}
/*ARGSUSED*/
int
gssprog_1_freeresult(SVCXPRT *transport, xdrproc_t xdr_res, caddr_t res)
{
xdr_free(xdr_res, res);
return (1);
}
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#ifndef _GSSD_H_RPCGEN
#define _GSSD_H_RPCGEN
#include
#ifndef _KERNEL
#include
#include
#endif /* !_KERNEL */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* RPC protocol information for gssd, the usermode daemon that
* assists the kernel with gssapi. It is gssd that executes all
* gssapi calls except for some such as gss_sign(), and
* gss_verify(), which are executed in the kernel itself.
*
* File generated from gssd.x
*/
#define NO 0
#define YES 1
#define FOREVER 1
#include
#include
#include
#ifndef _KERNEL
#include
#endif /* not _KERNEL */
#ifdef _KERNEL
extern void killgssd_handle(CLIENT *);
extern CLIENT *getgssd_handle(void);
#endif /* _KERNEL */
typedef u_int OM_UINT32;
typedef struct {
u_int GSS_CTX_ID_T_len;
char *GSS_CTX_ID_T_val;
} GSS_CTX_ID_T;
typedef struct {
u_int GSS_CRED_ID_T_len;
char *GSS_CRED_ID_T_val;
} GSS_CRED_ID_T;
typedef struct {
u_int GSS_OID_len;
char *GSS_OID_val;
} GSS_OID;
typedef struct {
u_int GSS_BUFFER_T_len;
char *GSS_BUFFER_T_val;
} GSS_BUFFER_T;
typedef struct {
u_int GSSCRED_GIDS_len;
gid_t *GSSCRED_GIDS_val;
} GSSCRED_GIDS;
typedef struct {
u_int GSS_OID_SET_len;
GSS_OID *GSS_OID_SET_val;
} GSS_OID_SET;
struct GSS_CHANNEL_BINDINGS_STRUCT {
int present;
OM_UINT32 initiator_addrtype;
GSS_BUFFER_T initiator_address;
OM_UINT32 acceptor_addrtype;
GSS_BUFFER_T acceptor_address;
GSS_BUFFER_T application_data;
};
typedef struct GSS_CHANNEL_BINDINGS_STRUCT GSS_CHANNEL_BINDINGS_STRUCT;
typedef GSS_CHANNEL_BINDINGS_STRUCT GSS_CHANNEL_BINDINGS;
struct gss_acquire_cred_arg {
uid_t uid;
GSS_BUFFER_T desired_name;
GSS_OID name_type;
OM_UINT32 time_req;
GSS_OID_SET desired_mechs;
int cred_usage;
};
typedef struct gss_acquire_cred_arg gss_acquire_cred_arg;
struct gss_acquire_cred_res {
OM_UINT32 minor_status;
GSS_CRED_ID_T output_cred_handle;
OM_UINT32 gssd_cred_verifier;
GSS_OID_SET actual_mechs;
OM_UINT32 time_rec;
OM_UINT32 status;
};
typedef struct gss_acquire_cred_res gss_acquire_cred_res;
struct gss_add_cred_arg {
uid_t uid;
GSS_CRED_ID_T input_cred_handle;
OM_UINT32 gssd_cred_verifier;
GSS_BUFFER_T desired_name;
GSS_OID name_type;
GSS_OID desired_mech_type;
int cred_usage;
OM_UINT32 initiator_time_req;
OM_UINT32 acceptor_time_req;
};
typedef struct gss_add_cred_arg gss_add_cred_arg;
struct gss_add_cred_res {
OM_UINT32 minor_status;
GSS_OID_SET actual_mechs;
OM_UINT32 initiator_time_rec;
OM_UINT32 acceptor_time_rec;
OM_UINT32 status;
};
typedef struct gss_add_cred_res gss_add_cred_res;
struct gss_release_cred_arg {
uid_t uid;
OM_UINT32 gssd_cred_verifier;
GSS_CRED_ID_T cred_handle;
};
typedef struct gss_release_cred_arg gss_release_cred_arg;
struct gss_release_cred_res {
OM_UINT32 minor_status;
OM_UINT32 status;
};
typedef struct gss_release_cred_res gss_release_cred_res;
struct gss_init_sec_context_arg {
uid_t uid;
GSS_CTX_ID_T context_handle;
OM_UINT32 gssd_context_verifier;
GSS_CRED_ID_T claimant_cred_handle;
OM_UINT32 gssd_cred_verifier;
GSS_BUFFER_T target_name;
GSS_OID name_type;
GSS_OID mech_type;
int req_flags;
OM_UINT32 time_req;
GSS_CHANNEL_BINDINGS input_chan_bindings;
GSS_BUFFER_T input_token;
};
typedef struct gss_init_sec_context_arg gss_init_sec_context_arg;
struct gss_init_sec_context_res {
GSS_CTX_ID_T context_handle;
OM_UINT32 gssd_context_verifier;
OM_UINT32 minor_status;
GSS_OID actual_mech_type;
GSS_BUFFER_T output_token;
OM_UINT32 ret_flags;
OM_UINT32 time_rec;
OM_UINT32 status;
};
typedef struct gss_init_sec_context_res gss_init_sec_context_res;
struct gss_accept_sec_context_arg {
uid_t uid;
GSS_CTX_ID_T context_handle;
OM_UINT32 gssd_context_verifier;
GSS_CRED_ID_T verifier_cred_handle;
OM_UINT32 gssd_cred_verifier;
GSS_BUFFER_T input_token_buffer;
GSS_CHANNEL_BINDINGS input_chan_bindings;
};
typedef struct gss_accept_sec_context_arg gss_accept_sec_context_arg;
struct gss_accept_sec_context_res {
GSS_CTX_ID_T context_handle;
OM_UINT32 gssd_context_verifier;
OM_UINT32 minor_status;
GSS_BUFFER_T src_name;
GSS_OID mech_type;
GSS_BUFFER_T output_token;
OM_UINT32 ret_flags;
OM_UINT32 time_rec;
GSS_CRED_ID_T delegated_cred_handle;
OM_UINT32 status;
};
typedef struct gss_accept_sec_context_res gss_accept_sec_context_res;
struct gss_process_context_token_arg {
uid_t uid;
OM_UINT32 gssd_context_verifier;
GSS_CTX_ID_T context_handle;
GSS_BUFFER_T token_buffer;
};
typedef struct gss_process_context_token_arg gss_process_context_token_arg;
struct gss_process_context_token_res {
OM_UINT32 minor_status;
OM_UINT32 status;
};
typedef struct gss_process_context_token_res gss_process_context_token_res;
struct gss_delete_sec_context_arg {
OM_UINT32 gssd_context_verifier;
GSS_CTX_ID_T context_handle;
};
typedef struct gss_delete_sec_context_arg gss_delete_sec_context_arg;
struct gss_delete_sec_context_res {
OM_UINT32 minor_status;
GSS_CTX_ID_T context_handle;
GSS_BUFFER_T output_token;
OM_UINT32 status;
};
typedef struct gss_delete_sec_context_res gss_delete_sec_context_res;
struct gss_export_sec_context_arg {
GSS_CTX_ID_T context_handle;
OM_UINT32 gssd_context_verifier;
};
typedef struct gss_export_sec_context_arg gss_export_sec_context_arg;
struct gss_export_sec_context_res {
OM_UINT32 minor_status;
GSS_CTX_ID_T context_handle;
GSS_BUFFER_T output_token;
OM_UINT32 status;
};
typedef struct gss_export_sec_context_res gss_export_sec_context_res;
struct gss_import_sec_context_arg {
GSS_BUFFER_T input_token;
OM_UINT32 gssd_context_verifier;
};
typedef struct gss_import_sec_context_arg gss_import_sec_context_arg;
struct gss_import_sec_context_res {
OM_UINT32 minor_status;
GSS_CTX_ID_T context_handle;
OM_UINT32 status;
};
typedef struct gss_import_sec_context_res gss_import_sec_context_res;
struct gss_context_time_arg {
uid_t uid;
OM_UINT32 gssd_context_verifier;
GSS_CTX_ID_T context_handle;
};
typedef struct gss_context_time_arg gss_context_time_arg;
struct gss_context_time_res {
OM_UINT32 minor_status;
OM_UINT32 time_rec;
OM_UINT32 status;
};
typedef struct gss_context_time_res gss_context_time_res;
struct gss_sign_arg {
OM_UINT32 gssd_context_verifier;
GSS_CTX_ID_T context_handle;
int qop_req;
GSS_BUFFER_T message_buffer;
};
typedef struct gss_sign_arg gss_sign_arg;
struct gss_sign_res {
OM_UINT32 minor_status;
GSS_BUFFER_T msg_token;
OM_UINT32 status;
};
typedef struct gss_sign_res gss_sign_res;
struct gss_verify_arg {
OM_UINT32 gssd_context_verifier;
GSS_CTX_ID_T context_handle;
GSS_BUFFER_T message_buffer;
GSS_BUFFER_T token_buffer;
};
typedef struct gss_verify_arg gss_verify_arg;
struct gss_verify_res {
OM_UINT32 minor_status;
int qop_state;
OM_UINT32 status;
};
typedef struct gss_verify_res gss_verify_res;
struct gss_seal_arg {
OM_UINT32 gssd_context_verifier;
GSS_CTX_ID_T context_handle;
int conf_req_flag;
int qop_req;
GSS_BUFFER_T input_message_buffer;
};
typedef struct gss_seal_arg gss_seal_arg;
struct gss_seal_res {
OM_UINT32 minor_status;
int conf_state;
GSS_BUFFER_T output_message_buffer;
OM_UINT32 status;
};
typedef struct gss_seal_res gss_seal_res;
struct gss_unseal_arg {
OM_UINT32 gssd_context_verifier;
GSS_CTX_ID_T context_handle;
GSS_BUFFER_T input_message_buffer;
};
typedef struct gss_unseal_arg gss_unseal_arg;
struct gss_unseal_res {
OM_UINT32 minor_status;
GSS_BUFFER_T output_message_buffer;
int conf_state;
int qop_state;
OM_UINT32 status;
};
typedef struct gss_unseal_res gss_unseal_res;
struct gss_display_status_arg {
uid_t uid;
int status_value;
int status_type;
GSS_OID mech_type;
OM_UINT32 message_context;
};
typedef struct gss_display_status_arg gss_display_status_arg;
struct gss_display_status_res {
OM_UINT32 minor_status;
int message_context;
GSS_BUFFER_T status_string;
OM_UINT32 status;
};
typedef struct gss_display_status_res gss_display_status_res;
/* gss_indicate_mechs_arg is void. This appears in the rpc call def */
struct gss_indicate_mechs_res {
OM_UINT32 minor_status;
GSS_OID_SET mech_set;
OM_UINT32 status;
};
typedef struct gss_indicate_mechs_res gss_indicate_mechs_res;
struct gss_inquire_cred_arg {
uid_t uid;
OM_UINT32 gssd_cred_verifier;
GSS_CRED_ID_T cred_handle;
};
typedef struct gss_inquire_cred_arg gss_inquire_cred_arg;
struct gss_inquire_cred_res {
OM_UINT32 minor_status;
GSS_BUFFER_T name;
GSS_OID name_type;
OM_UINT32 lifetime;
int cred_usage;
GSS_OID_SET mechanisms;
OM_UINT32 status;
};
typedef struct gss_inquire_cred_res gss_inquire_cred_res;
struct gss_inquire_cred_by_mech_arg {
uid_t uid;
OM_UINT32 gssd_cred_verifier;
GSS_CRED_ID_T cred_handle;
GSS_OID mech_type;
};
typedef struct gss_inquire_cred_by_mech_arg gss_inquire_cred_by_mech_arg;
struct gss_inquire_cred_by_mech_res {
OM_UINT32 minor_status;
OM_UINT32 status;
};
typedef struct gss_inquire_cred_by_mech_res gss_inquire_cred_by_mech_res;
struct gsscred_name_to_unix_cred_arg {
uid_t uid;
GSS_BUFFER_T pname;
GSS_OID name_type;
GSS_OID mech_type;
};
typedef struct gsscred_name_to_unix_cred_arg gsscred_name_to_unix_cred_arg;
struct gsscred_name_to_unix_cred_res {
uid_t uid;
gid_t gid;
GSSCRED_GIDS gids;
OM_UINT32 major;
};
typedef struct gsscred_name_to_unix_cred_res gsscred_name_to_unix_cred_res;
struct gsscred_expname_to_unix_cred_arg {
uid_t uid;
GSS_BUFFER_T expname;
};
typedef struct gsscred_expname_to_unix_cred_arg gsscred_expname_to_unix_cred_arg;
struct gsscred_expname_to_unix_cred_res {
uid_t uid;
gid_t gid;
GSSCRED_GIDS gids;
OM_UINT32 major;
};
typedef struct gsscred_expname_to_unix_cred_res gsscred_expname_to_unix_cred_res;
struct gss_get_group_info_arg {
uid_t uid;
uid_t puid;
};
typedef struct gss_get_group_info_arg gss_get_group_info_arg;
struct gss_get_group_info_res {
gid_t gid;
GSSCRED_GIDS gids;
OM_UINT32 major;
};
typedef struct gss_get_group_info_res gss_get_group_info_res;
struct gss_get_kmod_arg {
GSS_OID mech_oid;
};
typedef struct gss_get_kmod_arg gss_get_kmod_arg;
struct gss_get_kmod_res {
bool_t module_follow;
union {
char *modname;
} gss_get_kmod_res_u;
};
typedef struct gss_get_kmod_res gss_get_kmod_res;
#define GSSPROG 100234
#define GSSVERS 1
#define GSS_ACQUIRE_CRED 1
extern enum clnt_stat gss_acquire_cred_1();
extern bool_t gss_acquire_cred_1_svc();
#define GSS_RELEASE_CRED 2
extern enum clnt_stat gss_release_cred_1();
extern bool_t gss_release_cred_1_svc();
#define GSS_INIT_SEC_CONTEXT 3
extern enum clnt_stat gss_init_sec_context_1();
extern bool_t gss_init_sec_context_1_svc();
#define GSS_ACCEPT_SEC_CONTEXT 4
extern enum clnt_stat gss_accept_sec_context_1();
extern bool_t gss_accept_sec_context_1_svc();
#define GSS_PROCESS_CONTEXT_TOKEN 5
extern enum clnt_stat gss_process_context_token_1();
extern bool_t gss_process_context_token_1_svc();
#define GSS_DELETE_SEC_CONTEXT 6
extern enum clnt_stat gss_delete_sec_context_1();
extern bool_t gss_delete_sec_context_1_svc();
#define GSS_CONTEXT_TIME 7
extern enum clnt_stat gss_context_time_1();
extern bool_t gss_context_time_1_svc();
#define GSS_SIGN 8
extern enum clnt_stat gss_sign_1();
extern bool_t gss_sign_1_svc();
#define GSS_VERIFY 9
extern enum clnt_stat gss_verify_1();
extern bool_t gss_verify_1_svc();
#define GSS_DISPLAY_STATUS 10
extern enum clnt_stat gss_display_status_1();
extern bool_t gss_display_status_1_svc();
#define GSS_INDICATE_MECHS 11
extern enum clnt_stat gss_indicate_mechs_1();
extern bool_t gss_indicate_mechs_1_svc();
#define GSS_INQUIRE_CRED 12
extern enum clnt_stat gss_inquire_cred_1();
extern bool_t gss_inquire_cred_1_svc();
#define GSS_SEAL 13
extern enum clnt_stat gss_seal_1();
extern bool_t gss_seal_1_svc();
#define GSS_UNSEAL 14
extern enum clnt_stat gss_unseal_1();
extern bool_t gss_unseal_1_svc();
#define GSSCRED_EXPNAME_TO_UNIX_CRED 15
extern enum clnt_stat gsscred_expname_to_unix_cred_1();
extern bool_t gsscred_expname_to_unix_cred_1_svc();
#define GSSCRED_NAME_TO_UNIX_CRED 16
extern enum clnt_stat gsscred_name_to_unix_cred_1();
extern bool_t gsscred_name_to_unix_cred_1_svc();
#define GSS_GET_GROUP_INFO 17
extern enum clnt_stat gss_get_group_info_1();
extern bool_t gss_get_group_info_1_svc();
#define GSS_GET_KMOD 18
extern enum clnt_stat gss_get_kmod_1();
extern bool_t gss_get_kmod_1_svc();
#define GSS_EXPORT_SEC_CONTEXT 19
extern enum clnt_stat gss_export_sec_context_1();
extern bool_t gss_export_sec_context_1_svc();
#define GSS_IMPORT_SEC_CONTEXT 20
extern enum clnt_stat gss_import_sec_context_1();
extern bool_t gss_import_sec_context_1_svc();
#define GSS_ADD_CRED 21
extern enum clnt_stat gss_add_cred_1();
extern bool_t gss_add_cred_1_svc();
#define GSS_INQUIRE_CRED_BY_MECH 22
extern enum clnt_stat gss_inquire_cred_by_mech_1();
extern bool_t gss_inquire_cred_by_mech_1_svc();
extern int gssprog_1_freeresult();
/* the xdr functions */
extern bool_t xdr_OM_UINT32();
extern bool_t xdr_GSS_CTX_ID_T();
extern bool_t xdr_GSS_CRED_ID_T();
extern bool_t xdr_GSS_OID();
extern bool_t xdr_GSS_BUFFER_T();
extern bool_t xdr_GSSCRED_GIDS();
extern bool_t xdr_GSS_OID_SET();
extern bool_t xdr_GSS_CHANNEL_BINDINGS_STRUCT();
extern bool_t xdr_GSS_CHANNEL_BINDINGS();
extern bool_t xdr_gss_acquire_cred_arg();
extern bool_t xdr_gss_acquire_cred_res();
extern bool_t xdr_gss_add_cred_arg();
extern bool_t xdr_gss_add_cred_res();
extern bool_t xdr_gss_release_cred_arg();
extern bool_t xdr_gss_release_cred_res();
extern bool_t xdr_gss_init_sec_context_arg();
extern bool_t xdr_gss_init_sec_context_res();
extern bool_t xdr_gss_accept_sec_context_arg();
extern bool_t xdr_gss_accept_sec_context_res();
extern bool_t xdr_gss_process_context_token_arg();
extern bool_t xdr_gss_process_context_token_res();
extern bool_t xdr_gss_delete_sec_context_arg();
extern bool_t xdr_gss_delete_sec_context_res();
extern bool_t xdr_gss_export_sec_context_arg();
extern bool_t xdr_gss_export_sec_context_res();
extern bool_t xdr_gss_import_sec_context_arg();
extern bool_t xdr_gss_import_sec_context_res();
extern bool_t xdr_gss_context_time_arg();
extern bool_t xdr_gss_context_time_res();
extern bool_t xdr_gss_sign_arg();
extern bool_t xdr_gss_sign_res();
extern bool_t xdr_gss_verify_arg();
extern bool_t xdr_gss_verify_res();
extern bool_t xdr_gss_seal_arg();
extern bool_t xdr_gss_seal_res();
extern bool_t xdr_gss_unseal_arg();
extern bool_t xdr_gss_unseal_res();
extern bool_t xdr_gss_display_status_arg();
extern bool_t xdr_gss_display_status_res();
extern bool_t xdr_gss_indicate_mechs_res();
extern bool_t xdr_gss_inquire_cred_arg();
extern bool_t xdr_gss_inquire_cred_res();
extern bool_t xdr_gss_inquire_cred_by_mech_arg();
extern bool_t xdr_gss_inquire_cred_by_mech_res();
extern bool_t xdr_gsscred_name_to_unix_cred_arg();
extern bool_t xdr_gsscred_name_to_unix_cred_res();
extern bool_t xdr_gsscred_expname_to_unix_cred_arg();
extern bool_t xdr_gsscred_expname_to_unix_cred_res();
extern bool_t xdr_gss_get_group_info_arg();
extern bool_t xdr_gss_get_group_info_res();
extern bool_t xdr_gss_get_kmod_arg();
extern bool_t xdr_gss_get_kmod_res();
#endif /* !_GSSD_H_RPCGEN */
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include "gssd.h"
#ifndef _KERNEL
#include
#include /* getenv, exit */
#endif /* !_KERNEL */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* RPC protocol information for gssd, the usermode daemon that
* assists the kernel with gssapi. It is gssd that executes all
* gssapi calls except for some such as gss_sign(), and
* gss_verify(), which are executed in the kernel itself.
*
* File generated from gssd.x
*/
#define NO 0
#define YES 1
#define FOREVER 1
#include
#include
#include
#ifndef _KERNEL
#include
#endif /* not _KERNEL */
#ifdef _KERNEL
extern void killgssd_handle(CLIENT *);
extern CLIENT *getgssd_handle(void);
#endif /* _KERNEL */
/* gss_indicate_mechs_arg is void. This appears in the rpc call def */
/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 25, 0 };
enum clnt_stat
gss_acquire_cred_1(argp, clnt_res, clnt)
gss_acquire_cred_arg *argp;
gss_acquire_cred_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_ACQUIRE_CRED,
(xdrproc_t)xdr_gss_acquire_cred_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_acquire_cred_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_release_cred_1(argp, clnt_res, clnt)
gss_release_cred_arg *argp;
gss_release_cred_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_RELEASE_CRED,
(xdrproc_t)xdr_gss_release_cred_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_release_cred_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_init_sec_context_1(argp, clnt_res, clnt)
gss_init_sec_context_arg *argp;
gss_init_sec_context_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_INIT_SEC_CONTEXT,
(xdrproc_t)xdr_gss_init_sec_context_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_init_sec_context_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_accept_sec_context_1(argp, clnt_res, clnt)
gss_accept_sec_context_arg *argp;
gss_accept_sec_context_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_ACCEPT_SEC_CONTEXT,
(xdrproc_t)xdr_gss_accept_sec_context_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_accept_sec_context_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_process_context_token_1(argp, clnt_res, clnt)
gss_process_context_token_arg *argp;
gss_process_context_token_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_PROCESS_CONTEXT_TOKEN,
(xdrproc_t)xdr_gss_process_context_token_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_process_context_token_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_delete_sec_context_1(argp, clnt_res, clnt)
gss_delete_sec_context_arg *argp;
gss_delete_sec_context_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_DELETE_SEC_CONTEXT,
(xdrproc_t)xdr_gss_delete_sec_context_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_delete_sec_context_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_context_time_1(argp, clnt_res, clnt)
gss_context_time_arg *argp;
gss_context_time_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_CONTEXT_TIME,
(xdrproc_t)xdr_gss_context_time_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_context_time_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_sign_1(argp, clnt_res, clnt)
gss_sign_arg *argp;
gss_sign_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_SIGN,
(xdrproc_t)xdr_gss_sign_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_sign_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_verify_1(argp, clnt_res, clnt)
gss_verify_arg *argp;
gss_verify_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_VERIFY,
(xdrproc_t)xdr_gss_verify_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_verify_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_display_status_1(argp, clnt_res, clnt)
gss_display_status_arg *argp;
gss_display_status_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_DISPLAY_STATUS,
(xdrproc_t)xdr_gss_display_status_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_display_status_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_indicate_mechs_1(argp, clnt_res, clnt)
void *argp;
gss_indicate_mechs_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_INDICATE_MECHS,
(xdrproc_t)xdr_void, (caddr_t)argp,
(xdrproc_t)xdr_gss_indicate_mechs_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_inquire_cred_1(argp, clnt_res, clnt)
gss_inquire_cred_arg *argp;
gss_inquire_cred_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_INQUIRE_CRED,
(xdrproc_t)xdr_gss_inquire_cred_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_inquire_cred_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_seal_1(argp, clnt_res, clnt)
gss_seal_arg *argp;
gss_seal_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_SEAL,
(xdrproc_t)xdr_gss_seal_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_seal_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_unseal_1(argp, clnt_res, clnt)
gss_unseal_arg *argp;
gss_unseal_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_UNSEAL,
(xdrproc_t)xdr_gss_unseal_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_unseal_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gsscred_expname_to_unix_cred_1(argp, clnt_res, clnt)
gsscred_expname_to_unix_cred_arg *argp;
gsscred_expname_to_unix_cred_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSSCRED_EXPNAME_TO_UNIX_CRED,
(xdrproc_t)xdr_gsscred_expname_to_unix_cred_arg, (caddr_t)argp,
(xdrproc_t)xdr_gsscred_expname_to_unix_cred_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gsscred_name_to_unix_cred_1(argp, clnt_res, clnt)
gsscred_name_to_unix_cred_arg *argp;
gsscred_name_to_unix_cred_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSSCRED_NAME_TO_UNIX_CRED,
(xdrproc_t)xdr_gsscred_name_to_unix_cred_arg, (caddr_t)argp,
(xdrproc_t)xdr_gsscred_name_to_unix_cred_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_get_group_info_1(argp, clnt_res, clnt)
gss_get_group_info_arg *argp;
gss_get_group_info_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_GET_GROUP_INFO,
(xdrproc_t)xdr_gss_get_group_info_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_get_group_info_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_get_kmod_1(argp, clnt_res, clnt)
gss_get_kmod_arg *argp;
gss_get_kmod_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_GET_KMOD,
(xdrproc_t)xdr_gss_get_kmod_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_get_kmod_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_export_sec_context_1(argp, clnt_res, clnt)
gss_export_sec_context_arg *argp;
gss_export_sec_context_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_EXPORT_SEC_CONTEXT,
(xdrproc_t)xdr_gss_export_sec_context_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_export_sec_context_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_import_sec_context_1(argp, clnt_res, clnt)
gss_import_sec_context_arg *argp;
gss_import_sec_context_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_IMPORT_SEC_CONTEXT,
(xdrproc_t)xdr_gss_import_sec_context_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_import_sec_context_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_add_cred_1(argp, clnt_res, clnt)
gss_add_cred_arg *argp;
gss_add_cred_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_ADD_CRED,
(xdrproc_t)xdr_gss_add_cred_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_add_cred_res, (caddr_t)clnt_res,
TIMEOUT));
}
enum clnt_stat
gss_inquire_cred_by_mech_1(argp, clnt_res, clnt)
gss_inquire_cred_by_mech_arg *argp;
gss_inquire_cred_by_mech_res *clnt_res;
CLIENT *clnt;
{
return (clnt_call(clnt, GSS_INQUIRE_CRED_BY_MECH,
(xdrproc_t)xdr_gss_inquire_cred_by_mech_arg, (caddr_t)argp,
(xdrproc_t)xdr_gss_inquire_cred_by_mech_res, (caddr_t)clnt_res,
TIMEOUT));
}
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* GSSAPI library stub module for gssd.
*/
#include
#include
#include
#include "gssd.h"
#include
#ifdef _KERNEL
#define MALLOC(n) kmem_alloc((n), KM_SLEEP)
#define FREE(x, n) kmem_free((x), (n))
#define memcpy(dst, src, n) bcopy((src), (dst), (n))
#define clnt_pcreateerror(srv) printf("Cannot connect to server on %s\n", srv)
#ifdef DEBUG
#ifndef _SYS_CMN_ERR_H
#define _SYS_CMN_ERR_H
#define CE_NOTE 1
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#endif /* DEBUG */
#else /* !_KERNEL */
#define MALLOC(n) malloc(n)
#define FREE(x, n) free(x)
#endif /* _KERNEL */
#define DEFAULT_MINOR_STAT ((OM_uint32) ~0)
CLIENT *clnt, *getgssd_handle();
char *server = "localhost";
OM_uint32
kgss_acquire_cred_wrapped(minor_status,
desired_name,
time_req,
desired_mechs,
cred_usage,
output_cred_handle,
actual_mechs,
time_rec,
uid,
gssd_cred_verifier)
OM_uint32 *minor_status;
gss_name_t desired_name;
OM_uint32 time_req;
gss_OID_set desired_mechs;
int cred_usage;
gssd_cred_id_t *output_cred_handle;
gss_OID_set *actual_mechs;
OM_uint32 *time_rec;
uid_t uid;
OM_uint32 *gssd_cred_verifier;
{
OM_uint32 minor_status_temp;
gss_buffer_desc external_name;
gss_OID name_type;
int i;
gss_acquire_cred_arg arg;
gss_acquire_cred_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* convert the desired name from internal to external format */
if (gss_display_name(&minor_status_temp, desired_name, &external_name,
&name_type) != GSS_S_COMPLETE) {
*minor_status = (OM_uint32) minor_status_temp;
gss_release_buffer(&minor_status_temp, &external_name);
return ((OM_uint32) GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32)uid;
arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
arg.name_type.GSS_OID_len =
name_type == GSS_C_NULL_OID ?
0 : (uint_t)name_type->length;
arg.name_type.GSS_OID_val =
name_type == GSS_C_NULL_OID ?
(char *)NULL : (char *)name_type->elements;
arg.time_req = time_req;
if (desired_mechs != GSS_C_NULL_OID_SET) {
arg.desired_mechs.GSS_OID_SET_len =
(uint_t)desired_mechs->count;
arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *)
MALLOC(sizeof (GSS_OID) * desired_mechs->count);
for (i = 0; i < desired_mechs->count; i++) {
arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len =
(uint_t)desired_mechs->elements[i].length;
arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val =
(char *)
MALLOC(desired_mechs->elements[i].length);
memcpy(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
desired_mechs->elements[i].elements,
desired_mechs->elements[i].length);
}
} else
arg.desired_mechs.GSS_OID_SET_len = 0;
arg.cred_usage = cred_usage;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_acquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (output_cred_handle != NULL)
*output_cred_handle = 0;
if (actual_mechs != NULL)
*actual_mechs = NULL;
if (time_rec != NULL)
*time_rec = 0;
return (GSS_S_FAILURE);
}
/* free the allocated memory for the flattened name and desire_mechs */
gss_release_buffer(&minor_status_temp, &external_name);
for (i = 0; i < desired_mechs->count; i++)
FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len);
FREE(arg.desired_mechs.GSS_OID_SET_val,
arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID));
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (output_cred_handle != NULL) {
*output_cred_handle =
/*LINTED*/
*((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val);
*gssd_cred_verifier = res.gssd_cred_verifier;
}
if (res.status == GSS_S_COMPLETE &&
res.actual_mechs.GSS_OID_SET_len != 0 &&
actual_mechs != NULL) {
*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
(*actual_mechs)->count =
(int)res.actual_mechs.GSS_OID_SET_len;
(*actual_mechs)->elements = (gss_OID)
MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
for (i = 0; i < (*actual_mechs)->count; i++) {
(*actual_mechs)->elements[i].length = (OM_uint32)
res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
(*actual_mechs)->elements[i].elements =
(void *) MALLOC((*actual_mechs)->elements[i].length);
memcpy((*actual_mechs)->elements[i].elements,
res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
(*actual_mechs)->elements[i].length);
}
} else {
if (res.status == GSS_S_COMPLETE && actual_mechs != NULL)
(*actual_mechs)->count = 0;
}
if (time_rec != NULL)
*time_rec = res.time_rec;
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_acquire_cred(minor_status,
desired_name,
time_req,
desired_mechs,
cred_usage,
output_cred_handle,
actual_mechs,
time_rec,
uid)
OM_uint32 *minor_status;
gss_name_t desired_name;
OM_uint32 time_req;
gss_OID_set desired_mechs;
int cred_usage;
gss_cred_id_t *output_cred_handle;
gss_OID_set *actual_mechs;
OM_uint32 *time_rec;
uid_t uid;
{
OM_uint32 err;
struct kgss_cred *kcred;
kcred = KGSS_CRED_ALLOC();
*output_cred_handle = (gss_cred_id_t)kcred;
err = kgss_acquire_cred_wrapped(minor_status,
desired_name, time_req,
desired_mechs, cred_usage,
&kcred->gssd_cred, actual_mechs,
time_rec, uid,
&kcred->gssd_cred_verifier);
if (GSS_ERROR(err)) {
KGSS_CRED_FREE(kcred);
*output_cred_handle = GSS_C_NO_CREDENTIAL;
}
return (err);
}
OM_uint32
kgss_add_cred_wrapped(minor_status,
input_cred_handle,
gssd_cred_verifier,
desired_name,
desired_mech_type,
cred_usage,
initiator_time_req,
acceptor_time_req,
actual_mechs,
initiator_time_rec,
acceptor_time_rec,
uid)
OM_uint32 *minor_status;
gssd_cred_id_t input_cred_handle;
OM_uint32 gssd_cred_verifier;
gss_name_t desired_name;
gss_OID desired_mech_type;
int cred_usage;
int initiator_time_req;
int acceptor_time_req;
gss_OID_set *actual_mechs;
OM_uint32 *initiator_time_rec;
OM_uint32 *acceptor_time_rec;
uid_t uid;
{
CLIENT *clnt;
OM_uint32 minor_status_temp;
gss_buffer_desc external_name;
gss_OID name_type;
int i;
gss_add_cred_arg arg;
gss_add_cred_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* convert the desired name from internal to external format */
if (gss_display_name(&minor_status_temp, desired_name, &external_name,
&name_type) != GSS_S_COMPLETE) {
*minor_status = (OM_uint32) minor_status_temp;
(void) gss_release_buffer(&minor_status_temp, &external_name);
clnt_pcreateerror(server);
return ((OM_uint32) GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32) uid;
arg.input_cred_handle.GSS_CRED_ID_T_len =
input_cred_handle == GSSD_NO_CREDENTIAL ?
0 : (uint_t)sizeof (gssd_cred_id_t);
arg.input_cred_handle.GSS_CRED_ID_T_val =
(char *)&input_cred_handle;
arg.gssd_cred_verifier = gssd_cred_verifier;
arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
arg.name_type.GSS_OID_len =
name_type == GSS_C_NULL_OID ?
0 : (uint_t)name_type->length;
arg.name_type.GSS_OID_val =
name_type == GSS_C_NULL_OID ?
(char *)NULL : (char *)name_type->elements;
arg.desired_mech_type.GSS_OID_len =
(uint_t)(desired_mech_type != GSS_C_NULL_OID ?
desired_mech_type->length : 0);
arg.desired_mech_type.GSS_OID_val =
(char *)(desired_mech_type != GSS_C_NULL_OID ?
desired_mech_type->elements : 0);
arg.cred_usage = cred_usage;
arg.initiator_time_req = initiator_time_req;
arg.acceptor_time_req = acceptor_time_req;
/* call the remote procedure */
bzero((caddr_t)&res, sizeof (res));
if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return
* GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (actual_mechs != NULL)
*actual_mechs = NULL;
if (initiator_time_rec != NULL)
*initiator_time_rec = 0;
if (acceptor_time_rec != NULL)
*acceptor_time_rec = 0;
return (GSS_S_FAILURE);
}
/* free the allocated memory for the flattened name */
(void) gss_release_buffer(&minor_status_temp, &external_name);
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (res.status == GSS_S_COMPLETE &&
res.actual_mechs.GSS_OID_SET_len != 0 &&
actual_mechs != NULL) {
*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
(*actual_mechs)->count =
(int)res.actual_mechs.GSS_OID_SET_len;
(*actual_mechs)->elements = (gss_OID)
MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
for (i = 0; i < (*actual_mechs)->count; i++) {
(*actual_mechs)->elements[i].length = (OM_uint32)
res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
(*actual_mechs)->elements[i].elements =
(void *) MALLOC((*actual_mechs)->elements[i].length);
memcpy((*actual_mechs)->elements[i].elements,
res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
(*actual_mechs)->elements[i].length);
}
} else {
if (res.status == GSS_S_COMPLETE &&
actual_mechs != NULL)
(*actual_mechs)->count = 0;
}
if (initiator_time_rec != NULL)
*initiator_time_rec = res.initiator_time_rec;
if (acceptor_time_rec != NULL)
*acceptor_time_rec = res.acceptor_time_rec;
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_add_cred(minor_status,
input_cred_handle,
desired_name,
desired_mech_type,
cred_usage,
initiator_time_req,
acceptor_time_req,
actual_mechs,
initiator_time_rec,
acceptor_time_rec,
uid)
OM_uint32 *minor_status;
gss_cred_id_t input_cred_handle;
gss_name_t desired_name;
gss_OID desired_mech_type;
int cred_usage;
int initiator_time_req;
int acceptor_time_req;
gss_OID_set *actual_mechs;
OM_uint32 *initiator_time_rec;
OM_uint32 *acceptor_time_rec;
uid_t uid;
{
OM_uint32 err;
OM_uint32 gssd_cred_verifier;
gssd_cred_id_t gssd_input_cred_handle;
if (input_cred_handle != GSS_C_NO_CREDENTIAL) {
gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle);
gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle);
} else
gssd_input_cred_handle = GSSD_NO_CREDENTIAL;
err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle,
gssd_cred_verifier, desired_name, desired_mech_type,
cred_usage, initiator_time_req, acceptor_time_req,
actual_mechs, initiator_time_rec,
acceptor_time_rec, uid);
return (err);
}
OM_uint32
kgss_release_cred_wrapped(minor_status,
cred_handle,
uid,
gssd_cred_verifier)
OM_uint32 *minor_status;
gssd_cred_id_t *cred_handle;
uid_t uid;
OM_uint32 gssd_cred_verifier;
{
gss_release_cred_arg arg;
gss_release_cred_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32) uid;
arg.gssd_cred_verifier = gssd_cred_verifier;
if (cred_handle != NULL) {
arg.cred_handle.GSS_CRED_ID_T_len =
(uint_t)sizeof (gssd_cred_id_t);
arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle;
} else
arg.cred_handle.GSS_CRED_ID_T_len = 0;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its max value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (cred_handle != NULL)
*cred_handle = 0;
return (GSS_S_FAILURE);
}
/* if the release succeeded, null out the cred_handle */
if (res.status == GSS_S_COMPLETE && cred_handle != NULL)
*cred_handle = 0;
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
/* return with status returned in rpc call */
return (res.status);
}
OM_uint32
kgss_release_cred(minor_status,
cred_handle,
uid)
OM_uint32 *minor_status;
gss_cred_id_t *cred_handle;
uid_t uid;
{
OM_uint32 err;
struct kgss_cred *kcred;
if (*cred_handle == GSS_C_NO_CREDENTIAL)
return (GSS_S_COMPLETE);
else
kcred = KCRED_TO_KGSS_CRED(*cred_handle);
err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred,
uid, kcred->gssd_cred_verifier);
KGSS_CRED_FREE(kcred);
*cred_handle = GSS_C_NO_CREDENTIAL;
return (err);
}
OM_uint32
kgss_init_sec_context_wrapped(minor_status,
claimant_cred_handle,
gssd_cred_verifier,
context_handle,
gssd_context_verifier,
target_name,
mech_type,
req_flags,
time_req,
input_chan_bindings,
input_token,
actual_mech_type,
output_token,
ret_flags,
time_rec,
uid)
OM_uint32 *minor_status;
gssd_cred_id_t claimant_cred_handle;
OM_uint32 gssd_cred_verifier;
OM_uint32 *context_handle;
OM_uint32 *gssd_context_verifier;
gss_name_t target_name;
gss_OID mech_type;
int req_flags;
OM_uint32 time_req;
gss_channel_bindings_t input_chan_bindings;
gss_buffer_t input_token;
gss_OID *actual_mech_type;
gss_buffer_t output_token;
int *ret_flags;
OM_uint32 *time_rec;
uid_t uid;
{
OM_uint32 minor_status_temp;
gss_buffer_desc external_name;
gss_OID name_type;
gss_init_sec_context_arg arg;
gss_init_sec_context_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* convert the target name from internal to external format */
if (gss_display_name(&minor_status_temp, target_name,
&external_name, &name_type) != GSS_S_COMPLETE) {
*minor_status = (OM_uint32) minor_status_temp;
return ((OM_uint32) GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32) uid;
arg.context_handle.GSS_CTX_ID_T_len =
*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
(uint_t)sizeof (OM_uint32);
arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
arg.gssd_context_verifier = *gssd_context_verifier;
arg.claimant_cred_handle.GSS_CRED_ID_T_len =
claimant_cred_handle == GSSD_NO_CREDENTIAL ?
0 : (uint_t)sizeof (gssd_cred_id_t);
arg.claimant_cred_handle.GSS_CRED_ID_T_val =
(char *)&claimant_cred_handle;
arg.gssd_cred_verifier = gssd_cred_verifier;
arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value;
arg.name_type.GSS_OID_len =
name_type == GSS_C_NULL_OID ?
0 : (uint_t)name_type->length;
arg.name_type.GSS_OID_val =
name_type == GSS_C_NULL_OID ?
(char *)NULL : (char *)name_type->elements;
arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
mech_type->length : 0);
arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
mech_type->elements : 0);
arg.req_flags = req_flags;
arg.time_req = time_req;
if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
arg.input_chan_bindings.present = YES;
arg.input_chan_bindings.initiator_addrtype =
input_chan_bindings->initiator_addrtype;
arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
(uint_t)input_chan_bindings->initiator_address.length;
arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
(void *) input_chan_bindings->initiator_address.value;
arg.input_chan_bindings.acceptor_addrtype =
input_chan_bindings->acceptor_addrtype;
arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
(uint_t)input_chan_bindings->acceptor_address.length;
arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
(void *) input_chan_bindings->acceptor_address.value;
arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
(uint_t)input_chan_bindings->application_data.length;
arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
(void *) input_chan_bindings->application_data.value;
} else {
arg.input_chan_bindings.present = NO;
arg.input_chan_bindings.initiator_addrtype = 0;
arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
arg.input_chan_bindings.acceptor_addrtype = 0;
arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
}
arg.input_token.GSS_BUFFER_T_len = (uint_t)
(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
arg.input_token.GSS_BUFFER_T_val = (char *)
(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
/* initialize the output parameters to empty values */
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (actual_mech_type != NULL)
*actual_mech_type = NULL;
if (output_token != NULL)
output_token->length = 0;
if (ret_flags != NULL)
*ret_flags = 0;
if (time_rec != NULL)
*time_rec = 0;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
/* free the allocated memory for the flattened name */
gss_release_buffer(&minor_status_temp, &external_name);
return (GSS_S_FAILURE);
}
/*
* We could return from a GSS error here and need to return both the
* minor_status and output_token, back to the caller if applicable.
*/
if (minor_status != NULL)
*minor_status = res.minor_status;
if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
output_token->length =
(size_t)res.output_token.GSS_BUFFER_T_len;
output_token->value =
(void *)res.output_token.GSS_BUFFER_T_val;
res.output_token.GSS_BUFFER_T_val = NULL;
res.output_token.GSS_BUFFER_T_len = 0;
}
/* free the allocated memory for the flattened name */
gss_release_buffer(&minor_status_temp, &external_name);
/* if the call was successful, copy out the results */
if (res.status == (OM_uint32) GSS_S_COMPLETE ||
res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
/*
* copy the rpc results into the return argument
* on CONTINUE_NEEDED only ctx handle is ready.
*/
/*LINTED*/
*context_handle = *((OM_uint32 *)
res.context_handle.GSS_CTX_ID_T_val);
*gssd_context_verifier = res.gssd_context_verifier;
/* the rest of the parameters is only ready on COMPLETE */
if (res.status == GSS_S_COMPLETE) {
if (actual_mech_type != NULL) {
*actual_mech_type = (gss_OID)
MALLOC(sizeof (gss_OID_desc));
(*actual_mech_type)->length = (OM_UINT32)
res.actual_mech_type.GSS_OID_len;
(*actual_mech_type)->elements = (void *)
MALLOC((*actual_mech_type)->length);
memcpy((*actual_mech_type)->elements, (void *)
res.actual_mech_type.GSS_OID_val,
(*actual_mech_type)->length);
}
if (ret_flags != NULL)
*ret_flags = res.ret_flags;
if (time_rec != NULL)
*time_rec = res.time_rec;
}
}
/*
* free the memory allocated for the results and return with the
* status received in the rpc call.
*/
clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_init_sec_context(
OM_uint32 *minor_status,
gss_cred_id_t claimant_cred_handle,
gss_ctx_id_t *context_handle,
gss_name_t target_name,
gss_OID mech_type,
int req_flags,
OM_uint32 time_req,
gss_channel_bindings_t input_chan_bindings,
gss_buffer_t input_token,
gss_OID *actual_mech_type,
gss_buffer_t output_token,
int *ret_flags,
OM_uint32 *time_rec,
uid_t uid)
{
OM_uint32 err;
struct kgss_ctx *kctx;
OM_uint32 gssd_cred_verifier;
gssd_cred_id_t gssd_cl_cred_handle;
/*
* If this is an initial call, we'll need to create the
* wrapper struct that contains kernel state information, and
* a reference to the handle from gssd.
*/
if (*context_handle == GSS_C_NO_CONTEXT) {
kctx = KGSS_ALLOC();
*context_handle = (gss_ctx_id_t)kctx;
kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
} else
kctx = (struct kgss_ctx *)*context_handle;
if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
gssd_cred_verifier =
KCRED_TO_CREDV(claimant_cred_handle);
gssd_cl_cred_handle =
KCRED_TO_CRED(claimant_cred_handle);
} else {
gssd_cl_cred_handle = GSSD_NO_CREDENTIAL;
}
err = kgss_init_sec_context_wrapped(minor_status,
gssd_cl_cred_handle,
gssd_cred_verifier, &kctx->gssd_ctx,
&kctx->gssd_ctx_verifier,
target_name, mech_type, req_flags, time_req,
input_chan_bindings, input_token, actual_mech_type,
output_token, ret_flags, time_rec, uid);
if (GSS_ERROR(err)) {
KGSS_FREE(kctx);
*context_handle = GSS_C_NO_CONTEXT;
}
return (err);
}
OM_uint32
kgss_accept_sec_context_wrapped(minor_status,
context_handle,
gssd_context_verifier,
verifier_cred_handle,
gssd_cred_verifier,
input_token,
input_chan_bindings,
src_name,
mech_type,
output_token,
ret_flags,
time_rec,
delegated_cred_handle,
uid)
OM_uint32 *minor_status;
gssd_ctx_id_t *context_handle;
OM_uint32 *gssd_context_verifier;
gssd_cred_id_t verifier_cred_handle;
OM_uint32 gssd_cred_verifier;
gss_buffer_t input_token;
gss_channel_bindings_t input_chan_bindings;
gss_buffer_t src_name;
gss_OID *mech_type;
gss_buffer_t output_token;
int *ret_flags;
OM_uint32 *time_rec;
gss_cred_id_t *delegated_cred_handle;
uid_t uid;
{
gss_accept_sec_context_arg arg;
gss_accept_sec_context_res res;
struct kgss_cred *kcred;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32) uid;
arg.context_handle.GSS_CTX_ID_T_len =
*context_handle == GSSD_NO_CONTEXT ?
0 : (uint_t)sizeof (gssd_ctx_id_t);
arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
arg.gssd_context_verifier =
*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ?
0 : *gssd_context_verifier;
arg.verifier_cred_handle.GSS_CRED_ID_T_len =
verifier_cred_handle == GSSD_NO_CREDENTIAL ?
0 : (uint_t)sizeof (gssd_cred_id_t);
arg.verifier_cred_handle.GSS_CRED_ID_T_val =
(char *)&verifier_cred_handle;
arg.gssd_cred_verifier = gssd_cred_verifier;
arg.input_token_buffer.GSS_BUFFER_T_len =
(uint_t)(input_token != GSS_C_NO_BUFFER ?
input_token->length : 0);
arg.input_token_buffer.GSS_BUFFER_T_val =
(char *)(input_token != GSS_C_NO_BUFFER ?
input_token->value : 0);
if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
arg.input_chan_bindings.present = YES;
arg.input_chan_bindings.initiator_addrtype =
input_chan_bindings->initiator_addrtype;
arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
(uint_t)input_chan_bindings->initiator_address.length;
arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
(void *) input_chan_bindings->initiator_address.value;
arg.input_chan_bindings.acceptor_addrtype =
input_chan_bindings->acceptor_addrtype;
arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
(uint_t)input_chan_bindings->acceptor_address.length;
arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
(void *) input_chan_bindings->acceptor_address.value;
arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
(uint_t)input_chan_bindings->application_data.length;
arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
(void *) input_chan_bindings->application_data.value;
} else {
arg.input_chan_bindings.present = NO;
arg.input_chan_bindings.initiator_addrtype = 0;
arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
arg.input_chan_bindings.acceptor_addrtype = 0;
arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
}
/* set the output parameters to empty values.... */
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (src_name != NULL) {
src_name->length = 0;
src_name->value = NULL;
}
if (mech_type != NULL)
*mech_type = NULL;
if (output_token != NULL)
output_token->length = 0;
if (ret_flags != NULL)
*ret_flags = 0;
if (time_rec != NULL)
*time_rec = 0;
if (delegated_cred_handle != NULL)
*delegated_cred_handle = NULL;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
return (GSS_S_FAILURE);
}
/*
* We could return from a GSS error here and need to return both the
* minor_status and output_token, back to the caller if applicable.
*/
if (minor_status != NULL)
*minor_status = res.minor_status;
if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
output_token->length =
res.output_token.GSS_BUFFER_T_len;
output_token->value =
(void *) res.output_token.GSS_BUFFER_T_val;
res.output_token.GSS_BUFFER_T_val = 0;
res.output_token.GSS_BUFFER_T_len = 0;
}
if (res.status == (OM_uint32) GSS_S_COMPLETE ||
res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
/*
* when gss returns CONTINUE_NEEDED we can only
* use the context parameter.
*/
/*LINTED*/
*context_handle = *((gssd_ctx_id_t *)
res.context_handle.GSS_CTX_ID_T_val);
*gssd_context_verifier = res.gssd_context_verifier;
/* the other parameters are ready on for COMPLETE */
if (res.status == GSS_S_COMPLETE)
{
/*
* The src_name is in external format.
*/
if (src_name != NULL) {
src_name->length = res.src_name.GSS_BUFFER_T_len;
src_name->value = res.src_name.GSS_BUFFER_T_val;
res.src_name.GSS_BUFFER_T_val = NULL;
res.src_name.GSS_BUFFER_T_len = 0;
}
/*
* move mech type returned to mech_type
* for gss_import_name_for_mech()
*/
if (mech_type != NULL) {
*mech_type =
(gss_OID) MALLOC(sizeof (gss_OID_desc));
(*mech_type)->length =
(OM_UINT32) res.mech_type.GSS_OID_len;
(*mech_type)->elements =
(void *) MALLOC((*mech_type)->length);
memcpy((*mech_type)->elements,
res.mech_type.GSS_OID_val,
(*mech_type)->length);
}
if (ret_flags != NULL)
*ret_flags = res.ret_flags;
if (time_rec != NULL)
*time_rec = res.time_rec;
if ((delegated_cred_handle != NULL) &&
(res.delegated_cred_handle.GSS_CRED_ID_T_len
!= 0)) {
kcred = KGSS_CRED_ALLOC();
/*LINTED*/
kcred->gssd_cred = *((gssd_cred_id_t *)
res.delegated_cred_handle.GSS_CRED_ID_T_val);
kcred->gssd_cred_verifier =
res.gssd_context_verifier;
*delegated_cred_handle = (gss_cred_id_t)kcred;
}
} /* res.status == GSS_S_COMPLETE */
} /* res.status == GSS_S_COMPLETE or GSS_CONTINUE_NEEDED */
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_accept_sec_context(
OM_uint32 *minor_status,
gss_ctx_id_t *context_handle,
gss_cred_id_t verifier_cred_handle,
gss_buffer_t input_token,
gss_channel_bindings_t input_chan_bindings,
gss_buffer_t src_name,
gss_OID *mech_type,
gss_buffer_t output_token,
int *ret_flags,
OM_uint32 *time_rec,
gss_cred_id_t *delegated_cred_handle,
uid_t uid)
{
OM_uint32 err;
struct kgss_ctx *kctx;
OM_uint32 gssd_cred_verifier;
gssd_cred_id_t gssd_ver_cred_handle;
if (*context_handle == GSS_C_NO_CONTEXT) {
kctx = KGSS_ALLOC();
*context_handle = (gss_ctx_id_t)kctx;
kctx->gssd_ctx = GSSD_NO_CONTEXT;
} else
kctx = (struct kgss_ctx *)*context_handle;
if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) {
gssd_cred_verifier =
KCRED_TO_CREDV(verifier_cred_handle);
gssd_ver_cred_handle =
KCRED_TO_CRED(verifier_cred_handle);
} else
gssd_ver_cred_handle = GSSD_NO_CREDENTIAL;
err = kgss_accept_sec_context_wrapped(minor_status, &kctx->gssd_ctx,
&kctx->gssd_ctx_verifier, gssd_ver_cred_handle,
gssd_cred_verifier, input_token, input_chan_bindings,
src_name, mech_type, output_token, ret_flags,
time_rec, delegated_cred_handle, uid);
if (GSS_ERROR(err)) {
KGSS_FREE(kctx);
*context_handle = GSS_C_NO_CONTEXT;
}
return (err);
}
OM_uint32
kgss_process_context_token(minor_status,
context_handle,
token_buffer,
uid)
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t token_buffer;
uid_t uid;
{
OM_uint32 gssd_context_verifier;
gss_process_context_token_arg arg;
gss_process_context_token_res res;
gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle);
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32) uid;
arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
arg.gssd_context_verifier = gssd_context_verifier;
arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer;
arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
/* return with status returned in rpc call */
return (res.status);
}
OM_uint32
kgss_delete_sec_context_wrapped(minor_status,
context_handle,
gssd_context_verifier,
output_token)
OM_uint32 *minor_status;
gssd_ctx_id_t *context_handle;
OM_uint32 gssd_context_verifier;
gss_buffer_t output_token;
{
gss_delete_sec_context_arg arg;
gss_delete_sec_context_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.context_handle.GSS_CTX_ID_T_len =
*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
(uint_t)sizeof (OM_uint32);
arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
arg.gssd_context_verifier = gssd_context_verifier;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its max value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (context_handle != NULL)
*context_handle = 0;
if (output_token != NULL)
output_token->length = 0;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (res.context_handle.GSS_CTX_ID_T_len == 0)
*context_handle = 0;
else
/*LINTED*/
*context_handle = *((gssd_ctx_id_t *)
res.context_handle.GSS_CTX_ID_T_val);
if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
output_token->length = res.output_token.GSS_BUFFER_T_len;
output_token->value = res.output_token.GSS_BUFFER_T_val;
res.output_token.GSS_BUFFER_T_len = 0;
res.output_token.GSS_BUFFER_T_val = NULL;
}
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res);
return (res.status);
}
/*ARGSUSED*/
OM_uint32
kgss_delete_sec_context(
OM_uint32 *minor_status,
gss_ctx_id_t *context_handle,
gss_buffer_t output_token)
{
OM_uint32 err;
struct kgss_ctx *kctx;
if (*context_handle == GSS_C_NO_CONTEXT) {
return (GSS_S_NO_CONTEXT);
} else
kctx = KCTX_TO_KGSS_CTX(*context_handle);
err = kgss_delete_sec_context_wrapped(minor_status,
&kctx->gssd_ctx, kctx->gssd_ctx_verifier,
output_token);
if (kctx->gssd_ctx != GSSD_NO_CONTEXT)
err = GSS_S_FAILURE;
else
err = GSS_S_COMPLETE;
KGSS_FREE(kctx);
*context_handle = GSS_C_NO_CONTEXT;
return (err);
}
/*ARGSUSED*/
OM_uint32
kgss_context_time(minor_status,
context_handle,
time_rec,
uid)
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
OM_uint32 *time_rec;
uid_t uid;
{
return (GSS_S_FAILURE);
}
OM_uint32
kgss_sign_wrapped(minor_status,
context_handle,
qop_req,
message_buffer,
msg_token,
gssd_context_verifier)
OM_uint32 *minor_status;
gssd_ctx_id_t context_handle;
OM_uint32 gssd_context_verifier;
int qop_req;
gss_buffer_t message_buffer;
gss_buffer_t msg_token;
{
gss_sign_arg arg;
gss_sign_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
arg.gssd_context_verifier = gssd_context_verifier;
arg.qop_req = qop_req;
arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (msg_token != NULL)
msg_token->length = 0;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (msg_token != NULL) {
msg_token->length = res.msg_token.GSS_BUFFER_T_len;
msg_token->value = (void *) MALLOC(msg_token->length);
memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val,
msg_token->length);
}
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_sign(
OM_uint32 *minor_status,
gss_ctx_id_t context_handle,
int qop_req,
gss_buffer_t message_buffer,
gss_buffer_t msg_token)
{
if (context_handle == GSS_C_NO_CONTEXT)
return (GSS_S_FAILURE);
return (KGSS_SIGN(minor_status,
context_handle, qop_req, message_buffer,
msg_token));
}
OM_uint32
kgss_verify_wrapped(
minor_status,
context_handle,
message_buffer,
token_buffer,
qop_state,
gssd_context_verifier)
OM_uint32 *minor_status;
gssd_ctx_id_t context_handle;
OM_uint32 gssd_context_verifier;
gss_buffer_t message_buffer;
gss_buffer_t token_buffer;
int *qop_state;
{
gss_verify_arg arg;
gss_verify_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
arg.gssd_context_verifier = gssd_context_verifier;
arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (qop_state != NULL)
*qop_state = 0;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (qop_state != NULL)
*qop_state = res.qop_state;
/* return with status returned in rpc call */
return (res.status);
}
OM_uint32
kgss_verify(OM_uint32 *minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t message_buffer,
gss_buffer_t token_buffer,
int *qop_state)
{
if (context_handle == GSS_C_NO_CONTEXT)
return (GSS_S_FAILURE);
return (KGSS_VERIFY(minor_status, context_handle,
message_buffer, token_buffer, qop_state));
}
OM_uint32
kgss_seal_wrapped(
minor_status,
context_handle,
conf_req_flag,
qop_req,
input_message_buffer,
conf_state,
output_message_buffer,
gssd_context_verifier)
OM_uint32 *minor_status;
gssd_ctx_id_t context_handle;
OM_uint32 gssd_context_verifier;
int conf_req_flag;
int qop_req;
gss_buffer_t input_message_buffer;
int *conf_state;
gss_buffer_t output_message_buffer;
{
gss_seal_arg arg;
gss_seal_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
arg.gssd_context_verifier = gssd_context_verifier;
arg.conf_req_flag = conf_req_flag;
arg.qop_req = qop_req;
arg.input_message_buffer.GSS_BUFFER_T_len =
(uint_t)input_message_buffer->length;
arg.input_message_buffer.GSS_BUFFER_T_val =
(char *)input_message_buffer->value;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (conf_state != NULL)
*conf_state = 0;
if (output_message_buffer != NULL)
output_message_buffer->length = 0;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (conf_state != NULL)
*conf_state = res.conf_state;
if (output_message_buffer != NULL) {
output_message_buffer->length =
res.output_message_buffer.GSS_BUFFER_T_len;
output_message_buffer->value =
(void *) MALLOC(output_message_buffer->length);
memcpy(output_message_buffer->value,
res.output_message_buffer.GSS_BUFFER_T_val,
output_message_buffer->length);
}
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_seal(OM_uint32 *minor_status,
gss_ctx_id_t context_handle,
int conf_req_flag,
int qop_req,
gss_buffer_t input_message_buffer,
int *conf_state,
gss_buffer_t output_message_buffer)
{
if (context_handle == GSS_C_NO_CONTEXT)
return (GSS_S_FAILURE);
return (KGSS_SEAL(minor_status, context_handle,
conf_req_flag, qop_req,
input_message_buffer,
conf_state, output_message_buffer));
}
OM_uint32
kgss_unseal_wrapped(minor_status,
context_handle,
input_message_buffer,
output_message_buffer,
conf_state,
qop_state,
gssd_context_verifier)
OM_uint32 *minor_status;
gssd_ctx_id_t context_handle;
OM_uint32 gssd_context_verifier;
gss_buffer_t input_message_buffer;
gss_buffer_t output_message_buffer;
int *conf_state;
int *qop_state;
{
gss_unseal_arg arg;
gss_unseal_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
arg.gssd_context_verifier = gssd_context_verifier;
arg.input_message_buffer.GSS_BUFFER_T_len =
(uint_t)input_message_buffer->length;
arg.input_message_buffer.GSS_BUFFER_T_val =
(char *)input_message_buffer->value;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (output_message_buffer != NULL)
output_message_buffer->length = 0;
if (conf_state != NULL)
*conf_state = 0;
if (qop_state != NULL)
*qop_state = 0;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (output_message_buffer != NULL) {
output_message_buffer->length =
res.output_message_buffer.GSS_BUFFER_T_len;
output_message_buffer->value =
(void *) MALLOC(output_message_buffer->length);
memcpy(output_message_buffer->value,
res.output_message_buffer.GSS_BUFFER_T_val,
output_message_buffer->length);
}
if (conf_state != NULL)
*conf_state = res.conf_state;
if (qop_state != NULL)
*qop_state = res.qop_state;
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_unseal(OM_uint32 *minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t input_message_buffer,
gss_buffer_t output_message_buffer,
int *conf_state,
int *qop_state)
{
if (context_handle == GSS_C_NO_CONTEXT)
return (GSS_S_FAILURE);
return (KGSS_UNSEAL(minor_status, context_handle,
input_message_buffer, output_message_buffer,
conf_state, qop_state));
}
OM_uint32
kgss_display_status(minor_status,
status_value,
status_type,
mech_type,
message_context,
status_string,
uid)
OM_uint32 *minor_status;
OM_uint32 status_value;
int status_type;
gss_OID mech_type;
int *message_context;
gss_buffer_t status_string;
uid_t uid;
{
gss_display_status_arg arg;
gss_display_status_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32) uid;
arg.status_value = status_value;
arg.status_type = status_type;
arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
mech_type->length : 0);
arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
mech_type->elements : 0);
arg.message_context = *message_context;
/* call the remote procedure */
if (message_context != NULL)
*message_context = 0;
if (status_string != NULL) {
status_string->length = 0;
status_string->value = NULL;
}
memset(&res, 0, sizeof (res));
if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
return (GSS_S_FAILURE);
}
if (minor_status != NULL)
*minor_status = res.minor_status;
/* now process the results and pass them back to the caller */
if (res.status == GSS_S_COMPLETE) {
if (message_context != NULL)
*message_context = res.message_context;
if (status_string != NULL) {
status_string->length =
(size_t)res.status_string.GSS_BUFFER_T_len;
status_string->value =
(void *)MALLOC(status_string->length);
memcpy(status_string->value,
res.status_string.GSS_BUFFER_T_val,
status_string->length);
}
}
clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res);
return (res.status);
}
/*ARGSUSED*/
OM_uint32
kgss_indicate_mechs(minor_status,
mech_set,
uid)
OM_uint32 *minor_status;
gss_OID_set *mech_set;
uid_t uid;
{
void *arg;
gss_indicate_mechs_res res;
int i;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
memset(&res, 0, sizeof (res));
if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (mech_set != NULL)
*mech_set = NULL;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (mech_set != NULL) {
*mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
(*mech_set)->count = res.mech_set.GSS_OID_SET_len;
(*mech_set)->elements = (void *)
MALLOC ((*mech_set)->count * sizeof (gss_OID_desc));
for (i = 0; i < (*mech_set)->count; i++) {
(*mech_set)->elements[i].length =
res.mech_set.GSS_OID_SET_val[i].GSS_OID_len;
(*mech_set)->elements[i].elements = (void *)
MALLOC ((*mech_set)->elements[i].length);
memcpy ((*mech_set)->elements[i].elements,
res.mech_set.GSS_OID_SET_val[i].GSS_OID_val,
(*mech_set)->elements[i].length);
}
}
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_inquire_cred_wrapped(minor_status,
cred_handle,
gssd_cred_verifier,
name,
lifetime,
cred_usage,
mechanisms,
uid)
OM_uint32 *minor_status;
gssd_cred_id_t cred_handle;
OM_uint32 gssd_cred_verifier;
gss_name_t *name;
OM_uint32 *lifetime;
int *cred_usage;
gss_OID_set *mechanisms;
uid_t uid;
{
OM_uint32 minor_status_temp;
gss_buffer_desc external_name;
gss_OID name_type;
int i;
gss_inquire_cred_arg arg;
gss_inquire_cred_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32) uid;
arg.cred_handle.GSS_CRED_ID_T_len =
cred_handle == GSSD_NO_CREDENTIAL ?
0 : (uint_t)sizeof (gssd_cred_id_t);
arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
arg.gssd_cred_verifier = gssd_cred_verifier;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (name != NULL)
*name = NULL;
if (lifetime != NULL)
*lifetime = 0;
if (cred_usage != NULL)
*cred_usage = 0;
if (mechanisms != NULL)
*mechanisms = NULL;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
/* convert name from external to internal format */
if (name != NULL) {
external_name.length = res.name.GSS_BUFFER_T_len;
external_name.value = res.name.GSS_BUFFER_T_val;
/*
* we have to allocate a name_type descriptor and
* elements storage, since gss_import_name() only
* stores a pointer to the name_type info in the
* union_name struct
*/
name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc));
name_type->length = res.name_type.GSS_OID_len;
name_type->elements = (void *) MALLOC(name_type->length);
memcpy(name_type->elements, res.name_type.GSS_OID_val,
name_type->length);
if (gss_import_name(&minor_status_temp, &external_name,
name_type, name) != GSS_S_COMPLETE) {
*minor_status = (OM_uint32) minor_status_temp;
gss_release_buffer(&minor_status_temp, &external_name);
clnt_freeres(clnt, xdr_gss_inquire_cred_res,
(caddr_t)&res);
return ((OM_uint32) GSS_S_FAILURE);
}
}
if (lifetime != NULL)
*lifetime = res.lifetime;
if (cred_usage != NULL)
*cred_usage = res.cred_usage;
if (mechanisms != NULL) {
*mechanisms =
(gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
if (res.mechanisms.GSS_OID_SET_len != 0) {
(*mechanisms)->count =
(int)res.mechanisms.GSS_OID_SET_len;
(*mechanisms)->elements = (gss_OID)
MALLOC(sizeof (gss_OID) * (*mechanisms)->count);
for (i = 0; i < (*mechanisms)->count; i++) {
(*mechanisms)->elements[i].length = (OM_uint32)
res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len;
(*mechanisms)->elements[i].elements = (void *)
MALLOC((*mechanisms)->elements[i].length);
memcpy((*mechanisms)->elements[i].elements,
res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
(*mechanisms)->elements[i].length);
}
} else
(*mechanisms)->count = 0;
}
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_inquire_cred(minor_status,
cred_handle,
name,
lifetime,
cred_usage,
mechanisms,
uid)
OM_uint32 *minor_status;
gss_cred_id_t cred_handle;
gss_name_t *name;
OM_uint32 *lifetime;
int *cred_usage;
gss_OID_set * mechanisms;
uid_t uid;
{
OM_uint32 gssd_cred_verifier;
gssd_cred_id_t gssd_cred_handle;
gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
gssd_cred_handle = KCRED_TO_CRED(cred_handle);
return (kgss_inquire_cred_wrapped(minor_status,
gssd_cred_handle, gssd_cred_verifier,
name, lifetime, cred_usage, mechanisms, uid));
}
OM_uint32
kgss_inquire_cred_by_mech_wrapped(minor_status,
cred_handle,
gssd_cred_verifier,
mech_type,
uid)
OM_uint32 *minor_status;
gssd_cred_id_t cred_handle;
OM_uint32 gssd_cred_verifier;
gss_OID mech_type;
uid_t uid;
{
OM_uint32 minor_status_temp;
gss_inquire_cred_by_mech_arg arg;
gss_inquire_cred_by_mech_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.uid = (OM_uint32) uid;
arg.cred_handle.GSS_CRED_ID_T_len =
cred_handle == GSSD_NO_CREDENTIAL ?
0 : (uint_t)sizeof (gssd_cred_id_t);
arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
arg.gssd_cred_verifier = gssd_cred_verifier;
arg.mech_type.GSS_OID_len =
(uint_t)(mech_type != GSS_C_NULL_OID ?
mech_type->length : 0);
arg.mech_type.GSS_OID_val =
(char *)(mech_type != GSS_C_NULL_OID ?
mech_type->elements : 0);
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments,
* set minor_status to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
/* convert name from external to internal format */
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_inquire_cred_by_mech(minor_status,
cred_handle,
mech_type,
uid)
OM_uint32 *minor_status;
gss_cred_id_t cred_handle;
gss_OID mech_type;
uid_t uid;
{
OM_uint32 gssd_cred_verifier;
gssd_cred_id_t gssd_cred_handle;
gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
gssd_cred_handle = KCRED_TO_CRED(cred_handle);
return (kgss_inquire_cred_by_mech_wrapped(minor_status,
gssd_cred_handle, gssd_cred_verifier,
mech_type, uid));
}
OM_uint32
kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
const gss_buffer_t expName;
uid_t *uidOut;
gid_t *gidOut;
gid_t *gids[];
int *gidsLen;
uid_t uid;
{
gsscred_expname_to_unix_cred_arg args;
gsscred_expname_to_unix_cred_res res;
/* check input/output parameters */
if (expName == NULL || expName->value == NULL)
return (GSS_S_CALL_INACCESSIBLE_READ);
if (uidOut == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
/* NULL out output parameters */
*uidOut = 0;
if (gidsLen)
*gidsLen = 0;
if (gids)
*gids = NULL;
/* get the client handle to gssd */
if ((clnt = getgssd_handle()) == NULL)
{
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments */
args.uid = uid;
args.expname.GSS_BUFFER_T_val = expName->value;
args.expname.GSS_BUFFER_T_len = expName->length;
/* null out the return buffer and call the remote proc */
memset(&res, 0, sizeof (res));
if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
{
return (GSS_S_FAILURE);
}
/* copy the results into the result parameters */
if (res.major == GSS_S_COMPLETE)
{
*uidOut = res.uid;
if (gidOut)
*gidOut = res.gid;
if (gids && gidsLen)
{
*gids = res.gids.GSSCRED_GIDS_val;
*gidsLen = res.gids.GSSCRED_GIDS_len;
res.gids.GSSCRED_GIDS_val = NULL;
res.gids.GSSCRED_GIDS_len = 0;
}
}
/* free RPC results */
clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res);
return (res.major);
} /* kgsscred_expname_to_unix_cred */
OM_uint32
kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
gidsLen, uid)
const gss_name_t intName;
const gss_OID mechType;
uid_t *uidOut;
gid_t *gidOut;
gid_t *gids[];
int *gidsLen;
uid_t uid;
{
gsscred_name_to_unix_cred_arg args;
gsscred_name_to_unix_cred_res res;
OM_uint32 major, minor;
gss_OID nameOid;
gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER;
/* check the input/output parameters */
if (intName == NULL || mechType == NULL)
return (GSS_S_CALL_INACCESSIBLE_READ);
if (uidOut == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
/* NULL out the output parameters */
*uidOut = 0;
if (gids)
*gids = NULL;
if (gidsLen)
*gidsLen = 0;
/* get the client handle to gssd */
if ((clnt = getgssd_handle()) == NULL)
{
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* convert the name to flat representation */
if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
!= GSS_S_COMPLETE)
{
return (major);
}
/* set the rpc parameters */
args.uid = uid;
args.pname.GSS_BUFFER_T_len = flatName.length;
args.pname.GSS_BUFFER_T_val = flatName.value;
args.name_type.GSS_OID_len = nameOid->length;
args.name_type.GSS_OID_val = nameOid->elements;
args.mech_type.GSS_OID_len = mechType->length;
args.mech_type.GSS_OID_val = mechType->elements;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
{
gss_release_buffer(&minor, &flatName);
return (GSS_S_FAILURE);
}
gss_release_buffer(&minor, &flatName);
/* copy the output parameters on output */
if (res.major == GSS_S_COMPLETE)
{
*uidOut = res.uid;
if (gidOut)
*gidOut = res.gid;
if (gids && gidsLen)
{
*gids = res.gids.GSSCRED_GIDS_val;
*gidsLen = res.gids.GSSCRED_GIDS_len;
res.gids.GSSCRED_GIDS_val = NULL;
res.gids.GSSCRED_GIDS_len = 0;
}
}
/* delete RPC allocated memory */
clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res);
return (res.major);
} /* kgsscred_name_to_unix_cred */
OM_uint32
kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
const uid_t puid;
gid_t *gidOut;
gid_t *gids[];
int *gidsLen;
uid_t uid;
{
gss_get_group_info_arg args;
gss_get_group_info_res res;
/* check the output parameters */
if (gidOut == NULL || gids == NULL || gidsLen == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
/* get the client GSSD handle */
if ((clnt = getgssd_handle()) == NULL)
{
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* set the input parameters */
args.uid = uid;
args.puid = puid;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS)
{
return (GSS_S_FAILURE);
}
/* copy the results */
if (res.major == GSS_S_COMPLETE)
{
*gidOut = res.gid;
*gids = res.gids.GSSCRED_GIDS_val;
*gidsLen = res.gids.GSSCRED_GIDS_len;
res.gids.GSSCRED_GIDS_val = NULL;
res.gids.GSSCRED_GIDS_len = 0;
}
/* nothing to free */
return (res.major);
} /* kgss_get_group_info */
OM_uint32
kgss_export_sec_context_wrapped(minor_status,
context_handle,
output_token,
gssd_context_verifier)
OM_uint32 *minor_status;
gssd_ctx_id_t *context_handle;
gss_buffer_t output_token;
OM_uint32 gssd_context_verifier;
{
CLIENT *clnt;
gss_export_sec_context_arg arg;
gss_export_sec_context_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
arg.gssd_context_verifier = gssd_context_verifier;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments, set minor_status
* to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (context_handle != NULL)
*context_handle = 0;
if (output_token != NULL)
output_token->length = 0;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (res.context_handle.GSS_CTX_ID_T_len == 0)
*context_handle = 0;
else
*context_handle =
*((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
output_token->length = res.output_token.GSS_BUFFER_T_len;
output_token->value =
(void *) MALLOC(output_token->length);
memcpy(output_token->value,
res.output_token.GSS_BUFFER_T_val,
output_token->length);
}
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_export_sec_context(minor_status,
context_handle,
output_token)
OM_uint32 *minor_status;
gss_ctx_id_t *context_handle;
gss_buffer_t output_token;
{
OM_uint32 err;
struct kgss_ctx *kctx;
if (*context_handle == GSS_C_NO_CONTEXT) {
return (GSS_S_NO_CONTEXT);
} else
kctx = KCTX_TO_KGSS_CTX(*context_handle);
err = kgss_export_sec_context_wrapped(minor_status,
&kctx->gssd_ctx, output_token,
kctx->gssd_ctx_verifier);
if (GSS_ERROR(err))
return (err);
else {
KGSS_FREE(kctx);
*context_handle = GSS_C_NO_CONTEXT;
return (err);
}
}
OM_uint32
kgss_import_sec_context_wrapped(minor_status,
input_token,
context_handle,
gssd_context_verifier)
OM_uint32 *minor_status;
gss_buffer_t input_token;
gss_ctx_id_t *context_handle;
OM_uint32 gssd_context_verifier;
{
CLIENT *clnt;
gss_import_sec_context_arg arg;
gss_import_sec_context_res res;
/* get the client handle to GSSD */
if ((clnt = getgssd_handle()) == NULL) {
clnt_pcreateerror(server);
return (GSS_S_FAILURE);
}
/* copy the procedure arguments into the rpc arg parameter */
arg.input_token.GSS_BUFFER_T_len = (uint_t)
(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
arg.input_token.GSS_BUFFER_T_val = (char *)
(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
arg.gssd_context_verifier = gssd_context_verifier;
/* call the remote procedure */
memset(&res, 0, sizeof (res));
if (gss_import_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
/*
* if the RPC call times out, null out all return arguments, set minor_status
* to its maximum value, and return GSS_S_FAILURE
*/
if (minor_status != NULL)
*minor_status = DEFAULT_MINOR_STAT;
if (context_handle != NULL)
*context_handle = NULL;
return (GSS_S_FAILURE);
}
/* copy the rpc results into the return arguments */
if (minor_status != NULL)
*minor_status = res.minor_status;
if (res.context_handle.GSS_CTX_ID_T_len == 0)
*context_handle = NULL;
else
*context_handle =
*((gss_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
/*
* free the memory allocated for the results and return with the status
* received in the rpc call
*/
clnt_freeres(clnt, xdr_gss_import_sec_context_res, (caddr_t)&res);
return (res.status);
}
OM_uint32
kgss_import_sec_context(minor_status,
input_token,
context_handle)
OM_uint32 *minor_status;
gss_buffer_t input_token;
gss_ctx_id_t *context_handle;
{
struct kgss_ctx *kctx;
if (*context_handle == GSS_C_NO_CONTEXT) {
kctx = KGSS_ALLOC();
*context_handle = (gss_ctx_id_t)kctx;
kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
} else
kctx = (struct kgss_ctx *)*context_handle;
return (kgss_import_sec_context_wrapped(minor_status,
input_token, &kctx->gssd_ctx,
KCTX_TO_CTXV(context_handle)));
}
#ifdef _KERNEL
#include
static void *gss_clnt = NULL;
#ifdef DEBUG
typedef struct {
char *name; /* just put something here */
} gssd_devstate_t;
static void *gssd_state;
static int gssd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
/* cmn_err(CE_NOTE, "In gssd_attach"); */
switch (cmd) {
case DDI_ATTACH:
if (ddi_create_minor_node(dip, "gssd", S_IFCHR, 0, "gssd", 0)
== DDI_FAILURE) {
ddi_remove_minor_node(dip, NULL);
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
static int gssd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
void *arg, void **result)
{
dev_t dev;
int error;
/* cmn_err(CE_NOTE, "In gssd_getinfo"); */
switch (infocmd) {
case DDI_INFO_DEVT2INSTANCE:
dev = (dev_t)arg;
*result = (void *) getminor(dev);
error = DDI_SUCCESS;
break;
case DDI_INFO_DEVT2DEVINFO:
/* cmn_err(CE_NOTE, "getinfo wants devinfo"); */
default:
error = DDI_FAILURE;
break;
}
return (error);
}
static int gssd_identify(dev_info_t *dip)
{
/* cmn_err(CE_NOTE, "in gssd_identify"); */
if (strcmp(ddi_get_name(dip), "gssd") == 0)
return (DDI_IDENTIFIED);
else
return (DDI_NOT_IDENTIFIED);
}
static int gssd_probe(dev_info_t *dip)
{
/* cmn_err(CE_NOTE, "In gssd_probe"); */
return (DDI_PROBE_SUCCESS);
}
static int gssd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
{
/* cmn_err (CE_NOTE, "In gssd_open"); */
if (otyp != OTYP_CHR)
return (EINVAL);
gss_clnt = getgssd_handle();
return (0);
}
static int gssd_close(dev_t dev, int flag, int otyp, cred_t *credp)
{
/* cmn_err(CE_NOTE, "In gssd_close"); */
killgssd_handle(gss_clnt);
return (0);
}
static int gssd_write(dev_t dev, struct uio *uiop, cred_t *credp)
{
char buffer[1024];
int len;
/* cmn_err(CE_NOTE, "In gssd_write"); */
bzero(buffer, 1024);
uiomove(buffer, 1024, UIO_WRITE, uiop);
len = strlen(buffer);
if (buffer[len-1] == '\n')
buffer[--len] = '\0';
cmn_err(CE_NOTE, "Got command: (%d) \"%s\"", len, buffer);
do_gssdtest(buffer);
return (0);
}
static struct cb_ops gssd_cb_ops = {
gssd_open, /* cb_open */
gssd_close, /* cb_close */
nodev, /* cb_strategy */
nodev, /* cb_print */
nodev, /* cb_dump */
nulldev, /* cb_read */
gssd_write, /* cb_write */
nodev, /* cb_ioctl */
nodev, /* cb_devmap */
nodev, /* cb_mmap */
nodev, /* cb_segmap */
nochpoll, /* cb_chpoll */
ddi_prop_op, /* cb_prop_op */
NULL, /* cb_stream */
(int)(D_NEW|D_MP) /* cb_flag */
};
static struct dev_ops gssd_ops = {
DEVO_REV, /* devo_rev */
0, /* devo_refcnt */
gssd_getinfo, /* devo_getinfo */
gssd_identify, /* devo_identify */
nulldev, /* devo_probe */
gssd_attach, /* devo_attach */
nulldev, /* devo_detach */
nodev, /* devo_reset */
&gssd_cb_ops, /* devo_cb_ops */
(struct bus_ops *)NULL /* devo_bus_ops */
};
extern struct mod_ops mod_driverops;
static struct modldrv modlmisc = {
&mod_driverops,
"GSSD DRV Client Module",
&gssd_ops
#else /* !DEBUG */
static struct modlmisc modlmisc = {
&mod_miscops,
"GSSD Client Module"
#endif /* DEBUG */
};
static struct modlinkage modlinkage = {
MODREV_1,
(void *)&modlmisc,
NULL
};
char _depends_on[] = "strmod/rpcmod misc/tlimod";
_init(void)
{
int status;
if ((status = ddi_soft_state_init(&gssd_state,
sizeof (gssd_devstate_t), 1)) != 0)
return (status);
if ((status = mod_install((struct modlinkage *)&modlinkage)) != 0)
ddi_soft_state_fini(&gssd_state);
cmn_err(CE_NOTE, "gssd: I'm in the kernel: %d.", status);
return (status);
}
_fini()
{
int status;
killgssd_handle(gss_clnt);
cmn_err(CE_NOTE, "gssd: Handle destroyed.. leaving module.");
if ((status = mod_remove(&modlinkage)) != 0)
return (status);
ddi_soft_state_fini(&gssd_state);
return (status);
}
_info(modinfop)
struct modinfo *modinfop;
{
return (mod_info(&modlinkage, modinfop));
}
#endif
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 (c) 1988-1997, by Sun Microsystems, Inc.
* All rights reserved.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
extern int __rpc_negotiate_uid(int);
/*
* The highest level interface for server creation.
* Copied from svc_generic.c and cmd/keyserv/key_generic.c, but adapted
* to work only for TPI_CLTS semantics, and to be called only once
* from gssd.c. Returns 1 (interface created) on success and 0
* (no interfaces created) on failure.
*/
int
svc_create_local_service(dispatch, prognum, versnum, nettype, servname)
void (*dispatch) (); /* Dispatch function */
u_long prognum; /* Program number */
u_long versnum; /* Version number */
char *nettype; /* Networktype token */
char *servname; /* name of the service */
{
int num = 0;
SVCXPRT *xprt;
struct netconfig *nconf;
struct t_bind *bind_addr;
void *net;
int fd;
struct nd_hostserv ns;
struct nd_addrlist *nas;
if ((net = __rpc_setconf(nettype)) == 0) {
(void) syslog(LOG_ERR,
gettext("svc_create: could not read netconfig database"));
return (0);
}
while (nconf = __rpc_getconf(net)) {
if ((strcmp(nconf->nc_protofmly, NC_LOOPBACK)) ||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
continue;
if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) < 0) {
(void) syslog(LOG_ERR,
gettext("svc_create: %s: cannot open connection: %s"),
nconf->nc_netid, t_errlist[t_errno]);
break;
}
/*
* Negotiate for returning the uid of the caller.
* This should be done before enabling the endpoint for
* service via t_bind() (called in svc_tli_create())
* so that requests to gssd contain the uid.
*/
if (__rpc_negotiate_uid(fd) != 0) {
syslog(LOG_ERR,
gettext("Could not negotiate for"
" uid with loopback transport %s"),
nconf->nc_netid);
t_close(fd);
break;
}
/* LINTED pointer alignment */
bind_addr = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR);
if ((bind_addr == NULL)) {
(void) t_close(fd);
(void) syslog(LOG_ERR,
gettext("svc_create: t_alloc failed\n"));
break;
}
ns.h_host = HOST_SELF;
ns.h_serv = servname;
if (!netdir_getbyname(nconf, &ns, &nas)) {
/* Copy the address */
bind_addr->addr.len = nas->n_addrs->len;
(void) memcpy(bind_addr->addr.buf, nas->n_addrs->buf,
(int) nas->n_addrs->len);
bind_addr->qlen = 8;
netdir_free((char *) nas, ND_ADDRLIST);
} else {
(void) syslog(LOG_ERR,
gettext("svc_create: no well known "
"address for %s on %s\n"),
servname, nconf->nc_netid);
(void) t_free((char *) bind_addr, T_BIND);
bind_addr = NULL;
}
xprt = svc_tli_create(fd, nconf, bind_addr, 0, 0);
if (bind_addr)
(void) t_free((char *) bind_addr, T_BIND);
if (xprt == NULL) {
(void) t_close(fd);
(void) syslog(LOG_ERR,
gettext("svc_create: svc_tli_create failed\n"));
break;
} else {
(void) rpcb_unset(prognum, versnum, nconf);
if (svc_reg(xprt, prognum, versnum, dispatch, nconf)
== FALSE) {
(void) syslog(LOG_ERR,
gettext("svc_create: cannot"
" register %d vers %d on %s"),
prognum, versnum, nconf->nc_netid);
SVC_DESTROY(xprt); /* also t_closes fd */
break;
}
num = 1;
break;
}
}
__rpc_endconf(net);
return (num);
}
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Routines to set gssd value of uid and replace getuid libsys call.
*/
#include
#include
#include
#include
#include
#include
#include
#include
static uid_t krb5_cc_uid;
#define LOWPRIVS "basic,!file_link_any,!proc_info,!proc_session," \
"!proc_fork,!proc_exec"
static priv_set_t *lowprivs = NULL;
static priv_set_t *highprivs = NULL;
/*
* NOTE WELL: This assumes gssd is NOT multi-threaded. Do NOT add -A to
* the rpcgen argument list in the Makefile unless you also remove this
* assumption.
*/
void
set_gssd_uid(uid_t uid)
{
/* Initialize */
if (lowprivs == NULL) {
/* L, P & I shall not change in gssd; we manipulate P though */
if ((highprivs = priv_allocset()) == NULL ||
(lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) {
printf(gettext(
"fatal: can't allocate privilege set (%s)\n"),
strerror(ENOMEM));
syslog(LOG_ERR, "Fatal: can't allocate privilege "
"set (%s)"), strerror(ENOMEM);
exit(1);
}
/* P has the privs we need when we need privs */
(void) getppriv(PRIV_PERMITTED, highprivs);
/*
* In case "basic" grows privs not excluded in LOWPRIVS
* but excluded in the service's method_context
*/
priv_intersect(highprivs, lowprivs);
(void) setpflags(PRIV_AWARE, 1);
}
printf(gettext("set_gssd_uid called with uid = %d\n"), uid);
/*
* nfsd runs as UID 1, so upcalls triggered by nfsd will cause uid to
* 1 here, but nfsd's upcalls need to run as root with privs here.
*/
if (uid == 1)
uid = 0;
/*
* Set the value of krb5_cc_uid, so it can be retrieved when
* app_krb5_user_uid() is called by the underlying mechanism
* libraries. This should go away soon.
*/
krb5_cc_uid = uid;
/* Claw privs back */
(void) setppriv(PRIV_SET, PRIV_EFFECTIVE, highprivs);
/*
* Switch uid and set the saved set-uid to 0 so setuid(0) will work
* later.
*/
if (setuid(0) != 0 ||
(uid != 0 && setreuid(uid, -1) != 0) ||
(uid != 0 && seteuid(uid) != 0)) {
/* Not enough privs, so bail! */
printf(gettext(
"fatal: gssd is running with insufficient privilege\n"));
syslog(LOG_ERR, "Fatal: gssd is running with insufficient "
"privilege.");
exit(1);
}
/* Temporarily drop privs, but only if uid != 0 */
if (uid != 0)
(void) setppriv(PRIV_SET, PRIV_EFFECTIVE, lowprivs);
}
uid_t
app_krb5_user_uid(void)
{
/*
* return the value set when one of the gssd procedures was
* entered. This is the value of the uid under which the
* underlying mechanism library must operate in order to
* get the user's credentials. This call is necessary since
* gssd runs as root and credentials are many times stored
* in files and directories specific to the user
*/
printf(gettext(
"getuid called and returning krb5_cc_uid = %d\n"), krb5_cc_uid);
return (krb5_cc_uid);
}
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
* All Rights Reserved
*
* Portions of this source code were derived from Berkeley
* 4.3 BSD under license from the Regents of the University of
* California.
*/
/* from kerbd_handle.c 1.3 92/01/29 SMI */
/*
* gssd_handle.c, Interface to gssd
*
*/
#include
#include
#include
#include
#include
#include
#include
#include "gssd.h"
#ifdef DEBUG
#define dprt(msg) (void) fprintf(stderr, "%s\n", msg);
#else
#define dprt(msg)
#endif /* DEBUG */
/*
* Keep the handle cached. This call may be made quite often.
*/
CLIENT *
getgssd_handle()
{
void *localhandle;
struct netconfig *nconf;
struct netconfig *tpconf;
static CLIENT *clnt;
struct timeval wait_time;
struct utsname u;
static char *hostname;
static bool_t first_time = TRUE;
#define TOTAL_TIMEOUT 1000 /* total timeout talking to gssd */
#define TOTAL_TRIES 1 /* Number of tries */
if (clnt)
return (clnt);
if (!(localhandle = setnetconfig()))
return (NULL);
tpconf = NULL;
if (first_time == TRUE) {
if (uname(&u) == -1)
return ((CLIENT *) NULL);
if ((hostname = strdup(u.nodename)) == (char *)NULL)
return ((CLIENT *) NULL);
first_time = FALSE;
}
while (nconf = getnetconfig(localhandle)) {
if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
if (nconf->nc_semantics == NC_TPI_COTS_ORD) {
clnt = clnt_tp_create(hostname,
GSSPROG, GSSVERS, nconf);
if (clnt) {
dprt("got COTS_ORD\n");
break;
}
} else {
tpconf = nconf;
}
}
}
if ((clnt == NULL) && (tpconf)) {
/* Now, try the connection-oriented loopback transport */
clnt = clnt_tp_create(hostname, GSSPROG, GSSVERS, tpconf);
#ifdef DEBUG
if (clnt) {
dprt("got COTS\n");
}
#endif /* DEBUG */
}
endnetconfig(localhandle);
/*
* This bit of code uses an as yet unimplemented argument to
* clnt_control(). CLSET_SVC_PRIV specifies that the underlying
* loopback transport should be checked to ensure it is
* connected to a process running as root. If so, the clnt_control()
* call returns TRUE. If not, it returns FALSE.
*/
#ifdef CLSET_SVC_PRIV
if (clnt_control(clnt, CLSET_SVC_PRIV, NULL) != TRUE) {
clnt_destroy(clnt);
clnt = NULL;
return (NULL);
{
#endif
if (clnt == NULL)
return (NULL);
clnt->cl_auth = authsys_create("", getuid(), 0, 0, NULL);
if (clnt->cl_auth == NULL) {
clnt_destroy(clnt);
clnt = NULL;
return (NULL);
}
wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
wait_time.tv_usec = 0;
(void) clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *)&wait_time);
return (clnt);
}
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 2017 Joyent Inc
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
* RPC server procedures for the gssapi usermode daemon gssd.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gssd.h"
#include
#include
#include
#include
#include
#include
#define SRVTAB ""
#define FDCACHE_PERCENTAGE .75 /* Percentage of total FD limit */
#define FDCACHE_DEFAULT 16 /* Default LRU cache size */
#define GSSD_FD_LIMIT 255 /* Increase number of fds allowed */
extern int gssd_debug; /* declared in gssd.c */
static OM_uint32 gssd_time_verf; /* verifies same gssd */
static OM_uint32 context_verf; /* context sequence numbers */
struct gssd_ctx_slot {
struct gssd_ctx_slot *lru_next;
struct gssd_ctx_slot *lru_prev;
bool_t inuse;
OM_uint32 create_time;
OM_uint32 verf;
gss_ctx_id_t ctx;
gss_ctx_id_t rpcctx;
};
struct gssd_ctx_slot *gssd_ctx_slot_tbl;
struct gssd_ctx_slot *gssd_lru_head;
static int max_contexts;
static int checkfrom(struct svc_req *, uid_t *);
extern void set_gssd_uid(uid_t);
extern int __rpc_get_local_uid(SVCXPRT *, uid_t *);
/*
* Syslog (and output to stderr if debug set) the GSSAPI major
* and minor numbers.
*/
static void
syslog_gss_error(OM_uint32 maj_stat, OM_uint32 min_stat, char *errstr)
{
OM_uint32 gmaj_stat, gmin_stat;
gss_buffer_desc msg;
OM_uint32 msg_ctx = 0;
if (gssd_debug)
fprintf(stderr,
"gssd: syslog_gss_err: called from %s: maj=%d min=%d\n",
errstr ? errstr : "", maj_stat, min_stat);
/* Print the major status error from the mech. */
/* msg_ctx - skip the check for it as is probably unnecesary */
gmaj_stat = gss_display_status(&gmin_stat, maj_stat,
GSS_C_GSS_CODE,
GSS_C_NULL_OID, &msg_ctx, &msg);
if ((gmaj_stat == GSS_S_COMPLETE)||
(gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
syslog(LOG_DAEMON|LOG_NOTICE,
"GSSAPI error major: %s", (char *)msg.value);
if (gssd_debug)
(void) fprintf(stderr,
"gssd: GSSAPI error major: %s\n",
(char *)msg.value);
(void) gss_release_buffer(&gmin_stat, &msg);
}
/* Print the minor status error from the mech. */
msg_ctx = 0;
/* msg_ctx - skip the check for it as is probably unnecesary */
gmaj_stat = gss_display_status(&gmin_stat, min_stat,
GSS_C_MECH_CODE,
GSS_C_NULL_OID,
&msg_ctx, &msg);
if ((gmaj_stat == GSS_S_COMPLETE)||
(gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
syslog(LOG_DAEMON|LOG_NOTICE,
"GSSAPI error minor: %s",
(char *)msg.value);
if (gssd_debug)
(void) fprintf(stderr,
"gssd: GSSAPI error minor: %s\n",
(char *)msg.value);
(void) gss_release_buffer(&gmin_stat, &msg);
}
}
void
gssd_setup(char *arg)
{
int i;
struct rlimit rl;
hrtime_t high_res_time;
gssd_time_verf = (OM_uint32)time(NULL);
max_contexts = FDCACHE_DEFAULT;
/*
* Use low order bits of high resolution time to get a reasonably
* random number to start the context sequencing. This alternative
* to using a time value avoid clock resets via NTP or ntpdate.
*/
high_res_time = gethrtime();
context_verf = (OM_uint32)high_res_time;
/*
* Increase resource limit of FDs in case we get alot accept/init_
* sec_context calls before we're able to export them. This can
* happen in very heavily load environments where gssd doesn't get
* much time to work on its backlog.
*/
if ((getrlimit(RLIMIT_NOFILE, &rl)) == 0) {
rl.rlim_cur = (rl.rlim_max >= GSSD_FD_LIMIT) ?
GSSD_FD_LIMIT : rl.rlim_max;
if ((setrlimit(RLIMIT_NOFILE, &rl)) == 0)
max_contexts = rl.rlim_cur * FDCACHE_PERCENTAGE;
(void) enable_extended_FILE_stdio(-1, -1);
}
gssd_ctx_slot_tbl = (struct gssd_ctx_slot *)
malloc(sizeof (struct gssd_ctx_slot) * max_contexts);
if (gssd_ctx_slot_tbl == NULL) {
(void) fprintf(stderr,
gettext("[%s] could not allocate %d byte context table"
"\n"), arg,
(sizeof (struct gssd_ctx_slot) * max_contexts));
exit(1);
}
for (i = 1; i < max_contexts; i++) {
gssd_ctx_slot_tbl[i-1].lru_next = &gssd_ctx_slot_tbl[i];
gssd_ctx_slot_tbl[i].lru_prev = &gssd_ctx_slot_tbl[i-1];
gssd_ctx_slot_tbl[i].inuse = FALSE;
gssd_ctx_slot_tbl[i].verf = 0;
gssd_ctx_slot_tbl[i].create_time = 0;
gssd_ctx_slot_tbl[i].rpcctx = (gss_ctx_id_t)(i + 1);
}
gssd_ctx_slot_tbl[max_contexts - 1].lru_next = &gssd_ctx_slot_tbl[0];
gssd_ctx_slot_tbl[0].lru_prev = &gssd_ctx_slot_tbl[max_contexts - 1];
gssd_ctx_slot_tbl[0].inuse = FALSE;
gssd_ctx_slot_tbl[0].verf = 0;
gssd_ctx_slot_tbl[0].create_time = 0;
gssd_ctx_slot_tbl[0].rpcctx = (gss_ctx_id_t)1;
gssd_lru_head = &gssd_ctx_slot_tbl[0];
}
static OM_uint32 syslog_interval = 60;
static struct gssd_ctx_slot *
gssd_alloc_slot(gss_ctx_id_t ctx)
{
struct gssd_ctx_slot *lru;
OM_uint32 current_time;
static OM_uint32 last_syslog = 0;
static bool_t first_take = TRUE;
static int tooks;
OM_uint32 minor_status;
lru = gssd_lru_head;
gssd_lru_head = lru->lru_next;
current_time = (OM_uint32) time(NULL);
if (last_syslog == 0)
last_syslog = current_time; /* Save 1st alloc time */
if (lru->inuse) {
if (lru->ctx != GSS_C_NO_CONTEXT)
(void) gss_delete_sec_context(&minor_status,
&lru->ctx, NULL);
tooks++;
if (((current_time - last_syslog) > syslog_interval) ||
first_take) {
syslog(LOG_WARNING, gettext("re-used an existing "
"context slot of age %u seconds (%d slots re-"
"used during last %u seconds)"),
current_time - lru->create_time, tooks,
current_time - last_syslog);
last_syslog = current_time;
tooks = 0;
first_take = FALSE;
}
}
/*
* Assign the next context verifier to the context (avoiding zero).
*/
context_verf++;
if (context_verf == 0)
context_verf = 1;
lru->verf = context_verf;
lru->create_time = current_time;
lru->ctx = ctx;
lru->inuse = TRUE;
return (lru);
}
/*
* We always add 1 because we don't want slot 0 to be confused
* with GSS_C_NO_CONTEXT.
*/
static struct gssd_ctx_slot *
gssd_handle_to_slot(GSS_CTX_ID_T *h)
{
intptr_t i;
if (h->GSS_CTX_ID_T_len == 0) {
return (NULL);
}
if (h->GSS_CTX_ID_T_len != sizeof (i))
return (NULL);
i = (*(intptr_t *)(h->GSS_CTX_ID_T_val)) - 1;
if (i < 0 || i >= max_contexts)
return (NULL);
return (&gssd_ctx_slot_tbl[i]);
}
static void
gssd_rel_slot(struct gssd_ctx_slot *lru)
{
struct gssd_ctx_slot *prev, *next;
if (lru == NULL)
return;
lru->inuse = FALSE;
/*
* Remove entry from its current location in list
*/
prev = lru->lru_prev;
next = lru->lru_next;
prev->lru_next = next;
next->lru_prev = prev;
/*
* Since it is no longer in use, it is the least recently
* used.
*/
prev = gssd_lru_head->lru_prev;
next = gssd_lru_head;
prev->lru_next = lru;
lru->lru_prev = prev;
next->lru_prev = lru;
lru->lru_next = next;
gssd_lru_head = lru;
}
static void
gssd_convert_context_handle(GSS_CTX_ID_T *h,
gss_ctx_id_t *context_handle,
OM_uint32 verf,
bool_t *context_verf_ok,
struct gssd_ctx_slot **slotp)
{
struct gssd_ctx_slot *slot;
*context_verf_ok = FALSE;
*context_handle = (gss_ctx_id_t)1;
if (slotp != NULL)
*slotp = NULL;
if (h->GSS_CTX_ID_T_len == 0) {
*context_handle = GSS_C_NO_CONTEXT;
*context_verf_ok = TRUE;
return;
}
slot = gssd_handle_to_slot(h);
if (slot == NULL)
return;
if (verf != slot->verf)
return;
*context_verf_ok = TRUE;
*context_handle = slot->ctx;
if (slotp != NULL)
*slotp = slot;
}
bool_t
gss_acquire_cred_1_svc(argp, res, rqstp)
gss_acquire_cred_arg *argp;
gss_acquire_cred_res *res;
struct svc_req *rqstp;
{
OM_uint32 minor_status;
gss_name_t desired_name;
gss_OID_desc name_type_desc;
gss_OID name_type = &name_type_desc;
OM_uint32 time_req;
gss_OID_set_desc desired_mechs_desc;
gss_OID_set desired_mechs;
int cred_usage;
gss_cred_id_t output_cred_handle;
gss_OID_set actual_mechs;
gss_buffer_desc external_name;
uid_t uid;
int i, j;
if (gssd_debug)
fprintf(stderr, gettext("gss_acquire_cred\n"));
memset(res, 0, sizeof (*res));
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->output_cred_handle.GSS_CRED_ID_T_val = NULL;
res->actual_mechs.GSS_OID_SET_val = NULL;
return (FALSE);
}
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
/* convert the desired name from external to internal format */
external_name.length = argp->desired_name.GSS_BUFFER_T_len;
external_name.value = (void *)malloc(external_name.length);
if (!external_name.value)
return (GSS_S_FAILURE);
memcpy(external_name.value, argp->desired_name.GSS_BUFFER_T_val,
external_name.length);
if (argp->name_type.GSS_OID_len == 0) {
name_type = GSS_C_NULL_OID;
} else {
name_type->length = argp->name_type.GSS_OID_len;
name_type->elements = (void *)malloc(name_type->length);
if (!name_type->elements) {
free(external_name.value);
return (GSS_S_FAILURE);
}
memcpy(name_type->elements, argp->name_type.GSS_OID_val,
name_type->length);
}
if (gss_import_name(&minor_status, &external_name, name_type,
&desired_name) != GSS_S_COMPLETE) {
res->status = (OM_uint32) GSS_S_FAILURE;
res->minor_status = minor_status;
free(external_name.value);
if (name_type != GSS_C_NULL_OID)
free(name_type->elements);
return (TRUE);
}
/*
* copy the XDR structured arguments into their corresponding local GSSAPI
* variables.
*/
cred_usage = argp->cred_usage;
time_req = argp->time_req;
if (argp->desired_mechs.GSS_OID_SET_len != 0) {
desired_mechs = &desired_mechs_desc;
desired_mechs->count =
(int)argp->desired_mechs.GSS_OID_SET_len;
desired_mechs->elements = (gss_OID)
malloc(sizeof (gss_OID_desc) * desired_mechs->count);
if (!desired_mechs->elements) {
free(external_name.value);
free(name_type->elements);
return (GSS_S_FAILURE);
}
for (i = 0; i < desired_mechs->count; i++) {
desired_mechs->elements[i].length =
(OM_uint32)argp->desired_mechs.
GSS_OID_SET_val[i].GSS_OID_len;
desired_mechs->elements[i].elements =
(void *)malloc(desired_mechs->elements[i].
length);
if (!desired_mechs->elements[i].elements) {
free(external_name.value);
free(name_type->elements);
for (j = 0; j < (i -1); j++) {
free
(desired_mechs->elements[j].elements);
}
free(desired_mechs->elements);
return (GSS_S_FAILURE);
}
memcpy(desired_mechs->elements[i].elements,
argp->desired_mechs.GSS_OID_SET_val[i].
GSS_OID_val,
desired_mechs->elements[i].length);
}
} else
desired_mechs = GSS_C_NULL_OID_SET;
/* call the gssapi routine */
res->status = (OM_uint32)gss_acquire_cred(&res->minor_status,
desired_name,
time_req,
desired_mechs,
cred_usage,
&output_cred_handle,
&actual_mechs,
&res->time_rec);
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result
*/
res->output_cred_handle.GSS_CRED_ID_T_len = sizeof (gss_cred_id_t);
res->output_cred_handle.GSS_CRED_ID_T_val =
(void *)malloc(sizeof (gss_cred_id_t));
if (!res->output_cred_handle.GSS_CRED_ID_T_val) {
free(external_name.value);
free(name_type->elements);
for (i = 0; i < desired_mechs->count; i++) {
free(desired_mechs->elements[i].elements);
}
free(desired_mechs->elements);
return (GSS_S_FAILURE);
}
memcpy(res->output_cred_handle.GSS_CRED_ID_T_val, &output_cred_handle,
sizeof (gss_cred_id_t));
if (actual_mechs != GSS_C_NULL_OID_SET) {
res->actual_mechs.GSS_OID_SET_len =
(uint_t)actual_mechs->count;
res->actual_mechs.GSS_OID_SET_val = (GSS_OID *)
malloc(sizeof (GSS_OID) * actual_mechs->count);
if (!res->actual_mechs.GSS_OID_SET_val) {
free(external_name.value);
free(name_type->elements);
for (i = 0; i < desired_mechs->count; i++) {
free(desired_mechs->elements[i].elements);
}
free(desired_mechs->elements);
free(res->output_cred_handle.GSS_CRED_ID_T_val);
return (GSS_S_FAILURE);
}
for (i = 0; i < actual_mechs->count; i++) {
res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len =
(uint_t)actual_mechs->elements[i].length;
res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val =
(char *)malloc(actual_mechs->elements[i].
length);
if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) {
free(external_name.value);
free(name_type->elements);
free(desired_mechs->elements);
for (j = 0; j < desired_mechs->count; j++) {
free
(desired_mechs->elements[i].elements);
}
free(res->actual_mechs.GSS_OID_SET_val);
for (j = 0; j < (i - 1); j++) {
free
(res->actual_mechs.
GSS_OID_SET_val[j].GSS_OID_val);
}
return (GSS_S_FAILURE);
}
memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
actual_mechs->elements[i].elements,
actual_mechs->elements[i].length);
}
} else
res->actual_mechs.GSS_OID_SET_len = 0;
/*
* set the time verifier for credential handle. To ensure that the
* timestamp is not the same as previous gssd process, verify that
* time is not the same as set earlier at start of process. If it
* is, sleep one second and reset. (due to one second granularity)
*/
if (res->status == GSS_S_COMPLETE) {
res->gssd_cred_verifier = (OM_uint32)time(NULL);
if (res->gssd_cred_verifier == gssd_time_verf) {
sleep(1);
gssd_time_verf = (OM_uint32)time(NULL);
}
res->gssd_cred_verifier = gssd_time_verf;
} else
syslog_gss_error(res->status, res->minor_status,
"acquire_cred");
/*
* now release the space allocated by the underlying gssapi mechanism
* library for actual_mechs as well as by this routine for
* external_name, name_type and desired_name
*/
free(external_name.value);
if (name_type != GSS_C_NULL_OID)
free(name_type->elements);
gss_release_name(&minor_status, &desired_name);
if (actual_mechs != GSS_C_NULL_OID_SET) {
for (i = 0; i < actual_mechs->count; i++)
free(actual_mechs->elements[i].elements);
free(actual_mechs->elements);
free(actual_mechs);
}
if (desired_mechs != GSS_C_NULL_OID_SET) {
for (i = 0; i < desired_mechs->count; i++)
free(desired_mechs->elements[i].elements);
free(desired_mechs->elements);
}
/* return to caller */
return (TRUE);
}
bool_t
gss_add_cred_1_svc(argp, res, rqstp)
gss_add_cred_arg *argp;
gss_add_cred_res *res;
struct svc_req *rqstp;
{
OM_uint32 minor_status;
gss_name_t desired_name;
gss_OID_desc name_type_desc;
gss_OID name_type = &name_type_desc;
gss_OID_desc desired_mech_type_desc;
gss_OID desired_mech_type = &desired_mech_type_desc;
int cred_usage;
gss_cred_id_t input_cred_handle;
gss_OID_set actual_mechs;
gss_buffer_desc external_name;
uid_t uid;
int i, j;
if (gssd_debug)
fprintf(stderr, gettext("gss_add_cred\n"));
if (argp->gssd_cred_verifier != gssd_time_verf) {
res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
res->minor_status = 0;
res->actual_mechs.GSS_OID_SET_len = 0;
res->actual_mechs.GSS_OID_SET_val = NULL;
res->initiator_time_rec = 0;
res->acceptor_time_rec = 0;
fprintf(stderr, gettext("gss_add_cred defective cred\n"));
return (TRUE);
}
memset(res, 0, sizeof (*res));
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
return (FALSE);
}
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
/* convert the desired name from external to internal format */
external_name.length = argp->desired_name.GSS_BUFFER_T_len;
external_name.value = (void *)argp->desired_name.GSS_BUFFER_T_val;
name_type->length = argp->name_type.GSS_OID_len;
name_type->elements = (void *)argp->name_type.GSS_OID_val;
if (gss_import_name(&minor_status, &external_name, name_type,
&desired_name) != GSS_S_COMPLETE) {
if (gssd_debug)
fprintf(stderr,
gettext("gss_add_cred:import name"),
gettext(" failed status %d \n"),
res->status);
res->status = (OM_uint32)GSS_S_FAILURE;
res->minor_status = minor_status;
return (TRUE);
}
/*
* copy the XDR structured arguments into their corresponding local GSSAPI
* variables.
*/
cred_usage = argp->cred_usage;
if (argp->desired_mech_type.GSS_OID_len == 0)
desired_mech_type = GSS_C_NULL_OID;
else {
desired_mech_type->length =
(OM_uint32)argp->desired_mech_type.GSS_OID_len;
desired_mech_type->elements =
(void *)malloc(desired_mech_type->length);
if (!desired_mech_type->elements) {
return (GSS_S_FAILURE);
}
memcpy(desired_mech_type->elements,
argp->desired_mech_type.GSS_OID_val,
desired_mech_type->length);
}
input_cred_handle =
(argp->input_cred_handle.GSS_CRED_ID_T_len == 0 ?
GSS_C_NO_CREDENTIAL :
/*LINTED*/
*((gss_cred_id_t *)argp->input_cred_handle.
GSS_CRED_ID_T_val));
if (input_cred_handle != GSS_C_NO_CREDENTIAL)
/* verify the input_cred_handle */
if (argp->gssd_cred_verifier != gssd_time_verf) {
res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
res->minor_status = 0;
return (TRUE);
}
/* call the gssapi routine */
res->status = (OM_uint32)gss_add_cred(&res->minor_status,
input_cred_handle,
desired_name,
desired_mech_type,
cred_usage,
argp->initiator_time_req,
argp->acceptor_time_req,
NULL,
&actual_mechs,
&res->initiator_time_rec,
&res->acceptor_time_rec);
if ((res->status != GSS_S_COMPLETE) &&
(res->status != GSS_S_DUPLICATE_ELEMENT))
syslog_gss_error(res->status, res->minor_status, "add_cred");
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result
*/
if (actual_mechs != GSS_C_NULL_OID_SET) {
res->actual_mechs.GSS_OID_SET_len =
(uint_t)actual_mechs->count;
res->actual_mechs.GSS_OID_SET_val = (GSS_OID *)
malloc(sizeof (GSS_OID) * actual_mechs->count);
if (!res->actual_mechs.GSS_OID_SET_val) {
free(desired_mech_type->elements);
free(desired_mech_type);
return (GSS_S_FAILURE);
}
for (i = 0; i < actual_mechs->count; i++) {
res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_len =
(uint_t)actual_mechs->elements[i].length;
res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val =
(char *)malloc(actual_mechs->elements[i].
length);
if (!res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val) {
free(desired_mech_type->elements);
free(desired_mech_type);
free(res->actual_mechs.GSS_OID_SET_val);
for (j = 0; j < (i - 1); j++) {
free
(res->actual_mechs.
GSS_OID_SET_val[j].GSS_OID_val);
}
return (GSS_S_FAILURE);
}
memcpy(res->actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
actual_mechs->elements[i].elements,
actual_mechs->elements[i].length);
}
} else
res->actual_mechs.GSS_OID_SET_len = 0;
/*
* now release the space allocated for
* desired_name and desired_mech_type
*/
gss_release_name(&minor_status, &desired_name);
free(desired_mech_type->elements);
gss_release_oid_set(&minor_status, &actual_mechs);
/*
* if (actual_mechs != GSS_C_NULL_OID_SET) {
* for (i = 0; i < actual_mechs->count; i++)
* free(actual_mechs->elements[i].elements);
* free(actual_mechs->elements);
* free(actual_mechs);
* }
*/
/* return to caller */
return (TRUE);
}
bool_t
gss_release_cred_1_svc(argp, res, rqstp)
gss_release_cred_arg *argp;
gss_release_cred_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_cred_id_t cred_handle;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_release_cred\n"));
if (checkfrom(rqstp, &uid) == 0)
return (FALSE);
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
/*
* if the cred_handle verifier is not correct,
* set status to GSS_S_DEFECTIVE_CREDENTIAL and return
*/
if (argp->gssd_cred_verifier != gssd_time_verf) {
res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
return (TRUE);
}
/*
* if the cred_handle length is 0
* set cred_handle argument to GSS_S_NO_CREDENTIAL
*/
if (argp->cred_handle.GSS_CRED_ID_T_len == 0)
cred_handle = GSS_C_NO_CREDENTIAL;
else
cred_handle =
(gss_cred_id_t)argp->cred_handle.GSS_CRED_ID_T_val;
/* call the gssapi routine */
res->status = (OM_uint32)gss_release_cred(&res->minor_status,
&cred_handle);
/* return to caller */
return (TRUE);
}
bool_t
gss_init_sec_context_1_svc(argp, res, rqstp)
gss_init_sec_context_arg *argp;
gss_init_sec_context_res *res;
struct svc_req *rqstp;
{
OM_uint32 minor_status;
gss_ctx_id_t context_handle;
bool_t context_verf_ok;
gss_cred_id_t claimant_cred_handle;
gss_buffer_desc external_name;
gss_OID_desc name_type_desc;
gss_OID name_type = &name_type_desc;
gss_name_t internal_name;
gss_OID_desc mech_type_desc;
gss_OID mech_type = &mech_type_desc;
struct gss_channel_bindings_struct
input_chan_bindings;
gss_channel_bindings_t input_chan_bindings_ptr;
gss_buffer_desc input_token;
gss_buffer_desc output_token;
gss_buffer_t input_token_ptr;
gss_OID actual_mech_type;
struct gssd_ctx_slot *slot = NULL;
uid_t uid;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_init_sec_context\n"));
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->actual_mech_type.GSS_OID_val = NULL;
res->output_token.GSS_BUFFER_T_val = NULL;
return (FALSE);
}
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
/*
* copy the supplied context handle into the local context handle, so it
* can be supplied to the gss_init_sec_context call
*/
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, &slot);
claimant_cred_handle =
(argp->claimant_cred_handle.GSS_CRED_ID_T_len == 0 ?
GSS_C_NO_CREDENTIAL :
/*LINTED*/
*((gss_cred_id_t *)argp->claimant_cred_handle.
GSS_CRED_ID_T_val));
if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
/* verify the verifier_cred_handle */
if (argp->gssd_cred_verifier != gssd_time_verf) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->output_token.GSS_BUFFER_T_val = NULL;
res->actual_mech_type.GSS_OID_val = NULL;
res->context_handle.GSS_CTX_ID_T_len = 0;
res->output_token.GSS_BUFFER_T_len = 0;
res->actual_mech_type.GSS_OID_len = 0;
res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
res->minor_status = 0;
return (TRUE);
}
}
if (context_handle != GSS_C_NO_CONTEXT) {
/* verify the verifier_context_handle */
if (!context_verf_ok) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->output_token.GSS_BUFFER_T_val = NULL;
res->actual_mech_type.GSS_OID_val = NULL;
res->context_handle.GSS_CTX_ID_T_len = 0;
res->output_token.GSS_BUFFER_T_len = 0;
res->actual_mech_type.GSS_OID_len = 0;
res->status = (OM_uint32)GSS_S_NO_CONTEXT;
res->minor_status = 0;
return (TRUE);
}
}
/* convert the target name from external to internal format */
external_name.length = argp->target_name.GSS_BUFFER_T_len;
external_name.value = (void *)argp->target_name.GSS_BUFFER_T_val;
if (argp->name_type.GSS_OID_len == 0) {
name_type = GSS_C_NULL_OID;
} else {
name_type->length = argp->name_type.GSS_OID_len;
name_type->elements = (void *)malloc(name_type->length);
if (!name_type->elements)
return (GSS_S_FAILURE);
memcpy(name_type->elements, argp->name_type.GSS_OID_val,
name_type->length);
}
if (argp->mech_type.GSS_OID_len == 0)
mech_type = GSS_C_NULL_OID;
else {
mech_type->length = (OM_uint32)argp->mech_type.GSS_OID_len;
mech_type->elements = (void *)argp->mech_type.GSS_OID_val;
}
if (gss_import_name(&minor_status, &external_name, name_type,
&internal_name) != GSS_S_COMPLETE) {
if (name_type != GSS_C_NULL_OID)
free(name_type->elements);
res->status = (OM_uint32)GSS_S_FAILURE;
res->minor_status = minor_status;
return (TRUE);
}
/*
* copy the XDR structured arguments into their corresponding local GSSAPI
* variables.
*/
if (argp->input_chan_bindings.present == YES) {
input_chan_bindings_ptr = &input_chan_bindings;
input_chan_bindings.initiator_addrtype =
(OM_uint32)argp->input_chan_bindings.
initiator_addrtype;
input_chan_bindings.initiator_address.length =
(uint_t)argp->input_chan_bindings.initiator_address.
GSS_BUFFER_T_len;
input_chan_bindings.initiator_address.value =
(void *)argp->input_chan_bindings.initiator_address.
GSS_BUFFER_T_val;
input_chan_bindings.acceptor_addrtype =
(OM_uint32)argp->input_chan_bindings.acceptor_addrtype;
input_chan_bindings.acceptor_address.length =
(uint_t)argp->input_chan_bindings.acceptor_address.
GSS_BUFFER_T_len;
input_chan_bindings.acceptor_address.value =
(void *)argp->input_chan_bindings.acceptor_address.
GSS_BUFFER_T_val;
input_chan_bindings.application_data.length =
(uint_t)argp->input_chan_bindings.application_data.
GSS_BUFFER_T_len;
input_chan_bindings.application_data.value =
(void *)argp->input_chan_bindings.application_data.
GSS_BUFFER_T_val;
} else {
input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS;
input_chan_bindings.initiator_addrtype = 0;
input_chan_bindings.initiator_address.length = 0;
input_chan_bindings.initiator_address.value = 0;
input_chan_bindings.acceptor_addrtype = 0;
input_chan_bindings.acceptor_address.length = 0;
input_chan_bindings.acceptor_address.value = 0;
input_chan_bindings.application_data.length = 0;
input_chan_bindings.application_data.value = 0;
}
if (argp->input_token.GSS_BUFFER_T_len == 0) {
input_token_ptr = GSS_C_NO_BUFFER;
} else {
input_token_ptr = &input_token;
input_token.length = (size_t)
argp->input_token.GSS_BUFFER_T_len;
input_token.value = (void *)argp->input_token.GSS_BUFFER_T_val;
}
/* call the gssapi routine */
res->status = (OM_uint32)gss_init_sec_context(&res->minor_status,
(gss_cred_id_t)argp->claimant_cred_handle.
GSS_CRED_ID_T_val,
&context_handle,
internal_name,
mech_type,
argp->req_flags,
argp->time_req,
input_chan_bindings_ptr,
input_token_ptr,
&actual_mech_type,
&output_token,
&res->ret_flags,
&res->time_rec);
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result
*/
if (res->status == (OM_uint32)GSS_S_COMPLETE ||
res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
if (slot == NULL || slot->ctx != context_handle) {
/*
* Note that gssd_alloc_slot() will delete ctx's as long
* as we don't call gssd_rel_slot().
*/
slot = gssd_alloc_slot(context_handle);
}
res->gssd_context_verifier = slot->verf;
res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
res->context_handle.GSS_CTX_ID_T_val =
(void *)malloc(sizeof (gss_ctx_id_t));
if (!res->context_handle.GSS_CTX_ID_T_val) {
free(name_type->elements);
return (GSS_S_FAILURE);
}
memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
sizeof (gss_ctx_id_t));
res->output_token.GSS_BUFFER_T_len =
(uint_t)output_token.length;
res->output_token.GSS_BUFFER_T_val =
(char *)output_token.value;
/*
* the actual mech type parameter
* is ready only upon GSS_S_COMPLETE
*/
if (res->status == GSS_S_COMPLETE) {
res->actual_mech_type.GSS_OID_len =
(uint_t)actual_mech_type->length;
res->actual_mech_type.GSS_OID_val =
(void *)malloc(actual_mech_type->length);
if (!res->actual_mech_type.GSS_OID_val) {
free(name_type->elements);
free(res->context_handle.GSS_CTX_ID_T_val);
return (GSS_S_FAILURE);
}
memcpy(res->actual_mech_type.GSS_OID_val,
(char *)actual_mech_type->elements,
actual_mech_type->length);
} else
res->actual_mech_type.GSS_OID_len = 0;
} else {
syslog_gss_error(res->status, res->minor_status,
"init_sec_context");
if (context_handle != GSS_C_NO_CONTEXT) {
(void) gss_delete_sec_context(&minor_status,
&context_handle, NULL);
}
res->context_handle.GSS_CTX_ID_T_len = 0;
res->actual_mech_type.GSS_OID_len = 0;
res->output_token.GSS_BUFFER_T_len = 0;
}
/*
* now release the space allocated by the underlying gssapi mechanism
* library for internal_name and for the name_type.
*/
gss_release_name(&minor_status, &internal_name);
if (name_type != GSS_C_NULL_OID)
free(name_type->elements);
/* return to caller */
return (TRUE);
}
bool_t
gss_accept_sec_context_1_svc(argp, res, rqstp)
gss_accept_sec_context_arg *argp;
gss_accept_sec_context_res *res;
struct svc_req *rqstp;
{
uid_t uid;
OM_uint32 minor_status;
gss_ctx_id_t context_handle = NULL;
gss_cred_id_t verifier_cred_handle;
gss_buffer_desc external_name;
gss_name_t internal_name = NULL;
gss_buffer_desc input_token_buffer;
gss_buffer_t input_token_buffer_ptr;
struct gss_channel_bindings_struct
input_chan_bindings;
gss_channel_bindings_t input_chan_bindings_ptr;
gss_OID mech_type;
gss_buffer_desc output_token;
gss_cred_id_t delegated_cred_handle;
bool_t context_verf_ok;
struct gssd_ctx_slot *slot = NULL;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_accept_sec_context\n"));
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->src_name.GSS_BUFFER_T_val = NULL;
res->mech_type.GSS_OID_val = NULL;
res->output_token.GSS_BUFFER_T_val = NULL;
res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
return (FALSE);
}
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
/*
* copy the supplied context handle into the local context handle, so
* it can be supplied to the gss_accept_sec_context call
*/
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, &slot);
if (context_handle != GSS_C_NO_CONTEXT)
/* verify the context_handle */
if (!context_verf_ok) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->src_name.GSS_BUFFER_T_val = NULL;
res->mech_type.GSS_OID_val = NULL;
res->output_token.GSS_BUFFER_T_val = NULL;
res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
res->src_name.GSS_BUFFER_T_len = 0;
res->context_handle.GSS_CTX_ID_T_len = 0;
res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
res->output_token.GSS_BUFFER_T_len = 0;
res->mech_type.GSS_OID_len = 0;
res->status = (OM_uint32)GSS_S_NO_CONTEXT;
res->minor_status = 0;
return (TRUE);
}
/*
* copy the XDR structured arguments into their corresponding local
* GSSAPI variable equivalents.
*/
verifier_cred_handle =
(argp->verifier_cred_handle.GSS_CRED_ID_T_len == 0 ?
GSS_C_NO_CREDENTIAL :
/*LINTED*/
*((gss_cred_id_t *)argp->verifier_cred_handle.
GSS_CRED_ID_T_val));
if (verifier_cred_handle != GSS_C_NO_CREDENTIAL)
/* verify the verifier_cred_handle */
if (argp->gssd_cred_verifier != gssd_time_verf) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->src_name.GSS_BUFFER_T_val = NULL;
res->mech_type.GSS_OID_val = NULL;
res->output_token.GSS_BUFFER_T_val = NULL;
res->delegated_cred_handle.GSS_CRED_ID_T_val = NULL;
res->src_name.GSS_BUFFER_T_len = 0;
res->context_handle.GSS_CTX_ID_T_len = 0;
res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
res->output_token.GSS_BUFFER_T_len = 0;
res->mech_type.GSS_OID_len = 0;
res->status = (OM_uint32)GSS_S_DEFECTIVE_CREDENTIAL;
res->minor_status = 0;
return (TRUE);
}
input_token_buffer_ptr = &input_token_buffer;
input_token_buffer.length = (size_t)argp->input_token_buffer.
GSS_BUFFER_T_len;
input_token_buffer.value = (void *)argp->input_token_buffer.
GSS_BUFFER_T_val;
if (argp->input_chan_bindings.present == YES) {
input_chan_bindings_ptr = &input_chan_bindings;
input_chan_bindings.initiator_addrtype =
(OM_uint32)argp->input_chan_bindings.
initiator_addrtype;
input_chan_bindings.initiator_address.length =
(uint_t)argp->input_chan_bindings.initiator_address.
GSS_BUFFER_T_len;
input_chan_bindings.initiator_address.value =
(void *)argp->input_chan_bindings.initiator_address.
GSS_BUFFER_T_val;
input_chan_bindings.acceptor_addrtype =
(OM_uint32)argp->input_chan_bindings.
acceptor_addrtype;
input_chan_bindings.acceptor_address.length =
(uint_t)argp->input_chan_bindings.acceptor_address.
GSS_BUFFER_T_len;
input_chan_bindings.acceptor_address.value =
(void *)argp->input_chan_bindings.acceptor_address.
GSS_BUFFER_T_val;
input_chan_bindings.application_data.length =
(uint_t)argp->input_chan_bindings.application_data.
GSS_BUFFER_T_len;
input_chan_bindings.application_data.value =
(void *)argp->input_chan_bindings.application_data.
GSS_BUFFER_T_val;
} else {
input_chan_bindings_ptr = GSS_C_NO_CHANNEL_BINDINGS;
input_chan_bindings.initiator_addrtype = 0;
input_chan_bindings.initiator_address.length = 0;
input_chan_bindings.initiator_address.value = 0;
input_chan_bindings.acceptor_addrtype = 0;
input_chan_bindings.acceptor_address.length = 0;
input_chan_bindings.acceptor_address.value = 0;
input_chan_bindings.application_data.length = 0;
input_chan_bindings.application_data.value = 0;
}
/* call the gssapi routine */
res->status = (OM_uint32)gss_accept_sec_context(&res->minor_status,
&context_handle,
verifier_cred_handle,
input_token_buffer_ptr,
input_chan_bindings_ptr,
&internal_name,
&mech_type,
&output_token,
&res->ret_flags,
&res->time_rec,
&delegated_cred_handle);
/* convert the src name from internal to external format */
if (res->status == (OM_uint32)GSS_S_COMPLETE ||
res->status == (OM_uint32)GSS_S_CONTINUE_NEEDED) {
/*
* upon GSS_S_CONTINUE_NEEDED only the following
* parameters are ready: minor, ctxt, and output token
*/
res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
res->context_handle.GSS_CTX_ID_T_val =
(void *)malloc(sizeof (gss_ctx_id_t));
if (!res->context_handle.GSS_CTX_ID_T_val) {
res->status = (OM_uint32)GSS_S_FAILURE;
res->minor_status = 0;
return (TRUE);
}
if (slot == NULL || slot->ctx != context_handle) {
/*
* Note that gssd_alloc_slot() will delete ctx's as long
* as we don't call gssd_rel_slot().
*/
slot = gssd_alloc_slot(context_handle);
}
memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
sizeof (gss_ctx_id_t));
res->gssd_context_verifier = slot->verf;
res->output_token.GSS_BUFFER_T_len =
(uint_t)output_token.length;
res->output_token.GSS_BUFFER_T_val =
(char *)output_token.value;
if (res->status == GSS_S_COMPLETE) {
if (gss_export_name(&minor_status, internal_name,
&external_name)
!= GSS_S_COMPLETE) {
res->status = (OM_uint32)GSS_S_FAILURE;
res->minor_status = minor_status;
gss_release_name(&minor_status, &internal_name);
gss_delete_sec_context(&minor_status,
&context_handle, NULL);
free(res->context_handle.GSS_CTX_ID_T_val);
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->context_handle.GSS_CTX_ID_T_len = 0;
gss_release_buffer(&minor_status,
&output_token);
res->output_token.GSS_BUFFER_T_len = 0;
res->output_token.GSS_BUFFER_T_val = NULL;
return (TRUE);
}
res->src_name.GSS_BUFFER_T_len =
(uint_t)external_name.length;
res->src_name.GSS_BUFFER_T_val =
(void *)external_name.value;
res->delegated_cred_handle.GSS_CRED_ID_T_len =
sizeof (gss_cred_id_t);
res->delegated_cred_handle.GSS_CRED_ID_T_val =
(void *)malloc(sizeof (gss_cred_id_t));
if (!res->delegated_cred_handle.GSS_CRED_ID_T_val) {
free(res->context_handle.GSS_CTX_ID_T_val);
gss_release_name(&minor_status, &internal_name);
gss_delete_sec_context(&minor_status,
&context_handle, NULL);
gss_release_buffer(&minor_status,
&external_name);
res->status = (OM_uint32)GSS_S_FAILURE;
res->minor_status = 0;
return (TRUE);
}
memcpy(res->delegated_cred_handle.GSS_CRED_ID_T_val,
&delegated_cred_handle,
sizeof (gss_cred_id_t));
res->mech_type.GSS_OID_len = (uint_t)mech_type->length;
res->mech_type.GSS_OID_val =
(void *)malloc(mech_type->length);
if (!res->mech_type.GSS_OID_val) {
free(res->context_handle.GSS_CTX_ID_T_val);
free(res->delegated_cred_handle.GSS_CRED_ID_T_val);
gss_release_name(&minor_status, &internal_name);
gss_delete_sec_context(&minor_status,
&context_handle, NULL);
gss_release_buffer(&minor_status, &external_name);
res->status = (OM_uint32)GSS_S_FAILURE;
res->minor_status = 0;
return (TRUE);
}
memcpy(res->mech_type.GSS_OID_val, mech_type->elements,
mech_type->length);
/* release the space allocated for internal_name */
gss_release_name(&minor_status, &internal_name);
} else { /* GSS_S_CONTINUE_NEEDED */
res->src_name.GSS_BUFFER_T_len = 0;
res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
res->mech_type.GSS_OID_len = 0;
}
} else {
syslog_gss_error(res->status, res->minor_status,
"accept_sec_context");
if (context_handle != GSS_C_NO_CONTEXT) {
(void) gss_delete_sec_context(&minor_status,
&context_handle, NULL);
}
res->src_name.GSS_BUFFER_T_len = 0;
res->context_handle.GSS_CTX_ID_T_len = 0;
res->delegated_cred_handle.GSS_CRED_ID_T_len = 0;
res->output_token.GSS_BUFFER_T_len =
(uint_t)output_token.length;
res->output_token.GSS_BUFFER_T_val =
(char *)output_token.value;
res->mech_type.GSS_OID_len = 0;
}
/* return to caller */
return (TRUE);
}
bool_t
gss_process_context_token_1_svc(argp, res, rqstp)
gss_process_context_token_arg *argp;
gss_process_context_token_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_buffer_desc token_buffer;
gss_ctx_id_t context_handle;
bool_t context_verf_ok;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_process_context_token\n"));
if (checkfrom(rqstp, &uid) == 0)
return (FALSE);
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, NULL);
/* verify the context_handle */
if (!context_verf_ok) {
res->status = (OM_uint32) GSS_S_NO_CONTEXT;
res->minor_status = 0;
return (TRUE);
}
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
/*
* copy the XDR structured arguments into their corresponding local
* GSSAPI variable equivalents.
*/
token_buffer.length = (size_t)argp->token_buffer.GSS_BUFFER_T_len;
token_buffer.value = (void *)argp->token_buffer.GSS_BUFFER_T_val;
/* call the gssapi routine */
res->status = (OM_uint32)gss_process_context_token(&res->minor_status,
context_handle,
&token_buffer);
if (GSS_ERROR(res->status))
syslog_gss_error(res->status, res->minor_status,
"process_context_token");
/* return to caller */
return (TRUE);
}
bool_t
gss_delete_sec_context_1_svc(argp, res, rqstp)
gss_delete_sec_context_arg *argp;
gss_delete_sec_context_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_ctx_id_t context_handle;
gss_buffer_desc output_token;
bool_t context_verf_ok;
struct gssd_ctx_slot *slot = NULL;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_delete_sec_context\n"));
/*
* copy the supplied context handle into the local context handle, so it
* can be supplied to the gss_delete_sec_context call
*/
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, &slot);
/* verify the context_handle */
if (!context_verf_ok) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->context_handle.GSS_CTX_ID_T_len = 0;
res->output_token.GSS_BUFFER_T_val = NULL;
res->output_token.GSS_BUFFER_T_len = 0;
res->status = (OM_uint32)GSS_S_NO_CONTEXT;
res->minor_status = 0;
return (TRUE);
}
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->output_token.GSS_BUFFER_T_val = NULL;
return (FALSE);
}
/* call the gssapi routine */
res->status = (OM_uint32)gss_delete_sec_context(&res->minor_status,
&context_handle,
&output_token);
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result. If the delete succeeded, return a zero
* context handle.
*/
if (res->status == GSS_S_COMPLETE) {
if (context_handle != GSS_C_NO_CONTEXT)
return (GSS_S_FAILURE);
res->context_handle.GSS_CTX_ID_T_len = 0;
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->output_token.GSS_BUFFER_T_len =
(uint_t)output_token.length;
res->output_token.GSS_BUFFER_T_val =
(char *)output_token.value;
if (slot != NULL) {
/*
* gss_delete_sec_context deletes the context if it
* succeeds so clear slot->ctx to avoid a dangling
* reference.
*/
slot->ctx = GSS_C_NO_CONTEXT;
gssd_rel_slot(slot);
}
} else {
res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
res->context_handle.GSS_CTX_ID_T_val =
(void *)malloc(sizeof (gss_ctx_id_t));
if (!res->context_handle.GSS_CTX_ID_T_val) {
return (GSS_S_FAILURE);
}
if (slot == NULL || slot->ctx != context_handle) {
/*
* Note that gssd_alloc_slot() will delete ctx's as long
* as we don't call gssd_rel_slot().
*/
slot = gssd_alloc_slot(context_handle);
/*
* Note that no verifier is returned in the .x
* protocol. So if the context changes, we won't
* be able to release it now. So it will have to
* be LRUed out.
*/
}
memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
sizeof (gss_ctx_id_t));
res->output_token.GSS_BUFFER_T_len = 0;
res->output_token.GSS_BUFFER_T_val = NULL;
}
/* return to caller */
return (TRUE);
}
bool_t
gss_export_sec_context_1_svc(argp, res, rqstp)
gss_export_sec_context_arg *argp;
gss_export_sec_context_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_ctx_id_t context_handle;
gss_buffer_desc output_token;
bool_t context_verf_ok;
struct gssd_ctx_slot *slot = NULL;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, "gss_export_sec_context\n");
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->output_token.GSS_BUFFER_T_val = NULL;
return (FALSE);
}
/*
* copy the supplied context handle into the local context handle, so it
* can be supplied to the gss_export_sec_context call
*/
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, &slot);
/* verify the context_handle */
if (!context_verf_ok) {
res->status = (OM_uint32)GSS_S_NO_CONTEXT;
/* the rest of "res" was cleared by a previous memset() */
return (TRUE);
}
/* call the gssapi routine */
res->status = (OM_uint32)gss_export_sec_context(&res->minor_status,
&context_handle,
&output_token);
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result. If the delete succeeded, return a zero context
* handle.
*/
if (res->status == GSS_S_COMPLETE) {
if (context_handle != GSS_C_NO_CONTEXT)
return (GSS_S_FAILURE);
res->context_handle.GSS_CTX_ID_T_len = 0;
res->context_handle.GSS_CTX_ID_T_val = NULL;
res->output_token.GSS_BUFFER_T_len =
(uint_t)output_token.length;
res->output_token.GSS_BUFFER_T_val =
(char *)output_token.value;
if (slot != NULL) {
/*
* gss_export_sec_context deletes the context if it
* succeeds so set slot->ctx to avoid a dangling
* reference.
*/
slot->ctx = GSS_C_NO_CONTEXT;
gssd_rel_slot(slot);
}
} else {
res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
res->context_handle.GSS_CTX_ID_T_val =
(void *)malloc(sizeof (gss_ctx_id_t));
if (slot == NULL || slot->ctx != context_handle) {
/*
* Note that gssd_alloc_slot() will delete ctx's as long
* as we don't call gssd_rel_slot().
*/
slot = gssd_alloc_slot(context_handle);
/*
* Note that no verifier is returned in the .x
* protocol. So if the context changes, we won't
* be able to release it now. So it will have to
* be LRUed out.
*/
}
memcpy(res->context_handle.GSS_CTX_ID_T_val, &slot->rpcctx,
sizeof (gss_ctx_id_t));
res->output_token.GSS_BUFFER_T_len = 0;
res->output_token.GSS_BUFFER_T_val = NULL;
}
/* return to caller */
return (TRUE);
}
/*
* This routine doesn't appear to ever be called.
*/
bool_t
gss_import_sec_context_1_svc(argp, res, rqstp)
gss_import_sec_context_arg *argp;
gss_import_sec_context_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_ctx_id_t context_handle;
gss_buffer_desc input_token;
gss_buffer_t input_token_ptr;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, "gss_export_sec_context\n");
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->context_handle.GSS_CTX_ID_T_val = NULL;
return (FALSE);
}
if (argp->input_token.GSS_BUFFER_T_len == 0) {
input_token_ptr = GSS_C_NO_BUFFER;
} else {
input_token_ptr = &input_token;
input_token.length = (size_t)
argp->input_token.GSS_BUFFER_T_len;
input_token.value = (void *) argp->input_token.GSS_BUFFER_T_val;
}
/* call the gssapi routine */
res->status = (OM_uint32) gss_import_sec_context(&res->minor_status,
input_token_ptr,
&context_handle);
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result. If the delete succeeded, return a zero context
* handle.
*/
if (res->status == GSS_S_COMPLETE) {
res->context_handle.GSS_CTX_ID_T_len = sizeof (gss_ctx_id_t);
res->context_handle.GSS_CTX_ID_T_val =
(void *) malloc(sizeof (gss_ctx_id_t));
memcpy(res->context_handle.GSS_CTX_ID_T_val, &context_handle,
sizeof (gss_ctx_id_t));
} else {
res->context_handle.GSS_CTX_ID_T_len = 0;
res->context_handle.GSS_CTX_ID_T_val = NULL;
}
/* return to caller */
return (TRUE);
}
bool_t
gss_context_time_1_svc(argp, res, rqstp)
gss_context_time_arg *argp;
gss_context_time_res *res;
struct svc_req *rqstp;
{
uid_t uid;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_context_time\n"));
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0)
return (FALSE);
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
/* Semantics go here */
return (TRUE);
}
bool_t
gss_sign_1_svc(argp, res, rqstp)
gss_sign_arg *argp;
gss_sign_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_buffer_desc message_buffer;
gss_buffer_desc msg_token;
gss_ctx_id_t context_handle;
bool_t context_verf_ok;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_sign\n"));
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, NULL);
/* verify the context_handle */
if (!context_verf_ok) {
res->msg_token.GSS_BUFFER_T_val = NULL;
res->msg_token.GSS_BUFFER_T_len = 0;
res->status = (OM_uint32) GSS_S_NO_CONTEXT;
res->minor_status = 0;
return (TRUE);
}
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->msg_token.GSS_BUFFER_T_val = NULL;
return (FALSE);
}
/*
* copy the XDR structured arguments into their corresponding local
* GSSAPI variable equivalents.
*/
message_buffer.length = (size_t)argp->message_buffer.GSS_BUFFER_T_len;
message_buffer.value = (void *)argp->message_buffer.GSS_BUFFER_T_val;
/* call the gssapi routine */
res->status = (OM_uint32)gss_sign(&res->minor_status,
context_handle,
argp->qop_req,
(gss_buffer_t)&message_buffer,
(gss_buffer_t)&msg_token);
/*
* convert the output args from the parameter given in the call to
* the variable in the XDR result
*/
if (res->status == GSS_S_COMPLETE) {
res->msg_token.GSS_BUFFER_T_len = (uint_t)msg_token.length;
res->msg_token.GSS_BUFFER_T_val = (char *)msg_token.value;
} else
syslog_gss_error(res->status, res->minor_status, "sign");
/* return to caller */
return (TRUE);
}
bool_t
gss_verify_1_svc(argp, res, rqstp)
gss_verify_arg *argp;
gss_verify_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_buffer_desc message_buffer;
gss_buffer_desc token_buffer;
gss_ctx_id_t context_handle;
bool_t context_verf_ok;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_verify\n"));
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, NULL);
/* verify the context_handle */
if (!context_verf_ok) {
res->status = (OM_uint32) GSS_S_NO_CONTEXT;
res->minor_status = 0;
return (TRUE);
}
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0)
return (FALSE);
/*
* copy the XDR structured arguments into their corresponding local
* GSSAPI variable equivalents.
*/
message_buffer.length = (size_t)argp->message_buffer.GSS_BUFFER_T_len;
message_buffer.value = (void *)argp->message_buffer.GSS_BUFFER_T_val;
token_buffer.length = (size_t)argp->token_buffer.GSS_BUFFER_T_len;
token_buffer.value = (void *)argp->token_buffer.GSS_BUFFER_T_val;
/* call the gssapi routine */
res->status = (OM_uint32)gss_verify(&res->minor_status,
context_handle,
&message_buffer,
&token_buffer,
&res->qop_state);
if (GSS_ERROR(res->status))
syslog_gss_error(res->status, res->minor_status, "verify");
/* return to caller */
return (TRUE);
}
bool_t
gss_seal_1_svc(argp, res, rqstp)
gss_seal_arg *argp;
gss_seal_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_buffer_desc input_message_buffer;
gss_buffer_desc output_message_buffer;
gss_ctx_id_t context_handle;
bool_t context_verf_ok;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_seal\n"));
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, NULL);
/* verify the context_handle */
if (!context_verf_ok) {
res->output_message_buffer.GSS_BUFFER_T_val = NULL;
res->output_message_buffer.GSS_BUFFER_T_len = 0;
res->status = (OM_uint32) GSS_S_NO_CONTEXT;
res->minor_status = 0;
return (TRUE);
}
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->output_message_buffer.GSS_BUFFER_T_val = NULL;
return (FALSE);
}
/*
* copy the XDR structured arguments into their corresponding local
* GSSAPI variable equivalents.
*/
input_message_buffer.length = (size_t)argp->input_message_buffer.
GSS_BUFFER_T_len;
input_message_buffer.value = (void *)argp->input_message_buffer.
GSS_BUFFER_T_val;
/* call the gssapi routine */
res->status = (OM_uint32)gss_seal(&res->minor_status,
context_handle,
argp->conf_req_flag,
argp->qop_req,
&input_message_buffer,
&res->conf_state,
&output_message_buffer);
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result
*/
if (res->status == GSS_S_COMPLETE) {
res->output_message_buffer.GSS_BUFFER_T_len =
(uint_t)output_message_buffer.length;
res->output_message_buffer.GSS_BUFFER_T_val =
(char *)output_message_buffer.value;
} else
syslog_gss_error(res->status, res->minor_status, "seal");
/* return to caller */
return (TRUE);
}
bool_t
gss_unseal_1_svc(argp, res, rqstp)
gss_unseal_arg *argp;
gss_unseal_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_buffer_desc input_message_buffer;
gss_buffer_desc output_message_buffer;
gss_ctx_id_t context_handle;
bool_t context_verf_ok;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_unseal\n"));
/* verify the context_handle */
gssd_convert_context_handle(&argp->context_handle, &context_handle,
argp->gssd_context_verifier, &context_verf_ok, NULL);
/* verify the context_handle */
if (!context_verf_ok) {
res->output_message_buffer.GSS_BUFFER_T_val = NULL;
res->output_message_buffer.GSS_BUFFER_T_len = 0;
res->status = (OM_uint32)GSS_S_NO_CONTEXT;
res->minor_status = 0;
return (TRUE);
}
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->output_message_buffer.GSS_BUFFER_T_val = NULL;
return (FALSE);
}
/*
* copy the XDR structured arguments into their corresponding local
* GSSAPI variable equivalents.
*/
input_message_buffer.length = (size_t)argp->input_message_buffer.
GSS_BUFFER_T_len;
input_message_buffer.value = (void *)argp->input_message_buffer.
GSS_BUFFER_T_val;
/* call the gssapi routine */
res->status = (OM_uint32)gss_unseal(&res->minor_status,
context_handle,
&input_message_buffer,
&output_message_buffer,
&res->conf_state,
&res->qop_state);
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result
*/
if (res->status == GSS_S_COMPLETE) {
res->output_message_buffer.GSS_BUFFER_T_len =
(uint_t)output_message_buffer.length;
res->output_message_buffer.GSS_BUFFER_T_val =
(char *)output_message_buffer.value;
} else
syslog_gss_error(res->status, res->minor_status, "unseal");
/* return to caller */
return (TRUE);
}
bool_t
gss_display_status_1_svc(argp, res, rqstp)
gss_display_status_arg *argp;
gss_display_status_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_OID mech_type;
gss_OID_desc mech_type_desc;
gss_buffer_desc status_string;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_display_status\n"));
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->status_string.GSS_BUFFER_T_val = NULL;
return (FALSE);
}
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
/*
* copy the XDR structured arguments into their corresponding local
* GSSAPI variables.
*/
if (argp->mech_type.GSS_OID_len == 0)
mech_type = GSS_C_NULL_OID;
else {
mech_type = &mech_type_desc;
mech_type_desc.length = (OM_uint32) argp->mech_type.GSS_OID_len;
mech_type_desc.elements = (void *) argp->mech_type.GSS_OID_val;
}
/* call the gssapi routine */
res->status = (OM_uint32) gss_display_status(&res->minor_status,
argp->status_value,
argp->status_type,
mech_type,
(OM_uint32 *)&res->message_context,
&status_string);
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result
*/
if (res->status == GSS_S_COMPLETE) {
res->status_string.GSS_BUFFER_T_len =
(uint_t)status_string.length;
res->status_string.GSS_BUFFER_T_val =
(char *)status_string.value;
}
return (TRUE);
}
/*ARGSUSED*/
bool_t
gss_indicate_mechs_1_svc(argp, res, rqstp)
void *argp;
gss_indicate_mechs_res *res;
struct svc_req *rqstp;
{
gss_OID_set oid_set;
uid_t uid;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_indicate_mechs\n"));
res->mech_set.GSS_OID_SET_val = NULL;
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
return (FALSE);
}
res->status = gss_indicate_mechs(&res->minor_status, &oid_set);
if (res->status == GSS_S_COMPLETE) {
int i, j;
res->mech_set.GSS_OID_SET_len = oid_set->count;
res->mech_set.GSS_OID_SET_val = (void *)
malloc(oid_set->count * sizeof (GSS_OID));
if (!res->mech_set.GSS_OID_SET_val) {
return (GSS_S_FAILURE);
}
for (i = 0; i < oid_set->count; i++) {
res->mech_set.GSS_OID_SET_val[i].GSS_OID_len =
oid_set->elements[i].length;
res->mech_set.GSS_OID_SET_val[i].GSS_OID_val =
(char *)malloc(oid_set->elements[i].length);
if (!res->mech_set.GSS_OID_SET_val[i].GSS_OID_val) {
for (j = 0; j < (i -1); j++) {
free
(res->mech_set.GSS_OID_SET_val[i].GSS_OID_val);
}
free(res->mech_set.GSS_OID_SET_val);
return (GSS_S_FAILURE);
}
memcpy(res->mech_set.GSS_OID_SET_val[i].GSS_OID_val,
oid_set->elements[i].elements,
oid_set->elements[i].length);
}
}
return (TRUE);
}
bool_t
gss_inquire_cred_1_svc(argp, res, rqstp)
gss_inquire_cred_arg *argp;
gss_inquire_cred_res *res;
struct svc_req *rqstp;
{
uid_t uid;
OM_uint32 minor_status;
gss_cred_id_t cred_handle;
gss_buffer_desc external_name;
gss_OID name_type;
gss_name_t internal_name;
gss_OID_set mechanisms;
int i, j;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_inquire_cred\n"));
/* verify the verifier_cred_handle */
if (argp->gssd_cred_verifier != gssd_time_verf) {
res->name.GSS_BUFFER_T_val = NULL;
res->name_type.GSS_OID_val = NULL;
res->mechanisms.GSS_OID_SET_val = NULL;
res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
res->minor_status = 0;
return (TRUE);
}
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
res->name.GSS_BUFFER_T_val = NULL;
res->name_type.GSS_OID_val = NULL;
res->mechanisms.GSS_OID_SET_val = NULL;
return (FALSE);
}
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
GSS_C_NO_CREDENTIAL :
/*LINTED*/
*((gss_cred_id_t *)argp->cred_handle.
GSS_CRED_ID_T_val));
/* call the gssapi routine */
res->status = (OM_uint32)gss_inquire_cred(&res->minor_status,
cred_handle,
&internal_name,
&res->lifetime,
&res->cred_usage,
&mechanisms);
if (res->status != GSS_S_COMPLETE) {
syslog_gss_error(res->status, res->minor_status,
"inquire_cred");
return (TRUE);
}
/* convert the returned name from internal to external format */
if (gss_display_name(&minor_status, internal_name,
&external_name, &name_type)
!= GSS_S_COMPLETE) {
res->status = (OM_uint32)GSS_S_FAILURE;
res->minor_status = minor_status;
gss_release_name(&minor_status, &internal_name);
if (mechanisms != GSS_C_NULL_OID_SET) {
for (i = 0; i < mechanisms->count; i++)
free(mechanisms->elements[i].elements);
free(mechanisms->elements);
free(mechanisms);
}
return (TRUE);
}
/*
* convert the output args from the parameter given in the call to the
* variable in the XDR result
*/
res->name.GSS_BUFFER_T_len = (uint_t)external_name.length;
res->name.GSS_BUFFER_T_val = (void *)external_name.value;
/*
* we have to allocate storage for name_type here, since the value
* returned from gss_display_name points to the underlying mechanism
* static storage. If we didn't allocate storage, the next time
* through this routine, the xdr_free() call at the beginning would
* try to free up that static storage.
*/
res->name_type.GSS_OID_len = (uint_t)name_type->length;
res->name_type.GSS_OID_val = (void *)malloc(name_type->length);
if (!res->name_type.GSS_OID_val) {
return (GSS_S_FAILURE);
}
memcpy(res->name_type.GSS_OID_val, name_type->elements,
name_type->length);
if (mechanisms != GSS_C_NULL_OID_SET) {
res->mechanisms.GSS_OID_SET_len =
(uint_t)mechanisms->count;
res->mechanisms.GSS_OID_SET_val = (GSS_OID *)
malloc(sizeof (GSS_OID) * mechanisms->count);
if (!res->mechanisms.GSS_OID_SET_val) {
free(res->name_type.GSS_OID_val);
return (GSS_S_FAILURE);
}
for (i = 0; i < mechanisms->count; i++) {
res->mechanisms.GSS_OID_SET_val[i].GSS_OID_len =
(uint_t)mechanisms->elements[i].length;
res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val =
(char *)malloc(mechanisms->elements[i].
length);
if (!res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val) {
free(res->name_type.GSS_OID_val);
for (j = 0; j < i; j++) {
free(res->mechanisms.
GSS_OID_SET_val[i].GSS_OID_val);
}
free(res->mechanisms.GSS_OID_SET_val);
return (GSS_S_FAILURE);
}
memcpy(res->mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
mechanisms->elements[i].elements,
mechanisms->elements[i].length);
}
} else
res->mechanisms.GSS_OID_SET_len = 0;
/* release the space allocated for internal_name and mechanisms */
gss_release_name(&minor_status, &internal_name);
if (mechanisms != GSS_C_NULL_OID_SET) {
for (i = 0; i < mechanisms->count; i++)
free(mechanisms->elements[i].elements);
free(mechanisms->elements);
free(mechanisms);
}
/* return to caller */
return (TRUE);
}
bool_t
gss_inquire_cred_by_mech_1_svc(argp, res, rqstp)
gss_inquire_cred_by_mech_arg *argp;
gss_inquire_cred_by_mech_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_cred_id_t cred_handle;
gss_OID_desc mech_type_desc;
gss_OID mech_type = &mech_type_desc;
memset(res, 0, sizeof (*res));
if (gssd_debug)
fprintf(stderr, gettext("gss_inquire_cred\n"));
/* verify the verifier_cred_handle */
if (argp->gssd_cred_verifier != gssd_time_verf) {
res->status = (OM_uint32) GSS_S_DEFECTIVE_CREDENTIAL;
res->minor_status = 0;
return (TRUE);
}
/*
* if the request isn't from root, null out the result pointer
* entries, so the next time through xdr_free won't try to
* free unmalloc'd memory and then return NULL
*/
if (checkfrom(rqstp, &uid) == 0) {
return (FALSE);
}
/* set the uid sent as the RPC argument */
uid = argp->uid;
set_gssd_uid(uid);
cred_handle = (argp->cred_handle.GSS_CRED_ID_T_len == 0 ?
GSS_C_NO_CREDENTIAL :
/*LINTED*/
*((gss_cred_id_t *)argp->cred_handle.
GSS_CRED_ID_T_val));
/* call the gssapi routine */
if (argp->mech_type.GSS_OID_len == 0)
mech_type = GSS_C_NULL_OID;
else {
mech_type->length =
(OM_uint32)argp->mech_type.GSS_OID_len;
mech_type->elements =
(void *)malloc(mech_type->length);
if (!mech_type->elements) {
return (GSS_S_FAILURE);
}
memcpy(mech_type->elements,
argp->mech_type.GSS_OID_val,
mech_type->length);
}
res->status = (OM_uint32)gss_inquire_cred_by_mech(
&res->minor_status, cred_handle,
mech_type, NULL, NULL,
NULL, NULL);
/* return to caller */
return (TRUE);
}
bool_t
gsscred_name_to_unix_cred_1_svc(argsp, res, rqstp)
gsscred_name_to_unix_cred_arg *argsp;
gsscred_name_to_unix_cred_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_OID_desc oid;
gss_name_t gssName;
gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER;
OM_uint32 minor;
int gidsLen;
gid_t *gids, gidOut;
if (gssd_debug)
fprintf(stderr, gettext("gsscred_name_to_unix_cred\n"));
memset(res, 0, sizeof (*res));
/*
* check the request originator
*/
if (checkfrom(rqstp, &uid) == 0)
return (FALSE);
/* set the uid from the rpc request */
uid = argsp->uid;
set_gssd_uid(uid);
/*
* convert the principal name to gss internal format
* need not malloc the input parameters
*/
gssBuf.length = argsp->pname.GSS_BUFFER_T_len;
gssBuf.value = (void*)argsp->pname.GSS_BUFFER_T_val;
oid.length = argsp->name_type.GSS_OID_len;
oid.elements = (void*)argsp->name_type.GSS_OID_val;
res->major = gss_import_name(&minor, &gssBuf, &oid, &gssName);
if (res->major != GSS_S_COMPLETE)
return (TRUE);
/* retrieve the mechanism type from the arguments */
oid.length = argsp->mech_type.GSS_OID_len;
oid.elements = (void*)argsp->mech_type.GSS_OID_val;
/* call the gss extensions to map the principal name to unix creds */
res->major = gsscred_name_to_unix_cred(gssName, &oid, &uid, &gidOut,
&gids, &gidsLen);
gss_release_name(&minor, &gssName);
if (res->major == GSS_S_COMPLETE) {
res->uid = uid;
res->gid = gidOut;
res->gids.GSSCRED_GIDS_val = gids;
res->gids.GSSCRED_GIDS_len = gidsLen;
}
return (TRUE);
} /* gsscred_name_to_unix_cred_svc_1 */
bool_t
gsscred_expname_to_unix_cred_1_svc(argsp, res, rqstp)
gsscred_expname_to_unix_cred_arg *argsp;
gsscred_expname_to_unix_cred_res *res;
struct svc_req *rqstp;
{
uid_t uid;
gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
int gidsLen;
gid_t *gids, gidOut;
if (gssd_debug)
fprintf(stderr, gettext("gsscred_expname_to_unix_cred\n"));
memset(res, 0, sizeof (*res));
/*
* check the request originator
*/
if (checkfrom(rqstp, &uid) == 0)
return (FALSE);
/* set the uid from the rpc request */
uid = argsp->uid;
set_gssd_uid(uid);
/*
* extract the export name from arguments
* need not malloc the input parameters
*/
expName.length = argsp->expname.GSS_BUFFER_T_len;
expName.value = (void*)argsp->expname.GSS_BUFFER_T_val;
res->major = gsscred_expname_to_unix_cred(&expName, &uid,
&gidOut, &gids, &gidsLen);
if (res->major == GSS_S_COMPLETE) {
res->uid = uid;
res->gid = gidOut;
res->gids.GSSCRED_GIDS_val = gids;
res->gids.GSSCRED_GIDS_len = gidsLen;
}
return (TRUE);
} /* gsscred_expname_to_unix_cred_1_svc */
bool_t
gss_get_group_info_1_svc(argsp, res, rqstp)
gss_get_group_info_arg *argsp;
gss_get_group_info_res *res;
struct svc_req *rqstp;
{
uid_t uid;
int gidsLen;
gid_t *gids, gidOut;
if (gssd_debug)
fprintf(stderr, gettext("gss_get_group_info\n"));
memset(res, 0, sizeof (*res));
/*
* check the request originator
*/
if (checkfrom(rqstp, &uid) == 0)
return (FALSE);
/* set the uid from the rpc request */
uid = argsp->uid;
set_gssd_uid(uid);
/*
* extract the uid from the arguments
*/
uid = argsp->puid;
res->major = gss_get_group_info(uid, &gidOut, &gids, &gidsLen);
if (res->major == GSS_S_COMPLETE) {
res->gid = gidOut;
res->gids.GSSCRED_GIDS_val = gids;
res->gids.GSSCRED_GIDS_len = gidsLen;
}
return (TRUE);
} /* gss_get_group_info_1_svc */
/*ARGSUSED*/
bool_t
gss_get_kmod_1_svc(argsp, res, rqstp)
gss_get_kmod_arg *argsp;
gss_get_kmod_res *res;
struct svc_req *rqstp;
{
gss_OID_desc oid;
char *kmodName;
if (gssd_debug)
fprintf(stderr, gettext("gss_get_kmod\n"));
res->module_follow = FALSE;
oid.length = argsp->mech_oid.GSS_OID_len;
oid.elements = (void *)argsp->mech_oid.GSS_OID_val;
kmodName = __gss_get_kmodName(&oid);
if (kmodName != NULL) {
res->module_follow = TRUE;
res->gss_get_kmod_res_u.modname = kmodName;
}
return (TRUE);
}
/*
* Returns 1 if caller is ok, else 0.
* If caller ok, the uid is returned in uidp.
*/
static int
checkfrom(rqstp, uidp)
struct svc_req *rqstp;
uid_t *uidp;
{
SVCXPRT *xprt = rqstp->rq_xprt;
struct authunix_parms *aup;
uid_t uid;
/* check client agent uid to ensure it is privileged */
if (__rpc_get_local_uid(xprt, &uid) < 0) {
syslog(LOG_ERR, gettext("__rpc_get_local_uid failed %s %s"),
xprt->xp_netid, xprt->xp_tp);
goto weakauth;
}
if (gssd_debug)
fprintf(stderr, gettext("checkfrom: local_uid %d\n"), uid);
if (uid != 0) {
syslog(LOG_ERR,
gettext("checkfrom: caller (uid %d) not privileged"),
uid);
goto weakauth;
}
/*
* Request came from local privileged process.
* Proceed to get uid of client if needed by caller.
*/
if (uidp) {
if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
syslog(LOG_ERR, gettext("checkfrom: not UNIX credentials"));
goto weakauth;
}
CTASSERT(sizeof (struct authunix_parms) <= RQCRED_SIZE);
/*LINTED*/
aup = (struct authunix_parms *)rqstp->rq_clntcred;
*uidp = aup->aup_uid;
if (gssd_debug) {
fprintf(stderr,
gettext("checkfrom: caller's uid %d\n"), *uidp);
}
}
return (1);
weakauth:
svcerr_weakauth(xprt);
return (0);
}
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 (c) 1995,1997, by Sun Microsystems, Inc.
* All rights reserved.
*/
/*
* glue routine for gssd_release_name_and_type -- this is a hack,
* it is only used by the client-side rpc library. Perhaps it should
* be in there? Perhaps this should be a part of the release_name
* function? Or perhaps it should always allocate it? I don't know
* the right answer.
*/
#include
#include
#include
/*ARGSUSED*/
OM_uint32
gssd_release_name_and_type(minor_status, input_name)
OM_uint32 * minor_status;
gss_name_t * input_name;
{
gss_union_name_t union_name;
if (input_name == NULL)
return (GSS_S_COMPLETE);
/*
* free up the space for the external_name and also the name
* type data. Then free the union_name descriptor.
*/
union_name = (gss_union_name_t) *input_name;
*input_name = NULL;
if (union_name == NULL)
return (GSS_S_COMPLETE);
FREE(union_name->external_name->value,
union_name->external_name->length);
FREE(union_name->external_name, sizeof (gss_buffer_desc));
FREE(union_name->name_type->elements, union_name->name_type->length);
FREE(union_name->name_type, sizeof (gss_OID_desc));
FREE(union_name, sizeof (gss_union_name_desc));
return (GSS_S_COMPLETE);
}
OM_uint32
gss_release_oid_set_and_oids(minor_status, set)
OM_uint32 * minor_status;
gss_OID_set * set;
{
int i;
if (minor_status)
*minor_status = 0;
if (set == NULL)
return (GSS_S_COMPLETE);
if (*set == GSS_C_NULL_OID_SET)
return (GSS_S_COMPLETE);
for (i = 0; i < (*set)->count; i++)
FREE((*set)->elements[i].elements, (*set)->elements[i].length);
FREE((*set)->elements, (*set)->count * sizeof (gss_OID_desc));
FREE(*set, sizeof (gss_OID_set_desc));
*set = GSS_C_NULL_OID_SET;
return (GSS_S_COMPLETE);
}
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include "gssd.h"
#include
#include /* getenv, exit */
#include
#include
#include
#include
#include /* rlimit */
#include
#ifdef DEBUG
#define RPC_SVC_FG
#endif
#define _RPCSVC_CLOSEDOWN 120
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* RPC protocol information for gssd, the usermode daemon that
* assists the kernel with gssapi. It is gssd that executes all
* gssapi calls except for some such as gss_sign(), and
* gss_verify(), which are executed in the kernel itself.
*
* File generated from gssd.x
*/
#define NO 0
#define YES 1
#define FOREVER 1
#include
#include
#include
#ifndef _KERNEL
#include
#endif /* not _KERNEL */
#ifdef _KERNEL
extern void killgssd_handle(CLIENT *);
extern CLIENT *getgssd_handle(void);
#endif /* _KERNEL */
/* gss_indicate_mechs_arg is void. This appears in the rpc call def */
extern int _rpcpmstart; /* Started by a port monitor ? */
/* States a server can be in wrt request */
#define _IDLE 0
#define _SERVED 1
/* LINTED static unused if no main */
static int _rpcsvcstate = _IDLE; /* Set when a request is serviced */
static int _rpcsvccount = 0; /* Number of requests being serviced */
extern mutex_t _svcstate_lock; /* lock for _rpcsvcstate, _rpcsvccount */
#if defined(RPC_MSGOUT)
extern void RPC_MSGOUT();
#else /* defined(RPC_MSGOUT) */
static void
RPC_MSGOUT(fmt, msg)
char *fmt;
char *msg;
{
#ifdef RPC_SVC_FG
if (_rpcpmstart)
syslog(LOG_ERR, fmt, msg);
else {
(void) fprintf(stderr, fmt, msg);
(void) putc('\n', stderr);
}
#else
syslog(LOG_ERR, fmt, msg);
#endif
}
#endif /* defined(RPC_MSGOUT) */
void
gssprog_1(rqstp, transp)
struct svc_req *rqstp;
register SVCXPRT *transp;
{
union {
gss_acquire_cred_arg gss_acquire_cred_1_arg;
gss_release_cred_arg gss_release_cred_1_arg;
gss_init_sec_context_arg gss_init_sec_context_1_arg;
gss_accept_sec_context_arg gss_accept_sec_context_1_arg;
gss_process_context_token_arg gss_process_context_token_1_arg;
gss_delete_sec_context_arg gss_delete_sec_context_1_arg;
gss_context_time_arg gss_context_time_1_arg;
gss_sign_arg gss_sign_1_arg;
gss_verify_arg gss_verify_1_arg;
gss_display_status_arg gss_display_status_1_arg;
gss_inquire_cred_arg gss_inquire_cred_1_arg;
gss_seal_arg gss_seal_1_arg;
gss_unseal_arg gss_unseal_1_arg;
gsscred_expname_to_unix_cred_arg gsscred_expname_to_unix_cred_1_arg;
gsscred_name_to_unix_cred_arg gsscred_name_to_unix_cred_1_arg;
gss_get_group_info_arg gss_get_group_info_1_arg;
gss_get_kmod_arg gss_get_kmod_1_arg;
gss_export_sec_context_arg gss_export_sec_context_1_arg;
gss_import_sec_context_arg gss_import_sec_context_1_arg;
gss_add_cred_arg gss_add_cred_1_arg;
gss_inquire_cred_by_mech_arg gss_inquire_cred_by_mech_1_arg;
} argument;
union {
gss_acquire_cred_res gss_acquire_cred_1_res;
gss_release_cred_res gss_release_cred_1_res;
gss_init_sec_context_res gss_init_sec_context_1_res;
gss_accept_sec_context_res gss_accept_sec_context_1_res;
gss_process_context_token_res gss_process_context_token_1_res;
gss_delete_sec_context_res gss_delete_sec_context_1_res;
gss_context_time_res gss_context_time_1_res;
gss_sign_res gss_sign_1_res;
gss_verify_res gss_verify_1_res;
gss_display_status_res gss_display_status_1_res;
gss_indicate_mechs_res gss_indicate_mechs_1_res;
gss_inquire_cred_res gss_inquire_cred_1_res;
gss_seal_res gss_seal_1_res;
gss_unseal_res gss_unseal_1_res;
gsscred_expname_to_unix_cred_res gsscred_expname_to_unix_cred_1_res;
gsscred_name_to_unix_cred_res gsscred_name_to_unix_cred_1_res;
gss_get_group_info_res gss_get_group_info_1_res;
gss_get_kmod_res gss_get_kmod_1_res;
gss_export_sec_context_res gss_export_sec_context_1_res;
gss_import_sec_context_res gss_import_sec_context_1_res;
gss_add_cred_res gss_add_cred_1_res;
gss_inquire_cred_by_mech_res gss_inquire_cred_by_mech_1_res;
} result;
bool_t retval;
bool_t (*_xdr_argument)(), (*_xdr_result)();
bool_t (*local)();
(void) mutex_lock(&_svcstate_lock);
_rpcsvccount++;
(void) mutex_unlock(&_svcstate_lock);
switch (rqstp->rq_proc) {
case NULLPROC:
(void) svc_sendreply(transp, xdr_void,
NULL);
(void) mutex_lock(&_svcstate_lock);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
(void) mutex_unlock(&_svcstate_lock);
return; /* CSTYLED */
case GSS_ACQUIRE_CRED:
_xdr_argument = xdr_gss_acquire_cred_arg;
_xdr_result = xdr_gss_acquire_cred_res;
local = (bool_t (*)())
gss_acquire_cred_1_svc;
break;
case GSS_RELEASE_CRED:
_xdr_argument = xdr_gss_release_cred_arg;
_xdr_result = xdr_gss_release_cred_res;
local = (bool_t (*)())
gss_release_cred_1_svc;
break;
case GSS_INIT_SEC_CONTEXT:
_xdr_argument = xdr_gss_init_sec_context_arg;
_xdr_result = xdr_gss_init_sec_context_res;
local = (bool_t (*)())
gss_init_sec_context_1_svc;
break;
case GSS_ACCEPT_SEC_CONTEXT:
_xdr_argument = xdr_gss_accept_sec_context_arg;
_xdr_result = xdr_gss_accept_sec_context_res;
local = (bool_t (*)())
gss_accept_sec_context_1_svc;
break;
case GSS_PROCESS_CONTEXT_TOKEN:
_xdr_argument = xdr_gss_process_context_token_arg;
_xdr_result = xdr_gss_process_context_token_res;
local = (bool_t (*)())
gss_process_context_token_1_svc;
break;
case GSS_DELETE_SEC_CONTEXT:
_xdr_argument = xdr_gss_delete_sec_context_arg;
_xdr_result = xdr_gss_delete_sec_context_res;
local = (bool_t (*)())
gss_delete_sec_context_1_svc;
break;
case GSS_CONTEXT_TIME:
_xdr_argument = xdr_gss_context_time_arg;
_xdr_result = xdr_gss_context_time_res;
local = (bool_t (*)())
gss_context_time_1_svc;
break;
case GSS_SIGN:
_xdr_argument = xdr_gss_sign_arg;
_xdr_result = xdr_gss_sign_res;
local = (bool_t (*)())
gss_sign_1_svc;
break;
case GSS_VERIFY:
_xdr_argument = xdr_gss_verify_arg;
_xdr_result = xdr_gss_verify_res;
local = (bool_t (*)())
gss_verify_1_svc;
break;
case GSS_DISPLAY_STATUS:
_xdr_argument = xdr_gss_display_status_arg;
_xdr_result = xdr_gss_display_status_res;
local = (bool_t (*)())
gss_display_status_1_svc;
break;
case GSS_INDICATE_MECHS:
_xdr_argument = xdr_void;
_xdr_result = xdr_gss_indicate_mechs_res;
local = (bool_t (*)())
gss_indicate_mechs_1_svc;
break;
case GSS_INQUIRE_CRED:
_xdr_argument = xdr_gss_inquire_cred_arg;
_xdr_result = xdr_gss_inquire_cred_res;
local = (bool_t (*)())
gss_inquire_cred_1_svc;
break;
case GSS_SEAL:
_xdr_argument = xdr_gss_seal_arg;
_xdr_result = xdr_gss_seal_res;
local = (bool_t (*)())
gss_seal_1_svc;
break;
case GSS_UNSEAL:
_xdr_argument = xdr_gss_unseal_arg;
_xdr_result = xdr_gss_unseal_res;
local = (bool_t (*)())
gss_unseal_1_svc;
break;
case GSSCRED_EXPNAME_TO_UNIX_CRED:
_xdr_argument = xdr_gsscred_expname_to_unix_cred_arg;
_xdr_result = xdr_gsscred_expname_to_unix_cred_res;
local = (bool_t (*)())
gsscred_expname_to_unix_cred_1_svc;
break;
case GSSCRED_NAME_TO_UNIX_CRED:
_xdr_argument = xdr_gsscred_name_to_unix_cred_arg;
_xdr_result = xdr_gsscred_name_to_unix_cred_res;
local = (bool_t (*)())
gsscred_name_to_unix_cred_1_svc;
break;
case GSS_GET_GROUP_INFO:
_xdr_argument = xdr_gss_get_group_info_arg;
_xdr_result = xdr_gss_get_group_info_res;
local = (bool_t (*)())
gss_get_group_info_1_svc;
break;
case GSS_GET_KMOD:
_xdr_argument = xdr_gss_get_kmod_arg;
_xdr_result = xdr_gss_get_kmod_res;
local = (bool_t (*)())
gss_get_kmod_1_svc;
break;
case GSS_EXPORT_SEC_CONTEXT:
_xdr_argument = xdr_gss_export_sec_context_arg;
_xdr_result = xdr_gss_export_sec_context_res;
local = (bool_t (*)())
gss_export_sec_context_1_svc;
break;
case GSS_IMPORT_SEC_CONTEXT:
_xdr_argument = xdr_gss_import_sec_context_arg;
_xdr_result = xdr_gss_import_sec_context_res;
local = (bool_t (*)())
gss_import_sec_context_1_svc;
break;
case GSS_ADD_CRED:
_xdr_argument = xdr_gss_add_cred_arg;
_xdr_result = xdr_gss_add_cred_res;
local = (bool_t (*)())
gss_add_cred_1_svc;
break;
case GSS_INQUIRE_CRED_BY_MECH:
_xdr_argument = xdr_gss_inquire_cred_by_mech_arg;
_xdr_result = xdr_gss_inquire_cred_by_mech_res;
local = (bool_t (*)())
gss_inquire_cred_by_mech_1_svc;
break;
default:
svcerr_noproc(transp);
(void) mutex_lock(&_svcstate_lock);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
(void) mutex_unlock(&_svcstate_lock);
return; /* CSTYLED */
}
(void) memset((char *)&argument, 0, sizeof (argument));
if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) {
svcerr_decode(transp);
(void) mutex_lock(&_svcstate_lock);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
(void) mutex_unlock(&_svcstate_lock);
return; /* CSTYLED */
}
retval = (bool_t)(*local)(&argument, &result, rqstp);
if (_xdr_result && retval > 0 &&
!svc_sendreply(transp, _xdr_result, (char *)&result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) {
RPC_MSGOUT("%s",
"unable to free arguments");
exit(1);
}
if (_xdr_result != NULL) {
if (!gssprog_1_freeresult(transp, _xdr_result,
(caddr_t)&result))
RPC_MSGOUT("%s",
"unable to free results");
}
(void) mutex_lock(&_svcstate_lock);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
(void) mutex_unlock(&_svcstate_lock);
return; /* CSTYLED */
}
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include "gssd.h"
#ifndef _KERNEL
#include
#endif /* !_KERNEL */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* RPC protocol information for gssd, the usermode daemon that
* assists the kernel with gssapi. It is gssd that executes all
* gssapi calls except for some such as gss_sign(), and
* gss_verify(), which are executed in the kernel itself.
*
* File generated from gssd.x
*/
#define NO 0
#define YES 1
#define FOREVER 1
#include
#include
#include
#ifndef _KERNEL
#include
#endif /* not _KERNEL */
#ifdef _KERNEL
extern void killgssd_handle(CLIENT *);
extern CLIENT *getgssd_handle(void);
#endif /* _KERNEL */
bool_t
xdr_OM_UINT32(xdrs, objp)
XDR *xdrs;
OM_UINT32 *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_u_int(xdrs, objp))
return (FALSE);
return (TRUE);
}
bool_t
xdr_GSS_CTX_ID_T(xdrs, objp)
XDR *xdrs;
GSS_CTX_ID_T *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_bytes(xdrs, (char **)&objp->GSS_CTX_ID_T_val, (u_int *) &objp->GSS_CTX_ID_T_len, ~0))
return (FALSE);
return (TRUE);
}
bool_t
xdr_GSS_CRED_ID_T(xdrs, objp)
XDR *xdrs;
GSS_CRED_ID_T *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_bytes(xdrs, (char **)&objp->GSS_CRED_ID_T_val, (u_int *) &objp->GSS_CRED_ID_T_len, ~0))
return (FALSE);
return (TRUE);
}
bool_t
xdr_GSS_OID(xdrs, objp)
XDR *xdrs;
GSS_OID *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_bytes(xdrs, (char **)&objp->GSS_OID_val, (u_int *) &objp->GSS_OID_len, ~0))
return (FALSE);
return (TRUE);
}
bool_t
xdr_GSS_BUFFER_T(xdrs, objp)
XDR *xdrs;
GSS_BUFFER_T *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_bytes(xdrs, (char **)&objp->GSS_BUFFER_T_val, (u_int *) &objp->GSS_BUFFER_T_len, ~0))
return (FALSE);
return (TRUE);
}
bool_t
xdr_GSSCRED_GIDS(xdrs, objp)
XDR *xdrs;
GSSCRED_GIDS *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_array(xdrs, (char **)&objp->GSSCRED_GIDS_val, (u_int *) &objp->GSSCRED_GIDS_len, ~0,
sizeof (gid_t), (xdrproc_t)xdr_gid_t))
return (FALSE);
return (TRUE);
}
bool_t
xdr_GSS_OID_SET(xdrs, objp)
XDR *xdrs;
GSS_OID_SET *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_array(xdrs, (char **)&objp->GSS_OID_SET_val, (u_int *) &objp->GSS_OID_SET_len, ~0,
sizeof (GSS_OID), (xdrproc_t)xdr_GSS_OID))
return (FALSE);
return (TRUE);
}
bool_t
xdr_GSS_CHANNEL_BINDINGS_STRUCT(xdrs, objp)
XDR *xdrs;
GSS_CHANNEL_BINDINGS_STRUCT *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_int(xdrs, &objp->present))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->initiator_addrtype))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->initiator_address))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->acceptor_addrtype))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->acceptor_address))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->application_data))
return (FALSE);
return (TRUE);
}
bool_t
xdr_GSS_CHANNEL_BINDINGS(xdrs, objp)
XDR *xdrs;
GSS_CHANNEL_BINDINGS *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_GSS_CHANNEL_BINDINGS_STRUCT(xdrs, objp))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_acquire_cred_arg(xdrs, objp)
XDR *xdrs;
gss_acquire_cred_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->desired_name))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->name_type))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->time_req))
return (FALSE);
if (!xdr_GSS_OID_SET(xdrs, &objp->desired_mechs))
return (FALSE);
if (!xdr_int(xdrs, &objp->cred_usage))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_acquire_cred_res(xdrs, objp)
XDR *xdrs;
gss_acquire_cred_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_CRED_ID_T(xdrs, &objp->output_cred_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier))
return (FALSE);
if (!xdr_GSS_OID_SET(xdrs, &objp->actual_mechs))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->time_rec))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_add_cred_arg(xdrs, objp)
XDR *xdrs;
gss_add_cred_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_GSS_CRED_ID_T(xdrs, &objp->input_cred_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->desired_name))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->name_type))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->desired_mech_type))
return (FALSE);
if (!xdr_int(xdrs, &objp->cred_usage))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->initiator_time_req))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->acceptor_time_req))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_add_cred_res(xdrs, objp)
XDR *xdrs;
gss_add_cred_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_OID_SET(xdrs, &objp->actual_mechs))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->initiator_time_rec))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->acceptor_time_rec))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_release_cred_arg(xdrs, objp)
XDR *xdrs;
gss_release_cred_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier))
return (FALSE);
if (!xdr_GSS_CRED_ID_T(xdrs, &objp->cred_handle))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_release_cred_res(xdrs, objp)
XDR *xdrs;
gss_release_cred_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_init_sec_context_arg(xdrs, objp)
XDR *xdrs;
gss_init_sec_context_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CRED_ID_T(xdrs, &objp->claimant_cred_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->target_name))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->name_type))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->mech_type))
return (FALSE);
if (!xdr_int(xdrs, &objp->req_flags))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->time_req))
return (FALSE);
if (!xdr_GSS_CHANNEL_BINDINGS(xdrs, &objp->input_chan_bindings))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_token))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_init_sec_context_res(xdrs, objp)
XDR *xdrs;
gss_init_sec_context_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->actual_mech_type))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_token))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->ret_flags))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->time_rec))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_accept_sec_context_arg(xdrs, objp)
XDR *xdrs;
gss_accept_sec_context_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CRED_ID_T(xdrs, &objp->verifier_cred_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_token_buffer))
return (FALSE);
if (!xdr_GSS_CHANNEL_BINDINGS(xdrs, &objp->input_chan_bindings))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_accept_sec_context_res(xdrs, objp)
XDR *xdrs;
gss_accept_sec_context_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->src_name))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->mech_type))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_token))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->ret_flags))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->time_rec))
return (FALSE);
if (!xdr_GSS_CRED_ID_T(xdrs, &objp->delegated_cred_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_process_context_token_arg(xdrs, objp)
XDR *xdrs;
gss_process_context_token_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->token_buffer))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_process_context_token_res(xdrs, objp)
XDR *xdrs;
gss_process_context_token_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_delete_sec_context_arg(xdrs, objp)
XDR *xdrs;
gss_delete_sec_context_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_delete_sec_context_res(xdrs, objp)
XDR *xdrs;
gss_delete_sec_context_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_token))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_export_sec_context_arg(xdrs, objp)
XDR *xdrs;
gss_export_sec_context_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_export_sec_context_res(xdrs, objp)
XDR *xdrs;
gss_export_sec_context_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_token))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_import_sec_context_arg(xdrs, objp)
XDR *xdrs;
gss_import_sec_context_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_token))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_import_sec_context_res(xdrs, objp)
XDR *xdrs;
gss_import_sec_context_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_context_time_arg(xdrs, objp)
XDR *xdrs;
gss_context_time_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_context_time_res(xdrs, objp)
XDR *xdrs;
gss_context_time_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->time_rec))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_sign_arg(xdrs, objp)
XDR *xdrs;
gss_sign_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_int(xdrs, &objp->qop_req))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->message_buffer))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_sign_res(xdrs, objp)
XDR *xdrs;
gss_sign_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->msg_token))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_verify_arg(xdrs, objp)
XDR *xdrs;
gss_verify_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->message_buffer))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->token_buffer))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_verify_res(xdrs, objp)
XDR *xdrs;
gss_verify_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_int(xdrs, &objp->qop_state))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_seal_arg(xdrs, objp)
XDR *xdrs;
gss_seal_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_int(xdrs, &objp->conf_req_flag))
return (FALSE);
if (!xdr_int(xdrs, &objp->qop_req))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_message_buffer))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_seal_res(xdrs, objp)
XDR *xdrs;
gss_seal_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_int(xdrs, &objp->conf_state))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_message_buffer))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_unseal_arg(xdrs, objp)
XDR *xdrs;
gss_unseal_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier))
return (FALSE);
if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_message_buffer))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_unseal_res(xdrs, objp)
XDR *xdrs;
gss_unseal_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_message_buffer))
return (FALSE);
if (!xdr_int(xdrs, &objp->conf_state))
return (FALSE);
if (!xdr_int(xdrs, &objp->qop_state))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_display_status_arg(xdrs, objp)
XDR *xdrs;
gss_display_status_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_int(xdrs, &objp->status_value))
return (FALSE);
if (!xdr_int(xdrs, &objp->status_type))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->mech_type))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->message_context))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_display_status_res(xdrs, objp)
XDR *xdrs;
gss_display_status_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_int(xdrs, &objp->message_context))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->status_string))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
/* gss_indicate_mechs_arg is void. This appears in the rpc call def */
bool_t
xdr_gss_indicate_mechs_res(xdrs, objp)
XDR *xdrs;
gss_indicate_mechs_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_OID_SET(xdrs, &objp->mech_set))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_inquire_cred_arg(xdrs, objp)
XDR *xdrs;
gss_inquire_cred_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier))
return (FALSE);
if (!xdr_GSS_CRED_ID_T(xdrs, &objp->cred_handle))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_inquire_cred_res(xdrs, objp)
XDR *xdrs;
gss_inquire_cred_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->name))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->name_type))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->lifetime))
return (FALSE);
if (!xdr_int(xdrs, &objp->cred_usage))
return (FALSE);
if (!xdr_GSS_OID_SET(xdrs, &objp->mechanisms))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_inquire_cred_by_mech_arg(xdrs, objp)
XDR *xdrs;
gss_inquire_cred_by_mech_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier))
return (FALSE);
if (!xdr_GSS_CRED_ID_T(xdrs, &objp->cred_handle))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->mech_type))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_inquire_cred_by_mech_res(xdrs, objp)
XDR *xdrs;
gss_inquire_cred_by_mech_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_OM_UINT32(xdrs, &objp->minor_status))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->status))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gsscred_name_to_unix_cred_arg(xdrs, objp)
XDR *xdrs;
gsscred_name_to_unix_cred_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->pname))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->name_type))
return (FALSE);
if (!xdr_GSS_OID(xdrs, &objp->mech_type))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gsscred_name_to_unix_cred_res(xdrs, objp)
XDR *xdrs;
gsscred_name_to_unix_cred_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_gid_t(xdrs, &objp->gid))
return (FALSE);
if (!xdr_GSSCRED_GIDS(xdrs, &objp->gids))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->major))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gsscred_expname_to_unix_cred_arg(xdrs, objp)
XDR *xdrs;
gsscred_expname_to_unix_cred_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_GSS_BUFFER_T(xdrs, &objp->expname))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gsscred_expname_to_unix_cred_res(xdrs, objp)
XDR *xdrs;
gsscred_expname_to_unix_cred_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_gid_t(xdrs, &objp->gid))
return (FALSE);
if (!xdr_GSSCRED_GIDS(xdrs, &objp->gids))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->major))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_get_group_info_arg(xdrs, objp)
XDR *xdrs;
gss_get_group_info_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_uid_t(xdrs, &objp->uid))
return (FALSE);
if (!xdr_uid_t(xdrs, &objp->puid))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_get_group_info_res(xdrs, objp)
XDR *xdrs;
gss_get_group_info_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_gid_t(xdrs, &objp->gid))
return (FALSE);
if (!xdr_GSSCRED_GIDS(xdrs, &objp->gids))
return (FALSE);
if (!xdr_OM_UINT32(xdrs, &objp->major))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_get_kmod_arg(xdrs, objp)
XDR *xdrs;
gss_get_kmod_arg *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_GSS_OID(xdrs, &objp->mech_oid))
return (FALSE);
return (TRUE);
}
bool_t
xdr_gss_get_kmod_res(xdrs, objp)
XDR *xdrs;
gss_get_kmod_res *objp;
{
rpc_inline_t *buf __unused;
if (!xdr_bool(xdrs, &objp->module_follow))
return (FALSE);
switch (objp->module_follow) {
case TRUE:
if (!xdr_string(xdrs, &objp->gss_get_kmod_res_u.modname, ~0))
return (FALSE);
break;
case FALSE:
break;
default:
return (FALSE);
}
return (TRUE);
}
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 2017 Gary Mills
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Test client for gssd. This program is not shipped on the binary
* release.
*/
#include
#include
#include
#include
#include
#include
#include "gssd.h"
#include
#define _KERNEL
#include
#undef _KERNEL
int gss_major_code;
int gss_minor_code;
int init_sec_context_phase = 0;
int accept_sec_context_phase = 0;
gss_ctx_id_t initiator_context_handle;
gss_ctx_id_t acceptor_context_handle;
gss_cred_id_t acceptor_credentials;
gss_buffer_desc init_token_buffer;
gss_buffer_desc accept_token_buffer;
gss_buffer_desc delete_token_buffer;
gss_buffer_desc message_buffer;
gss_buffer_desc msg_token;
#define LOOP_COUNTER 100
#define GSS_KRB5_MECH_OID "1.2.840.113554.1.2.2"
#define GSS_DUMMY_MECH_OID "1.3.6.1.4.1.42.2.26.1.2"
#ifdef _KERNEL
#define OCTAL_MACRO "%03o."
#define MALLOC(n) kmem_alloc((n), KM_SLEEP)
#define CALLOC(n, s) kmem_zalloc((n)*(s), KM_SLEEP)
#define FREE(x, n) kmem_free((x), (n))
#define memcpy(dst, src, n) bcopy((src), (dst), (n))
#define fprintf(s, m) printf(m)
#define isspace(s) ((s) == ' ' || (s) == '\t' || (s) == '\n' || \
(s) == '\r' || (s) == '\v' || (s) == '\f')
static char *strdup(const char *s)
{
int len = strlen(s);
char *new = MALLOC(len+1);
strcpy(new, s);
return (new);
}
#else /* !_KERNEL */
#define OCTAL_MACRO "%03.3o."
#define MALLOC(n) malloc(n)
#define CALLOC(n, s) calloc((n), (s))
#define FREE(x, n) free(x)
#endif /* _KERNEL */
static gss_OID gss_str2oid(char *);
static char * gss_oid2str(gss_OID);
static void instructs();
static void usage();
static int parse_input_line(char *, int *, char ***);
extern uid_t getuid();
static void _gss_init_sec_context(int, char **);
static void _gss_acquire_cred(int, char **);
static void _gss_add_cred(int, char **);
static void _gss_sign(int, char **);
static void _gss_release_cred(int, char **);
static void _gss_accept_sec_context(int, char **);
static void _gss_process_context_token(int, char **);
static void _gss_delete_sec_context(int, char **);
static void _gss_context_time(int, char **);
static void _gss_verify(int, char **);
static void _gss_seal(int, char **);
static void _gss_unseal(int, char **);
static void _gss_display_status(int, char **);
static void _gss_indicate_mechs(int, char **);
static void _gss_inquire_cred(int, char **);
static void _gssd_expname_to_unix_cred(int, char **);
static void _gssd_name_to_unix_cred(int, char **);
static void _gssd_get_group_info(int, char **);
static int do_gssdtest(char *buf);
#ifndef _KERNEL
static int read_line(char *buf, int size)
{
int len;
/* read the next line. If cntl-d, return with zero char count */
printf(gettext("\n> "));
if (fgets(buf, size, stdin) == NULL)
return (0);
len = strlen(buf);
buf[--len] = '\0';
return (len);
}
int
main()
{
char buf[512];
int len, ret;
/* Print out usage and instructions to start off the session */
instructs();
usage();
/*
* Loop, repeatedly calling parse_input_line() to get the
* next line and parse it into argc and argv. Act on the
* arguements found on the line.
*/
do {
len = read_line(buf, 512);
if (len)
ret = do_gssdtest(buf);
} while (len && !ret);
return (0);
}
#endif /* !_KERNEL */
static int
do_gssdtest(char *buf)
{
int argc, seal_argc;
int i;
char **argv, **argv_array;
char *cmd;
char *seal_ini_array [] = { "initiator", " Hello"};
char *seal_acc_array [] = { "acceptor", " Hello"};
char *unseal_acc_array [] = {"acceptor"};
char *unseal_ini_array [] = {"initiator"};
char *delet_acc_array [] = {"acceptor"};
char *delet_ini_array [] = {"initiator"};
argv = 0;
if (parse_input_line(buf, &argc, &argv) == 0) {
printf(gettext("\n"));
return (1);
}
if (argc == 0) {
usage();
/*LINTED*/
FREE(argv_array, (argc+1)*sizeof (char *));
return (0);
}
/*
* remember argv_array address, which is memory calloc'd by
* parse_input_line, so it can be free'd at the end of the loop.
*/
argv_array = argv;
cmd = argv[0];
argc--;
argv++;
if (strcmp(cmd, "gss_loop") == 0 ||
strcmp(cmd, "loop") == 0) {
if (argc < 1) {
usage();
FREE(argv_array, (argc+2) * sizeof (char *));
return (0);
}
for (i = 0; i < LOOP_COUNTER; i++) {
printf(gettext("Loop Count is %d \n"), i);
/*
* if (i > 53)
* printf ("Loop counter is greater than 55\n");
*/
_gss_acquire_cred(argc, argv);
_gss_init_sec_context(argc, argv);
_gss_accept_sec_context(0, argv);
_gss_init_sec_context(argc, argv);
seal_argc = 2;
_gss_seal(seal_argc, seal_ini_array);
seal_argc = 1;
_gss_unseal(seal_argc, unseal_acc_array);
seal_argc = 2;
_gss_seal(seal_argc, seal_acc_array);
seal_argc = 1;
_gss_unseal(seal_argc, unseal_ini_array);
seal_argc = 2;
_gss_sign(seal_argc, seal_ini_array);
seal_argc = 1;
_gss_verify(seal_argc, unseal_acc_array);
seal_argc = 2;
_gss_sign(seal_argc, seal_acc_array);
seal_argc = 1;
_gss_verify(seal_argc, unseal_ini_array);
_gss_delete_sec_context(argc, delet_acc_array);
_gss_delete_sec_context(argc, delet_ini_array);
}
}
if (strcmp(cmd, "gss_all") == 0 ||
strcmp(cmd, "all") == 0) {
_gss_acquire_cred(argc, argv);
_gss_init_sec_context(argc, argv);
_gss_accept_sec_context(0, argv);
_gss_init_sec_context(argc, argv);
seal_argc = 2;
_gss_seal(seal_argc, seal_acc_array);
seal_argc = 1;
_gss_unseal(seal_argc, unseal_ini_array);
seal_argc = 2;
_gss_seal(seal_argc, seal_ini_array);
seal_argc = 1;
_gss_unseal(seal_argc, unseal_acc_array);
seal_argc = 2;
_gss_sign(seal_argc, seal_ini_array);
seal_argc = 1;
_gss_verify(seal_argc, unseal_acc_array);
seal_argc = 2;
_gss_sign(seal_argc, seal_acc_array);
seal_argc = 1;
_gss_verify(seal_argc, unseal_ini_array);
}
if (strcmp(cmd, "gss_acquire_cred") == 0 ||
strcmp(cmd, "acquire") == 0) {
_gss_acquire_cred(argc, argv);
if (argc == 1)
_gss_add_cred(argc, argv);
}
else if (strcmp(cmd, "gss_release_cred") == 0 ||
strcmp(cmd, "release") == 0)
_gss_release_cred(argc, argv);
else if (strcmp(cmd, "gss_init_sec_context") == 0 ||
strcmp(cmd, "init") == 0)
_gss_init_sec_context(argc, argv);
else if (strcmp(cmd, "gss_accept_sec_context") == 0 ||
strcmp(cmd, "accept") == 0)
_gss_accept_sec_context(argc, argv);
else if (strcmp(cmd, "gss_process_context_token") == 0 ||
strcmp(cmd, "process") == 0)
_gss_process_context_token(argc, argv);
else if (strcmp(cmd, "gss_delete_sec_context") == 0 ||
strcmp(cmd, "delete") == 0)
_gss_delete_sec_context(argc, argv);
else if (strcmp(cmd, "gss_context_time") == 0 ||
strcmp(cmd, "time") == 0)
_gss_context_time(argc, argv);
else if (strcmp(cmd, "gss_sign") == 0 ||
strcmp(cmd, "sign") == 0)
_gss_sign(argc, argv);
else if (strcmp(cmd, "gss_verify") == 0 ||
strcmp(cmd, "verify") == 0)
_gss_verify(argc, argv);
else if (strcmp(cmd, "gss_seal") == 0 ||
strcmp(cmd, "seal") == 0)
_gss_seal(argc, argv);
else if (strcmp(cmd, "gss_unseal") == 0 ||
strcmp(cmd, "unseal") == 0)
_gss_unseal(argc, argv);
else if (strcmp(cmd, "gss_display_status") == 0||
strcmp(cmd, "status") == 0)
_gss_display_status(argc, argv);
else if (strcmp(cmd, "gss_indicate_mechs") == 0 ||
strcmp(cmd, "indicate") == 0)
_gss_indicate_mechs(argc, argv);
else if (strcmp(cmd, "gss_inquire_cred") == 0 ||
strcmp(cmd, "inquire") == 0)
_gss_inquire_cred(argc, argv);
else if (strcmp(cmd, "expname2unixcred") == 0 ||
strcmp(cmd, "gsscred_expname_to_unix_cred") == 0)
_gssd_expname_to_unix_cred(argc, argv);
else if (strcmp(cmd, "name2unixcred") == 0 ||
strcmp(cmd, "gsscred_name_to_unix_cred") == 0)
_gssd_name_to_unix_cred(argc, argv);
else if (strcmp(cmd, "grpinfo") == 0 ||
strcmp(cmd, "gss_get_group_info") == 0)
_gssd_get_group_info(argc, argv);
else if (strcmp(cmd, "exit") == 0) {
printf(gettext("\n"));
FREE(argv_array, (argc+2) * sizeof (char *));
return (1);
} else
usage();
/* free argv array */
FREE(argv_array, (argc+2) * sizeof (char *));
return (0);
}
static void
_gss_acquire_cred(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status, minor_status;
gss_buffer_desc name;
gss_name_t desired_name = (gss_name_t) 0;
OM_uint32 time_req;
gss_OID_set_desc desired_mechs_desc;
gss_OID_set desired_mechs = &desired_mechs_desc;
int cred_usage;
gss_OID_set actual_mechs = GSS_C_NULL_OID_SET;
gss_OID_set inquire_mechs = GSS_C_NULL_OID_SET;
OM_UINT32 time_rec;
char * string;
char * inq_string;
uid_t uid;
gss_OID mech_type;
/*
* First set up the command line independent input arguments.
*/
time_req = (OM_uint32) 0;
cred_usage = GSS_C_ACCEPT;
uid = getuid();
/* Parse the command line for the variable input arguments */
if (argc == 0) {
usage();
return;
}
/*
* Get the name of the principal.
*/
name.length = strlen(argv[0])+1;
name.value = argv[0];
/*
* Now convert the string given by the first argument into internal
* form suitable for input to gss_acquire_cred()
*/
if ((status = gss_import_name(&minor_status, &name,
(gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &desired_name))
!= GSS_S_COMPLETE) {
printf(gettext(
"could not parse desired name: err (octal) %o (%s)\n"),
status, gettext("gss_acquire_cred error"));
return;
}
argc--;
argv++;
/*
* The next argument is an OID in dotted decimal form.
*/
if (argc == 0) {
printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
printf(gettext(
"The mech OID 1.2.840.113554.1.2.2 will be used\n"));
mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
} else
mech_type = gss_str2oid(argv[0]);
if (mech_type == 0 || mech_type->length == 0) {
printf(gettext("improperly formated mechanism OID\n"));
return;
}
/*
* set up desired_mechs so it points to mech_type.
*/
desired_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_desc));
desired_mechs->count = 1;
desired_mechs->elements = mech_type;
status = kgss_acquire_cred(
&minor_status,
desired_name,
time_req,
desired_mechs,
cred_usage,
&acceptor_credentials,
&actual_mechs,
&time_rec,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status == GSS_S_COMPLETE) {
/* process returned values */
printf(gettext("\nacquire succeeded\n\n"));
/*
* print out the actual mechs returned NB: Since only one
* mechanism is specified in desired_mechs, only one
* can be returned in actual_mechs. Consequently,
* actual_mechs->elements points to an array of only one
* element.
*/
if ((string = gss_oid2str(actual_mechs->elements)) == 0) {
printf(gettext("actual mechs == NULL\n\n"));
} else {
printf(gettext("actual mechs = %s\n\n"), string);
FREE(string, (actual_mechs->elements->length+1)*4+1);
}
if (cred_usage == GSS_C_BOTH)
printf(gettext("GSS_C_BOTH\n\n"));
if (cred_usage == GSS_C_INITIATE)
printf(gettext("GSS_C_INITIATE\n\n"));
if (cred_usage == GSS_C_ACCEPT)
printf(gettext("GSS_C_ACCEPT\n\n"));
status = kgss_inquire_cred(
&minor_status,
acceptor_credentials,
NULL,
&time_req,
&cred_usage,
&inquire_mechs,
uid);
if (status != GSS_S_COMPLETE)
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_inquire_cred error"));
else {
if ((inq_string =
gss_oid2str(inquire_mechs->elements)) == 0) {
printf(gettext
("mechs from inquire == NULL\n\n"));
} else {
printf(gettext
("mechs from inquiry = %s\n\n"),
inq_string);
FREE(inq_string,
(inquire_mechs->elements->length+1)*4+1);
}
printf(gettext("inquire_cred successful \n\n"));
}
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_acquire_cred error"));
}
/* free allocated memory */
/* actual mechs is allocated by clnt_stubs. Release it here */
if (actual_mechs != GSS_C_NULL_OID_SET)
gss_release_oid_set_and_oids(&minor_status, &actual_mechs);
if (inquire_mechs != GSS_C_NULL_OID_SET)
gss_release_oid_set_and_oids(&minor_status, &inquire_mechs);
gss_release_name(&minor_status, &desired_name);
/* mech_type and desired_mechs are allocated above. Release it here */
FREE(mech_type->elements, mech_type->length);
FREE(mech_type, sizeof (gss_OID_desc));
FREE(desired_mechs, sizeof (gss_OID_desc));
}
static void
_gss_add_cred(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status, minor_status;
gss_buffer_desc name;
gss_name_t desired_name = (gss_name_t) 0;
OM_uint32 time_req;
OM_uint32 initiator_time_req;
OM_uint32 acceptor_time_req;
int cred_usage;
gss_OID_set actual_mechs = GSS_C_NULL_OID_SET;
gss_OID_set inquire_mechs = GSS_C_NULL_OID_SET;
char * string;
uid_t uid;
gss_OID mech_type;
int i;
/*
* First set up the command line independent input arguments.
*/
initiator_time_req = (OM_uint32) 0;
acceptor_time_req = (OM_uint32) 0;
cred_usage = GSS_C_ACCEPT;
uid = getuid();
/* Parse the command line for the variable input arguments */
if (argc == 0) {
usage();
return;
}
/*
* Get the name of the principal.
*/
name.length = strlen(argv[0])+1;
name.value = argv[0];
/*
* Now convert the string given by the first argument into internal
* form suitable for input to gss_acquire_cred()
*/
if ((status = gss_import_name(&minor_status, &name,
(gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &desired_name))
!= GSS_S_COMPLETE) {
printf(gettext(
"could not parse desired name: err (octal) %o (%s)\n"),
status, gettext("gss_acquire_cred error"));
return;
}
argc--;
argv++;
/*
* The next argument is an OID in dotted decimal form.
*/
if (argc == 0) {
printf(gettext("Assuming dummy as the mechanism\n"));
printf(gettext(
"The mech OID 1.3.6.1.4.1.42.2.26.1.2 will be used\n"));
mech_type = gss_str2oid((char *)GSS_DUMMY_MECH_OID);
} else
mech_type = gss_str2oid(argv[0]);
if (mech_type == 0 || mech_type->length == 0) {
printf(gettext("improperly formated mechanism OID\n"));
return;
}
/*
* set up desired_mechs so it points to mech_type.
*/
status = kgss_add_cred(
&minor_status,
acceptor_credentials,
desired_name,
mech_type,
cred_usage,
initiator_time_req,
acceptor_time_req,
&actual_mechs,
NULL,
NULL,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status == GSS_S_COMPLETE) {
/* process returned values */
printf(gettext("\nadd succeeded\n\n"));
if (actual_mechs) {
for (i = 0; i < actual_mechs->count; i++) {
if ((string =
gss_oid2str
(&actual_mechs->elements[i])) == 0) {
printf(gettext
("actual mechs == NULL\n\n"));
} else {
printf(gettext
("actual mechs = %s\n\n"), string);
FREE(string,
(actual_mechs->elements->length+1)*4+1);
}
}
}
/*
* Try adding the cred again for the same mech
* We should get GSS_S_DUPLICATE_ELEMENT
* if not return an error
*/
status = kgss_add_cred(
&minor_status,
acceptor_credentials,
desired_name,
mech_type,
cred_usage,
initiator_time_req,
acceptor_time_req,
NULL, /* &actual_mechs, */
NULL,
NULL,
uid);
if (status != GSS_S_DUPLICATE_ELEMENT) {
printf(gettext("Expected duplicate element, Got "
" (octal) %o (%s)\n"),
status, gettext("gss_add_cred error"));
}
status = kgss_inquire_cred(
&minor_status,
acceptor_credentials,
NULL,
&time_req,
&cred_usage,
&inquire_mechs,
uid);
if (status != GSS_S_COMPLETE)
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_inquire_cred error"));
else {
for (i = 0; i < inquire_mechs->count; i++) {
if ((string =
gss_oid2str
(&inquire_mechs->elements[i])) == 0) {
printf(gettext
("inquire_mechs mechs == NULL\n\n"));
} else {
printf(gettext
("inquire_cred mechs = %s\n\n"),
string);
FREE(string,
(inquire_mechs->elements->length+1)*4
+1);
}
}
printf(gettext("inquire_cred successful \n\n"));
}
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_acquire_cred error"));
}
/* Let us do inquire_cred_by_mech for both mechanisms */
status = kgss_inquire_cred_by_mech(
&minor_status,
acceptor_credentials,
mech_type,
uid);
if (status != GSS_S_COMPLETE)
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_inquire_cred_by_mech"));
else
printf(gettext("gss_inquire_cred_by_mech successful"));
FREE(mech_type->elements, mech_type->length);
FREE(mech_type, sizeof (gss_OID_desc));
mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
status = kgss_inquire_cred_by_mech(
&minor_status,
acceptor_credentials,
mech_type,
uid);
if (status != GSS_S_COMPLETE)
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext
("gss_inquire_cred_by_mech for dummy mech error"));
/* free allocated memory */
/* actual mechs is allocated by clnt_stubs. Release it here */
if (actual_mechs != GSS_C_NULL_OID_SET)
gss_release_oid_set_and_oids(&minor_status, &actual_mechs);
if (inquire_mechs != GSS_C_NULL_OID_SET)
gss_release_oid_set_and_oids(&minor_status, &inquire_mechs);
gss_release_name(&minor_status, &desired_name);
/* mech_type and desired_mechs are allocated above. Release it here */
FREE(mech_type->elements, mech_type->length);
FREE(mech_type, sizeof (gss_OID_desc));
}
/*ARGSUSED*/
static void
_gss_release_cred(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
OM_UINT32 minor_status;
uid_t uid;
/* set up input arguments here */
if (argc != 0) {
usage();
return;
}
uid = getuid();
status = kgss_release_cred(
&minor_status,
&acceptor_credentials,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status == GSS_S_COMPLETE) {
printf(gettext("\nrelease succeeded\n\n"));
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_release_cred error"));
}
}
static void
_gss_init_sec_context(argc, argv)
int argc;
char **argv;
{
OM_uint32 status;
OM_uint32 minor_status;
gss_cred_id_t claimant_cred_handle;
gss_name_t target_name = (gss_name_t) 0;
gss_OID mech_type = (gss_OID) 0;
int req_flags;
OM_uint32 time_req;
gss_channel_bindings_t input_chan_bindings;
gss_buffer_t input_token;
gss_buffer_desc context_token;
gss_OID actual_mech_type;
int ret_flags;
OM_uint32 time_rec;
uid_t uid;
char * string;
gss_buffer_desc name;
/*
* If this is the first phase of the context establishment,
* clear initiator_context_handle and indicate next phase.
*/
if (init_sec_context_phase == 0) {
initiator_context_handle = GSS_C_NO_CONTEXT;
input_token = GSS_C_NO_BUFFER;
init_sec_context_phase = 1;
} else
input_token = &init_token_buffer;
/*
* First set up the non-variable command line independent input
* arguments
*/
claimant_cred_handle = GSS_C_NO_CREDENTIAL;
req_flags = GSS_C_MUTUAL_FLAG;
time_req = (OM_uint32) 0;
input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
uid = getuid();
/* Now parse the command line for the remaining input arguments */
if (argc == 0) {
usage();
return;
}
/*
* Get the name of the target.
*/
name.length = strlen(argv[0])+1;
name.value = argv[0];
/*
* Now convert the string given by the first argument into a target
* name suitable for input to gss_init_sec_context()
*/
if ((status = gss_import_name(&minor_status, &name,
/* GSS_C_NULL_OID, &target_name)) */
(gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &target_name))
!= GSS_S_COMPLETE) {
printf(gettext(
"could not parse target name: err (octal) %o (%s)\n"),
status,
gettext("gss_init_sec_context error"));
if (input_token != GSS_C_NO_BUFFER)
gss_release_buffer(&minor_status, &init_token_buffer);
init_sec_context_phase = 0;
return;
}
argc--;
argv++;
if (argc == 0) {
printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
printf(gettext(
"The mech OID 1.2.840.113554.1.2.2 will be used\n"));
mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
} else {
mech_type = gss_str2oid(argv[0]);
}
if (mech_type == 0 || mech_type->length == 0) {
printf(gettext("improperly formated mechanism OID\n"));
if (input_token != GSS_C_NO_BUFFER)
gss_release_buffer(&minor_status, &init_token_buffer);
init_sec_context_phase = 0;
return;
}
/* call kgss_init_sec_context */
status = kgss_init_sec_context(&minor_status,
claimant_cred_handle,
&initiator_context_handle,
target_name,
mech_type,
req_flags,
time_req,
input_chan_bindings,
input_token,
&actual_mech_type,
&accept_token_buffer,
&ret_flags,
&time_rec,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status != GSS_S_COMPLETE &&
status != GSS_S_CONTINUE_NEEDED) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, "gss_init_sec_context error");
init_sec_context_phase = 0;
if (status == GSS_S_NO_CRED)
printf(gettext(" : no credentials"));
if (input_token != GSS_C_NO_BUFFER)
gss_release_buffer(&minor_status, &init_token_buffer);
if (status != GSS_S_FAILURE && minor_status != 0xffffffff)
status = kgss_delete_sec_context(&minor_status,
&initiator_context_handle,
&msg_token);
return;
} else if (status == GSS_S_COMPLETE) {
/* process returned values */
printf(gettext("\ninit succeeded\n\n"));
/* print out the actual mechanism type */
if ((string = gss_oid2str(actual_mech_type)) == 0) {
printf(gettext(
"gssapi internal err : actual "
"mech type null\n"));
init_sec_context_phase = 0;
if (input_token != GSS_C_NO_BUFFER)
gss_release_buffer(&minor_status,
&init_token_buffer);
gss_release_buffer(&minor_status, &accept_token_buffer);
status = kgss_delete_sec_context(&minor_status,
&initiator_context_handle,
&msg_token);
return;
} else {
printf(gettext("actual mech type = %s\n\n"), string);
FREE(string, (actual_mech_type->length+1)*4+1);
}
/* print out value of ret_flags and time_req */
if (ret_flags & GSS_C_DELEG_FLAG)
printf(gettext("GSS_C_DELEG_FLAG = True\n"));
else
printf(gettext("GSS_C_DELEG_FLAG = False\n"));
if (ret_flags & GSS_C_MUTUAL_FLAG)
printf(gettext("GSS_C_MUTUAL_FLAG = True\n"));
else
printf(gettext("GSS_C_MUTUAL_FLAG = False\n"));
if (ret_flags & GSS_C_REPLAY_FLAG)
printf(gettext("GSS_C_REPLAY_FLAG = True\n"));
else
printf(gettext("GSS_C_REPLAY_FLAG = False\n"));
if (ret_flags & GSS_C_SEQUENCE_FLAG)
printf(gettext("GSS_C_SEQUENCE_FLAG = True\n"));
else
printf(gettext("GSS_C_SEQUENCE_FLAG = False\n"));
if (ret_flags & GSS_C_CONF_FLAG)
printf(gettext("GSS_C_CONF_FLAG = True\n"));
else
printf(gettext("GSS_C_CONF_FLAG = False\n"));
if (ret_flags & GSS_C_INTEG_FLAG)
printf(gettext("GSS_C_INTEG_FLAG = True\n\n"));
else
printf(gettext("GSS_C_INTEG_FLAG = False\n\n"));
printf(gettext("time_req = %u seconds\n\n"), time_rec);
/* free allocated memory */
FREE(mech_type->elements, mech_type->length);
FREE(mech_type, sizeof (gss_OID_desc));
/* these two were malloc'd by kgss_init_sec_context() */
FREE(actual_mech_type->elements, actual_mech_type->length);
FREE(actual_mech_type, sizeof (gss_OID_desc));
gss_release_name(&minor_status, &target_name);
if (input_token != GSS_C_NO_BUFFER)
gss_release_buffer(&minor_status, &init_token_buffer);
/*
* if status == GSS_S_COMPLETE, reset the phase to 0 and
* release token in accept_token_buffer
*/
init_sec_context_phase = 0;
/* Save and restore the context */
status = kgss_export_sec_context(&minor_status,
&initiator_context_handle,
&context_token);
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_export_sec_context_error"));
return;
}
status = kgss_import_sec_context(&minor_status,
&context_token,
&initiator_context_handle);
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_import_sec_context_error"));
return;
}
(void) gss_release_buffer(&minor_status, &context_token);
/* gss_export & gss_import secxc_context worked, return */
printf(gettext("\nexport and import of contexts succeeded\n"));
printf(gettext("\ninit completed"));
} else {
printf(gettext("\nfirst phase of init succeeded"));
printf(gettext("\ninit must be called again\n\n"));
}
}
/*ARGSUSED*/
static void
_gss_accept_sec_context(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
OM_uint32 minor_status;
gss_channel_bindings_t input_chan_bindings;
gss_OID mech_type;
int ret_flags;
OM_uint32 time_rec;
gss_cred_id_t delegated_cred_handle;
uid_t uid;
char *string;
gss_buffer_desc src_name, src_name_string;
gss_buffer_desc output_token;
gss_name_t gss_name;
gss_buffer_desc context_token;
/*
* If this is the first phase of the context establishment,
* clear acceptor_context_handle and indicate next phase.
*/
if (accept_sec_context_phase == 0) {
acceptor_context_handle = GSS_C_NO_CONTEXT;
accept_sec_context_phase = 1;
}
/* Now set up the other command line independent input arguments */
input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
uid = (uid_t) getuid();
if (argc != 0) {
usage();
return;
}
status = kgss_accept_sec_context(&minor_status,
&acceptor_context_handle,
acceptor_credentials,
&accept_token_buffer,
input_chan_bindings,
&src_name,
&mech_type,
&init_token_buffer,
&ret_flags,
&time_rec,
&delegated_cred_handle,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_accept_sec_context error"));
gss_release_buffer(&minor_status, &accept_token_buffer);
return;
} else if (status == GSS_S_COMPLETE) {
/* process returned values */
printf(gettext("\naccept succeeded\n\n"));
/*
* convert the exported name returned in src_name into
* a string and print it.
*/
if ((status = gss_import_name(&minor_status, &src_name,
(gss_OID) GSS_C_NT_EXPORT_NAME, &gss_name))
!= GSS_S_COMPLETE) {
printf(gettext(
"could not import src name 0x%x\n"), status);
accept_sec_context_phase = 0;
status = kgss_delete_sec_context(&minor_status,
&acceptor_context_handle,
&output_token);
gss_release_buffer(&minor_status, &accept_token_buffer);
if (status == GSS_S_CONTINUE_NEEDED)
gss_release_buffer(&minor_status,
&init_token_buffer);
gss_release_buffer(&minor_status, &src_name);
return;
}
memset(&src_name_string, 0, sizeof (src_name_string));
if ((status = gss_display_name(&minor_status, gss_name,
&src_name_string, NULL)) != GSS_S_COMPLETE) {
printf(gettext("could not display src name: "
"err (octal) %o (%s)\n"), status,
"gss_init_sec_context error");
accept_sec_context_phase = 0;
status = kgss_delete_sec_context(&minor_status,
&acceptor_context_handle,
&output_token);
gss_release_buffer(&minor_status, &accept_token_buffer);
if (status == GSS_S_CONTINUE_NEEDED)
gss_release_buffer(&minor_status,
&init_token_buffer);
gss_release_buffer(&minor_status, &src_name);
return;
}
printf(gettext("src name = %s\n"), src_name_string.value);
gss_release_name(&minor_status, &gss_name);
gss_release_buffer(&minor_status, &src_name_string);
gss_release_buffer(&minor_status, &src_name);
/* print out the mechanism type */
if ((string = gss_oid2str(mech_type)) == 0) {
printf(gettext(
"gssapi internal err :"
" actual mech type null\n"));
accept_sec_context_phase = 0;
status = kgss_delete_sec_context(&minor_status,
&acceptor_context_handle,
&output_token);
gss_release_buffer(&minor_status, &accept_token_buffer);
if (status == GSS_S_CONTINUE_NEEDED)
gss_release_buffer(&minor_status,
&init_token_buffer);
return;
} else {
printf(gettext("actual mech type = %s\n\n"), string);
FREE(string, (mech_type->length+1)*4+1);
}
/* Save and restore the context */
status = kgss_export_sec_context(&minor_status,
&initiator_context_handle,
&context_token);
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_export_sec_context_error"));
return;
}
status = kgss_import_sec_context(&minor_status,
&context_token,
&initiator_context_handle);
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_import_sec_context_error"));
return;
}
(void) gss_release_buffer(&minor_status, &context_token);
/* gss_export & gss_import secxc_context worked, return */
/* print out value of ret_flags and time_req */
if (ret_flags & GSS_C_DELEG_FLAG)
printf(gettext("GSS_C_DELEG_FLAG = True\n"));
else
printf(gettext("GSS_C_DELEG_FLAG = False\n"));
if (ret_flags & GSS_C_MUTUAL_FLAG)
printf(gettext("GSS_C_MUTUAL_FLAG = True\n"));
else
printf(gettext("GSS_C_MUTUAL_FLAG = False\n"));
if (ret_flags & GSS_C_REPLAY_FLAG)
printf(gettext("GSS_C_REPLAY_FLAG = True\n"));
else
printf(gettext("GSS_C_REPLAY_FLAG = False\n"));
if (ret_flags & GSS_C_SEQUENCE_FLAG)
printf(gettext("GSS_C_SEQUENCE_FLAG = True\n"));
else
printf(gettext("GSS_C_SEQUENCE_FLAG = False\n"));
if (ret_flags & GSS_C_CONF_FLAG)
printf(gettext("GSS_C_CONF_FLAG = True\n"));
else
printf(gettext("GSS_C_CONF_FLAG = False\n"));
if (ret_flags & GSS_C_INTEG_FLAG)
printf(gettext("GSS_C_INTEG_FLAG = True\n\n"));
else
printf(gettext("GSS_C_INTEG_FLAG = False\n\n"));
printf(gettext("time_rec = %d seconds\n\n"), time_rec);
/* free allocated memory */
printf(gettext("\nexport and import of contexts succeeded\n"));
FREE(mech_type->elements, mech_type->length);
FREE(mech_type, sizeof (gss_OID_desc));
} else {
printf(gettext("\nfirst phase of accept succeeded"));
printf(gettext("\naccept must be called again\n\n"));
}
/* free the input token in accept_token_buffer */
gss_release_buffer(&minor_status, &accept_token_buffer);
/* if status == GSS_S_COMPLETE, reset the phase to 0 */
if (status == GSS_S_COMPLETE)
accept_sec_context_phase = 0;
/* gss_accept_sec_context worked, return */
}
void
_gss_process_context_token(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
gss_ctx_id_t context_handle;
OM_uint32 minor_status;
uid_t uid;
uid = (uid_t) getuid();
/* parse the command line to determine the variable input argument */
if (argc == 0) {
usage();
return;
}
if (strcmp(argv[0], "initiator") == 0)
context_handle = initiator_context_handle;
else if (strcmp(argv[0], "acceptor") == 0)
context_handle = acceptor_context_handle;
else {
printf(gettext(
"must specify either \"initiator\" or \"acceptor\"\n"));
return;
}
argc--;
argv++;
if (argc != 0) {
usage();
return;
}
status = kgss_process_context_token(&minor_status,
context_handle,
delete_token_buffer,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_process_context_token error"));
return;
} else {
printf(gettext("\nprocess succeeded\n\n"));
return;
}
}
static void
_gss_delete_sec_context(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
gss_ctx_id_t *context_handle;
OM_uint32 minor_status;
/* parse the command line to determine the variable input argument */
if (argc == 0) {
usage();
return;
}
if (strcmp(argv[0], "initiator") == 0) {
context_handle = &initiator_context_handle;
} else if (strcmp(argv[0], "acceptor") == 0) {
context_handle = &acceptor_context_handle;
} else {
printf(gettext(
"must specify either \"initiator\" or \"acceptor\"\n"));
return;
}
argc--;
argv++;
if (argc != 0) {
usage();
return;
}
status = kgss_delete_sec_context(&minor_status,
context_handle,
&delete_token_buffer);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_delete_sec_context error"));
return;
} else {
printf(gettext("\ndelete succeeded\n\n"));
return;
}
}
/*ARGSUSED*/
static void
_gss_context_time(argc, argv)
int argc;
char **argv;
{
/*
* set up input arguments here
* this function is unimplemented. Call usage() and return
*/
printf(gettext("\nunimplemented function"));
}
static void
_gss_sign(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
OM_uint32 minor_status;
gss_ctx_id_t context_handle;
int qop_req;
uid_t uid;
uid = (uid_t) getuid();
/* specify the default quality of protection */
qop_req = GSS_C_QOP_DEFAULT;
/* set up the arguments specified in the input parameters */
if (argc == 0) {
usage();
return;
}
if (strcmp(argv[0], "initiator") == 0)
context_handle = initiator_context_handle;
else if (strcmp(argv[0], "acceptor") == 0)
context_handle = acceptor_context_handle;
else {
printf(gettext(
"must specify either \"initiator\" or \"acceptor\"\n"));
return;
}
argc--;
argv++;
if (argc == 0) {
usage();
return;
}
message_buffer.length = strlen(argv[0])+1;
message_buffer.value = (void *) MALLOC(message_buffer.length);
strcpy(message_buffer.value, argv[0]);
argc--;
argv++;
if (argc != 0) {
usage();
return;
}
status = kgss_sign(&minor_status,
context_handle,
qop_req,
&message_buffer,
&msg_token,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_sign error"));
return;
} else {
printf(gettext("\nsign succeeded\n\n"));
return;
}
}
static void
_gss_verify(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status, minor_status;
gss_ctx_id_t context_handle;
int qop_state;
uid_t uid;
uid = (uid_t) getuid();
/* set up the arguments specified in the input parameters */
if (argc == 0) {
usage();
return;
}
if (strcmp(argv[0], "initiator") == 0)
context_handle = initiator_context_handle;
else if (strcmp(argv[0], "acceptor") == 0)
context_handle = acceptor_context_handle;
else {
printf(gettext(
"must specify either \"initiator\" or \"acceptor\"\n"));
return;
}
argc--;
argv++;
if (argc != 0) {
usage();
return;
}
status = kgss_verify(&minor_status,
context_handle,
&message_buffer,
&msg_token,
&qop_state,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_verify error"));
return;
} else {
/* print out the verified message */
printf(gettext(
"verified message = \"%s\"\n\n"), message_buffer.value);
/* print out the quality of protection returned */
printf(gettext("quality of protection = %d \n\n"), qop_state);
/* free the message buffer and message token and return */
gss_release_buffer(&minor_status, &message_buffer);
gss_release_buffer(&minor_status, &msg_token);
return;
}
}
static void
_gss_seal(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
OM_uint32 minor_status;
gss_ctx_id_t context_handle;
int conf_req_flag;
int qop_req;
gss_buffer_desc input_message_buffer;
int conf_state;
uid_t uid;
uid = (uid_t) getuid();
/*
* specify the default confidentiality requested (both integrity
* and confidentiality) and quality of protection
*/
conf_req_flag = 1;
qop_req = GSS_C_QOP_DEFAULT;
/* set up the arguments specified in the input parameters */
if (argc == 0) {
usage();
return;
}
if (strcmp(argv[0], "initiator") == 0)
context_handle = initiator_context_handle;
else if (strcmp(argv[0], "acceptor") == 0)
context_handle = acceptor_context_handle;
else {
printf(gettext(
"must specify either \"initiator\" or \"acceptor\"\n"));
return;
}
argc--;
argv++;
if (argc == 0) {
usage();
return;
}
input_message_buffer.length = strlen(argv[0])+1;
input_message_buffer.value =
(void *) MALLOC(input_message_buffer.length);
strcpy(input_message_buffer.value, argv[0]);
argc--;
argv++;
if (argc != 0) {
usage();
return;
}
status = kgss_seal(&minor_status,
context_handle,
conf_req_flag,
qop_req,
&input_message_buffer,
&conf_state,
&message_buffer,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
/* free the inputmessage buffer */
gss_release_buffer(&minor_status, &input_message_buffer);
if (status != GSS_S_COMPLETE) {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_seal error"));
return;
} else {
printf(gettext("\nseal succeeded\n\n"));
return;
}
}
static void
_gss_unseal(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
OM_uint32 minor_status;
gss_ctx_id_t context_handle;
gss_buffer_desc output_message_buffer;
int conf_state;
int qop_state;
uid_t uid;
uid = (uid_t) getuid();
/* set up the arguments specified in the input parameters */
if (argc == 0) {
usage();
return;
}
if (strcmp(argv[0], "initiator") == 0)
context_handle = initiator_context_handle;
else if (strcmp(argv[0], "acceptor") == 0)
context_handle = acceptor_context_handle;
else {
printf(gettext(
"must specify either \"initiator\" or \"acceptor\"\n"));
return;
}
argc--;
argv++;
if (argc != 0) {
usage();
return;
}
status = kgss_unseal(&minor_status,
context_handle,
&message_buffer,
&output_message_buffer,
&conf_state,
&qop_state,
uid);
/* store major and minor status for gss_display_status() call */
gss_major_code = status;
gss_minor_code = minor_status;
if (status == GSS_S_COMPLETE) {
printf(gettext("\nunseal succeeded\n\n"));
printf(gettext("unsealed message = \"%s\"\n\n"),
output_message_buffer.value);
if (conf_state)
printf(gettext("confidentiality and integrity used\n"));
else
printf(gettext("only integrity used\n"));
printf(gettext("quality of protection = %d\n\n"), qop_state);
gss_release_buffer(&minor_status, &output_message_buffer);
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_unseal error"));
}
/* free the message buffer and return */
gss_release_buffer(&minor_status, &message_buffer);
}
static void
_gss_display_status(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
OM_uint32 minor_status;
int status_type;
int status_value;
gss_OID mech_type = (gss_OID) 0;
int message_context;
gss_buffer_desc status_string;
uid_t uid;
uid = (uid_t) getuid();
/* initialize message context to zero */
message_context = 0;
if (argc == 0) {
printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
printf(gettext(
"The mech OID 1.2.840.113554.1.2.2 will be used\n"));
mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
} else
mech_type = gss_str2oid(argv[0]);
if (mech_type == 0 || mech_type->length == 0) {
printf(gettext("improperly formated mechanism OID\n"));
return;
}
/* Is this call for the major or minor status? */
if (strcmp(argv[0], "major") == 0) {
status_type = GSS_C_GSS_CODE;
status_value = gss_major_code;
} else if (strcmp(argv[0], "minor") == 0) {
status_type = GSS_C_MECH_CODE;
status_value = gss_minor_code;
} else {
printf(gettext("must specify either \"major\" or \"minor\"\n"));
return;
}
argc--;
argv++;
if (argc != 0) {
usage();
return;
}
status = kgss_display_status(&minor_status,
status_value,
status_type,
mech_type,
&message_context,
&status_string,
uid);
if (status == GSS_S_COMPLETE) {
printf(gettext("status =\n %s\n\n"), status_string.value);
} else if (status == GSS_S_BAD_MECH) {
printf(gettext("invalide mechanism OID\n\n"));
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_display_status error"));
}
}
/*ARGSUSED*/
static void
_gss_indicate_mechs(argc, argv)
int argc;
char **argv;
{
OM_UINT32 status;
OM_UINT32 minor_status;
gss_OID_set oid_set = GSS_C_NULL_OID_SET;
uid_t uid;
uid = (uid_t) getuid();
/* set up input arguments here */
if (argc != 0) {
usage();
return;
}
status = kgss_indicate_mechs(&minor_status, &oid_set, uid);
if (status == GSS_S_COMPLETE) {
int i;
char *string;
printf(gettext("%d supported mechanism%s%s\n"), oid_set->count,
(oid_set->count == 1) ? "" : "s",
(oid_set->count > 0) ? ":" : "");
for (i = 0; i < oid_set->count; i++) {
string = gss_oid2str(&oid_set->elements[i]);
printf(gettext("\t%s\n"), string);
FREE(string, ((oid_set->elements[i].length+1)*4)+1);
}
printf("\n");
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
status, gettext("gss_indicate_mechs error"));
}
if (oid_set)
gss_release_oid_set_and_oids(&minor_status, &oid_set);
}
/*ARGSUSED*/
static void
_gss_inquire_cred(argc, argv)
int argc;
char **argv;
{
/* set up input arguments here */
if (argc != 0) {
usage();
return;
}
/* this function is unimplemented. Call usage() and return */
printf(gettext("\nUnsupported function"));
}
static char hexChars[] = "0123456789ABCDEF";
static void
_gssd_expname_to_unix_cred(argc, argv)
int argc;
char **argv;
{
OM_uint32 major;
gss_buffer_desc expName;
char krb5_root_name[] = "040100092A864886F712010202000000"
"25000A2A864886F71201020101726F6F744053554E534F46"
"542E454E472E53554E2E434F4D00";
unsigned char *byteStr, *hexStr;
uid_t uidOut, uidIn;
gid_t *gids, gidOut;
int gidsLen, i, newLen;
/* set up the arguments */
uidIn = (uid_t) getuid();
if (argc < 1) {
printf(gettext(
"Using principal name of root for krberos_v5\n"));
expName.value = (void*)krb5_root_name;
expName.length = strlen(krb5_root_name);
} else {
expName.value = (void*)argv[0];
expName.length = strlen(argv[0]);
}
/* convert the name from hex to byte... */
hexStr = (unsigned char *)expName.value;
newLen = expName.length/2;
byteStr = (unsigned char *)MALLOC(newLen+1);
expName.value = (char *)byteStr;
for (i = 0; i < expName.length; i += 2) {
*byteStr = (strchr(hexChars, *hexStr++) - hexChars) << 4;
*byteStr += (strchr(hexChars, *hexStr++) - hexChars);
byteStr++;
}
expName.length = newLen;
major = kgsscred_expname_to_unix_cred(&expName, &uidOut, &gidOut,
&gids, &gidsLen, uidIn);
FREE(expName.value, newLen);
if (major == GSS_S_COMPLETE) {
printf(gettext("uid = <%d>\tgid = <%d>\t"), uidOut, gidOut);
if (gidsLen > 0)
printf(gettext(" %d gids <"), gidsLen);
else
printf(gettext(
" no supplementary group information\n"));
for (i = 0; i < gidsLen; i++)
printf(" %d ", gids[i]);
if (gidsLen > 0) {
printf(">\n");
FREE(gids, gidsLen * sizeof (gid_t));
}
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
major, gettext("gsscred_expname_to_unix_cred"));
}
}
static void
_gssd_name_to_unix_cred(argc, argv)
int argc;
char **argv;
{
OM_uint32 major, minor;
gss_name_t gssName;
gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER;
int gidsLen, i;
gid_t *gids, gidOut;
uid_t uidOut, uid;
char defaultPrincipal[] = "root";
gss_OID mechType, nameType;
uid = getuid();
/* optional argument 1 - contains principal name */
if (argc > 0) {
gssBuf.value = (void *)argv[0];
gssBuf.length = strlen((char *)argv[0]);
} else {
gssBuf.value = (void *)defaultPrincipal;
gssBuf.length = strlen(defaultPrincipal);
}
printf(gettext(
"Using <%s> as the principal name.\n"), (char *)gssBuf.value);
/* optional argument 2 - contains name oid */
if (argc > 1)
nameType = gss_str2oid((char *) argv[1]);
else
nameType = (gss_OID)GSS_C_NT_USER_NAME;
if (nameType == NULL || nameType->length == 0) {
printf(gettext("improperly formated name OID\n"));
return;
}
printf(gettext("Principal name of type: <%s>.\n"),
(argc > 1) ? argv[1] : "GSS_C_NT_USER_NAME");
/* optional argument 3 - contains mech oid */
if (argc > 2)
mechType = gss_str2oid(argv[2]);
else
mechType = gss_str2oid((char *)GSS_KRB5_MECH_OID);
if (mechType == NULL || mechType->length == 0) {
FREE(nameType->elements, nameType->length);
FREE(nameType, sizeof (gss_OID_desc));
printf(gettext("improperly formated mech OID\n"));
return;
}
printf(gettext("Mechanism oid: <%s>.\n"),
(argc > 2) ? argv[2] :
(char *)GSS_KRB5_MECH_OID "(Kerberos v5)");
/* convert the name to internal format */
if ((major = gss_import_name(&minor, &gssBuf,
nameType, &gssName)) != GSS_S_COMPLETE) {
printf(gettext("could not parse name: err (octal) %o (%s)\n"),
major, "gss_import_name");
FREE(nameType->elements, nameType->length);
FREE(nameType, sizeof (gss_OID_desc));
return;
}
major = kgsscred_name_to_unix_cred(gssName, mechType, &uidOut,
&gidOut, &gids, &gidsLen, uid);
gss_release_name(&minor, &gssName);
FREE(mechType->elements, mechType->length);
FREE(mechType, sizeof (gss_OID_desc));
if (argc > 1) {
FREE(nameType->elements, nameType->length);
FREE(nameType, sizeof (gss_OID_desc));
}
if (major == GSS_S_COMPLETE) {
printf("uid = <%d>\tgid = <%d>\t", uidOut, gidOut);
if (gidsLen > 0)
printf(gettext(" %d gids <"), gidsLen);
else
printf(gettext(
" no supplementary group information\n"));
for (i = 0; i < gidsLen; i++)
printf(" %d ", gids[i]);
if (gidsLen > 0) {
printf(">\n");
FREE(gids, gidsLen * sizeof (gid_t));
}
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
major, gettext("gsscred_name_to_unix_cred"));
}
}
static void
_gssd_get_group_info(argc, argv)
int argc;
char **argv;
{
OM_uint32 major;
uid_t puid, uidIn;
gid_t *gids, gidOut;
int gidsLen, i;
/* set up the arguments */
uidIn = (uid_t) getuid();
if (argc < 1)
puid = 0;
else
puid = atol(argv[0]);
printf(gettext("Retrieving group info for uid of <%d>\n"), puid);
major = kgss_get_group_info(puid, &gidOut, &gids, &gidsLen, uidIn);
if (major == GSS_S_COMPLETE) {
printf(gettext("group id = <%d>\t"), gidOut);
if (gidsLen > 0)
printf(gettext(" %d gids <"), gidsLen);
else
printf(gettext(
" no supplementary group information\n"));
for (i = 0; i < gidsLen; i++)
printf(" %d ", gids[i]);
if (gidsLen > 0) {
printf(">\n");
FREE(gids, gidsLen * sizeof (gid_t));
}
} else {
printf(gettext("server ret err (octal) %o (%s)\n"),
major, "gss_get_group_info");
}
}
static gss_OID
gss_str2oid(string)
char * string;
{
/*
* a convenient wrapper routine for gss_str_to_oid
* this can handle all valid oid strings.
*/
OM_uint32 minor;
gss_buffer_desc abuf;
gss_OID oidOut;
abuf.value = (void*)string;
abuf.length = strlen(string);
if (gss_str_to_oid(&minor, &abuf, &oidOut) != GSS_S_COMPLETE)
return (NULL);
return (oidOut);
}
static char *
gss_oid2str(oid)
gss_OID oid;
{
/*
* a convenient wrapper for gss_oid_to_str
* this calls the GSS-API routine which should
* be able to handle all types of oids.
*/
OM_uint32 minor;
gss_buffer_desc oidStr;
if (gss_oid_to_str(&minor, oid, &oidStr) != GSS_S_COMPLETE)
return (NULL);
return ((char *)oidStr.value);
} /* gss_oid2str */
static void
instructs()
{
fprintf(stderr,
gettext(
"\nThis program must be run as root. Root must be installed on the KDC\n"
"and exist in srvtab as root/, where is the machine on\n"
"which the test runs. Before running gssdtest for Kerberos mechanism, the\n"
"operator running as root must kinit as some other principal, e.g., test.\n"
"There are two mechanisms avaialble: dummy and Kerberos(default).\n"
"The OID for dummy mechanism is 1.3.6.1.4.1.42.2.26.1.2.\n"
"The OID for Kerberos mechanism is 1.2.840.113554.1.2.2.\n"
"The order of context establishment calls is important. First, acquire must"
"\nbe called. This obtains the credentials used by accept. Acquire need\n"
"only be called once, since the credentials it returns are used each time\n"
"accept is called. Then init is called, followed by accept. Calling init\n"
"twice without calling accept or calling these in a different order gives\n"
"erroneous results and will cause memory leaks in the gssapi daemon. \n"
"Finally, after calling init and accept, init must be called again to\n"
"finish context establishment. So an example sequence (with data valid for\n"
"the Kerberos mechanism and running on the machine \"elrond\" in the realm\n"
"FOO.BAR.SUN.COM is :\n"));
fprintf(stderr,
gettext("\nacquire service@host 1.2.840.113554.1.2.2\n"
"init service@host 1.2.840.113554.1.2.2\n"
"accept\ninit service@host 1.2.840.113554.1.2.2\n"
"\nAfter a context is established, sign, seal,\n"
"verify and unseal may be called. Here are some examples\n"
"for these routines : \n\n"
"sign initiator ThisTestMessageIsForSigning\n"
"verify acceptor\nseal initiator ThisTestMessageIsForSealing\n"
"unseal acceptor\n\nEach input line is terminated by .\n"
"The program is terminated by cntl-d\nor the command \"exit\""
"\nfrom the prompt\n\n"));
}
static void
usage()
{
fprintf(stderr,
gettext(
"\nusage:\t[acquire | gss_acquire_cred]"
"desired_name mech_type\n"
"\t[release | gss_release_cred]\n"
"\t[init | gss_init_sec_context] target_name mech_type\n"
"\t[accept | gss_accept_sec_context]\n"
"\t[process | gss_process_context_token] initiator | acceptor\n"
"\t[delete | gss_delete_sec_context] initiator | acceptor\n"
"\t[time | gss_context_time] {not yet implemented}\n"
"\t[sign | gss_sign] initiator | acceptor message-to-sign\n"
"\t[verify | gss_verify] initiator | acceptor\n"
"\t[seal | gss_seal] initiator | acceptor message-to-seal\n"
"\t[unseal | gss_unseal] initiator | acceptor\n"
"\t[status | gss_display_status] mech_type [major | minor] \n"
"\t[indicate | gss_indicate_mechs]\n"
"\t[inquire | gss_inquire_cred] {not yet implemented}\n"
"\t[expname2unixcred | gsscred_expname_to_unix_cred]"
" export-name\n"
"\t[name2unixcred | gsscred_name_to_unix_cred] "
"pname [name_type mech_type]\n"
"\t[grpinfo | gss_get_group_info] uid\n"
"\t[gss_all | all] desired_name\n"
"\t[gss_loop | loop] desired_name\n"
"\texit\n\n"));
}
/* Copied from parse_argv(), then modified */
static int
parse_input_line(input_line, argc, argv)
char *input_line;
int * argc;
char ***argv;
{
const char nil = '\0';
char * chptr;
int chr_cnt;
int arg_cnt = 0;
int ch_was_space = 1;
int ch_is_space;
chr_cnt = strlen(input_line);
/* Count the arguments in the input_line string */
*argc = 1;
for (chptr = &input_line[0]; *chptr != nil; chptr++) {
ch_is_space = isspace(*chptr);
if (ch_is_space && !ch_was_space) {
(*argc)++;
}
ch_was_space = ch_is_space;
}
if (ch_was_space) {
(*argc)--;
} /* minus trailing spaces */
/* Now that we know how many args calloc the argv array */
*argv = (char **) CALLOC((*argc)+1, sizeof (char *));
chptr = (char *) (&input_line[0]);
for (ch_was_space = 1; *chptr != nil; chptr++) {
ch_is_space = isspace(*chptr);
if (ch_is_space) {
*chptr = nil; /* replace each space with nil */
} else if (ch_was_space) { /* begining of word? */
(*argv)[arg_cnt++] = chptr; /* new argument ? */
}
ch_was_space = ch_is_space;
}
return (chr_cnt);
}
#
# 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
# or http://www.opensolaris.org/os/licensing.
# 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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
#
# MAPFILE HEADER START
#
# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
# Object versioning must comply with the rules detailed in
#
# usr/src/lib/README.mapfiles
#
# You should not be making modifications here until you've read the most current
# copy of that file. If you need help, contact a gatekeeper for guidance.
#
# MAPFILE HEADER END
#
$mapfile_version 2
# gssd exports app_krb5_user_uid() - required by mech_krb5.
SYMBOL_SCOPE {
global:
app_krb5_user_uid;
};