Example #1
0
gboolean
mdm_verify_setup_user (MdmDisplay *d,
                       const gchar *login,
		       char **new_login)
{
	struct passwd *pwent;

	*new_login = NULL;

	pwent = getpwnam (login);
	if (pwent == NULL) {
		mdm_debug ("Cannot get passwd structure for user");
		return FALSE;
	}

	if ( ! mdm_setup_gids (login, pwent->pw_gid)) {
		mdm_debug ("Cannot set user group");
		mdm_errorgui_error_box (d,
					GTK_MESSAGE_ERROR,
					_("\nCannot set your user group; "
					  "you will not be able to log in. "
					  "Please contact your system administrator."));
		return FALSE;
	}

	return TRUE;
}
Example #2
0
void
mdm_save_customlist_data (const gchar *file,
			  const gchar *key,
			  const gchar *id)
{
	GKeyFile *cfg;

	mdm_debug ("Saving custom configuration data to file=%s, key=%s",
		file, key);
	cfg = mdm_common_config_load (file, NULL);
	if (cfg == NULL) {
		gint fd = -1;
                mdm_debug ("creating file: %s", file);
		VE_IGNORE_EINTR (fd = g_open (file,
			O_CREAT | O_TRUNC | O_RDWR, 0644));

		if (fd < 0)
			return;

		write (fd, "\n", 2);
		close (fd);
		cfg = mdm_common_config_load (file, NULL);
		if (cfg == NULL) {
			return;
		}
	}

	g_key_file_set_string (cfg, "GreeterInfo", key, ve_sure_string (id));
	mdm_common_config_save (cfg, file, NULL);
	g_key_file_free (cfg);
}
Example #3
0
/*
 * Get the VT number associated with the display via the XFree86_VT
 * Atom.
 */
