Don't use fstat for readable pipe chars in dtexec.
[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 #elif defined(CSRG_BASED)
1656             failsafeArgv[i++] = "/usr/local/bin/xterm";
1657 #else
1658             failsafeArgv[i++] = "/usr/bin/X11/xterm";
1659 #endif
1660             failsafeArgv[i++] = "-geometry";
1661             failsafeArgv[i++] = "80x10";
1662             failsafeArgv[i++] = "-bg";
1663             failsafeArgv[i++] = "white";
1664             failsafeArgv[i++] = "-fg";
1665             failsafeArgv[i++] = "black";
1666 #ifdef _AIX
1667             /* aixterm requires -lang option. */
1668             failsafeArgv[i++] = "-lang";
1669             failsafeArgv[i++] = lang;
1670 #else /* _AIX */
1671             failsafeArgv[i++] = "-fn";
1672
1673             if (font == NULL) font = "fixed";
1674             failsafeArgv[i++] = font;
1675 #endif /* _AIX */
1676
1677             failsafeArgv[i++] = "-e";
1678             failsafeArgv[i++] = "/bin/passwd";
1679 #if defined (__apollo) || defined(__PASSWD_ETC)
1680             failsafeArgv[i++] = "-n";
1681 #endif
1682             failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1683         }
1684         else {
1685             failsafeArgv[i++] = d->failsafeClient;
1686 #ifdef sun 
1687             failsafeArgv[i++] = "-C";
1688 #endif
1689             failsafeArgv[i++] = "-ls";
1690
1691             if (font != NULL) {
1692                 failsafeArgv[i++] = "-fn";
1693                 failsafeArgv[i++] = font;
1694             }
1695         }
1696
1697         failsafeArgv[i] = 0;
1698         Debug ("Executing failsafe session\n", failsafeArgv[0]);
1699         execute (failsafeArgv, verify->userEnviron);
1700         exit (1);
1701     case -1:
1702         Debug ("StartSession(): fork failed\n");
1703         LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1704                 d->name);
1705         return 0;
1706     default:
1707         Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1708         *pidp = pid;
1709
1710         return 1;
1711     }
1712 }
1713
1714 static jmp_buf  tenaciousClient;
1715
1716 static SIGVAL
1717 waitAbort( int arg )
1718 {
1719         longjmp (tenaciousClient, 1);
1720 }
1721
1722 #if defined(SYSV) || defined(SVR4)
1723 # include       <ctype.h>
1724 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1725 #endif /* SYSV */
1726
1727 static int 
1728 AbortClient( int pid )
1729 {
1730     int sig = SIGTERM;
1731 #ifdef __STDC__
1732     volatile int        i;
1733 #else
1734     int i;
1735 #endif
1736     int retId;
1737     for (i = 0; i < 4; i++) {
1738         if (killpg (pid, sig) == -1) {
1739             switch (errno) {
1740             case EPERM:
1741                 LogError(ReadCatalog(
1742                         MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1743             case EINVAL:
1744             case ESRCH:
1745                 return;
1746             }
1747         }
1748         if (!setjmp (tenaciousClient)) {
1749             (void) signal (SIGALRM, waitAbort);
1750             (void) alarm ((unsigned) 10);
1751             retId = wait ((waitType *) 0);
1752             (void) alarm ((unsigned) 0);
1753             (void) signal (SIGALRM, SIG_DFL);
1754             if (retId == pid)
1755                 break;
1756         } else
1757             signal (SIGALRM, SIG_DFL);
1758         sig = SIGKILL;
1759     }
1760 }
1761
1762 int 
1763 source( struct verify_info *verify, char *file )
1764 {
1765     char        *args[2];
1766     int         pid;
1767     waitType    result;
1768
1769     if (file && file[0]) {
1770         Debug ("Source(): %s\n", file);
1771         switch (pid = fork ()) {
1772         case 0:
1773             CleanUpChild ();
1774             args[0] = file;
1775             args[1] = NULL;
1776             execute (args, verify->systemEnviron);
1777             LogError(ReadCatalog(
1778                 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1779             exit (1);
1780         case -1:
1781             Debug ("Source(): fork failed\n");
1782             LogError(ReadCatalog(
1783                 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1784             return 1;
1785             break;
1786         default:
1787             while (wait (&result) != pid)
1788                     ;
1789             break;
1790         }
1791         return waitVal (result);
1792     }
1793     return 0;
1794 }
1795
1796 int 
1797 execute(char **argv, char **environ )
1798 {
1799
1800     /*
1801      *  make stdout follow stderr to the log file...
1802      */
1803
1804     dup2 (2,1);
1805     
1806     session_execve (argv[0], argv, environ);
1807
1808     /*
1809      * In case this is a shell script which hasn't been made executable
1810      * (or this is a SYSV box), do a reasonable thing...
1811      */
1812
1813 #ifdef _AIX
1814     /* errno is EACCES if not executable */
1815     if (errno == ENOEXEC || errno == EACCES) {
1816 #else /* _AIX */
1817     if (errno == ENOEXEC) {
1818 #endif /* _AIX */
1819         char    program[1024], *e, *p, *optarg;
1820         FILE    *f;
1821         char    **newargv, **av;
1822         int     argc;
1823
1824         /*
1825          * emulate BSD kernel behaviour -- read
1826          * the first line; check if it starts
1827          * with "#!", in which case it uses
1828          * the rest of the line as the name of
1829          * program to run.  Else use "/bin/sh".
1830          */
1831         f = fopen (argv[0], "r");
1832         if (!f)
1833             return;
1834         if (fgets (program, sizeof (program) - 1, f) == NULL)
1835         {
1836             fclose (f);
1837             return;
1838         }
1839         fclose (f);
1840         e = program + strlen (program) - 1;
1841         if (*e == '\n')
1842             *e = '\0';
1843         if (!strncmp (program, "#!", 2)) {
1844             p = program + 2;
1845             while (*p && isspace (*p))
1846                 ++p;
1847             optarg = p;
1848             while (*optarg && !isspace (*optarg))
1849                 ++optarg;
1850             if (*optarg) {
1851                 *optarg = '\0';
1852                 do
1853                     ++optarg;
1854                 while (*optarg && isspace (*optarg));
1855             } else
1856                 optarg = 0;
1857         } else {
1858             p = "/bin/sh";
1859             optarg = 0;
1860         }
1861         Debug ("Shell script execution: %s (optarg %s)\n",
1862                 p, optarg ? optarg : "(null)");
1863         for (av = argv, argc = 0; *av; av++, argc++)
1864                 ;
1865         newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1866         if (!newargv)
1867             return -1;
1868         av = newargv;
1869         *av++ = p;
1870         if (optarg)
1871             *av++ = optarg;
1872         while (*av++ = *argv++)
1873             ;
1874         session_execve (newargv[0], newargv, environ);
1875     }
1876 }
1877
1878
1879
1880
1881 /*****************************************************************************
1882 *    RunGreeter
1883 *    
1884 *    Invoke the Greeter process and wait for completion. If the user was 
1885 *    successfully verified, return to the calling process. If the user
1886 *    selected a restart or abort option, or there was an error invoking the
1887 *    Greeter, exit this entire process with appropriate status.
1888 *
1889 *****************************************************************************/
1890
1891 #define MSGSIZE 512
1892
1893 extern int session_set; 
1894 extern char *progName;  /* Global argv[0]; dtlogin name and path */
1895
1896 int         response[2], request[2];
1897
1898 /* Fixes problem with dtlogin signal handling */
1899 static int greeterPid = 0;
1900 static struct display *greeter_d = NULL;
1901
1902 static SIGVAL
1903 catchHUP(int arg)
1904 {
1905     Debug("Caught SIGHUP\n");
1906     if (greeterPid) 
1907     {
1908         Debug("Killing greeter process:  %d\n", greeterPid);
1909         kill(greeterPid, SIGHUP);
1910     }
1911     if (greeter_d)
1912       SessionExit(greeter_d, REMANAGE_DISPLAY);
1913     else
1914       exit(REMANAGE_DISPLAY);
1915 }
1916
1917 static void 
1918 RunGreeter( struct display *d, struct greet_info *greet,
1919             struct verify_info *verify )
1920 {
1921
1922     int       pid;
1923     waitType    status;
1924     
1925     int         rbytes;
1926     static char msg[MSGSIZE];
1927     char        *p;
1928     char        **env;
1929     char        *path;
1930     struct greet_state state;
1931     int         notify_dt;
1932
1933 #ifdef __PASSWD_ETC
1934 #  ifndef U_NAMELEN
1935 #    define U_NAMELEN   sizeof(rgy_$name_t)
1936 #  endif
1937
1938     int i;
1939     static char name_short[U_NAMELEN];
1940 #endif
1941
1942 #ifdef SIA
1943
1944     int argc = 1;
1945     char *argv[] = { "dtlogin", 0 };
1946     char *hostName = NULL;
1947     char *loginName = NULL;
1948     int siaStatus = -1;
1949
1950     /*
1951      * Initialize SIA
1952      */
1953     
1954     if (d->serverPid == -1)
1955       hostName = d->name;
1956
1957     siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName, 
1958                               loginName, d->name, 1, NULL);
1959     if (siaStatus != SIASUCCESS)
1960       {
1961       Debug("sia_ses_init failure status %d\n", siaStatus);
1962       exit(1);
1963       }
1964
1965 #endif
1966
1967     greeterPid = 0;
1968     if (!setjmp (abortSession)) {
1969         signal(SIGTERM, catchTerm);
1970
1971         /*
1972          * We've changed dtlogin to pass HUP's down to the children
1973          * so ignore any HUP's once the client has started.
1974          */
1975         greeter_d = d;
1976         signal(SIGHUP, catchHUP);
1977
1978         /*
1979          *  set up communication pipes...
1980          */
1981          
1982         pipe(response);
1983         pipe(request);
1984         rbytes = 0;
1985
1986
1987         switch (greeterPid = fork ()) {
1988         case 0:
1989
1990             /*
1991              *  pass some information in the environment...
1992              */
1993                    
1994             env = 0;
1995             sprintf(msg,"%d", d->grabServer);
1996             env = setEnv(env, GRABSERVER,  msg);
1997         
1998             sprintf(msg,"%d", d->grabTimeout);
1999             env = setEnv(env, GRABTIMEOUT, msg);
2000
2001
2002             if (timeZone && strlen(timeZone) > 0 )
2003                 env = setEnv(env, "TZ", timeZone);
2004
2005             if (errorLogFile && errorLogFile[0])
2006                 env = setEnv(env, ERRORLOG,  errorLogFile);
2007
2008             if (d->authFile)
2009                 env = setEnv(env, "XAUTHORITY", d->authFile);
2010
2011             if (d->dtlite)
2012                 env = setEnv(env, DTLITE,  "True");
2013
2014             if (d->session)  
2015                 env = setEnv(env, SESSION,  d->session);
2016
2017             if(session_set)
2018                 env = setEnv(env, SESSION_SET, "True");
2019
2020             if (d->pmSearchPath)
2021                 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
2022
2023             if (d->bmSearchPath)
2024                 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
2025
2026 #if defined (__KERBEROS) || defined (__AFS)
2027             if (d->verifyName) {
2028                 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2029                      (strcmp(d->verifyName, VN_KRB) == 0)    ) {
2030                      
2031                     env = setEnv(env, VERIFYNAME, d->verifyName );
2032                 }
2033                 else {
2034                     LogError(ReadCatalog(
2035                         MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2036                         d->verifyName);
2037                     d->verifyName = NULL;
2038                 }
2039             }
2040 #endif
2041                         
2042             if((path = getenv("NLSPATH")) != NULL)
2043                 env = setEnv(env, "NLSPATH", path);
2044 #ifdef __hp_osf
2045             env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2046 #endif
2047
2048             
2049             /*
2050              *  ping remote displays...
2051              *
2052              */
2053
2054             if (d->displayType.location == Local) {
2055                 GettyRunning(d); /* refresh gettyState */
2056                 if (d->gettyState != DM_GETTY_USER)
2057                     env = setEnv(env, LOCATION, "local");
2058             }
2059             else {
2060                 sprintf(msg,"%d", d->pingInterval);
2061                 env = setEnv(env, PINGINTERVAL,  msg);
2062         
2063                 sprintf(msg,"%d", d->pingTimeout);
2064                 env = setEnv(env, PINGTIMEOUT, msg);
2065             }
2066
2067
2068             if ( d->langList && strlen(d->langList) > 0 )
2069                 env = setEnv(env, LANGLIST,  d->langList);
2070 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2071             else if (languageList && strlen(languageList) > 0 )
2072                 env = setEnv(env, LANGLIST, languageList);
2073 #endif /* ENABLE_DYNAMIC_LANGLIST */
2074
2075             {
2076                 char *language = NULL;
2077
2078 #if defined (ENABLE_DYNAMIC_LANGLIST)
2079                 language = d->language;
2080 #endif /* ENABLE_DYNAMIC_LANGLIST */
2081
2082                 if ( d->language && strlen(d->language) > 0 )
2083                   env = setLang(d, env, language);
2084             }
2085
2086             if((path = getenv("XKEYSYMDB")) != NULL)
2087                 env = setEnv(env, "XKEYSYMDB", path);
2088
2089 #ifdef sun
2090             if((path = getenv("OPENWINHOME")) != NULL)
2091                 env = setEnv(env, "OPENWINHOME", path);
2092 #endif
2093
2094 #ifdef __apollo
2095             /*
2096              *  set environment for Domain machines...
2097              */
2098             env = setEnv(env, "ENVIRONMENT", "bsd");
2099             env = setEnv(env, "SYSTYPE", "bsd4.3");
2100 #endif
2101                 
2102
2103             Debug ("Greeter environment:\n");
2104             printEnv(env);
2105             Debug ("End of Greeter environment:\n");
2106
2107            /*
2108             * Writing to file descriptor 1 goes to response pipe instead.
2109             */
2110             close(1);
2111             dup(response[1]);
2112             close(response[0]);
2113             close(response[1]);
2114
2115            /*
2116             * Reading from file descriptor 0 reads from request pipe instead.
2117             */
2118             close(0);
2119             dup(request[0]);
2120             close(request[0]);
2121             close(request[1]);
2122
2123             CleanUpChild ();
2124
2125             /*
2126              * figure out path to dtgreet...
2127              */
2128
2129             strcpy(msg, progName);
2130     
2131             if ((p = (char *) strrchr(msg, '/')) == NULL)
2132                 strcpy(msg,"./");
2133             else
2134                 *(++p) = NULL;
2135
2136             strcat(msg,"dtgreet");
2137
2138             execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2139             LogError(ReadCatalog(
2140                 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2141                  msg, d->name);
2142             exit (NOTIFY_ABORT_DISPLAY);
2143
2144         case -1:
2145             Debug ("Fork of Greeter failed.\n");
2146             LogError(ReadCatalog(
2147                 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2148             close(request[0]);
2149             close(request[1]);
2150             close(response[0]);
2151             close(response[1]);
2152             exit (UNMANAGE_DISPLAY);
2153
2154         default:
2155             Debug ("Greeter started\n");
2156
2157             close(response[1]); /* Close write end of response pipe */
2158             close(request[0]); /* Close read end of request pipe */
2159
2160
2161             /*
2162              * Retrieve information from greeter and authenticate.
2163              */
2164             globalDisplayName = d->name;
2165             state.id = GREET_STATE_ENTER;
2166             state.waitForResponse = FALSE;
2167 #ifdef SIA
2168            
2169             /*
2170              * atexit() registers this function to be called if exit() is
2171              * called.  This is needed because in enhanced security mode, SIA
2172              * may call exit() whn the user fails to enter or change a
2173              * password.
2174              */
2175             sia_greeter_pid = greeterPid;
2176             if (!sia_exit_proc_reg)
2177                 {
2178                 atexit(KillGreeter);
2179                 sia_exit_proc_reg = TRUE;
2180                 }
2181   
2182             siaGreeterInfo.d = d;
2183             siaGreeterInfo.greet = greet;
2184             siaGreeterInfo.verify = verify;
2185             siaGreeterInfo.state = &state;
2186             siaGreeterInfo.status = TRUE;
2187   
2188             siaStatus =  -1;
2189             while(siaStatus != SIASUCCESS)
2190                 {
2191                 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2192                     {
2193                     Debug ("RunGreeter: before sia_ses_authent\n");
2194                     dt_in_sia_ses_authent = True;
2195                     siaStatus = sia_ses_authent(SiaManageGreeter, NULL, 
2196                                                 siaHandle);
2197                     dt_in_sia_ses_authent = False;
2198                     Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2199                                 siaStatus);
2200                     if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2201                         {
2202                         state.id = GREET_STATE_ERRORMESSAGE;
2203                         state.vf = VF_INVALID;
2204                         ManageGreeter(d, greet, verify, &state);
2205                         }
2206                     if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2207                         break;
2208                     }
2209                 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2210                     {
2211                     sia_ses_release(&siaHandle);
2212                     break;
2213                     }
2214   
2215                 Debug("RunGreeter: before sia_ses_estab\n");
2216                 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2217                 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2218                                 siaStatus);
2219   
2220                 if (!siaGreeterInfo.status)
2221                     break;
2222   
2223                 if (siaStatus == SIASUCCESS)
2224                     {
2225                     Debug("RunGreeter: before sia_ses_launch\n");
2226                     siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2227                     Debug("RunGreeter: after sia_ses_launch status = %d\n",
2228                                 siaStatus);
2229                     }
2230                 if (!siaGreeterInfo.status)
2231                     break;
2232   
2233                 if (siaStatus != SIASUCCESS)
2234                     {
2235                     Debug("RunGreeter: sia_ses_launch failure\n");
2236                     /* establish & launch failures do a release */
2237                     siaHandle = NULL;
2238                     siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName, 
2239                                                 loginName, d->name, 1, NULL);
2240                     if (siaStatus != SIASUCCESS)
2241                         {
2242                         Debug("sia_ses_init failure status %d\n", siaStatus);
2243                         exit(RESERVER_DISPLAY);
2244                         }
2245                     }
2246                 }
2247             /*
2248              * sia_ses_launch() wil probably seteuid to that of the
2249              * user, but we don't want that now.
2250              */
2251             seteuid(0);
2252             /*
2253              * extract necessary info from SIA context struct
2254              */
2255             if (siaHandle)
2256                 {
2257                 if (siaStatus == SIASUCCESS)
2258                     CopySiaInfo(siaHandle, greet);
2259                 sia_ses_release(&siaHandle);
2260                 }
2261             state.id = GREET_STATE_TERMINATEGREET;
2262             if (siaGreeterInfo.status)
2263                 {
2264                 while (ManageGreeter(d, greet, verify, &state))
2265                   ;
2266                 }
2267             sia_greeter_pid = 0;
2268 #else
2269             while (ManageGreeter(d, greet, verify, &state))
2270               ;
2271 #endif /* SIA */
2272
2273             /*
2274              * Wait for Greeter to end...
2275              */
2276             for (;;) {
2277                 pid = wait (&status);
2278                 if (pid == greeterPid)
2279                     break;
2280             }
2281
2282
2283             /*
2284              *  Greeter exited. Check return code...
2285              */
2286              
2287             Debug("Greeter return status; exit = %d, signal = %d\n", 
2288                    waitCode(status), waitSig(status));
2289
2290
2291             /*
2292              * remove authorization file if used...
2293              */
2294      
2295             if (d->authorizations && d->authFile &&
2296                 waitVal(status) != NOTIFY_LANG_CHANGE
2297 #ifdef BLS
2298                 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2299 #endif
2300                ) {
2301
2302 /***
2303                 Debug ("Done with authorization file %s, removing\n",
2304                         d->authFile);
2305                 (void) unlink (d->authFile);
2306 ***/
2307             }
2308
2309
2310                 if(waitVal(status) > NOTIFY_ALT_DTS) 
2311                       d->sessionType = waitVal(status);
2312
2313
2314             switch (waitVal(status)) {
2315             case NOTIFY_FAILSAFE:
2316                 greet->string = "failsafe";
2317                 break;
2318             case NOTIFY_PASSWD_EXPIRED:
2319                 greet->string = "password";
2320                 break;
2321             case NOTIFY_DTLITE:
2322             case NOTIFY_DT:
2323             case NOTIFY_OK:
2324             case NOTIFY_LAST_DT:
2325                 d->sessionType = waitVal(status);
2326                 break;
2327             default:
2328                 break;
2329             }
2330
2331           Debug("waitVal - status is  %d\n", waitVal(status));
2332            if(waitVal(status) > NOTIFY_ALT_DTS)
2333                 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2334             else
2335                 notify_dt = waitVal(status);
2336
2337             switch (notify_dt) {
2338             case NOTIFY_FAILSAFE:
2339             case NOTIFY_PASSWD_EXPIRED:
2340             case NOTIFY_DTLITE:
2341             case NOTIFY_DT:
2342             case NOTIFY_OK:
2343             case NOTIFY_LAST_DT:
2344             case NOTIFY_ALT_DTS:
2345
2346                if (NULL == greet->name) return;
2347
2348                /*
2349                 *  greet->name, greet->password set in ManageGreeter().
2350                 */
2351                 Debug("Greeter returned name '%s'\n", greet->name);
2352
2353 #ifdef __PASSWD_ETC
2354                 greet->name_full = greet->name;
2355                            /* get just person name out of full SID */
2356                 i = 0;
2357                 while (i < sizeof(rgy_$name_t) 
2358                      && greet->name_full[i] != '.'
2359                      && greet->name_full[i] != '\0') {
2360                      name_short[i] = greet->name_full[i];
2361                      i++;
2362                 }
2363                 name_short[i] = '\0';
2364                 greet->name = name_short;
2365 #endif
2366                     
2367 #ifdef __AFS
2368                /*
2369                 * groups[] set in Authenticate().
2370                 */
2371                 if ( IsVerifyName(VN_AFS) ) {
2372                   verify->groups[0] = groups[0];
2373                   verify->groups[1] = groups[1];
2374                   Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2375                   Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2376                 }
2377 #endif
2378                     
2379 #ifdef BLS
2380                /*
2381                 * sensitivityLevel set in BLS_Verify()
2382                 */
2383                 greet->b1security = sensitivityLevel;
2384 #endif
2385
2386                 Verify(d, greet, verify);
2387                 return;
2388
2389             case NOTIFY_ABORT:
2390                 Debug ("Greeter Xlib error or SIGTERM\n");
2391                 SessionExit(d, OPENFAILED_DISPLAY);
2392
2393             case NOTIFY_RESTART:
2394                 Debug ("Greeter requested RESTART_DISPLAY\n");
2395                 SessionExit(d, RESERVER_DISPLAY);
2396
2397             case NOTIFY_ABORT_DISPLAY:
2398                 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2399                 SessionExit(d, UNMANAGE_DISPLAY);
2400
2401             case NOTIFY_NO_WINDOWS:
2402                 Debug ("Greeter requested NO_WINDOWS mode\n");
2403                 if (d->serverPid >= 2)
2404                     /*
2405                      *  Don't do a SessionExit() here since that causes
2406                      *  the X-server to be reset. We know we are going to
2407                      *  terminate it anyway, so just go do that...
2408                      */
2409                     exit(SUSPEND_DISPLAY);
2410                 else
2411                     return;
2412
2413             case NOTIFY_LANG_CHANGE:
2414                 Debug ("Greeter requested LANG_CHANGE\n");
2415
2416                /*
2417                 * copy requested language into display struct "d". Note,
2418                 * this only happens in this child's copy of "d", not in
2419                 * the master struct. When the user logs out, the
2420                 * resource-specified language (if any) will reactivate.
2421                 */
2422                 Debug("Greeter returned language '%s'\n", d->language);
2423
2424                 if (strcmp(d->language, "default") == 0) {
2425                     int len = strlen(defaultLanguage) + 1;
2426                     d->language = (d->language == NULL  ?
2427                                    malloc(len) : realloc (d->language, len));
2428                     strcpy(d->language, defaultLanguage);
2429                 }
2430                 return;
2431 #ifdef  BLS
2432             case NOTIFY_BAD_SECLEVEL:
2433                 return;
2434 #endif
2435             case waitCompose (SIGTERM,0,0):
2436                 Debug ("Greeter exited on SIGTERM\n");
2437                 SessionExit(d, OPENFAILED_DISPLAY);
2438                 
2439             default:
2440                 Debug ("Greeter returned unknown status %d\n", 
2441                         waitVal(status));
2442                 SessionExit(d, REMANAGE_DISPLAY);
2443             }
2444         }
2445         signal(SIGHUP, SIG_DFL);
2446     }
2447     else {
2448         AbortClient(greeterPid);
2449         SessionExit(d, UNMANAGE_DISPLAY);
2450     }
2451 }
2452
2453 /*****************************************************************************
2454 * ManageGreeter
2455  
2456   State transitions
2457  
2458   enter -> ENTER: 
2459     This is the entry into greeter state processing. Allocate and initialize
2460     state structure.
2461
2462   ENTER -> LOGIN:
2463     Display the login screen. Upon display, the login screen can be 'reset'. If
2464     reset is true, the username and password fields are cleared and the focus
2465     is set to the username field. If reset is false, the username and password
2466     field is untouched and the focus is set to the password field.
2467
2468   LOGIN -> AUTHENTICATE:
2469     Authenticate the username entered on login screen. 
2470
2471   AUTHENTICATE -> TERMINATEGREET:
2472     User passed authentication so terminate the greeter.
2473
2474   AUTHENTICATE -> EXPASSWORD: 
2475     User passed authentication, but the their password has expired.
2476     Display old password message. This message allows the user to 
2477     change their password by starting a getty and running passwd(1).  
2478
2479   AUTHENTICATE -> BAD_HOSTNAME:
2480     User passed authentication, but the their hostname is empty.
2481     Display a dialog that allows the user to run a getty to fix the
2482     problem, or start the desktop anyway.
2483
2484   AUTHENTICATE -> ERRORMESSAGE:
2485     User failed authentication, so display error message. 
2486
2487   AUTHENTICATE -> LOGIN
2488     User failed authentication, but did not enter a password. Instead
2489     of displaying an error message, redisplay the login screen with
2490     the focus set to the password field. If the user authenticates again
2491     without the password field set, display an error. This allows a user
2492     to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2493
2494   EXIT -> exit
2495     Free state structure and return false to stop state transitions.
2496
2497   ERRORMESSAGE -> LOGIN
2498     Display error message base on return code from last authentication
2499     attempt. Redisplay login screen with reset set to true.
2500
2501   (state) -> LANG -> (state)
2502     User has chosen a new language. Transition to LANG state to save off
2503     the new language, and transition back to original state. 
2504   
2505 *****************************************************************************/
2506
2507 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2508
2509 static int
2510 ManageGreeter( struct display *d, struct greet_info *greet,
2511             struct verify_info *verify, struct greet_state *state )
2512 {
2513   struct {
2514     int id;
2515     char *def;
2516   } msg;
2517
2518   if (state->waitForResponse)
2519   {
2520     if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2521     {
2522      /*
2523       * Dtgreet has terminated. 
2524       */
2525       state->id = GREET_STATE_EXIT;
2526       state->waitForResponse = FALSE;
2527       return(TRUE);
2528     }
2529
2530     if (state->request->opcode != state->response->opcode)
2531     {
2532      /*
2533       * An unrequested event arrived. See if it's one we
2534       * are expecting.
2535       */
2536       switch(state->response->opcode)
2537       {
2538         case REQUEST_OP_LANG:
2539           {
2540            /*
2541             * User has changed language. Recursively handle this state
2542             * and return to current state.
2543             */
2544             struct greet_state lang_state;
2545
2546             lang_state = *state;
2547             lang_state.id = GREET_STATE_LANG;
2548             lang_state.waitForResponse = FALSE;
2549             ManageGreeter(d, greet, verify, &lang_state);
2550             Debug("Response opcode REQUEST_OP_LANG\n");
2551             return(TRUE);
2552           }
2553           break;
2554
2555         case REQUEST_OP_CLEAR:
2556           {
2557            /*
2558             * User has requested the screen be cleared.
2559             */
2560             state->id = GREET_STATE_USERNAME;
2561             state->waitForResponse = TRUE;
2562             Debug("Response opcode REQUEST_OP_CLEAR\n");
2563           }
2564           break;
2565     
2566         default:
2567           Debug("Response opcode UNEXPECTED RESPONSE!\n");
2568 #ifndef SIA
2569           return(TRUE);
2570 #endif
2571           break;
2572       }
2573     }
2574     else
2575     {
2576      /*
2577       * Got the response we were expecting.
2578       */
2579       state->waitForResponse = FALSE;
2580     }
2581   }
2582
2583   switch(state->id)
2584   {
2585     case GREET_STATE_ENTER:
2586       {
2587        /*
2588         * Enter - initialize state
2589         */
2590         Debug("GREET_STATE_ENTER\n");
2591
2592         state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2593         state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2594         state->authenticated = FALSE;
2595         state->msg = NULL;
2596
2597         state->id = GREET_STATE_USERNAME;
2598       }
2599       break;
2600
2601     case GREET_STATE_USERNAME:
2602       {
2603        /*
2604         * Get user name
2605         */
2606         RequestChallenge *r;
2607
2608         Debug("GREET_STATE_USERNAME\n");
2609
2610         Authenticate(d, NULL, NULL, NULL);
2611
2612         SETMC(msg, LOGIN_LABEL);
2613
2614         r = (RequestChallenge *)state->request;
2615         r->hdr.opcode = REQUEST_OP_CHALLENGE;
2616         r->hdr.reserved = 0;
2617         r->bEcho = TRUE;
2618         r->idMC = msg.id;
2619         r->hdr.length = sizeof(*r);
2620
2621         r->offChallenge = sizeof(*r);
2622         strcpy(((char *)r) + r->offChallenge, msg.def);
2623         r->hdr.length += strlen(msg.def) + 1;
2624
2625         if (greet->name)
2626         {
2627           r->offUserNameSeed = r->hdr.length;
2628           strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2629           r->hdr.length += strlen(greet->name) + 1;
2630           Debug("Greet name:  %s\n", greet->name);
2631         }
2632         else
2633         {
2634           r->offUserNameSeed = 0;
2635         }
2636
2637         if (greet->name)
2638         {
2639           free(greet->name); greet->name = NULL;
2640         }
2641         if (greet->password)
2642         {
2643           free(greet->password); greet->password = NULL;
2644         }
2645
2646         TellGreeter((RequestHeader *)r);
2647         state->waitForResponse = TRUE;
2648
2649         state->id = GREET_STATE_AUTHENTICATE;
2650       }
2651       break;
2652
2653     case GREET_STATE_CHALLENGE:
2654       {
2655        /*
2656         * Get user name
2657         */
2658         RequestChallenge *r;
2659
2660         Debug("GREET_STATE_CHALLENGE\n");
2661
2662         if (greet->password)
2663         {
2664           free(greet->password); greet->password = NULL;
2665         }
2666
2667         SETMC(msg, PASSWD_LABEL);
2668
2669         r = (RequestChallenge *)state->request;
2670         r->hdr.opcode = REQUEST_OP_CHALLENGE;
2671         r->hdr.reserved = 0;
2672         r->bEcho = FALSE;
2673         r->idMC = msg.id;
2674         r->offUserNameSeed = 0;
2675         r->offChallenge = sizeof(*r);
2676         strcpy(((char *)r) + r->offChallenge, msg.def);
2677         r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2678
2679         TellGreeter((RequestHeader *)r);
2680         state->waitForResponse = TRUE;
2681
2682         state->id = GREET_STATE_AUTHENTICATE;
2683       }
2684       break;
2685
2686     case GREET_STATE_AUTHENTICATE:
2687       {
2688        /*
2689         * Attempt to authenticate.
2690         */
2691         ResponseChallenge *r;
2692    
2693         Debug("GREET_STATE_AUTHENTICATE\n"); 
2694
2695         r = (ResponseChallenge *)state->response;
2696      
2697         if (greet->name == NULL)
2698         {
2699           greet->name = strdup(((char *)r) + r->offResponse);
2700           if (strlen(greet->name) == 0)
2701           {
2702             state->id = GREET_STATE_USERNAME;
2703             break;
2704           }
2705         }
2706         else 
2707         { 
2708           greet->password = strdup(((char *)r) + r->offResponse);
2709         }
2710
2711         if (state->msg)
2712         {
2713           free(state->msg);
2714           state->msg = NULL;
2715         }
2716
2717        /*
2718         * Attempt to authenticate user. 'username' should be a 
2719         * non-empty string. 'password' may be an empty string.
2720         */
2721         state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2722
2723         if (state->vf == VF_OK || 
2724             state->vf == VF_PASSWD_AGED || 
2725             state->vf == VF_BAD_HOSTNAME)
2726         {
2727           state->authenticated = TRUE;
2728         }
2729
2730        /*
2731         * General transitions.
2732         */
2733         switch (state->vf)
2734         {
2735           case VF_OK:           state->id = GREET_STATE_TERMINATEGREET; break; 
2736           case VF_PASSWD_AGED:  state->id = GREET_STATE_EXPASSWORD; break; 
2737           case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break; 
2738           case VF_CHALLENGE:    state->id = GREET_STATE_CHALLENGE; break; 
2739           default:              state->id = GREET_STATE_ERRORMESSAGE; break; 
2740         }
2741       }
2742       break;
2743
2744     case GREET_STATE_EXIT: 
2745       {
2746        /*
2747         * Free resources and leave.
2748         */
2749         Debug("GREET_STATE_EXIT\n");
2750
2751         if (state->msg)
2752         {
2753           free(state->msg);
2754         }
2755  
2756         if (!state->authenticated)
2757         {
2758           if (greet->name)
2759           {
2760             free(greet->name); greet->name = NULL;
2761           }
2762           if (greet->password)
2763           {
2764             free(greet->password); greet->password = NULL;
2765           }
2766         }
2767
2768         free(state->request);
2769         free(state->response);
2770         return(FALSE);
2771       }
2772       break;
2773
2774     case GREET_STATE_ERRORMESSAGE:
2775       {
2776        /* 
2777         * Display error message.
2778         */
2779         RequestMessage *r;
2780
2781         Debug("GREET_STATE_ERRORMESSAGE\n");
2782
2783         r = (RequestMessage *)state->request;
2784
2785         switch(state->vf)
2786         {
2787           case VF_INVALID:       SETMC(msg, LOGIN); break;
2788           case VF_HOME:          SETMC(msg, HOME); break;
2789           case VF_MAX_USERS:     SETMC(msg, MAX_USERS); break;
2790           case VF_BAD_UID:       SETMC(msg, BAD_UID); break;
2791           case VF_BAD_GID:       SETMC(msg, BAD_GID); break;
2792           case VF_BAD_AID:       SETMC(msg, BAD_AID); break;
2793           case VF_BAD_AFLAG:     SETMC(msg, BAD_AFLAG); break;
2794           case VF_NO_LOGIN:      SETMC(msg, NO_LOGIN); break;
2795 #ifdef BLS
2796           case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2797 #endif
2798           case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2799           default: msg.id=0; msg.def=""; break;
2800         }
2801
2802         r->hdr.opcode = REQUEST_OP_MESSAGE;
2803         r->hdr.reserved = 0;
2804         r->idMC = msg.id;
2805         r->offMessage = sizeof(*r);
2806         strcpy(((char *)r) + r->offMessage, msg.def);
2807         r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2808
2809         TellGreeter((RequestHeader *)r);
2810         state->waitForResponse = TRUE;
2811
2812         state->id = GREET_STATE_USERNAME;
2813       }
2814       break;
2815
2816     case GREET_STATE_LANG:
2817       {
2818        /*
2819         * User selected new language.
2820         */
2821         ResponseLang *r;
2822         char *lang;
2823         int len;
2824
2825         Debug("GREET_STATE_LANG\n");
2826
2827         r = (ResponseLang *)state->response;
2828         lang = ((char *)r) + r->offLang;
2829         len = strlen(lang) + 1;
2830
2831         d->language = (d->language == NULL ?
2832                        malloc(len) : realloc(d->language, len));
2833         strcpy(d->language, lang);
2834         Debug("Language returned:  %s\n", d->language);
2835       }
2836       break;
2837
2838     case GREET_STATE_TERMINATEGREET:
2839       {
2840        /*
2841         * Terminate dtgreet.
2842         */
2843         RequestExit *r;
2844
2845         Debug("GREET_STATE_TERMINATEGREET\n");
2846
2847         r = (RequestExit *)state->request;
2848
2849         r->hdr.opcode = REQUEST_OP_EXIT;
2850         r->hdr.reserved = 0;
2851         r->hdr.length = sizeof(*r);
2852
2853         TellGreeter((RequestHeader *)r);
2854         state->waitForResponse = TRUE;
2855
2856         state->id = GREET_STATE_EXIT;
2857       }
2858       break;
2859
2860     case GREET_STATE_EXPASSWORD:
2861       {
2862        /*
2863         * Display password expired message.
2864         */
2865         RequestExpassword *r;
2866
2867         Debug("GREET_STATE_EXPASSWORD\n");
2868
2869         r = (RequestExpassword *)state->request;
2870
2871         r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2872         r->hdr.reserved = 0;
2873         r->hdr.length = sizeof(*r);
2874
2875         TellGreeter((RequestHeader *)r);
2876         state->waitForResponse = TRUE;
2877
2878         state->id = GREET_STATE_USERNAME;
2879       }
2880       break;
2881
2882     case GREET_STATE_BAD_HOSTNAME:
2883       {
2884        /*
2885         * Display password expired message.
2886         */
2887         RequestHostname *r;
2888
2889         Debug("GREET_STATE_BAD_HOSTNAME\n");
2890
2891         r = (RequestHostname *)state->request;
2892
2893         r->hdr.opcode = REQUEST_OP_HOSTNAME;
2894         r->hdr.reserved = 0;
2895         r->hdr.length = sizeof(*r);
2896
2897         TellGreeter((RequestHeader *)r);
2898         state->waitForResponse = TRUE;
2899
2900         state->id = GREET_STATE_USERNAME;
2901       }
2902       break;
2903
2904 #ifdef SIA
2905     case GREET_STATE_FORM:
2906       {
2907        /*
2908         * Get arbitrary number of answers.
2909         */
2910
2911         Debug("GREET_STATE_FORM\n");
2912  
2913         AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2914  
2915         state->waitForResponse = FALSE;
2916         state->id = GREET_STATE_USERNAME;
2917       }
2918       break;
2919 #endif /* SIA */
2920   }
2921
2922   return(TRUE);
2923 }
2924
2925
2926 static void
2927 TellGreeter(
2928   RequestHeader *phdr)
2929 {
2930   write(request[1], phdr, phdr->length);
2931 }
2932
2933 static int
2934 AskGreeter(
2935   RequestHeader *preqhdr,
2936   char *buf,
2937   int blen)
2938 {
2939   int count;
2940   int remainder;
2941   ResponseHeader *phdr = (ResponseHeader *)buf;
2942
2943   if (preqhdr) TellGreeter(preqhdr);
2944
2945   phdr->opcode = REQUEST_OP_NONE;
2946
2947   count = read(response[0], buf, sizeof(*phdr));
2948
2949   if (count == sizeof(*phdr))
2950   {
2951    /*
2952     * Calculate amount of data after header.
2953     */
2954     remainder =  phdr->length - sizeof(*phdr);
2955     if (remainder > 0)
2956     {
2957      /*
2958       * Read remainder of response.
2959       */
2960       count += read(response[0], buf+sizeof(*phdr), remainder);
2961     }
2962   }
2963
2964 #if defined (DEBUG)
2965   if (debugLevel) PrintResponse(phdr, count);
2966 #endif /* DEBUG */
2967
2968   return(count);
2969 }
2970
2971 #if defined (DEBUG)
2972 static void
2973 PrintResponse(
2974   ResponseHeader *phdr,
2975   int count)
2976 {
2977   char *opstr = "UNKNOWN";
2978
2979   if (!count)
2980   {
2981     Debug("opcode = (EOF)\n");
2982     return;
2983   }
2984
2985   switch(phdr->opcode)
2986   {
2987     case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2988     case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2989     case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2990     case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2991     case REQUEST_OP_LANG: opstr = "LANG"; break;
2992     case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
2993   }
2994
2995   Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
2996   Debug("  reserved = %d\n", phdr->reserved);
2997   Debug("  length = %d\n", phdr->length);
2998
2999   switch(phdr->opcode)
3000   {
3001     case REQUEST_OP_EXIT: break;
3002     case REQUEST_OP_LANG:
3003       Debug("  offLang=%d\n", ((ResponseLang *)phdr)->offLang);
3004       Debug("  lang='%s'\n",
3005         ((char *)phdr)+((ResponseLang *)phdr)->offLang);
3006       break;
3007     case REQUEST_OP_MESSAGE: break;
3008     case REQUEST_OP_CHPASS: break;
3009     case REQUEST_OP_CHALLENGE:
3010       Debug("  offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
3011       Debug("  response='%s'\n",
3012         ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
3013       break;
3014     case REQUEST_OP_DEBUG:
3015       Debug("  offString=%d\n", ((ResponseDebug *)phdr)->offString);
3016       Debug("  string='%s'\n",
3017         ((char *)phdr)+((ResponseDebug *)phdr)->offString);
3018       break;
3019   }
3020 }
3021 #endif /* DEBUG */
3022
3023 #ifdef __KERBEROS
3024
3025 /***************************************************************************
3026  *
3027  *  SetTicketFileName
3028  *
3029  *  generate kerberos ticket file name. Name is returned in the static
3030  *  global variable "krb_ticket_string".
3031  *  
3032  ***************************************************************************/
3033
3034 static void 
3035 SetTicketFileName(uid_t uid)
3036 {
3037
3038
3039     char *env;
3040     char lhost[64], *p;
3041
3042
3043     /*
3044      *  generate ticket file pathname  (/tmp/tkt<uid>.<host>) ...
3045      */
3046
3047     if (env = (char *)getenv("KRBTKFILE")) {
3048         (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3049         krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3050
3051     } else {
3052         if (gethostname(lhost, sizeof(lhost)) != -1) {
3053             if (p = index(lhost, '.')) *p = '\0';
3054             (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3055         } else {
3056             /* 32 bits of signed integer will always fit in 11 characters
3057                (including the sign), so no need to worry about overflow */
3058             (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3059         }
3060     }
3061 }
3062
3063 #endif /* __KERBEROS */
3064
3065 #if defined (_AIX) && !defined (_POWER)
3066
3067 /***************************************************************************
3068  *
3069  *  session_execve
3070  *
3071  *  If this is an authenticated process (LOGNAME set), set user's 
3072  *  process environment by calling setpenv().
3073  *
3074  *  If this is not an authenticated process, just call execve()
3075  *  
3076  ***************************************************************************/
3077
3078 static int
3079 session_execve(
3080   char *path,
3081   char *argv[],
3082   char *envp[])
3083 {
3084   int rc;
3085   char *user = getEnv (envp, "LOGNAME");
3086  
3087   if (user == NULL)
3088   {
3089     rc = execve(path, argv, envp);
3090   }
3091   else
3092   {
3093     char *usrTag, *sysTag;
3094
3095    /*
3096     * Save pointers to tags. The setpenv() function clears the pointers
3097     * to the tags in userEnviron as a side-effect.
3098     */
3099     sysTag = envp[SYS_ENV_TAG];
3100     usrTag = envp[USR_ENV_TAG];
3101
3102    /*
3103     * Set the users process environment. This call execs arvg so it 
3104     * should not return. It it should return, restore the envp tags.
3105     */
3106     rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3107
3108    /*
3109     * Restore pointers to tags.
3110     */
3111     envp[SYS_ENV_TAG] = sysTag;
3112     envp[USR_ENV_TAG] = usrTag;
3113   }
3114
3115   return(rc);
3116 }
3117 #endif /* _AIX && !_POWER */
3118
3119 #ifdef SIA
3120
3121 /* collect the SIA parameters from a window system. */
3122
3123 static int SiaManageGreeter(
3124     int timeout,
3125     int rendition,
3126     unsigned char *title,
3127     int num_prompts,
3128     prompt_t *prompt)
3129 {
3130     int i;
3131     struct {
3132       RequestMessage  greeter_message;
3133       char            msg_buffer[256];
3134       } greeter_msg_and_buffer;
3135     RequestForm *request_form;
3136
3137     switch(rendition) 
3138       {
3139         case SIAMENUONE:
3140         case SIAMENUANY:
3141         case SIAONELINER:
3142         case SIAFORM:
3143           if (rendition == SIAFORM && dt_in_sia_ses_authent 
3144                                   && (num_prompts == 2))
3145               {
3146               /* Normal login, Password case */
3147               Debug ("SIAFORM Normal login, Password case\n");
3148               while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3149                     && siaGreeterInfo.state->id != GREET_STATE_EXIT
3150                     && (siaGreeterInfo.status = ManageGreeter(
3151                               siaGreeterInfo.d, siaGreeterInfo.greet, 
3152                               siaGreeterInfo.verify, siaGreeterInfo.state)))
3153                   ;
3154
3155               if (!siaGreeterInfo.status 
3156                       || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3157                   return(SIACOLABORT);
3158
3159               strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name, 
3160                       prompt[0].max_result_length);
3161               strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3162                       prompt[1].max_result_length);
3163               }
3164           else
3165               {
3166               char *res_ptr;
3167               char *pmpt_ptr;
3168               int req_form_size;
3169               ResponseForm *response_form;
3170
3171               switch(rendition) 
3172                   {
3173                   case SIAMENUONE:
3174                       Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3175                       break;
3176                   case SIAMENUANY:
3177                       Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3178                       break;
3179                   case SIAONELINER:
3180                       Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3181                       break;
3182                   case SIAFORM:
3183                       Debug("SIAFORM num_prompts = %d\n", num_prompts);
3184                       break;
3185                   }
3186
3187               /* need to display form */
3188
3189               req_form_size = sizeof(RequestForm) 
3190                                       + strlen((const char *)title) + 1;
3191               for (i=0; i<num_prompts; i++)
3192                   req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3193               request_form = (RequestForm *) alloca(req_form_size);
3194
3195               siaGreeterInfo.state->id = GREET_STATE_FORM;
3196               siaGreeterInfo.state->request = (RequestHeader *)request_form;
3197               /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3198
3199               request_form->hdr.opcode = REQUEST_OP_FORM;
3200               request_form->hdr.reserved = 0;
3201               request_form->hdr.length = req_form_size;
3202               request_form->num_prompts = num_prompts;
3203               request_form->rendition = rendition;
3204               request_form->offTitle = sizeof(RequestForm);
3205               request_form->offPrompts = sizeof(RequestForm) +
3206                                           strlen((const char *)title) + 1;
3207               strcpy((char *)request_form + request_form->offTitle, 
3208                       (const char *)title);
3209
3210               pmpt_ptr = (char *)request_form + request_form->offPrompts;
3211               for (i=0; i<num_prompts; i++)
3212                   {
3213                   if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3214                       *pmpt_ptr++ = '\0';
3215                   else
3216                       {
3217                       Debug("  prompt[%d]: %s\n", i, prompt[i].prompt);
3218                       strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3219                       pmpt_ptr += strlen((const char *)prompt[i].prompt);
3220                       }
3221                   request_form->visible[i] = 
3222                       (prompt[i].control_flags & SIARESINVIS) ? False : True;
3223                   }
3224
3225               siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d, 
3226                                                   siaGreeterInfo.greet,
3227                                                   siaGreeterInfo.verify, 
3228                                                   siaGreeterInfo.state);
3229
3230               response_form = (ResponseForm *)siaGreeterInfo.state->response;
3231               res_ptr = (char *)response_form + response_form->offAnswers;
3232               for (i = 0; i < response_form->num_answers; i++)
3233                   {
3234                   if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3235                       {
3236                       if (res_ptr[0])
3237                           prompt[i].result = (unsigned char *)1;
3238                       else
3239                           prompt[i].result = NULL;
3240                       }
3241                   else
3242                       {
3243                       strcpy((char *)prompt[0].result, res_ptr);
3244                       }
3245                   res_ptr += strlen(res_ptr) + 1;
3246                   }
3247               if (!response_form->collect_status)
3248                   siaGreeterInfo.status = FALSE;
3249               }
3250             break;
3251         case SIAINFO:
3252         case SIAWARNING:
3253
3254           Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3255
3256           siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3257           siaGreeterInfo.state->request = (RequestHeader *) 
3258                               &greeter_msg_and_buffer.greeter_message;
3259           siaGreeterInfo.state->vf = VF_MESSAGE;
3260           siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3261
3262           siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d, 
3263                                               siaGreeterInfo.greet,
3264                                               siaGreeterInfo.verify, 
3265                                               siaGreeterInfo.state);
3266             break;
3267         default:
3268             return(SIACOLABORT);
3269             break;
3270       }
3271     if (!siaGreeterInfo.status)
3272       return(SIACOLABORT);
3273     return(SIACOLSUCCESS);
3274 }
3275
3276 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3277 {
3278
3279     greet->name = malloc(strlen(siaHandle->name) + 1);
3280     strcpy (greet->name, siaHandle->name);
3281
3282     greet->password = malloc(strlen(siaHandle->password) + 1);
3283     strcpy (greet->password, siaHandle->password);
3284     
3285
3286 }
3287
3288 static void KillGreeter( void )
3289 {
3290     if (sia_greeter_pid)
3291       AbortClient(sia_greeter_pid);
3292     sia_greeter_pid = 0;
3293 }
3294 #endif /* SIA */