Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

EOP-281: OpenARC module and APIs #782

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
6 changes: 4 additions & 2 deletions content/momentum/4/4-lua-summary-table.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
lastUpdated: "10/05/2021"
lastUpdated: "12/01/2024"
title: "Lua Functions Summary"
description: "This section contains tables of Lua functions Click the function name for details Table 64 1 Lua functions all Function Description Params Package Version Phases ac esmtp capability add Add a capability to the EHLO response name msys extended ac 4 0 connect ehlo ac esmtp capability remove Removes a..."
---
Expand Down Expand Up @@ -174,6 +174,8 @@ This section contains tables of Lua functions. Click the function name for detai
| [msys.unlock](/momentum/4/lua/ref-msys-unlock) – Releases a lock obtained via msys.lock | mutexname | msys | 4.0 | any |
| [msys.validate.dk.get_responsible_domain](/momentum/4/lua/ref-msys-validate-dk-get-responsible-domain) – This function requires module "dk_validate". "msg" is a mail message. "ctx" is the validation context. It returns the responsible domain for the current message | msg, ctx | msys.validate.dk | 4.0 | data, data_spool, data_spool_each_rcpt |
| [msys.validate.dk.sign](/momentum/4/lua/ref-msys-validate-dk-sign) – Sign a message using a Domain Key | msg, ctx, options | msys.validate.dk | 4.0 | core_data_validation |
| [msys.validate.openarc.sign](/momentum/4/lua/ref-msys-validate-openarc-sign) – Sign a message using OpenARC | msg, options, [ar] | msys.validate.openarc | 5.0 | core_post_final_validation |
dkoerichbird marked this conversation as resolved.
Show resolved Hide resolved
dkoerichbird marked this conversation as resolved.
Show resolved Hide resolved
| [msys.validate.openarc.verify](/momentum/4/lua/ref-msys-validate-openarc-verify) – Verify ARC sets | msg | msys.validate.openarc | 5.0 | data_spool, data_spool_each_rcpt |
| [msys.validate.opendkim.get_num_sigs](/momentum/4/lua/ref-msys-validate-opendkim-get-num-sigs) – Return the number of DKIM signatures | dkim | msys.validate.opendkim | 4.0 | data, data_spool, data_spool_each_rcpt |
| [msys.validate.opendkim.get_sig](/momentum/4/lua/ref-msys-validate-opendkim-get-sig) – Get a signature from a DKIM object | dkim, [num] | msys.validate.opendkim | 4.0 | data, data_spool, data_spool_each_rcpt |
| [msys.validate.opendkim.get_sig_canons](/momentum/4/lua/ref-msys-validate-opendkim-get-sig-canons) – Fetch the canonicalizers used for a DKIM signature | dkim_sig | msys.validate.opendkim | 4.0 | data, data_spool, data_spool_each_rcpt |
Expand All @@ -186,7 +188,7 @@ This section contains tables of Lua functions. Click the function name for detai
| [msys.validate.opendkim.get_sig_selector](/momentum/4/lua/ref-msys-validate-opendkim-get-sig-selector) – Fetch the selector associated with a DKIM signature | dkim_sig | msys.validate.opendkim | 4.0 | data, data_spool, data_spool_each_rcpt |
| [msys.validate.opendkim.get_sig_signalg](/momentum/4/lua/ref-msys-validate-opendkim-get-sig-signalg) – Return the signing algorithm as a string | dkim_sig | msys.validate.opendkim | 4.0 | data, data_spool, data_spool_each_rcpt |
| [msys.validate.opendkim.sign](/momentum/4/lua/ref-msys-validate-opendkim-sign) – Sign a message using OpenDKIM | msg, vctx, [options] | msys.validate.opendkim | 4.0 | core_final_validation |
| [msys.validate.opendkim.verify](/momentum/4/lua/ref-msys-validate-opendkim-verify) – Verify an DKIM signature | m | msys.validate.opendkim | 4.0 | data, data_spool, data_spool_each_rcpt |
| [msys.validate.opendkim.verify](/momentum/4/lua/ref-msys-validate-opendkim-verify) – Verify an DKIM signature | msg | msys.validate.opendkim | 4.0 | data, data_spool, data_spool_each_rcpt |
| [sess:request_add_header](/momentum/4/lua/ref-sess-request-add-header) – Set the header of an HTTP session | header, value, replace | msys.httpclnt | 4.0 | http_request_eval |
| [sess:request_delete_header](/momentum/4/lua/ref-sess-request-delete-header) – Delete a header from an HTTP session | header | msys.httpclnt | 4.0 | http_request_eval |
| [sess:request_finalize](/momentum/4/lua/ref-sess-request-finalize) – Finalize changes to an HTTP request | update | msys.httpclnt | 4.0 | http_request_eval |
Expand Down
84 changes: 84 additions & 0 deletions content/momentum/4/hooks/core-post-final-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
lastUpdated: "11/26/2024"
title: "post_final_validation"
description: "hook invoked after the normal final validation"
---

