Skip to content

Commit

Permalink
mysql_adaptor: set up address_status bits for non-receiving accounts
Browse files Browse the repository at this point in the history
References: GXL-435
  • Loading branch information
grammmike committed Oct 20, 2023
1 parent 1ea9d52 commit 3ed03dc
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 12 deletions.
9 changes: 7 additions & 2 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
Development 2.15.1
==================
Development 2.15.17
===================

Fixes:

* oxvcard: export to .vcf now positions the VERSION property in accordance with
the vCard 4.0 specification.
* oxcmail: cease gratuitous RTF conversion of calendar items

Enhancements:

* Define the "suspended" user state (think of it as a "non-receiving shared
mailbox").


Gromox 2.15 (2023-10-18)
========================
Expand Down
5 changes: 2 additions & 3 deletions exch/mysql_adaptor/mysql_adaptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ errno_t mysql_adaptor_meta(const char *username, unsigned int wantpriv,
return EACCES;
}
auto address_status = strtoul(myrow[2], nullptr, 0);
if (address_status != 0 && !(wantpriv & WANTPRIV_METAONLY)) {
if (!afuser_login_allowed(address_status) && !(wantpriv & WANTPRIV_METAONLY)) {
auto uval = address_status & AF_USER__MASK;
if (address_status & AF_DOMAIN__MASK)
mres.errstr = fmt::format("Domain of user \"{}\" is disabled!", username);
Expand Down Expand Up @@ -921,8 +921,7 @@ bool mysql_adaptor_check_user(const char *user_raw, const char *delim,
auto myrow = pmyres.fetch_row();
if (path != nullptr)
gx_strlcpy(path, myrow[1], dsize);
unsigned int status = strtoul(myrow[0], nullptr, 0);
return status == AF_USER_NORMAL || status == AF_USER_SHAREDMBOX;
return afuser_store_canrecv(strtoul(myrow[0], nullptr, 0));
} catch (const std::exception &e) {
mlog(LV_ERR, "%s: %s", "E-1731", e.what());
return false;
Expand Down
47 changes: 42 additions & 5 deletions include/gromox/mysql_adaptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,28 @@

enum {
/* Reason codes (users.address_status) for forbidden login */
AF_USER_NORMAL = 0x00,
AF_USER_SUSPENDED = 0x01,
AF_USER_NORMAL = 0x00, // login pres recv
AF_USER_SUSPENDED = 0x01, // pres
AF_USER_DELETED = 0x03,
AF_USER_SHAREDMBOX = 0x04,
AF_USER_SHAREDMBOX = 0x04, // pres recv
AF_USER_CONTACT = 0x05,
AF_USER__MASK = 0x0F,

// historically: groups with AF_GROUP__MASK = 0xC0, with statuses NORMAL..DELETED
AF_DOMAIN_NORMAL = 0x00,
AF_DOMAIN_SUSPENDED = 0x10,
AF_DOMAIN_DELETED = 0x30,
AF_DOMAIN__MASK = 0x30,

/* note: users.address_status is a tinyint(4), so only 7 "usable" bits */
/*
* Note: users.address_status is a tinyint(4), which has a range of
* -127..128, so 7 bits are usable. Oddly enough, historically the high
* bits were also defined to be in use (but probably never were, due to
* the range limit):
*
* AF_GROUP__MASK = 0xC0,
*
* The (4) is the display width. 6 bits are currently in use.
*/
};

enum class mlist_type {
Expand Down Expand Up @@ -129,3 +137,32 @@ extern BOOL mysql_adaptor_get_mlist_memb(const char *username, const char *from,
extern bool mysql_adaptor_get_user_info(const char *username, char *maildir, size_t msize, char *lang, size_t lsize, char *timezone, size_t tsize);
extern void mysql_adaptor_encode_squote(const char *in, char *out);
extern gromox::errno_t mysql_adaptor_get_homeserver(const char *ent, bool is_pvt, std::pair<std::string, std::string> &);

/**
* Determines whether an arbitrary actor can generally open/read the primary
* store of a target user. (Further restrictions like ACLs not covered here.)
*
* @v: address_status of the target user
*/
static inline bool afuser_store_present(unsigned int st)
{
st &= AF_USER__MASK;
return st <= AF_USER_SUSPENDED || st == AF_USER_SHAREDMBOX;
}

/* Should usually be combined with afuser_store_present */
static inline bool afuser_store_canrecv(unsigned int st)
{
return st == AF_USER_NORMAL || st == AF_USER_SHAREDMBOX;
}

/**
* Determines whether an actor A is permitted to utilize the
* ropLogin/mapi_logon_zarafa functionality (on his own store).
*
* allowed := user value is exactly AF_USER_NORMAL &&
* domain is allowed (all bits of AF_DOMAIN__MASK are zero)
*
* Thus, the only permissible value is AF_USER_NORMAL.
*/
static inline bool afuser_login_allowed(unsigned int st) { return st == AF_USER_NORMAL; }
2 changes: 1 addition & 1 deletion tools/mkmidb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ int main(int argc, const char **argv) try
}

unsigned int address_status = strtoul(myrow[1], nullptr, 0);
if (address_status != AF_USER_NORMAL && address_status != AF_USER_SHAREDMBOX)
if (!afuser_store_present(address_status))
printf("Warning: Account status (0x%x) indicates this user object normally does not have a mailbox. Proceeding anyway for now...\n", address_status);
std::string dir = znul(myrow[2]);
myres.clear();
Expand Down
2 changes: 1 addition & 1 deletion tools/mkprivate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ int main(int argc, const char **argv) try
}

unsigned int address_status = strtoul(myrow[4], nullptr, 0);
if (address_status != AF_USER_NORMAL && address_status != AF_USER_SHAREDMBOX)
if (!afuser_store_present(address_status))
printf("Warning: Account status (0x%x) indicates this user object normally does not have a mailbox. Proceeding anyway for now...\n", address_status);

std::string dir = znul(myrow[1]), lang = znul(myrow[2]);
Expand Down

0 comments on commit 3ed03dc

Please sign in to comment.