Created
          July 16, 2009 03:29 
        
      - 
      
 - 
        
Save autoxr/148142 to your computer and use it in GitHub Desktop.  
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | + (BOOL)_copyPathWithForcedAuthentication:(NSString *)src toPath:(NSString *)dst error:(NSError **)error | |
| { | |
| NSString *tmp = [self _temporaryCopyNameForPath:dst]; | |
| const char* srcPath = [src fileSystemRepresentation]; | |
| const char* tmpPath = [tmp fileSystemRepresentation]; | |
| const char* dstPath = [dst fileSystemRepresentation]; | |
| struct stat dstSB; | |
| stat(dstPath, &dstSB); | |
| AuthorizationRef auth = NULL; | |
| OSStatus authStat = errAuthorizationDenied; | |
| while (authStat == errAuthorizationDenied) { | |
| authStat = AuthorizationCreate(NULL, | |
| kAuthorizationEmptyEnvironment, | |
| kAuthorizationFlagDefaults, | |
| &auth); | |
| } | |
| BOOL res = NO; | |
| if (authStat == errAuthorizationSuccess) { | |
| res = YES; | |
| char uidgid[42]; | |
| snprintf(uidgid, sizeof(uidgid), "%d:%d", | |
| dstSB.st_uid, dstSB.st_gid); | |
| const char* executables[] = { | |
| "/bin/rm", | |
| "/bin/mv", | |
| "/bin/mv", | |
| "/bin/rm", | |
| NULL, // pause here and do some housekeeping before | |
| // continuing | |
| "/usr/sbin/chown", | |
| NULL // stop here for real | |
| }; | |
| // 4 is the maximum number of arguments to any command, | |
| // including the NULL that signals the end of an argument | |
| // list. | |
| const char* const argumentLists[][4] = { | |
| { "-rf", tmpPath, NULL }, // make room for the temporary file... this is kinda unsafe; should probably do something better. | |
| { "-f", dstPath, tmpPath, NULL }, // mv | |
| { "-f", srcPath, dstPath, NULL }, // mv | |
| { "-rf", tmpPath, NULL }, // rm | |
| { NULL }, // pause | |
| { "-R", uidgid, dstPath, NULL }, // chown | |
| { NULL } // stop | |
| }; | |
| // Process the commands up until the first NULL | |
| int commandIndex = 0; | |
| for (; executables[commandIndex] != NULL; ++commandIndex) { | |
| if (res) | |
| res = AuthorizationExecuteWithPrivilegesAndWait(auth, executables[commandIndex], kAuthorizationFlagDefaults, argumentLists[commandIndex]); | |
| } | |
| // If the currently-running application is trusted, the new | |
| // version should be trusted as well. Remove it from the | |
| // quarantine to avoid a delay at launch, and to avoid | |
| // presenting the user with a confusing trust dialog. | |
| // | |
| // This needs to be done after the application is moved to its | |
| // new home with "mv" in case it's moved across filesystems: if | |
| // that happens, "mv" actually performs a copy and may result | |
| // in the application being quarantined. It also needs to be | |
| // done before "chown" changes ownership, because the ownership | |
| // change will almost certainly make it impossible to change | |
| // attributes to release the files from the quarantine. | |
| if (res) { | |
| [self releaseFromQuarantine:dst]; | |
| } | |
| // Now move past the NULL we found and continue executing | |
| // commands from the list. | |
| ++commandIndex; | |
| for (; executables[commandIndex] != NULL; ++commandIndex) { | |
| if (res) | |
| res = AuthorizationExecuteWithPrivilegesAndWait(auth, executables[commandIndex], kAuthorizationFlagDefaults, argumentLists[commandIndex]); | |
| } | |
| AuthorizationFree(auth, 0); | |
| if (!res) | |
| { | |
| // Something went wrong somewhere along the way, but we're not sure exactly where. | |
| NSString *errorMessage = [NSString stringWithFormat:@"Authenticated file copy from %@ to %@ failed.", src, dst]; | |
| if (error != NULL) | |
| *error = [NSError errorWithDomain:SUSparkleErrorDomain code:SUAuthenticationFailure userInfo:[NSDictionary dictionaryWithObject:errorMessage forKey:NSLocalizedDescriptionKey]]; | |
| } | |
| } | |
| else | |
| { | |
| if (error != NULL) | |
| *error = [NSError errorWithDomain:SUSparkleErrorDomain code:SUAuthenticationFailure userInfo:[NSDictionary dictionaryWithObject:@"Couldn't get permission to authenticate." forKey:NSLocalizedDescriptionKey]]; | |
| } | |
| return res; | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment