657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * CDDL HEADER START
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * The contents of this file are subject to the terms of the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Common Development and Distribution License (the "License").
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * You may not use this file except in compliance with the License.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * or http://www.opensolaris.org/os/licensing.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * See the License for the specific language governing permissions
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * and limitations under the License.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * When distributing Covered Code, include this CDDL HEADER in each
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * If applicable, add the following below this CDDL HEADER, with the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * fields enclosed by brackets "[]" replaced with your own identifying
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * information: Portions Copyright [yyyy] [name of copyright owner]
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * CDDL HEADER END
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Use is subject to license terms.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * transport layer for audit_remote (handles connection establishment, gss
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * context initialization, message encryption and verification)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <assert.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <audit_plugin.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <errno.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <fcntl.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <gssapi/gssapi.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <libintl.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <mtmalloc.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <netdb.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <netinet/in.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <netinet/tcp.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <stdio.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <stdlib.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <string.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <strings.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <syslog.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <sys/types.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <sys/socket.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <unistd.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <poll.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include <pthread.h>
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#include "audit_remote.h"
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int sockfd = -1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic struct hostent *current_host;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic gss_OID *current_mech_oid;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic in_port_t current_port;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t flush_transq;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic char *ver_str = "01"; /* supported protocol version */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic char *ver_str_concat; /* concat serv/client version */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic gss_ctx_id_t gss_ctx;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t gss_ctx_initialized;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelpthread_t recv_tid; /* receiving thread */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic pthread_once_t recv_once_control = PTHREAD_ONCE_INIT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelextern int timeout; /* connection timeout */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelextern pthread_mutex_t plugin_mutex;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedeltransq_hdr_t transq_hdr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * The three locks synchronize the simultaneous actions on top of transmission
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * queue, socket, gss_context.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelpthread_mutex_t transq_lock = PTHREAD_MUTEX_INITIALIZER;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelpthread_mutex_t sock_lock = PTHREAD_MUTEX_INITIALIZER;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelpthread_mutex_t gss_ctx_lock = PTHREAD_MUTEX_INITIALIZER;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/* reset routine synchronization - required by the sending thread */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelpthread_mutex_t reset_lock = PTHREAD_MUTEX_INITIALIZER;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t reset_in_progress; /* reset routine in progress */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#define NP_CLOSE -1 /* notification pipe - close message */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#define NP_EXIT -2 /* notification pipe - exit message */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelboolean_t notify_pipe_ready;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelint notify_pipe[2]; /* notif. pipe - receiving thread */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelpthread_cond_t reset_cv = PTHREAD_COND_INITIALIZER;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic close_rsn_t recv_closure_rsn;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#define MAX_TOK_LEN (128 * 1000) /* max token length we accept (B) */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/* transmission queue helpers */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void transq_dequeue(transq_node_t *);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t transq_enqueue(transq_node_t **, gss_buffer_t,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint64_t);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int transq_retransmit(void);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t init_poll(int);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void do_reset(int *, struct pollfd *, boolean_t);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void do_cleanup(int *, struct pollfd *, boolean_t);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void init_recv_record(void);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void recv_record();
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int connect_timeout(int, struct sockaddr *, int);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int send_timeout(int, const char *, size_t);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int recv_timeout(int, char *, size_t);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int send_token(int *, gss_buffer_t);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int recv_token(int, gss_buffer_t);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * report_err() - wrapper, mainly due to enhance the code readability - report
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * error to syslog via call to __audit_syslog().
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelreport_err(char *msg)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel __audit_syslog("audit_remote.so", LOG_CONS | LOG_NDELAY, LOG_DAEMON,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel LOG_ERR, msg);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * report_gss_err() - GSS API error reporting
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelreport_gss_err(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_buffer_desc msg_buf;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel OM_uint32 _min, msg_ctx;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel char *err_msg;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* major stat */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel msg_ctx = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel do {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_display_status(&_min, maj_stat, GSS_C_GSS_CODE,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *current_mech_oid, &msg_ctx, &msg_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) asprintf(&err_msg,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gettext("GSS API error - %s(%u): %.*s\n"), msg, maj_stat,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel msg_buf.length, (char *)msg_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (err_msg != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(err_msg);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(err_msg);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_buffer(&_min, &msg_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } while (msg_ctx);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* minor stat */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel msg_ctx = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel do {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_display_status(&_min, min_stat, GSS_C_MECH_CODE,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *current_mech_oid, &msg_ctx, &msg_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) asprintf(&err_msg,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gettext("GSS mech error - %s(%u): %.*s\n"), msg, min_stat,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel msg_buf.length, (char *)msg_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (err_msg != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(err_msg);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(err_msg);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_buffer(&_min, &msg_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } while (msg_ctx);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * prot_ver_negotiate() - negotiate/acknowledge the protocol version. Currently,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * there is only one version supported by the plugin - "01".
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Note: connection must be initiated prior version negotiation
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelprot_ver_negotiate()
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_buffer_desc out_buf, in_buf;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel size_t ver_str_concat_sz;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Set the version proposal string - once we support more than
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * version "01" this part should be extended to solve the concatenation
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * of supported version identifiers.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel out_buf.value = (void *)ver_str;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel out_buf.length = strlen((char *)out_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Protocol version proposal (size=%d): %.*s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel out_buf.length, out_buf.length, (char *)out_buf.value));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (send_token(&sockfd, &out_buf) < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Sending protocol version token failed\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (recv_token(sockfd, &in_buf) < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Receiving protocol version token failed\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Verify the sent/received string - memcmp() is sufficient here
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * because we support only one version and it is represented by
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the "01" string. The received version has to be "01" string as well.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (out_buf.length != in_buf.length ||
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel memcmp(out_buf.value, in_buf.value, out_buf.length) != 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Verification of the protocol version strings "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "failed [%d:%s][%d:%s]\n", out_buf.length,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (char *)out_buf.value, in_buf.length,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (char *)in_buf.value));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Prepare the concatenated client/server version strings later used
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * as an application_data field in the gss_channel_bindings_struct
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * structure.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel ver_str_concat_sz = out_buf.length + in_buf.length + 1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel ver_str_concat = (char *)calloc(1, ver_str_concat_sz);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (ver_str_concat == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Memory allocation failed"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Memory allocation failed: %s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) memcpy(ver_str_concat, out_buf.value, out_buf.length);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) memcpy(ver_str_concat + out_buf.length, in_buf.value,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf.length);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Concatenated version strings: %s\n", ver_str_concat));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Protocol version agreed.\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * sock_prepare() - creates and connects socket. Function returns
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * B_FALSE/B_TRUE on failure/success and sets the err_rsn accordingly to the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * reason of failure.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelsock_prepare(int *sockfdptr, struct hostent *host, close_rsn_t *err_rsn)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct sockaddr_storage addr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct sockaddr_in *sin;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct sockaddr_in6 *sin6;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel size_t addr_len;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int sock;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Creating socket for %s\n", host->h_name));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel bzero(&addr, sizeof (addr));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel addr.ss_family = host->h_addrtype;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel switch (host->h_addrtype) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case AF_INET:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sin = (struct sockaddr_in *)&addr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel addr_len = sizeof (struct sockaddr_in);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel bcopy(host->h_addr_list[0],
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel &(sin->sin_addr), sizeof (struct in_addr));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sin->sin_port = current_port;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case AF_INET6:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sin6 = (struct sockaddr_in6 *)&addr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel addr_len = sizeof (struct sockaddr_in6);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel bcopy(host->h_addr_list[0],
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel &(sin6->sin6_addr), sizeof (struct in6_addr));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sin6->sin6_port = current_port;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel default:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* unknown address family */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_UNKNOWN_AF;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_FALSE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if ((sock = socket(addr.ss_family, SOCK_STREAM, 0)) == -1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_SOCKET_CREATE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_FALSE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Socket created, fd=%d, connecting..\n", sock));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (connect_timeout(sock, (struct sockaddr *)&addr, addr_len)) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) close(sock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_CONNECTION_CREATE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_FALSE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *sockfdptr = sock;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Connected to %s via fd=%d\n", host->h_name,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *sockfdptr));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_TRUE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * establish_context() - establish the client/server GSS context.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Note: connection must be established and version negotiated (in plain text)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * prior to establishing context.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelestablish_context()
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_buffer_desc send_tok, recv_tok, *token_ptr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel OM_uint32 maj_stat, min_stat;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel OM_uint32 init_sec_min_stat, ret_flags;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_name_t gss_name;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel char *gss_svc_name = "audit";
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel char *svc_name;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct gss_channel_bindings_struct input_chan_bindings;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* GSS service name = gss_svc_name + "@" + remote hostname (fqdn) */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) asprintf(&svc_name, "%s@%s", gss_svc_name, current_host->h_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (svc_name == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Cannot allocate service name\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Memory allocation failed: %s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Service name: %s\n", svc_name));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel send_tok.value = svc_name;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel send_tok.length = strlen(svc_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat = gss_import_name(&min_stat, &send_tok,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &gss_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (maj_stat != GSS_S_COMPLETE) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_gss_err(gettext("initializing context"), maj_stat,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel min_stat);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(svc_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel token_ptr = GSS_C_NO_BUFFER;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_ctx = GSS_C_NO_CONTEXT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* initialize channel binding */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel bzero(&input_chan_bindings, sizeof (input_chan_bindings));
bf515db2f8b506f788f69875fa1319cfbf177c9dJan Friedel input_chan_bindings.initiator_addrtype = GSS_C_AF_NULLADDR;
bf515db2f8b506f788f69875fa1319cfbf177c9dJan Friedel input_chan_bindings.acceptor_addrtype = GSS_C_AF_NULLADDR;
c7bef3b16d3d2a0b09ff75fbbd724283ef1ee7e7Jan Friedel input_chan_bindings.application_data.length = strlen(ver_str_concat);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel input_chan_bindings.application_data.value = ver_str_concat;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel do {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat = gss_init_sec_context(&init_sec_min_stat,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel GSS_C_NO_CREDENTIAL, &gss_ctx, gss_name, *current_mech_oid,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel | GSS_C_CONF_FLAG, 0, &input_chan_bindings, token_ptr,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel NULL, &send_tok, &ret_flags, NULL);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (token_ptr != GSS_C_NO_BUFFER) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_buffer(&min_stat, &recv_tok);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (send_tok.length != 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "Sending init_sec_context token (size=%d)\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel send_tok.length));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (send_token(&sockfd, &send_tok) < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(svc_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_name(&min_stat, &gss_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (send_tok.value != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(send_tok.value); /* freeing svc_name */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel send_tok.value = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel send_tok.length = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (maj_stat != GSS_S_COMPLETE &&
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat != GSS_S_CONTINUE_NEEDED) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_gss_err(gettext("initializing context"),
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat, init_sec_min_stat);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (gss_ctx == GSS_C_NO_CONTEXT) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_delete_sec_context(&min_stat,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel &gss_ctx, GSS_C_NO_BUFFER);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_name(&min_stat, &gss_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (maj_stat == GSS_S_CONTINUE_NEEDED) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "continue needed... "));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (recv_token(sockfd, &recv_tok) < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_name(&min_stat, &gss_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel token_ptr = &recv_tok;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } while (maj_stat == GSS_S_CONTINUE_NEEDED);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_name(&min_stat, &gss_name);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "context established\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * delete_context() - release GSS context.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedeldelete_context()
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel OM_uint32 min_stat;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_delete_sec_context(&min_stat, &gss_ctx, GSS_C_NO_BUFFER);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "context deleted\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * send_token() - send GSS token over the wire.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelsend_token(int *fdptr, gss_buffer_t tok)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint32_t len;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint32_t lensz;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel char *out_buf;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int fd;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (*fdptr == -1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Socket detected as closed.\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fd = *fdptr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel len = htonl(tok->length);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel lensz = sizeof (len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel out_buf = (char *)malloc((size_t)(lensz + tok->length));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (out_buf == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Memory allocation failed"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Memory allocation failed: %s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) memcpy((void *)out_buf, (void *)&len, lensz);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) memcpy((void *)(out_buf + lensz), (void *)tok->value,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel tok->length);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (send_timeout(fd, out_buf, (lensz + tok->length))) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * recv_token() - receive GSS token over the wire.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelrecv_token(int fd, gss_buffer_t tok)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint32_t len;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (recv_timeout(fd, (char *)&len, sizeof (len))) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel len = ntohl(len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* simple DOS prevention mechanism */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (len > MAX_TOK_LEN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Indicated invalid token length"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Indicated token length > %dB\n", MAX_TOK_LEN));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel tok->value = (char *)malloc(len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (tok->value == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Memory allocation failed"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Memory allocation failed: %s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel tok->length = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (recv_timeout(fd, tok->value, len)) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(tok->value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel tok->value = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel tok->length = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel tok->length = len;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * I/O functions
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * connect_timeout() - sets nonblocking I/O on a socket and timeout-connects
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelconnect_timeout(int sockfd, struct sockaddr *name, int namelen)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int flags;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct pollfd fds;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int rc;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct sockaddr_storage addr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel socklen_t addr_len = sizeof (addr);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel flags = fcntl(sockfd, F_GETFL, 0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (connect(sockfd, name, namelen)) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!(errno == EINTR || errno == EINPROGRESS ||
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel errno == EWOULDBLOCK)) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.fd = sockfd;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.events = POLLOUT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel for (;;) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.revents = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel rc = poll(&fds, 1, timeout * 1000);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (rc == 0) { /* timeout */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else if (rc < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (errno == EINTR || errno == EAGAIN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (fds.revents) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (getpeername(sockfd, (struct sockaddr *)&addr,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel &addr_len))
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * send_timeout() - send data (in chunks if needed, each chunk in timeout secs).
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelsend_timeout(int fd, const char *buf, size_t len)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct pollfd fds;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int rc;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.fd = fd;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.events = POLLOUT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (len) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.revents = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel rc = poll(&fds, 1, timeout * 1000);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (rc == 0) { /* timeout */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else if (rc < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (errno == EINTR || errno == EAGAIN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!fds.revents) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel bytes = write(fd, buf, len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (bytes < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (errno == EINTR) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else if (bytes == 0) { /* eof */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel len -= bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel buf += bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * recv_timeout() - receive data (in chunks if needed, each chunk in timeout
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * secs). In case the function is called from receiving thread, the function
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * cycles the poll() call in timeout seconds (waits for input from server).
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelrecv_timeout(int fd, char *buf, size_t len)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct pollfd fds;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int rc;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.fd = fd;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.events = POLLIN;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (len) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds.revents = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel rc = poll(&fds, 1, timeout * 1000);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (rc == 0) { /* timeout */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else if (rc < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (errno == EINTR || errno == EAGAIN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!fds.revents) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel bytes = read(fd, buf, len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (bytes < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (errno == EINTR) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else if (bytes == 0) { /* eof */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (-1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel len -= bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel buf += bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * read_fd() - reads data of length len from the given file descriptor fd to the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * buffer buf, in chunks if needed. Function returns B_FALSE on failure,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * otherwise B_TRUE. Function preserves errno, if it was set by the read(2).
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelread_fd(int fd, char *buf, size_t len)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#ifdef DEBUG
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel size_t len_o = len;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#endif
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (len) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel bytes = read(fd, buf, len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (bytes < 0) { /* err */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (errno == EINTR || errno == EAGAIN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_FALSE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else if (bytes == 0) { /* eof */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_FALSE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel len -= bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel buf += bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "read_fd: Read %d bytes.\n", len_o - len));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_TRUE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * write_fd() - writes buf of length len to the opened file descriptor fd, in
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * chunks if needed. The data from the pipe are processed in the receiving
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * thread. Function returns B_FALSE on failure, otherwise B_TRUE. Function
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * preserves errno, if it was set by the write(2).
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelwrite_fd(int fd, char *buf, size_t len)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#ifdef DEBUG
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel size_t len_o = len;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel#endif
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (len) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel bytes = write(fd, buf, len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (bytes == -1) { /* err */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (errno == EINTR || errno == EAGAIN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_FALSE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel len -= bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel buf += bytes;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "write_fd: Wrote %d bytes.\n", len_o - len));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_TRUE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Plug-in entry point
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * send_record() - send an audit record to a host opening a connection,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * negotiate version and establish context if necessary.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelsend_record_rc_t
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelsend_record(struct hostlist_s *hostlptr, const char *input, size_t in_len,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint64_t sequence, close_rsn_t *err_rsn)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_buffer_desc in_buf, out_buf;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel OM_uint32 maj_stat, min_stat;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int conf_state;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int rc;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_node_t *node_ptr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint64_t seq_n; /* sequence in the network byte order */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel boolean_t init_sock_poll = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * We need to grab the reset_lock here, to prevent eventual
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * unsynchronized cleanup calls within the reset routine (reset caused
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * by the receiving thread) and the initialization calls in the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * send_record() code path.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Check whether the socket was closed by the recv thread prior to call
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * send_record() and behave accordingly to the reason of the closure.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (recv_closure_rsn != RSN_UNDEFINED) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = recv_closure_rsn;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (recv_closure_rsn == RSN_GSS_CTX_EXP) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel rc = SEND_RECORD_RETRY;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel rc = SEND_RECORD_NEXT;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_closure_rsn = RSN_UNDEFINED;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (rc);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Send request to other then previously used host.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (current_host != hostlptr->host) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Set new host: %s\n", hostlptr->host->h_name));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (sockfd != -1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_RETRY);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel current_host = (struct hostent *)hostlptr->host;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel current_mech_oid = &hostlptr->mech;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel current_port = hostlptr->port;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* initiate the receiving thread */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_once(&recv_once_control, init_recv_record);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* create and connect() socket, negotiate the protocol version */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (sockfd == -1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* socket operations */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Socket creation and connect\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!sock_prepare(&sockfd, current_host, err_rsn)) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* we believe the err_rsn set by sock_prepare() */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_NEXT);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* protocol version negotiation */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Protocol version negotiation\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (prot_ver_negotiate() != 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "Protocol version negotiation failed\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_PROTOCOL_NEGOTIATE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_NEXT);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* let the socket be initiated for poll() */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel init_sock_poll = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!gss_ctx_initialized) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Establishing context..\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (establish_context() != 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_GSS_CTX_ESTABLISH;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_NEXT);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_ctx_initialized = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* let the recv thread poll() on the sockfd */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (init_sock_poll) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel init_sock_poll = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!init_poll(sockfd)) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_INIT_POLL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_RETRY);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* if not empty, retransmit contents of the transmission queue */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (flush_transq) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Retransmitting remaining (%ld) tokens from "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "the transmission queue\n", transq_hdr.count));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if ((rc = transq_retransmit()) == 2) { /* gss context exp */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_GSS_CTX_EXP;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_RETRY);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else if (rc == 1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_OTHER_ERR;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_NEXT);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel flush_transq = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Concatenate sequence number and the new record. Note, that the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * pointer to the chunk of memory allocated for the concatenated values
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * is later passed to the transq_enqueu() function which stores the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * pointer in the transmission queue; subsequently called
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * transq_dequeue() frees the allocated memory once the MIC is verified
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * by the recv_record() function.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * If we return earlier than the transq_enqueue() is called, it's
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * necessary to free the in_buf.value explicitly prior to return.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf.length = in_len + sizeof (sequence);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf.value = malloc(in_buf.length);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (in_buf.value == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Memory allocation failed"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Memory allocation failed: %s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_MEMORY_ALLOCATE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_FAIL);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel seq_n = htonll(sequence);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) memcpy(in_buf.value, &seq_n, sizeof (seq_n));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) memcpy((char *)in_buf.value + sizeof (seq_n), input, in_len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* wrap sequence number and the new record to the per-message token */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (gss_ctx != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat = gss_wrap(&min_stat, gss_ctx, 1, GSS_C_QOP_DEFAULT,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel &in_buf, &conf_state, &out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel switch (maj_stat) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_COMPLETE:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_CONTEXT_EXPIRED:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_GSS_CTX_EXP;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_RETRY);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel default:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_gss_err(gettext("gss_wrap message"), maj_stat,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel min_stat);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_OTHER_ERR;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_NEXT);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else { /* GSS context deleted by the recv thread */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_OTHER_ERR;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_NEXT);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* enqueue the to-be-sent token into transmission queue */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!transq_enqueue(&node_ptr, &in_buf, sequence)) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_buffer(&min_stat, &out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_OTHER_ERR;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_RETRY);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Token enqueued for later verification\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* send token */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (send_token(&sockfd, &out_buf) < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Token sending failed\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_buffer(&min_stat, &out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_dequeue(node_ptr);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *err_rsn = RSN_OTHER_ERR;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_NEXT);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Token sent (transq size = %ld)\n", transq_hdr.count));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_buffer(&min_stat, &out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (SEND_RECORD_SUCCESS);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * init_recv_record() - initialize the receiver thread
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelinit_recv_record()
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Initiating the recv thread\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_create(&recv_tid, NULL, (void *(*)(void *))recv_record,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void *)NULL);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * recv_record() - the receiver thread routine
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelrecv_record()
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel OM_uint32 maj_stat, min_stat;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_qop_t qop_state;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_buffer_desc in_buf = GSS_C_EMPTY_BUFFER;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_buffer_desc in_buf_mic = GSS_C_EMPTY_BUFFER;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_node_t *cur_node;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint64_t r_seq_num; /* received sequence number */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel boolean_t token_verified;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel boolean_t break_flag;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct pollfd fds[2];
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int fds_cnt;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct pollfd *pipe_fd = &fds[0];
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel struct pollfd *recv_fd = &fds[1];
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint32_t len;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int rc;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel pipe_msg_t np_data;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Receiver thread initiated\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Fill in the information in the vector of file descriptors passed
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * later on to the poll() function. In the initial state, there is only
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * one struct pollfd in the vector which contains file descriptor of the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * notification pipe - notify_pipe[1]. There might be up to two file
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * descriptors (struct pollfd) in the vector - notify_pipe[1] which
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * resides in the vector during the entire life of the receiving thread,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * and the own file descriptor from which we read data sent by the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * remote server application.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel pipe_fd->fd = notify_pipe[1];
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel pipe_fd->events = POLLIN;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_fd->fd = -1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_fd->events = POLLIN;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds_cnt = 1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * In the endless loop, try to grab some data from the socket or
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * notify_pipe[1].
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel for (;;) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel pipe_fd->revents = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_fd->revents = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_closure_rsn = RSN_UNDEFINED;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* block on poll, thus rc != 0 */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel rc = poll(fds, fds_cnt, -1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (rc == -1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (errno == EAGAIN || errno == EINTR) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* silently continue on EAGAIN || EINTR */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* log the debug message in any other case */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "poll() failed: %s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("poll() failed.\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Receive a message from the notification pipe. Information
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * from the notification pipe takes precedence over the received
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * data from the remote server application.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Notification pipe message format - message accepted
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * from the notify pipe comprises of two parts (int ||
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * boolean_t), where if the first part (sizeof (int)) equals
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * NP_CLOSE, then the second part (sizeof (boolean_t)) signals
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the necessity of broadcasting (DO_SYNC/DO_NOT_SYNC) the end
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * of the reset routine.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (pipe_fd->revents & POLLIN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "An event on notify pipe detected\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!read_fd(pipe_fd->fd, (char *)&np_data,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sizeof (np_data))) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Reading notify pipe failed: "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "%s\n", strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Reading notify pipe "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "failed"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel switch (np_data.sock_num) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case NP_EXIT: /* exit receiving thread */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel do_cleanup(&fds_cnt, recv_fd,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel np_data.sync);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel pthread_exit((void *)NULL);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case NP_CLOSE: /* close and remove recv_fd */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel do_reset(&fds_cnt, recv_fd,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel np_data.sync);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel default: /* add rc_pipe to the fds */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_fd->fd = np_data.sock_num;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel fds_cnt = 2;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* Receive a token from the remote server application */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (recv_fd->revents & POLLIN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "An event on fd detected\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!read_fd(recv_fd->fd, (char *)&len, sizeof (len))) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Token length recv failed\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_closure_rsn = RSN_TOK_RECV_FAILED;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_NOT_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel len = ntohl(len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* simple DOS prevention mechanism */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (len > MAX_TOK_LEN) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Indicated invalid token "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "length"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Indicated token length > %dB\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel MAX_TOK_LEN));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_closure_rsn = RSN_TOK_TOO_BIG;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_NOT_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf.value = (char *)malloc(len);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (in_buf.value == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Memory allocation failed"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Memory allocation failed: %s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_closure_rsn = RSN_MEMORY_ALLOCATE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_NOT_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!read_fd(recv_fd->fd, (char *)in_buf.value, len)) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Token value recv failed\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_closure_rsn = RSN_TOK_RECV_FAILED;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_NOT_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf.length = len;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Extract the sequence number and the MIC from
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the per-message token
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) memcpy(&r_seq_num, in_buf.value, sizeof (r_seq_num));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel r_seq_num = ntohll(r_seq_num);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf_mic.length = in_buf.length - sizeof (r_seq_num);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf_mic.value = (char *)in_buf.value + sizeof (r_seq_num);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * seq_num/r_seq_num - the sequence number does not need to
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * be unique in the transmission queue. Any token in the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * transmission queue with the same seq_num as the acknowledge
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * token received from the server is tested. This is due to the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * fact that the plugin cannot influence (in the current
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * implementation) sequence numbers generated by the kernel (we
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * are reusing record sequence numbers as a transmission queue
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * sequence numbers). The probability of having two or more
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * tokens in the transmission queue is low and at the same time
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the performance gain due to using sequence numbers is quite
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * high.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * In case a harder condition with regard to duplicate sequence
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * numbers in the transmission queue will be desired over time,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the break_flag behavior used below should be
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * removed/changed_accordingly.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break_flag = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel token_verified = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel cur_node = transq_hdr.head;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (cur_node != NULL && !break_flag) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (cur_node->seq_num != r_seq_num) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel cur_node = cur_node->next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel continue;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat = gss_verify_mic(&min_stat, gss_ctx,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel &(cur_node->seq_token), &in_buf_mic,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel &qop_state);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!GSS_ERROR(maj_stat)) { /* the success case */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel switch (maj_stat) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * All the GSS_S_OLD_TOKEN, GSS_S_UNSEQ_TOKEN,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * GSS_S_GAP_TOKEN are perceived as correct
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * behavior of the server side. The plugin
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * implementation is resistant to any of the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * above mention cases of returned status codes.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*FALLTHRU*/
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_OLD_TOKEN:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_UNSEQ_TOKEN:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_GAP_TOKEN:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_COMPLETE:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * remove the verified record/node from
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the transmission queue
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_dequeue(cur_node);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Recv thread verified "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "the token (transq len = %ld)\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_hdr.count));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel token_verified = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break_flag = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Both the default case as well as
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * GSS_S_DUPLICATE_TOKEN case should never
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * occur. It's been left here for the sake of
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * completeness.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * If any of the two cases occur, it is
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * subsequently cought because we don't set
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the token_verified flag.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*FALLTHRU*/
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_DUPLICATE_TOKEN:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel default:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break_flag = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } /* switch (maj_stat) */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else { /* the failure case */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_gss_err(
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gettext("signature verification of the "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "received token failed"),
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat, min_stat);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel switch (maj_stat) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_CONTEXT_EXPIRED:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* retransmission necessary */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_closure_rsn = RSN_GSS_CTX_EXP;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break_flag = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Recv thread detected "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "the GSS context expiration\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_BAD_SIG:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Bad signature "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "detected (seq_num = %lld)\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel cur_node->seq_num));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel cur_node = cur_node->next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel default:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_gss_err(
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gettext("signature verification"),
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat, min_stat);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break_flag = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } /* while */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (in_buf.value != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(in_buf.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf.value = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel in_buf.length = 0;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!token_verified) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Received, but unverifiable token is perceived as
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the protocol flow corruption with the penalty of
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * reinitializing the client/server connection.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "received unverifiable token\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("received unverifiable token\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (recv_closure_rsn == RSN_UNDEFINED) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_closure_rsn = RSN_TOK_UNVERIFIABLE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_transport(DO_CLOSE, DO_NOT_SYNC);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } /* for (;;) */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * init_poll() - initiates the polling in the receiving thread via sending the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * appropriate message over the notify pipe. Message format = (int ||
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * booleant_t), where the first part (sizeof (int)) contains the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * newly_opened/to_be_polled socket file descriptor. The contents of the second
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * part (sizeof (boolean_t)) of the message works only as a padding here and no
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * action (no recv/send thread synchronisation) is made in the receiving thread
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * based on its value.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelinit_poll(int fd)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel pipe_msg_t np_data;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int pipe_in = notify_pipe[0];
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel np_data.sock_num = fd;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel np_data.sync = B_FALSE; /* padding only */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (!write_fd(pipe_in, (char *)&np_data, sizeof (np_data))) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Cannot write to the notify pipe\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("writing to the notify pipe failed"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_FALSE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_TRUE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * reset_transport() - locked by the reset_lock initiates the reset of socket,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * GSS security context and (possibly) flags the transq for retransmission; for
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * more detailed information see do_reset(). The reset_transport() also allows
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the synchronization - waiting for the reset to be finished.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * do_close: DO_SYNC, DO_NOT_SYNC
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * sync_on_return: DO_EXIT (DO_NOT_CLOSE), DO_CLOSE (DO_NOT_EXIT)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelvoid
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelreset_transport(boolean_t do_close, boolean_t sync_on_return)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int pipe_in = notify_pipe[0];
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel pipe_msg_t np_data;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Check if the reset routine is in progress or whether it was already
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * executed by some other thread.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (reset_in_progress) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_in_progress = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel np_data.sock_num = (do_close ? NP_CLOSE : NP_EXIT);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel np_data.sync = sync_on_return;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) write_fd(pipe_in, (char *)&np_data, sizeof (np_data));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (sync_on_return) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (reset_in_progress) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_cond_wait(&reset_cv, &reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Wait for sync\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Synced\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * do_reset() - the own reseting routine called from the recv thread. If the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * synchronization was requested, signal the finish via conditional variable.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedeldo_reset(int *fds_cnt, struct pollfd *recv_fd, boolean_t do_signal)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* socket */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (sockfd == -1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "socket already closed\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel goto out;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } else {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) close(sockfd);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sockfd = -1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_fd->fd = -1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *fds_cnt = 1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* context */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (gss_ctx_initialized) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel delete_context();
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_ctx_initialized = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_ctx = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* mark transq to be flushed */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (transq_hdr.count > 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel flush_transq = B_TRUE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelout:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_in_progress = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (do_signal) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_cond_broadcast(&reset_cv);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * do_cleanup() - removes all the preallocated space by the plugin; prepares the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * plugin/application to be gracefully finished. Even thought the function
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * allows execution without signalling the successful finish, it's recommended
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * to use it (we usually want to wait for cleanup before exiting).
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedeldo_cleanup(int *fds_cnt, struct pollfd *recv_fd, boolean_t do_signal)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * socket
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * note: keeping locking for safety, thought it shouldn't be necessary
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * in current implementation - we get here only in case the sending code
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * path calls auditd_plugin_close() (thus no socket manipulation) and
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * the recv thread is doing the own socket closure.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (sockfd != -1) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Closing socket: %d\n", sockfd));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) close(sockfd);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel sockfd = -1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel recv_fd->fd = -1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *fds_cnt = 1;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&sock_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* context */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (gss_ctx_initialized) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Deleting context: "));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel delete_context();
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_ctx_initialized = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_ctx = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* transmission queue */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (transq_hdr.count > 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Deallocating the transmission queue "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "(len = %ld)\n", transq_hdr.count));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (transq_hdr.count > 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_dequeue(transq_hdr.head);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* notification pipe */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (notify_pipe_ready) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) close(notify_pipe[0]);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) close(notify_pipe[1]);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel notify_pipe_ready = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel reset_in_progress = B_FALSE;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (do_signal) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_cond_broadcast(&reset_cv);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&reset_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * transq_dequeue() - dequeues given node pointed by the node_ptr from the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * transmission queue. Transmission queue should be locked prior to use of this
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * function.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic void
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedeltransq_dequeue(transq_node_t *node_ptr)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (node_ptr == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "transq_dequeue(): called with NULL pointer\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(node_ptr->seq_token.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (node_ptr->prev != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel node_ptr->prev->next = node_ptr->next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (node_ptr->next != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel node_ptr->next->prev = node_ptr->prev;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* update the transq_hdr */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (node_ptr->next == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_hdr.end = node_ptr->prev;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (node_ptr->prev == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_hdr.head = node_ptr->next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_hdr.count--;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(node_ptr);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * transq_enqueue() - creates new node in (at the end of) the transmission
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * queue. in_ptoken_ptr is a pointer to the plain token in a form of
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * gss_buffer_desc. Function returns 0 on success and updates the *node_ptr to
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * point to a newly added transmission queue node. In case of any failure
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * function returns 1 and sets the *node_ptr to NULL.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Transmission queue should be locked prior to use of this function.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic boolean_t
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedeltransq_enqueue(transq_node_t **node_ptr, gss_buffer_t in_seqtoken_ptr,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel uint64_t sequence)
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *node_ptr = calloc(1, sizeof (transq_node_t));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (*node_ptr == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_err(gettext("Memory allocation failed"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Memory allocation failed: %s\n",
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel strerror(errno)));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel goto errout;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* value of the seq_token.value = (sequence number || plain token) */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (*node_ptr)->seq_num = sequence;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (*node_ptr)->seq_token.length = in_seqtoken_ptr->length;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (*node_ptr)->seq_token.value = in_seqtoken_ptr->value;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel /* update the transq_hdr */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (transq_hdr.head == NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_hdr.head = *node_ptr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (transq_hdr.end != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (transq_hdr.end)->next = *node_ptr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (*node_ptr)->prev = transq_hdr.end;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_hdr.end = *node_ptr;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_hdr.count++;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_TRUE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelerrout:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (*node_ptr != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if ((*node_ptr)->seq_token.value != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free((*node_ptr)->seq_token.value);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel free(*node_ptr);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel *node_ptr = NULL;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (B_FALSE);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel/*
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * transq_retransmit() - traverse the transmission queue and try to, 1 by 1,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * re-wrap the tokens with the recent context information and retransmit the
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * tokens from the transmission queue.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * Function returns 2 on GSS context expiration, 1 on any other error, 0 on
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel * successfully resent transmission queue.
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedelstatic int
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedeltransq_retransmit()
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel{
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel OM_uint32 maj_stat, min_stat;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel transq_node_t *cur_node = transq_hdr.head;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel gss_buffer_desc out_buf;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel int conf_state;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Retransmission of the remainder in the transqueue\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel while (cur_node != NULL) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_lock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel maj_stat = gss_wrap(&min_stat, gss_ctx, 1, GSS_C_QOP_DEFAULT,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel &(cur_node->seq_token), &conf_state, &out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&gss_ctx_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel switch (maj_stat) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_COMPLETE:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel break;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel case GSS_S_CONTEXT_EXPIRED:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Context expired.\n"));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_gss_err(gettext("gss_wrap message"), maj_stat,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel min_stat);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (2);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel default:
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel report_gss_err(gettext("gss_wrap message"), maj_stat,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel min_stat);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel DPRINT((dfile, "Sending transmission queue token (seq=%lld, "
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel "size=%d, transq len=%ld)\n", cur_node->seq_num,
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel out_buf.length, transq_hdr.count));
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel if (send_token(&sockfd, &out_buf) < 0) {
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_buffer(&min_stat, &out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (1);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel }
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) gss_release_buffer(&min_stat, &out_buf);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel cur_node = cur_node->next;
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel (void) pthread_mutex_unlock(&transq_lock);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel } /* while */
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel return (0);
657a8c206b913d1ee578fd725f0b25eca5b77253Jan Friedel}