Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem using the "first matching rule" for the rights #374

Closed
maniackcrudelis opened this issue Apr 5, 2016 · 9 comments
Closed

Problem using the "first matching rule" for the rights #374

maniackcrudelis opened this issue Apr 5, 2016 · 9 comments
Assignees
Labels
Milestone

Comments

@maniackcrudelis
Copy link

Hello,

Following the PR #335, the default rules of the rights file does not work.

[...]
# Allow authenticated user to read all collections
[allow-everyone-read]
user: .+
collection: .*
permission: r

# Give write access to owners
[owner-write]
user: .+
collection: ^%(login)s/.*$
permission: w
[...]

The rule allow-everyone-read match before owner-write, so registered users have no write access...
The solution of course would be to reverse the order of the rules.
But this principle to stop at the first match rule is a real problem. It prevents creation of more complex rules (except to tear his hair with regex). This makes it impossible to authorize share a calendar for a user, as it has been before match in the file.

@liZe liZe self-assigned this Apr 5, 2016
@liZe liZe added this to the 2.0 milestone Apr 5, 2016
@liZe liZe added the bug label Apr 5, 2016
@liZe liZe changed the title Problème avec first matching sur le fichier rights Problem using the "first matching rule" for the rights Apr 8, 2016
@liZe liZe mentioned this issue Apr 9, 2016
39 tasks
liZe added a commit that referenced this issue Apr 9, 2016
@liZe
Copy link
Member

liZe commented Apr 9, 2016

The "rights" file is a list of independant examples, not a default configuration file. I've just added this to the file to make it clear.

I'm interested in real life examples of configuration files that were easy to write before #335 and hard to write now. Could you please provide such an example?

@maniackcrudelis
Copy link
Author

... Pour commencer, désolé d'être francophone... J'avais fait l'effort de traduire en anglais pour les autres. Mais si ma partie en français disparaît, je préfère ne pas écrire en anglais...


Un exemple dans la vraie vie? J'en ai eu un hier justement.
User1 doit accéder à sa propre collection, normal.

# Give write access to owners
[owner-write]
user: .+
collection: ^%(login)s/.+$
permission: rw

Mais User1 souhaite également accéder à un calendrier de User2 qui le partage avec lui.

[user1 can read user2/shared2]
user: ^User1$
collection: ^User2/shared2$
permission: r

Avant le PR #335, ça fonctionne sans problème. User1 a accès à sa collection et au calendrier partagé. Après ce PR, la seconde règle n'est pas vérifiée puisque la première est déjà validée.

C'est sans doute possible de régler ça avec des regex, mais c'est un casse tête infernal pour y parvenir. Et encore, c'est un seul calendrier partagé.

@liZe
Copy link
Member

liZe commented Apr 9, 2016

... Pour commencer, désolé d'être francophone... J'avais fait l'effort de traduire en anglais pour les autres. Mais si ma partie en français disparaît, je préfère ne pas écrire en anglais...

I'm a French guy too. I can understand what you wrote, and French is not a problem for me. But it could be a problem for the other ones. That's why I'd really prefer to have comments written in English, even if it's poor English with mistakes. People won't tell you that your English is horrible because they don't care, they'll be too happy to see that someone else has the same problem, sharing their issues and their solutions with you.

Thank you very much for taking the time to report this bug and to translate it in English. I'll leave your last comment in French. But if you want to share your problem with the other users, for this project, you'll have to write all your comments in English. Imagine this issue tracker filled with bugs written by users in their native languages. It doesn't work.

If you're shy: just don't be :).


[owner-write]
user: .+
collection: ^%(login)s/.+$
permission: rw

[user1 can read user2/shared2]
user: ^User1$
collection: ^User2/shared2$
permission: r

It's a really good example that was working before and is not working easily anymore. The original bug (#334) was proposing another solution, but I do prefer the current one, because it's a bit more secure.

We could:

  • add another rights manager working like the old one,
  • allow users to use their own external rights manager working like the old one,
  • add a character to the permissions to say that the rule is not blocking,
  • add a blocking: false line to say that the rule is not blocking.

