dtsession: implement screen lock/unlock for linux
[oweals/cde.git] / cde / programs / dtsession / SmLock.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: SmLock.c /main/8 1996/10/30 11:13:55 drk $ */
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  *****************************************************************************
32  **
33  **  File:        SmLock.c
34  **
35  **  Project:     HP DT Session Manager (dtsession)
36  **
37  **  Description:
38  **  -----------
39  **  In charge of locking and unlocking the display in response from
40  **  the front panel to so.
41  **
42  **
43  **
44  *******************************************************************
45  **  (c) Copyright Hewlett-Packard Company, 1990.  All rights are  
46  **  reserved.  Copying or other reproduction of this program      
47  **  except for archival purposes is prohibited without prior      
48  **  written consent of Hewlett-Packard Company.                     
49  ********************************************************************
50  **
51  **
52  **
53  *****************************************************************************
54  *************************************<+>*************************************/
55
56
57 #include <stdio.h>
58 #include <errno.h>
59 #include <pwd.h>
60 #include <string.h>
61 #include <fcntl.h>
62
63 #ifdef SIA
64 #include <sia.h>
65 #endif
66  
67 #ifdef USE_HP_SPECIFIC_XLIB
68 #include <X11/XHPlib.h>
69 #endif /* USE_HP_SPECIFIC_XLIB */
70
71 #include <X11/Intrinsic.h>
72 #include <Xm/Xm.h>
73 #include <Dt/UserMsg.h>
74 #include <Dt/Indicator.h>
75 #include <Tt/tttk.h>
76 #ifdef SVR4
77 # ifdef USL
78 #  include <iaf.h>
79 #  include <sys/types.h>
80 #  include <ia.h>
81 # else
82 #  include <shadow.h>
83 #endif
84 #endif
85
86 #if defined(linux)
87 # include <shadow.h>
88 #endif
89 #if defined(CSRG_BASED)
90 #include <sys/types.h>
91 #include <pwd.h>
92 #endif
93
94 #include "Sm.h"
95 #include "SmUI.h"
96 #include "SmError.h"
97 #include "SmLock.h"
98 #include "SmScreen.h"
99
100 /*
101  * Variables global to this module only
102  */
103
104 /*
105  * Global timer value
106  */
107 static XtIntervalId             timerId, lockTimeId, lockDelayId, cycleId, flash_id;
108
109 /*
110  * Global grab widget
111  */
112 static Widget                   grabWidget;
113
114 /*
115  * Lock dialog visibility
116  */
117 static Boolean                  lockDlgVisible;
118
119 #ifdef LOCK_SERVER_ACCESS
120 /* 
121  * Server Access Control Information
122  */
123 static Boolean                  RestrictingAccess = False;
124 static XHostAddress             *hostList;
125 static Bool                     hostListActive;
126 static int                      hostListLen;
127 #endif
128
129 /*
130  * Local Functions
131  */
132
133 static void FinishLocking(Widget, XtPointer, XEvent *, Boolean *);
134 static void RecolorCursor( void ) ;
135 static void EventDetected( Widget, XtPointer, XEvent *, Boolean *) ;
136 static void CheckString( char *, int ) ;
137 static Boolean CheckPassword( char * ) ;
138 #if defined (_AIX) && defined (_POWER)
139 static Boolean Authenticate( char *, uid_t, char * ) ;
140 #else
141 #define Authenticate(A,B,C) localAuthenticate(A,B,C)
142 #endif
143 static Boolean localAuthenticate( char *, uid_t, char * ) ;
144 static void UnlockDisplay( Boolean, Boolean ) ;
145 static void TakeDownLogin( XtPointer, XtIntervalId * ) ;
146 static void PutUpLogin( Boolean, Boolean ) ;
147 static void LockAttemptFailed( XtPointer, XtIntervalId *) ;
148 static void RequirePassword( XtPointer, XtIntervalId *) ;
149 static void CycleSaver( XtPointer, XtIntervalId *) ;
150 static void BlinkCaret( XtPointer, XtIntervalId *) ;
151
152 #if defined(linux)
153 /* #define JET_AUTHDEBUG */
154
155 /* Test for re-auth ability - see if we can re-authenticate via pwd,
156  * shadow, or NIS
157  */
158 static Boolean CanReAuthenticate(char *name, uid_t uid, char *passwd,
159                                  struct passwd **pwent, struct spwd **spent)
160 {
161   Boolean fail = False;
162
163   *pwent = (name == NULL) ? getpwuid(uid) : getpwnam(name);
164   *spent = getspnam((*pwent)->pw_name);
165
166 #ifdef JET_AUTHDEBUG
167   fprintf(stderr, "CanReAuthenticate(): %s %s %s\n",
168           (*pwent) ? "PWENT" : "NULL",
169           (*spent) ? "SPENT" : "NULL",
170           (name) ? name : "NULL");
171 #endif
172
173   /* some checking for aging stuff on RedPhat */
174
175   if (*pwent && (*pwent)->pw_passwd)
176     {
177       char *loc;
178
179       if ((loc = strchr((*pwent)->pw_passwd, ',')) != NULL)
180         *loc = '\0';
181 #ifdef JET_AUTHDEBUG
182       fprintf(stderr, "CanReAuthenticate(): pw: '%s'\n",
183               (*pwent)->pw_passwd);
184 #endif
185
186     }
187
188   if (*spent && (*spent)->sp_pwdp)
189     {
190       char *loc;
191
192       if ((loc = strchr((*spent)->sp_pwdp, ',')) != NULL)
193         *loc = '\0';
194     }
195
196   if (*pwent == NULL)
197     {                           /* if we can't get this, we're screwed. */
198 #ifdef JET_AUTHDEBUG
199       fprintf(stderr, "CanReAuthenticate(): PWENT == NULL - FALSE\n");
200 #endif
201       return False;
202     }
203
204   if ((*pwent)->pw_passwd == NULL)
205     {
206 #ifdef JET_AUTHDEBUG
207       fprintf(stderr, "CanReAuthenticate(): (*pwent)->pw_passwd == NULL - FALSE\n");
208 #endif
209
210       return False;
211     }
212
213   /* ok, now we have the prequisite data, look first to see if the
214    * passwd field is larger than 1 char - implying NIS, or a shadowed
215    * system.  if not look for *spent being non-NULL
216    */
217   if (*spent == NULL)
218     {                           /* if it's null, lets check for the NIS case */
219       if (strlen((*pwent)->pw_passwd) <= 1)
220         {
221 #ifdef JET_AUTHDEBUG
222           fprintf(stderr, "strlen((*pwent)->pw_passwd) <= 1\n");
223 #endif
224
225           return False;         /* not NIS */
226         }
227     }
228
229                                 /* supposedly we have valid data */
230 #ifdef JET_AUTHDEBUG
231       fprintf(stderr, "CanReAuthenticate(): TRUE\n");
232 #endif
233
234   return True;
235 }
236
237 #endif /* linux */
238
239
240
241 \f
242 /*************************************<->*************************************
243  *
244  *  LockDisplay ()
245  *
246  *
247  *  Description:
248  *  -----------
249  *  Calls the routines that are in charge of locking the display.
250  *
251  *
252  *  Inputs:
253  *  ------
254  *  lockNow - request to lock the display immediately
255  * 
256  *  Outputs:
257  *  -------
258  *
259  *  Comments:
260  *  --------
261  * 
262  *************************************<->***********************************/
263 /*
264  * Place holders for the lock position
265  */
266 static Position visibleY;
267 static Position hiddenY;
268
269 void 
270 LockDisplay( 
271   Boolean lockNow) 
272 {
273     register int i;
274     int      screenNum;
275     Widget   parent = NULL, lockDlg;
276     XColor   xcolors[2];
277     struct passwd *pw;
278     Boolean  secure;
279     int lockDelay;
280     int rc;
281
282     timerId = lockTimeId = lockDelayId = cycleId = flash_id = (XtIntervalId)0;
283
284    /*
285     * coverScreen 
286     *  0 - screen will not be covered, nor will external screen saver run
287     *  1 - screen will be covered, external screen saver may be run
288     *
289     * lockDelay
290     * -1 = no password required to unlock display
291     *  0 = password always required to unlock display
292     *  N = password required to unlock display after N seconds
293     */ 
294     if (smSaverRes.saverTimeout == 0)
295     {
296       smGD.coverScreen = 0; 
297       lockDelay = 0;        
298     }
299     else if (lockNow || smSaverRes.lockTimeout > 0)
300     {
301       smGD.coverScreen = 1; 
302       if (lockNow)
303         lockDelay = 0; 
304       else if (smSaverRes.lockTimeout == 0)
305         lockDelay = -1; 
306       else if (smSaverRes.lockTimeout <= smSaverRes.saverTimeout)
307         lockDelay = 0; 
308       else
309         lockDelay = smSaverRes.lockTimeout - smSaverRes.saverTimeout;
310     }
311     else
312     {
313       smGD.coverScreen = 1;
314       lockDelay = -1;
315     }
316
317     /*
318      * Before anything is done make sure we can unlock if we lock. 
319      */
320     if (localAuthenticate(NULL, getuid(), NULL) == False)
321        {
322         Tt_message msg;
323         PrintError(DtError, smNLS.trustedSystemErrorString);
324
325         XBell(smGD.display, 100);
326         
327         /*
328          * Tell the Workspace Manager to quit blinking
329          */
330         msg = tttk_message_create( 0, TT_NOTICE, TT_SESSION, 0,
331                                    "DtActivity_Began", 0 );
332         tt_message_send( msg );
333         tt_message_destroy( msg );
334         SetSystemReady();
335
336         return;
337     }
338      
339     if(((smDD.lockCoverDialog == NULL) && (smGD.coverScreen == True)) ||
340        ((smDD.lockDialog == NULL) && (smGD.coverScreen == False)))
341     {
342         /*
343          * Set up the grab widget in here
344          */
345         grabWidget = NULL;
346
347         /*
348          * If the user has specified cover - create the cover dialog
349          */
350         screenNum = DefaultScreen(smGD.display);
351         if(smGD.coverScreen == True)
352         {
353             for(i = (smGD.numSavedScreens - 1);i >= 0;i--)
354             {
355                 if(i == screenNum)
356                 {
357                     smDD.coverDialog[i] = CreateCoverDialog(i, True);
358                     parent = smDD.coverDrawing[i];
359                 }
360                 else
361                 {
362                     smDD.coverDialog[i] = CreateCoverDialog(i, False);
363                 }
364             }
365             smDD.lockCoverDialog = CreateLockDialogWithCover(parent);
366         }
367         
368         /*
369          * Create the lock dialog if the user has specified that
370          */
371         if((smDD.lockDialog == NULL) && (smGD.coverScreen == False))
372         {
373             smDD.lockDialog = CreateLockDialog();
374
375             /*
376              * Get colors for the password cursor
377              */
378             i = 0;
379             XtSetArg(uiArgs[i], XmNtopShadowColor, &(xcolors[0]));i++;
380             XtSetArg(uiArgs[i], XmNbottomShadowColor, &(xcolors[1]));i++;
381             XtGetValues(smDD.lockDialog, uiArgs, i);
382
383             smGD.backgroundPix = xcolors[0].pixel;
384             smGD.foregroundPix = xcolors[1].pixel;
385             if (smGD.backgroundPix == smGD.foregroundPix)
386             {
387                 smGD.backgroundPix = smGD.whitePixel;
388                 smGD.foregroundPix = smGD.blackPixel;
389             }           
390         }
391     }
392
393    /*
394     * Wait for a visibility event to occur on the window so that
395     * we can grab it
396     */
397     if(smGD.coverScreen == True)
398     {
399        smGD.lockCursor = smGD.blankCursor;
400        grabWidget = smDD.coverDialog[0];
401        lockDlg = smDD.lockCoverDialog;
402        lockDlgVisible = False; /* mappedWhenManaged False */
403     }
404     else
405     {
406        smGD.lockCursor = smGD.padlockCursor;
407        grabWidget = smDD.lockDialog;
408        lockDlg = smDD.lockDialog;
409        visibleY = hiddenY = -1;
410     }
411
412    /*
413     * Note: grabWidget must be mapped in order to grab it. This means
414     * that if coverScreen is True, smDD.coverDialog[0] must be mapped
415     * immediately and if coverScreen is False, smDD.lockDialog must be
416     * mapped immediately. Also, if a grabWidget is unmapped, the grab
417     * is lost. Ah X.
418     */
419     XtAddEventHandler(grabWidget, VisibilityChangeMask,
420                       False, FinishLocking, NULL);
421
422     XtManageChild(lockDlg);
423
424     if(smGD.coverScreen == True) {
425         flash_id = XtAppAddTimeOut(smGD.appCon,
426                                1000, BlinkCaret,smDD.indLabel[1]);
427     }
428     else{
429         flash_id = XtAppAddTimeOut(smGD.appCon,
430                                1000, BlinkCaret,smDD.indLabel[0]);
431     }
432
433     if (lockDelay > 0)
434     {
435      /*
436       * Wait for 'lockDelay' seconds before requiring a password. 
437       */
438       lockDelayId = XtAppAddTimeOut(smGD.appCon,
439                                lockDelay*1000, RequirePassword, NULL);
440   
441     }
442     else if (lockDelay == 0)
443     { 
444      /* 
445       * Immediately require a password to unlock the display.
446       */
447       smGD.lockedState = LOCKED;
448       PutUpLogin(True, False); /* map, but don't set timeout */
449     }
450
451     if (smGD.coverScreen == True && smSaverRes.cycleTimeout > 0)
452     { 
453      /*
454       * Cycle to next saver in 'cycleTimeout' seconds.
455       */
456       cycleId = XtAppAddTimeOut(smGD.appCon,
457                                smSaverRes.cycleTimeout*1000, CycleSaver, NULL);
458     }
459     
460     if(smGD.coverScreen == True)
461     {
462        for(i = (smGD.numSavedScreens - 1);i >= 0;i--)
463        {
464           XtPopup(smDD.coverDialog[i], XtGrabNone);
465        }
466     }
467
468    /*
469     * Add an event handler for when the keyboard and pointer are grabbed
470     */
471     XtAddEventHandler(grabWidget,
472                       (KeyPressMask | ButtonPressMask | PointerMotionMask),
473                       False, EventDetected, NULL);
474
475     /** wait 90 seconds for lock dialog to come up **/
476     lockTimeId = XtAppAddTimeOut(smGD.appCon,
477                                  90000, LockAttemptFailed, lockDlg);
478     return;
479 }
480
481
482 \f
483 /*************************************<->*************************************
484  *
485  *  FinishLocking ()
486  *
487  *
488  *  Description:
489  *  -----------
490  *  After the lock dialog is up - do the grab and lock the display
491  *
492  *
493  *  Inputs:
494  *  ------
495  * 
496  *  Outputs:
497  *  -------
498  *
499  *  Comments:
500  *  --------
501  * 
502  *************************************<->***********************************/
503 static void 
504 FinishLocking(Widget            wid,
505               XtPointer         ptr,
506               XEvent            *ev,
507               Boolean           *bl)
508 {
509     int i,j;
510     Boolean kbdGrabbed, pointerGrabbed;
511     int rc;
512
513         if (lockTimeId == (XtIntervalId)0)
514           return;
515
516         XtRemoveTimeOut(lockTimeId); 
517         lockTimeId = (XtIntervalId)0;
518         XtRemoveEventHandler(wid, VisibilityChangeMask,
519                              False, FinishLocking, NULL);
520         XSync(smGD.display, 0);
521
522         i = 0;
523         XtSetArg(uiArgs[i], XmNy, &visibleY);i++;
524         XtGetValues(wid, uiArgs, i);
525
526         hiddenY = (Position) DisplayHeight(smGD.display, smGD.screen) + 15;
527
528         /*
529          * Color the cursor for this color scheme
530          */
531         RecolorCursor();
532
533         XSync(smGD.display, 0);
534
535         /*
536          * grab control of the keyboard for the entire display
537          */
538         rc = XtGrabKeyboard(grabWidget, False,
539                                      GrabModeAsync, GrabModeAsync,
540                                      CurrentTime);
541         kbdGrabbed = (rc == GrabSuccess);
542
543 #ifdef USE_HP_SPECIFIC_XLIB
544        XHPDisableReset(smGD.display);
545 #endif /* USE_HP_SPECIFIC_XLIB */
546
547 #if defined (AIXV3) && !defined(_POWER)
548        if(smGD.secureSystem)
549        {
550          SM_SETEUID(smGD.unLockUID);
551          AixEnableHftRing(0);
552          SM_SETEUID(smGD.runningUID);
553        }
554 #endif
555
556         pointerGrabbed = (XtGrabPointer(grabWidget, False,
557                                         ButtonPressMask|PointerMotionMask,
558                                         GrabModeAsync, GrabModeAsync,
559                                         None, smGD.lockCursor, CurrentTime)
560                           == GrabSuccess);
561
562         {
563           pointerGrabbed = (XtGrabPointer(grabWidget, False,
564                                         ButtonPressMask|PointerMotionMask,
565                                         GrabModeAsync, GrabModeAsync,
566                                         None, smGD.lockCursor, CurrentTime)
567                             == GrabSuccess);
568         }
569
570
571         /*
572          * If the grab failed - try 3 more times and give up
573          */
574         if((kbdGrabbed == False) || (pointerGrabbed == False))
575         {
576             for(j = 0;(j < 3) && ((pointerGrabbed == False) ||
577                                   (kbdGrabbed == False));j++)
578             {
579                 /*
580                  * If a grab fails try one more time and then give up
581                  */
582                 if(kbdGrabbed == False)
583                 {
584                     sleep(1);
585                     kbdGrabbed = (XtGrabKeyboard(grabWidget, False,
586                                                  GrabModeAsync, GrabModeAsync,
587                                                  CurrentTime) == GrabSuccess);
588                 }
589
590                 if(pointerGrabbed == False)
591                 {
592                     sleep(1);
593                     pointerGrabbed = (XtGrabPointer(grabWidget, False,
594                                                     ButtonPressMask |
595                                                     PointerMotionMask,
596                                                     GrabModeAsync,
597                                                     GrabModeAsync,
598                                                     None, smGD.lockCursor,
599                                                     CurrentTime)
600                                       == GrabSuccess);
601                 }
602             }
603         }
604
605
606         /*
607          * Set status variable to lock if the lock has succeeded
608          */
609         if((pointerGrabbed != True) || (kbdGrabbed != True))
610         {
611             PrintError(DtError, smNLS.cantLockErrorString);
612             smGD.lockedState = UNLOCKED;
613             UnlockDisplay(pointerGrabbed, kbdGrabbed);
614         }
615         else
616         {
617
618 #ifdef LOCK_SERVER_ACCESS
619             /*
620              *  Wipe & enable X server access control list
621              */
622             hostList = XListHosts(smGD.display,
623                 &hostListLen, (Bool *) &hostListActive);
624             XRemoveHosts(smGD.display, hostList, hostListLen);
625             XEnableAccessControl(smGD.display);
626             RestrictingAccess = True;
627 #endif
628  
629             PutUpLogin(False, True); /* already mapped, but set timeout */
630
631            /*
632             * Start external screen saver.
633             */
634             if (smGD.coverScreen)
635             {
636               StartScreenSaver();
637             }
638         }
639
640     return;
641 }
642
643 \f
644 /*************************************<->*************************************
645  *
646  *  CreateLockCursor ()
647  *
648  *
649  *  Description:
650  *  -----------
651  *  Creates a padlock cursor if the user has specified lock.  Creates a
652  *  blank cursor if the user has specified cover.  Both are specified in the
653  *  users resource file.
654  * 
655  *
656  *
657  *  Inputs:
658  *  ------
659  *  buttonForm = widget from which cursor gets its color
660  *  smGD.coverScreen = (global) cover screen or put up a padlock
661  
662  *
663  * 
664  *  Outputs:
665  *  -------
666  *  smGD.lockCursor = (global) cursor when lock is active (blank or padlock)
667  *
668  *  Comments:
669  *  --------
670  * 
671  *************************************<->***********************************/
672 #define lock_m_hot_x    16
673 #define lock_m_hot_y    16
674 #define lock_m_bm_width 32
675 #define lock_m_bm_height 32
676 static unsigned char lock_m_bm_bits[] = {
677    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00,
678    0x00, 0xfc, 0x9f, 0x00, 0x00, 0x0e, 0x90, 0x01, 0x00, 0x06, 0x80, 0x01,
679    0x00, 0x06, 0x80, 0x01, 0x00, 0x06, 0x80, 0x01, 0x00, 0x06, 0x80, 0x01,
680    0x00, 0x06, 0x80, 0x01, 0x00, 0x06, 0x80, 0x01, 0x00, 0x06, 0x80, 0x01,
681    0x00, 0x06, 0x80, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c,
682    0x80, 0xaa, 0xaa, 0x0e, 0x00, 0x55, 0x55, 0x0f, 0x80, 0xaa, 0xaa, 0x0e,
683    0x00, 0x55, 0x55, 0x0f, 0x80, 0xaa, 0xaa, 0x0e, 0x00, 0x55, 0x55, 0x0f,
684    0x80, 0xaa, 0xaa, 0x0e, 0x00, 0x55, 0x55, 0x0f, 0x80, 0xaa, 0xaa, 0x0e,
685    0x00, 0x55, 0x55, 0x0f, 0x80, 0xaa, 0xaa, 0x0e, 0x00, 0x55, 0x55, 0x0f,
686    0x80, 0xaa, 0xaa, 0x0e, 0x00, 0x55, 0x55, 0x0f, 0x80, 0xaa, 0xaa, 0x0e,
687    0xc0, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0x0f};
688
689 #define lock_m_m_bm_width 32
690 #define lock_m_m_bm_height 32
691 static unsigned char lock_m_m_bm_bits[] = {
692    0x00, 0xf8, 0x1f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00,
693    0x00, 0xff, 0xff, 0x00, 0x80, 0x0f, 0xf0, 0x01, 0x80, 0x07, 0xe0, 0x01,
694    0x80, 0x07, 0xe0, 0x01, 0x80, 0x07, 0xe0, 0x01, 0x80, 0x07, 0xe0, 0x01,
695    0x80, 0x07, 0xe0, 0x01, 0x80, 0x07, 0xe0, 0x01, 0x80, 0x07, 0xe0, 0x01,
696    0x80, 0x07, 0xe0, 0x01, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
697    0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
698    0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
699    0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
700    0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
701    0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
702    0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f};
703
704 #define lock_s_hot_x    7
705 #define lock_s_hot_y    8
706 #define lock_s_bm_width 13
707 #define lock_s_bm_height 16
708 static unsigned char lock_s_bm_bits[] = {
709    0x00, 0x02, 0x00, 0x04, 0xf0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
710    0x00, 0x00, 0xa8, 0x1a, 0x54, 0x1d, 0xa8, 0x1a, 0x54, 0x1d, 0xa8, 0x1a,
711    0x54, 0x1d, 0xa8, 0x1a, 0x54, 0x1d, 0xfe, 0x1f};
712
713 #define lock_s_m_bm_width 13
714 #define lock_s_m_bm_height 16
715 static unsigned char lock_s_m_bm_bits[] = {
716    0xf8, 0x03, 0xfc, 0x07, 0xfe, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
717    0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f,
718    0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f};
719
720 void 
721 CreateLockCursor( void )
722 {
723     Pixmap source, mask;
724     Colormap cmap = XDefaultColormap(smGD.display, smGD.screen);
725     XColor xcolors[2];
726     char noCursorBits = 0x1;
727
728     if(InitCursorInfo() == False)
729     {
730         /*
731          * Create the SMALL padlock cursor
732          */
733         source = XCreateBitmapFromData(smGD.display,
734                                        XRootWindow(smGD.display,
735                                                    smGD.screen),
736                                        (char *) lock_s_bm_bits,
737                                        lock_s_bm_width,
738                                        lock_s_bm_height);
739         mask = XCreateBitmapFromData(smGD.display,
740                                      XRootWindow(smGD.display,
741                                                  smGD.screen),
742                                      (char *) lock_s_m_bm_bits,
743                                      lock_s_m_bm_width,
744                                      lock_s_m_bm_height);
745
746         /* translate the Pixels into XColors */
747         xcolors[0].pixel = smGD.blackPixel;
748         xcolors[1].pixel = smGD.whitePixel;
749         XQueryColors(smGD.display, cmap, xcolors, 2);
750
751         /* create the padlock cursor */
752         smGD.padlockCursor = XCreatePixmapCursor(smGD.display, source, mask,
753                                               &(xcolors[0]), &(xcolors[1]),
754                                               lock_s_hot_x,
755                                               lock_s_hot_y);
756         XFreePixmap(smGD.display, source);
757         XFreePixmap(smGD.display, mask);
758     }
759     else
760     {
761         /*
762          * Create the LARGE padlock cursor
763          */
764         source = XCreateBitmapFromData(smGD.display,
765                                        XRootWindow(smGD.display,
766                                                    smGD.screen),
767                                        (char *) lock_m_bm_bits,
768                                        lock_m_bm_width,
769                                        lock_m_bm_height);
770         mask = XCreateBitmapFromData(smGD.display,
771                                      XRootWindow(smGD.display,
772                                                  smGD.screen),
773                                      (char *) lock_m_m_bm_bits,
774                                      lock_m_m_bm_width,
775                                      lock_m_m_bm_height);
776
777         /* translate the Pixels into XColors */
778         xcolors[0].pixel = smGD.blackPixel;
779         xcolors[1].pixel = smGD.whitePixel;
780         XQueryColors(smGD.display, cmap, xcolors, 2);
781
782         /* create the padlock cursor */
783         smGD.padlockCursor = XCreatePixmapCursor(smGD.display, source, mask,
784                                                  &(xcolors[0]), &(xcolors[1]),
785                                                  lock_m_hot_x,
786                                                  lock_m_hot_y);
787         XFreePixmap(smGD.display, source);
788         XFreePixmap(smGD.display, mask);
789     }
790
791     /*
792      *
793      * create the blank cursor
794      */
795     source = XCreateBitmapFromData(smGD.display,
796                                    XRootWindow(smGD.display, smGD.screen),
797                                    &noCursorBits, 1, 1);
798
799     xcolors[0].pixel = smGD.blackPixel;
800     XQueryColor(smGD.display, cmap, &(xcolors[0]));
801     smGD.blankCursor = XCreatePixmapCursor(smGD.display, source, source,
802                                           &(xcolors[0]), &(xcolors[0]),
803                                           0, 0);
804     XFreePixmap(smGD.display, source);
805 }
806
807
808 \f
809 /*************************************<->*************************************
810  *
811  *  RecolorCursor ()
812  *
813  *
814  *  Description:
815  *  -----------
816  *  Recolors the padlock cursor to be the current color scheme.  This has
817  *  to be done because XCreatePixmapCursor allocates colors instead of jusst
818  *  using a pixel value.
819  * 
820  *
821  *
822  *  Inputs:
823  *  ------
824  *  smGD.backgroundPix = Pixel value to use for background color
825  *  smGD.foregroundPix = Pixel value to use for foreground color
826  *
827  * 
828  *  Outputs:
829  *  -------
830  *  smGD.lockCursor = (global) cursor when lock is active (padlock)
831  *
832  *  Comments:
833  *  --------
834  * 
835  *************************************<->***********************************/
836 static void 
837 RecolorCursor( void )
838 {
839     Colormap cmap = XDefaultColormap(smGD.display, smGD.screen);
840     XColor xcolors[2];
841
842     /*
843      * translate the Pixels into XColors
844      */
845     xcolors[0].pixel = smGD.foregroundPix;
846     xcolors[1].pixel = smGD.backgroundPix;
847     XQueryColors(smGD.display, cmap, xcolors, 2);
848
849     /*
850      * recolor the padlock cursor
851      */
852     XRecolorCursor(smGD.display, smGD.lockCursor, &(xcolors[0]),
853                    &(xcolors[1]));
854 }
855
856
857 \f
858 /*************************************<->*************************************
859  *
860  *  EventDetected (w, client_data, event)
861  *
862  *
863  *  Description:
864  *  -----------
865  *  Callback routine that detects an event when the display is locked.
866  *  If it's a correct password, it unlocks the display.  Otherwise, it
867  *  just displays status.  The event is detected by the popup login dialog.
868  *
869  *
870  *  Inputs:
871  *  ------
872  *  w = widget where event occured
873  *  client_data = client specific data sent to callback
874  *  event = event that triggered callback
875  *
876  * 
877  *  Outputs:
878  *  -------
879  *
880  *  Comments:
881  *  --------
882  * 
883  *************************************<->***********************************/
884 static void 
885 EventDetected(
886               Widget w,
887               XtPointer client_data,
888               XEvent *ev,
889               Boolean *bl)
890 {
891     char str[256];
892     int len;
893     XKeyEvent   *event = (XKeyEvent *) ev;
894    
895     if (smGD.lockedState == LOCKED)
896     {
897       if (lockDlgVisible == False)
898       {
899        /*
900         * Anytime input is received - show the passwd dialog and
901         * discard event. This is so a keypress event that causes
902         * the passwd dialog to appear will not be used in the password.
903         * CMVC 612.
904         */
905         PutUpLogin(True, True); /* map, and reset timeout */
906         return;
907       }
908       PutUpLogin(False, True); /* already mapped, but reset timeout */
909     }
910     else 
911     {
912       UnlockDisplay(True, True);
913       return;
914     }
915
916     /*
917      * If the detected event is anything but a keypress, processing is
918      * complete after refreshing the status string.
919      */
920     if (event->type != KeyPress)
921         return;
922
923     /*
924      * If XLookupString() returns anything (which it won't in the case of, say,
925      * pressing the shift key or an arrow key), process it.
926      */
927 #ifdef USE_HP_SPECIFIC_XLIB
928     if (len = XHPConvertLookup(event, str, sizeof(str), NULL, NULL,
929                                XHPGetEurasianCvt(smGD.display)))
930 #else /* USE_HP_SPECIFIC_XLIB */
931     if (len = XLookupString (event, str, sizeof(str), NULL, NULL))
932 #endif /* USE_HP_SPECIFIC_XLIB */
933     {
934         if (smGD.lockedState == LOCKED)
935             CheckString(str, len);
936     }
937 }
938
939
940 \f
941 /*************************************<->*************************************
942  *
943  *  CheckString (s, i)
944  *
945  *
946  *  Description:
947  *  -----------
948  *  Check string entered by user.  If it is a valid password, call routine to
949  *  unlock the display.  Otherwise, just keep track of what we have until
950  *  the password is valid
951  *
952  *
953  *  Inputs:
954  *  ------
955  *  s = string passed in for checking
956  *  i = length of string
957  *
958  * 
959  *  Outputs:
960  *  -------
961  *
962  *  Comments:
963  *  --------
964  * 
965  *************************************<->***********************************/
966 static void 
967 CheckString(
968         register char *s,
969         register int i )
970 {
971     /*
972      * password rules:
973      *  - Only the first eight characters are used.
974      *  - If pw_length > 8, we've gone over eight characters and won't
975      *    accept any more.
976      *  - An ESC kills the line.
977      */
978 #ifdef SIA
979     static char passwd[82];           /* password space */
980 #else
981     static char passwd[10];             /* password space */
982 #endif
983     static int pw_length = 0;           /* password length */
984
985     if (s == NULL)
986     {
987      /*
988       * Clear password.
989       */
990       pw_length = 0;
991       return;
992     }
993     
994     for (; i>0; s++,i--)
995     {
996         switch(*s)
997         {
998             case '\010':
999                 if (pw_length)
1000                     pw_length--;                /* back up one character */
1001                 break;
1002                 
1003             case '\e':
1004                 pw_length = 0;                  /* kill the character string */
1005                 break;
1006
1007             case '\n':
1008             case '\r':
1009 #ifdef SIA
1010                 if (pw_length > 80)
1011                 {
1012                     pw_length = 80;
1013                 }
1014 #else
1015                 if (pw_length > 8)
1016                 {
1017                     pw_length = 8;
1018                 }
1019 #endif
1020                 passwd[pw_length] = '\0';       /* terminate string */
1021                 pw_length = 0;                  /* reset length */
1022                 if (CheckPassword(passwd))
1023                 {
1024                     UpdatePasswdField(0);
1025                     UnlockDisplay(True, True);
1026                     return;
1027                 }
1028                 XBell(smGD.display, 100);       /* wrong, laserbreath */
1029                 break;
1030
1031             default:
1032 #ifdef SIA
1033                 if (pw_length < 80)
1034 #else
1035                 if (pw_length < 8)
1036 #endif
1037                     passwd[pw_length] = *s;     /* store character */
1038                 /*
1039                  * The length is incremented no matter what, so the user can
1040                  * think the program handles multi-thousand-character
1041                  * passwords.  If the user types twenty characters and eighteen
1042                  * erases (#), the result will be the first two characters
1043                  * entered, as expected.  Up to a point -- 65536 is long
1044                  * enough!
1045                  */
1046                 if (pw_length < 65535)
1047                     pw_length++;
1048                 break;
1049         }
1050     }
1051
1052     if(pw_length > 8)
1053     {
1054         UpdatePasswdField(8);
1055     }
1056     else
1057     {
1058         UpdatePasswdField(pw_length);
1059     }
1060 }
1061
1062
1063 \f
1064 /*************************************<->*************************************
1065  *
1066  *  CheckPassword (passwd)
1067  *
1068  *
1069  *  Description:
1070  *  -----------
1071  *  Check the password to see if it is the user's, roots, or one of the
1072  *  users specified in the host string
1073  *
1074  *
1075  *  Inputs:
1076  *  ------
1077  *  passwd = password passed in
1078  *
1079  * 
1080  *  Outputs:
1081  *  -------
1082  *  True if it is a valid password, false otherwise.
1083  *
1084  *  Comments:
1085  *  --------
1086  * 
1087  *************************************<->***********************************/
1088 static Boolean 
1089 CheckPassword(
1090         char *passwd )
1091 {
1092     char *p, *q;
1093     char *keyholderbuf;
1094
1095     if (Authenticate(NULL, getuid(), passwd) == True)
1096     {   
1097       return(True);  /* user password ok */
1098     }
1099
1100     if (Authenticate(NULL, 0, passwd) == True)
1101     {
1102       return(True);  /* root password ok */
1103     }
1104
1105     /* check passwords of users specified as keyholders */
1106     if (smGD.keyholders == NULL)
1107     {
1108         return(False);                  /* no keyholders */
1109     }
1110
1111     /* since strtok() is destructive, copy the keyholders string */
1112     keyholderbuf = (char *) SM_MALLOC(strlen(smGD.keyholders)+1);
1113     if(keyholderbuf == NULL)
1114     {
1115         PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1116         return(False); /* no memory */
1117     }
1118     
1119     strcpy(keyholderbuf, smGD.keyholders);
1120     for (p = keyholderbuf; (q = strtok(p, ", \t")) != NULL; p = NULL)
1121     {
1122         if (Authenticate(q, -1, passwd) == True)
1123         {
1124           SM_FREE(keyholderbuf);
1125           return(True); /* keyholder password ok */
1126         }
1127     }
1128     SM_FREE(keyholderbuf);
1129
1130     return(False); /* no matches */
1131 }
1132
1133
1134 \f
1135 /*************************************<->*************************************
1136  *
1137  *  UnlockDisplay ()
1138  *
1139  *
1140  *  Description:
1141  *  -----------
1142  *  If the user has entered a correct password, unlock the display and
1143  *  uncover the root window.
1144  *
1145  *
1146  *  Inputs:
1147  *  ------
1148  *  pointerGrabbed - Boolean tells if pointer is currently grabbed
1149  *  kbdGrabbed - Boolean tells if keyboard is currently grabbed
1150  *
1151  * 
1152  *  Outputs:
1153  *  -------
1154  *
1155  *
1156  *  Comments:
1157  *  --------
1158  * 
1159  *************************************<->***********************************/
1160 static void 
1161 UnlockDisplay(
1162         Boolean pointerGrabbed,
1163         Boolean kbdGrabbed)
1164 {
1165     int i;
1166     Tt_message msg;
1167
1168 #ifdef LOCK_SERVER_ACCESS
1169     /*
1170      * Restore X server access state
1171      */
1172     if (RestrictingAccess) {
1173         XAddHosts(smGD.display, hostList, hostListLen);
1174         if (!hostListActive) XDisableAccessControl(smGD.display);
1175         RestrictingAccess = False;
1176         XFree((void *) hostList);
1177     }
1178 #endif
1179
1180     /*
1181      * Stop external screen saver.
1182      */
1183     StopScreenSaver();
1184
1185     /*
1186      * Remove the event handler to grab the events
1187      */
1188     XtRemoveEventHandler(grabWidget,
1189                          (KeyPressMask | ButtonPressMask | PointerMotionMask),
1190                          False, EventDetected, NULL);
1191
1192     /*
1193      * Turn off alarms
1194      */
1195     if(lockDelayId != (XtIntervalId)0)
1196     {
1197         XtRemoveTimeOut(lockDelayId);
1198     }
1199
1200     if(cycleId != (XtIntervalId)0)
1201     {
1202         XtRemoveTimeOut(cycleId);
1203     }
1204
1205     if(timerId != (XtIntervalId)0)
1206     {
1207         XtRemoveTimeOut(timerId);
1208     }
1209
1210     if(flash_id != (XtIntervalId)0)
1211     {
1212         XtRemoveTimeOut(flash_id);
1213     }
1214
1215     if(pointerGrabbed == True)
1216     {
1217         XtUngrabPointer(grabWidget, CurrentTime);
1218     }
1219
1220     if(kbdGrabbed == True)
1221     {
1222         XtUngrabKeyboard(grabWidget, CurrentTime);
1223     }
1224     
1225 #ifdef USE_HP_SPECIFIC_XLIB
1226     XHPEnableReset(smGD.display);
1227 #endif /* USE_HP_SPECIFIC_XLIB */
1228
1229 #if defined (AIXV3) && !defined(_POWER)
1230     if(smGD.secureSystem)
1231     {
1232       SM_SETEUID(smGD.unLockUID);
1233       AixEnableHftRing(1);
1234       SM_SETEUID(smGD.runningUID);
1235     }
1236 #endif
1237
1238     XSync(smGD.display, 0);
1239
1240    /*
1241     * Unmanage session lock dialogs. If LOCKDLG_PERSIST is undefined,
1242     * destroy them. This is so the passwd dialog icon colors get freed
1243     * since currently it uses a lot of colors. 
1244     */
1245     if(smGD.coverScreen == False) 
1246     {
1247 #if defined (LOCKDLG_PERSIST)
1248         if (XtIsManaged(smDD.lockDialog))
1249         {
1250           XtUnmanageChild(smDD.lockDialog);
1251         }
1252 #else
1253         XtDestroyWidget(smDD.lockDialog);
1254         smDD.lockDialog = NULL;
1255 #endif
1256     }
1257     else
1258     {
1259 #if defined (LOCKDLG_PERSIST)
1260         if(!XtIsManaged(smDD.lockCoverDialog))
1261         {
1262             XtManageChild(smDD.lockCoverDialog);
1263         }
1264         
1265         for(i = (smGD.numSavedScreens - 1);i >= 0;i--)
1266         {
1267             XtPopdown(smDD.coverDialog[i]);
1268         }
1269 #else
1270         for(i = (smGD.numSavedScreens - 1);i >= 0;i--)
1271         {
1272             XtDestroyWidget(smDD.coverDialog[i]);
1273             smDD.coverDialog[i] = NULL;
1274         }
1275         smDD.lockCoverDialog = NULL;
1276 #endif
1277     }
1278
1279     smGD.lockedState = UNLOCKED;
1280
1281     XSync(smGD.display, 0);
1282
1283     /*
1284      * Tell the Workspace Manager to unlock the display (depress the lock
1285      * button)
1286     if(smGD.bmsDead == False)
1287     {
1288         msg = tttk_message_create(0, TT_REQUEST, TT_SESSION, 0,
1289                                   "Display_Unlock", 0);
1290         tt_message_send(msg);
1291         tt_message_destroy(msg);
1292     }
1293      */
1294
1295     SetSystemReady();
1296     
1297 }
1298
1299 static Position visibleY = -1;
1300 static Position hiddenY = -1;
1301
1302 \f
1303 /*************************************<->*************************************
1304  *
1305  *  TakeDownLogin ()
1306  *
1307  *
1308  *  Description:
1309  *  -----------
1310  *  When a timeout occurs - take down the login screen by unmanaging it.
1311  *
1312  *
1313  *  Inputs:
1314  *  ------
1315  *
1316  * 
1317  *  Outputs:
1318  *  -------
1319  *
1320  *
1321  *  Comments:
1322  *  --------
1323  * 
1324  *************************************<->***********************************/
1325 static void 
1326 TakeDownLogin(
1327         XtPointer client_data,
1328         XtIntervalId *id )
1329 {
1330   if (lockDlgVisible == True)
1331   {
1332     if (smGD.coverScreen == True)
1333     {
1334       XtUnmapWidget(smDD.lockCoverDialog);
1335     }
1336     else
1337     {
1338       if (hiddenY > -1)
1339       {
1340         int i = 0;
1341         XtSetArg(uiArgs[i], XmNy, hiddenY);i++;
1342         XtSetValues(smDD.lockDialog, uiArgs, i);
1343       }
1344     }
1345     
1346     timerId = (XtIntervalId)0; 
1347
1348    /*
1349     * Clear partially entered password if any.
1350     */
1351     CheckString(NULL, 0);
1352     lockDlgVisible = False;
1353
1354     XSync(smGD.display, 0);
1355   }
1356 }
1357
1358 \f
1359 /*************************************<->*************************************
1360  *
1361  *  PutUpLogin ()
1362  *
1363  *
1364  *  Description:
1365  *  -----------
1366  *  Redisplays the cover and the login when neccessary.
1367  *
1368  *
1369  *  Inputs:
1370  *  ------
1371  *
1372  * 
1373  *  Outputs:
1374  *  -------
1375  *
1376  *
1377  *  Comments:
1378  *  --------
1379  * 
1380  *************************************<->***********************************/
1381 static void 
1382 PutUpLogin(
1383   Boolean map,
1384   Boolean timeout )
1385 {
1386   if (map == True && lockDlgVisible == False)
1387   {
1388     if (smGD.coverScreen == True)
1389     {
1390       XtMapWidget(smDD.lockCoverDialog);
1391     }
1392     else
1393     {
1394       if (visibleY > -1)
1395       {
1396         int i = 0;
1397         XtSetArg(uiArgs[i], XmNy, visibleY);i++;
1398         XtSetValues(smDD.lockDialog, uiArgs, i);
1399       }
1400     }
1401     lockDlgVisible = True;
1402   }
1403
1404   if (timeout == True)
1405   {
1406     if(timerId != (XtIntervalId)0)
1407     {
1408         XtRemoveTimeOut(timerId);
1409     }
1410  
1411     if(smRes.alarmTime > 0)
1412     {
1413         timerId = XtAppAddTimeOut(smGD.appCon,
1414                                   (smRes.alarmTime * 1000),
1415                                   TakeDownLogin,NULL);
1416     }
1417   }
1418   XSync(smGD.display, 0);
1419 }
1420
1421 \f
1422 /*************************************<->*************************************
1423  *
1424  *  LockAttemptFailed ()
1425  *
1426  *
1427  *  Description:
1428  *  -----------
1429  *  Timed out trying to get a visibilitynotify on the lock
1430  *
1431  *
1432  *  Inputs:
1433  *  ------
1434  *
1435  * 
1436  *  Outputs:
1437  *  -------
1438  *
1439  *
1440  *  Comments:
1441  *  --------
1442  * 
1443  *************************************<->***********************************/
1444 static void 
1445 LockAttemptFailed(XtPointer     ptr,
1446                   XtIntervalId  *invId)
1447 {
1448     Widget lockWid = (Widget) ptr;
1449     
1450     PrintError(DtError, smNLS.cantLockErrorString);
1451     smGD.lockedState = UNLOCKED;
1452     XtRemoveEventHandler(lockWid, VisibilityChangeMask,
1453                          False, FinishLocking, NULL);
1454     UnlockDisplay(False, False);
1455     XSync(smGD.display, 0);
1456 }
1457
1458
1459
1460 \f
1461 /*************************************<->*************************************
1462  *
1463  *  RequirePassword ()
1464  *
1465  *
1466  *  Description:
1467  *  -----------
1468  *  Callback indicating a password is now required to unlock display.
1469  *
1470  *
1471  *  Inputs:
1472  *  ------
1473  *
1474  * 
1475  *  Outputs:
1476  *  -------
1477  *
1478  *
1479  *  Comments:
1480  *  --------
1481  * 
1482  *************************************<->***********************************/
1483 static void 
1484 RequirePassword(XtPointer       ptr,
1485                   XtIntervalId  *invId)
1486 {
1487   smGD.lockedState = LOCKED;
1488 }
1489
1490
1491 /*************************************<->*************************************
1492  *
1493  *  BlinkCaret ()
1494  *
1495  *
1496  *  Description:
1497  *  -----------
1498  *  blinks the caret in the password field
1499  *
1500  *
1501  *  Inputs:
1502  *  ------
1503  *
1504  *
1505  *  Outputs:
1506  *  -------
1507  *
1508  *
1509  *  Comments:
1510  *  --------
1511  *
1512  *************************************<->***********************************/
1513 static void
1514 BlinkCaret(XtPointer    ptr,
1515                   XtIntervalId  *invId)
1516 {
1517 static int flag = 1;
1518 XmString tmpString;
1519 int i;
1520  
1521  /*
1522   * Blink cursor to show the focus ..
1523   */
1524   if(flag){
1525      tmpString = XmStringCreateLocalized (" " );
1526      i = 0;
1527      XtSetArg(uiArgs[i], XmNlabelString,     tmpString); i++;
1528      XtSetValues(ptr, uiArgs, i);
1529      flag = 0;
1530   }
1531   else{
1532      tmpString = XmStringCreateLocalized ("|");
1533      i = 0;
1534      XtSetArg(uiArgs[i], XmNlabelString,     tmpString); i++;
1535      XtSetValues(ptr, uiArgs, i);
1536      flag = 1;
1537   }
1538  
1539   XmStringFree(tmpString);
1540   flash_id = XtAppAddTimeOut(smGD.appCon, 1000,
1541                             BlinkCaret, ptr);
1542 }
1543
1544
1545 \f
1546 /*************************************<->*************************************
1547  *
1548  *  CycleSaver ()
1549  *
1550  *
1551  *  Description:
1552  *  -----------
1553  *  Callback indicating we should cycle to next screen saver
1554  *
1555  *
1556  *  Inputs:
1557  *  ------
1558  *
1559  * 
1560  *  Outputs:
1561  *  -------
1562  *
1563  *
1564  *  Comments:
1565  *  --------
1566  * 
1567  *************************************<->***********************************/
1568 static void 
1569 CycleSaver(XtPointer    ptr,
1570                   XtIntervalId  *invId)
1571 {
1572  /*
1573   * Stop running screen saver, start a new one and reset timer.
1574   */
1575   StopScreenSaver();
1576   StartScreenSaver();  
1577   cycleId = XtAppAddTimeOut(smGD.appCon, smSaverRes.cycleTimeout*1000,
1578                             CycleSaver, NULL);
1579 }
1580
1581
1582 \f
1583 /*************************************<->*************************************
1584  *
1585  *  localAuthenticate (name, uid, passwd)
1586  *
1587  *
1588  *  Description:
1589  *  -----------
1590  *
1591  *
1592  *  Inputs:
1593  *  ------
1594  *
1595  * 
1596  *  Outputs:
1597  *  -------
1598  *
1599  *  Comments:
1600  *  --------
1601  * 
1602  *************************************<->***********************************/
1603 static Boolean 
1604 localAuthenticate(
1605         char *name,
1606         uid_t uid,
1607         char *passwd )
1608 #ifdef SIA
1609
1610
1611
1612   {
1613     char *Argv[2] = { "dtsession", NULL };
1614
1615     SIAENTITY *se = NULL;
1616     int code;
1617     char *  pw_name;
1618     uid_t real_uid;
1619
1620
1621     real_uid = getuid();
1622
1623     if (-1 == seteuid(0))
1624       return FALSE;
1625
1626
1627     if (passwd == NULL)
1628     {
1629       /*
1630       * Caller just checking if it is possible to access 
1631       * password file (ie is dtsession suid bit set properly).
1632       */
1633       seteuid(real_uid);
1634       return TRUE;
1635     }
1636     if (name && name[0])
1637       pw_name = name;
1638     else if (uid == 0)
1639       pw_name = "root";
1640     else
1641       pw_name = getlogin();
1642
1643
1644     if ( sia_ses_init(&se, 1, Argv, (char *)NULL,
1645                       pw_name, NULL, 0 /* don't collect info */, 
1646                       NULL) != SIASUCCESS)
1647       {
1648       seteuid(real_uid);
1649       return FALSE;
1650       }
1651     
1652     se->password = (char *)malloc(strlen(passwd) + 1);
1653     if ( se->password == (char *)NULL ) 
1654     {
1655         sia_ses_release(&se);
1656       seteuid(real_uid);
1657       return FALSE;
1658     }
1659
1660     strcpy(se->password, passwd);
1661
1662     code = sia_ses_reauthent (NULL, se);
1663     sia_ses_release(&se);
1664
1665     seteuid(real_uid);
1666
1667     if ( code == SIASUCCESS )
1668       return TRUE;
1669     else
1670       return FALSE;
1671 }
1672     
1673 #elif defined(linux)
1674
1675 {
1676     struct passwd *pwent = NULL;
1677     char *p, *q;
1678     char *crypt();
1679     Boolean rc = True;
1680     Boolean done = False;
1681     struct spwd *sp = NULL;
1682
1683     if(smGD.secureSystem)
1684     {   
1685       SM_SETEUID(smGD.unLockUID);
1686     }
1687
1688    /*
1689     * Get password entry for 'name' or 'uid'.
1690     */
1691     if (CanReAuthenticate(name, uid, passwd, &pwent, &sp) == False)
1692     {
1693      /*
1694       * Can't get entry.
1695       */
1696       rc = False;
1697       done = True;
1698     }
1699
1700     if(smGD.secureSystem)
1701     {
1702         SM_SETEUID(smGD.runningUID);
1703     }
1704
1705     if (done == False)
1706     {
1707
1708       if (pwent->pw_passwd == NULL || pwent->pw_passwd[0] == '*')
1709       {
1710                                 /* check sp */
1711         if (sp == NULL || sp->sp_pwdp == NULL)
1712           {
1713             /*
1714              * Could not read password.
1715              */
1716             rc = False;
1717             done = True;
1718           }
1719       }
1720     }
1721
1722     if (done == False)
1723     {
1724       if (passwd == NULL)
1725       {
1726        /*
1727         * Caller just checking if it is possible to access 
1728         * password file (ie is dtsession suid bit set properly).
1729         */
1730         rc = True; 
1731         done = True;
1732       }
1733     }
1734
1735     if (done == False)
1736     {
1737      /*
1738       * Check password.
1739       */
1740
1741       if (sp != NULL && !strcmp(sp->sp_pwdp, crypt(passwd,sp->sp_pwdp)))
1742         {                       /* a shadow match */
1743           rc = True;
1744           done = True;
1745         }
1746       else if (pwent != NULL && 
1747                !strcmp(pwent->pw_passwd, crypt(passwd, pwent->pw_passwd)))
1748         {                       /* passwd match */
1749           rc = True;
1750           done = True;
1751         }
1752       else
1753         {                       /* failure dude! */
1754           rc = False;
1755           done = True;
1756         }
1757     }
1758
1759     endpwent();
1760     endspent();
1761
1762     return(rc);
1763 }
1764
1765 #else
1766
1767 {
1768     register struct passwd *pwent;
1769     char *p, *q;
1770     char *crypt();
1771     Boolean rc = True;
1772     Boolean done = False;
1773
1774
1775 #ifdef SVR4
1776 # ifdef USL
1777     uinfo_t uinfo;
1778     char *upasswd, *newname = NULL;
1779 # else
1780     struct spwd *sp=NULL;
1781 # endif
1782 #endif
1783
1784     if(smGD.secureSystem)
1785     {   
1786         SM_SETEUID(smGD.unLockUID);
1787     }
1788
1789 #ifdef SVR4
1790    /*
1791     * Get shadow password entry for 'name' or 'uid'.
1792     */
1793     if (name == NULL)
1794     {
1795       pwent = getpwuid(uid);
1796       if (pwent != NULL) 
1797       {
1798 # ifdef USL
1799         name = newname = strdup(pwent->pw_name);
1800 # else
1801         name = pwent->pw_name;
1802 #endif
1803       }
1804     }
1805
1806     if (name == NULL ||
1807 # ifdef USL
1808         ia_openinfo(name, &uinfo)
1809 # else
1810         (sp = getspnam(name)) == NULL
1811 # endif
1812         )
1813     {
1814      /*
1815       * Can't get entry.
1816       */
1817       rc = False;
1818       done = True;
1819     }
1820 #else  /* SVR4 */
1821    /*
1822     * Get password entry for 'name' or 'uid'.
1823     */
1824     if ((pwent = (name == NULL ? getpwuid(uid) : getpwnam(name))) == NULL)
1825     {
1826      /*
1827       * Can't get entry.
1828       */
1829       rc = False;
1830       done = True;
1831     }
1832 #endif /* SVR4 */
1833
1834     if(smGD.secureSystem)
1835     {
1836         SM_SETEUID(smGD.runningUID);
1837     }
1838
1839     if (done == False)
1840     {
1841 #ifdef USL
1842         ia_get_logpwd(uinfo, &upasswd);
1843 #endif
1844       if (
1845           pwent->pw_passwd == NULL 
1846           || pwent->pw_passwd[0] == '*'
1847 #ifdef SVR4
1848 # ifdef USL
1849           || upasswd == NULL
1850 # else
1851           || sp == NULL
1852 # endif
1853 #endif
1854           )
1855       {
1856        /*
1857         * Could not read password.
1858         */
1859         rc = False;
1860         done = True;
1861       }
1862     }
1863
1864     if (done == False)
1865     {
1866       if (passwd == NULL)
1867       {
1868        /*
1869         * Caller just checking if it is possible to access 
1870         * password file (ie is dtsession suid bit set properly).
1871         */
1872         rc = True; 
1873         done = True;
1874       }
1875     }
1876
1877     if (done == False)
1878     {
1879      /*
1880       * Check password.
1881       */
1882 #ifdef SVR4
1883 # ifdef USL
1884       if (strcmp(crypt(passwd, upasswd), upasswd) != 0)
1885 # else
1886       if (strcmp(crypt(passwd,sp->sp_pwdp),sp->sp_pwdp) != 0)
1887 # endif
1888 #else
1889       if (strcmp(pwent->pw_passwd, crypt(passwd, pwent->pw_passwd)) != 0)
1890 #endif
1891       {
1892        /*
1893         * Password incorrect.
1894         */
1895         rc = False;
1896         done = True;
1897       }
1898     }
1899
1900     endpwent();
1901 #ifdef SVR4
1902 # ifdef USL
1903     ia_closeinfo(uinfo);
1904     if (newname) free(newname);
1905 # else
1906     endspent();
1907 # endif
1908 #endif
1909
1910     return(rc);
1911 }
1912 #endif /* SIA */
1913
1914 \f
1915 /*************************************<->*************************************
1916  *
1917  *  Authenticate (name, uid, passwd)
1918  *
1919  *
1920  *  Description:
1921  *  -----------
1922  *
1923  *
1924  *  Inputs:
1925  *  ------
1926  *
1927  * 
1928  *  Outputs:
1929  *  -------
1930  *
1931  *  Comments:
1932  *  --------
1933  * 
1934  *************************************<->***********************************/
1935
1936 #if defined (_AIX) && defined(_POWER)
1937
1938 static Boolean 
1939 Authenticate(
1940         char *name,
1941         uid_t uid,
1942         char *passwd )
1943 {
1944     register struct passwd *pwent;
1945     char *p, *q;
1946     char *crypt();
1947     Boolean rc = True;
1948     Boolean done = False;
1949
1950     int arc;
1951     int reenter;
1952     char *newname = NULL;
1953     char *msg;
1954
1955     if(smGD.secureSystem)
1956     {
1957         SM_SETEUID(smGD.unLockUID);
1958     }
1959
1960    /*
1961     * Map uid to name.
1962     */
1963     if (name == NULL)
1964     {
1965       pwent = getpwuid(uid);
1966       if (pwent != NULL)
1967       {
1968         name = newname = strdup(pwent->pw_name);
1969       }
1970       endpwent();
1971     }
1972  
1973    /* 
1974     * Authenticate user. Note: normally, we should check 'reenter' to
1975     * see if the user has another challenge. Since the dtsession screen
1976     * lock i/f does not yet have the support, our policy is to let the
1977     * user back in if they pass the first (password) challenge.
1978     */ 
1979     arc = authenticate(name, passwd, &reenter, &msg);
1980
1981     if(smGD.secureSystem)
1982     {
1983         SM_SETEUID(smGD.runningUID);
1984     }
1985
1986     if (msg) free(msg);
1987     if (newname) free(newname);
1988
1989     return(arc == 0 ? True : False);
1990 }
1991 #endif /* _AIX && _POWER */
1992