Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

816 Communicating with a Network Printer Chapter 21


122 FD_ZERO(&rendezvous);
123 maxfd=-1;
124 for (aip = ailist; aip != NULL; aip = aip->ai_next) {
125 if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr,
126 aip->ai_addrlen, QLEN)) >= 0) {
127 FD_SET(sockfd, &rendezvous);
128 if (sockfd > maxfd)
129 maxfd=sockfd;
130 }
131 }
132 if (maxfd == -1)
133 log_quit("service not enabled");
134 pwdp=getpwnam(LPNAME);
135 if (pwdp == NULL)
136 log_sys("can’t find user %s", LPNAME);
137 if (pwdp->pw_uid == 0)
138 log_quit("user %s is privileged", LPNAME);
139 if (setgid(pwdp->pw_gid) < 0 || setuid(pwdp->pw_uid) < 0)
140 log_sys("can’t change IDs to user %s", LPNAME);
141 init_request();
142 init_printer();

[122 – 131] We clear therendezvous fd_setvariable that we will use withselectto
wait for client connect requests. Weinitialize the maximum file descriptor to
−1 so that the first file descriptor we allocate is sure to be greater than
maxfd.For each network address on which we need to provide service, we
callinitserver(from Figure16.22) to allocate and initialize a socket. If
initserversucceeds, we add the file descriptor to thefd_set; if it is
greater than the maximum, we setmaxfdequal to the socket file descriptor.
[132 – 133] Ifmaxfdis still−1after stepping through the list ofaddrinfostructures,
we can’t enable the printer spooling service, so we log a message and exit.
[134 – 140] Our daemon needs superuser privileges to bind a socket to a reserved port
number.Now that this is done, we can lower its privileges by changing its
user and group IDs to the ones associated with theLPNAMEaccount. We
follow the principles of least privilege to avoid exposing the system to any
potential vulnerabilities in the daemon. We callgetpwnam to find the
passwordentry for the daemon. If no such user account exists, or if it exists
with the same user ID as the superuser, we log an error message and exit.
Otherwise, we change both the real and effective IDs by callingsetgidand
setuid.Toavoid exposing our system, we choose to provide no service at
all if we can’t reduce our privileges.
[141 – 142] We callinit_requestto initialize the job requests and ensurethat only
one copy of the daemon is running, and we callinit_printerto initialize
the printer information (we’ll see both of these functions shortly).
Free download pdf