home *** CD-ROM | disk | FTP | other *** search
- // Password.m
- //
- // implements a simple password protocol for a small amount of security
- // as a screen locker. Can be passed in a view to animate while
- // waiting for events to verify a password. This class isn't as stand-alone
- // as it might be, because it sucks its UI stuff out of a nib and relies
- // on the nib for a couple of connections, but that could be fixed.
- //
- // You may freely copy, distribute, and reuse the code in this example.
- // NeXT disclaims any warranty of any kind, expressed or implied, as to its
- // fitness for any particular use.
-
-
- #import "Password.h"
- #import "SpaceView.h"
- #import "psfuncts.h"
-
-
- #import <appkit/appkit.h>
- #import <pwd.h>
- #import <objc/NXBundle.h>
-
-
- @interface TileView:View
- @end
- @implementation TileView
- - drawSelf:(const NXRect *)rects :(int)rectCount
- {
- if (!rects || !rectCount) return self;
- NXDrawButton(&bounds, &bounds);
- return self;
- }
- @end
-
- @implementation Password
-
- static const char mess[] = " ";
- static const char unMess[] = "";
- static const char salt[] = "Uh";
-
- - init
- {
- const char *ptr;
-
- lockEnabled = NO;
-
- ptr = NXGetDefaultValue([NXApp appName], "encryptedPassword");
- if (ptr) safe_strcpy(password, ptr);
-
- return self;
- }
-
- - setPassword:sender
- {
- id ret;
-
- if (![self checkPassword : NXLocalString("Setting password. Enter old password:",0,0)
- randomPos:NO checkLock:NO withView:nil])
- return nil;
-
-
- [self attemptToSetPassword:
- NXLocalString("Enter new password:\n(NOT your account password!)",0,0)];
- safe_strcpy(attempt2, attempt1);
- [self attemptToSetPassword: NXLocalString("Reenter new password:",0,0)];
-
- if (!strcmp(attempt1, attempt2))
- {
- safe_strcpy(password, attempt1);
- NXWriteDefault([NXApp appName], "encryptedPassword", password);
- ret = self;
- }
- else
- {
- [[infoText cell] setStringValue:
- NXLocalString("Error: Passwords didn't match.",0,0)];
- ret = nil;
- [self activePauseWithView:nil];
- }
-
- [window orderOut:self];
- return ret;
- }
-
- - attemptToSetPassword:(const char *)text
- {
- if (!window) [self createWindow];
-
- [[infoText cell] setStringValue:text];
- [self orderWindowToFront];
-
- [NXApp runModalFor:window];
-
- //hey! I didn't want runmodal to put my window away!
- [self orderWindowToFront];
-
- safe_strcpy(attempt1,
- (const char *)(crypt((char *)[[clearText cell] stringValue],
- (char *)salt)));
- [[clearText cell] setStringValue: mess];
- [[clearText cell] setStringValue: unMess];
-
- return self;
- }
-
- - userTypedReturn:sender
- {
- [NXApp stopModal];
- return self;
- }
-
- - (BOOL) checkPassword:(const char *)text randomPos:(BOOL)random
- checkLock:(BOOL)check withView:aView
- {
- BOOL ret;
- NXModalSession session;
- BStimeval timeout = currentTimeInMs() + 6000;
-
- // we check lock to pass if the screen is locked
- // otherwise we always want to verify password
- if ((!lockEnabled && check) || !password[0]) return YES;
-
- // here I allow passage if password has been typed in last 6 seconds
- // NOT! I seem to have had some problems with time wrapping, I nixed this for security
- // if (currentTimeInMs() < (lastPasswordTime + 6000)) return YES;
-
- if (!window) [self createWindow];
-
- [NXApp beginModalSession:&session for:window];
-
- [[infoText cell] setStringValue:text];
-
- if (random) [self randomWindowPosition];
- else [window center];
- [self orderWindowToFront];
-
- for (;;) {
- if ([NXApp runModalSession:&session] != NX_RUNCONTINUES)
- break;
-
- if (currentTimeInMs() > timeout) break;
-
- if (aView)
- {
- [aView lockFocus];
- if ([aView respondsTo:@selector(didLockFocus)])
- [aView didLockFocus];
- [aView oneStep];
- [[aView window] flushWindow];
- NXPing (); // Synchronize postscript for smoother animation
- [aView unlockFocus];
- }
- }
-
- ret = (!strcmp(password,
- (crypt((char *)[[clearText cell] stringValue], (char *)salt))));
-
- // on BackSpace password failure, try user password
- if (!ret)
- {
- struct passwd *pwen = getpwuid( getuid() );
- ret = (!strcmp(pwen->pw_passwd,
- (crypt((char *)[[clearText cell] stringValue], pwen->pw_passwd))));
- }
-
- // on user password failure, try root password (only if there is one)
- if (!ret)
- {
- struct passwd *pwen = getpwuid(0);
- if (strlen(pwen->pw_passwd) == 0) ret = 0;
- else ret = (!strcmp(pwen->pw_passwd,
- (crypt((char *)[[clearText cell] stringValue], pwen->pw_passwd))));
- }
-
- [[clearText cell] setStringValue: mess];
- [[clearText cell] setStringValue: unMess];
-
-
-
- // did we get a valid password?
- if (!ret)
- {
- [[infoText cell] setStringValue:
- NXLocalString("Error: Incorrect password.",0,0)];
- [self activePauseWithView:aView];
- }
- else
- {
- lastPasswordTime = currentTimeInMs();
- }
-
- [window orderOut:self];
- [window center];
-
- [NXApp endModalSession:&session];
-
- // this display shouldn't be necessary, but is to ensure timely
- // redraw of a nonretained window. It looks yucky, though.
- // really should just display area uncovered by panel
- [aView display];
- return ret;
- }
-
- - orderWindowToFront
- {
- [clearText selectText:self];
- [window display];
-
- // make password window float over everything
- PSsetwindowlevel((SAVERTIER+1), [window windowNum]);
-
- [window makeKeyAndOrderFront:self];
- return self;
- }
-
- - randomWindowPosition
- {
- NXRect r;
- NXSize s;
- NXPoint p;
- [NXApp getScreenSize:&s];
- [window getFrame:&r];
- p.x = floor(randBetween(0, s.width - r.size.width));
- p.y = floor(randBetween(0, s.height - r.size.height));
-
- [window moveTo: p.x :p.y];
-
- return self;
- }
-
-
- - createWindow
- {
- NXRect r;
- id tileView;
-
- [contentBox getFrame:&r];
- r.origin.x = r.origin.y = 8;
- [contentBox setFrame:&r];
- r.size.width += 16;
- r.size.height += 16;
-
- window = [[Window alloc]
- initContent:&r style:NX_PLAINSTYLE
- backing:NX_BUFFERED buttonMask:0 defer:NO];
-
- [window center];
- tileView = [[TileView alloc] init];
-
- [contentBox removeFromSuperview]; //not really necessary
- [[window setContentView:tileView] free];
- [tileView addSubview:contentBox];
-
- [window useOptimizedDrawing:YES];
- [window display];
-
- return self;
- }
-
- - activePauseWithView:aView
- {
- BStimeval done;
-
- [window display];
- NXPing();
- done = currentTimeInMs() + 1500;
- if (aView)
- {
- [aView lockFocus];
- if ([aView respondsTo:@selector(didLockFocus)]) [aView didLockFocus];
-
- do {
- [aView oneStep];
- [[aView window] flushWindow];
- NXPing (); // Synchronize postscript for smoother animation
- } while (currentTimeInMs() < done);
-
- [aView unlockFocus];
- }
- else usleep(1500000);
- return self;
- }
-
- - setLock:(BOOL)flag;
- {
- lockEnabled = flag;
- return self;
- }
-
- - (BOOL) isLocked
- {
- return lockEnabled;
- }
-
- - (BOOL) validPassword
- {
- if (password[0]) return YES;
- return NO;
- }
-
- // this function just protects me from overrunning to, which
- // is assumed to always be of length LEN
- void safe_strcpy(char *to, const char *from)
- {
- if (strlen((char *)from) < LEN) strcpy(to,(char *)from);
- else strncpy(to,(char *)from,(LEN-1));
- }
-
- @end
-