@maniackcrudelis @daald @prlw1 What do you think of that? I like 2 and 4.

@maniackcrudelis
Copy link
Author

I know you're french. We work at few kilometers one of the other.

I translate in english (at least google does...) precisely because I understand the problem to be as universal as possible. But to read me, and for those who are allergic or do not understand english, allows me to express myself in words I understand.


The fourth solution seems very interesting, because it would use complex rules early in the rights file and block if validated.

At the moment, for my use, I patched the regex.py file. It works, but this idea seems a great way to fix this.



Je sais que tu es toi même français, nous travaillons à quelques kilomètres d'intervalle.

Je traduis en anglais (du moins google le fait...) justement car je comprend la problématique d'être le plus universel possible. Mais pour me relire, et pour tout ceux qui sont allergique ou qui ne comprenne pas l'anglais, permet moi de m'exprimer en des termes que je comprends.


La 4e solution me parait très intéressante, car elle permettrait d'utiliser des règles complexes au début du fichier de droits et de bloquer si elles sont validées.

Pour le moment, pour mon usage, j'ai patché le fichier regex.py. Ça fonctionne, mais cette idée me semble un excellent moyen d'arranger tout ça.

@liZe
Copy link
Member

liZe commented Apr 9, 2016

Well… After diving into the code, I think that your example actually works. When User1 tries to reach User2's calendar, the first rule doesn't match but the second one does, giving User1 read access as needed. Did I miss something?

@maniackcrudelis
Copy link
Author

Yes I see, as I wrote in fact, it should not validate the first rule.
But I come now to raise a similar problem, by sharing public calendars. I wanted to clean the rules "unnecessary".
I deleted

[allow-everyone-read]
user: .+
collection: .*
permission: r

For keeping only

[owner-write]
user: .+
collection: ^%(login)s/.+$
permission: rw

But this only rule seems not permitted to see the contents of the collection:

DEBUG: Test if 'user:/' matches against '.+:^user/.+$' from section 'owner-write'
DEBUG: Section 'owner-write' does not match
DEBUG: user has NO read access to collection /

I found myself obliged to put this rule for the collection to be readable, and it may have a right to read and write the contents of the collection.

A problem also happens for calendar sharing on clients that do not allow to connect to a specific calendar, only the complete collection. Typically a phone on android with DAVdroid.
The shares do not appear in the collection, even if the user has the right to see them.
I bypassed the problem with symbolic links (this is the hack, but it works). But that implies rights for the reading of each file in the collection.
I do not know if reading the rules (not application of them) is done by file collection or all of the collection?


Oui je vois, tel que je l'ai écrit en effet, il ne devrait pas valider la première règle.
Mais je viens à l'instant de soulever un autre problème similaire, en partageant des calendriers publics. J'ai voulu nettoyer les règles "inutiles".
J'ai supprimé

[allow-everyone-read]
user: .+
collection: .*
permission: r

Pour ne garder que

[owner-write]
user: .+
collection: ^%(login)s/.+$
permission: rw

Mais cette règle seule semble ne pas permettre de voir le contenu de la collection:

DEBUG: Test if 'user:/' matches against '.+:^user/.+$' from section 'owner-write'
DEBUG: Section 'owner-write' does not match
DEBUG: user has NO read access to collection /

Je me suis trouvé obligé de remettre cette règle pour que la collection soit lisible, et qu'il puisse avoir un droit de lecture et d'écriture sur le contenu de la collection.

Un problème se pose également pour le partage d'agenda sur des clients qui ne permette pas de se connecter à un calendrier en particulier, uniquement la collection complète. Typiquement un téléphone sous android avec DAVdroid.
Les partages n'apparaissent pas dans la collection, même si l'utilisateur a le droit de les voir.
J'ai contourné le problème avec un des liens symboliques (c'est de la bidouille, mais ça fonctionne). Mais ça implique des droits fins sur la lecture de chaque fichier de la collection.
J'ignore si la lecture des règles (pas leur application) se fait par fichier de la collection ou pour l'ensemble de la collection?

