0

私は、MY アプリケーションから VPN 接続を作成するために MAC アプリケーションに取り組んでいます。

多くの調査の結果、アプリケーションをROOTとして実行して、ユーザーパスワードとsharedSecretKeyをSYSTEMキーチェーンに保存する必要があることがわかりました。

アプリケーション ユーザーはアプリケーションを ROOT として開かないので、 ROOT アクセスなしでシステムキーチェーンにユーザー パスワードと sharedsecretkey を追加する必要があります。

これについてWebで検索したところ、Appleがこのコードを提供していることがわかりました:https://developer.apple.com/library/mac/samplecode/SMJobBless/Introduction/Intro.html https://developer.apple.com/library/mac /samplecode/EvenBetterAuthorizationSample/はじめに/Intro.html

しかし、アプリケーションでこの2つのコードを使用して、ユーザーのパスワードと SharedSecretKey をSYSTEM KEYCHAIN WITH OUT ROOT ACCESSに保存する方法がわかりませんでした。

どんな助けでも大歓迎です。

前もって感謝します。

SYSTEM KEYCHAIN にパスワードを追加するコードは次のとおりです。私のコードを ROOT として実行するとうまくいきます。

// Vendor dependencies
#import <Security/SecKeychain.h>

// Local dependencies
#import "VPNKeychain.h"

// These are the applications which are going to get access to new Keychain items.
// How do we know them? Just create a VPN service manualy and run the following command:
//   security dump-keychain -a /Library/Keychains/System.keychain
// Among the results, you will find your VPN service and you can see the paths that have access to it
static const char * trustedAppPaths[] = {
      "/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/Helpers/SCHelper",          "/System/Library/PreferencePanes/Network.prefPane/Contents/XPCServices/com.apple.preference.network.remoteservice.xpc",
  "/System/Library/CoreServices/SystemUIServer.app",
  "/usr/sbin/pppd",
  "/usr/sbin/racoon",
  "/usr/libexec/configd",
    };

// This class contains all code we need to handle System Keychain Items
// Exit status codes: 60-79
@implementation VPNKeychain


// This will create a PPP Password Keychain Item
+ (int) createPasswordKeyChainItem:(NSString*)label forService:(NSString*)service withAccount:(NSString*)account andPassword:(NSString*)password {
  return [self createItem:label withService:service account:account description:@"PPP Password" andPassword:password];
}

// This will create an IPSec Shared Secret Keychain Item
+ (int) createSharedSecretKeyChainItem:(NSString*)label forService:(NSString*)service withPassword:(NSString*)password {
  service = [NSString stringWithFormat:@"%@.SS", service];
  return [self createItem:label withService:service account:@"" description:@"IPSec Shared Secret" andPassword:password];
}


// A generic method to create Keychain Items holding Network service passwords
+ (int) createItem:(NSString*)label withService:(NSString*)service account:(NSString*)account description:(NSString*)description andPassword:(NSString*)password {

  // This variable will hold all sorts of operation status responses
  OSStatus status;

  // Converting the NSStrings to char* variables which we will need later
  const char *labelUTF8 = [label UTF8String];
  const char *serviceUTF8 = [service UTF8String];
  const char *accountUTF8 = [account UTF8String];
  const char *descriptionUTF8 = [description UTF8String];
  const char *passwordUTF8 = [password UTF8String];

  // This variable is soon to hold the System Keychain
  SecKeychainRef keychain = NULL;

  status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem,     &keychain);
  if (status == errSecSuccess) {
    NSLog(@"Succeeded opening System Keychain");
  } else {
    NSLog(@"Could not obtain System Keychain: %@", SecCopyErrorMessageString(status, NULL));
    return 60;
  }

  NSLog(@"Unlocking System Keychain");
  status = SecKeychainUnlock(keychain, 0, NULL, FALSE);
  if (status == errSecSuccess) {
    NSLog(@"Succeeded unlocking System Keychain");
  } else {
    NSLog(@"Could not unlock System Keychain: %@", SecCopyErrorMessageString(status, NULL));
    return 61;
  }

  // This variable is going to hold our new Keychain Item
  SecKeychainItemRef item = nil;

    SecAccessRef access = nil;
  status = SecAccessCreate(CFSTR("Some VPN Test"), (__bridge CFArrayRef)(self.trustedApps), &access);

  if(status == noErr) {
    NSLog(@"Created empty Keychain access object");
  } else {
    NSLog(@"Could not unlock System Keychain: %@", SecCopyErrorMessageString(status, NULL));
    return 62;
  }

  // Putting together the configuration options
  SecKeychainAttribute attrs[] = {
{kSecLabelItemAttr, (int)strlen(labelUTF8), (char *)labelUTF8},
{kSecAccountItemAttr, (int)strlen(accountUTF8), (char *)accountUTF8},
{kSecServiceItemAttr, (int)strlen(serviceUTF8), (char *)serviceUTF8},
{kSecDescriptionItemAttr, (int)strlen(descriptionUTF8), (char *)descriptionUTF8},
  };

  SecKeychainAttributeList attributes = {sizeof(attrs) / sizeof(attrs[0]), attrs};

  status = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, (int)strlen(passwordUTF8), passwordUTF8, keychain, access, &item);

  if(status == noErr) {
    NSLog(@"Successfully created Keychain Item");
  } else {
    NSLog(@"Creating Keychain item failed: %@", SecCopyErrorMessageString(status, NULL));
    return 63;
  }
  return 0;
}

