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