85.1.55. pepsi-helper-maildir-writer¶
drop a message into a local user’s Maildir/new/ as root
- Section du manuel:
1
85.1.55.1.1. Nom¶
pepsi-helper-maildir-writer - helper de remise locale privilégié qui écrit un message unique depuis l’entrée standard dans le Maildir/new/ d’un utilisateur cible.
85.1.55.1.2. Synopsis¶
pepsi-helper-maildir-writer [OPTIONS] TARGET-UID < message
pepsi-helper-maildir-writer measure [OPTIONS] TARGET-UID
85.1.55.1.3. Description¶
pepsi-helper-maildir-writer est un helper minimal et durci en sécurité qui remet exactement un message dans le Maildir d’un utilisateur local. Il existe afin qu’un appelant de confiance mais non privilégié (un membre du groupe pepsi-maildir) puisse déposer du courrier dans la boîte aux lettres de n’importe quel utilisateur local — et ne rien faire d’autre.
Le helper est installé setuid-root, possédé root:pepsi-maildir avec le mode 4750 (rwxr-x--- plus le bit setuid). Par conséquent, seuls les membres du groupe pepsi-maildir peuvent l’exécuter ; lorsqu’ils le font, le noyau l’exécute avec un uid effectif de root.
Recevant l’uid numérique de l’utilisateur cible, et le message brut sur l’entrée standard, le helper :
résout l’entrée passwd de l’utilisateur cible (son répertoire personnel et son groupe primaire), refusant l’uid
0et tout uid inférieur à/etc/login.defsUID_MIN(par défaut1000s’il est illisible) — les comptes système ne sont jamais des cibles de remise valides ;abandonne complètement et irréversiblement ses privilèges de
rootvers l’utilisateur cible — uid et gid réels, effectifs et sauvegardés — en abandonnant d’abord tous les groupes supplémentaires, puis le gid, puis l’uid, et vérifie que root ne peut être regagné. Tout ce qui suit agit avec l’identité de l’utilisateur cible, de sorte que tout fichier qu’il crée est possédé par cet utilisateur ;crée la disposition Maildir standard (
tmp,newetcur, mode0700) sous~/Maildir si elle n’existe pas déjà ;crée un fichier au nom unique dans
Maildir/tmp/avecO_CREAT|O_EXCL(de sorte qu’il a un contrôle exclusif sur le fichier et ne perturbe jamais le fichier d’une autre remise), mode0600, suivant la convention de nommage Maildir<seconds>.M<microseconds>P<pid>Q<sequence>.<hostname>;copie le message de l’entrée standard dans ce fichier, en utilisant
splice(2) lorsque les descripteurs le permettent (le cas courant, lorsque stdin est un tube) et une simple boucle lecture/écriture sinon, en comptant les octets au passage ;fait un
fsync(2) sur le fichier et — lorsqu’un quota est appliqué et que--measurea été donné — décide si la boîte aux lettres a de la place pour lui, abandonnant la remise avec le code de sortie 3 si ce n’est pas le cas ; etle renomme dans
Maildir/new/sous un nom portant l’étiquette Maildir++,S=taille, fait unfsync(2) sur ce répertoire, et rapporte sur la sortie standard ce que la boîte aux lettres contient désormais.
Le helper ne lit aucune configuration, n’ouvre aucune connexion réseau et ne contacte aucune base de données. La politique de quota est décidée par l’appelant et passée en arguments, parce qu’au moment où le helper pourrait lire quoi que ce soit il est l’utilisateur cible, qui n’a pas à choisir son propre quota.
85.1.55.1.4. Quota de boîte aux lettres¶
Le helper est la seule partie de Pepsi capable de voir à quel point une boîte aux lettres est pleine : un Maildir est en mode 0700, et c’est l’unique processus qui devient l’utilisateur. Tout le reste — les décisions de l’étape de remise, le refus de pepsi-ingress(1) au RCPT, le rapport de pepsi-status(1) — travaille à partir de chiffres que ce helper a rapportés.
Il ne mesure que lorsqu’on le lui demande (--measure). L’appelant tient une estimation courante dans pepsi.mailbox_quota et réclame une mesure lorsque cette estimation suggère que le compte pourrait être proche de sa limite ; comme l’estimation ne peut que surcompter (rien ne lui indique qu’un utilisateur supprime du courrier par IMAP), « pas besoin de mesure » est une preuve qu’il reste de la place. Une remise ordinaire dans une boîte aux lettres loin d’être pleine coûte donc un petit ajout et aucun parcours de répertoire.
Trois couches de comptabilité sont employées ensemble, la moins chère d’abord :
maildirsizeLe fichier de taille Maildir++ à la racine de la boîte aux lettres, au format de Courier (une ligne de définition de quota, puis des deltas
<bytes> <messages>ajoutés). Le backendquota = maildir:de Dovecot, Courier et lemaildir_use_size_filed’Exim lisent et écrivent tous le même fichier, de sorte qu’un site faisant tourner l’un d’eux pour IMAP et Pepsi pour la remise tient un seul jeu de chiffres. Pour cette raison, unmaildirsizeexistant est tenu à jour par chaque remise, même lorsque Pepsi lui-même n’applique aucun quota — sinon le compteur de l’autre agent sous-estimerait silencieusement tout ce que Pepsi remet. Sans quota en vigueur, il n’en est jamais créé là où il n’en existe pas. Il est utilisé lorsqu’il est à jour, et réécrit à partir d’un parcours complet lorsqu’il manque, ne s’analyse pas, a été calculé contre d’autres limites, ou a accumulé un long journal de deltas.La réécriture, contrairement au delta ajouté, n’a lieu que tant qu’une limite est en vigueur —
[pepsi] MAILBOX_QUOTA,MAILBOX_QUOTA_COUNTou une lignepepsi.mailbox_quotapour le compte — car elle remplace la ligne de définition de quota en tête du fichier, qu’il revient à l’autre agent d’écrire lorsque Pepsi n’applique rien. Il réside dans le répertoire propre de l’utilisateur : il n’est donc qu’indicatif, un utilisateur pouvant réécrire son propremaildirsize.- Un parcours complet de l’arborescence
new/etcur/de l’INBOX et de chaque dossier Maildir++ (.Sent,.Trash, …) — toute l’arborescence, ce que l’utilisateur appelle « ma boîte aux lettres ».tmp/n’est pas compté (un fichier là est une remise en vol). Le parcours est unreaddir(3) par dossier et aucun appelstat(2), parce que Maildir++ encode la taille de chaque message dans son nom de fichier (,S=n) — ce qui est exactement pourquoi ce helper étiquette les fichiers qu’il écrit. Un message laissé sans étiquette par un autre agent eststaté individuellement.quotactl(2)Avec
--fs-quota, la comptabilité propre du noyau est également consultée. C’est la seule couche inviolable, et sa limite resserre la limite effective : promettre de l’espace qu”EDQUOTrefuserait n’aide personne. Cela fonctionne sans privilège parce queQ_GETQUOTAest permis à un appelant qui interroge son propre uid, et à ce stade le helper est irréversiblement devenu cet utilisateur. Notez que le noyau compte chaque bloc que l’utilisateur possède sur ce système de fichiers, pas seulement son courrier : ses chiffres sont donc rapportés séparément plutôt que de remplacer la mesure de la boîte aux lettres. Un système de fichiers qui ne répond pas (quotas de projet XFS, ZFS, absence de support de quota) ne donne simplement rien, et les autres couches s’appliquent toujours.
Comme la taille du message est inconnue tant que l’entrée standard n’a pas été drainée, le message est mis en tampon dans tmp/ (qui ne compte pas dans le quota) avant que la décision ne soit prise, et supprimé s’il ne tient pas. L’entrée standard est drainée dans tous les cas : un helper qui sortirait trop tôt laisserait son appelant écrire dans un tube cassé, ce qui serait rapporté comme une panne de transport plutôt que comme le refus propre que c’est.
Deux remises simultanées peuvent toutes deux voir de la place et toutes deux écrire, dépassant la limite d’au plus un message chacune. Toute implémentation du quota Maildir++ l’accepte ; la couche de quota du noyau, là où un site en dispose, referme exactement cet écart.
85.1.55.1.5. Arguments¶
- TARGET-UID
L’identifiant numérique d’utilisateur de l’utilisateur local dans le
Maildir/new/duquel le message est remis. Il doit être un entier positif avec une entrée passwd correspondante ; l’uid0(root) et tout uid inférieur à/etc/login.defsUID_MINsont refusés.measureMesure la boîte aux lettres et rapporte, sans rien remettre. L’entrée standard n’est pas lue. Employé par
measureetreconcilede pepsi-quota(1).--measureÉtablit la taille réelle de la boîte aux lettres avant d’écrire, et applique contre elle le quota donné par
--quota-bytes/--quota-count. Sans cet indicateur, le helper remet sans condition et ne rapporte que ce qu’il a ajouté.--fs-quotaConsulte aussi
quotactl(2), rapporte les chiffres du noyau, et laisse la limite du noyau resserrer la limite effective. Positionné par l’étape de remise depuis[pepsi] MAILBOX_FS_QUOTA, que pepsi-setup(1) sonde.--quota-bytesNLa limite en octets à appliquer.
0ou absent signifie aucune limite.--quota-countNLa limite en nombre de messages à appliquer.
0ou absent signifie aucune limite.
Le message à remettre est lu dans son intégralité depuis l’entrée standard.
85.1.55.1.6. Sortie¶
Sur la sortie standard, le helper écrit un enregistrement étiqueté et séparé par des tabulations par ligne. Une étiquette inconnue est ignorée par l’appelant plutôt que d’être une erreur, de sorte qu’un helper plus récent puisse rapporter davantage à un appelant plus ancien.
uTABbytesTABmessagesOccupation mesurée de toute l’arborescence Maildir++, y compris le message qui vient d’être remis. L’appelant la stocke comme occupation du compte et remet à zéro ses compteurs depuis-la-mesure.
fTABusedTABlimitTABinodesTABinode-limitLes chiffres de
quotactl(2), avec0là où le noyau n’applique aucune limite.dTABbytesOctets ajoutés par cette exécution, rapportés à la place de
ulorsqu’aucune mesure n’a été faite, de sorte que l’appelant ajoute à son estimation plutôt que de la remplacer.sTAB(fsquota|maildirsize|scan)Comment le chiffre
ua été obtenu.wTABtextUn problème non fatal (un dossier illisible, un
maildirsizequi n’a pas pu être mis à jour). Jamais fatal pour la remise.
Un rapport est écrit même lorsque la remise a été refusée faute de place — surtout alors, puisque c’est une mesure récente qui autorise pepsi-ingress(1) à refuser le message suivant dans la session SMTP plutôt que de l’accepter pour le faire rebondir ensuite.
85.1.55.1.7. Installation¶
Le binaire doit être installé setuid-root et restreint au groupe
chown root:pepsi-maildir pepsi-helper-maildir-writer
chmod 4750 pepsi-helper-maildir-writer
make install fait cela automatiquement (son étape install-helper), à condition d’être exécuté en tant que root et que le groupe pepsi-maildir existe ; sinon il imprime les commandes exactes à exécuter à la main. Si le helper est placé sur un système de fichiers monté nosuid, le bit setuid est ignoré à l’exécution et le helper refusera de s’exécuter (il ne peut obtenir root), installez-le donc sur un système de fichiers normal.
85.1.55.1.8. Code de sortie¶
Le code de sortie indique à l’étape appelante si réessayer peut servir à quelque chose, de sorte qu’un message ne fait ni l’objet d’un rebond alors qu’il pourrait encore être remis, ni d’une attente de plusieurs jours en file d’attente contre une boîte aux lettres qui ne l’acceptera jamais. Un diagnostic est toujours écrit sur la sortie d’erreur standard, et pepsi-stage-relay-to-maildir(1) à la fois le journalise et le place dans le rebond qu’il génère.
- 0
Le message a été écrit dans le
Maildir/new/de l’utilisateur cible et synchronisé sur disque.- 1
Échec transitoire : une tentative ultérieure peut réussir, l’appelant garde donc le message en file et le réessaie à intervalles croissants. Cela couvre un disque plein (
ENOSPC), une erreur d’E/S, un système de fichiers en lecture seule, et un helper qui n’est pas (encore) installé setuid-root — autant de choses qu’un administrateur peut réparer sous un message en file. Cela couvre aussi tout échec survenant avant que la boîte aux lettres ne soit touchée, quel que soit l”errnoqu’il porte : une consultation passwd qui échoue ou ne trouve aucune entrée pour l’uid (un backend d’annuaire qui répond par intermittence, puisque l’étape a résolu l’uid un instant plus tôt), et un passage à l’utilisateur (setgroups,setgid,setuid) que le noyau refuse. Ceux-là signalent aussiEPERMouENOENT, et faire rebondir sur eux ferait rebondir chaque destinataire local pour une défaillance de l’hôte.- 2
Échec permanent : la boîte aux lettres est inutilisable et aucun réessai n’y changera rien tant qu’un administrateur n’aura pas réparé le compte ; l’appelant fait donc rebondir le message immédiatement. Cela couvre un
Maildirqui n’est pas un répertoire (un ancien fichier mbox), une appartenance ou un mode qui verrouille l’utilisateur hors de son propreMaildir(EACCES/EPERM), un répertoire personnel absent (ENOENT), un répertoire personnel non absolu, et un uid inférieur àUID_MIN. Les valeurs d”errnone comptent que pour les opérations sur la boîte aux lettres elle-même, après le passage à l’utilisateur.- 3
La boîte aux lettres est au-delà de son quota, le message n’a donc pas été écrit. Délibérément ni transitoire ni permanent : savoir si une boîte aux lettres pleine mérite qu’on l’attende est une politique de site (
[pepsi] MAILBOX_OVER_QUOTA), et le helper n’est pas en position de savoir si cet utilisateur vide sa boîte aux lettres tous les jours ou l’a abandonnée il y a un an. Il rapporte le fait ; pepsi-stage-relay-to-maildir(1) applique la politique. UnEDQUOTdu noyau est rapporté de la même façon — un disque plein est le problème de l’administrateur et se règle sous un message en file d’attente, tandis qu’une boîte aux lettres pleine est celui du destinataire et peut ne jamais se régler.
Lorsqu’il est invoqué par un utilisateur qui n’est pas membre du groupe pepsi-maildir, le noyau refuse purement et simplement d’exécuter le binaire (Permission denied) ; le helper lui-même ne s’exécute jamais.
85.1.55.1.9. Sécurité¶
Le helper fait confiance à son appelant pour être autorisé (l’appartenance au groupe pepsi-maildir est la barrière de contrôle d’accès) et remettra à n’importe quel utilisateur local ordinaire (uid ≥ UID_MIN, jamais un compte système). Il abandonne les groupes supplémentaires avant de changer d’uid puis se dépouille complètement de root (ids réel, effectif et sauvegardé), en vérifiant que root ne peut être regagné avant toute E/S de fichier, et crée le fichier de remise de façon exclusive afin de ne jamais pouvoir être trompé pour écrire par-dessus un fichier qu’il ne possède pas.
85.1.55.1.10. Voir aussi¶
pepsi-stage-relay-to-maildir(1), pepsi-ingress(1), pepsi-dispatch(1), pepsi.conf(5), maildir(5)
85.1.55.1.11. Bogues¶
Signalez les bogues au gestionnaire de tickets de Pepsi.