<a name="hooks.core.post_final_validation"></a>
## Name

post_final_validation — This hook is invoked after the normal
[final_validation](/momentum/3/3-api/hooks-core-final-validation) hook

## Synopsis

`#include "hooks/core/final_validation.h"`

`int core_post_final_validation(void closure, ec_message *msg, accept_construct *ac, valiate_context *ctx)`


## Description

This hook is invoked right after the
[final_validation](/momentum/3/3-api/hooks-core-final-validation) hook. Its return value
does not have significance for now.
This hook is added as the absolute last point before writing the message to spool for delivery.
It guarantees that operations implemented in this hook will happen after the operations done in
`final_validation`.
No message modification is expected after this stage.
juliebin marked this conversation as resolved.
Show resolved Hide resolved
To avoid undefined ordering between multiple implementations of the same hook, you shall have at most
one implementation for this hook.
> It's the recommended hook point for ARC signing/sealing.


**Parameters**

The parameters from this hook are the same as the ones for `final_validation` hook.

<dl class="variablelist">

<dt>closure</dt>

<dd>

A pointer to the closure function.

</dd>

<dt>msg</dt>

<dd>

A pointer to an ec_message struct. For documentation of this data structure see [“ec_message”](/momentum/3/3-api/structs-ec-message)

</dd>

<dt>ac</dt>

<dd>

The `accept_construct` struct. For documentation of this data structure see [“accept_construct”](/momentum/3/3-api/structs-accept-construct)

</dd>

<dt>ctx</dt>

<dd>

The `validate_context` struct. For documentation of this data structure see [“validate_context”](/momentum/3/3-api/structs-validate-context)

</dd>

</dl>

**Return Values**

This hook returns `int`, but for now the return value has no significance, i.e. it is not checked in
the caller.

**Threading**

This hook will be called in any thread.


<a name="idp45866720"></a>
5 changes: 3 additions & 2 deletions content/momentum/4/hooks/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
lastUpdated: "10/05/2021"
title: "Category File"
lastUpdated: "11/26/2024"
title: "Hook Points and C Functions Reference"
type: "custom"
name: "Hook Points and C Functions Reference"
description: "This chapter includes hook point and C function reference material that is specific to Momentum 4 Hook points and C functions that are common to Momentum 4 and Momentum 3 are provided in the Momentum 3 x documentation For hook points see the C API For C functions see the..."
Expand All @@ -11,6 +11,7 @@ description: "This chapter includes hook point and C function reference material
|---------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| [msg_gen_data_spool](/momentum/4/hooks/msg-gen-data-spool) | This hook is invoked after a message has been generated by the msg_gen module |
| [config_rsrc_setup](/momentum/4/hooks/config-rsrc-setup) | Register a resource |
| [core_post_final_validation](/momentum/4/hooks/core-post-final-validation) | Same usage as but invoked right after the `core_final_validation` hook |
dkoerichbird marked this conversation as resolved.
Show resolved Hide resolved
| [ec_config_rsrc_get](/momentum/4/apis-ec-config-rsrc-get) | Return a resource list blobject from the configuration system |
| [ec_httpsrv_register_auth](/momentum/4/apis-ec-httpsrv-register-auth) | Register an HTTP handler for authenticating a URI |
| [ec_httpsrv_request_local_address](/momentum/4/apis-ec-httpsrv-request-local-address) | Returns the local IP address from the current session |
Expand Down
4 changes: 3 additions & 1 deletion content/momentum/4/lua/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
lastUpdated: "10/05/2021"
lastUpdated: "12/01/2024"
title: "Category File"
type: "custom"
name: "Lua Functions Reference"
Expand Down Expand Up @@ -191,6 +191,8 @@ description: "This section details all Lua functions Functions are ordered alpha
| [msys.tls_params.set](/momentum/4/lua/ref-msys-tls-params-set) | Set a tls parameter string on a per connection basis |
| [msys.validate.dk.get_responsible_domain](/momentum/4/lua/ref-msys-validate-dk-get-responsible-domain) | Return the domain responsible for the current message |
| [msys.validate.dk.sign](/momentum/4/lua/ref-msys-validate-dk-sign) | Sign a message using a Domain Key |
| [msys.validate.openarc.sign](/momentum/4/lua/ref-msys-validate-openarc-sign) | Sign a message using OpenARC |
| [msys.validate.openarc.verify](/momentum/4/lua/ref-msys-validate-openarc-verify) | Verify ARC sets |
| [msys.validate.opendkim.get_num_sigs](/momentum/4/lua/ref-msys-validate-opendkim-get-num-sigs) | Return the number of DKIM signatures |
| [msys.validate.opendkim.get_sig](/momentum/4/lua/ref-msys-validate-opendkim-get-sig) | Get a signature from a DKIM object |
| [msys.validate.opendkim.get_sig_canons](/momentum/4/lua/ref-msys-validate-opendkim-get-sig-canons) | Fetch the canonicalizers used for a signature |
Expand Down
135 changes: 135 additions & 0 deletions content/momentum/4/lua/ref-msys-validate-openarc-sign.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
lastUpdated: "11/26/2024"
title: "msys.validate.openarc.sign"
description: "msys validate openarc sign seal add ARC set headers"
---

