SecItemAdd i SecItemCopyMatching zwracają kod błędu -34018 (errSecMissingEntitlement)

116

Czasami, gdy uruchamiam aplikację na urządzeniu z Xcode, próbuję uzyskać dostęp do pęku kluczy, ale kończy się to niepowodzeniem z powodu błędu -34018. Nie pasuje do żadnego z udokumentowanych kodów błędów pęku kluczy i nie może być konsekwentnie odtwarzane. (zdarza się może w 30% przypadków i nie jest dla mnie jasne, dlaczego tak się dzieje). To, co bardzo utrudnia debugowanie tego problemu, to całkowity brak dokumentacji. Masz jakiś pomysł, co to powoduje i jak to naprawić? Używam Xcode 5 i iOS 7.0.4 na urządzeniu.

W tym miejscu jest otwarty problem: https://github.com/soffes/sskeychain/issues/52

EDYCJA: Dodanie kodu dostępu do pęku kluczy na żądanie

Używam SSKeychainbiblioteki do łączenia się z pękiem kluczy. Oto fragment.

#define SERVICE @"default"

@implementation SSKeychain (EXT)

+ (void)setValue:(NSString *)value forKey:(NSString *)key {
    NSError *error = nil;
    BOOL success = NO;
    if (value) {
        success = [self setPassword:value forService:SERVICE account:key error:&error];
    } else {
        success = [self deletePasswordForService:SERVICE account:key error:&error];
    }
    NSAssert(success, @"Unable to set keychain value %@ for key %@ error %@", value, key, error);
    if (!success) {
        LogError(@"Unable to set value to keychain %@", error);
    }
    LogTrace(@"Will set keychain account %@. is to nil? %d", key, value == nil);
    if (value == nil)
        LogWarn(@"Setting keychain %@ to nil!!!", key);
}

+ (NSString *)valueForKey:(NSString *)key {
    NSError *error = nil;
    NSString *value = [self passwordForService:SERVICE account:key error:&error];
    if (error && error.code != errSecItemNotFound) {
        NSAssert(!error, @"Unable to retrieve keychain value for key %@ error %@", key, error);
        LogError(@"Unable to retrieve keychain value for key %@ error %@", key, error);
    }
    return value;
}

+ (BOOL)removeAllValues {
    LogInfo(@"Completely Reseting Keychain");
    return [[self accountsForService:SERVICE] all:^BOOL(NSDictionary *accountInfo) {
        return [self deletePasswordForService:SERVICE account:accountInfo[@"acct"]];
    }];
}

@end

Przez większość czasu jest dobrze. Czasami trafiam w błędy asercji, w których nie mogę ani pisać ani czytać z pęku kluczy, co powoduje krytyczny błąd asercji.

Tony
źródło
Mam ten sam problem i nie mogę go odtworzyć ... Używam klasy KeychainItemWrapper firmy Apple. Czasami ulega awarii w Google Analytics z tym samym komunikatem o błędzie. Korzystam z Google Analytics v3.02.
Joey
Wygląda na to, że jest OK w aplikacji z AppStore. dzieje się tak tylko w aplikacji w wersji rozwojowej.
Joey
2
Mam crashlytics dla wersji ze sklepu z aplikacjami i niestety wydaje się, że zdarza się to również w sklepie z aplikacjami, choć rzadziej niż na dev: /
Tony
3
Zastanawiam się nad odejściem od pęku kluczy, ponieważ fakt, że dane przechowywane w pęku kluczy mogą zostać losowo utracone w ten sposób, jest w zasadzie fatalnym błędem dla aplikacji.
Tony
2
Widzimy również ten sporadyczny problem. Zgłaszamy wyjątek, gdy otrzymamy nieoczekiwany kod rc z secItemCopyMatching, w tym przypadek -34018. Próbowaliśmy (niechętnie) dodać mechanizm, w którym po uzyskaniu potrzebnej wartości z pęku kluczy buforujemy ją w pamięci aplikacji, a następnie udostępniamy ją stamtąd bez dostępu do pęku kluczy. Ale teraz widzimy rzadkie sytuacje, w których jeden dostęp do pęku kluczy, aby go uzyskać, zawodzi z -34018. Czy ktoś próbował ponawiać operację po -34018?
Chris Markle,

