TR: 3.8.1p1 option "permitopennet" added

Bucaille, Lionel lionel.bucaille at caissedesdepots.fr
Wed Feb 23 00:54:35 EST 2005


Patch is below :

diff -nru openssh-3.8.1p1/auth-options.c openssh-3.8.1p1-devs//auth-options.c
--- openssh-3.8.1p1/auth-options.c	Tue Jun  3 02:25:48 2003
+++ openssh-3.8.1p1-devs//auth-options.c	Mon Feb 21 16:56:49 2005
@@ -265,6 +265,81 @@
 			xfree(patterns);
 			goto next_option;
 		}
+
+/* e.g: permitopenned="158.156.0.0/255.255.255.0:25[-1024]"
+ * note that part between [] is optionnal for 1 port specification
+ */
+		cp = "permitopennet=\"";
+		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+			char	netblock[256], netmask[256],
+				sporta[6], sportb[6];
+			u_short porta, portb;
+
+			char *patterns = xmalloc(strlen(opts) + 1);
+			netblock[0] = netmask[0] = sporta[0] = sportb[0] = 0;
+			porta = portb = 0;
+
+			opts += strlen(cp);
+			i = 0;
+			while (*opts) {
+				if (*opts == '"')
+					break;
+				if (*opts == '\\' && opts[1] == '"') {
+					opts += 2;
+					patterns[i++] = '"';
+					continue;
+				}
+				patterns[i++] = *opts++;
+			}
+			if (!*opts) {
+				debug("%.100s, line %lu: missing end quote",
+				    file, linenum);
+				auth_debug_add("%.100s, line %lu: missing end quote",
+				    file, linenum);
+				xfree(patterns);
+				goto bad_option;
+			}
+			patterns[i] = 0;
+			opts++;
+
+			if (sscanf(patterns, "%255[^:/]/%255[^:]:%5[0-9]-%5[0-9]", netblock, netmask , sporta, sportb) != 4 &&
+				sscanf(patterns, "%255[^:/]/%255[^:]:%5[0-9]", netblock, netmask , sporta) != 3	) {
+				debug("%.100s, line %lu: Bad permitopennet specification "
+				    "<%.100s>", file, linenum, patterns);
+				auth_debug_add("%.100s, line %lu: "
+				    "Bad permitopennet specification", file, linenum);
+				xfree(patterns);
+				goto bad_option;
+			}
+
+			if ((porta = a2port(sporta)) == 0) {
+				debug("%.100s, line %lu: Bad permitopen port <%.100s>",
+				    file, linenum, sporta);
+				auth_debug_add("%.100s, line %lu: "
+				    "Bad permitopennet port a", file, linenum);
+				xfree(patterns);
+				goto bad_option;
+			}
+
+			if ( *sportb && ((portb = a2port(sportb)) == 0)) {
+				debug("%.100s, line %lu: Bad permitopen port <%.100s>",
+				    file, linenum, sportb);
+				auth_debug_add("%.100s, line %lu: "
+				    "Bad permitopennet port b", file, linenum);
+				xfree(patterns);
+				goto bad_option;
+			}
+
+			auth_debug_add("%.100s, line %lu: "
+			    "permitopennet specification : %s/%s : %d %d", file, linenum,
+				netblock, netmask, porta, portb);
+
+			if (options.allow_tcp_forwarding)
+				channel_add_permittednet_opens(netblock, netmask, porta, portb);
+
+			xfree(patterns);
+			goto next_option;
+		}
 next_option:
 		/*
 		 * Skip the comma, and move to the next option
diff -nru openssh-3.8.1p1/channels.c openssh-3.8.1p1-devs//channels.c
--- openssh-3.8.1p1/channels.c	Wed Jan 21 01:02:09 2004
+++ openssh-3.8.1p1-devs//channels.c	Tue Feb 22 10:36:55 2005
@@ -55,6 +55,7 @@
 #include "authfd.h"
 #include "pathnames.h"
 #include "bufaux.h"
+#include "auth.h"
 
 /* -- channel core */
 
@@ -91,11 +92,27 @@
 	u_short listen_port;		/* Remote side should listen port number. */
 } ForwardPermission;
 
+/* That structure _only_ stocks authorized permitopennet demands
+ * A ForwardPermission entry is added at each incoming connexion
+ * in "permitted_opens" array
+ */
+typedef struct {
+	struct in_addr * netblock_to_connect;
+	struct in_addr * netmask_to_connect;
+	u_short porta_to_connect;
+	u_short portb_to_connect;
+} ForwardNetPermission;
+
 /* List of all permitted host/port pairs to connect. */
 static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
 