@liZe
Copy link
Member

liZe commented Apr 9, 2016

I don't get it. I think that what you need is:

[owner-write]
user: .+
collection: ^%(login)s/.+$
permission: rw

[allow-everyone-read]
user: .+
collection: .*
permission: r

Is there anything wrong with that for your use?

A problem also happens for calendar sharing on clients that do not allow to connect to a specific calendar, only the complete collection. Typically a phone on android with DAVdroid.
The shares do not appear in the collection, even if the user has the right to see them.

That's another point. This behaviour is caused by two different problems:

  • When you give it / as base URL, DAVdroid's collection discovering tries to find calendars in /, and then in the user's principal path, which is /<username>/ in Radicale.
  • If your user1 has the right to read /user2/calendar.ics but not /user2/, DAVdroid's collection discovering won't find the calendar, even if you give it /user2/ at base path.

With the rights rules above and /user2/ as base URL in DAVdroid's account, user1 should be able to see /user2/calendar.ics. The second point is solved.

The problem is that because of point 1, you need one account (/ or /user1/) finding user1's calendars, and another one (/user2/) finding user2's calendars. Finding calendars at depth 2 (/depth1/depth2.ics when base URL is /) is authorized by the CalDAV protocol and by Radicale, but DAVdroid's only asks for one depth. I don't think that it's configurable in DAVdroid.

Another solution is to use a different pattern for your calendars. Keeping only 1 depth (storing calendars in /) and using calendar names with the user name (/user1-calendar1.ics, /user1-calendar2.ics) is enough to workaround DAVdroid's limitations. You just have to replace / by - in the rights.

@maniackcrudelis
Copy link
Author

The order of owner-write and allow-everyone-read not matter in my use case since regex.py is patched to not stop at the first validated rule.

The problem is that without the rule allow-everyone-read, the collection appears empty because it does not get any reading right and the client (InfCloud) refuses to connect. That may be abnormal behavior?

Here is the log of what happened:

2016-04-10 12:47:22,412 - DEBUG: Authentication type is LDAP
2016-04-10 12:47:28,810 - INFO: PROPFIND request at /radicale/ received
2016-04-10 12:47:28,815 - DEBUG: Request headers:
{'CONTENT_LENGTH': '122',
 'CONTENT_TYPE': 'text/xml; charset=utf-8',
 'DOCUMENT_ROOT': '/usr/share/nginx/html',
 'HTTPS': 'on',
 'HTTP_ACCEPT': 'application/xml, text/xml, */*; q=0.01',
 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br',
 'HTTP_ACCEPT_LANGUAGE': 'fr-FR,fr;q=0.8,en-US;q=0.5,en;q=0.3',
 'HTTP_AUTHORIZATION': 'Basic bWNydWRlbGlNvMnNlcnYxLnByaXY=',
 'HTTP_AUTH_USER': 'USER1',
 'HTTP_CONNECTION': 'keep-alive',
 'HTTP_CONTENT_LENGTH': '122',
 'HTTP_CONTENT_TYPE': 'text/xml; charset=utf-8',
 'HTTP_COOKIE': 'TeamPass_PFSK_c81e728d9d4c2f636f067f89cc14862c=M25odFZFaG90VVNYUjNEaERrYEODM5UUdvNDNvZ2Znd1JJa1sNV%2BHwCPsuh4B%2FNzn%2BXPuZiRrXoZlQfjVyIhACSyJ%2FM2UyZDM5NmU5N2FlM2Y4YTQ2Nzc0ZmZiNGEzZmU2YjU4Zjk1Zjk3N2UxNjRmMzYyMjM5eG14am8yczE3M3IzeDRpM291NmllOWJlbHhrcWJzeHI3enhtY3R2cXl4NGhwMXQzOGVicXdxdXB0ZTE%3D; sort_method=percent_completed; __zlcmid=X2f0DTlUcb7j2q; style_cookie=null; jstree_select=18; compact_display_state=false; sort_direction=ascending; SSOwAuthUser=USER1; SSOwAuthHash=22da55117ec1e9bccf1e1a13e89f7a0d; SSOwAuthExpire=1460830077.999',
 'HTTP_DEPTH': '0',
 'HTTP_DNT': '1',
 'HTTP_EMAIL': 'user@domain.tld',
 'HTTP_HOST': 'domain.tld',
 'HTTP_NAME': 'User 1',
 'HTTP_REFERER': 'https://domain.tld/radicale/infcloud/',
 'HTTP_REMOTE_USER': 'USER1',
 'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:45.0) Gecko/20100101 Firefox/45.0',
 'HTTP_X_CLIENT': 'InfCloud 0.13.1 (Inf-IT CalDAV/CardDAV Web Client)',
 'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
 'PATH_INFO': '/radicale/',
 'QUERY_STRING': '',
 'REMOTE_ADDR': '192.168.1.151',
 'REMOTE_PORT': '51773',
 'REQUEST_METHOD': 'PROPFIND',
 'REQUEST_URI': '/radicale/',
 'SERVER_NAME': 'domain.tld',
 'SERVER_PORT': '443',
 'SERVER_PROTOCOL': 'HTTP/1.1',
 'uwsgi.node': 'domain',
 'uwsgi.version': '2.0.7-debian',
 'wsgi.errors': <open file 'wsgi_errors', mode 'w' at 0xb62de128>,
 'wsgi.file_wrapper': <built-in function uwsgi_sendfile>,
 'wsgi.input': <uwsgi._Input object at 0xb6c556d0>,
 'wsgi.multiprocess': True,
 'wsgi.multithread': False,
 'wsgi.run_once': False,
 'wsgi.url_scheme': 'https',
 'wsgi.version': (1, 0)}
