Sisyphus repositório
Última atualização: 1 outubro 2023 | SRPMs: 18631 | Visitas: 37868920
en ru br
ALT Linux repositórios
S:4.4.3.P1-alt1
5.0: 3.0.7-alt1
4.1: 3.0.6-alt2.M41.1
4.0: 3.0.6-alt1
3.0: 3.0.2-alt1

Group :: Sistema/Servidores
RPM: dhcp

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs e FR  Repocop 

Patch: dhcp-3.0.7-alt1.patch
Download


 Makefile               |   14 +++---
 Makefile.conf          |    2 +-
 README                 |   16 ++++++
 client/Makefile.dist   |    2 +-
 client/dhclient.c      |   10 +++-
 client/scripts/linux   |   51 +++++++++++++-------
 common/Makefile.dist   |    4 +-
 common/bpf.c           |    2 +-
 common/comapi.c        |    2 +-
 common/dns.c           |    4 +-
 common/droproot.c      |  121 ++++++++++++++++++++++++++++++++++++++++++++++++
 common/inet.c          |    2 +-
 common/lpf.c           |    1 +
 common/packet.c        |    1 +
 common/parse.c         |   31 ++++++++++--
 common/print.c         |   19 ++++----
 common/tree.c          |   18 ++++----
 common/upf.c           |    2 +-
 dhcpctl/dhcpctl.3      |    5 +-
 dst/Makefile.dist      |    4 +-
 dst/dst_api.c          |   10 ++++-
 dst/dst_support.c      |    4 +-
 dst/hmac_link.c        |    2 +-
 includes/cf/linux.h    |    4 +-
 includes/dhcpd.h       |    3 +
 minires/res_mkupdate.c |    8 ++--
 minires/res_query.c    |    2 +-
 omapip/errwarn.c       |   82 ++++++++++++++++++++------------
 omapip/iscprint.c      |   18 ++++----
 omapip/result.c        |    2 +-
 relay/Makefile.dist    |    2 +-
 relay/dhcrelay.8       |   22 ++++++++-
 relay/dhcrelay.c       |   43 ++++++++++++-----
 server/Makefile.dist   |    2 +-
 server/confpars.c      |    7 ++-
 server/db.c            |    4 +-
 server/ddns.c          |    2 +-
 server/dhcp.c          |    4 +-
 server/dhcpd.8         |   19 ++++++++
 server/dhcpd.c         |   67 ++++++++++++++++++--------
 server/dhcpd.conf.5    |   21 ++++-----
 server/failover.c      |   12 ++--
 server/omapi.c         |    2 +-
 43 files changed, 474 insertions(+), 179 deletions(-)
diff --git a/Makefile b/Makefile
index 78867f8..3bbc8b8 100644
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ all:
 	 if [ ! -d work.$$sysname ]; then \
 	   echo No build directory for $$sysname - please run ./configure.; \
 	else \
-	   (cd work.$$sysname; make all); \
+	   $(MAKE) -C work.$$sysname all; \
 	fi
 
 install:
@@ -41,7 +41,7 @@ install:
 	 if [ ! -d work.$$sysname ]; then \
 	   echo No build directory for $$sysname - please run ./configure.; \
 	else \
-	   (cd work.$$sysname; make install); \
+	   $(MAKE) -C work.$$sysname install; \
 	fi
 
 depend:
@@ -49,7 +49,7 @@ depend:
 	 if [ ! -d work.$$sysname ]; then \
 	   echo No build directory for $$sysname - please run ./configure.; \
 	else \
-	   (cd work.$$sysname; make depend); \
+	   $(MAKE) -C work.$$sysname depend; \
 	fi
 
 clean:
@@ -57,7 +57,7 @@ clean:
 	 if [ ! -d work.$$sysname ]; then \
 	   echo No build directory for $$sysname - please run ./configure.; \
 	else \
-	   (cd work.$$sysname; make clean); \
+	   $(MAKE) -C work.$$sysname clean; \
 	fi
 
 realclean:
@@ -65,7 +65,7 @@ realclean:
 	 if [ ! -d work.$$sysname ]; then \
 	   echo No build directory for $$sysname - please run ./configure.; \
 	else \
-	   (cd work.$$sysname; make realclean); \
+	   $(MAKE) -C work.$$sysname realclean; \
 	fi
 
 distclean:
@@ -73,7 +73,7 @@ distclean:
 	 if [ ! -d work.$$sysname ]; then \
 	   echo No build directory for $$sysname - please run ./configure.; \
 	else \
-	   (cd work.$$sysname; make distclean); \
+	   $(MAKE) -C work.$$sysname distclean; \
 	fi
 
 links:
@@ -81,6 +81,6 @@ links:
 	 if [ ! -d work.$$sysname ]; then \
 	   echo No build directory for $$sysname - please run ./configure.; \
 	else \
-	   (cd work.$$sysname; make links); \
+	   $(MAKE) -C work.$$sysname links; \
 	fi
 
diff --git a/Makefile.conf b/Makefile.conf
index acdfb58..c6cb3ea 100644
--- a/Makefile.conf
+++ b/Makefile.conf
@@ -50,7 +50,7 @@ DEBUG = -g
 #WARNERR = -Werror
 RANLIB = ranlib
 MKDEP = mkdep
-CLIENT_PATH = '"PATH=/usr/ucb:/usr/bin:/usr/sbin:/bin:/sbin"'
+CLIENT_PATH = '"PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin"'
 
 BINDLIB = ../minires/libres.a
 BINDINC =
diff --git a/README b/README
index 2aa92bd..4747c9d 100644
--- a/README
+++ b/README
@@ -1,6 +1,7 @@
 	       Internet Systems Consortium DHCP Distribution
 	                      Version 3.0.7
 		               May 14, 2008
+                    (with modifications for ALT Linux)
 
 			       README FILE
 
@@ -458,6 +459,21 @@ for AIX would be welcome.
 
 			       SUPPORT
 
+Please note the following before requesting help:
+
+This software is a part of the Internet Software Consortium's DHCP suite
+with modifications for ALT Linux.
+The ISC folks quite reasonably require that you do not bother them with
+questions on software that includes third-party modifications and might
+not be based off their latest code.  Hence, please direct any questions
+to the community@ mailing list instead; the subscription instructions
+are given at http://lists.altlinux.org/mailman/listinfo/community .
+
+The rest of this section describes the ISC's original guidelines on
+requesting support and/or reporting bugs.  These will only apply to
+you if you reproduce your problem on the latest version of ISC's DHCP
+suite as available from ftp://ftp.isc.org .
+
 The Internet Systems Consortium DHCP server is developed and distributed
 by ISC in the public trust, thanks to the generous donations of its
 sponsors.  ISC now also offers commercial quality support contracts for
diff --git a/client/Makefile.dist b/client/Makefile.dist
index c123963..5ee6e71 100644
--- a/client/Makefile.dist
+++ b/client/Makefile.dist
@@ -128,6 +128,6 @@ dhclient.leases.cat5:	dhclient.leases.man5
 
 
 dhclient:	$(OBJS) $(DHCPLIB)
-	$(CC) $(LFLAGS) -o $(PROG) $(OBJS) $(DHCPLIB) $(LIBS)
+	$(CC) -pie $(LFLAGS) -o $(PROG) $(OBJS) $(DHCPLIB) $(LIBS)
 
 # Dependencies (semi-automatically-generated)
diff --git a/client/dhclient.c b/client/dhclient.c
index 921dade..c9998fe 100644
--- a/client/dhclient.c
+++ b/client/dhclient.c
@@ -1092,7 +1092,8 @@ void dhcpoffer (packet)
 		return;
 	}
 
-	sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
+	snprintf (obuf, sizeof(obuf),
+		"%s from %s", name, piaddr (packet -> client_addr));
 
 
 	/* If this lease doesn't supply the minimum required parameters,
@@ -2648,7 +2649,7 @@ void client_envadd (struct client_state *client,
 {
 	char spbuf [1024];
 	char *s;
-	unsigned len, i;
+	int len;
 	struct string_list *val;
 	va_list list;
 
@@ -2656,6 +2657,11 @@ void client_envadd (struct client_state *client,
 	len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
 	va_end (list);
 
+/* Handle truncation on glibc 2.0.x or possible unexpected errors on others;
+ * avoid integer overflow in the addition below. */
+	if (len < 0 || len > 0x3fffffff)
+		return;
+
 	val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
 		       len + sizeof *val, MDL);
 	if (!val)
diff --git a/client/scripts/linux b/client/scripts/linux
index 31ddd2f..26a2d2e 100755
--- a/client/scripts/linux
+++ b/client/scripts/linux
@@ -1,8 +1,6 @@
 #!/bin/bash
 # dhclient-script for Linux. Dan Halbert, March, 1997.
 # Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