+(NSArray*) trustedApps {
  NSMutableArray *apps = [NSMutableArray array];
  SecTrustedApplicationRef app;
  OSStatus err;

  for (int i = 0; i < (sizeof(trustedAppPaths) /     sizeof(*trustedAppPaths)); i++) {
    err = SecTrustedApplicationCreateFromPath(trustedAppPaths[i], &app);
    if (err == errSecSuccess) {
      //NSLog(@"SecTrustedApplicationCreateFromPath succeeded: %@", SecCopyErrorMessageString(err, NULL));
    } else {
      NSLog(@"SecTrustedApplicationCreateFromPath failed: %@", SecCopyErrorMessageString(err, NULL));
    }

    [apps addObject:(__bridge id)app];
  }

  return apps;
}
4

2 に答える 2

1

OS X では、アプリケーションはユーザーの資格情報を直接処理するのではなく、関数呼び出し AuthorizationCopyRights を介してシステムに要求します。これについてはAuthorization Servicesに記載されています。

Gui アプリケーションは管理 (ルート) アクションを直接実行できず、Yosemite (10.10) 以降、Gui アプリケーションはルートとして実行できません。代わりに、アプリケーションは XPC サービスを介して「ヘルパー」アプリケーションを使用する必要があります。これは、SMJobBless および BetterAuthorization のサンプルが示すものです。XPCの詳細については、こちらをご覧ください。

あなたの場合、システム キーチェーンにアクセスするために必要な権限を持つヘルパー アプリケーションを作成する必要があります。

Apple Store 経由でアプリケーションを配布する予定の場合、アプリケーションはサンドボックス化する必要があり、AuthorizationCopyRights 関数の呼び出しなどのセキュリティ サービスを使用できないことに注意してください。

于 2015-03-31T14:39:51.853 に答える
1

リンク先のサンプル コードで説明されています。 ReadMe.txtを参照してください。

サンプルを実行すると、管理者のユーザー名とパスワードの入力を求められます。管理者のユーザー名とパスワードを入力します。問題がなければ、サンプルのウィンドウに「The Helper Tool is available!」と表示されます。すべてが正常であることを示します。そうでない場合は、コンソール ログで障害に関する情報を確認できます。

したがって、通常、アプリケーションはある時点で管理者の資格情報を要求する必要があります。

アップデート:

これは、引用されたSMJobBless例に示されているように、特権ヘルパー ツールを使用して実行する必要があります。ヘルパー ツールは、アプリのキーチェーン アクセスを実行する必要があります。このようなヘルパー ツールをインストールする主な手順は次のとおりです。

  • 関数を使用して認可オブジェクトを作成しAuthorizationCreateます。

  • 関数を使用して、指定された一連の権利を持つオブジェクトに対して事前承認を実行し AuthorizationCopyRightsます。実際、これにより、ユーザーに管理者の資格情報が求められます。

  • 関数を使用して、ヘルパー ツールを確認、インストール、および launchd に登録し SMJobBlessます。

ヘルパー ツールをインストールして登録したら、ヘルパー ツールとNSXPCConnection対話するために を使用する必要があります。実現方法の詳細については、NSXPCConnectionサンプル コードを使用したサンドボックス化を参照してください。

于 2015-03-31T10:19:55.817 に答える