Chúng tôi có một Daemon khởi chạy (nhất thiết, vì nhiều lý do) chạy dưới dạng root và giao tiếp với một thành phần máy chủ qua mạng. Nó cần phải xác thực với dịch vụ, vì vậy khi nó lần đầu tiên có được mật khẩu, chúng tôi lưu nó vào keychain hệ thống. Trong lần khởi chạy tiếp theo, ý tưởng là lấy lại mật khẩu từ móc khóa và sử dụng nó để xác thực với dịch vụ mạng.Mac Khởi động Daemon không thể lấy mật khẩu từ móc khóa hệ thống sau khi lưu nó ở đó
Điều này đã hoạt động tốt, nhưng trên macOS 10.12 mã hiện tại ngừng hoạt động và chúng tôi đã hoàn toàn bối rối về cách sửa lỗi này. Nó nắm này:
Cho dù chúng ta đang tiết kiệm một mật khẩu mới hoặc lấy một cái cũ, chúng tôi có được một tham chiếu đến keychain hệ thống sử dụng này:
SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &system_keychain);
Chúng tôi cũng vô hiệu hóa tương tác người dùng cho biện pháp tốt, mặc dù chúng tôi hy vọng nó đã được tắt trong bối cảnh của một daemon.
SecKeychainSetUserInteractionAllowed(false);
Khi lưu một mật khẩu mới cho keychain, chúng tôi sử dụng
OSStatus status = SecKeychainAddInternetPassword(
system_keychain,
urlLength, server_base_url,
0, NULL,
usernameLength, username,
0, NULL,
0,
kSecProtocolTypeAny, kSecAuthenticationTypeAny,
passwordLength, password,
NULL);
này nhiều công trình. Thành công được báo cáo và tôi có thể thấy mục trong keychain "hệ thống" trong Keychain Access.app.
Lấy nó trên chạy tiếp theo của daemon của chúng tôi được thực hiện với dòng này:
status = SecKeychainFindInternetPassword(
system_keychain,
urlLength, url,
0, NULL,
usernameLength, username,
0, NULL,
0,
kSecProtocolTypeAny, kSecAuthenticationTypeAny,
&passwordLength, &password_data,
NULL);
Thật không may, điều này đã bắt đầu quay trở lại errSecAuthFailed
vì lý do đó không rõ ràng đối với chúng tôi.
Một vài chi tiết thêm, chúng tôi đã kiểm tra và điều chúng tôi đã cố gắng, không có kết quả:
- Các nhị phân daemon được ký kết với một chứng chỉ Id phát triển.
- Mã nhị phân daemon chứa phần Info.plist được nhúng với ID gói và phiên bản.
- Tôi có thể xem nhị phân daemon trong danh sách "Luôn cho phép truy cập bởi các ứng dụng này" trong tab "Kiểm soát truy cập" của mục mật khẩu trong Keychain Access.app.
- Nếu tôi tự chuyển sang "Cho phép tất cả ứng dụng truy cập mục này" trong Keychain Access, nó hoạt động. Điều này phần nào đánh bại các điểm tiết kiệm mật khẩu trong keychain, tuy nhiên.
- Chúng tôi đã thử chơi xung quanh với các tham số cho
SecKeychainAddInternetPassword
, nhưng điều này dường như không tạo ra bất kỳ sự khác biệt nào. - Chúng tôi đã cố gắng mở khoá một cách rõ ràng với
SecKeychainUnlock()
, nhưng như tài liệu cho thấy, điều này có vẻ không cần thiết. - Xóa mục trong
Keychain Access.app
gây raSecKeychainFindInternetPassword()
để mang lạierrSecItemNotFound
, như bạn mong đợi. Vì vậy, nó có thể chắc chắn tìm thấy mục đã lưu, nó không được phép đọc nó.
Tài liệu móc khóa không phải là dễ đọc chính xác và ở các phần thay đổi theo kinh nghiệm. ("Để làm Y, bạn cần phải làm Y", mà không đề cập đến lý do tại sao bạn muốn làm Y.) Tuy nhiên, tôi nghĩ rằng tôi đã thực hiện nó thông qua và đã hiểu hầu hết của nó.Các khía cạnh khác nhau của thiết lập cụ thể của chúng tôi không được đề cập chi tiết (truy cập từ một daemon), nhưng có vẻ khá rõ ràng khi truy cập một mục trước đây được lưu bởi cùng một ứng dụng không yêu cầu bất kỳ ủy quyền hoặc xác thực đặc biệt nào. Đó là mâu thuẫn trực tiếp với hành vi mà chúng ta đang thấy.
Bất kỳ ý tưởng nào?