Blame SOURCES/ntp-4.2.6p4-droproot.patch

473877
diff -up ntp-4.2.6p4/html/ntpdate.html.droproot ntp-4.2.6p4/html/ntpdate.html
473877
--- ntp-4.2.6p4/html/ntpdate.html.droproot	2011-07-11 04:18:25.000000000 +0200
473877
+++ ntp-4.2.6p4/html/ntpdate.html	2011-10-05 15:47:29.643634928 +0200
473877
@@ -18,7 +18,7 @@
473877
 		
473877
 		

Disclaimer: The functionality of this program is now available in the <tt>ntpd</tt> program. See the <tt>-q</tt> command line option in the <tt>ntpd</tt> - Network Time Protocol (NTP) daemon page. After a suitable period of mourning, the <tt>ntpdate</tt> program is to be retired from this distribution

473877
 		

Synopsis

473877
-		<tt>ntpdate [ -46bBdqsuv ] [ -a key ] [ -e authdelay ] [ -k keyfile ] [ -o version ] [ -p samples ] [ -t timeout ] server [ ... ]</tt>
473877
+		<tt>ntpdate [ -46bBdqsuv ] [ -a key ] [ -e authdelay ] [ -k keyfile ] [ -o version ] [ -p samples ] [ -t timeout ] [ -U user_name ] server [ ... ]</tt>
473877
 		

Description

473877
 		

<tt>ntpdate</tt> sets the local date and time by polling the Network Time Protocol (NTP) server(s) given as the server arguments to determine the correct time. It must be run as root on the local host. A number of samples are obtained from each of the servers specified and a subset of the NTP clock filter and selection algorithms are applied to select the best of these. Note that the accuracy and reliability of <tt>ntpdate</tt> depends on the number of servers, the number of polls each time it is run and the interval between runs.

473877
 		

<tt>ntpdate</tt> can be run manually as necessary to set the host clock, or it can be run from the host startup script to set the clock at boot time. This is useful in some cases to set the clock initially before starting the NTP daemon <tt>ntpd</tt>. It is also possible to run <tt>ntpdate</tt> from a <tt>cron</tt> script. However, it is important to note that <tt>ntpdate</tt> with contrived <tt>cron</tt> scripts is no substitute for the NTP daemon, which uses sophisticated algorithms to maximize accuracy and reliability while minimizing resource use. Finally, since <tt>ntpdate</tt> does not discipline the host clock frequency as does <tt>ntpd</tt>, the accuracy using <tt>ntpdate</tt> is limited.

473877
@@ -58,6 +58,10 @@
473877
 			
Direct <tt>ntpdate</tt> to use an unprivileged port for outgoing packets. This is most useful when behind a firewall that blocks incoming traffic to privileged ports, and you want to synchronize with hosts beyond the firewall. Note that the <tt>-d</tt> option always uses unprivileged ports.
473877
 			
<tt>-v</tt>
473877
 			
Be verbose. This option will cause <tt>ntpdate</tt>'s version identification string to be logged.
473877
+			
<tt>-U user_name</tt>
473877
+			
ntpdate process drops root privileges and changes user ID to
473877
+			user_name and group ID to the primary group of 
473877
+			server_user.
473877
 		
473877
 		

Diagnostics

473877
 		<tt>ntpdate</tt>'s exit status is zero if it finds a server and updates the clock, and nonzero otherwise.
473877
diff -up ntp-4.2.6p4/ntpdate/ntpdate.c.droproot ntp-4.2.6p4/ntpdate/ntpdate.c
473877
--- ntp-4.2.6p4/ntpdate/ntpdate.c.droproot	2011-05-25 07:06:09.000000000 +0200
473877
+++ ntp-4.2.6p4/ntpdate/ntpdate.c	2011-10-05 15:45:39.570555972 +0200
473877
@@ -49,6 +49,12 @@
473877
 
473877
 #include <arpa/inet.h>
473877
 
473877
+/* Linux capabilities */
473877
+#include <sys/capability.h>
473877
+#include <sys/prctl.h>
473877
+#include <pwd.h>
473877
+#include <grp.h>
473877
+
473877
 #ifdef SYS_VXWORKS
473877
 # include "ioLib.h"
473877
 # include "sockLib.h"
473877
@@ -153,6 +159,11 @@ int simple_query = 0;
473877
 int unpriv_port = 0;
473877
 
473877
 /*
473877
+ * Use capabilities to drop privileges and switch uids
473877
+ */
473877
+char *server_user;
473877
+
473877
+/*
473877
  * Program name.
473877
  */
473877
 char *progname;
473877
@@ -294,6 +305,88 @@ void clear_globals()
473877
 static ni_namelist *getnetinfoservers (void);
473877
 #endif
473877
 