+/* List of all permitted netblock/portblock pairs to connect. */
+static ForwardNetPermission permittednet_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
+
 /* Number of permitted host/port pairs in the array. */
 static int num_permitted_opens = 0;
+/* Number of permitted netblock/portblock pairs in the array. */
+static int num_permittednet_opens = 0;
 /*
  * If this is true, all opens are permitted.  This is the case on the server
  * on which we have to trust the client anyway, and the user could do
@@ -2110,7 +2127,7 @@
 		originator_string = xstrdup("unknown (remote did not supply name)");
 	}
 	packet_check_eom();
-	sock = channel_connect_to(host, host_port);
+	sock = channel_connect_to(host, host_port, ctxt);
 	if (sock != -1) {
 		c = channel_new("connected socket",
 		    SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,
@@ -2349,7 +2366,7 @@
 void
 channel_permit_all_opens(void)
 {
-	if (num_permitted_opens == 0)
+	if (num_permitted_opens == 0 && num_permittednet_opens == 0)
 		all_opens_permitted = 1;
 }
 
@@ -2368,6 +2385,35 @@
 }
 
 void
+channel_add_permittednet_opens(char *netblock, char *netmask, int porta, int portb)
+{
+	/* XXX this does not make any sens */
+	if (num_permittednet_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
+		fatal("channel_request_remote_forwarding: too many forwards");
+
+	if (portb)	debug("allow port forwarding to netblock %s/%s port %d-%d", netblock,netmask, porta, portb);
+	else		debug("allow port forwarding to netblock %s/%s port %d", netblock,netmask, porta);
+
+	/* Continue if conversion fails - checked while parsing option ...
+	   Note that "permitted_opens" array int not affected */
+
+	permittednet_opens[num_permittednet_opens].netblock_to_connect = (struct in_addr *)malloc(sizeof(struct in_addr));
+	permittednet_opens[num_permittednet_opens].netmask_to_connect = (struct in_addr *)malloc(sizeof(struct in_addr));
+
+	if (! inet_aton(netblock, permittednet_opens[num_permittednet_opens].netblock_to_connect)) 
+		error("channel_add_permittednet_opens: pbm while converting netblock [%s]", netblock);
+
+	if (! inet_aton(netmask, permittednet_opens[num_permittednet_opens].netmask_to_connect)) 
+		error("channel_add_permittednet_opens: pbm while converting netmask [%s]", netmask);
+
+	permittednet_opens[num_permittednet_opens].porta_to_connect = porta;
+	permittednet_opens[num_permittednet_opens].portb_to_connect = portb;
+	num_permittednet_opens++;
+
+	all_opens_permitted = 0;
+}
+
+void
 channel_clear_permitted_opens(void)
 {
 	int i;
@@ -2374,6 +2420,10 @@
 
 	for (i = 0; i < num_permitted_opens; i++)
 		xfree(permitted_opens[i].host_to_connect);
+	for (i = 0; i < num_permittednet_opens; i++) {
+		xfree(permittednet_opens[i].netblock_to_connect);
+		xfree(permittednet_opens[i].netmask_to_connect);
+	}
 	num_permitted_opens = 0;
 
 }
@@ -2452,23 +2502,52 @@
 
 /* Check if connecting to that port is permitted and connect. */
 int
-channel_connect_to(const char *host, u_short port)
+channel_connect_to(const char *host, u_short port, void * a_ctxt)
 {
 	int i, permit;
+	struct in_addr *host_dst;
+	Authctxt * ctxt = a_ctxt;
+	struct passwd *pw = ctxt->pw;
 
 	permit = all_opens_permitted;
 	if (!permit) {
-		for (i = 0; i < num_permitted_opens; i++)
+		/* check against "permitopen" option */
+		for (i = 0; i < num_permitted_opens && !permit; i++)
 			if (permitted_opens[i].port_to_connect == port &&
 			    strcmp(permitted_opens[i].host_to_connect, host) == 0)
 				permit = 1;
-
 	}
 	if (!permit) {
-		logit("Received request to connect to host %.100s port %d, "
-		    "but the request was denied.", host, port);
+		/* last check : against "permitopennet" option */
+		host_dst = (struct in_addr *)malloc(sizeof(struct in_addr));
+		if (inet_aton(host, host_dst)) {
+			for (i = 0 ; i < num_permittednet_opens && !permit ; i++) {
+				if ((host_dst->s_addr & permittednet_opens[i].netmask_to_connect->s_addr) ==
+					permittednet_opens[i].netblock_to_connect->s_addr) {
+					if ((permittednet_opens[i].porta_to_connect && permittednet_opens[i].portb_to_connect &&
+						 port >= permittednet_opens[i].porta_to_connect &&
+						 port <= permittednet_opens[i].portb_to_connect) ||
+						(!permittednet_opens[i].portb_to_connect &&
+						 permittednet_opens[i].porta_to_connect == port)) {
+						channel_add_permitted_opens(host,port);
+						permit = 1;
+					}
+				}
+			}
+			xfree(host_dst);
+		}
+	}
+	if (!permit) {
+		if (pw && ctxt->valid) 
+			logit("%s (uid:%d) requests to connect to host %.100s port %d, "
+			    "but the request was denied.",ctxt->pw->pw_name,ctxt->pw->pw_uid, host, port);
 		return -1;
 	}
+
+	if (pw && ctxt->valid) 
+		logit("%s (uid:%d) requests to connect to host %.100s port %d, "
+		    "and the request was accepted.",ctxt->pw->pw_name,ctxt->pw->pw_uid, host, port);
+
 	return connect_to(host, port);
 }
 