Odpowiedzi:

45

Poprawka iOS 10 / XCode 8:

Dodaj uprawnienia do łańcucha kluczy, przejdź do ustawień projektu-> Możliwości-> Udostępnianie pęku kluczy-> Dodaj grupy pęku kluczy + włącz

Tutaj odpowiedź od Apple:

AKTUALIZACJA: w końcu udało nam się odtworzyć błąd -34018 w iOS 8.3. To pierwszy krok do zidentyfikowania głównej przyczyny, a następnie znalezienia rozwiązania.

Jak zwykle nie możemy zobowiązać się do terminu wydania, ale wpłynęło to na wielu programistów i naprawdę chcemy rozwiązać ten problem.

Wcześniej zasugerowałem dodanie małego opóźnienia w aplikacji: didFinishLaunchingWithOptions i applicationDidBecomeActive: przed uzyskaniem dostępu do pęku kluczy jako obejście. Jednak to nie wydaje się pomagać. Oznacza to, że w tej chwili nie jest znane żadne obejście problemu poza ponownym uruchomieniem aplikacji.

Wydaje się, że problem jest związany z presją pamięci, więc być może bardziej agresywna obsługa ostrzeżeń dotyczących pamięci może złagodzić problem

https://forums.developer.apple.com/thread/4743#14441

AKTUALIZACJA

OK, oto najnowsze.
Jest to złożony problem z wieloma możliwymi przyczynami:

  • Niektóre wystąpienia problemu są spowodowane nieprawidłowym podpisywaniem aplikacji. Możesz łatwo odróżnić ten przypadek, ponieważ problem jest w 100% powtarzalny.
  • Niektóre przypadki problemu są spowodowane błędem w sposobie, w jaki iOS obsługuje tworzenie aplikacji (r. 23 991 853). Debugowanie tego było skomplikowane przez fakt, że inny błąd w systemie operacyjnym (23 770 418) maskował swój wpływ, co oznacza, że ​​problem pojawiał się tylko wtedy, gdy urządzenie było pod presją pamięci. Uważamy, że te problemy zostały rozwiązane w iOS 9.3.
  • Podejrzewamy, że przyczyn tego problemu może być jeszcze więcej.

Tak więc, jeśli widzisz ten problem na urządzeniu użytkownika (takim, z którym nie rozmawiał Xcode) z systemem iOS 9.3 lub nowszym, prześlij raport o błędzie. Spróbuj dołączyć dziennik systemowy urządzenia do swojego raportu o błędzie (zdaję sobie sprawę, że może to być trudne w przypadku urządzeń klienta; jedną z opcji jest poproszenie klienta o zainstalowanie programu Apple Configurator, który umożliwia przeglądanie dziennika systemowego). A jeśli zgłosisz błąd, prześlij swój numer błędu, tylko do wiadomości.

W imieniu Apple chciałbym podziękować wszystkim za ich wysiłki w wyśledzeniu tego dość okropnego problemu. Dziel się i ciesz się

https://forums.developer.apple.com/thread/4743#126088

daidai
źródło
2
Problem nadal powtarza się na iOS 9.2, iPhone 5S.
DevGansta,
1
Wygląda na to, że system iOS 9.3 powinien rozwiązać ten problem zgodnie z najnowszą odpowiedzią firmy Apple w wątku, do którego prowadzi łącze. @daidai, czy możesz zaktualizować swoją odpowiedź o te nowe informacje?
jf
1
@YoonLee widzę to również w iOS10 - również przy użyciu AWS 2.4.8 SDK. Wystąpił błąd w linii 54 AWSClientContext.m. Czy udało Ci się rozwiązać ten problem?
CharlesA
1
@YoonLee btw, właśnie rozwiązałem ten problem, korzystając z jednej z poniższych odpowiedzi: „Udostępnianie KeyChain włączone dla celów docelowych”
CharlesA
1
@CharlesA Tak, rozwiązałem tego dnia. Masz rację. Wydaje się, że opcja „Włącz uprawnienia do łańcucha kluczy” rozwiązuje problem. O dziwo, ten błąd nie zawsze się uruchamia. W każdym razie, teraz włączam to.
Yoon Lee,
26

