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>
68 #if defined(__FreeBSD__)
81 #include <X11/Intrinsic.h>
84 # include <X11/Xresource.h>
95 # include <sys/security.h>
101 #endif /* __KERBEROS */
104 #include "rgy_base.h"
109 static SIAENTITY *siaHandle = NULL;
110 static Boolean dt_in_sia_ses_authent = False;
112 static struct sia_greeter_info {
114 struct greet_info *greet;
115 struct verify_info *verify;
116 struct greet_state *state;
120 static int SiaManageGreeter(
123 unsigned char *title,
127 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet);
129 static void KillGreeter( void );
131 static int sia_greeter_pid;
132 static int sia_exit_proc_reg = FALSE;
138 extern char *getenv();
141 #define GREET_STATE_LOGIN 0
142 #define GREET_STATE_AUTHENTICATE 1
143 #define GREET_STATE_EXIT 2
144 #define GREET_STATE_EXPASSWORD 3
145 #define GREET_STATE_ERRORMESSAGE 4
146 #define GREET_STATE_LANG 5
147 #define GREET_STATE_BAD_HOSTNAME 6
148 #define GREET_STATE_ENTER 7
149 #define GREET_STATE_TERMINATEGREET 8
150 #define GREET_STATE_USERNAME 9
151 #define GREET_STATE_CHALLENGE 10
152 #define GREET_STATE_FORM 11
155 #define DEF_SESSION CDE_INSTALLATION_TOP "/bin/Xsession"
163 int waitForResponse; /* TRUE=wait for response from dtgreet */
164 RequestHeader *request; /* request buffer */
165 ResponseHeader *response; /* response buffer */
166 int authenticated; /* TRUE=user is authenticated */
167 int vf; /* last return code from Authenticate() */
168 int loginReset; /* reset flag for LOGIN state */
169 char *msg; /* message for VF_MESSAGE */
172 char *globalDisplayName;
174 /***************************************************************************
176 * Local procedure declarations
178 ***************************************************************************/
180 static int AbortClient( int pid) ;
181 static void DeleteXloginResources( struct display *d, Display *dpy) ;
182 int LoadXloginResources( struct display *d) ;
183 static int ErrorHandler( Display *dpy, XErrorEvent *event) ;
184 static int IOErrorHandler( Display *dpy) ;
185 static int ManageGreeter( struct display *d, struct greet_info *greet,
186 struct verify_info *verify, struct greet_state *state) ;
187 static void RunGreeter( struct display *d, struct greet_info *greet,
188 struct verify_info *verify) ;
189 static void SessionExit( struct display *d, int status) ;
190 static void SessionPingFailed( struct display *d) ;
191 static int StartClient(struct verify_info *verify, struct display *d,
193 static SIGVAL catchAlrm( int arg ) ;
194 static SIGVAL catchHUP( int arg ) ;
195 static SIGVAL catchTerm( int arg ) ;
196 static SIGVAL waitAbort( int arg ) ;
197 static void SetupDisplay(struct display *d);
199 static void TellGreeter(RequestHeader *phdr);
200 static int AskGreeter(RequestHeader *preqhdr, char *b, int blen);
202 static void PrintResponse(ResponseHeader *phdr, int count);
205 #if defined (_AIX) && defined (_POWER)
206 static void release_aix_lic(void);
209 #if defined (_AIX) && !defined (_POWER)
210 static int session_execve(char *path, char *argv[], char *envp[]);
212 #define session_execve(A,B,C) execve(A,B,C)
216 static void SetTicketFileName(uid_t uid);
217 # endif /* __KERBEROS */
219 static void LoadAltDtsResources( struct display *d);
220 char * _ExpandLang(char *string, char *lang);
224 /***************************************************************************
228 ***************************************************************************/
230 static int clientPid;
231 static struct greet_info greet;
232 static struct verify_info verify;
233 static char *defaultLanguage = NULL;
235 static jmp_buf abortSession;
238 static char *sensitivityLevel;
242 static char krb_ticket_string[MAXPATHLEN];
243 #endif /* __KERBEROS */
246 XrmDatabase XresourceDB;
253 longjmp (abortSession, 1);
256 static jmp_buf pingTime;
261 longjmp (pingTime, 1);
265 FileNameCompare (a, b)
266 #if defined(__STDC__)
272 return strcoll (*(char **)a, *(char **)b);
276 SessionPingFailed( struct display *d )
280 AbortClient (clientPid);
281 source (&verify, d->reset);
283 #if defined (PAM) || defined(SUNAUTH)
285 char* user = getEnv (verify.userEnviron, "USER");
286 char* ttyLine = d->gettyLine;
288 #ifdef DEF_NETWORK_DEV
290 * If location is not local (remote XDMCP dtlogin) and
291 * remote accouting is enabled (networkDev start with /dev/...)
292 * Set tty line name to match network device for accouting.
293 * Unless the resource was specifically set, default is value
294 * of DEF_NETWORK_DEV define (/dev/dtremote)
297 if ( d->displayType.location != Local &&
298 networkDev && !strncmp(networkDev,"/dev/",5)) {
299 ttyLine = networkDev+5;
304 PamAccounting( verify.argv[0], d->name, d->utmpId, user,
305 ttyLine, clientPid, ACCOUNTING, NULL);
307 solaris_accounting( verify.argv[0], d->name, d->utmpId, user,
308 ttyLine, clientPid, ACCOUNTING, NULL);
312 solaris_resetdevperm(ttyLine);
318 SessionExit (d, RESERVER_DISPLAY);
323 * We need our own error handlers because we can't be sure what exit code Xlib
324 * will use, and our Xlib does exit(1) which matches REMANAGE_DISPLAY, which
325 * can cause a race condition leaving the display wedged. We need to use
326 * RESERVER_DISPLAY for IO errors, to ensure that the manager waits for the
327 * server to terminate. For other X errors, we should give up.
331 IOErrorHandler( Display *dpy )
334 char *s = ((errno >= 0 && errno < sys_nerr) ? sys_errlist[errno]
337 LogError(ReadCatalog(
338 MC_LOG_SET,MC_LOG_FATAL_IO,MC_DEF_LOG_FATAL_IO),
340 exit(RESERVER_DISPLAY);
345 ErrorHandler( Display *dpy, XErrorEvent *event )
347 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_X_ERR,MC_DEF_LOG_X_ERR));
348 if (XmuPrintDefaultErrorMessage (dpy, event, stderr) == 0) return 0;
349 exit(UNMANAGE_DISPLAY);
355 ManageSession( struct display *d )
361 char *BypassUsername;
363 #endif /* BYPASSLOGIN */
366 Debug ("ManageSession():\n");
368 /***********************************/
369 /** remember the default language **/
370 /***********************************/
371 if (defaultLanguage == NULL) {
372 if ( (d->language != NULL) && (strlen(d->language) > 0) ) {
373 defaultLanguage = strdup(d->language);
375 defaultLanguage = "C";
381 if ((BypassUsername = BypassLogin(d->name)) != NULL) {
383 Debug("Login bypassed, running as %s\n",BypassUsername);
384 greet.name = BypassUsername;
385 if (!Verify (d, &greet, &verify)) {
386 Debug ("Login bypass verify failed!\n");
387 SessionExit (d, GREETLESS_FAILED);
389 Debug("Login bypass verify succeded!\n");
391 #endif /* BYPASSLOGIN */
396 (void)XSetIOErrorHandler(IOErrorHandler);
397 (void)XSetErrorHandler(ErrorHandler);
398 SetTitle(d->name, (char *) 0);
401 * set root background to black...
404 dpy = XOpenDisplay(d->name);
405 for (i = ScreenCount(dpy) - 1; i >= 0; i--)
407 Window tmproot = RootWindow(dpy, i);
409 if (i == DefaultScreen(dpy))
412 XSetWindowBackground(dpy, tmproot, BlackPixel(dpy, i));
413 XClearWindow(dpy, tmproot);
419 ** Invoke Greet program, wait for completion.
420 ** If this routine returns, the user will have been
421 ** verified, otherwise the routine will exit inter-
422 ** nally with an appropriate exit code for the master
427 greet.name = greet.string = NULL;
429 while (greet.name == NULL) {
430 SetHourGlassCursor(dpy, root);
431 LoadXloginResources (d);
433 ApplyFontPathMods(d, dpy);
434 (void)XSetErrorHandler(ErrorHandler);
435 RunGreeter(d, &greet, &verify);
437 DeleteXloginResources (d, dpy);
439 XSetInputFocus(dpy, root, RevertToNone, CurrentTime);
445 * Generate Kerberos ticket file name. Put in system and user
449 if ( IsVerifyName(VN_KRB)) {
450 SetTicketFileName(verify.uid);
451 krb_set_tkt_string(krb_ticket_string);
452 verify.systemEnviron = setEnv (verify.systemEnviron,
456 verify.userEnviron = setEnv (verify.userEnviron,
460 #endif /* __KERBEROS */
462 /* set LOCATION env var */
463 if(d->displayType.location == Local) {
464 verify.systemEnviron = setEnv (verify.systemEnviron,
467 /* ITE is needed only for Local displays */
468 /* set ITE env var */
470 verify.systemEnviron = setEnv (verify.systemEnviron,
475 verify.systemEnviron = setEnv (verify.systemEnviron,
482 sprintf(gid,"%ld",(long)getgid());
483 /* set user group id (USER_GID) env var */
484 verify.systemEnviron = setEnv (verify.systemEnviron,
488 /* set root group id (ROOT_GID) env var */
489 pwd = getpwnam("root");
491 sprintf(gid,"%ld",(long)pwd->pw_gid);
492 verify.systemEnviron = setEnv (verify.systemEnviron,
499 * Run system-wide initialization file
501 if (source (&verify, d->startup) != 0)
503 Debug ("Startup program %s exited with non-zero status\n",
505 SessionExit (d, OBEYSESS_DISPLAY);
509 if ( solaris_setdevperm(d->gettyLine, verify.uid, verify.gid) == 0 ) {
510 SessionExit (d, OBEYSESS_DISPLAY);
515 if (!setjmp (abortSession)) {
516 signal (SIGTERM, catchTerm);
518 * Start the clients, changing uid/groups
519 * setting up environment and running the session
521 if (StartClient (&verify, d, &clientPid)) {
522 Debug ("Client started\n");
525 * We've changed dtlogin to pass HUP's down to the children
526 * so ignore any HUP's once the client has started.
528 signal(SIGHUP, SIG_IGN);
531 * Wait for session to end,
536 if (!setjmp (pingTime))
538 signal (SIGALRM, catchAlrm);
539 alarm (d->pingInterval * 60);
540 pid = wait ((waitType *) 0);
546 if (!PingServer (d, (Display *) NULL))
547 SessionPingFailed (d);
552 pid = wait ((waitType *) 0);
554 if (pid == clientPid)
559 * We've changed dtlogin to pass HUP's down to the children
560 * so ignore any HUP's once the client has started.
562 signal(SIGHUP, SIG_DFL);
564 LogError(ReadCatalog(
565 MC_LOG_SET,MC_LOG_FAIL_START,MC_DEF_LOG_FAIL_START));
569 * when terminating the session, nuke
570 * the child and then run the reset script
572 AbortClient (clientPid);
576 * on foreign displays without XDMCP, send a SIGTERM to the process
577 * group of the session manager. This augments the "resetServer()"
578 * routine and helps get all clients killed. It is possible for a client
579 * to have a connection to the server, but not have a window.
582 if (d->displayType.location == Foreign &&
583 d->displayType.origin != FromXDMCP )
584 AbortClient(clientPid);
589 * remove ticket file...
592 if ( IsVerifyName(VN_KRB) ) {
596 #endif /* __KERBEROS */
600 * run system-wide reset file
602 Debug ("Source reset program %s\n", d->reset);
603 source (&verify, d->reset);
605 #if defined(PAM) || defined(SUNAUTH)
607 char* user = getEnv (verify.userEnviron, "USER");
608 char* ttyLine = d->gettyLine;
610 # ifdef DEF_NETWORK_DEV
612 * If location is not local (remote XDMCP dtlogin) and
613 * remote accouting is enabled (networkDev start with /dev/...)
614 * Set tty line name to match network device for accouting.
615 * Unless the resource was specifically set, default is value
616 * of DEF_NETWORK_DEV define (/dev/dtremote)
619 if ( d->displayType.location != Local &&
620 networkDev && !strncmp(networkDev,"/dev/",5)) {
621 ttyLine = networkDev+5;
626 PamAccounting( verify.argv[0], d->name, d->utmpId, user,
627 ttyLine, clientPid, ACCOUNTING, NULL);
629 solaris_accounting( verify.argv[0], d->name, d->utmpId, user,
630 ttyLine, clientPid, ACCOUNTING, NULL);
634 solaris_resetdevperm(ttyLine);
639 SessionExit (d, OBEYSESS_DISPLAY);
644 LoadXloginResources( struct display *d )
651 char *resources = NULL;
655 if (d->resources && d->resources[0]) {
656 resources = _ExpandLang(d->resources, d->language);
657 if (access (resources, R_OK) != 0) {
658 /** fallback to the C locale for resources **/
659 Debug("LoadXloginResources - cant access %s\n", resources);
660 Debug("\t %s. Falling back to C.\n", sys_errlist[errno]);
662 resources = _ExpandLang(d->resources, "C");
663 if (access (resources, R_OK) != 0) {
664 /** can't find a resource file, so bail **/
665 Debug("LoadXloginResources - cant access %s.\n", resources);
666 Debug("\t %s. Unable to find resource file.\n",
673 if (d->authFile && strlen(d->authFile) > 0 ) {
674 authority = d->authFile;
675 auth_key = "XAUTHORITY=";
678 if (d->language && strlen(d->language) > 0 ) {
679 language = strdup(d->language);
684 * replace any "-" or "." in the language name with "_". The C
685 * preprocessor used by xrdb does not accept "-" or "." in a name.
688 while ( (p = strchr(language, '-')) != NULL ) {
692 while ( (p = strchr(language, '.')) != NULL ) {
696 if ( strlen(language) > 0 )
700 Debug("LoadXloginResources - loading resource db from %s\n", resources);
701 if((XresourceDB = XrmGetFileDatabase(resources)) == NULL)
702 Debug("LoadXloginResources - Loading resource db from %s failed\n",
705 LoadAltDtsResources(d);
707 strcpy(tmpname,"/var/dt/dtlogin_XXXXXX");
708 (void) mktemp(tmpname);
710 XrmPutFileDatabase(XresourceDB, tmpname);
712 sprintf (cmd, "%s%s %s -display %s -load %s",
713 auth_key, authority, d->xrdb, d->name, tmpname);
714 Debug ("Loading resource file: %s\n", cmd);
718 if (debugLevel <= 10)
719 if (unlink (tmpname) == -1)
720 Debug ("unlink() on %s failed\n", tmpname);
723 if (resources) free (resources);
728 /***************************************************************************
730 * LoadAltDtsResources
733 * set up alternate desktop resources..
735 ***************************************************************************/
738 LoadAltDtsResources(struct display *d)
742 char dirname[2][MAXPATHLEN];
743 char res_file[MAXPATHLEN];
744 char *rmtype; /* for XrmGetResource() */
745 XrmValue rmvalue; /* for XrmGetResource() */
746 char buf[MAXPATHLEN];
747 char tempbuf[MAXPATHLEN];
750 char altdtres[MAXPATHLEN];
751 char Altdtres[MAXPATHLEN];
754 char *resources = NULL;
756 int num_allocated = 0;
757 char **file_list = NULL;
760 if ( XrmGetResource(XresourceDB,
761 "Dtlogin*altDts", "Dtlogin*AltDts",
762 &rmtype, &rmvalue ) ) {
763 strcpy(tempbuf,rmvalue.addr);
767 strcpy(dirname[0],CDE_INSTALLATION_TOP "/config/%L/Xresources.d/");
768 strcpy(dirname[1],CDE_CONFIGURATION_TOP "/config/%L/Xresources.d/");
770 for(j = 0; j < 2 ; ++j)
772 resources = _ExpandLang(dirname[j], d->language);
773 if (access (resources, R_OK) != 0)
775 Debug("LoadAltDtsResources- cant access %s.\n", resources);
776 Debug("\t %s. Falling back to C.\n", sys_errlist[errno]);
784 resources = _ExpandLang(dirname[j], "C");
785 if (access (resources, R_OK) != 0)
787 Debug("LoadAltDtsResources- cant access %s.\n", resources);
788 Debug("\t %s.\n", sys_errlist[errno]);
791 strcpy(dirname[j], resources);
794 strcpy(dirname[j],resources);
795 Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
807 * Create a list of the alt DT files
809 * NOTE - an assumption made here is that files in /etc/dt
810 * should take precedence over files in /usr/dt. This precedence
811 * is maintained during the sort becase /etc/dt will come before
815 for(j = 0; j < 2 ; ++j) {
817 if((dirp = opendir(dirname[j])) != NULL) {
819 while((dp = readdir(dirp)) != NULL) {
821 if ((strcmp(dp->d_name, DOT) != 0) &&
822 (strcmp(dp->d_name, DOTDOT) != 0)) {
824 sprintf (res_file, "%s%s", dirname[j],dp->d_name);
825 if ((access (res_file, R_OK)) != 0)
827 Debug("LoadAltDtsResources- cant access %s.\n",
829 Debug("\t %s.\n", sys_errlist[errno]);
833 if (file_count == 0) {
834 file_list = malloc (list_incr * sizeof(char **));
835 num_allocated += list_incr;
837 if (file_count + 1 > num_allocated) {
838 num_allocated += list_incr;
839 file_list = realloc (file_list,
840 num_allocated * sizeof(char **));
842 file_list[file_count] = strdup (res_file);
851 qsort (file_list, file_count, sizeof (char *), FileNameCompare);
853 for (j = 0; j < file_count ; j++) {
855 userDb = XrmGetFileDatabase(file_list[j]);
856 XrmMergeDatabases(userDb,&XresourceDB);
858 if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
859 "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
862 * remove the trailing spaces
864 if(strchr(rmvalue.addr,' '))
865 strcpy(tempbuf, strtok(rmvalue.addr," "));
867 strcpy(tempbuf, rmvalue.addr);
869 if ((strcmp(tempbuf, "True") == 0) ||
870 (strcmp(tempbuf, "TRUE") == 0)) {
872 if ( XrmGetResource(XresourceDB,
873 "Dtlogin*altDtKey", "Dtlogin*AltDtKey",
874 &rmtype, &rmvalue ) ) {
876 sprintf(altdtres,"Dtlogin*altDtKey%d",i);
877 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
882 if ( XrmGetResource(XresourceDB,
883 "Dtlogin*altDtName", "Dtlogin*AltDtName",
884 &rmtype, &rmvalue ) ) {
885 sprintf(altdtres,"Dtlogin*altDtName%d",i);
886 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
888 if ( XrmGetResource(XresourceDB,
889 "Dtlogin*altDtStart", "Dtlogin*AltDtStart",
890 &rmtype, &rmvalue ) ) {
891 sprintf(altdtres,"Dtlogin*altDtStart%d",i);
892 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
894 if ( XrmGetResource(XresourceDB,
895 "Dtlogin*altDtLogo", "Dtlogin*AltDtLogo",
896 &rmtype, &rmvalue ) ) {
897 sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
898 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
904 sprintf(tempbuf,"%d",i);
905 XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf);
907 if (file_count > 0) {
908 for (i = 0; i < file_count; i++) {
909 Debug ("Loading resource file: %s\n", file_list[i]);
919 * Function Name: _ExpandLang
923 * This function takes the string "string", searches for occurences of
924 * "%L" in the string and if found, the "%L" is substituted with
925 * the value of the $LANG environment variable.
927 * If $LANG is not defined, the %L is replace with NULL.
931 * _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
935 * ret_string = _ExpandLang (string);
937 * char *ret_string; Returns NULL if "string" is NULL or it points
938 * to the expanded string.
940 * char *string; The first part of the pathname. Typically
941 * the directory containing the item of interest.
943 * Note: The caller is responsible for free'ing the returned string.
965 * Count the number of expansions that will occur.
969 for (n = 0, pch = string ; pch != NULL ; ) {
970 if ((pch = strchr (pch, '%')) != NULL) {
977 return (strdup(string));
980 * We should really be calling setlocale to determine the "default"
981 * locale but setlocale's return value is not standardized across
982 * the various vendor platforms nor is it consistent within differnt
983 * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
984 * HP-UX 10.0). The "right" call would be the following line:
986 * if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
988 * Here we hard code the default to "C" instead of leaving it NULL.
990 if (lang || (lang = getenv ("LANG")) || (lang = "C"))
991 lang_len = strlen (lang);
994 * Create the space needed.
996 tmp_len = strlen (string) + (n * lang_len) + n + 1;
997 tmp = (char *) malloc (tmp_len);
998 for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
1002 while (pch != NULL) {
1005 if ((pch = strchr (pch, '%')) != NULL) {
1010 (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
1012 else if ((pch != NULL) && *pch == 'L') {
1013 if (lang_len == 0) {
1014 if (((pch - trail) >=2) && (*(pch-2) == '/'))
1016 * Remove the "/" as well as the "%L".
1018 (void) strncat (tmp, trail, (pch - trail) - 2);
1020 (void) strncat (tmp, trail, (pch - trail) - 1);
1024 * Remove the "%L" and then append the LANG.
1026 (void) strncat (tmp, trail, (pch - trail) - 1);
1027 (void) strcat (tmp, lang);
1031 (void) strncat (tmp, trail, (pch - trail) + 1);
1038 * A '%' was not found.
1040 (void) strcat (tmp, trail);
1049 SetupDisplay (struct display *d)
1051 char **env = 0, **crt_systemEnviron;
1053 if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1055 crt_systemEnviron = verify.systemEnviron;
1056 env = systemEnv (d, (char *) 0, (char *) 0);
1057 if (d->authFile && strlen(d->authFile) > 0 )
1058 env = setEnv( env, "XAUTHORITY", d->authFile );
1059 if(d->displayType.location == Local)
1060 env = setEnv (env, LOCATION, "local");
1062 env = setEnv (env, LOCATION, "remote");
1063 verify.systemEnviron = env;
1064 source (&verify, d->setup);
1065 verify.systemEnviron = crt_systemEnviron;
1072 DeleteXloginResources( struct display *d, Display *dpy )
1074 XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1077 #if 0 /* dead code: transferred to Dtgreet */
1079 static jmp_buf syncJump;
1084 longjmp (syncJump, 1);
1088 SecureDisplay (d, dpy)
1092 Debug ("SecureDisplay():\n");
1093 signal (SIGALRM, syncTimeout);
1094 if (setjmp (syncJump)) {
1095 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1097 SessionExit (d, RESERVER_DISPLAY);
1099 alarm ((unsigned) d->grabTimeout);
1100 Debug ("Before XGrabServer()\n");
1102 if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1103 GrabModeAsync, CurrentTime) != GrabSuccess)
1106 signal (SIGALRM, SIG_DFL);
1107 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1109 SessionExit (d, RESERVER_DISPLAY);
1111 Debug ("XGrabKeyboard() succeeded\n");
1113 signal (SIGALRM, SIG_DFL);
1117 XUngrabServer (dpy);
1120 Debug ("Done secure %s\n", d->name);
1123 UnsecureDisplay (d, dpy)
1127 Debug ("Unsecure display %s\n", d->name);
1129 XUngrabServer (dpy);
1138 release_aix_lic(void)
1141 * Release AIX iFOR/LS license (if any)
1149 release_me.request_type = -1;
1150 release_me.login_pid = getpid();
1151 if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1153 write(fd, &release_me, sizeof(release_me));
1156 Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1164 SessionExit( struct display *d, int status )
1173 /* make sure the server gets reset after the session is over */
1174 if (d->serverPid >= 2) {
1175 Debug("Reseting server: pid %d signal %d\n",
1176 d->serverPid, d->resetSignal);
1178 if (d->terminateServer == 0 && d->resetSignal)
1179 kill (d->serverPid, d->resetSignal);
1184 Debug("Exiting Session with status: %d\n", status);
1189 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1192 char currentdir[PATH_MAX+1];
1193 char *failsafeArgv[20];
1194 char *user; /* users name */
1195 char *lang, *font; /* failsafe LANG and font */
1198 int failsafe = FALSE; /* do we run the failsafe session? */
1199 int password = FALSE; /* do we run /bin/passwd? */
1202 char lastsessfile[MAXPATHLEN];
1205 struct pr_passwd *b1_pwd;
1209 #define NOPAG 0xffffffff
1211 long ngroups, groups[NGROUPS];
1217 Debug ("StartSession %s: ", verify->argv[0]);
1218 for (f = verify->argv; *f; f++) {
1220 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1221 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1225 if (verify->userEnviron) {
1226 for (f = verify->userEnviron; *f; f++)
1231 user = getEnv (verify->userEnviron, "USER");
1233 switch (pid = fork ()) {
1236 /* Force a failsafe session if we can't touch the home directory
1237 * SIA has already attempted to chdir to HOME, and the current dir
1238 * will be set to / if it failed. We just check to see if the HOME
1239 * path is our current directory or not.
1241 home = getEnv (verify->userEnviron, "HOME");
1242 getcwd(currentdir, PATH_MAX+1);
1243 Debug("Current directory is: %s\n", currentdir);
1247 * The following little check doesn't really work. For example,
1248 * here at the XC, NIS reports my home directory as
1249 * "/site/guests/montyb" while getcwd comes up with
1250 * "/net/nexus/site/guests/montyb".
1252 if (strcmp(home, currentdir)) {
1253 Debug("Can't access home directory, setting failsafe to TRUE\n");
1255 LogError (ReadCatalog(
1256 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1257 home, getEnv (verify->userEnviron, "USER"));
1258 verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1266 * do process accounting...
1268 #if defined(PAM) || defined(SUNAUTH)
1270 char* ttyLine = d->gettyLine;
1272 # ifdef DEF_NETWORK_DEV
1274 * If location is not local (remote XDMCP dtlogin) and
1275 * remote accouting is enabled (networkDev start with /dev/...)
1276 * Set tty line name to match network device for accouting.
1277 * Unless the resource was specifically set, default is value
1278 * of DEF_NETWORK_DEV define (/dev/dtremote)
1281 if ( d->displayType.location != Local &&
1282 networkDev && !strncmp(networkDev,"/dev/",5)) {
1283 ttyLine = networkDev+5;
1288 PamAccounting(verify->argv[0], d->name, d->utmpId, user,
1289 ttyLine, getpid(), USER_PROCESS, NULL);
1291 solaris_accounting(verify->argv[0], d->name, d->utmpId, user,
1292 ttyLine, getpid(), USER_PROCESS, NULL);
1297 #if !defined(sun) && !defined(CSRG_BASED)
1298 Account(d, user, NULL, getpid(), USER_PROCESS, status);
1303 * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1304 * setpenv() to set up the user's process environment and return
1305 * without execing. This allows us to set up the process environment
1306 * and proceed to the execute() call as do the other platforms.
1308 * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1309 * we have to pospone the setpenv() to the actual execute().
1313 * These defines are the tag locations in userEnviron.
1314 * IMPORTANT: changes to the locations of these tags in verify.c
1315 * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1317 #define SYS_ENV_TAG 0
1318 #define USR_ENV_TAG 3
1321 * Set the user's credentials: uid, gid, groups,
1322 * audit classes, user limits, and umask.
1325 if (setpcred(user, NULL) == -1)
1327 Debug("Can't set User's Credentials (user=%s)\n",user);
1332 char *usrTag, *sysTag;
1333 extern char **newenv;
1336 * Save pointers to tags. The setpenv() function clears the pointers
1337 * to the tags in userEnviron as a side-effect.
1339 sysTag = verify->userEnviron[SYS_ENV_TAG];
1340 usrTag = verify->userEnviron[USR_ENV_TAG];
1343 * Set the users process environment. Store protected variables and
1344 * obtain updated user environment list. This call will initialize
1347 #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1348 if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1350 Debug("Can't set process environment (user=%s)\n",user);
1355 * Restore pointers to tags.
1357 verify->userEnviron[SYS_ENV_TAG] = sysTag;
1358 verify->userEnviron[USR_ENV_TAG] = usrTag;
1361 * Free old userEnviron and replace with newenv from setpenv().
1363 freeEnv(verify->userEnviron);
1364 verify->userEnviron = newenv;
1374 if (PamSetCred( verify->argv[0],
1375 user, verify->uid, verify->gid) > 0 ) {
1376 Debug("Can't set User's Credentials (user=%s)\n",user);
1382 if ( solaris_setcred(verify->argv[0],
1383 user, verify->uid, verify->gid) > 0 ) {
1384 Debug("Can't set User's Credentials (user=%s)\n",user);
1387 #endif /* SUNAUTH */
1394 * HP BLS B1 session setup...
1396 * 1. look up user's protected account information.
1397 * 2. set the session sensitivity/clearance levels
1398 * 3. set the logical UID (LUID)
1402 Debug("BLS - Setting user's clearance, security level and luid.\n");
1403 set_auth_parameters(1, verify->argv);
1406 verify->user_name = user;
1407 strncpy(verify->terminal,d->name,15);
1408 verify->terminal[15]='\0';
1409 verify->pwd = getpwnam(user);
1411 if ( verify->pwd == NULL || strlen(user) == 0 ) {
1412 LogError(ReadCatalog(
1413 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1416 verify->prpwd= b1_pwd = getprpwnam(user);
1417 verify->uid = b1_pwd->ufld.fd_uid;
1419 if ( b1_pwd == NULL || strlen(user) == 0 ) {
1420 LogError(ReadCatalog(
1421 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1426 * This has already been done successfully by dtgreet
1427 * but we need to get all the information again for the
1430 if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1431 Debug("BLS - Could not verify sensitivity level.\n");
1432 LogError(ReadCatalog(
1433 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1437 if ( change_to_user(verify) != 1 ) {
1438 Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1439 LogError(ReadCatalog(
1440 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1445 Debug("BLS - Session setup complete.\n");
1452 * This should never fail since everything has been verified already.
1453 * If it does it must mean registry strangeness, so exit, and try
1457 if (!DoLogin (user, greet.password, d->name)) exit (1);
1460 * extract the SYSTYPE and ISP environment values and set into user's
1461 * environment. This is necessary since we do an execve below...
1464 verify->userEnviron = setEnv(verify->userEnviron, "SYSTYPE",
1467 verify->userEnviron = setEnv(verify->userEnviron, "ISP",
1470 #else /* ! __apollo */
1474 if ( IsVerifyName(VN_AFS) ) {
1475 pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1476 Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1478 initgroups(greet.name, verify->groups[2]);
1479 ngroups = getgroups(NGROUPS, groups);
1480 Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1481 for (i=0; i < ngroups; i++)
1482 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1484 if ((pagval != NOPAG) &&
1485 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1486 /* we will have to shift grouplist to make room for pag */
1487 if (ngroups+2 > NGROUPS)
1489 for (j=ngroups-1; j >= 0; j--) {
1490 groups[j+2] = groups[j];
1493 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1494 if (setgroups(ngroups, groups) == -1) {
1497 MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1502 # else /* ! __AFS */
1503 /* If SIA is enabled, the initgroups and setgid calls are redundant
1510 * if your system does not support "initgroups(3C)", use
1511 * the "setgroups()" call instead...
1514 # if (defined(__hpux) || defined(__osf__))
1515 initgroups(user, -1);
1517 setgroups (verify->ngroups, verify->groups);
1520 /* setpenv() will set gid for AIX */
1522 setgid (verify->groups[0]);
1525 # else /* ! NGROUPS */
1527 /* setpenv() will set gid for AIX */
1529 setgid (verify->gid);
1532 # endif /* NGROUPS */
1538 setaudid(verify->audid);
1539 setaudproc(verify->audflg);
1542 /* setpenv() will set uid for AIX */
1544 if (setuid(verify->uid) != 0) {
1545 Debug( "Setuid failed for user %s, errno = %d\n", user, errno);
1546 LogError(ReadCatalog(
1547 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1553 #endif /* __apollo */
1556 } /* ends the else clause of if ( ISSECURE ) */
1562 * check home directory again...
1566 /* Don't need to do this if SIA is enabled, already been done.
1568 home = getEnv (verify->userEnviron, "HOME");
1570 if (chdir (home) == -1) {
1571 LogError (ReadCatalog(
1572 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1573 home, getEnv (verify->userEnviron, "USER"));
1575 verify->userEnviron = setEnv(verify->userEnviron,
1578 else if(!failsafe) {
1579 strcpy(lastsessfile,home); /* save user's last session */
1580 strcat(lastsessfile,LAST_SESSION_FILE);
1581 if((lastsession = fopen(lastsessfile,"w")) == NULL)
1582 Debug("Unable to open file for writing: %s\n",lastsessfile);
1584 fputs(verify->argv[0],lastsession);
1585 fclose(lastsession);
1592 SetUserAuthorization (d, verify);
1598 bzero(greet.password, strlen(greet.password));
1602 * Write login information to a file
1603 * The file name should really be settable by some kind of resource
1604 * but time is short so we hard-wire it to ".dtlogininfo".
1606 if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1607 Debug("Unable to write \".dtlogininfo\"\n");
1609 /* extra debugging */
1610 if(!dump_sec_debug_info(verify)) {
1611 Debug("Something wrong with environment\n");
1614 # endif /* ! NDEBUG */
1622 Debug ("Executing session %s\n", verify->argv[0]);
1623 execute (verify->argv, verify->userEnviron);
1624 LogError(ReadCatalog(
1625 MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1629 LogError(ReadCatalog(
1630 MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1637 * specify a font for the multi-byte languages...
1641 lang = getEnv (verify->userEnviron, "LANG");
1648 failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1650 failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1651 #elif defined (USL) || defined(__uxp__)
1652 failsafeArgv[i++] = "/usr/X/bin/xterm";
1653 #elif defined(__hpux)
1654 failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1655 #elif defined(__OpenBSD__)
1656 failsafeArgv[i++] = "/usr/X11R6/bin/xterm";
1657 #elif defined(__NetBSD__)
1658 failsafeArgv[i++] = "/usr/X11R7/bin/xterm";
1659 #elif defined(__FreeBSD__)
1660 failsafeArgv[i++] = "/usr/local/bin/xterm";
1662 failsafeArgv[i++] = "/usr/bin/X11/xterm";
1664 failsafeArgv[i++] = "-geometry";
1665 failsafeArgv[i++] = "80x10";
1666 failsafeArgv[i++] = "-bg";
1667 failsafeArgv[i++] = "white";
1668 failsafeArgv[i++] = "-fg";
1669 failsafeArgv[i++] = "black";
1671 /* aixterm requires -lang option. */
1672 failsafeArgv[i++] = "-lang";
1673 failsafeArgv[i++] = lang;
1675 failsafeArgv[i++] = "-fn";
1677 if (font == NULL) font = "fixed";
1678 failsafeArgv[i++] = font;
1681 failsafeArgv[i++] = "-e";
1682 failsafeArgv[i++] = "/bin/passwd";
1683 #if defined (__apollo) || defined(__PASSWD_ETC)
1684 failsafeArgv[i++] = "-n";
1686 failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1689 failsafeArgv[i++] = d->failsafeClient;
1691 failsafeArgv[i++] = "-C";
1693 failsafeArgv[i++] = "-ls";
1696 failsafeArgv[i++] = "-fn";
1697 failsafeArgv[i++] = font;
1701 failsafeArgv[i] = 0;
1702 Debug ("Executing failsafe session\n", failsafeArgv[0]);
1703 execute (failsafeArgv, verify->userEnviron);
1706 Debug ("StartSession(): fork failed\n");
1707 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1711 Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1718 static jmp_buf tenaciousClient;
1721 waitAbort( int arg )
1723 longjmp (tenaciousClient, 1);
1726 #if defined(SYSV) || defined(SVR4)
1728 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1732 AbortClient( int pid )
1741 for (i = 0; i < 4; i++) {
1742 if (killpg (pid, sig) == -1) {
1745 LogError(ReadCatalog(
1746 MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1752 if (!setjmp (tenaciousClient)) {
1753 (void) signal (SIGALRM, waitAbort);
1754 (void) alarm ((unsigned) 10);
1755 retId = wait ((waitType *) 0);
1756 (void) alarm ((unsigned) 0);
1757 (void) signal (SIGALRM, SIG_DFL);
1761 signal (SIGALRM, SIG_DFL);
1767 source( struct verify_info *verify, char *file )
1773 if (file && file[0]) {
1774 Debug ("Source(): %s\n", file);
1775 switch (pid = fork ()) {
1780 execute (args, verify->systemEnviron);
1781 LogError(ReadCatalog(
1782 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1785 Debug ("Source(): fork failed\n");
1786 LogError(ReadCatalog(
1787 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1791 while (wait (&result) != pid)
1795 return waitVal (result);
1801 execute(char **argv, char **environ )
1805 * make stdout follow stderr to the log file...
1810 session_execve (argv[0], argv, environ);
1813 * In case this is a shell script which hasn't been made executable
1814 * (or this is a SYSV box), do a reasonable thing...
1818 /* errno is EACCES if not executable */
1819 if (errno == ENOEXEC || errno == EACCES) {
1821 if (errno == ENOEXEC) {
1823 char program[1024], *e, *p, *optarg;
1825 char **newargv, **av;
1829 * emulate BSD kernel behaviour -- read
1830 * the first line; check if it starts
1831 * with "#!", in which case it uses
1832 * the rest of the line as the name of
1833 * program to run. Else use "/bin/sh".
1835 f = fopen (argv[0], "r");
1838 if (fgets (program, sizeof (program) - 1, f) == NULL)
1844 e = program + strlen (program) - 1;
1847 if (!strncmp (program, "#!", 2)) {
1849 while (*p && isspace (*p))
1852 while (*optarg && !isspace (*optarg))
1858 while (*optarg && isspace (*optarg));
1865 Debug ("Shell script execution: %s (optarg %s)\n",
1866 p, optarg ? optarg : "(null)");
1867 for (av = argv, argc = 0; *av; av++, argc++)
1869 newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1876 while (*av++ = *argv++)
1878 session_execve (newargv[0], newargv, environ);
1885 /*****************************************************************************
1888 * Invoke the Greeter process and wait for completion. If the user was
1889 * successfully verified, return to the calling process. If the user
1890 * selected a restart or abort option, or there was an error invoking the
1891 * Greeter, exit this entire process with appropriate status.
1893 *****************************************************************************/
1897 extern int session_set;
1898 extern char *progName; /* Global argv[0]; dtlogin name and path */
1900 int response[2], request[2];
1902 /* Fixes problem with dtlogin signal handling */
1903 static int greeterPid = 0;
1904 static struct display *greeter_d = NULL;
1909 Debug("Caught SIGHUP\n");
1912 Debug("Killing greeter process: %d\n", greeterPid);
1913 kill(greeterPid, SIGHUP);
1916 SessionExit(greeter_d, REMANAGE_DISPLAY);
1918 exit(REMANAGE_DISPLAY);
1922 RunGreeter( struct display *d, struct greet_info *greet,
1923 struct verify_info *verify )
1930 static char msg[MSGSIZE];
1934 struct greet_state state;
1939 # define U_NAMELEN sizeof(rgy_$name_t)
1943 static char name_short[U_NAMELEN];
1949 char *argv[] = { "dtlogin", 0 };
1950 char *hostName = NULL;
1951 char *loginName = NULL;
1958 if (d->serverPid == -1)
1961 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
1962 loginName, d->name, 1, NULL);
1963 if (siaStatus != SIASUCCESS)
1965 Debug("sia_ses_init failure status %d\n", siaStatus);
1972 if (!setjmp (abortSession)) {
1973 signal(SIGTERM, catchTerm);
1976 * We've changed dtlogin to pass HUP's down to the children
1977 * so ignore any HUP's once the client has started.
1980 signal(SIGHUP, catchHUP);
1983 * set up communication pipes...
1991 switch (greeterPid = fork ()) {
1995 * pass some information in the environment...
1999 sprintf(msg,"%d", d->grabServer);
2000 env = setEnv(env, GRABSERVER, msg);
2002 sprintf(msg,"%d", d->grabTimeout);
2003 env = setEnv(env, GRABTIMEOUT, msg);
2006 if (timeZone && strlen(timeZone) > 0 )
2007 env = setEnv(env, "TZ", timeZone);
2009 if (errorLogFile && errorLogFile[0])
2010 env = setEnv(env, ERRORLOG, errorLogFile);
2013 env = setEnv(env, "XAUTHORITY", d->authFile);
2016 env = setEnv(env, DTLITE, "True");
2019 env = setEnv(env, SESSION, d->session);
2022 env = setEnv(env, SESSION_SET, "True");
2024 if (d->pmSearchPath)
2025 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
2027 if (d->bmSearchPath)
2028 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
2030 #if defined (__KERBEROS) || defined (__AFS)
2031 if (d->verifyName) {
2032 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2033 (strcmp(d->verifyName, VN_KRB) == 0) ) {
2035 env = setEnv(env, VERIFYNAME, d->verifyName );
2038 LogError(ReadCatalog(
2039 MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2041 d->verifyName = NULL;
2046 if((path = getenv("NLSPATH")) != NULL)
2047 env = setEnv(env, "NLSPATH", path);
2049 env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2054 * ping remote displays...
2058 if (d->displayType.location == Local) {
2059 GettyRunning(d); /* refresh gettyState */
2060 if (d->gettyState != DM_GETTY_USER)
2061 env = setEnv(env, LOCATION, "local");
2064 sprintf(msg,"%d", d->pingInterval);
2065 env = setEnv(env, PINGINTERVAL, msg);
2067 sprintf(msg,"%d", d->pingTimeout);
2068 env = setEnv(env, PINGTIMEOUT, msg);
2072 if ( d->langList && strlen(d->langList) > 0 )
2073 env = setEnv(env, LANGLIST, d->langList);
2074 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2075 else if (languageList && strlen(languageList) > 0 )
2076 env = setEnv(env, LANGLIST, languageList);
2077 #endif /* ENABLE_DYNAMIC_LANGLIST */
2080 char *language = NULL;
2082 #if defined (ENABLE_DYNAMIC_LANGLIST)
2083 language = d->language;
2084 #endif /* ENABLE_DYNAMIC_LANGLIST */
2086 if ( d->language && strlen(d->language) > 0 )
2087 env = setLang(d, env, language);
2090 if((path = getenv("XKEYSYMDB")) != NULL)
2091 env = setEnv(env, "XKEYSYMDB", path);
2094 if((path = getenv("OPENWINHOME")) != NULL)
2095 env = setEnv(env, "OPENWINHOME", path);
2100 * set environment for Domain machines...
2102 env = setEnv(env, "ENVIRONMENT", "bsd");
2103 env = setEnv(env, "SYSTYPE", "bsd4.3");
2107 Debug ("Greeter environment:\n");
2109 Debug ("End of Greeter environment:\n");
2112 * Writing to file descriptor 1 goes to response pipe instead.
2120 * Reading from file descriptor 0 reads from request pipe instead.
2130 * figure out path to dtgreet...
2133 strcpy(msg, progName);
2135 if ((p = (char *) strrchr(msg, '/')) == NULL)
2140 strcat(msg,"dtgreet");
2142 execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2143 LogError(ReadCatalog(
2144 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2146 exit (NOTIFY_ABORT_DISPLAY);
2149 Debug ("Fork of Greeter failed.\n");
2150 LogError(ReadCatalog(
2151 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2156 exit (UNMANAGE_DISPLAY);
2159 Debug ("Greeter started\n");
2161 close(response[1]); /* Close write end of response pipe */
2162 close(request[0]); /* Close read end of request pipe */
2166 * Retrieve information from greeter and authenticate.
2168 globalDisplayName = d->name;
2169 state.id = GREET_STATE_ENTER;
2170 state.waitForResponse = FALSE;
2174 * atexit() registers this function to be called if exit() is
2175 * called. This is needed because in enhanced security mode, SIA
2176 * may call exit() whn the user fails to enter or change a
2179 sia_greeter_pid = greeterPid;
2180 if (!sia_exit_proc_reg)
2182 atexit(KillGreeter);
2183 sia_exit_proc_reg = TRUE;
2186 siaGreeterInfo.d = d;
2187 siaGreeterInfo.greet = greet;
2188 siaGreeterInfo.verify = verify;
2189 siaGreeterInfo.state = &state;
2190 siaGreeterInfo.status = TRUE;
2193 while(siaStatus != SIASUCCESS)
2195 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2197 Debug ("RunGreeter: before sia_ses_authent\n");
2198 dt_in_sia_ses_authent = True;
2199 siaStatus = sia_ses_authent(SiaManageGreeter, NULL,
2201 dt_in_sia_ses_authent = False;
2202 Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2204 if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2206 state.id = GREET_STATE_ERRORMESSAGE;
2207 state.vf = VF_INVALID;
2208 ManageGreeter(d, greet, verify, &state);
2210 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2213 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2215 sia_ses_release(&siaHandle);
2219 Debug("RunGreeter: before sia_ses_estab\n");
2220 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2221 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2224 if (!siaGreeterInfo.status)
2227 if (siaStatus == SIASUCCESS)
2229 Debug("RunGreeter: before sia_ses_launch\n");
2230 siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2231 Debug("RunGreeter: after sia_ses_launch status = %d\n",
2234 if (!siaGreeterInfo.status)
2237 if (siaStatus != SIASUCCESS)
2239 Debug("RunGreeter: sia_ses_launch failure\n");
2240 /* establish & launch failures do a release */
2242 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
2243 loginName, d->name, 1, NULL);
2244 if (siaStatus != SIASUCCESS)
2246 Debug("sia_ses_init failure status %d\n", siaStatus);
2247 exit(RESERVER_DISPLAY);
2252 * sia_ses_launch() wil probably seteuid to that of the
2253 * user, but we don't want that now.
2257 * extract necessary info from SIA context struct
2261 if (siaStatus == SIASUCCESS)
2262 CopySiaInfo(siaHandle, greet);
2263 sia_ses_release(&siaHandle);
2265 state.id = GREET_STATE_TERMINATEGREET;
2266 if (siaGreeterInfo.status)
2268 while (ManageGreeter(d, greet, verify, &state))
2271 sia_greeter_pid = 0;
2273 while (ManageGreeter(d, greet, verify, &state))
2278 * Wait for Greeter to end...
2281 pid = wait (&status);
2282 if (pid == greeterPid)
2288 * Greeter exited. Check return code...
2291 Debug("Greeter return status; exit = %d, signal = %d\n",
2292 waitCode(status), waitSig(status));
2296 * remove authorization file if used...
2299 if (d->authorizations && d->authFile &&
2300 waitVal(status) != NOTIFY_LANG_CHANGE
2302 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2307 Debug ("Done with authorization file %s, removing\n",
2309 (void) unlink (d->authFile);
2314 if(waitVal(status) > NOTIFY_ALT_DTS)
2315 d->sessionType = waitVal(status);
2318 switch (waitVal(status)) {
2319 case NOTIFY_FAILSAFE:
2320 greet->string = "failsafe";
2322 case NOTIFY_PASSWD_EXPIRED:
2323 greet->string = "password";
2328 case NOTIFY_LAST_DT:
2329 d->sessionType = waitVal(status);
2335 Debug("waitVal - status is %d\n", waitVal(status));
2336 if(waitVal(status) > NOTIFY_ALT_DTS)
2337 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2339 notify_dt = waitVal(status);
2341 switch (notify_dt) {
2342 case NOTIFY_FAILSAFE:
2343 case NOTIFY_PASSWD_EXPIRED:
2347 case NOTIFY_LAST_DT:
2348 case NOTIFY_ALT_DTS:
2350 if (NULL == greet->name) return;
2353 * greet->name, greet->password set in ManageGreeter().
2355 Debug("Greeter returned name '%s'\n", greet->name);
2358 greet->name_full = greet->name;
2359 /* get just person name out of full SID */
2361 while (i < sizeof(rgy_$name_t)
2362 && greet->name_full[i] != '.'
2363 && greet->name_full[i] != '\0') {
2364 name_short[i] = greet->name_full[i];
2367 name_short[i] = '\0';
2368 greet->name = name_short;
2373 * groups[] set in Authenticate().
2375 if ( IsVerifyName(VN_AFS) ) {
2376 verify->groups[0] = groups[0];
2377 verify->groups[1] = groups[1];
2378 Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2379 Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2385 * sensitivityLevel set in BLS_Verify()
2387 greet->b1security = sensitivityLevel;
2390 Verify(d, greet, verify);
2394 Debug ("Greeter Xlib error or SIGTERM\n");
2395 SessionExit(d, OPENFAILED_DISPLAY);
2397 case NOTIFY_RESTART:
2398 Debug ("Greeter requested RESTART_DISPLAY\n");
2399 SessionExit(d, RESERVER_DISPLAY);
2401 case NOTIFY_ABORT_DISPLAY:
2402 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2403 SessionExit(d, UNMANAGE_DISPLAY);
2405 case NOTIFY_NO_WINDOWS:
2406 Debug ("Greeter requested NO_WINDOWS mode\n");
2407 if (d->serverPid >= 2)
2409 * Don't do a SessionExit() here since that causes
2410 * the X-server to be reset. We know we are going to
2411 * terminate it anyway, so just go do that...
2413 exit(SUSPEND_DISPLAY);
2417 case NOTIFY_LANG_CHANGE:
2418 Debug ("Greeter requested LANG_CHANGE\n");
2421 * copy requested language into display struct "d". Note,
2422 * this only happens in this child's copy of "d", not in
2423 * the master struct. When the user logs out, the
2424 * resource-specified language (if any) will reactivate.
2426 Debug("Greeter returned language '%s'\n", d->language);
2428 if (strcmp(d->language, "default") == 0) {
2429 int len = strlen(defaultLanguage) + 1;
2430 d->language = (d->language == NULL ?
2431 malloc(len) : realloc (d->language, len));
2432 strcpy(d->language, defaultLanguage);
2436 case NOTIFY_BAD_SECLEVEL:
2439 case waitCompose (SIGTERM,0,0):
2440 Debug ("Greeter exited on SIGTERM\n");
2441 SessionExit(d, OPENFAILED_DISPLAY);
2444 Debug ("Greeter returned unknown status %d\n",
2446 SessionExit(d, REMANAGE_DISPLAY);
2449 signal(SIGHUP, SIG_DFL);
2452 AbortClient(greeterPid);
2453 SessionExit(d, UNMANAGE_DISPLAY);
2457 /*****************************************************************************
2463 This is the entry into greeter state processing. Allocate and initialize
2467 Display the login screen. Upon display, the login screen can be 'reset'. If
2468 reset is true, the username and password fields are cleared and the focus
2469 is set to the username field. If reset is false, the username and password
2470 field is untouched and the focus is set to the password field.
2472 LOGIN -> AUTHENTICATE:
2473 Authenticate the username entered on login screen.
2475 AUTHENTICATE -> TERMINATEGREET:
2476 User passed authentication so terminate the greeter.
2478 AUTHENTICATE -> EXPASSWORD:
2479 User passed authentication, but the their password has expired.
2480 Display old password message. This message allows the user to
2481 change their password by starting a getty and running passwd(1).
2483 AUTHENTICATE -> BAD_HOSTNAME:
2484 User passed authentication, but the their hostname is empty.
2485 Display a dialog that allows the user to run a getty to fix the
2486 problem, or start the desktop anyway.
2488 AUTHENTICATE -> ERRORMESSAGE:
2489 User failed authentication, so display error message.
2491 AUTHENTICATE -> LOGIN
2492 User failed authentication, but did not enter a password. Instead
2493 of displaying an error message, redisplay the login screen with
2494 the focus set to the password field. If the user authenticates again
2495 without the password field set, display an error. This allows a user
2496 to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2499 Free state structure and return false to stop state transitions.
2501 ERRORMESSAGE -> LOGIN
2502 Display error message base on return code from last authentication
2503 attempt. Redisplay login screen with reset set to true.
2505 (state) -> LANG -> (state)
2506 User has chosen a new language. Transition to LANG state to save off
2507 the new language, and transition back to original state.
2509 *****************************************************************************/
2511 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2514 ManageGreeter( struct display *d, struct greet_info *greet,
2515 struct verify_info *verify, struct greet_state *state )
2522 if (state->waitForResponse)
2524 if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2527 * Dtgreet has terminated.
2529 state->id = GREET_STATE_EXIT;
2530 state->waitForResponse = FALSE;
2534 if (state->request->opcode != state->response->opcode)
2537 * An unrequested event arrived. See if it's one we
2540 switch(state->response->opcode)
2542 case REQUEST_OP_LANG:
2545 * User has changed language. Recursively handle this state
2546 * and return to current state.
2548 struct greet_state lang_state;
2550 lang_state = *state;
2551 lang_state.id = GREET_STATE_LANG;
2552 lang_state.waitForResponse = FALSE;
2553 ManageGreeter(d, greet, verify, &lang_state);
2554 Debug("Response opcode REQUEST_OP_LANG\n");
2559 case REQUEST_OP_CLEAR:
2562 * User has requested the screen be cleared.
2564 state->id = GREET_STATE_USERNAME;
2565 state->waitForResponse = TRUE;
2566 Debug("Response opcode REQUEST_OP_CLEAR\n");
2571 Debug("Response opcode UNEXPECTED RESPONSE!\n");
2581 * Got the response we were expecting.
2583 state->waitForResponse = FALSE;
2589 case GREET_STATE_ENTER:
2592 * Enter - initialize state
2594 Debug("GREET_STATE_ENTER\n");
2596 state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2597 state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2598 state->authenticated = FALSE;
2601 state->id = GREET_STATE_USERNAME;
2605 case GREET_STATE_USERNAME:
2610 RequestChallenge *r;
2612 Debug("GREET_STATE_USERNAME\n");
2614 Authenticate(d, NULL, NULL, NULL);
2616 SETMC(msg, LOGIN_LABEL);
2618 r = (RequestChallenge *)state->request;
2619 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2620 r->hdr.reserved = 0;
2623 r->hdr.length = sizeof(*r);
2625 r->offChallenge = sizeof(*r);
2626 strcpy(((char *)r) + r->offChallenge, msg.def);
2627 r->hdr.length += strlen(msg.def) + 1;
2631 r->offUserNameSeed = r->hdr.length;
2632 strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2633 r->hdr.length += strlen(greet->name) + 1;
2634 Debug("Greet name: %s\n", greet->name);
2638 r->offUserNameSeed = 0;
2643 free(greet->name); greet->name = NULL;
2645 if (greet->password)
2647 free(greet->password); greet->password = NULL;
2650 TellGreeter((RequestHeader *)r);
2651 state->waitForResponse = TRUE;
2653 state->id = GREET_STATE_AUTHENTICATE;
2657 case GREET_STATE_CHALLENGE:
2662 RequestChallenge *r;
2664 Debug("GREET_STATE_CHALLENGE\n");
2666 if (greet->password)
2668 free(greet->password); greet->password = NULL;
2671 SETMC(msg, PASSWD_LABEL);
2673 r = (RequestChallenge *)state->request;
2674 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2675 r->hdr.reserved = 0;
2678 r->offUserNameSeed = 0;
2679 r->offChallenge = sizeof(*r);
2680 strcpy(((char *)r) + r->offChallenge, msg.def);
2681 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2683 TellGreeter((RequestHeader *)r);
2684 state->waitForResponse = TRUE;
2686 state->id = GREET_STATE_AUTHENTICATE;
2690 case GREET_STATE_AUTHENTICATE:
2693 * Attempt to authenticate.
2695 ResponseChallenge *r;
2697 Debug("GREET_STATE_AUTHENTICATE\n");
2699 r = (ResponseChallenge *)state->response;
2701 if (greet->name == NULL)
2703 greet->name = strdup(((char *)r) + r->offResponse);
2704 if (strlen(greet->name) == 0)
2706 state->id = GREET_STATE_USERNAME;
2712 greet->password = strdup(((char *)r) + r->offResponse);
2722 * Attempt to authenticate user. 'username' should be a
2723 * non-empty string. 'password' may be an empty string.
2725 state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2727 if (state->vf == VF_OK ||
2728 state->vf == VF_PASSWD_AGED ||
2729 state->vf == VF_BAD_HOSTNAME)
2731 state->authenticated = TRUE;
2735 * General transitions.
2739 case VF_OK: state->id = GREET_STATE_TERMINATEGREET; break;
2740 case VF_PASSWD_AGED: state->id = GREET_STATE_EXPASSWORD; break;
2741 case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break;
2742 case VF_CHALLENGE: state->id = GREET_STATE_CHALLENGE; break;
2743 default: state->id = GREET_STATE_ERRORMESSAGE; break;
2748 case GREET_STATE_EXIT:
2751 * Free resources and leave.
2753 Debug("GREET_STATE_EXIT\n");
2760 if (!state->authenticated)
2764 free(greet->name); greet->name = NULL;
2766 if (greet->password)
2768 free(greet->password); greet->password = NULL;
2772 free(state->request);
2773 free(state->response);
2778 case GREET_STATE_ERRORMESSAGE:
2781 * Display error message.
2785 Debug("GREET_STATE_ERRORMESSAGE\n");
2787 r = (RequestMessage *)state->request;
2791 case VF_INVALID: SETMC(msg, LOGIN); break;
2792 case VF_HOME: SETMC(msg, HOME); break;
2793 case VF_MAX_USERS: SETMC(msg, MAX_USERS); break;
2794 case VF_BAD_UID: SETMC(msg, BAD_UID); break;
2795 case VF_BAD_GID: SETMC(msg, BAD_GID); break;
2796 case VF_BAD_AID: SETMC(msg, BAD_AID); break;
2797 case VF_BAD_AFLAG: SETMC(msg, BAD_AFLAG); break;
2798 case VF_NO_LOGIN: SETMC(msg, NO_LOGIN); break;
2800 case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2802 case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2803 default: msg.id=0; msg.def=""; break;
2806 r->hdr.opcode = REQUEST_OP_MESSAGE;
2807 r->hdr.reserved = 0;
2809 r->offMessage = sizeof(*r);
2810 strcpy(((char *)r) + r->offMessage, msg.def);
2811 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2813 TellGreeter((RequestHeader *)r);
2814 state->waitForResponse = TRUE;
2816 state->id = GREET_STATE_USERNAME;
2820 case GREET_STATE_LANG:
2823 * User selected new language.
2829 Debug("GREET_STATE_LANG\n");
2831 r = (ResponseLang *)state->response;
2832 lang = ((char *)r) + r->offLang;
2833 len = strlen(lang) + 1;
2835 d->language = (d->language == NULL ?
2836 malloc(len) : realloc(d->language, len));
2837 strcpy(d->language, lang);
2838 Debug("Language returned: %s\n", d->language);
2842 case GREET_STATE_TERMINATEGREET:
2845 * Terminate dtgreet.
2849 Debug("GREET_STATE_TERMINATEGREET\n");
2851 r = (RequestExit *)state->request;
2853 r->hdr.opcode = REQUEST_OP_EXIT;
2854 r->hdr.reserved = 0;
2855 r->hdr.length = sizeof(*r);
2857 TellGreeter((RequestHeader *)r);
2858 state->waitForResponse = TRUE;
2860 state->id = GREET_STATE_EXIT;
2864 case GREET_STATE_EXPASSWORD:
2867 * Display password expired message.
2869 RequestExpassword *r;
2871 Debug("GREET_STATE_EXPASSWORD\n");
2873 r = (RequestExpassword *)state->request;
2875 r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2876 r->hdr.reserved = 0;
2877 r->hdr.length = sizeof(*r);
2879 TellGreeter((RequestHeader *)r);
2880 state->waitForResponse = TRUE;
2882 state->id = GREET_STATE_USERNAME;
2886 case GREET_STATE_BAD_HOSTNAME:
2889 * Display password expired message.
2893 Debug("GREET_STATE_BAD_HOSTNAME\n");
2895 r = (RequestHostname *)state->request;
2897 r->hdr.opcode = REQUEST_OP_HOSTNAME;
2898 r->hdr.reserved = 0;
2899 r->hdr.length = sizeof(*r);
2901 TellGreeter((RequestHeader *)r);
2902 state->waitForResponse = TRUE;
2904 state->id = GREET_STATE_USERNAME;
2909 case GREET_STATE_FORM:
2912 * Get arbitrary number of answers.
2915 Debug("GREET_STATE_FORM\n");
2917 AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2919 state->waitForResponse = FALSE;
2920 state->id = GREET_STATE_USERNAME;
2932 RequestHeader *phdr)
2934 write(request[1], phdr, phdr->length);
2939 RequestHeader *preqhdr,
2945 ResponseHeader *phdr = (ResponseHeader *)buf;
2947 if (preqhdr) TellGreeter(preqhdr);
2949 phdr->opcode = REQUEST_OP_NONE;
2951 count = read(response[0], buf, sizeof(*phdr));
2953 if (count == sizeof(*phdr))
2956 * Calculate amount of data after header.
2958 remainder = phdr->length - sizeof(*phdr);
2962 * Read remainder of response.
2964 count += read(response[0], buf+sizeof(*phdr), remainder);
2969 if (debugLevel) PrintResponse(phdr, count);
2978 ResponseHeader *phdr,
2981 char *opstr = "UNKNOWN";
2985 Debug("opcode = (EOF)\n");
2989 switch(phdr->opcode)
2991 case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2992 case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2993 case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2994 case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2995 case REQUEST_OP_LANG: opstr = "LANG"; break;
2996 case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
2999 Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
3000 Debug(" reserved = %d\n", phdr->reserved);
3001 Debug(" length = %d\n", phdr->length);
3003 switch(phdr->opcode)
3005 case REQUEST_OP_EXIT: break;
3006 case REQUEST_OP_LANG:
3007 Debug(" offLang=%d\n", ((ResponseLang *)phdr)->offLang);
3008 Debug(" lang='%s'\n",
3009 ((char *)phdr)+((ResponseLang *)phdr)->offLang);
3011 case REQUEST_OP_MESSAGE: break;
3012 case REQUEST_OP_CHPASS: break;
3013 case REQUEST_OP_CHALLENGE:
3014 Debug(" offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
3015 Debug(" response='%s'\n",
3016 ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
3018 case REQUEST_OP_DEBUG:
3019 Debug(" offString=%d\n", ((ResponseDebug *)phdr)->offString);
3020 Debug(" string='%s'\n",
3021 ((char *)phdr)+((ResponseDebug *)phdr)->offString);
3029 /***************************************************************************
3033 * generate kerberos ticket file name. Name is returned in the static
3034 * global variable "krb_ticket_string".
3036 ***************************************************************************/
3039 SetTicketFileName(uid_t uid)
3048 * generate ticket file pathname (/tmp/tkt<uid>.<host>) ...
3051 if (env = (char *)getenv("KRBTKFILE")) {
3052 (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3053 krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3056 if (gethostname(lhost, sizeof(lhost)) != -1) {
3057 if (p = index(lhost, '.')) *p = '\0';
3058 (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3060 /* 32 bits of signed integer will always fit in 11 characters
3061 (including the sign), so no need to worry about overflow */
3062 (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3067 #endif /* __KERBEROS */
3069 #if defined (_AIX) && !defined (_POWER)
3071 /***************************************************************************
3075 * If this is an authenticated process (LOGNAME set), set user's
3076 * process environment by calling setpenv().
3078 * If this is not an authenticated process, just call execve()
3080 ***************************************************************************/
3089 char *user = getEnv (envp, "LOGNAME");
3093 rc = execve(path, argv, envp);
3097 char *usrTag, *sysTag;
3100 * Save pointers to tags. The setpenv() function clears the pointers
3101 * to the tags in userEnviron as a side-effect.
3103 sysTag = envp[SYS_ENV_TAG];
3104 usrTag = envp[USR_ENV_TAG];
3107 * Set the users process environment. This call execs arvg so it
3108 * should not return. It it should return, restore the envp tags.
3110 rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3113 * Restore pointers to tags.
3115 envp[SYS_ENV_TAG] = sysTag;
3116 envp[USR_ENV_TAG] = usrTag;
3121 #endif /* _AIX && !_POWER */
3125 /* collect the SIA parameters from a window system. */
3127 static int SiaManageGreeter(
3130 unsigned char *title,
3136 RequestMessage greeter_message;
3137 char msg_buffer[256];
3138 } greeter_msg_and_buffer;
3139 RequestForm *request_form;
3147 if (rendition == SIAFORM && dt_in_sia_ses_authent
3148 && (num_prompts == 2))
3150 /* Normal login, Password case */
3151 Debug ("SIAFORM Normal login, Password case\n");
3152 while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3153 && siaGreeterInfo.state->id != GREET_STATE_EXIT
3154 && (siaGreeterInfo.status = ManageGreeter(
3155 siaGreeterInfo.d, siaGreeterInfo.greet,
3156 siaGreeterInfo.verify, siaGreeterInfo.state)))
3159 if (!siaGreeterInfo.status
3160 || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3161 return(SIACOLABORT);
3163 strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name,
3164 prompt[0].max_result_length);
3165 strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3166 prompt[1].max_result_length);
3173 ResponseForm *response_form;
3178 Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3181 Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3184 Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3187 Debug("SIAFORM num_prompts = %d\n", num_prompts);
3191 /* need to display form */
3193 req_form_size = sizeof(RequestForm)
3194 + strlen((const char *)title) + 1;
3195 for (i=0; i<num_prompts; i++)
3196 req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3197 request_form = (RequestForm *) alloca(req_form_size);
3199 siaGreeterInfo.state->id = GREET_STATE_FORM;
3200 siaGreeterInfo.state->request = (RequestHeader *)request_form;
3201 /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3203 request_form->hdr.opcode = REQUEST_OP_FORM;
3204 request_form->hdr.reserved = 0;
3205 request_form->hdr.length = req_form_size;
3206 request_form->num_prompts = num_prompts;
3207 request_form->rendition = rendition;
3208 request_form->offTitle = sizeof(RequestForm);
3209 request_form->offPrompts = sizeof(RequestForm) +
3210 strlen((const char *)title) + 1;
3211 strcpy((char *)request_form + request_form->offTitle,
3212 (const char *)title);
3214 pmpt_ptr = (char *)request_form + request_form->offPrompts;
3215 for (i=0; i<num_prompts; i++)
3217 if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3221 Debug(" prompt[%d]: %s\n", i, prompt[i].prompt);
3222 strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3223 pmpt_ptr += strlen((const char *)prompt[i].prompt);
3225 request_form->visible[i] =
3226 (prompt[i].control_flags & SIARESINVIS) ? False : True;
3229 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3230 siaGreeterInfo.greet,
3231 siaGreeterInfo.verify,
3232 siaGreeterInfo.state);
3234 response_form = (ResponseForm *)siaGreeterInfo.state->response;
3235 res_ptr = (char *)response_form + response_form->offAnswers;
3236 for (i = 0; i < response_form->num_answers; i++)
3238 if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3241 prompt[i].result = (unsigned char *)1;
3243 prompt[i].result = NULL;
3247 strcpy((char *)prompt[0].result, res_ptr);
3249 res_ptr += strlen(res_ptr) + 1;
3251 if (!response_form->collect_status)
3252 siaGreeterInfo.status = FALSE;
3258 Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3260 siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3261 siaGreeterInfo.state->request = (RequestHeader *)
3262 &greeter_msg_and_buffer.greeter_message;
3263 siaGreeterInfo.state->vf = VF_MESSAGE;
3264 siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3266 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3267 siaGreeterInfo.greet,
3268 siaGreeterInfo.verify,
3269 siaGreeterInfo.state);
3272 return(SIACOLABORT);
3275 if (!siaGreeterInfo.status)
3276 return(SIACOLABORT);
3277 return(SIACOLSUCCESS);
3280 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3283 greet->name = malloc(strlen(siaHandle->name) + 1);
3284 strcpy (greet->name, siaHandle->name);
3286 greet->password = malloc(strlen(siaHandle->password) + 1);
3287 strcpy (greet->password, siaHandle->password);
3292 static void KillGreeter( void )
3294 if (sia_greeter_pid)
3295 AbortClient(sia_greeter_pid);
3296 sia_greeter_pid = 0;