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));
760 resources = _ExpandLang(dirname[j], "C");
761 if (access (resources, R_OK) != 0)
763 Debug("LoadAltDtsResources- cant access %s.\n", resources);
764 Debug("\t %s.\n", strerror(errno));
767 snprintf(dirname[j], sizeof(dirname[j]), "%s", resources);
770 snprintf(dirname[j], sizeof(dirname[j]), "%s", resources);
771 Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
780 * Create a list of the alt DT files
782 * NOTE - an assumption made here is that files in /etc/dt
783 * should take precedence over files in /usr/dt. This precedence
784 * is maintained during the sort becase /etc/dt will come before
788 for(j = 0; j < 2 ; ++j) {
790 if((dirp = opendir(dirname[j])) != NULL) {
792 while((dp = readdir(dirp)) != NULL) {
794 if ((strcmp(dp->d_name, DOT) != 0) &&
795 (strcmp(dp->d_name, DOTDOT) != 0)) {
797 sprintf (res_file, "%s%s", dirname[j],dp->d_name);
798 if ((access (res_file, R_OK)) != 0)
800 Debug("LoadAltDtsResources- cant access %s.\n",
802 Debug("\t %s.\n", strerror(errno));
806 if (file_count == 0) {
807 file_list = malloc (list_incr * sizeof(char *));
808 num_allocated += list_incr;
810 if (file_count + 1 > num_allocated) {
811 num_allocated += list_incr;
812 file_list = realloc (file_list,
813 num_allocated * sizeof(char *));
815 file_list[file_count] = strdup (res_file);
824 qsort (file_list, file_count, sizeof (char *), FileNameCompare);
826 for (j = 0; j < file_count ; j++) {
828 userDb = XrmGetFileDatabase(file_list[j]);
829 XrmMergeDatabases(userDb,&XresourceDB);
831 if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
832 "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
835 * remove the trailing spaces
837 if(strchr(rmvalue.addr,' '))
838 snprintf(tempbuf, sizeof(tempbuf), "%s", strtok(rmvalue.addr," "));
840 snprintf(tempbuf, sizeof(tempbuf), "%s", rmvalue.addr);
842 if ((strcmp(tempbuf, "True") == 0) ||
843 (strcmp(tempbuf, "TRUE") == 0)) {
845 if ( XrmGetResource(XresourceDB,
846 "Dtlogin*altDtKey", "Dtlogin*AltDtKey",
847 &rmtype, &rmvalue ) ) {
849 sprintf(altdtres,"Dtlogin*altDtKey%d",i);
850 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
855 if ( XrmGetResource(XresourceDB,
856 "Dtlogin*altDtName", "Dtlogin*AltDtName",
857 &rmtype, &rmvalue ) ) {
858 sprintf(altdtres,"Dtlogin*altDtName%d",i);
859 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
861 if ( XrmGetResource(XresourceDB,
862 "Dtlogin*altDtStart", "Dtlogin*AltDtStart",
863 &rmtype, &rmvalue ) ) {
864 sprintf(altdtres,"Dtlogin*altDtStart%d",i);
865 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
867 if ( XrmGetResource(XresourceDB,
868 "Dtlogin*altDtLogo", "Dtlogin*AltDtLogo",
869 &rmtype, &rmvalue ) ) {
870 sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
871 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
877 sprintf(tempbuf,"%d",i);
878 XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf);
880 if (file_count > 0) {
881 for (i = 0; i < file_count; i++) {
882 Debug ("Loading resource file: %s\n", file_list[i]);
892 * Function Name: _ExpandLang
896 * This function takes the string "string", searches for occurences of
897 * "%L" in the string and if found, the "%L" is substituted with
898 * the value of the $LANG environment variable.
900 * If $LANG is not defined, the %L is replace with NULL.
904 * _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
908 * ret_string = _ExpandLang (string);
910 * char *ret_string; Returns NULL if "string" is NULL or it points
911 * to the expanded string.
913 * char *string; The first part of the pathname. Typically
914 * the directory containing the item of interest.
916 * Note: The caller is responsible for free'ing the returned string.
938 * Count the number of expansions that will occur.
942 for (n = 0, pch = string ; pch != NULL ; ) {
943 if ((pch = strchr (pch, '%')) != NULL) {
950 return (strdup(string));
953 * We should really be calling setlocale to determine the "default"
954 * locale but setlocale's return value is not standardized across
955 * the various vendor platforms nor is it consistent within differnt
956 * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
957 * HP-UX 10.0). The "right" call would be the following line:
959 * if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
961 * Here we hard code the default to "C" instead of leaving it NULL.
963 if (lang || (lang = getenv ("LANG")) || (lang = "C"))
964 lang_len = strlen (lang);
967 * Create the space needed.
969 tmp_len = strlen (string) + (n * lang_len) + n + 1;
970 tmp = (char *) malloc (tmp_len);
971 for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
975 while (pch != NULL) {
978 if ((pch = strchr (pch, '%')) != NULL) {
983 (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
985 else if ((pch != NULL) && *pch == 'L') {
987 if (((pch - trail) >=2) && (*(pch-2) == '/'))
989 * Remove the "/" as well as the "%L".
991 (void) strncat (tmp, trail, (pch - trail) - 2);
993 (void) strncat (tmp, trail, (pch - trail) - 1);
997 * Remove the "%L" and then append the LANG.
999 (void) strncat (tmp, trail, (pch - trail) - 1);
1000 (void) strcat (tmp, lang);
1004 (void) strncat (tmp, trail, (pch - trail) + 1);
1011 * A '%' was not found.
1013 (void) strcat (tmp, trail);
1022 SetupDisplay (struct display *d)
1024 char **env = 0, **crt_systemEnviron;
1026 if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1028 crt_systemEnviron = verify.systemEnviron;
1029 env = systemEnv (d, (char *) 0, (char *) 0);
1030 if (d->authFile && strlen(d->authFile) > 0 )
1031 env = setEnv( env, "XAUTHORITY", d->authFile );
1032 if(d->displayType.location == Local)
1033 env = setEnv (env, LOCATION, "local");
1035 env = setEnv (env, LOCATION, "remote");
1036 verify.systemEnviron = env;
1037 source (&verify, d->setup);
1038 verify.systemEnviron = crt_systemEnviron;
1045 DeleteXloginResources( struct display *d, Display *dpy )
1047 XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1050 #if 0 /* dead code: transferred to Dtgreet */
1052 static jmp_buf syncJump;
1057 longjmp (syncJump, 1);
1061 SecureDisplay (d, dpy)
1065 Debug ("SecureDisplay():\n");
1066 signal (SIGALRM, syncTimeout);
1067 if (setjmp (syncJump)) {
1068 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1070 SessionExit (d, RESERVER_DISPLAY);
1072 alarm ((unsigned) d->grabTimeout);
1073 Debug ("Before XGrabServer()\n");
1075 if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1076 GrabModeAsync, CurrentTime) != GrabSuccess)
1079 signal (SIGALRM, SIG_DFL);
1080 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1082 SessionExit (d, RESERVER_DISPLAY);
1084 Debug ("XGrabKeyboard() succeeded\n");
1086 signal (SIGALRM, SIG_DFL);
1090 XUngrabServer (dpy);
1093 Debug ("Done secure %s\n", d->name);
1096 UnsecureDisplay (d, dpy)
1100 Debug ("Unsecure display %s\n", d->name);
1102 XUngrabServer (dpy);
1111 release_aix_lic(void)
1114 * Release AIX iFOR/LS license (if any)
1122 release_me.request_type = -1;
1123 release_me.login_pid = getpid();
1124 if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1126 write(fd, &release_me, sizeof(release_me));
1129 Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1137 SessionExit( struct display *d, int status )
1146 /* make sure the server gets reset after the session is over */
1147 if (d->serverPid >= 2) {
1148 Debug("Reseting server: pid %d signal %d\n",
1149 d->serverPid, d->resetSignal);
1151 if (d->terminateServer == 0 && d->resetSignal)
1152 kill (d->serverPid, d->resetSignal);
1157 Debug("Exiting Session with status: %d\n", status);
1162 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1165 char currentdir[PATH_MAX+1];
1166 char *failsafeArgv[20];
1167 char *user; /* users name */
1168 char *lang, *font; /* failsafe LANG and font */
1171 int failsafe = FALSE; /* do we run the failsafe session? */
1172 int password = FALSE; /* do we run /bin/passwd? */
1175 char lastsessfile[MAXPATHLEN];
1178 struct pr_passwd *b1_pwd;
1182 #define NOPAG 0xffffffff
1184 long ngroups, groups[NGROUPS];
1190 Debug ("StartSession %s: ", verify->argv[0]);
1191 for (f = verify->argv; *f; f++) {
1193 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1194 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1198 if (verify->userEnviron) {
1199 for (f = verify->userEnviron; *f; f++)
1204 user = getEnv (verify->userEnviron, "USER");
1206 switch (pid = fork ()) {
1209 /* Force a failsafe session if we can't touch the home directory
1210 * SIA has already attempted to chdir to HOME, and the current dir
1211 * will be set to / if it failed. We just check to see if the HOME
1212 * path is our current directory or not.
1214 home = getEnv (verify->userEnviron, "HOME");
1215 getcwd(currentdir, PATH_MAX+1);
1216 Debug("Current directory is: %s\n", currentdir);
1220 * The following little check doesn't really work. For example,
1221 * here at the XC, NIS reports my home directory as
1222 * "/site/guests/montyb" while getcwd comes up with
1223 * "/net/nexus/site/guests/montyb".
1225 if (strcmp(home, currentdir)) {
1226 Debug("Can't access home directory, setting failsafe to TRUE\n");
1228 LogError (ReadCatalog(
1229 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1230 home, getEnv (verify->userEnviron, "USER"));
1231 verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1239 * do process accounting...
1241 #if defined(PAM) || defined(SUNAUTH)
1243 char* ttyLine = d->gettyLine;
1245 # ifdef DEF_NETWORK_DEV
1247 * If location is not local (remote XDMCP dtlogin) and
1248 * remote accouting is enabled (networkDev start with /dev/...)
1249 * Set tty line name to match network device for accouting.
1250 * Unless the resource was specifically set, default is value
1251 * of DEF_NETWORK_DEV define (/dev/dtremote)
1254 if ( d->displayType.location != Local &&
1255 networkDev && !strncmp(networkDev,"/dev/",5)) {
1256 ttyLine = networkDev+5;
1261 PamAccounting(verify->argv[0], d->name, d->utmpId, user,
1262 ttyLine, getpid(), USER_PROCESS, NULL);
1264 solaris_accounting(verify->argv[0], d->name, d->utmpId, user,
1265 ttyLine, getpid(), USER_PROCESS, NULL);
1270 #if !defined(sun) && !defined(CSRG_BASED)
1271 Account(d, user, NULL, getpid(), USER_PROCESS, status);
1276 * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1277 * setpenv() to set up the user's process environment and return
1278 * without execing. This allows us to set up the process environment
1279 * and proceed to the execute() call as do the other platforms.
1281 * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1282 * we have to pospone the setpenv() to the actual execute().
1286 * These defines are the tag locations in userEnviron.
1287 * IMPORTANT: changes to the locations of these tags in verify.c
1288 * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1290 #define SYS_ENV_TAG 0
1291 #define USR_ENV_TAG 3
1294 * Set the user's credentials: uid, gid, groups,
1295 * audit classes, user limits, and umask.
1298 if (setpcred(user, NULL) == -1)
1300 Debug("Can't set User's Credentials (user=%s)\n",user);
1305 char *usrTag, *sysTag;
1306 extern char **newenv;
1309 * Save pointers to tags. The setpenv() function clears the pointers
1310 * to the tags in userEnviron as a side-effect.
1312 sysTag = verify->userEnviron[SYS_ENV_TAG];
1313 usrTag = verify->userEnviron[USR_ENV_TAG];
1316 * Set the users process environment. Store protected variables and
1317 * obtain updated user environment list. This call will initialize
1320 #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1321 if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1323 Debug("Can't set process environment (user=%s)\n",user);
1328 * Restore pointers to tags.
1330 verify->userEnviron[SYS_ENV_TAG] = sysTag;
1331 verify->userEnviron[USR_ENV_TAG] = usrTag;
1334 * Free old userEnviron and replace with newenv from setpenv().
1336 freeEnv(verify->userEnviron);
1337 verify->userEnviron = newenv;
1347 if (PamSetCred( verify->argv[0],
1348 user, verify->uid, verify->gid) > 0 ) {
1349 Debug("Can't set User's Credentials (user=%s)\n",user);
1355 if ( solaris_setcred(verify->argv[0],
1356 user, verify->uid, verify->gid) > 0 ) {
1357 Debug("Can't set User's Credentials (user=%s)\n",user);
1360 #endif /* SUNAUTH */
1367 * HP BLS B1 session setup...
1369 * 1. look up user's protected account information.
1370 * 2. set the session sensitivity/clearance levels
1371 * 3. set the logical UID (LUID)
1375 Debug("BLS - Setting user's clearance, security level and luid.\n");
1376 set_auth_parameters(1, verify->argv);
1379 verify->user_name = user;
1380 strncpy(verify->terminal,d->name,15);
1381 verify->terminal[15]='\0';
1382 verify->pwd = getpwnam(user);
1384 if ( verify->pwd == NULL || strlen(user) == 0 ) {
1385 LogError(ReadCatalog(
1386 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1389 verify->prpwd= b1_pwd = getprpwnam(user);
1390 verify->uid = b1_pwd->ufld.fd_uid;
1392 if ( b1_pwd == NULL || strlen(user) == 0 ) {
1393 LogError(ReadCatalog(
1394 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1399 * This has already been done successfully by dtgreet
1400 * but we need to get all the information again for the
1403 if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1404 Debug("BLS - Could not verify sensitivity level.\n");
1405 LogError(ReadCatalog(
1406 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1410 if ( change_to_user(verify) != 1 ) {
1411 Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1412 LogError(ReadCatalog(
1413 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1418 Debug("BLS - Session setup complete.\n");
1425 * This should never fail since everything has been verified already.
1426 * If it does it must mean registry strangeness, so exit, and try
1430 if (!DoLogin (user, greet.password, d->name)) exit (1);
1433 * extract the SYSTYPE and ISP environment values and set into user's
1434 * environment. This is necessary since we do an execve below...
1437 verify->userEnviron = setEnv(verify->userEnviron, "SYSTYPE",
1440 verify->userEnviron = setEnv(verify->userEnviron, "ISP",
1443 #else /* ! __apollo */
1447 if ( IsVerifyName(VN_AFS) ) {
1448 pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1449 Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1451 initgroups(greet.name, verify->groups[2]);
1452 ngroups = getgroups(NGROUPS, groups);
1453 Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1454 for (i=0; i < ngroups; i++)
1455 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1457 if ((pagval != NOPAG) &&
1458 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1459 /* we will have to shift grouplist to make room for pag */
1460 if (ngroups+2 > NGROUPS)
1462 for (j=ngroups-1; j >= 0; j--) {
1463 groups[j+2] = groups[j];
1466 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1467 if (setgroups(ngroups, groups) == -1) {
1470 MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1475 # else /* ! __AFS */
1476 /* If SIA is enabled, the initgroups and setgid calls are redundant
1483 * if your system does not support "initgroups(3C)", use
1484 * the "setgroups()" call instead...
1487 # if (defined(__hpux) || defined(__osf__))
1488 initgroups(user, -1);
1490 setgroups (verify->ngroups, verify->groups);
1493 /* setpenv() will set gid for AIX */
1495 if(-1 == setgid (verify->groups[0])) {
1496 perror(strerror(errno));
1500 # else /* ! NGROUPS */
1502 /* setpenv() will set gid for AIX */
1504 setgid (verify->gid);
1507 # endif /* NGROUPS */
1513 setaudid(verify->audid);
1514 setaudproc(verify->audflg);
1517 /* setpenv() will set uid for AIX */
1519 if (setuid(verify->uid) != 0) {
1520 Debug( "Setuid failed for user %s, errno = %d\n", user, errno);
1521 LogError(ReadCatalog(
1522 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1528 #endif /* __apollo */
1531 } /* ends the else clause of if ( ISSECURE ) */
1537 * check home directory again...
1541 /* Don't need to do this if SIA is enabled, already been done.
1543 home = getEnv (verify->userEnviron, "HOME");
1545 if (chdir (home) == -1) {
1546 LogError (ReadCatalog(
1547 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1548 home, getEnv (verify->userEnviron, "USER"));
1549 if(-1 == chdir ("/")) {
1550 perror(strerror(errno));
1552 verify->userEnviron = setEnv(verify->userEnviron,
1555 else if(!failsafe) {
1556 strcpy(lastsessfile,home); /* save user's last session */
1557 strcat(lastsessfile,LAST_SESSION_FILE);
1558 if((lastsession = fopen(lastsessfile,"w")) == NULL)
1559 Debug("Unable to open file for writing: %s\n",lastsessfile);
1561 fputs(verify->argv[0],lastsession);
1562 fclose(lastsession);
1569 SetUserAuthorization (d, verify);
1575 bzero(greet.password, strlen(greet.password));
1579 * Write login information to a file
1580 * The file name should really be settable by some kind of resource
1581 * but time is short so we hard-wire it to ".dtlogininfo".
1583 if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1584 Debug("Unable to write \".dtlogininfo\"\n");
1586 /* extra debugging */
1587 if(!dump_sec_debug_info(verify)) {
1588 Debug("Something wrong with environment\n");
1591 # endif /* ! NDEBUG */
1599 Debug ("Executing session %s\n", verify->argv[0]);
1600 execute (verify->argv, verify->userEnviron);
1601 LogError(ReadCatalog(
1602 MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1606 LogError(ReadCatalog(
1607 MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1614 * specify a font for the multi-byte languages...
1618 lang = getEnv (verify->userEnviron, "LANG");
1625 failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1627 failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1628 #elif defined (USL) || defined(__uxp__)
1629 failsafeArgv[i++] = "/usr/X/bin/xterm";
1630 #elif defined(__hpux)
1631 failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1632 #elif defined(__OpenBSD__)
1633 failsafeArgv[i++] = "/usr/X11R6/bin/xterm";
1634 #elif defined(__NetBSD__)
1635 failsafeArgv[i++] = "/usr/X11R7/bin/xterm";
1636 #elif defined(__FreeBSD__)
1637 failsafeArgv[i++] = "/usr/local/bin/xterm";
1639 failsafeArgv[i++] = "/usr/bin/X11/xterm";
1641 failsafeArgv[i++] = "-geometry";
1642 failsafeArgv[i++] = "80x10";
1643 failsafeArgv[i++] = "-bg";
1644 failsafeArgv[i++] = "white";
1645 failsafeArgv[i++] = "-fg";
1646 failsafeArgv[i++] = "black";
1648 /* aixterm requires -lang option. */
1649 failsafeArgv[i++] = "-lang";
1650 failsafeArgv[i++] = lang;
1652 failsafeArgv[i++] = "-fn";
1654 if (font == NULL) font = "fixed";
1655 failsafeArgv[i++] = font;
1658 failsafeArgv[i++] = "-e";
1659 failsafeArgv[i++] = "/bin/passwd";
1660 #if defined (__apollo) || defined(__PASSWD_ETC)
1661 failsafeArgv[i++] = "-n";
1663 failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1666 failsafeArgv[i++] = d->failsafeClient;
1668 failsafeArgv[i++] = "-C";
1670 failsafeArgv[i++] = "-ls";
1673 failsafeArgv[i++] = "-fn";
1674 failsafeArgv[i++] = font;
1678 failsafeArgv[i] = 0;
1679 Debug ("Executing failsafe session\n", failsafeArgv[0]);
1680 execute (failsafeArgv, verify->userEnviron);
1683 Debug ("StartSession(): fork failed\n");
1684 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1688 Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1695 static jmp_buf tenaciousClient;
1698 waitAbort( int arg )
1700 longjmp (tenaciousClient, 1);
1703 #if defined(SYSV) || defined(SVR4)
1705 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1709 AbortClient( int pid )
1718 for (i = 0; i < 4; i++) {
1719 if (killpg (pid, sig) == -1) {
1722 LogError(ReadCatalog(
1723 MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1729 if (!setjmp (tenaciousClient)) {
1730 (void) signal (SIGALRM, waitAbort);
1731 (void) alarm ((unsigned) 10);
1732 retId = wait ((waitType *) 0);
1733 (void) alarm ((unsigned) 0);
1734 (void) signal (SIGALRM, SIG_DFL);
1738 signal (SIGALRM, SIG_DFL);
1745 source( struct verify_info *verify, char *file )
1751 if (file && file[0]) {
1752 Debug ("Source(): %s\n", file);
1753 switch (pid = fork ()) {
1758 execute (args, verify->systemEnviron);
1759 LogError(ReadCatalog(
1760 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1763 Debug ("Source(): fork failed\n");
1764 LogError(ReadCatalog(
1765 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1769 while (wait (&result) != pid)
1773 return waitVal (result);
1778 /* returns 0 on failure, -1 on out of mem, and 1 on success */
1780 execute(char **argv, char **environ )
1784 * make stdout follow stderr to the log file...
1789 session_execve (argv[0], argv, environ);
1792 * In case this is a shell script which hasn't been made executable
1793 * (or this is a SYSV box), do a reasonable thing...
1797 /* errno is EACCES if not executable */
1798 if (errno == ENOEXEC || errno == EACCES) {
1800 if (errno == ENOEXEC) {
1802 char program[1024], *e, *p, *optarg;
1804 char **newargv, **av;
1808 * emulate BSD kernel behaviour -- read
1809 * the first line; check if it starts
1810 * with "#!", in which case it uses
1811 * the rest of the line as the name of
1812 * program to run. Else use "/bin/sh".
1814 f = fopen (argv[0], "r");
1817 if (fgets (program, sizeof (program) - 1, f) == NULL)
1823 e = program + strlen (program) - 1;
1826 if (!strncmp (program, "#!", 2)) {
1828 while (*p && isspace (*p))
1831 while (*optarg && !isspace (*optarg))
1837 while (*optarg && isspace (*optarg));
1844 Debug ("Shell script execution: %s (optarg %s)\n",
1845 p, optarg ? optarg : "(null)");
1846 for (av = argv, argc = 0; *av; av++, argc++)
1848 newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1855 while (*av++ = *argv++)
1857 session_execve (newargv[0], newargv, environ);
1866 /*****************************************************************************
1869 * Invoke the Greeter process and wait for completion. If the user was
1870 * successfully verified, return to the calling process. If the user
1871 * selected a restart or abort option, or there was an error invoking the
1872 * Greeter, exit this entire process with appropriate status.
1874 *****************************************************************************/
1878 extern int session_set;
1879 extern char *progName; /* Global argv[0]; dtlogin name and path */
1881 int response[2], request[2];
1883 /* Fixes problem with dtlogin signal handling */
1884 static int greeterPid = 0;
1885 static struct display *greeter_d = NULL;
1890 Debug("Caught SIGHUP\n");
1893 Debug("Killing greeter process: %d\n", greeterPid);
1894 kill(greeterPid, SIGHUP);
1897 SessionExit(greeter_d, REMANAGE_DISPLAY);
1899 exit(REMANAGE_DISPLAY);
1903 RunGreeter( struct display *d, struct greet_info *greet,
1904 struct verify_info *verify )
1911 static char msg[MSGSIZE];
1915 struct greet_state state = {};
1922 # define U_NAMELEN sizeof(rgy_$name_t)
1926 static char name_short[U_NAMELEN];
1932 char *argv[] = { "dtlogin", 0 };
1933 char *hostName = NULL;
1934 char *loginName = NULL;
1941 if (d->serverPid == -1)
1944 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
1945 loginName, d->name, 1, NULL);
1946 if (siaStatus != SIASUCCESS)
1948 Debug("sia_ses_init failure status %d\n", siaStatus);
1955 if (!setjmp (abortSession)) {
1956 signal(SIGTERM, catchTerm);
1959 * We've changed dtlogin to pass HUP's down to the children
1960 * so ignore any HUP's once the client has started.
1963 signal(SIGHUP, catchHUP);
1966 * set up communication pipes...
1969 if(-1 == pipe(response)) {
1970 perror(strerror(errno));
1972 if(-1 == pipe(request)) {
1973 perror(strerror(errno));
1978 switch (greeterPid = fork ()) {
1982 * pass some information in the environment...
1986 sprintf(msg,"%d", d->grabServer);
1987 env = setEnv(env, GRABSERVER, msg);
1989 sprintf(msg,"%d", d->grabTimeout);
1990 env = setEnv(env, GRABTIMEOUT, msg);
1993 if (timeZone && strlen(timeZone) > 0 )
1994 env = setEnv(env, "TZ", timeZone);
1996 if (errorLogFile && errorLogFile[0])
1997 env = setEnv(env, ERRORLOG, errorLogFile);
2000 env = setEnv(env, "XAUTHORITY", d->authFile);
2003 env = setEnv(env, DTLITE, "True");
2006 env = setEnv(env, SESSION, d->session);
2009 env = setEnv(env, SESSION_SET, "True");
2011 if (d->pmSearchPath)
2012 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
2014 if (d->bmSearchPath)
2015 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
2017 #if defined (__KERBEROS) || defined (__AFS)
2018 if (d->verifyName) {
2019 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2020 (strcmp(d->verifyName, VN_KRB) == 0) ) {
2022 env = setEnv(env, VERIFYNAME, d->verifyName );
2025 LogError(ReadCatalog(
2026 MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2028 d->verifyName = NULL;
2033 if((path = getenv("NLSPATH")) != NULL)
2034 env = setEnv(env, "NLSPATH", path);
2036 env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2041 * ping remote displays...
2045 if (d->displayType.location == Local) {
2046 GettyRunning(d); /* refresh gettyState */
2047 if (d->gettyState != DM_GETTY_USER)
2048 env = setEnv(env, LOCATION, "local");
2051 sprintf(msg,"%d", d->pingInterval);
2052 env = setEnv(env, PINGINTERVAL, msg);
2054 sprintf(msg,"%d", d->pingTimeout);
2055 env = setEnv(env, PINGTIMEOUT, msg);
2059 if ( d->langList && strlen(d->langList) > 0 )
2060 env = setEnv(env, LANGLIST, d->langList);
2061 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2062 else if (strlen(languageList) > 0 )
2063 env = setEnv(env, LANGLIST, languageList);
2064 #endif /* ENABLE_DYNAMIC_LANGLIST */
2067 char *language = NULL;
2069 #if defined (ENABLE_DYNAMIC_LANGLIST)
2070 language = d->language;
2071 #endif /* ENABLE_DYNAMIC_LANGLIST */
2073 if (env && d->language && strlen(d->language) > 0 )
2074 env = setLang(d, env, language);
2077 if((path = getenv("XKEYSYMDB")) != NULL)
2078 env = setEnv(env, "XKEYSYMDB", path);
2081 if((path = getenv("OPENWINHOME")) != NULL)
2082 env = setEnv(env, "OPENWINHOME", path);
2087 * set environment for Domain machines...
2089 env = setEnv(env, "ENVIRONMENT", "bsd");
2090 env = setEnv(env, "SYSTYPE", "bsd4.3");
2094 Debug ("Greeter environment:\n");
2096 Debug ("End of Greeter environment:\n");
2099 * Writing to file descriptor 1 goes to response pipe instead.
2102 dupfp = dup(response[1]);
2104 perror(strerror(errno));
2110 * Reading from file descriptor 0 reads from request pipe instead.
2113 dupfp2 = dup(request[0]);
2115 perror(strerror(errno));
2123 * figure out path to dtgreet...
2126 snprintf(msg, sizeof(msg), "%s", progName);
2128 if ((p = (char *) strrchr(msg, '/')) == NULL)
2133 strcat(msg,"dtgreet");
2135 execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2136 LogError(ReadCatalog(
2137 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2139 exit (NOTIFY_ABORT_DISPLAY);
2142 Debug ("Fork of Greeter failed.\n");
2143 LogError(ReadCatalog(
2144 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2149 exit (UNMANAGE_DISPLAY);
2152 Debug ("Greeter started\n");
2154 close(response[1]); /* Close write end of response pipe */
2155 close(request[0]); /* Close read end of request pipe */
2159 * Retrieve information from greeter and authenticate.
2161 globalDisplayName = d->name;
2162 state.id = GREET_STATE_ENTER;
2163 state.waitForResponse = FALSE;
2167 * atexit() registers this function to be called if exit() is
2168 * called. This is needed because in enhanced security mode, SIA
2169 * may call exit() whn the user fails to enter or change a
2172 sia_greeter_pid = greeterPid;
2173 if (!sia_exit_proc_reg)
2175 atexit(KillGreeter);
2176 sia_exit_proc_reg = TRUE;
2179 siaGreeterInfo.d = d;
2180 siaGreeterInfo.greet = greet;
2181 siaGreeterInfo.verify = verify;
2182 siaGreeterInfo.state = &state;
2183 siaGreeterInfo.status = TRUE;
2186 while(siaStatus != SIASUCCESS)
2188 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2190 Debug ("RunGreeter: before sia_ses_authent\n");
2191 dt_in_sia_ses_authent = True;
2192 siaStatus = sia_ses_authent(SiaManageGreeter, NULL,
2194 dt_in_sia_ses_authent = False;
2195 Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2197 if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2199 state.id = GREET_STATE_ERRORMESSAGE;
2200 state.vf = VF_INVALID;
2201 ManageGreeter(d, greet, verify, &state);
2203 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2206 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2208 sia_ses_release(&siaHandle);
2212 Debug("RunGreeter: before sia_ses_estab\n");
2213 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2214 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2217 if (!siaGreeterInfo.status)
2220 if (siaStatus == SIASUCCESS)
2222 Debug("RunGreeter: before sia_ses_launch\n");
2223 siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2224 Debug("RunGreeter: after sia_ses_launch status = %d\n",
2227 if (!siaGreeterInfo.status)
2230 if (siaStatus != SIASUCCESS)
2232 Debug("RunGreeter: sia_ses_launch failure\n");
2233 /* establish & launch failures do a release */
2235 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
2236 loginName, d->name, 1, NULL);
2237 if (siaStatus != SIASUCCESS)
2239 Debug("sia_ses_init failure status %d\n", siaStatus);
2240 exit(RESERVER_DISPLAY);
2245 * sia_ses_launch() wil probably seteuid to that of the
2246 * user, but we don't want that now.
2250 * extract necessary info from SIA context struct
2254 if (siaStatus == SIASUCCESS)
2255 CopySiaInfo(siaHandle, greet);
2256 sia_ses_release(&siaHandle);
2258 state.id = GREET_STATE_TERMINATEGREET;
2259 if (siaGreeterInfo.status)
2261 while (ManageGreeter(d, greet, verify, &state))
2264 sia_greeter_pid = 0;
2266 while (ManageGreeter(d, greet, verify, &state))
2271 * Wait for Greeter to end...
2274 pid = wait (&status);
2275 if (pid == greeterPid)
2281 * Greeter exited. Check return code...
2284 Debug("Greeter return status; exit = %d, signal = %d\n",
2285 waitCode(status), waitSig(status));
2289 * remove authorization file if used...
2292 if (d->authorizations && d->authFile &&
2293 waitVal(status) != NOTIFY_LANG_CHANGE
2295 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2300 Debug ("Done with authorization file %s, removing\n",
2302 (void) unlink (d->authFile);
2307 if(waitVal(status) > NOTIFY_ALT_DTS)
2308 d->sessionType = waitVal(status);
2311 switch (waitVal(status)) {
2312 case NOTIFY_FAILSAFE:
2313 greet->string = "failsafe";
2315 case NOTIFY_PASSWD_EXPIRED:
2316 greet->string = "password";
2321 case NOTIFY_LAST_DT:
2322 d->sessionType = waitVal(status);
2328 Debug("waitVal - status is %d\n", waitVal(status));
2329 if(waitVal(status) > NOTIFY_ALT_DTS)
2330 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2332 notify_dt = waitVal(status);
2334 switch (notify_dt) {
2335 case NOTIFY_FAILSAFE:
2336 case NOTIFY_PASSWD_EXPIRED:
2340 case NOTIFY_LAST_DT:
2341 case NOTIFY_ALT_DTS:
2343 if (NULL == greet->name) return;
2346 * greet->name, greet->password set in ManageGreeter().
2348 Debug("Greeter returned name '%s'\n", greet->name);
2351 greet->name_full = greet->name;
2352 /* get just person name out of full SID */
2354 while (i < sizeof(rgy_$name_t)
2355 && greet->name_full[i] != '.'
2356 && greet->name_full[i] != '\0') {
2357 name_short[i] = greet->name_full[i];
2360 name_short[i] = '\0';
2361 greet->name = name_short;
2366 * groups[] set in Authenticate().
2368 if ( IsVerifyName(VN_AFS) ) {
2369 verify->groups[0] = groups[0];
2370 verify->groups[1] = groups[1];
2371 Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2372 Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2378 * sensitivityLevel set in BLS_Verify()
2380 greet->b1security = sensitivityLevel;
2383 Verify(d, greet, verify);
2387 Debug ("Greeter Xlib error or SIGTERM\n");
2388 SessionExit(d, OPENFAILED_DISPLAY);
2390 case NOTIFY_RESTART:
2391 Debug ("Greeter requested RESTART_DISPLAY\n");
2392 SessionExit(d, RESERVER_DISPLAY);
2394 case NOTIFY_ABORT_DISPLAY:
2395 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2396 SessionExit(d, UNMANAGE_DISPLAY);
2398 case NOTIFY_NO_WINDOWS:
2399 Debug ("Greeter requested NO_WINDOWS mode\n");
2400 if (d->serverPid >= 2)
2402 * Don't do a SessionExit() here since that causes
2403 * the X-server to be reset. We know we are going to
2404 * terminate it anyway, so just go do that...
2406 exit(SUSPEND_DISPLAY);
2410 case NOTIFY_LANG_CHANGE:
2411 Debug ("Greeter requested LANG_CHANGE\n");
2414 * copy requested language into display struct "d". Note,
2415 * this only happens in this child's copy of "d", not in
2416 * the master struct. When the user logs out, the
2417 * resource-specified language (if any) will reactivate.
2420 Debug("Greeter returned language '%s'\n", d->language);
2422 Debug("Greeter returned language (NULL)\n");
2425 if (strcmp(d->language, "default") == 0) {
2426 int len = strlen(defaultLanguage) + 1;
2427 d->language = (d->language == NULL ?
2428 malloc(len) : realloc (d->language, len));
2429 strcpy(d->language, defaultLanguage);
2433 case NOTIFY_BAD_SECLEVEL:
2436 case waitCompose (SIGTERM,0,0):
2437 Debug ("Greeter exited on SIGTERM\n");
2438 SessionExit(d, OPENFAILED_DISPLAY);
2441 Debug ("Greeter returned unknown status %d\n",
2443 SessionExit(d, REMANAGE_DISPLAY);
2446 signal(SIGHUP, SIG_DFL);
2449 AbortClient(greeterPid);
2450 SessionExit(d, UNMANAGE_DISPLAY);
2454 /*****************************************************************************
2460 This is the entry into greeter state processing. Allocate and initialize
2464 Display the login screen. Upon display, the login screen can be 'reset'. If
2465 reset is true, the username and password fields are cleared and the focus
2466 is set to the username field. If reset is false, the username and password
2467 field is untouched and the focus is set to the password field.
2469 LOGIN -> AUTHENTICATE:
2470 Authenticate the username entered on login screen.
2472 AUTHENTICATE -> TERMINATEGREET:
2473 User passed authentication so terminate the greeter.
2475 AUTHENTICATE -> EXPASSWORD:
2476 User passed authentication, but the their password has expired.
2477 Display old password message. This message allows the user to
2478 change their password by starting a getty and running passwd(1).
2480 AUTHENTICATE -> BAD_HOSTNAME:
2481 User passed authentication, but the their hostname is empty.
2482 Display a dialog that allows the user to run a getty to fix the
2483 problem, or start the desktop anyway.
2485 AUTHENTICATE -> ERRORMESSAGE:
2486 User failed authentication, so display error message.
2488 AUTHENTICATE -> LOGIN
2489 User failed authentication, but did not enter a password. Instead
2490 of displaying an error message, redisplay the login screen with
2491 the focus set to the password field. If the user authenticates again
2492 without the password field set, display an error. This allows a user
2493 to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2496 Free state structure and return false to stop state transitions.
2498 ERRORMESSAGE -> LOGIN
2499 Display error message base on return code from last authentication
2500 attempt. Redisplay login screen with reset set to true.
2502 (state) -> LANG -> (state)
2503 User has chosen a new language. Transition to LANG state to save off
2504 the new language, and transition back to original state.
2506 *****************************************************************************/
2508 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2511 ManageGreeter( struct display *d, struct greet_info *greet,
2512 struct verify_info *verify, struct greet_state *state )
2519 if (state->waitForResponse)
2521 if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2524 * Dtgreet has terminated.
2526 state->id = GREET_STATE_EXIT;
2527 state->waitForResponse = FALSE;
2531 if (state->request->opcode != state->response->opcode)
2534 * An unrequested event arrived. See if it's one we
2537 switch(state->response->opcode)
2539 case REQUEST_OP_LANG:
2542 * User has changed language. Recursively handle this state
2543 * and return to current state.
2545 struct greet_state lang_state;
2547 lang_state = *state;
2548 lang_state.id = GREET_STATE_LANG;
2549 lang_state.waitForResponse = FALSE;
2550 ManageGreeter(d, greet, verify, &lang_state);
2551 Debug("Response opcode REQUEST_OP_LANG\n");
2556 case REQUEST_OP_CLEAR:
2559 * User has requested the screen be cleared.
2561 state->id = GREET_STATE_USERNAME;
2562 state->waitForResponse = TRUE;
2563 Debug("Response opcode REQUEST_OP_CLEAR\n");
2568 Debug("Response opcode UNEXPECTED RESPONSE!\n");
2578 * Got the response we were expecting.
2580 state->waitForResponse = FALSE;
2586 case GREET_STATE_ENTER:
2589 * Enter - initialize state
2591 Debug("GREET_STATE_ENTER\n");
2593 state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2594 state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2595 state->authenticated = FALSE;
2598 state->id = GREET_STATE_USERNAME;
2602 case GREET_STATE_USERNAME:
2607 RequestChallenge *r;
2609 Debug("GREET_STATE_USERNAME\n");
2611 Authenticate(d, NULL, NULL, NULL);
2613 SETMC(msg, LOGIN_LABEL);
2615 r = (RequestChallenge *)state->request;
2616 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2617 r->hdr.reserved = 0;
2620 r->hdr.length = sizeof(*r);
2622 r->offChallenge = sizeof(*r);
2623 strcpy(((char *)r) + r->offChallenge, msg.def);
2624 r->hdr.length += strlen(msg.def) + 1;
2628 r->offUserNameSeed = r->hdr.length;
2629 strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2630 r->hdr.length += strlen(greet->name) + 1;
2631 Debug("Greet name: %s\n", greet->name);
2635 r->offUserNameSeed = 0;
2640 free(greet->name); greet->name = NULL;
2642 if (greet->password)
2644 free(greet->password); greet->password = NULL;
2647 TellGreeter((RequestHeader *)r);
2648 state->waitForResponse = TRUE;
2650 state->id = GREET_STATE_AUTHENTICATE;
2654 case GREET_STATE_CHALLENGE:
2659 RequestChallenge *r;
2661 Debug("GREET_STATE_CHALLENGE\n");
2663 if (greet->password)
2665 free(greet->password); greet->password = NULL;
2668 SETMC(msg, PASSWD_LABEL);
2670 r = (RequestChallenge *)state->request;
2671 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2672 r->hdr.reserved = 0;
2675 r->offUserNameSeed = 0;
2676 r->offChallenge = sizeof(*r);
2677 strcpy(((char *)r) + r->offChallenge, msg.def);
2678 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2680 TellGreeter((RequestHeader *)r);
2681 state->waitForResponse = TRUE;
2683 state->id = GREET_STATE_AUTHENTICATE;
2687 case GREET_STATE_AUTHENTICATE:
2690 * Attempt to authenticate.
2692 ResponseChallenge *r;
2694 Debug("GREET_STATE_AUTHENTICATE\n");
2696 r = (ResponseChallenge *)state->response;
2698 if (greet->name == NULL)
2700 greet->name = strdup(((char *)r) + r->offResponse);
2701 if (strlen(greet->name) == 0)
2703 state->id = GREET_STATE_USERNAME;
2709 greet->password = strdup(((char *)r) + r->offResponse);
2719 * Attempt to authenticate user. 'username' should be a
2720 * non-empty string. 'password' may be an empty string.
2722 state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2724 if (state->vf == VF_OK ||
2725 state->vf == VF_PASSWD_AGED ||
2726 state->vf == VF_BAD_HOSTNAME)
2728 state->authenticated = TRUE;
2732 * General transitions.
2736 case VF_OK: state->id = GREET_STATE_TERMINATEGREET; break;
2737 case VF_PASSWD_AGED: state->id = GREET_STATE_EXPASSWORD; break;
2738 case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break;
2739 case VF_CHALLENGE: state->id = GREET_STATE_CHALLENGE; break;
2740 default: state->id = GREET_STATE_ERRORMESSAGE; break;
2745 case GREET_STATE_EXIT:
2748 * Free resources and leave.
2750 Debug("GREET_STATE_EXIT\n");
2757 if (!state->authenticated)
2761 free(greet->name); greet->name = NULL;
2763 if (greet->password)
2765 free(greet->password); greet->password = NULL;
2769 free(state->request);
2770 free(state->response);
2775 case GREET_STATE_ERRORMESSAGE:
2778 * Display error message.
2782 Debug("GREET_STATE_ERRORMESSAGE\n");
2784 r = (RequestMessage *)state->request;
2788 case VF_INVALID: SETMC(msg, LOGIN); break;
2789 case VF_HOME: SETMC(msg, HOME); break;
2790 case VF_MAX_USERS: SETMC(msg, MAX_USERS); break;
2791 case VF_BAD_UID: SETMC(msg, BAD_UID); break;
2792 case VF_BAD_GID: SETMC(msg, BAD_GID); break;
2793 case VF_BAD_AID: SETMC(msg, BAD_AID); break;
2794 case VF_BAD_AFLAG: SETMC(msg, BAD_AFLAG); break;
2795 case VF_NO_LOGIN: SETMC(msg, NO_LOGIN); break;
2797 case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2799 case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2800 default: msg.id=0; msg.def=""; break;
2803 r->hdr.opcode = REQUEST_OP_MESSAGE;
2804 r->hdr.reserved = 0;
2806 r->offMessage = sizeof(*r);
2807 strcpy(((char *)r) + r->offMessage, msg.def);
2808 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2810 TellGreeter((RequestHeader *)r);
2811 state->waitForResponse = TRUE;
2813 state->id = GREET_STATE_USERNAME;
2817 case GREET_STATE_LANG:
2820 * User selected new language.
2826 Debug("GREET_STATE_LANG\n");
2828 r = (ResponseLang *)state->response;
2829 lang = ((char *)r) + r->offLang;
2830 len = strlen(lang) + 1;
2832 d->language = (d->language == NULL ?
2833 malloc(len) : realloc(d->language, len));
2834 strcpy(d->language, lang);
2835 Debug("Language returned: %s\n", d->language);
2839 case GREET_STATE_TERMINATEGREET:
2842 * Terminate dtgreet.
2846 Debug("GREET_STATE_TERMINATEGREET\n");
2848 r = (RequestExit *)state->request;
2850 r->hdr.opcode = REQUEST_OP_EXIT;
2851 r->hdr.reserved = 0;
2852 r->hdr.length = sizeof(*r);
2854 TellGreeter((RequestHeader *)r);
2855 state->waitForResponse = TRUE;
2857 state->id = GREET_STATE_EXIT;
2861 case GREET_STATE_EXPASSWORD:
2864 * Display password expired message.
2866 RequestExpassword *r;
2868 Debug("GREET_STATE_EXPASSWORD\n");
2870 r = (RequestExpassword *)state->request;
2872 r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2873 r->hdr.reserved = 0;
2874 r->hdr.length = sizeof(*r);
2876 TellGreeter((RequestHeader *)r);
2877 state->waitForResponse = TRUE;
2879 state->id = GREET_STATE_USERNAME;
2883 case GREET_STATE_BAD_HOSTNAME:
2886 * Display password expired message.
2890 Debug("GREET_STATE_BAD_HOSTNAME\n");
2892 r = (RequestHostname *)state->request;
2894 r->hdr.opcode = REQUEST_OP_HOSTNAME;
2895 r->hdr.reserved = 0;
2896 r->hdr.length = sizeof(*r);
2898 TellGreeter((RequestHeader *)r);
2899 state->waitForResponse = TRUE;
2901 state->id = GREET_STATE_USERNAME;
2906 case GREET_STATE_FORM:
2909 * Get arbitrary number of answers.
2912 Debug("GREET_STATE_FORM\n");
2914 AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2916 state->waitForResponse = FALSE;
2917 state->id = GREET_STATE_USERNAME;
2929 RequestHeader *phdr)
2931 if(-1 == write(request[1], phdr, phdr->length)) {
2932 perror(strerror(errno));
2938 RequestHeader *preqhdr,
2944 ResponseHeader *phdr = (ResponseHeader *)buf;
2946 if (preqhdr) TellGreeter(preqhdr);
2948 phdr->opcode = REQUEST_OP_NONE;
2950 count = read(response[0], buf, sizeof(*phdr));
2952 if (count == sizeof(*phdr))
2955 * Calculate amount of data after header.
2957 remainder = phdr->length - sizeof(*phdr);
2961 * Read remainder of response.
2963 count += read(response[0], buf+sizeof(*phdr), remainder);
2968 if (debugLevel) PrintResponse(phdr, count);
2977 ResponseHeader *phdr,
2980 char *opstr = "UNKNOWN";
2984 Debug("opcode = (EOF)\n");
2988 switch(phdr->opcode)
2990 case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2991 case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2992 case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2993 case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2994 case REQUEST_OP_LANG: opstr = "LANG"; break;
2995 case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
2998 Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
2999 Debug(" reserved = %d\n", phdr->reserved);
3000 Debug(" length = %d\n", phdr->length);
3002 switch(phdr->opcode)
3004 case REQUEST_OP_EXIT: break;
3005 case REQUEST_OP_LANG:
3006 Debug(" offLang=%d\n", ((ResponseLang *)phdr)->offLang);
3007 Debug(" lang='%s'\n",
3008 ((char *)phdr)+((ResponseLang *)phdr)->offLang);
3010 case REQUEST_OP_MESSAGE: break;
3011 case REQUEST_OP_CHPASS: break;
3012 case REQUEST_OP_CHALLENGE:
3013 Debug(" offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
3014 Debug(" response='%s'\n",
3015 ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
3017 case REQUEST_OP_DEBUG:
3018 Debug(" offString=%d\n", ((ResponseDebug *)phdr)->offString);
3019 Debug(" string='%s'\n",
3020 ((char *)phdr)+((ResponseDebug *)phdr)->offString);
3028 /***************************************************************************
3032 * generate kerberos ticket file name. Name is returned in the static
3033 * global variable "krb_ticket_string".
3035 ***************************************************************************/
3038 SetTicketFileName(uid_t uid)
3047 * generate ticket file pathname (/tmp/tkt<uid>.<host>) ...
3050 if (env = (char *)getenv("KRBTKFILE")) {
3051 (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3052 krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3055 if (gethostname(lhost, sizeof(lhost)) != -1) {
3056 if (p = index(lhost, '.')) *p = '\0';
3057 (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3059 /* 32 bits of signed integer will always fit in 11 characters
3060 (including the sign), so no need to worry about overflow */
3061 (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3066 #endif /* __KERBEROS */
3068 #if defined (_AIX) && !defined (_POWER)
3070 /***************************************************************************
3074 * If this is an authenticated process (LOGNAME set), set user's
3075 * process environment by calling setpenv().
3077 * If this is not an authenticated process, just call execve()
3079 ***************************************************************************/
3088 char *user = getEnv (envp, "LOGNAME");
3092 rc = execve(path, argv, envp);
3096 char *usrTag, *sysTag;
3099 * Save pointers to tags. The setpenv() function clears the pointers
3100 * to the tags in userEnviron as a side-effect.
3102 sysTag = envp[SYS_ENV_TAG];
3103 usrTag = envp[USR_ENV_TAG];
3106 * Set the users process environment. This call execs arvg so it
3107 * should not return. It it should return, restore the envp tags.
3109 rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3112 * Restore pointers to tags.
3114 envp[SYS_ENV_TAG] = sysTag;
3115 envp[USR_ENV_TAG] = usrTag;
3120 #endif /* _AIX && !_POWER */
3124 /* collect the SIA parameters from a window system. */
3126 static int SiaManageGreeter(
3129 unsigned char *title,
3135 RequestMessage greeter_message;
3136 char msg_buffer[256];
3137 } greeter_msg_and_buffer;
3138 RequestForm *request_form;
3146 if (rendition == SIAFORM && dt_in_sia_ses_authent
3147 && (num_prompts == 2))
3149 /* Normal login, Password case */
3150 Debug ("SIAFORM Normal login, Password case\n");
3151 while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3152 && siaGreeterInfo.state->id != GREET_STATE_EXIT
3153 && (siaGreeterInfo.status = ManageGreeter(
3154 siaGreeterInfo.d, siaGreeterInfo.greet,
3155 siaGreeterInfo.verify, siaGreeterInfo.state)))
3158 if (!siaGreeterInfo.status
3159 || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3160 return(SIACOLABORT);
3162 strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name,
3163 prompt[0].max_result_length);
3164 strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3165 prompt[1].max_result_length);
3172 ResponseForm *response_form;
3177 Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3180 Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3183 Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3186 Debug("SIAFORM num_prompts = %d\n", num_prompts);
3190 /* need to display form */
3192 req_form_size = sizeof(RequestForm)
3193 + strlen((const char *)title) + 1;
3194 for (i=0; i<num_prompts; i++)
3195 req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3196 request_form = (RequestForm *) alloca(req_form_size);
3198 siaGreeterInfo.state->id = GREET_STATE_FORM;
3199 siaGreeterInfo.state->request = (RequestHeader *)request_form;
3200 /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3202 request_form->hdr.opcode = REQUEST_OP_FORM;
3203 request_form->hdr.reserved = 0;
3204 request_form->hdr.length = req_form_size;
3205 request_form->num_prompts = num_prompts;
3206 request_form->rendition = rendition;
3207 request_form->offTitle = sizeof(RequestForm);
3208 request_form->offPrompts = sizeof(RequestForm) +
3209 strlen((const char *)title) + 1;
3210 strcpy((char *)request_form + request_form->offTitle,
3211 (const char *)title);
3213 pmpt_ptr = (char *)request_form + request_form->offPrompts;
3214 for (i=0; i<num_prompts; i++)
3216 if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3220 Debug(" prompt[%d]: %s\n", i, prompt[i].prompt);
3221 strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3222 pmpt_ptr += strlen((const char *)prompt[i].prompt);
3224 request_form->visible[i] =
3225 (prompt[i].control_flags & SIARESINVIS) ? False : True;
3228 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3229 siaGreeterInfo.greet,
3230 siaGreeterInfo.verify,
3231 siaGreeterInfo.state);
3233 response_form = (ResponseForm *)siaGreeterInfo.state->response;
3234 res_ptr = (char *)response_form + response_form->offAnswers;
3235 for (i = 0; i < response_form->num_answers; i++)
3237 if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3240 prompt[i].result = (unsigned char *)1;
3242 prompt[i].result = NULL;
3246 strcpy((char *)prompt[0].result, res_ptr);
3248 res_ptr += strlen(res_ptr) + 1;
3250 if (!response_form->collect_status)
3251 siaGreeterInfo.status = FALSE;
3257 Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3259 siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3260 siaGreeterInfo.state->request = (RequestHeader *)
3261 &greeter_msg_and_buffer.greeter_message;
3262 siaGreeterInfo.state->vf = VF_MESSAGE;
3263 siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3265 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3266 siaGreeterInfo.greet,
3267 siaGreeterInfo.verify,
3268 siaGreeterInfo.state);
3271 return(SIACOLABORT);
3274 if (!siaGreeterInfo.status)
3275 return(SIACOLABORT);
3276 return(SIACOLSUCCESS);
3279 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3282 greet->name = malloc(strlen(siaHandle->name) + 1);
3283 strcpy (greet->name, siaHandle->name);
3285 greet->password = malloc(strlen(siaHandle->password) + 1);
3286 strcpy (greet->password, siaHandle->password);
3291 static void KillGreeter( void )
3293 if (sia_greeter_pid)
3294 AbortClient(sia_greeter_pid);
3295 sia_greeter_pid = 0;