Ejemplo n.º 1
0
static security_context_t
security_label_tty(pam_handle_t *pamh, char *tty,
		   security_context_t usercon)
{
  char ttybuf[PATH_MAX];
  int status=0;
  security_context_t newdev_context=NULL; /* The new context of a device */
  security_context_t prev_context=NULL; /* The new context of a device */
  const char *ptr;

  if(strncmp("/dev/", tty, 5))
  {
    snprintf(ttybuf,sizeof(ttybuf),"/dev/%s",tty);
    ptr = ttybuf;
  }
  else
    ptr = tty;

  if (getfilecon(ptr, &prev_context) < 0)
  {
    if(errno != ENOENT)
      pam_syslog(pamh, LOG_NOTICE,
	     "Warning!  Could not get current context for %s, not relabeling: %m",
	     ptr);
    return NULL;
  }
  if( security_compute_relabel(usercon,prev_context,SECCLASS_CHR_FILE,
                               &newdev_context)!=0)
  {
    pam_syslog(pamh, LOG_NOTICE,
           "Warning!  Could not get new context for %s, not relabeling: %m",
           ptr);
    pam_syslog(pamh, LOG_NOTICE,
	       "usercon=%s, prev_context=%s", usercon, prev_context);
    freecon(prev_context);
    return NULL;
  }
  status=setfilecon(ptr,newdev_context);
  if (status)
  {
      pam_syslog(pamh, LOG_NOTICE,
		 "Warning!  Could not relabel %s with %s, not relabeling: %m",
		 ptr,newdev_context);
      freecon(prev_context);
      prev_context=NULL;
  }
  freecon(newdev_context);
  return prev_context;
}
Ejemplo n.º 2
0
/* Set the TTY context for the specified user */
void
ssh_selinux_setup_pty(char *pwname, const char *tty)
{
	security_context_t new_tty_ctx = NULL;
	security_context_t user_ctx = NULL;
	security_context_t old_tty_ctx = NULL;

	if (!ssh_selinux_enabled())
		return;

	debug3("%s: setting TTY context on %s", __func__, tty);

	user_ctx = ssh_selinux_getctxbyname(pwname);

	/* XXX: should these calls fatal() upon failure in enforcing mode? */

	if (getfilecon(tty, &old_tty_ctx) == -1) {
		error("%s: getfilecon: %s", __func__, strerror(errno));
		goto out;
	}

	if (security_compute_relabel(user_ctx, old_tty_ctx,
	    SECCLASS_CHR_FILE, &new_tty_ctx) != 0) {
		error("%s: security_compute_relabel: %s",
		    __func__, strerror(errno));
		goto out;
	}

	if (setfilecon(tty, new_tty_ctx) != 0)
		error("%s: setfilecon: %s", __func__, strerror(errno));
 out:
	if (new_tty_ctx != NULL)
		freecon(new_tty_ctx);
	if (old_tty_ctx != NULL)
		freecon(old_tty_ctx);
	if (user_ctx != NULL)
		freecon(user_ctx);
	debug3("%s: done", __func__);
}
Ejemplo n.º 3
0
static void initselinux(char *username, char *full_tty,
                        security_context_t *user_sid)
{
    security_context_t old_tty_sid, new_tty_sid;

    if (!is_selinux_enabled())
        return;

    if (get_default_context(username, NULL, user_sid)) {
        bb_error_msg_and_die("can't get SID for %s", username);
    }
    if (getfilecon(full_tty, &old_tty_sid) < 0) {
        bb_perror_msg_and_die("getfilecon(%s) failed", full_tty);
    }
    if (security_compute_relabel(*user_sid, old_tty_sid,
                                 SECCLASS_CHR_FILE, &new_tty_sid) != 0) {
        bb_perror_msg_and_die("security_change_sid(%s) failed", full_tty);
    }
    if (setfilecon(full_tty, new_tty_sid) != 0) {
        bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, new_tty_sid);
    }
}
Ejemplo n.º 4
0
/*
 * This function attempts to relabel the tty. If this function fails, then
 * the contexts are free'd and -1 is returned. On success, 0 is returned
 * and tty_context and new_tty_context are set.
 *
 * This function will not fail if it can not relabel the tty when selinux is
 * in permissive mode.
 */
