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