]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/journal-util.c
tree-wide: drop license boilerplate
[thirdparty/systemd.git] / src / shared / journal-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Zbigniew Jędrzejewski-Szmek
6 Copyright 2015 Lennart Poettering
7 ***/
8
9 #include "acl-util.h"
10 #include "fs-util.h"
11 #include "hashmap.h"
12 #include "journal-internal.h"
13 #include "journal-util.h"
14 #include "log.h"
15 #include "strv.h"
16 #include "user-util.h"
17
18 static int access_check_var_log_journal(sd_journal *j, bool want_other_users) {
19 #if HAVE_ACL
20 _cleanup_strv_free_ char **g = NULL;
21 const char* dir;
22 #endif
23 int r;
24
25 assert(j);
26
27 /* If we are root, we should have access, don't warn. */
28 if (getuid() == 0)
29 return 0;
30
31 /* If we are in the 'systemd-journal' group, we should have
32 * access too. */
33 r = in_group("systemd-journal");
34 if (r < 0)
35 return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m");
36 if (r > 0)
37 return 0;
38
39 #if HAVE_ACL
40 if (laccess("/run/log/journal", F_OK) >= 0)
41 dir = "/run/log/journal";
42 else
43 dir = "/var/log/journal";
44
45 /* If we are in any of the groups listed in the journal ACLs,
46 * then all is good, too. Let's enumerate all groups from the
47 * default ACL of the directory, which generally should allow
48 * access to most journal files too. */
49 r = acl_search_groups(dir, &g);
50 if (r < 0)
51 return log_error_errno(r, "Failed to search journal ACL: %m");
52 if (r > 0)
53 return 0;
54
55 /* Print a pretty list, if there were ACLs set. */
56 if (!strv_isempty(g)) {
57 _cleanup_free_ char *s = NULL;
58
59 /* Thre are groups in the ACL, let's list them */
60 r = strv_extend(&g, "systemd-journal");
61 if (r < 0)
62 return log_oom();
63
64 strv_sort(g);
65 strv_uniq(g);
66
67 s = strv_join(g, "', '");
68 if (!s)
69 return log_oom();
70
71 log_notice("Hint: You are currently not seeing messages from %s.\n"
72 " Users in groups '%s' can see all messages.\n"
73 " Pass -q to turn off this notice.",
74 want_other_users ? "other users and the system" : "the system",
75 s);
76 return 1;
77 }
78 #endif
79
80 /* If no ACLs were found, print a short version of the message. */
81 log_notice("Hint: You are currently not seeing messages from %s.\n"
82 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
83 " turn off this notice.",
84 want_other_users ? "other users and the system" : "the system");
85
86 return 1;
87 }
88
89 int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users) {
90 Iterator it;
91 void *code;
92 char *path;
93 int r = 0;
94
95 assert(j);
96
97 if (hashmap_isempty(j->errors)) {
98 if (ordered_hashmap_isempty(j->files) && !quiet)
99 log_notice("No journal files were found.");
100
101 return 0;
102 }
103
104 if (hashmap_contains(j->errors, INT_TO_PTR(-EACCES))) {
105 if (!quiet)
106 (void) access_check_var_log_journal(j, want_other_users);
107
108 if (ordered_hashmap_isempty(j->files))
109 r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
110 }
111
112 HASHMAP_FOREACH_KEY(path, code, j->errors, it) {
113 int err;
114
115 err = abs(PTR_TO_INT(code));
116
117 switch (err) {
118 case EACCES:
119 continue;
120
121 case ENODATA:
122 log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path);
123 break;
124
125 case EPROTONOSUPPORT:
126 log_warning_errno(err, "Journal file %1$s uses an unsupported feature, ignoring file.\n"
127 "Use SYSTEMD_LOG_LEVEL=debug journalctl --file=%1$s to see the details.",
128 path);
129 break;
130
131 case EBADMSG:
132 log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path);
133 break;
134
135 default:
136 log_warning_errno(err, "An error was encountered while opening journal file or directory %s, ignoring file: %m", path);
137 break;
138 }
139 }
140
141 return r;
142 }
143
144 bool journal_field_valid(const char *p, size_t l, bool allow_protected) {
145 const char *a;
146
147 /* We kinda enforce POSIX syntax recommendations for
148 environment variables here, but make a couple of additional
149 requirements.
150
151 http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
152
153 if (l == (size_t) -1)
154 l = strlen(p);
155
156 /* No empty field names */
157 if (l <= 0)
158 return false;
159
160 /* Don't allow names longer than 64 chars */
161 if (l > 64)
162 return false;
163
164 /* Variables starting with an underscore are protected */
165 if (!allow_protected && p[0] == '_')
166 return false;
167
168 /* Don't allow digits as first character */
169 if (p[0] >= '0' && p[0] <= '9')
170 return false;
171
172 /* Only allow A-Z0-9 and '_' */
173 for (a = p; a < p + l; a++)
174 if ((*a < 'A' || *a > 'Z') &&
175 (*a < '0' || *a > '9') &&
176 *a != '_')
177 return false;
178
179 return true;
180 }