components/proftpd/mod_solaris_priv.c
changeset 707 5953149bd743
parent 619 7e9d43a6a553
child 718 480dcaab9d63
equal deleted inserted replaced
706:6e61f0012046 707:5953149bd743
     1 /*
     1 /*
     2  * ProFTPD - FTP server daemon
     2  * ProFTPD - FTP server daemon
     3  * Copyright (c) 1997, 1998 Public Flood Software
     3  * Copyright (c) 1997, 1998 Public Flood Software
     4  * Copyright (c) 2003-2010 The ProFTPD Project team
     4  * Copyright (c) 2003-2010 The ProFTPD Project team
     5  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     5  * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
     6  *
     6  *
     7  * This program is free software; you can redistribute it and/or modify
     7  * This program is free software; you can redistribute it and/or modify
     8  * it under the terms of the GNU General Public License as published by
     8  * it under the terms of the GNU General Public License as published by
     9  * the Free Software Foundation; either version 2 of the License, or
     9  * the Free Software Foundation; either version 2 of the License, or
    10  * (at your option) any later version.
    10  * (at your option) any later version.
   167     /* Needed to call settaskid(). */
   167     /* Needed to call settaskid(). */
   168     priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_TASKID, NULL);
   168     priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_TASKID, NULL);
   169 
   169 
   170     /* Needed to access /dev/urandom. */
   170     /* Needed to access /dev/urandom. */
   171     priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DEVICES, NULL);
   171     priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DEVICES, NULL);
       
   172 
       
   173     /* Needed for pam_unix_cred to chown files. */
       
   174     priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_CHOWN_SELF, NULL);
       
   175 
       
   176     /* Needed to access /var/adm/wtmpx. */
       
   177     priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_DAC_WRITE, NULL);
   172 }
   178 }
   173 
   179 
   174 /* Setup priviledges before the user responds to the user prompt
   180 /* Setup priviledges before the user responds to the user prompt
   175  * from the ftp server so that a secure Kerberos session can be
   181  * from the ftp server so that a secure Kerberos session can be
   176  * established and also the user can login as root
   182  * established and also the user can login as root
   179 MODRET solaris_priv_pre_pass(cmd_rec *cmd) {
   185 MODRET solaris_priv_pre_pass(cmd_rec *cmd) {
   180     set_privs();
   186     set_privs();
   181     return PR_DECLINED(cmd);
   187     return PR_DECLINED(cmd);
   182 }
   188 }
   183 
   189 
       
   190 static priv_set_t* allocset(void) {
       
   191   priv_set_t* ret;
       
   192 
       
   193   if ((ret = priv_allocset()) == NULL) {
       
   194     pr_log_pri(PR_LOG_ERR, MOD_SOLARIS_PRIV_VERSION ": priv_allocset: %s",
       
   195       strerror(errno));
       
   196     pr_signals_unblock();
       
   197     end_login(1);
       
   198   }
       
   199 
       
   200   return ret;
       
   201 }
       
   202 
       
   203 static void delset(priv_set_t *sp, const char *priv) {
       
   204   if (priv_delset(sp, priv) != 0) {
       
   205     pr_log_pri(PR_LOG_ERR, MOD_SOLARIS_PRIV_VERSION ": priv_delset: %s",
       
   206       strerror(errno));
       
   207     pr_signals_unblock();
       
   208     end_login(1);
       
   209   }
       
   210 }
       
   211 
       
   212 static void addset(priv_set_t *sp, const char *priv) {
       
   213   if (priv_addset(sp, priv) != 0) {
       
   214     pr_log_pri(PR_LOG_ERR, MOD_SOLARIS_PRIV_VERSION ": priv_addset: %s",
       
   215       strerror(errno));
       
   216     pr_signals_unblock();
       
   217     end_login(1);
       
   218   }
       
   219 }
       
   220 
       
   221 static void _setppriv(priv_op_t op, priv_ptype_t which, priv_set_t *set) {
       
   222   if (setppriv(op, which, set) != 0) {
       
   223     pr_log_pri(PR_LOG_ERR, MOD_SOLARIS_PRIV_VERSION ": setppriv: %s",
       
   224       strerror(errno));
       
   225     pr_signals_unblock();
       
   226     end_login(1);
       
   227   }
       
   228 }
       
   229 
   184 /* The POST_CMD handler for "PASS" is only called after PASS has
   230 /* The POST_CMD handler for "PASS" is only called after PASS has
   185  * successfully completed, which means authentication is successful,
   231  * successfully completed, which means authentication is successful,
   186  * so we can "tweak" our root access down to almost nothing.
   232  * so we can "tweak" our root access down to almost nothing.
   187  */
   233  */
   188 MODRET solaris_priv_post_pass(cmd_rec *cmd) {
   234 MODRET solaris_priv_post_pass(cmd_rec *cmd) {
   189   int res = 0;
   235   int res = 0;
   190   priv_set_t *p, *i;
   236   priv_set_t *ps = NULL;
   191 
   237 
   192   if (!use_privs)
   238   if (!use_privs)
   193     return PR_DECLINED(cmd);
   239     return PR_DECLINED(cmd);
   194 
   240 
   195   pr_signals_block();
   241   pr_signals_block();
   201    *
   247    *
   202    * We also remove the basic Solaris privileges we know we will
   248    * We also remove the basic Solaris privileges we know we will
   203    * never need.
   249    * never need.
   204    */
   250    */
   205 
   251 
   206   i = priv_allocset();
   252   ps = allocset();
   207   priv_basicset(i);
   253   priv_basicset(ps);
   208   priv_delset(i, PRIV_PROC_EXEC);
   254   delset(ps, PRIV_PROC_EXEC);
   209   priv_delset(i, PRIV_PROC_FORK);
   255   delset(ps, PRIV_PROC_FORK);
   210   priv_delset(i, PRIV_PROC_INFO);
   256   delset(ps, PRIV_PROC_INFO);
   211   priv_delset(i, PRIV_PROC_SESSION);
   257   delset(ps, PRIV_PROC_SESSION);
   212   setppriv(PRIV_SET, PRIV_INHERITABLE, i);
   258   _setppriv(PRIV_SET, PRIV_INHERITABLE, ps);
   213 
   259 
   214   p = priv_allocset();
   260   priv_basicset(ps);
   215   priv_basicset(p);
   261 
   216 
   262   addset(ps, PRIV_NET_PRIVADDR);
   217   priv_addset(p, PRIV_NET_PRIVADDR);
   263   addset(ps, PRIV_PROC_AUDIT);
   218   priv_addset(p, PRIV_PROC_AUDIT);
   264 
   219 
   265   delset(ps, PRIV_PROC_EXEC);
   220   priv_delset(p, PRIV_PROC_EXEC);
   266   delset(ps, PRIV_PROC_FORK);
   221   priv_delset(p, PRIV_PROC_FORK);
   267   delset(ps, PRIV_PROC_INFO);
   222   priv_delset(p, PRIV_PROC_INFO);
   268   delset(ps, PRIV_PROC_SESSION);
   223   priv_delset(p, PRIV_PROC_SESSION);
       
   224 
   269 
   225   /* If the proftpd process is not running as root, but as user ftp,
   270   /* If the proftpd process is not running as root, but as user ftp,
   226    * then this is necessary in order to make the setreuid work.
   271    * then this is necessary in order to make the setreuid work.
   227    * Without this, the setreuid would fail. The PRIV_PROC_SETID privilege 
   272    * Without this, the setreuid would fail. The PRIV_PROC_SETID privilege 
   228    * is removed afterwards.
   273    * is removed afterwards.
   229    */
   274    */
   230   priv_addset(p, PRIV_PROC_SETID);
   275   addset(ps, PRIV_PROC_SETID);
   231 
   276 
   232   /* Add any of the configurable privileges. */
   277   /* Add any of the configurable privileges. */
   233   if (solaris_priv_flags & PRIV_USE_FILE_CHOWN)
   278   if (solaris_priv_flags & PRIV_USE_FILE_CHOWN)
   234     priv_addset(p, PRIV_FILE_CHOWN);
   279     addset(ps, PRIV_FILE_CHOWN);
   235 
   280 
   236   if (solaris_priv_flags & PRIV_USE_FILE_CHOWN_SELF)
   281   if (solaris_priv_flags & PRIV_USE_FILE_CHOWN_SELF)
   237     priv_addset(p, PRIV_FILE_CHOWN_SELF);
   282     addset(ps, PRIV_FILE_CHOWN_SELF);
   238 
   283 
   239   if (solaris_priv_flags & PRIV_USE_DAC_READ)
   284   if (solaris_priv_flags & PRIV_USE_DAC_READ)
   240     priv_addset(p, PRIV_FILE_DAC_READ);
   285     addset(ps, PRIV_FILE_DAC_READ);
   241 
   286 
   242   if (solaris_priv_flags & PRIV_USE_DAC_WRITE)
   287   if (solaris_priv_flags & PRIV_USE_DAC_WRITE)
   243     priv_addset(p, PRIV_FILE_DAC_WRITE);
   288     addset(ps, PRIV_FILE_DAC_WRITE);
   244 
   289 
   245   if (solaris_priv_flags & PRIV_USE_DAC_SEARCH)
   290   if (solaris_priv_flags & PRIV_USE_DAC_SEARCH)
   246     priv_addset(p, PRIV_FILE_DAC_SEARCH);
   291     addset(ps, PRIV_FILE_DAC_SEARCH);
   247 
   292 
   248   if (solaris_priv_flags & PRIV_USE_FILE_OWNER)
   293   if (solaris_priv_flags & PRIV_USE_FILE_OWNER)
   249     priv_addset(p, PRIV_FILE_OWNER);
   294     addset(ps, PRIV_FILE_OWNER);
   250 
   295 
   251   if (solaris_priv_flags & PRIV_DROP_FILE_WRITE)
   296   if (solaris_priv_flags & PRIV_DROP_FILE_WRITE)
   252     priv_delset(p, PRIV_FILE_WRITE);
   297     delset(ps, PRIV_FILE_WRITE);
   253 
   298 
   254   res = setppriv(PRIV_SET, PRIV_PERMITTED, p);
   299   _setppriv(PRIV_SET, PRIV_PERMITTED, ps);
   255   res = setppriv(PRIV_SET, PRIV_EFFECTIVE, p);
   300   _setppriv(PRIV_SET, PRIV_EFFECTIVE, ps);
   256 
   301 
   257   if (setreuid(session.uid, session.uid) == -1) {
   302   if (setreuid(session.uid, session.uid) == -1) {
   258     pr_log_pri(PR_LOG_ERR, MOD_SOLARIS_PRIV_VERSION ": setreuid: %s",
   303     pr_log_pri(PR_LOG_ERR, MOD_SOLARIS_PRIV_VERSION ": setreuid: %s",
   259       strerror(errno));
   304       strerror(errno));
   260     pr_signals_unblock();
   305     pr_signals_unblock();
   261     end_login(1);
   306     end_login(1);
   262   }
   307   }
   263 
   308 
   264   if (!(solaris_priv_flags & PRIV_USE_SETID)) {
   309   if (!(solaris_priv_flags & PRIV_USE_SETID)) {
   265     priv_delset(p, PRIV_PROC_SETID);
   310     delset(ps, PRIV_PROC_SETID);
   266     res = setppriv(PRIV_SET, PRIV_PERMITTED, p);
   311     _setppriv(PRIV_SET, PRIV_PERMITTED, ps);
   267     res = setppriv(PRIV_SET, PRIV_EFFECTIVE, p);
   312     _setppriv(PRIV_SET, PRIV_EFFECTIVE, ps);
   268   }
   313   }
       
   314 
       
   315   priv_freeset(ps);
   269 
   316 
   270   pr_signals_unblock();
   317   pr_signals_unblock();
   271 
   318 
   272   if (res != -1) {
   319   /* That's it!  Disable all further id switching */
   273     /* That's it!  Disable all further id switching */
   320   session.disable_id_switching = TRUE;
   274     session.disable_id_switching = TRUE;
       
   275 
       
   276   } else {
       
   277     pr_log_pri(PR_LOG_NOTICE, MOD_SOLARIS_PRIV_VERSION ": attempt to configure "
       
   278       "capabilities failed, reverting to normal operation");
       
   279   }
       
   280 
   321 
   281   return PR_DECLINED(cmd);
   322   return PR_DECLINED(cmd);
   282 }
   323 }
   283 
   324 
   284 /* Initialization routines
   325 /* Initialization routines