1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <security/pam_ext.h>
4 #include <syslog.h>
5 #include <stdlib.h>
6
7 #include "alloc-util.h"
8 #include "errno-util.h"
9 #include "macro.h"
10 #include "pam-util.h"
11
pam_log_oom(pam_handle_t * handle)12 int pam_log_oom(pam_handle_t *handle) {
13 /* This is like log_oom(), but uses PAM logging */
14 pam_syslog(handle, LOG_ERR, "Out of memory.");
15 return PAM_BUF_ERR;
16 }
17
pam_bus_log_create_error(pam_handle_t * handle,int r)18 int pam_bus_log_create_error(pam_handle_t *handle, int r) {
19 /* This is like bus_log_create_error(), but uses PAM logging */
20 pam_syslog(handle, LOG_ERR, "Failed to create bus message: %s", strerror_safe(r));
21 return PAM_BUF_ERR;
22 }
23
pam_bus_log_parse_error(pam_handle_t * handle,int r)24 int pam_bus_log_parse_error(pam_handle_t *handle, int r) {
25 /* This is like bus_log_parse_error(), but uses PAM logging */
26 pam_syslog(handle, LOG_ERR, "Failed to parse bus message: %s", strerror_safe(r));
27 return PAM_BUF_ERR;
28 }
29
cleanup_system_bus(pam_handle_t * handle,void * data,int error_status)30 static void cleanup_system_bus(pam_handle_t *handle, void *data, int error_status) {
31 sd_bus_flush_close_unref(data);
32 }
33
pam_acquire_bus_connection(pam_handle_t * handle,sd_bus ** ret)34 int pam_acquire_bus_connection(pam_handle_t *handle, sd_bus **ret) {
35 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
36 int r;
37
38 assert(handle);
39 assert(ret);
40
41 /* We cache the bus connection so that we can share it between the session and the authentication hooks */
42 r = pam_get_data(handle, "systemd-system-bus", (const void**) &bus);
43 if (r == PAM_SUCCESS && bus) {
44 *ret = sd_bus_ref(TAKE_PTR(bus)); /* Increase the reference counter, so that the PAM data stays valid */
45 return PAM_SUCCESS;
46 }
47 if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA)) {
48 pam_syslog(handle, LOG_ERR, "Failed to get bus connection: %s", pam_strerror(handle, r));
49 return r;
50 }
51
52 r = sd_bus_open_system(&bus);
53 if (r < 0) {
54 pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror_safe(r));
55 return PAM_SERVICE_ERR;
56 }
57
58 r = pam_set_data(handle, "systemd-system-bus", bus, cleanup_system_bus);
59 if (r != PAM_SUCCESS) {
60 pam_syslog(handle, LOG_ERR, "Failed to set PAM bus data: %s", pam_strerror(handle, r));
61 return r;
62 }
63
64 sd_bus_ref(bus);
65 *ret = TAKE_PTR(bus);
66
67 return PAM_SUCCESS;
68 }
69
pam_release_bus_connection(pam_handle_t * handle)70 int pam_release_bus_connection(pam_handle_t *handle) {
71 int r;
72
73 r = pam_set_data(handle, "systemd-system-bus", NULL, NULL);
74 if (r != PAM_SUCCESS)
75 pam_syslog(handle, LOG_ERR, "Failed to release PAM user record data: %s", pam_strerror(handle, r));
76
77 return r;
78 }
79
pam_cleanup_free(pam_handle_t * handle,void * data,int error_status)80 void pam_cleanup_free(pam_handle_t *handle, void *data, int error_status) {
81 /* A generic destructor for pam_set_data() that just frees the specified data */
82 free(data);
83 }
84