long
mdm_get_current_vtnum (Display *display)
{
	Atom prop;
	Atom actualtype;
	int actualformat;
	unsigned long nitems;
	unsigned long bytes_after;
	unsigned char *buf;
	unsigned long num;

	if (display == NULL)
		return -1;

	prop = XInternAtom (display, "XFree86_VT", True);
	if (prop == None) {
	        mdm_debug ("no XFree86_VT atom\n");
	        return -1;
	}
	if (XGetWindowProperty (display, DefaultRootWindow (display), prop, 0, 1,
		False, AnyPropertyType, &actualtype, &actualformat,
		&nitems, &bytes_after, &buf)) {
		mdm_debug ("no XFree86_VT property\n");
		return -1;
	}
	if (nitems != 1) {
		mdm_debug ("%lu items in XFree86_VT property!\n", nitems);
		XFree (buf);
		return -1;
	}

	switch (actualtype) {
	case XA_CARDINAL:
	case XA_INTEGER:
	case XA_WINDOW:
		switch (actualformat) {
		case  8:
			num = (*(uint8_t  *)(void *)buf);
			break;
		case 16:
			num = (*(uint16_t *)(void *)buf);
			break;
		case 32:
			num = (*(uint32_t *)(void *)buf);
			break;
		default:
			mdm_debug ("format %d in XFree86_VT property!\n", actualformat);
			XFree (buf);
			return -1;
		}
		break;
	default:
		mdm_debug ("type %lx in XFree86_VT property!\n", actualtype);
		XFree (buf);
		return -1;
	}
	XFree (buf);
	return num;
}
Example #4
0
void
mdm_verify_cleanup (MdmDisplay *d)
{
	gid_t groups[1] = { 0 };
	cur_mdm_disp = d;

	if (pamh != NULL) {
		gint pamerr;
		pam_handle_t *tmp_pamh;
		gboolean old_opened_session;
		gboolean old_did_setcred;

		mdm_debug ("Running mdm_verify_cleanup and pamh != NULL");

		mdm_sigterm_block_push ();
		mdm_sigchld_block_push ();
		tmp_pamh = pamh;
		pamh = NULL;
		old_opened_session = opened_session;
		opened_session = FALSE;
		old_did_setcred = did_setcred;
		did_setcred = FALSE;
		mdm_sigchld_block_pop ();
		mdm_sigterm_block_pop ();

		pamerr = PAM_SUCCESS;

		/* Close the users session */
		if (old_opened_session) {
			mdm_debug ("Running pam_close_session");
			pamerr = pam_close_session (tmp_pamh, 0);
		}

		/* Throw away the credentials */
		if (old_did_setcred) {
			mdm_debug ("Running pam_setcred with PAM_DELETE_CRED");
			pamerr = pam_setcred (tmp_pamh, PAM_DELETE_CRED);
		}

		pam_end (tmp_pamh, pamerr);

		/* Workaround to avoid mdm messages being logged as PAM_pwdb */
                mdm_log_shutdown ();
                mdm_log_init ();
	}

	/* Clear the group setup */
	setgid (0);
	/* this will get rid of any suplementary groups etc... */
	setgroups (1, groups);

	cur_mdm_disp = NULL;

	/* reset limits */
	mdm_reset_limits ();
}
Example #5
0
/* Preselects the last logged in user */
static void mdm_preselect_user (int *pamerr) {
	
	// Return if user preselection isn't enabled
	if (!mdm_daemon_config_get_value_bool (MDM_KEY_SELECT_LAST_LOGIN)) {
		return;
	}
	
	// Return if we're using automatic or timed login
	if (mdm_daemon_config_get_value_bool (MDM_KEY_AUTOMATIC_LOGIN_ENABLE) || mdm_daemon_config_get_value_bool (MDM_KEY_TIMED_LOGIN_ENABLE)) {
		mdm_debug("mdm_preselect_user: Automatic/Timed login detected, not presetting user.");
		return;
	}

        // Return if the user list is disabled (relevant to mdmlogin)
        if (!mdm_daemon_config_get_value_bool (MDM_KEY_BROWSER)) {
		mdm_debug("mdm_preselect_user: User list disabled, not presetting user.");
                return;
        }

	// Find the name of the last logged in user
	char last_username[255];
	FILE *fp = popen("last -w | grep tty | head -1 | awk {'print $1;'}", "r");
	fscanf(fp, "%s", last_username);
	pclose(fp);

	// If for any reason the user isn't selectable, don't preset.
	if (!mdm_verify_check_selectable_user(last_username)) {
		return;
	}	

	// Preset the user
	mdm_debug("mdm_verify_user: presetting user to '%s'", last_username);
	if ((*pamerr = pam_set_item (pamh, PAM_USER, last_username)) != PAM_SUCCESS) {		
		if (mdm_slave_action_pending ()) {
			mdm_error ("Can't set PAM_USER='******'", last_username);
		}
	}

	mdm_verify_set_user_settings (last_username);

}
Example #6
0
void mdm_verify_set_user_settings (const char *user) {
	char * session;
	char * language;
	gboolean savesess = FALSE;

	if (mdm_verify_check_selectable_user(user)) {
		mdm_debug("mdm_verify_set_user_settings: Checking settings for '%s'", user);
		char * home_dir = g_strdup_printf("/home/%s", user);
		if ( !(g_file_test(home_dir, G_FILE_TEST_EXISTS))) {
			mdm_debug("mdm_verify_set_user_settings: user '%s' doesn't exist.", user);
			return;
		}
		mdm_daemon_config_get_user_session_lang (&session, &language, home_dir, &savesess);
		if (!ve_string_empty(session)) {
			mdm_debug("mdm_verify_set_user_settings: Found session '%s'.", session);
			mdm_slave_greeter_ctl_no_ret (MDM_SETSESS, session);
		}
		else {
			mdm_debug("mdm_verify_set_user_settings: No session found, setting to default '%s'.", "default");
			mdm_slave_greeter_ctl_no_ret (MDM_SETSESS, "default"); // Do not translate "default" here, it's a value
		}
		if (!ve_string_empty(language)) {
			mdm_debug("mdm_verify_set_user_settings: Found language '%s'.", language);
			mdm_slave_greeter_ctl_no_ret (MDM_SETLANG, language);
		}
		else {
			const char * mdmlang = g_getenv ("LANG");
			if (mdmlang) {				
				mdm_debug("mdm_verify_set_user_settings: No language found, setting to default '%s'.", mdmlang);
				mdm_slave_greeter_ctl_no_ret (MDM_SETLANG, mdmlang);
			}
		}
	}
}
Example #7
0
/**
 * mdm_display_unmanage:
 * @d: Pointer to a MdmDisplay struct
 *
 * Stop services for a display
 */
