home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Utilities / Fiend-1.4.1-src / Password.m < prev    next >
Encoding:
Text File  |  1995-08-29  |  6.7 KB  |  310 lines

  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("BackSpace", "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("BackSpace", "encryptedPassword", password);
  71.         ret = self;
  72.     }
  73.     else
  74.     {
  75.         [infoText setStringValue:NXLocalString("Error: Passwords didn't match.",0,0)];
  76.         ret = nil;
  77.         [self activePauseWithView:nil];
  78.     }
  79.  
  80.     [window orderOut:self];
  81.     return ret;
  82. }
  83.  
  84. - attemptToSetPassword:(const char *)text
  85. {
  86.     if (!window) [self createWindow];
  87.     
  88.     [infoText setStringValue:text];
  89.     [self orderWindowToFront];
  90.  
  91.     [NXApp runModalFor:window];
  92.  
  93.     safe_strcpy(attempt1, 
  94.         (const char *)(crypt((char *)[clearText stringValue],
  95.         (char *)salt)));
  96.     [clearText setStringValue: mess];
  97.     [clearText setStringValue: unMess];
  98.  
  99.     //hey!  I didn't want runmodal to put my window away!
  100.     [self orderWindowToFront];
  101.  
  102.     return self;
  103. }
  104.  
  105. - userTypedReturn:sender
  106. {
  107.     [NXApp stopModal];
  108.     return self;
  109. }
  110.  
  111. - (BOOL) checkPassword:(const char *)text randomPos:(BOOL)random 
  112.     checkLock:(BOOL)check withView:aView
  113. {
  114.     BOOL ret;
  115.     NXModalSession session;
  116.     BStimeval timeout = currentTimeInMs() + 6000;
  117.  
  118.     // we check lock to pass if the screen is locked
  119.     // otherwise we always want to verify password
  120.     if ((!lockEnabled && check) || !password[0]) return YES;
  121.     
  122.     // here I allow passage if password has been typed in last 6 seconds
  123.     // NOT! I seem to have had some problems with time wrapping, I nixed this for security
  124.     // if (currentTimeInMs() < (lastPasswordTime + 6000)) return YES;
  125.     
  126.     if (!window) [self createWindow];
  127.  
  128.     [NXApp beginModalSession:&session for:window];
  129.  
  130.     [infoText setStringValue:text];
  131.     
  132.     if (random)
  133.         [self randomWindowPosition];
  134.     else
  135.         [window center];
  136.     [self orderWindowToFront];
  137.  
  138.     [clearText setStringValue:mess];
  139.     [clearText setStringValue:unMess];
  140.     [clearText selectText:self];
  141.  
  142.     for (;;) {
  143.         if ([NXApp runModalSession:&session] != NX_RUNCONTINUES)
  144.             break;
  145.             
  146.         if (currentTimeInMs() > timeout) break;
  147.  
  148.         if (aView)
  149.         {
  150.             [aView lockFocus];
  151.             if ([aView respondsTo:@selector(didLockFocus)]) 
  152.                 [aView didLockFocus];
  153.             [aView oneStep];
  154.             [[aView window] flushWindow];
  155.             NXPing ();    // Synchronize postscript for smoother animation
  156.             [aView unlockFocus];
  157.         }
  158.     }
  159.  
  160.     ret = (!strcmp(password, 
  161.         (crypt((char *)[clearText stringValue], (char *)salt))));
  162.  
  163.     // on BackSpace password failure, try user password
  164.     if (!ret)
  165.     {
  166.         struct passwd *pwen = getpwuid( getuid() );
  167.         ret = (!strcmp(pwen->pw_passwd,
  168.             (crypt((char *)[clearText stringValue], pwen->pw_passwd))));
  169.     }
  170.  
  171.     // on user password failure, try root password (only if there is one)
  172.     if (!ret)
  173.     {
  174.         struct passwd *pwen = getpwuid(0);
  175.         if (strlen(pwen->pw_passwd) == 0) ret = 0;
  176.         else ret = (!strcmp(pwen->pw_passwd,
  177.             (crypt((char *)[clearText stringValue], pwen->pw_passwd))));
  178.     }
  179.  
  180.     // did we get a valid password?
  181.     if (!ret)
  182.     {
  183.         [infoText setStringValue:NXLocalString("Error: Incorrect password.",0,0)];
  184.         [self activePauseWithView:aView];
  185.     }
  186.     else
  187.     {
  188.         lastPasswordTime = currentTimeInMs();
  189.     }
  190.     
  191.     [window orderOut:self];
  192.     [window center];
  193.     
  194.     [NXApp endModalSession:&session];
  195.  
  196.     // this display shouldn't be necessary, but is to ensure timely
  197.     // redraw of a nonretained window.  It looks yucky, though.
  198.     // really should just display area uncovered by panel
  199.     [aView display];
  200.     return ret;
  201. }
  202.  
  203. - orderWindowToFront
  204. {
  205.     // make password window float over everything
  206.     PSsetwindowlevel((SAVERTIER+1), [window windowNum]);
  207.  
  208. //    [[[clearText setStringValue:""] selectText:self] display];
  209.     [window makeKeyAndOrderFront:self];
  210.  
  211.     return self;
  212. }
  213.  
  214. - randomWindowPosition
  215. {
  216.     NXRect r;
  217.     NXSize s;
  218.     NXPoint p;
  219.     [NXApp getScreenSize:&s];
  220.     [window getFrame:&r];
  221.     p.x = floor(randBetween(0, s.width - r.size.width));
  222.     p.y = floor(randBetween(0, s.height - r.size.height));
  223.     
  224.     [window moveTo: p.x :p.y];
  225.  
  226.     return self;
  227. }
  228.  
  229.  
  230. - createWindow
  231. {
  232.     NXRect r;
  233.     id tileView;
  234.     
  235.     [contentBox getFrame:&r];
  236.     r.origin.x = r.origin.y = 8;
  237.     [contentBox setFrame:&r];
  238.     r.size.width += 16;
  239.     r.size.height += 16;
  240.     
  241.     window = [[Window alloc]
  242.             initContent:&r style:NX_PLAINSTYLE
  243.             backing:NX_BUFFERED buttonMask:0 defer:NO];
  244.  
  245.     [window center];
  246.     tileView = [[TileView alloc] init];
  247.     
  248.     [contentBox removeFromSuperview];        //not really necessary
  249.     [[window setContentView:tileView] free];
  250.     [tileView addSubview:contentBox];
  251.  
  252.     [window useOptimizedDrawing:YES];
  253.     [window display];
  254.     
  255.     return self;
  256. }
  257.  
  258. - activePauseWithView:aView
  259. {
  260.     BStimeval done;
  261.     
  262.     [window display];
  263.     NXPing();
  264.     done = currentTimeInMs() + 1500;
  265.     if (aView)
  266.     {
  267.         [aView lockFocus];
  268.         if ([aView respondsTo:@selector(didLockFocus)]) [aView didLockFocus];
  269.  
  270.         do {
  271.             [aView oneStep];
  272.             [[aView window] flushWindow];
  273.             NXPing ();    // Synchronize postscript for smoother animation
  274.            } while (currentTimeInMs() < done);
  275.            
  276.         [aView unlockFocus];
  277.     }
  278.     else
  279.         thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, 1500);
  280.  
  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
  310.