ftp.nice.ch/pub/next/tools/screen/BackSpace.1.02.N.bs.tar.gz#/BackSpace/backspace/Password.m

This is Password.m in view mode; [Download] [Up]

// 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.

#import "Password.h"
#import "Thinker.h"
#import "SpaceView.h"
#import "psfuncts.h"
#import "Localization.h"
#import <appkit/View.h>
#import <appkit/Panel.h>
#import <appkit/Application.h>
#import <appkit/TextField.h>
#import <appkit/TextFieldCell.h>
#import <appkit/graphics.h>
#import <appkit/defaults.h>
#import <libc.h>
#import <math.h>
#import <pwd.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[] = "xxxxxxxxxxxxxxxxxxx";	
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 : LocalString("Setting password.  Enter old password:",0,0)
			randomPos:NO checkLock:NO withView:nil])
		return nil;


	[self attemptToSetPassword:
		LocalString("Enter new password:\n(NOT your account password!)",0,0)];
	safe_strcpy(attempt2, attempt1);
	[self attemptToSetPassword: LocalString("Reenter new password:",0,0)];

	if (!strcmp(attempt1, attempt2)) 
	{
		safe_strcpy(password, attempt1);
		NXWriteDefault([NXApp appName], "encryptedPassword", password);
		ret = self;
	}
	else
	{
		[[infoText cell] setStringValue:
			LocalString("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() + 5000;
	char tsalt[3];
	
	if ((!lockEnabled && check) || !password[0]) 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];
			NXPing ();	// Synchronize postscript for smoother animation
			[[aView window] flushWindow];
			[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() );
		tsalt[0] = pwen->pw_passwd[0];
		tsalt[1] = pwen->pw_passwd[1];
		tsalt[2] = 0;
		ret = (!strcmp(pwen->pw_passwd,
			(crypt((char *)[[clearText cell] stringValue], tsalt))));
		//printf("user passwd = %s, scratch = %s\n", pwen->pw_passwd, scratch);
	}

	// on user password failure, try root password
	if (!ret)
	{
		struct passwd *pwen = getpwnam("root");
		tsalt[0] = pwen->pw_passwd[0];
		tsalt[1] = pwen->pw_passwd[1];
		tsalt[2] = 0;
		ret = (!strcmp(pwen->pw_passwd,
			(crypt((char *)[[clearText cell] stringValue], tsalt))));
		//printf("root passwd = %s, scratch = %s\n", pwen->pw_passwd, scratch);
	}

	[[clearText cell] setStringValue: mess];
	[[clearText cell] setStringValue: unMess];



	// did we get a valid password?
	if (!ret)
	{
		[[infoText cell] setStringValue:
			LocalString("Error: Incorrect password.",0,0)];
		[self activePauseWithView:aView];
	}
	
    [NXApp endModalSession:&session];

	[window orderOut:self];
	[window center];
	
	// this display shouldn't be necessary, but is to ensure timely
	// redraw of a nonretained window.  It looks shitty, though.
	[aView display];
	return ret;
}

- orderWindowToFront
{
	[clearText selectText:self];
	[window display];

	// make password window float over everything
	setWindowLevel([window windowNum],(SAVERTIER+1));

	[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];
			NXPing ();	// Synchronize postscript for smoother animation
			[[aView window] flushWindow];
		   } 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

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.