void
mdm_display_unmanage (MdmDisplay *d)
{
    if (!d)
	return;

    mdm_debug ("mdm_display_unmanage: Stopping %s (slave pid: %d)",
	       d->name, (int)d->slavepid);

    /* whack connections about this display */
    if (unixconn != NULL)
      mdm_kill_subconnections_with_display (unixconn, d);

    /* Kill slave, this may in fact hang for a bit at least until the
     * slave dies, which should be ASAP though */
    whack_old_slave (d, TRUE /* kill_connection */);
    
    d->dispstat = DISPLAY_DEAD;
    if (d->type != TYPE_STATIC)
		mdm_display_dispose (d);

    mdm_debug ("mdm_display_unmanage: Display stopped");
}
Example #8
0
gboolean mdm_verify_check_selectable_user (const char * user) {		
	
	// Return if the username is null or empty
	if (user == NULL || strcmp (user, "") == 0) {
		mdm_debug("mdm_verify_check_selectable_user: invalid username.");
		return FALSE;
	}

	// Return if the username is "oem"
	if (strcmp (user, "oem") == 0) {
		mdm_debug("mdm_verify_check_selectable_user: username is 'oem'.");
		return FALSE;
	}

	char * home_dir = g_strdup_printf("/home/%s", user);
	char * accounts_service = g_strdup_printf("/var/lib/AccountsService/users/%s", user);

	// Return if the user doesn't exist (check /home and AccountsService)
	if ( !(g_file_test(home_dir, G_FILE_TEST_EXISTS) || g_file_test(accounts_service, G_FILE_TEST_EXISTS)) ) {
		mdm_debug("mdm_verify_check_selectable_user: user '%s' doesn't exist.", user);
		return FALSE;
	}

	// Return if the user belongs to the nopasswdlogin group
	char result[255];
	char * command = g_strdup_printf("id '%s' 2>/dev/null | grep nopasswdlogin | wc -l", user);
	FILE *fp = popen(command, "r");
	fscanf(fp, "%s", result);
	pclose(fp);
	if (strcmp(result, "0") != 0) {
		mdm_debug("mdm_verify_check_selectable_user: user '%s' is part of the nopasswdlogin group.", user);
		return FALSE;
	}

	return TRUE;
}
Example #9
0
File: xdmcp.c Project: AlbertJP/mdm
static void
reconnect_to_parent (MdmDisplay *to)
{
       GError *error;
       gchar *command_argv[10];
       const gchar *proxyreconnect = mdm_daemon_config_get_value_string (MDM_KEY_XDMCP_PROXY_RECONNECT);

       command_argv[0] = (char *)proxyreconnect;
       command_argv[1] = "--display";
       command_argv[2] = to->parent_disp;
       command_argv[3] = "--display-authfile";
       command_argv[4] = to->parent_auth_file;
       command_argv[5] = "--to";
       command_argv[6] = to->name;
       command_argv[7] = "--to-authfile";
       command_argv[8] = to->authfile;
       command_argv[9] = NULL;

       mdm_debug ("XDMCP: migrating display by running "
                  "'%s --display %s --display-authfile %s --to %s --to-authfile %s'",
                  proxyreconnect,
                  to->parent_disp, to->parent_auth_file,
                  to->name, to->authfile);

       error = NULL;
       if (!g_spawn_async (NULL, command_argv, NULL, 0, NULL, NULL, NULL, &error)) {
               mdm_error (_("%s: Failed to run "
                            "'%s --display %s --display-authfile %s --to %s --to-authfile %s': %s"),
                          "mdm_xdmcp_migrate",
                          proxyreconnect,
                          to->parent_disp, to->parent_auth_file,
                          to->name, to->authfile,
                          error->message);
               g_error_free (error);
       }
}
Example #10
0
/* Creates a pam handle for the auto login */
static gboolean
create_pamh (MdmDisplay *d,
	     const char *service,
	     const char *login,
	     struct pam_conv *conv,
	     const char *display,
	     int *pamerr)
{

	if (display == NULL) {
		mdm_error ("Cannot setup pam handle with null display");
		return FALSE;
	}

	if (pamh != NULL) {
		mdm_error ("create_pamh: Stale pamh around, cleaning up");
		pam_end (pamh, PAM_SUCCESS);
	}
	/* init things */
	pamh = NULL;
	opened_session = FALSE;
	did_setcred = FALSE;

	/* Initialize a PAM session for the user */
	if ((*pamerr = pam_start (service, login, conv, &pamh)) != PAM_SUCCESS) {
		pamh = NULL; /* be anal */
		if (mdm_slave_action_pending ())
			mdm_error ("Unable to establish service %s: %s\n", service, pam_strerror (NULL, *pamerr));
		return FALSE;
	}

	/* Inform PAM of the user's tty */
		if ((*pamerr = pam_set_item (pamh, PAM_TTY, display)) != PAM_SUCCESS) {
			if (mdm_slave_action_pending ())
				mdm_error ("Can't set PAM_TTY=%s", display);
			return FALSE;
		}

	if ( ! d->attached) {
		/* Only set RHOST if host is remote */
		/* From the host of the display */
		if ((*pamerr = pam_set_item (pamh, PAM_RHOST,
					     d->hostname)) != PAM_SUCCESS) {
			if (mdm_slave_action_pending ())
				mdm_error ("Can't set PAM_RHOST=%s", d->hostname);
			return FALSE;
		}
	}

	// Preselect the previous user
	if (do_we_need_to_preset_the_username) {		
		do_we_need_to_preset_the_username = FALSE;
		if (mdm_daemon_config_get_value_bool (MDM_KEY_SELECT_LAST_LOGIN)) {

			if (mdm_daemon_config_get_value_bool (MDM_KEY_AUTOMATIC_LOGIN_ENABLE) || mdm_daemon_config_get_value_bool (MDM_KEY_TIMED_LOGIN_ENABLE)) {
				mdm_debug("mdm_verify_user: Automatic/Timed login detected, not presetting user.");
			}
			else {
				char last_username[255];
				FILE *fp = popen("last -w | grep tty | head -1 | awk {'print $1;'}", "r");
				fscanf(fp, "%s", last_username);
				pclose(fp);
				if (last_username != NULL && strcmp (last_username, "") != 0) {
					// Verify that the username returned is actually legit
					char * home_dir = g_strdup_printf("/home/%s", last_username);
	  				char * accounts_service = g_strdup_printf("/var/lib/AccountsService/users/%s", last_username);
					if ((g_file_test(home_dir, G_FILE_TEST_EXISTS)) || (g_file_test(accounts_service, G_FILE_TEST_EXISTS))) {
						// Preset the user
	    				mdm_debug("mdm_verify_user: presetting user to '%s'", last_username);
						if ((*pamerr = pam_set_item (pamh, PAM_USER, last_username)) != PAM_SUCCESS) {
							if (mdm_slave_action_pending ()) {
								mdm_error ("Can't set PAM_USER='******'", last_username);
							}
						}
	  				}				
				}
			}
		}
	}

	return TRUE;
}
Example #11
0
gchar *
mdm_verify_user (MdmDisplay *d,
		 const char *username,
		 gboolean allow_retry)
{
	gchar *login, *passwd, *ppasswd;
	struct passwd *pwent;
	struct spwd *sp;
#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS)	\
	|| defined (HAVE_LOGINRESTRICTIONS)
	gchar *message = NULL;
#endif
#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS)
	gchar *info_msg = NULL, *response = NULL;
	gint reEnter, ret;
#endif

	if (d->attached && d->timed_login_ok)
		mdm_slave_greeter_ctl_no_ret (MDM_STARTTIMER, "");

	if (username == NULL) {
	authenticate_again:
		/* Ask for the user's login */
		mdm_verify_select_user (NULL);
		mdm_slave_greeter_ctl_no_ret (MDM_MSG, _("Please enter your username"));
		login = mdm_slave_greeter_ctl (MDM_PROMPT, _("Username:"******"");
				g_free (login);
				return NULL;
			}
		}
		mdm_slave_greeter_ctl_no_ret (MDM_MSG, "");

		if (mdm_daemon_config_get_value_bool (MDM_KEY_DISPLAY_LAST_LOGIN)) {
			char *info = mdm_get_last_info (login);
			mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX, info);
			g_free (info);
		}
	} else {
		login = g_strdup (username);
	}
	mdm_slave_greeter_ctl_no_ret (MDM_SETLOGIN, login);

	pwent = getpwnam (login);

	setspent ();

	/* Lookup shadow password */
	sp = getspnam (login);

	/* Use shadow password when available */
	if (sp != NULL) {
		ppasswd = g_strdup (sp->sp_pwdp);
	} else {
		/* In case shadow password cannot be retrieved (when using NIS
		   authentication for example), use standard passwd */
		if (pwent != NULL &&
		    pwent->pw_passwd != NULL)
			ppasswd = g_strdup (pwent->pw_passwd);
		else
			/* If no password can be retrieved, set it to NULL */
			ppasswd = NULL;
	}

	endspent ();

	/* Request the user's password */
	if (pwent != NULL &&
	    ve_string_empty (ppasswd)) {
		/* eeek a passwordless account */
		passwd = g_strdup ("");
	} else {
		passwd = mdm_slave_greeter_ctl (MDM_NOECHO, _("Password:"******"");
		if (mdm_slave_greeter_check_interruption ()) {
			if (d->attached)
				mdm_slave_greeter_ctl_no_ret (MDM_STOPTIMER, "");
			g_free (login);
			g_free (passwd);
			g_free (ppasswd);
			return NULL;
		}
	}

	if (d->attached)
		mdm_slave_greeter_ctl_no_ret (MDM_STOPTIMER, "");

	if (pwent == NULL) {
		mdm_sleep_no_signal (mdm_daemon_config_get_value_int (MDM_KEY_RETRY_DELAY));
		mdm_debug ("Couldn't authenticate user");

		print_cant_auth_errbox ();

		g_free (login);
		g_free (passwd);
		g_free (ppasswd);
		return NULL;
	}

	/* Check whether password is valid */
	if (ppasswd == NULL || (ppasswd[0] != '\0' &&
				strcmp (crypt (passwd, ppasswd), ppasswd) != 0)) {
		mdm_sleep_no_signal (mdm_daemon_config_get_value_int (MDM_KEY_RETRY_DELAY));
		mdm_debug ("Couldn't authenticate user");

		print_cant_auth_errbox ();

		g_free (login);
		g_free (passwd);
		g_free (ppasswd);
		return NULL;
	}

	if (( ! mdm_daemon_config_get_value_bool (MDM_KEY_ALLOW_ROOT) ||
	    ( ! mdm_daemon_config_get_value_bool (MDM_KEY_ALLOW_REMOTE_ROOT) &&
              ! d->attached)) && pwent->pw_uid == 0) {

		mdm_debug ("Root login disallowed on display '%s'", d->name);
		mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
					      _("The system administrator "
						"is not allowed to login "
						"from this screen"));
		/*mdm_slave_greeter_ctl_no_ret (MDM_ERRDLG,
		  _("Root login disallowed"));*/
		g_free (login);
		g_free (passwd);
		g_free (ppasswd);
		return NULL;
	}

#ifdef HAVE_LOGINRESTRICTIONS

	/* Check with the 'loginrestrictions' function
	   if the user has been disallowed */
	if (loginrestrictions (login, 0, NULL, &message) != 0) {
		mdm_debug ("User not allowed to log in");
		mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
					      _("\nThe system administrator "
						"has disabled your "
						"account."));
		g_free (login);
		g_free (passwd);
		g_free (ppasswd);
		if (message != NULL)
			free (message);
		return NULL;
	}

	if (message != NULL)
		free (message);
	message = NULL;

#else /* ! HAVE_LOGINRESTRICTIONS */

	/* check for the standard method of disallowing users */
	if (pwent->pw_shell != NULL &&
	    (strcmp (pwent->pw_shell, NOLOGIN) == 0 ||
	     strcmp (pwent->pw_shell, "/bin/true") == 0 ||
	     strcmp (pwent->pw_shell, "/bin/false") == 0)) {
		mdm_debug ("User not allowed to log in");
		mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
					      _("\nThe system administrator "
						"has disabled your "
						"account."));
		/*mdm_slave_greeter_ctl_no_ret (MDM_ERRDLG,
		  _("Login disabled"));*/
		g_free (login);
		g_free (passwd);
		g_free (ppasswd);
		return NULL;
	}

