+/*
+ * Copyright (c) 2016, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
#include <gsscon.h>
#include <gssapi.h>
#include <fcntl.h>
#include <tr_debug.h>
#include <trp_internal.h>
+#include <tr_socket.h>
/* Threading note: mutex lock is only used for protecting get_status() and set_status().
* If needed, locking for other operations (notably adding/removing connections) must be managed
gss_buffer_desc peer_display_name={0,NULL};
int local=0;
- tr_debug("gssctx = %p", trp_connection_get_gssctx(conn));
- tr_debug("*gssctx = %p", *trp_connection_get_gssctx(conn));
major_status=gss_inquire_context(&minor_status,
*trp_connection_get_gssctx(conn),
&source_name,
if (conn->peer==NULL)
return TRP_ERROR;
-
+
+ tr_debug("trp_connection_set_peer: set peer for %p to %.*s (%p).", conn, conn->peer->len, conn->peer->buf, conn->peer);
return TRP_SUCCESS;
}
TRP_CONNECTION_STATUS trp_connection_get_status(TRP_CONNECTION *conn)
{
- TRP_CONNECTION_STATUS status;
+ TRP_CONNECTION_STATUS status=TRP_CONNECTION_UNKNOWN;
trp_connection_lock(conn);
status=conn->status;
trp_connection_unlock(conn);
static void trp_connection_set_status(TRP_CONNECTION *conn, TRP_CONNECTION_STATUS status)
{
+ TRP_CONNECTION_STATUS old_status=TRP_CONNECTION_UNKNOWN;
trp_connection_lock(conn);
+ old_status=conn->status;
conn->status=status;
trp_connection_unlock(conn);
+ if ((status!=old_status) && (conn->status_change_cb!=NULL))
+ conn->status_change_cb(conn, conn->status_change_cookie);
}
pthread_t *trp_connection_get_thread(TRP_CONNECTION *conn)
static int trp_connection_destructor(void *object)
{
TRP_CONNECTION *conn=talloc_get_type_abort(object, TRP_CONNECTION); /* aborts on wrong type */
- if ((trp_connection_get_status(conn)!=TRP_CONNECTION_DOWN)
+ if ((trp_connection_get_status(conn)!=TRP_CONNECTION_CLOSED)
&& (trp_connection_get_fd(conn)!=-1))
close(trp_connection_get_fd(conn));
if (conn->peer!=NULL)
trp_connection_set_fd(new_conn, -1);
trp_connection_set_gssname(new_conn, NULL);
trp_connection_mutex_init(new_conn);
- trp_connection_set_status(new_conn, TRP_CONNECTION_DOWN);
new_conn->peer=NULL; /* no true set function for this */
+ new_conn->status_change_cb=NULL;
+ new_conn->status_change_cookie=NULL;
+ new_conn->status=TRP_CONNECTION_CLOSED;
+
thread=talloc(new_conn, pthread_t);
- gssctx=talloc(new_conn, gss_ctx_id_t);
- if (gssctx==NULL) {
+ if (thread==NULL) {
talloc_free(new_conn);
return NULL;
}
- trp_connection_set_gssctx(new_conn, gssctx);
- if (thread==NULL) {
+ trp_connection_set_thread(new_conn, thread);
+
+ gssctx=talloc(new_conn, gss_ctx_id_t);
+ if (gssctx==NULL) {
talloc_free(new_conn);
return NULL;
}
- trp_connection_set_thread(new_conn, thread);
+ trp_connection_set_gssctx(new_conn, gssctx);
talloc_set_destructor((void *)new_conn, trp_connection_destructor);
}
return new_conn;
void trp_connection_close(TRP_CONNECTION *conn)
{
- close(trp_connection_get_fd(conn));
+ if ((conn->status!=TRP_CONNECTION_DOWN) && (conn->fd>0))
+ close(trp_connection_get_fd(conn));
trp_connection_set_fd(conn, -1);
trp_connection_set_status(conn, TRP_CONNECTION_DOWN);
}
gss_buffer_desc nameBuffer = {0, NULL};
gss_ctx_id_t *gssctx=trp_connection_get_gssctx(conn);
- /* TODO: shouldn't really peek into TR_NAME... */
nameBuffer.length = trp_connection_get_gssname(conn)->len;
- nameBuffer.value = trp_connection_get_gssname(conn)->buf;
+ nameBuffer.value = tr_name_strdup(trp_connection_get_gssname(conn));
tr_debug("trp_connection_auth: beginning passive authentication");
+ if (trp_connection_get_status(conn)!=TRP_CONNECTION_AUTHORIZING)
+ tr_warning("trp_connection_auth: warning: connection was not in TRP_CONNECTION_AUTHORIZING state.");
+
rc = gsscon_passive_authenticate(trp_connection_get_fd(conn), nameBuffer, gssctx, auth_callback, callback_data);
gss_release_buffer(NULL, &nameBuffer);
if (rc!=0) {
tr_debug("trp_connection_auth: Error from gsscon_passive_authenticate(), rc = 0x%08X.", rc);
+ trp_connection_set_status(conn, TRP_CONNECTION_DOWN);
return -1;
}
if (rc = gsscon_authorize(*gssctx, &auth, &autherr)) {
tr_debug("trp_connection_auth: Error from gsscon_authorize, rc = %d, autherr = %d.",
rc, autherr);
+ trp_connection_set_status(conn, TRP_CONNECTION_DOWN);
return -1;
}
int conn_fd=-1;
TRP_CONNECTION *conn=NULL;
- conn_fd = accept(listen, NULL, NULL);
+ conn_fd = tr_sock_accept(listen);
if (0 > conn_fd) {
- tr_notice("trp_connection_accept: accept() returned error.");
+ tr_notice("trp_connection_accept: Error accepting connection.");
return NULL;
}
conn=trp_connection_new(mem_ctx);
trp_connection_set_fd(conn, conn_fd);
trp_connection_set_gssname(conn, gssname);
+ trp_connection_set_status(conn, TRP_CONNECTION_AUTHORIZING);
return conn;
}
&fd,
trp_connection_get_gssctx(conn));
if (err) {
- tr_debug("trp_connection_initiate: connection failed.");
- talloc_free(conn);
+ tr_err("trp_connection_initiate: connection failed.");
return TRP_ERROR;
} else {
tr_debug("trp_connection_initiate: connected.");
trp_connection_set_fd(conn, fd);
- trp_connection_set_peer(conn);
+ if (trp_connection_set_peer(conn)!=TRP_SUCCESS) {
+ tr_err("trp_connection_initiate: error setting peer gssname.");
+ trp_connection_close(conn);
+ return TRP_ERROR;
+ }
trp_connection_set_status(conn, TRP_CONNECTION_UP);
return TRP_SUCCESS;
}