Basic authentication support
This commit is contained in:
@@ -63,7 +63,7 @@
|
|||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
<CommandLineArguments>
|
<CommandLineArguments>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
argument = "-s -c certificate.p12"
|
argument = "-s -c certificate.p12 -a access.asc"
|
||||||
isEnabled = "YES">
|
isEnabled = "YES">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
</CommandLineArguments>
|
</CommandLineArguments>
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -40,4 +40,14 @@ If you want to run with SSL, you have to generate a self-signed certificate, and
|
|||||||
### Start kordophone with the SSL options and provide the p12
|
### Start kordophone with the SSL options and provide the p12
|
||||||
`kordophoned -s -c certificate.p12`
|
`kordophoned -s -c certificate.p12`
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
Basic Authentication is also optional, but requires SSL to be enabled as well. To configure basic authentication, create a file containing your username and password on two separate lines encrypted with your GPG key.
|
||||||
|
|
||||||
|
`echo "username\npassword" > password.txt"`
|
||||||
|
`gpg -e -r (your email) -o password.asc password.txt`
|
||||||
|
|
||||||
|
Then run kordophoned with the following option
|
||||||
|
`kordophone -s -c certificate.p12 -a password.asc`
|
||||||
|
|
||||||
|
You may need to unlock your GPG keyring (via gpg-agent) when running kordophoned the first time.
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@property (nonatomic, assign) UInt16 port;
|
@property (nonatomic, assign) UInt16 port;
|
||||||
@property (nonatomic, readonly) NSOperationQueue *operationQueue;
|
@property (nonatomic, readonly) NSOperationQueue *operationQueue;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL usesAccessControl;
|
||||||
|
@property (nonatomic, strong) NSString *authUsername;
|
||||||
|
@property (nonatomic, strong) NSString *authPassword;
|
||||||
|
|
||||||
@property (nonatomic, assign) BOOL usesSSL;
|
@property (nonatomic, assign) BOOL usesSSL;
|
||||||
@property (nonatomic, strong) NSString *sslCertPath;
|
@property (nonatomic, strong) NSString *sslCertPath;
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,28 @@
|
|||||||
return [[MBIMBridge sharedInstance] sslCertificateAndIdentity];
|
return [[MBIMBridge sharedInstance] sslCertificateAndIdentity];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)isPasswordProtected:(NSString *)path
|
||||||
|
{
|
||||||
|
return [[MBIMBridge sharedInstance] usesAccessControl];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)passwordForUser:(NSString *)username
|
||||||
|
{
|
||||||
|
MBIMBridge *bridge = [MBIMBridge sharedInstance];
|
||||||
|
if ([username isEqualToString:bridge.authUsername]) {
|
||||||
|
return bridge.authPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)useDigestAccessAuthentication
|
||||||
|
{
|
||||||
|
// TODO: should use digest all the time, but it's a bit more complicated. Allow this to be NO if
|
||||||
|
// SSL is on, because then at least basic auth is encrypted
|
||||||
|
return ![[MBIMBridge sharedInstance] usesSSL];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path
|
- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path
|
||||||
{
|
{
|
||||||
if ([method isEqualToString:@"GET"] || [method isEqualToString:@"POST"]) {
|
if ([method isEqualToString:@"GET"] || [method isEqualToString:@"POST"]) {
|
||||||
|
|||||||
@@ -12,20 +12,83 @@
|
|||||||
|
|
||||||
void printUsage()
|
void printUsage()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: kordophoned [-h] [-s | -c (certificate.p12)]\n");
|
fprintf(stderr, "Usage: kordophoned [-h] [-s | -c (certificate.p12)] [-a (access control file)\n");
|
||||||
fprintf(stderr, "\t-h \t Show this help message\n");
|
fprintf(stderr, "\t-h \t Show this help message\n");
|
||||||
fprintf(stderr, "\t-s \t Use SSL (requires -c option)\n");
|
fprintf(stderr, "\t-s \t Use SSL (requires -c option)\n");
|
||||||
fprintf(stderr, "\t-c \t SSL certificate path encoded as pkcs12\n");
|
fprintf(stderr, "\t-c \t SSL certificate path encoded as pkcs12\n");
|
||||||
|
fprintf(stderr, "\t-a \t Optional GPG encrypted access control file\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL acquireCredentials(const char *accessFile, NSString **out_username, NSString **out_password)
|
||||||
|
{
|
||||||
|
NSPipe *stdoutPipe = [NSPipe pipe];
|
||||||
|
NSPipe *stderrPipe = [NSPipe pipe];
|
||||||
|
NSTask *task = [[NSTask alloc] init];
|
||||||
|
task.launchPath = @"/usr/local/bin/gpg";
|
||||||
|
task.arguments = @[ @"-q", @"-d", [NSString stringWithUTF8String:accessFile] ];
|
||||||
|
task.standardOutput = stdoutPipe;
|
||||||
|
task.standardError = stderrPipe;
|
||||||
|
|
||||||
|
NSError *launchError = nil;
|
||||||
|
BOOL success = [task launchAndReturnError:&launchError];
|
||||||
|
[task waitUntilExit];
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
NSFileHandle *stdoutFile = stdoutPipe.fileHandleForReading;
|
||||||
|
NSData *data = [stdoutFile readDataToEndOfFile]; // blocks
|
||||||
|
[stdoutFile closeFile];
|
||||||
|
|
||||||
|
if ([task terminationStatus] != 0) {
|
||||||
|
NSData *stderrData = [[stderrPipe fileHandleForReading] readDataToEndOfFile];
|
||||||
|
MBIMLogFatal(@"GPG error when decrypting access file: %@", [[NSString alloc] initWithData:stderrData encoding:NSUTF8StringEncoding]);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *asString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||||
|
NSScanner *scanner = [NSScanner scannerWithString:asString];
|
||||||
|
|
||||||
|
BOOL scannerSuccess = NO;
|
||||||
|
NSString *username = nil;
|
||||||
|
scannerSuccess = [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet]
|
||||||
|
intoString:&username];
|
||||||
|
if (!scannerSuccess) {
|
||||||
|
MBIMLogFatal(@"Error parsing username from access file");
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *password = nil;
|
||||||
|
scannerSuccess = [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet]
|
||||||
|
intoString:&password];
|
||||||
|
if (!scannerSuccess) {
|
||||||
|
MBIMLogFatal(@"Error parsing password from access file");
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([username length] && [password length]) {
|
||||||
|
*out_username = username;
|
||||||
|
*out_password = password;
|
||||||
|
} else {
|
||||||
|
MBIMLogFatal(@"Error parsing username or password from access file");
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MBIMLogFatal(@"Unable to launch GPG executable to decrypt access file: %@", [launchError localizedDescription]);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *const argv[]) {
|
int main(int argc, char *const argv[]) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
BOOL usesSSL = NO;
|
BOOL usesSSL = NO;
|
||||||
BOOL showHelp = NO;
|
BOOL showHelp = NO;
|
||||||
|
BOOL usesAccessControl = NO;
|
||||||
const char *certPath = NULL;
|
const char *certPath = NULL;
|
||||||
|
const char *accessFilePath = NULL;
|
||||||
|
|
||||||
int c = -1;
|
int c = -1;
|
||||||
while ( (c = getopt(argc, argv, "hsc:")) != -1 ) {
|
while ( (c = getopt(argc, argv, "hsc:a:")) != -1 ) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 's':
|
case 's':
|
||||||
usesSSL = YES;
|
usesSSL = YES;
|
||||||
@@ -33,6 +96,10 @@ int main(int argc, char *const argv[]) {
|
|||||||
case 'c':
|
case 'c':
|
||||||
certPath = optarg;
|
certPath = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'a':
|
||||||
|
usesAccessControl = YES;
|
||||||
|
accessFilePath = optarg;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
showHelp = YES;
|
showHelp = YES;
|
||||||
break;
|
break;
|
||||||
@@ -62,6 +129,33 @@ int main(int argc, char *const argv[]) {
|
|||||||
|
|
||||||
MBIMBridge *bridge = [MBIMBridge sharedInstance];
|
MBIMBridge *bridge = [MBIMBridge sharedInstance];
|
||||||
|
|
||||||
|
if (usesAccessControl) {
|
||||||
|
NSString *username = nil;
|
||||||
|
NSString *password = nil;
|
||||||
|
|
||||||
|
BOOL success = acquireCredentials(accessFilePath, &username, &password);
|
||||||
|
if (!success) {
|
||||||
|
MBIMLogInfo(
|
||||||
|
@"Access file must be a GPG encrypted file (encrypted with your private key, to your pub key) "
|
||||||
|
"with the follwing format: \n"
|
||||||
|
"(username)\n"
|
||||||
|
"(password)"
|
||||||
|
);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
const ssize_t ast_len = 55;
|
||||||
|
const unichar asterisks[ast_len] = u"*******************************************************";
|
||||||
|
NSString *obscuredPassword = [NSString stringWithCharacters:asterisks
|
||||||
|
length:MIN([password length], ast_len)];
|
||||||
|
MBIMLogNotify(@"Using access control credentials: username(%@) password(%@)", username, obscuredPassword);
|
||||||
|
|
||||||
|
bridge.usesAccessControl = YES;
|
||||||
|
bridge.authUsername = username;
|
||||||
|
bridge.authPassword = password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (usesSSL && certPath != NULL) {
|
if (usesSSL && certPath != NULL) {
|
||||||
bridge.usesSSL = YES;
|
bridge.usesSSL = YES;
|
||||||
bridge.sslCertPath = [NSString stringWithCString:certPath encoding:NSASCIIStringEncoding];
|
bridge.sslCertPath = [NSString stringWithCString:certPath encoding:NSASCIIStringEncoding];
|
||||||
|
|||||||
Reference in New Issue
Block a user