#endif /* HAVE_LOGINRESTRICTIONS */

	g_free (passwd);
	g_free (ppasswd);

	if ( ! mdm_slave_check_user_wants_to_log_in (login)) {
		g_free (login);
		login = NULL;
		goto authenticate_again;
	}

	if ( ! mdm_setup_gids (login, pwent->pw_gid)) {
		mdm_debug ("Cannot set user group");
		mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
					      _("\nCannot set your user group; "
						"you will not be able to log in. "
						"Please contact your system administrator."));
		g_free (login);
		return NULL;
	}

#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS)

	switch (passwdexpired (login, &info_msg)) {
	case 1 :
		mdm_debug ("User password has expired");
		mdm_errorgui_error_box (d, GTK_MESSAGE_ERROR,
					_("You are required to change your password.\n"
					  "Please choose a new one."));
		g_free (info_msg);

		do {
			ret = chpass (login, response, &reEnter, &message);
			g_free (response);

			if (ret != 1) {
				if (ret != 0) {
					mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
								      _("\nCannot change your password; "
									"you will not be able to log in. "
									"Please try again later or contact "
									"your system administrator."));
				} else if ((reEnter != 0) && (message)) {
					response = mdm_slave_greeter_ctl (MDM_NOECHO, message);
					if (response == NULL)
						response = g_strdup ("");
				}
			}

			g_free (message);
			message = NULL;

		} while ( ((reEnter != 0) && (ret == 0))
			  || (ret ==1) );

		g_free (response);
		g_free (message);

		if ((ret != 0) || (reEnter != 0)) {
			return NULL;
		}

#if defined (CAN_CLEAR_ADMCHG)
		/* The password is changed by root, clear the ADM_CHG
		   flag in the passwd file */
		ret = setpwdb (S_READ | S_WRITE);
		if (!ret) {
			upwd = getuserpw (login);
			if (upwd == NULL) {
				ret = -1;
			}
			else {
				upwd->upw_flags &= ~PW_ADMCHG;
				ret = putuserpw (upwd);
				if (!ret) {
					ret = endpwdb ();
				}
			}
		}

		if (ret) {
			mdm_errorgui_error_box (d, GTK_MESSAGE_WARNING,
						_("Your password has been changed but "
						  "you may have to change it again. "
						  "Please try again later or contact "
						  "your system administrator."));
		}

