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