Skip to content

Commit 4e54ff9

Browse files
committed
Revert "get back the old gitx_asskpasswd"
This reverts commit fb6abc7.
1 parent 34300f9 commit 4e54ff9

File tree

2 files changed

+214
-137
lines changed

2 files changed

+214
-137
lines changed

ApplicationController.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ - (void)applicationDidFinishLaunching:(NSNotification*)notification
6868

6969
if ([PBGitDefaults useAskPasswd]) {
7070
// Make sure Git's SSH password requests get forwarded to our little UI tool:
71-
setenv( "SSH_ASKPASS", [[[NSBundle mainBundle] pathForResource: @"gitx_askpasswd" ofType: @""] UTF8String], 1 );
72-
setenv( "DISPLAY", "localhost:0", 1 );
71+
setenv( "SSH_ASKPASS", [[[NSBundle mainBundle] pathForResource: @"gitx_askpasswd" ofType: @""] UTF8String], 1 );
72+
setenv( "DISPLAY", "localhost:0", 1 );
7373
}
7474

7575
[self registerServices];

gitx_askpasswd_main.m

Lines changed: 212 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -9,166 +9,243 @@
99

1010
#include <ApplicationServices/ApplicationServices.h>
1111
#import <AppKit/AppKit.h>
12-
13-
#define OKBUTTONWIDTH 100.0
14-
#define OKBUTTONHEIGHT 24.0
15-
#define CANCELBUTTONWIDTH 100.0
16-
#define CANCELBUTTONHEIGHT 24.0
17-
#define PASSHEIGHT 22.0
18-
#define PASSLABELHEIGHT 16.0
19-
#define WINDOWAUTOSAVENAME @"GitXAskPasswordWindowFrame"
20-
21-
22-
@interface GAPAppDelegate : NSObject
12+
#include <errno.h>
13+
#include <string.h>
14+
#include <sys/sysctl.h>
15+
#include <Security/Security.h>
16+
#include <CoreServices/CoreServices.h>
17+
#include <Security/SecKeychain.h>
18+
#include <Security/SecKeychainItem.h>
19+
#include <Security/SecAccess.h>
20+
#include <Security/SecTrustedApplication.h>
21+
#include <Security/SecACL.h>
22+
#include <CoreFoundation/CoreFoundation.h>
23+
24+
#define OKBUTTONWIDTH 100.0
25+
#define OKBUTTONHEIGHT 24.0
26+
#define CANCELBUTTONWIDTH 100.0
27+
#define CANCELBUTTONHEIGHT 24.0
28+
#define PASSHEIGHT 22.0
29+
#define PASSLABELHEIGHT 16.0
30+
#define WINDOWAUTOSAVENAME @"GitXAskPasswordWindowFrame"
31+
32+
33+
@interface GAPAppDelegate : NSObject /*<NSApplicationDelegate>*/
2334
{
24-
NSPanel* mPasswordPanel;
25-
NSSecureTextField* mPasswordField;
2635
}
2736

28-
-(NSPanel*) passwordPanel;
37+
@end
2938

30-
-(IBAction) doOKButton: (id)sender;
31-
-(IBAction) doCancelButton: (id)sender;
39+
NSString* url;
40+
OSStatus StorePasswordKeychain (const char *url, UInt32 urlLength, void* password,UInt32 passwordLength);
3241

33-
@end
3442

43+
@implementation GAPAppDelegate
3544

36-
@implementation GAPAppDelegate
45+
-(void)yesNo:(NSString *)prompt url:(NSString *)url{
46+
NSAlert *alert = [[NSAlert alloc] init];
47+
[alert addButtonWithTitle:@"YES"];
48+
[alert addButtonWithTitle:@"NO"];
49+
[alert setMessageText:[NSString stringWithFormat:@"%@?",url]];
50+
[alert setInformativeText:prompt];
51+
[alert setAlertStyle:NSWarningAlertStyle];
52+
NSInteger result = [alert runModal];
53+
54+
Boolean yes=NO;
55+
if ( result == NSAlertFirstButtonReturn ) {
56+
yes=YES;
57+
}
58+
[alert release];
59+
printf("%s",yes?"yes":"no");
60+
}
3761

