]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/pam_systemd_loadkey.c
Merge pull request #32547 from YHNdnzj/minor-cleanup
[thirdparty/systemd.git] / src / login / pam_systemd_loadkey.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <security/_pam_macros.h>
5 #include <security/pam_ext.h>
6 #include <security/pam_misc.h>
7 #include <security/pam_modules.h>
8 #include <security/pam_modutil.h>
9
10 #include "keyring-util.h"
11 #include "macro.h"
12 #include "missing_syscall.h"
13 #include "nulstr-util.h"
14 #include "pam-util.h"
15 #include "strv.h"
16
17 /* By default, this module retrieves the key stored by systemd-cryptsetup.
18 * This can be overridden by the keyname= parameter. */
19 static const char DEFAULT_KEYNAME[] = "cryptsetup";
20
21 _public_ PAM_EXTERN int pam_sm_authenticate(
22 pam_handle_t *handle,
23 int flags,
24 int argc, const char **argv) {
25
26 assert(handle);
27
28 pam_log_setup();
29
30 /* Parse argv. */
31
32 assert(argc >= 0);
33 assert(argc == 0 || argv);
34
35 const char *keyname = DEFAULT_KEYNAME;
36 bool debug = false;
37
38 for (int i = 0; i < argc; i++) {
39 const char *p;
40
41 if ((p = startswith(argv[i], "keyname=")))
42 keyname = p;
43 else if (streq(argv[i], "debug"))
44 debug = true;
45 else
46 pam_syslog(handle, LOG_WARNING, "Unknown parameter '%s', ignoring.", argv[i]);
47 }
48
49 pam_debug_syslog(handle, debug, "pam-systemd-loadkey initializing");
50
51 /* Retrieve the key. */
52
53 key_serial_t serial;
54 serial = request_key("user", keyname, NULL, 0);
55 if (serial < 0) {
56 if (errno == ENOKEY) {
57 pam_debug_syslog(handle, debug, "Key not found: %s", keyname);
58 return PAM_AUTHINFO_UNAVAIL;
59 } else if (errno == EKEYEXPIRED) {
60 pam_debug_syslog(handle, debug, "Key expired: %s", keyname);
61 return PAM_AUTHINFO_UNAVAIL;
62 } else
63 return pam_syslog_errno(handle, LOG_ERR, errno, "Failed to look up the key: %m");
64 }
65
66 _cleanup_(erase_and_freep) void *p = NULL;
67 size_t n;
68 int r;
69
70 r = keyring_read(serial, &p, &n);
71 if (r < 0)
72 return pam_syslog_errno(handle, LOG_ERR, r, "Failed to read the key: %m");
73
74 /* Split the key by NUL. Set the last item as authtok. */
75
76 _cleanup_(strv_free_erasep) char **passwords = strv_parse_nulstr(p, n);
77 if (!passwords)
78 return pam_log_oom(handle);
79
80 size_t passwords_len = strv_length(passwords);
81 if (passwords_len == 0) {
82 pam_debug_syslog(handle, debug, "Key is empty");
83 return PAM_AUTHINFO_UNAVAIL;
84 } else if (passwords_len > 1)
85 pam_debug_syslog(handle, debug, "Multiple passwords found in the key. Using the last one");
86
87 r = pam_set_item(handle, PAM_AUTHTOK, passwords[passwords_len - 1]);
88 if (r != PAM_SUCCESS)
89 return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to set PAM auth token: @PAMERR@");
90
91 return PAM_SUCCESS;
92 }
93
94 _public_ PAM_EXTERN int pam_sm_setcred(
95 pam_handle_t *handle,
96 int flags,
97 int argc, const char **argv) {
98
99 return PAM_SUCCESS;
100 }