Ejemplo n.º 1
0
int sss_get_seuser(const char *linuxuser,
                   char **selinuxuser,
                   char **level)
{
    int ret;
    semanage_handle_t *handle;

    handle = semanage_handle_create();
    if (handle == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux management handle\n");
        return EIO;
    }

    semanage_msg_set_callback(handle,
                              sss_semanage_error_callback,
                              NULL);

    /* We only needed the handle for this call. Close the handle right
     * after it */
    ret = sss_is_selinux_managed(handle);
    sss_semanage_close(handle);
    if (ret != EOK) {
        return ret;
    }

    return getseuserbyname(linuxuser, selinuxuser, level);
}
Ejemplo n.º 2
0
static const security_context_t 
selinux_get_user_context(const char *name)
{
	security_context_t user_context=NULL;
	char *role=NULL;
	int ret = -1;
	char *seuser=NULL;
	char *level=NULL;

	if (the_authctxt) 
          role=the_authctxt->role;
        if (getseuserbyname(name, &seuser, &level)==0) {
          if (role != NULL && role[0])
            ret=get_default_context_with_rolelevel(seuser, role, level,NULL,
                                                   &user_context);
          else
            ret=get_default_context_with_level(seuser, level, NULL,&user_context);
        }
	if ( ret < 0 ) {
          if (security_getenforce() > 0)
            fatal("Failed to get default security context for %s.",
                  name);
          else
            error("Failed to get default security context for %s."
                  "Continuing in permissive mode",
                  name);
	}
	return user_context;
}
Ejemplo n.º 3
0
int main(int argc, char **argv) 
{
  char *seuser = NULL, *level = NULL;
  security_context_t *contextlist;
  int rc, n, i;
 
  if (argc != 3) {
	fprintf(stderr, "usage:  %s linuxuser fromcon\n", argv[0]);
	exit(1);
  }

  rc = getseuserbyname(argv[1], &seuser, &level);
  if (rc) {
	  fprintf(stderr, "getseuserbyname failed:  %s\n", strerror(errno));
	  exit(2);
  }
  printf("seuser:  %s, level %s\n", seuser, level);
  n = get_ordered_context_list_with_level(seuser, level, argv[2], &contextlist);
  if (n <= 0) {
	  fprintf(stderr, "get_ordered_context_list_with_level failed:  %s\n", strerror(errno));
	  exit(3);
  }
  free(seuser);
  free(level);
  for (i = 0; i < n; i++)
	printf("Context %d\t%s\n", i, contextlist[i]);
  freeconary(contextlist);
  exit(0);
}
Ejemplo n.º 4
0
/* Return the default security context for the given username */
static security_context_t
ssh_selinux_getctxbyname(char *pwname)
{
	security_context_t sc = NULL;
	char *sename = NULL, *lvl = NULL;
	int r;

#ifdef HAVE_GETSEUSERBYNAME
	if (getseuserbyname(pwname, &sename, &lvl) != 0)
		return NULL;
#else
	sename = pwname;
	lvl = NULL;
#endif

#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
	r = get_default_context_with_level(sename, lvl, NULL, &sc);
#else
	r = get_default_context(sename, NULL, &sc);
#endif

	if (r != 0) {
		switch (security_getenforce()) {
		case -1:
			fatal("%s: ssh_selinux_getctxbyname: "
			    "security_getenforce() failed", __func__);
		case 0:
			error("%s: Failed to get default SELinux security "
			    "context for %s", __func__, pwname);
			sc = NULL;
			break;
		default:
			fatal("%s: Failed to get default SELinux security "
			    "context for %s (in enforcing mode)",
			    __func__, pwname);
		}
	}

#ifdef HAVE_GETSEUSERBYNAME
	if (sename != NULL)
		xfree(sename);
	if (lvl != NULL)
		xfree(lvl);
#endif

	return sc;
}
Ejemplo n.º 5
0
/* selinux_prepare_fork - Initialize context switching
 *
 * Returns
 *  - 0 if everything is OK, 
 *  - +1 if the code should continue, even if SELinux wouldn't allow
 *       (for instance due to permissive mode)
 *  - -1 if the code should not continue
 */