38-
-(NSPanel*) passwordPanel
39-
{
40-
if( !mPasswordPanel )
41-
{
42-
NSRect box = NSMakeRect( 100, 100, 400, 134 );
43-
mPasswordPanel = [[NSPanel alloc] initWithContentRect: box
44-
styleMask: NSTitledWindowMask
45-
backing: NSBackingStoreBuffered defer: NO];
46-
[mPasswordPanel setHidesOnDeactivate: NO];
47-
[mPasswordPanel setLevel: NSFloatingWindowLevel];
48-
[mPasswordPanel setTitle: @"GitX SSH Remote Login"];
49-
if (![mPasswordPanel setFrameUsingName: WINDOWAUTOSAVENAME]) {
50-
[mPasswordPanel center];
51-
[mPasswordPanel setFrameAutosaveName: WINDOWAUTOSAVENAME];
62+
63+
- (void)pasword:(NSString *)prompt url:(NSString *)url{
64+
65+
NSRect box = NSMakeRect(0, 0, 200, 24);
66+
67+
NSSecureTextField * passView = [[NSSecureTextField alloc] initWithFrame: box];
68+
[passView setSelectable: YES];
69+
[passView setEditable: YES];
70+
[passView setBordered: YES];
71+
[passView setBezeled: YES];
72+
[passView setBezelStyle: NSTextFieldSquareBezel];
73+
[passView selectText: self];
74+
75+
76+
NSAlert *alert = [[NSAlert alloc] init];
77+
[alert addButtonWithTitle:@"Ok"];
78+
[alert addButtonWithTitle:@"cancel"];
79+
[alert setMessageText:[NSString stringWithFormat:@"%@?",url]];
80+
[alert setInformativeText:prompt];
81+
[alert setAlertStyle:NSWarningAlertStyle];
82+
[alert setAccessoryView:passView];
83+
[alert setShowsSuppressionButton:YES];
84+
[[alert suppressionButton] setTitle:@"Save on keychain"];
85+
NSInteger result = [alert runModal];
86+
if ( result == NSAlertFirstButtonReturn ) {
87+
NSString *pas=[passView stringValue];
88+
printf( "%s", [pas UTF8String] );
89+
if ([[alert suppressionButton] state] == NSOnState) {
90+
StorePasswordKeychain ([url cStringUsingEncoding:NSASCIIStringEncoding],
91+
[url lengthOfBytesUsingEncoding:NSASCIIStringEncoding],
92+
(void *)[pas cStringUsingEncoding:NSASCIIStringEncoding],
93+
[pas lengthOfBytesUsingEncoding:NSASCIIStringEncoding]);
5294
}
53-
54-
box.origin = NSZeroPoint; // Only need local coords from now on.
55-
56-
// OK:
57-
NSRect okBox = box;
58-
okBox.origin.x = NSMaxX( box ) -OKBUTTONWIDTH -20;
59-
okBox.size.width = OKBUTTONWIDTH;
60-
okBox.origin.y += 20;
61-
okBox.size.height = OKBUTTONHEIGHT;
62-
NSButton *okButton = [[NSButton alloc] initWithFrame: okBox];
63-
[okButton setTarget: self];
64-
[okButton setAction: @selector(doOKButton:)];
65-
[okButton setTitle: @"OK"]; // +++ Localize.
66-
[okButton setKeyEquivalent: @"\r"];
67-
[okButton setBordered: YES];
68-
[okButton setBezelStyle: NSRoundedBezelStyle];
69-
[[mPasswordPanel contentView] addSubview: okButton];
70-
71-
// Cancel:
72-
NSRect cancelBox = box;
73-
cancelBox.origin.x = NSMinX( okBox ) -CANCELBUTTONWIDTH -6;
74-
cancelBox.size.width = CANCELBUTTONWIDTH;
75-
cancelBox.origin.y += 20;
76-
cancelBox.size.height = CANCELBUTTONHEIGHT;
77-
NSButton *cancleButton = [[NSButton alloc] initWithFrame: cancelBox];
78-
[cancleButton setTarget: self];
79-
[cancleButton setAction: @selector(doCancelButton:)];
80-
[cancleButton setTitle: @"Cancel"]; // +++ Localize.
81-
[cancleButton setBordered: YES];
82-
[cancleButton setBezelStyle: NSRoundedBezelStyle];
83-
[[mPasswordPanel contentView] addSubview: cancleButton];
84-
85-
// Password field:
86-
NSRect passBox = box;
87-
passBox.origin.y = NSMaxY(okBox) + 24;
88-
passBox.size.height = PASSHEIGHT;
89-
passBox.origin.x += 104;
90-
passBox.size.width -= 104 + 20;
91-
mPasswordField = [[NSSecureTextField alloc] initWithFrame: passBox];
92-
[mPasswordField setSelectable: YES];
93-
[mPasswordField setEditable: YES];
94-
[mPasswordField setBordered: YES];
95-
[mPasswordField setBezeled: YES];
96-
[mPasswordField setBezelStyle: NSTextFieldSquareBezel];
97-
[mPasswordField selectText: self];
98-
[[mPasswordPanel contentView] addSubview: mPasswordField];
99-
100-
// Password label:
101-
NSRect passLabelBox = box;
102-
passLabelBox.origin.y = NSMaxY(passBox) + 8;
103-
passLabelBox.size.height = PASSLABELHEIGHT;
104-
passLabelBox.origin.x += 100;
105-
passLabelBox.size.width -= 100 + 20;
106-
NSTextField *passwordLabel = [[NSTextField alloc] initWithFrame: passLabelBox];
107-
[passwordLabel setSelectable: YES];
108-
[passwordLabel setEditable: NO];
109-
[passwordLabel setBordered: NO];
110-
[passwordLabel setBezeled: NO];
111-
[passwordLabel setDrawsBackground: NO];
112-
[passwordLabel setStringValue: @"Please enter your password:"]; // +++ Localize.
113-
[[mPasswordPanel contentView] addSubview: passwordLabel];
114-
115-
// GitX icon:
116-
NSRect gitxIconBox = box;
117-
gitxIconBox.origin.y = NSMaxY(box) - 78;
118-
gitxIconBox.size.height = 64;
119-
gitxIconBox.origin.x += 20;
120-
gitxIconBox.size.width = 64;
121-
NSImageView *gitxIconView = [[NSImageView alloc] initWithFrame: gitxIconBox];
122-
[gitxIconView setEditable: NO];
123-
NSString *gitxIconPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: @"gitx.icns"];
124-
NSImage *gitxIcon = [[NSImage alloc] initWithContentsOfFile: gitxIconPath];
125-
[gitxIconView setImage: gitxIcon];
126-
[[mPasswordPanel contentView] addSubview: gitxIconView];
12795
}
12896

129-
return mPasswordPanel;
97+
[alert release];
13098
}
13199

100+
@end
101+
102+
void getproclline(pid_t pid, char *command_name);
132103

133-
-(IBAction) doOKButton: (id)sender
104+
void getproclline(pid_t pid, char *command_name)
134105
{
135-
printf( "%s\n", [[mPasswordField stringValue] UTF8String] );
136-
[[NSApplication sharedApplication] stopModalWithCode: 0];
106+
int mib[3], argmax, nargs, c = 0;
107+
size_t size;
108+
char *procargs, *sp, *np, *cp;
109+
110+
mib[0] = CTL_KERN;
111+
mib[1] = KERN_ARGMAX;
112+
113+
size = sizeof(argmax);
114+
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
115+
return;
116+
}
117+
118+
/* Allocate space for the arguments. */
119+
procargs = (char *)malloc(argmax);
120+
if (procargs == NULL) {
121+
return;
122+
}
123+
124+
mib[0] = CTL_KERN;
125+
mib[1] = KERN_PROCARGS2;
126+
mib[2] = pid;
127+
128+
size = (size_t)argmax;
129+
if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) {
130+
return;
131+
}
132+
133+
memcpy(&nargs, procargs, sizeof(nargs));
134+
cp = procargs + sizeof(nargs);
135+
136+
/* Skip the saved exec_path. */
137+
for (; cp < &procargs[size]; cp++) {
138+
if (*cp == '\0') {
139+
/* End of exec_path reached. */
140+
break;
141+
}
142+
}
143+
if (cp == &procargs[size]) {
144+
return;
145+
}
146+
147+
/* Skip trailing '\0' characters. */
148+
for (; cp < &procargs[size]; cp++) {
149+
if (*cp != '\0') {
150+
/* Beginning of first argument reached. */
151+
break;
152+
}
153+
}
154+
if (cp == &procargs[size]) {
155+
return;
156+
}
157+
/* Save where the argv[0] string starts. */
158+
sp = cp;
159+
160+
for (np = NULL; c < nargs && cp < &procargs[size]; cp++) {
161+
if (*cp == '\0') {
162+
c++;
163+
if (np != NULL) {
164+
*np = ' ';
165+
}
166+
np = cp;
167+
}
168+
}
169+
sprintf(command_name, "%s",sp);
137170
}
138171

