|
| 1 | +// |
| 2 | +// GTCredential.m |
| 3 | +// ObjectiveGitFramework |
| 4 | +// |
| 5 | +// Created by Etienne on 10/09/13. |
| 6 | +// Copyright (c) 2013 GitHub, Inc. All rights reserved. |
| 7 | +// |
| 8 | + |
| 9 | +#import <ObjectiveGit/NSError+Git.h> |
| 10 | +#import "GTCredential.h" |
| 11 | +#import "GTCredential+Private.h" |
| 12 | +#import <libssh2.h> |
| 13 | + |
| 14 | +typedef GTCredential *(^GTCredentialProviderBlock)(GTCredentialType allowedTypes, NSString *URL, NSString *userName); |
| 15 | + |
| 16 | +@interface GTCredentialProvider () |
| 17 | +@property (nonatomic, readonly, copy) GTCredentialProviderBlock credBlock; |
| 18 | +@end |
| 19 | + |
| 20 | +@implementation GTCredentialProvider |
| 21 | ++ (instancetype)providerWithBlock:(GTCredentialProviderBlock)credentialBlock { |
| 22 | + NSParameterAssert(credentialBlock != nil); |
| 23 | + |
| 24 | + GTCredentialProvider *provider = [[self alloc] init]; |
| 25 | + |
| 26 | + provider->_credBlock = [credentialBlock copy]; |
| 27 | + |
| 28 | + return provider; |
| 29 | +} |
| 30 | + |
| 31 | +- (GTCredential *)credentialForType:(GTCredentialType)type URL:(NSString *)URL userName:(NSString *)userName { |
| 32 | + NSAssert(self.credBlock != nil, @"Provider asked for credentials without block being set."); |
| 33 | + |
| 34 | + return self.credBlock(type, URL, userName); |
| 35 | +} |
| 36 | + |
| 37 | +@end |
| 38 | + |
| 39 | +@interface GTCredential () |
| 40 | +@property (nonatomic, assign, readonly) git_cred *git_cred; |
| 41 | +@end |
| 42 | + |
| 43 | +@implementation GTCredential |
| 44 | + |
| 45 | ++ (instancetype)credentialWithUserName:(NSString *)userName password:(NSString *)password error:(NSError **)error { |
| 46 | + git_cred *cred; |
| 47 | + int gitError = git_cred_userpass_plaintext_new(&cred, userName.UTF8String, password.UTF8String); |
| 48 | + if (gitError != GIT_OK) { |
| 49 | + if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@.", userName]; |
| 50 | + return nil; |
| 51 | + } |
| 52 | + |
| 53 | + return [[self alloc] initWithGitCred:cred]; |
| 54 | +} |
| 55 | + |
| 56 | ++ (instancetype)credentialWithUserName:(NSString *)userName publicKeyURL:(NSURL *)publicKeyURL privateKeyURL:(NSURL *)privateKeyURL passphrase:(NSString *)passphrase error:(NSError **)error { |
| 57 | + NSParameterAssert(privateKeyURL != nil); |
| 58 | + NSString *publicKeyPath = publicKeyURL.filePathURL.path; |
| 59 | + NSString *privateKeyPath = privateKeyURL.filePathURL.path; |
| 60 | + NSAssert(privateKeyPath != nil, @"Invalid file URL passed: %@", privateKeyURL); |
| 61 | + |
| 62 | + git_cred *cred; |
| 63 | + int gitError = git_cred_ssh_keyfile_passphrase_new(&cred, userName.UTF8String, publicKeyPath.fileSystemRepresentation, privateKeyPath.fileSystemRepresentation, passphrase.UTF8String); |
| 64 | + if (gitError != GIT_OK) { |
| 65 | + if (error) *error = [NSError git_errorFor:gitError description:@"Failed to create credentials object" failureReason:@"There was an error creating a credential object for username %@ with the provided public/private key pair.\nPublic key: %@\nPrivate key: %@", userName, publicKeyURL, privateKeyURL]; |
| 66 | + return nil; |
| 67 | + } |
| 68 | + |
| 69 | + return [[self alloc] initWithGitCred:cred]; |
| 70 | +} |
| 71 | + |
| 72 | +- (instancetype)initWithGitCred:(git_cred *)cred { |
| 73 | + NSParameterAssert(cred != nil); |
| 74 | + self = [self init]; |
| 75 | + |
| 76 | + if (self == nil) return nil; |
| 77 | + |
| 78 | + _git_cred = cred; |
| 79 | + |
| 80 | + return self; |
| 81 | +} |
| 82 | + |
| 83 | +@end |
| 84 | + |
| 85 | +int GTCredentialAcquireCallback(git_cred **git_cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) { |
| 86 | + NSCParameterAssert(git_cred != NULL); |
| 87 | + NSCParameterAssert(payload != NULL); |
| 88 | + |
| 89 | + GTCredentialAcquireCallbackInfo *info = payload; |
| 90 | + GTCredentialProvider *provider = info->credProvider; |
| 91 | + |
| 92 | + if (provider == nil) { |
| 93 | + giterr_set_str(GIT_EUSER, "No GTCredentialProvider set, but authentication was requested."); |
| 94 | + return GIT_ERROR; |
| 95 | + } |
| 96 | + |
| 97 | + NSString *URL = (url != NULL ? @(url) : nil); |
| 98 | + NSString *userName = (username_from_url != NULL ? @(username_from_url) : nil); |
| 99 | + |
| 100 | + GTCredential *cred = [provider credentialForType:(GTCredentialType)allowed_types URL:URL userName:userName]; |
| 101 | + if (cred == nil) { |
| 102 | + giterr_set_str(GIT_EUSER, "GTCredentialProvider failed to provide credentials."); |
| 103 | + return GIT_ERROR; |
| 104 | + } |
| 105 | + |
| 106 | + *git_cred = cred.git_cred; |
| 107 | + return GIT_OK; |
| 108 | +} |
0 commit comments