int selinux_prepare_fork(char * name) {
#ifndef SELINUX
  return 0;
#else
  char * newcon = 0;
  char * curcon = 0;
  struct av_decision avd;
  int rc;
  int permissive = 0;
  int dom_permissive = 0;

  char * sename = 0;
  char * selevel = 0;

  /*
   * See if SELinux is enabled.
   * If not, then we can immediately tell the code
   * that everything is OK.
   */
  rc = is_selinux_enabled();
  if (rc == 0) {
    out(DEBUG, "SELinux is not enabled.\n");
    return 0;
  } else if (rc == -1) {
    out(WARN, "Could not check SELinux state (is_selinux_enabled() failed)\n");
    return 1;
  };
  out(DEBUG, "SELinux is enabled.\n");

  /*
   * See if SELinux is in enforcing mode
   * or permissive mode
   */
  rc = security_getenforce();
  if (rc == 0) {
    permissive = 1;
  } else if (rc == 1) {
    permissive = 0;
  } else {
    out(WARN, "Could not check SELinux mode (security_getenforce() failed)\n");
  }
  out(DEBUG, "SELinux mode is %s\n", permissive ? "permissive" : "enforcing");

  /*
   * Get the current SELinux context of the process.
   * Always interesting to log this for end users
   * trying to debug a possible issue.
   */
  rc = getcon(&curcon);
  if (rc) {
    out(WARN, "Could not get current SELinux context (getcon() failed)\n");
    if (permissive)
      return +1;
    else
      return -1;
  };
  out(DEBUG, "Currently in SELinux context \"%s\"\n", (char *) curcon);
 
  /*
   * Get the SELinux user given the Linux user
   * name passed on to this function.
   */
  rc = getseuserbyname(name, &sename, &selevel);
  if (rc) {
    out(WARN, "Could not find SELinux user for Linux user \"%s\" (getseuserbyname() failed)\n", name);
    freecon(curcon);
    if (permissive)
      return +1;
    else
      return -1;
  };
  out(DEBUG, "SELinux user for Linux user \"%s\" is \"%s\"\n", name, sename);

  /*
   * Find out what the context is that this process should transition
   * to.
   */
  rc = get_default_context(sename, NULL, &newcon);
  if (rc) {
    out(WARN, "Could not deduce default context for SELinux user \"%s\" given our current context (\"%s\")\n", sename, (char *) curcon);
    freecon(curcon);
    if (permissive)
      return +1;
    else
      return -1;
  };
  out(DEBUG, "SELinux context to transition to is \"%s\"\n", (char *) newcon);

  /*
   * Now let's look if we are allowed to transition to the new context.
   * We currently only check the transition access for the process class. However,
   * transitioning is a bit more complex (execute rights on target context, 
   * entrypoint of that context for the new domain, no constraints like target
   * domain not being a valid one, MLS constraints, etc.).
   */
  rc = security_compute_av_flags(curcon, newcon, SECCLASS_PROCESS, PROCESS__TRANSITION, &avd);
  if (rc) {
    out(WARN, "Could not deduce rights for transitioning \"%s\" -> \"%s\" (security_compute_av_flags() failed)\n", (char *) curcon, (char *) newcon);
    freecon(curcon);
    freecon(newcon);
    if (permissive)
      return +1;
    else
      return -1;
  };
  /* Validate the response 
   *
   * We are interested in two things:
   * - Is the transition allowed, but also
   * - Is the permissive flag set
   *
   * If the permissive flag is set, then we
   * know the current domain is permissive
   * (even if the rest of the system is in
   * enforcing mode).
   */
  if (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE) {
    out(DEBUG, "The SELINUX_AVD_FLAGS_PERMISSIVE flag is set, so domain is permissive.\n");
    dom_permissive = 1;
  };
  if (!(avd.allowed & PROCESS__TRANSITION)) {
    // The transition is denied
    if (permissive) {
      out(DEBUG, "Transition is not allowed by SELinux, but permissive mode is enabled. Continuing.\n");
    };
    if (dom_permissive) {
      out(DEBUG, "Transition is not allowed by SELinux, but domain is in permissive mode. Continuing.\n");
    };
    if ((permissive == 0) && (dom_permissive == 0)) {
      out(WARN, "The domain transition is not allowed and we are not in permissive mode.\n");
      freecon(curcon);
      freecon(newcon);
      return -1;
    };
  };


  /*
   * Set the context for the fork (process execution).
   */
  rc = setexeccon(newcon);
  if (rc) {
    out(WARN, "Could not set execution context (setexeccon() failed)\n");
    freecon(curcon);
    freecon(newcon);
    if ((permissive) || (dom_permissive))
      return +1;
    else
      return -1;
  };

  freecon(newcon);
  freecon(curcon);

  return 0;
#endif
};
Ejemplo n.º 6
0
// sushell.cmt
static
void sushell(struct passwd *pwd)
{
	char shell[128];
	char home[128];
	char *p;
	char *sushell;

	/*
	 *	Set directory and shell.
	 */
	(void)chdir(pwd->pw_dir);
	if ((p = getenv("SUSHELL")) != NULL)
		sushell = p;
	else if ((p = getenv("sushell")) != NULL)
		sushell = p;
	else {
		if (pwd->pw_shell[0])
			sushell = pwd->pw_shell;
		else
			sushell = BINSH;
	}
	if ((p = strrchr(sushell, '/')) == NULL)
		p = sushell;
	else
		p++;
	snprintf(shell, sizeof(shell), profile ? "-%s" : "%s", p);

	/*
	 *	Set some important environment variables.
	 */
	getcwd(home, sizeof(home));
	setenv("HOME", home, 1);
	setenv("LOGNAME", "root", 1);
	setenv("USER", "root", 1);
	if (!profile)
		setenv("SHLVL","0",1);

	/*
	 *	Try to execute a shell.
	 */
	setenv("SHELL", sushell, 1);
	signal(SIGINT,  saved_sigint);
	signal(SIGTSTP, saved_sigtstp);
	signal(SIGQUIT, saved_sigquit);
#ifdef WITH_SELINUX
	if (is_selinux_enabled() > 0) {
	  security_context_t scon=NULL;
	  char *seuser=NULL;
	  char *level=NULL;
	  if (getseuserbyname("root", &seuser, &level) == 0)
		  if (get_default_context_with_level(seuser, level, 0, &scon) == 0) {
			  if (setexeccon(scon) != 0) 
				  fprintf(stderr, "setexeccon faile\n");
			  freecon(scon);
		  }
		free(seuser);
		free(level);
	}
#endif
	execl(sushell, shell, NULL);
	perror(sushell);

	setenv("SHELL", BINSH, 1);
	execl(BINSH, profile ? "-sh" : "sh", NULL);
	perror(BINSH);

	/* Fall back to staticly linked shell if both the users shell
	   and /bin/sh failed to execute. */
	setenv("SHELL", STATICSH, 1);
	execl(STATICSH, STATICSH, NULL);
	perror(STATICSH);
}
Ejemplo n.º 7
0
/*
 * Password was OK, execute a shell.
 */