139-
140-
// TODO: Need to find out how to get SSH to cancel.
141-
// When the user cancels the window it is opened again for however
142-
// many times the remote server allows failed attempts.
143-
-(IBAction) doCancelButton: (id)sender
172+
OSStatus StorePasswordKeychain (const char *url, UInt32 urlLength, void* password,UInt32 passwordLength)
144173
{
145-
[[NSApplication sharedApplication] stopModalWithCode: 1];
174+
OSStatus status;
175+
status = SecKeychainAddGenericPassword (
176+
NULL, // default keychain
177+
4, // length of service name
178+
"GitX", // service name
179+
urlLength, // length of account name
180+
url, // account name
181+
passwordLength, // length of password
182+
password, // pointer to password data
183+
NULL // the item reference
184+
);
185+
return (status);
146186
}
147187

148-
@end
149-
188+
OSStatus GetPasswordKeychain (const char *url, UInt32 urlLength ,void *passwordData,UInt32 *passwordLength,
189+
SecKeychainItemRef *itemRef)
190+
{
191+
OSStatus status ;
192+
status = SecKeychainFindGenericPassword (
193+
NULL, // default keychain
194+
4, // length of service name
195+
"GitX", // service name
196+
urlLength, // length of account name
197+
url, // account name
198+
passwordLength, // length of password
199+
passwordData, // pointer to password data
200+
itemRef // the item reference
201+
);
202+
return (status);
203+
}
150204

