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