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