151205

152-
int main( int argc, const char** argv )
206+
int main( int argc, const char* argv[] )
153207
{
154-
// close stderr to stop cocoa log messages from being picked up by GitX
155-
close(STDERR_FILENO);
156-
157-
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
208+
// close stderr to stop cocoa log messages from being picked up by GitX
209+
close(STDERR_FILENO);
158210

159-
ProcessSerialNumber myPSN = { 0, kCurrentProcess };
160-
TransformProcessType( &myPSN, kProcessTransformToForegroundApplication );
211+
ProcessSerialNumber myPSN = { 0, kCurrentProcess };
212+
TransformProcessType( &myPSN, kProcessTransformToForegroundApplication );
213+
214+
NSApplication *app = [NSApplication sharedApplication];
215+
GAPAppDelegate *appDel = [[GAPAppDelegate alloc] init];
216+
[app setDelegate: appDel];
161217

162-
NSApplication *app = [NSApplication sharedApplication];
163-
GAPAppDelegate *appDel = [[GAPAppDelegate alloc] init];
164-
[app setDelegate: appDel];
165-
NSWindow *passPanel = [appDel passwordPanel];
218+
219+
char args[4024];
220+
getproclline(getppid(),args);
221+
NSString *cmd=[NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:args]];
166222

167-
[app activateIgnoringOtherApps: YES];
168-
[passPanel makeKeyAndOrderFront: nil];
169-
NSInteger code = [app runModalForWindow: passPanel];
223+
NSLog(@"cmd: '%@'",cmd);
170224

171-
[defaults synchronize];
225+
if([cmd hasPrefix:@"git-remote"]){
226+
NSArray *args=[cmd componentsSeparatedByString:@" "];
227+
NSString *url=[args objectAtIndex:[args count]-1];
228+
229+
void *passwordData = nil;
230+
SecKeychainItemRef itemRef = nil;
231+
UInt32 passwordLength = 0;
232+
233+
OSStatus status = GetPasswordKeychain ([url cStringUsingEncoding:NSASCIIStringEncoding],[url lengthOfBytesUsingEncoding:NSASCIIStringEncoding],&passwordData,&passwordLength,&itemRef);
234+
if (status == noErr) {
235+
SecKeychainItemFreeContent (NULL,passwordData);
236+
NSString *pas=[[NSString stringWithCString:passwordData encoding:NSASCIIStringEncoding] substringToIndex:passwordLength];
237+
printf( "%s", [pas UTF8String] );
238+
return 0;
239+
}
240+
241+
NSString *prompt=[NSString stringWithFormat:@"%@",[NSString stringWithCString:argv[1] encoding:NSASCIIStringEncoding]];
242+
[appDel pasword:prompt url:url];
243+
}else{ // yes/no?
244+
NSString *prompt=[NSString stringWithFormat:@"%@",[NSString stringWithCString:argv[1] encoding:NSASCIIStringEncoding]];
245+
NSArray *args=[cmd componentsSeparatedByString:@" "];
246+
NSString *url=[args objectAtIndex:1];
247+
[appDel yesNo:prompt url:url];
248+
}
172249

173-
return code;
174-
}
250+
return 0;
251+
}

0 commit comments

Comments
 (0)