#else /* !CAN_CLEAR_ADMCHG */
		mdm_errorgui_error_box (d, GTK_MESSAGE_WARNING,
					_("Your password has been changed but you "
					  "may have to change it again. Please try again "
					  "later or contact your system administrator."));

#endif /* CAN_CLEAR_ADMCHG */

		break;

	case 2 :
		mdm_debug ("User password has expired");
		mdm_errorgui_error_box (d, GTK_MESSAGE_ERROR,
					_("Your password has expired.\n"
					  "Only a system administrator can now change it"));
		g_free (info_msg);
		return NULL;
		break;

	case -1 :
		mdm_debug ("Internal error on passwdexpired");
		mdm_errorgui_error_box (d, GTK_MESSAGE_ERROR,
					_("An internal error occurred. You will not be able to log in.\n"
					  "Please try again later or contact your system administrator."));
		g_free (info_msg);
		return NULL;
		break;

	default :
		g_free (info_msg);
		break;
	}

#endif /* HAVE_PASSWDEXPIRED && HAVE_CHPASS */

	return login;
}
Example #12
0
void
mdm_display_dispose (MdmDisplay *d)
{

    if (d == NULL)
	return;

    /* paranoia */
    if (unixconn != NULL)
            mdm_kill_subconnections_with_display (unixconn, d);

    if (d->socket_conn != NULL) {
	    MdmConnection *conn = d->socket_conn;
	    d->socket_conn = NULL;
	    mdm_connection_set_close_notify (conn, NULL, NULL);
    }

    if (d->slave_notify_fd >= 0) {
	    VE_IGNORE_EINTR (close (d->slave_notify_fd));
	    d->slave_notify_fd = -1;
    }

    if (d->master_notify_fd >= 0) {
	    VE_IGNORE_EINTR (close (d->master_notify_fd));
	    d->master_notify_fd = -1;
    }

    mdm_daemon_config_display_list_remove (d);

    d->dispstat = DISPLAY_DEAD;
    d->type = -1;

    count_session_limits ();

    if (d->name) {
	mdm_debug ("mdm_display_dispose: Disposing %s", d->name);
	g_free (d->name);
	d->name = NULL;
    }
    
    g_free (d->chosen_hostname);
    d->chosen_hostname = NULL;

    g_free (d->hostname);
    d->hostname = NULL;

    g_free (d->windowpath);
    d->windowpath = NULL;

    g_free (d->addrs);
    d->addrs = NULL;
    d->addr_count = 0;

    g_free (d->authfile);
    d->authfile = NULL;

    g_free (d->authfile_mdm);
    d->authfile_mdm = NULL; 

    if (d->auths) {
	    mdm_auth_free_auth_list (d->auths);
	    d->auths = NULL;
    }

    if (d->local_auths) {
	    mdm_auth_free_auth_list (d->local_auths);
	    d->local_auths = NULL;
    }

    g_free (d->userauth);
    d->userauth = NULL;

    g_free (d->windowpath);
    d->windowpath = NULL;

    g_free (d->command);
    d->command = NULL;

    g_free (d->device_name);
    d->device_name = NULL;

    g_free (d->cookie);
    d->cookie = NULL;

    g_free (d->bcookie);
    d->bcookie = NULL;
    
    d->indirect_id = 0;   
   
    g_free (d->login);
    d->login = NULL;

    g_free (d->preset_user);
    d->preset_user = NULL;

    g_free (d->xsession_errors_filename);
    d->xsession_errors_filename = NULL;

    if (d->session_output_fd >= 0) {
	    VE_IGNORE_EINTR (close (d->session_output_fd));
	    d->session_output_fd = -1;
    }

    if (d->xsession_errors_fd >= 0) {
	    VE_IGNORE_EINTR (close (d->xsession_errors_fd));
	    d->xsession_errors_fd = -1;
    }

    g_free (d->chooser_last_line);
    d->chooser_last_line = NULL;

    if (d->chooser_output_fd >= 0) {
	    VE_IGNORE_EINTR (close (d->chooser_output_fd));
	    d->chooser_output_fd = -1;
    }

    g_free (d->theme_name);
    d->theme_name = NULL;

    g_free (d->xserver_session_args);
    d->xserver_session_args = NULL;

    g_free (d);
}
Example #13
0
gboolean 
mdm_display_manage (MdmDisplay *d)
{
    pid_t pid;
    int fds[2];

    if (!d) 
	return FALSE;

    mdm_debug ("mdm_display_manage: Managing %s", d->name);

    if (pipe (fds) < 0) {
	    mdm_error ("mdm_display_manage: Cannot create pipe");
    }

    if ( ! mdm_display_check_loop (d))
	    return FALSE;

    if (d->slavepid != 0)
	    mdm_debug ("mdm_display_manage: Old slave pid is %d", (int)d->slavepid);

    /* If we have an old slave process hanging around, kill it */
    /* This shouldn't be a normal code path however, so it doesn't matter
     * that we are hanging */
    whack_old_slave (d, FALSE /* kill_connection */);

    /* Ensure that /tmp/.ICE-unix and /tmp/.X11-unix exist and have the
     * correct permissions */
    mdm_ensure_sanity ();

    d->managetime = time (NULL);

    mdm_debug ("Forking slave process");

    /* Fork slave process */
    pid = d->slavepid = fork ();

    switch (pid) {

    case 0:

	setpgid (0, 0);

	/* Make the slave it's own leader.  This 1) makes killing -pid of
	 * the daemon work more sanely because the daemon can whack the
	 * slave much better itself */
	setsid ();

	/* In the child setup empty mask and set all signals to
	 * default values, we'll make them more fun later */
	mdm_unset_signals ();

	d->slavepid = getpid ();
	
	mdm_connection_close (pipeconn);
	pipeconn = NULL;
	mdm_connection_close (unixconn);
	unixconn = NULL;

	mdm_log_shutdown ();

	/* Debian changes */
#if 0
	/* upstream version */
-	/* Close everything */
-	mdm_close_all_descriptors (0 /* from */, fds[0] /* except */, slave_fifo_pipe_fd /* except2 */);
#endif
	/* Close stdin/stdout/stderr.  Leave others, as pam modules may have them open */
	VE_IGNORE_EINTR (close (0));
	VE_IGNORE_EINTR (close (1));
	VE_IGNORE_EINTR (close (2));
	/* End of Debian changes */

	/* No error checking here - if it's messed the best response
         * is to ignore & try to continue */
	mdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */
	mdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */
	mdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */

	mdm_log_init ();

	d->slave_notify_fd = fds[0];

	fcntl (d->slave_notify_fd, F_SETFL, fcntl (d->slave_notify_fd, F_GETFL) | O_NONBLOCK);

	mdm_slave_start (d);
	/* should never retern */

	/* yaikes, how did we ever get here? */
	mdm_server_stop (d);
	_exit (DISPLAY_REMANAGE);

	break;

    case -1:
	d->slavepid = 0;
	mdm_error ("mdm_display_manage: Failed forking MDM slave process for %s", d->name);

	return FALSE;

    default:
	mdm_debug ("mdm_display_manage: Forked slave: %d", (int)pid);
	d->master_notify_fd = fds[1];
	VE_IGNORE_EINTR (close (fds[0]));
	break;
    }

    /* invalidate chosen hostname */
    g_free (d->chosen_hostname);
    d->chosen_hostname = NULL;

    /* use_chooser can only be temporary, if you want it permanent you set it
       up in the server definition with "chooser=true" and it will get set up
       during server command line resolution */
    d->use_chooser = FALSE;

    if (SERVER_IS_LOCAL (d)) {
	    d->dispstat = DISPLAY_ALIVE;
    }

    /* reset sleep to 1, to sleep just in case (avoids X server races) */
    d->sleep_before_run = 1;

    return TRUE;
}
Example #14
0
static void
whack_old_slave (MdmDisplay *d, gboolean kill_connection)
{
    time_t t = time (NULL);
    gboolean waitsleep = TRUE;

    if (kill_connection) {
	    /* This should never happen, but just in case */
	    if (d->socket_conn != NULL) {
		    MdmConnection *conn = d->socket_conn;
		    d->socket_conn = NULL;
		    mdm_connection_set_close_notify (conn, NULL, NULL);
	    }
    }

    if (d->master_notify_fd >= 0) {
	    VE_IGNORE_EINTR (close (d->master_notify_fd));
	    d->master_notify_fd = -1;
    }

    /* if we have DISPLAY_DEAD set, then this has already been killed */
    if (d->dispstat == DISPLAY_DEAD)
	    waitsleep = FALSE;

    /* Kill slave */
    if (d->slavepid > 1 &&
	(d->dispstat == DISPLAY_DEAD || kill (d->slavepid, SIGTERM) == 0)) {
	    int exitstatus;
	    int ret;
wait_again:
		
	    if (waitsleep) {
		    /* wait for some signal, yes this is a race */
		    mdm_debug ("mdm whack_old_slave: sleeping for 10 seconds");
		    sleep (10);
		  }
	    waitsleep = TRUE;
	    errno = 0;
	    ret = waitpid (d->slavepid, &exitstatus, WNOHANG);
	    if (ret <= 0) {
		    /* rekill the slave to tell it to
		       hurry up and die if we're getting
		       killed ourselves */
		    if ((mdm_daemon_config_signal_terminthup_was_notified ()) ||
			(t + 10 <= time (NULL))) {
			    mdm_debug ("whack_old_slave: GOT ANOTHER SIGTERM (or it was 10 secs already), killing slave again with SIGKILL");
			    t = time (NULL);
			    kill (d->slavepid, SIGKILL);
			    goto wait_again;
		    } else if (ret < 0 && errno == EINTR) {
			    goto wait_again;
		    }
	    }

	    if (WIFSIGNALED (exitstatus)) {
		    mdm_debug ("whack_old_slave: Slave crashed (signal %d), killing its children",
			       (int)WTERMSIG (exitstatus));

		    if (d->sesspid > 1)
			    kill (-(d->sesspid), SIGTERM);
		    d->sesspid = 0;
		    if (d->greetpid > 1)
			    kill (-(d->greetpid), SIGTERM);
		    d->greetpid = 0;
		    if (d->chooserpid > 1)
			    kill (-(d->chooserpid), SIGTERM);
		    d->chooserpid = 0;
		    if (d->servpid > 1)
			    kill (d->servpid, SIGTERM);
		    d->servpid = 0;
	    }
    }
    d->slavepid = 0;
}
Example #15
0
static gboolean
mdm_display_check_loop (MdmDisplay *disp)
{
  time_t now;
  time_t since_last;
  time_t since_loop;
  
  now = time (NULL);

  mdm_debug ("loop check: last_start %ld, last_loop %ld, now: %ld, retry_count: %d", (long)disp->last_start_time, (long) disp->last_loop_start_time, (long) now, disp->retry_count);
  
  if (disp->last_loop_start_time > now || disp->last_loop_start_time == 0)
    {
      /* Reset everything if this is the first time in this
       * function, or if the system clock got reset backward.
       */
      disp->last_loop_start_time = now;
      disp->last_start_time = now;
      disp->retry_count = 1;

      mdm_debug ("Resetting counts for loop of death detection");
      
      return TRUE;
    }

  since_loop = now - disp->last_loop_start_time;
  since_last = now - disp->last_start_time;

  /* If it's been at least 1.5 minutes since the last startup loop
   * attempt, then we reset everything.  Or if the last startup was more then
   * 30 seconds ago, then it was likely a successful session.
   */

  if (since_loop >= 90 || since_last >= 30)
    {
      disp->last_loop_start_time = now;
      disp->last_start_time = now;
      disp->retry_count = 1;

      mdm_debug ("Resetting counts for loop of death detection, 90 seconds elapsed since loop started or session lasted more then 30 seconds.");
      
      return TRUE;
    }

  /* If we've tried too many times we bail out. i.e. this means we
   * tried too many times in the 90-second period.
   */
  if (disp->retry_count >= 6) {
	  /* This means we have no clue what's happening,
	   * it's not X server crashing as we would have
	   * cought that elsewhere.  Things are just
	   * not working out, so tell the user.
	   * However this may have been caused by a malicious local user
	   * zapping the display repeatedly, that shouldn't cause mdm
	   * to stop working completely so just wait for 2 minutes,
	   * that should give people ample time to stop mdm if needed,
	   * or just wait for the stupid malicious user to get bored
	   * and go away */
	  char *s = g_strdup_printf (C_(N_("The display server has been shut down "
					   "about 6 times in the last 90 seconds. "
					   "It is likely that something bad is "
					   "going on.  Waiting for 2 minutes "
					   "before trying again on display %s.")),
					disp->name);
	  /* only display a dialog box if this is a local display */
	  if (disp->type == TYPE_STATIC ||
	      disp->type == TYPE_FLEXI) {
		  mdm_text_message_dialog (s);
	  }
	  mdm_error ("%s", s);
	  g_free (s);

	  /* Wait 2 minutes */
	  disp->sleep_before_run = 120;
	  /* well, "last" start time will really be in the future */
	  disp->last_start_time = now + disp->sleep_before_run;

	  disp->retry_count = 1;
	  /* this will reset stuff in the next run (after this
	     "after-two-minutes" server starts) */
	  disp->last_loop_start_time = 0;
	  
	  return TRUE;
  }
  
  /* At least 8 seconds between start attempts, but only after
   * the second start attempt, so you can try to kill mdm from the console
   * in these gaps.
   */
  if (disp->retry_count > 2 && since_last < 8)
    {
      mdm_debug ("Will sleep %ld seconds before next X server restart attempt",
                 (long)(8 - since_last));
      now = time (NULL) + 8 - since_last;
      disp->sleep_before_run = 8 - since_last;
      /* well, "last" start time will really be in the future */
      disp->last_start_time = now + disp->sleep_before_run;
    }
  else
    {
      /* wait one second just for safety (avoids X server races) */
      disp->sleep_before_run = 1;
      disp->last_start_time = now;
    }

  disp->retry_count++;

  return TRUE;
}