Subject: bin/2771: lpd no network listen patch (third try)
To: None <gnats-bugs@gnats.netbsd.org>
From: None <daw@panix.com>
List: netbsd-bugs
Date: 09/20/1996 16:26:36
>Number:         2771
>Category:       bin
>Synopsis:       patch no add no network listen option to lpd
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Sep 20 13:35:01 1996
>Last-Modified:
>Originator:     Nathaniel D. Daw
>Organization:
Piermont Information Systems
>Release:        netbsd current as of today (1.2 beta)
>Environment:
System: NetBSD daw.dialup.access.net 1.2_BETA NetBSD 1.2_BETA (NAT2) #21: Fri Aug 2 10:04:22 EDT 1996 nat@dialup227.cc.columbia.edu:/usr/src/sys/arch/i386/compile/NAT2 i386


>Description:
	this is my third try at sending this pr -- I believe its
	predecessors didn't get through, but if they did I apologize.

	lpd is a little fast and free with accepting connections over
	the network. It uses insecure host-based authentication, and,
	in many environments (such as my own) it is only used for
	local spooling anyway, making its network receive feature at
	best superfluous and at worst a potential security hole. I
	attach a simple patch to add a -s option (modeled after the
	recently committed syslogd -s option) that causes lpd to run
	as usual but only accept jobs over unix domain sockets, not
	over the network. This option is appropriate for those who
	require local print spooling but wish to limit their network
	exposure.

>How-To-Repeat:
	run lpd and do a netstat -a -finet and you will see that it is
	listening on the network.
>Fix:
	The following patch is trivial (about six lines of code)
	... the reason it is so long is merely that a block of code
	was reindented. lpd already had the capacity of running
	without a network socket (used just in case the call to socket()
	failed); all that is necessary is to recognize the option and
	force the behavior.

	these patches are for usr.sbin/lpr/lpd.c and usr.sbin/lpr/lpd.8




*** lpd.c.orig  Thu Apr 25 07:39:54 1996
--- lpd.c       Thu Sep  5 00:29:51 1996
***************
*** 98,103 ****
--- 98,104 ----
  #include "extern.h"
  
  int   lflag;                          /* log requests flag */
+ int   sflag;                          /* secure (no inet) flag */
  int   from_remote;                    /* from remote socket */
  
  static void       reapchild __P((int));
***************
*** 122,127 ****
--- 123,129 ----
        euid = geteuid();       /* these shouldn't be different */
        uid = getuid();
        options = 0;
+       sflag = 0;
        gethostname(host, sizeof(host));
        name = argv[0];
  
***************
*** 135,140 ****
--- 137,145 ----
                        case 'l':
                                lflag++;
                                break;
+                       case 's':
+                               sflag++;
+                               break;
                        }
        }
  
***************
*** 200,228 ****
        FD_ZERO(&defreadfds);
        FD_SET(funix, &defreadfds);
        listen(funix, 5);
!       finet = socket(AF_INET, SOCK_STREAM, 0);
!       if (finet >= 0) {
!               struct servent *sp;
! 
!               if (options & SO_DEBUG)
!                       if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) {
!                               syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
                                mcleanup(0);
                        }
!               sp = getservbyname("printer", "tcp");
!               if (sp == NULL) {
!                       syslog(LOG_ERR, "printer/tcp: unknown service");
!                       mcleanup(0);
!               }
!               memset(&sin, 0, sizeof(sin));
!               sin.sin_family = AF_INET;
!               sin.sin_port = sp->s_port;
!               if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
!                       syslog(LOG_ERR, "bind: %m");
!                       mcleanup(0);
                }
-               FD_SET(finet, &defreadfds);
-               listen(finet, 5);
        }
        /*
         * Main loop: accept, do a request, continue.
--- 205,239 ----
        FD_ZERO(&defreadfds);
        FD_SET(funix, &defreadfds);
        listen(funix, 5);
!       if (!sflag) {
!               finet = socket(AF_INET, SOCK_STREAM, 0);
!               if (finet >= 0) {
!                       struct servent *sp;
! 
!                       if (options & SO_DEBUG)
!                               if (setsockopt(finet, SOL_SOCKET,
!                                              SO_DEBUG, 0, 0) < 0) {
!                                       syslog(LOG_ERR,
!                                              "setsockopt (SO_DEBUG): %m");
!                                       mcleanup(0);
!                               }
!                       sp = getservbyname("printer", "tcp");
!                       if (sp == NULL) {
!                               syslog(LOG_ERR,
!                                      "printer/tcp: unknown service");
                                mcleanup(0);
                        }
!                       memset(&sin, 0, sizeof(sin));
!                       sin.sin_family = AF_INET;
!                       sin.sin_port = sp->s_port;
!                       if (bind(finet, (struct sockaddr *)&sin,
!                                sizeof(sin)) < 0) {
!                               syslog(LOG_ERR, "bind: %m");
!                               mcleanup(0);
!                       }
!                       FD_SET(finet, &defreadfds);
!                       listen(finet, 5);
                }
        }
        /*
         * Main loop: accept, do a request, continue.
***************
*** 261,267 ****
                        signal(SIGQUIT, SIG_IGN);
                        signal(SIGTERM, SIG_IGN);
                        (void) close(funix);
!                       (void) close(finet);
                        dup2(s, 1);
                        (void) close(s);
                        if (domain == AF_INET) {
--- 272,279 ----
                        signal(SIGQUIT, SIG_IGN);
                        signal(SIGTERM, SIG_IGN);
                        (void) close(funix);
!                       if (!sflag)
!                               (void) close(finet);
                        dup2(s, 1);
                        (void) close(s);
                        if (domain == AF_INET) {





*** lpd.8.orig  Mon Dec 11 15:57:19 1995
--- lpd.8       Thu Sep  5 00:15:48 1996
***************
*** 68,73 ****
--- 68,84 ----
  .Nm lpd
  to log valid requests received from the network. This can be useful
  for debugging purposes.
+ .It Fl s
+ The
+ .Fl s
+ flag selects ``secure'' mode, in which 
+ .Nm lpd
+ does not listen on a TCP socket but only takes commands from a UNIX
+ domain socket.  This is valuable when the machine on which
+ .Nm lpd 
+ runs is subject to attack over the network and it is desired that the
+ machine be protected from attempts to remotely fill spools and similar
+ attacks.
  .It Ar "port#"
  The Internet port number used to rendezvous
  with other processes is normally obtained with
>Audit-Trail:
>Unformatted: