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.