1 /* (c) Copyright 1997 The Open Group */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
4 * (c) Copyright 1993, 1994 International Business Machines Corp. *
5 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
6 * (c) Copyright 1993, 1994 Novell, Inc. *
9 * Xdm - display manager daemon
11 * $TOG: session.c /main/21 1998/11/02 14:32:42 mgreess $
13 * Copyright 1988 Massachusetts Institute of Technology
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted, provided
17 * that the above copyright notice appear in all copies and that both that
18 * copyright notice and this permission notice appear in supporting
19 * documentation, and that the name of M.I.T. not be used in advertising or
20 * publicity pertaining to distribution of the software without specific,
21 * written prior permission. M.I.T. makes no representations about the
22 * suitability of this software for any purpose. It is provided "as is"
23 * without express or implied warranty.
25 * Author: Keith Packard, MIT X Consortium
44 # include <X11/Xatom.h>
55 #include <X11/Intrinsic.h>
58 # include <X11/Xresource.h>
69 # include <sys/security.h>
75 #endif /* __KERBEROS */
83 static SIAENTITY *siaHandle = NULL;
84 static Boolean dt_in_sia_ses_authent = False;
86 static struct sia_greeter_info {
88 struct greet_info *greet;
89 struct verify_info *verify;
90 struct greet_state *state;
94 static int SiaManageGreeter(
101 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet);
103 static void KillGreeter( void );
105 static int sia_greeter_pid;
106 static int sia_exit_proc_reg = FALSE;
112 extern char *getenv();
115 #define GREET_STATE_LOGIN 0
116 #define GREET_STATE_AUTHENTICATE 1
117 #define GREET_STATE_EXIT 2
118 #define GREET_STATE_EXPASSWORD 3
119 #define GREET_STATE_ERRORMESSAGE 4
120 #define GREET_STATE_LANG 5
121 #define GREET_STATE_BAD_HOSTNAME 6
122 #define GREET_STATE_ENTER 7
123 #define GREET_STATE_TERMINATEGREET 8
124 #define GREET_STATE_USERNAME 9
125 #define GREET_STATE_CHALLENGE 10
126 #define GREET_STATE_FORM 11
129 #define DEF_SESSION CDE_INSTALLATION_TOP "/bin/Xsession"
137 int waitForResponse; /* TRUE=wait for response from dtgreet */
138 RequestHeader *request; /* request buffer */
139 ResponseHeader *response; /* response buffer */
140 int authenticated; /* TRUE=user is authenticated */
141 int vf; /* last return code from Authenticate() */
142 int loginReset; /* reset flag for LOGIN state */
143 char *msg; /* message for VF_MESSAGE */
146 char *globalDisplayName;
148 /***************************************************************************
150 * Local procedure declarations
152 ***************************************************************************/
154 static int AbortClient( int pid) ;
155 static void DeleteXloginResources( struct display *d, Display *dpy) ;
156 int LoadXloginResources( struct display *d) ;
157 static int ErrorHandler( Display *dpy, XErrorEvent *event) ;
158 static int IOErrorHandler( Display *dpy) ;
159 static int ManageGreeter( struct display *d, struct greet_info *greet,
160 struct verify_info *verify, struct greet_state *state) ;
161 static void RunGreeter( struct display *d, struct greet_info *greet,
162 struct verify_info *verify) ;
163 static void SessionExit( struct display *d, int status) ;
164 static void SessionPingFailed( struct display *d) ;
165 static int StartClient(struct verify_info *verify, struct display *d,
167 static SIGVAL catchAlrm( int arg ) ;
168 static SIGVAL catchHUP( int arg ) ;
169 static SIGVAL catchTerm( int arg ) ;
170 static SIGVAL waitAbort( int arg ) ;
171 static void SetupDisplay(struct display *d);
173 static void TellGreeter(RequestHeader *phdr);
174 static int AskGreeter(RequestHeader *preqhdr, char *b, int blen);
176 static void PrintResponse(ResponseHeader *phdr, int count);
179 #if defined (_AIX) && defined (_POWER)
180 static void release_aix_lic(void);
183 #if defined (_AIX) && !defined (_POWER)
184 static int session_execve(char *path, char *argv[], char *envp[]);
186 #define session_execve(A,B,C) execve(A,B,C)
190 static void SetTicketFileName(uid_t uid);
191 # endif /* __KERBEROS */
193 static void LoadAltDtsResources( struct display *d);
194 char * _ExpandLang(char *string, char *lang);
198 /***************************************************************************
202 ***************************************************************************/
204 static int clientPid;
205 static struct greet_info greet;
206 static struct verify_info verify;
207 static char *defaultLanguage = NULL;
209 static jmp_buf abortSession;
212 static char *sensitivityLevel;
216 static char krb_ticket_string[MAXPATHLEN];
217 #endif /* __KERBEROS */
220 XrmDatabase XresourceDB;
227 longjmp (abortSession, 1);
230 static jmp_buf pingTime;
235 longjmp (pingTime, 1);
239 FileNameCompare (a, b)
240 #if defined(__STDC__)
246 return strcoll (*(char **)a, *(char **)b);
250 SessionPingFailed( struct display *d )
254 AbortClient (clientPid);
255 source (&verify, d->reset);
257 #if defined (PAM) || defined(SUNAUTH)
259 char* user = getEnv (verify.userEnviron, "USER");
260 char* ttyLine = d->gettyLine;
262 #ifdef DEF_NETWORK_DEV
264 * If location is not local (remote XDMCP dtlogin) and
265 * remote accouting is enabled (networkDev start with /dev/...)
266 * Set tty line name to match network device for accouting.
267 * Unless the resource was specifically set, default is value
268 * of DEF_NETWORK_DEV define (/dev/dtremote)
271 if ( d->displayType.location != Local &&
272 networkDev && !strncmp(networkDev,"/dev/",5)) {
273 ttyLine = networkDev+5;
278 PamAccounting( verify.argv[0], d->name, d->utmpId, user,
279 ttyLine, clientPid, ACCOUNTING, NULL);
281 solaris_accounting( verify.argv[0], d->name, d->utmpId, user,
282 ttyLine, clientPid, ACCOUNTING, NULL);
286 solaris_resetdevperm(ttyLine);
292 SessionExit (d, RESERVER_DISPLAY);
297 * We need our own error handlers because we can't be sure what exit code Xlib
298 * will use, and our Xlib does exit(1) which matches REMANAGE_DISPLAY, which
299 * can cause a race condition leaving the display wedged. We need to use
300 * RESERVER_DISPLAY for IO errors, to ensure that the manager waits for the
301 * server to terminate. For other X errors, we should give up.
305 IOErrorHandler( Display *dpy )
308 char *s = ((errno >= 0 && errno < sys_nerr) ? sys_errlist[errno]
311 LogError(ReadCatalog(
312 MC_LOG_SET,MC_LOG_FATAL_IO,MC_DEF_LOG_FATAL_IO),
314 exit(RESERVER_DISPLAY);
319 ErrorHandler( Display *dpy, XErrorEvent *event )
321 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_X_ERR,MC_DEF_LOG_X_ERR));
322 if (XmuPrintDefaultErrorMessage (dpy, event, stderr) == 0) return 0;
323 exit(UNMANAGE_DISPLAY);
329 ManageSession( struct display *d )
335 char *BypassUsername;
337 #endif /* BYPASSLOGIN */
340 Debug ("ManageSession():\n");
342 /***********************************/
343 /** remember the default language **/
344 /***********************************/
345 if (defaultLanguage == NULL) {
346 if ( (d->language != NULL) && (strlen(d->language) > 0) ) {
347 defaultLanguage = strdup(d->language);
349 defaultLanguage = "C";
355 if ((BypassUsername = BypassLogin(d->name)) != NULL) {
357 Debug("Login bypassed, running as %s\n",BypassUsername);
358 greet.name = BypassUsername;
359 if (!Verify (d, &greet, &verify)) {
360 Debug ("Login bypass verify failed!\n");
361 SessionExit (d, GREETLESS_FAILED);
363 Debug("Login bypass verify succeded!\n");
365 #endif /* BYPASSLOGIN */
370 (void)XSetIOErrorHandler(IOErrorHandler);
371 (void)XSetErrorHandler(ErrorHandler);
372 SetTitle(d->name, (char *) 0);
375 * set root background to black...
378 dpy = XOpenDisplay(d->name);
379 for (i = ScreenCount(dpy) - 1; i >= 0; i--)
381 Window tmproot = RootWindow(dpy, i);
383 if (i == DefaultScreen(dpy))
386 XSetWindowBackground(dpy, tmproot, BlackPixel(dpy, i));
387 XClearWindow(dpy, tmproot);
393 ** Invoke Greet program, wait for completion.
394 ** If this routine returns, the user will have been
395 ** verified, otherwise the routine will exit inter-
396 ** nally with an appropriate exit code for the master
401 greet.name = greet.string = NULL;
403 while (greet.name == NULL) {
404 SetHourGlassCursor(dpy, root);
405 LoadXloginResources (d);
407 ApplyFontPathMods(d, dpy);
408 (void)XSetErrorHandler(ErrorHandler);
409 RunGreeter(d, &greet, &verify);
411 DeleteXloginResources (d, dpy);
413 XSetInputFocus(dpy, root, RevertToNone, CurrentTime);
419 * Generate Kerberos ticket file name. Put in system and user
423 if ( IsVerifyName(VN_KRB)) {
424 SetTicketFileName(verify.uid);
425 krb_set_tkt_string(krb_ticket_string);
426 verify.systemEnviron = setEnv (verify.systemEnviron,
430 verify.userEnviron = setEnv (verify.userEnviron,
434 #endif /* __KERBEROS */
436 /* set LOCATION env var */
437 if(d->displayType.location == Local) {
438 verify.systemEnviron = setEnv (verify.systemEnviron,
441 /* ITE is needed only for Local displays */
442 /* set ITE env var */
444 verify.systemEnviron = setEnv (verify.systemEnviron,
449 verify.systemEnviron = setEnv (verify.systemEnviron,
456 sprintf(gid,"%ld",(long)getgid());
457 /* set user group id (USER_GID) env var */
458 verify.systemEnviron = setEnv (verify.systemEnviron,
462 /* set root group id (ROOT_GID) env var */
463 pwd = getpwnam("root");
465 sprintf(gid,"%ld",(long)pwd->pw_gid);
466 verify.systemEnviron = setEnv (verify.systemEnviron,
473 * Run system-wide initialization file
475 if (source (&verify, d->startup) != 0)
477 Debug ("Startup program %s exited with non-zero status\n",
479 SessionExit (d, OBEYSESS_DISPLAY);
483 if ( solaris_setdevperm(d->gettyLine, verify.uid, verify.gid) == 0 ) {
484 SessionExit (d, OBEYSESS_DISPLAY);
489 if (!setjmp (abortSession)) {
490 signal (SIGTERM, catchTerm);
492 * Start the clients, changing uid/groups
493 * setting up environment and running the session
495 if (StartClient (&verify, d, &clientPid)) {
496 Debug ("Client started\n");
499 * We've changed dtlogin to pass HUP's down to the children
500 * so ignore any HUP's once the client has started.
502 signal(SIGHUP, SIG_IGN);
505 * Wait for session to end,
510 if (!setjmp (pingTime))
512 signal (SIGALRM, catchAlrm);
513 alarm (d->pingInterval * 60);
514 pid = wait ((waitType *) 0);
520 if (!PingServer (d, (Display *) NULL))
521 SessionPingFailed (d);
526 pid = wait ((waitType *) 0);
528 if (pid == clientPid)
533 * We've changed dtlogin to pass HUP's down to the children
534 * so ignore any HUP's once the client has started.
536 signal(SIGHUP, SIG_DFL);
538 LogError(ReadCatalog(
539 MC_LOG_SET,MC_LOG_FAIL_START,MC_DEF_LOG_FAIL_START));
543 * when terminating the session, nuke
544 * the child and then run the reset script
546 AbortClient (clientPid);
550 * on foreign displays without XDMCP, send a SIGTERM to the process
551 * group of the session manager. This augments the "resetServer()"
552 * routine and helps get all clients killed. It is possible for a client
553 * to have a connection to the server, but not have a window.
556 if (d->displayType.location == Foreign &&
557 d->displayType.origin != FromXDMCP )
558 AbortClient(clientPid);
563 * remove ticket file...
566 if ( IsVerifyName(VN_KRB) ) {
570 #endif /* __KERBEROS */
574 * run system-wide reset file
576 Debug ("Source reset program %s\n", d->reset);
577 source (&verify, d->reset);
579 #if defined(PAM) || defined(SUNAUTH)
581 char* user = getEnv (verify.userEnviron, "USER");
582 char* ttyLine = d->gettyLine;
584 # ifdef DEF_NETWORK_DEV
586 * If location is not local (remote XDMCP dtlogin) and
587 * remote accouting is enabled (networkDev start with /dev/...)
588 * Set tty line name to match network device for accouting.
589 * Unless the resource was specifically set, default is value
590 * of DEF_NETWORK_DEV define (/dev/dtremote)
593 if ( d->displayType.location != Local &&
594 networkDev && !strncmp(networkDev,"/dev/",5)) {
595 ttyLine = networkDev+5;
600 PamAccounting( verify.argv[0], d->name, d->utmpId, user,
601 ttyLine, clientPid, ACCOUNTING, NULL);
603 solaris_accounting( verify.argv[0], d->name, d->utmpId, user,
604 ttyLine, clientPid, ACCOUNTING, NULL);
608 solaris_resetdevperm(ttyLine);
613 SessionExit (d, OBEYSESS_DISPLAY);
618 LoadXloginResources( struct display *d )
625 char *resources = NULL;
629 if (d->resources && d->resources[0]) {
630 resources = _ExpandLang(d->resources, d->language);
631 if (access (resources, R_OK) != 0) {
632 /** fallback to the C locale for resources **/
633 Debug("LoadXloginResources - cant access %s\n", resources);
634 Debug("\t %s. Falling back to C.\n", sys_errlist[errno]);
636 resources = _ExpandLang(d->resources, "C");
637 if (access (resources, R_OK) != 0) {
638 /** can't find a resource file, so bail **/
639 Debug("LoadXloginResources - cant access %s.\n", resources);
640 Debug("\t %s. Unable to find resource file.\n",
647 if (d->authFile && strlen(d->authFile) > 0 ) {
648 authority = d->authFile;
649 auth_key = "XAUTHORITY=";
652 if (d->language && strlen(d->language) > 0 ) {
653 language = strdup(d->language);
658 * replace any "-" or "." in the language name with "_". The C
659 * preprocessor used by xrdb does not accept "-" or "." in a name.
662 while ( (p = strchr(language, '-')) != NULL ) {
666 while ( (p = strchr(language, '.')) != NULL ) {
670 if ( strlen(language) > 0 )
674 Debug("LoadXloginResources - loading resource db from %s\n", resources);
675 if((XresourceDB = XrmGetFileDatabase(resources)) == NULL)
676 Debug("LoadXloginResources - Loading resource db from %s failed\n",
679 LoadAltDtsResources(d);
681 strcpy(tmpname,"/var/dt/dtlogin_XXXXXX");
682 (void) mktemp(tmpname);
684 XrmPutFileDatabase(XresourceDB, tmpname);
686 sprintf (cmd, "%s%s %s -display %s -load %s",
687 auth_key, authority, d->xrdb, d->name, tmpname);
688 Debug ("Loading resource file: %s\n", cmd);
692 if (debugLevel <= 10)
693 if (unlink (tmpname) == -1)
694 Debug ("unlink() on %s failed\n", tmpname);
697 if (resources) free (resources);
702 /***************************************************************************
704 * LoadAltDtsResources
707 * set up alternate desktop resources..
709 ***************************************************************************/
712 LoadAltDtsResources(struct display *d)
716 char dirname[2][MAXPATHLEN];
717 char res_file[MAXPATHLEN];
718 char *rmtype; /* for XrmGetResource() */
719 XrmValue rmvalue; /* for XrmGetResource() */
720 char buf[MAXPATHLEN];
721 char tempbuf[MAXPATHLEN];
724 char altdtres[MAXPATHLEN];
725 char Altdtres[MAXPATHLEN];
728 char *resources = NULL;
730 int num_allocated = 0;
731 char **file_list = NULL;
734 if ( XrmGetResource(XresourceDB,
735 "Dtlogin*altDts", "Dtlogin*AltDts",
736 &rmtype, &rmvalue ) ) {
737 strcpy(tempbuf,rmvalue.addr);
741 strcpy(dirname[0],CDE_INSTALLATION_TOP "/config/%L/Xresources.d/");
742 strcpy(dirname[1],CDE_CONFIGURATION_TOP "/config/%L/Xresources.d/");
744 for(j = 0; j < 2 ; ++j)
746 resources = _ExpandLang(dirname[j], d->language);
747 if (access (resources, R_OK) != 0)
749 Debug("LoadAltDtsResources- cant access %s.\n", resources);
750 Debug("\t %s. Falling back to C.\n", sys_errlist[errno]);
758 resources = _ExpandLang(dirname[j], "C");
759 if (access (resources, R_OK) != 0)
761 Debug("LoadAltDtsResources- cant access %s.\n", resources);
762 Debug("\t %s.\n", sys_errlist[errno]);
765 strcpy(dirname[j], resources);
768 strcpy(dirname[j],resources);
769 Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
781 * Create a list of the alt DT files
783 * NOTE - an assumption made here is that files in /etc/dt
784 * should take precedence over files in /usr/dt. This precedence
785 * is maintained during the sort becase /etc/dt will come before
789 for(j = 0; j < 2 ; ++j) {
791 if((dirp = opendir(dirname[j])) != NULL) {
793 while((dp = readdir(dirp)) != NULL) {
795 if ((strcmp(dp->d_name, DOT) != 0) &&
796 (strcmp(dp->d_name, DOTDOT) != 0)) {
798 sprintf (res_file, "%s%s", dirname[j],dp->d_name);
799 if ((access (res_file, R_OK)) != 0)
801 Debug("LoadAltDtsResources- cant access %s.\n",
803 Debug("\t %s.\n", sys_errlist[errno]);
807 if (file_count == 0) {
808 file_list = malloc (list_incr * sizeof(char **));
809 num_allocated += list_incr;
811 if (file_count + 1 > num_allocated) {
812 num_allocated += list_incr;
813 file_list = realloc (file_list,
814 num_allocated * sizeof(char **));
816 file_list[file_count] = strdup (res_file);
825 qsort (file_list, file_count, sizeof (char *), FileNameCompare);
827 for (j = 0; j < file_count ; j++) {
829 userDb = XrmGetFileDatabase(file_list[j]);
830 XrmMergeDatabases(userDb,&XresourceDB);
832 if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
833 "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
836 * remove the trailing spaces
838 if(strchr(rmvalue.addr,' '))
839 strcpy(tempbuf, strtok(rmvalue.addr," "));
841 strcpy(tempbuf, rmvalue.addr);
843 if ((strcmp(tempbuf, "True") == 0) ||
844 (strcmp(tempbuf, "TRUE") == 0)) {
846 if ( XrmGetResource(XresourceDB,
847 "Dtlogin*altDtKey", "Dtlogin*AltDtKey",
848 &rmtype, &rmvalue ) ) {
850 sprintf(altdtres,"Dtlogin*altDtKey%d",i);
851 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
856 if ( XrmGetResource(XresourceDB,
857 "Dtlogin*altDtName", "Dtlogin*AltDtName",
858 &rmtype, &rmvalue ) ) {
859 sprintf(altdtres,"Dtlogin*altDtName%d",i);
860 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
862 if ( XrmGetResource(XresourceDB,
863 "Dtlogin*altDtStart", "Dtlogin*AltDtStart",
864 &rmtype, &rmvalue ) ) {
865 sprintf(altdtres,"Dtlogin*altDtStart%d",i);
866 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
868 if ( XrmGetResource(XresourceDB,
869 "Dtlogin*altDtLogo", "Dtlogin*AltDtLogo",
870 &rmtype, &rmvalue ) ) {
871 sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
872 XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
878 sprintf(tempbuf,"%d",i);
879 XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf);
881 if (file_count > 0) {
882 for (i = 0; i < file_count; i++) {
883 Debug ("Loading resource file: %s\n", file_list[i]);
893 * Function Name: _ExpandLang
897 * This function takes the string "string", searches for occurences of
898 * "%L" in the string and if found, the "%L" is substituted with
899 * the value of the $LANG environment variable.
901 * If $LANG is not defined, the %L is replace with NULL.
905 * _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
909 * ret_string = _ExpandLang (string);
911 * char *ret_string; Returns NULL if "string" is NULL or it points
912 * to the expanded string.
914 * char *string; The first part of the pathname. Typically
915 * the directory containing the item of interest.
917 * Note: The caller is responsible for free'ing the returned string.
939 * Count the number of expansions that will occur.
943 for (n = 0, pch = string ; pch != NULL ; ) {
944 if ((pch = strchr (pch, '%')) != NULL) {
951 return (strdup(string));
954 * We should really be calling setlocale to determine the "default"
955 * locale but setlocale's return value is not standardized across
956 * the various vendor platforms nor is it consistent within differnt
957 * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
958 * HP-UX 10.0). The "right" call would be the following line:
960 * if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
962 * Here we hard code the default to "C" instead of leaving it NULL.
964 if (lang || (lang = getenv ("LANG")) || (lang = "C"))
965 lang_len = strlen (lang);
968 * Create the space needed.
970 tmp_len = strlen (string) + (n * lang_len) + n + 1;
971 tmp = (char *) malloc (tmp_len);
972 for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
976 while (pch != NULL) {
979 if ((pch = strchr (pch, '%')) != NULL) {
984 (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
986 else if ((pch != NULL) && *pch == 'L') {
988 if (((pch - trail) >=2) && (*(pch-2) == '/'))
990 * Remove the "/" as well as the "%L".
992 (void) strncat (tmp, trail, (pch - trail) - 2);
994 (void) strncat (tmp, trail, (pch - trail) - 1);
998 * Remove the "%L" and then append the LANG.
1000 (void) strncat (tmp, trail, (pch - trail) - 1);
1001 (void) strcat (tmp, lang);
1005 (void) strncat (tmp, trail, (pch - trail) + 1);
1012 * A '%' was not found.
1014 (void) strcat (tmp, trail);
1023 SetupDisplay (struct display *d)
1025 char **env = 0, **crt_systemEnviron;
1027 if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1029 crt_systemEnviron = verify.systemEnviron;
1030 env = systemEnv (d, (char *) 0, (char *) 0);
1031 if (d->authFile && strlen(d->authFile) > 0 )
1032 env = setEnv( env, "XAUTHORITY", d->authFile );
1033 if(d->displayType.location == Local)
1034 env = setEnv (env, LOCATION, "local");
1036 env = setEnv (env, LOCATION, "remote");
1037 verify.systemEnviron = env;
1038 source (&verify, d->setup);
1039 verify.systemEnviron = crt_systemEnviron;
1046 DeleteXloginResources( struct display *d, Display *dpy )
1048 XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1051 #if 0 /* dead code: transferred to Dtgreet */
1053 static jmp_buf syncJump;
1058 longjmp (syncJump, 1);
1062 SecureDisplay (d, dpy)
1066 Debug ("SecureDisplay():\n");
1067 signal (SIGALRM, syncTimeout);
1068 if (setjmp (syncJump)) {
1069 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1071 SessionExit (d, RESERVER_DISPLAY);
1073 alarm ((unsigned) d->grabTimeout);
1074 Debug ("Before XGrabServer()\n");
1076 if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1077 GrabModeAsync, CurrentTime) != GrabSuccess)
1080 signal (SIGALRM, SIG_DFL);
1081 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1083 SessionExit (d, RESERVER_DISPLAY);
1085 Debug ("XGrabKeyboard() succeeded\n");
1087 signal (SIGALRM, SIG_DFL);
1091 XUngrabServer (dpy);
1094 Debug ("Done secure %s\n", d->name);
1097 UnsecureDisplay (d, dpy)
1101 Debug ("Unsecure display %s\n", d->name);
1103 XUngrabServer (dpy);
1112 release_aix_lic(void)
1115 * Release AIX iFOR/LS license (if any)
1123 release_me.request_type = -1;
1124 release_me.login_pid = getpid();
1125 if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1127 write(fd, &release_me, sizeof(release_me));
1130 Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1138 SessionExit( struct display *d, int status )
1147 /* make sure the server gets reset after the session is over */
1148 if (d->serverPid >= 2) {
1149 Debug("Reseting server: pid %d signal %d\n",
1150 d->serverPid, d->resetSignal);
1152 if (d->terminateServer == 0 && d->resetSignal)
1153 kill (d->serverPid, d->resetSignal);
1158 Debug("Exiting Session with status: %d\n", status);
1163 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1166 char currentdir[PATH_MAX+1];
1167 char *failsafeArgv[20];
1168 char *user; /* users name */
1169 char *lang, *font; /* failsafe LANG and font */
1172 int failsafe = FALSE; /* do we run the failsafe session? */
1173 int password = FALSE; /* do we run /bin/passwd? */
1176 char lastsessfile[MAXPATHLEN];
1179 struct pr_passwd *b1_pwd;
1183 #define NOPAG 0xffffffff
1185 long ngroups, groups[NGROUPS];
1191 Debug ("StartSession %s: ", verify->argv[0]);
1192 for (f = verify->argv; *f; f++) {
1194 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1195 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1199 if (verify->userEnviron) {
1200 for (f = verify->userEnviron; *f; f++)
1205 user = getEnv (verify->userEnviron, "USER");
1207 switch (pid = fork ()) {
1210 /* Force a failsafe session if we can't touch the home directory
1211 * SIA has already attempted to chdir to HOME, and the current dir
1212 * will be set to / if it failed. We just check to see if the HOME
1213 * path is our current directory or not.
1215 home = getEnv (verify->userEnviron, "HOME");
1216 getcwd(currentdir, PATH_MAX+1);
1217 Debug("Current directory is: %s\n", currentdir);
1221 * The following little check doesn't really work. For example,
1222 * here at the XC, NIS reports my home directory as
1223 * "/site/guests/montyb" while getcwd comes up with
1224 * "/net/nexus/site/guests/montyb".
1226 if (strcmp(home, currentdir)) {
1227 Debug("Can't access home directory, setting failsafe to TRUE\n");
1229 LogError (ReadCatalog(
1230 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1231 home, getEnv (verify->userEnviron, "USER"));
1232 verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1240 * do process accounting...
1242 #if defined(PAM) || defined(SUNAUTH)
1244 char* ttyLine = d->gettyLine;
1246 # ifdef DEF_NETWORK_DEV
1248 * If location is not local (remote XDMCP dtlogin) and
1249 * remote accouting is enabled (networkDev start with /dev/...)
1250 * Set tty line name to match network device for accouting.
1251 * Unless the resource was specifically set, default is value
1252 * of DEF_NETWORK_DEV define (/dev/dtremote)
1255 if ( d->displayType.location != Local &&
1256 networkDev && !strncmp(networkDev,"/dev/",5)) {
1257 ttyLine = networkDev+5;
1262 PamAccounting(verify->argv[0], d->name, d->utmpId, user,
1263 ttyLine, getpid(), USER_PROCESS, NULL);
1265 solaris_accounting(verify->argv[0], d->name, d->utmpId, user,
1266 ttyLine, getpid(), USER_PROCESS, NULL);
1272 Account(d, user, NULL, getpid(), USER_PROCESS, status);
1277 * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1278 * setpenv() to set up the user's process environment and return
1279 * without execing. This allows us to set up the process environment
1280 * and proceed to the execute() call as do the other platforms.
1282 * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1283 * we have to pospone the setpenv() to the actual execute().
1287 * These defines are the tag locations in userEnviron.
1288 * IMPORTANT: changes to the locations of these tags in verify.c
1289 * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1291 #define SYS_ENV_TAG 0
1292 #define USR_ENV_TAG 3
1295 * Set the user's credentials: uid, gid, groups,
1296 * audit classes, user limits, and umask.
1299 if (setpcred(user, NULL) == -1)
1301 Debug("Can't set User's Credentials (user=%s)\n",user);
1306 char *usrTag, *sysTag;
1307 extern char **newenv;
1310 * Save pointers to tags. The setpenv() function clears the pointers
1311 * to the tags in userEnviron as a side-effect.
1313 sysTag = verify->userEnviron[SYS_ENV_TAG];
1314 usrTag = verify->userEnviron[USR_ENV_TAG];
1317 * Set the users process environment. Store protected variables and
1318 * obtain updated user environment list. This call will initialize
1321 #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1322 if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1324 Debug("Can't set process environment (user=%s)\n",user);
1329 * Restore pointers to tags.
1331 verify->userEnviron[SYS_ENV_TAG] = sysTag;
1332 verify->userEnviron[USR_ENV_TAG] = usrTag;
1335 * Free old userEnviron and replace with newenv from setpenv().
1337 freeEnv(verify->userEnviron);
1338 verify->userEnviron = newenv;
1348 if (PamSetCred( verify->argv[0],
1349 user, verify->uid, verify->gid) > 0 ) {
1350 Debug("Can't set User's Credentials (user=%s)\n",user);
1356 if ( solaris_setcred(verify->argv[0],
1357 user, verify->uid, verify->gid) > 0 ) {
1358 Debug("Can't set User's Credentials (user=%s)\n",user);
1361 #endif /* SUNAUTH */
1368 * HP BLS B1 session setup...
1370 * 1. look up user's protected account information.
1371 * 2. set the session sensitivity/clearance levels
1372 * 3. set the logical UID (LUID)
1376 Debug("BLS - Setting user's clearance, security level and luid.\n");
1377 set_auth_parameters(1, verify->argv);
1380 verify->user_name = user;
1381 strncpy(verify->terminal,d->name,15);
1382 verify->terminal[15]='\0';
1383 verify->pwd = getpwnam(user);
1385 if ( verify->pwd == NULL || strlen(user) == 0 ) {
1386 LogError(ReadCatalog(
1387 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1390 verify->prpwd= b1_pwd = getprpwnam(user);
1391 verify->uid = b1_pwd->ufld.fd_uid;
1393 if ( b1_pwd == NULL || strlen(user) == 0 ) {
1394 LogError(ReadCatalog(
1395 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1400 * This has already been done successfully by dtgreet
1401 * but we need to get all the information again for the
1404 if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1405 Debug("BLS - Could not verify sensitivity level.\n");
1406 LogError(ReadCatalog(
1407 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1411 if ( change_to_user(verify) != 1 ) {
1412 Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1413 LogError(ReadCatalog(
1414 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1419 Debug("BLS - Session setup complete.\n");
1426 * This should never fail since everything has been verified already.
1427 * If it does it must mean registry strangeness, so exit, and try
1431 if (!DoLogin (user, greet.password, d->name)) exit (1);
1434 * extract the SYSTYPE and ISP environment values and set into user's
1435 * environment. This is necessary since we do an execve below...
1438 verify->userEnviron = setEnv(verify->userEnviron, "SYSTYPE",
1441 verify->userEnviron = setEnv(verify->userEnviron, "ISP",
1444 #else /* ! __apollo */
1448 if ( IsVerifyName(VN_AFS) ) {
1449 pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1450 Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1452 initgroups(greet.name, verify->groups[2]);
1453 ngroups = getgroups(NGROUPS, groups);
1454 Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1455 for (i=0; i < ngroups; i++)
1456 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1458 if ((pagval != NOPAG) &&
1459 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1460 /* we will have to shift grouplist to make room for pag */
1461 if (ngroups+2 > NGROUPS)
1463 for (j=ngroups-1; j >= 0; j--) {
1464 groups[j+2] = groups[j];
1467 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1468 if (setgroups(ngroups, groups) == -1) {
1471 MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1476 # else /* ! __AFS */
1477 /* If SIA is enabled, the initgroups and setgid calls are redundant
1484 * if your system does not support "initgroups(3C)", use
1485 * the "setgroups()" call instead...
1488 # if (defined(__hpux) || defined(__osf__))
1489 initgroups(user, -1);
1491 setgroups (verify->ngroups, verify->groups);
1494 /* setpenv() will set gid for AIX */
1496 setgid (verify->groups[0]);
1499 # else /* ! NGROUPS */
1501 /* setpenv() will set gid for AIX */
1503 setgid (verify->gid);
1506 # endif /* NGROUPS */
1512 setaudid(verify->audid);
1513 setaudproc(verify->audflg);
1516 /* setpenv() will set uid for AIX */
1518 if (setuid(verify->uid) != 0) {
1519 Debug( "Setuid failed for user %s, errno = %d\n", user, errno);
1520 LogError(ReadCatalog(
1521 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1527 #endif /* __apollo */
1530 } /* ends the else clause of if ( ISSECURE ) */
1536 * check home directory again...
1540 /* Don't need to do this if SIA is enabled, already been done.
1542 home = getEnv (verify->userEnviron, "HOME");
1544 if (chdir (home) == -1) {
1545 LogError (ReadCatalog(
1546 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1547 home, getEnv (verify->userEnviron, "USER"));
1549 verify->userEnviron = setEnv(verify->userEnviron,
1552 else if(!failsafe) {
1553 strcpy(lastsessfile,home); /* save user's last session */
1554 strcat(lastsessfile,LAST_SESSION_FILE);
1555 if((lastsession = fopen(lastsessfile,"w")) == NULL)
1556 Debug("Unable to open file for writing: %s\n",lastsessfile);
1558 fputs(verify->argv[0],lastsession);
1559 fclose(lastsession);
1566 SetUserAuthorization (d, verify);
1572 bzero(greet.password, strlen(greet.password));
1576 * Write login information to a file
1577 * The file name should really be settable by some kind of resource
1578 * but time is short so we hard-wire it to ".dtlogininfo".
1580 if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1581 Debug("Unable to write \".dtlogininfo\"\n");
1583 /* extra debugging */
1584 if(!dump_sec_debug_info(verify)) {
1585 Debug("Something wrong with environment\n");
1588 # endif /* ! NDEBUG */
1596 Debug ("Executing session %s\n", verify->argv[0]);
1597 execute (verify->argv, verify->userEnviron);
1598 LogError(ReadCatalog(
1599 MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1603 LogError(ReadCatalog(
1604 MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1611 * specify a font for the multi-byte languages...
1615 lang = getEnv (verify->userEnviron, "LANG");
1622 failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1624 failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1625 #elif defined (USL) || defined(__uxp__)
1626 failsafeArgv[i++] = "/usr/X/bin/xterm";
1627 #elif defined(__hpux)
1628 failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1630 failsafeArgv[i++] = "/usr/bin/X11/xterm";
1632 failsafeArgv[i++] = "-geometry";
1633 failsafeArgv[i++] = "80x10";
1634 failsafeArgv[i++] = "-bg";
1635 failsafeArgv[i++] = "white";
1636 failsafeArgv[i++] = "-fg";
1637 failsafeArgv[i++] = "black";
1639 /* aixterm requires -lang option. */
1640 failsafeArgv[i++] = "-lang";
1641 failsafeArgv[i++] = lang;
1643 failsafeArgv[i++] = "-fn";
1645 if (font == NULL) font = "fixed";
1646 failsafeArgv[i++] = font;
1649 failsafeArgv[i++] = "-e";
1650 failsafeArgv[i++] = "/bin/passwd";
1651 #if defined (__apollo) || defined(__PASSWD_ETC)
1652 failsafeArgv[i++] = "-n";
1654 failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1657 failsafeArgv[i++] = d->failsafeClient;
1659 failsafeArgv[i++] = "-C";
1661 failsafeArgv[i++] = "-ls";
1664 failsafeArgv[i++] = "-fn";
1665 failsafeArgv[i++] = font;
1669 failsafeArgv[i] = 0;
1670 Debug ("Executing failsafe session\n", failsafeArgv[0]);
1671 execute (failsafeArgv, verify->userEnviron);
1674 Debug ("StartSession(): fork failed\n");
1675 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1679 Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1686 static jmp_buf tenaciousClient;
1689 waitAbort( int arg )
1691 longjmp (tenaciousClient, 1);
1694 #if defined(SYSV) || defined(SVR4)
1696 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1700 AbortClient( int pid )
1709 for (i = 0; i < 4; i++) {
1710 if (killpg (pid, sig) == -1) {
1713 LogError(ReadCatalog(
1714 MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1720 if (!setjmp (tenaciousClient)) {
1721 (void) signal (SIGALRM, waitAbort);
1722 (void) alarm ((unsigned) 10);
1723 retId = wait ((waitType *) 0);
1724 (void) alarm ((unsigned) 0);
1725 (void) signal (SIGALRM, SIG_DFL);
1729 signal (SIGALRM, SIG_DFL);
1735 source( struct verify_info *verify, char *file )
1741 if (file && file[0]) {
1742 Debug ("Source(): %s\n", file);
1743 switch (pid = fork ()) {
1748 execute (args, verify->systemEnviron);
1749 LogError(ReadCatalog(
1750 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1753 Debug ("Source(): fork failed\n");
1754 LogError(ReadCatalog(
1755 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1759 while (wait (&result) != pid)
1763 return waitVal (result);
1769 execute(char **argv, char **environ )
1773 * make stdout follow stderr to the log file...
1778 session_execve (argv[0], argv, environ);
1781 * In case this is a shell script which hasn't been made executable
1782 * (or this is a SYSV box), do a reasonable thing...
1786 /* errno is EACCES if not executable */
1787 if (errno == ENOEXEC || errno == EACCES) {
1789 if (errno == ENOEXEC) {
1791 char program[1024], *e, *p, *optarg;
1793 char **newargv, **av;
1797 * emulate BSD kernel behaviour -- read
1798 * the first line; check if it starts
1799 * with "#!", in which case it uses
1800 * the rest of the line as the name of
1801 * program to run. Else use "/bin/sh".
1803 f = fopen (argv[0], "r");
1806 if (fgets (program, sizeof (program) - 1, f) == NULL)
1812 e = program + strlen (program) - 1;
1815 if (!strncmp (program, "#!", 2)) {
1817 while (*p && isspace (*p))
1820 while (*optarg && !isspace (*optarg))
1826 while (*optarg && isspace (*optarg));
1833 Debug ("Shell script execution: %s (optarg %s)\n",
1834 p, optarg ? optarg : "(null)");
1835 for (av = argv, argc = 0; *av; av++, argc++)
1837 newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1844 while (*av++ = *argv++)
1846 session_execve (newargv[0], newargv, environ);
1853 /*****************************************************************************
1856 * Invoke the Greeter process and wait for completion. If the user was
1857 * successfully verified, return to the calling process. If the user
1858 * selected a restart or abort option, or there was an error invoking the
1859 * Greeter, exit this entire process with appropriate status.
1861 *****************************************************************************/
1865 extern int session_set;
1866 extern char *progName; /* Global argv[0]; dtlogin name and path */
1868 int response[2], request[2];
1870 /* Fixes problem with dtlogin signal handling */
1871 static int greeterPid = 0;
1872 static struct display *greeter_d = NULL;
1877 Debug("Caught SIGHUP\n");
1880 Debug("Killing greeter process: %d\n", greeterPid);
1881 kill(greeterPid, SIGHUP);
1884 SessionExit(greeter_d, REMANAGE_DISPLAY);
1886 exit(REMANAGE_DISPLAY);
1890 RunGreeter( struct display *d, struct greet_info *greet,
1891 struct verify_info *verify )
1898 static char msg[MSGSIZE];
1902 struct greet_state state;
1907 # define U_NAMELEN sizeof(rgy_$name_t)
1911 static char name_short[U_NAMELEN];
1917 char *argv[] = { "dtlogin", 0 };
1918 char *hostName = NULL;
1919 char *loginName = NULL;
1926 if (d->serverPid == -1)
1929 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
1930 loginName, d->name, 1, NULL);
1931 if (siaStatus != SIASUCCESS)
1933 Debug("sia_ses_init failure status %d\n", siaStatus);
1940 if (!setjmp (abortSession)) {
1941 signal(SIGTERM, catchTerm);
1944 * We've changed dtlogin to pass HUP's down to the children
1945 * so ignore any HUP's once the client has started.
1948 signal(SIGHUP, catchHUP);
1951 * set up communication pipes...
1959 switch (greeterPid = fork ()) {
1963 * pass some information in the environment...
1967 sprintf(msg,"%d", d->grabServer);
1968 env = setEnv(env, GRABSERVER, msg);
1970 sprintf(msg,"%d", d->grabTimeout);
1971 env = setEnv(env, GRABTIMEOUT, msg);
1974 if (timeZone && strlen(timeZone) > 0 )
1975 env = setEnv(env, "TZ", timeZone);
1977 if (errorLogFile && errorLogFile[0])
1978 env = setEnv(env, ERRORLOG, errorLogFile);
1981 env = setEnv(env, "XAUTHORITY", d->authFile);
1984 env = setEnv(env, DTLITE, "True");
1987 env = setEnv(env, SESSION, d->session);
1990 env = setEnv(env, SESSION_SET, "True");
1992 if (d->pmSearchPath)
1993 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
1995 if (d->bmSearchPath)
1996 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
1998 #if defined (__KERBEROS) || defined (__AFS)
1999 if (d->verifyName) {
2000 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2001 (strcmp(d->verifyName, VN_KRB) == 0) ) {
2003 env = setEnv(env, VERIFYNAME, d->verifyName );
2006 LogError(ReadCatalog(
2007 MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2009 d->verifyName = NULL;
2014 if((path = getenv("NLSPATH")) != NULL)
2015 env = setEnv(env, "NLSPATH", path);
2017 env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2022 * ping remote displays...
2026 if (d->displayType.location == Local) {
2027 GettyRunning(d); /* refresh gettyState */
2028 if (d->gettyState != DM_GETTY_USER)
2029 env = setEnv(env, LOCATION, "local");
2032 sprintf(msg,"%d", d->pingInterval);
2033 env = setEnv(env, PINGINTERVAL, msg);
2035 sprintf(msg,"%d", d->pingTimeout);
2036 env = setEnv(env, PINGTIMEOUT, msg);
2040 if ( d->langList && strlen(d->langList) > 0 )
2041 env = setEnv(env, LANGLIST, d->langList);
2042 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2043 else if (languageList && strlen(languageList) > 0 )
2044 env = setEnv(env, LANGLIST, languageList);
2045 #endif /* ENABLE_DYNAMIC_LANGLIST */
2048 char *language = NULL;
2050 #if defined (ENABLE_DYNAMIC_LANGLIST)
2051 language = d->language;
2052 #endif /* ENABLE_DYNAMIC_LANGLIST */
2054 if ( d->language && strlen(d->language) > 0 )
2055 env = setLang(d, env, language);
2058 if((path = getenv("XKEYSYMDB")) != NULL)
2059 env = setEnv(env, "XKEYSYMDB", path);
2062 if((path = getenv("OPENWINHOME")) != NULL)
2063 env = setEnv(env, "OPENWINHOME", path);
2068 * set environment for Domain machines...
2070 env = setEnv(env, "ENVIRONMENT", "bsd");
2071 env = setEnv(env, "SYSTYPE", "bsd4.3");
2075 Debug ("Greeter environment:\n");
2077 Debug ("End of Greeter environment:\n");
2080 * Writing to file descriptor 1 goes to response pipe instead.
2088 * Reading from file descriptor 0 reads from request pipe instead.
2098 * figure out path to dtgreet...
2101 strcpy(msg, progName);
2103 if ((p = (char *) strrchr(msg, '/')) == NULL)
2108 strcat(msg,"dtgreet");
2110 execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2111 LogError(ReadCatalog(
2112 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2114 exit (NOTIFY_ABORT_DISPLAY);
2117 Debug ("Fork of Greeter failed.\n");
2118 LogError(ReadCatalog(
2119 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2124 exit (UNMANAGE_DISPLAY);
2127 Debug ("Greeter started\n");
2129 close(response[1]); /* Close write end of response pipe */
2130 close(request[0]); /* Close read end of request pipe */
2134 * Retrieve information from greeter and authenticate.
2136 globalDisplayName = d->name;
2137 state.id = GREET_STATE_ENTER;
2138 state.waitForResponse = FALSE;
2142 * atexit() registers this function to be called if exit() is
2143 * called. This is needed because in enhanced security mode, SIA
2144 * may call exit() whn the user fails to enter or change a
2147 sia_greeter_pid = greeterPid;
2148 if (!sia_exit_proc_reg)
2150 atexit(KillGreeter);
2151 sia_exit_proc_reg = TRUE;
2154 siaGreeterInfo.d = d;
2155 siaGreeterInfo.greet = greet;
2156 siaGreeterInfo.verify = verify;
2157 siaGreeterInfo.state = &state;
2158 siaGreeterInfo.status = TRUE;
2161 while(siaStatus != SIASUCCESS)
2163 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2165 Debug ("RunGreeter: before sia_ses_authent\n");
2166 dt_in_sia_ses_authent = True;
2167 siaStatus = sia_ses_authent(SiaManageGreeter, NULL,
2169 dt_in_sia_ses_authent = False;
2170 Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2172 if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2174 state.id = GREET_STATE_ERRORMESSAGE;
2175 state.vf = VF_INVALID;
2176 ManageGreeter(d, greet, verify, &state);
2178 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2181 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2183 sia_ses_release(&siaHandle);
2187 Debug("RunGreeter: before sia_ses_estab\n");
2188 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2189 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2192 if (!siaGreeterInfo.status)
2195 if (siaStatus == SIASUCCESS)
2197 Debug("RunGreeter: before sia_ses_launch\n");
2198 siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2199 Debug("RunGreeter: after sia_ses_launch status = %d\n",
2202 if (!siaGreeterInfo.status)
2205 if (siaStatus != SIASUCCESS)
2207 Debug("RunGreeter: sia_ses_launch failure\n");
2208 /* establish & launch failures do a release */
2210 siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName,
2211 loginName, d->name, 1, NULL);
2212 if (siaStatus != SIASUCCESS)
2214 Debug("sia_ses_init failure status %d\n", siaStatus);
2215 exit(RESERVER_DISPLAY);
2220 * sia_ses_launch() wil probably seteuid to that of the
2221 * user, but we don't want that now.
2225 * extract necessary info from SIA context struct
2229 if (siaStatus == SIASUCCESS)
2230 CopySiaInfo(siaHandle, greet);
2231 sia_ses_release(&siaHandle);
2233 state.id = GREET_STATE_TERMINATEGREET;
2234 if (siaGreeterInfo.status)
2236 while (ManageGreeter(d, greet, verify, &state))
2239 sia_greeter_pid = 0;
2241 while (ManageGreeter(d, greet, verify, &state))
2246 * Wait for Greeter to end...
2249 pid = wait (&status);
2250 if (pid == greeterPid)
2256 * Greeter exited. Check return code...
2259 Debug("Greeter return status; exit = %d, signal = %d\n",
2260 waitCode(status), waitSig(status));
2264 * remove authorization file if used...
2267 if (d->authorizations && d->authFile &&
2268 waitVal(status) != NOTIFY_LANG_CHANGE
2270 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2275 Debug ("Done with authorization file %s, removing\n",
2277 (void) unlink (d->authFile);
2282 if(waitVal(status) > NOTIFY_ALT_DTS)
2283 d->sessionType = waitVal(status);
2286 switch (waitVal(status)) {
2287 case NOTIFY_FAILSAFE:
2288 greet->string = "failsafe";
2290 case NOTIFY_PASSWD_EXPIRED:
2291 greet->string = "password";
2296 case NOTIFY_LAST_DT:
2297 d->sessionType = waitVal(status);
2303 Debug("waitVal - status is %d\n", waitVal(status));
2304 if(waitVal(status) > NOTIFY_ALT_DTS)
2305 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2307 notify_dt = waitVal(status);
2309 switch (notify_dt) {
2310 case NOTIFY_FAILSAFE:
2311 case NOTIFY_PASSWD_EXPIRED:
2315 case NOTIFY_LAST_DT:
2316 case NOTIFY_ALT_DTS:
2318 if (NULL == greet->name) return;
2321 * greet->name, greet->password set in ManageGreeter().
2323 Debug("Greeter returned name '%s'\n", greet->name);
2326 greet->name_full = greet->name;
2327 /* get just person name out of full SID */
2329 while (i < sizeof(rgy_$name_t)
2330 && greet->name_full[i] != '.'
2331 && greet->name_full[i] != '\0') {
2332 name_short[i] = greet->name_full[i];
2335 name_short[i] = '\0';
2336 greet->name = name_short;
2341 * groups[] set in Authenticate().
2343 if ( IsVerifyName(VN_AFS) ) {
2344 verify->groups[0] = groups[0];
2345 verify->groups[1] = groups[1];
2346 Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2347 Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2353 * sensitivityLevel set in BLS_Verify()
2355 greet->b1security = sensitivityLevel;
2358 Verify(d, greet, verify);
2362 Debug ("Greeter Xlib error or SIGTERM\n");
2363 SessionExit(d, OPENFAILED_DISPLAY);
2365 case NOTIFY_RESTART:
2366 Debug ("Greeter requested RESTART_DISPLAY\n");
2367 SessionExit(d, RESERVER_DISPLAY);
2369 case NOTIFY_ABORT_DISPLAY:
2370 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2371 SessionExit(d, UNMANAGE_DISPLAY);
2373 case NOTIFY_NO_WINDOWS:
2374 Debug ("Greeter requested NO_WINDOWS mode\n");
2375 if (d->serverPid >= 2)
2377 * Don't do a SessionExit() here since that causes
2378 * the X-server to be reset. We know we are going to
2379 * terminate it anyway, so just go do that...
2381 exit(SUSPEND_DISPLAY);
2385 case NOTIFY_LANG_CHANGE:
2386 Debug ("Greeter requested LANG_CHANGE\n");
2389 * copy requested language into display struct "d". Note,
2390 * this only happens in this child's copy of "d", not in
2391 * the master struct. When the user logs out, the
2392 * resource-specified language (if any) will reactivate.
2394 Debug("Greeter returned language '%s'\n", d->language);
2396 if (strcmp(d->language, "default") == 0) {
2397 int len = strlen(defaultLanguage) + 1;
2398 d->language = (d->language == NULL ?
2399 malloc(len) : realloc (d->language, len));
2400 strcpy(d->language, defaultLanguage);
2404 case NOTIFY_BAD_SECLEVEL:
2407 case waitCompose (SIGTERM,0,0):
2408 Debug ("Greeter exited on SIGTERM\n");
2409 SessionExit(d, OPENFAILED_DISPLAY);
2412 Debug ("Greeter returned unknown status %d\n",
2414 SessionExit(d, REMANAGE_DISPLAY);
2417 signal(SIGHUP, SIG_DFL);
2420 AbortClient(greeterPid);
2421 SessionExit(d, UNMANAGE_DISPLAY);
2425 /*****************************************************************************
2431 This is the entry into greeter state processing. Allocate and initialize
2435 Display the login screen. Upon display, the login screen can be 'reset'. If
2436 reset is true, the username and password fields are cleared and the focus
2437 is set to the username field. If reset is false, the username and password
2438 field is untouched and the focus is set to the password field.
2440 LOGIN -> AUTHENTICATE:
2441 Authenticate the username entered on login screen.
2443 AUTHENTICATE -> TERMINATEGREET:
2444 User passed authentication so terminate the greeter.
2446 AUTHENTICATE -> EXPASSWORD:
2447 User passed authentication, but the their password has expired.
2448 Display old password message. This message allows the user to
2449 change their password by starting a getty and running passwd(1).
2451 AUTHENTICATE -> BAD_HOSTNAME:
2452 User passed authentication, but the their hostname is empty.
2453 Display a dialog that allows the user to run a getty to fix the
2454 problem, or start the desktop anyway.
2456 AUTHENTICATE -> ERRORMESSAGE:
2457 User failed authentication, so display error message.
2459 AUTHENTICATE -> LOGIN
2460 User failed authentication, but did not enter a password. Instead
2461 of displaying an error message, redisplay the login screen with
2462 the focus set to the password field. If the user authenticates again
2463 without the password field set, display an error. This allows a user
2464 to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2467 Free state structure and return false to stop state transitions.
2469 ERRORMESSAGE -> LOGIN
2470 Display error message base on return code from last authentication
2471 attempt. Redisplay login screen with reset set to true.
2473 (state) -> LANG -> (state)
2474 User has chosen a new language. Transition to LANG state to save off
2475 the new language, and transition back to original state.
2477 *****************************************************************************/
2479 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2482 ManageGreeter( struct display *d, struct greet_info *greet,
2483 struct verify_info *verify, struct greet_state *state )
2490 if (state->waitForResponse)
2492 if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2495 * Dtgreet has terminated.
2497 state->id = GREET_STATE_EXIT;
2498 state->waitForResponse = FALSE;
2502 if (state->request->opcode != state->response->opcode)
2505 * An unrequested event arrived. See if it's one we
2508 switch(state->response->opcode)
2510 case REQUEST_OP_LANG:
2513 * User has changed language. Recursively handle this state
2514 * and return to current state.
2516 struct greet_state lang_state;
2518 lang_state = *state;
2519 lang_state.id = GREET_STATE_LANG;
2520 lang_state.waitForResponse = FALSE;
2521 ManageGreeter(d, greet, verify, &lang_state);
2522 Debug("Response opcode REQUEST_OP_LANG\n");
2527 case REQUEST_OP_CLEAR:
2530 * User has requested the screen be cleared.
2532 state->id = GREET_STATE_USERNAME;
2533 state->waitForResponse = TRUE;
2534 Debug("Response opcode REQUEST_OP_CLEAR\n");
2539 Debug("Response opcode UNEXPECTED RESPONSE!\n");
2549 * Got the response we were expecting.
2551 state->waitForResponse = FALSE;
2557 case GREET_STATE_ENTER:
2560 * Enter - initialize state
2562 Debug("GREET_STATE_ENTER\n");
2564 state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2565 state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2566 state->authenticated = FALSE;
2569 state->id = GREET_STATE_USERNAME;
2573 case GREET_STATE_USERNAME:
2578 RequestChallenge *r;
2580 Debug("GREET_STATE_USERNAME\n");
2582 Authenticate(d, NULL, NULL, NULL);
2584 SETMC(msg, LOGIN_LABEL);
2586 r = (RequestChallenge *)state->request;
2587 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2588 r->hdr.reserved = 0;
2591 r->hdr.length = sizeof(*r);
2593 r->offChallenge = sizeof(*r);
2594 strcpy(((char *)r) + r->offChallenge, msg.def);
2595 r->hdr.length += strlen(msg.def) + 1;
2599 r->offUserNameSeed = r->hdr.length;
2600 strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2601 r->hdr.length += strlen(greet->name) + 1;
2602 Debug("Greet name: %s\n", greet->name);
2606 r->offUserNameSeed = 0;
2611 free(greet->name); greet->name = NULL;
2613 if (greet->password)
2615 free(greet->password); greet->password = NULL;
2618 TellGreeter((RequestHeader *)r);
2619 state->waitForResponse = TRUE;
2621 state->id = GREET_STATE_AUTHENTICATE;
2625 case GREET_STATE_CHALLENGE:
2630 RequestChallenge *r;
2632 Debug("GREET_STATE_CHALLENGE\n");
2634 if (greet->password)
2636 free(greet->password); greet->password = NULL;
2639 SETMC(msg, PASSWD_LABEL);
2641 r = (RequestChallenge *)state->request;
2642 r->hdr.opcode = REQUEST_OP_CHALLENGE;
2643 r->hdr.reserved = 0;
2646 r->offUserNameSeed = 0;
2647 r->offChallenge = sizeof(*r);
2648 strcpy(((char *)r) + r->offChallenge, msg.def);
2649 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2651 TellGreeter((RequestHeader *)r);
2652 state->waitForResponse = TRUE;
2654 state->id = GREET_STATE_AUTHENTICATE;
2658 case GREET_STATE_AUTHENTICATE:
2661 * Attempt to authenticate.
2663 ResponseChallenge *r;
2665 Debug("GREET_STATE_AUTHENTICATE\n");
2667 r = (ResponseChallenge *)state->response;
2669 if (greet->name == NULL)
2671 greet->name = strdup(((char *)r) + r->offResponse);
2672 if (strlen(greet->name) == 0)
2674 state->id = GREET_STATE_USERNAME;
2680 greet->password = strdup(((char *)r) + r->offResponse);
2690 * Attempt to authenticate user. 'username' should be a
2691 * non-empty string. 'password' may be an empty string.
2693 state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2695 if (state->vf == VF_OK ||
2696 state->vf == VF_PASSWD_AGED ||
2697 state->vf == VF_BAD_HOSTNAME)
2699 state->authenticated = TRUE;
2703 * General transitions.
2707 case VF_OK: state->id = GREET_STATE_TERMINATEGREET; break;
2708 case VF_PASSWD_AGED: state->id = GREET_STATE_EXPASSWORD; break;
2709 case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break;
2710 case VF_CHALLENGE: state->id = GREET_STATE_CHALLENGE; break;
2711 default: state->id = GREET_STATE_ERRORMESSAGE; break;
2716 case GREET_STATE_EXIT:
2719 * Free resources and leave.
2721 Debug("GREET_STATE_EXIT\n");
2728 if (!state->authenticated)
2732 free(greet->name); greet->name = NULL;
2734 if (greet->password)
2736 free(greet->password); greet->password = NULL;
2740 free(state->request);
2741 free(state->response);
2746 case GREET_STATE_ERRORMESSAGE:
2749 * Display error message.
2753 Debug("GREET_STATE_ERRORMESSAGE\n");
2755 r = (RequestMessage *)state->request;
2759 case VF_INVALID: SETMC(msg, LOGIN); break;
2760 case VF_HOME: SETMC(msg, HOME); break;
2761 case VF_MAX_USERS: SETMC(msg, MAX_USERS); break;
2762 case VF_BAD_UID: SETMC(msg, BAD_UID); break;
2763 case VF_BAD_GID: SETMC(msg, BAD_GID); break;
2764 case VF_BAD_AID: SETMC(msg, BAD_AID); break;
2765 case VF_BAD_AFLAG: SETMC(msg, BAD_AFLAG); break;
2766 case VF_NO_LOGIN: SETMC(msg, NO_LOGIN); break;
2768 case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2770 case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2771 default: msg.id=0; msg.def=""; break;
2774 r->hdr.opcode = REQUEST_OP_MESSAGE;
2775 r->hdr.reserved = 0;
2777 r->offMessage = sizeof(*r);
2778 strcpy(((char *)r) + r->offMessage, msg.def);
2779 r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2781 TellGreeter((RequestHeader *)r);
2782 state->waitForResponse = TRUE;
2784 state->id = GREET_STATE_USERNAME;
2788 case GREET_STATE_LANG:
2791 * User selected new language.
2797 Debug("GREET_STATE_LANG\n");
2799 r = (ResponseLang *)state->response;
2800 lang = ((char *)r) + r->offLang;
2801 len = strlen(lang) + 1;
2803 d->language = (d->language == NULL ?
2804 malloc(len) : realloc(d->language, len));
2805 strcpy(d->language, lang);
2806 Debug("Language returned: %s\n", d->language);
2810 case GREET_STATE_TERMINATEGREET:
2813 * Terminate dtgreet.
2817 Debug("GREET_STATE_TERMINATEGREET\n");
2819 r = (RequestExit *)state->request;
2821 r->hdr.opcode = REQUEST_OP_EXIT;
2822 r->hdr.reserved = 0;
2823 r->hdr.length = sizeof(*r);
2825 TellGreeter((RequestHeader *)r);
2826 state->waitForResponse = TRUE;
2828 state->id = GREET_STATE_EXIT;
2832 case GREET_STATE_EXPASSWORD:
2835 * Display password expired message.
2837 RequestExpassword *r;
2839 Debug("GREET_STATE_EXPASSWORD\n");
2841 r = (RequestExpassword *)state->request;
2843 r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2844 r->hdr.reserved = 0;
2845 r->hdr.length = sizeof(*r);
2847 TellGreeter((RequestHeader *)r);
2848 state->waitForResponse = TRUE;
2850 state->id = GREET_STATE_USERNAME;
2854 case GREET_STATE_BAD_HOSTNAME:
2857 * Display password expired message.
2861 Debug("GREET_STATE_BAD_HOSTNAME\n");
2863 r = (RequestHostname *)state->request;
2865 r->hdr.opcode = REQUEST_OP_HOSTNAME;
2866 r->hdr.reserved = 0;
2867 r->hdr.length = sizeof(*r);
2869 TellGreeter((RequestHeader *)r);
2870 state->waitForResponse = TRUE;
2872 state->id = GREET_STATE_USERNAME;
2877 case GREET_STATE_FORM:
2880 * Get arbitrary number of answers.
2883 Debug("GREET_STATE_FORM\n");
2885 AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2887 state->waitForResponse = FALSE;
2888 state->id = GREET_STATE_USERNAME;
2900 RequestHeader *phdr)
2902 write(request[1], phdr, phdr->length);
2907 RequestHeader *preqhdr,
2913 ResponseHeader *phdr = (ResponseHeader *)buf;
2915 if (preqhdr) TellGreeter(preqhdr);
2917 phdr->opcode = REQUEST_OP_NONE;
2919 count = read(response[0], buf, sizeof(*phdr));
2921 if (count == sizeof(*phdr))
2924 * Calculate amount of data after header.
2926 remainder = phdr->length - sizeof(*phdr);
2930 * Read remainder of response.
2932 count += read(response[0], buf+sizeof(*phdr), remainder);
2937 if (debugLevel) PrintResponse(phdr, count);
2946 ResponseHeader *phdr,
2949 char *opstr = "UNKNOWN";
2953 Debug("opcode = (EOF)\n");
2957 switch(phdr->opcode)
2959 case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2960 case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2961 case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2962 case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2963 case REQUEST_OP_LANG: opstr = "LANG"; break;
2964 case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
2967 Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
2968 Debug(" reserved = %d\n", phdr->reserved);
2969 Debug(" length = %d\n", phdr->length);
2971 switch(phdr->opcode)
2973 case REQUEST_OP_EXIT: break;
2974 case REQUEST_OP_LANG:
2975 Debug(" offLang=%d\n", ((ResponseLang *)phdr)->offLang);
2976 Debug(" lang='%s'\n",
2977 ((char *)phdr)+((ResponseLang *)phdr)->offLang);
2979 case REQUEST_OP_MESSAGE: break;
2980 case REQUEST_OP_CHPASS: break;
2981 case REQUEST_OP_CHALLENGE:
2982 Debug(" offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
2983 Debug(" response='%s'\n",
2984 ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
2986 case REQUEST_OP_DEBUG:
2987 Debug(" offString=%d\n", ((ResponseDebug *)phdr)->offString);
2988 Debug(" string='%s'\n",
2989 ((char *)phdr)+((ResponseDebug *)phdr)->offString);
2997 /***************************************************************************
3001 * generate kerberos ticket file name. Name is returned in the static
3002 * global variable "krb_ticket_string".
3004 ***************************************************************************/
3007 SetTicketFileName(uid_t uid)
3016 * generate ticket file pathname (/tmp/tkt<uid>.<host>) ...
3019 if (env = (char *)getenv("KRBTKFILE")) {
3020 (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3021 krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3024 if (gethostname(lhost, sizeof(lhost)) != -1) {
3025 if (p = index(lhost, '.')) *p = '\0';
3026 (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3028 /* 32 bits of signed integer will always fit in 11 characters
3029 (including the sign), so no need to worry about overflow */
3030 (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3035 #endif /* __KERBEROS */
3037 #if defined (_AIX) && !defined (_POWER)
3039 /***************************************************************************
3043 * If this is an authenticated process (LOGNAME set), set user's
3044 * process environment by calling setpenv().
3046 * If this is not an authenticated process, just call execve()
3048 ***************************************************************************/
3057 char *user = getEnv (envp, "LOGNAME");
3061 rc = execve(path, argv, envp);
3065 char *usrTag, *sysTag;
3068 * Save pointers to tags. The setpenv() function clears the pointers
3069 * to the tags in userEnviron as a side-effect.
3071 sysTag = envp[SYS_ENV_TAG];
3072 usrTag = envp[USR_ENV_TAG];
3075 * Set the users process environment. This call execs arvg so it
3076 * should not return. It it should return, restore the envp tags.
3078 rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3081 * Restore pointers to tags.
3083 envp[SYS_ENV_TAG] = sysTag;
3084 envp[USR_ENV_TAG] = usrTag;
3089 #endif /* _AIX && !_POWER */
3093 /* collect the SIA parameters from a window system. */
3095 static int SiaManageGreeter(
3098 unsigned char *title,
3104 RequestMessage greeter_message;
3105 char msg_buffer[256];
3106 } greeter_msg_and_buffer;
3107 RequestForm *request_form;
3115 if (rendition == SIAFORM && dt_in_sia_ses_authent
3116 && (num_prompts == 2))
3118 /* Normal login, Password case */
3119 Debug ("SIAFORM Normal login, Password case\n");
3120 while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3121 && siaGreeterInfo.state->id != GREET_STATE_EXIT
3122 && (siaGreeterInfo.status = ManageGreeter(
3123 siaGreeterInfo.d, siaGreeterInfo.greet,
3124 siaGreeterInfo.verify, siaGreeterInfo.state)))
3127 if (!siaGreeterInfo.status
3128 || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3129 return(SIACOLABORT);
3131 strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name,
3132 prompt[0].max_result_length);
3133 strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3134 prompt[1].max_result_length);
3141 ResponseForm *response_form;
3146 Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3149 Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3152 Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3155 Debug("SIAFORM num_prompts = %d\n", num_prompts);
3159 /* need to display form */
3161 req_form_size = sizeof(RequestForm)
3162 + strlen((const char *)title) + 1;
3163 for (i=0; i<num_prompts; i++)
3164 req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3165 request_form = (RequestForm *) alloca(req_form_size);
3167 siaGreeterInfo.state->id = GREET_STATE_FORM;
3168 siaGreeterInfo.state->request = (RequestHeader *)request_form;
3169 /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3171 request_form->hdr.opcode = REQUEST_OP_FORM;
3172 request_form->hdr.reserved = 0;
3173 request_form->hdr.length = req_form_size;
3174 request_form->num_prompts = num_prompts;
3175 request_form->rendition = rendition;
3176 request_form->offTitle = sizeof(RequestForm);
3177 request_form->offPrompts = sizeof(RequestForm) +
3178 strlen((const char *)title) + 1;
3179 strcpy((char *)request_form + request_form->offTitle,
3180 (const char *)title);
3182 pmpt_ptr = (char *)request_form + request_form->offPrompts;
3183 for (i=0; i<num_prompts; i++)
3185 if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3189 Debug(" prompt[%d]: %s\n", i, prompt[i].prompt);
3190 strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3191 pmpt_ptr += strlen((const char *)prompt[i].prompt);
3193 request_form->visible[i] =
3194 (prompt[i].control_flags & SIARESINVIS) ? False : True;
3197 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3198 siaGreeterInfo.greet,
3199 siaGreeterInfo.verify,
3200 siaGreeterInfo.state);
3202 response_form = (ResponseForm *)siaGreeterInfo.state->response;
3203 res_ptr = (char *)response_form + response_form->offAnswers;
3204 for (i = 0; i < response_form->num_answers; i++)
3206 if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3209 prompt[i].result = (unsigned char *)1;
3211 prompt[i].result = NULL;
3215 strcpy((char *)prompt[0].result, res_ptr);
3217 res_ptr += strlen(res_ptr) + 1;
3219 if (!response_form->collect_status)
3220 siaGreeterInfo.status = FALSE;
3226 Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3228 siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3229 siaGreeterInfo.state->request = (RequestHeader *)
3230 &greeter_msg_and_buffer.greeter_message;
3231 siaGreeterInfo.state->vf = VF_MESSAGE;
3232 siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3234 siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d,
3235 siaGreeterInfo.greet,
3236 siaGreeterInfo.verify,
3237 siaGreeterInfo.state);
3240 return(SIACOLABORT);
3243 if (!siaGreeterInfo.status)
3244 return(SIACOLABORT);
3245 return(SIACOLSUCCESS);
3248 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3251 greet->name = malloc(strlen(siaHandle->name) + 1);
3252 strcpy (greet->name, siaHandle->name);
3254 greet->password = malloc(strlen(siaHandle->password) + 1);
3255 strcpy (greet->password, siaHandle->password);
3260 static void KillGreeter( void )
3262 if (sia_greeter_pid)
3263 AbortClient(sia_greeter_pid);
3264 sia_greeter_pid = 0;