Only allow auto-creation of OIDC backed users if the node where the
user logs in is the active master.
Reported-by: Lukas Wagner <l.wagner@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
[TL: use more telling error message]
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
verify_username is used in many places to split into realms (the part
after the last '@') and usernames (everthing before).
The commit disallowing '@' in usernames broke quarantine login
(users login with `localpart@domainname.com@quarantine`)
Fixes: 9665bbc ("utils: user schema: explicitly forbid @ in user-names")
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
deprecate the fixed role assignment property and replace it with one
that allows to select the source of the role, for now allow static,
which is equivalent with what we had, and also to query the role from
a role claim, so that the OIDC provider can return the correct role
inside the returned user information.
Tested the dynamic role assignment with keycload by setting up an
'User Attribute' Mapper for a client and added added the respective
user attribute to some test user.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Return a quoted regex that is surrounded by a non-capturing group,
which makes it behave more like expected if used with anchors
I.e., previously a match like /^$valid_pmg_realm_regex$/ would look
like it must be an exact match, but actually only anchor the first
case at the start, the last case at the end and the others nowhere.
As concrete example /^foo|bar|baz$/ allows any string that starts with
foo, any string that ends with baz and any string that contains bar
somewhere, i.e. "foo" is accepted just like "foo123".
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
PMGs terms are:
* 'userid' consists of 'username'@'realm'
without this patch it was possible to create a user through the api,
with @ in the username ('foo@bar@pmg'), and it got written to the
user-conf.
Reading that entry was not possible, as the verification on read was
stricter.
This patch forbids '@' in usernames, and additionally drops the
maxLength of 64, as 60 are already enforced by the regex pattern match
(leaving 4 as minimal length for '@pmg'/'@pam').
Potential for regression should be minimal (the users could not be
read-back from the config).
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
reuse the existing helpers in PMG::Utils to forbid creating:
* users with an unallowed realm
* passing a different realm than what we receive in the userid
* users in the pam realm
Reported-by: Mira Limbeck <m.limbeck@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Avoid having to read the whole realm config for cases where we have
dedicated detection and handling for built-in realms anyway.
As a nice side-effect this should reduce chance that a broken realm
config locks out admins.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Move over the valid_pmg_realm_regex from PMG::Utils to
PMG::Auth::Plugin. For one most use-sites already include the
Auth::Plugin module and we have the is_valid_realm method there too,
so it's only fitting to have similar methods near each other.
Drop the unused $id intermediate variable while at it.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
by defining the name once in PMG::Auth::Plugin, and using the sub
there to retrieve it where needed.
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
it's the class that actually needs them, and where we want
to keep the definitions.
move happens in order to not have a cyclical include
(PMG::Auth::Plugin including PMG::Utils for the schema definitions,
and PMG::Utils including PMG::Auth::Plugin to get the realms from its
config file).
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Allow OpenID Connect login using the Rust OIDC module.
PMG::API2::OIDC is based on pve-access-control's PVE::API2::OpenId
Signed-off-by: Markus Frank <m.frank@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
To ensure the Proxmox::RS::OIDC module, which got moved from pve-rs to
the common shared package, is available.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Adapted from PVE, i.e. the PMG::API2::AuthRealm module is based on
pve-access-control's PVE::API2::Domains. The base-name AuthRealm was
chosen because a Domain module already exists and as AuthRealm is more
telling and consistent with the terminology we present to the user,
which favors "realm" over "domain".
Signed-off-by: Markus Frank <m.frank@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
PMG::Auth::OIDC is based on pve-access-control's PVE::Auth::OpenId and
adds an autocreate-role option. If the autocreate option is enabled, the
user is automatically created with the Audit role. With autocreate-role
this role can be changed.
Signed-off-by: Markus Frank <m.frank@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
To differentiate between usernames, the realm is also stored in the
user.conf file. Old config file syntax can be read, but will be
overwritten after a change.
This is a carryover from PVE. Previously there was no realm for a
username. Now the realm is also stored after an @ sign in user.conf.
Utils generates a list of valid realm names, including any newly added
realms, to ensure proper validation of a specified realm name.
Signed-off-by: Markus Frank <m.frank@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
not guarding for install-mode, as the file will not exist on a fresh
install (and we need to do the stat(2) for it anyways).
did not add `|| true` to the `mv` invocation, as moving a file failing
probably warrants apt to error out.
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
keeping the shadow-file in /var/cache breaks their application if
/var/cache is on another filesystem than /etc/mail/spamassassin.
Perl's `rename` function [0], which is a wrapper for rename(2).
`rename` does not work across filesystem boundaries (errors out with
EXDEV).
having `/var` on another filesystem is becoming less common, but
should probably be supported.
Instead of using some other means of file moving, just put the
shadow file in the same directory as pmg-scores.cf.
SpamAssassin only reads files ending in .(cf|pre)$ from its
config-dirs, so having both files in the same directory should not be
an issue. The use of '.new' for the shadow-file follows the naming for
/etc/network/interfaces(.new).
reported in our community-forum:
https://forum.proxmox.com/threads/.154814/
tested in a container with a seperate volume for `/var/cache`.
[0] https://perldoc.perl.org/functions/rename
[1] https://github.com/apache/spamassassin/blob/trunk/README
Suggested-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
as most mails PMG generates locally has an empty envelope-sender,
signing only makes sense when the from-header domain is used as
signing domain.
This fixes#3423, and partially addresses #2971 and #4658 (bounces
generated by postfix directly are not passed through our stack, and
should not be processed in general - see
https://www.postfix.org/postconf.5.html#internal_mail_filter_classes).
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
for mail locally generated by PMG the signing sources
(envelope-sender, From header) can contain only a local-part
(postmaster) or even be empty (envelope-sender).
While such mail cannot be sensibly signed, it should be treated as if
the domain is not listed in DKIM-domains - by an log message on 'info'
level instead of a `die`.
the sub with the changed behavior is only used in this module, and
sign_entity as external entry-point is only called in eval context,
resulting in a log message on level 'warn'.
so effectively this change should only reduce log-levels for DKIM
failures in these cases from 'warning' to 'info'
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
use the new setting as From header for notifications, but keep
the envelope-sender fixed as 'postmaster'.
add a comment that we do not want to sign a mail released from the
quarantine, as it remains the only use of 'postmaster' without this
fallback, but as above - only for the envelope-sender.
the admin-mail-from setting has to be carried through pmg-smtp-filter
in the msginfo variable as was done for the dkim settings as well.
This changes the From header for Notifications sent from the
rulesystem from: 'postmaster' to 'Proxmox Mail Gateway <postmaster>'
(or the setting of admin-mail-from).
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
generate_ndr is currently only used to generate a bounce-mail if the
following occur:
* email is blocked only for part of the receivers
* before-queue-filtering is active - in the after-queue case postfix
generates the bounces for us.
With this patch the header of the bounce message will contain
'Proxmox Mail Gateway <postmaster>' (or the setting of
admin-mail-from) instead of 'postmaster', but this should not affect
deliverability of these mails.
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
this sets the admin-mail-from header information for all local emails
generated through the templateing system, which are not already using
the 'mailfrom' setting from the 'spamquar' config-section.
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
To be used as From header for mails generated by the PMG stack.
Currently this is hardcoded to postmaster in a few places, and
Proxmox Mail Gateway <postmaster> in a few other places..
While PMG generates mails as the mail-system and postmaster is a
good choice for such mails, users sometimes wish to customize the
e-mail shown e.g. in the backup-notification and the daily admin
report.
The set value will be used in the header only, following the similar
setting 'mailfrom' in the 'spamquar' setting.
I decided against reusing the existing setting, as it's specifically
tied to a category.
The format is restricted by regex to printable ascii-characters for
now[1], as being more permissive later (even allowing all unicode
printables) is easy. The length restriction to 998 characters ist due
to a few SMTP-RFCs [2].
Envelope-from addresses for mail generated by will remain empty or
'postmaster'.
This is a first step towards DKIM signing those mails.
Users will have to opt-in to it and use a email with domain-part to
get DKIM signing.
I decided against changing the current behavior of using 'postmaster'
without domain, as this makes postfix complete the address with
'@$myorigin.$mydomain'[0], and I've seen quite a few installations
which set those settings in their main.cf.in templates.
[0] https://www.postfix.org/postconf.5.html#internal_mail_filter_classes
[1] https://perldoc.perl.org/perlrecharclass
[2] https://www.rfc-editor.org/rfc/rfc5322#section-2.1.1
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
The variable was introduced in a early version of c320d56 ("utils:
content-type: don't fallback to header information for magic"
without realizing that the PMX_magic|glob_ct variables are only set
for MIME-Parts with bodyhandle - and expecting to replace the
header-lookup in multiple places. As the header is also present and
needed for MIME-Parts without bodyhandle (parts that have subparts
have no bodyhandle) - drop the variable, in order to cause less
confusion.
Also drop '$magic' as part of the nested if-condition, as it is
already checked in the if one line above.
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Reviewed-by: Dominik Csapak <d.csapak@proxmox.com>
Tested-by: Dominik Csapak <d.csapak@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
As noted in the cover-letter for v3 of the series introducing this [0]
the PMX_magic_ct, PMX_glob_ct and PMX_header_ct are only set if there
is a bodyhandle for a mime-part, which only exists if the part has no
sub-parts.
[0]: https://lore.proxmox.com/pmg-devel/74a089b6-d858-4525-9822-da58b9c8f4d7@proxmox.com/T/#t
However we want to match on content-types even for mail-parts which
have no bodyhandle:
* our internal regression-test suite has a mail with `message/partial`
set
* there are probably sensible uses for matching `multipart/related`
parts (e.g. when trying to get a negated match.
Noticed during a check of our regression-tests.
Fixes: c320d56 ("utils: content-type: don't fallback to header information for magic")
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Reviewed-by: Dominik Csapak <d.csapak@proxmox.com>
Tested-by: Dominik Csapak <d.csapak@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
the default of 'only_content' gets set when fetching the entries from
the database in load_attr - and it defaults to false, making the `// 1`
even more confusing.
Noticed while debugging another issue, and considered if this false
setting might be the cause.
Fixes: af418f4 ("ruledb: content-type: add flag for matching only based on magic/content")
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Reviewed-by: Dominik Csapak <d.csapak@proxmox.com>
Tested-by: Dominik Csapak <d.csapak@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
currently an update to SpamAssassin does not reload any of the
services.
This patch simply adds interest-noawait on a trigger activated by
proxmox-spamassassin, which in turn reloads all services (as already
done for updates to pve-common, and in PVE on updates on other
packages that affect the API).
Technically it might only be necessary to reload pmg-smtp-filter,
pmgproxy and pmgdaemon, to get the benefits of a new spamassassin
version, but reloading all services seems more robust in the long run.
[0] https://git.dpkg.org/cgit/dpkg/dpkg.git/tree/doc/spec/triggers.txt
[1] https://manpages.debian.org/bookworm/dpkg-dev/deb-triggers.5.en.html
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
The current Match Field (header) what-objects always traverse each
mime-part of a mail.
This can be inconvenient, and causes unexpected matches when you
forward a message as attachment(message/rfc822).
following the patches for adding a Disclaimer on top of a mail from an
implementation point of view, this simply adds an optional
top-level-only attribute for the MatchField object, which is disabled
by default for backwards-compatibility.
Tested-by: Dominik Csapak <d.csapak@proxmox.com>
Reviewed-by: Dominik Csapak <d.csapak@proxmox.com>
Tested-by: Friedrich Weber <f.weber@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
our current content-type matching is sensibly quite cautious in
matching if any available information indicates a potential match:
* mime-type detection based on file contents
* mime-type detection based on file suffix
* content-type header
Sometimes this can lead to surprises (e.g. when a MUA sets the
filetype of a pdf to application/octet-stream (the default type if no
information is available), or a filter for zip-files matching
docx-files.
This change gives users the option to restrict matching only on the
content as detected by xdg_mime_get_mime_type_for_data.
This is a fix for the intial request in #2691 and addresses the
suggestion from Friedrich from:
https://bugzilla.proxmox.com/show_bug.cgi?id=5618#c2
matches on the other items can be created with Match Field objects
(for the content-type header) and Filename (for the match based on the
provided filename - combinations of those should give us the complete
flexibility.
inspired by the changes for disclaimer released with PMG 8.1:
51d1507 ("fix #2430: ruledb disclaimer: make separator configurable")
Tested-by: Dominik Csapak <d.csapak@proxmox.com>
Reviewed-by: Dominik Csapak <d.csapak@proxmox.com>
Tested-by: Friedrich Weber <f.weber@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
file-type detection based on content/magic is the single piece of
information not determined by the headers of the e-mail, and thus not
directly controlled by the sender.
this patch removes the fallback to the content-type header mime-type
in case magic_mime_type_for_file does not detect the type.
one exception to this is trying to eagerly gain information from
archives - where we want to try to unpack an archive if the header
says it is an archive but the content is not detected as such.
Reported-by: Friedrich Weber <f.weber@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
as one object(_id) belongs is of one object type, we can safely remove
all associated attribut entries from the database at once instead of
running 2 separate statements to delete each individually
noticed this while adding new attribut entries to the content-type
check.
Tested-by: Dominik Csapak <d.csapak@proxmox.com>
Reviewed-by: Dominik Csapak <d.csapak@proxmox.com>
Tested-by: Friedrich Weber <f.weber@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
This was reported through our enterprise support and was easy to
reproduce.
When clicking on the action-links in the spamreport multiple times the
action was equally done multiple times, which was surprising
especially when you deliver a quarantined mail more than once.
As quarantined mail-files are not deleted upon deliver/delete (mails
can have multiple recipients), but asynchronously after the quarantine
lifetime they are only marked with status 'D'.
Use this information to prevent multiple deliveries and superfluous
database updates.
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Tested-by: Christian Ebner <c.ebner@proxmox.com>
The question: "What happened to the quarantined e-mail" comes up every
now and then in our support-channels, and it always feels a bit clumsy
to explain how to get to the fitting logline, by referring to the
general timeframe when a user did the request and to look for the
queue-ids and quarantine-file-ids for identifying a particular mail.
Adding the receiver of the mail to the log lines should make this a
bit more straight-forward.
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Tested-by: Christian Ebner <c.ebner@proxmox.com>