MFA fix, added IP blacklist, update webmail client
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CreateSMIMEIdentity adds a new S/MIME identity for a mailbox — a mailbox may hold
|
||||
// several at once (see esrv_mailbox_smime_identities in schema.go).
|
||||
func (d *DB) CreateSMIMEIdentity(mailboxID int64, certPEM, keyPEM string, notAfter time.Time) (int64, error) {
|
||||
res, err := d.Exec(`
|
||||
INSERT INTO esrv_mailbox_smime_identities (mailbox_id, cert_pem, key_pem, not_after)
|
||||
VALUES (?, ?, ?, ?)
|
||||
`, mailboxID, certPEM, keyPEM, notAfter)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return res.LastInsertId()
|
||||
}
|
||||
|
||||
// ListSMIMEIdentities returns a mailbox's S/MIME identities, most recent first.
|
||||
func (d *DB) ListSMIMEIdentities(mailboxID int64) ([]MailboxSMIMEIdentity, error) {
|
||||
rows, err := d.Query(`SELECT id, mailbox_id, cert_pem, key_pem, not_after, created_at
|
||||
FROM esrv_mailbox_smime_identities WHERE mailbox_id = ? ORDER BY created_at DESC, id DESC`, mailboxID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []MailboxSMIMEIdentity
|
||||
for rows.Next() {
|
||||
var id MailboxSMIMEIdentity
|
||||
if err := rows.Scan(&id.ID, &id.MailboxID, &id.CertPEM, &id.KeyPEM, &id.NotAfter, &id.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, id)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// GetSMIMEIdentity returns nil, nil if no such identity exists for this mailbox —
|
||||
// scoped to mailboxID so one mailbox owner can't reach another's identity by
|
||||
// guessing its ID.
|
||||
func (d *DB) GetSMIMEIdentity(mailboxID, identityID int64) (*MailboxSMIMEIdentity, error) {
|
||||
row := d.QueryRow(`SELECT id, mailbox_id, cert_pem, key_pem, not_after, created_at
|
||||
FROM esrv_mailbox_smime_identities WHERE mailbox_id = ? AND id = ?`, mailboxID, identityID)
|
||||
var id MailboxSMIMEIdentity
|
||||
if err := row.Scan(&id.ID, &id.MailboxID, &id.CertPEM, &id.KeyPEM, &id.NotAfter, &id.CreatedAt); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &id, nil
|
||||
}
|
||||
|
||||
// DeleteSMIMEIdentity removes one identity, scoped to mailboxID.
|
||||
func (d *DB) DeleteSMIMEIdentity(mailboxID, identityID int64) error {
|
||||
_, err := d.Exec(`DELETE FROM esrv_mailbox_smime_identities WHERE mailbox_id = ? AND id = ?`, mailboxID, identityID)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpsertSMIMEContact adds a contact certificate, replacing any existing certificate
|
||||
// already on file for that email (e.g. after the contact renews their cert).
|
||||
func (d *DB) UpsertSMIMEContact(mailboxID int64, email, certPEM string) error {
|
||||
_, err := d.Exec(`
|
||||
INSERT INTO esrv_mailbox_smime_contacts (mailbox_id, email, cert_pem)
|
||||
VALUES (?, ?, ?)
|
||||
ON CONFLICT(mailbox_id, email) DO UPDATE SET cert_pem = excluded.cert_pem
|
||||
`, mailboxID, email, certPEM)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetSMIMEContact returns nil, nil if no certificate is on file for that email.
|
||||
func (d *DB) GetSMIMEContact(mailboxID int64, email string) (*MailboxSMIMEContact, error) {
|
||||
row := d.QueryRow(`SELECT id, mailbox_id, email, cert_pem, created_at FROM esrv_mailbox_smime_contacts WHERE mailbox_id = ? AND email = ?`, mailboxID, email)
|
||||
var c MailboxSMIMEContact
|
||||
if err := row.Scan(&c.ID, &c.MailboxID, &c.Email, &c.CertPEM, &c.CreatedAt); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// ListSMIMEContacts returns a mailbox's collected contact certificates, alphabetical
|
||||
// by email.
|
||||
func (d *DB) ListSMIMEContacts(mailboxID int64) ([]MailboxSMIMEContact, error) {
|
||||
rows, err := d.Query(`SELECT id, mailbox_id, email, cert_pem, created_at FROM esrv_mailbox_smime_contacts WHERE mailbox_id = ? ORDER BY email`, mailboxID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []MailboxSMIMEContact
|
||||
for rows.Next() {
|
||||
var c MailboxSMIMEContact
|
||||
if err := rows.Scan(&c.ID, &c.MailboxID, &c.Email, &c.CertPEM, &c.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, c)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// DeleteSMIMEContact removes one contact certificate, scoped to mailboxID so one
|
||||
// mailbox owner can't delete another's contact by guessing its ID.
|
||||
func (d *DB) DeleteSMIMEContact(mailboxID, contactID int64) error {
|
||||
_, err := d.Exec(`DELETE FROM esrv_mailbox_smime_contacts WHERE mailbox_id = ? AND id = ?`, mailboxID, contactID)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user