2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* (c) Copyright 1997 The Open Group */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
31 * Xdm - display manager daemon
33 * $TOG: session.c /main/21 1998/11/02 14:32:42 mgreess $
35 * Copyright 1988 Massachusetts Institute of Technology
37 * Permission to use, copy, modify, and distribute this software and its
38 * documentation for any purpose and without fee is hereby granted, provided
39 * that the above copyright notice appear in all copies and that both that
40 * copyright notice and this permission notice appear in supporting
41 * documentation, and that the name of M.I.T. not be used in advertising or
42 * publicity pertaining to distribution of the software without specific,
43 * written prior permission. M.I.T. makes no representations about the
44 * suitability of this software for any purpose. It is provided "as is"
45 * without express or implied warranty.
47 * Author: Keith Packard, MIT X Consortium
67 # include <X11/Xatom.h>
69 #if defined(__FreeBSD__) && OSMAJORVERSION > 8
82 #include <X11/Intrinsic.h>
85 # include <X11/Xresource.h>
96 # include <sys/security.h>
102 #endif /* __KERBEROS */
105 #include "rgy_base.h"
110 static SIAENTITY *siaHandle = NULL;
111 static Boolean dt_in_sia_ses_authent = False;
113 static struct sia_greeter_info {
115 struct greet_info *greet;
116 struct verify_info *verify;
117 struct greet_state *state;
121 static int SiaManageGreeter(
124 unsigned char *title,
128 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet);
130 static void KillGreeter( void );
132 static int sia_greeter_pid;
133 static int sia_exit_proc_reg = FALSE;
137 #define GREET_STATE_LOGIN 0
138 #define GREET_STATE_AUTHENTICATE 1
139 #define GREET_STATE_EXIT 2
140 #define GREET_STATE_EXPASSWORD 3
141 #define GREET_STATE_ERRORMESSAGE 4
142 #define GREET_STATE_LANG 5
143 #define GREET_STATE_BAD_HOSTNAME 6
144 #define GREET_STATE_ENTER 7
145 #define GREET_STATE_TERMINATEGREET 8
146 #define GREET_STATE_USERNAME 9
147 #define GREET_STATE_CHALLENGE 10
148 #define GREET_STATE_FORM 11
151 #define DEF_SESSION CDE_INSTALLATION_TOP "/bin/Xsession"
159 int waitForResponse; /* TRUE=wait for response from dtgreet */
160 RequestHeader *request; /* request buffer */
161 ResponseHeader *response; /* response buffer */
162 int authenticated; /* TRUE=user is authenticated */
163 int vf; /* last return code from Authenticate() */
164 int loginReset; /* reset flag for LOGIN state */
165 char *msg; /* message for VF_MESSAGE */
168 char *globalDisplayName;
170 /***************************************************************************
172 * Local procedure declarations
174 ***************************************************************************/
176 static int AbortClient( int pid) ;
177 static void DeleteXloginResources( struct display *d, Display *dpy) ;
178 int LoadXloginResources( struct display *d) ;
179 static int ErrorHandler( Display *dpy, XErrorEvent *event) ;
180 static int IOErrorHandler( Display *dpy) ;
181 static int ManageGreeter( struct display *d, struct greet_info *greet,
182 struct verify_info *verify, struct greet_state *state) ;
183 static void RunGreeter( struct display *d, struct greet_info *greet,
184 struct verify_info *verify) ;
185 static void SessionExit( struct display *d, int status) ;
186 static void SessionPingFailed( struct display *d) ;
187 static int StartClient(struct verify_info *verify, struct display *d,
189 static SIGVAL catchAlrm( int arg ) ;
190 static SIGVAL catchHUP( int arg ) ;
191 static SIGVAL catchTerm( int arg ) ;
192 static SIGVAL waitAbort( int arg ) ;
193 static void SetupDisplay(struct display *d);
195 static void TellGreeter(RequestHeader *phdr);
196 static int AskGreeter(RequestHeader *preqhdr, char *b, int blen);
198 static void PrintResponse(ResponseHeader *phdr, int count);
201 #if defined (_AIX) && defined (_POWER)
202 static void release_aix_lic(void);
205 #if defined (_AIX) && !defined (_POWER)
206 static int session_execve(char *path, char *argv[], char *envp[]);
208 #define session_execve(A,B,C) execve(A,B,C)
212 static void SetTicketFileName(uid_t uid);
213 # endif /* __KERBEROS */
215 static void LoadAltDtsResources( struct display *d);
216 char * _ExpandLang(char *string, char *lang);
220 /***************************************************************************
224 ***************************************************************************/
226 static int clientPid;
227 static struct greet_info greet;
228 static struct verify_info verify;
229 static char *defaultLanguage = NULL;
231 static jmp_buf abortSession;
234 static char *sensitivityLevel;
238 static char krb_ticket_string[MAXPATHLEN];
239 #endif /* __KERBEROS */
242 XrmDatabase XresourceDB;
249 longjmp (abortSession, 1);
252 static jmp_buf pingTime;
257 longjmp (pingTime, 1);
260 #if defined(__STDC__)
262 FileNameCompare (const char *a, const char *b)
265 FileNameCompare (char *a, char *b)
268 return strcoll (*(char **)a, *(char **)b);
272 SessionPingFailed( struct display *d )
276 AbortClient (clientPid);
277 source (&verify, d->reset);
279 #if defined (PAM) || defined(SUNAUTH)
281 char* user = getEnv (verify.userEnviron, "USER");
282 char* ttyLine = d->gettyLine;
284 #ifdef DEF_NETWORK_DEV
286 * If location is not local (remote XDMCP dtlogin) and
287 * remote accouting is enabled (networkDev start with /dev/...)
288 * Set tty line name to match network device for accouting.
289 * Unless the resource was specifically set, default is value
290 * of DEF_NETWORK_DEV define (/dev/dtremote)
293 if ( d->displayType.location != Local &&
294 networkDev && !strncmp(networkDev,"/dev/",5)) {
295 ttyLine = networkDev+5;
300 PamAccounting( verify.argv[0], d->name, d->utmpId, user,
301 ttyLine, clientPid, ACCOUNTING, NULL);
303 solaris_accounting( verify.argv[0], d->name, d->utmpId, user,
304 ttyLine, clientPid, ACCOUNTING, NULL);
308 solaris_resetdevperm(ttyLine);
314 SessionExit (d, RESERVER_DISPLAY);
319 * We need our own error handlers because we can't be sure what exit code Xlib
320 * will use, and our Xlib does exit(1) which matches REMANAGE_DISPLAY, which
321 * can cause a race condition leaving the display wedged. We need to use
322 * RESERVER_DISPLAY for IO errors, to ensure that the manager waits for the
323 * server to terminate. For other X errors, we should give up.
327 IOErrorHandler( Display *dpy )
330 const char *s = strerror(errno);
332 LogError(ReadCatalog(
333 MC_LOG_SET,MC_LOG_FATAL_IO,MC_DEF_LOG_FATAL_IO),
335 exit(RESERVER_DISPLAY);
340 ErrorHandler( Display *dpy, XErrorEvent *event )
342 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_X_ERR,MC_DEF_LOG_X_ERR));
343 if (XmuPrintDefaultErrorMessage (dpy, event, stderr) == 0) return 0;
344 exit(UNMANAGE_DISPLAY);
350 ManageSession( struct display *d )
356 char *BypassUsername;
358 #endif /* BYPASSLOGIN */
361 Debug ("ManageSession():\n");
363 /***********************************/
364 /** remember the default language **/
365 /***********************************/
366 if (defaultLanguage == NULL) {
367 if ( (d->language != NULL) && (strlen(d->language) > 0) ) {
368 defaultLanguage = strdup(d->language);
370 defaultLanguage = "C";
376 if ((BypassUsername = BypassLogin(d->name)) != NULL) {
378 Debug("Login bypassed, running as %s\n",BypassUsername);
379 greet.name = BypassUsername;
380 if (!Verify (d, &greet, &verify)) {
381 Debug ("Login bypass verify failed!\n");
382 SessionExit (d, GREETLESS_FAILED);
384 Debug("Login bypass verify succeded!\n");
386 #endif /* BYPASSLOGIN */
391 (void)XSetIOErrorHandler(IOErrorHandler);
392 (void)XSetErrorHandler(ErrorHandler);
393 SetTitle(d->name, (char *) 0);
396 * set root background to black...
399 dpy = XOpenDisplay(d->name);
400 for (i = ScreenCount(dpy) - 1; i >= 0; i--)
402 Window tmproot = RootWindow(dpy, i);
404 if (i == DefaultScreen(dpy))
407 XSetWindowBackground(dpy, tmproot, BlackPixel(dpy, i));
408 XClearWindow(dpy, tmproot);
414 ** Invoke Greet program, wait for completion.
415 ** If this routine returns, the user will have been
416 ** verified, otherwise the routine will exit inter-
417 ** nally with an appropriate exit code for the master
422 greet.name = greet.string = NULL;
424 while (greet.name == NULL) {
425 SetHourGlassCursor(dpy, root);
426 LoadXloginResources (d);
428 ApplyFontPathMods(d, dpy);
429 (void)XSetErrorHandler(ErrorHandler);
430 RunGreeter(d, &greet, &verify);
432 DeleteXloginResources (d, dpy);
434 XSetInputFocus(dpy, root, RevertToNone, CurrentTime);
440 * Generate Kerberos ticket file name. Put in system and user
444 if ( IsVerifyName(VN_KRB)) {
445 SetTicketFileName(verify.uid);
446 krb_set_tkt_string(krb_ticket_string);
447 verify.systemEnviron = setEnv (verify.systemEnviron,
451 verify.userEnviron = setEnv (verify.userEnviron,
455 #endif /* __KERBEROS */
457 /* set LOCATION env var */
458 if(d->displayType.location == Local) {
459 verify.systemEnviron = setEnv (verify.systemEnviron,
462 /* ITE is needed only for Local displays */
463 /* set ITE env var */
465 verify.systemEnviron = setEnv (verify.systemEnviron,
470 verify.systemEnviron = setEnv (verify.systemEnviron,
477 sprintf(gid,"%ld",(long)getgid());
478 /* set user group id (USER_GID) env var */
479 verify.systemEnviron = setEnv (verify.systemEnviron,
483 /* set root group id (ROOT_GID) env var */
484 pwd = getpwnam("root");
486 sprintf(gid,"%ld",(long)pwd->pw_gid);
487 verify.systemEnviron = setEnv (verify.systemEnviron,
494 * Run system-wide initialization file
496 if (source (&verify, d->startup) != 0)
498 Debug ("Startup program %s exited with non-zero status\n",
500 SessionExit (d, OBEYSESS_DISPLAY);
504 if ( solaris_setdevperm(d->gettyLine, verify.uid, verify.gid) == 0 ) {
505 SessionExit (d, OBEYSESS_DISPLAY);
510 if (!setjmp (abortSession)) {
511 signal (SIGTERM, catchTerm);
513 * Start the clients, changing uid/groups
514 * setting up environment and running the session
516 if (StartClient (&verify, d, &clientPid)) {
517 Debug ("Client started\n");
520 * We've changed dtlogin to pass HUP's down to the children
521 * so ignore any HUP's once the client has started.
523 signal(SIGHUP, SIG_IGN);
526 * Wait for session to end,
531 if (!setjmp (pingTime))
533 signal (SIGALRM, catchAlrm);
534 alarm (d->pingInterval * 60);
535 pid = wait ((waitType *) 0);
541 if (!PingServer (d, (Display *) NULL))
542 SessionPingFailed (d);
547 pid = wait ((waitType *) 0);
549 if (pid == clientPid)
554 * We've changed dtlogin to pass HUP's down to the children
555 * so ignore any HUP's once the client has started.
557 signal(SIGHUP, SIG_DFL);
559 LogError(ReadCatalog(
560 MC_LOG_SET,MC_LOG_FAIL_START,MC_DEF_LOG_FAIL_START));
564 * when terminating the session, nuke
565 * the child and then run the reset script
567 AbortClient (clientPid);
571 * on foreign displays without XDMCP, send a SIGTERM to the process
572 * group of the session manager. This augments the "resetServer()"
573 * routine and helps get all clients killed. It is possible for a client
574 * to have a connection to the server, but not have a window.
577 if (d->displayType.location == Foreign &&
578 d->displayType.origin != FromXDMCP )
579 AbortClient(clientPid);
584 * remove ticket file...
587 if ( IsVerifyName(VN_KRB) ) {
591 #endif /* __KERBEROS */
595 * run system-wide reset file
597 Debug ("Source reset program %s\n", d->reset);
598 source (&verify, d->reset);
600 #if defined(PAM) || defined(SUNAUTH)
602 char* user = getEnv (verify.userEnviron, "USER");
603 char* ttyLine = d->gettyLine;
605 # ifdef DEF_NETWORK_DEV
607 * If location is not local (remote XDMCP dtlogin) and
608 * remote accouting is enabled (networkDev start with /dev/...)
609 * Set tty line name to match network device for accouting.
610 * Unless the resource was specifically set, default is value
611 * of DEF_NETWORK_DEV define (/dev/dtremote)
614 if ( d->displayType.location != Local &&
615 networkDev && !strncmp(networkDev,"/dev/",5)) {
616 ttyLine = networkDev+5;
621 PamAccounting( verify.argv[0], d->name, d->utmpId, user,
622 ttyLine, clientPid, ACCOUNTING, NULL);
624 solaris_accounting( verify.argv[0], d->name, d->utmpId, user,
625 ttyLine, clientPid, ACCOUNTING, NULL);
629 solaris_resetdevperm(ttyLine);
634 SessionExit (d, OBEYSESS_DISPLAY);
639 LoadXloginResources( struct display *d )
644 char *resources = NULL;
648 if (d->resources && d->resources[0]) {
649 resources = _ExpandLang(d->resources, d->language);
650 if (access (resources, R_OK) != 0) {
651 /** fallback to the C locale for resources **/
652 Debug("LoadXloginResources - cant access %s\n", resources);
653 Debug("\t %s. Falling back to C.\n", strerror(errno));
655 resources = _ExpandLang(d->resources, "C");
656 if (access (resources, R_OK) != 0) {
657 /** can't find a resource file, so bail **/
658 Debug("LoadXloginResources - cant access %s.\n", resources);
659 Debug("\t %s. Unable to find resource file.\n",
666 if (d->authFile && strlen(d->authFile) > 0 ) {
667 authority = d->authFile;
668 auth_key = "XAUTHORITY=";
671 Debug("LoadXloginResources - loading resource db from %s\n", resources);
672 if((XresourceDB = XrmGetFileDatabase(resources)) == NULL)
673 Debug("LoadXloginResources - Loading resource db from %s failed\n",
676 LoadAltDtsResources(d);
678 strcpy(tmpname,"/var/dt/dtlogin_XXXXXX");
679 (void) mktemp(tmpname);
681 XrmPutFileDatabase(XresourceDB, tmpname);
683 sprintf (cmd, "%s%s %s -display %s -load %s",
684 auth_key, authority, d->xrdb, d->name, tmpname);
685 Debug ("Loading resource file: %s\n", cmd);
687 if(-1 == system (cmd)) {
688 Debug ("system() failed on cmd '%s'\n", cmd);
692 if (debugLevel <= 10)
693 if (unlink (tmpname) == -1)
694 Debug ("unlink() on %s failed\n", tmpname);
697 if (resources) free (resources);
702 /***************************************************************************
704 * LoadAltDtsResources
707 * set up alternate desktop resources..
709 ***************************************************************************/
712 LoadAltDtsResources(struct display *d)
716 char dirname[2][MAXPATHLEN];
717 char res_file[MAXPATHLEN];
718 char *rmtype; /* for XrmGetResource() */
719 XrmValue rmvalue; /* for XrmGetResource() */
720 char buf[MAXPATHLEN];
721 char tempbuf[MAXPATHLEN];
724 char altdtres[MAXPATHLEN];
725 char Altdtres[MAXPATHLEN];
728 char *resources = NULL;
730 int num_allocated = 0;
731 char **file_list = NULL;
734 if ( XrmGetResource(XresourceDB,
735 "Dtlogin*altDts", "Dtlogin*AltDts",
736 &rmtype, &rmvalue ) ) {
737 snprintf(tempbuf, sizeof(tempbuf), "%s", rmvalue.addr);
741 strcpy(dirname[0],CDE_INSTALLATION_TOP "/config/%L/Xresources.d/");
742 strcpy(dirname[1],CDE_CONFIGURATION_TOP "/config/%L/Xresources.d/");
744 for(j = 0; j < 2 ; ++j)
746 resources = _ExpandLang(dirname[j], d->language);
747 if (access (resources, R_OK) != 0)
749 Debug("LoadAltDtsResources- cant access %s.\n", resources);
750 Debug("\t %s. Falling back to C.\n", strerror(errno));
755 resources = _ExpandLang(dirname[j], "C");
756 if (access (resources, R_OK) != 0)
758 Debug("LoadAltDtsResources- cant access %s.\n", resources);
759 Debug("\t %s.\n", strerror(errno));
762 snprintf(dirname[j], sizeof(dirname[j]), "%s", resources);
765 snprintf(dirname[j], sizeof(dirname[j]), "%s", resources);
766 Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
775 * Create a list of the alt DT files
777 * NOTE - an assumption made here is that files in /etc/dt
778 * should take precedence over files in /usr/dt. This precedence
779 * is maintained during the sort becase /etc/dt will come before
783 for(j = 0; j < 2 ; ++j) {
785 if((dirp = opendir(dirname[j])) != NULL) {
787 while((dp = readdir(dirp)) != NULL) {
789 if ((strcmp(dp->d_name, DOT) != 0) &&
790 (strcmp(dp->d_name, DOTDOT) != 0)) {
792 sprintf (res_file, "%s%s", dirname[j],dp->d_name);
793 if ((access (res_file, R_OK)) != 0)
795 Debug("LoadAltDtsResources- cant access %s.\n",
797 Debug("\t %s.\n", strerror(errno));
801 if (file_count == 0) {
802 file_list = malloc (list_incr * sizeof(char *));
803 num_allocated += list_incr;
805 if (file_count + 1 > num_allocated) {
806 num_allocated += list_incr;
807 file_list = realloc (file_list,
808 num_allocated * sizeof(char *));
810 file_list[file_count] = strdup (res_file);
819 qsort (file_list, file_count, sizeof (char *), FileNameCompare);
821 for (j = 0; j < file_count ; j++) {
823 userDb = XrmGetFileDatabase(file_list[j]);
824 XrmMergeDatabases(userDb,&XresourceDB);
826 if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
827 "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
830 * remove the trailing spaces
832 if(strchr(rmvalue.addr,' '))
833 snprintf(tempbuf, sizeof(tempbuf), "%s", strtok(rmvalue.addr," "));
835 snprintf(tempbuf, sizeof(tempbuf), "%s", rmvalue.addr);
837 if ((strcmp(tempbuf, "True") == 0) ||
838 (strcmp(tempbuf, "TRUE") == 0)) {
840 if ( XrmGetResource(XresourceDB,
841 "Dtlogin*altDtKey", "Dtlogin*AltDtKey",
842 &rmtype, &rmvalue ) ) {
844 sprintf(altdtres,"Dtlogin*altDtKey%d",i);
845 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
850 if ( XrmGetResource(XresourceDB,
851 "Dtlogin*altDtName", "Dtlogin*AltDtName",
852 &rmtype, &rmvalue ) ) {
853 sprintf(altdtres,"Dtlogin*altDtName%d",i);
854 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
856 if ( XrmGetResource(XresourceDB,
857 "Dtlogin*altDtStart", "Dtlogin*AltDtStart",
858 &rmtype, &rmvalue ) ) {
859 sprintf(altdtres,"Dtlogin*altDtStart%d",i);
860 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
862 if ( XrmGetResource(XresourceDB,
863 "Dtlogin*altDtLogo", "Dtlogin*AltDtLogo",
864 &rmtype, &rmvalue ) ) {
865 sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
866 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
872 sprintf(tempbuf,"%d",i);
873 XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf);
875 if (file_count > 0) {
876 for (i = 0; i < file_count; i++) {
877 Debug ("Loading resource file: %s\n", file_list[i]);
887 * Function Name: _ExpandLang
891 * This function takes the string "string", searches for occurences of
892 * "%L" in the string and if found, the "%L" is substituted with
893 * the value of the $LANG environment variable.
895 * If $LANG is not defined, the %L is replace with NULL.
899 * _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
903 * ret_string = _ExpandLang (string);
905 * char *ret_string; Returns NULL if "string" is NULL or it points
906 * to the expanded string.
908 * char *string; The first part of the pathname. Typically
909 * the directory containing the item of interest.
911 * Note: The caller is responsible for free'ing the returned string.
933 * Count the number of expansions that will occur.
937 for (n = 0, pch = string ; pch != NULL ; ) {
938 if ((pch = strchr (pch, '%')) != NULL) {
945 return (strdup(string));
948 * We should really be calling setlocale to determine the "default"
949 * locale but setlocale's return value is not standardized across
950 * the various vendor platforms nor is it consistent within differnt
951 * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
952 * HP-UX 10.0). The "right" call would be the following line:
954 * if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
956 * Here we hard code the default to "C" instead of leaving it NULL.
958 if (lang || (lang = getenv ("LANG")) || (lang = "C"))
959 lang_len = strlen (lang);
962 * Create the space needed.
964 tmp_len = strlen (string) + (n * lang_len) + n + 1;
965 tmp = (char *) malloc (tmp_len);
966 for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
970 while (pch != NULL) {
973 if ((pch = strchr (pch, '%')) != NULL) {
978 (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
980 else if ((pch != NULL) && *pch == 'L') {
982 if (((pch - trail) >=2) && (*(pch-2) == '/'))
984 * Remove the "/" as well as the "%L".
986 (void) strncat (tmp, trail, (pch - trail) - 2);
988 (void) strncat (tmp, trail, (pch - trail) - 1);
992 * Remove the "%L" and then append the LANG.
994 (void) strncat (tmp, trail, (pch - trail) - 1);
995 (void) strcat (tmp, lang);
999 (void) strncat (tmp, trail, (pch - trail) + 1);
1006 * A '%' was not found.
1008 (void) strcat (tmp, trail);
1017 SetupDisplay (struct display *d)
1019 char **env = 0, **crt_systemEnviron;
1021 if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1023 crt_systemEnviron = verify.systemEnviron;
1024 env = systemEnv (d, (char *) 0, (char *) 0);
1025 if (d->authFile && strlen(d->authFile) > 0 )
1026 env = setEnv( env, "XAUTHORITY", d->authFile );
1027 if(d->displayType.location == Local)
1028 env = setEnv (env, LOCATION, "local");
1030 env = setEnv (env, LOCATION, "remote");
1031 verify.systemEnviron = env;
1032 source (&verify, d->setup);
1033 verify.systemEnviron = crt_systemEnviron;
1040 DeleteXloginResources( struct display *d, Display *dpy )
1042 XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1045 #if 0 /* dead code: transferred to Dtgreet */
1047 static jmp_buf syncJump;
1052 longjmp (syncJump, 1);
1056 SecureDisplay (d, dpy)
1060 Debug ("SecureDisplay():\n");
1061 signal (SIGALRM, syncTimeout);
1062 if (setjmp (syncJump)) {
1063 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1065 SessionExit (d, RESERVER_DISPLAY);
1067 alarm ((unsigned) d->grabTimeout);
1068 Debug ("Before XGrabServer()\n");
1070 if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1071 GrabModeAsync, CurrentTime) != GrabSuccess)
1074 signal (SIGALRM, SIG_DFL);
1075 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1077 SessionExit (d, RESERVER_DISPLAY);
1079 Debug ("XGrabKeyboard() succeeded\n");
1081 signal (SIGALRM, SIG_DFL);
1085 XUngrabServer (dpy);
1088 Debug ("Done secure %s\n", d->name);
1091 UnsecureDisplay (d, dpy)
1095 Debug ("Unsecure display %s\n", d->name);
1097 XUngrabServer (dpy);
1106 release_aix_lic(void)
1109 * Release AIX iFOR/LS license (if any)
1117 release_me.request_type = -1;
1118 release_me.login_pid = getpid();
1119 if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1121 write(fd, &release_me, sizeof(release_me));
1124 Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1132 SessionExit( struct display *d, int status )
1141 /* make sure the server gets reset after the session is over */
1142 if (d->serverPid >= 2) {
1143 Debug("Resetting server: pid %d signal %d\n",
1144 d->serverPid, d->resetSignal);
1146 if (d->terminateServer == 0 && d->resetSignal)
1147 kill (d->serverPid, d->resetSignal);
1152 Debug("Exiting Session with status: %d\n", status);
1157 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1160 char currentdir[PATH_MAX+1];
1161 char *failsafeArgv[20];
1162 char *user; /* users name */
1163 char *lang, *font; /* failsafe LANG and font */
1166 int failsafe = FALSE; /* do we run the failsafe session? */
1167 int password = FALSE; /* do we run /bin/passwd? */
1170 char lastsessfile[MAXPATHLEN];
1173 struct pr_passwd *b1_pwd;
1177 #define NOPAG 0xffffffff
1179 long ngroups, groups[NGROUPS];
1185 Debug ("StartSession %s: ", verify->argv[0]);
1186 for (f = verify->argv; *f; f++) {
1188 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1189 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1193 if (verify->userEnviron) {
1194 for (f = verify->userEnviron; *f; f++)
1199 user = getEnv (verify->userEnviron, "USER");
1201 switch (pid = fork ()) {
1204 /* Force a failsafe session if we can't touch the home directory
1205 * SIA has already attempted to chdir to HOME, and the current dir
1206 * will be set to / if it failed. We just check to see if the HOME
1207 * path is our current directory or not.
1209 home = getEnv (verify->userEnviron, "HOME");
1210 getcwd(currentdir, PATH_MAX+1);
1211 Debug("Current directory is: %s\n", currentdir);
1215 * The following little check doesn't really work. For example,
1216 * here at the XC, NIS reports my home directory as
1217 * "/site/guests/montyb" while getcwd comes up with
1218 * "/net/nexus/site/guests/montyb".
1220 if (strcmp(home, currentdir)) {
1221 Debug("Can't access home directory, setting failsafe to TRUE\n");
1223 LogError (ReadCatalog(
1224 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1225 home, getEnv (verify->userEnviron, "USER"));
1226 verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1234 * do process accounting...
1236 #if defined(PAM) || defined(SUNAUTH)
1238 char* ttyLine = d->gettyLine;
1240 # ifdef DEF_NETWORK_DEV
1242 * If location is not local (remote XDMCP dtlogin) and
1243 * remote accouting is enabled (networkDev start with /dev/...)
1244 * Set tty line name to match network device for accouting.
1245 * Unless the resource was specifically set, default is value
1246 * of DEF_NETWORK_DEV define (/dev/dtremote)
1249 if ( d->displayType.location != Local &&
1250 networkDev && !strncmp(networkDev,"/dev/",5)) {
1251 ttyLine = networkDev+5;
1256 PamAccounting(verify->argv[0], d->name, d->utmpId, user,
1257 ttyLine, getpid(), USER_PROCESS, NULL);
1259 solaris_accounting(verify->argv[0], d->name, d->utmpId, user,
1260 ttyLine, getpid(), USER_PROCESS, NULL);
1265 #if !defined(sun) && !defined(CSRG_BASED)
1266 Account(d, user, NULL, getpid(), USER_PROCESS, status);
1271 * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1272 * setpenv() to set up the user's process environment and return
1273 * without execing. This allows us to set up the process environment
1274 * and proceed to the execute() call as do the other platforms.
1276 * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1277 * we have to pospone the setpenv() to the actual execute().
1281 * These defines are the tag locations in userEnviron.
1282 * IMPORTANT: changes to the locations of these tags in verify.c
1283 * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1285 #define SYS_ENV_TAG 0
1286 #define USR_ENV_TAG 3
1289 * Set the user's credentials: uid, gid, groups,
1290 * audit classes, user limits, and umask.
1293 if (setpcred(user, NULL) == -1)
1295 Debug("Can't set User's Credentials (user=%s)\n",user);
1300 char *usrTag, *sysTag;
1301 extern char **newenv;
1304 * Save pointers to tags. The setpenv() function clears the pointers
1305 * to the tags in userEnviron as a side-effect.
1307 sysTag = verify->userEnviron[SYS_ENV_TAG];
1308 usrTag = verify->userEnviron[USR_ENV_TAG];
1311 * Set the users process environment. Store protected variables and
1312 * obtain updated user environment list. This call will initialize
1315 #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1316 if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1318 Debug("Can't set process environment (user=%s)\n",user);
1323 * Restore pointers to tags.
1325 verify->userEnviron[SYS_ENV_TAG] = sysTag;
1326 verify->userEnviron[USR_ENV_TAG] = usrTag;
1329 * Free old userEnviron and replace with newenv from setpenv().
1331 freeEnv(verify->userEnviron);
1332 verify->userEnviron = newenv;
1342 if (PamSetCred( verify->argv[0],
1343 user, verify->uid, verify->gid) > 0 ) {
1344 Debug("Can't set User's Credentials (user=%s)\n",user);
1350 if ( solaris_setcred(verify->argv[0],
1351 user, verify->uid, verify->gid) > 0 ) {
1352 Debug("Can't set User's Credentials (user=%s)\n",user);
1355 #endif /* SUNAUTH */
1362 * HP BLS B1 session setup...
1364 * 1. look up user's protected account information.
1365 * 2. set the session sensitivity/clearance levels
1366 * 3. set the logical UID (LUID)
1370 Debug("BLS - Setting user's clearance, security level and luid.\n");
1371 set_auth_parameters(1, verify->argv);
1374 verify->user_name = user;
1375 strncpy(verify->terminal,d->name,15);
1376 verify->terminal[15]='\0';
1377 verify->pwd = getpwnam(user);
1379 if ( verify->pwd == NULL || strlen(user) == 0 ) {
1380 LogError(ReadCatalog(
1381 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1384 verify->prpwd= b1_pwd = getprpwnam(user);
1385 verify->uid = b1_pwd->ufld.fd_uid;
1387 if ( b1_pwd == NULL || strlen(user) == 0 ) {
1388 LogError(ReadCatalog(
1389 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1394 * This has already been done successfully by dtgreet
1395 * but we need to get all the information again for the
1398 if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1399 Debug("BLS - Could not verify sensitivity level.\n");
1400 LogError(ReadCatalog(
1401 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1405 if ( change_to_user(verify) != 1 ) {
1406 Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1407 LogError(ReadCatalog(
1408 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1413 Debug("BLS - Session setup complete.\n");
1418 if ( IsVerifyName(VN_AFS) ) {
1419 pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1420 Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1422 initgroups(greet.name, verify->groups[2]);
1423 ngroups = getgroups(NGROUPS, groups);
1424 Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1425 for (i=0; i < ngroups; i++)
1426 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1428 if ((pagval != NOPAG) &&
1429 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1430 /* we will have to shift grouplist to make room for pag */
1431 if (ngroups+2 > NGROUPS)
1433 for (j=ngroups-1; j >= 0; j--) {
1434 groups[j+2] = groups[j];
1437 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1438 if (setgroups(ngroups, groups) == -1) {
1441 MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1446 # else /* ! __AFS */
1447 /* If SIA is enabled, the initgroups and setgid calls are redundant
1454 * if your system does not support "initgroups(3C)", use
1455 * the "setgroups()" call instead...
1458 # if defined(__hpux)
1459 initgroups(user, -1);
1461 setgroups (verify->ngroups, verify->groups);
1464 /* setpenv() will set gid for AIX */
1466 if(-1 == setgid (verify->groups[0])) {
1467 perror(strerror(errno));
1471 # else /* ! NGROUPS */
1473 /* setpenv() will set gid for AIX */
1475 setgid (verify->gid);
1478 # endif /* NGROUPS */
1484 setaudid(verify->audid);
1485 setaudproc(verify->audflg);
1488 /* setpenv() will set uid for AIX */
1490 if (setuid(verify->uid) != 0) {
1491 Debug( "Setuid failed for user %s, errno = %d\n", user, errno);
1492 LogError(ReadCatalog(
1493 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1500 } /* ends the else clause of if ( ISSECURE ) */
1506 * check home directory again...
1510 /* Don't need to do this if SIA is enabled, already been done.
1512 home = getEnv (verify->userEnviron, "HOME");
1514 if (chdir (home) == -1) {
1515 LogError (ReadCatalog(
1516 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1517 home, getEnv (verify->userEnviron, "USER"));
1518 if(-1 == chdir ("/")) {
1519 perror(strerror(errno));
1521 verify->userEnviron = setEnv(verify->userEnviron,
1524 else if(!failsafe) {
1525 strcpy(lastsessfile,home); /* save user's last session */
1526 strcat(lastsessfile,LAST_SESSION_FILE);
1527 if((lastsession = fopen(lastsessfile,"w")) == NULL)
1528 Debug("Unable to open file for writing: %s\n",lastsessfile);
1530 fputs(verify->argv[0],lastsession);
1531 fclose(lastsession);
1538 SetUserAuthorization (d, verify);
1544 bzero(greet.password, strlen(greet.password));
1548 * Write login information to a file
1549 * The file name should really be settable by some kind of resource
1550 * but time is short so we hard-wire it to ".dtlogininfo".
1552 if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1553 Debug("Unable to write \".dtlogininfo\"\n");
1555 /* extra debugging */
1556 if(!dump_sec_debug_info(verify)) {
1557 Debug("Something wrong with environment\n");
1560 # endif /* ! NDEBUG */
1568 Debug ("Executing session %s\n", verify->argv[0]);
1569 execute (verify->argv, verify->userEnviron);
1570 LogError(ReadCatalog(
1571 MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1575 LogError(ReadCatalog(
1576 MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1583 * specify a font for the multi-byte languages...
1587 lang = getEnv (verify->userEnviron, "LANG");
1594 failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1596 failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1597 #elif defined(__hpux)
1598 failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1599 #elif defined(__OpenBSD__)
1600 failsafeArgv[i++] = "/usr/X11R6/bin/xterm";
1601 #elif defined(__NetBSD__)
1602 failsafeArgv[i++] = "/usr/X11R7/bin/xterm";
1603 #elif defined(__FreeBSD__)
1604 failsafeArgv[i++] = "/usr/local/bin/xterm";
1606 failsafeArgv[i++] = "/usr/bin/X11/xterm";
1608 failsafeArgv[i++] = "-geometry";
1609 failsafeArgv[i++] = "80x10";
1610 failsafeArgv[i++] = "-bg";
1611 failsafeArgv[i++] = "white";
1612 failsafeArgv[i++] = "-fg";
1613 failsafeArgv[i++] = "black";
1615 /* aixterm requires -lang option. */
1616 failsafeArgv[i++] = "-lang";
1617 failsafeArgv[i++] = lang;
1619 failsafeArgv[i++] = "-fn";
1621 if (font == NULL) font = "fixed";
1622 failsafeArgv[i++] = font;
1625 failsafeArgv[i++] = "-e";
1626 failsafeArgv[i++] = "/bin/passwd";
1627 #if defined(__PASSWD_ETC)
1628 failsafeArgv[i++] = "-n";
1630 failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1633 failsafeArgv[i++] = d->failsafeClient;
1635 failsafeArgv[i++] = "-C";
1637 failsafeArgv[i++] = "-ls";
1640 failsafeArgv[i++] = "-fn";
1641 failsafeArgv[i++] = font;
1645 failsafeArgv[i] = 0;
1646 Debug ("Executing failsafe session\n", failsafeArgv[0]);
1647 execute (failsafeArgv, verify->userEnviron);
1650 Debug ("StartSession(): fork failed\n");
1651 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1655 Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1662 static jmp_buf tenaciousClient;
1665 waitAbort( int arg )
1667 longjmp (tenaciousClient, 1);
1670 #if defined(SYSV) || defined(SVR4)
1672 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1676 AbortClient( int pid )
1685 for (i = 0; i < 4; i++) {
1686 if (killpg (pid, sig) == -1) {
1689 LogError(ReadCatalog(
1690 MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1696 if (!setjmp (tenaciousClient)) {
1697 (void) signal (SIGALRM, waitAbort);
1698 (void) alarm ((unsigned) 10);
1699 retId = wait ((waitType *) 0);
1700 (void) alarm ((unsigned) 0);
1701 (void) signal (SIGALRM, SIG_DFL);
1705 signal (SIGALRM, SIG_DFL);
1712 source( struct verify_info *verify, char *file )
1718 if (file && file[0]) {
1719 Debug ("Source(): %s\n", file);
1720 switch (pid = fork ()) {
1725 execute (args, verify->systemEnviron);
1726 LogError(ReadCatalog(
1727 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1730 Debug ("Source(): fork failed\n");
1731 LogError(ReadCatalog(
1732 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1736 while (wait (&result) != pid)
1740 return waitVal (result);
1745 /* returns 0 on failure, -1 on out of mem, and 1 on success */
1747 execute(char **argv, char **environ )
1751 * make stdout follow stderr to the log file...
1756 session_execve (argv[0], argv, environ);
1759 * In case this is a shell script which hasn't been made executable
1760 * (or this is a SYSV box), do a reasonable thing...
1764 /* errno is EACCES if not executable */
1765 if (errno == ENOEXEC || errno == EACCES) {
1767 if (errno == ENOEXEC) {
1769 char program[1024], *e, *p, *optarg;
1771 char **newargv, **av;
1775 * emulate BSD kernel behaviour -- read
1776 * the first line; check if it starts
1777 * with "#!", in which case it uses
1778 * the rest of the line as the name of
1779 * program to run. Else use "/bin/sh".
1781 f = fopen (argv[0], "r");
1784 if (fgets (program, sizeof (program) - 1, f) == NULL)
1790 e = program + strlen (program) - 1;
1793 if (!strncmp (program, "#!", 2)) {
1795 while (*p && isspace (*p))
1798 while (*optarg && !isspace (*optarg))
1804 while (*optarg && isspace (*optarg));
1811 Debug ("Shell script execution: %s (optarg %s)\n",
1812 p, optarg ? optarg : "(null)");
1813 for (av = argv, argc = 0; *av; av++, argc++)
1815 newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1822 while (*av++ = *argv++)
1824 session_execve (newargv[0], newargv, environ);
1833 /*****************************************************************************
1836 * Invoke the Greeter process and wait for completion. If the user was
1837 * successfully verified, return to the calling process. If the user
1838 * selected a restart or abort option, or there was an error invoking the
1839 * Greeter, exit this entire process with appropriate status.
1841 *****************************************************************************/
1845 extern int session_set;
1846 extern char *progName; /* Global argv[0]; dtlogin name and path */
1848 int response[2], request[2];
1850 /* Fixes problem with dtlogin signal handling */
1851 static int greeterPid = 0;
1852 static struct display *greeter_d = NULL;
1857 Debug("Caught SIGHUP\n");
1860 Debug("Killing greeter process: %d\n", greeterPid);
1861 kill(greeterPid, SIGHUP);
1864 SessionExit(greeter_d, REMANAGE_DISPLAY);
1866 exit(REMANAGE_DISPLAY);
1870 RunGreeter( struct display *d, struct greet_info *greet,
1871 struct verify_info *verify )
1878 static char msg[MSGSIZE];
1882 struct greet_state state;
1889 # define U_NAMELEN sizeof(rgy_$name_t)
1893 static char name_short[U_NAMELEN];
1899 char *argv[] = { "dtlogin", 0 };
1900 char *hostName = NULL;
1901 char *loginName = NULL;
1908 if (d->serverPid == -1)
1911 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
1912 loginName, d->name, 1, NULL);
1913 if (siaStatus != SIASUCCESS)
1915 Debug("sia_ses_init failure status %d\n", siaStatus);
1922 if (!setjmp (abortSession)) {
1923 signal(SIGTERM, catchTerm);
1926 * We've changed dtlogin to pass HUP's down to the children
1927 * so ignore any HUP's once the client has started.
1930 signal(SIGHUP, catchHUP);
1933 * set up communication pipes...
1936 if(-1 == pipe(response)) {
1937 perror(strerror(errno));
1939 if(-1 == pipe(request)) {
1940 perror(strerror(errno));
1945 switch (greeterPid = fork ()) {
1949 * pass some information in the environment...
1953 sprintf(msg,"%d", d->grabServer);
1954 env = setEnv(env, GRABSERVER, msg);
1956 sprintf(msg,"%d", d->grabTimeout);
1957 env = setEnv(env, GRABTIMEOUT, msg);
1960 if (timeZone && strlen(timeZone) > 0 )
1961 env = setEnv(env, "TZ", timeZone);
1963 if (errorLogFile && errorLogFile[0])
1964 env = setEnv(env, ERRORLOG, errorLogFile);
1967 env = setEnv(env, "XAUTHORITY", d->authFile);
1970 env = setEnv(env, DTLITE, "True");
1973 env = setEnv(env, SESSION, d->session);
1976 env = setEnv(env, SESSION_SET, "True");
1978 if (d->pmSearchPath)
1979 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
1981 if (d->bmSearchPath)
1982 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
1984 #if defined (__KERBEROS) || defined (__AFS)
1985 if (d->verifyName) {
1986 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
1987 (strcmp(d->verifyName, VN_KRB) == 0) ) {
1989 env = setEnv(env, VERIFYNAME, d->verifyName );
1992 LogError(ReadCatalog(
1993 MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
1995 d->verifyName = NULL;
2000 if((path = getenv("NLSPATH")) != NULL)
2001 env = setEnv(env, "NLSPATH", path);
2005 * ping remote displays...
2009 if (d->displayType.location == Local) {
2010 GettyRunning(d); /* refresh gettyState */
2011 if (d->gettyState != DM_GETTY_USER)
2012 env = setEnv(env, LOCATION, "local");
2015 sprintf(msg,"%d", d->pingInterval);
2016 env = setEnv(env, PINGINTERVAL, msg);
2018 sprintf(msg,"%d", d->pingTimeout);
2019 env = setEnv(env, PINGTIMEOUT, msg);
2023 if ( d->langList && strlen(d->langList) > 0 )
2024 env = setEnv(env, LANGLIST, d->langList);
2025 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2026 else if (strlen(languageList) > 0 )
2027 env = setEnv(env, LANGLIST, languageList);
2028 #endif /* ENABLE_DYNAMIC_LANGLIST */
2031 char *language = NULL;
2033 #if defined (ENABLE_DYNAMIC_LANGLIST)
2034 language = d->language;
2035 #endif /* ENABLE_DYNAMIC_LANGLIST */
2037 if (env && d->language && strlen(d->language) > 0 )
2038 env = setLang(d, env, language);
2041 if((path = getenv("XKEYSYMDB")) != NULL)
2042 env = setEnv(env, "XKEYSYMDB", path);
2045 if((path = getenv("OPENWINHOME")) != NULL)
2046 env = setEnv(env, "OPENWINHOME", path);
2049 Debug ("Greeter environment:\n");
2051 Debug ("End of Greeter environment:\n");
2054 * Writing to file descriptor 1 goes to response pipe instead.
2057 dupfp = dup(response[1]);
2059 perror(strerror(errno));
2065 * Reading from file descriptor 0 reads from request pipe instead.
2068 dupfp2 = dup(request[0]);
2070 perror(strerror(errno));
2078 * figure out path to dtgreet...
2081 snprintf(msg, sizeof(msg), "%s", progName);
2083 if ((p = (char *) strrchr(msg, '/')) == NULL)
2088 strcat(msg,"dtgreet");
2090 execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2091 LogError(ReadCatalog(
2092 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2094 exit (NOTIFY_ABORT_DISPLAY);
2097 Debug ("Fork of Greeter failed.\n");
2098 LogError(ReadCatalog(
2099 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2104 exit (UNMANAGE_DISPLAY);
2107 Debug ("Greeter started\n");
2109 close(response[1]); /* Close write end of response pipe */
2110 close(request[0]); /* Close read end of request pipe */
2114 * Retrieve information from greeter and authenticate.
2116 globalDisplayName = d->name;
2117 state.id = GREET_STATE_ENTER;
2118 state.waitForResponse = FALSE;
2122 * atexit() registers this function to be called if exit() is
2123 * called. This is needed because in enhanced security mode, SIA
2124 * may call exit() whn the user fails to enter or change a
2127 sia_greeter_pid = greeterPid;
2128 if (!sia_exit_proc_reg)
2130 atexit(KillGreeter);
2131 sia_exit_proc_reg = TRUE;
2134 siaGreeterInfo.d = d;
2135 siaGreeterInfo.greet = greet;
2136 siaGreeterInfo.verify = verify;
2137 siaGreeterInfo.state = &state;
2138 siaGreeterInfo.status = TRUE;
2141 while(siaStatus != SIASUCCESS)
2143 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2145 Debug ("RunGreeter: before sia_ses_authent\n");
2146 dt_in_sia_ses_authent = True;
2147 siaStatus = sia_ses_authent(SiaManageGreeter, NULL,
2149 dt_in_sia_ses_authent = False;
2150 Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2152 if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2154 state.id = GREET_STATE_ERRORMESSAGE;
2155 state.vf = VF_INVALID;
2156 ManageGreeter(d, greet, verify, &state);
2158 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2161 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2163 sia_ses_release(&siaHandle);
2167 Debug("RunGreeter: before sia_ses_estab\n");
2168 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2169 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2172 if (!siaGreeterInfo.status)
2175 if (siaStatus == SIASUCCESS)
2177 Debug("RunGreeter: before sia_ses_launch\n");
2178 siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2179 Debug("RunGreeter: after sia_ses_launch status = %d\n",
2182 if (!siaGreeterInfo.status)
2185 if (siaStatus != SIASUCCESS)
2187 Debug("RunGreeter: sia_ses_launch failure\n");
2188 /* establish & launch failures do a release */
2190 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
2191 loginName, d->name, 1, NULL);
2192 if (siaStatus != SIASUCCESS)
2194 Debug("sia_ses_init failure status %d\n", siaStatus);
2195 exit(RESERVER_DISPLAY);
2200 * sia_ses_launch() wil probably seteuid to that of the
2201 * user, but we don't want that now.
2205 * extract necessary info from SIA context struct
2209 if (siaStatus == SIASUCCESS)
2210 CopySiaInfo(siaHandle, greet);
2211 sia_ses_release(&siaHandle);
2213 state.id = GREET_STATE_TERMINATEGREET;
2214 if (siaGreeterInfo.status)
2216 while (ManageGreeter(d, greet, verify, &state))
2219 sia_greeter_pid = 0;
2221 while (ManageGreeter(d, greet, verify, &state))
2226 * Wait for Greeter to end...
2229 pid = wait (&status);
2230 if (pid == greeterPid)
2236 * Greeter exited. Check return code...
2239 Debug("Greeter return status; exit = %d, signal = %d\n",
2240 waitCode(status), waitSig(status));
2244 * remove authorization file if used...
2247 if (d->authorizations && d->authFile &&
2248 waitVal(status) != NOTIFY_LANG_CHANGE
2250 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2255 Debug ("Done with authorization file %s, removing\n",
2257 (void) unlink (d->authFile);
2262 if(waitVal(status) > NOTIFY_ALT_DTS)
2263 d->sessionType = waitVal(status);
2266 switch (waitVal(status)) {
2267 case NOTIFY_FAILSAFE:
2268 greet->string = "failsafe";
2270 case NOTIFY_PASSWD_EXPIRED:
2271 greet->string = "password";
2276 case NOTIFY_LAST_DT:
2277 d->sessionType = waitVal(status);
2283 Debug("waitVal - status is %d\n", waitVal(status));
2284 if(waitVal(status) > NOTIFY_ALT_DTS)
2285 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2287 notify_dt = waitVal(status);
2289 switch (notify_dt) {
2290 case NOTIFY_FAILSAFE:
2291 case NOTIFY_PASSWD_EXPIRED:
2295 case NOTIFY_LAST_DT:
2296 case NOTIFY_ALT_DTS:
2298 if (NULL == greet->name) return;
2301 * greet->name, greet->password set in ManageGreeter().
2303 Debug("Greeter returned name '%s'\n", greet->name);
2306 greet->name_full = greet->name;
2307 /* get just person name out of full SID */
2309 while (i < sizeof(rgy_$name_t)
2310 && greet->name_full[i] != '.'
2311 && greet->name_full[i] != '\0') {
2312 name_short[i] = greet->name_full[i];
2315 name_short[i] = '\0';
2316 greet->name = name_short;
2321 * groups[] set in Authenticate().
2323 if ( IsVerifyName(VN_AFS) ) {
2324 verify->groups[0] = groups[0];
2325 verify->groups[1] = groups[1];
2326 Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2327 Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2333 * sensitivityLevel set in BLS_Verify()
2335 greet->b1security = sensitivityLevel;
2338 Verify(d, greet, verify);
2342 Debug ("Greeter Xlib error or SIGTERM\n");
2343 SessionExit(d, OPENFAILED_DISPLAY);
2345 case NOTIFY_RESTART:
2346 Debug ("Greeter requested RESTART_DISPLAY\n");
2347 SessionExit(d, RESERVER_DISPLAY);
2349 case NOTIFY_ABORT_DISPLAY:
2350 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2351 SessionExit(d, UNMANAGE_DISPLAY);
2353 case NOTIFY_NO_WINDOWS:
2354 Debug ("Greeter requested NO_WINDOWS mode\n");
2355 if (d->serverPid >= 2)
2357 * Don't do a SessionExit() here since that causes
2358 * the X-server to be reset. We know we are going to
2359 * terminate it anyway, so just go do that...
2361 exit(SUSPEND_DISPLAY);
2365 case NOTIFY_LANG_CHANGE:
2366 Debug ("Greeter requested LANG_CHANGE\n");
2369 * copy requested language into display struct "d". Note,
2370 * this only happens in this child's copy of "d", not in
2371 * the master struct. When the user logs out, the
2372 * resource-specified language (if any) will reactivate.
2375 Debug("Greeter returned language '%s'\n", d->language);
2377 Debug("Greeter returned language (NULL)\n");
2380 if (strcmp(d->language, "default") == 0) {
2381 int len = strlen(defaultLanguage) + 1;
2382 d->language = (d->language == NULL ?
2383 malloc(len) : realloc (d->language, len));
2384 strcpy(d->language, defaultLanguage);
2388 case NOTIFY_BAD_SECLEVEL:
2391 case waitCompose (SIGTERM,0,0):
2392 Debug ("Greeter exited on SIGTERM\n");
2393 SessionExit(d, OPENFAILED_DISPLAY);
2396 Debug ("Greeter returned unknown status %d\n",
2398 SessionExit(d, REMANAGE_DISPLAY);
2401 signal(SIGHUP, SIG_DFL);
2404 AbortClient(greeterPid);
2405 SessionExit(d, UNMANAGE_DISPLAY);
2409 /*****************************************************************************
2415 This is the entry into greeter state processing. Allocate and initialize
2419 Display the login screen. Upon display, the login screen can be 'reset'. If
2420 reset is true, the username and password fields are cleared and the focus
2421 is set to the username field. If reset is false, the username and password
2422 field is untouched and the focus is set to the password field.
2424 LOGIN -> AUTHENTICATE:
2425 Authenticate the username entered on login screen.
2427 AUTHENTICATE -> TERMINATEGREET:
2428 User passed authentication so terminate the greeter.
2430 AUTHENTICATE -> EXPASSWORD:
2431 User passed authentication, but the their password has expired.
2432 Display old password message. This message allows the user to
2433 change their password by starting a getty and running passwd(1).
2435 AUTHENTICATE -> BAD_HOSTNAME:
2436 User passed authentication, but the their hostname is empty.
2437 Display a dialog that allows the user to run a getty to fix the
2438 problem, or start the desktop anyway.
2440 AUTHENTICATE -> ERRORMESSAGE:
2441 User failed authentication, so display error message.
2443 AUTHENTICATE -> LOGIN
2444 User failed authentication, but did not enter a password. Instead
2445 of displaying an error message, redisplay the login screen with
2446 the focus set to the password field. If the user authenticates again
2447 without the password field set, display an error. This allows a user
2448 to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2451 Free state structure and return false to stop state transitions.
2453 ERRORMESSAGE -> LOGIN
2454 Display error message base on return code from last authentication
2455 attempt. Redisplay login screen with reset set to true.
2457 (state) -> LANG -> (state)
2458 User has chosen a new language. Transition to LANG state to save off
2459 the new language, and transition back to original state.
2461 *****************************************************************************/
2463 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2466 ManageGreeter( struct display *d, struct greet_info *greet,
2467 struct verify_info *verify, struct greet_state *state )
2474 if (state->waitForResponse)
2476 if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2479 * Dtgreet has terminated.
2481 state->id = GREET_STATE_EXIT;
2482 state->waitForResponse = FALSE;
2486 if (state->request->opcode != state->response->opcode)
2489 * An unrequested event arrived. See if it's one we
2492 switch(state->response->opcode)
2494 case REQUEST_OP_LANG:
2497 * User has changed language. Recursively handle this state
2498 * and return to current state.
2500 struct greet_state lang_state;
2502 lang_state = *state;
2503 lang_state.id = GREET_STATE_LANG;
2504 lang_state.waitForResponse = FALSE;
2505 ManageGreeter(d, greet, verify, &lang_state);
2506 Debug("Response opcode REQUEST_OP_LANG\n");
2511 case REQUEST_OP_CLEAR:
2514 * User has requested the screen be cleared.
2516 state->id = GREET_STATE_USERNAME;
2517 state->waitForResponse = TRUE;
2518 Debug("Response opcode REQUEST_OP_CLEAR\n");
2523 Debug("Response opcode UNEXPECTED RESPONSE!\n");
2533 * Got the response we were expecting.
2535 state->waitForResponse = FALSE;
2541 case GREET_STATE_ENTER:
2544 * Enter - initialize state
2546 Debug("GREET_STATE_ENTER\n");
2548 state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2549 state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2550 state->authenticated = FALSE;
2553 state->id = GREET_STATE_USERNAME;
2557 case GREET_STATE_USERNAME:
2562 RequestChallenge *r;
2564 Debug("GREET_STATE_USERNAME\n");
2566 Authenticate(d, NULL, NULL, NULL);
2568 SETMC(msg, LOGIN_LABEL);
2570 r = (RequestChallenge *)state->request;
2571 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2572 r->hdr.reserved = 0;
2575 r->hdr.length = sizeof(*r);
2577 r->offChallenge = sizeof(*r);
2578 strcpy(((char *)r) + r->offChallenge, msg.def);
2579 r->hdr.length += strlen(msg.def) + 1;
2583 r->offUserNameSeed = r->hdr.length;
2584 strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2585 r->hdr.length += strlen(greet->name) + 1;
2586 Debug("Greet name: %s\n", greet->name);
2590 r->offUserNameSeed = 0;
2595 free(greet->name); greet->name = NULL;
2597 if (greet->password)
2599 free(greet->password); greet->password = NULL;
2602 TellGreeter((RequestHeader *)r);
2603 state->waitForResponse = TRUE;
2605 state->id = GREET_STATE_AUTHENTICATE;
2609 case GREET_STATE_CHALLENGE:
2614 RequestChallenge *r;
2616 Debug("GREET_STATE_CHALLENGE\n");
2618 if (greet->password)
2620 free(greet->password); greet->password = NULL;
2623 SETMC(msg, PASSWD_LABEL);
2625 r = (RequestChallenge *)state->request;
2626 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2627 r->hdr.reserved = 0;
2630 r->offUserNameSeed = 0;
2631 r->offChallenge = sizeof(*r);
2632 strcpy(((char *)r) + r->offChallenge, msg.def);
2633 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2635 TellGreeter((RequestHeader *)r);
2636 state->waitForResponse = TRUE;
2638 state->id = GREET_STATE_AUTHENTICATE;
2642 case GREET_STATE_AUTHENTICATE:
2645 * Attempt to authenticate.
2647 ResponseChallenge *r;
2649 Debug("GREET_STATE_AUTHENTICATE\n");
2651 r = (ResponseChallenge *)state->response;
2653 if (greet->name == NULL)
2655 greet->name = strdup(((char *)r) + r->offResponse);
2656 if (strlen(greet->name) == 0)
2658 state->id = GREET_STATE_USERNAME;
2664 greet->password = strdup(((char *)r) + r->offResponse);
2674 * Attempt to authenticate user. 'username' should be a
2675 * non-empty string. 'password' may be an empty string.
2677 state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2679 if (state->vf == VF_OK ||
2680 state->vf == VF_PASSWD_AGED ||
2681 state->vf == VF_BAD_HOSTNAME)
2683 state->authenticated = TRUE;
2687 * General transitions.
2691 case VF_OK: state->id = GREET_STATE_TERMINATEGREET; break;
2692 case VF_PASSWD_AGED: state->id = GREET_STATE_EXPASSWORD; break;
2693 case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break;
2694 case VF_CHALLENGE: state->id = GREET_STATE_CHALLENGE; break;
2695 default: state->id = GREET_STATE_ERRORMESSAGE; break;
2700 case GREET_STATE_EXIT:
2703 * Free resources and leave.
2705 Debug("GREET_STATE_EXIT\n");
2712 if (!state->authenticated)
2716 free(greet->name); greet->name = NULL;
2718 if (greet->password)
2720 free(greet->password); greet->password = NULL;
2724 free(state->request);
2725 free(state->response);
2730 case GREET_STATE_ERRORMESSAGE:
2733 * Display error message.
2737 Debug("GREET_STATE_ERRORMESSAGE\n");
2739 r = (RequestMessage *)state->request;
2743 case VF_INVALID: SETMC(msg, LOGIN); break;
2744 case VF_HOME: SETMC(msg, HOME); break;
2745 case VF_MAX_USERS: SETMC(msg, MAX_USERS); break;
2746 case VF_BAD_UID: SETMC(msg, BAD_UID); break;
2747 case VF_BAD_GID: SETMC(msg, BAD_GID); break;
2748 case VF_BAD_AID: SETMC(msg, BAD_AID); break;
2749 case VF_BAD_AFLAG: SETMC(msg, BAD_AFLAG); break;
2750 case VF_NO_LOGIN: SETMC(msg, NO_LOGIN); break;
2752 case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2754 case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2755 default: msg.id=0; msg.def=""; break;
2758 r->hdr.opcode = REQUEST_OP_MESSAGE;
2759 r->hdr.reserved = 0;
2761 r->offMessage = sizeof(*r);
2762 strcpy(((char *)r) + r->offMessage, msg.def);
2763 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2765 TellGreeter((RequestHeader *)r);
2766 state->waitForResponse = TRUE;
2768 state->id = GREET_STATE_USERNAME;
2772 case GREET_STATE_LANG:
2775 * User selected new language.
2781 Debug("GREET_STATE_LANG\n");
2783 r = (ResponseLang *)state->response;
2784 lang = ((char *)r) + r->offLang;
2785 len = strlen(lang) + 1;
2787 d->language = (d->language == NULL ?
2788 malloc(len) : realloc(d->language, len));
2789 strcpy(d->language, lang);
2790 Debug("Language returned: %s\n", d->language);
2794 case GREET_STATE_TERMINATEGREET:
2797 * Terminate dtgreet.
2801 Debug("GREET_STATE_TERMINATEGREET\n");
2803 r = (RequestExit *)state->request;
2805 r->hdr.opcode = REQUEST_OP_EXIT;
2806 r->hdr.reserved = 0;
2807 r->hdr.length = sizeof(*r);
2809 TellGreeter((RequestHeader *)r);
2810 state->waitForResponse = TRUE;
2812 state->id = GREET_STATE_EXIT;
2816 case GREET_STATE_EXPASSWORD:
2819 * Display password expired message.
2821 RequestExpassword *r;
2823 Debug("GREET_STATE_EXPASSWORD\n");
2825 r = (RequestExpassword *)state->request;
2827 r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2828 r->hdr.reserved = 0;
2829 r->hdr.length = sizeof(*r);
2831 TellGreeter((RequestHeader *)r);
2832 state->waitForResponse = TRUE;
2834 state->id = GREET_STATE_USERNAME;
2838 case GREET_STATE_BAD_HOSTNAME:
2841 * Display password expired message.
2845 Debug("GREET_STATE_BAD_HOSTNAME\n");
2847 r = (RequestHostname *)state->request;
2849 r->hdr.opcode = REQUEST_OP_HOSTNAME;
2850 r->hdr.reserved = 0;
2851 r->hdr.length = sizeof(*r);
2853 TellGreeter((RequestHeader *)r);
2854 state->waitForResponse = TRUE;
2856 state->id = GREET_STATE_USERNAME;
2861 case GREET_STATE_FORM:
2864 * Get arbitrary number of answers.
2867 Debug("GREET_STATE_FORM\n");
2869 AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2871 state->waitForResponse = FALSE;
2872 state->id = GREET_STATE_USERNAME;
2884 RequestHeader *phdr)
2886 if(-1 == write(request[1], phdr, phdr->length)) {
2887 perror(strerror(errno));
2893 RequestHeader *preqhdr,
2899 ResponseHeader *phdr = (ResponseHeader *)buf;
2901 if (preqhdr) TellGreeter(preqhdr);
2903 phdr->opcode = REQUEST_OP_NONE;
2905 count = read(response[0], buf, sizeof(*phdr));
2907 if (count == sizeof(*phdr))
2910 * Calculate amount of data after header.
2912 remainder = phdr->length - sizeof(*phdr);
2916 * Read remainder of response.
2918 count += read(response[0], buf+sizeof(*phdr), remainder);
2923 if (debugLevel) PrintResponse(phdr, count);
2932 ResponseHeader *phdr,
2935 char *opstr = "UNKNOWN";
2939 Debug("opcode = (EOF)\n");
2943 switch(phdr->opcode)
2945 case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2946 case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2947 case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2948 case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2949 case REQUEST_OP_LANG: opstr = "LANG"; break;
2950 case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
2953 Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
2954 Debug(" reserved = %d\n", phdr->reserved);
2955 Debug(" length = %d\n", phdr->length);
2957 switch(phdr->opcode)
2959 case REQUEST_OP_EXIT: break;
2960 case REQUEST_OP_LANG:
2961 Debug(" offLang=%d\n", ((ResponseLang *)phdr)->offLang);
2962 Debug(" lang='%s'\n",
2963 ((char *)phdr)+((ResponseLang *)phdr)->offLang);
2965 case REQUEST_OP_MESSAGE: break;
2966 case REQUEST_OP_CHPASS: break;
2967 case REQUEST_OP_CHALLENGE:
2968 Debug(" offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
2969 Debug(" response='%s'\n",
2970 ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
2972 case REQUEST_OP_DEBUG:
2973 Debug(" offString=%d\n", ((ResponseDebug *)phdr)->offString);
2974 Debug(" string='%s'\n",
2975 ((char *)phdr)+((ResponseDebug *)phdr)->offString);
2983 /***************************************************************************
2987 * generate kerberos ticket file name. Name is returned in the static
2988 * global variable "krb_ticket_string".
2990 ***************************************************************************/
2993 SetTicketFileName(uid_t uid)
3002 * generate ticket file pathname (/tmp/tkt<uid>.<host>) ...
3005 if (env = (char *)getenv("KRBTKFILE")) {
3006 (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3007 krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3010 if (gethostname(lhost, sizeof(lhost)) != -1) {
3011 if (p = index(lhost, '.')) *p = '\0';
3012 (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3014 /* 32 bits of signed integer will always fit in 11 characters
3015 (including the sign), so no need to worry about overflow */
3016 (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3021 #endif /* __KERBEROS */
3023 #if defined (_AIX) && !defined (_POWER)
3025 /***************************************************************************
3029 * If this is an authenticated process (LOGNAME set), set user's
3030 * process environment by calling setpenv().
3032 * If this is not an authenticated process, just call execve()
3034 ***************************************************************************/
3043 char *user = getEnv (envp, "LOGNAME");
3047 rc = execve(path, argv, envp);
3051 char *usrTag, *sysTag;
3054 * Save pointers to tags. The setpenv() function clears the pointers
3055 * to the tags in userEnviron as a side-effect.
3057 sysTag = envp[SYS_ENV_TAG];
3058 usrTag = envp[USR_ENV_TAG];
3061 * Set the users process environment. This call execs arvg so it
3062 * should not return. It it should return, restore the envp tags.
3064 rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3067 * Restore pointers to tags.
3069 envp[SYS_ENV_TAG] = sysTag;
3070 envp[USR_ENV_TAG] = usrTag;
3075 #endif /* _AIX && !_POWER */
3079 /* collect the SIA parameters from a window system. */
3081 static int SiaManageGreeter(
3084 unsigned char *title,
3090 RequestMessage greeter_message;
3091 char msg_buffer[256];
3092 } greeter_msg_and_buffer;
3093 RequestForm *request_form;
3101 if (rendition == SIAFORM && dt_in_sia_ses_authent
3102 && (num_prompts == 2))
3104 /* Normal login, Password case */
3105 Debug ("SIAFORM Normal login, Password case\n");
3106 while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3107 && siaGreeterInfo.state->id != GREET_STATE_EXIT
3108 && (siaGreeterInfo.status = ManageGreeter(
3109 siaGreeterInfo.d, siaGreeterInfo.greet,
3110 siaGreeterInfo.verify, siaGreeterInfo.state)))
3113 if (!siaGreeterInfo.status
3114 || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3115 return(SIACOLABORT);
3117 strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name,
3118 prompt[0].max_result_length);
3119 strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3120 prompt[1].max_result_length);
3127 ResponseForm *response_form;
3132 Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3135 Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3138 Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3141 Debug("SIAFORM num_prompts = %d\n", num_prompts);
3145 /* need to display form */
3147 req_form_size = sizeof(RequestForm)
3148 + strlen((const char *)title) + 1;
3149 for (i=0; i<num_prompts; i++)
3150 req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3151 request_form = (RequestForm *) alloca(req_form_size);
3153 siaGreeterInfo.state->id = GREET_STATE_FORM;
3154 siaGreeterInfo.state->request = (RequestHeader *)request_form;
3155 /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3157 request_form->hdr.opcode = REQUEST_OP_FORM;
3158 request_form->hdr.reserved = 0;
3159 request_form->hdr.length = req_form_size;
3160 request_form->num_prompts = num_prompts;
3161 request_form->rendition = rendition;
3162 request_form->offTitle = sizeof(RequestForm);
3163 request_form->offPrompts = sizeof(RequestForm) +
3164 strlen((const char *)title) + 1;
3165 strcpy((char *)request_form + request_form->offTitle,
3166 (const char *)title);
3168 pmpt_ptr = (char *)request_form + request_form->offPrompts;
3169 for (i=0; i<num_prompts; i++)
3171 if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3175 Debug(" prompt[%d]: %s\n", i, prompt[i].prompt);
3176 strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3177 pmpt_ptr += strlen((const char *)prompt[i].prompt);
3179 request_form->visible[i] =
3180 (prompt[i].control_flags & SIARESINVIS) ? False : True;
3183 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3184 siaGreeterInfo.greet,
3185 siaGreeterInfo.verify,
3186 siaGreeterInfo.state);
3188 response_form = (ResponseForm *)siaGreeterInfo.state->response;
3189 res_ptr = (char *)response_form + response_form->offAnswers;
3190 for (i = 0; i < response_form->num_answers; i++)
3192 if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3195 prompt[i].result = (unsigned char *)1;
3197 prompt[i].result = NULL;
3201 strcpy((char *)prompt[0].result, res_ptr);
3203 res_ptr += strlen(res_ptr) + 1;
3205 if (!response_form->collect_status)
3206 siaGreeterInfo.status = FALSE;
3212 Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3214 siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3215 siaGreeterInfo.state->request = (RequestHeader *)
3216 &greeter_msg_and_buffer.greeter_message;
3217 siaGreeterInfo.state->vf = VF_MESSAGE;
3218 siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3220 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3221 siaGreeterInfo.greet,
3222 siaGreeterInfo.verify,
3223 siaGreeterInfo.state);
3226 return(SIACOLABORT);
3229 if (!siaGreeterInfo.status)
3230 return(SIACOLABORT);
3231 return(SIACOLSUCCESS);
3234 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3237 greet->name = malloc(strlen(siaHandle->name) + 1);
3238 strcpy (greet->name, siaHandle->name);
3240 greet->password = malloc(strlen(siaHandle->password) + 1);
3241 strcpy (greet->password, siaHandle->password);
3246 static void KillGreeter( void )
3248 if (sia_greeter_pid)
3249 AbortClient(sia_greeter_pid);
3250 sia_greeter_pid = 0;