473877
+/* This patch is adapted (copied) from Chris Wings drop root patch
473877
+ * for xntpd.
473877
+ */
473877
+void drop_root(uid_t server_uid, gid_t server_gid)
473877
+{
473877
+  cap_t caps;
473877
+
473877
+  if (prctl(PR_SET_KEEPCAPS, 1)) {
473877
+		if (syslogit) {
473877
+			msyslog(LOG_ERR, "prctl(PR_SET_KEEPCAPS, 1) failed");
473877
+		}
473877
+		else {
473877
+			fprintf(stderr, "prctl(PR_SET_KEEPCAPS, 1) failed.\n");
473877
+		}
473877
+    exit(1);
473877
+  }
473877
+
473877
+  if ( setgroups(0, NULL) == -1 ) {
473877
+		if (syslogit) {
473877
+			msyslog(LOG_ERR, "setgroups failed.");
473877
+		}
473877
+		else {
473877
+			fprintf(stderr, "setgroups failed.\n");
473877
+		}
473877
+    exit(1);
473877
+  }
473877
+
473877
+  if ( setegid(server_gid) == -1 || seteuid(server_uid) == -1 ) {
473877
+		if (syslogit) {
473877
+			msyslog(LOG_ERR, "setegid/seteuid to uid=%d/gid=%d failed.", server_uid,
473877
+							server_gid);
473877
+		}
473877
+		else {
473877
+			fprintf(stderr, "setegid/seteuid to uid=%d/gid=%d failed.\n", server_uid,
473877
+							server_gid);
473877
+		}
473877
+    exit(1);
473877
+  }
473877
+
473877
+  caps = cap_from_text("cap_sys_time=epi");
473877
+  if (caps == NULL) {
473877
+		if (syslogit) {
473877
+			msyslog(LOG_ERR, "cap_from_text failed.");
473877
+		}
473877
+		else {
473877
+			fprintf(stderr, "cap_from_text failed.\n");
473877
+		}
473877
+    exit(1);
473877
+  }
473877
+
473877
+  if (cap_set_proc(caps) == -1) {
473877
+		if (syslogit) {
473877
+			msyslog(LOG_ERR, "cap_set_proc failed.");
473877
+		}
473877
+		else {
473877
+			fprintf(stderr, "cap_set_proc failed.\n");
473877
+		}
473877
+    exit(1);
473877
+  }
473877
+  
473877
+  /* Try to free the memory from cap_from_text */
473877
+  cap_free( caps );
473877
+
473877
+  if ( setregid(server_gid, server_gid) == -1 ||
473877
+       setreuid(server_uid, server_uid) == -1 ) {
473877
+		if (syslogit) {
473877
+			msyslog(LOG_ERR, "setregid/setreuid to uid=%d/gid=%d failed.",
473877
+							server_uid, server_gid);
473877
+		}
473877
+		else {
473877
+			fprintf(stderr, "setregid/setreuid to uid=%d/gid=%d failed.\n",
473877
+							server_uid, server_gid);
473877
+		}
473877
+    exit(1);
473877
+  }
473877
+
473877
+	if (syslogit) {
473877
+		msyslog(LOG_DEBUG, "running as uid(%d)/gid(%d) euid(%d)/egid(%d).",
473877
+						getuid(), getgid(), geteuid(), getegid());
473877
+	}
473877
+}
473877
+
473877
 /*
473877
  * Main program.  Initialize us and loop waiting for I/O and/or
473877
  * timer expiries.
473877
@@ -341,6 +434,8 @@ ntpdatemain (
473877
 
473877
 	init_lib();	/* sets up ipv4_works, ipv6_works */
473877
 
473877
+	server_user = NULL;
473877
+
473877
 	/* Check to see if we have IPv6. Otherwise default to IPv4 */
473877
 	if (!ipv6_works)
473877
 		ai_fam_templ = AF_INET;
473877
@@ -352,7 +447,7 @@ ntpdatemain (
473877
 	/*
473877
 	 * Decode argument list
473877
 	 */
473877
-	while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qst:uv")) != EOF)
473877
+ 	while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qst:uvU:")) != EOF)
473877
 		switch (c)
473877
 		{
473877
 		case '4':
473877
@@ -429,6 +524,14 @@ ntpdatemain (
473877
 		case 'u':
473877
 			unpriv_port = 1;
473877
 			break;
473877
+ 		case 'U':
473877
+ 			if (ntp_optarg) {
473877
+ 				server_user = strdup(ntp_optarg);
473877
+ 			}
473877
+ 			else {
473877
+ 				++errflg;
473877
+ 			}
473877
+ 			break;
473877
 		case '?':
473877
 			++errflg;
473877
 			break;
473877
@@ -438,7 +541,7 @@ ntpdatemain (
473877
 	
473877
 	if (errflg) {
473877
 		(void) fprintf(stderr,
473877
-		    "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-t timeo] server ...\n",
473877
+		    "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-t timeo] [-U username] server ...\n",
473877
 		    progname);
473877
 		exit(2);
473877
 	}
473877
@@ -544,6 +647,24 @@ ntpdatemain (
473877
 	initializing = 0;
473877
 	was_alarmed = 0;
473877
 
473877
+	if (server_user) {
473877
+		struct passwd *pwd = NULL;
473877
+
473877
+		/* Lookup server_user uid/gid before chroot/chdir */
473877
+		pwd = getpwnam( server_user );
473877
+		if ( pwd == NULL ) {
473877
+			if (syslogit) {
473877
+				msyslog(LOG_ERR, "Failed to lookup user '%s'.", server_user);
473877
+			}
473877
+			else {
473877
+				fprintf(stderr, "Failed to lookup user '%s'.\n", server_user);
473877
+			}
473877
+			exit(1);
473877
+		}
473877
+		drop_root(pwd->pw_uid, pwd->pw_gid);
473877
+	}
473877
+
473877
+
473877
 	while (complete_servers < sys_numservers) {
473877
 #ifdef HAVE_POLL_H
473877
 		struct pollfd* rdfdes;