-# No guarantees about this. I'm a novice at the details of Linux
-# networking.
 
 # Notes:
 
@@ -19,13 +17,13 @@
 # address if it is not supplied. This might be much more easily done
 # by the dhclient C code, and passed on.
 
-# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious
-# of the $1 in its args.
-
 make_resolv_conf() {
-  if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then
-    echo search $new_domain_name >/etc/resolv.conf
+  if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
+    echo '; generated by /sbin/dhclient-script' > /etc/resolv.conf
     chmod 644 /etc/resolv.conf
+    if [ -n "$new_domain_name" ]; then
+       echo search $new_domain_name >> /etc/resolv.conf
+    fi
     for nameserver in $new_domain_name_servers; do
       echo nameserver $nameserver >>/etc/resolv.conf
     done
@@ -53,6 +51,22 @@ if [ -f /etc/dhclient-enter-hooks ]; then
   fi
 fi
 
+cd /etc/sysconfig/network-scripts
+. /etc/sysconfig/network-scripts/network-functions
+. /etc/rc.d/init.d/functions
+
+[ -f ../network ] && . ../network
+[ -f ../networking/network ] && . ../networking/network
+
+CONFIG="ifcfg-$interface"
+
+[ -f "${CONFIG}" ] || {
+    echo $"$0: configuration for $interface not found." >&2
+    exit_with_hooks 1
+}
+
+source_config
+
 release=`uname -r`
 release=`expr $release : '\(.*\)\..*'`
 relminor=`echo $release |sed -e 's/[0-9]*\.\([0-9][0-9]*\)\(\..*\)*$/\1/'`
@@ -106,13 +120,10 @@ fi
   
 if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
    [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
-  current_hostname=`hostname`
-  if [ x$current_hostname = x ] || \
-     [ x$current_hostname = x$old_host_name ]; then
-    if [ x$current_hostname = x ] || \
-       [ x$new_host_name != x$old_host_name ]; then
-      hostname $new_host_name
-    fi
+  if [ -n "$new_host_name" ] && need_hostname; then
+       if need_hostname || [ "`hostname`" != "$new_host_name" ]; then
+               hostname $new_host_name
+       fi
   fi
     
   if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
@@ -146,7 +157,10 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
     ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
     route add -host $alias_ip_address $interface:0
   fi
-  make_resolv_conf
+  if [ "${PEERDNS}" != "no" ]; then
+    make_resolv_conf
+  fi
+
   exit_with_hooks 0
 fi
 
@@ -174,8 +188,7 @@ if [ x$reason = xTIMEOUT ]; then
   ifconfig $interface inet $new_ip_address $new_subnet_arg \
 					$new_broadcast_arg
   set $new_routers
-  ############## what is -w in ping?
-  if ping -q -c 1 $1; then
+  if ping -q -c 1 -w 10 $1; then
     if [ x$new_ip_address != x$alias_ip_address ] && \
 			[ x$alias_ip_address != x ]; then
       ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
@@ -188,7 +201,9 @@ if [ x$reason = xTIMEOUT ]; then
     for router in $new_routers; do
       route add default gw $router
     done
-    make_resolv_conf
+    if [ "${PEERDNS}" != "no" ]; then
+      make_resolv_conf
+    fi
     exit_with_hooks 0
   fi
   ifconfig $interface inet 0 down
diff --git a/common/Makefile.dist b/common/Makefile.dist
index 5e40a0f..cd2defe 100644
--- a/common/Makefile.dist
+++ b/common/Makefile.dist
@@ -25,11 +25,11 @@ SEDMANPAGES = dhcp-options.man5 dhcp-eval.man5
 SRC    = raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \
 	 lpf.c dlpi.c packet.c tr.c ethernet.c memory.c print.c options.c \
 	 inet.c tree.c tables.c alloc.c fddi.c ctrace.c dns.c resolv.c \
-	 execute.c discover.c comapi.c
+	 execute.c discover.c comapi.c droproot.c
 OBJ    = raw.o parse.o nit.o icmp.o dispatch.o conflex.o upf.o bpf.o socket.o \
 	 lpf.o dlpi.o packet.o tr.o ethernet.o memory.o print.o options.o \
 	 inet.o tree.o tables.o alloc.o fddi.o ctrace.o dns.o resolv.o \
-	 execute.o discover.o comapi.o
+	 execute.o discover.o comapi.o droproot.o
 MAN    = dhcp-options.5 dhcp-eval.5
 
 INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
diff --git a/common/bpf.c b/common/bpf.c
index 6a387d9..6f50f11 100644
--- a/common/bpf.c
+++ b/common/bpf.c
@@ -91,7 +91,7 @@ int if_register_bpf (info)
 	/* Open a BPF device */
 	for (b = 0; 1; b++) {
 		/* %Audit% 31 bytes max. %2004.06.17,Safe% */
-		sprintf(filename, BPF_FORMAT, b);
+		snprintf(filename, sizeof(filename), BPF_FORMAT, b);
 		sock = open (filename, O_RDWR, 0);
 		if (sock < 0) {
 			if (errno == EBUSY) {
diff --git a/common/comapi.c b/common/comapi.c
index 1307968..c58ffde 100644
--- a/common/comapi.c
+++ b/common/comapi.c
@@ -288,7 +288,7 @@ isc_result_t dhcp_group_signal_handler (omapi_object_t *h,
 		/* Group objects always have to have names. */
 		if (!group -> name) {
 			char hnbuf [64];
-			sprintf (hnbuf, "ng%08lx%08lx",
+			snprintf (hnbuf, sizeof(hnbuf), "ng%08lx%08lx",
 				 (unsigned long)cur_time,
 				 (unsigned long)group);
 			group -> name = dmalloc (strlen (hnbuf) + 1, MDL);
diff --git a/common/dns.c b/common/dns.c
index 03a76a8..c489201 100644
--- a/common/dns.c
+++ b/common/dns.c
@@ -533,7 +533,7 @@ isc_result_t ddns_update_a (struct data_string *ddns_fwd_name,
 		return ISC_R_INVALIDARG;
 
 	/* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */
-	sprintf (ddns_address, "%u.%u.%u.%u",
+	snprintf (ddns_address, sizeof(ddns_address), "%u.%u.%u.%u",
 		  ddns_addr.iabuf[0], ddns_addr.iabuf[1],
 		  ddns_addr.iabuf[2], ddns_addr.iabuf[3]);
 
@@ -794,7 +794,7 @@ isc_result_t ddns_remove_a (struct data_string *ddns_fwd_name,
 		return ISC_R_INVALIDARG;
 
 	/* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */
-	sprintf (ddns_address, "%u.%u.%u.%u",
+	snprintf (ddns_address, sizeof(ddns_address), "%u.%u.%u.%u",
 		  ddns_addr.iabuf[0], ddns_addr.iabuf[1],
 		  ddns_addr.iabuf[2], ddns_addr.iabuf[3]);
 
diff --git a/common/droproot.c b/common/droproot.c
new file mode 100644
index 0000000..36c42dd
--- /dev/null
+++ b/common/droproot.c
@@ -0,0 +1,121 @@
+#include "dhcpd.h"
+#include <unistd.h>
+#include <time.h>
+#include <pwd.h>
+#define group real_group
+#include <grp.h>
+#undef group
+
+#include <sys/capability.h>
+#include <sys/prctl.h>
+
+static int minimized = 0;
+
+void
+dhcpd_priv_minimize(const char *user, const char *dir)
+{
+	struct passwd *pw;
+	uid_t   uid;
+	gid_t   gid;
+
+	if (!*user)
+		return;
+
+	if (!(pw = getpwnam(user)))
+		log_fatal("Failed to lower privileges: getpwnam: %s", user);
+
+	uid = pw->pw_uid;
+	gid = pw->pw_gid;
+
+	tzset();
+
+	if (initgroups(user, gid))
+		log_fatal("Failed to lower privileges: initgroups: %s/%u: %m",
+			  user, (unsigned) gid);
+
+	endpwent();
+
+	if (*dir && (chdir(dir) || chroot(".")))
+		log_fatal("Failed to lower privileges: chroot: %s: %m", dir);
+
+	if (setgid(gid))
+		log_fatal("Failed to lower privileges: setgid: %s/%u: %m",
+			  user, (unsigned) gid);
+
+	if (prctl(PR_SET_KEEPCAPS, 1))
+		log_fatal("Failed to lower privileges: prctl: %m");
+
+	if (setreuid(uid, uid))
+		log_fatal("Failed to lower privileges: setreuid: %s/%u: %m",
+			  user, (unsigned) uid);
+
+	cap_t   caps = cap_from_text("cap_net_bind_service=ep");
+
+	if (!caps)
+		log_fatal("Failed to lower privileges: cap_from_text: %m");
+
+	if (cap_set_proc(caps) < 0)
+		log_fatal("Failed to lower privileges: cap_set_proc: %m");
+
+	cap_free(caps);
+	minimized = 1;
+}
+
+static void
+drop_minimized(void)
+{
+	cap_t   caps = cap_from_text("all-ep");
+	if (!caps)
+		log_fatal("Failed to lower privileges: cap_from_text: %m");
+
+	if (cap_set_proc(caps) < 0)
+		log_fatal("Failed to lower privileges: cap_set_proc: %m");
+
+	cap_free(caps);
+}
+
+static void
+drop_all(const char *user, const char *dir)
+{
+	struct passwd *pw;
+	uid_t   uid;
+	gid_t   gid;
+
+	if (!(pw = getpwnam(user)))
+		log_fatal("Failed to lower privileges: getpwnam: %s", user);
+
+	uid = pw->pw_uid;
+	gid = pw->pw_gid;
+
+	tzset();
+
+	if (initgroups(user, gid))
+		log_fatal("Failed to lower privileges: initgroups: %s/%u: %m",
+			  user, (unsigned) gid);
+
+	endpwent();
+
+	if (*dir && (chdir(dir) || chroot(".")))
+		log_fatal("Failed to lower privileges: chroot: %s: %m", dir);
+
+	if (setgid(gid))
+		log_fatal("Failed to lower privileges: setgid: %s/%u: %m",
+			  user, (unsigned) gid);
+
+	if (setuid(uid))
+		log_fatal("Failed to lower privileges: setuid: %s/%u: %m",
+			  user, (unsigned) uid);
+}
+
+
+void
+dhcpd_priv_drop(const char *user, const char *dir)
+{
+	if (!*user)
+		return;
+
+	if (minimized)
+		drop_minimized();
+	else
+		drop_all(user, dir);
+}
diff --git a/common/inet.c b/common/inet.c
index 3c86e5a..488b15a 100644
--- a/common/inet.c
+++ b/common/inet.c
@@ -188,7 +188,7 @@ int addr_eq (addr1, addr2)
 char *piaddr (addr)
 	struct iaddr addr;
 {
-	static char pbuf [4 * 16];
+	static char pbuf [4 * sizeof(addr.iabuf)];
 	char *s = pbuf;
 	int i;
 
diff --git a/common/lpf.c b/common/lpf.c
index dc7f3f2..3f19b43 100644
--- a/common/lpf.c
+++ b/common/lpf.c
@@ -253,6 +253,7 @@ static void lpf_tr_filter_setup (info)
 
 	/* Set up the bpf filter program structure.    This is defined in
 	   bpf.c */
+	memset(&p, '\0', sizeof p);
 	p.len = dhcp_bpf_tr_filter_len;
 	p.filter = dhcp_bpf_tr_filter;
 
diff --git a/common/packet.c b/common/packet.c
index 668106c..fdd569f 100644
--- a/common/packet.c
+++ b/common/packet.c
@@ -141,6 +141,7 @@ void assemble_udp_ip_header (interface, buf, bufix,
 	struct udphdr udp;
 
 	/* Fill out the IP header */
+	memset( &ip, '\0', sizeof ip);
 	IP_V_SET (&ip, 4);
 	IP_HL_SET (&ip, 20);
 	ip.ip_tos = IPTOS_LOWDELAY;
diff --git a/common/parse.c b/common/parse.c
index 9efd146..f4d6c46 100644
--- a/common/parse.c
+++ b/common/parse.c
@@ -4798,6 +4798,25 @@ int parse_X (cfile, buf, max)
 	return len;
 }
 
+static ssize_t
+write_loop (int fd, const char *buffer, size_t count)
+{
+	ssize_t offset = 0;
+
+	while (count > 0)
+	{
+		ssize_t block = write (fd, &buffer[offset], count);
+
+		if (block < 0 && errno == EINTR)
+			continue;
+		if (block <= 0)
+			return offset ? : block;
+		offset += block;
+		count -= block;
+	}
+	return offset;
+}
+
 int parse_warn (struct parse *cfile, const char *fmt, ...)
 {
 	va_list list;
@@ -4838,14 +4857,14 @@ int parse_warn (struct parse *cfile, const char *fmt, ...)
 #endif
 
 	if (log_perror) {
-		write (STDERR_FILENO, mbuf, strlen (mbuf));
-		write (STDERR_FILENO, "\n", 1);
-		write (STDERR_FILENO, cfile -> token_line,
+		write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
+		write_loop (STDERR_FILENO, "\n", 1);
+		write_loop (STDERR_FILENO, cfile -> token_line,
 		       strlen (cfile -> token_line));
-		write (STDERR_FILENO, "\n", 1);
+		write_loop (STDERR_FILENO, "\n", 1);
 		if (cfile -> lexchar < 81)
-			write (STDERR_FILENO, lexbuf, lix);
-		write (STDERR_FILENO, "^\n", 2);
+			write_loop (STDERR_FILENO, lexbuf, lix);
+		write_loop (STDERR_FILENO, "^\n", 2);
 	}
 
 	cfile -> warnings_occurred = 1;
diff --git a/common/print.c b/common/print.c
index 446de78..a49e747 100644
--- a/common/print.c
+++ b/common/print.c
@@ -437,7 +437,7 @@ char *print_dec_1 (val)
 	unsigned long val;
 {
 	static char vbuf [32];
-	sprintf (vbuf, "%lu", val);
+	snprintf (vbuf, sizeof(vbuf), "%lu", val);
 	return vbuf;
 }
 
@@ -445,7 +445,7 @@ char *print_dec_2 (val)
 	unsigned long val;
 {
 	static char vbuf [32];
-	sprintf (vbuf, "%lu", val);
+	snprintf (vbuf, sizeof(vbuf), "%lu", val);
 	return vbuf;
 }
 
@@ -478,7 +478,7 @@ static unsigned print_subexpression (expr, buf, len)
 	      case expr_check:
 		rv = 10 + strlen (expr -> data.check -> name);
 		if (len > rv) {
-			sprintf (buf, "(check %s)",
+			snprintf (buf, len, "(check %s)",
 				 expr -> data.check -> name);
 			return rv;
 		}
@@ -585,7 +585,7 @@ static unsigned print_subexpression (expr, buf, len)
 	      case expr_host_lookup:
 		rv = 15 + strlen (expr -> data.host_lookup -> hostname);
 		if (len > rv) {
-			sprintf (buf, "(dns-lookup %s)",
+			snprintf (buf, len, "(dns-lookup %s)",
 				 expr -> data.host_lookup -> hostname);
 			return rv;
 		}
@@ -669,7 +669,7 @@ static unsigned print_subexpression (expr, buf, len)
 		rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
 			   strlen (expr -> data.option -> universe -> name));
 		if (len > rv) {
-			sprintf (buf, "(option %s.%s)",
+			snprintf (buf, len, "(option %s.%s)",
 				 expr -> data.option -> universe -> name,
 				 expr -> data.option -> name);
 			return rv;
@@ -805,7 +805,7 @@ static unsigned print_subexpression (expr, buf, len)
 		rv = 10 + (strlen (expr -> data.option -> name) +
 			   strlen (expr -> data.option -> universe -> name));
 		if (len > rv) {
-			sprintf (buf, "(exists %s.%s)",
+			snprintf (buf, len, "(exists %s.%s)",
 				 expr -> data.option -> universe -> name,
 				 expr -> data.option -> name);
 			return rv;
@@ -815,7 +815,8 @@ static unsigned print_subexpression (expr, buf, len)
 	      case expr_variable_exists:
 		rv = 10 + strlen (expr -> data.variable);
 		if (len > rv) {
-			sprintf (buf, "(defined %s)", expr -> data.variable);
+			snprintf (buf, len,
+				"(defined %s)", expr -> data.variable);
 			return rv;
 		}
 		break;
@@ -823,7 +824,7 @@ static unsigned print_subexpression (expr, buf, len)
 	      case expr_variable_reference:
 		rv = strlen (expr -> data.variable);
 		if (len > rv) {
-			sprintf (buf, "%s", expr -> data.variable);
+			snprintf (buf, len, "%s", expr -> data.variable);
 			return rv;
 		}
 		break;
@@ -1106,7 +1107,7 @@ int token_indent_data_string (FILE *file, int col, int indent,
 	}
 
 	for (i = 0; i < data -> len; i++) {
-		sprintf (obuf, "%2.2x", data -> data [i]);
+		snprintf (obuf, sizeof(obuf), "%2.2x", data -> data [i]);
 		col = token_print_indent (file, col, indent,
 					  i == 0 ? prefix : "",
 					  (i + 1 == data -> len
diff --git a/common/tree.c b/common/tree.c
index 56d262f..7130839 100644
--- a/common/tree.c
+++ b/common/tree.c
@@ -738,8 +738,8 @@ int evaluate_dns_expression (result, packet, lease, client_state, in_options,
 				    (*result) -> r_data =
 					    (*result) -> r_data_ephem;
 				    /*%Audit% 16 bytes max. %2004.06.17,Safe%*/
-				    sprintf ((char *)(*result) -> r_data_ephem,
-					     "%u.%u.%u.%u",
+				    snprintf ((char *)(*result) -> r_data_ephem,
+					     16, "%u.%u.%u.%u",
 					     data.data [0] & 0xff,
 					     data.data [1] & 0xff,
 					     data.data [2] & 0xff,
@@ -3428,7 +3428,7 @@ int write_expression (file, expr, col, indent, firstp)
 		col = write_expression (file, expr -> data.extract_int,
 					col, indent, 1);
 		col = token_print_indent (file, col, scol, "", " ", ",");
-		sprintf (obuf, "%d", width);
+		snprintf (obuf, sizeof(obuf), "%d", width);
 		col = token_print_indent (file, col, scol, " ", "", obuf);
 		col = token_print_indent (file, col, indent, "", "", ")");
 		break;
@@ -3451,7 +3451,7 @@ int write_expression (file, expr, col, indent, firstp)
 		col = write_expression (file, expr -> data.extract_int,
 					col, indent, 1);
 		col = token_print_indent (file, col, scol, "", " ", ",");
-		sprintf (obuf, "%d", width);
+		snprintf (obuf, sizeof(obuf), "%d", width);
 		col = token_print_indent (file, col, scol, " ", "", obuf);
 		col = token_print_indent (file, col, indent, "", "",
 					  ")");
@@ -3466,7 +3466,7 @@ int write_expression (file, expr, col, indent, firstp)
 		goto encode_int;
 
 	      case expr_const_int:
-		sprintf (obuf, "%lu", expr -> data.const_int);
+		snprintf (obuf, sizeof(obuf), "%lu", expr -> data.const_int);
 		col = token_print_indent (file, col, indent, "", "", obuf);
 		break;
 
@@ -3615,11 +3615,11 @@ int write_expression (file, expr, col, indent, firstp)
 		col = token_print_indent (file, col, indent, " ", "",
 					  "(");
 		scol = col;
-		sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
+		snprintf (obuf, sizeof(obuf), "%d", expr -> data.ns_add.rrclass);
 		col = token_print_indent (file, col, scol, "", "", obuf);
 		col = token_print_indent (file, col, scol, "", " ",
 					  ",");
-		sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
+		snprintf (obuf, sizeof(obuf), "%d", expr -> data.ns_add.rrtype);
 		col = token_print_indent (file, col, scol, "", "", obuf);
 		col = token_print_indent (file, col, scol, "", " ",
 					  ",");
@@ -3644,11 +3644,11 @@ int write_expression (file, expr, col, indent, firstp)
 					  "(");
 	      finish_ns_small:
 		scol = col;
-		sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
+		snprintf (obuf, sizeof(obuf), "%d", expr -> data.ns_add.rrclass);
 		col = token_print_indent (file, col, scol, "", "", obuf);
 		col = token_print_indent (file, col, scol, "", " ",
 					  ",");
-		sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
+		snprintf (obuf, sizeof(obuf), "%d", expr -> data.ns_add.rrtype);
 		col = token_print_indent (file, col, scol, "", "", obuf);
 		col = token_print_indent (file, col, scol, "", " ",
 					  ",");
diff --git a/common/upf.c b/common/upf.c
index 89c217a..116449b 100644
--- a/common/upf.c
+++ b/common/upf.c
@@ -80,7 +80,7 @@ int if_register_upf (info)
 	/* Open a UPF device */
 	for (b = 0; 1; b++) {
 		/* %Audit% Cannot exceed 36 bytes. %2004.06.17,Safe% */
-		sprintf(filename, "/dev/pf/pfilt%d", b);
+		snprintf(filename, sizeof(filename), "/dev/pf/pfilt%d", b);
 
 		sock = open (filename, O_RDWR, 0);
 		if (sock < 0) {
diff --git a/dhcpctl/dhcpctl.3 b/dhcpctl/dhcpctl.3
index 352bf3b..880285d 100644
--- a/dhcpctl/dhcpctl.3
+++ b/dhcpctl/dhcpctl.3
@@ -43,7 +43,8 @@
 .\"
 .\"
 .Sh SYNOPSIS
-.Fd #include <dhcpctl/dhcpctl.h>
+.Fd #include <dhcpctl.h>
+.sp
 .Ft dhcpctl_status
 .Fo dhcpctl_initialize
 .Fa void
@@ -426,7 +427,7 @@ that most error checking has been ommitted for brevity.
 #include <netinet/in.h>
 
 #include <isc/result.h>
-#include <dhcpctl/dhcpctl.h>
+#include <dhcpctl.h>
 
 int main (int argc, char **argv) {
 	dhcpctl_data_string ipaddrstring = NULL;
diff --git a/dst/Makefile.dist b/dst/Makefile.dist
index ffe7e4e..9282e59 100644
--- a/dst/Makefile.dist
+++ b/dst/Makefile.dist
@@ -30,7 +30,9 @@ CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) -DHMAC_MD5 -DMINIRES_LIB
 
 all:	libdst.a
 
-install:
+install: all
+	mkdir -p $(DESTDIR)$(LIBDIR)
+	$(INSTALL) libdst.a $(DESTDIR)$(LIBDIR)/
 
 libdst.a:	$(OBJ)
 	rm -f dst.a
diff --git a/dst/dst_api.c b/dst/dst_api.c
index 64114cb..ff396f2 100644
--- a/dst/dst_api.c
+++ b/dst/dst_api.c
@@ -440,6 +440,7 @@ dst_s_write_private_key(const DST_KEY *key)
 		if ((nn = fwrite(encoded_block, 1, len, fp)) != len) {
 			EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n",
 				 file, out_len, nn, errno));
+			fclose(fp);
 			return (-5);
 		}
 		fclose(fp);
@@ -526,6 +527,7 @@ dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg)
 	/* Locate and skip "KEY" */
 	if (c != 'K' && c != 'k') {
 		EREPORT(("\"KEY\" doesn't appear in file: %s", name));
+		fclose(fp);
 		return NULL;
 	}
 	while ((c = getc(fp)) != EOF)
@@ -540,10 +542,15 @@ dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg)
 	if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) {
 		EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n"
 			 ,name));
+		fclose(fp);
 		return (NULL);
 	}
 	/* read in the key string */
-	fgets(enckey, sizeof(enckey), fp);
+	if (!fgets(enckey, sizeof(enckey), fp)) {
+		EREPORT(("Key too short in file: %s", name));
+		fclose(fp);
+		return NULL;
+	}
 
 	/* If we aren't at end-of-file, something is wrong.  */
 	while ((c = getc(fp)) != EOF)
@@ -551,6 +558,7 @@ dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg)
 			break;
 	if (!feof(fp)) {
 		EREPORT(("Key too long in file: %s", name));
+		fclose(fp);
 		return NULL;
 	}
 	fclose(fp);
diff --git a/dst/dst_support.c b/dst/dst_support.c
index 581445b..a8c1ba8 100644
--- a/dst/dst_support.c
+++ b/dst/dst_support.c
@@ -418,8 +418,8 @@ dst_s_build_filename(char *filename, const char *name, unsigned id,
 	if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
 		return (-1);
 	my_id = id;
-	sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
-		(const char *) suffix);
+	snprintf(filename, filename_length, "K%s+%03d+%05d.%s",
+		name, alg, my_id, (const char *) suffix);
 	if (strrchr(filename, '/'))
 		return (-1);
 	if (strrchr(filename, '\\'))
diff --git a/dst/hmac_link.c b/dst/hmac_link.c
index 90b92e2..ad95c7a 100644
--- a/dst/hmac_link.c
+++ b/dst/hmac_link.c
@@ -280,7 +280,7 @@ dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff,
 	hkey = (HMAC_Key *) dkey->dk_KEY_struct;
 	memset(buff, 0, buff_len);	/* just in case */
 	/* write file header */
-	sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
+	snprintf(buff, buff_len, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
 
 	bp = (char *) strchr(buff, '\0');
 	b_len = buff_len - (bp - buff);
diff --git a/includes/cf/linux.h b/includes/cf/linux.h
index a286084..d37e335 100644
--- a/includes/cf/linux.h
+++ b/includes/cf/linux.h
@@ -83,11 +83,11 @@ extern int h_errno;
    directory. */
 
 #ifndef _PATH_DHCPD_DB
-#define _PATH_DHCPD_DB		"/var/state/dhcp/dhcpd.leases"
+#define _PATH_DHCPD_DB		"/state/dhcpd.leases"
 #endif
 
 #ifndef _PATH_DHCLIENT_DB
-#define _PATH_DHCLIENT_DB	"/var/state/dhcp/dhclient.leases"
+#define _PATH_DHCLIENT_DB	"/var/lib/dhcp/dhclient/state/dhclient.leases"
 #endif
 
 /* Varargs stuff... */
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index ba2911b..d6acec1 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -2643,3 +2643,6 @@ OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_link, dhcp_failover_link_t,
 #endif /* FAILOVER_PROTOCOL */
 
 const char *binding_state_print (enum failover_state);
+
+extern void dhcpd_priv_minimize(const char *server_user, const char *server_jail);
+extern void dhcpd_priv_drop(const char *server_user, const char *server_jail);
diff --git a/minires/res_mkupdate.c b/minires/res_mkupdate.c
index 19f2d50..537f636 100644
--- a/minires/res_mkupdate.c
+++ b/minires/res_mkupdate.c
@@ -1113,14 +1113,14 @@ cgetprotobynumber(int proto) {				/* Host byte order. */
 
 const char *
 res_protocolname(int num) {
-	static char number[8];
+	static char number[2 + sizeof(num) * 3];
 	struct protoent *pp;
 
 	if (protolist == (struct valuelist *)0)
 		res_buildprotolist();
 	pp = cgetprotobynumber(num);
 	if (pp == 0)  {
-		(void) sprintf(number, "%d", num);
+		(void) snprintf(number, sizeof(number), "%d", num);
 		return (number);
 	}
 	return (pp->p_name);
@@ -1128,14 +1128,14 @@ res_protocolname(int num) {
 
 const char *
 res_servicename(u_int16_t port, const char *proto) {	/* Host byte order. */
-	static char number[8];
+	static char number[2 + sizeof(port) * 3];
 	struct servent *ss;
 
 	if (servicelist == (struct valuelist *)0)
 		res_buildservicelist();
 	ss = cgetservbyport(htons(port), proto);
 	if (ss == 0)  {
-		(void) sprintf(number, "%d", port);
+		(void) snprintf(number, sizeof(number), "%d", port);
 		return (number);
 	}
 	return (ss->s_name);
diff --git a/minires/res_query.c b/minires/res_query.c
index 7c3912f..170d999 100644
--- a/minires/res_query.c
+++ b/minires/res_query.c
@@ -375,7 +375,7 @@ res_nquerydomain(res_state statp,
 			RES_SET_H_ERRNO(statp, NO_RECOVERY);
 			return ISC_R_NOSPACE;
 		}
-		sprintf(nbuf, "%s.%s", name, domain);
+		snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
 	}
 	return res_nquery(statp,
 			  longname, class, type, answer, anslen, ansret);
diff --git a/omapip/errwarn.c b/omapip/errwarn.c
index be0e6d8..f1d7343 100644
--- a/omapip/errwarn.c
+++ b/omapip/errwarn.c
@@ -51,6 +51,25 @@ void (*log_cleanup) (void);
 static char mbuf [CVT_BUF_MAX + 1];
 static char fbuf [CVT_BUF_MAX + 1];
 
+static ssize_t
+write_loop (int fd, const char *buffer, size_t count)
+{
+	ssize_t offset = 0;
+
+	while (count > 0)
+	{
+		ssize_t block = write (fd, &buffer[offset], count);
+
+		if (block < 0 && errno == EINTR)
+			continue;
+		if (block <= 0)
+			return offset ? : block;
+		offset += block;
+		count -= block;
+	}
+	return offset;
+}
+
 /* Log an error message, then exit... */
 
 void log_fatal (const char * fmt, ... )
@@ -67,33 +86,31 @@ void log_fatal (const char * fmt, ... )
   va_end (list);
 
 #ifndef DEBUG
-  syslog (log_priority | LOG_ERR, "%s", mbuf);
+  if (*mbuf)
+	syslog (log_priority | LOG_ERR, "%s", mbuf);
 #endif
 
   /* Also log it to stderr? */
-  if (log_perror) {
-	  write (STDERR_FILENO, mbuf, strlen (mbuf));
-	  write (STDERR_FILENO, "\n", 1);
+  if (log_perror && *mbuf) {
+	  write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
+	  write_loop (STDERR_FILENO, "\n", 1);
   }
 
 #if !defined (NOMINUM)
+  log_error ("%s", "Please note the following before requesting help:");
   log_error ("%s", "");
-  log_error ("If you did not get this software from ftp.isc.org, please");
-  log_error ("get the latest from ftp.isc.org and install that before");
-  log_error ("requesting help.");
-  log_error ("%s", "");
-  log_error ("If you did get this software from ftp.isc.org and have not");
-  log_error ("yet read the README, please read it before requesting help.");
-  log_error ("If you intend to request help from the dhcp-server@isc.org");
-  log_error ("mailing list, please read the section on the README about");
-  log_error ("submitting bug reports and requests for help.");
+  log_error ("%s", "This software is a part of the Internet Software Consortium's DHCP suite");
+  log_error ("%s", "with modifications for ALT Linux.");
+  log_error ("%s", "The ISC folks quite reasonably require that you do not bother them with");
+  log_error ("%s", "questions on software that includes third-party modifications and might");
+  log_error ("%s", "not be based off their latest code.  Hence, please direct any questions");
+  log_error ("%s", "to the community@ mailing list instead; the subscription instructions");
+  log_error ("%s", "are given at http://lists.altlinux.org/mailman/listinfo/community .");
   log_error ("%s", "");
-  log_error ("Please do not under any circumstances send requests for");
-  log_error ("help directly to the authors of this software - please");
-  log_error ("send them to the appropriate mailing list as described in");
-  log_error ("the README file.");
+  log_error ("%s", "Please also read the SUPPORT section on the README about");
+  log_error ("%s", "submitting bug reports and requests for help.");
   log_error ("%s", "");
-  log_error ("exiting.");
+  log_error ("%s", "exiting.");
 #endif
   if (log_cleanup)
 	  (*log_cleanup) ();
@@ -116,12 +133,13 @@ int log_error (const char * fmt, ...)
   va_end (list);
 
 #ifndef DEBUG
-  syslog (log_priority | LOG_ERR, "%s", mbuf);
+  if (*mbuf)
+	syslog (log_priority | LOG_ERR, "%s", mbuf);
 #endif
 
-  if (log_perror) {
-	  write (STDERR_FILENO, mbuf, strlen (mbuf));
-	  write (STDERR_FILENO, "\n", 1);
+  if (log_perror && *mbuf) {
+	  write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
+	  write_loop (STDERR_FILENO, "\n", 1);
   }
 
   return 0;
@@ -143,12 +161,13 @@ int log_info (const char *fmt, ...)
   va_end (list);
 
 #ifndef DEBUG
-  syslog (log_priority | LOG_INFO, "%s", mbuf);
+  if (*mbuf)
+	syslog (log_priority | LOG_INFO, "%s", mbuf);
 #endif
 
-  if (log_perror) {
-	  write (STDERR_FILENO, mbuf, strlen (mbuf));
-	  write (STDERR_FILENO, "\n", 1);
+  if (log_perror && *mbuf) {
+	  write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
+	  write_loop (STDERR_FILENO, "\n", 1);
   }
 
   return 0;
@@ -170,12 +189,13 @@ int log_debug (const char *fmt, ...)
   va_end (list);
 
 #ifndef DEBUG
-  syslog (log_priority | LOG_DEBUG, "%s", mbuf);
+  if (*mbuf)
+	syslog (log_priority | LOG_DEBUG, "%s", mbuf);
 #endif
 
-  if (log_perror) {
-	  write (STDERR_FILENO, mbuf, strlen (mbuf));
-	  write (STDERR_FILENO, "\n", 1);
+  if (log_perror && *mbuf) {
+	  write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
+	  write_loop (STDERR_FILENO, "\n", 1);
   }
 
   return 0;
@@ -236,7 +256,7 @@ char *strerror (err)
 	static char errbuf [128];
 
 	if (err < 0 || err >= sys_nerr) {
-		sprintf (errbuf, "Error %d", err);
+		snprintf (errbuf, sizeof(errbuf), "Error %d", err);
 		return errbuf;
 	}
 	return sys_errlist [err];
diff --git a/omapip/iscprint.c b/omapip/iscprint.c
index de331a1..e3e5e80 100644
--- a/omapip/iscprint.c
+++ b/omapip/iscprint.c
@@ -230,7 +230,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
 						head = "";
 					tmpui = tmpi;
 				}
-				sprintf(buf, "%u", tmpui);
+				snprintf(buf, sizeof(buf), "%u", tmpui);
 				goto printint;
 			case 'o':
 				if (q)
@@ -239,7 +239,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
 					tmpui = va_arg(ap, long int);
 				else
 					tmpui = va_arg(ap, int);
-				sprintf(buf, alt ? "%#o"
+				snprintf(buf, sizeof(buf), alt ? "%#o"
 						 : "%o", tmpui);
 				goto printint;
 			case 'u':
@@ -249,7 +249,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
 					tmpui = va_arg(ap, unsigned long int);
 				else
 					tmpui = va_arg(ap, unsigned int);
-				sprintf(buf, "%u", tmpui);
+				snprintf(buf, sizeof(buf), "%u", tmpui);
 				goto printint;
 			case 'x':
 				if (q)
@@ -263,7 +263,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
 					if (precision > 2)
 						precision -= 2;
 				}
-				sprintf(buf, "%x", tmpui);
+				snprintf(buf, sizeof(buf), "%x", tmpui);
 				goto printint;
 			case 'X':
 				if (q)
@@ -277,7 +277,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
 					if (precision > 2)
 						precision -= 2;
 				}
-				sprintf(buf, "%X", tmpui);
+				snprintf(buf, sizeof(buf), "%X", tmpui);
 				goto printint;
 			printint:
 				if (precision != 0 || width != 0) {
@@ -403,7 +403,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
 			break;
 		case 'p':
 			v = va_arg(ap, void *);
-			sprintf(buf, "%p", v);
+			snprintf(buf, sizeof(buf), "%p", v);
 			length = strlen(buf);
 			if (precision > length)
 				zeropad = precision - length;
@@ -479,7 +479,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
 			 */
 			if (precision > 512)
 				precision = 512;
-			sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
+			snprintf(fmt, sizeof(fmt), "%%%s%s.%lu%s%c", alt ? "#" : "",
 				plus ? "+" : space ? " " : "",
 				precision, l ? "L" : "", *format);
 			switch (*format) {
@@ -491,12 +491,12 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
 #ifdef HAVE_LONG_DOUBLE
 				if (l) {
 					ldbl = va_arg(ap, long double);
-					sprintf(buf, fmt, ldbl);
+					snprintf(buf, sizeof(buf), fmt, ldbl);
 				} else
 #endif
 				{
 					dbl = va_arg(ap, double);
-					sprintf(buf, fmt, dbl);
+					snprintf(buf, sizeof(buf), fmt, dbl);
 				}
 				length = strlen(buf);
 				if (width > 0) {
diff --git a/omapip/result.c b/omapip/result.c
index 2274689..e598e26 100644
--- a/omapip/result.c
+++ b/omapip/result.c
@@ -114,6 +114,6 @@ const char *isc_result_totext (isc_result_t result)
 
 	if (result >= ISC_R_SUCCESS && result < ISC_R_NRESULTS)
 		return text [result];
-	sprintf(ebuf, "unknown error: %d", result);
+	snprintf(ebuf, sizeof(ebuf), "unknown error: %d", result);
 	return ebuf;
 }
diff --git a/relay/Makefile.dist b/relay/Makefile.dist
index 8f1da98..b5fc8c4 100644
--- a/relay/Makefile.dist
+++ b/relay/Makefile.dist
@@ -83,6 +83,6 @@ dhcrelay.man8:	dhcrelay.8
 		-e "s#RUNDIR#$(VARRUN)#" < dhcrelay.8 >dhcrelay.man8
 
 dhcrelay:	dhcrelay.o $(DHCPLIB)
-	$(CC) $(LFLAGS) -o $(PROG) dhcrelay.o $(DHCPLIB) $(LIBS)
+	$(CC) -pie $(LFLAGS) -o $(PROG) dhcrelay.o $(DHCPLIB) $(LIBS) -lcap
 
 # Dependencies (semi-automatically-generated)
diff --git a/relay/dhcrelay.8 b/relay/dhcrelay.8
index 115d8a3..82aff34 100644
--- a/relay/dhcrelay.8
+++ b/relay/dhcrelay.8
@@ -77,6 +77,14 @@ dhcrelay - Dynamic Host Configuration Protocol Relay Agent
 |
 .I discard
 ]
+[
+.B -u
+.I user
+]
+[
+.B -j
+.I chroot-dir
+]
 .I server0
 [
 .I ...serverN
@@ -139,6 +147,11 @@ This can be unhelpful in a system startup script - to disable this
 behaviour, specify the
 .B -q
 flag.
+.PP
+Upon startup, this version of dhcrelay will switch to a non-root
+pseudo-user and enter a chroot jail.  The default username (\fIdhcrelay\fR)
+and the default chroot jail directory path (\fI/var/empty\fR)
+may be overridden with the \fB-u\fR and \fB-j\fR options, respectively.
 .SH RELAY AGENT INFORMATION OPTIONS
 If the
 .B -a
@@ -239,7 +252,12 @@ has been written for Internet Systems Consortium
 by Ted Lemon in cooperation with Vixie
 Enterprises.  To learn more about Internet Systems Consortium,
 see
-.B http://www.isc.org/isc.
+.BR http://www.isc.org/isc .
 To learn more about Vixie
 Enterprises, see
-.B http://www.vix.com.
+.BR http://www.vix.com .
+.PP
+This version of dhcrelay has been modified for ALT Linux
+.RB ( http://www.altlinux.com/ ).
+In particular, the privilege reduction functionality and the \fB-u\fR
+and \fB-j\fR options are Openwall/ALT Linux extensions.
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index 5d19ec2..5dfd0e8 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -106,23 +106,28 @@ int main (argc, argv, envp)
 	int argc;
 	char **argv, **envp;
 {
-	int i;
+	int i, null_fd;
 	struct servent *ent;
 	struct server_list *sp = (struct server_list *)0;
 	int no_daemon = 0;
 	int quiet = 0;
 	isc_result_t status;
 	char *s;
+	char *server_user = "dhcrelay";
+	char *server_jail = "/var/empty";
 
 	/* Make sure we have stdin, stdout and stderr. */
-	i = open ("/dev/null", O_RDWR);
-	if (i == 0)
-		i = open ("/dev/null", O_RDWR);
-	if (i == 1) {
-		i = open ("/dev/null", O_RDWR);
+	null_fd = open ("/dev/null", O_RDWR);
+	if (null_fd == 0)
+		null_fd = open ("/dev/null", O_RDWR);
+	if (null_fd == 1)
+		null_fd = open ("/dev/null", O_RDWR);
+	if (null_fd == 2) {
+		null_fd = open ("/dev/null", O_RDWR);
 		log_perror = 0; /* No sense logging to /dev/null. */
-	} else if (i != -1)
-		close (i);
+	}
+	if (null_fd < 0)
+		log_fatal ("Can't open %s: %m", "/dev/null");
 
 #ifdef SYSLOG_4_2
 	openlog ("dhcrelay", LOG_NDELAY);
@@ -185,6 +190,14 @@ int main (argc, argv, envp)
 			if (++i == argc)
 				usage ();
 			dhcp_max_agent_option_packet_length = atoi (argv [i]);
+		} else if (!strcmp (argv [i], "-u")) {
+			if (++i == argc)
+				usage ();
+			server_user = argv[i];
+		} else if (!strcmp (argv [i], "-j")) {
+			if (++i == argc)
+				usage ();
+			server_jail = argv[i];
 		} else if (!strcmp (argv [i], "-m")) {
 			if (++i == argc)
 				usage ();
@@ -310,12 +323,17 @@ int main (argc, argv, envp)
 			}	
 		}
 
-		close (0);
-		close (1);
-		close (2);
+		if (dup2 (null_fd, 0) != 0 ||
+		    dup2 (null_fd, 1) != 1 ||
+		    dup2 (null_fd, 2) != 2)
+			log_fatal("Can't daemonize: %m");
+		close (null_fd);
+		null_fd = -1;
 		pid = setsid ();
 	}
 
+	dhcpd_priv_drop(server_user, server_jail);
+
 	/* Start dispatching packets and timeouts... */
 	dispatch ();
 
@@ -455,10 +473,11 @@ void relay (ip, packet, length, from_port, from, hfrom)
 
 static void usage ()
 {
-	log_fatal ("Usage: dhcrelay [-p <port>] [-d] [-D] [-i %s%s%s%s",
+	log_fatal ("Usage: dhcrelay [-p <port>] [-d] [-D] [-i %s%s%s%s%s",
 		"interface] [-q] [-a]\n                ",
 		"[-c count] [-A length] ",
 		"[-m append|replace|forward|discard]\n",
+		"[-u user] [-j chroot-dir]\n",
 		"                [server1 [... serverN]]");
 }
 
diff --git a/server/Makefile.dist b/server/Makefile.dist
index b7d1216..9202441 100644
--- a/server/Makefile.dist
+++ b/server/Makefile.dist
@@ -103,6 +103,6 @@ dhcpd.leases.man5:	dhcpd.leases.5
 		-e "s#RUNDIR#$(VARRUN)#g" < dhcpd.leases.5 >dhcpd.leases.man5
 
 dhcpd:	$(OBJS) $(COBJ) $(DHCPLIB)
-	$(CC) $(LFLAGS) -o dhcpd $(OBJS) $(DHCPLIB) $(LIBS)
+	$(CC) -pie $(LFLAGS) -o dhcpd $(OBJS) $(DHCPLIB) $(LIBS) -lcap
 
 # Dependencies (semi-automatically-generated)
diff --git a/server/confpars.c b/server/confpars.c
index cb12397..e658edd 100644
--- a/server/confpars.c
+++ b/server/confpars.c
@@ -1013,10 +1013,13 @@ void parse_failover_peer (cfile, group, type)
 		parse_warn (cfile, "peer address may not be omitted");
 
 	/* XXX - when/if we get a port number assigned, just set as default */
+	/* See http://bugzilla.redhat.com/show_bug.cgi?id=167292
+	 * IANA registration by Bernard Volz <volz at cisco.com>
+	 */
 	if (!peer -> me.port)
-		parse_warn (cfile, "local port may not be omitted");
+		peer -> me.port = 647;
 	if (!peer -> partner.port)
-		parse_warn (cfile, "peer port may not be omitted");
+		peer -> partner.port = 847;
 
 	if (peer -> i_am == primary) {
 	    if (!peer -> hba) {
diff --git a/server/db.c b/server/db.c
index bb0ab86..d1e6c8d 100644
--- a/server/db.c
+++ b/server/db.c
@@ -81,7 +81,7 @@ int write_lease (lease)
 		if (lease -> starts != MAX_TIME) {
 			t = gmtime (&lease -> starts);
 			/* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
-			sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
+			snprintf (tbuf, sizeof(tbuf), "%d %d/%02d/%02d %02d:%02d:%02d;",
 				 t -> tm_wday, t -> tm_year + 1900,
 				 t -> tm_mon + 1, t -> tm_mday,
 				 t -> tm_hour, t -> tm_min, t -> tm_sec);
@@ -98,7 +98,7 @@ int write_lease (lease)
 		if (lease -> ends != MAX_TIME) {
 			t = gmtime (&lease -> ends);
 			/* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
-			sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
+			snprintf (tbuf, sizeof(tbuf), "%d %d/%02d/%02d %02d:%02d:%02d;",
 				 t -> tm_wday, t -> tm_year + 1900,
 				 t -> tm_mon + 1, t -> tm_mday,
 				 t -> tm_hour, t -> tm_min, t -> tm_sec);
diff --git a/server/ddns.c b/server/ddns.c
index 7c2df4b..1459a4c 100644
--- a/server/ddns.c
+++ b/server/ddns.c
@@ -499,7 +499,7 @@ int ddns_updates (struct packet *packet,
 			ddns_rev_name.data = ddns_rev_name.buffer -> data;
 
 			/* %Audit% Cannot exceed 17 bytes. %2004.06.17,Safe% */
-			sprintf ((char *)ddns_rev_name.buffer -> data,
+			snprintf ((char *)ddns_rev_name.buffer -> data, 17,
 				  "%u.%u.%u.%u.",
 				  lease -> ip_addr . iabuf[3] & 0xff,
 				  lease -> ip_addr . iabuf[2] & 0xff,
diff --git a/server/dhcp.c b/server/dhcp.c
index f502b19..31fd31a 100644
--- a/server/dhcp.c
+++ b/server/dhcp.c
@@ -81,7 +81,7 @@ void dhcp (packet)
 			s = dhcp_type_names [packet -> packet_type - 1];
 		} else {
 			/* %Audit% Cannot exceed 28 bytes. %2004.06.17,Safe% */
-			sprintf (typebuf, "type %d", packet -> packet_type);
+			snprintf (typebuf, sizeof(typebuf), "type %d", packet -> packet_type);
 			s = typebuf;
 		}
 		
@@ -447,7 +447,7 @@ void dhcprequest (packet, ms_nulltp, ip_lease)
 		/* piaddr() should not return more than a 15 byte string.
 		 * safe.
 		 */
-		sprintf (smbuf, " (%s)", piaddr (sip));
+		snprintf (smbuf, sizeof(smbuf), " (%s)", piaddr (sip));
 		have_server_identifier = 1;
 	} else
 		smbuf [0] = 0;
diff --git a/server/dhcpd.8 b/server/dhcpd.8
index b63336a..8ff7b50 100644
--- a/server/dhcpd.8
+++ b/server/dhcpd.8
@@ -74,6 +74,14 @@ dhcpd - Dynamic Host Configuration Protocol Server
 .I trace-playback-file
 ]
 [
+.B -u
+.I user
+]
+[
+.B -j
+.I chroot-dir
+]
+[
 .I if0
 [
 .I ...ifN
@@ -239,6 +247,12 @@ using the \fB-lf\fR switch, so that the DHCP server doesn't wipe out
 your existing lease file with its test data.  The DHCP server will
 refuse to operate in playback mode unless you specify an alternate
 lease file.
+.PP
+Upon startup, this version of the DHCP server will switch to a non-root
+pseudo-user and enter a chroot jail.  The default username (\fIdhcpd\fR)
+and the default chroot jail directory path (\fI/var/lib/dhcp/dhcpd\fR)
+may be overridden with the \fB-u\fR and \fB-j\fR options, respectively.
+.PP
 .SH CONFIGURATION
 The syntax of the dhcpd.conf(5) file is discussed separately.   This
 section should be used as an overview of the configuration process,
@@ -746,3 +760,8 @@ Consortium.   Version 3 of the DHCP server was funded by Nominum, Inc.
 Information about Internet Systems Consortium is available at
 .B http://www.isc.org/\fR.
 Information about Nominum can be found at \fBhttp://www.nominum.com/\fR.
+.PP
+This version of dhcpd has been modified for ALT Linux
+.RB ( http://www.altlinux.com/ ).
+In particular, the privilege reduction functionality and the \fB-u\fR
+and \fB-j\fR options are Openwall/ALT Linux extensions.
diff --git a/server/dhcpd.c b/server/dhcpd.c
index 8deb8d0..f0166e7 100644
--- a/server/dhcpd.c
+++ b/server/dhcpd.c
@@ -197,7 +197,7 @@ int main (argc, argv, envp)
 	int argc;
 	char **argv, **envp;
 {
-	int i, status;
+	int i, status, null_fd;
 	struct servent *ent;
 	char *s;
 	int cftest = 0;
@@ -224,16 +224,21 @@ int main (argc, argv, envp)
 	char *traceinfile = (char *)0;
 	char *traceoutfile = (char *)0;
 #endif
+	char *server_user = "dhcpd";
+	char *server_jail = "/var/lib/dhcp/dhcpd";
 
 	/* Make sure we have stdin, stdout and stderr. */
-	status = open ("/dev/null", O_RDWR);
-	if (status == 0)
-		status = open ("/dev/null", O_RDWR);
-	if (status == 1) {
-		status = open ("/dev/null", O_RDWR);
+	null_fd = open ("/dev/null", O_RDWR);
+	if (null_fd == 0)
+		null_fd = open ("/dev/null", O_RDWR);
+	if (null_fd == 1)
+		null_fd = open ("/dev/null", O_RDWR);
+	if (null_fd == 2) {
+		null_fd = open ("/dev/null", O_RDWR);
 		log_perror = 0; /* No sense logging to /dev/null. */
-	} else if (status != -1)
-		close (status);
+	}
+	if (null_fd < 0)
+		log_fatal ("Can't open %s: %m", "/dev/null");
 
 	/* Set up the client classification system. */
 	classification_setup ();
@@ -319,6 +324,14 @@ int main (argc, argv, envp)
 		} else if (!strcmp (argv [i], "-q")) {
 			quiet = 1;
 			quiet_interface_discovery = 1;
+		} else if (!strcmp (argv [i], "-u")) {
+			if (++i == argc)
+				usage();
+			server_user = argv[i];
+		} else if (!strcmp (argv [i], "-j")) {
+			if (++i == argc)
+				usage();
+			server_jail = argv[i];
 		} else if (!strcmp (argv [i], "--version")) {
 			log_info ("isc-dhcpd-%s", DHCP_VERSION);
 			exit (0);
@@ -498,12 +511,6 @@ int main (argc, argv, envp)
 
 	group_write_hook = group_writer;
 
-	/* Start up the database... */
-	db_startup (lftest);
-
-	if (lftest)
-		exit (0);
-
 	/* Discover all the network interfaces and initialize them. */
 	discover_interfaces (DISCOVER_SERVER);
 
@@ -524,7 +531,6 @@ int main (argc, argv, envp)
 #if defined (TRACING)
 	trace_seed_stash (trace_srandom, seed + cur_time);
 #endif
-	postdb_startup ();
 
 #ifndef DEBUG
 	if (daemon) {
@@ -555,14 +561,18 @@ int main (argc, argv, envp)
 
         /* Write new pid file. */
         if ((i = open(path_dhcpd_pid, O_WRONLY|O_CREAT|O_TRUNC, 0644)) >= 0) {
-                sprintf(pbuf, "%d\n", (int) getpid());
-                write(i, pbuf, strlen(pbuf));
+                snprintf(pbuf, sizeof(pbuf), "%d\n", (int) getpid());
+                if (write(i, pbuf, strlen(pbuf)) != strlen(pbuf))
+			log_fatal("Error writing pid file: %s: %m",
+				  path_dhcpd_pid);
                 close(i);
         } else {
                 log_error("Can't create PID file %s: %m.", path_dhcpd_pid);
         }
 
 
+	dhcpd_priv_minimize (server_user, server_jail);
+
 	/* If we were requested to log to stdout on the command line,
 	   keep doing so; otherwise, stop. */
 	if (log_perror == -1)
@@ -572,11 +582,25 @@ int main (argc, argv, envp)
 
 	if (daemon) {
 		/* Become session leader and get pid... */
-		close (0);
-		close (1);
-		close (2);
+		if (dup2 (null_fd, 0) != 0 ||
+		    dup2 (null_fd, 1) != 1 ||
+		    dup2 (null_fd, 2) != 2)
+			log_fatal("Can't daemonize: %m");
+		close (null_fd);
+		null_fd = -1;
 		pid = setsid ();
 	}
+
+	/* Start up the database... */
+	db_startup (lftest);
+
+	if (lftest)
+		exit (0);
+
+	postdb_startup ();
+
+	dhcpd_priv_drop (server_user, server_jail);
+
 #endif /* !DEBUG */
 
 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
@@ -865,8 +889,9 @@ static void usage ()
 	log_info (copyright);
 	log_info (arr);
 
-	log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f]%s%s%s%s",
+	log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f]%s%s%s%s%s",
 		   "\n             [-cf config-file] [-lf lease-file]",
+		   "\n             [-u user] [-j chroot-dir]",
 #if defined (TRACING)
 		   "\n		   [-tf trace-output-file]",
 		   "\n		   [-play trace-input-file]",
diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5
index 04afd4e..ad29ebb 100644
--- a/server/dhcpd.conf.5
+++ b/server/dhcpd.conf.5
@@ -531,9 +531,9 @@ primary server might look like this:
 failover peer "foo" {
   primary;
   address anthrax.rc.vix.com;
-  port 519;
+  port 647;
   peer address trantor.rc.vix.com;
-  peer port 520;
+  peer port 847;
   max-response-delay 60;
   max-unacked-updates 10;
   mclt 3600;
@@ -592,9 +592,7 @@ statement
 .B port \fIport-number\fR\fB;\fR
 .PP
 The \fBport\fR statement declares the TCP port on which the server
-should listen for connections from its failover peer.   This statement
-may not currently be omitted, because the failover protocol does not
-yet have a reserved TCP port number.
+should listen for connections from its failover peer.
 .RE
 .PP
 The 
@@ -606,10 +604,8 @@ statement
 .PP
 The \fBpeer port\fR statement declares the TCP port to which the
 server should connect to reach its failover peer for failover
-messages.   This statement may not be omitted because the failover
-protocol does not yet have a reserved TCP port number.   The port
-number declared in the \fBpeer port\fR statement may be the same as
-the port number declared in the \fBport\fR statement.
+messages.  The port number declared in the \fBpeer port\fR statement
+may be the same as the port number declared in the \fBport\fR statement.
 .RE
 .PP
 The 
@@ -2038,8 +2034,8 @@ The syntax of the \fIsyslog.conf\fR file may be different on some
 operating systems - consult the \fIsyslog.conf\fR manual page to be
 sure.  To get syslog to start logging to the new file, you must first
 create the file with correct ownership and permissions (usually, the
-same owner and permissions of your /var/log/messages or
-/usr/adm/messages file should be fine) and send a SIGHUP to syslogd.
+same owner and permissions of your /var/log/messages
+file should be fine) and send a SIGHUP to syslogd.
 Some systems support log rollover using a shell script or program
 called newsyslog or logrotate, and you may be able to configure this
 as well so that your log file doesn't grow uncontrollably.
@@ -2114,7 +2110,8 @@ statement
 The \fInext-server\fR statement is used to specify the host address of
 the server from which the initial boot file (specified in the
 \fIfilename\fR statement) is to be loaded.   \fIServer-name\fR should
-be a numeric IP address or a domain name.
+be a numeric IP address or a domain name.  If no \fInext-server\fR
+statement applies to a given client, the address 0.0.0.0 is used.
 .RE
 .PP
 The
diff --git a/server/failover.c b/server/failover.c
index 1be6c04..8dca575 100644
--- a/server/failover.c
+++ b/server/failover.c
@@ -3615,7 +3615,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
 			val = va_arg (va, unsigned);
 #if defined (DEBUG_FAILOVER_MESSAGES)
 			/* %Audit% Cannot exceed 24 bytes. %2004.06.17,Safe% */
-			sprintf (tbuf, " %d", val);
+			snprintf (tbuf, sizeof(tbuf), " %d", val);
 			failover_print (obuf, obufix, obufmax, tbuf);
 #endif
 			option.data [i + 4] = val;
@@ -3635,7 +3635,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
 				
 #if defined (DEBUG_FAILOVER_MESSAGES)
 			/*%Audit% Cannot exceed 17 bytes.  %2004.06.17,Safe%*/
-			sprintf (tbuf, " %u.%u.%u.%u",
+			snprintf (tbuf, sizeof(tbuf), " %u.%u.%u.%u",
 				  iaddr [0], iaddr [1], iaddr [2], iaddr [3]);
 			failover_print (obuf, obufix, obufmax, tbuf);
 #endif
@@ -3648,7 +3648,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
 			val = va_arg (va, unsigned);
 #if defined (DEBUG_FAILOVER_MESSAGES)
 			/*%Audit% Cannot exceed 24 bytes.  %2004.06.17,Safe%*/
-			sprintf (tbuf, " %d", val);
+			snprintf (tbuf, sizeof(tbuf), " %d", val);
 			failover_print (obuf, obufix, obufmax, tbuf);
 #endif
 			putULong (&option.data [4 + i * 4], val);
@@ -3661,7 +3661,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
 #if defined (DEBUG_FAILOVER_MESSAGES)
 		for (i = 0; i < count; i++) {
 			/* 23 bytes plus nul, safe. */
-			sprintf (tbuf, " %d", bval [i]);
+			snprintf (tbuf, sizeof(tbuf), " %d", bval [i]);
 			failover_print (obuf, obufix, obufmax, tbuf);
 		}
 #endif
@@ -3699,7 +3699,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
 #if defined (DEBUG_FAILOVER_MESSAGES)
 		for (i = 4; i < size; i++) {
 			/*%Audit% Cannot exceed 24 bytes. %2004.06.17,Safe%*/
-			sprintf (tbuf, " %d", option.data [i]);
+			snprintf (tbuf, sizeof(tbuf), " %d", option.data [i]);
 			failover_print (obuf, obufix, obufmax, tbuf);
 		}
 #endif
@@ -3710,7 +3710,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
 			val = va_arg (va, u_int32_t);
 #if defined (DEBUG_FAILOVER_MESSAGES)
 			/*%Audit% Cannot exceed 24 bytes. %2004.06.17,Safe%*/
-			sprintf (tbuf, " %d", val);
+			snprintf (tbuf, sizeof(tbuf), " %d", val);
 			failover_print (obuf, obufix, obufmax, tbuf);
 #endif
 			putUShort (&option.data [4 + i * 2], val);
diff --git a/server/omapi.c b/server/omapi.c
index c87f05b..f807c5d 100644
--- a/server/omapi.c
+++ b/server/omapi.c
@@ -1186,7 +1186,7 @@ isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
 
 		if (!host -> name) {
 			char hnbuf [64];
-			sprintf (hnbuf, "nh%08lx%08lx",
+			snprintf (hnbuf, sizeof(hnbuf), "nh%08lx%08lx",
 				 (unsigned long)cur_time, (unsigned long)host);
 			host -> name = dmalloc (strlen (hnbuf) + 1, MDL);
 			if (!host -> name)
 
projeto & código: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
mantenedor atual: Michael Shigorin
mantenedor da tradução: Fernando Martini aka fmartini © 2009