2016-04-10 12:47:28,815 - DEBUG: Sanitized path: /
2016-04-10 12:47:28,869 - DEBUG: LDAP bind for uid=USER1 in base ou=users,dc=yunohost,dc=org
2016-04-10 12:47:28,869 - DEBUG: Used LDAP filter: uid=USER1
2016-04-10 12:47:28,872 - DEBUG: User USER1 found
2016-04-10 12:47:28,875 - DEBUG: LDAP bind OK
2016-04-10 12:47:28,876 - DEBUG: Reading rights from file /etc/radicale/rights
2016-04-10 12:47:28,879 - DEBUG: Test if 'USER1:/' matches against '.+:^USER1/.+$' from section 'owner-write'
2016-04-10 12:47:28,880 - DEBUG: Section 'owner-write' does not match
2016-04-10 12:47:28,880 - DEBUG: Test if 'USER1:/' matches against '.*:^USER1/calendarA*' from section 'calendarA public readonly'
2016-04-10 12:47:28,891 - DEBUG: Section 'calendarA public readonly' does not match
2016-04-10 12:47:28,891 - DEBUG: Test if 'USER1:/' matches against '.*:^USER1/calendarB*' from section 'calendarB public readonly'
2016-04-10 12:47:28,892 - DEBUG: Section 'calendarB public readonly' does not match
2016-04-10 12:47:28,892 - DEBUG: Test if 'USER1:/' matches against '.*:^USER1/calendarC*' from section 'calendarC public readonly'
2016-04-10 12:47:28,898 - DEBUG: Section 'calendarC public readonly' does not match
2016-04-10 12:47:28,898 - DEBUG: USER1 has NO read access to collection /
2016-04-10 12:47:28,899 - DEBUG: Reading rights from file /etc/radicale/rights
2016-04-10 12:47:28,901 - DEBUG: Test if 'USER1:/' matches against '.+:^USER1/.+$' from section 'owner-write'
2016-04-10 12:47:28,905 - DEBUG: Section 'owner-write' does not match
2016-04-10 12:47:28,906 - DEBUG: Test if 'USER1:/' matches against '.*:^USER1/calendarA*' from section 'calendarA public readonly'
2016-04-10 12:47:28,906 - DEBUG: Section 'calendarA public readonly' does not match
2016-04-10 12:47:28,906 - DEBUG: Test if 'USER1:/' matches against '.*:^USER1/calendarB*' from section 'calendarB public readonly'
2016-04-10 12:47:28,907 - DEBUG: Section 'calendarB public readonly' does not match
2016-04-10 12:47:28,907 - DEBUG: Test if 'USER1:/' matches against '.*:^USER1/calendarC*' from section 'calendarC public readonly'
2016-04-10 12:47:28,907 - DEBUG: Section 'calendarC public readonly' does not match
2016-04-10 12:47:28,908 - DEBUG: USER1 has NO write access to collection /
2016-04-10 12:47:28,908 - DEBUG: Request content:
<?xml version="1.0" encoding="utf-8"?><D:propfind xmlns:D="DAV:"><D:prop><D:current-user-principal/></D:prop></D:propfind>
2016-04-10 12:47:28,929 - DEBUG: Response content:
<?xml version="1.0"?>
<multistatus xmlns="DAV:" />
2016-04-10 12:47:28,930 - DEBUG: Answer status: 207 Unknown

