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