Skip to content
Snippets Groups Projects
Commit 39c2b2cb authored by George Nachman's avatar George Nachman
Browse files

Polish up auth

parent 848b6fed
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -10,6 +10,7 @@
#import "Api.pbobjc.h"
 
@protocol iTermAPIServerDelegate<NSObject>
- (BOOL)apiServerAuthorizeProcess:(pid_t)pid;
- (void)apiServerGetBuffer:(ITMGetBufferRequest *)request handler:(void (^)(ITMGetBufferResponse *))handler;
- (void)apiServerGetPrompt:(ITMGetPromptRequest *)request handler:(void (^)(ITMGetPromptResponse *))handler;
- (void)apiServerNotification:(ITMNotificationRequest *)request
Loading
Loading
Loading
Loading
@@ -190,7 +190,8 @@ const char *kWebSocketConnectionHandleAssociatedObjectKey = "kWebSocketConnectio
- (void)didAcceptConnectionOnFileDescriptor:(int)fd fromAddress:(iTermSocketAddress *)address {
ILog(@"Accepted connection");
__weak __typeof(self) weakSelf = self;
dispatch_async(_queue, ^{
dispatch_queue_t queue = _queue;
dispatch_async(queue, ^{
iTermHTTPConnection *connection = [[iTermHTTPConnection alloc] initWithFileDescriptor:fd clientAddress:address];
 
pid_t pid = [iTermLSOF processIDWithConnectionFromAddress:address];
Loading
Loading
@@ -201,8 +202,8 @@ const char *kWebSocketConnectionHandleAssociatedObjectKey = "kWebSocketConnectio
}
 
dispatch_async(dispatch_get_main_queue(), ^{
if ([weakSelf authenticateProcess:pid]) {
dispatch_async(_queue, ^{ [weakSelf startRequestOnConnection:connection]; });
if ([weakSelf.delegate apiServerAuthorizeProcess:pid]) {
dispatch_async(queue, ^{ [weakSelf startRequestOnConnection:connection]; });
} else {
ELog(@"Reject unauthenticated process (pid %d)", pid);
[connection unauthorized];
Loading
Loading
@@ -212,22 +213,6 @@ const char *kWebSocketConnectionHandleAssociatedObjectKey = "kWebSocketConnectio
});
}
 
- (BOOL)authenticateProcess:(pid_t)pid {
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
if (!app) {
ELog(@"No running app with pid %d", (int)pid);
return NO;
}
NSAlert *alert = [[NSAlert alloc] init];
alert.messageText = @"API Access Request";
alert.informativeText = [NSString stringWithFormat:@"The application “%@” (%@) would like to control iTerm2. This exposes a significant amount of data in iTerm2 to %@. Allow this request?", app.localizedName, app.bundleIdentifier, app.localizedName];
[alert addButtonWithTitle:@"Deny"];
[alert addButtonWithTitle:@"Allow"];
NSModalResponse response = [alert runModal];
return response == NSAlertSecondButtonReturn;
}
- (void)startRequestOnConnection:(iTermHTTPConnection *)connection {
NSURLRequest *request = [connection readRequest];
if (!request) {
Loading
Loading
Loading
Loading
@@ -111,6 +111,14 @@ static NSString *LEGACY_DEFAULT_ARRANGEMENT_NAME = @"Default";
static BOOL ranAutoLaunchScript = NO;
static BOOL hasBecomeActive = NO;
 
static NSString *const kBundlesWithAPIAccessSettingKey = @"NoSyncBundlesWithAPIAccessSettings";
static NSString *const kAPIAccessAllowed = @"allowed";
static NSString *const kAPIAccessDate = @"date";
static NSString *const kAPINextConfirmationDate = @"next confirmation";
static NSString *const kAPIAccessLocalizedName = @"app name";
static const NSTimeInterval kOneMonth = 30 * 24 * 60 * 60;
@interface iTermApplicationDelegate () <iTermAPIServerDelegate, iTermPasswordManagerDelegate>
 
@property(nonatomic, readwrite) BOOL workspaceSessionActive;
Loading
Loading
@@ -1989,6 +1997,75 @@ static BOOL hasBecomeActive = NO;
 
#pragma mark - iTermAPIServerDelegate
 
- (BOOL)apiServerAuthorizeProcess:(pid_t)pid {
NSMutableDictionary *bundles = [[[NSUserDefaults standardUserDefaults] objectForKey:kBundlesWithAPIAccessSettingKey] mutableCopy];
if (!bundles) {
bundles = [NSMutableDictionary dictionary];
}
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
if (!app) {
ELog(@"No running app with pid %d", (int)pid);
return NO;
}
if (!app.localizedName || !app.bundleIdentifier) {
ELog(@"App is missing name or bundle ID");
return NO;
}
NSString *key = [NSString stringWithFormat:@"bundle=%@", app.bundleIdentifier];
NSDictionary *setting = bundles[key];
BOOL reauth = NO;
if (setting) {
if (![setting[kAPIAccessAllowed] boolValue]) {
// Access permanently disallowed.
return NO;
}
NSString *name = setting[kAPIAccessLocalizedName];
if ([app.localizedName isEqualToString:name]) {
// Access is permanently allowed and the display name is unchanged. Do we need to reauth?
NSDate *confirm = setting[kAPINextConfirmationDate];
if ([[NSDate date] compare:confirm] == NSOrderedAscending) {
// No need to reauth, allow it.
ELog(@"Allowing API access to process id %d, name %@, bundle ID %@", pid, app.localizedName, app.bundleIdentifier);
return YES;
}
// It's been a month since API access was confirmed. Request it again.
reauth = YES;
}
}
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
if (reauth) {
alert.messageText = @"Reauthorize API Access";
alert.informativeText = [NSString stringWithFormat:@"The application “%@” (%@) has API access, which grants it permission to see and control your activity. Would you like it to continue?", app.localizedName, app.bundleIdentifier];
} else {
alert.messageText = @"API Access Request";
alert.informativeText = [NSString stringWithFormat:@"The application “%@” (%@) would like to control iTerm2. This exposes a significant amount of data in iTerm2 to %@. Allow this request?", app.localizedName, app.bundleIdentifier, app.localizedName];
}
[alert addButtonWithTitle:@"Deny"];
[alert addButtonWithTitle:@"Allow"];
if (!reauth) {
// Reauth is always persistent so don't show the button.
alert.suppressionButton.title = @"Remember my selection";
alert.showsSuppressionButton = YES;
}
NSModalResponse response = [alert runModal];
BOOL allow = (response == NSAlertSecondButtonReturn);
if (reauth || alert.suppressionButton.state == NSOnState) {
bundles[key] = @{ kAPIAccessAllowed: @(allow),
kAPIAccessDate: [NSDate date],
kAPINextConfirmationDate: [[NSDate date] dateByAddingTimeInterval:kOneMonth],
kAPIAccessLocalizedName: app.localizedName };
} else {
[bundles removeObjectForKey:key];
}
[[NSUserDefaults standardUserDefaults] setObject:bundles forKey:kBundlesWithAPIAccessSettingKey];
return allow;
}
- (PTYSession *)sessionForAPIIdentifier:(NSString *)identifier {
if (identifier) {
for (PseudoTerminal *term in [[iTermController sharedInstance] terminals]) {
Loading
Loading
Loading
Loading
@@ -23,14 +23,12 @@
 
+ (pid_t)processIDWithConnectionFromAddress:(iTermSocketAddress *)socketAddress {
__block pid_t result = -1;
pid_t pid = 319;
// [self enumerateProcesses:^(pid_t pid, BOOL *stop) {
[self enumerateProcesses:^(pid_t pid, BOOL *stop) {
[self enumerateFileDescriptorsInfoInProcess:pid ofType:PROX_FDTYPE_SOCKET block:^(struct socket_fdinfo *fdInfo, BOOL *stop) {
int family = [self addressFamilyForFDInfo:fdInfo];
if (family != AF_INET && family != AF_INET6) {
return;
}
NSLog(@"Consider port %d or %d", fdInfo->psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport, ntohs(fdInfo->psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport));
struct sockaddr_storage local = [self localSocketAddressInFDInfo:fdInfo];
if (![socketAddress isEqualToSockAddr:(struct sockaddr *)&local]) {
return;
Loading
Loading
@@ -42,7 +40,7 @@
result = pid;
*stop = YES;
}];
// }];
}];
return result;
}
 
Loading
Loading
@@ -89,7 +87,6 @@
BOOL stop = NO;
for (int j = 0; j < count; j++) {
struct proc_fdinfo *fdinfo = &fds[j];
NSLog(@"file descriptor %d", fdinfo->proc_fd);
if (fdinfo->proc_fdtype == PROX_FDTYPE_SOCKET) {
int fd = fdinfo->proc_fd;
struct socket_fdinfo socketFileDescriptorInfo;
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment