LCOV - code coverage report
Current view: top level - tools - sss_userdel.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 158 0.0 %
Date: 2015-10-19 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    sss_userdel
       5             : 
       6             :    Copyright (C) Jakub Hrozek <jhrozek@redhat.com>        2009
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include <nss.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <talloc.h>
      26             : #include <popt.h>
      27             : #include <sys/types.h>
      28             : #include <sys/wait.h>
      29             : 
      30             : #include "db/sysdb.h"
      31             : #include "util/util.h"
      32             : #include "util/find_uid.h"
      33             : #include "tools/tools_util.h"
      34             : #include "tools/sss_sync_ops.h"
      35             : 
      36             : #ifndef KILL_CMD
      37             : #define KILL_CMD "killall"
      38             : #endif
      39             : 
      40             : #ifndef KILL_CMD_USER_FLAG
      41             : #define KILL_CMD_USER_FLAG "-u"
      42             : #endif
      43             : 
      44             : #ifndef KILL_CMD_SIGNAL_FLAG
      45             : #define KILL_CMD_SIGNAL_FLAG "-s"
      46             : #endif
      47             : 
      48             : #ifndef KILL_CMD_SIGNAL
      49             : #define KILL_CMD_SIGNAL "SIGKILL"
      50             : #endif
      51             : 
      52           0 : static int is_logged_in(TALLOC_CTX *mem_ctx, uid_t uid)
      53             : {
      54             :     int ret;
      55             :     hash_key_t key;
      56             :     hash_value_t value;
      57             :     hash_table_t *uid_table;
      58             : 
      59           0 :     ret = get_uid_table(mem_ctx, &uid_table);
      60           0 :     if (ret == ENOSYS) return ret;
      61           0 :     if (ret != EOK) {
      62           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize hash table.\n");
      63           0 :         return ret;
      64             :     }
      65             : 
      66           0 :     key.type = HASH_KEY_ULONG;
      67           0 :     key.ul   = (unsigned long) uid;
      68             : 
      69           0 :     ret = hash_lookup(uid_table, &key, &value);
      70           0 :     talloc_zfree(uid_table);
      71           0 :     return ret == HASH_SUCCESS ? EOK : ENOENT;
      72             : }
      73             : 
      74           0 : static int kick_user(struct tools_ctx *tctx)
      75             : {
      76             :     int ret;
      77             :     int status;
      78             :     pid_t pid, child_pid;
      79             : 
      80           0 :     tctx->octx->lock = 1;
      81             : 
      82           0 :     ret = usermod(tctx, tctx->octx);
      83           0 :     if (ret != EOK) {
      84           0 :         return ret;
      85             :     }
      86             : 
      87           0 :     errno = 0;
      88           0 :     pid = fork();
      89           0 :     if (pid == 0) {
      90             :         /* child */
      91           0 :         execlp(KILL_CMD, KILL_CMD,
      92           0 :                KILL_CMD_USER_FLAG, tctx->octx->name,
      93             :                KILL_CMD_SIGNAL_FLAG, KILL_CMD_SIGNAL,
      94             :                (char *) NULL);
      95           0 :         exit(errno);
      96             :     } else {
      97             :         /* parent */
      98           0 :         if (pid == -1) {
      99           0 :             ret = errno;
     100           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     101             :                   "fork failed [%d]: %s\n", ret, strerror(ret));
     102           0 :             return ret;
     103             :         }
     104             : 
     105           0 :         while((child_pid = waitpid(pid, &status, 0)) > 0) {
     106             : 
     107           0 :             if (WIFEXITED(status)) {
     108           0 :                 break;
     109             :             }
     110             :         }
     111           0 :         if (child_pid == -1) {
     112           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "waitpid failed\n");
     113           0 :             return errno;
     114             :         }
     115             :     }
     116             : 
     117           0 :     return EOK;
     118             : }
     119             : 
     120           0 : int main(int argc, const char **argv)
     121             : {
     122           0 :     int ret = EXIT_SUCCESS;
     123           0 :     struct tools_ctx *tctx = NULL;
     124           0 :     const char *pc_username = NULL;
     125             : 
     126           0 :     int pc_debug = SSSDBG_DEFAULT;
     127           0 :     int pc_remove = 0;
     128           0 :     int pc_force = 0;
     129           0 :     int pc_kick = 0;
     130           0 :     poptContext pc = NULL;
     131           0 :     struct poptOption long_options[] = {
     132             :         POPT_AUTOHELP
     133             :         { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug,
     134           0 :                     0, _("The debug level to run with"), NULL },
     135             :         { "remove", 'r', POPT_ARG_NONE, NULL, 'r',
     136           0 :                     _("Remove home directory and mail spool"), NULL },
     137             :         { "no-remove", 'R', POPT_ARG_NONE, NULL, 'R',
     138           0 :                     _("Do not remove home directory and mail spool"), NULL },
     139             :         { "force", 'f', POPT_ARG_NONE, NULL, 'f',
     140           0 :                     _("Force removal of files not owned by the user"), NULL },
     141             :         { "kick", 'k', POPT_ARG_NONE, NULL, 'k',
     142           0 :                     _("Kill users' processes before removing him"), NULL },
     143             :         POPT_TABLEEND
     144             :     };
     145             : 
     146           0 :     debug_prg_name = argv[0];
     147             : 
     148           0 :     ret = set_locale();
     149           0 :     if (ret != EOK) {
     150           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     151             :               "set_locale failed (%d): %s\n", ret, strerror(ret));
     152           0 :         ERROR("Error setting the locale\n");
     153           0 :         ret = EXIT_FAILURE;
     154           0 :         goto fini;
     155             :     }
     156             : 
     157             :     /* parse parameters */
     158           0 :     pc = poptGetContext(NULL, argc, argv, long_options, 0);
     159           0 :     poptSetOtherOptionHelp(pc, "USERNAME");
     160           0 :     while ((ret = poptGetNextOpt(pc)) > 0) {
     161           0 :         switch (ret) {
     162             :             case 'r':
     163           0 :                 pc_remove = DO_REMOVE_HOME;
     164           0 :                 break;
     165             : 
     166             :             case 'R':
     167           0 :                 pc_remove = DO_NOT_REMOVE_HOME;
     168           0 :                 break;
     169             : 
     170             :             case 'f':
     171           0 :                 pc_force = DO_FORCE_REMOVAL;
     172           0 :                 break;
     173             : 
     174             :             case 'k':
     175           0 :                 pc_kick = 1;
     176           0 :                 break;
     177             :         }
     178             :     }
     179             : 
     180           0 :     DEBUG_CLI_INIT(pc_debug);
     181             : 
     182           0 :     if (ret != -1) {
     183           0 :         BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
     184             :     }
     185             : 
     186           0 :     pc_username = poptGetArg(pc);
     187           0 :     if (pc_username == NULL) {
     188           0 :         BAD_POPT_PARAMS(pc, _("Specify user to delete\n"), ret, fini);
     189             :     }
     190             : 
     191           0 :     CHECK_ROOT(ret, debug_prg_name);
     192             : 
     193           0 :     ret = init_sss_tools(&tctx);
     194           0 :     if (ret != EOK) {
     195           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     196             :               "init_sss_tools failed (%d): %s\n", ret, strerror(ret));
     197           0 :         if (ret == ENOENT) {
     198           0 :             ERROR("Error initializing the tools - no local domain\n");
     199             :         } else {
     200           0 :             ERROR("Error initializing the tools\n");
     201             :         }
     202           0 :         ret = EXIT_FAILURE;
     203           0 :         goto fini;
     204             :     }
     205             : 
     206             :     /* if the domain was not given as part of FQDN, default to local domain */
     207           0 :     ret = parse_name_domain(tctx, pc_username);
     208           0 :     if (ret != EOK) {
     209           0 :         ERROR("Invalid domain specified in FQDN\n");
     210           0 :         ret = EXIT_FAILURE;
     211           0 :         goto fini;
     212             :     }
     213             : 
     214             :     /*
     215             :      * Fills in defaults for ops_ctx user did not specify.
     216             :      */
     217           0 :     ret = userdel_defaults(tctx, tctx->confdb, tctx->octx, pc_remove);
     218           0 :     if (ret != EOK) {
     219           0 :         ERROR("Cannot set default values\n");
     220           0 :         ret = EXIT_FAILURE;
     221           0 :         goto fini;
     222             :     }
     223             : 
     224           0 :     ret = sysdb_getpwnam_sync(tctx,
     225           0 :                               tctx->octx->name,
     226           0 :                               tctx->octx);
     227           0 :     if (ret != EOK) {
     228             :         /* Error message will be printed in the switch */
     229           0 :         goto done;
     230             :     }
     231             : 
     232           0 :     if ((tctx->octx->uid < tctx->local->id_min) ||
     233           0 :         (tctx->local->id_max && tctx->octx->uid > tctx->local->id_max)) {
     234           0 :         ERROR("User %1$s is outside the defined ID range for domain\n",
     235             :               tctx->octx->name);
     236           0 :         ret = EXIT_FAILURE;
     237           0 :         goto fini;
     238             :     }
     239             : 
     240           0 :     if (pc_kick) {
     241           0 :         ret = kick_user(tctx);
     242           0 :         if (ret != EOK) {
     243           0 :             tctx->error = ret;
     244             : 
     245           0 :             goto done;
     246             :         }
     247             :     }
     248             : 
     249             :     /* userdel */
     250           0 :     ret = userdel(tctx, tctx->sysdb, tctx->octx);
     251           0 :     if (ret != EOK) {
     252           0 :         goto done;
     253             :     }
     254             : 
     255             :     /* Set SELinux login context - must be done after transaction is done
     256             :      * b/c libselinux calls getpwnam */
     257           0 :     ret = del_seuser(tctx->octx->name);
     258           0 :     if (ret != EOK) {
     259           0 :         ERROR("Cannot reset SELinux login context\n");
     260           0 :         ret = EXIT_FAILURE;
     261           0 :         goto fini;
     262             :     }
     263             : 
     264           0 :     if (!pc_kick) {
     265           0 :         ret = is_logged_in(tctx, tctx->octx->uid);
     266           0 :         switch(ret) {
     267             :             case ENOENT:
     268           0 :                 break;
     269             : 
     270             :             case EOK:
     271           0 :                 ERROR("WARNING: The user (uid %1$lu) was still logged in when "
     272             :                       "deleted.\n", (unsigned long) tctx->octx->uid);
     273           0 :                 break;
     274             : 
     275             :             case ENOSYS:
     276           0 :                 ERROR("Cannot determine if the user was logged in on this "
     277             :                       "platform");
     278           0 :                 break;
     279             : 
     280             :             default:
     281           0 :                 ERROR("Error while checking if the user was logged in\n");
     282           0 :                 break;
     283             :         }
     284             :     }
     285             : 
     286           0 :     ret = run_userdel_cmd(tctx);
     287           0 :     if (ret != EOK) {
     288           0 :         ERROR("The post-delete command failed: %1$s\n", strerror(ret));
     289           0 :         goto fini;
     290             :     }
     291             : 
     292             :     /* Delete user from memory cache */
     293           0 :     ret = sss_mc_refresh_user(pc_username);
     294           0 :     if (ret != EOK) {
     295           0 :         ERROR("NSS request failed (%1$d). Entry might remain in memory "
     296             :               "cache.\n", ret);
     297             :         /* Nothing we can do about it */
     298             :     }
     299             : 
     300           0 :     if (tctx->octx->remove_homedir) {
     301           0 :         ret = remove_homedir(tctx,
     302           0 :                              tctx->octx->home,
     303           0 :                              tctx->octx->maildir,
     304           0 :                              tctx->octx->name,
     305           0 :                              tctx->octx->uid,
     306             :                              pc_force);
     307           0 :         if (ret == EPERM) {
     308           0 :             ERROR("Not removing home dir - not owned by user\n");
     309           0 :         } else if (ret != EOK) {
     310           0 :             ERROR("Cannot remove homedir: %1$s\n", strerror(ret));
     311           0 :             ret = EXIT_FAILURE;
     312           0 :             goto fini;
     313             :         }
     314             :     }
     315             : 
     316           0 :     ret = EOK;
     317             : 
     318             : done:
     319           0 :     if (ret) {
     320           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     321             :               "sysdb operation failed (%d)[%s]\n", ret, strerror(ret));
     322           0 :         switch (ret) {
     323             :             case ENOENT:
     324           0 :                 ERROR("No such user in local domain. "
     325             :                       "Removing users only allowed in local domain.\n");
     326           0 :                 break;
     327             : 
     328             :             default:
     329           0 :                 ERROR("Internal error. Could not remove user.\n");
     330           0 :                 break;
     331             :         }
     332           0 :         ret = EXIT_FAILURE;
     333           0 :         goto fini;
     334             :     }
     335             : 
     336           0 :     ret = EXIT_SUCCESS;
     337             : 
     338             : fini:
     339           0 :     talloc_free(tctx);
     340           0 :     poptFreeContext(pc);
     341           0 :     exit(ret);
     342             : }
     343             : 

Generated by: LCOV version 1.10