If I re-established the rule, everything is back in order.

The client will connect to https://domain.tld/radicale/
I can not tell it to connect to a user in particular failing to remove its multi-user function.

I had not thought possible to create schedules in this way user1-calendar1.ics. In the state, the rights of the file rights prohibit me but it must be corrected.

Anyway, I think come to the same conclusion.
To allow user1 to access /user2/calendar.ics/, must add a rule authorizing it.
Even if I connect directly to /user2/ with the login user1.
It reproduces the problem if the first rule, allowing his own collection, is blocking.

DAVdroid is capable of charging multiple accounts, so he should be able to access these shares. However this is not the case for Agendav or CalDavZap.
The question I ask myself on this point are is this a limitation of the CardDAV protocol that does not allow a user to view shared calendars with him in his own collection?

Finally to return about this issue, do you think as even if share calendars, it is possible to get by with a blocking rule?


L'ordre de owner-write et allow-everyone-read importe peu dans mon cas d'usage puisque regex.py est patché pour ne pas s'arrêter à la première règle validée.

Le problème est bien que sans la règle allow-everyone-read, la collection apparait vide car il n'obtient aucun droit de lecture et le client (InfCloud) refuse de se connecter. C'est peut-être un comportement anormal?

Voila le log de ce qui s'est passé:

[...] Voir au dessus

Si je rétabli la règle, tout entre en ordre.

Le client se connecte à l'adresse https://domain.tld/radicale/
Je ne peux pas lui indiquer de se connecter à un user en particulier sous peine de lui retirer sa fonction multi-utilisateurs.

Je ne pensais pas possible de créer des calendriers de cette manière, user1-calendar1.ics. En l'état, les droits du fichier rights me l'interdise mais ça doit pouvoir se corriger.

Quoi qu'il en soit, je crois arriver à la même conclusion.
Pour autoriser user1 à accéder à /user2/calendar.ics/, il faut ajouter une règle l'y autorisant.
Même si je me connecte directement /user2/ avec le login de user1.
On reproduit le problème si la première règle, autorisant sa propre collection, est bloquante.

DAVdroid est capable de charger plusieurs comptes, donc il devrait pouvoir accéder à ces partages. En revanche ce n'est pas le cas de Agendav et CalDavZap.
La question que je me pose sur ce point, c'est est-ce une limitation du protocole carddav que de ne pas permettre à un user de voir les calendriers partagés avec lui dans sa propre collection?

Enfin pour revenir au sujet de cet issue, penses-tu alors que même en cas de partage de calendriers, il est possible de s'en sortir avec une règle bloquante?

@liZe
Copy link
Member

liZe commented Aug 1, 2016

I think that with the current master branch, this problem is fixed because discovery will start from / (instead of /user/), allowing user1 to see /user1/* and /user2/* if it has the rigth to see user1's collections.

@liZe liZe closed this as completed Mar 4, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants