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