static int
relabel_tty(const char *ttyn, int ptyfd)
{
    security_context_t tty_con = NULL;
    security_context_t new_tty_con = NULL;
    struct stat sb;
    int fd;
    debug_decl(relabel_tty, SUDO_DEBUG_SELINUX)

    se_state.ttyfd = ptyfd;

    /* It is perfectly legal to have no tty. */
    if (ptyfd == -1 && ttyn == NULL)
	debug_return_int(0);

    /* If sudo is not allocating a pty for the command, open current tty. */
    if (ptyfd == -1) {
	se_state.ttyfd = open(ttyn, O_RDWR|O_NOCTTY|O_NONBLOCK);
	if (se_state.ttyfd == -1 || fstat(se_state.ttyfd, &sb) == -1) {
	    sudo_warn(U_("unable to open %s, not relabeling tty"), ttyn);
	    goto bad;
	}
	if (!S_ISCHR(sb.st_mode)) {
	    sudo_warn(U_("%s is not a character device, not relabeling tty"),
		ttyn);
	    goto bad;
	}
	(void)fcntl(se_state.ttyfd, F_SETFL,
	    fcntl(se_state.ttyfd, F_GETFL, 0) & ~O_NONBLOCK);
    }

    if (fgetfilecon(se_state.ttyfd, &tty_con) < 0) {
	sudo_warn(U_("unable to get current tty context, not relabeling tty"));
	goto bad;
    }

    if (tty_con) {
	security_class_t tclass = string_to_security_class("chr_file");
	if (tclass == 0) {
	    sudo_warn(U_("unknown security class \"chr_file\", not relabeling tty"));
	    goto bad;
	}
	if (security_compute_relabel(se_state.new_context, tty_con,
	    tclass, &new_tty_con) < 0) {
	    sudo_warn(U_("unable to get new tty context, not relabeling tty"));
	    goto bad;
	}
    }

    if (new_tty_con != NULL) {
	if (fsetfilecon(se_state.ttyfd, new_tty_con) < 0) {
	    sudo_warn(U_("unable to set new tty context"));
	    goto bad;
	}
    }

    if (ptyfd != -1) {
	/* Reopen pty that was relabeled, std{in,out,err} are reset later. */
	se_state.ttyfd = open(ttyn, O_RDWR|O_NOCTTY, 0);
	if (se_state.ttyfd == -1 || fstat(se_state.ttyfd, &sb) == -1) {
	    sudo_warn(U_("unable to open %s"), ttyn);
	    goto bad;
	}
	if (!S_ISCHR(sb.st_mode)) {
	    sudo_warn(U_("%s is not a character device, not relabeling tty"),
		ttyn);
	    goto bad;
	}
	if (dup2(se_state.ttyfd, ptyfd) == -1) {
	    sudo_warn("dup2");
	    goto bad;
	}
    } else {
	/* Re-open tty to get new label and reset std{in,out,err} */
	close(se_state.ttyfd);
	se_state.ttyfd = open(ttyn, O_RDWR|O_NOCTTY|O_NONBLOCK);
	if (se_state.ttyfd == -1 || fstat(se_state.ttyfd, &sb) == -1) {
	    sudo_warn(U_("unable to open %s"), ttyn);
	    goto bad;
	}
	if (!S_ISCHR(sb.st_mode)) {
	    sudo_warn(U_("%s is not a character device, not relabeling tty"),
		ttyn);
	    goto bad;
	}
	(void)fcntl(se_state.ttyfd, F_SETFL,
	    fcntl(se_state.ttyfd, F_GETFL, 0) & ~O_NONBLOCK);
	for (fd = STDIN_FILENO; fd <= STDERR_FILENO; fd++) {
	    if (isatty(fd) && dup2(se_state.ttyfd, fd) == -1) {
		sudo_warn("dup2");
		goto bad;
	    }
	}
    }
    /* Retain se_state.ttyfd so we can restore label when command finishes. */
    (void)fcntl(se_state.ttyfd, F_SETFD, FD_CLOEXEC);

    se_state.ttyn = ttyn;
    se_state.tty_context = tty_con;
    se_state.new_tty_context = new_tty_con;
    debug_return_int(0);

bad:
    if (se_state.ttyfd != -1 && se_state.ttyfd != ptyfd) {
	close(se_state.ttyfd);
	se_state.ttyfd = -1;
    }
    freecon(tty_con);
    debug_return_int(se_state.enforcing ? -1 : 0);
}
Ejemplo n.º 5
0
int login_main(int argc, char **argv)
{
	char tty[BUFSIZ];
	char full_tty[200];
	char fromhost[512];
	char username[USERNAME_SIZE];
	const char *tmp;
	int amroot;
	int flag;
	int failed;
	int count=0;
	struct passwd *pw, pw_copy;
#ifdef CONFIG_WHEEL_GROUP
	struct group *grp;
#endif
	int opt_preserve = 0;
	int opt_fflag = 0;
	char *opt_host = 0;
	int alarmstarted = 0;
#ifdef CONFIG_SELINUX
	security_context_t stat_sid = NULL, sid = NULL, old_tty_sid=NULL, new_tty_sid=NULL;
#endif

	username[0]=0;
	amroot = ( getuid ( ) == 0 );
	signal ( SIGALRM, alarm_handler );
	alarm ( TIMEOUT );
	alarmstarted = 1;

	while (( flag = getopt(argc, argv, "f:h:p")) != EOF ) {
		switch ( flag ) {
		case 'p':
			opt_preserve = 1;
			break;
		case 'f':
			/*
			 * username must be a separate token
			 * (-f root, *NOT* -froot). --marekm
			 */
			if ( optarg != argv[optind-1] )
				bb_show_usage( );

			if ( !amroot )		/* Auth bypass only if real UID is zero */
				bb_error_msg_and_die ( "-f permission denied" );

			safe_strncpy(username, optarg, USERNAME_SIZE);
			opt_fflag = 1;
			break;
		case 'h':
			opt_host = optarg;
			break;
		default:
			bb_show_usage( );
		}
	}

	if (optind < argc)             // user from command line (getty)
		safe_strncpy(username, argv[optind], USERNAME_SIZE);

	if ( !isatty ( 0 ) || !isatty ( 1 ) || !isatty ( 2 ))
		return EXIT_FAILURE;		/* Must be a terminal */

#ifdef CONFIG_FEATURE_UTMP
	checkutmp ( !amroot );
#endif

	tmp = ttyname ( 0 );
	if ( tmp && ( strncmp ( tmp, "/dev/", 5 ) == 0 ))
		safe_strncpy ( tty, tmp + 5, sizeof( tty ));
	else if ( tmp && *tmp == '/' )
		safe_strncpy ( tty, tmp, sizeof( tty ));
	else
		safe_strncpy ( tty, "UNKNOWN", sizeof( tty ));

#ifdef CONFIG_FEATURE_UTMP
	if ( amroot )
		memset ( utent.ut_host, 0, sizeof utent.ut_host );
#endif

	if ( opt_host ) {
#ifdef CONFIG_FEATURE_UTMP
		safe_strncpy ( utent.ut_host, opt_host, sizeof( utent. ut_host ));
#endif
		snprintf ( fromhost, sizeof( fromhost ) - 1, " on `%.100s' from `%.200s'", tty, opt_host );
	}
	else
		snprintf ( fromhost, sizeof( fromhost ) - 1, " on `%.100s'", tty );

	setpgrp();

	openlog ( "login", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH );

	while ( 1 ) {
		failed = 0;

		if ( !username[0] )
			if(!login_prompt ( username ))
				return EXIT_FAILURE;

		if ( !alarmstarted && ( TIMEOUT > 0 )) {
			alarm ( TIMEOUT );
			alarmstarted = 1;
		}

		if (!( pw = getpwnam ( username ))) {
			pw_copy.pw_name   = "UNKNOWN";
			pw_copy.pw_passwd = "!";
			opt_fflag = 0;
			failed = 1;
		} else
			pw_copy = *pw;

		pw = &pw_copy;

		if (( pw-> pw_passwd [0] == '!' ) || ( pw-> pw_passwd[0] == '*' ))
			failed = 1;

		if ( opt_fflag ) {
			opt_fflag = 0;
			goto auth_ok;
		}

		if (!failed && ( pw-> pw_uid == 0 ) && ( !check_tty ( tty )))
			failed = 1;

		/* Don't check the password if password entry is empty (!) */
		if ( !pw-> pw_passwd[0] )
			goto auth_ok;

		/* authorization takes place here */
		if ( correct_password ( pw ))
			goto auth_ok;

		failed = 1;

auth_ok:
		if ( !failed)
			break;

		bb_do_delay(FAIL_DELAY);
		puts("Login incorrect");
		username[0] = 0;
		if ( ++count == 3 ) {
			syslog ( LOG_WARNING, "invalid password for `%s'%s\n", pw->pw_name, fromhost);
			return EXIT_FAILURE;
	}
	}

	alarm ( 0 );
	if ( check_nologin ( pw-> pw_uid == 0 ))
		return EXIT_FAILURE;

#ifdef CONFIG_FEATURE_UTMP
	setutmp ( username, tty );
#endif

	if ( *tty != '/' )
		snprintf ( full_tty, sizeof( full_tty ) - 1, "/dev/%s", tty);
	else
		safe_strncpy ( full_tty, tty, sizeof( full_tty ) - 1 );

#ifdef CONFIG_SELINUX
	if (is_selinux_enabled())
	{
		struct stat st;
		int rc;

		if (get_default_context(username, NULL, &sid))
		{
			fprintf(stderr, "Unable to get SID for %s\n", username);
			exit(1);
		}
		rc = getfilecon(full_tty,&stat_sid);
		freecon(stat_sid);
		if ((rc<0) || (stat(full_tty, &st)<0))
		{
			fprintf(stderr, "stat_secure(%.100s) failed: %.100s\n", full_tty, strerror(errno));
			return EXIT_FAILURE;
		}
		if (security_compute_relabel (sid, old_tty_sid, SECCLASS_CHR_FILE, &new_tty_sid) != 0)
		{
			fprintf(stderr, "security_change_sid(%.100s) failed: %.100s\n", full_tty, strerror(errno));
			return EXIT_FAILURE;
		}
		if(setfilecon(full_tty, new_tty_sid) != 0)
		{
			fprintf(stderr, "chsid(%.100s, %s) failed: %.100s\n", full_tty, new_tty_sid, strerror(errno));
			return EXIT_FAILURE;
		}
		freecon(sid);
		freecon(old_tty_sid);
		freecon(new_tty_sid);
	}
#endif
	if ( !is_my_tty ( full_tty ))
		syslog ( LOG_ERR, "unable to determine TTY name, got %s\n", full_tty );

	/* Try these, but don't complain if they fail
	 * (for example when the root fs is read only) */
	chown ( full_tty, pw-> pw_uid, pw-> pw_gid );
	chmod ( full_tty, 0600 );

	change_identity ( pw );
	tmp = pw-> pw_shell;
	if(!tmp || !*tmp)
		tmp = DEFAULT_SHELL;
	setup_environment ( tmp, 1, !opt_preserve, pw );

	motd ( );
	signal ( SIGALRM, SIG_DFL );	/* default alarm signal */

	if ( pw-> pw_uid == 0 )
		syslog ( LOG_INFO, "root login %s\n", fromhost );
#ifdef CONFIG_SELINUX
	set_current_security_context(sid);
#endif
	run_shell ( tmp, 1, 0, 0);	/* exec the shell finally. */

	return EXIT_FAILURE;
}
Ejemplo n.º 6
0
Archivo: selinux.c Proyecto: aosm/sudo
/*
 * This function attempts to relabel the tty. If this function fails, then
 * the contexts are free'd and -1 is returned. On success, 0 is returned
 * and tty_context and new_tty_context are set.
 *
 * This function will not fail if it can not relabel the tty when selinux is
 * in permissive mode.
 */
