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