Zasadniczo musisz kodować swój folder .xcttest, dodając następujący skrypt jako skrypt uruchamiania w celu testowym.

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

Podczas testowania pęku kluczy na urządzeniu dostałem wiele błędów -34018 i udało mi się to naprawić.

Jeśli problem nie istnieje w celu testowym, prawdopodobnie nie jest to rozwiązanie.

JorgeDeCorte
źródło
Potwierdzono to naprawiło to w środowisku testowym. Musiałem dodać skrypt uruchamiania do rzeczywistego celu testu (np. Tych ze wszystkimi testami jednostkowymi, a nie celu kompilacji, który działa na urządzeniu). Potwierdzono również, że był to problem tylko na urządzeniu, a nie na symulatorze.
iwasrobbed
2
Otrzymuję „: nie znaleziono tożsamości Polecenie / bin / sh nie powiodło się z kodem zakończenia 1”, kiedy to robię? Zgaduję, że nie mam $ CODE_SIGN_IDENTITY. Masz jakiś pomysł, jak to naprawić?
Daniel Coffman
1
@DanielCoffman, musisz przejść do ustawień docelowych iw polu Code Signing Identity wybierz opcję „iOS Developer” (lub inną prawidłową tożsamość). To naprawia błąd kompilacji, ale przynajmniej dla mnie nie rozwiązuje problemu pęku kluczy. Nadal otrzymuję kod błędu -34018.
Marcin
3
Dzięki Marcin. Zacząłem otrzymywać ten błąd po przełączeniu na xcode 6 beta. Żadna sugestia w tym wątku nie została rozwiązana. Przywrócony do xcode 5 i -34018 już nie występuje.
Daniel Coffman
Występuje również ten błąd po raz pierwszy od czasu, gdy używam XCode 6.3.
Vladimír Slavík
13

Po sprawdzeniu kodu źródłowego . Zauważyłem, że dostęp do funkcji pęku kluczy uzyskuje się za pośrednictwem demona bezpieczeństwa, który działa we własnym procesie (oddzielonym od procesu aplikacji).

Twoja aplikacja i proces securityd „rozmawiają” ze sobą dzięki technologii o nazwie XPC .

Jeśli to konieczne, securityd jest uruchamiany za pomocą dobrze znanego polecenia launchd firmy XPC. Prawdopodobnie możesz sprawdzić, czy demon działa w aplikacji Monitor aktywności (jeśli oczywiście działa w symulatorze) i czy jego proces nadrzędny jest uruchomiony.

Domyślam się, że jest możliwe, że z jakiegoś nieznanego powodu demon bezpieczeństwa nie uruchamia się lub robi to zbyt wolno i nie jest gotowy, gdy próbujesz go użyć.

Może mógłbyś pomyśleć o tym, jak wstępnie uruchomić demona.

Przepraszam, że nie jestem bardziej precyzyjny. Mam nadzieję, że pomoże ci to pogłębić swoje badania.

Vincent Zgueb
źródło
2
Ten problem pojawia się tylko wtedy, gdy moja aplikacja jest ponownie otwierana za pomocą głębokiego łącza z następującą metodą delegata aplikacji: - (BOOL) aplikacja: (UIApplication *) application handleOpenURL: (NSURL *) url. Jeśli tylko uruchomię aplikację, pisanie pęku kluczy działa, a jeśli zminimalizuję i zmaksymalizuję aplikację, nadal będzie działać. Problem pojawia się dopiero po ponownym otwarciu z głębokim linkiem. Mam skonfigurowane MyApp.entitlements w moim projekcie (Udostępnianie pęku kluczy na karcie Możliwości) Xcode 7 beta 4.
FranticRock
Mój przypadek jest podobny do przypadku Alexa, co ma miejsce tylko wtedy, gdy aplikacja jest głęboko powiązana. W przeciwnym razie działa dobrze. Może jakiś kontekst jest nieprawidłowy, gdy aplikacja jest otwierana z innej aplikacji.
CodeBrew
12

