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
67 # include <X11/Xatom.h>
69 #if defined(__FreeBSD__) && OSMAJORVERSION > 8
82 #include <X11/Intrinsic.h>
85 # include <X11/Xresource.h>
96 # include <sys/security.h>
102 #endif /* __KERBEROS */
105 #include "rgy_base.h"
110 static SIAENTITY *siaHandle = NULL;
111 static Boolean dt_in_sia_ses_authent = False;
113 static struct sia_greeter_info {
115 struct greet_info *greet;
116 struct verify_info *verify;
117 struct greet_state *state;
121 static int SiaManageGreeter(
124 unsigned char *title,
128 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet);
130 static void KillGreeter( void );
132 static int sia_greeter_pid;
133 static int sia_exit_proc_reg = FALSE;
139 extern char *getenv();
142 #define GREET_STATE_LOGIN 0
143 #define GREET_STATE_AUTHENTICATE 1
144 #define GREET_STATE_EXIT 2
145 #define GREET_STATE_EXPASSWORD 3
146 #define GREET_STATE_ERRORMESSAGE 4
147 #define GREET_STATE_LANG 5
148 #define GREET_STATE_BAD_HOSTNAME 6
149 #define GREET_STATE_ENTER 7
150 #define GREET_STATE_TERMINATEGREET 8
151 #define GREET_STATE_USERNAME 9
152 #define GREET_STATE_CHALLENGE 10
153 #define GREET_STATE_FORM 11
156 #define DEF_SESSION CDE_INSTALLATION_TOP "/bin/Xsession"
164 int waitForResponse; /* TRUE=wait for response from dtgreet */
165 RequestHeader *request; /* request buffer */
166 ResponseHeader *response; /* response buffer */
167 int authenticated; /* TRUE=user is authenticated */
168 int vf; /* last return code from Authenticate() */
169 int loginReset; /* reset flag for LOGIN state */
170 char *msg; /* message for VF_MESSAGE */
173 char *globalDisplayName;
175 /***************************************************************************
177 * Local procedure declarations
179 ***************************************************************************/
181 static int AbortClient( int pid) ;
182 static void DeleteXloginResources( struct display *d, Display *dpy) ;
183 int LoadXloginResources( struct display *d) ;
184 static int ErrorHandler( Display *dpy, XErrorEvent *event) ;
185 static int IOErrorHandler( Display *dpy) ;
186 static int ManageGreeter( struct display *d, struct greet_info *greet,
187 struct verify_info *verify, struct greet_state *state) ;
188 static void RunGreeter( struct display *d, struct greet_info *greet,
189 struct verify_info *verify) ;
190 static void SessionExit( struct display *d, int status) ;
191 static void SessionPingFailed( struct display *d) ;
192 static int StartClient(struct verify_info *verify, struct display *d,
194 static SIGVAL catchAlrm( int arg ) ;
195 static SIGVAL catchHUP( int arg ) ;
196 static SIGVAL catchTerm( int arg ) ;
197 static SIGVAL waitAbort( int arg ) ;
198 static void SetupDisplay(struct display *d);
200 static void TellGreeter(RequestHeader *phdr);
201 static int AskGreeter(RequestHeader *preqhdr, char *b, int blen);
203 static void PrintResponse(ResponseHeader *phdr, int count);
206 #if defined (_AIX) && defined (_POWER)
207 static void release_aix_lic(void);
210 #if defined (_AIX) && !defined (_POWER)
211 static int session_execve(char *path, char *argv[], char *envp[]);
213 #define session_execve(A,B,C) execve(A,B,C)
217 static void SetTicketFileName(uid_t uid);
218 # endif /* __KERBEROS */
220 static void LoadAltDtsResources( struct display *d);
221 char * _ExpandLang(char *string, char *lang);
225 /***************************************************************************
229 ***************************************************************************/
231 static int clientPid;
232 static struct greet_info greet;
233 static struct verify_info verify;
234 static char *defaultLanguage = NULL;
236 static jmp_buf abortSession;
239 static char *sensitivityLevel;
243 static char krb_ticket_string[MAXPATHLEN];
244 #endif /* __KERBEROS */
247 XrmDatabase XresourceDB;
254 longjmp (abortSession, 1);
257 static jmp_buf pingTime;
262 longjmp (pingTime, 1);
266 FileNameCompare (a, b)
267 #if defined(__STDC__)
273 return strcoll (*(char **)a, *(char **)b);
277 SessionPingFailed( struct display *d )
281 AbortClient (clientPid);
282 source (&verify, d->reset);
284 #if defined (PAM) || defined(SUNAUTH)
286 char* user = getEnv (verify.userEnviron, "USER");
287 char* ttyLine = d->gettyLine;
289 #ifdef DEF_NETWORK_DEV
291 * If location is not local (remote XDMCP dtlogin) and
292 * remote accouting is enabled (networkDev start with /dev/...)
293 * Set tty line name to match network device for accouting.
294 * Unless the resource was specifically set, default is value
295 * of DEF_NETWORK_DEV define (/dev/dtremote)
298 if ( d->displayType.location != Local &&
299 networkDev && !strncmp(networkDev,"/dev/",5)) {
300 ttyLine = networkDev+5;
305 PamAccounting( verify.argv[0], d->name, d->utmpId, user,
306 ttyLine, clientPid, ACCOUNTING, NULL);
308 solaris_accounting( verify.argv[0], d->name, d->utmpId, user,
309 ttyLine, clientPid, ACCOUNTING, NULL);
313 solaris_resetdevperm(ttyLine);
319 SessionExit (d, RESERVER_DISPLAY);
324 * We need our own error handlers because we can't be sure what exit code Xlib
325 * will use, and our Xlib does exit(1) which matches REMANAGE_DISPLAY, which
326 * can cause a race condition leaving the display wedged. We need to use
327 * RESERVER_DISPLAY for IO errors, to ensure that the manager waits for the
328 * server to terminate. For other X errors, we should give up.
332 IOErrorHandler( Display *dpy )
335 const char *s = strerror(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 )
649 char *resources = NULL;
653 if (d->resources && d->resources[0]) {
654 resources = _ExpandLang(d->resources, d->language);
655 if (access (resources, R_OK) != 0) {
656 /** fallback to the C locale for resources **/
657 Debug("LoadXloginResources - cant access %s\n", resources);
658 Debug("\t %s. Falling back to C.\n", strerror(errno));
660 resources = _ExpandLang(d->resources, "C");
661 if (access (resources, R_OK) != 0) {
662 /** can't find a resource file, so bail **/
663 Debug("LoadXloginResources - cant access %s.\n", resources);
664 Debug("\t %s. Unable to find resource file.\n",
671 if (d->authFile && strlen(d->authFile) > 0 ) {
672 authority = d->authFile;
673 auth_key = "XAUTHORITY=";
676 Debug("LoadXloginResources - loading resource db from %s\n", resources);
677 if((XresourceDB = XrmGetFileDatabase(resources)) == NULL)
678 Debug("LoadXloginResources - Loading resource db from %s failed\n",
681 LoadAltDtsResources(d);
683 strcpy(tmpname,"/var/dt/dtlogin_XXXXXX");
684 (void) mktemp(tmpname);
686 XrmPutFileDatabase(XresourceDB, tmpname);
688 sprintf (cmd, "%s%s %s -display %s -load %s",
689 auth_key, authority, d->xrdb, d->name, tmpname);
690 Debug ("Loading resource file: %s\n", cmd);
692 if(-1 == system (cmd)) {
693 Debug ("system() failed on cmd '%s'\n", cmd);
697 if (debugLevel <= 10)
698 if (unlink (tmpname) == -1)
699 Debug ("unlink() on %s failed\n", tmpname);
702 if (resources) free (resources);
707 /***************************************************************************
709 * LoadAltDtsResources
712 * set up alternate desktop resources..
714 ***************************************************************************/
717 LoadAltDtsResources(struct display *d)
721 char dirname[2][MAXPATHLEN];
722 char res_file[MAXPATHLEN];
723 char *rmtype; /* for XrmGetResource() */
724 XrmValue rmvalue; /* for XrmGetResource() */
725 char buf[MAXPATHLEN];
726 char tempbuf[MAXPATHLEN];
729 char altdtres[MAXPATHLEN];
730 char Altdtres[MAXPATHLEN];
733 char *resources = NULL;
735 int num_allocated = 0;
736 char **file_list = NULL;
739 if ( XrmGetResource(XresourceDB,
740 "Dtlogin*altDts", "Dtlogin*AltDts",
741 &rmtype, &rmvalue ) ) {
742 strcpy(tempbuf,rmvalue.addr);
746 strcpy(dirname[0],CDE_INSTALLATION_TOP "/config/%L/Xresources.d/");
747 strcpy(dirname[1],CDE_CONFIGURATION_TOP "/config/%L/Xresources.d/");
749 for(j = 0; j < 2 ; ++j)
751 resources = _ExpandLang(dirname[j], d->language);
752 if (access (resources, R_OK) != 0)
754 Debug("LoadAltDtsResources- cant access %s.\n", resources);
755 Debug("\t %s. Falling back to C.\n", strerror(errno));
763 resources = _ExpandLang(dirname[j], "C");
764 if (access (resources, R_OK) != 0)
766 Debug("LoadAltDtsResources- cant access %s.\n", resources);
767 Debug("\t %s.\n", strerror(errno));
770 strcpy(dirname[j], resources);
773 strcpy(dirname[j],resources);
774 Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
786 * Create a list of the alt DT files
788 * NOTE - an assumption made here is that files in /etc/dt
789 * should take precedence over files in /usr/dt. This precedence
790 * is maintained during the sort becase /etc/dt will come before
794 for(j = 0; j < 2 ; ++j) {
796 if((dirp = opendir(dirname[j])) != NULL) {
798 while((dp = readdir(dirp)) != NULL) {
800 if ((strcmp(dp->d_name, DOT) != 0) &&
801 (strcmp(dp->d_name, DOTDOT) != 0)) {
803 sprintf (res_file, "%s%s", dirname[j],dp->d_name);
804 if ((access (res_file, R_OK)) != 0)
806 Debug("LoadAltDtsResources- cant access %s.\n",
808 Debug("\t %s.\n", strerror(errno));
812 if (file_count == 0) {
813 file_list = malloc (list_incr * sizeof(char **));
814 num_allocated += list_incr;
816 if (file_count + 1 > num_allocated) {
817 num_allocated += list_incr;
818 file_list = realloc (file_list,
819 num_allocated * sizeof(char **));
821 file_list[file_count] = strdup (res_file);
830 qsort (file_list, file_count, sizeof (char *), FileNameCompare);
832 for (j = 0; j < file_count ; j++) {
834 userDb = XrmGetFileDatabase(file_list[j]);
835 XrmMergeDatabases(userDb,&XresourceDB);
837 if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
838 "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
841 * remove the trailing spaces
843 if(strchr(rmvalue.addr,' '))
844 strcpy(tempbuf, strtok(rmvalue.addr," "));
846 strcpy(tempbuf, rmvalue.addr);
848 if ((strcmp(tempbuf, "True") == 0) ||
849 (strcmp(tempbuf, "TRUE") == 0)) {
851 if ( XrmGetResource(XresourceDB,
852 "Dtlogin*altDtKey", "Dtlogin*AltDtKey",
853 &rmtype, &rmvalue ) ) {
855 sprintf(altdtres,"Dtlogin*altDtKey%d",i);
856 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
861 if ( XrmGetResource(XresourceDB,
862 "Dtlogin*altDtName", "Dtlogin*AltDtName",
863 &rmtype, &rmvalue ) ) {
864 sprintf(altdtres,"Dtlogin*altDtName%d",i);
865 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
867 if ( XrmGetResource(XresourceDB,
868 "Dtlogin*altDtStart", "Dtlogin*AltDtStart",
869 &rmtype, &rmvalue ) ) {
870 sprintf(altdtres,"Dtlogin*altDtStart%d",i);
871 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
873 if ( XrmGetResource(XresourceDB,
874 "Dtlogin*altDtLogo", "Dtlogin*AltDtLogo",
875 &rmtype, &rmvalue ) ) {
876 sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
877 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
883 sprintf(tempbuf,"%d",i);
884 XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf);
886 if (file_count > 0) {
887 for (i = 0; i < file_count; i++) {
888 Debug ("Loading resource file: %s\n", file_list[i]);
898 * Function Name: _ExpandLang
902 * This function takes the string "string", searches for occurences of
903 * "%L" in the string and if found, the "%L" is substituted with
904 * the value of the $LANG environment variable.
906 * If $LANG is not defined, the %L is replace with NULL.
910 * _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
914 * ret_string = _ExpandLang (string);
916 * char *ret_string; Returns NULL if "string" is NULL or it points
917 * to the expanded string.
919 * char *string; The first part of the pathname. Typically
920 * the directory containing the item of interest.
922 * Note: The caller is responsible for free'ing the returned string.
944 * Count the number of expansions that will occur.
948 for (n = 0, pch = string ; pch != NULL ; ) {
949 if ((pch = strchr (pch, '%')) != NULL) {
956 return (strdup(string));
959 * We should really be calling setlocale to determine the "default"
960 * locale but setlocale's return value is not standardized across
961 * the various vendor platforms nor is it consistent within differnt
962 * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
963 * HP-UX 10.0). The "right" call would be the following line:
965 * if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
967 * Here we hard code the default to "C" instead of leaving it NULL.
969 if (lang || (lang = getenv ("LANG")) || (lang = "C"))
970 lang_len = strlen (lang);
973 * Create the space needed.
975 tmp_len = strlen (string) + (n * lang_len) + n + 1;
976 tmp = (char *) malloc (tmp_len);
977 for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
981 while (pch != NULL) {
984 if ((pch = strchr (pch, '%')) != NULL) {
989 (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
991 else if ((pch != NULL) && *pch == 'L') {
993 if (((pch - trail) >=2) && (*(pch-2) == '/'))
995 * Remove the "/" as well as the "%L".
997 (void) strncat (tmp, trail, (pch - trail) - 2);
999 (void) strncat (tmp, trail, (pch - trail) - 1);
1003 * Remove the "%L" and then append the LANG.
1005 (void) strncat (tmp, trail, (pch - trail) - 1);
1006 (void) strcat (tmp, lang);
1010 (void) strncat (tmp, trail, (pch - trail) + 1);
1017 * A '%' was not found.
1019 (void) strcat (tmp, trail);
1028 SetupDisplay (struct display *d)
1030 char **env = 0, **crt_systemEnviron;
1032 if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1034 crt_systemEnviron = verify.systemEnviron;
1035 env = systemEnv (d, (char *) 0, (char *) 0);
1036 if (d->authFile && strlen(d->authFile) > 0 )
1037 env = setEnv( env, "XAUTHORITY", d->authFile );
1038 if(d->displayType.location == Local)
1039 env = setEnv (env, LOCATION, "local");
1041 env = setEnv (env, LOCATION, "remote");
1042 verify.systemEnviron = env;
1043 source (&verify, d->setup);
1044 verify.systemEnviron = crt_systemEnviron;
1051 DeleteXloginResources( struct display *d, Display *dpy )
1053 XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1056 #if 0 /* dead code: transferred to Dtgreet */
1058 static jmp_buf syncJump;
1063 longjmp (syncJump, 1);
1067 SecureDisplay (d, dpy)
1071 Debug ("SecureDisplay():\n");
1072 signal (SIGALRM, syncTimeout);
1073 if (setjmp (syncJump)) {
1074 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1076 SessionExit (d, RESERVER_DISPLAY);
1078 alarm ((unsigned) d->grabTimeout);
1079 Debug ("Before XGrabServer()\n");
1081 if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1082 GrabModeAsync, CurrentTime) != GrabSuccess)
1085 signal (SIGALRM, SIG_DFL);
1086 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1088 SessionExit (d, RESERVER_DISPLAY);
1090 Debug ("XGrabKeyboard() succeeded\n");
1092 signal (SIGALRM, SIG_DFL);
1096 XUngrabServer (dpy);
1099 Debug ("Done secure %s\n", d->name);
1102 UnsecureDisplay (d, dpy)
1106 Debug ("Unsecure display %s\n", d->name);
1108 XUngrabServer (dpy);
1117 release_aix_lic(void)
1120 * Release AIX iFOR/LS license (if any)
1128 release_me.request_type = -1;
1129 release_me.login_pid = getpid();
1130 if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1132 write(fd, &release_me, sizeof(release_me));
1135 Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1143 SessionExit( struct display *d, int status )
1152 /* make sure the server gets reset after the session is over */
1153 if (d->serverPid >= 2) {
1154 Debug("Reseting server: pid %d signal %d\n",
1155 d->serverPid, d->resetSignal);
1157 if (d->terminateServer == 0 && d->resetSignal)
1158 kill (d->serverPid, d->resetSignal);
1163 Debug("Exiting Session with status: %d\n", status);
1168 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1171 char currentdir[PATH_MAX+1];
1172 char *failsafeArgv[20];
1173 char *user; /* users name */
1174 char *lang, *font; /* failsafe LANG and font */
1177 int failsafe = FALSE; /* do we run the failsafe session? */
1178 int password = FALSE; /* do we run /bin/passwd? */
1181 char lastsessfile[MAXPATHLEN];
1184 struct pr_passwd *b1_pwd;
1188 #define NOPAG 0xffffffff
1190 long ngroups, groups[NGROUPS];
1196 Debug ("StartSession %s: ", verify->argv[0]);
1197 for (f = verify->argv; *f; f++) {
1199 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1200 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1204 if (verify->userEnviron) {
1205 for (f = verify->userEnviron; *f; f++)
1210 user = getEnv (verify->userEnviron, "USER");
1212 switch (pid = fork ()) {
1215 /* Force a failsafe session if we can't touch the home directory
1216 * SIA has already attempted to chdir to HOME, and the current dir
1217 * will be set to / if it failed. We just check to see if the HOME
1218 * path is our current directory or not.
1220 home = getEnv (verify->userEnviron, "HOME");
1221 getcwd(currentdir, PATH_MAX+1);
1222 Debug("Current directory is: %s\n", currentdir);
1226 * The following little check doesn't really work. For example,
1227 * here at the XC, NIS reports my home directory as
1228 * "/site/guests/montyb" while getcwd comes up with
1229 * "/net/nexus/site/guests/montyb".
1231 if (strcmp(home, currentdir)) {
1232 Debug("Can't access home directory, setting failsafe to TRUE\n");
1234 LogError (ReadCatalog(
1235 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1236 home, getEnv (verify->userEnviron, "USER"));
1237 verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1245 * do process accounting...
1247 #if defined(PAM) || defined(SUNAUTH)
1249 char* ttyLine = d->gettyLine;
1251 # ifdef DEF_NETWORK_DEV
1253 * If location is not local (remote XDMCP dtlogin) and
1254 * remote accouting is enabled (networkDev start with /dev/...)
1255 * Set tty line name to match network device for accouting.
1256 * Unless the resource was specifically set, default is value
1257 * of DEF_NETWORK_DEV define (/dev/dtremote)
1260 if ( d->displayType.location != Local &&
1261 networkDev && !strncmp(networkDev,"/dev/",5)) {
1262 ttyLine = networkDev+5;
1267 PamAccounting(verify->argv[0], d->name, d->utmpId, user,
1268 ttyLine, getpid(), USER_PROCESS, NULL);
1270 solaris_accounting(verify->argv[0], d->name, d->utmpId, user,
1271 ttyLine, getpid(), USER_PROCESS, NULL);
1276 #if !defined(sun) && !defined(CSRG_BASED)
1277 Account(d, user, NULL, getpid(), USER_PROCESS, status);
1282 * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1283 * setpenv() to set up the user's process environment and return
1284 * without execing. This allows us to set up the process environment
1285 * and proceed to the execute() call as do the other platforms.
1287 * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1288 * we have to pospone the setpenv() to the actual execute().
1292 * These defines are the tag locations in userEnviron.
1293 * IMPORTANT: changes to the locations of these tags in verify.c
1294 * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1296 #define SYS_ENV_TAG 0
1297 #define USR_ENV_TAG 3
1300 * Set the user's credentials: uid, gid, groups,
1301 * audit classes, user limits, and umask.
1304 if (setpcred(user, NULL) == -1)
1306 Debug("Can't set User's Credentials (user=%s)\n",user);
1311 char *usrTag, *sysTag;
1312 extern char **newenv;
1315 * Save pointers to tags. The setpenv() function clears the pointers
1316 * to the tags in userEnviron as a side-effect.
1318 sysTag = verify->userEnviron[SYS_ENV_TAG];
1319 usrTag = verify->userEnviron[USR_ENV_TAG];
1322 * Set the users process environment. Store protected variables and
1323 * obtain updated user environment list. This call will initialize
1326 #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1327 if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1329 Debug("Can't set process environment (user=%s)\n",user);
1334 * Restore pointers to tags.
1336 verify->userEnviron[SYS_ENV_TAG] = sysTag;
1337 verify->userEnviron[USR_ENV_TAG] = usrTag;
1340 * Free old userEnviron and replace with newenv from setpenv().
1342 freeEnv(verify->userEnviron);
1343 verify->userEnviron = newenv;
1353 if (PamSetCred( verify->argv[0],
1354 user, verify->uid, verify->gid) > 0 ) {
1355 Debug("Can't set User's Credentials (user=%s)\n",user);
1361 if ( solaris_setcred(verify->argv[0],
1362 user, verify->uid, verify->gid) > 0 ) {
1363 Debug("Can't set User's Credentials (user=%s)\n",user);
1366 #endif /* SUNAUTH */
1373 * HP BLS B1 session setup...
1375 * 1. look up user's protected account information.
1376 * 2. set the session sensitivity/clearance levels
1377 * 3. set the logical UID (LUID)
1381 Debug("BLS - Setting user's clearance, security level and luid.\n");
1382 set_auth_parameters(1, verify->argv);
1385 verify->user_name = user;
1386 strncpy(verify->terminal,d->name,15);
1387 verify->terminal[15]='\0';
1388 verify->pwd = getpwnam(user);
1390 if ( verify->pwd == NULL || strlen(user) == 0 ) {
1391 LogError(ReadCatalog(
1392 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1395 verify->prpwd= b1_pwd = getprpwnam(user);
1396 verify->uid = b1_pwd->ufld.fd_uid;
1398 if ( b1_pwd == NULL || strlen(user) == 0 ) {
1399 LogError(ReadCatalog(
1400 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1405 * This has already been done successfully by dtgreet
1406 * but we need to get all the information again for the
1409 if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1410 Debug("BLS - Could not verify sensitivity level.\n");
1411 LogError(ReadCatalog(
1412 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1416 if ( change_to_user(verify) != 1 ) {
1417 Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1418 LogError(ReadCatalog(
1419 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1424 Debug("BLS - Session setup complete.\n");
1431 * This should never fail since everything has been verified already.
1432 * If it does it must mean registry strangeness, so exit, and try
1436 if (!DoLogin (user, greet.password, d->name)) exit (1);
1439 * extract the SYSTYPE and ISP environment values and set into user's
1440 * environment. This is necessary since we do an execve below...
1443 verify->userEnviron = setEnv(verify->userEnviron, "SYSTYPE",
1446 verify->userEnviron = setEnv(verify->userEnviron, "ISP",
1449 #else /* ! __apollo */
1453 if ( IsVerifyName(VN_AFS) ) {
1454 pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1455 Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1457 initgroups(greet.name, verify->groups[2]);
1458 ngroups = getgroups(NGROUPS, groups);
1459 Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1460 for (i=0; i < ngroups; i++)
1461 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1463 if ((pagval != NOPAG) &&
1464 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1465 /* we will have to shift grouplist to make room for pag */
1466 if (ngroups+2 > NGROUPS)
1468 for (j=ngroups-1; j >= 0; j--) {
1469 groups[j+2] = groups[j];
1472 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1473 if (setgroups(ngroups, groups) == -1) {
1476 MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1481 # else /* ! __AFS */
1482 /* If SIA is enabled, the initgroups and setgid calls are redundant
1489 * if your system does not support "initgroups(3C)", use
1490 * the "setgroups()" call instead...
1493 # if (defined(__hpux) || defined(__osf__))
1494 initgroups(user, -1);
1496 setgroups (verify->ngroups, verify->groups);
1499 /* setpenv() will set gid for AIX */
1501 if(-1 == setgid (verify->groups[0])) {
1502 perror(strerror(errno));
1506 # else /* ! NGROUPS */
1508 /* setpenv() will set gid for AIX */
1510 setgid (verify->gid);
1513 # endif /* NGROUPS */
1519 setaudid(verify->audid);
1520 setaudproc(verify->audflg);
1523 /* setpenv() will set uid for AIX */
1525 if (setuid(verify->uid) != 0) {
1526 Debug( "Setuid failed for user %s, errno = %d\n", user, errno);
1527 LogError(ReadCatalog(
1528 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1534 #endif /* __apollo */
1537 } /* ends the else clause of if ( ISSECURE ) */
1543 * check home directory again...
1547 /* Don't need to do this if SIA is enabled, already been done.
1549 home = getEnv (verify->userEnviron, "HOME");
1551 if (chdir (home) == -1) {
1552 LogError (ReadCatalog(
1553 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1554 home, getEnv (verify->userEnviron, "USER"));
1555 if(-1 == chdir ("/")) {
1556 perror(strerror(errno));
1558 verify->userEnviron = setEnv(verify->userEnviron,
1561 else if(!failsafe) {
1562 strcpy(lastsessfile,home); /* save user's last session */
1563 strcat(lastsessfile,LAST_SESSION_FILE);
1564 if((lastsession = fopen(lastsessfile,"w")) == NULL)
1565 Debug("Unable to open file for writing: %s\n",lastsessfile);
1567 fputs(verify->argv[0],lastsession);
1568 fclose(lastsession);
1575 SetUserAuthorization (d, verify);
1581 bzero(greet.password, strlen(greet.password));
1585 * Write login information to a file
1586 * The file name should really be settable by some kind of resource
1587 * but time is short so we hard-wire it to ".dtlogininfo".
1589 if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1590 Debug("Unable to write \".dtlogininfo\"\n");
1592 /* extra debugging */
1593 if(!dump_sec_debug_info(verify)) {
1594 Debug("Something wrong with environment\n");
1597 # endif /* ! NDEBUG */
1605 Debug ("Executing session %s\n", verify->argv[0]);
1606 execute (verify->argv, verify->userEnviron);
1607 LogError(ReadCatalog(
1608 MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1612 LogError(ReadCatalog(
1613 MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1620 * specify a font for the multi-byte languages...
1624 lang = getEnv (verify->userEnviron, "LANG");
1631 failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1633 failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1634 #elif defined (USL) || defined(__uxp__)
1635 failsafeArgv[i++] = "/usr/X/bin/xterm";
1636 #elif defined(__hpux)
1637 failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1638 #elif defined(__OpenBSD__)
1639 failsafeArgv[i++] = "/usr/X11R6/bin/xterm";
1640 #elif defined(__NetBSD__)
1641 failsafeArgv[i++] = "/usr/X11R7/bin/xterm";
1642 #elif defined(__FreeBSD__)
1643 failsafeArgv[i++] = "/usr/local/bin/xterm";
1645 failsafeArgv[i++] = "/usr/bin/X11/xterm";
1647 failsafeArgv[i++] = "-geometry";
1648 failsafeArgv[i++] = "80x10";
1649 failsafeArgv[i++] = "-bg";
1650 failsafeArgv[i++] = "white";
1651 failsafeArgv[i++] = "-fg";
1652 failsafeArgv[i++] = "black";
1654 /* aixterm requires -lang option. */
1655 failsafeArgv[i++] = "-lang";
1656 failsafeArgv[i++] = lang;
1658 failsafeArgv[i++] = "-fn";
1660 if (font == NULL) font = "fixed";
1661 failsafeArgv[i++] = font;
1664 failsafeArgv[i++] = "-e";
1665 failsafeArgv[i++] = "/bin/passwd";
1666 #if defined (__apollo) || defined(__PASSWD_ETC)
1667 failsafeArgv[i++] = "-n";
1669 failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1672 failsafeArgv[i++] = d->failsafeClient;
1674 failsafeArgv[i++] = "-C";
1676 failsafeArgv[i++] = "-ls";
1679 failsafeArgv[i++] = "-fn";
1680 failsafeArgv[i++] = font;
1684 failsafeArgv[i] = 0;
1685 Debug ("Executing failsafe session\n", failsafeArgv[0]);
1686 execute (failsafeArgv, verify->userEnviron);
1689 Debug ("StartSession(): fork failed\n");
1690 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1694 Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1701 static jmp_buf tenaciousClient;
1704 waitAbort( int arg )
1706 longjmp (tenaciousClient, 1);
1709 #if defined(SYSV) || defined(SVR4)
1711 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1715 AbortClient( int pid )
1724 for (i = 0; i < 4; i++) {
1725 if (killpg (pid, sig) == -1) {
1728 LogError(ReadCatalog(
1729 MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1735 if (!setjmp (tenaciousClient)) {
1736 (void) signal (SIGALRM, waitAbort);
1737 (void) alarm ((unsigned) 10);
1738 retId = wait ((waitType *) 0);
1739 (void) alarm ((unsigned) 0);
1740 (void) signal (SIGALRM, SIG_DFL);
1744 signal (SIGALRM, SIG_DFL);
1751 source( struct verify_info *verify, char *file )
1757 if (file && file[0]) {
1758 Debug ("Source(): %s\n", file);
1759 switch (pid = fork ()) {
1764 execute (args, verify->systemEnviron);
1765 LogError(ReadCatalog(
1766 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1769 Debug ("Source(): fork failed\n");
1770 LogError(ReadCatalog(
1771 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1775 while (wait (&result) != pid)
1779 return waitVal (result);
1784 /* returns 0 on failure, -1 on out of mem, and 1 on success */
1786 execute(char **argv, char **environ )
1790 * make stdout follow stderr to the log file...
1795 session_execve (argv[0], argv, environ);
1798 * In case this is a shell script which hasn't been made executable
1799 * (or this is a SYSV box), do a reasonable thing...
1803 /* errno is EACCES if not executable */
1804 if (errno == ENOEXEC || errno == EACCES) {
1806 if (errno == ENOEXEC) {
1808 char program[1024], *e, *p, *optarg;
1810 char **newargv, **av;
1814 * emulate BSD kernel behaviour -- read
1815 * the first line; check if it starts
1816 * with "#!", in which case it uses
1817 * the rest of the line as the name of
1818 * program to run. Else use "/bin/sh".
1820 f = fopen (argv[0], "r");
1823 if (fgets (program, sizeof (program) - 1, f) == NULL)
1829 e = program + strlen (program) - 1;
1832 if (!strncmp (program, "#!", 2)) {
1834 while (*p && isspace (*p))
1837 while (*optarg && !isspace (*optarg))
1843 while (*optarg && isspace (*optarg));
1850 Debug ("Shell script execution: %s (optarg %s)\n",
1851 p, optarg ? optarg : "(null)");
1852 for (av = argv, argc = 0; *av; av++, argc++)
1854 newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1861 while (*av++ = *argv++)
1863 session_execve (newargv[0], newargv, environ);
1872 /*****************************************************************************
1875 * Invoke the Greeter process and wait for completion. If the user was
1876 * successfully verified, return to the calling process. If the user
1877 * selected a restart or abort option, or there was an error invoking the
1878 * Greeter, exit this entire process with appropriate status.
1880 *****************************************************************************/
1884 extern int session_set;
1885 extern char *progName; /* Global argv[0]; dtlogin name and path */
1887 int response[2], request[2];
1889 /* Fixes problem with dtlogin signal handling */
1890 static int greeterPid = 0;
1891 static struct display *greeter_d = NULL;
1896 Debug("Caught SIGHUP\n");
1899 Debug("Killing greeter process: %d\n", greeterPid);
1900 kill(greeterPid, SIGHUP);
1903 SessionExit(greeter_d, REMANAGE_DISPLAY);
1905 exit(REMANAGE_DISPLAY);
1909 RunGreeter( struct display *d, struct greet_info *greet,
1910 struct verify_info *verify )
1917 static char msg[MSGSIZE];
1921 struct greet_state state = {};
1928 # define U_NAMELEN sizeof(rgy_$name_t)
1932 static char name_short[U_NAMELEN];
1938 char *argv[] = { "dtlogin", 0 };
1939 char *hostName = NULL;
1940 char *loginName = NULL;
1947 if (d->serverPid == -1)
1950 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
1951 loginName, d->name, 1, NULL);
1952 if (siaStatus != SIASUCCESS)
1954 Debug("sia_ses_init failure status %d\n", siaStatus);
1961 if (!setjmp (abortSession)) {
1962 signal(SIGTERM, catchTerm);
1965 * We've changed dtlogin to pass HUP's down to the children
1966 * so ignore any HUP's once the client has started.
1969 signal(SIGHUP, catchHUP);
1972 * set up communication pipes...
1975 if(-1 == pipe(response)) {
1976 perror(strerror(errno));
1978 if(-1 == pipe(request)) {
1979 perror(strerror(errno));
1984 switch (greeterPid = fork ()) {
1988 * pass some information in the environment...
1992 sprintf(msg,"%d", d->grabServer);
1993 env = setEnv(env, GRABSERVER, msg);
1995 sprintf(msg,"%d", d->grabTimeout);
1996 env = setEnv(env, GRABTIMEOUT, msg);
1999 if (timeZone && strlen(timeZone) > 0 )
2000 env = setEnv(env, "TZ", timeZone);
2002 if (errorLogFile && errorLogFile[0])
2003 env = setEnv(env, ERRORLOG, errorLogFile);
2006 env = setEnv(env, "XAUTHORITY", d->authFile);
2009 env = setEnv(env, DTLITE, "True");
2012 env = setEnv(env, SESSION, d->session);
2015 env = setEnv(env, SESSION_SET, "True");
2017 if (d->pmSearchPath)
2018 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
2020 if (d->bmSearchPath)
2021 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
2023 #if defined (__KERBEROS) || defined (__AFS)
2024 if (d->verifyName) {
2025 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2026 (strcmp(d->verifyName, VN_KRB) == 0) ) {
2028 env = setEnv(env, VERIFYNAME, d->verifyName );
2031 LogError(ReadCatalog(
2032 MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2034 d->verifyName = NULL;
2039 if((path = getenv("NLSPATH")) != NULL)
2040 env = setEnv(env, "NLSPATH", path);
2042 env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2047 * ping remote displays...
2051 if (d->displayType.location == Local) {
2052 GettyRunning(d); /* refresh gettyState */
2053 if (d->gettyState != DM_GETTY_USER)
2054 env = setEnv(env, LOCATION, "local");
2057 sprintf(msg,"%d", d->pingInterval);
2058 env = setEnv(env, PINGINTERVAL, msg);
2060 sprintf(msg,"%d", d->pingTimeout);
2061 env = setEnv(env, PINGTIMEOUT, msg);
2065 if ( d->langList && strlen(d->langList) > 0 )
2066 env = setEnv(env, LANGLIST, d->langList);
2067 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2068 else if (languageList && strlen(languageList) > 0 )
2069 env = setEnv(env, LANGLIST, languageList);
2070 #endif /* ENABLE_DYNAMIC_LANGLIST */
2073 char *language = NULL;
2075 #if defined (ENABLE_DYNAMIC_LANGLIST)
2076 language = d->language;
2077 #endif /* ENABLE_DYNAMIC_LANGLIST */
2079 if ( d->language && strlen(d->language) > 0 )
2080 env = setLang(d, env, language);
2083 if((path = getenv("XKEYSYMDB")) != NULL)
2084 env = setEnv(env, "XKEYSYMDB", path);
2087 if((path = getenv("OPENWINHOME")) != NULL)
2088 env = setEnv(env, "OPENWINHOME", path);
2093 * set environment for Domain machines...
2095 env = setEnv(env, "ENVIRONMENT", "bsd");
2096 env = setEnv(env, "SYSTYPE", "bsd4.3");
2100 Debug ("Greeter environment:\n");
2102 Debug ("End of Greeter environment:\n");
2105 * Writing to file descriptor 1 goes to response pipe instead.
2108 dupfp = dup(response[1]);
2110 perror(strerror(errno));
2116 * Reading from file descriptor 0 reads from request pipe instead.
2119 dupfp2 = dup(request[0]);
2121 perror(strerror(errno));
2129 * figure out path to dtgreet...
2132 strcpy(msg, progName);
2134 if ((p = (char *) strrchr(msg, '/')) == NULL)
2139 strcat(msg,"dtgreet");
2141 execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2142 LogError(ReadCatalog(
2143 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2145 exit (NOTIFY_ABORT_DISPLAY);
2148 Debug ("Fork of Greeter failed.\n");
2149 LogError(ReadCatalog(
2150 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2155 exit (UNMANAGE_DISPLAY);
2158 Debug ("Greeter started\n");
2160 close(response[1]); /* Close write end of response pipe */
2161 close(request[0]); /* Close read end of request pipe */
2165 * Retrieve information from greeter and authenticate.
2167 globalDisplayName = d->name;
2168 state.id = GREET_STATE_ENTER;
2169 state.waitForResponse = FALSE;
2173 * atexit() registers this function to be called if exit() is
2174 * called. This is needed because in enhanced security mode, SIA
2175 * may call exit() whn the user fails to enter or change a
2178 sia_greeter_pid = greeterPid;
2179 if (!sia_exit_proc_reg)
2181 atexit(KillGreeter);
2182 sia_exit_proc_reg = TRUE;
2185 siaGreeterInfo.d = d;
2186 siaGreeterInfo.greet = greet;
2187 siaGreeterInfo.verify = verify;
2188 siaGreeterInfo.state = &state;
2189 siaGreeterInfo.status = TRUE;
2192 while(siaStatus != SIASUCCESS)
2194 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2196 Debug ("RunGreeter: before sia_ses_authent\n");
2197 dt_in_sia_ses_authent = True;
2198 siaStatus = sia_ses_authent(SiaManageGreeter, NULL,
2200 dt_in_sia_ses_authent = False;
2201 Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2203 if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2205 state.id = GREET_STATE_ERRORMESSAGE;
2206 state.vf = VF_INVALID;
2207 ManageGreeter(d, greet, verify, &state);
2209 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2212 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2214 sia_ses_release(&siaHandle);
2218 Debug("RunGreeter: before sia_ses_estab\n");
2219 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2220 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2223 if (!siaGreeterInfo.status)
2226 if (siaStatus == SIASUCCESS)
2228 Debug("RunGreeter: before sia_ses_launch\n");
2229 siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2230 Debug("RunGreeter: after sia_ses_launch status = %d\n",
2233 if (!siaGreeterInfo.status)
2236 if (siaStatus != SIASUCCESS)
2238 Debug("RunGreeter: sia_ses_launch failure\n");
2239 /* establish & launch failures do a release */
2241 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
2242 loginName, d->name, 1, NULL);
2243 if (siaStatus != SIASUCCESS)
2245 Debug("sia_ses_init failure status %d\n", siaStatus);
2246 exit(RESERVER_DISPLAY);
2251 * sia_ses_launch() wil probably seteuid to that of the
2252 * user, but we don't want that now.
2256 * extract necessary info from SIA context struct
2260 if (siaStatus == SIASUCCESS)
2261 CopySiaInfo(siaHandle, greet);
2262 sia_ses_release(&siaHandle);
2264 state.id = GREET_STATE_TERMINATEGREET;
2265 if (siaGreeterInfo.status)
2267 while (ManageGreeter(d, greet, verify, &state))
2270 sia_greeter_pid = 0;
2272 while (ManageGreeter(d, greet, verify, &state))
2277 * Wait for Greeter to end...
2280 pid = wait (&status);
2281 if (pid == greeterPid)
2287 * Greeter exited. Check return code...
2290 Debug("Greeter return status; exit = %d, signal = %d\n",
2291 waitCode(status), waitSig(status));
2295 * remove authorization file if used...
2298 if (d->authorizations && d->authFile &&
2299 waitVal(status) != NOTIFY_LANG_CHANGE
2301 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2306 Debug ("Done with authorization file %s, removing\n",
2308 (void) unlink (d->authFile);
2313 if(waitVal(status) > NOTIFY_ALT_DTS)
2314 d->sessionType = waitVal(status);
2317 switch (waitVal(status)) {
2318 case NOTIFY_FAILSAFE:
2319 greet->string = "failsafe";
2321 case NOTIFY_PASSWD_EXPIRED:
2322 greet->string = "password";
2327 case NOTIFY_LAST_DT:
2328 d->sessionType = waitVal(status);
2334 Debug("waitVal - status is %d\n", waitVal(status));
2335 if(waitVal(status) > NOTIFY_ALT_DTS)
2336 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2338 notify_dt = waitVal(status);
2340 switch (notify_dt) {
2341 case NOTIFY_FAILSAFE:
2342 case NOTIFY_PASSWD_EXPIRED:
2346 case NOTIFY_LAST_DT:
2347 case NOTIFY_ALT_DTS:
2349 if (NULL == greet->name) return;
2352 * greet->name, greet->password set in ManageGreeter().
2354 Debug("Greeter returned name '%s'\n", greet->name);
2357 greet->name_full = greet->name;
2358 /* get just person name out of full SID */
2360 while (i < sizeof(rgy_$name_t)
2361 && greet->name_full[i] != '.'
2362 && greet->name_full[i] != '\0') {
2363 name_short[i] = greet->name_full[i];
2366 name_short[i] = '\0';
2367 greet->name = name_short;
2372 * groups[] set in Authenticate().
2374 if ( IsVerifyName(VN_AFS) ) {
2375 verify->groups[0] = groups[0];
2376 verify->groups[1] = groups[1];
2377 Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2378 Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2384 * sensitivityLevel set in BLS_Verify()
2386 greet->b1security = sensitivityLevel;
2389 Verify(d, greet, verify);
2393 Debug ("Greeter Xlib error or SIGTERM\n");
2394 SessionExit(d, OPENFAILED_DISPLAY);
2396 case NOTIFY_RESTART:
2397 Debug ("Greeter requested RESTART_DISPLAY\n");
2398 SessionExit(d, RESERVER_DISPLAY);
2400 case NOTIFY_ABORT_DISPLAY:
2401 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2402 SessionExit(d, UNMANAGE_DISPLAY);
2404 case NOTIFY_NO_WINDOWS:
2405 Debug ("Greeter requested NO_WINDOWS mode\n");
2406 if (d->serverPid >= 2)
2408 * Don't do a SessionExit() here since that causes
2409 * the X-server to be reset. We know we are going to
2410 * terminate it anyway, so just go do that...
2412 exit(SUSPEND_DISPLAY);
2416 case NOTIFY_LANG_CHANGE:
2417 Debug ("Greeter requested LANG_CHANGE\n");
2420 * copy requested language into display struct "d". Note,
2421 * this only happens in this child's copy of "d", not in
2422 * the master struct. When the user logs out, the
2423 * resource-specified language (if any) will reactivate.
2426 Debug("Greeter returned language '%s'\n", d->language);
2428 Debug("Greeter returned language (NULL)\n");
2431 if (strcmp(d->language, "default") == 0) {
2432 int len = strlen(defaultLanguage) + 1;
2433 d->language = (d->language == NULL ?
2434 malloc(len) : realloc (d->language, len));
2435 strcpy(d->language, defaultLanguage);
2439 case NOTIFY_BAD_SECLEVEL:
2442 case waitCompose (SIGTERM,0,0):
2443 Debug ("Greeter exited on SIGTERM\n");
2444 SessionExit(d, OPENFAILED_DISPLAY);
2447 Debug ("Greeter returned unknown status %d\n",
2449 SessionExit(d, REMANAGE_DISPLAY);
2452 signal(SIGHUP, SIG_DFL);
2455 AbortClient(greeterPid);
2456 SessionExit(d, UNMANAGE_DISPLAY);
2460 /*****************************************************************************
2466 This is the entry into greeter state processing. Allocate and initialize
2470 Display the login screen. Upon display, the login screen can be 'reset'. If
2471 reset is true, the username and password fields are cleared and the focus
2472 is set to the username field. If reset is false, the username and password
2473 field is untouched and the focus is set to the password field.
2475 LOGIN -> AUTHENTICATE:
2476 Authenticate the username entered on login screen.
2478 AUTHENTICATE -> TERMINATEGREET:
2479 User passed authentication so terminate the greeter.
2481 AUTHENTICATE -> EXPASSWORD:
2482 User passed authentication, but the their password has expired.
2483 Display old password message. This message allows the user to
2484 change their password by starting a getty and running passwd(1).
2486 AUTHENTICATE -> BAD_HOSTNAME:
2487 User passed authentication, but the their hostname is empty.
2488 Display a dialog that allows the user to run a getty to fix the
2489 problem, or start the desktop anyway.
2491 AUTHENTICATE -> ERRORMESSAGE:
2492 User failed authentication, so display error message.
2494 AUTHENTICATE -> LOGIN
2495 User failed authentication, but did not enter a password. Instead
2496 of displaying an error message, redisplay the login screen with
2497 the focus set to the password field. If the user authenticates again
2498 without the password field set, display an error. This allows a user
2499 to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2502 Free state structure and return false to stop state transitions.
2504 ERRORMESSAGE -> LOGIN
2505 Display error message base on return code from last authentication
2506 attempt. Redisplay login screen with reset set to true.
2508 (state) -> LANG -> (state)
2509 User has chosen a new language. Transition to LANG state to save off
2510 the new language, and transition back to original state.
2512 *****************************************************************************/
2514 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2517 ManageGreeter( struct display *d, struct greet_info *greet,
2518 struct verify_info *verify, struct greet_state *state )
2525 if (state->waitForResponse)
2527 if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2530 * Dtgreet has terminated.
2532 state->id = GREET_STATE_EXIT;
2533 state->waitForResponse = FALSE;
2537 if (state->request->opcode != state->response->opcode)
2540 * An unrequested event arrived. See if it's one we
2543 switch(state->response->opcode)
2545 case REQUEST_OP_LANG:
2548 * User has changed language. Recursively handle this state
2549 * and return to current state.
2551 struct greet_state lang_state;
2553 lang_state = *state;
2554 lang_state.id = GREET_STATE_LANG;
2555 lang_state.waitForResponse = FALSE;
2556 ManageGreeter(d, greet, verify, &lang_state);
2557 Debug("Response opcode REQUEST_OP_LANG\n");
2562 case REQUEST_OP_CLEAR:
2565 * User has requested the screen be cleared.
2567 state->id = GREET_STATE_USERNAME;
2568 state->waitForResponse = TRUE;
2569 Debug("Response opcode REQUEST_OP_CLEAR\n");
2574 Debug("Response opcode UNEXPECTED RESPONSE!\n");
2584 * Got the response we were expecting.
2586 state->waitForResponse = FALSE;
2592 case GREET_STATE_ENTER:
2595 * Enter - initialize state
2597 Debug("GREET_STATE_ENTER\n");
2599 state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2600 state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2601 state->authenticated = FALSE;
2604 state->id = GREET_STATE_USERNAME;
2608 case GREET_STATE_USERNAME:
2613 RequestChallenge *r;
2615 Debug("GREET_STATE_USERNAME\n");
2617 Authenticate(d, NULL, NULL, NULL);
2619 SETMC(msg, LOGIN_LABEL);
2621 r = (RequestChallenge *)state->request;
2622 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2623 r->hdr.reserved = 0;
2626 r->hdr.length = sizeof(*r);
2628 r->offChallenge = sizeof(*r);
2629 strcpy(((char *)r) + r->offChallenge, msg.def);
2630 r->hdr.length += strlen(msg.def) + 1;
2634 r->offUserNameSeed = r->hdr.length;
2635 strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2636 r->hdr.length += strlen(greet->name) + 1;
2637 Debug("Greet name: %s\n", greet->name);
2641 r->offUserNameSeed = 0;
2646 free(greet->name); greet->name = NULL;
2648 if (greet->password)
2650 free(greet->password); greet->password = NULL;
2653 TellGreeter((RequestHeader *)r);
2654 state->waitForResponse = TRUE;
2656 state->id = GREET_STATE_AUTHENTICATE;
2660 case GREET_STATE_CHALLENGE:
2665 RequestChallenge *r;
2667 Debug("GREET_STATE_CHALLENGE\n");
2669 if (greet->password)
2671 free(greet->password); greet->password = NULL;
2674 SETMC(msg, PASSWD_LABEL);
2676 r = (RequestChallenge *)state->request;
2677 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2678 r->hdr.reserved = 0;
2681 r->offUserNameSeed = 0;
2682 r->offChallenge = sizeof(*r);
2683 strcpy(((char *)r) + r->offChallenge, msg.def);
2684 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2686 TellGreeter((RequestHeader *)r);
2687 state->waitForResponse = TRUE;
2689 state->id = GREET_STATE_AUTHENTICATE;
2693 case GREET_STATE_AUTHENTICATE:
2696 * Attempt to authenticate.
2698 ResponseChallenge *r;
2700 Debug("GREET_STATE_AUTHENTICATE\n");
2702 r = (ResponseChallenge *)state->response;
2704 if (greet->name == NULL)
2706 greet->name = strdup(((char *)r) + r->offResponse);
2707 if (strlen(greet->name) == 0)
2709 state->id = GREET_STATE_USERNAME;
2715 greet->password = strdup(((char *)r) + r->offResponse);
2725 * Attempt to authenticate user. 'username' should be a
2726 * non-empty string. 'password' may be an empty string.
2728 state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2730 if (state->vf == VF_OK ||
2731 state->vf == VF_PASSWD_AGED ||
2732 state->vf == VF_BAD_HOSTNAME)
2734 state->authenticated = TRUE;
2738 * General transitions.
2742 case VF_OK: state->id = GREET_STATE_TERMINATEGREET; break;
2743 case VF_PASSWD_AGED: state->id = GREET_STATE_EXPASSWORD; break;
2744 case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break;
2745 case VF_CHALLENGE: state->id = GREET_STATE_CHALLENGE; break;
2746 default: state->id = GREET_STATE_ERRORMESSAGE; break;
2751 case GREET_STATE_EXIT:
2754 * Free resources and leave.
2756 Debug("GREET_STATE_EXIT\n");
2763 if (!state->authenticated)
2767 free(greet->name); greet->name = NULL;
2769 if (greet->password)
2771 free(greet->password); greet->password = NULL;
2775 free(state->request);
2776 free(state->response);
2781 case GREET_STATE_ERRORMESSAGE:
2784 * Display error message.
2788 Debug("GREET_STATE_ERRORMESSAGE\n");
2790 r = (RequestMessage *)state->request;
2794 case VF_INVALID: SETMC(msg, LOGIN); break;
2795 case VF_HOME: SETMC(msg, HOME); break;
2796 case VF_MAX_USERS: SETMC(msg, MAX_USERS); break;
2797 case VF_BAD_UID: SETMC(msg, BAD_UID); break;
2798 case VF_BAD_GID: SETMC(msg, BAD_GID); break;
2799 case VF_BAD_AID: SETMC(msg, BAD_AID); break;
2800 case VF_BAD_AFLAG: SETMC(msg, BAD_AFLAG); break;
2801 case VF_NO_LOGIN: SETMC(msg, NO_LOGIN); break;
2803 case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2805 case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2806 default: msg.id=0; msg.def=""; break;
2809 r->hdr.opcode = REQUEST_OP_MESSAGE;
2810 r->hdr.reserved = 0;
2812 r->offMessage = sizeof(*r);
2813 strcpy(((char *)r) + r->offMessage, msg.def);
2814 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2816 TellGreeter((RequestHeader *)r);
2817 state->waitForResponse = TRUE;
2819 state->id = GREET_STATE_USERNAME;
2823 case GREET_STATE_LANG:
2826 * User selected new language.
2832 Debug("GREET_STATE_LANG\n");
2834 r = (ResponseLang *)state->response;
2835 lang = ((char *)r) + r->offLang;
2836 len = strlen(lang) + 1;
2838 d->language = (d->language == NULL ?
2839 malloc(len) : realloc(d->language, len));
2840 strcpy(d->language, lang);
2841 Debug("Language returned: %s\n", d->language);
2845 case GREET_STATE_TERMINATEGREET:
2848 * Terminate dtgreet.
2852 Debug("GREET_STATE_TERMINATEGREET\n");
2854 r = (RequestExit *)state->request;
2856 r->hdr.opcode = REQUEST_OP_EXIT;
2857 r->hdr.reserved = 0;
2858 r->hdr.length = sizeof(*r);
2860 TellGreeter((RequestHeader *)r);
2861 state->waitForResponse = TRUE;
2863 state->id = GREET_STATE_EXIT;
2867 case GREET_STATE_EXPASSWORD:
2870 * Display password expired message.
2872 RequestExpassword *r;
2874 Debug("GREET_STATE_EXPASSWORD\n");
2876 r = (RequestExpassword *)state->request;
2878 r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2879 r->hdr.reserved = 0;
2880 r->hdr.length = sizeof(*r);
2882 TellGreeter((RequestHeader *)r);
2883 state->waitForResponse = TRUE;
2885 state->id = GREET_STATE_USERNAME;
2889 case GREET_STATE_BAD_HOSTNAME:
2892 * Display password expired message.
2896 Debug("GREET_STATE_BAD_HOSTNAME\n");
2898 r = (RequestHostname *)state->request;
2900 r->hdr.opcode = REQUEST_OP_HOSTNAME;
2901 r->hdr.reserved = 0;
2902 r->hdr.length = sizeof(*r);
2904 TellGreeter((RequestHeader *)r);
2905 state->waitForResponse = TRUE;
2907 state->id = GREET_STATE_USERNAME;
2912 case GREET_STATE_FORM:
2915 * Get arbitrary number of answers.
2918 Debug("GREET_STATE_FORM\n");
2920 AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2922 state->waitForResponse = FALSE;
2923 state->id = GREET_STATE_USERNAME;
2935 RequestHeader *phdr)
2937 if(-1 == write(request[1], phdr, phdr->length)) {
2938 perror(strerror(errno));
2944 RequestHeader *preqhdr,
2950 ResponseHeader *phdr = (ResponseHeader *)buf;
2952 if (preqhdr) TellGreeter(preqhdr);
2954 phdr->opcode = REQUEST_OP_NONE;
2956 count = read(response[0], buf, sizeof(*phdr));
2958 if (count == sizeof(*phdr))
2961 * Calculate amount of data after header.
2963 remainder = phdr->length - sizeof(*phdr);
2967 * Read remainder of response.
2969 count += read(response[0], buf+sizeof(*phdr), remainder);
2974 if (debugLevel) PrintResponse(phdr, count);
2983 ResponseHeader *phdr,
2986 char *opstr = "UNKNOWN";
2990 Debug("opcode = (EOF)\n");
2994 switch(phdr->opcode)
2996 case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2997 case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2998 case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2999 case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
3000 case REQUEST_OP_LANG: opstr = "LANG"; break;
3001 case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
3004 Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
3005 Debug(" reserved = %d\n", phdr->reserved);
3006 Debug(" length = %d\n", phdr->length);
3008 switch(phdr->opcode)
3010 case REQUEST_OP_EXIT: break;
3011 case REQUEST_OP_LANG:
3012 Debug(" offLang=%d\n", ((ResponseLang *)phdr)->offLang);
3013 Debug(" lang='%s'\n",
3014 ((char *)phdr)+((ResponseLang *)phdr)->offLang);
3016 case REQUEST_OP_MESSAGE: break;
3017 case REQUEST_OP_CHPASS: break;
3018 case REQUEST_OP_CHALLENGE:
3019 Debug(" offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
3020 Debug(" response='%s'\n",
3021 ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
3023 case REQUEST_OP_DEBUG:
3024 Debug(" offString=%d\n", ((ResponseDebug *)phdr)->offString);
3025 Debug(" string='%s'\n",
3026 ((char *)phdr)+((ResponseDebug *)phdr)->offString);
3034 /***************************************************************************
3038 * generate kerberos ticket file name. Name is returned in the static
3039 * global variable "krb_ticket_string".
3041 ***************************************************************************/
3044 SetTicketFileName(uid_t uid)
3053 * generate ticket file pathname (/tmp/tkt<uid>.<host>) ...
3056 if (env = (char *)getenv("KRBTKFILE")) {
3057 (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3058 krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3061 if (gethostname(lhost, sizeof(lhost)) != -1) {
3062 if (p = index(lhost, '.')) *p = '\0';
3063 (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3065 /* 32 bits of signed integer will always fit in 11 characters
3066 (including the sign), so no need to worry about overflow */
3067 (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3072 #endif /* __KERBEROS */
3074 #if defined (_AIX) && !defined (_POWER)
3076 /***************************************************************************
3080 * If this is an authenticated process (LOGNAME set), set user's
3081 * process environment by calling setpenv().
3083 * If this is not an authenticated process, just call execve()
3085 ***************************************************************************/
3094 char *user = getEnv (envp, "LOGNAME");
3098 rc = execve(path, argv, envp);
3102 char *usrTag, *sysTag;
3105 * Save pointers to tags. The setpenv() function clears the pointers
3106 * to the tags in userEnviron as a side-effect.
3108 sysTag = envp[SYS_ENV_TAG];
3109 usrTag = envp[USR_ENV_TAG];
3112 * Set the users process environment. This call execs arvg so it
3113 * should not return. It it should return, restore the envp tags.
3115 rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3118 * Restore pointers to tags.
3120 envp[SYS_ENV_TAG] = sysTag;
3121 envp[USR_ENV_TAG] = usrTag;
3126 #endif /* _AIX && !_POWER */
3130 /* collect the SIA parameters from a window system. */
3132 static int SiaManageGreeter(
3135 unsigned char *title,
3141 RequestMessage greeter_message;
3142 char msg_buffer[256];
3143 } greeter_msg_and_buffer;
3144 RequestForm *request_form;
3152 if (rendition == SIAFORM && dt_in_sia_ses_authent
3153 && (num_prompts == 2))
3155 /* Normal login, Password case */
3156 Debug ("SIAFORM Normal login, Password case\n");
3157 while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3158 && siaGreeterInfo.state->id != GREET_STATE_EXIT
3159 && (siaGreeterInfo.status = ManageGreeter(
3160 siaGreeterInfo.d, siaGreeterInfo.greet,
3161 siaGreeterInfo.verify, siaGreeterInfo.state)))
3164 if (!siaGreeterInfo.status
3165 || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3166 return(SIACOLABORT);
3168 strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name,
3169 prompt[0].max_result_length);
3170 strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3171 prompt[1].max_result_length);
3178 ResponseForm *response_form;
3183 Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3186 Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3189 Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3192 Debug("SIAFORM num_prompts = %d\n", num_prompts);
3196 /* need to display form */
3198 req_form_size = sizeof(RequestForm)
3199 + strlen((const char *)title) + 1;
3200 for (i=0; i<num_prompts; i++)
3201 req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3202 request_form = (RequestForm *) alloca(req_form_size);
3204 siaGreeterInfo.state->id = GREET_STATE_FORM;
3205 siaGreeterInfo.state->request = (RequestHeader *)request_form;
3206 /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3208 request_form->hdr.opcode = REQUEST_OP_FORM;
3209 request_form->hdr.reserved = 0;
3210 request_form->hdr.length = req_form_size;
3211 request_form->num_prompts = num_prompts;
3212 request_form->rendition = rendition;
3213 request_form->offTitle = sizeof(RequestForm);
3214 request_form->offPrompts = sizeof(RequestForm) +
3215 strlen((const char *)title) + 1;
3216 strcpy((char *)request_form + request_form->offTitle,
3217 (const char *)title);
3219 pmpt_ptr = (char *)request_form + request_form->offPrompts;
3220 for (i=0; i<num_prompts; i++)
3222 if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3226 Debug(" prompt[%d]: %s\n", i, prompt[i].prompt);
3227 strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3228 pmpt_ptr += strlen((const char *)prompt[i].prompt);
3230 request_form->visible[i] =
3231 (prompt[i].control_flags & SIARESINVIS) ? False : True;
3234 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3235 siaGreeterInfo.greet,
3236 siaGreeterInfo.verify,
3237 siaGreeterInfo.state);
3239 response_form = (ResponseForm *)siaGreeterInfo.state->response;
3240 res_ptr = (char *)response_form + response_form->offAnswers;
3241 for (i = 0; i < response_form->num_answers; i++)
3243 if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3246 prompt[i].result = (unsigned char *)1;
3248 prompt[i].result = NULL;
3252 strcpy((char *)prompt[0].result, res_ptr);
3254 res_ptr += strlen(res_ptr) + 1;
3256 if (!response_form->collect_status)
3257 siaGreeterInfo.status = FALSE;
3263 Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3265 siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3266 siaGreeterInfo.state->request = (RequestHeader *)
3267 &greeter_msg_and_buffer.greeter_message;
3268 siaGreeterInfo.state->vf = VF_MESSAGE;
3269 siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3271 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3272 siaGreeterInfo.greet,
3273 siaGreeterInfo.verify,
3274 siaGreeterInfo.state);
3277 return(SIACOLABORT);
3280 if (!siaGreeterInfo.status)
3281 return(SIACOLABORT);
3282 return(SIACOLSUCCESS);
3285 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3288 greet->name = malloc(strlen(siaHandle->name) + 1);
3289 strcpy (greet->name, siaHandle->name);
3291 greet->password = malloc(strlen(siaHandle->password) + 1);
3292 strcpy (greet->password, siaHandle->password);
3297 static void KillGreeter( void )
3299 if (sia_greeter_pid)
3300 AbortClient(sia_greeter_pid);
3301 sia_greeter_pid = 0;