]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
4f37cbd9 ZJS |
2 | /*** |
3 | This file is part of systemd. | |
4 | ||
5 | Copyright 2013 Zbigniew Jędrzejewski-Szmek | |
6 | Copyright 2015 Lennart Poettering | |
4f37cbd9 ZJS |
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 | ||
e79d0b59 | 18 | static int access_check_var_log_journal(sd_journal *j, bool want_other_users) { |
349cc4a5 | 19 | #if HAVE_ACL |
4f37cbd9 ZJS |
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 | ||
349cc4a5 | 39 | #if HAVE_ACL |
4f37cbd9 ZJS |
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 | ||
e79d0b59 | 71 | log_notice("Hint: You are currently not seeing messages from %s.\n" |
4f37cbd9 | 72 | " Users in groups '%s' can see all messages.\n" |
e79d0b59 ZJS |
73 | " Pass -q to turn off this notice.", |
74 | want_other_users ? "other users and the system" : "the system", | |
75 | s); | |
4f37cbd9 ZJS |
76 | return 1; |
77 | } | |
78 | #endif | |
79 | ||
80 | /* If no ACLs were found, print a short version of the message. */ | |
e79d0b59 | 81 | log_notice("Hint: You are currently not seeing messages from %s.\n" |
4f37cbd9 | 82 | " Users in the 'systemd-journal' group can see all messages. Pass -q to\n" |
e79d0b59 ZJS |
83 | " turn off this notice.", |
84 | want_other_users ? "other users and the system" : "the system"); | |
4f37cbd9 ZJS |
85 | |
86 | return 1; | |
87 | } | |
88 | ||
e79d0b59 | 89 | int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users) { |
4f37cbd9 ZJS |
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) | |
e79d0b59 | 106 | (void) access_check_var_log_journal(j, want_other_users); |
4f37cbd9 ZJS |
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 | } | |
53978b98 LP |
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 | } |