/usr/share/doc/courier-doc/README.sharedfolders.html is in courier-doc 0.68.2-1ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content=
"text/html; charset=us-ascii" />
<title>Shared folders</title>
<meta name="MSSmartTagsPreventParsing" content="TRUE" />
</head>
<!-- Copyright 2000 Double Precision, Inc. See COPYING for -->
<!-- distribution information. -->
<body>
<h1>Shared folders</h1>
<p>This document describes how shared folders are implemented by
Courier-IMAP, and SqWebMail.</p>
<p>Courier-IMAP and SqWebMail actually have two different shared
folder implementations, for two situations: A) Filesystem
permissions-based shared folders, for systems with traditional
shell login accounts, and mailboxes; and B) virtual shared
folders, for closed systems that provide mail access only, with
all mailboxes using the same system userid/groupid, and no
end-user shell login access.</p>
<p>This documentation is also applicable to the Courier mail
server, which includes Courier-IMAP and SqWebMail as its
components. There are some minor implementation differences
between the standalone Courier-IMAP and SqWebMail packages, and
Courier; namely the different locations of several key
configuration files. Aside from that, both implementation are
equivalent.</p>
<table>
<tbody>
<tr>
<th align="left" colspan="2">Table Of Contents</th>
</tr>
<tr>
<td colspan="2"><a href="#newshared">Virtual shared
folders</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#newsharedterm">Terminology</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#newsharedtech">Technical Overview</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#newsharedfunc">Functional Overview</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#combo">Combining Courier-IMAP's and SqWebMail
index files</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#imapacl">IMAP Access Control List and account
groups</a></td>
</tr>
<tr>
<td colspan="2"> </td>
</tr>
<tr>
<td colspan="2"><a href="#oldshared">Filesystem
permissions-based shared folders</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#oldsharedterm">Terminology</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#oldsharedtech">Technical Overview</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#oldsharedfunc">Functional Overview</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#oldsharedaccess">Accessing shared
folders</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#oldsharedsub">Subscribing to a shared
folder</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#oldsharedunsub">Unsubscribing to a shared
folder</a></td>
</tr>
<tr>
<td> </td>
<td><a href="#oldsharedopen">Opening a shared
folder</a></td>
</tr>
</tbody>
</table>
<h1><a name="newshared" id="newshared">Virtual shared
folders</a></h1>
<h2><a name="newsharedterm" id=
"newsharedterm">Terminology</a></h2>
<p>Virtual shared folders are implemented in a completely
different manner. In a virtual setup, all mailboxes use the same
system userid and groupid; there is no shell login access to the
mail server, and all access is managed by setting up access
control lists. Each individual user may voluntarily grant access
to a folder to another user or group of user. Access control
lists permit fine-grained control. It is possible to specify what
different users are permitted to do to the folder or its
contents. Since there is no shell login access, all access to
mail folders occurs through an IMAP connection to the server, and
the IMAP server observes the defined access control lists on each
folder.</p>
<blockquote>
<p><em>NOTE:</em></p>
<p>The references to IMAP in this documentation equally apply
to SqWebMail as well. This documentation file is included in
Courier-IMAP's and SqWebMail's tarballs. When reading this
documentation file in the SqWebMail tarball, mentally replace
all references to IMAP with webmail. SqWebMail does not use
IMAP, the server reads the maildirs directory; but it uses the
same shared library as Courier-IMAP, which explains the similar
implementation.</p>
</blockquote>
<p>For more information on how to set up access control lists,
see the <a href="maildiracl">maildiracl(1)</a> manual page.</p>
<h2><a name="newsharedtech" id="newsharedtech">Technical
Overview</a></h2>
<p>After logging in, the server process runs in the logged in
account's maildir. As the INSTALL file describes in great detail,
virtual mail accounts may be maintained via a wide variety of
back-end databases, including MySQL, PostgresSQL, or an LDAP
directory. If now the server needs to check the access controls
on another account's mail folder, to determine if the user has
access to it, the server needs to now locate where the other
account is located.</p>
<p>However, there are several reasons why the server cannot
directly go back to the authentication database. The first reason
is that after logging in the server process no longer has root
privileges; and database configuration files normally require
root privileges (since they may contain administrative
passwords). Although there might be ways to hack around that, the
second reason is the show-stopper: IMAP's design permits clients
to enumerate all available shared mail accounts, or arbitrary
subsets of them. And, in fact, many of them do just that; mainly
because IMAP's design leaves no other alternative, in some
situations.</p>
<p>Clearly, it is not feasible to have hundreds of clients
hammering at the database server, repeatedly downloading huge
lists of available shared folders (which may number in tens of
thousands, on a busy server). Therefore, the following approach
is used.</p>
<p>One or more flat text files are set up, which contain an index
of all virtual mail folders. The list is, essentially, downloaded
from the authentication database. The text file contain a subset
of the data in the authentication database; only the minimum
amount of fields necessary to specify the account's name, and
where the account lives. The server process quickly reads the
text file(s) in order to locate another account's folder, and to
check its access control list.</p>
<p>The system administrator will need to set up a
regularly-scheduled process that rebuilds the shared folder
index. Yes, that means that a new account's shared folders will
not be accessible, by other accounts, until the shared folder
index gets rebuilt (but the account still has immediate access to
its own folders, after creation). The shared folder index will be
updated in a manner that allows the update to occur live, without
requiring any system downtime.</p>
<p>On moderately-sized systems it might be feasible to invoke the
shared index update script as part of the process that adds or
removes an account; thereby the shared folder index files will
always be kept up to date.</p>
<p>In its most simple form, the shared index is a single file,
called <em>SYSCONFDIR/shared/index</em>, where "SYSCONFDIR" is
the server's configuration directory. The following table
provides the default locations of the configuration file:</p>
<table>
<tbody>
<tr>
<td>Courier-IMAP:</td>
<td>
<code>/usr/lib/courier-imap/etc/shared/index</code></td>
</tr>
<tr>
<td>Courier:</td>
<td><code>/usr/lib/courier/etc/shared/index</code></td>
</tr>
<tr>
<td>Courier (Red Hat/Fedora build):</td>
<td><code>/etc/courier/shared/index</code></td>
</tr>
<tr>
<td>SqWebMail (standalone build):</td>
<td>
<code>/usr/local/share/sqwebmail/shared/index</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p><em>NOTE:</em></p>
<p>If the "shared" directory doesn't exist, just create it.</p>
</blockquote>
<p>Blank lines in this file are ignored, as well as lines that
begin with a single "#" character, which are arbitrary comments.
Each remaining line specifies the location of an account's
maildir. The line contains the following fields, separated by a
single tab character:</p>
<ol>
<li>name</li>
<li>system userid</li>
<li>system groupid</li>
<li>virtual home directory</li>
<li>maildir path, relative to the virtual home directory</li>
</ol>
<p>"name" <em>SHOULD</em> be the account's login name (which in
some rare configurations may not actually match the IMAP login
used by the client; this is the name that's logged to syslog when
the account successfully logs in, which is usually the same as the
IMAP login id). In most situations all accounts will have the
same system userid and groupid. The server doesn't actually do
anything with these fields at this time, but may do so in the
future.</p>
<p>The virtual account's home directory is taken verbatim from
the authentication database. The maildir path field is optional.
If missing, it defaults to "./Maildir". Combining the home
directory, and the maildir path, results in the location where
the specified account's maildir folders may be found.</p>
<p>Inaccessible accounts are silently ignored. This allows the
shared folder index to be itself shared between multiple servers
even though that accounts themselves are not shared. Each server
will only see the accounts it can access.</p>
<p>As mentioned previously, IMAP clients will often want to
obtain a complete list of shared folders. If the mail server has
more than a a couple of hundred accounts, a single index file may
be inefficient, and the mail accounts should be segregated into
different groups. An account group entry in the index file looks
like this:</p>
<ol>
<li>group name</li>
<li>*</li>
<li>filename</li>
</ol>
<p>When the second tab-delimited field is a single asterisk, the
first field is taken to be a name of an account group; and
"filename" is the name of another, separate, index file that
lists all accounts that belong in this group. The second file
should also be installed in <code>SYSCONFDIR/shared</code>.</p>
<p>When it's time to use account groups,
<code><em>SYSCONFDIR/shared/index</em></code> will usually
contain only group entries, with the accounts themselves
dispersed in other files in the same directory.</p>
<p>Account names and group names use the <code>UTF-8</code>
character set. This is not usually an issue for account names,
which are almost always limited to the Latin character set. Group
names may be arbitrary, though, and include non-Latin characters,
using <code>UTF-8</code>.</p>
<p>Courier does not allow IMAP folder names to contain the "." or
the "/" characters. The shared index file may include those
characters in account or group names, and they will be
automatically replaced by spaces (which are allowed).</p>
<p>This is not normally an issue, unless there exists two
separate accounts or groups whose names are the same, except that
one name contains spaces, and the other name contains the
forbidden characters. This is obviously not something that is
likely to occur, but if it did the end result would be that one
of the names will have its punctuation characters replaced by
spaces, and now two virtual folders will exist with the same
name.</p>
<p>If this rather unlikely scenario somehow materializes the
solution is to enable the <code>IMAP_SHAREDMUNGENAMES</code>
setting in Courier-IMAP's configuration file. When enabled, this
setting replaces the "." and "/" with a two character sequence:
"\:" and "\;". Any the existing backslashes are doubled, thus
preserving folder name uniqueness. This is not something you'd
want to do unless you have no other choice.</p>
<p>The equivalent setting for SqWebMail (or Courier's webmail
server) is the <code>SQWEBMAIL_SHAREDMUNGENAMES</code>. When
using SqWebMail at the same time as Courier-IMAP, and if
<code>IMAP_SHAREDMUNGENAMES</code> is set, the
<code>SQWEBMAIL_SHAREDMUNGENAMES</code> variable must also be set
in order for everyone to be in sync. This can be done in one of
two different ways:</p>
<blockquote>
<ol>
<li>
<p>Set this variable before running the <code>sqwebmaild
start</code> command:</p>
<pre>
SQWEBMAIL_SHAREDMUNGENAMES=1
export SQWEBMAIL_SHAREDMUNGENAMES
sqwebmaild start
</pre>
</li>
<li>
<p>Set this environment variable in the web server's
configuration files. With Apache, for example:</p>
<pre>
SetEnv SQWEGBMAIL_SHAREDMUNGENAMES 1
</pre>
</li>
</ol>
</blockquote>
<h3>Many Shared Accounts</h3>
<p>When the number of mail accounts begins to exceed a couple of
thousand (or even less, depending on the mail server), even
account groups will not be enough. If a single mail server has
tens of thousands of accounts, an individual IMAP client may
potentially access hundreds of thousands of folders.</p>
<p>It is a sad fact of life that there are poorly-designed IMAP
clients that insist on searching for every accessible folder,
every time. They will stubornly scan the entire IMAP folder
namespace, recursively reading each folder hierarchy, to compile
a list of available folders. Even though there may only be a few
folders shared by their owners, the server still has to check
whether the IMAP client has access to each folder, in order to
compile the list of accessible folders. No mail server will like
an IMAP client that insists on reading the access control lists
of hundreds of thousand of folders.</p>
<p>This problem is solved by setting the
"<code>sharedgroup</code>" option for each account. The
<code>INSTALL</code> file contains a more specific description of
how to initialize account options. Normally, the shared folder
index file is "<em>SYSCONFDIR/shared/index</em>"; however, if the
"<code>sharedgroup</code>" option is set, the value of
"<code>sharedgroup</code>" is appended to the shared folder index
filename. So, if user1's account has the
"<code>sharedgroup=12</code>" option, as far as this account is
concerned the shared folder index file is
"<em>SYSCONFDIR/shared/index12</em>". Note that
<em>SYSCONFDIR/shared/index12</em> may still contain account
group entries that point to other shared index files.</p>
<p>This enables the ability to partition all accounts into
smaller "universes". The list of accounts is broken up into
individual universe. Accounts within a universe can only see
other accounts in the same universe. Even if a given folder's
access control lists permit global access, only accounts in the
same universe will be able to access it.</p>
<p>Also note that trans-universal wormholes are possible. Two, or
more, top-level index files may list the same set of account
groups, and those accounts will be visible from both (or more)
universes.</p>
<p><strong>IMPORTANT</strong>: Under no circumstances should you
install circular wormholes (index file A lists index file B as a
group, and index file B lists index file A as a group). The
consequences would be disastrous for both universes.</p>
<h2><a name="newsharedfunc" id="newsharedfunc">Functional
Overview</a></h2>
<p>As mentioned in the previous section, it is necessary to set
up a regularly-scheduled system process that updates the shared
folder index files. The procedure for doing so is site-specific.
Individual sites will need to put together a set of custom
scripts that create the shared folder index files in
<em>SYSCONFDIR/shared</em>. This is likely to be a highly
site-specific code; however Courier installs several generic
shell scripts that can be used as a working starting point.</p>
<p>The most important step in the process is actually the final
step of installing new shared folder index files in
<em>SYSCONFDIR/shared</em>. They must be installed in a way that
can be done live, without shutting down the system, and without
affecting any existing processes. This can be done using the
“sharedindexinstall” script, which may be found in
the <code>sbin</code> directory. To use
<code>sharedindexinstall</code>, first create the shared index
files in a temporary directory called
<em>SYSCONFDIR/shared.tmp</em>, then run the script to move all
the files in this directory to <em>SYSCONFDIR/shared</em>.</p>
<p>So a typical script that updates shared index files will
generally look like this (this example uses Courier-IMAP, for
SqWebMail the directory locations will be different):</p>
<blockquote>
<hr />
<pre>
#!/bin/sh
sysconfdir="/usr/lib/courier-imap/etc" # Or /etc/courier, or whatever...
sbindir="/usr/lib/courier-imap/sbin" # Or, wherever it actually is...
rm -rf $sysconfdir/shared.tmp
mkdir $sysconfdir/shared.tmp || exit 1
#
# A magical process creates updated shared index files right about now...
#
$sbindir/sharedindexinstall
</pre>
<hr />
</blockquote>
<blockquote>
<h4>NOTE</h4>
<p>Existing IMAP server processes may continue to use cached
shared folder index data for some time, after
<code>sharedindexinstall</code>. This will not cause any
problems.</p>
</blockquote>
<h3>Using <code>authenumerate</code></h3>
<p>In most cases, systems that use a single shared index file are
likely to need to only run the “authenumerate”
program in order to build the shared folder index. As long as
Courier's authentication modules are properly configured (and
<code>authdaemond</code> is running) <code>authenumerate</code>
will download the list of accounts from the configured
authentication module, and generate a suitably-formatted list on
standard output. So the complete shared folder index update
script will look like this:</p>
<blockquote>
<hr />
<pre>
#!/bin/sh
sysconfdir="/usr/lib/courier-imap/etc"
sbindir="/usr/lib/courier-imap/sbin"
rm -rf $sysconfdir/shared.tmp
mkdir $sysconfdir/shared.tmp || exit 1
$sbindir/authenumerate -s >$sysconfdir/shared.tmp/index || exit 1
$sbindir/sharedindexinstall
</pre>
<hr />
</blockquote>
<p>The functionality to enumerate accounts is new to Courier-IMAP
3.0. When upgrading from an earlier versions, systems that are
configured to use a custom MySQL, PostgreSQL, or LDAP queries
will need to enter a new configuration setting in the appropriate
configuration file. The update process will add a new variable to
the configuration file, which must be initialized to contain the
custom query that reads the account list accordingly. In most
cases the query only needs to be a slight variation on the
existing query that checks the password of a specific account
that's requesting authentication.</p>
<p>Systems that do not use the custom query option should not
need to make any additional setting, as the standard query
authentication variables contain all the information that's
needed to obtain a complete list of accounts.</p>
<p>If only a small proportion of your users are entitled to use
shared mailboxes, then it helps scalability enormously if you
restrict the shared index file to contain just those accounts.
The <b>-s</b> flag to <code>authenumerate</code> implements this,
by discarding all accounts which have the option
<code>disableshared</code> set to a non-zero value. Further
efficiency can be gained by customising your database query so
that the database itself returns only the relevant accounts. Use
option <code>MYSQL_ENUMERATE_CLAUSE</code>,
<code>PGSQL_ENUMERATE_CLAUSE</code> or
<code>LDAP_ENUMERATE_FILTER</code> as appropriate.</p>
<p>Note also that you can set
<code>DEFAULTOPTIONS="disableshared=1"</code> in
<code>authdaemonrc</code> to make sharing disabled for everyone,
and then set option <code>disableshared=0</code> only on
permitted accounts.</p>
<blockquote>
<h4>NOTE</h4>
<p><code>authenumerate</code> tries not to download the
complete results of each query into a memory buffer, but it may
be that this still happens due to circumstances out of its
control (e.g. older versions of MySQL or PostgreSQL client
libraries may force this to happen). If so, it's possible that
<code>authenumerate</code>'s memory requirements may be large
enough to affect the running system. In this case you will need
to come up with an alternative mechanism to obtain the list of
accounts, in some other way.</p>
</blockquote>
<blockquote>
<h4>NOTE</h4>
<p>The PAM library does not have a function that obtains a list
of available accounts. Therefore, on all systems that use the
<code>authpwd</code>, <code>authshadow</code>, or
<code>authpam</code> modules, <code>authenumerate</code> works
in exactly the same way: by using the <code>getpwent</code>()
function. Systems that use certain PAM modules, such as ones
that authenticate against a MySQL, a PostgreSQL, or an LDAP
database, will not be able to use <code>authenumerate</code>,
and must come up with a suitable replacement.</p>
</blockquote>
<h3>Using <code>sharedindexsplit</code></h3>
<p>As mentioned in the <a href="#newsharedtech">technical
overview</a>, a single index file may not be feasible if the
number of accounts is more than a thousand, or so. At that point
it becomes necessary to split the shared folder index into
multiple files.</p>
<p>The <code>sharedindexsplit</code> script reads a list of all
accounts, formatted as a single shared folder index (which,
incidentally, matches <code>authenumerate</code>'s output format
as well) and splits it into multiple files. The first argument to
<code>sharedindexsplit</code> is the name of the directory where
the output files are going to be created. The directory must be
empty.</p>
<p><code>sharedindexsplit</code> splits the index into multiple
files, based on either the 'sharedgroup' account option, or the
first character or characters of the account's name. Use the
optional second argument to <code>sharedindexsplit</code> to
specify a number, if splitting the account list based on initial
characters is desired. If splitting based on the 'sharedgroup'
account option then use the <code>-o</code> flag to
<code>authenumerate</code> to get it to include the account
options in its output.</p>
<p>Perl 5.8.0, or greater, must be installed if account names
include non-Latin characters. For best results, the shared folder
index input to <code>sharedindexsplit</code> should already be
sorted, but it doesn't have to be.</p>
<p>Therefore, the following scripts should produce good results
on a system with a large, but a moderate number of accounts.
Split on 'sharedgroup' if you have a number of separate
'universes' where sharing is only permitted within each universe;
otherwise split on the account name if all users can potentially
access all shared mailboxes.</p>
<blockquote>
<hr />
<pre>
#!/bin/sh
sysconfdir="/usr/lib/courier-imap/etc"
sbindir="/usr/lib/courier-imap/sbin"
rm -rf $sysconfdir/shared.tmp
mkdir $sysconfdir/shared.tmp || exit 1
# split on the 'sharedgroup' option
$sbindir/authenumerate -s -o >$sysconfdir/shared.tmp/.tmplist || exit 1
$sbindir/sharedindexsplit $sysconfdir/shared.tmp <$sysconfdir/shared.tmp/.tmplist || exit 1
rm -f $sysconfdir/shared.tmp/.tmplist
$sbindir/sharedindexinstall
</pre>
<hr />
<pre>
#!/bin/sh
sysconfdir="/usr/lib/courier-imap/etc"
sbindir="/usr/lib/courier-imap/sbin"
rm -rf $sysconfdir/shared.tmp
mkdir $sysconfdir/shared.tmp || exit 1
# split on the first 1 character of the username
$sbindir/authenumerate -s >$sysconfdir/shared.tmp/.tmplist || exit 1
$sbindir/sharedindexsplit $sysconfdir/shared.tmp 1 <$sysconfdir/shared.tmp/.tmplist || exit 1
rm -f $sysconfdir/shared.tmp/.tmplist
$sbindir/sharedindexinstall
</pre>
<hr />
</blockquote>
<p><code>authenumerate</code> is saved to a temporary file,
instead of being piped directly, is so that its exit code can be
checked. We want to abort the entire process if
<code>authenumerate</code> terminates with a non-zero exit code.
If <code>authenumerate</code> pipes its output directly to
<code>sharedindexsplit</code>, and aborts with an error, then
<code>sharedindexsplit</code> will read an empty shared folder
index, consequently the output directory will be empty, and then
<code>sharedindexinstall</code> will obligingly install an empty
list of shared folders.</p>
<p>As mentioned previously, at some point
<code>authenumerate</code>'s memory requirements may become too
much to handle, and an alternative mechanism will need to be
improvised. <code>sharedindexsplit</code>'s memory requirements
are not dependent on the number of accounts, so this script can
still be used even with very many accounts.</p>
<p>When it's time to use account groups,
<em>SYSCONFDIR/shared/index</em> will usually contain only group
entries, with the accounts themselves dispersed in other files in
the same directory.</p>
<h2><a name="combo" id="combo">Combining Courier-IMAP's and
SqWebMail index files</a></h2>
<p>The information in this section is applicable only when
running both Courier-IMAP and SqWebMail packages. This is not
applicable when running Courier, which includes both the IMAP
server and the webmail server. In the Courier build, both servers
are set up to use the same shared index file.</p>
<p>But, if both standalone builds are installed, Courier-IMAP
will want to use
<code>/usr/lib/courier-imap/etc/shared/index</code> as its shared
index file, while SqWebMail will read
<code>/usr/local/share/sqwebmail/shared/index</code>.</p>
<p>To make both servers use the same shared folder index, create
a soft link:</p>
<pre>
ln -s /usr/lib/courier-imap/etc/shared /usr/local/share/sqwebmail/shared
</pre>
<p>It's important to create a soft link to the entire "shared"
directory, otherwise index group files will not work.</p>
<h2><a name="imapacl" id="imapacl">IMAP Access Control List and
account groups</a></h2>
<p>Even after setting up shared folders indexes correctly, the
mail client will show an empty list of shared folders. This is
because even though each account's folders may be shared, they
will not be visible to other accounts until the mail account's
owner explicitly grants public access to a folder. This can be
done using an IMAP mail client that understands access control
lists, using Courier's SqWebMail, or the <tt>maildiracl</tt>
command. The <tt>maildiracl</tt> manual page includes an overview
of access control lists and how to control who gets what kind of
rights on a folder. See the <tt>maildiracl</tt> manual page for
more information.</p>
<h1><a name="oldshared" id="oldshared">Filesystem
permissions-based shared folders</a></h1>
<h2><a name="oldsharedterm" id=
"oldsharedterm">Terminology</a></h2>
<ul>
<li>Sharable Maildir - a maildir that contains folders that can
be shared.</li>
<li>Sharable folder - one or more folders in a sharable Maildir
that can be shared.</li>
</ul>
<h2><a name="oldsharedtech" id="oldsharedtech">Technical
Overview</a></h2>
<ul>
<li>They are a somewhat logical extension of the base Maildir
format.</li>
<li>Older versions of Courier-IMAP and SqWebMail will
completely ignore shared folders.</li>
<li>Messages in shared folders do not count towards any
individual maildir quotas (see <tt><a href=
"README.maildirquota.html">README.maildirquota.html</a></tt>).</li>
<li>Shared folders are implemented as additional, Maildir-based
folders. The messages will be soft links to the messages in the
sharable folder. Soft links will be used instead of hard links
in order to be able to have a folder containing large messages,
and then be able to reclaim space immediately when the messages
are purged, instead of waiting for everyone to sync up and
delete their hard link. The flip side is that you can expect
the usual sorts of errors and increased confusion if someone
attempts to read a message that has just been removed, but
their client (Courier-IMAP or SqWebMail) doesn't know that yet.
That's unavoidable. You'll probably have to set some kind of a
policy in order to keep the expected insanity to a
minimum.</li>
<li>Sharable folders are subscribed to by creating a separate
maildir-type directory within the main Maildir. It's created in
a separate subdirectory that is ignored by other Maildir
clients.</li>
<li>The new directory will contains soft links to the messages
in the sharable folder. "Synchronization" code will be used to
synchronize the contents of the sharable folder, and the copy
of it in the regular Maildir. Once links to the messages are
created, they can be manipulated like regular messages in a
Maildir. This procedure will be transparently performed by
Courier-IMAP or SqWebMail behind the scenes.</li>
<li>Access to shared folders is controlled by a combination of
an explicit configuration, plus regular filesystem permissions.
If account owners have shell access to the server, they can
create shared folders, and link their mailbox to other
accounts' shared folders. Then, the actual access is controlled
by regular filesystem permissions. The owner of the shared
folder will use the regular filesystem permission to give read
and/or write access to either everyone else, or everyone else
who uses the same system group ID. Read access allows people to
read messages from a shared folder. Write access allows people
to add and delete messages in the shared. The owner of the
shared folder can remove any message, everyone else will be
able to remove only their own messages.</li>
</ul>
<h2><a name="oldsharedfunc" id="oldsharedfunc">Functional
Overview</a></h2>
<p>Generally speaking, shared folders are configured using a
feature-enhanced <tt>maildirmake</tt> command as follows:</p>
<ul>
<li><tt>make install</tt> will install a <tt>maildirmake</tt>
command that has a bunch of funny options. The modified
<tt>maildirmake</tt> command is installed into Courier-IMAP's
or SqWebMail's installation directory.</li>
<li>Somebody, maybe you, will use some of these options to
create a maildir with modified permissions. The same somebody
will run <tt>maildirmake</tt> again, with a few other options,
to create folders in that maildir, also with modified
permissions. Those permissions allows global read (and
optionally write) access to those folders.</li>
<li>Do NOT use this maildir as the primary mailbox, INBOX, for
an account. Instead, you must create this maildir separately,
perhaps as $HOME/Maildir-shared, then set it up as one of your
sharable maildirs (see below), and access it in shared mode.
Because you own it, you have unlimited read/write access to it.
The previously mentioned options will select whether or not
access permissions are given to everyone else, and they do not
apply to you.</li>
<li>Everyone else will run <tt>maildirmake</tt> with even more
funny options. Those options install a link from their own
maildir to a maildir that contains sharable folders. A given
maildir may contain links to more than one sharable maildir. As
long as their system user/group permissions allow them to
access messages, they can SUBSCRIBE via their IMAP client to
the folder, or use the SUBSCRIBE function in SqWebmail.</li>
<li>If people do not have shell access, the system
administrator will have to run <tt>maildirmake</tt> on their
behalf, in order to create the links to the sharable
maildirs.</li>
<li>People with write access can add messages to a sharable
folder. Messages from a sharable folder can be removed only by
the owner of the shared folder, or by the owner of each
message.</li>
<li>This sharable maildir implementation cannot use maildir
soft-quotas. There cannot be a soft-quota installed in a
sharable maildir. If you need quota support, you will have to
use filesystem-based quotas. There are some sticky issues with
updating quotas on a sharable maildir.</li>
</ul>
<p>Also, note that anyone, not just the superuser, can create a
sharable maildir in their account, and invite anyone else to
access it, as long as their system user/group permissions allow
them access.</p>
<p>To summarize:</p>
<ul>
<li>Use the -S option to <tt>maildirmake</tt> to create a
maildir that can contain sharable folders.</li>
<li>Use the -s and -f options to <tt>maildirmake</tt> to create
sharable folders. The same sharable maildir may contain
multiple sharable folders with different access permissions, as
selected by the -s option.</li>
<li>Use the <tt>--add</tt> option to install a link from a
regular maildir to a sharable maildir. Afterwards, IMAP clients
will be able to subscribe to folders in the sharable
maildir.</li>
<li>Use the <tt>--del</tt> option to remove a link.</li>
</ul>
<p>For more information on these options, see the
<tt>maildirmake</tt> manual page that will be installed.</p>
<h3>More on additional options for the <tt>maildirmake</tt>
command</h3>The '-S' option to <tt>maildirmake</tt> to create a
maildir that will contain shared folders. The -S option gives
group and world read permissions on the maildir itself (where
group/world permissions are normally not set for a regular
maildir). This allows access to any folders in the shared
maildir, and that's why you should not use this Maildir directly
as your primary mailbox.
<p>The "new" and "cur" subdirectories will not be used or shared,
although they will still be created. Both SqWebMail and
Courier-IMAP create their auxiliary files in the main Maildir
with the group and world permissions turned off, so this maildir
can, theoretically, still be used as the primary INBOX, but I
don't recommend that.</p>
<p>The -S option is not limited to the system administrator. In
fact, anyone can use the -S option, to create shared maildirs
that they maintain.</p>
<p>Shared folders are created like any other folder, using the
<tt>-f</tt> option to <tt>maildirmake</tt>. However, that
normally creates a folder that is not sharable, because it will
not have any group or world permissions. Therefore,
<tt>maildirmake</tt> will take the following options to create a
sharable folder:</p>
<ul>
<li><tt>-s read</tt> will create a "moderated" folder. The
folder will have group and world read permissions, letting
anyone read messages, but only the owner of the sharable
Maildir can add messages to the sharable folder.</li>
<li><tt>-s write</tt> will create an "unmoderated" folder. The
folder will have group and world read/write permissions,
letting anyone read and add messages to the folder. The folder
will be created with the sticky bit set, like the <tt>/tmp</tt>
directory, preventing people from removing someone else's
messages.</li>
<li><tt>-s read,group/-s write,group</tt> append a comma and
the word "group" to modify the semantics of moderated and
unmoderated folders only on the group level, not the group and
world level, as far as permissions go. This restricts sharing
the folder only to members of the same system group as the
owner of the sharable maildir.</li>
</ul>
<p>It's worth noting that it is perfectly permissible for folders
in the same sharable maildir to have different access levels.</p>
<p>Also, this is driven entirely by filesystem permissions, so
theoretically it's possible to create a folder that has write
permissions for the group, and read permissions for everyone
else. However, I'm too lazy to actually do it. Feel free to patch
<tt>maildirmake</tt> to add this functionality, then send me the
patch.</p>
<h2><a name="oldsharedaccess" id="oldsharedaccess">Accessing
shared folders</a></h2>
<p>The rest of the document consists of technical implementation
notes.</p>
<p>Accessing a collection of shared folders is implemented by a
new file that is installed in the primary maildir (usually
$HOME/Maildir), and a new subdirectory hierarchy underneath the
primary maildir, which are hereby declared.</p>
<h3><tt>shared-maildirs</tt></h3>
<p>This file must be created by the administrator or by the
maildir owner, manually. This file lists all available sharable
maildirs that this maildir can access in shared mode (confused
yet?). This file contains one or more lines of the following
format:</p>
<p><tt>name /path/to/shared/maildir</tt></p>
<p>"<em>name</em>" is an arbitrary name that's given to this
collection of shared folders. The name may not contain slashes,
periods, or spaces. This is followed by a pathname to the maildir
containing shared folders. Note that this is NOT the sharable
folder itself, but the maildir that contains one or more sharable
folders. The maildir client will be able to selectively subscribe
to any sharable folder in that maildir.</p>
<h3><tt>shared-folders</tt></h3>
<p>This subdirectory forms the root of all the shared folders
that are subscribed to. Let's say that <tt>shared-maildirs</tt>
has the following contents:</p>
<p><tt>firmwide /home/bigcheese/Maildir-shared</tt> <tt>tech
/home/gearhead/Maildir-shared</tt></p>
<p>Subscribing to folders 'golf' and 'boat' in bigcheese's shared
Maildir, and to the folder 'maintenance' in gearhead's shared
Maildir involves creating the following subdirectories:
<tt>shared-folders/firmwide/.golf</tt>,
<tt>shared-folders/firmwide/.boat</tt>, and
<tt>shared-folders/tech/.maintenance</tt>.</p>
<h3><tt>shared</tt></h3>This is a soft link that's automatically
created in <tt>shared-folders/<em>name</em></tt>. It is a soft
link that points to the sharable maildir, which contains the
sharable folders.
<h2><a name="oldsharedsub" id="oldsharedsub">Subscribing to a
shared folder</a></h2>
<ul>
<li>Read <tt>shared-maildirs</tt>.</li>
<li>Read the <tt>shared-folders</tt> hierarchy to determine
which folders are already subscribed to.</li>
<li>Read the folders in each maildir listed in
<tt>shared-folders</tt>, and ignore the ones that are already
subscribed to. Make sure to stat() each folder to make sure
that you can read it.</li>
<li>If necessary, create <tt>shared-folders/<em>name</em></tt>,
and create the <tt>shared-folders/<em>name</em>/shared</tt>
soft link.</li>
<li>Create <tt>shared-folders/name/.foldername</tt>, then
create the standard <tt>tmp</tt>, <tt>new</tt>, and
<tt>cur</tt> subdirectories. All the directories are created
without any group or world permissions.</li>
</ul>
<h2><a name="oldsharedunsub" id=
"oldsharedunsub">Unsubscribing</a></h2>
<ul>
<li>Delete everything in
<tt>shared-folders/name/<em>foldername</em></tt>.</li>
<li>If this is there are no more subscribed folders in this
sharable maildir, delete <tt>shared-folders/name</tt> for good
measure as well.</li>
</ul>
<h2><a name="oldsharedopen" id="oldsharedopen">Opening a shared
folder</a></h2>
<p>The process of "opening" a shared folder involves basically
"syncing" the contents of
<tt>shared-folders/name/.foldername</tt> with the contents of the
sharable folder in the original sharable maildir.</p>
<ul>
<li>Do the usual processing on the <tt>tmp
subdirectory</tt>.</li>
<li>Read the contents of
<tt>shared-folders/name/<em>foldername</em>/shared/new</tt>. If
you find <em>anything</em> in there, rename it to
<tt>../cur</tt>, ignoring any errors from the rename. The
sharable maildir owner can arrange for mail to be delivered
directly to this folder, and the first one to open it will put
the message into <tt>cur</tt>.</li>
<li>Read the contents of
<tt>shared-folder/name/<em>foldername</em>/shared/cur</tt>.
Call this directory "A", for short.</li>
<li>Read the contents of
<tt>shared-folder/name/<em>foldername</em>/cur</tt>. Call this
directory "B", for short.</li>
<li><tt>stat()</tt> A and B to see if they live on different
devices.</li>
<li>Remove all messages in B that do not exist in A. You want
to compare the filenames up to the : character.</li>
<li>Create soft links from messages that exist in A and do not
exist in B. The name in B should not have any flags after the
:, so it shows up as a new message.</li>
<li>You can now do whatever you normally do with a maildir.
Note that <tt>new</tt> is completely ignored, though. Moving
messages IN and OUT of the shared folder involves copying the
message as if it were a new message. Copying the message INTO
the shared folder means copying the message into the underlying
sharable folder's tmp/cur directory, and it will show up after
the next sync.</li>
</ul>
</body>
</html>
|