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