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