Hồ sơ VPN trên iOS: passwordReference, không phải mật khẩu
Tham chiếu chuỗi khóa là một tay nắm, không phải bí mật. Truyền byte giải thích lỗi -50, sự cố sau khi khởi động lại và bẫy luân chuyển trong hồ sơ VPN đã lưu.
Bạn cài một hồ sơ, đường hầm dựng lên và mọi thứ trông như đã xong. Rồi điện thoại khởi động lại, on-demand đánh thức kết nối mà không có ứng dụng nào ở tiền cảnh, và đường hầm từ chối khởi động. Hồ sơ vẫn còn đó và mật khẩu vẫn đúng, đó là lý do sự cố này khiến người ta tìm sai chỗ. Network Extension không thể đọc bí mật của bạn từ hồ sơ: nó cần một tham chiếu chuỗi khóa mà nó tự giải được.
Phần dưới đây theo dõi một lần thử kết nối qua bước bàn giao đó, từ truy vấn dựng nên tham chiếu đến lần khởi động lại kiểm tra nó.
Hồ sơ lưu một tay nắm, không phải bí mật
NEVPNProtocol phơi ra passwordReference và sharedSecretReference vì một lý do. Khi daemon khởi động một đường hầm, nó có thể không chạy trong tiến trình của bạn, nên không thể gọi mã của bạn và xin mật khẩu. Nó đọc một tham chiếu bền vững trong chuỗi khóa, giải nó trong ngữ cảnh riêng và tự lấy mục đó.
Bạn dựng tham chiếu đó bằng cách hỏi chuỗi khóa, đây là một yêu cầu khác với yêu cầu dữ liệu:
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: "vpn-credentials",
kSecAttrAccount as String: "user",
kSecReturnPersistentRef as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]Hãy trao đối tượng trả về cho giao thức, không phải dữ liệu của mục. Trên thực tế hồ sơ ghi lại nơi bí mật sống, vì thế bản sao lưu cấu hình không âm thầm nhân đôi mật khẩu vào một plist.
Vì sao API trả lời -50
errSecParam nghĩa là yêu cầu hoặc giá trị bị tạo sai hình dạng cho thao tác đó, và đây là lỗi hay gặp nhất khi các yêu cầu tham chiếu và dữ liệu lẫn lộn. Yêu cầu dữ liệu trong khi mã nhận mong đợi một tham chiếu, gán byte thô vào passwordReference, hoặc truy vấn bằng một nhóm truy cập mà ứng dụng không dùng được, tất cả đều sinh ra nó.
Thư viện bọc mời gọi điều này. Một hàm trợ giúp trả byte không thay thế được cho hàm trả tham chiếu, nên cách sửa thường là một truy vấn khác chứ không phải một mật khẩu khác.
Cùng sự không khớp đó giải thích một hồ sơ lưu không kêu ca rồi không kết nối được: thứ được lưu là một blob, không phải tay nắm, và daemon không có gì để giải.
Lưu tốt, hỏng khi kết nối
Việc lưu dùng ngữ cảnh của ứng dụng bạn. Việc kết nối dùng ngữ cảnh của daemon, và hai bên không có cùng quyền truy cập. Vì thế một hồ sơ có thể qua mọi bài kiểm tra trong trình giả lập và hỏng ngay lần khởi động on-demand đầu tiên.
Hình dạng triệu chứng khi khởi động lại cũng vậy: nó chạy khi ứng dụng mở và chết khi hệ thống tự khởi động đường hầm.
Hãy thử đường nền một cách có chủ đích trước khi phát hành. Kích hoạt một kết nối on-demand khi ứng dụng đóng, rồi đọc bảng điều khiển của thiết bị chứ không phải nhật ký ứng dụng, vì sự cố do tiến trình đã cố giải tham chiếu ghi lại. Nếu bảng điều khiển cho thấy daemon từ chối mục, tham chiếu vẫn tốt và vấn đề là khả năng truy cập của mục.
Khả năng truy cập quyết định lần khởi động lại có chạy không
Mục phải đọc được bởi bất kỳ tiến trình hệ thống nào khởi động đường hầm, và đó là nhóm rộng hơn ứng dụng của bạn khi ở tiền cảnh. Ràng buộc đó chọn thuộc tính truy cập thay bạn. Một mục được bảo vệ đến lần mở khóa đầu tiên thì sẵn có cho lần khởi động nền sau khi thiết bị đã mở khóa một lần; một mục đòi thiết bị phải mở khóa ngay bây giờ thì không.
Chọn lớp chặt hơn thì hấp dẫn, và chính nó làm hỏng hồ sơ on-demand trên một chiếc điện thoại đang khóa.
Sau khi đổi lớp, hãy tạo lại mục thay vì sửa thuộc tính trên mục đang có, rồi lưu lại giao thức với tham chiếu mới. Thay đổi thuộc tính trên một mục đang có không phải lúc nào cũng cho hành vi mà tài liệu ngụ ý, và một mục được dựng lại xóa đi nghi ngờ.
Luân chuyển là nơi hồ sơ đã lưu mục rữa
Đổi mật khẩu trong chuỗi khóa không tự động đổi thứ mà hồ sơ đã lưu trỏ tới. Xóa mục thì tệ hơn: hồ sơ giữ một tham chiếu tới thứ không còn nữa, và sự cố trông như bị từ chối xác thực.
Luân chuyển theo một thứ tự. Cập nhật mục, truy vấn một tham chiếu bền vững mới, lưu lại giao thức, rồi kết nối khi ứng dụng đóng để chứng minh daemon vẫn giải được nó. Giữ mật khẩu người dùng và bí mật chia sẻ trong các mục riêng để mỗi thứ luân chuyển theo lịch của nó, và không bao giờ ghi nhật ký từ điển truy vấn hay chính tham chiếu. Tay nắm không phải bí mật, nhưng nó là bản đồ dẫn tới bí mật.