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 librararies 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
66 # include <X11/Xatom.h>
77 #include <X11/Intrinsic.h>
80 # include <X11/Xresource.h>
91 # include <sys/security.h>
97 #endif /* __KERBEROS */
100 #include "rgy_base.h"
105 static SIAENTITY *siaHandle = NULL;
106 static Boolean dt_in_sia_ses_authent = False;
108 static struct sia_greeter_info {
110 struct greet_info *greet;
111 struct verify_info *verify;
112 struct greet_state *state;
116 static int SiaManageGreeter(
119 unsigned char *title,
123 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet);
125 static void KillGreeter( void );
127 static int sia_greeter_pid;
128 static int sia_exit_proc_reg = FALSE;
134 extern char *getenv();
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);
261 FileNameCompare (a, b)
262 #if defined(__STDC__)
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 char *s = ((errno >= 0 && errno < sys_nerr) ? sys_errlist[errno]
333 LogError(ReadCatalog(
334 MC_LOG_SET,MC_LOG_FATAL_IO,MC_DEF_LOG_FATAL_IO),
336 exit(RESERVER_DISPLAY);
341 ErrorHandler( Display *dpy, XErrorEvent *event )
343 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_X_ERR,MC_DEF_LOG_X_ERR));
344 if (XmuPrintDefaultErrorMessage (dpy, event, stderr) == 0) return 0;
345 exit(UNMANAGE_DISPLAY);
351 ManageSession( struct display *d )
357 char *BypassUsername;
359 #endif /* BYPASSLOGIN */
362 Debug ("ManageSession():\n");
364 /***********************************/
365 /** remember the default language **/
366 /***********************************/
367 if (defaultLanguage == NULL) {
368 if ( (d->language != NULL) && (strlen(d->language) > 0) ) {
369 defaultLanguage = strdup(d->language);
371 defaultLanguage = "C";
377 if ((BypassUsername = BypassLogin(d->name)) != NULL) {
379 Debug("Login bypassed, running as %s\n",BypassUsername);
380 greet.name = BypassUsername;
381 if (!Verify (d, &greet, &verify)) {
382 Debug ("Login bypass verify failed!\n");
383 SessionExit (d, GREETLESS_FAILED);
385 Debug("Login bypass verify succeded!\n");
387 #endif /* BYPASSLOGIN */
392 (void)XSetIOErrorHandler(IOErrorHandler);
393 (void)XSetErrorHandler(ErrorHandler);
394 SetTitle(d->name, (char *) 0);
397 * set root background to black...
400 dpy = XOpenDisplay(d->name);
401 for (i = ScreenCount(dpy) - 1; i >= 0; i--)
403 Window tmproot = RootWindow(dpy, i);
405 if (i == DefaultScreen(dpy))
408 XSetWindowBackground(dpy, tmproot, BlackPixel(dpy, i));
409 XClearWindow(dpy, tmproot);
415 ** Invoke Greet program, wait for completion.
416 ** If this routine returns, the user will have been
417 ** verified, otherwise the routine will exit inter-
418 ** nally with an appropriate exit code for the master
423 greet.name = greet.string = NULL;
425 while (greet.name == NULL) {
426 SetHourGlassCursor(dpy, root);
427 LoadXloginResources (d);
429 ApplyFontPathMods(d, dpy);
430 (void)XSetErrorHandler(ErrorHandler);
431 RunGreeter(d, &greet, &verify);
433 DeleteXloginResources (d, dpy);
435 XSetInputFocus(dpy, root, RevertToNone, CurrentTime);
441 * Generate Kerberos ticket file name. Put in system and user
445 if ( IsVerifyName(VN_KRB)) {
446 SetTicketFileName(verify.uid);
447 krb_set_tkt_string(krb_ticket_string);
448 verify.systemEnviron = setEnv (verify.systemEnviron,
452 verify.userEnviron = setEnv (verify.userEnviron,
456 #endif /* __KERBEROS */
458 /* set LOCATION env var */
459 if(d->displayType.location == Local) {
460 verify.systemEnviron = setEnv (verify.systemEnviron,
463 /* ITE is needed only for Local displays */
464 /* set ITE env var */
466 verify.systemEnviron = setEnv (verify.systemEnviron,
471 verify.systemEnviron = setEnv (verify.systemEnviron,
478 sprintf(gid,"%ld",(long)getgid());
479 /* set user group id (USER_GID) env var */
480 verify.systemEnviron = setEnv (verify.systemEnviron,
484 /* set root group id (ROOT_GID) env var */
485 pwd = getpwnam("root");
487 sprintf(gid,"%ld",(long)pwd->pw_gid);
488 verify.systemEnviron = setEnv (verify.systemEnviron,
495 * Run system-wide initialization file
497 if (source (&verify, d->startup) != 0)
499 Debug ("Startup program %s exited with non-zero status\n",
501 SessionExit (d, OBEYSESS_DISPLAY);
505 if ( solaris_setdevperm(d->gettyLine, verify.uid, verify.gid) == 0 ) {
506 SessionExit (d, OBEYSESS_DISPLAY);
511 if (!setjmp (abortSession)) {
512 signal (SIGTERM, catchTerm);
514 * Start the clients, changing uid/groups
515 * setting up environment and running the session
517 if (StartClient (&verify, d, &clientPid)) {
518 Debug ("Client started\n");
521 * We've changed dtlogin to pass HUP's down to the children
522 * so ignore any HUP's once the client has started.
524 signal(SIGHUP, SIG_IGN);
527 * Wait for session to end,
532 if (!setjmp (pingTime))
534 signal (SIGALRM, catchAlrm);
535 alarm (d->pingInterval * 60);
536 pid = wait ((waitType *) 0);
542 if (!PingServer (d, (Display *) NULL))
543 SessionPingFailed (d);
548 pid = wait ((waitType *) 0);
550 if (pid == clientPid)
555 * We've changed dtlogin to pass HUP's down to the children
556 * so ignore any HUP's once the client has started.
558 signal(SIGHUP, SIG_DFL);
560 LogError(ReadCatalog(
561 MC_LOG_SET,MC_LOG_FAIL_START,MC_DEF_LOG_FAIL_START));
565 * when terminating the session, nuke
566 * the child and then run the reset script
568 AbortClient (clientPid);
572 * on foreign displays without XDMCP, send a SIGTERM to the process
573 * group of the session manager. This augments the "resetServer()"
574 * routine and helps get all clients killed. It is possible for a client
575 * to have a connection to the server, but not have a window.
578 if (d->displayType.location == Foreign &&
579 d->displayType.origin != FromXDMCP )
580 AbortClient(clientPid);
585 * remove ticket file...
588 if ( IsVerifyName(VN_KRB) ) {
592 #endif /* __KERBEROS */
596 * run system-wide reset file
598 Debug ("Source reset program %s\n", d->reset);
599 source (&verify, d->reset);
601 #if defined(PAM) || defined(SUNAUTH)
603 char* user = getEnv (verify.userEnviron, "USER");
604 char* ttyLine = d->gettyLine;
606 # ifdef DEF_NETWORK_DEV
608 * If location is not local (remote XDMCP dtlogin) and
609 * remote accouting is enabled (networkDev start with /dev/...)
610 * Set tty line name to match network device for accouting.
611 * Unless the resource was specifically set, default is value
612 * of DEF_NETWORK_DEV define (/dev/dtremote)
615 if ( d->displayType.location != Local &&
616 networkDev && !strncmp(networkDev,"/dev/",5)) {
617 ttyLine = networkDev+5;
622 PamAccounting( verify.argv[0], d->name, d->utmpId, user,
623 ttyLine, clientPid, ACCOUNTING, NULL);
625 solaris_accounting( verify.argv[0], d->name, d->utmpId, user,
626 ttyLine, clientPid, ACCOUNTING, NULL);
630 solaris_resetdevperm(ttyLine);
635 SessionExit (d, OBEYSESS_DISPLAY);
640 LoadXloginResources( struct display *d )
647 char *resources = NULL;
651 if (d->resources && d->resources[0]) {
652 resources = _ExpandLang(d->resources, d->language);
653 if (access (resources, R_OK) != 0) {
654 /** fallback to the C locale for resources **/
655 Debug("LoadXloginResources - cant access %s\n", resources);
656 Debug("\t %s. Falling back to C.\n", sys_errlist[errno]);
658 resources = _ExpandLang(d->resources, "C");
659 if (access (resources, R_OK) != 0) {
660 /** can't find a resource file, so bail **/
661 Debug("LoadXloginResources - cant access %s.\n", resources);
662 Debug("\t %s. Unable to find resource file.\n",
669 if (d->authFile && strlen(d->authFile) > 0 ) {
670 authority = d->authFile;
671 auth_key = "XAUTHORITY=";
674 if (d->language && strlen(d->language) > 0 ) {
675 language = strdup(d->language);
680 * replace any "-" or "." in the language name with "_". The C
681 * preprocessor used by xrdb does not accept "-" or "." in a name.
684 while ( (p = strchr(language, '-')) != NULL ) {
688 while ( (p = strchr(language, '.')) != NULL ) {
692 if ( strlen(language) > 0 )
696 Debug("LoadXloginResources - loading resource db from %s\n", resources);
697 if((XresourceDB = XrmGetFileDatabase(resources)) == NULL)
698 Debug("LoadXloginResources - Loading resource db from %s failed\n",
701 LoadAltDtsResources(d);
703 strcpy(tmpname,"/var/dt/dtlogin_XXXXXX");
704 (void) mktemp(tmpname);
706 XrmPutFileDatabase(XresourceDB, tmpname);
708 sprintf (cmd, "%s%s %s -display %s -load %s",
709 auth_key, authority, d->xrdb, d->name, tmpname);
710 Debug ("Loading resource file: %s\n", cmd);
714 if (debugLevel <= 10)
715 if (unlink (tmpname) == -1)
716 Debug ("unlink() on %s failed\n", tmpname);
719 if (resources) free (resources);
724 /***************************************************************************
726 * LoadAltDtsResources
729 * set up alternate desktop resources..
731 ***************************************************************************/
734 LoadAltDtsResources(struct display *d)
738 char dirname[2][MAXPATHLEN];
739 char res_file[MAXPATHLEN];
740 char *rmtype; /* for XrmGetResource() */
741 XrmValue rmvalue; /* for XrmGetResource() */
742 char buf[MAXPATHLEN];
743 char tempbuf[MAXPATHLEN];
746 char altdtres[MAXPATHLEN];
747 char Altdtres[MAXPATHLEN];
750 char *resources = NULL;
752 int num_allocated = 0;
753 char **file_list = NULL;
756 if ( XrmGetResource(XresourceDB,
757 "Dtlogin*altDts", "Dtlogin*AltDts",
758 &rmtype, &rmvalue ) ) {
759 strcpy(tempbuf,rmvalue.addr);
763 strcpy(dirname[0],CDE_INSTALLATION_TOP "/config/%L/Xresources.d/");
764 strcpy(dirname[1],CDE_CONFIGURATION_TOP "/config/%L/Xresources.d/");
766 for(j = 0; j < 2 ; ++j)
768 resources = _ExpandLang(dirname[j], d->language);
769 if (access (resources, R_OK) != 0)
771 Debug("LoadAltDtsResources- cant access %s.\n", resources);
772 Debug("\t %s. Falling back to C.\n", sys_errlist[errno]);
780 resources = _ExpandLang(dirname[j], "C");
781 if (access (resources, R_OK) != 0)
783 Debug("LoadAltDtsResources- cant access %s.\n", resources);
784 Debug("\t %s.\n", sys_errlist[errno]);
787 strcpy(dirname[j], resources);
790 strcpy(dirname[j],resources);
791 Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
803 * Create a list of the alt DT files
805 * NOTE - an assumption made here is that files in /etc/dt
806 * should take precedence over files in /usr/dt. This precedence
807 * is maintained during the sort becase /etc/dt will come before
811 for(j = 0; j < 2 ; ++j) {
813 if((dirp = opendir(dirname[j])) != NULL) {
815 while((dp = readdir(dirp)) != NULL) {
817 if ((strcmp(dp->d_name, DOT) != 0) &&
818 (strcmp(dp->d_name, DOTDOT) != 0)) {
820 sprintf (res_file, "%s%s", dirname[j],dp->d_name);
821 if ((access (res_file, R_OK)) != 0)
823 Debug("LoadAltDtsResources- cant access %s.\n",
825 Debug("\t %s.\n", sys_errlist[errno]);
829 if (file_count == 0) {
830 file_list = malloc (list_incr * sizeof(char **));
831 num_allocated += list_incr;
833 if (file_count + 1 > num_allocated) {
834 num_allocated += list_incr;
835 file_list = realloc (file_list,
836 num_allocated * sizeof(char **));
838 file_list[file_count] = strdup (res_file);
847 qsort (file_list, file_count, sizeof (char *), FileNameCompare);
849 for (j = 0; j < file_count ; j++) {
851 userDb = XrmGetFileDatabase(file_list[j]);
852 XrmMergeDatabases(userDb,&XresourceDB);
854 if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
855 "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
858 * remove the trailing spaces
860 if(strchr(rmvalue.addr,' '))
861 strcpy(tempbuf, strtok(rmvalue.addr," "));
863 strcpy(tempbuf, rmvalue.addr);
865 if ((strcmp(tempbuf, "True") == 0) ||
866 (strcmp(tempbuf, "TRUE") == 0)) {
868 if ( XrmGetResource(XresourceDB,
869 "Dtlogin*altDtKey", "Dtlogin*AltDtKey",
870 &rmtype, &rmvalue ) ) {
872 sprintf(altdtres,"Dtlogin*altDtKey%d",i);
873 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
878 if ( XrmGetResource(XresourceDB,
879 "Dtlogin*altDtName", "Dtlogin*AltDtName",
880 &rmtype, &rmvalue ) ) {
881 sprintf(altdtres,"Dtlogin*altDtName%d",i);
882 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
884 if ( XrmGetResource(XresourceDB,
885 "Dtlogin*altDtStart", "Dtlogin*AltDtStart",
886 &rmtype, &rmvalue ) ) {
887 sprintf(altdtres,"Dtlogin*altDtStart%d",i);
888 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
890 if ( XrmGetResource(XresourceDB,
891 "Dtlogin*altDtLogo", "Dtlogin*AltDtLogo",
892 &rmtype, &rmvalue ) ) {
893 sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
894 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
900 sprintf(tempbuf,"%d",i);
901 XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf);
903 if (file_count > 0) {
904 for (i = 0; i < file_count; i++) {
905 Debug ("Loading resource file: %s\n", file_list[i]);
915 * Function Name: _ExpandLang
919 * This function takes the string "string", searches for occurences of
920 * "%L" in the string and if found, the "%L" is substituted with
921 * the value of the $LANG environment variable.
923 * If $LANG is not defined, the %L is replace with NULL.
927 * _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
931 * ret_string = _ExpandLang (string);
933 * char *ret_string; Returns NULL if "string" is NULL or it points
934 * to the expanded string.
936 * char *string; The first part of the pathname. Typically
937 * the directory containing the item of interest.
939 * Note: The caller is responsible for free'ing the returned string.
961 * Count the number of expansions that will occur.
965 for (n = 0, pch = string ; pch != NULL ; ) {
966 if ((pch = strchr (pch, '%')) != NULL) {
973 return (strdup(string));
976 * We should really be calling setlocale to determine the "default"
977 * locale but setlocale's return value is not standardized across
978 * the various vendor platforms nor is it consistent within differnt
979 * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
980 * HP-UX 10.0). The "right" call would be the following line:
982 * if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
984 * Here we hard code the default to "C" instead of leaving it NULL.
986 if (lang || (lang = getenv ("LANG")) || (lang = "C"))
987 lang_len = strlen (lang);
990 * Create the space needed.
992 tmp_len = strlen (string) + (n * lang_len) + n + 1;
993 tmp = (char *) malloc (tmp_len);
994 for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
998 while (pch != NULL) {
1001 if ((pch = strchr (pch, '%')) != NULL) {
1006 (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
1008 else if ((pch != NULL) && *pch == 'L') {
1009 if (lang_len == 0) {
1010 if (((pch - trail) >=2) && (*(pch-2) == '/'))
1012 * Remove the "/" as well as the "%L".
1014 (void) strncat (tmp, trail, (pch - trail) - 2);
1016 (void) strncat (tmp, trail, (pch - trail) - 1);
1020 * Remove the "%L" and then append the LANG.
1022 (void) strncat (tmp, trail, (pch - trail) - 1);
1023 (void) strcat (tmp, lang);
1027 (void) strncat (tmp, trail, (pch - trail) + 1);
1034 * A '%' was not found.
1036 (void) strcat (tmp, trail);
1045 SetupDisplay (struct display *d)
1047 char **env = 0, **crt_systemEnviron;
1049 if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1051 crt_systemEnviron = verify.systemEnviron;
1052 env = systemEnv (d, (char *) 0, (char *) 0);
1053 if (d->authFile && strlen(d->authFile) > 0 )
1054 env = setEnv( env, "XAUTHORITY", d->authFile );
1055 if(d->displayType.location == Local)
1056 env = setEnv (env, LOCATION, "local");
1058 env = setEnv (env, LOCATION, "remote");
1059 verify.systemEnviron = env;
1060 source (&verify, d->setup);
1061 verify.systemEnviron = crt_systemEnviron;
1068 DeleteXloginResources( struct display *d, Display *dpy )
1070 XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1073 #if 0 /* dead code: transferred to Dtgreet */
1075 static jmp_buf syncJump;
1080 longjmp (syncJump, 1);
1084 SecureDisplay (d, dpy)
1088 Debug ("SecureDisplay():\n");
1089 signal (SIGALRM, syncTimeout);
1090 if (setjmp (syncJump)) {
1091 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1093 SessionExit (d, RESERVER_DISPLAY);
1095 alarm ((unsigned) d->grabTimeout);
1096 Debug ("Before XGrabServer()\n");
1098 if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1099 GrabModeAsync, CurrentTime) != GrabSuccess)
1102 signal (SIGALRM, SIG_DFL);
1103 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1105 SessionExit (d, RESERVER_DISPLAY);
1107 Debug ("XGrabKeyboard() succeeded\n");
1109 signal (SIGALRM, SIG_DFL);
1113 XUngrabServer (dpy);
1116 Debug ("Done secure %s\n", d->name);
1119 UnsecureDisplay (d, dpy)
1123 Debug ("Unsecure display %s\n", d->name);
1125 XUngrabServer (dpy);
1134 release_aix_lic(void)
1137 * Release AIX iFOR/LS license (if any)
1145 release_me.request_type = -1;
1146 release_me.login_pid = getpid();
1147 if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1149 write(fd, &release_me, sizeof(release_me));
1152 Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1160 SessionExit( struct display *d, int status )
1169 /* make sure the server gets reset after the session is over */
1170 if (d->serverPid >= 2) {
1171 Debug("Reseting server: pid %d signal %d\n",
1172 d->serverPid, d->resetSignal);
1174 if (d->terminateServer == 0 && d->resetSignal)
1175 kill (d->serverPid, d->resetSignal);
1180 Debug("Exiting Session with status: %d\n", status);
1185 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1188 char currentdir[PATH_MAX+1];
1189 char *failsafeArgv[20];
1190 char *user; /* users name */
1191 char *lang, *font; /* failsafe LANG and font */
1194 int failsafe = FALSE; /* do we run the failsafe session? */
1195 int password = FALSE; /* do we run /bin/passwd? */
1198 char lastsessfile[MAXPATHLEN];
1201 struct pr_passwd *b1_pwd;
1205 #define NOPAG 0xffffffff
1207 long ngroups, groups[NGROUPS];
1213 Debug ("StartSession %s: ", verify->argv[0]);
1214 for (f = verify->argv; *f; f++) {
1216 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1217 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1221 if (verify->userEnviron) {
1222 for (f = verify->userEnviron; *f; f++)
1227 user = getEnv (verify->userEnviron, "USER");
1229 switch (pid = fork ()) {
1232 /* Force a failsafe session if we can't touch the home directory
1233 * SIA has already attempted to chdir to HOME, and the current dir
1234 * will be set to / if it failed. We just check to see if the HOME
1235 * path is our current directory or not.
1237 home = getEnv (verify->userEnviron, "HOME");
1238 getcwd(currentdir, PATH_MAX+1);
1239 Debug("Current directory is: %s\n", currentdir);
1243 * The following little check doesn't really work. For example,
1244 * here at the XC, NIS reports my home directory as
1245 * "/site/guests/montyb" while getcwd comes up with
1246 * "/net/nexus/site/guests/montyb".
1248 if (strcmp(home, currentdir)) {
1249 Debug("Can't access home directory, setting failsafe to TRUE\n");
1251 LogError (ReadCatalog(
1252 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1253 home, getEnv (verify->userEnviron, "USER"));
1254 verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1262 * do process accounting...
1264 #if defined(PAM) || defined(SUNAUTH)
1266 char* ttyLine = d->gettyLine;
1268 # ifdef DEF_NETWORK_DEV
1270 * If location is not local (remote XDMCP dtlogin) and
1271 * remote accouting is enabled (networkDev start with /dev/...)
1272 * Set tty line name to match network device for accouting.
1273 * Unless the resource was specifically set, default is value
1274 * of DEF_NETWORK_DEV define (/dev/dtremote)
1277 if ( d->displayType.location != Local &&
1278 networkDev && !strncmp(networkDev,"/dev/",5)) {
1279 ttyLine = networkDev+5;
1284 PamAccounting(verify->argv[0], d->name, d->utmpId, user,
1285 ttyLine, getpid(), USER_PROCESS, NULL);
1287 solaris_accounting(verify->argv[0], d->name, d->utmpId, user,
1288 ttyLine, getpid(), USER_PROCESS, NULL);
1293 #if !defined(sun) && !defined(CSRG_BASED)
1294 Account(d, user, NULL, getpid(), USER_PROCESS, status);
1299 * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1300 * setpenv() to set up the user's process environment and return
1301 * without execing. This allows us to set up the process environment
1302 * and proceed to the execute() call as do the other platforms.
1304 * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1305 * we have to pospone the setpenv() to the actual execute().
1309 * These defines are the tag locations in userEnviron.
1310 * IMPORTANT: changes to the locations of these tags in verify.c
1311 * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1313 #define SYS_ENV_TAG 0
1314 #define USR_ENV_TAG 3
1317 * Set the user's credentials: uid, gid, groups,
1318 * audit classes, user limits, and umask.
1321 if (setpcred(user, NULL) == -1)
1323 Debug("Can't set User's Credentials (user=%s)\n",user);
1328 char *usrTag, *sysTag;
1329 extern char **newenv;
1332 * Save pointers to tags. The setpenv() function clears the pointers
1333 * to the tags in userEnviron as a side-effect.
1335 sysTag = verify->userEnviron[SYS_ENV_TAG];
1336 usrTag = verify->userEnviron[USR_ENV_TAG];
1339 * Set the users process environment. Store protected variables and
1340 * obtain updated user environment list. This call will initialize
1343 #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1344 if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1346 Debug("Can't set process environment (user=%s)\n",user);
1351 * Restore pointers to tags.
1353 verify->userEnviron[SYS_ENV_TAG] = sysTag;
1354 verify->userEnviron[USR_ENV_TAG] = usrTag;
1357 * Free old userEnviron and replace with newenv from setpenv().
1359 freeEnv(verify->userEnviron);
1360 verify->userEnviron = newenv;
1370 if (PamSetCred( verify->argv[0],
1371 user, verify->uid, verify->gid) > 0 ) {
1372 Debug("Can't set User's Credentials (user=%s)\n",user);
1378 if ( solaris_setcred(verify->argv[0],
1379 user, verify->uid, verify->gid) > 0 ) {
1380 Debug("Can't set User's Credentials (user=%s)\n",user);
1383 #endif /* SUNAUTH */
1390 * HP BLS B1 session setup...
1392 * 1. look up user's protected account information.
1393 * 2. set the session sensitivity/clearance levels
1394 * 3. set the logical UID (LUID)
1398 Debug("BLS - Setting user's clearance, security level and luid.\n");
1399 set_auth_parameters(1, verify->argv);
1402 verify->user_name = user;
1403 strncpy(verify->terminal,d->name,15);
1404 verify->terminal[15]='\0';
1405 verify->pwd = getpwnam(user);
1407 if ( verify->pwd == NULL || strlen(user) == 0 ) {
1408 LogError(ReadCatalog(
1409 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1412 verify->prpwd= b1_pwd = getprpwnam(user);
1413 verify->uid = b1_pwd->ufld.fd_uid;
1415 if ( b1_pwd == NULL || strlen(user) == 0 ) {
1416 LogError(ReadCatalog(
1417 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1422 * This has already been done successfully by dtgreet
1423 * but we need to get all the information again for the
1426 if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1427 Debug("BLS - Could not verify sensitivity level.\n");
1428 LogError(ReadCatalog(
1429 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1433 if ( change_to_user(verify) != 1 ) {
1434 Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1435 LogError(ReadCatalog(
1436 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1441 Debug("BLS - Session setup complete.\n");
1448 * This should never fail since everything has been verified already.
1449 * If it does it must mean registry strangeness, so exit, and try
1453 if (!DoLogin (user, greet.password, d->name)) exit (1);
1456 * extract the SYSTYPE and ISP environment values and set into user's
1457 * environment. This is necessary since we do an execve below...
1460 verify->userEnviron = setEnv(verify->userEnviron, "SYSTYPE",
1463 verify->userEnviron = setEnv(verify->userEnviron, "ISP",
1466 #else /* ! __apollo */
1470 if ( IsVerifyName(VN_AFS) ) {
1471 pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1472 Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1474 initgroups(greet.name, verify->groups[2]);
1475 ngroups = getgroups(NGROUPS, groups);
1476 Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1477 for (i=0; i < ngroups; i++)
1478 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1480 if ((pagval != NOPAG) &&
1481 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1482 /* we will have to shift grouplist to make room for pag */
1483 if (ngroups+2 > NGROUPS)
1485 for (j=ngroups-1; j >= 0; j--) {
1486 groups[j+2] = groups[j];
1489 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1490 if (setgroups(ngroups, groups) == -1) {
1493 MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1498 # else /* ! __AFS */
1499 /* If SIA is enabled, the initgroups and setgid calls are redundant
1506 * if your system does not support "initgroups(3C)", use
1507 * the "setgroups()" call instead...
1510 # if (defined(__hpux) || defined(__osf__))
1511 initgroups(user, -1);
1513 setgroups (verify->ngroups, verify->groups);
1516 /* setpenv() will set gid for AIX */
1518 setgid (verify->groups[0]);
1521 # else /* ! NGROUPS */
1523 /* setpenv() will set gid for AIX */
1525 setgid (verify->gid);
1528 # endif /* NGROUPS */
1534 setaudid(verify->audid);
1535 setaudproc(verify->audflg);
1538 /* setpenv() will set uid for AIX */
1540 if (setuid(verify->uid) != 0) {
1541 Debug( "Setuid failed for user %s, errno = %d\n", user, errno);
1542 LogError(ReadCatalog(
1543 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1549 #endif /* __apollo */
1552 } /* ends the else clause of if ( ISSECURE ) */
1558 * check home directory again...
1562 /* Don't need to do this if SIA is enabled, already been done.
1564 home = getEnv (verify->userEnviron, "HOME");
1566 if (chdir (home) == -1) {
1567 LogError (ReadCatalog(
1568 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1569 home, getEnv (verify->userEnviron, "USER"));
1571 verify->userEnviron = setEnv(verify->userEnviron,
1574 else if(!failsafe) {
1575 strcpy(lastsessfile,home); /* save user's last session */
1576 strcat(lastsessfile,LAST_SESSION_FILE);
1577 if((lastsession = fopen(lastsessfile,"w")) == NULL)
1578 Debug("Unable to open file for writing: %s\n",lastsessfile);
1580 fputs(verify->argv[0],lastsession);
1581 fclose(lastsession);
1588 SetUserAuthorization (d, verify);
1594 bzero(greet.password, strlen(greet.password));
1598 * Write login information to a file
1599 * The file name should really be settable by some kind of resource
1600 * but time is short so we hard-wire it to ".dtlogininfo".
1602 if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1603 Debug("Unable to write \".dtlogininfo\"\n");
1605 /* extra debugging */
1606 if(!dump_sec_debug_info(verify)) {
1607 Debug("Something wrong with environment\n");
1610 # endif /* ! NDEBUG */
1618 Debug ("Executing session %s\n", verify->argv[0]);
1619 execute (verify->argv, verify->userEnviron);
1620 LogError(ReadCatalog(
1621 MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1625 LogError(ReadCatalog(
1626 MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1633 * specify a font for the multi-byte languages...
1637 lang = getEnv (verify->userEnviron, "LANG");
1644 failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1646 failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1647 #elif defined (USL) || defined(__uxp__)
1648 failsafeArgv[i++] = "/usr/X/bin/xterm";
1649 #elif defined(__hpux)
1650 failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1652 failsafeArgv[i++] = "/usr/bin/X11/xterm";
1654 failsafeArgv[i++] = "-geometry";
1655 failsafeArgv[i++] = "80x10";
1656 failsafeArgv[i++] = "-bg";
1657 failsafeArgv[i++] = "white";
1658 failsafeArgv[i++] = "-fg";
1659 failsafeArgv[i++] = "black";
1661 /* aixterm requires -lang option. */
1662 failsafeArgv[i++] = "-lang";
1663 failsafeArgv[i++] = lang;
1665 failsafeArgv[i++] = "-fn";
1667 if (font == NULL) font = "fixed";
1668 failsafeArgv[i++] = font;
1671 failsafeArgv[i++] = "-e";
1672 failsafeArgv[i++] = "/bin/passwd";
1673 #if defined (__apollo) || defined(__PASSWD_ETC)
1674 failsafeArgv[i++] = "-n";
1676 failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1679 failsafeArgv[i++] = d->failsafeClient;
1681 failsafeArgv[i++] = "-C";
1683 failsafeArgv[i++] = "-ls";
1686 failsafeArgv[i++] = "-fn";
1687 failsafeArgv[i++] = font;
1691 failsafeArgv[i] = 0;
1692 Debug ("Executing failsafe session\n", failsafeArgv[0]);
1693 execute (failsafeArgv, verify->userEnviron);
1696 Debug ("StartSession(): fork failed\n");
1697 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1701 Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1708 static jmp_buf tenaciousClient;
1711 waitAbort( int arg )
1713 longjmp (tenaciousClient, 1);
1716 #if defined(SYSV) || defined(SVR4)
1718 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1722 AbortClient( int pid )
1731 for (i = 0; i < 4; i++) {
1732 if (killpg (pid, sig) == -1) {
1735 LogError(ReadCatalog(
1736 MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1742 if (!setjmp (tenaciousClient)) {
1743 (void) signal (SIGALRM, waitAbort);
1744 (void) alarm ((unsigned) 10);
1745 retId = wait ((waitType *) 0);
1746 (void) alarm ((unsigned) 0);
1747 (void) signal (SIGALRM, SIG_DFL);
1751 signal (SIGALRM, SIG_DFL);
1757 source( struct verify_info *verify, char *file )
1763 if (file && file[0]) {
1764 Debug ("Source(): %s\n", file);
1765 switch (pid = fork ()) {
1770 execute (args, verify->systemEnviron);
1771 LogError(ReadCatalog(
1772 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1775 Debug ("Source(): fork failed\n");
1776 LogError(ReadCatalog(
1777 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1781 while (wait (&result) != pid)
1785 return waitVal (result);
1791 execute(char **argv, char **environ )
1795 * make stdout follow stderr to the log file...
1800 session_execve (argv[0], argv, environ);
1803 * In case this is a shell script which hasn't been made executable
1804 * (or this is a SYSV box), do a reasonable thing...
1808 /* errno is EACCES if not executable */
1809 if (errno == ENOEXEC || errno == EACCES) {
1811 if (errno == ENOEXEC) {
1813 char program[1024], *e, *p, *optarg;
1815 char **newargv, **av;
1819 * emulate BSD kernel behaviour -- read
1820 * the first line; check if it starts
1821 * with "#!", in which case it uses
1822 * the rest of the line as the name of
1823 * program to run. Else use "/bin/sh".
1825 f = fopen (argv[0], "r");
1828 if (fgets (program, sizeof (program) - 1, f) == NULL)
1834 e = program + strlen (program) - 1;
1837 if (!strncmp (program, "#!", 2)) {
1839 while (*p && isspace (*p))
1842 while (*optarg && !isspace (*optarg))
1848 while (*optarg && isspace (*optarg));
1855 Debug ("Shell script execution: %s (optarg %s)\n",
1856 p, optarg ? optarg : "(null)");
1857 for (av = argv, argc = 0; *av; av++, argc++)
1859 newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1866 while (*av++ = *argv++)
1868 session_execve (newargv[0], newargv, environ);
1875 /*****************************************************************************
1878 * Invoke the Greeter process and wait for completion. If the user was
1879 * successfully verified, return to the calling process. If the user
1880 * selected a restart or abort option, or there was an error invoking the
1881 * Greeter, exit this entire process with appropriate status.
1883 *****************************************************************************/
1887 extern int session_set;
1888 extern char *progName; /* Global argv[0]; dtlogin name and path */
1890 int response[2], request[2];
1892 /* Fixes problem with dtlogin signal handling */
1893 static int greeterPid = 0;
1894 static struct display *greeter_d = NULL;
1899 Debug("Caught SIGHUP\n");
1902 Debug("Killing greeter process: %d\n", greeterPid);
1903 kill(greeterPid, SIGHUP);
1906 SessionExit(greeter_d, REMANAGE_DISPLAY);
1908 exit(REMANAGE_DISPLAY);
1912 RunGreeter( struct display *d, struct greet_info *greet,
1913 struct verify_info *verify )
1920 static char msg[MSGSIZE];
1924 struct greet_state state;
1929 # define U_NAMELEN sizeof(rgy_$name_t)
1933 static char name_short[U_NAMELEN];
1939 char *argv[] = { "dtlogin", 0 };
1940 char *hostName = NULL;
1941 char *loginName = NULL;
1948 if (d->serverPid == -1)
1951 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
1952 loginName, d->name, 1, NULL);
1953 if (siaStatus != SIASUCCESS)
1955 Debug("sia_ses_init failure status %d\n", siaStatus);
1962 if (!setjmp (abortSession)) {
1963 signal(SIGTERM, catchTerm);
1966 * We've changed dtlogin to pass HUP's down to the children
1967 * so ignore any HUP's once the client has started.
1970 signal(SIGHUP, catchHUP);
1973 * set up communication pipes...
1981 switch (greeterPid = fork ()) {
1985 * pass some information in the environment...
1989 sprintf(msg,"%d", d->grabServer);
1990 env = setEnv(env, GRABSERVER, msg);
1992 sprintf(msg,"%d", d->grabTimeout);
1993 env = setEnv(env, GRABTIMEOUT, msg);
1996 if (timeZone && strlen(timeZone) > 0 )
1997 env = setEnv(env, "TZ", timeZone);
1999 if (errorLogFile && errorLogFile[0])
2000 env = setEnv(env, ERRORLOG, errorLogFile);
2003 env = setEnv(env, "XAUTHORITY", d->authFile);
2006 env = setEnv(env, DTLITE, "True");
2009 env = setEnv(env, SESSION, d->session);
2012 env = setEnv(env, SESSION_SET, "True");
2014 if (d->pmSearchPath)
2015 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
2017 if (d->bmSearchPath)
2018 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
2020 #if defined (__KERBEROS) || defined (__AFS)
2021 if (d->verifyName) {
2022 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2023 (strcmp(d->verifyName, VN_KRB) == 0) ) {
2025 env = setEnv(env, VERIFYNAME, d->verifyName );
2028 LogError(ReadCatalog(
2029 MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2031 d->verifyName = NULL;
2036 if((path = getenv("NLSPATH")) != NULL)
2037 env = setEnv(env, "NLSPATH", path);
2039 env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2044 * ping remote displays...
2048 if (d->displayType.location == Local) {
2049 GettyRunning(d); /* refresh gettyState */
2050 if (d->gettyState != DM_GETTY_USER)
2051 env = setEnv(env, LOCATION, "local");
2054 sprintf(msg,"%d", d->pingInterval);
2055 env = setEnv(env, PINGINTERVAL, msg);
2057 sprintf(msg,"%d", d->pingTimeout);
2058 env = setEnv(env, PINGTIMEOUT, msg);
2062 if ( d->langList && strlen(d->langList) > 0 )
2063 env = setEnv(env, LANGLIST, d->langList);
2064 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2065 else if (languageList && strlen(languageList) > 0 )
2066 env = setEnv(env, LANGLIST, languageList);
2067 #endif /* ENABLE_DYNAMIC_LANGLIST */
2070 char *language = NULL;
2072 #if defined (ENABLE_DYNAMIC_LANGLIST)
2073 language = d->language;
2074 #endif /* ENABLE_DYNAMIC_LANGLIST */
2076 if ( d->language && strlen(d->language) > 0 )
2077 env = setLang(d, env, language);
2080 if((path = getenv("XKEYSYMDB")) != NULL)
2081 env = setEnv(env, "XKEYSYMDB", path);
2084 if((path = getenv("OPENWINHOME")) != NULL)
2085 env = setEnv(env, "OPENWINHOME", path);
2090 * set environment for Domain machines...
2092 env = setEnv(env, "ENVIRONMENT", "bsd");
2093 env = setEnv(env, "SYSTYPE", "bsd4.3");
2097 Debug ("Greeter environment:\n");
2099 Debug ("End of Greeter environment:\n");
2102 * Writing to file descriptor 1 goes to response pipe instead.
2110 * Reading from file descriptor 0 reads from request pipe instead.
2120 * figure out path to dtgreet...
2123 strcpy(msg, progName);
2125 if ((p = (char *) strrchr(msg, '/')) == NULL)
2130 strcat(msg,"dtgreet");
2132 execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2133 LogError(ReadCatalog(
2134 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2136 exit (NOTIFY_ABORT_DISPLAY);
2139 Debug ("Fork of Greeter failed.\n");
2140 LogError(ReadCatalog(
2141 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2146 exit (UNMANAGE_DISPLAY);
2149 Debug ("Greeter started\n");
2151 close(response[1]); /* Close write end of response pipe */
2152 close(request[0]); /* Close read end of request pipe */
2156 * Retrieve information from greeter and authenticate.
2158 globalDisplayName = d->name;
2159 state.id = GREET_STATE_ENTER;
2160 state.waitForResponse = FALSE;
2164 * atexit() registers this function to be called if exit() is
2165 * called. This is needed because in enhanced security mode, SIA
2166 * may call exit() whn the user fails to enter or change a
2169 sia_greeter_pid = greeterPid;
2170 if (!sia_exit_proc_reg)
2172 atexit(KillGreeter);
2173 sia_exit_proc_reg = TRUE;
2176 siaGreeterInfo.d = d;
2177 siaGreeterInfo.greet = greet;
2178 siaGreeterInfo.verify = verify;
2179 siaGreeterInfo.state = &state;
2180 siaGreeterInfo.status = TRUE;
2183 while(siaStatus != SIASUCCESS)
2185 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2187 Debug ("RunGreeter: before sia_ses_authent\n");
2188 dt_in_sia_ses_authent = True;
2189 siaStatus = sia_ses_authent(SiaManageGreeter, NULL,
2191 dt_in_sia_ses_authent = False;
2192 Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2194 if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2196 state.id = GREET_STATE_ERRORMESSAGE;
2197 state.vf = VF_INVALID;
2198 ManageGreeter(d, greet, verify, &state);
2200 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2203 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2205 sia_ses_release(&siaHandle);
2209 Debug("RunGreeter: before sia_ses_estab\n");
2210 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2211 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2214 if (!siaGreeterInfo.status)
2217 if (siaStatus == SIASUCCESS)
2219 Debug("RunGreeter: before sia_ses_launch\n");
2220 siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2221 Debug("RunGreeter: after sia_ses_launch status = %d\n",
2224 if (!siaGreeterInfo.status)
2227 if (siaStatus != SIASUCCESS)
2229 Debug("RunGreeter: sia_ses_launch failure\n");
2230 /* establish & launch failures do a release */
2232 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
2233 loginName, d->name, 1, NULL);
2234 if (siaStatus != SIASUCCESS)
2236 Debug("sia_ses_init failure status %d\n", siaStatus);
2237 exit(RESERVER_DISPLAY);
2242 * sia_ses_launch() wil probably seteuid to that of the
2243 * user, but we don't want that now.
2247 * extract necessary info from SIA context struct
2251 if (siaStatus == SIASUCCESS)
2252 CopySiaInfo(siaHandle, greet);
2253 sia_ses_release(&siaHandle);
2255 state.id = GREET_STATE_TERMINATEGREET;
2256 if (siaGreeterInfo.status)
2258 while (ManageGreeter(d, greet, verify, &state))
2261 sia_greeter_pid = 0;
2263 while (ManageGreeter(d, greet, verify, &state))
2268 * Wait for Greeter to end...
2271 pid = wait (&status);
2272 if (pid == greeterPid)
2278 * Greeter exited. Check return code...
2281 Debug("Greeter return status; exit = %d, signal = %d\n",
2282 waitCode(status), waitSig(status));
2286 * remove authorization file if used...
2289 if (d->authorizations && d->authFile &&
2290 waitVal(status) != NOTIFY_LANG_CHANGE
2292 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2297 Debug ("Done with authorization file %s, removing\n",
2299 (void) unlink (d->authFile);
2304 if(waitVal(status) > NOTIFY_ALT_DTS)
2305 d->sessionType = waitVal(status);
2308 switch (waitVal(status)) {
2309 case NOTIFY_FAILSAFE:
2310 greet->string = "failsafe";
2312 case NOTIFY_PASSWD_EXPIRED:
2313 greet->string = "password";
2318 case NOTIFY_LAST_DT:
2319 d->sessionType = waitVal(status);
2325 Debug("waitVal - status is %d\n", waitVal(status));
2326 if(waitVal(status) > NOTIFY_ALT_DTS)
2327 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2329 notify_dt = waitVal(status);
2331 switch (notify_dt) {
2332 case NOTIFY_FAILSAFE:
2333 case NOTIFY_PASSWD_EXPIRED:
2337 case NOTIFY_LAST_DT:
2338 case NOTIFY_ALT_DTS:
2340 if (NULL == greet->name) return;
2343 * greet->name, greet->password set in ManageGreeter().
2345 Debug("Greeter returned name '%s'\n", greet->name);
2348 greet->name_full = greet->name;
2349 /* get just person name out of full SID */
2351 while (i < sizeof(rgy_$name_t)
2352 && greet->name_full[i] != '.'
2353 && greet->name_full[i] != '\0') {
2354 name_short[i] = greet->name_full[i];
2357 name_short[i] = '\0';
2358 greet->name = name_short;
2363 * groups[] set in Authenticate().
2365 if ( IsVerifyName(VN_AFS) ) {
2366 verify->groups[0] = groups[0];
2367 verify->groups[1] = groups[1];
2368 Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2369 Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2375 * sensitivityLevel set in BLS_Verify()
2377 greet->b1security = sensitivityLevel;
2380 Verify(d, greet, verify);
2384 Debug ("Greeter Xlib error or SIGTERM\n");
2385 SessionExit(d, OPENFAILED_DISPLAY);
2387 case NOTIFY_RESTART:
2388 Debug ("Greeter requested RESTART_DISPLAY\n");
2389 SessionExit(d, RESERVER_DISPLAY);
2391 case NOTIFY_ABORT_DISPLAY:
2392 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2393 SessionExit(d, UNMANAGE_DISPLAY);
2395 case NOTIFY_NO_WINDOWS:
2396 Debug ("Greeter requested NO_WINDOWS mode\n");
2397 if (d->serverPid >= 2)
2399 * Don't do a SessionExit() here since that causes
2400 * the X-server to be reset. We know we are going to
2401 * terminate it anyway, so just go do that...
2403 exit(SUSPEND_DISPLAY);
2407 case NOTIFY_LANG_CHANGE:
2408 Debug ("Greeter requested LANG_CHANGE\n");
2411 * copy requested language into display struct "d". Note,
2412 * this only happens in this child's copy of "d", not in
2413 * the master struct. When the user logs out, the
2414 * resource-specified language (if any) will reactivate.
2416 Debug("Greeter returned language '%s'\n", d->language);
2418 if (strcmp(d->language, "default") == 0) {
2419 int len = strlen(defaultLanguage) + 1;
2420 d->language = (d->language == NULL ?
2421 malloc(len) : realloc (d->language, len));
2422 strcpy(d->language, defaultLanguage);
2426 case NOTIFY_BAD_SECLEVEL:
2429 case waitCompose (SIGTERM,0,0):
2430 Debug ("Greeter exited on SIGTERM\n");
2431 SessionExit(d, OPENFAILED_DISPLAY);
2434 Debug ("Greeter returned unknown status %d\n",
2436 SessionExit(d, REMANAGE_DISPLAY);
2439 signal(SIGHUP, SIG_DFL);
2442 AbortClient(greeterPid);
2443 SessionExit(d, UNMANAGE_DISPLAY);
2447 /*****************************************************************************
2453 This is the entry into greeter state processing. Allocate and initialize
2457 Display the login screen. Upon display, the login screen can be 'reset'. If
2458 reset is true, the username and password fields are cleared and the focus
2459 is set to the username field. If reset is false, the username and password
2460 field is untouched and the focus is set to the password field.
2462 LOGIN -> AUTHENTICATE:
2463 Authenticate the username entered on login screen.
2465 AUTHENTICATE -> TERMINATEGREET:
2466 User passed authentication so terminate the greeter.
2468 AUTHENTICATE -> EXPASSWORD:
2469 User passed authentication, but the their password has expired.
2470 Display old password message. This message allows the user to
2471 change their password by starting a getty and running passwd(1).
2473 AUTHENTICATE -> BAD_HOSTNAME:
2474 User passed authentication, but the their hostname is empty.
2475 Display a dialog that allows the user to run a getty to fix the
2476 problem, or start the desktop anyway.
2478 AUTHENTICATE -> ERRORMESSAGE:
2479 User failed authentication, so display error message.
2481 AUTHENTICATE -> LOGIN
2482 User failed authentication, but did not enter a password. Instead
2483 of displaying an error message, redisplay the login screen with
2484 the focus set to the password field. If the user authenticates again
2485 without the password field set, display an error. This allows a user
2486 to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2489 Free state structure and return false to stop state transitions.
2491 ERRORMESSAGE -> LOGIN
2492 Display error message base on return code from last authentication
2493 attempt. Redisplay login screen with reset set to true.
2495 (state) -> LANG -> (state)
2496 User has chosen a new language. Transition to LANG state to save off
2497 the new language, and transition back to original state.
2499 *****************************************************************************/
2501 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2504 ManageGreeter( struct display *d, struct greet_info *greet,
2505 struct verify_info *verify, struct greet_state *state )
2512 if (state->waitForResponse)
2514 if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2517 * Dtgreet has terminated.
2519 state->id = GREET_STATE_EXIT;
2520 state->waitForResponse = FALSE;
2524 if (state->request->opcode != state->response->opcode)
2527 * An unrequested event arrived. See if it's one we
2530 switch(state->response->opcode)
2532 case REQUEST_OP_LANG:
2535 * User has changed language. Recursively handle this state
2536 * and return to current state.
2538 struct greet_state lang_state;
2540 lang_state = *state;
2541 lang_state.id = GREET_STATE_LANG;
2542 lang_state.waitForResponse = FALSE;
2543 ManageGreeter(d, greet, verify, &lang_state);
2544 Debug("Response opcode REQUEST_OP_LANG\n");
2549 case REQUEST_OP_CLEAR:
2552 * User has requested the screen be cleared.
2554 state->id = GREET_STATE_USERNAME;
2555 state->waitForResponse = TRUE;
2556 Debug("Response opcode REQUEST_OP_CLEAR\n");
2561 Debug("Response opcode UNEXPECTED RESPONSE!\n");
2571 * Got the response we were expecting.
2573 state->waitForResponse = FALSE;
2579 case GREET_STATE_ENTER:
2582 * Enter - initialize state
2584 Debug("GREET_STATE_ENTER\n");
2586 state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2587 state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2588 state->authenticated = FALSE;
2591 state->id = GREET_STATE_USERNAME;
2595 case GREET_STATE_USERNAME:
2600 RequestChallenge *r;
2602 Debug("GREET_STATE_USERNAME\n");
2604 Authenticate(d, NULL, NULL, NULL);
2606 SETMC(msg, LOGIN_LABEL);
2608 r = (RequestChallenge *)state->request;
2609 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2610 r->hdr.reserved = 0;
2613 r->hdr.length = sizeof(*r);
2615 r->offChallenge = sizeof(*r);
2616 strcpy(((char *)r) + r->offChallenge, msg.def);
2617 r->hdr.length += strlen(msg.def) + 1;
2621 r->offUserNameSeed = r->hdr.length;
2622 strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2623 r->hdr.length += strlen(greet->name) + 1;
2624 Debug("Greet name: %s\n", greet->name);
2628 r->offUserNameSeed = 0;
2633 free(greet->name); greet->name = NULL;
2635 if (greet->password)
2637 free(greet->password); greet->password = NULL;
2640 TellGreeter((RequestHeader *)r);
2641 state->waitForResponse = TRUE;
2643 state->id = GREET_STATE_AUTHENTICATE;
2647 case GREET_STATE_CHALLENGE:
2652 RequestChallenge *r;
2654 Debug("GREET_STATE_CHALLENGE\n");
2656 if (greet->password)
2658 free(greet->password); greet->password = NULL;
2661 SETMC(msg, PASSWD_LABEL);
2663 r = (RequestChallenge *)state->request;
2664 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2665 r->hdr.reserved = 0;
2668 r->offUserNameSeed = 0;
2669 r->offChallenge = sizeof(*r);
2670 strcpy(((char *)r) + r->offChallenge, msg.def);
2671 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2673 TellGreeter((RequestHeader *)r);
2674 state->waitForResponse = TRUE;
2676 state->id = GREET_STATE_AUTHENTICATE;
2680 case GREET_STATE_AUTHENTICATE:
2683 * Attempt to authenticate.
2685 ResponseChallenge *r;
2687 Debug("GREET_STATE_AUTHENTICATE\n");
2689 r = (ResponseChallenge *)state->response;
2691 if (greet->name == NULL)
2693 greet->name = strdup(((char *)r) + r->offResponse);
2694 if (strlen(greet->name) == 0)
2696 state->id = GREET_STATE_USERNAME;
2702 greet->password = strdup(((char *)r) + r->offResponse);
2712 * Attempt to authenticate user. 'username' should be a
2713 * non-empty string. 'password' may be an empty string.
2715 state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2717 if (state->vf == VF_OK ||
2718 state->vf == VF_PASSWD_AGED ||
2719 state->vf == VF_BAD_HOSTNAME)
2721 state->authenticated = TRUE;
2725 * General transitions.
2729 case VF_OK: state->id = GREET_STATE_TERMINATEGREET; break;
2730 case VF_PASSWD_AGED: state->id = GREET_STATE_EXPASSWORD; break;
2731 case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break;
2732 case VF_CHALLENGE: state->id = GREET_STATE_CHALLENGE; break;
2733 default: state->id = GREET_STATE_ERRORMESSAGE; break;
2738 case GREET_STATE_EXIT:
2741 * Free resources and leave.
2743 Debug("GREET_STATE_EXIT\n");
2750 if (!state->authenticated)
2754 free(greet->name); greet->name = NULL;
2756 if (greet->password)
2758 free(greet->password); greet->password = NULL;
2762 free(state->request);
2763 free(state->response);
2768 case GREET_STATE_ERRORMESSAGE:
2771 * Display error message.
2775 Debug("GREET_STATE_ERRORMESSAGE\n");
2777 r = (RequestMessage *)state->request;
2781 case VF_INVALID: SETMC(msg, LOGIN); break;
2782 case VF_HOME: SETMC(msg, HOME); break;
2783 case VF_MAX_USERS: SETMC(msg, MAX_USERS); break;
2784 case VF_BAD_UID: SETMC(msg, BAD_UID); break;
2785 case VF_BAD_GID: SETMC(msg, BAD_GID); break;
2786 case VF_BAD_AID: SETMC(msg, BAD_AID); break;
2787 case VF_BAD_AFLAG: SETMC(msg, BAD_AFLAG); break;
2788 case VF_NO_LOGIN: SETMC(msg, NO_LOGIN); break;
2790 case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2792 case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2793 default: msg.id=0; msg.def=""; break;
2796 r->hdr.opcode = REQUEST_OP_MESSAGE;
2797 r->hdr.reserved = 0;
2799 r->offMessage = sizeof(*r);
2800 strcpy(((char *)r) + r->offMessage, msg.def);
2801 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2803 TellGreeter((RequestHeader *)r);
2804 state->waitForResponse = TRUE;
2806 state->id = GREET_STATE_USERNAME;
2810 case GREET_STATE_LANG:
2813 * User selected new language.
2819 Debug("GREET_STATE_LANG\n");
2821 r = (ResponseLang *)state->response;
2822 lang = ((char *)r) + r->offLang;
2823 len = strlen(lang) + 1;
2825 d->language = (d->language == NULL ?
2826 malloc(len) : realloc(d->language, len));
2827 strcpy(d->language, lang);
2828 Debug("Language returned: %s\n", d->language);
2832 case GREET_STATE_TERMINATEGREET:
2835 * Terminate dtgreet.
2839 Debug("GREET_STATE_TERMINATEGREET\n");
2841 r = (RequestExit *)state->request;
2843 r->hdr.opcode = REQUEST_OP_EXIT;
2844 r->hdr.reserved = 0;
2845 r->hdr.length = sizeof(*r);
2847 TellGreeter((RequestHeader *)r);
2848 state->waitForResponse = TRUE;
2850 state->id = GREET_STATE_EXIT;
2854 case GREET_STATE_EXPASSWORD:
2857 * Display password expired message.
2859 RequestExpassword *r;
2861 Debug("GREET_STATE_EXPASSWORD\n");
2863 r = (RequestExpassword *)state->request;
2865 r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2866 r->hdr.reserved = 0;
2867 r->hdr.length = sizeof(*r);
2869 TellGreeter((RequestHeader *)r);
2870 state->waitForResponse = TRUE;
2872 state->id = GREET_STATE_USERNAME;
2876 case GREET_STATE_BAD_HOSTNAME:
2879 * Display password expired message.
2883 Debug("GREET_STATE_BAD_HOSTNAME\n");
2885 r = (RequestHostname *)state->request;
2887 r->hdr.opcode = REQUEST_OP_HOSTNAME;
2888 r->hdr.reserved = 0;
2889 r->hdr.length = sizeof(*r);
2891 TellGreeter((RequestHeader *)r);
2892 state->waitForResponse = TRUE;
2894 state->id = GREET_STATE_USERNAME;
2899 case GREET_STATE_FORM:
2902 * Get arbitrary number of answers.
2905 Debug("GREET_STATE_FORM\n");
2907 AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2909 state->waitForResponse = FALSE;
2910 state->id = GREET_STATE_USERNAME;
2922 RequestHeader *phdr)
2924 write(request[1], phdr, phdr->length);
2929 RequestHeader *preqhdr,
2935 ResponseHeader *phdr = (ResponseHeader *)buf;
2937 if (preqhdr) TellGreeter(preqhdr);
2939 phdr->opcode = REQUEST_OP_NONE;
2941 count = read(response[0], buf, sizeof(*phdr));
2943 if (count == sizeof(*phdr))
2946 * Calculate amount of data after header.
2948 remainder = phdr->length - sizeof(*phdr);
2952 * Read remainder of response.
2954 count += read(response[0], buf+sizeof(*phdr), remainder);
2959 if (debugLevel) PrintResponse(phdr, count);
2968 ResponseHeader *phdr,
2971 char *opstr = "UNKNOWN";
2975 Debug("opcode = (EOF)\n");
2979 switch(phdr->opcode)
2981 case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2982 case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2983 case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2984 case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2985 case REQUEST_OP_LANG: opstr = "LANG"; break;
2986 case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
2989 Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
2990 Debug(" reserved = %d\n", phdr->reserved);
2991 Debug(" length = %d\n", phdr->length);
2993 switch(phdr->opcode)
2995 case REQUEST_OP_EXIT: break;
2996 case REQUEST_OP_LANG:
2997 Debug(" offLang=%d\n", ((ResponseLang *)phdr)->offLang);
2998 Debug(" lang='%s'\n",
2999 ((char *)phdr)+((ResponseLang *)phdr)->offLang);
3001 case REQUEST_OP_MESSAGE: break;
3002 case REQUEST_OP_CHPASS: break;
3003 case REQUEST_OP_CHALLENGE:
3004 Debug(" offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
3005 Debug(" response='%s'\n",
3006 ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
3008 case REQUEST_OP_DEBUG:
3009 Debug(" offString=%d\n", ((ResponseDebug *)phdr)->offString);
3010 Debug(" string='%s'\n",
3011 ((char *)phdr)+((ResponseDebug *)phdr)->offString);
3019 /***************************************************************************
3023 * generate kerberos ticket file name. Name is returned in the static
3024 * global variable "krb_ticket_string".
3026 ***************************************************************************/
3029 SetTicketFileName(uid_t uid)
3038 * generate ticket file pathname (/tmp/tkt<uid>.<host>) ...
3041 if (env = (char *)getenv("KRBTKFILE")) {
3042 (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3043 krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3046 if (gethostname(lhost, sizeof(lhost)) != -1) {
3047 if (p = index(lhost, '.')) *p = '\0';
3048 (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3050 /* 32 bits of signed integer will always fit in 11 characters
3051 (including the sign), so no need to worry about overflow */
3052 (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3057 #endif /* __KERBEROS */
3059 #if defined (_AIX) && !defined (_POWER)
3061 /***************************************************************************
3065 * If this is an authenticated process (LOGNAME set), set user's
3066 * process environment by calling setpenv().
3068 * If this is not an authenticated process, just call execve()
3070 ***************************************************************************/
3079 char *user = getEnv (envp, "LOGNAME");
3083 rc = execve(path, argv, envp);
3087 char *usrTag, *sysTag;
3090 * Save pointers to tags. The setpenv() function clears the pointers
3091 * to the tags in userEnviron as a side-effect.
3093 sysTag = envp[SYS_ENV_TAG];
3094 usrTag = envp[USR_ENV_TAG];
3097 * Set the users process environment. This call execs arvg so it
3098 * should not return. It it should return, restore the envp tags.
3100 rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3103 * Restore pointers to tags.
3105 envp[SYS_ENV_TAG] = sysTag;
3106 envp[USR_ENV_TAG] = usrTag;
3111 #endif /* _AIX && !_POWER */
3115 /* collect the SIA parameters from a window system. */
3117 static int SiaManageGreeter(
3120 unsigned char *title,
3126 RequestMessage greeter_message;
3127 char msg_buffer[256];
3128 } greeter_msg_and_buffer;
3129 RequestForm *request_form;
3137 if (rendition == SIAFORM && dt_in_sia_ses_authent
3138 && (num_prompts == 2))
3140 /* Normal login, Password case */
3141 Debug ("SIAFORM Normal login, Password case\n");
3142 while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3143 && siaGreeterInfo.state->id != GREET_STATE_EXIT
3144 && (siaGreeterInfo.status = ManageGreeter(
3145 siaGreeterInfo.d, siaGreeterInfo.greet,
3146 siaGreeterInfo.verify, siaGreeterInfo.state)))
3149 if (!siaGreeterInfo.status
3150 || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3151 return(SIACOLABORT);
3153 strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name,
3154 prompt[0].max_result_length);
3155 strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3156 prompt[1].max_result_length);
3163 ResponseForm *response_form;
3168 Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3171 Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3174 Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3177 Debug("SIAFORM num_prompts = %d\n", num_prompts);
3181 /* need to display form */
3183 req_form_size = sizeof(RequestForm)
3184 + strlen((const char *)title) + 1;
3185 for (i=0; i<num_prompts; i++)
3186 req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3187 request_form = (RequestForm *) alloca(req_form_size);
3189 siaGreeterInfo.state->id = GREET_STATE_FORM;
3190 siaGreeterInfo.state->request = (RequestHeader *)request_form;
3191 /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3193 request_form->hdr.opcode = REQUEST_OP_FORM;
3194 request_form->hdr.reserved = 0;
3195 request_form->hdr.length = req_form_size;
3196 request_form->num_prompts = num_prompts;
3197 request_form->rendition = rendition;
3198 request_form->offTitle = sizeof(RequestForm);
3199 request_form->offPrompts = sizeof(RequestForm) +
3200 strlen((const char *)title) + 1;
3201 strcpy((char *)request_form + request_form->offTitle,
3202 (const char *)title);
3204 pmpt_ptr = (char *)request_form + request_form->offPrompts;
3205 for (i=0; i<num_prompts; i++)
3207 if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3211 Debug(" prompt[%d]: %s\n", i, prompt[i].prompt);
3212 strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3213 pmpt_ptr += strlen((const char *)prompt[i].prompt);
3215 request_form->visible[i] =
3216 (prompt[i].control_flags & SIARESINVIS) ? False : True;
3219 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3220 siaGreeterInfo.greet,
3221 siaGreeterInfo.verify,
3222 siaGreeterInfo.state);
3224 response_form = (ResponseForm *)siaGreeterInfo.state->response;
3225 res_ptr = (char *)response_form + response_form->offAnswers;
3226 for (i = 0; i < response_form->num_answers; i++)
3228 if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3231 prompt[i].result = (unsigned char *)1;
3233 prompt[i].result = NULL;
3237 strcpy((char *)prompt[0].result, res_ptr);
3239 res_ptr += strlen(res_ptr) + 1;
3241 if (!response_form->collect_status)
3242 siaGreeterInfo.status = FALSE;
3248 Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3250 siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3251 siaGreeterInfo.state->request = (RequestHeader *)
3252 &greeter_msg_and_buffer.greeter_message;
3253 siaGreeterInfo.state->vf = VF_MESSAGE;
3254 siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3256 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3257 siaGreeterInfo.greet,
3258 siaGreeterInfo.verify,
3259 siaGreeterInfo.state);
3262 return(SIACOLABORT);
3265 if (!siaGreeterInfo.status)
3266 return(SIACOLABORT);
3267 return(SIACOLSUCCESS);
3270 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3273 greet->name = malloc(strlen(siaHandle->name) + 1);
3274 strcpy (greet->name, siaHandle->name);
3276 greet->password = malloc(strlen(siaHandle->password) + 1);
3277 strcpy (greet->password, siaHandle->password);
3282 static void KillGreeter( void )
3284 if (sia_greeter_pid)
3285 AbortClient(sia_greeter_pid);
3286 sia_greeter_pid = 0;