dtlogin.c revision 781
/* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* to whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
* OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
* INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder
* shall not be used in advertising or otherwise to promote the sale, use
* or other dealings in this Software without prior written authorization
* of the copyright holder.
*/
#pragma ident "@(#)dtlogin.c 1.20 09/09/11 SMI"
* communication pipe. The Display Manager process will start
* the X window server at system boot time before any user
* has logged into the system. The X server is by default
* started as the root UID "0".
*
* At login time the Xserver local communication pipe is provided
* by the Xserver for user specific configuration data supplied
* by the display manager. It notifies the Xserver it needs to change
* over to the user's credentials (UID, GID, GID_LIST) and
* also switch CWD (current working directory) of to match
* the user's CWD home.
*
*
* For the original definition, see Sun ASARC case 1995/390
*/
#include <netdb.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include "misc.h"
#include "osdep.h"
#include "input.h"
#include "dixstruct.h"
#include "dixfont.h"
#include "opaque.h"
#include <pwd.h>
#include <project.h>
#include <ctype.h>
#include "scrnintstr.h"
#define DTLOGIN_PATH "/var/dt/sdtlogin"
#define BUFLEN 1024
int xf86ConsoleFd = -1;
extern const char *GetAuthFilename(void);
/* Data about the user we need to switch to */
struct dmuser {
int groupid_cnt;
char * homedir;
};
struct dmdata {
int pipeFD;
char * pipename; /* path to pipe */
char * buf; /* contains characters to be processed */
int bufsize; /* size allocated for buf */
};
/* Data stored in screen privates */
struct dmScreenPriv {
};
static int dmScreenKeyIndex;
static struct dmdata *dmHandlerData;
static int dtlogin_create_pipe(int, struct dmdata *);
static void dtlogin_receive_packet(struct dmdata *);
static int dtlogin_parse_packet(struct dmdata *, char *);
static void dtlogin_close_pipe(struct dmdata *);
/*
* initialize DTLOGIN: create pipe; set handlers.
*/
_X_HIDDEN void
DtloginInit(void)
{
int displayNumber = 0;
if (serverGeneration != 1) return;
if (getuid() != 0) return;
DtloginError("Failed to allocate %d bytes for display manager pipe",
sizeof(struct dmdata));
return;
}
return;
}
dmHandlerData = dmd;
}
/*
* cleanup dtlogin pipe at exit if still running, reset privs back to
* root as needed for various cleanup tasks.
*/
_X_HIDDEN void
DtloginCloseDown(void)
{
if (geteuid() != 0) { /* reset privs back to root */
if (seteuid(0) < 0) {
DtloginError("Error in resetting euid to %d", 0);
}
dtlogin_process(&originalUser, 0);
}
if (dmHandlerData != NULL) {
}
}
static Bool
{
struct dmScreenPriv *pScreenPriv;
/* Unwrap CloseScreen and call down to further levels */
pScreenPriv = (struct dmScreenPriv *)
}
static void
{
}
static void
int i,
{
if (i > 0)
{
{
/* dmd may have been freed in dtlogin_receive_packet, do
not use after this point */
}
}
}
static int
{
char pipename[128];
int pipeFD = -1;
DtloginError("Cannot create %s directory for display "
"manager pipe", DTLOGIN_PATH);
return -1;
}
DtloginError("Cannot create display manager pipe: "
"%s is not a directory", DTLOGIN_PATH);
return -1;
}
return -1;
return -1;
}
/* To make sure root has rw permissions. */
return pipeFD;
}
{
if (dmHandlerData == dmd) {
}
}
static void
{
char *p, *n;
int done = 0;
}
/* Read data from pipe and split into tokens, buffering the rest */
while (!done) {
/*
* Realloc only if buf has filled up and we don't have a record
* delimiter yet. Keep track of alloced size.
*/
}
if (nbRead == -1) {
continue;
return; /* return to WaitFor, wait for select() */
} else {
return;
}
}
if (nbRead == 0) { /* End of file */
return;
}
*n = '\0';
DtloginInfo("Next packet: %s\n", p);
if (done) {
return;
}
p = n+1;
}
/* save the rest for the next iteration */
DtloginInfo("Left over: %s\n", p);
}
}
}
/* Parse data from packet
*
* Example Record:
* UID="xxx" GID="yyy";
* G_LIST_ID="aaa" G_LIST_ID="bbb" G_LIST_ID="ccc";
*/
static int
{
char *k, *v, *p;
/* format is key="value" - split into key & value pair */
for (k = s ; (*k != '\0') && isspace(*k); k++) {
/* Skip over whitespace */
}
if (*k == '\0') {
break;
}
p = strchr(k, '=');
if (p == NULL) {
DtloginInfo("Malformed key \'%s\'\n", k);
return 0;
}
*p = '\0'; /* end of key string */
p++;
if (*p != '\"') {
DtloginInfo("Bad delimiter at \'%s\'\n", p);
return 0;
}
v = p + 1; /* start of value string */
p = strchr(v, '\"');
if (p == NULL) {
DtloginInfo("Missing quote after value \'%s\'\n", v);
break;
}
*p = '\0'; /* end of value string */
s = p + 1; /* start of next pair */
DtloginInfo("Received key \"%s\" =>", k);
DtloginInfo(" value \"%s\"\n", v);
/* Found key & value, now process & put into dmd */
if (strcmp(k, "EOF") == 0) {
/* End of transmission, process & close */
return 1;
}
else if (strcmp(k, "HOME") == 0) {
}
|| (strcmp(k, "G_LIST_ID") == 0) ) {
/* Value is numeric, convert to int */
int val;
errno = 0;
/* strtol couldn't parse the results */
DtloginInfo("Invalid number \"%s\"\n", v);
continue;
}
/* Value out of range */
DtloginInfo("Out of range number \"%s\"\n", v);
continue;
}
if (strcmp(k, "UID") == 0) {
}
else if (strcmp(k, "GID") == 0) {
}
else if (strcmp(k, "G_LIST_ID") == 0) {
}
}
}
else {
DtloginInfo("Unrecognized key \"%s\"\n", k);
}
}
return 0;
}
static void
{
char proj_buf[PROJECT_BUFSZ];
auth_file = GetAuthFilename();
if (auth_file) {
}
/* This gid dance is necessary in order to make sure
our "saved-set-gid" is 0 so that we can regain gid
0 when necessary for priocntl & power management.
The first step sets rgid to the user's gid and
makes the egid & saved-gid be 0. The second then
sets the egid to the users gid, but leaves the
saved-gid as 0. */
}
if (user->groupid_cnt >= 0) {
DtloginError("Error in setting supplemental (%d) groups",
user->groupid_cnt);
}
/*
* BUG: 4462531: Set project ID for Xserver
* Get user name and default project.
* Set before the uid value is set.
*/
}
} else {
DtloginError("Error in getting project id for %s",
} else {
TASK_NORMAL) == -1) {
DtloginError("Error in setting project to %s",
}
}
}
}
/* Wrap closeScreen to allow resetting uid on closedown */
int i;
for (i = 0; i < screenInfo.numScreens; i++)
{
struct dmScreenPriv *pScreenPriv;
pScreenPriv = (struct dmScreenPriv *)
Xcalloc(sizeof(struct dmScreenPriv));
if (pScreenPriv != NULL) {
}
}
}
}
} else {
}
DtloginError("Error in changing working directory to %s",
}
/* Inform the kernel whether a user has logged in on this VT device */
if (xf86ConsoleFd != -1)
}