1 /*
2    Drawpile - a collaborative drawing program.
3 
4    Copyright (C) 2015-2018 Calle Laakkonen
5 
6    Drawpile is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10 
11    Drawpile is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with Drawpile.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "aclfilter.h"
21 
22 #include "../libshared/net/meta.h"
23 #include "../libshared/net/meta2.h"
24 #include "../libshared/net/brushes.h"
25 #include "../libshared/net/image.h"
26 #include "../libshared/net/layer.h"
27 #include "../libshared/net/annotation.h"
28 #include "../libshared/net/undo.h"
29 
30 namespace canvas {
31 
AclFilter(QObject * parent)32 AclFilter::AclFilter(QObject *parent)
33 	: QObject(parent)
34 {
35 }
36 
clone(QObject * newParent) const37 AclFilter *AclFilter::clone(QObject *newParent) const
38 {
39 	AclFilter *f = new AclFilter(newParent);
40 
41 	f->m_myId = m_myId;
42 	f->m_isOperator = m_isOperator;
43 	f->m_isTrusted = m_isTrusted;
44 	f->m_sessionLocked = m_sessionLocked;
45 	f->m_localUserLocked = m_localUserLocked;
46 
47 	f->m_layers = m_layers;
48 	f->m_ops = m_ops;
49 	f->m_trusted = m_trusted;
50 	f->m_auth = m_auth;
51 	f->m_userlocks = m_userlocks;
52 	f->m_protectedAnnotations = m_protectedAnnotations;
53 	for(int i=0;i<FeatureCount;++i)
54 		f->m_featureTiers[i] = m_featureTiers[i];
55 
56 	return f;
57 }
58 
reset(uint8_t myId,bool localMode)59 void AclFilter::reset(uint8_t myId, bool localMode)
60 {
61 	m_layers.clear();
62 	m_myId = myId;
63 	m_isTrusted = false;
64 	m_sessionLocked = false;
65 	m_localUserLocked = false;
66 
67 	m_ops.reset();
68 	m_trusted.reset();
69 	m_auth.reset();
70 	m_userlocks.reset();
71 	m_protectedAnnotations.clear();
72 
73 	if(localMode)
74 		m_ops.set(myId);
75 	setOperator(localMode);
76 
77 	emit localLockChanged(false);
78 
79 	// Default feature access levels
80 	setFeature(        Feature::PutImage, Tier::Guest);
81 	setFeature(      Feature::RegionMove, Tier::Guest);
82 	setFeature(          Feature::Resize, Tier::Op);
83 	setFeature(      Feature::Background, Tier::Op);
84 	setFeature(      Feature::EditLayers, Tier::Op);
85 	setFeature(       Feature::OwnLayers, Tier::Guest);
86 	setFeature(Feature::CreateAnnotation, Tier::Guest);
87 	setFeature(           Feature::Laser, Tier::Guest);
88 	setFeature(            Feature::Undo, Tier::Guest);
89 	static_assert(FeatureCount == 9, "missing default feature tiers");
90 }
91 
setOnlineMode(uint8_t myId)92 void AclFilter::setOnlineMode(uint8_t myId)
93 {
94 	m_myId = myId;
95 	// We will soon get the correct values for these
96 	m_isOperator = false;
97 	m_isTrusted = false;
98 }
99 
100 // Get the ID of the layer's creator. This assumes the ID prefixing convention is used.
layerCreator(uint16_t layerId)101 static uint8_t layerCreator(uint16_t layerId) {
102 	return layerId >> 8;
103 }
104 
filterMessage(const protocol::Message & msg)105 bool AclFilter::filterMessage(const protocol::Message &msg)
106 {
107 	using namespace protocol;
108 
109 	// Session and user specific locks apply to all Command type messages
110 	if(msg.isCommand() && (m_sessionLocked || m_userlocks.contains(msg.contextId())))
111 		return false;
112 
113 	// This user's access level tier determines which features are available
114 	const Tier tier = userTier(msg.contextId());
115 
116 	switch(msg.type()) {
117 	case MSG_USER_JOIN:
118 		if((static_cast<const UserJoin&>(msg).flags() & UserJoin::FLAG_AUTH))
119 			m_auth.set(msg.contextId());
120 
121 		// Make sure the user's access bits are up to date
122 		emit operatorListChanged(m_ops.toList());
123 		emit trustedUserListChanged(m_trusted.toList());
124 
125 		if(msg.contextId() == m_myId) {
126 			for(int i=0;i<FeatureCount;++i)
127 				emit featureAccessChanged(Feature(i), canUseFeature(Feature(i)));
128 		}
129 
130 		break;
131 
132 	case MSG_USER_LEAVE: {
133 		// User left: remove locks
134 		m_ops.unset(msg.contextId());
135 		m_trusted.unset(msg.contextId());
136 		m_auth.unset(msg.contextId());
137 		m_userlocks.unset(msg.contextId());
138 
139 		QMutableHashIterator<int,LayerAcl> i(m_layers);
140 		while(i.hasNext()) {
141 			i.next();
142 			if(i.value().exclusive.removeAll(msg.contextId())>0)
143 				emit layerAclChanged(i.key());
144 		}
145 
146 		// Refresh UI
147 		if(msg.contextId() == m_myId) {
148 			setOperator(false);
149 			setTrusted(false);
150 			m_localUserLocked = false;
151 			emit localLockChanged(isLocked());
152 		}
153 		break; }
154 
155 	case MSG_SESSION_OWNER:
156 		// This command is validated by the server
157 		updateSessionOwnership(static_cast<const SessionOwner&>(msg));
158 		return true;
159 
160 	case MSG_TRUSTED_USERS:
161 		// this command is validated by the server
162 		updateTrustedUserList(static_cast<const TrustedUsers&>(msg));
163 		return true;
164 
165 	case MSG_LAYER_ACL:
166 		if( tier <= featureTier(Feature::EditLayers) ||
167 		   (tier <= featureTier(Feature::OwnLayers) && layerCreator(msg.layer()) == msg.contextId())
168 		) {
169 			const auto &lmsg = static_cast<const LayerACL&>(msg);
170 
171 			if(lmsg.layer() == 0) {
172 				// Layer 0 sets the general session lock.
173 				// Exclusive user list is not used in this case.
174 				if(tier > Tier::Op)
175 					return false;
176 				setSessionLock(lmsg.locked());
177 				return true;
178 			}
179 
180 			const Tier tier = Tier(qBound(0, int(lmsg.tier()), TierCount));
181 			m_layers[lmsg.layer()] = LayerAcl { lmsg.locked(), tier, lmsg.exclusive() };
182 
183 			// Emit this to refresh the UI in case our selected layer was (un)locked.
184 			// (We don't actually know which layer is selected in the UI here.)
185 			emit localLockChanged(isLocked());
186 			emit layerAclChanged(lmsg.layer());
187 
188 			return true;
189 		}
190 		return false;
191 
192 	case MSG_FEATURE_LEVELS: {
193 		if(tier > Tier::Op)
194 			return false;
195 
196 		const auto &flmsg = static_cast<const FeatureAccessLevels&>(msg);
197 		for(int i=0;i<canvas::FeatureCount;++i) {
198 			setFeature(Feature(i), Tier(qBound(0, int(flmsg.featureTier(i)), canvas::TierCount)));
199 		}
200 		return true;
201 	}
202 
203 	case MSG_USER_ACL: {
204 		if(tier > Tier::Op)
205 			return false;
206 
207 		const auto &lmsg = static_cast<const UserACL&>(msg);
208 		m_userlocks.setFromList(lmsg.ids());
209 		emit userLocksChanged(lmsg.ids());
210 		setUserLock(m_userlocks.contains(m_myId));
211 		return true;
212 	}
213 
214 	case MSG_LAYER_DEFAULT:
215 		return tier == Tier::Op;
216 
217 	case MSG_CHAT:
218 		// Only operators can pin messages
219 		if(static_cast<const protocol::Chat&>(msg).isPin() && tier > Tier::Op)
220 			return false;
221 		break;
222 
223 	case MSG_LASERTRAIL:
224 		return tier <= featureTier(Feature::Laser);
225 
226 	case MSG_CANVAS_RESIZE: return tier <= featureTier(Feature::Resize);
227 	case MSG_PUTTILE: return tier == Tier::Op;
228 	case MSG_CANVAS_BACKGROUND: return tier <= featureTier(Feature::Background);
229 
230 	case MSG_LAYER_CREATE: {
231 		if(tier > Tier::Op && layerCreator(msg.layer()) != msg.contextId()) {
232 			qWarning("non-op user %d tried to create layer with context id %d", msg.contextId(), layerCreator(msg.layer()));
233 			return false;
234 		}
235 
236 		// Must have either general or ownlayer permission to create layers
237 		return tier <= featureTier(Feature::EditLayers) || tier <= featureTier(Feature::OwnLayers);
238 	}
239 	case MSG_LAYER_ATTR:
240 		if(static_cast<const protocol::LayerAttributes&>(msg).sublayer()>0 && tier > Tier::Op) {
241 			// Direct sublayer editing is used only by operators during session init
242 			return false;
243 		}
244 		Q_FALLTHROUGH();
245 
246 	case MSG_LAYER_RETITLE:
247 	case MSG_LAYER_DELETE: {
248 		const uint8_t createdBy = layerCreator(msg.layer());
249 		// EDITLAYERS feature gives permission to edit all layers
250 		// OWNLAYERS feature gives permission to edit layers created by this user
251 		if(
252 			(createdBy != msg.contextId() && tier > featureTier(Feature::EditLayers)) ||
253 			(createdBy == msg.contextId() && tier > featureTier(Feature::OwnLayers))
254 		  )
255 			return false;
256 
257 		if(msg.type() == MSG_LAYER_DELETE)
258 			m_layers.remove(msg.layer());
259 		break;
260 	}
261 	case MSG_LAYER_ORDER:
262 		return tier <= featureTier(Feature::EditLayers);
263 
264 	case MSG_PUTIMAGE:
265 	case MSG_FILLRECT:
266 		return tier <= featureTier(Feature::PutImage) && !isLayerLockedFor(msg.layer(), msg.contextId(), tier);
267 
268 	case MSG_DRAWDABS_CLASSIC:
269 	case MSG_DRAWDABS_PIXEL:
270 		return !isLayerLockedFor(msg.layer(), msg.contextId(), tier);
271 
272 	case MSG_REGION_MOVE:
273 		return tier <= featureTier(Feature::RegionMove) && !isLayerLockedFor(msg.layer(), msg.contextId(), tier);
274 
275 	case MSG_ANNOTATION_CREATE:
276 		if(tier > featureTier(Feature::CreateAnnotation))
277 			return false;
278 
279 		if(tier > Tier::Op && layerCreator(msg.layer()) != msg.contextId()) {
280 			qWarning("non-op user %d tried to create annotation with context id %d", msg.contextId(), layerCreator(msg.layer()));
281 			return false;
282 		}
283 		break;
284 	case MSG_ANNOTATION_EDIT:
285 		// Non-operators can't edit protected annotations created by other users
286 		if(m_protectedAnnotations.contains(layerCreator(msg.layer())) && tier > Tier::Op && layerCreator(msg.layer()) != msg.contextId())
287 			return false;
288 
289 		if((static_cast<const AnnotationEdit&>(msg).flags() & protocol::AnnotationEdit::FLAG_PROTECT))
290 			m_protectedAnnotations.insert(msg.layer());
291 		else
292 			m_protectedAnnotations.remove(msg.layer());
293 		break;
294 	case MSG_ANNOTATION_DELETE:
295 	case MSG_ANNOTATION_RESHAPE:
296 		if(m_protectedAnnotations.contains(msg.layer()) && tier > Tier::Op && layerCreator(msg.layer())!=msg.contextId())
297 			return false;
298 		if(msg.type() == MSG_ANNOTATION_DELETE)
299 			m_protectedAnnotations.remove(msg.layer());
300 		break;
301 
302 	case MSG_UNDO:
303 		if(tier > featureTier(Feature::Undo))
304 			return false;
305 
306 		// Only operators can override Undos.
307 		if(tier > Tier::Op && static_cast<const Undo&>(msg).overrideId()>0)
308 			return false;
309 		break;
310 
311 	default: break;
312 	}
313 
314 	return true;
315 }
316 
layerAcl(int layerId) const317 AclFilter::LayerAcl AclFilter::layerAcl(int layerId) const
318 {
319 	if(!m_layers.contains(layerId))
320 		return LayerAcl { false, Tier::Guest, QList<uint8_t>() };
321 
322 	return m_layers[layerId];
323 }
324 
isLayerLockedFor(int layerId,uint8_t userId,Tier userTier) const325 bool AclFilter::isLayerLockedFor(int layerId, uint8_t userId, Tier userTier) const
326 {
327 	if(!m_layers.contains(layerId))
328 		return false;
329 
330 	const LayerAcl &l = m_layers[layerId];
331 	// Locking a layer locks it for everyone
332 	if(l.locked)
333 		return true;
334 
335 	// If the layer has not been configured for exclusive user access,
336 	// permit access by user tier
337 	if(l.exclusive.isEmpty())
338 		return l.tier < userTier;
339 	else
340 		return !l.exclusive.contains(userId);
341 }
342 
updateSessionOwnership(const protocol::SessionOwner & msg)343 void AclFilter::updateSessionOwnership(const protocol::SessionOwner &msg)
344 {
345 	m_ops.setFromList(msg.ids());
346 	emit operatorListChanged(msg.ids());
347 	setOperator(m_ops.contains(m_myId));
348 }
349 
updateTrustedUserList(const protocol::TrustedUsers & msg)350 void AclFilter::updateTrustedUserList(const protocol::TrustedUsers &msg)
351 {
352 	m_trusted.setFromList(msg.ids());
353 	emit trustedUserListChanged(msg.ids());
354 	setTrusted(m_trusted.contains(m_myId));
355 }
356 
setOperator(bool op)357 void AclFilter::setOperator(bool op)
358 {
359 	if(op != m_isOperator) {
360 		m_isOperator = op;
361 		emit localOpChanged(op);
362 
363 		// Op and Trusted status change affects available features
364 		for(int i=0;i<FeatureCount;++i)
365 			emit featureAccessChanged(Feature(i), canUseFeature(Feature(i)));
366 	}
367 }
368 
setTrusted(bool trusted)369 void AclFilter::setTrusted(bool trusted)
370 {
371 	if(trusted != m_isTrusted) {
372 		m_isTrusted = trusted;
373 
374 		// Op and Trusted status change affects available features
375 		for(int i=0;i<FeatureCount;++i)
376 			emit featureAccessChanged(Feature(i), canUseFeature(Feature(i)));
377 	}
378 }
379 
setSessionLock(bool lock)380 void AclFilter::setSessionLock(bool lock)
381 {
382 	bool wasLocked = isLocked();
383 	m_sessionLocked = lock;
384 	if(wasLocked != isLocked())
385 		emit localLockChanged(isLocked());
386 }
387 
setUserLock(bool lock)388 void AclFilter::setUserLock(bool lock)
389 {
390 	bool wasLocked = isLocked();
391 	m_localUserLocked = lock;
392 	if(wasLocked != isLocked())
393 		emit localLockChanged(isLocked());
394 }
395 
setFeature(Feature feature,Tier tier)396 void AclFilter::setFeature(Feature feature, Tier tier)
397 {
398 	if(m_featureTiers[int(feature)] == tier)
399 		return;
400 
401 	const bool hadAccess = canUseFeature(feature);
402 	m_featureTiers[int(feature)] = tier;
403 
404 	if(canUseFeature(feature) != hadAccess)
405 		emit featureAccessChanged(feature, !hadAccess);
406 
407 	emit featureTierChanged(feature, tier);
408 }
409 
410 }
411 
412