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