57e73948ed75de478a2615ee205af9acd6bb1c82
[oweals/cde.git] / cde / programs / dtlogin / session.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* (c) Copyright 1997 The Open Group */
24 /*                                                                      *
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.                                *
29  */
30 /*
31  * Xdm - display manager daemon
32  *
33  * $TOG: session.c /main/21 1998/11/02 14:32:42 mgreess $
34  *
35  * Copyright 1988 Massachusetts Institute of Technology
36  *
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.
46  *
47  * Author:  Keith Packard, MIT X Consortium
48  */
49
50 /*
51  * session.c
52  */
53
54 #ifdef _AIX
55 #ifdef _POWER
56 #include <stdio.h>
57 #include <sys/file.h>
58 #endif /* _POWER */
59 # include <usersec.h>
60 #endif /* _AIX */
61
62
63 # include "dm.h"
64 # include "vgmsg.h"
65 # include <signal.h>
66 # include <X11/Xatom.h>
67 # include <setjmp.h>
68 #if defined(__FreeBSD__)
69 # include <utmpx.h>
70 #else
71 # include <utmp.h>
72 #endif
73 #include <unistd.h>
74 #include <pwd.h>
75 #include <dirent.h>
76 #include <limits.h>
77
78 #ifdef SIA
79 #include <sia.h>
80 #include <siad.h>
81 #include <X11/Intrinsic.h>
82 #endif
83
84 # include <X11/Xresource.h>
85
86 # include "vgproto.h"
87 # include "sysauth.h"
88
89
90 #ifdef sun
91 # include "solaris.h"
92 #endif
93
94 #ifdef BLS
95 # include <sys/security.h>
96 # include <prot.h>
97 #endif
98
99 #ifdef __KERBEROS
100 # include <krb.h>
101 #endif /*  __KERBEROS  */
102
103 #ifdef __PASSWD_ETC
104 #include "rgy_base.h"
105 #endif
106
107 #ifdef SIA
108
109 static  SIAENTITY *siaHandle = NULL;
110 static Boolean        dt_in_sia_ses_authent = False;
111
112 static struct sia_greeter_info {
113     struct display *d;
114     struct greet_info *greet;
115     struct verify_info *verify;
116     struct greet_state *state;
117     int       status;
118     } siaGreeterInfo;
119
120 static int SiaManageGreeter(
121     int timeout,
122     int rendition,
123     unsigned char *title,
124     int num_prompts,
125     prompt_t *prompt);
126
127 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet);
128
129 static void KillGreeter( void );
130
131 static int sia_greeter_pid;
132 static int sia_exit_proc_reg = FALSE;
133
134 #endif /* SIA */
135
136
137 #ifdef __apollo
138   extern char *getenv();
139 #endif  
140
141 #define GREET_STATE_LOGIN             0
142 #define GREET_STATE_AUTHENTICATE      1
143 #define GREET_STATE_EXIT              2
144 #define GREET_STATE_EXPASSWORD        3
145 #define GREET_STATE_ERRORMESSAGE      4
146 #define GREET_STATE_LANG              5
147 #define GREET_STATE_BAD_HOSTNAME      6
148 #define GREET_STATE_ENTER             7
149 #define GREET_STATE_TERMINATEGREET    8
150 #define GREET_STATE_USERNAME          9
151 #define GREET_STATE_CHALLENGE        10
152 #define GREET_STATE_FORM             11
153
154 #ifndef DEF_SESSION
155 #define DEF_SESSION CDE_INSTALLATION_TOP "/bin/Xsession"
156 #endif
157
158 #define DOT             "."
159 #define DOTDOT          ".."
160
161 struct greet_state {
162   int id;               /* state */
163   int waitForResponse;  /* TRUE=wait for response from dtgreet */
164   RequestHeader *request;      /* request buffer */
165   ResponseHeader *response;    /* response buffer */
166   int authenticated;    /* TRUE=user is authenticated */
167   int vf;               /* last return code from Authenticate() */
168   int loginReset;       /* reset flag for LOGIN state */
169   char *msg;            /* message for VF_MESSAGE */
170 };
171
172 char *globalDisplayName;
173
174 /***************************************************************************
175  *
176  *  Local procedure declarations
177  *
178  ***************************************************************************/
179
180 static int  AbortClient( int pid) ;
181 static void DeleteXloginResources( struct display *d, Display *dpy) ;
182        int  LoadXloginResources( struct display *d) ;
183 static int  ErrorHandler( Display *dpy, XErrorEvent *event) ;
184 static int  IOErrorHandler( Display *dpy) ;
185 static int  ManageGreeter( struct display *d, struct greet_info *greet,
186                         struct verify_info *verify, struct greet_state *state) ;
187 static void RunGreeter( struct display *d, struct greet_info *greet,
188                         struct verify_info *verify) ;
189 static void SessionExit( struct display *d, int status) ;
190 static void SessionPingFailed( struct display *d) ;
191 static int  StartClient(struct verify_info *verify, struct display *d,
192                         int *pidp) ;
193 static SIGVAL catchAlrm( int arg ) ;
194 static SIGVAL catchHUP( int arg ) ;
195 static SIGVAL catchTerm( int arg ) ;
196 static SIGVAL waitAbort( int arg ) ;
197 static void SetupDisplay(struct display *d);
198
199 static void TellGreeter(RequestHeader *phdr);
200 static int AskGreeter(RequestHeader *preqhdr, char *b, int blen);
201 #if defined (DEBUG)
202 static void PrintResponse(ResponseHeader *phdr, int count);
203 #endif /* DEBUG */
204
205 #if defined (_AIX) && defined (_POWER)
206 static void release_aix_lic(void);
207 #endif
208
209 #if defined (_AIX) && !defined (_POWER)
210 static int session_execve(char *path, char *argv[], char *envp[]);
211 #else
212 #define session_execve(A,B,C) execve(A,B,C)
213 #endif 
214
215 #  ifdef __KERBEROS
216       static void SetTicketFileName(uid_t uid);
217 #  endif /* __KERBEROS */
218
219 static void LoadAltDtsResources( struct display *d);
220 char * _ExpandLang(char *string, char *lang);
221
222
223
224 /***************************************************************************
225  *
226  *  Global variables
227  *
228  ***************************************************************************/
229
230 static int                      clientPid;
231 static struct greet_info        greet;
232 static struct verify_info       verify;
233 static char                     *defaultLanguage = NULL;
234
235 static jmp_buf  abortSession;
236
237 #ifdef BLS
238   static char *sensitivityLevel;
239 #endif
240
241 #ifdef __KERBEROS
242   static char krb_ticket_string[MAXPATHLEN];
243 #endif /* __KERBEROS */
244
245
246 XrmDatabase XresourceDB;
247 XrmDatabase XDB;
248
249
250 static SIGVAL
251 catchTerm( int arg )
252 {
253     longjmp (abortSession, 1);
254 }
255
256 static jmp_buf  pingTime;
257
258 static SIGVAL
259 catchAlrm( int arg )
260 {
261     longjmp (pingTime, 1);
262 }
263
264 static int
265 FileNameCompare (a, b)
266 #if defined(__STDC__)
267         const void *a, *b;
268 #else
269         char *a, *b;
270 #endif
271 {
272     return strcoll (*(char **)a, *(char **)b);
273 }
274
275 static void
276 SessionPingFailed( struct display *d )
277 {
278     if (clientPid > 1)
279     {
280         AbortClient (clientPid);
281         source (&verify, d->reset);
282
283 #if defined (PAM) || defined(SUNAUTH) 
284         {
285             char* user = getEnv (verify.userEnviron, "USER");
286             char* ttyLine = d->gettyLine;
287             
288 #ifdef DEF_NETWORK_DEV
289             /* 
290              * If location is not local (remote XDMCP dtlogin) and 
291              * remote accouting is enabled (networkDev start with /dev/...)
292              * Set tty line name to match network device for accouting.  
293              * Unless the resource was specifically set, default is value 
294              * of DEF_NETWORK_DEV define (/dev/dtremote) 
295              */
296                
297             if ( d->displayType.location != Local && 
298                  networkDev && !strncmp(networkDev,"/dev/",5)) {
299                 ttyLine = networkDev+5;
300             }
301 #endif 
302
303 #   ifdef PAM 
304             PamAccounting( verify.argv[0], d->name, d->utmpId, user, 
305                            ttyLine, clientPid, ACCOUNTING, NULL);
306 #   else
307             solaris_accounting( verify.argv[0], d->name, d->utmpId, user, 
308                                 ttyLine, clientPid, ACCOUNTING, NULL);
309 #   endif
310
311 #   ifdef sun
312             solaris_resetdevperm(ttyLine);
313 #   endif
314         }
315 #endif
316
317     }
318     SessionExit (d, RESERVER_DISPLAY);
319 }
320
321
322 /*
323  * We need our own error handlers because we can't be sure what exit code Xlib
324  * will use, and our Xlib does exit(1) which matches REMANAGE_DISPLAY, which
325  * can cause a race condition leaving the display wedged.  We need to use
326  * RESERVER_DISPLAY for IO errors, to ensure that the manager waits for the
327  * server to terminate.  For other X errors, we should give up.
328  */
329
330 static int 
331 IOErrorHandler( Display *dpy )
332 {
333
334     char *s = ((errno >= 0 && errno < sys_nerr) ? sys_errlist[errno]
335                                                 : "unknown error");
336
337     LogError(ReadCatalog(
338                        MC_LOG_SET,MC_LOG_FATAL_IO,MC_DEF_LOG_FATAL_IO),
339         errno,s);
340     exit(RESERVER_DISPLAY);
341     return 0;
342 }
343
344 static int 
345 ErrorHandler( Display *dpy, XErrorEvent *event )
346 {
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);
350 }
351
352     Display             *dpy;
353
354 void
355 ManageSession( struct display *d )
356 {
357     int                 pid;
358     Window              root;
359    /* Display           *dpy; */
360 #ifdef BYPASSLOGIN
361     char        *BypassUsername;
362     char        *BypassLogin();
363 #endif /* BYPASSLOGIN */
364         
365
366     Debug ("ManageSession():\n");
367
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);
374         } else {
375             defaultLanguage = "C";
376         }
377     }
378
379 #ifdef BYPASSLOGIN
380     d->bypassLogin = 0;
381     if ((BypassUsername = BypassLogin(d->name)) != NULL) {
382         d->bypassLogin = 1;
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);
388         }
389         Debug("Login bypass verify succeded!\n");
390     } else
391 #endif /* BYPASSLOGIN */
392
393     {
394         int i;
395
396         (void)XSetIOErrorHandler(IOErrorHandler);
397         (void)XSetErrorHandler(ErrorHandler);
398         SetTitle(d->name, (char *) 0);
399
400         /*
401          * set root background to black...
402          */
403
404         dpy = XOpenDisplay(d->name);
405         for (i = ScreenCount(dpy) - 1; i >= 0; i--)
406         {
407             Window      tmproot = RootWindow(dpy, i);
408
409             if (i == DefaultScreen(dpy))
410               root = tmproot;
411             
412             XSetWindowBackground(dpy, tmproot, BlackPixel(dpy, i));
413             XClearWindow(dpy, tmproot);
414         }
415         XFlush(dpy);
416
417         /*
418         ** Step 5:  
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
423         ** Dtlogin process.
424         */
425      
426
427         greet.name = greet.string = NULL;
428
429         while (greet.name == NULL) {
430             SetHourGlassCursor(dpy, root);
431             LoadXloginResources (d);
432             SetupDisplay(d);
433             ApplyFontPathMods(d, dpy);
434             (void)XSetErrorHandler(ErrorHandler);
435             RunGreeter(d, &greet, &verify);
436
437             DeleteXloginResources (d, dpy);
438         }
439         XSetInputFocus(dpy, root, RevertToNone, CurrentTime);
440         XCloseDisplay(dpy);
441     }
442
443 #ifdef __KERBEROS
444     /*
445      *  Generate Kerberos ticket file name. Put in system and user
446      *  environments...
447      */
448
449     if ( IsVerifyName(VN_KRB)) {
450         SetTicketFileName(verify.uid);
451         krb_set_tkt_string(krb_ticket_string);
452         verify.systemEnviron = setEnv (verify.systemEnviron, 
453                                    "KRBTKFILE",
454                                    krb_ticket_string);
455
456         verify.userEnviron   = setEnv (verify.userEnviron, 
457                                    "KRBTKFILE",
458                                    krb_ticket_string);
459     }
460 #endif /* __KERBEROS */
461
462    /* set LOCATION env var */
463     if(d->displayType.location == Local)  {
464         verify.systemEnviron = setEnv (verify.systemEnviron,
465                                    LOCATION,
466                                    "local");
467         /* ITE is needed only for Local displays */
468         /* set ITE env var */
469         if(d->gettyLine)
470            verify.systemEnviron = setEnv (verify.systemEnviron,
471                                   "ITE",
472                                   d->gettyLine);
473     }
474     else
475         verify.systemEnviron = setEnv (verify.systemEnviron,
476                                    LOCATION,
477                                    "remote");
478
479     {
480         struct passwd *pwd;
481         char   gid[25];
482         sprintf(gid,"%ld",(long)getgid());
483         /* set user group id (USER_GID) env var */
484         verify.systemEnviron = setEnv (verify.systemEnviron,
485                                    "USER_GID",
486                                    gid);
487
488         /* set root group id (ROOT_GID) env var */
489         pwd = getpwnam("root");
490         if(pwd)  {
491            sprintf(gid,"%ld",(long)pwd->pw_gid);
492            verify.systemEnviron = setEnv (verify.systemEnviron,
493                                       "ROOT_GID",
494                                       gid);
495         }
496     }
497
498     /*
499      * Run system-wide initialization file
500      */
501     if (source (&verify, d->startup) != 0)
502     {
503         Debug ("Startup program %s exited with non-zero status\n",
504                 d->startup);
505         SessionExit (d, OBEYSESS_DISPLAY);
506     }
507
508 #ifdef sun
509     if ( solaris_setdevperm(d->gettyLine, verify.uid, verify.gid) == 0 ) {
510         SessionExit (d, OBEYSESS_DISPLAY);
511     }
512 #endif
513
514     clientPid = 0;
515     if (!setjmp (abortSession)) {
516         signal (SIGTERM, catchTerm);
517         /*
518          * Start the clients, changing uid/groups
519          *         setting up environment and running the session
520          */
521         if (StartClient (&verify, d, &clientPid)) {
522             Debug ("Client started\n");
523
524             /*
525              * We've changed dtlogin to pass HUP's down to the children
526              * so ignore any HUP's once the client has started.
527              */
528             signal(SIGHUP, SIG_IGN);
529
530             /*
531              * Wait for session to end,
532              */
533             for (;;) {
534                 if (d->pingInterval)
535                 {
536                     if (!setjmp (pingTime))
537                     {
538                         signal (SIGALRM, catchAlrm);
539                         alarm (d->pingInterval * 60);
540                         pid = wait ((waitType *) 0);
541                         alarm (0);
542                     }
543                     else
544                     {
545                         alarm (0);
546                         if (!PingServer (d, (Display *) NULL))
547                             SessionPingFailed (d);
548                     }
549                 }
550                 else
551                 {
552                     pid = wait ((waitType *) 0);
553                 }
554                 if (pid == clientPid)
555                     break;
556             }
557
558             /*
559              * We've changed dtlogin to pass HUP's down to the children
560              * so ignore any HUP's once the client has started.
561              */
562             signal(SIGHUP, SIG_DFL);
563         } else {
564             LogError(ReadCatalog(
565                 MC_LOG_SET,MC_LOG_FAIL_START,MC_DEF_LOG_FAIL_START));
566         }
567     } else {
568         /*
569          * when terminating the session, nuke
570          * the child and then run the reset script
571          */
572         AbortClient (clientPid);
573     }
574
575     /*
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.
580      */
581
582     if (d->displayType.location == Foreign   &&
583         d->displayType.origin   != FromXDMCP    )
584         AbortClient(clientPid);
585
586
587 #ifdef __KERBEROS
588     /*
589      * remove ticket file...
590      */
591
592     if ( IsVerifyName(VN_KRB) ) {
593         dest_tkt();
594     }
595
596 #endif /* __KERBEROS */
597
598         
599     /*
600      * run system-wide reset file
601      */
602     Debug ("Source reset program %s\n", d->reset);
603     source (&verify, d->reset);
604
605 #if defined(PAM) || defined(SUNAUTH)
606     {
607         char* user = getEnv (verify.userEnviron, "USER");
608         char* ttyLine = d->gettyLine;
609             
610 #   ifdef DEF_NETWORK_DEV
611             /* 
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) 
617              */
618                
619             if ( d->displayType.location != Local && 
620                  networkDev && !strncmp(networkDev,"/dev/",5)) {
621                 ttyLine = networkDev+5;
622             }
623 #   endif 
624
625 #   ifdef PAM
626         PamAccounting( verify.argv[0], d->name, d->utmpId, user, 
627                        ttyLine, clientPid, ACCOUNTING, NULL);
628 #   else
629         solaris_accounting( verify.argv[0], d->name, d->utmpId, user, 
630                             ttyLine, clientPid, ACCOUNTING, NULL);
631 #   endif
632
633 #   ifdef sun
634         solaris_resetdevperm(ttyLine);
635 #   endif
636     }
637 #endif
638
639     SessionExit (d, OBEYSESS_DISPLAY);
640 }
641
642
643 int
644 LoadXloginResources( struct display *d )
645 {
646     char        cmd[1024];
647     char        *language="";
648     char        *lang_key="";
649     char        *authority="";
650     char        *auth_key="";
651     char        *resources = NULL;
652     char        *p;
653     char        tmpname[32];
654
655     if (d->resources && d->resources[0]) { 
656         resources = _ExpandLang(d->resources, d->language);
657         if (access (resources, R_OK) != 0) {
658             /** fallback to the C locale for resources **/
659             Debug("LoadXloginResources - cant access %s\n", resources);
660             Debug("\t %s.  Falling back to C.\n", sys_errlist[errno]);
661             free(resources);
662             resources = _ExpandLang(d->resources, "C");
663             if (access (resources, R_OK) != 0) {
664                 /** can't find a resource file, so bail **/
665                 Debug("LoadXloginResources - cant access %s.\n", resources);
666                 Debug("\t %s.  Unable to find resource file.\n",
667                       sys_errlist[errno]);
668                 free(resources);
669                 return(-1);
670             }
671         }
672
673         if (d->authFile && strlen(d->authFile) > 0 ) {
674                 authority = d->authFile;
675                 auth_key = "XAUTHORITY=";
676         }
677
678         if (d->language && strlen(d->language) > 0 ) {
679                 language = strdup(d->language);
680                 lang_key = "-D";
681         }
682
683         /*
684          *  replace any "-" or "." in the language name with "_". The C
685          *  preprocessor used by xrdb does not accept "-" or "." in a name.
686          */
687          
688         while ( (p = strchr(language, '-')) != NULL ) {
689             *p = '_';
690         }
691          
692         while ( (p = strchr(language, '.')) != NULL ) {
693             *p = '_';
694         }
695                     
696         if ( strlen(language) > 0 )
697             free(language);
698
699
700         Debug("LoadXloginResources - loading resource db from %s\n", resources);
701         if((XresourceDB = XrmGetFileDatabase(resources)) == NULL)
702           Debug("LoadXloginResources - Loading resource db from %s failed\n",
703                 resources);
704
705         LoadAltDtsResources(d); 
706
707         strcpy(tmpname,"/var/dt/dtlogin_XXXXXX");
708         (void) mktemp(tmpname);
709
710         XrmPutFileDatabase(XresourceDB, tmpname);
711
712         sprintf (cmd, "%s%s %s -display %s -load %s",
713                         auth_key, authority, d->xrdb, d->name, tmpname);
714         Debug ("Loading resource file: %s\n", cmd);
715
716         system (cmd);  
717
718         if (debugLevel <= 10)
719           if (unlink (tmpname) == -1)
720             Debug ("unlink() on %s failed\n", tmpname);
721     }
722
723     if (resources) free (resources);
724
725     return (0);
726 }
727
728 /***************************************************************************
729  *
730  *  LoadAltDtsResources 
731  *
732  *
733  *  set up alternate desktop resources..
734  *
735  ***************************************************************************/
736  
737 static void
738 LoadAltDtsResources(struct display *d)
739 {
740     DIR         *dirp;
741     struct dirent *dp;
742     char        dirname[2][MAXPATHLEN];
743     char        res_file[MAXPATHLEN];
744     char        *rmtype;        /* for XrmGetResource()                    */
745     XrmValue    rmvalue;        /* for XrmGetResource()                    */
746     char        buf[MAXPATHLEN];
747     char        tempbuf[MAXPATHLEN];
748     XrmDatabase defDb;
749     XrmDatabase userDb;
750     char        altdtres[MAXPATHLEN];
751     char        Altdtres[MAXPATHLEN];
752     int         i = 0;
753     int         j = 0;
754     char        *resources = NULL;
755     int         file_count = 0;
756     int         num_allocated = 0;
757     char        **file_list = NULL;
758     int         list_incr = 10;
759
760     if ( XrmGetResource(XresourceDB,
761                    "Dtlogin*altDts",  "Dtlogin*AltDts",
762                    &rmtype, &rmvalue ) ) {
763                 strcpy(tempbuf,rmvalue.addr);
764                 i = atoi(tempbuf);
765     }
766
767     strcpy(dirname[0],CDE_INSTALLATION_TOP "/config/%L/Xresources.d/");
768     strcpy(dirname[1],CDE_CONFIGURATION_TOP "/config/%L/Xresources.d/");
769
770     for(j = 0; j < 2 ; ++j)
771     {
772         resources = _ExpandLang(dirname[j], d->language);
773         if (access (resources, R_OK) != 0)
774         {
775             Debug("LoadAltDtsResources- cant access %s.\n", resources);
776             Debug("\t %s.  Falling back to C.\n", sys_errlist[errno]);
777
778             if (resources)
779             {
780                 free (resources);
781                 resources = NULL;
782             }
783
784             resources = _ExpandLang(dirname[j], "C");
785             if (access (resources, R_OK) != 0)
786             {
787                 Debug("LoadAltDtsResources- cant access %s.\n", resources);
788                 Debug("\t %s.\n", sys_errlist[errno]);
789             }
790             else
791               strcpy(dirname[j], resources);
792         }
793         else {
794             strcpy(dirname[j],resources);
795             Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
796         }
797
798         if (resources)
799         {
800             free (resources);
801             resources = NULL;
802         }
803     }
804
805
806     /*
807      * Create a list of the alt DT files
808      *
809      * NOTE - an assumption made here is that files in /etc/dt
810      * should take precedence over files in /usr/dt.  This precedence
811      * is maintained during the sort becase /etc/dt will come before
812      * /usr/dt
813      */
814
815     for(j = 0; j < 2 ; ++j) {
816
817         if((dirp = opendir(dirname[j])) != NULL) {
818
819             while((dp = readdir(dirp)) != NULL) {
820
821                 if ((strcmp(dp->d_name, DOT)    != 0) &&
822                     (strcmp(dp->d_name, DOTDOT) != 0)) {
823
824                     sprintf (res_file, "%s%s", dirname[j],dp->d_name);
825                     if ((access (res_file, R_OK)) != 0)
826                     {
827                         Debug("LoadAltDtsResources- cant access %s.\n",
828                               resources);
829                         Debug("\t %s.\n", sys_errlist[errno]);
830                         continue;
831                     }
832
833                     if (file_count == 0) {
834                         file_list = malloc (list_incr * sizeof(char **));
835                         num_allocated += list_incr;
836                     }
837                     if (file_count + 1 > num_allocated) {
838                         num_allocated += list_incr;
839                         file_list = realloc (file_list,
840                                              num_allocated * sizeof(char **));
841                     }
842                     file_list[file_count] = strdup (res_file);
843                     file_count++;
844                 }
845             }
846             closedir(dirp);
847         }
848     }
849
850     if (file_count > 0)
851         qsort (file_list, file_count, sizeof (char *), FileNameCompare);
852
853     for (j = 0; j < file_count ; j++) {
854
855         userDb = XrmGetFileDatabase(file_list[j]);
856         XrmMergeDatabases(userDb,&XresourceDB);
857  
858         if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
859                         "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
860
861             /* 
862              * remove the trailing spaces 
863              */
864             if(strchr(rmvalue.addr,' '))
865                 strcpy(tempbuf, strtok(rmvalue.addr," "));
866             else
867                 strcpy(tempbuf, rmvalue.addr);
868
869             if ((strcmp(tempbuf, "True") == 0) || 
870                 (strcmp(tempbuf, "TRUE") == 0))  {
871  
872                 if ( XrmGetResource(XresourceDB,
873                                 "Dtlogin*altDtKey",  "Dtlogin*AltDtKey",
874                                 &rmtype, &rmvalue ) ) {
875                      ++i;
876                      sprintf(altdtres,"Dtlogin*altDtKey%d",i);
877                      XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
878                  }
879                  else
880                     continue;
881  
882                  if ( XrmGetResource(XresourceDB,
883                                 "Dtlogin*altDtName",  "Dtlogin*AltDtName",
884                                 &rmtype, &rmvalue ) ) {
885                      sprintf(altdtres,"Dtlogin*altDtName%d",i);
886                      XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
887                  }
888                  if ( XrmGetResource(XresourceDB,
889                                 "Dtlogin*altDtStart",  "Dtlogin*AltDtStart",
890                                 &rmtype, &rmvalue ) ) {
891                      sprintf(altdtres,"Dtlogin*altDtStart%d",i);
892                      XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
893                  }
894                  if ( XrmGetResource(XresourceDB,
895                                 "Dtlogin*altDtLogo",  "Dtlogin*AltDtLogo",
896                                 &rmtype, &rmvalue ) ) {
897                      sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
898                      XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
899                  }
900             }
901         }
902     }
903
904     sprintf(tempbuf,"%d",i);
905     XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf); 
906
907     if (file_count > 0) {
908         for (i = 0; i < file_count; i++) {
909             Debug ("Loading resource file: %s\n", file_list[i]);
910             free (file_list[i]);
911         }
912         free (file_list);
913     }
914 }
915
916
917 /******************
918  *
919  * Function Name:  _ExpandLang
920  *
921  * Description:
922  *
923  *      This function takes the string "string", searches for occurences of
924  *      "%L" in the string and if found, the "%L" is substituted with
925  *      the value of the $LANG environment variable.
926  *
927  *      If $LANG is not defined, the %L is replace with NULL.
928  *
929  * Note: 
930  *
931  *      _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
932  *
933  * Synopsis:
934  *
935  *      ret_string = _ExpandLang (string);
936  *
937  *      char *ret_string;       Returns NULL if "string" is NULL or it points
938  *                              to the expanded string.
939  *
940  *      char *string;           The first part of the pathname.  Typically
941  *                              the directory containing the item of interest.
942  *
943  * Note: The caller is responsible for free'ing the returned string.
944  *
945  ******************/
946
947
948 char *
949 _ExpandLang(
950         char *string,
951         char *lang )
952 {
953    char         *tmp;
954    char         *pch;
955    char         *trail;
956    int          n = 0;
957    int          lang_len = 0;
958    int          tmp_len;
959    int          i = 0;
960
961    if (string == NULL)
962       return (NULL);
963
964    /*
965     * Count the number of expansions that will occur.
966     */
967
968
969    for (n = 0, pch = string ; pch != NULL ; ) {
970       if ((pch = strchr (pch, '%')) != NULL) {
971          n++;
972          pch++;
973       }
974    }
975
976    if (n == 0)
977       return (strdup(string));
978
979 /*
980  * We should really be calling setlocale to determine the "default"
981  * locale but setlocale's return value is not standardized across
982  * the various vendor platforms nor is it consistent within differnt
983  * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
984  * HP-UX 10.0).   The "right" call would be the following line:
985  *
986  *  if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
987  *
988  * Here we hard code the default to "C" instead of leaving it NULL.
989  */
990    if (lang || (lang = getenv ("LANG")) || (lang = "C"))
991       lang_len = strlen (lang);
992
993    /*
994     * Create the space needed.
995     */
996    tmp_len = strlen (string) + (n * lang_len) + n + 1;
997    tmp = (char *) malloc (tmp_len);
998    for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
999
1000    pch = string;
1001
1002    while (pch != NULL) {
1003       trail = pch;
1004
1005       if ((pch = strchr (pch, '%')) != NULL) {
1006
1007          pch++;
1008
1009          if (pch == NULL) {
1010             (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
1011          }
1012          else if ((pch != NULL) && *pch == 'L') {
1013             if (lang_len == 0) {
1014                if (((pch - trail) >=2) && (*(pch-2) == '/'))
1015                   /*
1016                    * Remove the "/" as well as the "%L".
1017                    */
1018                   (void) strncat (tmp, trail, (pch - trail) - 2);
1019                else
1020                   (void) strncat (tmp, trail, (pch - trail) - 1);
1021             }
1022             else {
1023                /*
1024                 * Remove the "%L" and then append the LANG.
1025                 */
1026                (void) strncat (tmp, trail, (pch - trail) - 1);
1027                (void) strcat (tmp, lang);
1028             }
1029          }
1030          else {
1031             (void) strncat (tmp, trail, (pch - trail) + 1);
1032          }
1033          if (pch != NULL)
1034             pch++;
1035       }
1036       else {
1037          /*
1038           * A '%' was not found.
1039           */
1040          (void) strcat (tmp, trail);
1041       }
1042    }
1043
1044    return (tmp);
1045 }
1046
1047
1048 static void
1049 SetupDisplay (struct display *d)
1050 {
1051     char **env = 0, **crt_systemEnviron;
1052
1053     if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1054     {
1055         crt_systemEnviron = verify.systemEnviron;
1056         env = systemEnv (d, (char *) 0, (char *) 0);
1057         if (d->authFile && strlen(d->authFile) > 0 )
1058             env = setEnv( env, "XAUTHORITY", d->authFile );
1059         if(d->displayType.location == Local)  
1060             env = setEnv (env, LOCATION, "local");
1061         else
1062             env = setEnv (env, LOCATION, "remote");
1063         verify.systemEnviron = env;
1064         source (&verify, d->setup);
1065         verify.systemEnviron = crt_systemEnviron;
1066         freeEnv (env);
1067     }
1068 }
1069
1070 /*ARGSUSED*/
1071 static void 
1072 DeleteXloginResources( struct display *d, Display *dpy )
1073 {
1074     XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1075 }
1076
1077 #if  0                    /* dead code: transferred to Dtgreet */
1078
1079 static jmp_buf syncJump;
1080
1081 static SIGVAL
1082 syncTimeout ()
1083 {
1084     longjmp (syncJump, 1);
1085 }
1086
1087
1088 SecureDisplay (d, dpy)
1089 struct display  *d;
1090 Display         *dpy;
1091 {
1092     Debug ("SecureDisplay():\n");
1093     signal (SIGALRM, syncTimeout);
1094     if (setjmp (syncJump)) {
1095         LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1096                    d->name);
1097         SessionExit (d, RESERVER_DISPLAY);
1098     }
1099     alarm ((unsigned) d->grabTimeout);
1100     Debug ("Before XGrabServer()\n");
1101     XGrabServer (dpy);
1102     if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1103                        GrabModeAsync, CurrentTime) != GrabSuccess)
1104     {
1105         alarm (0);
1106         signal (SIGALRM, SIG_DFL);
1107         LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1108                   d->name);
1109         SessionExit (d, RESERVER_DISPLAY);
1110     }
1111     Debug ("XGrabKeyboard() succeeded\n");
1112     alarm (0);
1113     signal (SIGALRM, SIG_DFL);
1114     pseudoReset (dpy);
1115     if (!d->grabServer)
1116     {
1117         XUngrabServer (dpy);
1118         XSync (dpy, 0);
1119     }
1120     Debug ("Done secure %s\n", d->name);
1121 }
1122
1123 UnsecureDisplay (d, dpy)
1124 struct display  *d;
1125 Display         *dpy;
1126 {
1127     Debug ("Unsecure display %s\n", d->name);
1128     if (d->grabServer)
1129         XUngrabServer (dpy);
1130     XSync (dpy, 0);
1131 }
1132 #endif
1133
1134 #ifdef _AIX
1135 #ifdef _POWER
1136
1137 static void
1138 release_aix_lic(void)
1139 {
1140  /*
1141   * Release AIX iFOR/LS license (if any)
1142   */
1143   int fd;
1144   struct pipeinfo {
1145     int request_type;
1146     pid_t login_pid;
1147   } release_me;
1148   
1149   release_me.request_type = -1;
1150   release_me.login_pid = getpid();
1151   if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1152   {
1153     write(fd, &release_me, sizeof(release_me));
1154     close(fd);
1155   }
1156   Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1157 }
1158
1159 #endif /* _POWER */
1160 #endif /* _AIX */
1161
1162
1163 static void
1164 SessionExit( struct display *d, int status )
1165 {
1166
1167 #ifdef _AIX
1168 #ifdef _POWER
1169     release_aix_lic();
1170 #endif /* _POWER */
1171 #endif /* _AIX */
1172
1173     /* make sure the server gets reset after the session is over */
1174     if (d->serverPid >= 2) {
1175         Debug("Reseting server:  pid %d signal %d\n",
1176               d->serverPid, d->resetSignal);
1177
1178         if (d->terminateServer == 0 && d->resetSignal)
1179             kill (d->serverPid, d->resetSignal);
1180     }
1181     else
1182         ResetServer (d);
1183
1184     Debug("Exiting Session with status:  %d\n", status);
1185     exit (status);
1186 }
1187
1188 static int 
1189 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1190 {
1191     char        **f, *home;
1192     char        currentdir[PATH_MAX+1];
1193     char        *failsafeArgv[20];
1194     char        *user;                  /* users name                      */
1195     char        *lang, *font;           /* failsafe LANG and font          */
1196
1197     int pid;
1198     int         failsafe = FALSE;       /* do we run the failsafe session? */
1199     int         password = FALSE;       /* do we run /bin/passwd?          */
1200     int         i;
1201     FILE        *lastsession;
1202     char        lastsessfile[MAXPATHLEN];
1203
1204 #ifdef BLS
1205    struct pr_passwd     *b1_pwd;
1206 #endif
1207
1208 #ifdef __AFS
1209 #define NOPAG 0xffffffff
1210     long        pagval, j;
1211     long        ngroups, groups[NGROUPS];
1212 #endif /* __AFS */
1213
1214     waitType  status;
1215
1216     if (verify->argv) {
1217         Debug ("StartSession %s: ", verify->argv[0]);
1218         for (f = verify->argv; *f; f++) {
1219                 Debug ("%s ", *f);
1220                 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1221                 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1222         }
1223         Debug ("; ");
1224     }
1225     if (verify->userEnviron) {
1226         for (f = verify->userEnviron; *f; f++)
1227                 Debug ("%s ", *f);
1228         Debug ("\n");
1229     }
1230
1231     user = getEnv (verify->userEnviron, "USER");
1232     
1233     switch (pid = fork ()) {
1234     case 0:
1235 #ifdef SIA
1236         /* Force a failsafe session if we can't touch the home directory 
1237          * SIA has already attempted to chdir to HOME, and the current dir 
1238          * will be set to / if it failed. We just check to see if the HOME
1239          * path is our current directory or not.
1240          */
1241         home = getEnv (verify->userEnviron, "HOME");
1242         getcwd(currentdir, PATH_MAX+1);
1243         Debug("Current directory is: %s\n", currentdir);
1244 #if 0
1245         /*
1246          * CDExc17917
1247          * The following little check doesn't really work.  For example,
1248          * here at the XC, NIS reports my home directory as
1249          * "/site/guests/montyb" while getcwd comes up with
1250          * "/net/nexus/site/guests/montyb".
1251          */
1252         if (strcmp(home, currentdir)) {
1253             Debug("Can't access home directory, setting failsafe to TRUE\n");
1254             failsafe = TRUE;
1255             LogError (ReadCatalog(
1256                       MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1257                       home, getEnv (verify->userEnviron, "USER"));
1258             verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1259         }
1260 #endif
1261 #endif /* SIA */
1262
1263         CleanUpChild ();
1264
1265         /*
1266          *  do process accounting...
1267          */
1268 #if defined(PAM) || defined(SUNAUTH)
1269         {
1270             char* ttyLine = d->gettyLine;
1271             
1272 #   ifdef DEF_NETWORK_DEV
1273             /* 
1274              * If location is not local (remote XDMCP dtlogin) and 
1275              * remote accouting is enabled (networkDev start with /dev/...)
1276              * Set tty line name to match network device for accouting.  
1277              * Unless the resource was specifically set, default is value 
1278              * of DEF_NETWORK_DEV define (/dev/dtremote) 
1279              */
1280                
1281             if ( d->displayType.location != Local && 
1282                  networkDev && !strncmp(networkDev,"/dev/",5)) {
1283                 ttyLine = networkDev+5;
1284             }
1285 #   endif 
1286
1287 #   ifdef PAM
1288             PamAccounting(verify->argv[0], d->name, d->utmpId, user, 
1289                           ttyLine, getpid(), USER_PROCESS, NULL);
1290 #   else
1291             solaris_accounting(verify->argv[0], d->name, d->utmpId, user, 
1292                                ttyLine, getpid(), USER_PROCESS, NULL);
1293 #   endif
1294         }
1295 #endif
1296
1297 #if !defined(sun) && !defined(CSRG_BASED)
1298         Account(d, user, NULL, getpid(), USER_PROCESS, status);
1299 #endif
1300
1301 #ifdef AIXV3
1302          /*
1303           * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1304           * setpenv() to set up the user's process environment and return
1305           * without execing. This allows us to set up the process environment
1306           * and proceed to the execute() call as do the other platforms. 
1307           *
1308           * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1309           * we have to pospone the setpenv() to the actual execute().
1310           */
1311
1312          /*
1313           * These defines are the tag locations in userEnviron.
1314           * IMPORTANT: changes to the locations of these tags in verify.c
1315           * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1316           */
1317           #define SYS_ENV_TAG 0
1318           #define USR_ENV_TAG 3
1319
1320         /*
1321          * Set the user's credentials: uid, gid, groups,
1322          * audit classes, user limits, and umask.
1323          * RK 09.13.93
1324          */
1325         if (setpcred(user, NULL) == -1)
1326         {
1327             Debug("Can't set User's Credentials (user=%s)\n",user);
1328             return (0);
1329         }
1330 #ifdef _POWER
1331         {
1332           char *usrTag, *sysTag;
1333           extern char **newenv;
1334
1335          /*
1336           * Save pointers to tags. The setpenv() function clears the pointers
1337           * to the tags in userEnviron as a side-effect.
1338           */
1339           sysTag = verify->userEnviron[SYS_ENV_TAG];
1340           usrTag = verify->userEnviron[USR_ENV_TAG];
1341
1342          /*
1343           * Set the users process environment. Store protected variables and
1344           * obtain updated user environment list. This call will initialize
1345           * global 'newenv'.
1346           */
1347           #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1348           if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1349           {
1350               Debug("Can't set process environment (user=%s)\n",user);
1351               return(0);
1352           }
1353
1354          /*
1355           * Restore pointers to tags.
1356           */
1357           verify->userEnviron[SYS_ENV_TAG] = sysTag;
1358           verify->userEnviron[USR_ENV_TAG] = usrTag;
1359
1360          /*
1361           * Free old userEnviron and replace with newenv from setpenv().
1362           */
1363           freeEnv(verify->userEnviron);
1364           verify->userEnviron = newenv;
1365         }
1366 #endif /* _POWER */
1367         
1368
1369 #endif /* AIXV3 */
1370
1371
1372
1373 #if defined(PAM)
1374         if (PamSetCred( verify->argv[0], 
1375                              user, verify->uid, verify->gid) > 0 ) {
1376             Debug("Can't set User's Credentials (user=%s)\n",user);
1377             return(0);
1378         } 
1379 #endif
1380
1381 #ifdef SUNAUTH 
1382         if ( solaris_setcred(verify->argv[0], 
1383                              user, verify->uid, verify->gid) > 0 ) {
1384             Debug("Can't set User's Credentials (user=%s)\n",user);
1385             return(0);
1386         }
1387 #endif /* SUNAUTH */
1388
1389
1390 #ifndef sun
1391
1392 #ifdef BLS
1393     /*
1394      *  HP BLS B1 session setup...
1395      *
1396      *   1. look up user's protected account information.
1397      *   2. set the session sensitivity/clearance levels 
1398      *   3. set the logical UID (LUID)
1399      */
1400
1401     if ( ISSECURE ) {
1402         Debug("BLS - Setting user's clearance, security level and luid.\n");
1403         set_auth_parameters(1, verify->argv);
1404         init_security();
1405
1406         verify->user_name = user;
1407         strncpy(verify->terminal,d->name,15);
1408         verify->terminal[15]='\0';
1409         verify->pwd = getpwnam(user);
1410
1411         if ( verify->pwd == NULL || strlen(user) == 0 ) {
1412             LogError(ReadCatalog(
1413                 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1414             exit (1);
1415         }
1416         verify->prpwd= b1_pwd = getprpwnam(user);
1417         verify->uid = b1_pwd->ufld.fd_uid;
1418     
1419         if ( b1_pwd == NULL || strlen(user) == 0 ) {
1420             LogError(ReadCatalog(
1421                 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1422             exit (1);
1423         }
1424
1425         /*
1426          * This has already been done successfully by dtgreet
1427          * but we need to get all the information again for the
1428          * dtlogin process.
1429          */
1430         if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1431             Debug("BLS - Could not verify sensitivity level.\n");
1432             LogError(ReadCatalog(
1433                 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1434             exit (1);
1435         }
1436
1437         if ( change_to_user(verify) != 1 ) {
1438             Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1439             LogError(ReadCatalog(
1440                 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1441                 verify->user_name);
1442             exit (1);
1443         }
1444
1445         Debug("BLS - Session setup complete.\n");
1446     } else {
1447 #endif /* BLS */
1448                         
1449 #ifdef __apollo
1450
1451         /* 
1452          * This should never fail since everything has been verified already.
1453          * If it does it must mean registry strangeness, so exit, and try
1454          * again...
1455          */
1456
1457         if (!DoLogin (user, greet.password, d->name)) exit (1);
1458         
1459         /*
1460          * extract the SYSTYPE and ISP environment values and set into user's 
1461          * environment. This is necessary since we do an execve below...
1462          */
1463          
1464         verify->userEnviron = setEnv(verify->userEnviron, "SYSTYPE",
1465                                      getenv("SYSTYPE"));
1466
1467         verify->userEnviron = setEnv(verify->userEnviron, "ISP",
1468                                      getenv("ISP"));
1469
1470 #else /* ! __apollo */
1471
1472
1473 #  ifdef __AFS
1474         if ( IsVerifyName(VN_AFS) ) {
1475             pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1476             Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1477
1478             initgroups(greet.name, verify->groups[2]);
1479             ngroups = getgroups(NGROUPS, groups);
1480             Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1481             for (i=0; i < ngroups; i++)
1482                 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1483
1484             if ((pagval != NOPAG) &&
1485                 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1486                 /* we will have to shift grouplist to make room for pag */
1487                 if (ngroups+2 > NGROUPS)
1488                     ngroups=NGROUPS-2;
1489                 for (j=ngroups-1; j >= 0; j--) {
1490                     groups[j+2] = groups[j];
1491                 }
1492                 ngroups += 2;
1493                 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1494                 if (setgroups(ngroups, groups) == -1) {
1495                     LogError(
1496                         ReadCatalog(
1497                           MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1498                     exit(1);
1499                 }
1500             }
1501         }
1502 #  else /* ! __AFS */
1503 /* If SIA is enabled, the initgroups and setgid calls are redundant
1504  * so skip them.
1505  */
1506 #  ifndef SIA
1507 #    ifdef NGROUPS
1508
1509         /*
1510          * if your system does not support "initgroups(3C)", use
1511          * the "setgroups()" call instead...
1512          */
1513          
1514 #      if (defined(__hpux) || defined(__osf__))
1515         initgroups(user, -1);
1516 #      else
1517         setgroups (verify->ngroups, verify->groups);
1518 #      endif
1519
1520 /* setpenv() will set gid for AIX */
1521 #if !defined (_AIX)
1522         setgid (verify->groups[0]);
1523 #endif
1524
1525 #    else  /* ! NGROUPS */
1526
1527 /* setpenv() will set gid for AIX */
1528 #if !defined (_AIX)
1529         setgid (verify->gid);
1530 #endif
1531
1532 #    endif /* NGROUPS */
1533 #  endif /* !SIA */
1534 #  endif /* __AFS */
1535
1536
1537 #  ifdef AUDIT
1538         setaudid(verify->audid);
1539         setaudproc(verify->audflg);
1540 #  endif
1541
1542 /* setpenv() will set uid for AIX */
1543 #if !defined(_AIX)
1544         if (setuid(verify->uid) != 0) {
1545             Debug(   "Setuid failed for user %s, errno = %d\n", user, errno);
1546             LogError(ReadCatalog(
1547                 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1548                 user,errno);
1549             exit (1);
1550         }
1551 #endif
1552
1553 #endif /* __apollo */
1554
1555 #ifdef BLS
1556     }  /* ends the else clause of if ( ISSECURE ) */
1557 #endif /* BLS */
1558
1559 #endif /* ! sun */
1560                     
1561         /*
1562          *  check home directory again...
1563          */
1564
1565 #ifndef SIA
1566 /* Don't need to do this if SIA is enabled, already been done.
1567  */
1568         home = getEnv (verify->userEnviron, "HOME");
1569         if (home) {
1570                 if (chdir (home) == -1) {
1571                         LogError (ReadCatalog(
1572                                 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1573                                 home, getEnv (verify->userEnviron, "USER"));
1574                         chdir ("/");
1575                         verify->userEnviron = setEnv(verify->userEnviron, 
1576                                                      "HOME", "/");
1577                 }
1578                 else if(!failsafe) {
1579                         strcpy(lastsessfile,home);                      /* save user's last session */
1580                         strcat(lastsessfile,LAST_SESSION_FILE);
1581                         if((lastsession = fopen(lastsessfile,"w")) == NULL)
1582                                 Debug("Unable to open file for writing: %s\n",lastsessfile);
1583                         else{
1584                                 fputs(verify->argv[0],lastsession);
1585                                 fclose(lastsession);
1586                          }
1587                 }
1588         }
1589 #endif
1590
1591
1592         SetUserAuthorization (d, verify);
1593
1594         /*
1595          * clear password...
1596          */
1597         if (greet.password)
1598             bzero(greet.password, strlen(greet.password));
1599
1600 #ifdef  BLS
1601         /*
1602          * Write login information to a file
1603          * The file name should really be settable by some kind of resource
1604          * but time is short so we hard-wire it to ".dtlogininfo".
1605          */
1606         if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1607                 Debug("Unable to write \".dtlogininfo\"\n");
1608 #  ifndef NDEBUG
1609         /* extra debugging */
1610         if(!dump_sec_debug_info(verify)) {
1611             Debug("Something wrong with environment\n");
1612             exit(1);
1613         }
1614 #  endif  /* ! NDEBUG */
1615 #endif  /* BLS */
1616
1617         /*
1618          *  exec session...
1619          */
1620         if (verify->argv) {
1621             if ( !failsafe) {
1622                 Debug ("Executing session %s\n", verify->argv[0]);
1623                 execute (verify->argv, verify->userEnviron);
1624                 LogError(ReadCatalog(
1625                         MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1626                         verify->argv[0]);
1627             }
1628         } else {
1629                 LogError(ReadCatalog(
1630                         MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1631         }
1632         
1633         
1634
1635
1636         /*
1637          * specify a font for the multi-byte languages...
1638          */
1639             
1640         font = NULL;
1641         lang = getEnv (verify->userEnviron, "LANG");
1642
1643
1644
1645         i = 0;
1646         if ( password ) {
1647 #if defined(_AIX)
1648             failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1649 #elif defined(sun)
1650             failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1651 #elif defined (USL) || defined(__uxp__)
1652             failsafeArgv[i++] = "/usr/X/bin/xterm";
1653 #elif defined(__hpux)
1654             failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1655 #else
1656             failsafeArgv[i++] = "/usr/bin/X11/xterm";
1657 #endif
1658             failsafeArgv[i++] = "-geometry";
1659             failsafeArgv[i++] = "80x10";
1660             failsafeArgv[i++] = "-bg";
1661             failsafeArgv[i++] = "white";
1662             failsafeArgv[i++] = "-fg";
1663             failsafeArgv[i++] = "black";
1664 #ifdef _AIX
1665             /* aixterm requires -lang option. */
1666             failsafeArgv[i++] = "-lang";
1667             failsafeArgv[i++] = lang;
1668 #else /* _AIX */
1669             failsafeArgv[i++] = "-fn";
1670
1671             if (font == NULL) font = "fixed";
1672             failsafeArgv[i++] = font;
1673 #endif /* _AIX */
1674
1675             failsafeArgv[i++] = "-e";
1676             failsafeArgv[i++] = "/bin/passwd";
1677 #if defined (__apollo) || defined(__PASSWD_ETC)
1678             failsafeArgv[i++] = "-n";
1679 #endif
1680             failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1681         }
1682         else {
1683             failsafeArgv[i++] = d->failsafeClient;
1684 #ifdef sun 
1685             failsafeArgv[i++] = "-C";
1686 #endif
1687             failsafeArgv[i++] = "-ls";
1688
1689             if (font != NULL) {
1690                 failsafeArgv[i++] = "-fn";
1691                 failsafeArgv[i++] = font;
1692             }
1693         }
1694
1695         failsafeArgv[i] = 0;
1696         Debug ("Executing failsafe session\n", failsafeArgv[0]);
1697         execute (failsafeArgv, verify->userEnviron);
1698         exit (1);
1699     case -1:
1700         Debug ("StartSession(): fork failed\n");
1701         LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1702                 d->name);
1703         return 0;
1704     default:
1705         Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1706         *pidp = pid;
1707
1708         return 1;
1709     }
1710 }
1711
1712 static jmp_buf  tenaciousClient;
1713
1714 static SIGVAL
1715 waitAbort( int arg )
1716 {
1717         longjmp (tenaciousClient, 1);
1718 }
1719
1720 #if defined(SYSV) || defined(SVR4)
1721 # include       <ctype.h>
1722 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1723 #endif /* SYSV */
1724
1725 static int 
1726 AbortClient( int pid )
1727 {
1728     int sig = SIGTERM;
1729 #ifdef __STDC__
1730     volatile int        i;
1731 #else
1732     int i;
1733 #endif
1734     int retId;
1735     for (i = 0; i < 4; i++) {
1736         if (killpg (pid, sig) == -1) {
1737             switch (errno) {
1738             case EPERM:
1739                 LogError(ReadCatalog(
1740                         MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1741             case EINVAL:
1742             case ESRCH:
1743                 return;
1744             }
1745         }
1746         if (!setjmp (tenaciousClient)) {
1747             (void) signal (SIGALRM, waitAbort);
1748             (void) alarm ((unsigned) 10);
1749             retId = wait ((waitType *) 0);
1750             (void) alarm ((unsigned) 0);
1751             (void) signal (SIGALRM, SIG_DFL);
1752             if (retId == pid)
1753                 break;
1754         } else
1755             signal (SIGALRM, SIG_DFL);
1756         sig = SIGKILL;
1757     }
1758 }
1759
1760 int 
1761 source( struct verify_info *verify, char *file )
1762 {
1763     char        *args[2];
1764     int         pid;
1765     waitType    result;
1766
1767     if (file && file[0]) {
1768         Debug ("Source(): %s\n", file);
1769         switch (pid = fork ()) {
1770         case 0:
1771             CleanUpChild ();
1772             args[0] = file;
1773             args[1] = NULL;
1774             execute (args, verify->systemEnviron);
1775             LogError(ReadCatalog(
1776                 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1777             exit (1);
1778         case -1:
1779             Debug ("Source(): fork failed\n");
1780             LogError(ReadCatalog(
1781                 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1782             return 1;
1783             break;
1784         default:
1785             while (wait (&result) != pid)
1786                     ;
1787             break;
1788         }
1789         return waitVal (result);
1790     }
1791     return 0;
1792 }
1793
1794 int 
1795 execute(char **argv, char **environ )
1796 {
1797
1798     /*
1799      *  make stdout follow stderr to the log file...
1800      */
1801
1802     dup2 (2,1);
1803     
1804     session_execve (argv[0], argv, environ);
1805
1806     /*
1807      * In case this is a shell script which hasn't been made executable
1808      * (or this is a SYSV box), do a reasonable thing...
1809      */
1810
1811 #ifdef _AIX
1812     /* errno is EACCES if not executable */
1813     if (errno == ENOEXEC || errno == EACCES) {
1814 #else /* _AIX */
1815     if (errno == ENOEXEC) {
1816 #endif /* _AIX */
1817         char    program[1024], *e, *p, *optarg;
1818         FILE    *f;
1819         char    **newargv, **av;
1820         int     argc;
1821
1822         /*
1823          * emulate BSD kernel behaviour -- read
1824          * the first line; check if it starts
1825          * with "#!", in which case it uses
1826          * the rest of the line as the name of
1827          * program to run.  Else use "/bin/sh".
1828          */
1829         f = fopen (argv[0], "r");
1830         if (!f)
1831             return;
1832         if (fgets (program, sizeof (program) - 1, f) == NULL)
1833         {
1834             fclose (f);
1835             return;
1836         }
1837         fclose (f);
1838         e = program + strlen (program) - 1;
1839         if (*e == '\n')
1840             *e = '\0';
1841         if (!strncmp (program, "#!", 2)) {
1842             p = program + 2;
1843             while (*p && isspace (*p))
1844                 ++p;
1845             optarg = p;
1846             while (*optarg && !isspace (*optarg))
1847                 ++optarg;
1848             if (*optarg) {
1849                 *optarg = '\0';
1850                 do
1851                     ++optarg;
1852                 while (*optarg && isspace (*optarg));
1853             } else
1854                 optarg = 0;
1855         } else {
1856             p = "/bin/sh";
1857             optarg = 0;
1858         }
1859         Debug ("Shell script execution: %s (optarg %s)\n",
1860                 p, optarg ? optarg : "(null)");
1861         for (av = argv, argc = 0; *av; av++, argc++)
1862                 ;
1863         newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1864         if (!newargv)
1865             return -1;
1866         av = newargv;
1867         *av++ = p;
1868         if (optarg)
1869             *av++ = optarg;
1870         while (*av++ = *argv++)
1871             ;
1872         session_execve (newargv[0], newargv, environ);
1873     }
1874 }
1875
1876
1877
1878
1879 /*****************************************************************************
1880 *    RunGreeter
1881 *    
1882 *    Invoke the Greeter process and wait for completion. If the user was 
1883 *    successfully verified, return to the calling process. If the user
1884 *    selected a restart or abort option, or there was an error invoking the
1885 *    Greeter, exit this entire process with appropriate status.
1886 *
1887 *****************************************************************************/
1888
1889 #define MSGSIZE 512
1890
1891 extern int session_set; 
1892 extern char *progName;  /* Global argv[0]; dtlogin name and path */
1893
1894 int         response[2], request[2];
1895
1896 /* Fixes problem with dtlogin signal handling */
1897 static int greeterPid = 0;
1898 static struct display *greeter_d = NULL;
1899
1900 static SIGVAL
1901 catchHUP(int arg)
1902 {
1903     Debug("Caught SIGHUP\n");
1904     if (greeterPid) 
1905     {
1906         Debug("Killing greeter process:  %d\n", greeterPid);
1907         kill(greeterPid, SIGHUP);
1908     }
1909     if (greeter_d)
1910       SessionExit(greeter_d, REMANAGE_DISPLAY);
1911     else
1912       exit(REMANAGE_DISPLAY);
1913 }
1914
1915 static void 
1916 RunGreeter( struct display *d, struct greet_info *greet,
1917             struct verify_info *verify )
1918 {
1919
1920     int       pid;
1921     waitType    status;
1922     
1923     int         rbytes;
1924     static char msg[MSGSIZE];
1925     char        *p;
1926     char        **env;
1927     char        *path;
1928     struct greet_state state;
1929     int         notify_dt;
1930
1931 #ifdef __PASSWD_ETC
1932 #  ifndef U_NAMELEN
1933 #    define U_NAMELEN   sizeof(rgy_$name_t)
1934 #  endif
1935
1936     int i;
1937     static char name_short[U_NAMELEN];
1938 #endif
1939
1940 #ifdef SIA
1941
1942     int argc = 1;
1943     char *argv[] = { "dtlogin", 0 };
1944     char *hostName = NULL;
1945     char *loginName = NULL;
1946     int siaStatus = -1;
1947
1948     /*
1949      * Initialize SIA
1950      */
1951     
1952     if (d->serverPid == -1)
1953       hostName = d->name;
1954
1955     siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName, 
1956                               loginName, d->name, 1, NULL);
1957     if (siaStatus != SIASUCCESS)
1958       {
1959       Debug("sia_ses_init failure status %d\n", siaStatus);
1960       exit(1);
1961       }
1962
1963 #endif
1964
1965     greeterPid = 0;
1966     if (!setjmp (abortSession)) {
1967         signal(SIGTERM, catchTerm);
1968
1969         /*
1970          * We've changed dtlogin to pass HUP's down to the children
1971          * so ignore any HUP's once the client has started.
1972          */
1973         greeter_d = d;
1974         signal(SIGHUP, catchHUP);
1975
1976         /*
1977          *  set up communication pipes...
1978          */
1979          
1980         pipe(response);
1981         pipe(request);
1982         rbytes = 0;
1983
1984
1985         switch (greeterPid = fork ()) {
1986         case 0:
1987
1988             /*
1989              *  pass some information in the environment...
1990              */
1991                    
1992             env = 0;
1993             sprintf(msg,"%d", d->grabServer);
1994             env = setEnv(env, GRABSERVER,  msg);
1995         
1996             sprintf(msg,"%d", d->grabTimeout);
1997             env = setEnv(env, GRABTIMEOUT, msg);
1998
1999
2000             if (timeZone && strlen(timeZone) > 0 )
2001                 env = setEnv(env, "TZ", timeZone);
2002
2003             if (errorLogFile && errorLogFile[0])
2004                 env = setEnv(env, ERRORLOG,  errorLogFile);
2005
2006             if (d->authFile)
2007                 env = setEnv(env, "XAUTHORITY", d->authFile);
2008
2009             if (d->dtlite)
2010                 env = setEnv(env, DTLITE,  "True");
2011
2012             if (d->session)  
2013                 env = setEnv(env, SESSION,  d->session);
2014
2015             if(session_set)
2016                 env = setEnv(env, SESSION_SET, "True");
2017
2018             if (d->pmSearchPath)
2019                 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
2020
2021             if (d->bmSearchPath)
2022                 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
2023
2024 #if defined (__KERBEROS) || defined (__AFS)
2025             if (d->verifyName) {
2026                 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2027                      (strcmp(d->verifyName, VN_KRB) == 0)    ) {
2028                      
2029                     env = setEnv(env, VERIFYNAME, d->verifyName );
2030                 }
2031                 else {
2032                     LogError(ReadCatalog(
2033                         MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2034                         d->verifyName);
2035                     d->verifyName = NULL;
2036                 }
2037             }
2038 #endif
2039                         
2040             if((path = getenv("NLSPATH")) != NULL)
2041                 env = setEnv(env, "NLSPATH", path);
2042 #ifdef __hp_osf
2043             env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2044 #endif
2045
2046             
2047             /*
2048              *  ping remote displays...
2049              *
2050              */
2051
2052             if (d->displayType.location == Local) {
2053                 GettyRunning(d); /* refresh gettyState */
2054                 if (d->gettyState != DM_GETTY_USER)
2055                     env = setEnv(env, LOCATION, "local");
2056             }
2057             else {
2058                 sprintf(msg,"%d", d->pingInterval);
2059                 env = setEnv(env, PINGINTERVAL,  msg);
2060         
2061                 sprintf(msg,"%d", d->pingTimeout);
2062                 env = setEnv(env, PINGTIMEOUT, msg);
2063             }
2064
2065
2066             if ( d->langList && strlen(d->langList) > 0 )
2067                 env = setEnv(env, LANGLIST,  d->langList);
2068 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2069             else if (languageList && strlen(languageList) > 0 )
2070                 env = setEnv(env, LANGLIST, languageList);
2071 #endif /* ENABLE_DYNAMIC_LANGLIST */
2072
2073             {
2074                 char *language = NULL;
2075
2076 #if defined (ENABLE_DYNAMIC_LANGLIST)
2077                 language = d->language;
2078 #endif /* ENABLE_DYNAMIC_LANGLIST */
2079
2080                 if ( d->language && strlen(d->language) > 0 )
2081                   env = setLang(d, env, language);
2082             }
2083
2084             if((path = getenv("XKEYSYMDB")) != NULL)
2085                 env = setEnv(env, "XKEYSYMDB", path);
2086
2087 #ifdef sun
2088             if((path = getenv("OPENWINHOME")) != NULL)
2089                 env = setEnv(env, "OPENWINHOME", path);
2090 #endif
2091
2092 #ifdef __apollo
2093             /*
2094              *  set environment for Domain machines...
2095              */
2096             env = setEnv(env, "ENVIRONMENT", "bsd");
2097             env = setEnv(env, "SYSTYPE", "bsd4.3");
2098 #endif
2099                 
2100
2101             Debug ("Greeter environment:\n");
2102             printEnv(env);
2103             Debug ("End of Greeter environment:\n");
2104
2105            /*
2106             * Writing to file descriptor 1 goes to response pipe instead.
2107             */
2108             close(1);
2109             dup(response[1]);
2110             close(response[0]);
2111             close(response[1]);
2112
2113            /*
2114             * Reading from file descriptor 0 reads from request pipe instead.
2115             */
2116             close(0);
2117             dup(request[0]);
2118             close(request[0]);
2119             close(request[1]);
2120
2121             CleanUpChild ();
2122
2123             /*
2124              * figure out path to dtgreet...
2125              */
2126
2127             strcpy(msg, progName);
2128     
2129             if ((p = (char *) strrchr(msg, '/')) == NULL)
2130                 strcpy(msg,"./");
2131             else
2132                 *(++p) = NULL;
2133
2134             strcat(msg,"dtgreet");
2135
2136             execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2137             LogError(ReadCatalog(
2138                 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2139                  msg, d->name);
2140             exit (NOTIFY_ABORT_DISPLAY);
2141
2142         case -1:
2143             Debug ("Fork of Greeter failed.\n");
2144             LogError(ReadCatalog(
2145                 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2146             close(request[0]);
2147             close(request[1]);
2148             close(response[0]);
2149             close(response[1]);
2150             exit (UNMANAGE_DISPLAY);
2151
2152         default:
2153             Debug ("Greeter started\n");
2154
2155             close(response[1]); /* Close write end of response pipe */
2156             close(request[0]); /* Close read end of request pipe */
2157
2158
2159             /*
2160              * Retrieve information from greeter and authenticate.
2161              */
2162             globalDisplayName = d->name;
2163             state.id = GREET_STATE_ENTER;
2164             state.waitForResponse = FALSE;
2165 #ifdef SIA
2166            
2167             /*
2168              * atexit() registers this function to be called if exit() is
2169              * called.  This is needed because in enhanced security mode, SIA
2170              * may call exit() whn the user fails to enter or change a
2171              * password.
2172              */
2173             sia_greeter_pid = greeterPid;
2174             if (!sia_exit_proc_reg)
2175                 {
2176                 atexit(KillGreeter);
2177                 sia_exit_proc_reg = TRUE;
2178                 }
2179   
2180             siaGreeterInfo.d = d;
2181             siaGreeterInfo.greet = greet;
2182             siaGreeterInfo.verify = verify;
2183             siaGreeterInfo.state = &state;
2184             siaGreeterInfo.status = TRUE;
2185   
2186             siaStatus =  -1;
2187             while(siaStatus != SIASUCCESS)
2188                 {
2189                 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2190                     {
2191                     Debug ("RunGreeter: before sia_ses_authent\n");
2192                     dt_in_sia_ses_authent = True;
2193                     siaStatus = sia_ses_authent(SiaManageGreeter, NULL, 
2194                                                 siaHandle);
2195                     dt_in_sia_ses_authent = False;
2196                     Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2197                                 siaStatus);
2198                     if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2199                         {
2200                         state.id = GREET_STATE_ERRORMESSAGE;
2201                         state.vf = VF_INVALID;
2202                         ManageGreeter(d, greet, verify, &state);
2203                         }
2204                     if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2205                         break;
2206                     }
2207                 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2208                     {
2209                     sia_ses_release(&siaHandle);
2210                     break;
2211                     }
2212   
2213                 Debug("RunGreeter: before sia_ses_estab\n");
2214                 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2215                 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2216                                 siaStatus);
2217   
2218                 if (!siaGreeterInfo.status)
2219                     break;
2220   
2221                 if (siaStatus == SIASUCCESS)
2222                     {
2223                     Debug("RunGreeter: before sia_ses_launch\n");
2224                     siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2225                     Debug("RunGreeter: after sia_ses_launch status = %d\n",
2226                                 siaStatus);
2227                     }
2228                 if (!siaGreeterInfo.status)
2229                     break;
2230   
2231                 if (siaStatus != SIASUCCESS)
2232                     {
2233                     Debug("RunGreeter: sia_ses_launch failure\n");
2234                     /* establish & launch failures do a release */
2235                     siaHandle = NULL;
2236                     siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName, 
2237                                                 loginName, d->name, 1, NULL);
2238                     if (siaStatus != SIASUCCESS)
2239                         {
2240                         Debug("sia_ses_init failure status %d\n", siaStatus);
2241                         exit(RESERVER_DISPLAY);
2242                         }
2243                     }
2244                 }
2245             /*
2246              * sia_ses_launch() wil probably seteuid to that of the
2247              * user, but we don't want that now.
2248              */
2249             seteuid(0);
2250             /*
2251              * extract necessary info from SIA context struct
2252              */
2253             if (siaHandle)
2254                 {
2255                 if (siaStatus == SIASUCCESS)
2256                     CopySiaInfo(siaHandle, greet);
2257                 sia_ses_release(&siaHandle);
2258                 }
2259             state.id = GREET_STATE_TERMINATEGREET;
2260             if (siaGreeterInfo.status)
2261                 {
2262                 while (ManageGreeter(d, greet, verify, &state))
2263                   ;
2264                 }
2265             sia_greeter_pid = 0;
2266 #else
2267             while (ManageGreeter(d, greet, verify, &state))
2268               ;
2269 #endif /* SIA */
2270
2271             /*
2272              * Wait for Greeter to end...
2273              */
2274             for (;;) {
2275                 pid = wait (&status);
2276                 if (pid == greeterPid)
2277                     break;
2278             }
2279
2280
2281             /*
2282              *  Greeter exited. Check return code...
2283              */
2284              
2285             Debug("Greeter return status; exit = %d, signal = %d\n", 
2286                    waitCode(status), waitSig(status));
2287
2288
2289             /*
2290              * remove authorization file if used...
2291              */
2292      
2293             if (d->authorizations && d->authFile &&
2294                 waitVal(status) != NOTIFY_LANG_CHANGE
2295 #ifdef BLS
2296                 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2297 #endif
2298                ) {
2299
2300 /***
2301                 Debug ("Done with authorization file %s, removing\n",
2302                         d->authFile);
2303                 (void) unlink (d->authFile);
2304 ***/
2305             }
2306
2307
2308                 if(waitVal(status) > NOTIFY_ALT_DTS) 
2309                       d->sessionType = waitVal(status);
2310
2311
2312             switch (waitVal(status)) {
2313             case NOTIFY_FAILSAFE:
2314                 greet->string = "failsafe";
2315                 break;
2316             case NOTIFY_PASSWD_EXPIRED:
2317                 greet->string = "password";
2318                 break;
2319             case NOTIFY_DTLITE:
2320             case NOTIFY_DT:
2321             case NOTIFY_OK:
2322             case NOTIFY_LAST_DT:
2323                 d->sessionType = waitVal(status);
2324                 break;
2325             default:
2326                 break;
2327             }
2328
2329           Debug("waitVal - status is  %d\n", waitVal(status));
2330            if(waitVal(status) > NOTIFY_ALT_DTS)
2331                 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2332             else
2333                 notify_dt = waitVal(status);
2334
2335             switch (notify_dt) {
2336             case NOTIFY_FAILSAFE:
2337             case NOTIFY_PASSWD_EXPIRED:
2338             case NOTIFY_DTLITE:
2339             case NOTIFY_DT:
2340             case NOTIFY_OK:
2341             case NOTIFY_LAST_DT:
2342             case NOTIFY_ALT_DTS:
2343
2344                if (NULL == greet->name) return;
2345
2346                /*
2347                 *  greet->name, greet->password set in ManageGreeter().
2348                 */
2349                 Debug("Greeter returned name '%s'\n", greet->name);
2350
2351 #ifdef __PASSWD_ETC
2352                 greet->name_full = greet->name;
2353                            /* get just person name out of full SID */
2354                 i = 0;
2355                 while (i < sizeof(rgy_$name_t) 
2356                      && greet->name_full[i] != '.'
2357                      && greet->name_full[i] != '\0') {
2358                      name_short[i] = greet->name_full[i];
2359                      i++;
2360                 }
2361                 name_short[i] = '\0';
2362                 greet->name = name_short;
2363 #endif
2364                     
2365 #ifdef __AFS
2366                /*
2367                 * groups[] set in Authenticate().
2368                 */
2369                 if ( IsVerifyName(VN_AFS) ) {
2370                   verify->groups[0] = groups[0];
2371                   verify->groups[1] = groups[1];
2372                   Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2373                   Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2374                 }
2375 #endif
2376                     
2377 #ifdef BLS
2378                /*
2379                 * sensitivityLevel set in BLS_Verify()
2380                 */
2381                 greet->b1security = sensitivityLevel;
2382 #endif
2383
2384                 Verify(d, greet, verify);
2385                 return;
2386
2387             case NOTIFY_ABORT:
2388                 Debug ("Greeter Xlib error or SIGTERM\n");
2389                 SessionExit(d, OPENFAILED_DISPLAY);
2390
2391             case NOTIFY_RESTART:
2392                 Debug ("Greeter requested RESTART_DISPLAY\n");
2393                 SessionExit(d, RESERVER_DISPLAY);
2394
2395             case NOTIFY_ABORT_DISPLAY:
2396                 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2397                 SessionExit(d, UNMANAGE_DISPLAY);
2398
2399             case NOTIFY_NO_WINDOWS:
2400                 Debug ("Greeter requested NO_WINDOWS mode\n");
2401                 if (d->serverPid >= 2)
2402                     /*
2403                      *  Don't do a SessionExit() here since that causes
2404                      *  the X-server to be reset. We know we are going to
2405                      *  terminate it anyway, so just go do that...
2406                      */
2407                     exit(SUSPEND_DISPLAY);
2408                 else
2409                     return;
2410
2411             case NOTIFY_LANG_CHANGE:
2412                 Debug ("Greeter requested LANG_CHANGE\n");
2413
2414                /*
2415                 * copy requested language into display struct "d". Note,
2416                 * this only happens in this child's copy of "d", not in
2417                 * the master struct. When the user logs out, the
2418                 * resource-specified language (if any) will reactivate.
2419                 */
2420                 Debug("Greeter returned language '%s'\n", d->language);
2421
2422                 if (strcmp(d->language, "default") == 0) {
2423                     int len = strlen(defaultLanguage) + 1;
2424                     d->language = (d->language == NULL  ?
2425                                    malloc(len) : realloc (d->language, len));
2426                     strcpy(d->language, defaultLanguage);
2427                 }
2428                 return;
2429 #ifdef  BLS
2430             case NOTIFY_BAD_SECLEVEL:
2431                 return;
2432 #endif
2433             case waitCompose (SIGTERM,0,0):
2434                 Debug ("Greeter exited on SIGTERM\n");
2435                 SessionExit(d, OPENFAILED_DISPLAY);
2436                 
2437             default:
2438                 Debug ("Greeter returned unknown status %d\n", 
2439                         waitVal(status));
2440                 SessionExit(d, REMANAGE_DISPLAY);
2441             }
2442         }
2443         signal(SIGHUP, SIG_DFL);
2444     }
2445     else {
2446         AbortClient(greeterPid);
2447         SessionExit(d, UNMANAGE_DISPLAY);
2448     }
2449 }
2450
2451 /*****************************************************************************
2452 * ManageGreeter
2453  
2454   State transitions
2455  
2456   enter -> ENTER: 
2457     This is the entry into greeter state processing. Allocate and initialize
2458     state structure.
2459
2460   ENTER -> LOGIN:
2461     Display the login screen. Upon display, the login screen can be 'reset'. If
2462     reset is true, the username and password fields are cleared and the focus
2463     is set to the username field. If reset is false, the username and password
2464     field is untouched and the focus is set to the password field.
2465
2466   LOGIN -> AUTHENTICATE:
2467     Authenticate the username entered on login screen. 
2468
2469   AUTHENTICATE -> TERMINATEGREET:
2470     User passed authentication so terminate the greeter.
2471
2472   AUTHENTICATE -> EXPASSWORD: 
2473     User passed authentication, but the their password has expired.
2474     Display old password message. This message allows the user to 
2475     change their password by starting a getty and running passwd(1).  
2476
2477   AUTHENTICATE -> BAD_HOSTNAME:
2478     User passed authentication, but the their hostname is empty.
2479     Display a dialog that allows the user to run a getty to fix the
2480     problem, or start the desktop anyway.
2481
2482   AUTHENTICATE -> ERRORMESSAGE:
2483     User failed authentication, so display error message. 
2484
2485   AUTHENTICATE -> LOGIN
2486     User failed authentication, but did not enter a password. Instead
2487     of displaying an error message, redisplay the login screen with
2488     the focus set to the password field. If the user authenticates again
2489     without the password field set, display an error. This allows a user
2490     to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2491
2492   EXIT -> exit
2493     Free state structure and return false to stop state transitions.
2494
2495   ERRORMESSAGE -> LOGIN
2496     Display error message base on return code from last authentication
2497     attempt. Redisplay login screen with reset set to true.
2498
2499   (state) -> LANG -> (state)
2500     User has chosen a new language. Transition to LANG state to save off
2501     the new language, and transition back to original state. 
2502   
2503 *****************************************************************************/
2504
2505 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2506
2507 static int
2508 ManageGreeter( struct display *d, struct greet_info *greet,
2509             struct verify_info *verify, struct greet_state *state )
2510 {
2511   struct {
2512     int id;
2513     char *def;
2514   } msg;
2515
2516   if (state->waitForResponse)
2517   {
2518     if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2519     {
2520      /*
2521       * Dtgreet has terminated. 
2522       */
2523       state->id = GREET_STATE_EXIT;
2524       state->waitForResponse = FALSE;
2525       return(TRUE);
2526     }
2527
2528     if (state->request->opcode != state->response->opcode)
2529     {
2530      /*
2531       * An unrequested event arrived. See if it's one we
2532       * are expecting.
2533       */
2534       switch(state->response->opcode)
2535       {
2536         case REQUEST_OP_LANG:
2537           {
2538            /*
2539             * User has changed language. Recursively handle this state
2540             * and return to current state.
2541             */
2542             struct greet_state lang_state;
2543
2544             lang_state = *state;
2545             lang_state.id = GREET_STATE_LANG;
2546             lang_state.waitForResponse = FALSE;
2547             ManageGreeter(d, greet, verify, &lang_state);
2548             Debug("Response opcode REQUEST_OP_LANG\n");
2549             return(TRUE);
2550           }
2551           break;
2552
2553         case REQUEST_OP_CLEAR:
2554           {
2555            /*
2556             * User has requested the screen be cleared.
2557             */
2558             state->id = GREET_STATE_USERNAME;
2559             state->waitForResponse = TRUE;
2560             Debug("Response opcode REQUEST_OP_CLEAR\n");
2561           }
2562           break;
2563     
2564         default:
2565           Debug("Response opcode UNEXPECTED RESPONSE!\n");
2566 #ifndef SIA
2567           return(TRUE);
2568 #endif
2569           break;
2570       }
2571     }
2572     else
2573     {
2574      /*
2575       * Got the response we were expecting.
2576       */
2577       state->waitForResponse = FALSE;
2578     }
2579   }
2580
2581   switch(state->id)
2582   {
2583     case GREET_STATE_ENTER:
2584       {
2585        /*
2586         * Enter - initialize state
2587         */
2588         Debug("GREET_STATE_ENTER\n");
2589
2590         state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2591         state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2592         state->authenticated = FALSE;
2593         state->msg = NULL;
2594
2595         state->id = GREET_STATE_USERNAME;
2596       }
2597       break;
2598
2599     case GREET_STATE_USERNAME:
2600       {
2601        /*
2602         * Get user name
2603         */
2604         RequestChallenge *r;
2605
2606         Debug("GREET_STATE_USERNAME\n");
2607
2608         Authenticate(d, NULL, NULL, NULL);
2609
2610         SETMC(msg, LOGIN_LABEL);
2611
2612         r = (RequestChallenge *)state->request;
2613         r->hdr.opcode = REQUEST_OP_CHALLENGE;
2614         r->hdr.reserved = 0;
2615         r->bEcho = TRUE;
2616         r->idMC = msg.id;
2617         r->hdr.length = sizeof(*r);
2618
2619         r->offChallenge = sizeof(*r);
2620         strcpy(((char *)r) + r->offChallenge, msg.def);
2621         r->hdr.length += strlen(msg.def) + 1;
2622
2623         if (greet->name)
2624         {
2625           r->offUserNameSeed = r->hdr.length;
2626           strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2627           r->hdr.length += strlen(greet->name) + 1;
2628           Debug("Greet name:  %s\n", greet->name);
2629         }
2630         else
2631         {
2632           r->offUserNameSeed = 0;
2633         }
2634
2635         if (greet->name)
2636         {
2637           free(greet->name); greet->name = NULL;
2638         }
2639         if (greet->password)
2640         {
2641           free(greet->password); greet->password = NULL;
2642         }
2643
2644         TellGreeter((RequestHeader *)r);
2645         state->waitForResponse = TRUE;
2646
2647         state->id = GREET_STATE_AUTHENTICATE;
2648       }
2649       break;
2650
2651     case GREET_STATE_CHALLENGE:
2652       {
2653        /*
2654         * Get user name
2655         */
2656         RequestChallenge *r;
2657
2658         Debug("GREET_STATE_CHALLENGE\n");
2659
2660         if (greet->password)
2661         {
2662           free(greet->password); greet->password = NULL;
2663         }
2664
2665         SETMC(msg, PASSWD_LABEL);
2666
2667         r = (RequestChallenge *)state->request;
2668         r->hdr.opcode = REQUEST_OP_CHALLENGE;
2669         r->hdr.reserved = 0;
2670         r->bEcho = FALSE;
2671         r->idMC = msg.id;
2672         r->offUserNameSeed = 0;
2673         r->offChallenge = sizeof(*r);
2674         strcpy(((char *)r) + r->offChallenge, msg.def);
2675         r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2676
2677         TellGreeter((RequestHeader *)r);
2678         state->waitForResponse = TRUE;
2679
2680         state->id = GREET_STATE_AUTHENTICATE;
2681       }
2682       break;
2683
2684     case GREET_STATE_AUTHENTICATE:
2685       {
2686        /*
2687         * Attempt to authenticate.
2688         */
2689         ResponseChallenge *r;
2690    
2691         Debug("GREET_STATE_AUTHENTICATE\n"); 
2692
2693         r = (ResponseChallenge *)state->response;
2694      
2695         if (greet->name == NULL)
2696         {
2697           greet->name = strdup(((char *)r) + r->offResponse);
2698           if (strlen(greet->name) == 0)
2699           {
2700             state->id = GREET_STATE_USERNAME;
2701             break;
2702           }
2703         }
2704         else 
2705         { 
2706           greet->password = strdup(((char *)r) + r->offResponse);
2707         }
2708
2709         if (state->msg)
2710         {
2711           free(state->msg);
2712           state->msg = NULL;
2713         }
2714
2715        /*
2716         * Attempt to authenticate user. 'username' should be a 
2717         * non-empty string. 'password' may be an empty string.
2718         */
2719         state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2720
2721         if (state->vf == VF_OK || 
2722             state->vf == VF_PASSWD_AGED || 
2723             state->vf == VF_BAD_HOSTNAME)
2724         {
2725           state->authenticated = TRUE;
2726         }
2727
2728        /*
2729         * General transitions.
2730         */
2731         switch (state->vf)
2732         {
2733           case VF_OK:           state->id = GREET_STATE_TERMINATEGREET; break; 
2734           case VF_PASSWD_AGED:  state->id = GREET_STATE_EXPASSWORD; break; 
2735           case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break; 
2736           case VF_CHALLENGE:    state->id = GREET_STATE_CHALLENGE; break; 
2737           default:              state->id = GREET_STATE_ERRORMESSAGE; break; 
2738         }
2739       }
2740       break;
2741
2742     case GREET_STATE_EXIT: 
2743       {
2744        /*
2745         * Free resources and leave.
2746         */
2747         Debug("GREET_STATE_EXIT\n");
2748
2749         if (state->msg)
2750         {
2751           free(state->msg);
2752         }
2753  
2754         if (!state->authenticated)
2755         {
2756           if (greet->name)
2757           {
2758             free(greet->name); greet->name = NULL;
2759           }
2760           if (greet->password)
2761           {
2762             free(greet->password); greet->password = NULL;
2763           }
2764         }
2765
2766         free(state->request);
2767         free(state->response);
2768         return(FALSE);
2769       }
2770       break;
2771
2772     case GREET_STATE_ERRORMESSAGE:
2773       {
2774        /* 
2775         * Display error message.
2776         */
2777         RequestMessage *r;
2778
2779         Debug("GREET_STATE_ERRORMESSAGE\n");
2780
2781         r = (RequestMessage *)state->request;
2782
2783         switch(state->vf)
2784         {
2785           case VF_INVALID:       SETMC(msg, LOGIN); break;
2786           case VF_HOME:          SETMC(msg, HOME); break;
2787           case VF_MAX_USERS:     SETMC(msg, MAX_USERS); break;
2788           case VF_BAD_UID:       SETMC(msg, BAD_UID); break;
2789           case VF_BAD_GID:       SETMC(msg, BAD_GID); break;
2790           case VF_BAD_AID:       SETMC(msg, BAD_AID); break;
2791           case VF_BAD_AFLAG:     SETMC(msg, BAD_AFLAG); break;
2792           case VF_NO_LOGIN:      SETMC(msg, NO_LOGIN); break;
2793 #ifdef BLS
2794           case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2795 #endif
2796           case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2797           default: msg.id=0; msg.def=""; break;
2798         }
2799
2800         r->hdr.opcode = REQUEST_OP_MESSAGE;
2801         r->hdr.reserved = 0;
2802         r->idMC = msg.id;
2803         r->offMessage = sizeof(*r);
2804         strcpy(((char *)r) + r->offMessage, msg.def);
2805         r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2806
2807         TellGreeter((RequestHeader *)r);
2808         state->waitForResponse = TRUE;
2809
2810         state->id = GREET_STATE_USERNAME;
2811       }
2812       break;
2813
2814     case GREET_STATE_LANG:
2815       {
2816        /*
2817         * User selected new language.
2818         */
2819         ResponseLang *r;
2820         char *lang;
2821         int len;
2822
2823         Debug("GREET_STATE_LANG\n");
2824
2825         r = (ResponseLang *)state->response;
2826         lang = ((char *)r) + r->offLang;
2827         len = strlen(lang) + 1;
2828
2829         d->language = (d->language == NULL ?
2830                        malloc(len) : realloc(d->language, len));
2831         strcpy(d->language, lang);
2832         Debug("Language returned:  %s\n", d->language);
2833       }
2834       break;
2835
2836     case GREET_STATE_TERMINATEGREET:
2837       {
2838        /*
2839         * Terminate dtgreet.
2840         */
2841         RequestExit *r;
2842
2843         Debug("GREET_STATE_TERMINATEGREET\n");
2844
2845         r = (RequestExit *)state->request;
2846
2847         r->hdr.opcode = REQUEST_OP_EXIT;
2848         r->hdr.reserved = 0;
2849         r->hdr.length = sizeof(*r);
2850
2851         TellGreeter((RequestHeader *)r);
2852         state->waitForResponse = TRUE;
2853
2854         state->id = GREET_STATE_EXIT;
2855       }
2856       break;
2857
2858     case GREET_STATE_EXPASSWORD:
2859       {
2860        /*
2861         * Display password expired message.
2862         */
2863         RequestExpassword *r;
2864
2865         Debug("GREET_STATE_EXPASSWORD\n");
2866
2867         r = (RequestExpassword *)state->request;
2868
2869         r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2870         r->hdr.reserved = 0;
2871         r->hdr.length = sizeof(*r);
2872
2873         TellGreeter((RequestHeader *)r);
2874         state->waitForResponse = TRUE;
2875
2876         state->id = GREET_STATE_USERNAME;
2877       }
2878       break;
2879
2880     case GREET_STATE_BAD_HOSTNAME:
2881       {
2882        /*
2883         * Display password expired message.
2884         */
2885         RequestHostname *r;
2886
2887         Debug("GREET_STATE_BAD_HOSTNAME\n");
2888
2889         r = (RequestHostname *)state->request;
2890
2891         r->hdr.opcode = REQUEST_OP_HOSTNAME;
2892         r->hdr.reserved = 0;
2893         r->hdr.length = sizeof(*r);
2894
2895         TellGreeter((RequestHeader *)r);
2896         state->waitForResponse = TRUE;
2897
2898         state->id = GREET_STATE_USERNAME;
2899       }
2900       break;
2901
2902 #ifdef SIA
2903     case GREET_STATE_FORM:
2904       {
2905        /*
2906         * Get arbitrary number of answers.
2907         */
2908
2909         Debug("GREET_STATE_FORM\n");
2910  
2911         AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2912  
2913         state->waitForResponse = FALSE;
2914         state->id = GREET_STATE_USERNAME;
2915       }
2916       break;
2917 #endif /* SIA */
2918   }
2919
2920   return(TRUE);
2921 }
2922
2923
2924 static void
2925 TellGreeter(
2926   RequestHeader *phdr)
2927 {
2928   write(request[1], phdr, phdr->length);
2929 }
2930
2931 static int
2932 AskGreeter(
2933   RequestHeader *preqhdr,
2934   char *buf,
2935   int blen)
2936 {
2937   int count;
2938   int remainder;
2939   ResponseHeader *phdr = (ResponseHeader *)buf;
2940
2941   if (preqhdr) TellGreeter(preqhdr);
2942
2943   phdr->opcode = REQUEST_OP_NONE;
2944
2945   count = read(response[0], buf, sizeof(*phdr));
2946
2947   if (count == sizeof(*phdr))
2948   {
2949    /*
2950     * Calculate amount of data after header.
2951     */
2952     remainder =  phdr->length - sizeof(*phdr);
2953     if (remainder > 0)
2954     {
2955      /*
2956       * Read remainder of response.
2957       */
2958       count += read(response[0], buf+sizeof(*phdr), remainder);
2959     }
2960   }
2961
2962 #if defined (DEBUG)
2963   if (debugLevel) PrintResponse(phdr, count);
2964 #endif /* DEBUG */
2965
2966   return(count);
2967 }
2968
2969 #if defined (DEBUG)
2970 static void
2971 PrintResponse(
2972   ResponseHeader *phdr,
2973   int count)
2974 {
2975   char *opstr = "UNKNOWN";
2976
2977   if (!count)
2978   {
2979     Debug("opcode = (EOF)\n");
2980     return;
2981   }
2982
2983   switch(phdr->opcode)
2984   {
2985     case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2986     case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2987     case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2988     case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2989     case REQUEST_OP_LANG: opstr = "LANG"; break;
2990     case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
2991   }
2992
2993   Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
2994   Debug("  reserved = %d\n", phdr->reserved);
2995   Debug("  length = %d\n", phdr->length);
2996
2997   switch(phdr->opcode)
2998   {
2999     case REQUEST_OP_EXIT: break;
3000     case REQUEST_OP_LANG:
3001       Debug("  offLang=%d\n", ((ResponseLang *)phdr)->offLang);
3002       Debug("  lang='%s'\n",
3003         ((char *)phdr)+((ResponseLang *)phdr)->offLang);
3004       break;
3005     case REQUEST_OP_MESSAGE: break;
3006     case REQUEST_OP_CHPASS: break;
3007     case REQUEST_OP_CHALLENGE:
3008       Debug("  offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
3009       Debug("  response='%s'\n",
3010         ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
3011       break;
3012     case REQUEST_OP_DEBUG:
3013       Debug("  offString=%d\n", ((ResponseDebug *)phdr)->offString);
3014       Debug("  string='%s'\n",
3015         ((char *)phdr)+((ResponseDebug *)phdr)->offString);
3016       break;
3017   }
3018 }
3019 #endif /* DEBUG */
3020
3021 #ifdef __KERBEROS
3022
3023 /***************************************************************************
3024  *
3025  *  SetTicketFileName
3026  *
3027  *  generate kerberos ticket file name. Name is returned in the static
3028  *  global variable "krb_ticket_string".
3029  *  
3030  ***************************************************************************/
3031
3032 static void 
3033 SetTicketFileName(uid_t uid)
3034 {
3035
3036
3037     char *env;
3038     char lhost[64], *p;
3039
3040
3041     /*
3042      *  generate ticket file pathname  (/tmp/tkt<uid>.<host>) ...
3043      */
3044
3045     if (env = (char *)getenv("KRBTKFILE")) {
3046         (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3047         krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3048
3049     } else {
3050         if (gethostname(lhost, sizeof(lhost)) != -1) {
3051             if (p = index(lhost, '.')) *p = '\0';
3052             (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3053         } else {
3054             /* 32 bits of signed integer will always fit in 11 characters
3055                (including the sign), so no need to worry about overflow */
3056             (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3057         }
3058     }
3059 }
3060
3061 #endif /* __KERBEROS */
3062
3063 #if defined (_AIX) && !defined (_POWER)
3064
3065 /***************************************************************************
3066  *
3067  *  session_execve
3068  *
3069  *  If this is an authenticated process (LOGNAME set), set user's 
3070  *  process environment by calling setpenv().
3071  *
3072  *  If this is not an authenticated process, just call execve()
3073  *  
3074  ***************************************************************************/
3075
3076 static int
3077 session_execve(
3078   char *path,
3079   char *argv[],
3080   char *envp[])
3081 {
3082   int rc;
3083   char *user = getEnv (envp, "LOGNAME");
3084  
3085   if (user == NULL)
3086   {
3087     rc = execve(path, argv, envp);
3088   }
3089   else
3090   {
3091     char *usrTag, *sysTag;
3092
3093    /*
3094     * Save pointers to tags. The setpenv() function clears the pointers
3095     * to the tags in userEnviron as a side-effect.
3096     */
3097     sysTag = envp[SYS_ENV_TAG];
3098     usrTag = envp[USR_ENV_TAG];
3099
3100    /*
3101     * Set the users process environment. This call execs arvg so it 
3102     * should not return. It it should return, restore the envp tags.
3103     */
3104     rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3105
3106    /*
3107     * Restore pointers to tags.
3108     */
3109     envp[SYS_ENV_TAG] = sysTag;
3110     envp[USR_ENV_TAG] = usrTag;
3111   }
3112
3113   return(rc);
3114 }
3115 #endif /* _AIX && !_POWER */
3116
3117 #ifdef SIA
3118
3119 /* collect the SIA parameters from a window system. */
3120
3121 static int SiaManageGreeter(
3122     int timeout,
3123     int rendition,
3124     unsigned char *title,
3125     int num_prompts,
3126     prompt_t *prompt)
3127 {
3128     int i;
3129     struct {
3130       RequestMessage  greeter_message;
3131       char            msg_buffer[256];
3132       } greeter_msg_and_buffer;
3133     RequestForm *request_form;
3134
3135     switch(rendition) 
3136       {
3137         case SIAMENUONE:
3138         case SIAMENUANY:
3139         case SIAONELINER:
3140         case SIAFORM:
3141           if (rendition == SIAFORM && dt_in_sia_ses_authent 
3142                                   && (num_prompts == 2))
3143               {
3144               /* Normal login, Password case */
3145               Debug ("SIAFORM Normal login, Password case\n");
3146               while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3147                     && siaGreeterInfo.state->id != GREET_STATE_EXIT
3148                     && (siaGreeterInfo.status = ManageGreeter(
3149                               siaGreeterInfo.d, siaGreeterInfo.greet, 
3150                               siaGreeterInfo.verify, siaGreeterInfo.state)))
3151                   ;
3152
3153               if (!siaGreeterInfo.status 
3154                       || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3155                   return(SIACOLABORT);
3156
3157               strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name, 
3158                       prompt[0].max_result_length);
3159               strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3160                       prompt[1].max_result_length);
3161               }
3162           else
3163               {
3164               char *res_ptr;
3165               char *pmpt_ptr;
3166               int req_form_size;
3167               ResponseForm *response_form;
3168
3169               switch(rendition) 
3170                   {
3171                   case SIAMENUONE:
3172                       Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3173                       break;
3174                   case SIAMENUANY:
3175                       Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3176                       break;
3177                   case SIAONELINER:
3178                       Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3179                       break;
3180                   case SIAFORM:
3181                       Debug("SIAFORM num_prompts = %d\n", num_prompts);
3182                       break;
3183                   }
3184
3185               /* need to display form */
3186
3187               req_form_size = sizeof(RequestForm) 
3188                                       + strlen((const char *)title) + 1;
3189               for (i=0; i<num_prompts; i++)
3190                   req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3191               request_form = (RequestForm *) alloca(req_form_size);
3192
3193               siaGreeterInfo.state->id = GREET_STATE_FORM;
3194               siaGreeterInfo.state->request = (RequestHeader *)request_form;
3195               /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3196
3197               request_form->hdr.opcode = REQUEST_OP_FORM;
3198               request_form->hdr.reserved = 0;
3199               request_form->hdr.length = req_form_size;
3200               request_form->num_prompts = num_prompts;
3201               request_form->rendition = rendition;
3202               request_form->offTitle = sizeof(RequestForm);
3203               request_form->offPrompts = sizeof(RequestForm) +
3204                                           strlen((const char *)title) + 1;
3205               strcpy((char *)request_form + request_form->offTitle, 
3206                       (const char *)title);
3207
3208               pmpt_ptr = (char *)request_form + request_form->offPrompts;
3209               for (i=0; i<num_prompts; i++)
3210                   {
3211                   if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3212                       *pmpt_ptr++ = '\0';
3213                   else
3214                       {
3215                       Debug("  prompt[%d]: %s\n", i, prompt[i].prompt);
3216                       strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3217                       pmpt_ptr += strlen((const char *)prompt[i].prompt);
3218                       }
3219                   request_form->visible[i] = 
3220                       (prompt[i].control_flags & SIARESINVIS) ? False : True;
3221                   }
3222
3223               siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d, 
3224                                                   siaGreeterInfo.greet,
3225                                                   siaGreeterInfo.verify, 
3226                                                   siaGreeterInfo.state);
3227
3228               response_form = (ResponseForm *)siaGreeterInfo.state->response;
3229               res_ptr = (char *)response_form + response_form->offAnswers;
3230               for (i = 0; i < response_form->num_answers; i++)
3231                   {
3232                   if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3233                       {
3234                       if (res_ptr[0])
3235                           prompt[i].result = (unsigned char *)1;
3236                       else
3237                           prompt[i].result = NULL;
3238                       }
3239                   else
3240                       {
3241                       strcpy((char *)prompt[0].result, res_ptr);
3242                       }
3243                   res_ptr += strlen(res_ptr) + 1;
3244                   }
3245               if (!response_form->collect_status)
3246                   siaGreeterInfo.status = FALSE;
3247               }
3248             break;
3249         case SIAINFO:
3250         case SIAWARNING:
3251
3252           Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3253
3254           siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3255           siaGreeterInfo.state->request = (RequestHeader *) 
3256                               &greeter_msg_and_buffer.greeter_message;
3257           siaGreeterInfo.state->vf = VF_MESSAGE;
3258           siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3259
3260           siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d, 
3261                                               siaGreeterInfo.greet,
3262                                               siaGreeterInfo.verify, 
3263                                               siaGreeterInfo.state);
3264             break;
3265         default:
3266             return(SIACOLABORT);
3267             break;
3268       }
3269     if (!siaGreeterInfo.status)
3270       return(SIACOLABORT);
3271     return(SIACOLSUCCESS);
3272 }
3273
3274 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3275 {
3276
3277     greet->name = malloc(strlen(siaHandle->name) + 1);
3278     strcpy (greet->name, siaHandle->name);
3279
3280     greet->password = malloc(strlen(siaHandle->password) + 1);
3281     strcpy (greet->password, siaHandle->password);
3282     
3283
3284 }
3285
3286 static void KillGreeter( void )
3287 {
3288     if (sia_greeter_pid)
3289       AbortClient(sia_greeter_pid);
3290     sia_greeter_pid = 0;
3291 }
3292 #endif /* SIA */