static void sushell(struct passwd *pwd)
{
	char shell[PATH_MAX];
	char home[PATH_MAX];
	char *p;
	char *su_shell;

	/*
	 * Set directory and shell.
	 */
	if (chdir(pwd->pw_dir) != 0) {
		warn(_("%s: change directory failed"), pwd->pw_dir);
		printf(_("Logging in with home = \"/\".\n"));

		if (chdir("/") != 0)
			warn(_("change directory to system root failed"));
	}

	if ((p = getenv("SUSHELL")) != NULL)
		su_shell = p;
	else if ((p = getenv("sushell")) != NULL)
		su_shell = p;
	else {
		if (pwd->pw_shell[0])
			su_shell = pwd->pw_shell;
		else
			su_shell = "/bin/sh";
	}
	if ((p = strrchr(su_shell, '/')) == NULL)
		p = su_shell;
	else
		p++;

	snprintf(shell, sizeof(shell), profile ? "-%s" : "%s", p);

	/*
	 * Set some important environment variables.
	 */
	if (getcwd(home, sizeof(home)) != NULL)
		setenv("HOME", home, 1);

	setenv("LOGNAME", "root", 1);
	setenv("USER", "root", 1);
	if (!profile)
		setenv("SHLVL","0",1);

	/*
	 * Try to execute a shell.
	 */
	setenv("SHELL", su_shell, 1);
	unmask_signal(SIGINT, &saved_sigint);
	unmask_signal(SIGTSTP, &saved_sigtstp);
	unmask_signal(SIGQUIT, &saved_sigquit);

#ifdef HAVE_LIBSELINUX
	if (is_selinux_enabled() > 0) {
		security_context_t scon=NULL;
		char *seuser=NULL;
		char *level=NULL;
		if (getseuserbyname("root", &seuser, &level) == 0) {
			if (get_default_context_with_level(seuser, level, 0, &scon) == 0) {
				if (setexeccon(scon) != 0)
					warnx(_("setexeccon failed"));
				freecon(scon);
			}
		}
		free(seuser);
		free(level);
	}
#endif
	execl(su_shell, shell, NULL);
	warn(_("%s: exec failed"), su_shell);

	setenv("SHELL", "/bin/sh", 1);
	execl("/bin/sh", profile ? "-sh" : "sh", NULL);
	warn(_("%s: exec failed"), "/bin/sh");
}
Ejemplo n.º 8
0
int getseuser(const char *username, const char *service, 
	      char **r_seuser, char **r_level) {
	int ret = -1;
	int len = 0;
	char *seuser = NULL;
	char *level = NULL;
	char *buffer = NULL;
	size_t size = 0;
	char *rec = NULL;
	char *path = NULL;
	FILE *fp = NULL;
	if (asprintf(&path,"%s/logins/%s", selinux_policy_root(), username) <  0)
		goto err;
	fp = fopen(path, "re");
	free(path);
	if (fp == NULL) goto err;
	__fsetlocking(fp, FSETLOCKING_BYCALLER);
	while (getline(&buffer, &size, fp) > 0) {
		if (strncmp(buffer, "*:", 2) == 0) {
			free(rec);
			rec = strdup(buffer);
			continue;
		}
		if (!service)
			continue;
		len = strlen(service);
		if ((strncmp(buffer, service, len) == 0) &&
		    (buffer[len] == ':')) {
			free(rec);
			rec = strdup(buffer);
			break;
		}
	}

	if (! rec)  goto err;
	seuser = strchr(rec, ':');
	if (! seuser) goto err;

	seuser++;
	level = strchr(seuser, ':');
	if (! level) goto err;
	*level = 0;
	level++;
	*r_seuser = strdup(seuser);
	if (! *r_seuser) goto err;

	len = strlen(level);
	if (len && level[len-1] == '\n')
		level[len-1] = 0;

	*r_level = strdup(level);
	if (! *r_level) {
		free(*r_seuser);
		goto err;
	}
	ret = 0;

	err:
	free(buffer);
	if (fp) fclose(fp);
	free(rec);

	return (ret ? getseuserbyname(username, r_seuser, r_level) : ret);
}
Ejemplo n.º 9
0
static int get_security_context(char *name, int crontab_fd, security_context_t
                                *rcontext, char *tabname) {
    security_context_t *context_list = NULL;
    security_context_t current_con;
    int list_count = 0;
    security_context_t  file_context=NULL;
    struct av_decision avd;
    int retval=0;
    char *seuser = NULL;
    char *level = NULL;
    int i;

    if (name != NULL) {
        if (getseuserbyname(name, &seuser, &level)) {
            log_it(name, getpid(), "getseuserbyname FAILED", tabname);
            return (security_getenforce() > 0);
        }
    }
    else
    {
        seuser = strdup("system_u");
    }

    *rcontext = NULL;
    if(getcon(&current_con)) {
        log_it(name, getpid(), "Can't get current context", tabname);
        return -1;
    }
    list_count = get_ordered_context_list_with_level(seuser, level, current_con, &context_list);
    freecon(current_con);
    free(seuser);
    free(level);
    if (list_count == -1) {
        if (security_getenforce() > 0) {
            log_it(name, getpid(), "No SELinux security context", tabname);
            return -1;
        } else {
            log_it(name, getpid(),
                   "No security context but SELinux in permissive mode,"
                   " continuing", tabname);
	    return 0;
        }
    }

    if (fgetfilecon(crontab_fd, &file_context) < OK) {
        if (security_getenforce() > 0) {
            log_it(name, getpid(), "getfilecon FAILED", tabname);
            freeconary(context_list);
            return -1;
        } else {
            log_it(name, getpid(), "getfilecon FAILED but SELinux in "
                   "permissive mode, continuing", tabname);
            *rcontext = strdup(context_list[0]);
            freeconary(context_list);
            return 0;
        }
    }

    /*
     * Since crontab files are not directly executed,
     * crond must ensure that the crontab file has
     * a context that is appropriate for the context of
     * the user cron job.  It performs an entrypoint
     * permission check for this purpose.
     */

    for(i = 0; i < list_count; i++)
    {
        retval = security_compute_av(context_list[i],
                                 file_context,
                                 SECCLASS_FILE,
                                 FILE__ENTRYPOINT,
                                 &avd);
        if(!retval && ((FILE__ENTRYPOINT & avd.allowed) == FILE__ENTRYPOINT)) {
            *rcontext = strdup(context_list[i]);
            freecon(file_context);
            freeconary(context_list);
            return 0;
        }
    }
    freecon(file_context);
    if (security_getenforce() > 0) {
        log_it(name, getpid(), "ENTRYPOINT FAILED", tabname);
        freeconary(context_list);
        return -1;
    } else {
        log_it(name, getpid(), "ENTRYPOINT FAILED but SELinux in permissive mode, continuing", tabname);
        *rcontext = strdup(context_list[0]);
        freeconary(context_list);
    }
    return 0;
}