[Dovecot v2.3.9.3] HTTP API Endpoint for mailbox cryptokey operations

Thibault HUTTIN-PASSERON thibault.passeron at swhawk.eu
Thu May 14 22:28:29 EEST 2020


Hello everyone,

I successfully set up the mail_crypt plugin using folder keys, and 
require user's key to be encrypted with a password using 
mail_crypt_require_encrypted_user_key = yes.

As I'm trying to streamline the process of creating a user, and want to 
develop an application in PHP to help me in that process, I'm very 
interested in the doveadm HTTP API. Although the mail_crypt plugin is 
not referenced in the API, I discovered that it could be accessed all 
the same, provided some camelCase changes. So far I've been able to 
generate the following json for the mailbox cryptokey generate command:

curl -X POST -H "Authorization: X-Dovecot-API <base64-api-token>" -H 
"Content-Type: application/json" -d 
'[["mailboxCryptokeyGenerate",{"user":"<username>","userKeyOnly":true},"tag1"]]' 
http://localhost:8081/doveadm/v1

which is able to give me the same output as the related command:

doveadm mailbox cryptokey generate -u <username> -U.

This only works if a keypair has already been generated for the user, 
which is kind of counter-productive in my use case. I would like to know 
if there was a way to adapt the following command into a json API call :

doveadm -o plugin/mail_crypt_private_password=<password> mailbox 
cryptokey generate -u <username> -U

Especially the -o plugin/mail_crypt_private_password=<password> part, 
since it seems I've figured out the other part partly tinkering partly 
looking through the source code.

Thanks everyone for your input.

Thibault PASSERON

PS : excerpts from my configuration :

doveconf -n
===========

# 2.3.9.3 (9f41b88fa): /etc/dovecot/dovecot.conf
# Pigeonhole version 0.5.9 (db4e9a2f)
# OS: Linux 5.6.7-300.fc32.x86_64 x86_64 Fedora release 32 (Thirty Two)
# Hostname: <hostname>
auth_mechanisms = plain login
dict {
   sqldict = mysql:/etc/dovecot/dovecot-sql-dict.conf.ext
}
doveadm_api_key = # hidden, use -P to show it
mail_attribute_dict = proxy:dict:sqldict
mail_plugins = quota mail_crypt
passdb {
   args = /etc/dovecot/dovecot-sql.conf.ext
   driver = sql
}
plugin {
   mail_crypt_curve = secp521r1
   mail_crypt_require_encrypted_user_key = yes
   mail_crypt_save_version = 2
}
service dict {
   unix_listener dict {
     group = vmail
     mode = 0600
     user = vmail
   }
}
service doveadm {
   inet_listener http {
     port = 8081
   }
   unix_listener doveadm-server {
   }
}
userdb {
   args = /etc/dovecot/dovecot-sql.conf.ext
   driver = sql
}
protocol lmtp {
   mail_plugins = quota mail_crypt sieve
}

dovecot-sql.conf.ext
====================

driver = mysql
connect = "host=/var/lib/mysql/mysql.sock user=<user> password=<pass> 
dbname=<db>"
#SQL Query used to fetch the user from the DB
user_query = SELECT email as user, \
     CONCAT('*:bytes=',quota) AS quota_rule, \
     '/var/spool/mail/virtual_mailboxes/%d/%n' as home, \
     5000 AS uid, \
     5000 AS gid, \
     crypt AS mail_crypt_save_version \
     FROM virtual_users WHERE email='%u';
#SQL Query used to fetch the user's password from the DB
password_query = SELECT password, \
     crypt AS userdb_mail_crypt_save_version, \
     '%w' AS userdb_mail_crypt_private_password \
     FROM virtual_users WHERE email='%u';
#SQL Query to iterate over all users
iterate_query = SELECT email AS user FROM virtual_users;

dovecot-sql-dict.conf.ext
=========================

#driver = mysql
connect = "host=/var/lib/mysql/mysql.sock user=<user> password=<pass> 
dbname=<db>"

# User's private keys
map {
   pattern = 
priv/$mailboxid/vendor/vendor.dovecot/pvt/crypt/privkeys/$digest
   table = virtual_users_cryptokeys_priv_dict
   username_field = email
   value_field = key_contents

   fields {
     mailbox_id = $mailboxid
     key_digest = $digest
   }
}

map {
   pattern = 
priv/$mailboxid/vendor/vendor.dovecot/pvt/server/vendor/vendor.dovecot/pvt/crypt/privkeys/$digest
   table = virtual_users_cryptokeys_priv_server_dict
   username_field = email
   value_field = key_contents

   fields {
     mailbox_id = $mailboxid
     key_digest = $digest
   }
}

#User's active private key
map {
   pattern = priv/$mailboxid/vendor/vendor.dovecot/pvt/crypt/active
   table = virtual_users_cryptokeys_priv_active_dict
   username_field = email
   value_field = key_digest

   fields {
     mailbox_id = $mailboxid
   }
}

map {
   pattern = 
priv/$mailboxid/vendor/vendor.dovecot/pvt/server/vendor/vendor.dovecot/pvt/crypt/active
   table = virtual_users_cryptokeys_priv_active_server_dict
   username_field = email
   value_field = key_digest

   fields {
     mailbox_id = $mailboxid
   }
}

#Public keys
map {
   pattern = 
shared/$mailboxid/vendor/vendor.dovecot/pvt/crypt/pubkeys/$digest
   table = virtual_users_cryptokeys_shared_dict
   value_field = key_contents

   fields {
     mailbox_id = $mailboxid
     key_digest = $digest
   }
}

map {
   pattern = 
shared/$mailboxid/vendor/vendor.dovecot/pvt/server/vendor/vendor.dovecot/pvt/crypt/pubkeys/$digest
   table = virtual_users_cryptokeys_shared_server_dict
   value_field = key_contents

   fields {
     mailbox_id = $mailboxid
     key_digest = $digest
   }
}

#Active public keys
map {
   pattern = 
shared/$mailboxid/vendor/vendor.dovecot/pvt/server/vendor/vendor.dovecot/pvt/crypt/active
   table = virtual_users_cryptokeys_shared_active_server_dict
   value_field = key_digest

   fields {
     mailbox_id = $mailboxid
   }
}

map {
   pattern = shared/$mailboxid/vendor/vendor.dovecot/pvt/crypt/active
   table = virtual_users_cryptokeys_shared_active_dict
   value_field = key_digest

   fields {
     mailbox_id = $mailboxid
   }
}


More information about the dovecot mailing list