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