proposed linc API change ...



Hi Guys,

	I hope we can fast track this, since ultimately it's a really simple
flag addition. The rational for this is that ORBit has always used
'security by obscurity' ie. generating a very random object key and then
hoping that no-one can guess it [ much like X cookies, but more random
]. Sadly Solaris has no good way to produce safe random numbers,
consequently we have taken a drastic performance hit - test measurements
show this to be a factor of ~1000 over the new method we propose [ for
object instantiation ].

	So - in order to use this far faster, simpler approach - we need to be
able to detect whether an incoming connection comes from a local machine
- and is thus de-facto secure, this is the case for Unix domain sockets,
and also loopback TCP/IP connections.

	So - we want to add this flag and some internal gubbins to make it
work; this would only affect ORBit2 and linc and have no external API
impact, whilst providing a massive Solaris/AIX/HPUX performance boost.

	 The only substantial change is:

Index: include/linc/linc-types.h
===================================================================
RCS file: /cvs/gnome/linc/include/linc/linc-types.h,v
retrieving revision 1.23
diff -u -p -u -r1.23 linc-types.h
--- include/linc/linc-types.h	2001/12/31 10:29:10	1.23
+++ include/linc/linc-types.h	2002/01/16 13:24:27
@@ -21,7 +21,8 @@ G_BEGIN_DECLS
 typedef enum {
 	LINC_CONNECTION_SSL          = 1 << 0,
 	LINC_CONNECTION_NONBLOCKING  = 1 << 1,
-	LINC_CONNECTION_BLOCK_SIGNAL = 1 << 2
+	LINC_CONNECTION_BLOCK_SIGNAL = 1 << 2,
+	LINC_CONNECTION_LOCAL_ONLY   = 1 << 3
 } LINCConnectionOptions;
 
 typedef struct _LincWatch        LincWatch;

	But; we also add a virtual method to:

Index: include/linc/linc-protocol.h
===================================================================
RCS file: /cvs/gnome/linc/include/linc/linc-protocol.h,v
retrieving revision 1.13
diff -u -p -u -r1.13 linc-protocol.h
--- include/linc/linc-protocol.h	2001/12/20 09:35:18	1.13
+++ include/linc/linc-protocol.h	2002/01/16 13:24:27
@@ -41,6 +41,10 @@ typedef gboolean (*LINCProtocolGetSockIn
 						 gchar                 **hostname,
 						 gchar                 **service);
 