diff -nru openssh-3.8.1p1/channels.h openssh-3.8.1p1-devs//channels.h
--- openssh-3.8.1p1/channels.h	Thu Oct  2 08:17:00 2003
+++ openssh-3.8.1p1-devs//channels.h	Mon Feb 21 17:09:18 2005
@@ -195,9 +195,10 @@
 void	 channel_set_af(int af);
 void     channel_permit_all_opens(void);
 void	 channel_add_permitted_opens(char *, int);
+void	 channel_add_permittednet_opens(char *, char *, int, int);
 void	 channel_clear_permitted_opens(void);
 void     channel_input_port_forward_request(int, int);
-int	 channel_connect_to(const char *, u_short);
+int	 channel_connect_to(const char *, u_short, void *);
 int	 channel_connect_by_listen_address(u_short);
 void	 channel_request_remote_forwarding(u_short, const char *, u_short);
 int	 channel_setup_local_fwd_listener(u_short, const char *, u_short, int);
diff -nru openssh-3.8.1p1/serverloop.c openssh-3.8.1p1-devs//serverloop.c
--- openssh-3.8.1p1/serverloop.c	Wed Jan 21 01:02:50 2004
+++ openssh-3.8.1p1-devs//serverloop.c	Mon Feb 21 11:33:13 2005
@@ -867,7 +867,7 @@
 	   originator, originator_port, target, target_port);
 
 	/* XXX check permission */
-	sock = channel_connect_to(target, target_port);
+	sock = channel_connect_to(target, target_port, the_authctxt);
 	xfree(target);
 	xfree(originator);
 	if (sock < 0)

-----Message d'origine-----
De : Bucaille, Lionel 
Envoyé : mardi 22 février 2005 11:21
À : 'openssh-unix-dev at mindrot.org'
Objet : 3.8.1p1 option "permitopennet" added

Hello,

I send you a small patch about a "new" option called "permitopennet". The behaviour is the same as "permitopen" except the accept/deny statement is based on this syntax : "netblock/netmask:porta[-portb]".

Moreover, I also added some useful log lines : the uid is logged while doing port forwarding.

Sample conf : 

permitopennet="158.156.156.128/255.255.255.128:25-1024" ssh-dss AAAAB3NzaC1kc3MAAACAbAehy7ov+HQvaSalGdJaNA3YAunrEIT3sqNqqs8CVIAgv2p ...

Logs :

eym59365 (uid:620) requests to connect to host 158.156.156.70 port 80, but the request was denied.

eym59365 (uid:620) requests to connect to host 158.156.156.251 port 80, and the request was accepted.

Waiting for your remarks or comments.

Lionel.



Ce message et toutes les pièces jointes (ci-après le « message ») sont confidentiels et établis à l'intention exclusive de ses destinataires. Toute utilisation de ce message non conforme à sa destination, toute diffusion ou toute publication, totale ou partielle, est interdite, sauf autorisation expresse. Si vous recevez ce message par erreur, merci de le détruire sans en conserver de copie et d'en avertir immédiatement l'expéditeur. Internet ne permettant pas de garantir l'intégrité de ce message, la Caisse des dépôts et consignations décline toute responsabilité au titre de ce message s'il a été modifié, altéré, déformé ou falsifié.

This message and any attachments (the « message ») are confidential and intended solely for the addresses. Any use not in accord with its purpose, any dissemination or disclosure, either whole or partial, is prohibited without formal approval. If you receive this message in error, please delete it without storing any evidence and immediately notify the sender. Internet can not guarantee the integrity of this message, neither shall Caisse des depots et consignations be liable for the message if modified, altered, changed or falsified.




More information about the openssh-unix-dev mailing list