Obserwuję podobne zachowanie po skompilowaniu i uruchomieniu mojego kodu w Xcode 6 beta z iOS 8 SDK (działa poprawnie z Xcode 5 / iOS 7). W Xcode 6 w symulatorze iOS SecItemCopyMatching zawsze zwraca wartość -34018. Zaczęło działać po włączeniu „Udostępniania pęku kluczy” na karcie Możliwości.

Jednak mam inny problem. Tworzę bibliotekę statyczną, z której korzysta m.in. aplikacja Demo. Powyższe rozwiązanie działa w przypadku projektu aplikacji Demo, ale kiedy próbuję przetestować jednostkę mojego projektu biblioteki statycznej, mam dokładnie ten sam błąd. Problem polega na tym, że mój projekt biblioteki statycznej nie ma karty Możliwości (ponieważ nie jest to samodzielna aplikacja).

Wypróbowałem rozwiązanie opublikowane tutaj przez JorgeDeCorte, z kodowaniem w celu testowym, ale dla mnie nie działa.

Marcin
źródło
8
I znowu w iOS 8 beta 3 :)
Mustafa
7
I znowu w iOS 9.0
Alex Stone
4
A teraz z powrotem w iOS 9.2 :-(
Vamos
4
Powrót do iOS 10 beta 2
Pranjal Bikash Das
3
I znowu w iOS 10 beta 5
Pascal,
6

Spróbuj wyłączyć wszystkie punkty przerwania podczas uruchamiania aplikacji z Xcode. Możesz je później włączyć.

(Żadne z powyższych obejść nie zadziałało dla mnie)

HeTzi
źródło
Dziwne. Wydaje się, że dla mnie też ten problem rozwiązuje! Za każdym razem, gdy zaczynałem debugowanie na symulatorze, mogłem zobaczyć -34018 OSStatus.
midori
4

Właśnie miałem ten sam problem na symulatorze z systemem 7.1 i 8.0. Podczas poszukiwań zauważyłem, że przykładowa aplikacja Apple miała włączone udostępnianie KeyChain ze względu na jej docelowe możliwości. Włączyłem go dla mojej aplikacji, co zaowocowało utworzeniem pliku uprawnień, który zostawiłem z domyślnymi wartościami i teraz nie dostaję już błędów -34018. To nie jest idealne, ale na razie będę korzystać z opcji udostępniania KeyChain.

Laurent
źródło
4

Projektowanie pakietu .xctest nie jest tak łatwe, jak się wydaje w niektórych przypadkach. Zasadniczo JorgeDeCorte ma rację, odpowiadając, że podana krótka linijka Run Scriptwystarczy większości deweloperów.

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

Ale jeśli masz wiele certyfikatów w swoim pęku kluczy, zakończy się niepowodzeniem z następującym wierszem

iPhone Developer: ambiguous (matches "iPhone Developer: Your Name (ABC123DEF45)" and "iPhone Developer: Your Name (123ABC456DE)"

Rozwiązaniem umożliwiającym uzyskanie odpowiedniego certyfikatu nawet przy wielu certyfikatach jest ten krótki skrypt. Na pewno nie jest to idealne rozwiązanie, ale z mojej wiedzy nie masz szans na zdobycie certyfikatu, który Xcode znalazł i używa do podpisywania aplikacji.

echo "codesign --verify --force --sign \"$CODE_SIGN_IDENTITY\" \"$CODESIGNING_FOLDER_PATH\""
IDENTITIES=`security find-identity -v -s "Code Signing" | grep "iPhone Developer" | awk '{ print $2 }'`

for SHA in $IDENTITIES; do
    codesign --verify --force --sign $SHA "$CODESIGNING_FOLDER_PATH"
    if [ $? -eq 0 ]; then
        echo "Matching identity found: $SHA"
        exit 0
    fi
done;

exit 1
Patrik
źródło
4

To też mnie ugryzło i żadne inne obejście nie powiodło się. Następnie wyczyściłem moje profile obsługi administracyjnej na samych urządzeniach, usuwając wszystkie z nich związane z moją aplikacją, a także wszystkie profile z symbolami wieloznacznymi (wydaje się, że o to chodzi). Aby to zrobić, przejdź do okna „Urządzenia” w Xcode i kliknij prawym przyciskiem myszy (podłączony) telefon:

Kliknij „Pokaż profile obsługi” i usuń powiązane, a zwłaszcza profile zespołu:

w tym te oznaczone gwiazdką. Po ponownej instalacji aplikacji wszystko wróciło do normy.

k1th
źródło
Pomogło mi to uruchomić aplikację z Xcode i kontynuować proces rozwoju.
salabaha
Podczas tworzenia wersji AdHoc możesz sprawdzić, które PP są używane. jeśli zobaczysz jakieś profile XC:, usuń je i odśwież swój PP!
dogsgod
Widzę, jak to może mieć znaczenie. Co za bałagan !! Robię porządki po upadku
David
3

Naprawiłem ten problem (chyba). Na moim urządzeniu był profil aprowizacji z użyciem symboli wieloznacznych, który wskazywał, że nie ma ono prawidłowej tożsamości podpisującej. Miałem też ważny profil aprowizacji dla mojej aplikacji. Kiedy usunąłem profil z symbolem wieloznacznym, przestałem otrzymywać błędy -34018.

Upewniłem się również, że tożsamość podpisywania kodu i profil aprowizacji wymienione w sekcji Podpisywanie kodu w ustawieniach kompilacji obiektu docelowego są identyczne z tymi dla aplikacji (nie z ogólnym „iPhone Developer”)

Dave Hirsch
źródło
Podobnie jak to naprawiło to dla mnie. Ustaw podpisywanie kodu na poziomie projektu na „iPhone Developer” na potrzeby debugowania i „iPhone Distribution” na potrzeby wydania. Następnie usunąłem zmiany w głównym celu, aby pokazywały to samo. Wcześniej zapisywanie w pęku kluczy kończyło się niepowodzeniem w 100%. Po tym zapisywanie w pęku kluczy wydaje się stabilne.
jowie
2

Bardzo rzadko otrzymywałem błąd -34018 w mojej aplikacji (iOS 8.4). Po dokładnym zbadaniu stwierdziłem, że ten problem występuje, gdy aplikacja zbyt często żąda danych z pęku kluczy .
Na przykład w mojej sytuacji były to dwa żądania odczytu jednego konkretnego klucza w tym samym czasie z różnych modułów aplikacji.
Aby to naprawić, właśnie dodałem buforowanie tej wartości w pamięci

somedev
źródło
1

Miałem ten sam problem, nieoczekiwanie, działając na urządzeniu testowym z Xcode 6.2, iPhone 6, iOS 8.3. Dla jasności, nie wystąpiło to podczas uruchamiania testów Xcode, ale raczej podczas uruchamiania rzeczywistej aplikacji na moim urządzeniu. W symulatorze wszystko było w porządku, a działanie samej aplikacji do niedawna było w porządku.

Wypróbowałem wszystkie sugestie, które mogłem tutaj znaleźć, takie jak usunięcie profili aprowizacji na moim urządzeniu (usunąłem WSZYSTKIE), tymczasowe włączenie funkcji Udostępnianie pęku kluczy w moim projekcie (nawet jeśli tak naprawdę tego nie potrzebujemy), jestem pewien, że moje konto deweloperskie w Xcode zostało całkowicie odświeżone z wszystkimi certyfikatami i profilami obsługi administracyjnej itp. Nic nie pomogło.

Następnie tymczasowo zmieniłem poziom dostępności z kSecAttrAccessibleAfterFirstUnlockna kSecAttrAccessibleAlwaysThisDeviceOnly, uruchomiłem aplikację i działała dobrze i mogłem pisać do pęku kluczy. Potem zmieniłem go z powrotem na kSecAttrAccessibleAfterFirstUnlocki problem wydaje się znikać „na stałe”.

Mason G. Zhwiti
źródło
1

Właśnie ugryzł mnie ten błąd w Xcode 8 Beta 3. Włączenie udostępniania pęku kluczy wydaje się być jedynym rozwiązaniem.

XCool
źródło
1

Miałem ten sam problem. Naprawiono to, konfigurując udostępnianie pęku kluczy.

lumenela
źródło
1

(to nie jest bezpośrednia odpowiedź na pytanie PO, ale może pomóc innym)

Zaczęto otrzymywać błąd pęku kluczy -34018 konsekwentnie w symulatorze po zaktualizowaniu Xcode z wersji 7.3.1 do 8.0.

Zgodnie z tą wskazówką z odpowiedzi Daidai ,

Niektóre wystąpienia problemu są spowodowane nieprawidłowym podpisywaniem aplikacji. Możesz łatwo odróżnić ten przypadek, ponieważ problem jest w 100% powtarzalny.

odkryto, że profil obsługi administracyjnej został w jakiś sposób ustawiony na Brak w sekcjach podpisywania obiektu docelowego.

Jednak ustawienie pól profilu aprowizacji na prawidłowe wartości nie było wystarczające, aby rozwiązać problem w tym przypadku.

Dalsze dochodzenie wykazało, że uprawnienie do powiadomień push również wyświetlało błąd. Jest tam napisane „Dodaj funkcję powiadomień push do identyfikatora aplikacji”. krok został zakończony, ale krok „Dodaj uprawnienie do powiadomień push do pliku uprawnień” nie.

Po naciśnięciu „Napraw problem” w celu naprawienia problemu z powiadomieniem wypychanym błąd pęku kluczy został rozwiązany.

W przypadku tego konkretnego celu uprawnienie „Udostępnianie pęku kluczy” zostało już wcześniej włączone. Wyłączenie go nie spowodowało na razie ponownego pojawienia się błędu pęku kluczy, więc nie jest jasne, czy jest to konieczne w tym przypadku.

jk7
źródło
0

W iOS 9 wyłączyłem Address Sanitizer i zacząłem działać na urządzeniu.

Pulse4life
źródło
0

Jedynym rozwiązaniem, które działało dla mnie, było najpierw zapisanie zera dla określonego klucza, a następnie zapisanie mojej nowej wartości za pomocą oddzielnej operacji. Gdybym spróbował zastąpić istniejącą wartość, nie powiedzie się z powodu błędu -34018. Ale tak długo, jak zapisałem zero jako pierwszy, zaktualizowana wartość zostanie pomyślnie zapisana natychmiast potem.

FranticRock
źródło
0

Spotkałem się dzisiaj z problemem -34018 podczas uruchamiania interfejsu API SecItemDelete. To, co zrobiłem, aby to naprawić, to: 1. Po rozwiązaniu @ k1th https://stackoverflow.com/a/33085955/889892 2. Uruchom SecItemDelete w głównym wątku (poprzednio było to odczytywane z głównego wątku, więc po prostu dopasuj to do usuwania) .

Przepraszam, że wraca ponownie :(

Senry
źródło
0

Włącz udostępnianie pęku kluczy w możliwościach projektu, powinno to rozwiązać problem. wprowadź opis obrazu tutaj

Rizwan Ahmed
źródło
0

Co mi pomogło

  • Włącz udostępnianie pęku kluczy.
  • Używaj pęku kluczy jak najmniej i buforuj dane w pamięci, preferencjach użytkownika, dysku itp.
  • Ponów wiele razy operacje CRUD pęku kluczy, jeśli te nie powiodły się.
  • Użyj DispatchQueue.sync do przechowywania / usuwania / aktualizowania danych.
rockdaswift
źródło
0

Dla mnie był to problem z podpisywaniem aplikacji. Po prostu przełączyłem się na właściwy zespół podpisujący w Xcode i błąd już się nie pojawiał

Adam Smith
źródło