+typedef gboolean (*LINCProtocolIsLocal)         (const LINCProtocolInfo *proto,
+						 const struct sockaddr  *sockaddr,
+						 socklen_t               saddr_len);
+
 struct _LINCProtocolInfo {
 	const char                 *name;
 	int                         family;
@@ -52,6 +56,7 @@ struct _LINCProtocolInfo {
 	LINCProtocolDestroyFunc     destroy;
 	LINCProtocolGetSockAddrFunc get_sockaddr;
 	LINCProtocolGetSockInfoFunc get_sockinfo;
+	LINCProtocolIsLocal         is_local;
 };
 
 LINCProtocolInfo * const linc_protocol_find     (const char *name);


	Essentially for internal use.

	The rest of the patch follows,

	Thanks,

		Michael.

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/linc/ChangeLog,v
retrieving revision 1.99
diff -u -p -u -r1.99 ChangeLog
--- ChangeLog	2002/01/10 19:05:53	1.99
+++ ChangeLog	2002/01/16 13:24:27
@@ -1,3 +1,21 @@
+2002-01-16  Michael Meeks  <michael@ximian.com>
+
+	* src/linc-protocols.c (get_local_hostname): impl. so
+	we can call it lots.
+	(linc_protocol_get_sockinfo_ipv46): upd.
+	(linc_protocol_get_sockinfo_unix): upd.
+	(linc_protocol_is_local): impl.
+	(linc_protocol_unix_is_local): impl.
+	(linc_protocol_is_local_ipv46): impl.
+
+	* src/linc-server.c (linc_server_accept_connection):
+	check for remote connections - if in local only mode,
+	using new is_local API.
+
+	* include/linc/linc-protocol.h: add is_local.
+
+	* include/linc/linc-types.h: add local only flag.
+
 2002-10-10  Roland Juelich <rj@atecom.com>
 
 	* src/linc-source.c (linc_io_add_watch): create our own
Index: src/linc-private.h
===================================================================
RCS file: /cvs/gnome/linc/src/linc-private.h,v
retrieving revision 1.13
diff -u -p -u -r1.13 linc-private.h
--- src/linc-private.h	2002/01/10 19:05:56	1.13
+++ src/linc-private.h	2002/01/16 13:24:27
@@ -76,8 +76,11 @@ struct sockaddr *linc_protocol_get_socka
 gboolean         linc_protocol_get_sockinfo (const LINCProtocolInfo *proto,
 					     const struct sockaddr  *saddr,
 					     gchar                 **hostname,
-
 					     gchar                 **service);
+
+gboolean         linc_protocol_is_local     (const LINCProtocolInfo  *proto,
+					     const struct sockaddr   *saddr,
+					     socklen_t                saddr_len);
 
 LincWatch       *linc_io_add_watch_fd       (int                     fd,
 					     GIOCondition            condition,
Index: src/linc-protocols.c
===================================================================
RCS file: /cvs/gnome/linc/src/linc-protocols.c,v
retrieving revision 1.34
diff -u -p -u -r1.34 linc-protocols.c
--- src/linc-protocols.c	2001/12/14 10:55:59	1.34
+++ src/linc-protocols.c	2002/01/16 13:24:27
@@ -197,6 +197,61 @@ linc_set_tmpdir (const char *dir)
 #define LINC_RESOLV_CLEAR_IPV6
 #endif
 
+#if defined(AF_INET) || defined(AF_INET6) || defined (AF_UNIX)
+static const char *
+get_local_hostname (void)
+{
+	static char local_host[NI_MAXHOST] = { 0 };
+
+	if (local_host [0])
+		return local_host;
+
+	if (gethostname (local_host, NI_MAXHOST) == -1)
+		return NULL;
+
+	return local_host;
+}
+
+static gboolean
+linc_protocol_is_local_ipv46 (const LINCProtocolInfo *proto,
+			      const struct sockaddr   *saddr,
+			      socklen_t                saddr_len)
+{
+	int i;
+	static int warned = 0;
+	static struct hostent *local_hostent = NULL;
+	
+	if (!local_hostent)
+		local_hostent = gethostbyname (get_local_hostname ());
+
+	if (!local_hostent) {
+		if (!warned++)
+			g_warning ("can't gethostbyname on '%s'",
+				   get_local_hostname ());
+		return FALSE;
+	}
+
+	if (local_hostent->h_addrtype != saddr->sa_family) {
+		if (!warned++)
+			g_warning ("FIXME: can't compare different family "
+				   "address types for locality");
+		return FALSE;
+	}
+
+	g_warning ("Compare vs %d matches len %d",
+		   local_hostent->h_length, saddr_len);
+
+	for (i = 0; i < local_hostent->h_length; i++) {
+		if (!memcmp (local_hostent->h_addr_list [i],
+			     saddr->sa_data, saddr_len))
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+#endif
+
 /*
  * linc_protocol_get_sockaddr_ipv4:
  * @proto: the #LINCProtocolInfo structure for the IPv4 protocol.
@@ -458,11 +513,10 @@ linc_protocol_get_sockinfo_ipv46 (struct
 				  gchar          **hostname,
 				  char           **portnum)
 {
-
 	if (!host) {
-		char local_host[MAXHOSTNAMELEN];
+		const char *local_host;
 
-		if (gethostname (local_host, MAXHOSTNAMELEN) == -1)
+		if (!(local_host = get_local_hostname ()))
 			return FALSE;
 
 		host = gethostbyname (local_host);
@@ -598,12 +652,12 @@ linc_protocol_get_sockinfo_unix (const L
 	g_assert (proto && saddr && saddr->sa_family == AF_UNIX);
 
 	if (hostname) {
-		gchar hname [NI_MAXHOST];
+		const char *local_host;
 
-		if (gethostname (hname, NI_MAXHOST) == -1)
+		if (!(local_host = get_local_hostname ()))
 			return FALSE;
 
-		*hostname = g_strdup (hname);
+		*hostname = g_strdup (local_host);
 	}
 
 	if (sock_path)
@@ -665,6 +719,27 @@ linc_protocol_get_sockinfo (const LINCPr
 	return FALSE;
 }
 
+/**
+ * linc_protocol_is_local:
+ * @proto: the protocol
+ * @saddr: the socket address of a connecting client.
+ * 
+ *   This method determines if the client is from the same
+ * machine or not - per protocol.
+ * 
+ * Return value: TRUE if the connection is local, else FALSE
+ **/
+gboolean
+linc_protocol_is_local (const LINCProtocolInfo  *proto,
+			const struct sockaddr   *saddr,
+			socklen_t                saddr_len)
+{
+	if (proto && proto->is_local)
+		return proto->is_local (proto, saddr, saddr_len);
+
+	return FALSE;
+}
+
 /*
  * af_unix_destroy:
  * @fd: file descriptor of the socket.
@@ -681,6 +756,14 @@ linc_protocol_unix_destroy (int         
 {
 	unlink (pathname);
 }
+
+static gboolean
+linc_protocol_unix_is_local (const LINCProtocolInfo *proto,
+			     const struct sockaddr   *saddr,
+			     socklen_t                saddr_len)
+{
+	return TRUE;
+}
 #endif /* AF_UNIX */
 
 /*
@@ -724,7 +807,8 @@ static LINCProtocolInfo static_linc_prot
 	linc_protocol_tcp_setup, 	/* setup */
 	NULL, 				/* destroy */
 	linc_protocol_get_sockaddr_ipv4,/* get_sockaddr */
-	linc_protocol_get_sockinfo_ipv4 /* get_sockinfo */
+	linc_protocol_get_sockinfo_ipv4,/* get_sockinfo */
+	linc_protocol_is_local_ipv46    /* is_local */
 	},
 #endif
 #if defined(AF_INET6)
@@ -737,7 +821,8 @@ static LINCProtocolInfo static_linc_prot
 	linc_protocol_tcp_setup, 	/* setup */
 	NULL, 				/* destroy */
 	linc_protocol_get_sockaddr_ipv6,/* get_sockaddr */
-	linc_protocol_get_sockinfo_ipv6	/* get_sockinfo */
+	linc_protocol_get_sockinfo_ipv6,/* get_sockinfo */
+	linc_protocol_is_local_ipv46    /* is_local */
 	},
 #endif
 #ifdef AF_UNIX
@@ -750,7 +835,8 @@ static LINCProtocolInfo static_linc_prot
 	NULL,  						/* setup */
 	linc_protocol_unix_destroy,  			/* destroy */
 	linc_protocol_get_sockaddr_unix, 		/* get_sockaddr */
-	linc_protocol_get_sockinfo_unix 		/* get_sockinfo */
+	linc_protocol_get_sockinfo_unix, 		/* get_sockinfo */
+	linc_protocol_unix_is_local                     /* is_local */
 	},
 #endif
 #ifdef AF_IRDA
@@ -763,7 +849,8 @@ static LINCProtocolInfo static_linc_prot
 	NULL, 					/* setup */
 	NULL, 					/* destroy */
 	linc_protocol_get_sockaddr_irda, 	/* get_sockaddr */
-	linc_protocol_get_sockinfo_irda 	/* get_sockinfo */
+	linc_protocol_get_sockinfo_irda, 	/* get_sockinfo */
+	NULL                                    /* is_local */
 	},
 #endif
 	{ NULL /* name */ }
Index: src/linc-server.c
===================================================================
RCS file: /cvs/gnome/linc/src/linc-server.c,v
retrieving revision 1.45
diff -u -p -u -r1.45 linc-server.c
--- src/linc-server.c	2002/01/04 22:50:58	1.45
+++ src/linc-server.c	2002/01/16 13:24:27
@@ -151,6 +151,12 @@ linc_server_accept_connection (LINCServe
 		return FALSE; /* error */
 	}
 
+	if (server->create_options & LINC_CONNECTION_LOCAL_ONLY &&
+	    !linc_protocol_is_local (server->proto, saddr, addrlen)) {
+		close (fd);
+		return FALSE;
+	}
+
 	if (server->create_options & LINC_CONNECTION_NONBLOCKING)
 		if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) {
 			d_printf ("failed to set O_NONBLOCK on %d", fd);


-- 
 mmeeks@gnu.org  <><, Pseudo Engineer, itinerant idiot




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]