<a name="lua.ref.msys.validate.openarc.sign"></a>
## Name

msys.validate.openarc.sign — builds and adds the ARC set headers into an email.

msys.validate.openarc.seal - synonym of `msys.validation.openarc.sign`.

## Synopsis

`msys.validate.openarc.sign(msg, options, ar)`

`msys.validate.openarc.seal(msg, options, ar)`

```
msg: userdata, ec_message type
options: table
ar: string, optional. It's the message's authentication assessment to be copied as-is into the AAR header.

```

## Description

This function does ARC validation first, then combine the validation result with authentication
assessments from other methods (e.g. SPF, DKIM, etc) defined by the `ar` and put it into the AAR
(ARC-Authentication-Results) header;
then sign and seal the message by adding the AMS (ARC-Message-Signature) and AS
(ARC-Seal) headers, using the signing mechanism defined in the `options` table.

This function requires the [`openarc`](/momentum/4/modules/openarc) module.

Enable this function with the statement `require('msys.validate.openarc')`.

This function takes the following parameters:

* `msg` - mail message to sign

* `options` - table defines the options for signature generation/signing:

* `signing_domain` – signing domain

* `selector` – signing selector

* `authservid` – authentication service identifier, as
[authserv-id](https://datatracker.ietf.org/doc/html/rfc8601#section-2.5) defined in RFC.

If not set, will be defaulted to the hostname.

* `header_canon` – header canonicalization setting.

Supported values are `relaxed`, `simple`. Defaults to `relaxed`.

* `body_canon` – body canonicalization setting

Supported values are `relaxed`, `simple`. Defaults to `relaxed`.

* `digest` – signing algorithm digest setting.

Supported values are `rsa-sha1` and `rsa-sha256`. Defaults to `rsa-sha256`.

* `keyfile` – signing key file

* `keybuf` – signing key

Must contain the PEM encoded private key to use for signing the
message. This must be a contiguous string, with no line breaks and no white spaces, without the
`BEGIN` and `END` tags that are found in the key file itself. The format is similar to the
format used for OpenDKIM signing.

If not defined, will be built from the `keyfile`.

* `headerlist` – colon-separated list of headers to sign

* `oversign_headerlist` – colon-separated list of headers for over signing

* `skip_ar_header_update` – if set, no update to the AR (Authentication-Results) header.

If not set, Momentum will append the ARC verification result (e.g. `arc=pass`) to
the existing AR header or create one if it does not exist.

* `ar` - authentication assessment to be copied as-is into the AAR (ARC-Authentication-Results) header.

If not provided, Momentum will take the value from the existing `Authentication-Results` header.
Momentum appends this value with the ARC verification result (e.g. `arc=pass`) and uses it to
build the AAR header.


### Note

Since ARC sealing must not happen until all potential modification of a message is done, this function
should be invoked in the `post_final_validation` stage after all the other validation phases.

If for any reason the ARC signing/sealing failed, the context variable `arc_seal` of the `ec_message`
will not be set, and the error reason is logged into paniclog.


<a name="lua.ref.msys.validate.openarc.sign.example"></a>
### Example


```
require("msys.core");
require("msys.validate.openarc");
local mod = {};

function mod:core_post_final_validation(msg, accept, vctx)
local sealer = {}
sealer.signing_domain = "sparkpost.com"
sealer.selector = "dkim-s1024"
sealer.keyfile = "path-to-keyfile"
sealer.headerlist = "From:Subject:Date:To:MIME-Version:Content-Type"
sealer.oversign_headerlist = "From:To:Subject"

msys.validate.openarc.sign(msg, sealer)

-- check sign/seal result
local ok = msg:context_get(msys.core.ECMESS_CTX_MESS, "arc_seal")
if ok == nil or ok == '' then
print("ARC seal failed. No ARC set add! Check paniclog for reasons.")
else
print("ARC seal ok. ARC set added!")
end
end

msys.registerModule("openarc_sign", mod);
```

## See Also

[msys.validate.openarc.verify](/momentum/4/lua/ref-msys-validate-openarc-verify)
62 changes: 62 additions & 0 deletions content/momentum/4/lua/ref-msys-validate-openarc-verify.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
lastUpdated: "11/26/2024"
title: "msys.validate.openarc.verify"
description: "msys validate openarc verify Verify ARC sets headers"
---

<a name="lua.ref.msys.validate.openarc.verify"></a>
## Name

msys.validate.openarc.verify — Verifies ARC set headers in an email, and stores the verification results
(`none/pass/fail`) into the email's context variable.

## Synopsis

`msys.validate.openarc.verify(msg)`

`msg: userdata, ec_message type`<a name="idp19138336"></a>
## Description

This function validates the ARC set headers contained in the input message. The validation result
will be stored as string value (`none` or `pass` or `fail`) in the `ec_message`'s context variable
of `arc_cv`. A caller can take actions (e.g. disposition of the message) based on the validation
result.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing "none" means no ARC headers rather than the status of "cv=none" which is normal for just one ARC header set?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

none means cv=none in ARC-Seal, also means no ARC headers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) seems like if a single set of ARC headers checks out, the result should be 'pass', not 'none.


