2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* (c) Copyright 1997 The Open Group */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
31 * Xdm - display manager daemon
33 * $TOG: session.c /main/21 1998/11/02 14:32:42 mgreess $
35 * Copyright 1988 Massachusetts Institute of Technology
37 * Permission to use, copy, modify, and distribute this software and its
38 * documentation for any purpose and without fee is hereby granted, provided
39 * that the above copyright notice appear in all copies and that both that
40 * copyright notice and this permission notice appear in supporting
41 * documentation, and that the name of M.I.T. not be used in advertising or
42 * publicity pertaining to distribution of the software without specific,
43 * written prior permission. M.I.T. makes no representations about the
44 * suitability of this software for any purpose. It is provided "as is"
45 * without express or implied warranty.
47 * Author: Keith Packard, MIT X Consortium
67 # include <X11/Xatom.h>
69 #if defined(__FreeBSD__) && OSMAJORVERSION > 8
82 #include <X11/Intrinsic.h>
85 # include <X11/Xresource.h>
96 # include <sys/security.h>
102 #endif /* __KERBEROS */
105 #include "rgy_base.h"
110 static SIAENTITY *siaHandle = NULL;
111 static Boolean dt_in_sia_ses_authent = False;
113 static struct sia_greeter_info {
115 struct greet_info *greet;
116 struct verify_info *verify;
117 struct greet_state *state;
121 static int SiaManageGreeter(
124 unsigned char *title,
128 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet);
130 static void KillGreeter( void );
132 static int sia_greeter_pid;
133 static int sia_exit_proc_reg = FALSE;
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 snprintf(tempbuf, sizeof(tempbuf), "%s", 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 snprintf(dirname[j], sizeof(dirname[j]), "%s", resources);
773 snprintf(dirname[j], sizeof(dirname[j]), "%s", resources);
774 Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
783 * Create a list of the alt DT files
785 * NOTE - an assumption made here is that files in /etc/dt
786 * should take precedence over files in /usr/dt. This precedence
787 * is maintained during the sort becase /etc/dt will come before
791 for(j = 0; j < 2 ; ++j) {
793 if((dirp = opendir(dirname[j])) != NULL) {
795 while((dp = readdir(dirp)) != NULL) {
797 if ((strcmp(dp->d_name, DOT) != 0) &&
798 (strcmp(dp->d_name, DOTDOT) != 0)) {
800 sprintf (res_file, "%s%s", dirname[j],dp->d_name);
801 if ((access (res_file, R_OK)) != 0)
803 Debug("LoadAltDtsResources- cant access %s.\n",
805 Debug("\t %s.\n", strerror(errno));
809 if (file_count == 0) {
810 file_list = malloc (list_incr * sizeof(char *));
811 num_allocated += list_incr;
813 if (file_count + 1 > num_allocated) {
814 num_allocated += list_incr;
815 file_list = realloc (file_list,
816 num_allocated * sizeof(char *));
818 file_list[file_count] = strdup (res_file);
827 qsort (file_list, file_count, sizeof (char *), FileNameCompare);
829 for (j = 0; j < file_count ; j++) {
831 userDb = XrmGetFileDatabase(file_list[j]);
832 XrmMergeDatabases(userDb,&XresourceDB);
834 if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
835 "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
838 * remove the trailing spaces
840 if(strchr(rmvalue.addr,' '))
841 snprintf(tempbuf, sizeof(tempbuf), "%s", strtok(rmvalue.addr," "));
843 snprintf(tempbuf, sizeof(tempbuf), "%s", rmvalue.addr);
845 if ((strcmp(tempbuf, "True") == 0) ||
846 (strcmp(tempbuf, "TRUE") == 0)) {
848 if ( XrmGetResource(XresourceDB,
849 "Dtlogin*altDtKey", "Dtlogin*AltDtKey",
850 &rmtype, &rmvalue ) ) {
852 sprintf(altdtres,"Dtlogin*altDtKey%d",i);
853 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
858 if ( XrmGetResource(XresourceDB,
859 "Dtlogin*altDtName", "Dtlogin*AltDtName",
860 &rmtype, &rmvalue ) ) {
861 sprintf(altdtres,"Dtlogin*altDtName%d",i);
862 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
864 if ( XrmGetResource(XresourceDB,
865 "Dtlogin*altDtStart", "Dtlogin*AltDtStart",
866 &rmtype, &rmvalue ) ) {
867 sprintf(altdtres,"Dtlogin*altDtStart%d",i);
868 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
870 if ( XrmGetResource(XresourceDB,
871 "Dtlogin*altDtLogo", "Dtlogin*AltDtLogo",
872 &rmtype, &rmvalue ) ) {
873 sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
874 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
880 sprintf(tempbuf,"%d",i);
881 XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf);
883 if (file_count > 0) {
884 for (i = 0; i < file_count; i++) {
885 Debug ("Loading resource file: %s\n", file_list[i]);
895 * Function Name: _ExpandLang
899 * This function takes the string "string", searches for occurences of
900 * "%L" in the string and if found, the "%L" is substituted with
901 * the value of the $LANG environment variable.
903 * If $LANG is not defined, the %L is replace with NULL.
907 * _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
911 * ret_string = _ExpandLang (string);
913 * char *ret_string; Returns NULL if "string" is NULL or it points
914 * to the expanded string.
916 * char *string; The first part of the pathname. Typically
917 * the directory containing the item of interest.
919 * Note: The caller is responsible for free'ing the returned string.
941 * Count the number of expansions that will occur.
945 for (n = 0, pch = string ; pch != NULL ; ) {
946 if ((pch = strchr (pch, '%')) != NULL) {
953 return (strdup(string));
956 * We should really be calling setlocale to determine the "default"
957 * locale but setlocale's return value is not standardized across
958 * the various vendor platforms nor is it consistent within differnt
959 * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
960 * HP-UX 10.0). The "right" call would be the following line:
962 * if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
964 * Here we hard code the default to "C" instead of leaving it NULL.
966 if (lang || (lang = getenv ("LANG")) || (lang = "C"))
967 lang_len = strlen (lang);
970 * Create the space needed.
972 tmp_len = strlen (string) + (n * lang_len) + n + 1;
973 tmp = (char *) malloc (tmp_len);
974 for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
978 while (pch != NULL) {
981 if ((pch = strchr (pch, '%')) != NULL) {
986 (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
988 else if ((pch != NULL) && *pch == 'L') {
990 if (((pch - trail) >=2) && (*(pch-2) == '/'))
992 * Remove the "/" as well as the "%L".
994 (void) strncat (tmp, trail, (pch - trail) - 2);
996 (void) strncat (tmp, trail, (pch - trail) - 1);
1000 * Remove the "%L" and then append the LANG.
1002 (void) strncat (tmp, trail, (pch - trail) - 1);
1003 (void) strcat (tmp, lang);
1007 (void) strncat (tmp, trail, (pch - trail) + 1);
1014 * A '%' was not found.
1016 (void) strcat (tmp, trail);
1025 SetupDisplay (struct display *d)
1027 char **env = 0, **crt_systemEnviron;
1029 if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1031 crt_systemEnviron = verify.systemEnviron;
1032 env = systemEnv (d, (char *) 0, (char *) 0);
1033 if (d->authFile && strlen(d->authFile) > 0 )
1034 env = setEnv( env, "XAUTHORITY", d->authFile );
1035 if(d->displayType.location == Local)
1036 env = setEnv (env, LOCATION, "local");
1038 env = setEnv (env, LOCATION, "remote");
1039 verify.systemEnviron = env;
1040 source (&verify, d->setup);
1041 verify.systemEnviron = crt_systemEnviron;
1048 DeleteXloginResources( struct display *d, Display *dpy )
1050 XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1053 #if 0 /* dead code: transferred to Dtgreet */
1055 static jmp_buf syncJump;
1060 longjmp (syncJump, 1);
1064 SecureDisplay (d, dpy)
1068 Debug ("SecureDisplay():\n");
1069 signal (SIGALRM, syncTimeout);
1070 if (setjmp (syncJump)) {
1071 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1073 SessionExit (d, RESERVER_DISPLAY);
1075 alarm ((unsigned) d->grabTimeout);
1076 Debug ("Before XGrabServer()\n");
1078 if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1079 GrabModeAsync, CurrentTime) != GrabSuccess)
1082 signal (SIGALRM, SIG_DFL);
1083 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1085 SessionExit (d, RESERVER_DISPLAY);
1087 Debug ("XGrabKeyboard() succeeded\n");
1089 signal (SIGALRM, SIG_DFL);
1093 XUngrabServer (dpy);
1096 Debug ("Done secure %s\n", d->name);
1099 UnsecureDisplay (d, dpy)
1103 Debug ("Unsecure display %s\n", d->name);
1105 XUngrabServer (dpy);
1114 release_aix_lic(void)
1117 * Release AIX iFOR/LS license (if any)
1125 release_me.request_type = -1;
1126 release_me.login_pid = getpid();
1127 if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1129 write(fd, &release_me, sizeof(release_me));
1132 Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1140 SessionExit( struct display *d, int status )
1149 /* make sure the server gets reset after the session is over */
1150 if (d->serverPid >= 2) {
1151 Debug("Reseting server: pid %d signal %d\n",
1152 d->serverPid, d->resetSignal);
1154 if (d->terminateServer == 0 && d->resetSignal)
1155 kill (d->serverPid, d->resetSignal);
1160 Debug("Exiting Session with status: %d\n", status);
1165 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1168 char currentdir[PATH_MAX+1];
1169 char *failsafeArgv[20];
1170 char *user; /* users name */
1171 char *lang, *font; /* failsafe LANG and font */
1174 int failsafe = FALSE; /* do we run the failsafe session? */
1175 int password = FALSE; /* do we run /bin/passwd? */
1178 char lastsessfile[MAXPATHLEN];
1181 struct pr_passwd *b1_pwd;
1185 #define NOPAG 0xffffffff
1187 long ngroups, groups[NGROUPS];
1193 Debug ("StartSession %s: ", verify->argv[0]);
1194 for (f = verify->argv; *f; f++) {
1196 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1197 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1201 if (verify->userEnviron) {
1202 for (f = verify->userEnviron; *f; f++)
1207 user = getEnv (verify->userEnviron, "USER");
1209 switch (pid = fork ()) {
1212 /* Force a failsafe session if we can't touch the home directory
1213 * SIA has already attempted to chdir to HOME, and the current dir
1214 * will be set to / if it failed. We just check to see if the HOME
1215 * path is our current directory or not.
1217 home = getEnv (verify->userEnviron, "HOME");
1218 getcwd(currentdir, PATH_MAX+1);
1219 Debug("Current directory is: %s\n", currentdir);
1223 * The following little check doesn't really work. For example,
1224 * here at the XC, NIS reports my home directory as
1225 * "/site/guests/montyb" while getcwd comes up with
1226 * "/net/nexus/site/guests/montyb".
1228 if (strcmp(home, currentdir)) {
1229 Debug("Can't access home directory, setting failsafe to TRUE\n");
1231 LogError (ReadCatalog(
1232 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1233 home, getEnv (verify->userEnviron, "USER"));
1234 verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1242 * do process accounting...
1244 #if defined(PAM) || defined(SUNAUTH)
1246 char* ttyLine = d->gettyLine;
1248 # ifdef DEF_NETWORK_DEV
1250 * If location is not local (remote XDMCP dtlogin) and
1251 * remote accouting is enabled (networkDev start with /dev/...)
1252 * Set tty line name to match network device for accouting.
1253 * Unless the resource was specifically set, default is value
1254 * of DEF_NETWORK_DEV define (/dev/dtremote)
1257 if ( d->displayType.location != Local &&
1258 networkDev && !strncmp(networkDev,"/dev/",5)) {
1259 ttyLine = networkDev+5;
1264 PamAccounting(verify->argv[0], d->name, d->utmpId, user,
1265 ttyLine, getpid(), USER_PROCESS, NULL);
1267 solaris_accounting(verify->argv[0], d->name, d->utmpId, user,
1268 ttyLine, getpid(), USER_PROCESS, NULL);
1273 #if !defined(sun) && !defined(CSRG_BASED)
1274 Account(d, user, NULL, getpid(), USER_PROCESS, status);
1279 * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1280 * setpenv() to set up the user's process environment and return
1281 * without execing. This allows us to set up the process environment
1282 * and proceed to the execute() call as do the other platforms.
1284 * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1285 * we have to pospone the setpenv() to the actual execute().
1289 * These defines are the tag locations in userEnviron.
1290 * IMPORTANT: changes to the locations of these tags in verify.c
1291 * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1293 #define SYS_ENV_TAG 0
1294 #define USR_ENV_TAG 3
1297 * Set the user's credentials: uid, gid, groups,
1298 * audit classes, user limits, and umask.
1301 if (setpcred(user, NULL) == -1)
1303 Debug("Can't set User's Credentials (user=%s)\n",user);
1308 char *usrTag, *sysTag;
1309 extern char **newenv;
1312 * Save pointers to tags. The setpenv() function clears the pointers
1313 * to the tags in userEnviron as a side-effect.
1315 sysTag = verify->userEnviron[SYS_ENV_TAG];
1316 usrTag = verify->userEnviron[USR_ENV_TAG];
1319 * Set the users process environment. Store protected variables and
1320 * obtain updated user environment list. This call will initialize
1323 #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1324 if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1326 Debug("Can't set process environment (user=%s)\n",user);
1331 * Restore pointers to tags.
1333 verify->userEnviron[SYS_ENV_TAG] = sysTag;
1334 verify->userEnviron[USR_ENV_TAG] = usrTag;
1337 * Free old userEnviron and replace with newenv from setpenv().
1339 freeEnv(verify->userEnviron);
1340 verify->userEnviron = newenv;
1350 if (PamSetCred( verify->argv[0],
1351 user, verify->uid, verify->gid) > 0 ) {
1352 Debug("Can't set User's Credentials (user=%s)\n",user);
1358 if ( solaris_setcred(verify->argv[0],
1359 user, verify->uid, verify->gid) > 0 ) {
1360 Debug("Can't set User's Credentials (user=%s)\n",user);
1363 #endif /* SUNAUTH */
1370 * HP BLS B1 session setup...
1372 * 1. look up user's protected account information.
1373 * 2. set the session sensitivity/clearance levels
1374 * 3. set the logical UID (LUID)
1378 Debug("BLS - Setting user's clearance, security level and luid.\n");
1379 set_auth_parameters(1, verify->argv);
1382 verify->user_name = user;
1383 strncpy(verify->terminal,d->name,15);
1384 verify->terminal[15]='\0';
1385 verify->pwd = getpwnam(user);
1387 if ( verify->pwd == NULL || strlen(user) == 0 ) {
1388 LogError(ReadCatalog(
1389 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1392 verify->prpwd= b1_pwd = getprpwnam(user);
1393 verify->uid = b1_pwd->ufld.fd_uid;
1395 if ( b1_pwd == NULL || strlen(user) == 0 ) {
1396 LogError(ReadCatalog(
1397 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1402 * This has already been done successfully by dtgreet
1403 * but we need to get all the information again for the
1406 if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1407 Debug("BLS - Could not verify sensitivity level.\n");
1408 LogError(ReadCatalog(
1409 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1413 if ( change_to_user(verify) != 1 ) {
1414 Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1415 LogError(ReadCatalog(
1416 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1421 Debug("BLS - Session setup complete.\n");
1428 * This should never fail since everything has been verified already.
1429 * If it does it must mean registry strangeness, so exit, and try
1433 if (!DoLogin (user, greet.password, d->name)) exit (1);
1436 * extract the SYSTYPE and ISP environment values and set into user's
1437 * environment. This is necessary since we do an execve below...
1440 verify->userEnviron = setEnv(verify->userEnviron, "SYSTYPE",
1443 verify->userEnviron = setEnv(verify->userEnviron, "ISP",
1446 #else /* ! __apollo */
1450 if ( IsVerifyName(VN_AFS) ) {
1451 pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1452 Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1454 initgroups(greet.name, verify->groups[2]);
1455 ngroups = getgroups(NGROUPS, groups);
1456 Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1457 for (i=0; i < ngroups; i++)
1458 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1460 if ((pagval != NOPAG) &&
1461 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1462 /* we will have to shift grouplist to make room for pag */
1463 if (ngroups+2 > NGROUPS)
1465 for (j=ngroups-1; j >= 0; j--) {
1466 groups[j+2] = groups[j];
1469 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1470 if (setgroups(ngroups, groups) == -1) {
1473 MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1478 # else /* ! __AFS */
1479 /* If SIA is enabled, the initgroups and setgid calls are redundant
1486 * if your system does not support "initgroups(3C)", use
1487 * the "setgroups()" call instead...
1490 # if (defined(__hpux) || defined(__osf__))
1491 initgroups(user, -1);
1493 setgroups (verify->ngroups, verify->groups);
1496 /* setpenv() will set gid for AIX */
1498 if(-1 == setgid (verify->groups[0])) {
1499 perror(strerror(errno));
1503 # else /* ! NGROUPS */
1505 /* setpenv() will set gid for AIX */
1507 setgid (verify->gid);
1510 # endif /* NGROUPS */
1516 setaudid(verify->audid);
1517 setaudproc(verify->audflg);
1520 /* setpenv() will set uid for AIX */
1522 if (setuid(verify->uid) != 0) {
1523 Debug( "Setuid failed for user %s, errno = %d\n", user, errno);
1524 LogError(ReadCatalog(
1525 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1531 #endif /* __apollo */
1534 } /* ends the else clause of if ( ISSECURE ) */
1540 * check home directory again...
1544 /* Don't need to do this if SIA is enabled, already been done.
1546 home = getEnv (verify->userEnviron, "HOME");
1548 if (chdir (home) == -1) {
1549 LogError (ReadCatalog(
1550 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1551 home, getEnv (verify->userEnviron, "USER"));
1552 if(-1 == chdir ("/")) {
1553 perror(strerror(errno));
1555 verify->userEnviron = setEnv(verify->userEnviron,
1558 else if(!failsafe) {
1559 strcpy(lastsessfile,home); /* save user's last session */
1560 strcat(lastsessfile,LAST_SESSION_FILE);
1561 if((lastsession = fopen(lastsessfile,"w")) == NULL)
1562 Debug("Unable to open file for writing: %s\n",lastsessfile);
1564 fputs(verify->argv[0],lastsession);
1565 fclose(lastsession);
1572 SetUserAuthorization (d, verify);
1578 bzero(greet.password, strlen(greet.password));
1582 * Write login information to a file
1583 * The file name should really be settable by some kind of resource
1584 * but time is short so we hard-wire it to ".dtlogininfo".
1586 if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1587 Debug("Unable to write \".dtlogininfo\"\n");
1589 /* extra debugging */
1590 if(!dump_sec_debug_info(verify)) {
1591 Debug("Something wrong with environment\n");
1594 # endif /* ! NDEBUG */
1602 Debug ("Executing session %s\n", verify->argv[0]);
1603 execute (verify->argv, verify->userEnviron);
1604 LogError(ReadCatalog(
1605 MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1609 LogError(ReadCatalog(
1610 MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1617 * specify a font for the multi-byte languages...
1621 lang = getEnv (verify->userEnviron, "LANG");
1628 failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1630 failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1631 #elif defined (USL) || defined(__uxp__)
1632 failsafeArgv[i++] = "/usr/X/bin/xterm";
1633 #elif defined(__hpux)
1634 failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1635 #elif defined(__OpenBSD__)
1636 failsafeArgv[i++] = "/usr/X11R6/bin/xterm";
1637 #elif defined(__NetBSD__)
1638 failsafeArgv[i++] = "/usr/X11R7/bin/xterm";
1639 #elif defined(__FreeBSD__)
1640 failsafeArgv[i++] = "/usr/local/bin/xterm";
1642 failsafeArgv[i++] = "/usr/bin/X11/xterm";
1644 failsafeArgv[i++] = "-geometry";
1645 failsafeArgv[i++] = "80x10";
1646 failsafeArgv[i++] = "-bg";
1647 failsafeArgv[i++] = "white";
1648 failsafeArgv[i++] = "-fg";
1649 failsafeArgv[i++] = "black";
1651 /* aixterm requires -lang option. */
1652 failsafeArgv[i++] = "-lang";
1653 failsafeArgv[i++] = lang;
1655 failsafeArgv[i++] = "-fn";
1657 if (font == NULL) font = "fixed";
1658 failsafeArgv[i++] = font;
1661 failsafeArgv[i++] = "-e";
1662 failsafeArgv[i++] = "/bin/passwd";
1663 #if defined (__apollo) || defined(__PASSWD_ETC)
1664 failsafeArgv[i++] = "-n";
1666 failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1669 failsafeArgv[i++] = d->failsafeClient;
1671 failsafeArgv[i++] = "-C";
1673 failsafeArgv[i++] = "-ls";
1676 failsafeArgv[i++] = "-fn";
1677 failsafeArgv[i++] = font;
1681 failsafeArgv[i] = 0;
1682 Debug ("Executing failsafe session\n", failsafeArgv[0]);
1683 execute (failsafeArgv, verify->userEnviron);
1686 Debug ("StartSession(): fork failed\n");
1687 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1691 Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1698 static jmp_buf tenaciousClient;
1701 waitAbort( int arg )
1703 longjmp (tenaciousClient, 1);
1706 #if defined(SYSV) || defined(SVR4)
1708 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1712 AbortClient( int pid )
1721 for (i = 0; i < 4; i++) {
1722 if (killpg (pid, sig) == -1) {
1725 LogError(ReadCatalog(
1726 MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1732 if (!setjmp (tenaciousClient)) {
1733 (void) signal (SIGALRM, waitAbort);
1734 (void) alarm ((unsigned) 10);
1735 retId = wait ((waitType *) 0);
1736 (void) alarm ((unsigned) 0);
1737 (void) signal (SIGALRM, SIG_DFL);
1741 signal (SIGALRM, SIG_DFL);
1748 source( struct verify_info *verify, char *file )
1754 if (file && file[0]) {
1755 Debug ("Source(): %s\n", file);
1756 switch (pid = fork ()) {
1761 execute (args, verify->systemEnviron);
1762 LogError(ReadCatalog(
1763 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1766 Debug ("Source(): fork failed\n");
1767 LogError(ReadCatalog(
1768 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1772 while (wait (&result) != pid)
1776 return waitVal (result);
1781 /* returns 0 on failure, -1 on out of mem, and 1 on success */
1783 execute(char **argv, char **environ )
1787 * make stdout follow stderr to the log file...
1792 session_execve (argv[0], argv, environ);
1795 * In case this is a shell script which hasn't been made executable
1796 * (or this is a SYSV box), do a reasonable thing...
1800 /* errno is EACCES if not executable */
1801 if (errno == ENOEXEC || errno == EACCES) {
1803 if (errno == ENOEXEC) {
1805 char program[1024], *e, *p, *optarg;
1807 char **newargv, **av;
1811 * emulate BSD kernel behaviour -- read
1812 * the first line; check if it starts
1813 * with "#!", in which case it uses
1814 * the rest of the line as the name of
1815 * program to run. Else use "/bin/sh".
1817 f = fopen (argv[0], "r");
1820 if (fgets (program, sizeof (program) - 1, f) == NULL)
1826 e = program + strlen (program) - 1;
1829 if (!strncmp (program, "#!", 2)) {
1831 while (*p && isspace (*p))
1834 while (*optarg && !isspace (*optarg))
1840 while (*optarg && isspace (*optarg));
1847 Debug ("Shell script execution: %s (optarg %s)\n",
1848 p, optarg ? optarg : "(null)");
1849 for (av = argv, argc = 0; *av; av++, argc++)
1851 newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1858 while (*av++ = *argv++)
1860 session_execve (newargv[0], newargv, environ);
1869 /*****************************************************************************
1872 * Invoke the Greeter process and wait for completion. If the user was
1873 * successfully verified, return to the calling process. If the user
1874 * selected a restart or abort option, or there was an error invoking the
1875 * Greeter, exit this entire process with appropriate status.
1877 *****************************************************************************/
1881 extern int session_set;
1882 extern char *progName; /* Global argv[0]; dtlogin name and path */
1884 int response[2], request[2];
1886 /* Fixes problem with dtlogin signal handling */
1887 static int greeterPid = 0;
1888 static struct display *greeter_d = NULL;
1893 Debug("Caught SIGHUP\n");
1896 Debug("Killing greeter process: %d\n", greeterPid);
1897 kill(greeterPid, SIGHUP);
1900 SessionExit(greeter_d, REMANAGE_DISPLAY);
1902 exit(REMANAGE_DISPLAY);
1906 RunGreeter( struct display *d, struct greet_info *greet,
1907 struct verify_info *verify )
1914 static char msg[MSGSIZE];
1918 struct greet_state state = {};
1925 # define U_NAMELEN sizeof(rgy_$name_t)
1929 static char name_short[U_NAMELEN];
1935 char *argv[] = { "dtlogin", 0 };
1936 char *hostName = NULL;
1937 char *loginName = NULL;
1944 if (d->serverPid == -1)
1947 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
1948 loginName, d->name, 1, NULL);
1949 if (siaStatus != SIASUCCESS)
1951 Debug("sia_ses_init failure status %d\n", siaStatus);
1958 if (!setjmp (abortSession)) {
1959 signal(SIGTERM, catchTerm);
1962 * We've changed dtlogin to pass HUP's down to the children
1963 * so ignore any HUP's once the client has started.
1966 signal(SIGHUP, catchHUP);
1969 * set up communication pipes...
1972 if(-1 == pipe(response)) {
1973 perror(strerror(errno));
1975 if(-1 == pipe(request)) {
1976 perror(strerror(errno));
1981 switch (greeterPid = fork ()) {
1985 * pass some information in the environment...
1989 sprintf(msg,"%d", d->grabServer);
1990 env = setEnv(env, GRABSERVER, msg);
1992 sprintf(msg,"%d", d->grabTimeout);
1993 env = setEnv(env, GRABTIMEOUT, msg);
1996 if (timeZone && strlen(timeZone) > 0 )
1997 env = setEnv(env, "TZ", timeZone);
1999 if (errorLogFile && errorLogFile[0])
2000 env = setEnv(env, ERRORLOG, errorLogFile);
2003 env = setEnv(env, "XAUTHORITY", d->authFile);
2006 env = setEnv(env, DTLITE, "True");
2009 env = setEnv(env, SESSION, d->session);
2012 env = setEnv(env, SESSION_SET, "True");
2014 if (d->pmSearchPath)
2015 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
2017 if (d->bmSearchPath)
2018 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
2020 #if defined (__KERBEROS) || defined (__AFS)
2021 if (d->verifyName) {
2022 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2023 (strcmp(d->verifyName, VN_KRB) == 0) ) {
2025 env = setEnv(env, VERIFYNAME, d->verifyName );
2028 LogError(ReadCatalog(
2029 MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2031 d->verifyName = NULL;
2036 if((path = getenv("NLSPATH")) != NULL)
2037 env = setEnv(env, "NLSPATH", path);
2039 env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2044 * ping remote displays...
2048 if (d->displayType.location == Local) {
2049 GettyRunning(d); /* refresh gettyState */
2050 if (d->gettyState != DM_GETTY_USER)
2051 env = setEnv(env, LOCATION, "local");
2054 sprintf(msg,"%d", d->pingInterval);
2055 env = setEnv(env, PINGINTERVAL, msg);
2057 sprintf(msg,"%d", d->pingTimeout);
2058 env = setEnv(env, PINGTIMEOUT, msg);
2062 if ( d->langList && strlen(d->langList) > 0 )
2063 env = setEnv(env, LANGLIST, d->langList);
2064 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2065 else if (strlen(languageList) > 0 )
2066 env = setEnv(env, LANGLIST, languageList);
2067 #endif /* ENABLE_DYNAMIC_LANGLIST */
2070 char *language = NULL;
2072 #if defined (ENABLE_DYNAMIC_LANGLIST)
2073 language = d->language;
2074 #endif /* ENABLE_DYNAMIC_LANGLIST */
2076 if ( d->language && strlen(d->language) > 0 )
2077 env = setLang(d, env, language);
2080 if((path = getenv("XKEYSYMDB")) != NULL)
2081 env = setEnv(env, "XKEYSYMDB", path);
2084 if((path = getenv("OPENWINHOME")) != NULL)
2085 env = setEnv(env, "OPENWINHOME", path);
2090 * set environment for Domain machines...
2092 env = setEnv(env, "ENVIRONMENT", "bsd");
2093 env = setEnv(env, "SYSTYPE", "bsd4.3");
2097 Debug ("Greeter environment:\n");
2099 Debug ("End of Greeter environment:\n");
2102 * Writing to file descriptor 1 goes to response pipe instead.
2105 dupfp = dup(response[1]);
2107 perror(strerror(errno));
2113 * Reading from file descriptor 0 reads from request pipe instead.
2116 dupfp2 = dup(request[0]);
2118 perror(strerror(errno));
2126 * figure out path to dtgreet...
2129 snprintf(msg, sizeof(msg), "%s", progName);
2131 if ((p = (char *) strrchr(msg, '/')) == NULL)
2136 strcat(msg,"dtgreet");
2138 execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2139 LogError(ReadCatalog(
2140 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2142 exit (NOTIFY_ABORT_DISPLAY);
2145 Debug ("Fork of Greeter failed.\n");
2146 LogError(ReadCatalog(
2147 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2152 exit (UNMANAGE_DISPLAY);
2155 Debug ("Greeter started\n");
2157 close(response[1]); /* Close write end of response pipe */
2158 close(request[0]); /* Close read end of request pipe */
2162 * Retrieve information from greeter and authenticate.
2164 globalDisplayName = d->name;
2165 state.id = GREET_STATE_ENTER;
2166 state.waitForResponse = FALSE;
2170 * atexit() registers this function to be called if exit() is
2171 * called. This is needed because in enhanced security mode, SIA
2172 * may call exit() whn the user fails to enter or change a
2175 sia_greeter_pid = greeterPid;
2176 if (!sia_exit_proc_reg)
2178 atexit(KillGreeter);
2179 sia_exit_proc_reg = TRUE;
2182 siaGreeterInfo.d = d;
2183 siaGreeterInfo.greet = greet;
2184 siaGreeterInfo.verify = verify;
2185 siaGreeterInfo.state = &state;
2186 siaGreeterInfo.status = TRUE;
2189 while(siaStatus != SIASUCCESS)
2191 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2193 Debug ("RunGreeter: before sia_ses_authent\n");
2194 dt_in_sia_ses_authent = True;
2195 siaStatus = sia_ses_authent(SiaManageGreeter, NULL,
2197 dt_in_sia_ses_authent = False;
2198 Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2200 if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2202 state.id = GREET_STATE_ERRORMESSAGE;
2203 state.vf = VF_INVALID;
2204 ManageGreeter(d, greet, verify, &state);
2206 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2209 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2211 sia_ses_release(&siaHandle);
2215 Debug("RunGreeter: before sia_ses_estab\n");
2216 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2217 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2220 if (!siaGreeterInfo.status)
2223 if (siaStatus == SIASUCCESS)
2225 Debug("RunGreeter: before sia_ses_launch\n");
2226 siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2227 Debug("RunGreeter: after sia_ses_launch status = %d\n",
2230 if (!siaGreeterInfo.status)
2233 if (siaStatus != SIASUCCESS)
2235 Debug("RunGreeter: sia_ses_launch failure\n");
2236 /* establish & launch failures do a release */
2238 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
2239 loginName, d->name, 1, NULL);
2240 if (siaStatus != SIASUCCESS)
2242 Debug("sia_ses_init failure status %d\n", siaStatus);
2243 exit(RESERVER_DISPLAY);
2248 * sia_ses_launch() wil probably seteuid to that of the
2249 * user, but we don't want that now.
2253 * extract necessary info from SIA context struct
2257 if (siaStatus == SIASUCCESS)
2258 CopySiaInfo(siaHandle, greet);
2259 sia_ses_release(&siaHandle);
2261 state.id = GREET_STATE_TERMINATEGREET;
2262 if (siaGreeterInfo.status)
2264 while (ManageGreeter(d, greet, verify, &state))
2267 sia_greeter_pid = 0;
2269 while (ManageGreeter(d, greet, verify, &state))
2274 * Wait for Greeter to end...
2277 pid = wait (&status);
2278 if (pid == greeterPid)
2284 * Greeter exited. Check return code...
2287 Debug("Greeter return status; exit = %d, signal = %d\n",
2288 waitCode(status), waitSig(status));
2292 * remove authorization file if used...
2295 if (d->authorizations && d->authFile &&
2296 waitVal(status) != NOTIFY_LANG_CHANGE
2298 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2303 Debug ("Done with authorization file %s, removing\n",
2305 (void) unlink (d->authFile);
2310 if(waitVal(status) > NOTIFY_ALT_DTS)
2311 d->sessionType = waitVal(status);
2314 switch (waitVal(status)) {
2315 case NOTIFY_FAILSAFE:
2316 greet->string = "failsafe";
2318 case NOTIFY_PASSWD_EXPIRED:
2319 greet->string = "password";
2324 case NOTIFY_LAST_DT:
2325 d->sessionType = waitVal(status);
2331 Debug("waitVal - status is %d\n", waitVal(status));
2332 if(waitVal(status) > NOTIFY_ALT_DTS)
2333 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2335 notify_dt = waitVal(status);
2337 switch (notify_dt) {
2338 case NOTIFY_FAILSAFE:
2339 case NOTIFY_PASSWD_EXPIRED:
2343 case NOTIFY_LAST_DT:
2344 case NOTIFY_ALT_DTS:
2346 if (NULL == greet->name) return;
2349 * greet->name, greet->password set in ManageGreeter().
2351 Debug("Greeter returned name '%s'\n", greet->name);
2354 greet->name_full = greet->name;
2355 /* get just person name out of full SID */
2357 while (i < sizeof(rgy_$name_t)
2358 && greet->name_full[i] != '.'
2359 && greet->name_full[i] != '\0') {
2360 name_short[i] = greet->name_full[i];
2363 name_short[i] = '\0';
2364 greet->name = name_short;
2369 * groups[] set in Authenticate().
2371 if ( IsVerifyName(VN_AFS) ) {
2372 verify->groups[0] = groups[0];
2373 verify->groups[1] = groups[1];
2374 Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2375 Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2381 * sensitivityLevel set in BLS_Verify()
2383 greet->b1security = sensitivityLevel;
2386 Verify(d, greet, verify);
2390 Debug ("Greeter Xlib error or SIGTERM\n");
2391 SessionExit(d, OPENFAILED_DISPLAY);
2393 case NOTIFY_RESTART:
2394 Debug ("Greeter requested RESTART_DISPLAY\n");
2395 SessionExit(d, RESERVER_DISPLAY);
2397 case NOTIFY_ABORT_DISPLAY:
2398 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2399 SessionExit(d, UNMANAGE_DISPLAY);
2401 case NOTIFY_NO_WINDOWS:
2402 Debug ("Greeter requested NO_WINDOWS mode\n");
2403 if (d->serverPid >= 2)
2405 * Don't do a SessionExit() here since that causes
2406 * the X-server to be reset. We know we are going to
2407 * terminate it anyway, so just go do that...
2409 exit(SUSPEND_DISPLAY);
2413 case NOTIFY_LANG_CHANGE:
2414 Debug ("Greeter requested LANG_CHANGE\n");
2417 * copy requested language into display struct "d". Note,
2418 * this only happens in this child's copy of "d", not in
2419 * the master struct. When the user logs out, the
2420 * resource-specified language (if any) will reactivate.
2423 Debug("Greeter returned language '%s'\n", d->language);
2425 Debug("Greeter returned language (NULL)\n");
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 if(-1 == write(request[1], phdr, phdr->length)) {
2935 perror(strerror(errno));
2941 RequestHeader *preqhdr,
2947 ResponseHeader *phdr = (ResponseHeader *)buf;
2949 if (preqhdr) TellGreeter(preqhdr);
2951 phdr->opcode = REQUEST_OP_NONE;
2953 count = read(response[0], buf, sizeof(*phdr));
2955 if (count == sizeof(*phdr))
2958 * Calculate amount of data after header.
2960 remainder = phdr->length - sizeof(*phdr);
2964 * Read remainder of response.
2966 count += read(response[0], buf+sizeof(*phdr), remainder);
2971 if (debugLevel) PrintResponse(phdr, count);
2980 ResponseHeader *phdr,
2983 char *opstr = "UNKNOWN";
2987 Debug("opcode = (EOF)\n");
2991 switch(phdr->opcode)
2993 case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2994 case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2995 case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2996 case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2997 case REQUEST_OP_LANG: opstr = "LANG"; break;
2998 case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
3001 Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
3002 Debug(" reserved = %d\n", phdr->reserved);
3003 Debug(" length = %d\n", phdr->length);
3005 switch(phdr->opcode)
3007 case REQUEST_OP_EXIT: break;
3008 case REQUEST_OP_LANG:
3009 Debug(" offLang=%d\n", ((ResponseLang *)phdr)->offLang);
3010 Debug(" lang='%s'\n",
3011 ((char *)phdr)+((ResponseLang *)phdr)->offLang);
3013 case REQUEST_OP_MESSAGE: break;
3014 case REQUEST_OP_CHPASS: break;
3015 case REQUEST_OP_CHALLENGE:
3016 Debug(" offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
3017 Debug(" response='%s'\n",
3018 ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
3020 case REQUEST_OP_DEBUG:
3021 Debug(" offString=%d\n", ((ResponseDebug *)phdr)->offString);
3022 Debug(" string='%s'\n",
3023 ((char *)phdr)+((ResponseDebug *)phdr)->offString);
3031 /***************************************************************************
3035 * generate kerberos ticket file name. Name is returned in the static
3036 * global variable "krb_ticket_string".
3038 ***************************************************************************/
3041 SetTicketFileName(uid_t uid)
3050 * generate ticket file pathname (/tmp/tkt<uid>.<host>) ...
3053 if (env = (char *)getenv("KRBTKFILE")) {
3054 (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3055 krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3058 if (gethostname(lhost, sizeof(lhost)) != -1) {
3059 if (p = index(lhost, '.')) *p = '\0';
3060 (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3062 /* 32 bits of signed integer will always fit in 11 characters
3063 (including the sign), so no need to worry about overflow */
3064 (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3069 #endif /* __KERBEROS */
3071 #if defined (_AIX) && !defined (_POWER)
3073 /***************************************************************************
3077 * If this is an authenticated process (LOGNAME set), set user's
3078 * process environment by calling setpenv().
3080 * If this is not an authenticated process, just call execve()
3082 ***************************************************************************/
3091 char *user = getEnv (envp, "LOGNAME");
3095 rc = execve(path, argv, envp);
3099 char *usrTag, *sysTag;
3102 * Save pointers to tags. The setpenv() function clears the pointers
3103 * to the tags in userEnviron as a side-effect.
3105 sysTag = envp[SYS_ENV_TAG];
3106 usrTag = envp[USR_ENV_TAG];
3109 * Set the users process environment. This call execs arvg so it
3110 * should not return. It it should return, restore the envp tags.
3112 rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3115 * Restore pointers to tags.
3117 envp[SYS_ENV_TAG] = sysTag;
3118 envp[USR_ENV_TAG] = usrTag;
3123 #endif /* _AIX && !_POWER */
3127 /* collect the SIA parameters from a window system. */
3129 static int SiaManageGreeter(
3132 unsigned char *title,
3138 RequestMessage greeter_message;
3139 char msg_buffer[256];
3140 } greeter_msg_and_buffer;
3141 RequestForm *request_form;
3149 if (rendition == SIAFORM && dt_in_sia_ses_authent
3150 && (num_prompts == 2))
3152 /* Normal login, Password case */
3153 Debug ("SIAFORM Normal login, Password case\n");
3154 while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3155 && siaGreeterInfo.state->id != GREET_STATE_EXIT
3156 && (siaGreeterInfo.status = ManageGreeter(
3157 siaGreeterInfo.d, siaGreeterInfo.greet,
3158 siaGreeterInfo.verify, siaGreeterInfo.state)))
3161 if (!siaGreeterInfo.status
3162 || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3163 return(SIACOLABORT);
3165 strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name,
3166 prompt[0].max_result_length);
3167 strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3168 prompt[1].max_result_length);
3175 ResponseForm *response_form;
3180 Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3183 Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3186 Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3189 Debug("SIAFORM num_prompts = %d\n", num_prompts);
3193 /* need to display form */
3195 req_form_size = sizeof(RequestForm)
3196 + strlen((const char *)title) + 1;
3197 for (i=0; i<num_prompts; i++)
3198 req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3199 request_form = (RequestForm *) alloca(req_form_size);
3201 siaGreeterInfo.state->id = GREET_STATE_FORM;
3202 siaGreeterInfo.state->request = (RequestHeader *)request_form;
3203 /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3205 request_form->hdr.opcode = REQUEST_OP_FORM;
3206 request_form->hdr.reserved = 0;
3207 request_form->hdr.length = req_form_size;
3208 request_form->num_prompts = num_prompts;
3209 request_form->rendition = rendition;
3210 request_form->offTitle = sizeof(RequestForm);
3211 request_form->offPrompts = sizeof(RequestForm) +
3212 strlen((const char *)title) + 1;
3213 strcpy((char *)request_form + request_form->offTitle,
3214 (const char *)title);
3216 pmpt_ptr = (char *)request_form + request_form->offPrompts;
3217 for (i=0; i<num_prompts; i++)
3219 if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3223 Debug(" prompt[%d]: %s\n", i, prompt[i].prompt);
3224 strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3225 pmpt_ptr += strlen((const char *)prompt[i].prompt);
3227 request_form->visible[i] =
3228 (prompt[i].control_flags & SIARESINVIS) ? False : True;
3231 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3232 siaGreeterInfo.greet,
3233 siaGreeterInfo.verify,
3234 siaGreeterInfo.state);
3236 response_form = (ResponseForm *)siaGreeterInfo.state->response;
3237 res_ptr = (char *)response_form + response_form->offAnswers;
3238 for (i = 0; i < response_form->num_answers; i++)
3240 if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3243 prompt[i].result = (unsigned char *)1;
3245 prompt[i].result = NULL;
3249 strcpy((char *)prompt[0].result, res_ptr);
3251 res_ptr += strlen(res_ptr) + 1;
3253 if (!response_form->collect_status)
3254 siaGreeterInfo.status = FALSE;
3260 Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3262 siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3263 siaGreeterInfo.state->request = (RequestHeader *)
3264 &greeter_msg_and_buffer.greeter_message;
3265 siaGreeterInfo.state->vf = VF_MESSAGE;
3266 siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3268 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3269 siaGreeterInfo.greet,
3270 siaGreeterInfo.verify,
3271 siaGreeterInfo.state);
3274 return(SIACOLABORT);
3277 if (!siaGreeterInfo.status)
3278 return(SIACOLABORT);
3279 return(SIACOLSUCCESS);
3282 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3285 greet->name = malloc(strlen(siaHandle->name) + 1);
3286 strcpy (greet->name, siaHandle->name);
3288 greet->password = malloc(strlen(siaHandle->password) + 1);
3289 strcpy (greet->password, siaHandle->password);
3294 static void KillGreeter( void )
3296 if (sia_greeter_pid)
3297 AbortClient(sia_greeter_pid);
3298 sia_greeter_pid = 0;