Skip to content

Commit fb6abc7

Browse files
committed
get back the old gitx_asskpasswd
1 parent 3c3b9ad commit fb6abc7

File tree

2 files changed

+137
-214
lines changed

2 files changed

+137
-214
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: 135 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -9,243 +9,166 @@
99

1010
#include <ApplicationServices/ApplicationServices.h>
1111
#import <AppKit/AppKit.h>
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>*/
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
3423
{
24+
NSPanel* mPasswordPanel;
25+
NSSecureTextField* mPasswordField;
3526
}
3627

37-
@end
38-
39-
NSString* url;
40-
OSStatus StorePasswordKeychain (const char *url, UInt32 urlLength, void* password,UInt32 passwordLength);
28+
-(NSPanel*) passwordPanel;
4129

30+
-(IBAction) doOKButton: (id)sender;
31+
-(IBAction) doCancelButton: (id)sender;
4232

43-
@implementation GAPAppDelegate
33+
@end
4434

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-
}
6135

36+
@implementation GAPAppDelegate
6237

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]);
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];
9452
}
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];
95127
}
96128

97-
[alert release];
129+
return mPasswordPanel;
98130
}
99131

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

104-
void getproclline(pid_t pid, char *command_name)
133+
-(IBAction) doOKButton: (id)sender
105134
{
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);
135+
printf( "%s\n", [[mPasswordField stringValue] UTF8String] );
136+
[[NSApplication sharedApplication] stopModalWithCode: 0];
170137
}
171138

172-
OSStatus StorePasswordKeychain (const char *url, UInt32 urlLength, void* password,UInt32 passwordLength)
173-
{
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);
186-
}
187139

188-
OSStatus GetPasswordKeychain (const char *url, UInt32 urlLength ,void *passwordData,UInt32 *passwordLength,
189-
SecKeychainItemRef *itemRef)
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
190144
{
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);
145+
[[NSApplication sharedApplication] stopModalWithCode: 1];
203146
}
204147

148+
@end
149+
205150

206-
int main( int argc, const char* argv[] )
151+
152+
int main( int argc, const char** argv )
207153
{
208-
// close stderr to stop cocoa log messages from being picked up by GitX
209-
close(STDERR_FILENO);
154+
// close stderr to stop cocoa log messages from being picked up by GitX
155+
close(STDERR_FILENO);
210156

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];
157+
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
217158

218-
219-
char args[4024];
220-
getproclline(getppid(),args);
221-
NSString *cmd=[NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:args]];
159+
ProcessSerialNumber myPSN = { 0, kCurrentProcess };
160+
TransformProcessType( &myPSN, kProcessTransformToForegroundApplication );
222161

223-
NSLog(@"cmd: '%@'",cmd);
162+
NSApplication *app = [NSApplication sharedApplication];
163+
GAPAppDelegate *appDel = [[GAPAppDelegate alloc] init];
164+
[app setDelegate: appDel];
165+
NSWindow *passPanel = [appDel passwordPanel];
224166

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-
}
167+
[app activateIgnoringOtherApps: YES];
168+
[passPanel makeKeyAndOrderFront: nil];
169+
NSInteger code = [app runModalForWindow: passPanel];
249170

250-
return 0;
251-
}
171+
[defaults synchronize];
172+
173+
return code;
174+
}

0 commit comments

Comments
 (0)