2016-11-16 9 views
5

हमारे पास एक लॉन्च डेमॉन है (जरूरी है कि, विभिन्न कारणों से) रूट के रूप में चलता है, और जो नेटवर्क के माध्यम से सर्वर घटक के साथ संचार करता है। इसे सेवा के साथ प्रमाणित करने की आवश्यकता है, इसलिए जब यह पहली बार पासवर्ड प्राप्त करता है, तो हम इसे सिस्टम कीचेन में सहेजते हैं। बाद के लॉन्च पर, विचार कुंजीचैन से पासवर्ड पुनर्प्राप्त करना और नेटवर्क सेवा के साथ प्रमाणित करने के लिए इसका उपयोग करना है।मैक लॉन्च डेमन इसे सहेजने के बाद सिस्टम कीचेन से पासवर्ड पुनर्प्राप्त करने में असमर्थ

यह ठीक काम कर रहा है, लेकिन मैकोज़ 10.12 पर मौजूदा कोड काम करना बंद कर दिया है, और हम पूरी तरह से इसे ठीक करने के तरीके पर फंस गए हैं। यह इस करने पर निर्भर करता:

हम एक नया पासवर्ड बचत या एक पुराने एक को पुन: प्राप्त कर रहे हैं के बावजूद, हम प्रणाली कीचेन के लिए एक संदर्भ इस का उपयोग कर प्राप्त:

SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &system_keychain); 

हम भी अक्षम उपयोगकर्ता संपर्क अच्छा उपाय, हालांकि हम उम्मीद करेंगे कि यह पहले से ही एक डेमॉन के संदर्भ में बंद हो जाएगा।

SecKeychainSetUserInteractionAllowed(false); 

जब कीचेन के लिए एक नया पासवर्ड बचत, हम

OSStatus status = SecKeychainAddInternetPassword(
    system_keychain, 
    urlLength, server_base_url, 
    0, NULL, 
    usernameLength, username, 
    0, NULL, 
    0, 
    kSecProtocolTypeAny, kSecAuthenticationTypeAny, 
    passwordLength, password, 
    NULL); 

यह बहुत काम करता है का उपयोग करें। सफलता की सूचना दी गई है, और मैं Keychain Access.app में "सिस्टम" कीचेन में आइटम देख सकता हूं।

हमारे डेमॉन के बाद रन पर प्राप्त कर रहा है इस लाइन के साथ किया जाता है:

status = SecKeychainFindInternetPassword(
    system_keychain, 
    urlLength, url, 
    0, NULL, 
    usernameLength, username, 
    0, NULL, 
    0, 
    kSecProtocolTypeAny, kSecAuthenticationTypeAny, 
    &passwordLength, &password_data, 
    NULL); 

दुर्भाग्य से, यह कारण है कि हमें यह स्पष्ट नहीं कर रहे हैं के लिए errSecAuthFailed लौटने शुरू हो गया है।

कुछ अतिरिक्त विवरण हम जांच की है और बातें हम कोशिश की है, कोई लाभ नहीं हुआ:

  • डेमॉन बाइनरी में डेवलपर आईडी प्रमाणपत्र के साथ हस्ताक्षरित किया गया है।
  • डेमॉन बाइनरी में एक बंडल आईडी और संस्करण के साथ एक एम्बेडेड Info.plist अनुभाग होता है।
  • मैं Keychain Access.app में पासवर्ड आइटम के "एक्सेस कंट्रोल" टैब में "हमेशा इन एप्लिकेशन द्वारा एक्सेस की अनुमति दें" सूची में डेमन बाइनरी देख सकता हूं।
  • यदि मैं मैन्युअल रूप से कुंजीपैन एक्सेस में "सभी एप्लिकेशन को इस आइटम तक पहुंचने की अनुमति देता हूं" पर स्विच करता हूं, तो यह काम करता है। हालांकि, यह कुछ हद तक कुंजीचैन में पासवर्ड को सहेजने के बिंदु को हरा देता है।
  • हमने पैरामीटर के साथ SecKeychainAddInternetPassword पर खेलने की कोशिश की है, लेकिन ऐसा कोई फर्क नहीं पड़ता है।
  • हमने SecKeychainUnlock() के साथ कीचेन को स्पष्ट रूप से अनलॉक करने का प्रयास किया है, लेकिन जैसा कि प्रलेखन सुझाव देता है, यह अनिवार्य प्रतीत होता है।
  • Keychain Access.app में आइटम को हटाने से SecKeychainFindInternetPassword()errSecItemNotFound उत्पन्न करने के कारण होता है, जैसा कि आप उम्मीद करेंगे। तो यह निश्चित रूप से सहेजे गए आइटम को ढूंढ सकता है, इसे पढ़ने की अनुमति नहीं है।

