7087047 proftpd should support standard Kerberos client configuration
authortomas klacko - Sun Microsystems - Prague Czech Republic <tomas.klacko@oracle.com>
Tue, 13 Dec 2011 06:37:17 -0800
changeset 619 7e9d43a6a553
parent 618 9eb376524c7b
child 620 224989d93a26
7087047 proftpd should support standard Kerberos client configuration
components/proftpd/mod_solaris_priv.c
--- a/components/proftpd/mod_solaris_priv.c	Mon Dec 12 16:47:20 2011 -0800
+++ b/components/proftpd/mod_solaris_priv.c	Tue Dec 13 06:37:17 2011 -0800
@@ -139,6 +139,48 @@
 /* Command handlers
  */
 
+/* The pre and post adat command handlers first enable
+ * and then disable file_dac_read. This is done in order
+ * for the mod_gss module to be able to read /etc/krb5/krb5.keytab,
+ * when the proftpd server runs as user/group ftp/ftp.
+ */
+MODRET solaris_priv_pre_adat(cmd_rec *cmd) {
+    priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL);
+    return PR_DECLINED(cmd);
+}
+
+MODRET solaris_priv_post_adat(cmd_rec *cmd) {
+    priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL);
+    return PR_DECLINED(cmd);
+}
+
+static void set_privs(void) {
+    /* This is for PAM code which decides to create an audit session
+     * when the user is logging into ftp as root.
+     */
+    priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
+    priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_AUDIT, NULL);
+
+    /* Needed to call seteuid(). */
+    priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_SETID, NULL);
+
+    /* Needed to call settaskid(). */
+    priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_TASKID, NULL);
+
+    /* Needed to access /dev/urandom. */
+    priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DEVICES, NULL);
+}
+
+/* Setup priviledges before the user responds to the user prompt
+ * from the ftp server so that a secure Kerberos session can be
+ * established and also the user can login as root
+ * when the ftp server is running as user/group ftp/ftp.
+ */
+MODRET solaris_priv_pre_pass(cmd_rec *cmd) {
+    set_privs();
+    return PR_DECLINED(cmd);
+}
+
 /* The POST_CMD handler for "PASS" is only called after PASS has
  * successfully completed, which means authentication is successful,
  * so we can "tweak" our root access down to almost nothing.
@@ -180,8 +222,12 @@
   priv_delset(p, PRIV_PROC_INFO);
   priv_delset(p, PRIV_PROC_SESSION);
 
-  if (solaris_priv_flags & PRIV_USE_SETID)
-    priv_addset(p, PRIV_PROC_SETID);
+  /* If the proftpd process is not running as root, but as user ftp,
+   * then this is necessary in order to make the setreuid work.
+   * Without this, the setreuid would fail. The PRIV_PROC_SETID privilege 
+   * is removed afterwards.
+   */
+  priv_addset(p, PRIV_PROC_SETID);
 
   /* Add any of the configurable privileges. */
   if (solaris_priv_flags & PRIV_USE_FILE_CHOWN)
@@ -210,10 +256,17 @@
 
   if (setreuid(session.uid, session.uid) == -1) {
     pr_log_pri(PR_LOG_ERR, MOD_SOLARIS_PRIV_VERSION ": setreuid: %s",
-	strerror(errno));
+      strerror(errno));
     pr_signals_unblock();
     end_login(1);
   }
+
+  if (!(solaris_priv_flags & PRIV_USE_SETID)) {
+    priv_delset(p, PRIV_PROC_SETID);
+    res = setppriv(PRIV_SET, PRIV_PERMITTED, p);
+    res = setppriv(PRIV_SET, PRIV_EFFECTIVE, p);
+  }
+
   pr_signals_unblock();
 
   if (res != -1) {
@@ -349,6 +402,9 @@
 };
 
 static cmdtable solaris_priv_cmdtab[] = {
+  { PRE_CMD, C_ADAT, G_NONE, solaris_priv_pre_adat, FALSE, FALSE },
+  { POST_CMD, C_ADAT, G_NONE, solaris_priv_post_adat, FALSE, FALSE },
+  { PRE_CMD, C_PASS, G_NONE, solaris_priv_pre_pass, FALSE, FALSE },
   { POST_CMD, C_PASS, G_NONE, solaris_priv_post_pass, FALSE, FALSE },
   { 0, NULL }
 };