|
|
1.1 root 1: // Password.m
2: //
3: // implements a simple password protocol for a small amount of security
4: // as a screen locker. Can be passed in a view to animate while
5: // waiting for events to verify a password. This class isn't as stand-alone
6: // as it might be, because it sucks its UI stuff out of a nib and relies
7: // on the nib for a couple of connections, but that could be fixed.
8: //
9: // You may freely copy, distribute, and reuse the code in this example.
10: // NeXT disclaims any warranty of any kind, expressed or implied, as to its
11: // fitness for any particular use.
12:
13:
14: #import "Password.h"
15: #import "SpaceView.h"
16: #import "psfuncts.h"
17:
18:
19: #import <appkit/appkit.h>
20: #import <pwd.h>
21: #import <objc/NXBundle.h>
22:
23:
24: @interface TileView:View
25: @end
26: @implementation TileView
27: - drawSelf:(const NXRect *)rects :(int)rectCount
28: {
29: if (!rects || !rectCount) return self;
30: NXDrawButton(&bounds, &bounds);
31: return self;
32: }
33: @end
34:
35: @implementation Password
36:
37: static const char mess[] = " ";
38: static const char unMess[] = "";
39: static const char salt[] = "Uh";
40:
41: - init
42: {
43: const char *ptr;
44:
45: lockEnabled = NO;
46:
47: ptr = NXGetDefaultValue([NXApp appName], "encryptedPassword");
48: if (ptr) safe_strcpy(password, ptr);
49:
50: return self;
51: }
52:
53: - setPassword:sender
54: {
55: id ret;
56:
57: if (![self checkPassword : NXLocalString("Setting password. Enter old password:",0,0)
58: randomPos:NO checkLock:NO withView:nil])
59: return nil;
60:
61:
62: [self attemptToSetPassword:
63: NXLocalString("Enter new password:\n(NOT your account password!)",0,0)];
64: safe_strcpy(attempt2, attempt1);
65: [self attemptToSetPassword: NXLocalString("Reenter new password:",0,0)];
66:
67: if (!strcmp(attempt1, attempt2))
68: {
69: safe_strcpy(password, attempt1);
70: NXWriteDefault([NXApp appName], "encryptedPassword", password);
71: ret = self;
72: }
73: else
74: {
75: [[infoText cell] setStringValue:
76: NXLocalString("Error: Passwords didn't match.",0,0)];
77: ret = nil;
78: [self activePauseWithView:nil];
79: }
80:
81: [window orderOut:self];
82: return ret;
83: }
84:
85: - attemptToSetPassword:(const char *)text
86: {
87: if (!window) [self createWindow];
88:
89: [[infoText cell] setStringValue:text];
90: [self orderWindowToFront];
91:
92: [NXApp runModalFor:window];
93:
94: //hey! I didn't want runmodal to put my window away!
95: [self orderWindowToFront];
96:
97: safe_strcpy(attempt1,
98: (const char *)(crypt((char *)[[clearText cell] stringValue],
99: (char *)salt)));
100: [[clearText cell] setStringValue: mess];
101: [[clearText cell] setStringValue: unMess];
102:
103: return self;
104: }
105:
106: - userTypedReturn:sender
107: {
108: [NXApp stopModal];
109: return self;
110: }
111:
112: - (BOOL) checkPassword:(const char *)text randomPos:(BOOL)random
113: checkLock:(BOOL)check withView:aView
114: {
115: BOOL ret;
116: NXModalSession session;
117: BStimeval timeout = currentTimeInMs() + 6000;
118:
119: // we check lock to pass if the screen is locked
120: // otherwise we always want to verify password
121: if ((!lockEnabled && check) || !password[0]) return YES;
122:
123: // here I allow passage if password has been typed in last 6 seconds
124: // NOT! I seem to have had some problems with time wrapping, I nixed this for security
125: // if (currentTimeInMs() < (lastPasswordTime + 6000)) return YES;
126:
127: if (!window) [self createWindow];
128:
129: [NXApp beginModalSession:&session for:window];
130:
131: [[infoText cell] setStringValue:text];
132:
133: if (random) [self randomWindowPosition];
134: else [window center];
135: [self orderWindowToFront];
136:
137: for (;;) {
138: if ([NXApp runModalSession:&session] != NX_RUNCONTINUES)
139: break;
140:
141: if (currentTimeInMs() > timeout) break;
142:
143: if (aView)
144: {
145: [aView lockFocus];
146: if ([aView respondsTo:@selector(didLockFocus)])
147: [aView didLockFocus];
148: [aView oneStep];
149: [[aView window] flushWindow];
150: NXPing (); // Synchronize postscript for smoother animation
151: [aView unlockFocus];
152: }
153: }
154:
155: ret = (!strcmp(password,
156: (crypt((char *)[[clearText cell] stringValue], (char *)salt))));
157:
158: // on BackSpace password failure, try user password
159: if (!ret)
160: {
161: struct passwd *pwen = getpwuid( getuid() );
162: ret = (!strcmp(pwen->pw_passwd,
163: (crypt((char *)[[clearText cell] stringValue], pwen->pw_passwd))));
164: }
165:
166: // on user password failure, try root password (only if there is one)
167: if (!ret)
168: {
169: struct passwd *pwen = getpwuid(0);
170: if (strlen(pwen->pw_passwd) == 0) ret = 0;
171: else ret = (!strcmp(pwen->pw_passwd,
172: (crypt((char *)[[clearText cell] stringValue], pwen->pw_passwd))));
173: }
174:
175: [[clearText cell] setStringValue: mess];
176: [[clearText cell] setStringValue: unMess];
177:
178:
179:
180: // did we get a valid password?
181: if (!ret)
182: {
183: [[infoText cell] setStringValue:
184: NXLocalString("Error: Incorrect password.",0,0)];
185: [self activePauseWithView:aView];
186: }
187: else
188: {
189: lastPasswordTime = currentTimeInMs();
190: }
191:
192: [window orderOut:self];
193: [window center];
194:
195: [NXApp endModalSession:&session];
196:
197: // this display shouldn't be necessary, but is to ensure timely
198: // redraw of a nonretained window. It looks yucky, though.
199: // really should just display area uncovered by panel
200: [aView display];
201: return ret;
202: }
203:
204: - orderWindowToFront
205: {
206: [clearText selectText:self];
207: [window display];
208:
209: // make password window float over everything
210: PSsetwindowlevel((SAVERTIER+1), [window windowNum]);
211:
212: [window makeKeyAndOrderFront:self];
213: return self;
214: }
215:
216: - randomWindowPosition
217: {
218: NXRect r;
219: NXSize s;
220: NXPoint p;
221: [NXApp getScreenSize:&s];
222: [window getFrame:&r];
223: p.x = floor(randBetween(0, s.width - r.size.width));
224: p.y = floor(randBetween(0, s.height - r.size.height));
225:
226: [window moveTo: p.x :p.y];
227:
228: return self;
229: }
230:
231:
232: - createWindow
233: {
234: NXRect r;
235: id tileView;
236:
237: [contentBox getFrame:&r];
238: r.origin.x = r.origin.y = 8;
239: [contentBox setFrame:&r];
240: r.size.width += 16;
241: r.size.height += 16;
242:
243: window = [[Window alloc]
244: initContent:&r style:NX_PLAINSTYLE
245: backing:NX_BUFFERED buttonMask:0 defer:NO];
246:
247: [window center];
248: tileView = [[TileView alloc] init];
249:
250: [contentBox removeFromSuperview]; //not really necessary
251: [[window setContentView:tileView] free];
252: [tileView addSubview:contentBox];
253:
254: [window useOptimizedDrawing:YES];
255: [window display];
256:
257: return self;
258: }
259:
260: - activePauseWithView:aView
261: {
262: BStimeval done;
263:
264: [window display];
265: NXPing();
266: done = currentTimeInMs() + 1500;
267: if (aView)
268: {
269: [aView lockFocus];
270: if ([aView respondsTo:@selector(didLockFocus)]) [aView didLockFocus];
271:
272: do {
273: [aView oneStep];
274: [[aView window] flushWindow];
275: NXPing (); // Synchronize postscript for smoother animation
276: } while (currentTimeInMs() < done);
277:
278: [aView unlockFocus];
279: }
280: else usleep(1500000);
281: return self;
282: }
283:
284: - setLock:(BOOL)flag;
285: {
286: lockEnabled = flag;
287: return self;
288: }
289:
290: - (BOOL) isLocked
291: {
292: return lockEnabled;
293: }
294:
295: - (BOOL) validPassword
296: {
297: if (password[0]) return YES;
298: return NO;
299: }
300:
301: // this function just protects me from overrunning to, which
302: // is assumed to always be of length LEN
303: void safe_strcpy(char *to, const char *from)
304: {
305: if (strlen((char *)from) < LEN) strcpy(to,(char *)from);
306: else strncpy(to,(char *)from,(LEN-1));
307: }
308:
309: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.