कीचेन दस्तावेज पढ़ने और भागों में बल्कि tautological के लिए बिल्कुल आसान नहीं है। ("वाई करने के लिए, आपको वाई करने की ज़रूरत है," यह उल्लेख किए बिना कि आप वाई क्यों करना चाहते हैं।) फिर भी, मुझे लगता है कि मैंने इसे बनाया है और इसमें से अधिकांश को समझ लिया है।हमारे विशेष सेटअप के विभिन्न पहलुओं को विस्तार से शामिल नहीं किया गया है (एक डेमॉन से एक्सेस), लेकिन यह बहुत स्पष्ट लगता है कि एक ही ऐप को उसी ऐप द्वारा सहेजा गया एक आइटम तक पहुंचने से पहले को किसी विशेष प्राधिकरण या प्रमाणीकरण की आवश्यकता नहीं होनी चाहिए। जो हम देख रहे व्यवहार के प्रत्यक्ष विरोधाभास में है।

कोई भी विचार?

उत्तर

7

कई दिनों में इस पर कुछ और घंटों खर्च करने के बाद, हमने आखिरकार काम किया कि क्या हो रहा था।

सबसे पहले, मैंने एक न्यूनतम उदाहरण बनाने की कोशिश की जो समस्या को पुन: उत्पन्न करेगी। यह errSecAuthFailed के साथ विफल नहीं हुआ और इस प्रकार समस्या को पुन: उत्पन्न नहीं किया। तो मूल डेमॉन पर वापस, इसके बारे में विशेष रूप से कुछ होना चाहिए जो गलत हो रहा था।

अगले विचार समय के लिए सिस्टम लॉग की जाँच करने के लिए जब SecKeychainFindInternetPassword() बुलाया गया था था। इससे कुछ त्रुटि संदेश सामने आए:

securityd CSSM Exception: -2147411889 CSSMERR_CL_UNKNOWN_TAG 
securityd MacOS error: -67063 
securityd MacOS error: -67063 
securityd code requirement check failed (-67063), client is not Apple-signed 
securityd CSSM Exception: 32 CSSM_ERRCODE_OPERATION_AUTH_DENIED 
OurDaemon subsystem: com.apple.securityd, category: security_exception, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 2, enable_private_data: 0 
OurDaemon CSSM Exception: -2147416032 CSSMERR_CSP_OPERATION_AUTH_DENIED 

यह सुझाव दिया गया कि समस्या कोड हस्ताक्षर के साथ हो सकती है। अजीब। codesign -vv के साथ बाइनरी के कोड हस्ताक्षर की जांच करने से कोई समस्या नहीं आई है।

त्रुटि संदेश के विभिन्न भागों के लिए वेब के आसपास शिकार के बाद, मैं -67063 corresponds to errSecCSGuestInvalid पाया। टिप्पणी पढ़ती है "कोड पहचान अवैध कर दी गई है।"

ठीक है, निश्चित रूप से कुछ कोडिंग त्रुटि है, लेकिन इसका क्या अर्थ है, और ऐसा क्यों हुआ?

शिकार कुछ और अंत में स्पष्टीकरण, और भी समाधान कर दिया चारों ओर: http://lists.apple.com/archives/apple-cdsa/2010/Mar/msg00027.html

इसका मतलब है कि कुछ बिंदु के बाद से कार्यक्रम शुरू हुई है, कुछ यह हुआ है कि यह अवैध बना दिया पर।

और

यदि आप एक हस्ताक्षर किए कार्यक्रम चलाने, तो इसे बदलना (द्वारा, कहते हैं, जगह :-) में एक नए संस्करण का निर्माण, और फिर नए संस्करण, कर्नेल चलाने अभी भी निष्पादन योग्य vnode से जुड़ा पुराना हस्ताक्षर रखेगा। यदि यह आपकी स्थिति है, तो निष्पादन योग्य को हटा दें और को पुन: प्रयास करें, यह अच्छी तरह से समस्या को साफ़ करता है (जब तक आप फ़ाइल को फिर से लिखते हैं :-)। हम अनुशंसा करते हैं कि हस्ताक्षरित कोड हमेशा प्रतिस्थापित किया जाए (एमवी (1), सीपी (1), या समकक्ष)।

यह समझाया। मैं

sudo cp path/to/built/daemon /usr/local/libexec/ 

जाहिर है, कि बजाय एक नया vnode बनाना, जिनका लेखन, और फिर पुरानी फाइल के ऊपर इसका नाम से यथा-स्थान फ़ाइल अधिलेखित कर देता है का उपयोग कर जगह में डेमॉन के नए संस्करणों को कॉपी किया गया था। इसलिए समाधान cp को पहले एक temp निर्देशिका में, और फिर mv स्थान पर है। या cp का उपयोग करने से पहले गंतव्य फ़ाइल को हटाएं।

जैसे ही मैंने ऐसा किया, यह काम किया!

संबंधित मुद्दे