This function requires the [`openarc`](/momentum/4/modules/openarc) module.

Enable this function with the statement `require('msys.validate.openarc')`.

### Note

If the `ec_message` context variable `arc_cv` is not set after this function call, errors happened
and were logged into paniclog.

This function invokes dns lookup for signature validation. It's recommended to invoke it from a hook
which would not block Momentum's main tasks, e.g. from the `validate_data_spool` hook.

<a name="lua.ref.msys.validate.openarc.verify.example"></a>
### Example


```
require("msys.core");
require("msys.extended.message");
require("msys.validate.openarc");
local mod = {};

function mod:validate_data_spool(msg, ac, vctx)
msys.validate.openarc.verify(msg)
local cv = msg:context_get(msys.core.ECMESS_CTX_MESS, "arc_cv")
if cv then
print("ARC validation result: ", cv)
else
print("Failed to do ARC validation. Check paniclog for reasons.")
end
end

msys.registerModule("openarc_verify", mod);
```

## See Also

[msys.validate.openarc.sign](/momentum/4/lua/ref-msys-validate-openarc-sign)
3 changes: 2 additions & 1 deletion content/momentum/4/modules/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
lastUpdated: "10/05/2021"
lastUpdated: "12/01/2024"
title: "Category File"
type: "custom"
name: "Modules Reference"
Expand Down Expand Up @@ -60,6 +60,7 @@ description: "Table of Contents 71 1 Introduction 71 2 ac auth Authentication Ha
| [msgc](/momentum/4/modules/msgc) | Message Systems Group Communication |
| [msg_gen](/momentum/4/modules/msg-gen) | Message Generation |
| [mxip](/momentum/4/modules/mxip) | IP Addresses In MX Records |
| [openarc](/momentum/4/modules/openarc) | Open Source ARC |
| [opendkim](/momentum/4/modules/opendkim) | Open Source DKIM |
| [outbound_audit](/momentum/4/modules/outbound-audit) | Outbound traffic analytics |
| [outbound_smtp_auth(modules.outbound_smtp_auth.php) |
Expand Down
Loading
Loading