#include <gsscon.h>
+#include <gssapi.h>
#include <fcntl.h>
#include <talloc.h>
#include <unistd.h>
#include <tr_debug.h>
#include <trp_internal.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
+ * by whomever is holding on to the connection list. */
+
+int trp_connection_lock(TRP_CONNECTION *conn)
+{
+ return pthread_mutex_lock(&(conn->mutex));
+}
+
+int trp_connection_unlock(TRP_CONNECTION *conn)
+{
+ return pthread_mutex_unlock(&(conn->mutex));
+}
+
int trp_connection_get_fd(TRP_CONNECTION *conn)
{
return conn->fd;
conn->fd=fd;
}
+/* we use the gss name of the peer to identify it */
+static TRP_RC trp_connection_set_peer(TRP_CONNECTION *conn)
+{
+ OM_uint32 major_status=0;
+ OM_uint32 minor_status=0;
+ gss_name_t source_name=GSS_C_NO_NAME;
+ gss_name_t target_name=GSS_C_NO_NAME;
+ 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,
+ &target_name,
+ NULL,
+ NULL,
+ NULL,
+ &local,
+ NULL);
+
+ if (major_status != GSS_S_COMPLETE) {
+ tr_err("trp_connection_set_peer: unable to identify GSS peer.");
+ if (source_name!=GSS_C_NO_NAME)
+ gss_release_name(&minor_status, &source_name);
+ if (target_name!=GSS_C_NO_NAME)
+ gss_release_name(&minor_status, &target_name);
+ return TRP_ERROR;
+ }
+
+ if (local) {
+ /* we are the source, peer is the target */
+ major_status=gss_display_name(&minor_status, target_name, &peer_display_name, NULL);
+ } else {
+ /* we are the target, peer is the source */
+ major_status=gss_display_name(&minor_status, source_name, &peer_display_name, NULL);
+ }
+ gss_release_name(&minor_status, &source_name);
+ gss_release_name(&minor_status, &target_name);
+
+ conn->peer=tr_new_name(peer_display_name.value);
+ if (conn->peer==NULL)
+ tr_err("trp_connection_set_peer: unable to allocate peer name.");
+ else {
+ if (conn->peer->len != peer_display_name.length) {
+ tr_err("trp_connection_set_peer: error converting GSS display name to TR_NAME.");
+ tr_free_name(conn->peer);
+ conn->peer=NULL;
+ }
+ }
+ gss_release_buffer(&minor_status, &peer_display_name);
+
+ if (conn->peer==NULL)
+ return TRP_ERROR;
+
+ return TRP_SUCCESS;
+}
+
+TR_NAME *trp_connection_get_peer(TRP_CONNECTION *conn)
+{
+ return conn->peer;
+}
+
TR_NAME *trp_connection_get_gssname(TRP_CONNECTION *conn)
{
return conn->gssname;
TRP_CONNECTION_STATUS trp_connection_get_status(TRP_CONNECTION *conn)
{
TRP_CONNECTION_STATUS status;
- pthread_mutex_lock(&(conn->status_mutex));
+ trp_connection_lock(conn);
status=conn->status;
- pthread_mutex_unlock(&(conn->status_mutex));
+ trp_connection_unlock(conn);
return status;
}
static void trp_connection_set_status(TRP_CONNECTION *conn, TRP_CONNECTION_STATUS status)
{
- pthread_mutex_lock(&(conn->status_mutex));
+ trp_connection_lock(conn);
conn->status=status;
- pthread_mutex_unlock(&(conn->status_mutex));
+ trp_connection_unlock(conn);
}
pthread_t *trp_connection_get_thread(TRP_CONNECTION *conn)
conn->next=next;
}
-/* Ok to call more than once; guarantees connection no longer in the list.
+/* Ok to call more than once; guarantees connection no longer in the list. Does not free removed element.
* Returns handle to new list, you must replace your old handle on the list with this. */
TRP_CONNECTION *trp_connection_remove(TRP_CONNECTION *conn, TRP_CONNECTION *remove)
{
/* first element is a special case */
if (cur==remove) {
conn=trp_connection_get_next(cur); /* advance list head */
- trp_connection_free(cur);
} else {
/* it was not the first element */
last=cur;
while (cur!=NULL) {
if (cur==remove) {
trp_connection_set_next(last, trp_connection_get_next(cur));
- trp_connection_free(cur);
break;
}
last=cur;
static void trp_connection_mutex_init(TRP_CONNECTION *conn)
{
- pthread_mutex_init(&(conn->status_mutex), NULL);
+ pthread_mutex_init(&(conn->mutex), NULL);
}
/* talloc destructor for a connection: ensures connection is closed, memory freed */
if ((trp_connection_get_status(conn)!=TRP_CONNECTION_DOWN)
&& (trp_connection_get_fd(conn)!=-1))
close(trp_connection_get_fd(conn));
+ if (conn->peer!=NULL)
+ tr_free_name(conn->peer);
if (conn->gssname!=NULL)
tr_free_name(conn->gssname);
return 0;
if (new_conn != NULL) {
trp_connection_set_next(new_conn, NULL);
trp_connection_set_fd(new_conn, -1);
- trp_connection_set_gssctx(new_conn, NULL);
+ trp_connection_set_gssname(new_conn, NULL);
trp_connection_mutex_init(new_conn);
trp_connection_set_status(new_conn, TRP_CONNECTION_DOWN);
thread=talloc(new_conn, pthread_t);
return -1;
}
+ trp_connection_set_peer(conn);
+ trp_connection_set_status(conn, TRP_CONNECTION_UP);
+
if (auth)
tr_debug("trp_connection_auth: Connection authenticated, fd = %d.", trp_connection_get_fd(conn));
else
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_UP);
return conn;
}
+/* Initiate connection */
+TRP_RC trp_connection_initiate(TRP_CONNECTION *conn, char *server, unsigned int port)
+{
+ int err = 0;
+ int fd=-1;
+ unsigned int use_port=0;
+
+ if (0 == port)
+ use_port = TRP_PORT;
+ else
+ use_port = port;
+
+ if (conn==NULL) {
+ tr_err("trp_connection_initiate: null TRP_CONNECTION");
+ return TRP_BADARG;
+ }
+
+ tr_debug("trp_connection_initiate: opening GSS connection to %s:%d",
+ server,
+ use_port);
+ err = gsscon_connect(server,
+ use_port,
+ "trustrouter",
+ &fd,
+ trp_connection_get_gssctx(conn));
+ tr_debug("trp_connection_initiate: connected");
+
+ if (err) {
+ talloc_free(conn);
+ return TRP_ERROR;
+ } else {
+ trp_connection_set_fd(conn, fd);
+ trp_connection_set_peer(conn);
+ trp_connection_set_status(conn, TRP_CONNECTION_UP);
+ return TRP_SUCCESS;
+ }
+}