static int
relabel_tty(const char *ttyn, int ptyfd)
{
    security_context_t tty_con = NULL;
    security_context_t new_tty_con = NULL;
    int fd;

    se_state.ttyfd = ptyfd;

    /* It is perfectly legal to have no tty. */
    if (ptyfd == -1 && ttyn == NULL)
	return 0;

    /* If sudo is not allocating a pty for the command, open current tty. */
    if (ptyfd == -1) {
	se_state.ttyfd = open(ttyn, O_RDWR|O_NONBLOCK);
	if (se_state.ttyfd == -1) {
	    warning("unable to open %s, not relabeling tty", ttyn);
	    if (se_state.enforcing)
		goto bad;
	}
	(void)fcntl(se_state.ttyfd, F_SETFL,
	    fcntl(se_state.ttyfd, F_GETFL, 0) & ~O_NONBLOCK);
    }

    if (fgetfilecon(se_state.ttyfd, &tty_con) < 0) {
	warning("unable to get current tty context, not relabeling tty");
	if (se_state.enforcing)
	    goto bad;
    }

    if (tty_con && (security_compute_relabel(se_state.new_context, tty_con,
	SECCLASS_CHR_FILE, &new_tty_con) < 0)) {
	warning("unable to get new tty context, not relabeling tty");
	if (se_state.enforcing)
	    goto bad;
    }

    if (new_tty_con != NULL) {
	if (fsetfilecon(se_state.ttyfd, new_tty_con) < 0) {
	    warning("unable to set new tty context");
	    if (se_state.enforcing)
		goto bad;
	}
    }

    if (ptyfd != -1) {
	/* Reopen pty that was relabeled, std{in,out,err} are reset later. */
	se_state.ttyfd = open(ttyn, O_RDWR|O_NOCTTY, 0);
	if (se_state.ttyfd == -1) {
	    warning("cannot open %s", ttyn);
	    if (se_state.enforcing)
		goto bad;
	}
	if (dup2(se_state.ttyfd, ptyfd) == -1) {
	    warning("dup2");
	    goto bad;
	}
    } else {
	/* Re-open tty to get new label and reset std{in,out,err} */
	close(se_state.ttyfd);
	se_state.ttyfd = open(ttyn, O_RDWR|O_NONBLOCK);
	if (se_state.ttyfd == -1) {
	    warning("unable to open %s", ttyn);
	    goto bad;
	}
	(void)fcntl(se_state.ttyfd, F_SETFL,
	    fcntl(se_state.ttyfd, F_GETFL, 0) & ~O_NONBLOCK);
	for (fd = STDIN_FILENO; fd <= STDERR_FILENO; fd++) {
	    if (isatty(fd) && dup2(se_state.ttyfd, fd) == -1) {
		warning("dup2");
		goto bad;
	    }
	}
    }
    /* Retain se_state.ttyfd so we can restore label when command finishes. */
    (void)fcntl(se_state.ttyfd, F_SETFD, FD_CLOEXEC);

    se_state.ttyn = ttyn;
    se_state.tty_context = tty_con;
    se_state.new_tty_context = new_tty_con;
    return 0;

bad:
    if (se_state.ttyfd != -1 && se_state.ttyfd != ptyfd) {
	close(se_state.ttyfd);
	se_state.ttyfd = -1;
    }
    freecon(tty_con);
    return -1;
}