1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3
/* Copyright (C) 2001-2004 Novell, Inc.
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of version 2 of the GNU Lesser General Public
7
* License as published by the Free Software Foundation.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this program; if not, write to the
16
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
* Boston, MA 02110-1301, USA.
24
#include "e2k-security-descriptor.h"
29
#include <libxml/parser.h>
30
#include <libxml/tree.h>
31
#include <libxml/xmlmemory.h>
33
struct _E2kSecurityDescriptorPrivate {
35
guint16 control_flags;
38
E2kSid *default_sid, *owner, *group;
39
GHashTable *sids, *sid_order;
50
} E2k_SECURITY_DESCRIPTOR_RELATIVE;
52
#define E2K_SECURITY_DESCRIPTOR_REVISION 1
53
#define E2K_SE_DACL_PRESENT GUINT16_TO_LE(0x0004)
54
#define E2K_SE_SACL_PRESENT GUINT16_TO_LE(0x0010)
55
#define E2K_SE_DACL_PROTECTED GUINT16_TO_LE(0x1000)
65
#define E2K_ACL_REVISION 2
73
#define E2K_ACCESS_ALLOWED_ACE_TYPE (0x00)
74
#define E2K_ACCESS_DENIED_ACE_TYPE (0x01)
76
#define E2K_OBJECT_INHERIT_ACE (0x01)
77
#define E2K_CONTAINER_INHERIT_ACE (0x02)
78
#define E2K_INHERIT_ONLY_ACE (0x08)
81
E2k_ACE_HEADER Header;
87
guint32 mapi_permission;
88
guint32 container_allowed, container_not_denied;
89
guint32 object_allowed, object_not_denied;
92
/* The magic numbers are from the WSS SDK, except modified to match
95
#define LE(x) (GUINT32_TO_LE (x))
96
static E2kPermissionsMap permissions_map[] = {
97
{ E2K_PERMISSION_READ_ANY,
98
LE(0x000000), LE(0x000000), LE(0x1208a9), LE(0x0008a9) },
99
{ E2K_PERMISSION_CREATE,
100
LE(0x000002), LE(0x000002), LE(0x000000), LE(0x000000) },
101
{ E2K_PERMISSION_CREATE_SUBFOLDER,
102
LE(0x000004), LE(0x000004), LE(0x000000), LE(0x000000) },
103
{ E2K_PERMISSION_EDIT_OWNED,
104
LE(0x000000), LE(0x000000), LE(0x000200), LE(0x000000) },
105
{ E2K_PERMISSION_DELETE_OWNED,
106
LE(0x000000), LE(0x000000), LE(0x000400), LE(0x000000) },
107
{ E2K_PERMISSION_EDIT_ANY,
108
LE(0x000000), LE(0x000000), LE(0x0c0116), LE(0x1e0316) },
109
{ E2K_PERMISSION_DELETE_ANY,
110
LE(0x000000), LE(0x000000), LE(0x010000), LE(0x010400) },
111
{ E2K_PERMISSION_OWNER,
112
LE(0x0d4110), LE(0x0d4110), LE(0x000000), LE(0x000000) },
113
{ E2K_PERMISSION_CONTACT,
114
LE(0x008000), LE(0x008000), LE(0x000000), LE(0x000000) },
115
{ E2K_PERMISSION_FOLDER_VISIBLE,
116
LE(0x1208a9), LE(0x1200a9), LE(0x000000), LE(0x000000) }
118
static const gint permissions_map_size =
119
sizeof (permissions_map) / sizeof (permissions_map[0]);
121
static const guint32 container_permissions_all = LE(0x1fc9bf);
122
static const guint32 object_permissions_all = LE(0x1f0fbf);
125
#define PARENT_TYPE G_TYPE_OBJECT
126
static GObjectClass *parent_class = NULL;
128
static void dispose (GObject *object);
131
class_init (GObjectClass *object_class)
133
parent_class = g_type_class_ref (PARENT_TYPE);
135
object_class->dispose = dispose;
139
init (E2kSecurityDescriptor *sd)
141
sd->priv = g_new0 (E2kSecurityDescriptorPrivate, 1);
143
sd->priv->sids = g_hash_table_new (e2k_sid_binary_sid_hash,
144
e2k_sid_binary_sid_equal);
145
sd->priv->sid_order = g_hash_table_new (NULL, NULL);
146
sd->priv->aces = g_array_new (FALSE, TRUE, sizeof (E2k_ACE));
150
free_sid (gpointer key, gpointer sid, gpointer data)
152
g_object_unref (sid);
156
dispose (GObject *object)
158
E2kSecurityDescriptor *sd = (E2kSecurityDescriptor *) object;
161
g_hash_table_foreach (sd->priv->sids, free_sid, NULL);
162
g_hash_table_destroy (sd->priv->sids);
163
g_hash_table_destroy (sd->priv->sid_order);
165
g_array_free (sd->priv->aces, TRUE);
167
if (sd->priv->header)
168
g_byte_array_free (sd->priv->header, TRUE);
174
G_OBJECT_CLASS (parent_class)->dispose (object);
177
E2K_MAKE_TYPE (e2k_security_descriptor, E2kSecurityDescriptor, class_init, init, PARENT_TYPE)
179
/* This determines the relative ordering of any two ACEs in a SID.
180
* See docs/security for details.
183
ace_compar (E2k_ACE *ace1, E2k_ACE *ace2, E2kSecurityDescriptor *sd)
192
/* Figure out which overall section the SID will go in and
193
* what its order within that group is.
195
if (ace1->Sid == sd->priv->default_sid)
196
t1 = E2K_SID_TYPE_GROUP;
198
t1 = e2k_sid_get_sid_type (ace1->Sid);
199
order1 = GPOINTER_TO_INT (g_hash_table_lookup (sd->priv->sid_order,
202
if (ace2->Sid == sd->priv->default_sid)
203
t2 = E2K_SID_TYPE_GROUP;
205
t2 = e2k_sid_get_sid_type (ace2->Sid);
206
order2 = GPOINTER_TO_INT (g_hash_table_lookup (sd->priv->sid_order,
210
if (t1 == E2K_SID_TYPE_USER)
212
else if (t2 == E2K_SID_TYPE_USER)
214
else if (t1 == E2K_SID_TYPE_GROUP)
216
else /* (t2 == E2K_SID_TYPE_GROUP) */
220
if (t1 != E2K_SID_TYPE_GROUP) {
221
/* Object-level ACEs go before Container-level ACEs */
222
if ((ace1->Header.AceFlags & E2K_OBJECT_INHERIT_ACE) &&
223
!(ace2->Header.AceFlags & E2K_OBJECT_INHERIT_ACE))
225
else if ((ace2->Header.AceFlags & E2K_OBJECT_INHERIT_ACE) &&
226
!(ace1->Header.AceFlags & E2K_OBJECT_INHERIT_ACE))
229
/* Compare SID order */
232
else if (order1 > order2)
235
/* Allowed ACEs for a given SID go before Denied ACEs */
236
if (ace1->Header.AceType == ace2->Header.AceType)
238
else if (ace1->Header.AceType == E2K_ACCESS_ALLOWED_ACE_TYPE)
243
/* For groups, object-level ACEs go after Container-level */
244
if ((ace1->Header.AceFlags & E2K_OBJECT_INHERIT_ACE) &&
245
!(ace2->Header.AceFlags & E2K_OBJECT_INHERIT_ACE))
247
else if ((ace2->Header.AceFlags & E2K_OBJECT_INHERIT_ACE) &&
248
!(ace1->Header.AceFlags & E2K_OBJECT_INHERIT_ACE))
251
/* Default comes after groups in each section */
252
if (ace1->Sid != ace2->Sid) {
253
if (ace1->Sid == sd->priv->default_sid)
255
else if (ace2->Sid == sd->priv->default_sid)
259
/* All Allowed ACEs go before all Denied ACEs */
260
if (ace1->Header.AceType == E2K_ACCESS_ALLOWED_ACE_TYPE &&
261
ace2->Header.AceType == E2K_ACCESS_DENIED_ACE_TYPE)
263
else if (ace1->Header.AceType == E2K_ACCESS_DENIED_ACE_TYPE &&
264
ace2->Header.AceType == E2K_ACCESS_ALLOWED_ACE_TYPE)
267
/* Compare SID order */
270
else if (order1 > order2)
278
find_child (xmlNode *node, const xmlChar *name)
280
for (node = node->xmlChildrenNode; node; node = node->next) {
281
if (node->name && !xmlStrcmp (node->name, name))
288
extract_sids (E2kSecurityDescriptor *sd, xmlNodePtr node)
290
xmlNodePtr string_sid_node, type_node, display_name_node;
291
xmlChar *string_sid, *content, *display_name;
296
for (; node; node = node->next) {
297
if (xmlStrcmp (node->name, (xmlChar *) "sid") != 0) {
298
if (node->xmlChildrenNode)
299
extract_sids (sd, node->xmlChildrenNode);
303
string_sid_node = find_child (node, (xmlChar *) "string_sid");
304
type_node = find_child (node, (xmlChar *) "type");
305
display_name_node = find_child (node, (xmlChar *) "display_name");
306
if (!string_sid_node || !type_node)
309
string_sid = xmlNodeGetContent (string_sid_node);
311
content = xmlNodeGetContent (type_node);
312
if (!content || !xmlStrcmp (content, (xmlChar *) "user"))
313
type = E2K_SID_TYPE_USER;
314
else if (!xmlStrcmp (content, (xmlChar *) "group"))
315
type = E2K_SID_TYPE_GROUP;
316
else if (!xmlStrcmp (content, (xmlChar *) "well_known_group"))
317
type = E2K_SID_TYPE_WELL_KNOWN_GROUP;
318
else if (!xmlStrcmp (content, (xmlChar *) "alias"))
319
type = E2K_SID_TYPE_ALIAS;
321
type = E2K_SID_TYPE_INVALID;
324
if (display_name_node)
325
display_name = xmlNodeGetContent (display_name_node);
329
sid = e2k_sid_new_from_string_sid (type, (gchar *) string_sid,
330
(gchar *) display_name);
331
xmlFree (string_sid);
333
xmlFree (display_name);
335
bsid = e2k_sid_get_binary_sid (sid);
336
if (g_hash_table_lookup (sd->priv->sids, bsid)) {
337
g_object_unref (sid);
341
g_hash_table_insert (sd->priv->sids, (gchar *)bsid, sid);
346
parse_sid (E2kSecurityDescriptor *sd, GByteArray *binsd, guint16 *off,
351
if (binsd->len - *off < E2K_SID_BINARY_SID_MIN_LEN)
353
sid_len = E2K_SID_BINARY_SID_LEN (binsd->data + *off);
354
if (binsd->len - *off < sid_len)
357
*sid = g_hash_table_lookup (sd->priv->sids, binsd->data + *off);
364
parse_acl (E2kSecurityDescriptor *sd, GByteArray *binsd, guint16 *off)
370
if (binsd->len - *off < sizeof (E2k_ACL))
373
memcpy (&aclbuf, binsd->data + *off, sizeof (aclbuf));
374
if (*off + GUINT16_FROM_LE (aclbuf.AclSize) > binsd->len)
376
if (aclbuf.AclRevision != E2K_ACL_REVISION)
379
ace_count = GUINT16_FROM_LE (aclbuf.AceCount);
381
*off += sizeof (aclbuf);
382
for (i = 0; i < ace_count; i++) {
383
if (binsd->len - *off < sizeof (E2k_ACE))
386
memcpy (&acebuf, binsd->data + *off,
387
sizeof (acebuf.Header) + sizeof (acebuf.Mask));
388
*off += sizeof (acebuf.Header) + sizeof (acebuf.Mask);
390
/* If either of OBJECT_INHERIT_ACE or INHERIT_ONLY_ACE
391
* is set, both must be.
393
if (acebuf.Header.AceFlags & E2K_OBJECT_INHERIT_ACE) {
394
if (!(acebuf.Header.AceFlags & E2K_INHERIT_ONLY_ACE))
397
if (acebuf.Header.AceFlags & E2K_INHERIT_ONLY_ACE)
401
if (!parse_sid (sd, binsd, off, &acebuf.Sid))
404
if (!g_hash_table_lookup (sd->priv->sid_order, acebuf.Sid)) {
405
gint size = g_hash_table_size (sd->priv->sid_order);
407
g_hash_table_insert (sd->priv->sid_order, acebuf.Sid,
408
GUINT_TO_POINTER (size + 1));
411
g_array_append_val (sd->priv->aces, acebuf);
418
* e2k_security_descriptor_new:
419
* @xml_form: the XML form of the folder's security descriptor
420
* (The "http://schemas.microsoft.com/exchange/security/descriptor"
421
* property, aka %E2K_PR_EXCHANGE_SD_XML)
422
* @binary_form: the binary form of the folder's security descriptor
423
* (The "http://schemas.microsoft.com/exchange/ntsecuritydescriptor"
424
* property, aka %E2K_PR_EXCHANGE_SD_BINARY)
426
* Constructs an #E2kSecurityDescriptor from the data in @xml_form and
429
* Return value: the security descriptor, or %NULL if the data could
432
E2kSecurityDescriptor *
433
e2k_security_descriptor_new (xmlNodePtr xml_form, GByteArray *binary_form)
435
E2kSecurityDescriptor *sd;
436
E2k_SECURITY_DESCRIPTOR_RELATIVE sdbuf;
437
guint16 off, header_len;
439
g_return_val_if_fail (xml_form != NULL, NULL);
440
g_return_val_if_fail (binary_form != NULL, NULL);
442
if (binary_form->len < 2)
445
memcpy (&header_len, binary_form->data, 2);
446
header_len = GUINT16_FROM_LE (header_len);
447
if (header_len + sizeof (sdbuf) > binary_form->len)
450
memcpy (&sdbuf, binary_form->data + header_len, sizeof (sdbuf));
451
if (sdbuf.Revision != E2K_SECURITY_DESCRIPTOR_REVISION)
453
if ((sdbuf.Control & (E2K_SE_DACL_PRESENT | E2K_SE_SACL_PRESENT)) !=
457
sd = g_object_new (E2K_TYPE_SECURITY_DESCRIPTOR, NULL);
458
sd->priv->header = g_byte_array_new ();
459
g_byte_array_append (sd->priv->header, binary_form->data, header_len);
460
sd->priv->control_flags = sdbuf.Control;
462
/* Create a SID for "Default" then extract remaining SIDs from
463
* the XML form since they have display names associated with
466
sd->priv->default_sid =
467
e2k_sid_new_from_string_sid (E2K_SID_TYPE_WELL_KNOWN_GROUP,
468
E2K_SID_WKS_EVERYONE, NULL);
469
g_hash_table_insert (sd->priv->sids,
470
(gchar *)e2k_sid_get_binary_sid (sd->priv->default_sid),
471
sd->priv->default_sid);
472
extract_sids (sd, xml_form);
474
off = GUINT32_FROM_LE (sdbuf.Owner) + sd->priv->header->len;
475
if (!parse_sid (sd, binary_form, &off, &sd->priv->owner))
477
off = GUINT32_FROM_LE (sdbuf.Group) + sd->priv->header->len;
478
if (!parse_sid (sd, binary_form, &off, &sd->priv->group))
481
off = GUINT32_FROM_LE (sdbuf.Dacl) + sd->priv->header->len;
482
if (!parse_acl (sd, binary_form, &off))
493
* e2k_security_descriptor_to_binary:
494
* @sd: an #E2kSecurityDescriptor
496
* Converts @sd back to binary (#E2K_PR_EXCHANGE_SD_BINARY) form
497
* so it can be PROPPATCHed back to the server.
499
* Return value: the binary form of @sd.
502
e2k_security_descriptor_to_binary (E2kSecurityDescriptor *sd)
505
E2k_SECURITY_DESCRIPTOR_RELATIVE sdbuf;
508
gint off, ace, last_ace = -1, acl_size, ace_count;
511
g_return_val_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd), NULL);
513
aces = (E2k_ACE *)sd->priv->aces->data;
515
/* Compute the length of the ACL first */
516
acl_size = sizeof (E2k_ACL);
517
for (ace = ace_count = 0; ace < sd->priv->aces->len; ace++) {
518
if (aces[ace].Mask) {
520
acl_size += GUINT16_FROM_LE (aces[ace].Header.AceSize);
524
binsd = g_byte_array_new ();
526
/* Exchange-specific header */
527
g_byte_array_append (binsd, sd->priv->header->data,
528
sd->priv->header->len);
530
/* SECURITY_DESCRIPTOR header */
531
memset (&sdbuf, 0, sizeof (sdbuf));
532
sdbuf.Revision = E2K_SECURITY_DESCRIPTOR_REVISION;
533
sdbuf.Control = sd->priv->control_flags;
534
off = sizeof (sdbuf);
535
sdbuf.Dacl = GUINT32_TO_LE (off);
537
sdbuf.Owner = GUINT32_TO_LE (off);
538
bsid = e2k_sid_get_binary_sid (sd->priv->owner);
539
off += E2K_SID_BINARY_SID_LEN (bsid);
540
sdbuf.Group = GUINT32_TO_LE (off);
541
g_byte_array_append (binsd, (gpointer)&sdbuf, sizeof (sdbuf));
544
aclbuf.AclRevision = E2K_ACL_REVISION;
546
aclbuf.AclSize = GUINT16_TO_LE (acl_size);
547
aclbuf.AceCount = GUINT16_TO_LE (ace_count);
549
g_byte_array_append (binsd, (gpointer)&aclbuf, sizeof (aclbuf));
552
for (ace = 0; ace < sd->priv->aces->len; ace++) {
556
if (last_ace != -1) {
557
if (ace_compar (&aces[last_ace], &aces[ace], sd) != -1) {
558
g_warning ("ACE order mismatch at %d\n", ace);
559
g_byte_array_free (binsd, TRUE);
564
g_byte_array_append (binsd, (gpointer)&aces[ace],
565
sizeof (aces[ace].Header) +
566
sizeof (aces[ace].Mask));
567
bsid = e2k_sid_get_binary_sid (aces[ace].Sid);
568
g_byte_array_append (binsd, bsid,
569
E2K_SID_BINARY_SID_LEN (bsid));
573
/* Owner and Group */
574
bsid = e2k_sid_get_binary_sid (sd->priv->owner);
575
g_byte_array_append (binsd, bsid, E2K_SID_BINARY_SID_LEN (bsid));
576
bsid = e2k_sid_get_binary_sid (sd->priv->group);
577
g_byte_array_append (binsd, bsid, E2K_SID_BINARY_SID_LEN (bsid));
583
* e2k_security_descriptor_get_default:
584
* @sd: a security descriptor
586
* Returns an #E2kSid corresponding to the default permissions
587
* associated with @sd. You can pass this to
588
* e2k_security_descriptor_get_permissions() and
589
* e2k_security_descriptor_set_permissions().
591
* Return value: the "Default" SID
594
e2k_security_descriptor_get_default (E2kSecurityDescriptor *sd)
596
return sd->priv->default_sid;
600
* e2k_security_descriptor_get_sids:
601
* @sd: a security descriptor
603
* Returns a #GList containing the SIDs of each user or group
604
* represented in @sd. You can pass these SIDs to
605
* e2k_security_descriptor_get_permissions(),
606
* e2k_security_descriptor_set_permissions(), and
607
* e2k_security_descriptor_remove_sid().
609
* Return value: a list of SIDs. The caller must free the list
610
* with g_list_free(), but should not free the contents.
613
e2k_security_descriptor_get_sids (E2kSecurityDescriptor *sd)
616
GHashTable *added_sids;
620
g_return_val_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd), NULL);
622
added_sids = g_hash_table_new (NULL, NULL);
623
aces = (E2k_ACE *)sd->priv->aces->data;
624
for (ace = 0; ace < sd->priv->aces->len; ace++) {
625
if (!g_hash_table_lookup (added_sids, aces[ace].Sid)) {
626
g_hash_table_insert (added_sids, aces[ace].Sid,
628
sids = g_list_prepend (sids, aces[ace].Sid);
631
g_hash_table_destroy (added_sids);
637
* e2k_security_descriptor_remove_sid:
638
* @sd: a security descriptor
641
* Removes @sid from @sd. If @sid is a user, this means s/he will now
642
* have only the default permissions on @sd (unless s/he is a member
643
* of a group that is also present in @sd.)
646
e2k_security_descriptor_remove_sid (E2kSecurityDescriptor *sd,
652
g_return_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd));
653
g_return_if_fail (E2K_IS_SID (sid));
655
/* Canonicalize the SID */
656
sid = g_hash_table_lookup (sd->priv->sids,
657
e2k_sid_get_binary_sid (sid));
661
/* We can't actually remove all trace of the user, because if
662
* he is removed and then re-added without saving in between,
663
* then we need to keep the original AceFlags. So we just
664
* clear out all of the masks, which (assuming the user is
665
* not re-added) will result in him not being written out
669
aces = (E2k_ACE *)sd->priv->aces->data;
670
for (ace = 0; ace < sd->priv->aces->len; ace++) {
671
if (aces[ace].Sid == sid)
677
* e2k_security_descriptor_get_permissions:
678
* @sd: a security descriptor
681
* Computes the MAPI permissions associated with @sid. (Only the
682
* permissions *directly* associated with @sid, not any acquired via
683
* group memberships or the Default SID.)
685
* Return value: the MAPI permissions
688
e2k_security_descriptor_get_permissions (E2kSecurityDescriptor *sd,
692
guint32 mapi_perms, checkperm;
695
g_return_val_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd), 0);
696
g_return_val_if_fail (E2K_IS_SID (sid), 0);
698
/* Canonicalize the SID */
699
sid = g_hash_table_lookup (sd->priv->sids,
700
e2k_sid_get_binary_sid (sid));
705
aces = (E2k_ACE *)sd->priv->aces->data;
706
for (ace = 0; ace < sd->priv->aces->len; ace++) {
707
if (aces[ace].Sid != sid)
709
if (aces[ace].Header.AceType == E2K_ACCESS_DENIED_ACE_TYPE)
712
for (map = 0; map < permissions_map_size; map++) {
713
if (aces[ace].Header.AceFlags & E2K_OBJECT_INHERIT_ACE)
714
checkperm = permissions_map[map].object_allowed;
716
checkperm = permissions_map[map].container_allowed;
720
if ((aces[ace].Mask & checkperm) == checkperm)
721
mapi_perms |= permissions_map[map].mapi_permission;
728
/* Put @ace into @sd. If no ACE corresponding to @ace currently exists,
729
* it will be added in the right place. If it does already exist, its
730
* flags (in particular INHERITED_ACE) will be preserved and only the
731
* mask will be changed.
734
set_ace (E2kSecurityDescriptor *sd, E2k_ACE *ace)
736
E2k_ACE *aces = (E2k_ACE *)sd->priv->aces->data;
737
gint low, mid = 0, high, cmp = -1;
740
high = sd->priv->aces->len - 1;
741
while (low <= high) {
742
mid = (low + high) / 2;
743
cmp = ace_compar (ace, &aces[mid], sd);
746
aces[mid].Mask = ace->Mask;
748
g_array_remove_index (sd->priv->aces, mid);
757
g_array_insert_vals (sd->priv->aces, cmp < 0 ? mid : mid + 1, ace, 1);
761
* e2k_security_descriptor_set_permissions:
762
* @sd: a security descriptor
764
* @perms: the MAPI permissions
766
* Updates or sets @sid's permissions on @sd.
769
e2k_security_descriptor_set_permissions (E2kSecurityDescriptor *sd,
770
E2kSid *sid, guint32 perms)
773
guint32 object_allowed, object_denied;
774
guint32 container_allowed, container_denied;
779
g_return_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd));
780
g_return_if_fail (E2K_IS_SID (sid));
782
bsid = e2k_sid_get_binary_sid (sid);
783
sid2 = g_hash_table_lookup (sd->priv->sids, bsid);
785
gint size = g_hash_table_size (sd->priv->sid_order);
787
g_hash_table_insert (sd->priv->sids, (gchar *)bsid, sid);
790
g_hash_table_insert (sd->priv->sid_order, sid,
791
GUINT_TO_POINTER (size + 1));
796
object_denied = object_permissions_all;
797
container_allowed = 0;
798
container_denied = container_permissions_all;
800
for (map = 0; map < permissions_map_size; map++) {
801
if (!(permissions_map[map].mapi_permission & perms))
804
object_allowed |= permissions_map[map].object_allowed;
805
object_denied &= ~permissions_map[map].object_not_denied;
806
container_allowed |= permissions_map[map].container_allowed;
807
container_denied &= ~permissions_map[map].container_not_denied;
811
ace.Header.AceSize = GUINT16_TO_LE (sizeof (ace.Header) +
813
E2K_SID_BINARY_SID_LEN (bsid));
815
ace.Header.AceType = E2K_ACCESS_ALLOWED_ACE_TYPE;
816
ace.Header.AceFlags = E2K_OBJECT_INHERIT_ACE | E2K_INHERIT_ONLY_ACE;
817
ace.Mask = object_allowed;
819
if (sid != sd->priv->default_sid) {
820
ace.Header.AceType = E2K_ACCESS_DENIED_ACE_TYPE;
821
ace.Header.AceFlags = E2K_OBJECT_INHERIT_ACE | E2K_INHERIT_ONLY_ACE;
822
ace.Mask = object_denied;
826
ace.Header.AceType = E2K_ACCESS_ALLOWED_ACE_TYPE;
827
ace.Header.AceFlags = E2K_CONTAINER_INHERIT_ACE;
828
ace.Mask = container_allowed;
830
if (sid != sd->priv->default_sid) {
831
ace.Header.AceType = E2K_ACCESS_DENIED_ACE_TYPE;
832
ace.Header.AceFlags = E2K_CONTAINER_INHERIT_ACE;
833
ace.Mask = container_denied;
841
} roles[E2K_PERMISSIONS_ROLE_NUM_ROLES] = {
842
/* i18n: These are Outlook's words for the default roles in
843
the folder permissions dialog. */
844
{ N_("Owner"), (E2K_PERMISSION_FOLDER_VISIBLE |
845
E2K_PERMISSION_READ_ANY |
846
E2K_PERMISSION_CREATE |
847
E2K_PERMISSION_DELETE_OWNED |
848
E2K_PERMISSION_EDIT_OWNED |
849
E2K_PERMISSION_DELETE_ANY |
850
E2K_PERMISSION_EDIT_ANY |
851
E2K_PERMISSION_CREATE_SUBFOLDER |
852
E2K_PERMISSION_CONTACT |
853
E2K_PERMISSION_OWNER) },
854
{ N_("Publishing Editor"), (E2K_PERMISSION_FOLDER_VISIBLE |
855
E2K_PERMISSION_READ_ANY |
856
E2K_PERMISSION_CREATE |
857
E2K_PERMISSION_DELETE_OWNED |
858
E2K_PERMISSION_EDIT_OWNED |
859
E2K_PERMISSION_DELETE_ANY |
860
E2K_PERMISSION_EDIT_ANY |
861
E2K_PERMISSION_CREATE_SUBFOLDER) },
862
{ N_("Editor"), (E2K_PERMISSION_FOLDER_VISIBLE |
863
E2K_PERMISSION_READ_ANY |
864
E2K_PERMISSION_CREATE |
865
E2K_PERMISSION_DELETE_OWNED |
866
E2K_PERMISSION_EDIT_OWNED |
867
E2K_PERMISSION_DELETE_ANY |
868
E2K_PERMISSION_EDIT_ANY) },
869
{ N_("Publishing Author"), (E2K_PERMISSION_FOLDER_VISIBLE |
870
E2K_PERMISSION_READ_ANY |
871
E2K_PERMISSION_CREATE |
872
E2K_PERMISSION_DELETE_OWNED |
873
E2K_PERMISSION_EDIT_OWNED |
874
E2K_PERMISSION_CREATE_SUBFOLDER) },
875
{ N_("Author"), (E2K_PERMISSION_FOLDER_VISIBLE |
876
E2K_PERMISSION_READ_ANY |
877
E2K_PERMISSION_CREATE |
878
E2K_PERMISSION_DELETE_OWNED |
879
E2K_PERMISSION_EDIT_OWNED) },
880
{ N_("Non-editing Author"),(E2K_PERMISSION_FOLDER_VISIBLE |
881
E2K_PERMISSION_READ_ANY |
882
E2K_PERMISSION_CREATE |
883
E2K_PERMISSION_DELETE_OWNED) },
884
{ N_("Reviewer"), (E2K_PERMISSION_FOLDER_VISIBLE |
885
E2K_PERMISSION_READ_ANY) },
886
{ N_("Contributor"), (E2K_PERMISSION_FOLDER_VISIBLE |
887
E2K_PERMISSION_CREATE) },
888
{ N_("None"), (E2K_PERMISSION_FOLDER_VISIBLE) }
892
* e2k_permissions_role_get_name:
893
* @role: a permissions role
895
* Returns the localized name corresponding to @role
897
* Return value: the name
900
e2k_permissions_role_get_name (E2kPermissionsRole role)
902
if (role == E2K_PERMISSIONS_ROLE_CUSTOM)
905
g_return_val_if_fail (role > E2K_PERMISSIONS_ROLE_CUSTOM &&
906
role < E2K_PERMISSIONS_ROLE_NUM_ROLES, NULL);
907
return _(roles[role].name);
911
* e2k_permissions_role_get_perms
912
* @role: a permissions role
914
* Returns the MAPI permissions associated with @role. @role may not
915
* be %E2K_PERMISSIONS_ROLE_CUSTOM.
917
* Return value: the MAPI permissions
920
e2k_permissions_role_get_perms (E2kPermissionsRole role)
922
g_return_val_if_fail (role >= E2K_PERMISSIONS_ROLE_CUSTOM &&
923
role < E2K_PERMISSIONS_ROLE_NUM_ROLES, 0);
924
return roles[role].perms;
928
* e2k_permissions_role_find:
929
* @perms: MAPI permissions
931
* Finds the #E2kPermissionsRole value associated with @perms. If
932
* @perms don't describe any standard role, the return value will be
933
* %E2K_PERMISSIONS_ROLE_CUSTOM
935
* Return value: the role
938
e2k_permissions_role_find (guint perms)
942
/* "Folder contact" isn't actually a permission, and is ignored
943
* for purposes of roles.
945
perms &= ~E2K_PERMISSION_CONTACT;
947
/* The standard "None" permission includes "Folder visible",
948
* but 0 counts as "None" too.
951
return E2K_PERMISSIONS_ROLE_NONE;
953
for (role = 0; role < E2K_PERMISSIONS_ROLE_NUM_ROLES; role++) {
954
if ((roles[role].perms & ~E2K_PERMISSION_CONTACT) == perms)
958
return E2K_PERMISSIONS_ROLE_CUSTOM;