NSTask and Git -- Permissions issues
Asked Answered
S

1

9

In my Cocoa application I'm trying to use NSTask to run some basic Git commands. Whenever I run a command that requires permissions (SSH keys) to access a remote (e.g. git push, git pull), it fails with the following error:

Permission denied (publickey). The remote end hung up unexpectedly

Running the same commands from Terminal works just fine, so I'm thinking that this might be an issue with NSTask not setting an environment variable that would be used somewhere in the process of accessing the ssh keys. I tried manually setting the HOME and USER environment variables like this:

[task setEnvironment:[NSDictionary dictionaryWithObjectsAndKeys:NSHomeDirectory(), @"HOME", NSUserName(), @"USER", nil]];

But this has no effect. Is there any particular environment variable I have to set in NSTask for this to work properly?

EDIT: Thanks to Dustin's tip, I got a little bit further in figuring this out. I used the env command to list the environment variables for my current session and I found this:

SSH_AUTH_SOCK=/tmp/launch-DMQopt/Listeners

To test, I copied that path and set it as an environment variable of NSTask and ran the code again, and this time it worked! That said, I'm certain that SSH_AUTH_SOCK changes for each session so I can't just hardcode it. How do I dynamically generate/retrieve this variable?

Squeaky answered 3/6, 2011 at 3:20 Comment(2)
try it the other way, use env -i on the commandline and see how much you need to add back before it works.Cogitable
Got a little bit further thanks to your tip, read my edited post :)Squeaky
C
4

You could try and follow the tutorial "Wrapping rsync or SSH in an NSTask" (from Ira), which does mention SSH_AUTH_SOCK variable:

Since writing this post I've realised that I omitted an important additional step in setting up the environment variables for the NSTask.
In order to make passwordless key-based authentication work it's necessary to grab the SSH_AUTH_SOCK variable from the user's environment and include this in the NSTask's environment.
So, when setting environment variables for example;

NSTask *task;
NSDictionary *environmentDict = [[NSProcessInfo processInfo] environment];
// Environment variables needed for password based authentication 
NSMutableDictionary *env = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                         @"NONE", @"DISPLAY",                           askPassPath, @"SSH_ASKPASS",
                         userName,@"AUTH_USERNAME",
                         hostName,@"AUTH_HOSTNAME",
                         nil];
 
// Environment variable needed for key based authentication
[env setObject:[environmentDict objectForKey:@"SSH_AUTH_SOCK"] forKey:@"SSH_AUTH_SOCK"];
 
// Setting the task's environment
[task setEnvironment:env];

However, the OP indragie comments:

I had tried this earlier but since it was being invoked with XCode, the SSH_AUTH_SOCK env var. wasn't being passed to it.
Opening the app from Finder corrects this issue.



With askPassPath being the path for the Askpass executable, which is included as part of the application’s main bundle. (In order to do this, find the executable under “Products” in xcode, and then drag it into “Copy Bundle Resources” on the main application’s target.)

// Get the path of the Askpass program, which is
// setup to be included as part of the main application bundle
NSString *askPassPath = [NSBundle pathForResource:@"Askpass"
              ofType:@"" 
              inDirectory:[[NSBundle mainBundle] bundlePath]];
Convocation answered 3/6, 2011 at 7:16 Comment(7)
I had tried this earlier but since it was being invoked with Xcode, the SSH_AUTH_SOCK env var. wasn't being passed to it. Opening the app from Finder corrects this issue. Thank you!Squeaky
@indragie: Excellent. I have included your comment in the answer for more visibility.Convocation
@Convocation Can you tell me what variable is the askPassPath?Erase
@user76859403 sure, I have restored the links, and included askPassPath in the edited answer.Convocation
@Convocation ok.. this seems to be my problem. Using MaC OSx Xcode with NSTask.. --> ssh_askpass: exec(/usr/libexec/ssh-askpass): No such file or directory. Host key verification failed. I guess i will have to find another solution to this. (the file doesnt exist on my system, yet it keeps looking for it. I was attempting a GIT clone). That code edit you did also gives me nil.Erase
Ira's article can still be found in the Wayback Machine: web.archive.org/web/20150306200934/http://…Grimes
@ThomasTempelmann Thank you for the feedback. I have edited the answer and restored the first two links.Convocation

© 2022 - 2024 — McMap. All rights reserved.