9a42844737f8f62f0cf4b8aa6723c4a205c404f0
[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 = NULL;
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     int         dupfp = -1;
1947     int         dupfp2 = -1;
1948
1949 #ifdef __PASSWD_ETC
1950 #  ifndef U_NAMELEN
1951 #    define U_NAMELEN   sizeof(rgy_$name_t)
1952 #  endif
1953
1954     int i;
1955     static char name_short[U_NAMELEN];
1956 #endif
1957
1958 #ifdef SIA
1959
1960     int argc = 1;
1961     char *argv[] = { "dtlogin", 0 };
1962     char *hostName = NULL;
1963     char *loginName = NULL;
1964     int siaStatus = -1;
1965
1966     /*
1967      * Initialize SIA
1968      */
1969     
1970     if (d->serverPid == -1)
1971       hostName = d->name;
1972
1973     siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName, 
1974                               loginName, d->name, 1, NULL);
1975     if (siaStatus != SIASUCCESS)
1976       {
1977       Debug("sia_ses_init failure status %d\n", siaStatus);
1978       exit(1);
1979       }
1980
1981 #endif
1982
1983     greeterPid = 0;
1984     if (!setjmp (abortSession)) {
1985         signal(SIGTERM, catchTerm);
1986
1987         /*
1988          * We've changed dtlogin to pass HUP's down to the children
1989          * so ignore any HUP's once the client has started.
1990          */
1991         greeter_d = d;
1992         signal(SIGHUP, catchHUP);
1993
1994         /*
1995          *  set up communication pipes...
1996          */
1997          
1998         if(-1 == pipe(response)) {
1999             perror(strerror(errno));
2000         }
2001         if(-1 == pipe(request)) {
2002             perror(strerror(errno));
2003         }
2004         rbytes = 0;
2005
2006
2007         switch (greeterPid = fork ()) {
2008         case 0:
2009
2010             /*
2011              *  pass some information in the environment...
2012              */
2013                    
2014             env = 0;
2015             sprintf(msg,"%d", d->grabServer);
2016             env = setEnv(env, GRABSERVER,  msg);
2017         
2018             sprintf(msg,"%d", d->grabTimeout);
2019             env = setEnv(env, GRABTIMEOUT, msg);
2020
2021
2022             if (timeZone && strlen(timeZone) > 0 )
2023                 env = setEnv(env, "TZ", timeZone);
2024
2025             if (errorLogFile && errorLogFile[0])
2026                 env = setEnv(env, ERRORLOG,  errorLogFile);
2027
2028             if (d->authFile)
2029                 env = setEnv(env, "XAUTHORITY", d->authFile);
2030
2031             if (d->dtlite)
2032                 env = setEnv(env, DTLITE,  "True");
2033
2034             if (d->session)  
2035                 env = setEnv(env, SESSION,  d->session);
2036
2037             if(session_set)
2038                 env = setEnv(env, SESSION_SET, "True");
2039
2040             if (d->pmSearchPath)
2041                 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
2042
2043             if (d->bmSearchPath)
2044                 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
2045
2046 #if defined (__KERBEROS) || defined (__AFS)
2047             if (d->verifyName) {
2048                 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2049                      (strcmp(d->verifyName, VN_KRB) == 0)    ) {
2050                      
2051                     env = setEnv(env, VERIFYNAME, d->verifyName );
2052                 }
2053                 else {
2054                     LogError(ReadCatalog(
2055                         MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2056                         d->verifyName);
2057                     d->verifyName = NULL;
2058                 }
2059             }
2060 #endif
2061                         
2062             if((path = getenv("NLSPATH")) != NULL)
2063                 env = setEnv(env, "NLSPATH", path);
2064 #ifdef __hp_osf
2065             env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2066 #endif
2067
2068             
2069             /*
2070              *  ping remote displays...
2071              *
2072              */
2073
2074             if (d->displayType.location == Local) {
2075                 GettyRunning(d); /* refresh gettyState */
2076                 if (d->gettyState != DM_GETTY_USER)
2077                     env = setEnv(env, LOCATION, "local");
2078             }
2079             else {
2080                 sprintf(msg,"%d", d->pingInterval);
2081                 env = setEnv(env, PINGINTERVAL,  msg);
2082         
2083                 sprintf(msg,"%d", d->pingTimeout);
2084                 env = setEnv(env, PINGTIMEOUT, msg);
2085             }
2086
2087
2088             if ( d->langList && strlen(d->langList) > 0 )
2089                 env = setEnv(env, LANGLIST,  d->langList);
2090 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2091             else if (languageList && strlen(languageList) > 0 )
2092                 env = setEnv(env, LANGLIST, languageList);
2093 #endif /* ENABLE_DYNAMIC_LANGLIST */
2094
2095             {
2096                 char *language = NULL;
2097
2098 #if defined (ENABLE_DYNAMIC_LANGLIST)
2099                 language = d->language;
2100 #endif /* ENABLE_DYNAMIC_LANGLIST */
2101
2102                 if ( d->language && strlen(d->language) > 0 )
2103                   env = setLang(d, env, language);
2104             }
2105
2106             if((path = getenv("XKEYSYMDB")) != NULL)
2107                 env = setEnv(env, "XKEYSYMDB", path);
2108
2109 #ifdef sun
2110             if((path = getenv("OPENWINHOME")) != NULL)
2111                 env = setEnv(env, "OPENWINHOME", path);
2112 #endif
2113
2114 #ifdef __apollo
2115             /*
2116              *  set environment for Domain machines...
2117              */
2118             env = setEnv(env, "ENVIRONMENT", "bsd");
2119             env = setEnv(env, "SYSTYPE", "bsd4.3");
2120 #endif
2121                 
2122
2123             Debug ("Greeter environment:\n");
2124             printEnv(env);
2125             Debug ("End of Greeter environment:\n");
2126
2127            /*
2128             * Writing to file descriptor 1 goes to response pipe instead.
2129             */
2130             close(1);
2131             dupfp = dup(response[1]);
2132             if(-1 == dupfp) {
2133                 perror(strerror(errno));
2134             }
2135             close(response[0]);
2136             close(response[1]);
2137
2138            /*
2139             * Reading from file descriptor 0 reads from request pipe instead.
2140             */
2141             close(0);
2142             dupfp2 = dup(request[0]);
2143             if(-1 == dupfp2) {
2144                 perror(strerror(errno));
2145             }
2146             close(request[0]);
2147             close(request[1]);
2148
2149             CleanUpChild ();
2150
2151             /*
2152              * figure out path to dtgreet...
2153              */
2154
2155             strcpy(msg, progName);
2156     
2157             if ((p = (char *) strrchr(msg, '/')) == NULL)
2158                 strcpy(msg,"./");
2159             else
2160                 *(++p) = '\0';
2161
2162             strcat(msg,"dtgreet");
2163
2164             execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2165             LogError(ReadCatalog(
2166                 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2167                  msg, d->name);
2168             exit (NOTIFY_ABORT_DISPLAY);
2169
2170         case -1:
2171             Debug ("Fork of Greeter failed.\n");
2172             LogError(ReadCatalog(
2173                 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2174             close(request[0]);
2175             close(request[1]);
2176             close(response[0]);
2177             close(response[1]);
2178             exit (UNMANAGE_DISPLAY);
2179
2180         default:
2181             Debug ("Greeter started\n");
2182
2183             close(response[1]); /* Close write end of response pipe */
2184             close(request[0]); /* Close read end of request pipe */
2185
2186
2187             /*
2188              * Retrieve information from greeter and authenticate.
2189              */
2190             globalDisplayName = d->name;
2191             state.id = GREET_STATE_ENTER;
2192             state.waitForResponse = FALSE;
2193 #ifdef SIA
2194            
2195             /*
2196              * atexit() registers this function to be called if exit() is
2197              * called.  This is needed because in enhanced security mode, SIA
2198              * may call exit() whn the user fails to enter or change a
2199              * password.
2200              */
2201             sia_greeter_pid = greeterPid;
2202             if (!sia_exit_proc_reg)
2203                 {
2204                 atexit(KillGreeter);
2205                 sia_exit_proc_reg = TRUE;
2206                 }
2207   
2208             siaGreeterInfo.d = d;
2209             siaGreeterInfo.greet = greet;
2210             siaGreeterInfo.verify = verify;
2211             siaGreeterInfo.state = &state;
2212             siaGreeterInfo.status = TRUE;
2213   
2214             siaStatus =  -1;
2215             while(siaStatus != SIASUCCESS)
2216                 {
2217                 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2218                     {
2219                     Debug ("RunGreeter: before sia_ses_authent\n");
2220                     dt_in_sia_ses_authent = True;
2221                     siaStatus = sia_ses_authent(SiaManageGreeter, NULL, 
2222                                                 siaHandle);
2223                     dt_in_sia_ses_authent = False;
2224                     Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2225                                 siaStatus);
2226                     if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2227                         {
2228                         state.id = GREET_STATE_ERRORMESSAGE;
2229                         state.vf = VF_INVALID;
2230                         ManageGreeter(d, greet, verify, &state);
2231                         }
2232                     if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2233                         break;
2234                     }
2235                 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2236                     {
2237                     sia_ses_release(&siaHandle);
2238                     break;
2239                     }
2240   
2241                 Debug("RunGreeter: before sia_ses_estab\n");
2242                 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2243                 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2244                                 siaStatus);
2245   
2246                 if (!siaGreeterInfo.status)
2247                     break;
2248   
2249                 if (siaStatus == SIASUCCESS)
2250                     {
2251                     Debug("RunGreeter: before sia_ses_launch\n");
2252                     siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2253                     Debug("RunGreeter: after sia_ses_launch status = %d\n",
2254                                 siaStatus);
2255                     }
2256                 if (!siaGreeterInfo.status)
2257                     break;
2258   
2259                 if (siaStatus != SIASUCCESS)
2260                     {
2261                     Debug("RunGreeter: sia_ses_launch failure\n");
2262                     /* establish & launch failures do a release */
2263                     siaHandle = NULL;
2264                     siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName, 
2265                                                 loginName, d->name, 1, NULL);
2266                     if (siaStatus != SIASUCCESS)
2267                         {
2268                         Debug("sia_ses_init failure status %d\n", siaStatus);
2269                         exit(RESERVER_DISPLAY);
2270                         }
2271                     }
2272                 }
2273             /*
2274              * sia_ses_launch() wil probably seteuid to that of the
2275              * user, but we don't want that now.
2276              */
2277             seteuid(0);
2278             /*
2279              * extract necessary info from SIA context struct
2280              */
2281             if (siaHandle)
2282                 {
2283                 if (siaStatus == SIASUCCESS)
2284                     CopySiaInfo(siaHandle, greet);
2285                 sia_ses_release(&siaHandle);
2286                 }
2287             state.id = GREET_STATE_TERMINATEGREET;
2288             if (siaGreeterInfo.status)
2289                 {
2290                 while (ManageGreeter(d, greet, verify, &state))
2291                   ;
2292                 }
2293             sia_greeter_pid = 0;
2294 #else
2295             while (ManageGreeter(d, greet, verify, &state))
2296               ;
2297 #endif /* SIA */
2298
2299             /*
2300              * Wait for Greeter to end...
2301              */
2302             for (;;) {
2303                 pid = wait (&status);
2304                 if (pid == greeterPid)
2305                     break;
2306             }
2307
2308
2309             /*
2310              *  Greeter exited. Check return code...
2311              */
2312              
2313             Debug("Greeter return status; exit = %d, signal = %d\n", 
2314                    waitCode(status), waitSig(status));
2315
2316
2317             /*
2318              * remove authorization file if used...
2319              */
2320      
2321             if (d->authorizations && d->authFile &&
2322                 waitVal(status) != NOTIFY_LANG_CHANGE
2323 #ifdef BLS
2324                 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2325 #endif
2326                ) {
2327
2328 /***
2329                 Debug ("Done with authorization file %s, removing\n",
2330                         d->authFile);
2331                 (void) unlink (d->authFile);
2332 ***/
2333             }
2334
2335
2336                 if(waitVal(status) > NOTIFY_ALT_DTS) 
2337                       d->sessionType = waitVal(status);
2338
2339
2340             switch (waitVal(status)) {
2341             case NOTIFY_FAILSAFE:
2342                 greet->string = "failsafe";
2343                 break;
2344             case NOTIFY_PASSWD_EXPIRED:
2345                 greet->string = "password";
2346                 break;
2347             case NOTIFY_DTLITE:
2348             case NOTIFY_DT:
2349             case NOTIFY_OK:
2350             case NOTIFY_LAST_DT:
2351                 d->sessionType = waitVal(status);
2352                 break;
2353             default:
2354                 break;
2355             }
2356
2357           Debug("waitVal - status is  %d\n", waitVal(status));
2358            if(waitVal(status) > NOTIFY_ALT_DTS)
2359                 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2360             else
2361                 notify_dt = waitVal(status);
2362
2363             switch (notify_dt) {
2364             case NOTIFY_FAILSAFE:
2365             case NOTIFY_PASSWD_EXPIRED:
2366             case NOTIFY_DTLITE:
2367             case NOTIFY_DT:
2368             case NOTIFY_OK:
2369             case NOTIFY_LAST_DT:
2370             case NOTIFY_ALT_DTS:
2371
2372                if (NULL == greet->name) return;
2373
2374                /*
2375                 *  greet->name, greet->password set in ManageGreeter().
2376                 */
2377                 Debug("Greeter returned name '%s'\n", greet->name);
2378
2379 #ifdef __PASSWD_ETC
2380                 greet->name_full = greet->name;
2381                            /* get just person name out of full SID */
2382                 i = 0;
2383                 while (i < sizeof(rgy_$name_t) 
2384                      && greet->name_full[i] != '.'
2385                      && greet->name_full[i] != '\0') {
2386                      name_short[i] = greet->name_full[i];
2387                      i++;
2388                 }
2389                 name_short[i] = '\0';
2390                 greet->name = name_short;
2391 #endif
2392                     
2393 #ifdef __AFS
2394                /*
2395                 * groups[] set in Authenticate().
2396                 */
2397                 if ( IsVerifyName(VN_AFS) ) {
2398                   verify->groups[0] = groups[0];
2399                   verify->groups[1] = groups[1];
2400                   Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2401                   Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2402                 }
2403 #endif
2404                     
2405 #ifdef BLS
2406                /*
2407                 * sensitivityLevel set in BLS_Verify()
2408                 */
2409                 greet->b1security = sensitivityLevel;
2410 #endif
2411
2412                 Verify(d, greet, verify);
2413                 return;
2414
2415             case NOTIFY_ABORT:
2416                 Debug ("Greeter Xlib error or SIGTERM\n");
2417                 SessionExit(d, OPENFAILED_DISPLAY);
2418
2419             case NOTIFY_RESTART:
2420                 Debug ("Greeter requested RESTART_DISPLAY\n");
2421                 SessionExit(d, RESERVER_DISPLAY);
2422
2423             case NOTIFY_ABORT_DISPLAY:
2424                 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2425                 SessionExit(d, UNMANAGE_DISPLAY);
2426
2427             case NOTIFY_NO_WINDOWS:
2428                 Debug ("Greeter requested NO_WINDOWS mode\n");
2429                 if (d->serverPid >= 2)
2430                     /*
2431                      *  Don't do a SessionExit() here since that causes
2432                      *  the X-server to be reset. We know we are going to
2433                      *  terminate it anyway, so just go do that...
2434                      */
2435                     exit(SUSPEND_DISPLAY);
2436                 else
2437                     return;
2438
2439             case NOTIFY_LANG_CHANGE:
2440                 Debug ("Greeter requested LANG_CHANGE\n");
2441
2442                /*
2443                 * copy requested language into display struct "d". Note,
2444                 * this only happens in this child's copy of "d", not in
2445                 * the master struct. When the user logs out, the
2446                 * resource-specified language (if any) will reactivate.
2447                 */
2448                 if (d->language)
2449                   Debug("Greeter returned language '%s'\n", d->language);
2450                 else
2451                   Debug("Greeter returned language (NULL)\n");
2452
2453
2454                 if (strcmp(d->language, "default") == 0) {
2455                     int len = strlen(defaultLanguage) + 1;
2456                     d->language = (d->language == NULL  ?
2457                                    malloc(len) : realloc (d->language, len));
2458                     strcpy(d->language, defaultLanguage);
2459                 }
2460                 return;
2461 #ifdef  BLS
2462             case NOTIFY_BAD_SECLEVEL:
2463                 return;
2464 #endif
2465             case waitCompose (SIGTERM,0,0):
2466                 Debug ("Greeter exited on SIGTERM\n");
2467                 SessionExit(d, OPENFAILED_DISPLAY);
2468                 
2469             default:
2470                 Debug ("Greeter returned unknown status %d\n", 
2471                         waitVal(status));
2472                 SessionExit(d, REMANAGE_DISPLAY);
2473             }
2474         }
2475         signal(SIGHUP, SIG_DFL);
2476     }
2477     else {
2478         AbortClient(greeterPid);
2479         SessionExit(d, UNMANAGE_DISPLAY);
2480     }
2481 }
2482
2483 /*****************************************************************************
2484 * ManageGreeter
2485  
2486   State transitions
2487  
2488   enter -> ENTER: 
2489     This is the entry into greeter state processing. Allocate and initialize
2490     state structure.
2491
2492   ENTER -> LOGIN:
2493     Display the login screen. Upon display, the login screen can be 'reset'. If
2494     reset is true, the username and password fields are cleared and the focus
2495     is set to the username field. If reset is false, the username and password
2496     field is untouched and the focus is set to the password field.
2497
2498   LOGIN -> AUTHENTICATE:
2499     Authenticate the username entered on login screen. 
2500
2501   AUTHENTICATE -> TERMINATEGREET:
2502     User passed authentication so terminate the greeter.
2503
2504   AUTHENTICATE -> EXPASSWORD: 
2505     User passed authentication, but the their password has expired.
2506     Display old password message. This message allows the user to 
2507     change their password by starting a getty and running passwd(1).  
2508
2509   AUTHENTICATE -> BAD_HOSTNAME:
2510     User passed authentication, but the their hostname is empty.
2511     Display a dialog that allows the user to run a getty to fix the
2512     problem, or start the desktop anyway.
2513
2514   AUTHENTICATE -> ERRORMESSAGE:
2515     User failed authentication, so display error message. 
2516
2517   AUTHENTICATE -> LOGIN
2518     User failed authentication, but did not enter a password. Instead
2519     of displaying an error message, redisplay the login screen with
2520     the focus set to the password field. If the user authenticates again
2521     without the password field set, display an error. This allows a user
2522     to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2523
2524   EXIT -> exit
2525     Free state structure and return false to stop state transitions.
2526
2527   ERRORMESSAGE -> LOGIN
2528     Display error message base on return code from last authentication
2529     attempt. Redisplay login screen with reset set to true.
2530
2531   (state) -> LANG -> (state)
2532     User has chosen a new language. Transition to LANG state to save off
2533     the new language, and transition back to original state. 
2534   
2535 *****************************************************************************/
2536
2537 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2538
2539 static int
2540 ManageGreeter( struct display *d, struct greet_info *greet,
2541             struct verify_info *verify, struct greet_state *state )
2542 {
2543   struct {
2544     int id;
2545     char *def;
2546   } msg;
2547
2548   if (state->waitForResponse)
2549   {
2550     if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2551     {
2552      /*
2553       * Dtgreet has terminated. 
2554       */
2555       state->id = GREET_STATE_EXIT;
2556       state->waitForResponse = FALSE;
2557       return(TRUE);
2558     }
2559
2560     if (state->request->opcode != state->response->opcode)
2561     {
2562      /*
2563       * An unrequested event arrived. See if it's one we
2564       * are expecting.
2565       */
2566       switch(state->response->opcode)
2567       {
2568         case REQUEST_OP_LANG:
2569           {
2570            /*
2571             * User has changed language. Recursively handle this state
2572             * and return to current state.
2573             */
2574             struct greet_state lang_state;
2575
2576             lang_state = *state;
2577             lang_state.id = GREET_STATE_LANG;
2578             lang_state.waitForResponse = FALSE;
2579             ManageGreeter(d, greet, verify, &lang_state);
2580             Debug("Response opcode REQUEST_OP_LANG\n");
2581             return(TRUE);
2582           }
2583           break;
2584
2585         case REQUEST_OP_CLEAR:
2586           {
2587            /*
2588             * User has requested the screen be cleared.
2589             */
2590             state->id = GREET_STATE_USERNAME;
2591             state->waitForResponse = TRUE;
2592             Debug("Response opcode REQUEST_OP_CLEAR\n");
2593           }
2594           break;
2595     
2596         default:
2597           Debug("Response opcode UNEXPECTED RESPONSE!\n");
2598 #ifndef SIA
2599           return(TRUE);
2600 #endif
2601           break;
2602       }
2603     }
2604     else
2605     {
2606      /*
2607       * Got the response we were expecting.
2608       */
2609       state->waitForResponse = FALSE;
2610     }
2611   }
2612
2613   switch(state->id)
2614   {
2615     case GREET_STATE_ENTER:
2616       {
2617        /*
2618         * Enter - initialize state
2619         */
2620         Debug("GREET_STATE_ENTER\n");
2621
2622         state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2623         state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2624         state->authenticated = FALSE;
2625         state->msg = NULL;
2626
2627         state->id = GREET_STATE_USERNAME;
2628       }
2629       break;
2630
2631     case GREET_STATE_USERNAME:
2632       {
2633        /*
2634         * Get user name
2635         */
2636         RequestChallenge *r;
2637
2638         Debug("GREET_STATE_USERNAME\n");
2639
2640         Authenticate(d, NULL, NULL, NULL);
2641
2642         SETMC(msg, LOGIN_LABEL);
2643
2644         r = (RequestChallenge *)state->request;
2645         r->hdr.opcode = REQUEST_OP_CHALLENGE;
2646         r->hdr.reserved = 0;
2647         r->bEcho = TRUE;
2648         r->idMC = msg.id;
2649         r->hdr.length = sizeof(*r);
2650
2651         r->offChallenge = sizeof(*r);
2652         strcpy(((char *)r) + r->offChallenge, msg.def);
2653         r->hdr.length += strlen(msg.def) + 1;
2654
2655         if (greet->name)
2656         {
2657           r->offUserNameSeed = r->hdr.length;
2658           strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2659           r->hdr.length += strlen(greet->name) + 1;
2660           Debug("Greet name:  %s\n", greet->name);
2661         }
2662         else
2663         {
2664           r->offUserNameSeed = 0;
2665         }
2666
2667         if (greet->name)
2668         {
2669           free(greet->name); greet->name = NULL;
2670         }
2671         if (greet->password)
2672         {
2673           free(greet->password); greet->password = NULL;
2674         }
2675
2676         TellGreeter((RequestHeader *)r);
2677         state->waitForResponse = TRUE;
2678
2679         state->id = GREET_STATE_AUTHENTICATE;
2680       }
2681       break;
2682
2683     case GREET_STATE_CHALLENGE:
2684       {
2685        /*
2686         * Get user name
2687         */
2688         RequestChallenge *r;
2689
2690         Debug("GREET_STATE_CHALLENGE\n");
2691
2692         if (greet->password)
2693         {
2694           free(greet->password); greet->password = NULL;
2695         }
2696
2697         SETMC(msg, PASSWD_LABEL);
2698
2699         r = (RequestChallenge *)state->request;
2700         r->hdr.opcode = REQUEST_OP_CHALLENGE;
2701         r->hdr.reserved = 0;
2702         r->bEcho = FALSE;
2703         r->idMC = msg.id;
2704         r->offUserNameSeed = 0;
2705         r->offChallenge = sizeof(*r);
2706         strcpy(((char *)r) + r->offChallenge, msg.def);
2707         r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2708
2709         TellGreeter((RequestHeader *)r);
2710         state->waitForResponse = TRUE;
2711
2712         state->id = GREET_STATE_AUTHENTICATE;
2713       }
2714       break;
2715
2716     case GREET_STATE_AUTHENTICATE:
2717       {
2718        /*
2719         * Attempt to authenticate.
2720         */
2721         ResponseChallenge *r;
2722    
2723         Debug("GREET_STATE_AUTHENTICATE\n"); 
2724
2725         r = (ResponseChallenge *)state->response;
2726      
2727         if (greet->name == NULL)
2728         {
2729           greet->name = strdup(((char *)r) + r->offResponse);
2730           if (strlen(greet->name) == 0)
2731           {
2732             state->id = GREET_STATE_USERNAME;
2733             break;
2734           }
2735         }
2736         else 
2737         { 
2738           greet->password = strdup(((char *)r) + r->offResponse);
2739         }
2740
2741         if (state->msg)
2742         {
2743           free(state->msg);
2744           state->msg = NULL;
2745         }
2746
2747        /*
2748         * Attempt to authenticate user. 'username' should be a 
2749         * non-empty string. 'password' may be an empty string.
2750         */
2751         state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2752
2753         if (state->vf == VF_OK || 
2754             state->vf == VF_PASSWD_AGED || 
2755             state->vf == VF_BAD_HOSTNAME)
2756         {
2757           state->authenticated = TRUE;
2758         }
2759
2760        /*
2761         * General transitions.
2762         */
2763         switch (state->vf)
2764         {
2765           case VF_OK:           state->id = GREET_STATE_TERMINATEGREET; break; 
2766           case VF_PASSWD_AGED:  state->id = GREET_STATE_EXPASSWORD; break; 
2767           case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break; 
2768           case VF_CHALLENGE:    state->id = GREET_STATE_CHALLENGE; break; 
2769           default:              state->id = GREET_STATE_ERRORMESSAGE; break; 
2770         }
2771       }
2772       break;
2773
2774     case GREET_STATE_EXIT: 
2775       {
2776        /*
2777         * Free resources and leave.
2778         */
2779         Debug("GREET_STATE_EXIT\n");
2780
2781         if (state->msg)
2782         {
2783           free(state->msg);
2784         }
2785  
2786         if (!state->authenticated)
2787         {
2788           if (greet->name)
2789           {
2790             free(greet->name); greet->name = NULL;
2791           }
2792           if (greet->password)
2793           {
2794             free(greet->password); greet->password = NULL;
2795           }
2796         }
2797
2798         free(state->request);
2799         free(state->response);
2800         return(FALSE);
2801       }
2802       break;
2803
2804     case GREET_STATE_ERRORMESSAGE:
2805       {
2806        /* 
2807         * Display error message.
2808         */
2809         RequestMessage *r;
2810
2811         Debug("GREET_STATE_ERRORMESSAGE\n");
2812
2813         r = (RequestMessage *)state->request;
2814
2815         switch(state->vf)
2816         {
2817           case VF_INVALID:       SETMC(msg, LOGIN); break;
2818           case VF_HOME:          SETMC(msg, HOME); break;
2819           case VF_MAX_USERS:     SETMC(msg, MAX_USERS); break;
2820           case VF_BAD_UID:       SETMC(msg, BAD_UID); break;
2821           case VF_BAD_GID:       SETMC(msg, BAD_GID); break;
2822           case VF_BAD_AID:       SETMC(msg, BAD_AID); break;
2823           case VF_BAD_AFLAG:     SETMC(msg, BAD_AFLAG); break;
2824           case VF_NO_LOGIN:      SETMC(msg, NO_LOGIN); break;
2825 #ifdef BLS
2826           case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2827 #endif
2828           case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2829           default: msg.id=0; msg.def=""; break;
2830         }
2831
2832         r->hdr.opcode = REQUEST_OP_MESSAGE;
2833         r->hdr.reserved = 0;
2834         r->idMC = msg.id;
2835         r->offMessage = sizeof(*r);
2836         strcpy(((char *)r) + r->offMessage, msg.def);
2837         r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2838
2839         TellGreeter((RequestHeader *)r);
2840         state->waitForResponse = TRUE;
2841
2842         state->id = GREET_STATE_USERNAME;
2843       }
2844       break;
2845
2846     case GREET_STATE_LANG:
2847       {
2848        /*
2849         * User selected new language.
2850         */
2851         ResponseLang *r;
2852         char *lang;
2853         int len;
2854
2855         Debug("GREET_STATE_LANG\n");
2856
2857         r = (ResponseLang *)state->response;
2858         lang = ((char *)r) + r->offLang;
2859         len = strlen(lang) + 1;
2860
2861         d->language = (d->language == NULL ?
2862                        malloc(len) : realloc(d->language, len));
2863         strcpy(d->language, lang);
2864         Debug("Language returned:  %s\n", d->language);
2865       }
2866       break;
2867
2868     case GREET_STATE_TERMINATEGREET:
2869       {
2870        /*
2871         * Terminate dtgreet.
2872         */
2873         RequestExit *r;
2874
2875         Debug("GREET_STATE_TERMINATEGREET\n");
2876
2877         r = (RequestExit *)state->request;
2878
2879         r->hdr.opcode = REQUEST_OP_EXIT;
2880         r->hdr.reserved = 0;
2881         r->hdr.length = sizeof(*r);
2882
2883         TellGreeter((RequestHeader *)r);
2884         state->waitForResponse = TRUE;
2885
2886         state->id = GREET_STATE_EXIT;
2887       }
2888       break;
2889
2890     case GREET_STATE_EXPASSWORD:
2891       {
2892        /*
2893         * Display password expired message.
2894         */
2895         RequestExpassword *r;
2896
2897         Debug("GREET_STATE_EXPASSWORD\n");
2898
2899         r = (RequestExpassword *)state->request;
2900
2901         r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2902         r->hdr.reserved = 0;
2903         r->hdr.length = sizeof(*r);
2904
2905         TellGreeter((RequestHeader *)r);
2906         state->waitForResponse = TRUE;
2907
2908         state->id = GREET_STATE_USERNAME;
2909       }
2910       break;
2911
2912     case GREET_STATE_BAD_HOSTNAME:
2913       {
2914        /*
2915         * Display password expired message.
2916         */
2917         RequestHostname *r;
2918
2919         Debug("GREET_STATE_BAD_HOSTNAME\n");
2920
2921         r = (RequestHostname *)state->request;
2922
2923         r->hdr.opcode = REQUEST_OP_HOSTNAME;
2924         r->hdr.reserved = 0;
2925         r->hdr.length = sizeof(*r);
2926
2927         TellGreeter((RequestHeader *)r);
2928         state->waitForResponse = TRUE;
2929
2930         state->id = GREET_STATE_USERNAME;
2931       }
2932       break;
2933
2934 #ifdef SIA
2935     case GREET_STATE_FORM:
2936       {
2937        /*
2938         * Get arbitrary number of answers.
2939         */
2940
2941         Debug("GREET_STATE_FORM\n");
2942  
2943         AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2944  
2945         state->waitForResponse = FALSE;
2946         state->id = GREET_STATE_USERNAME;
2947       }
2948       break;
2949 #endif /* SIA */
2950   }
2951
2952   return(TRUE);
2953 }
2954
2955
2956 static void
2957 TellGreeter(
2958   RequestHeader *phdr)
2959 {
2960   if(-1 == write(request[1], phdr, phdr->length)) {
2961     perror(strerror(errno));
2962   }
2963 }
2964
2965 static int
2966 AskGreeter(
2967   RequestHeader *preqhdr,
2968   char *buf,
2969   int blen)
2970 {
2971   int count;
2972   int remainder;
2973   ResponseHeader *phdr = (ResponseHeader *)buf;
2974
2975   if (preqhdr) TellGreeter(preqhdr);
2976
2977   phdr->opcode = REQUEST_OP_NONE;
2978
2979   count = read(response[0], buf, sizeof(*phdr));
2980
2981   if (count == sizeof(*phdr))
2982   {
2983    /*
2984     * Calculate amount of data after header.
2985     */
2986     remainder =  phdr->length - sizeof(*phdr);
2987     if (remainder > 0)
2988     {
2989      /*
2990       * Read remainder of response.
2991       */
2992       count += read(response[0], buf+sizeof(*phdr), remainder);
2993     }
2994   }
2995
2996 #if defined (DEBUG)
2997   if (debugLevel) PrintResponse(phdr, count);
2998 #endif /* DEBUG */
2999
3000   return(count);
3001 }
3002
3003 #if defined (DEBUG)
3004 static void
3005 PrintResponse(
3006   ResponseHeader *phdr,
3007   int count)
3008 {
3009   char *opstr = "UNKNOWN";
3010
3011   if (!count)
3012   {
3013     Debug("opcode = (EOF)\n");
3014     return;
3015   }
3016
3017   switch(phdr->opcode)
3018   {
3019     case REQUEST_OP_EXIT: opstr = "EXIT"; break;
3020     case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
3021     case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
3022     case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
3023     case REQUEST_OP_LANG: opstr = "LANG"; break;
3024     case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
3025   }
3026
3027   Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
3028   Debug("  reserved = %d\n", phdr->reserved);
3029   Debug("  length = %d\n", phdr->length);
3030
3031   switch(phdr->opcode)
3032   {
3033     case REQUEST_OP_EXIT: break;
3034     case REQUEST_OP_LANG:
3035       Debug("  offLang=%d\n", ((ResponseLang *)phdr)->offLang);
3036       Debug("  lang='%s'\n",
3037         ((char *)phdr)+((ResponseLang *)phdr)->offLang);
3038       break;
3039     case REQUEST_OP_MESSAGE: break;
3040     case REQUEST_OP_CHPASS: break;
3041     case REQUEST_OP_CHALLENGE:
3042       Debug("  offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
3043       Debug("  response='%s'\n",
3044         ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
3045       break;
3046     case REQUEST_OP_DEBUG:
3047       Debug("  offString=%d\n", ((ResponseDebug *)phdr)->offString);
3048       Debug("  string='%s'\n",
3049         ((char *)phdr)+((ResponseDebug *)phdr)->offString);
3050       break;
3051   }
3052 }
3053 #endif /* DEBUG */
3054
3055 #ifdef __KERBEROS
3056
3057 /***************************************************************************
3058  *
3059  *  SetTicketFileName
3060  *
3061  *  generate kerberos ticket file name. Name is returned in the static
3062  *  global variable "krb_ticket_string".
3063  *  
3064  ***************************************************************************/
3065
3066 static void 
3067 SetTicketFileName(uid_t uid)
3068 {
3069
3070
3071     char *env;
3072     char lhost[64], *p;
3073
3074
3075     /*
3076      *  generate ticket file pathname  (/tmp/tkt<uid>.<host>) ...
3077      */
3078
3079     if (env = (char *)getenv("KRBTKFILE")) {
3080         (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3081         krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3082
3083     } else {
3084         if (gethostname(lhost, sizeof(lhost)) != -1) {
3085             if (p = index(lhost, '.')) *p = '\0';
3086             (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3087         } else {
3088             /* 32 bits of signed integer will always fit in 11 characters
3089                (including the sign), so no need to worry about overflow */
3090             (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3091         }
3092     }
3093 }
3094
3095 #endif /* __KERBEROS */
3096
3097 #if defined (_AIX) && !defined (_POWER)
3098
3099 /***************************************************************************
3100  *
3101  *  session_execve
3102  *
3103  *  If this is an authenticated process (LOGNAME set), set user's 
3104  *  process environment by calling setpenv().
3105  *
3106  *  If this is not an authenticated process, just call execve()
3107  *  
3108  ***************************************************************************/
3109
3110 static int
3111 session_execve(
3112   char *path,
3113   char *argv[],
3114   char *envp[])
3115 {
3116   int rc;
3117   char *user = getEnv (envp, "LOGNAME");
3118  
3119   if (user == NULL)
3120   {
3121     rc = execve(path, argv, envp);
3122   }
3123   else
3124   {
3125     char *usrTag, *sysTag;
3126
3127    /*
3128     * Save pointers to tags. The setpenv() function clears the pointers
3129     * to the tags in userEnviron as a side-effect.
3130     */
3131     sysTag = envp[SYS_ENV_TAG];
3132     usrTag = envp[USR_ENV_TAG];
3133
3134    /*
3135     * Set the users process environment. This call execs arvg so it 
3136     * should not return. It it should return, restore the envp tags.
3137     */
3138     rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3139
3140    /*
3141     * Restore pointers to tags.
3142     */
3143     envp[SYS_ENV_TAG] = sysTag;
3144     envp[USR_ENV_TAG] = usrTag;
3145   }
3146
3147   return(rc);
3148 }
3149 #endif /* _AIX && !_POWER */
3150
3151 #ifdef SIA
3152
3153 /* collect the SIA parameters from a window system. */
3154
3155 static int SiaManageGreeter(
3156     int timeout,
3157     int rendition,
3158     unsigned char *title,
3159     int num_prompts,
3160     prompt_t *prompt)
3161 {
3162     int i;
3163     struct {
3164       RequestMessage  greeter_message;
3165       char            msg_buffer[256];
3166       } greeter_msg_and_buffer;
3167     RequestForm *request_form;
3168
3169     switch(rendition) 
3170       {
3171         case SIAMENUONE:
3172         case SIAMENUANY:
3173         case SIAONELINER:
3174         case SIAFORM:
3175           if (rendition == SIAFORM && dt_in_sia_ses_authent 
3176                                   && (num_prompts == 2))
3177               {
3178               /* Normal login, Password case */
3179               Debug ("SIAFORM Normal login, Password case\n");
3180               while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3181                     && siaGreeterInfo.state->id != GREET_STATE_EXIT
3182                     && (siaGreeterInfo.status = ManageGreeter(
3183                               siaGreeterInfo.d, siaGreeterInfo.greet, 
3184                               siaGreeterInfo.verify, siaGreeterInfo.state)))
3185                   ;
3186
3187               if (!siaGreeterInfo.status 
3188                       || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3189                   return(SIACOLABORT);
3190
3191               strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name, 
3192                       prompt[0].max_result_length);
3193               strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3194                       prompt[1].max_result_length);
3195               }
3196           else
3197               {
3198               char *res_ptr;
3199               char *pmpt_ptr;
3200               int req_form_size;
3201               ResponseForm *response_form;
3202
3203               switch(rendition) 
3204                   {
3205                   case SIAMENUONE:
3206                       Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3207                       break;
3208                   case SIAMENUANY:
3209                       Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3210                       break;
3211                   case SIAONELINER:
3212                       Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3213                       break;
3214                   case SIAFORM:
3215                       Debug("SIAFORM num_prompts = %d\n", num_prompts);
3216                       break;
3217                   }
3218
3219               /* need to display form */
3220
3221               req_form_size = sizeof(RequestForm) 
3222                                       + strlen((const char *)title) + 1;
3223               for (i=0; i<num_prompts; i++)
3224                   req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3225               request_form = (RequestForm *) alloca(req_form_size);
3226
3227               siaGreeterInfo.state->id = GREET_STATE_FORM;
3228               siaGreeterInfo.state->request = (RequestHeader *)request_form;
3229               /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3230
3231               request_form->hdr.opcode = REQUEST_OP_FORM;
3232               request_form->hdr.reserved = 0;
3233               request_form->hdr.length = req_form_size;
3234               request_form->num_prompts = num_prompts;
3235               request_form->rendition = rendition;
3236               request_form->offTitle = sizeof(RequestForm);
3237               request_form->offPrompts = sizeof(RequestForm) +
3238                                           strlen((const char *)title) + 1;
3239               strcpy((char *)request_form + request_form->offTitle, 
3240                       (const char *)title);
3241
3242               pmpt_ptr = (char *)request_form + request_form->offPrompts;
3243               for (i=0; i<num_prompts; i++)
3244                   {
3245                   if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3246                       *pmpt_ptr++ = '\0';
3247                   else
3248                       {
3249                       Debug("  prompt[%d]: %s\n", i, prompt[i].prompt);
3250                       strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3251                       pmpt_ptr += strlen((const char *)prompt[i].prompt);
3252                       }
3253                   request_form->visible[i] = 
3254                       (prompt[i].control_flags & SIARESINVIS) ? False : True;
3255                   }
3256
3257               siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d, 
3258                                                   siaGreeterInfo.greet,
3259                                                   siaGreeterInfo.verify, 
3260                                                   siaGreeterInfo.state);
3261
3262               response_form = (ResponseForm *)siaGreeterInfo.state->response;
3263               res_ptr = (char *)response_form + response_form->offAnswers;
3264               for (i = 0; i < response_form->num_answers; i++)
3265                   {
3266                   if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3267                       {
3268                       if (res_ptr[0])
3269                           prompt[i].result = (unsigned char *)1;
3270                       else
3271                           prompt[i].result = NULL;
3272                       }
3273                   else
3274                       {
3275                       strcpy((char *)prompt[0].result, res_ptr);
3276                       }
3277                   res_ptr += strlen(res_ptr) + 1;
3278                   }
3279               if (!response_form->collect_status)
3280                   siaGreeterInfo.status = FALSE;
3281               }
3282             break;
3283         case SIAINFO:
3284         case SIAWARNING:
3285
3286           Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3287
3288           siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3289           siaGreeterInfo.state->request = (RequestHeader *) 
3290                               &greeter_msg_and_buffer.greeter_message;
3291           siaGreeterInfo.state->vf = VF_MESSAGE;
3292           siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3293
3294           siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d, 
3295                                               siaGreeterInfo.greet,
3296                                               siaGreeterInfo.verify, 
3297                                               siaGreeterInfo.state);
3298             break;
3299         default:
3300             return(SIACOLABORT);
3301             break;
3302       }
3303     if (!siaGreeterInfo.status)
3304       return(SIACOLABORT);
3305     return(SIACOLSUCCESS);
3306 }
3307
3308 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3309 {
3310
3311     greet->name = malloc(strlen(siaHandle->name) + 1);
3312     strcpy (greet->name, siaHandle->name);
3313
3314     greet->password = malloc(strlen(siaHandle->password) + 1);
3315     strcpy (greet->password, siaHandle->password);
3316     
3317
3318 }
3319
3320 static void KillGreeter( void )
3321 {
3322     if (sia_greeter_pid)
3323       AbortClient(sia_greeter_pid);
3324     sia_greeter_pid = 0;
3325 }
3326 #endif /* SIA */