Skip to content

Commit

Permalink
lib-smtp: client: Add support for recording extra (non-standard) capa…
Browse files Browse the repository at this point in the history
…bilities from server.
  • Loading branch information
stephanbosch committed Oct 29, 2018
1 parent 8d4a0e0 commit 55c07f5
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 0 deletions.
83 changes: 83 additions & 0 deletions src/lib-smtp/smtp-client-connection.c
Expand Up @@ -56,6 +56,33 @@ uoff_t smtp_client_connection_get_size_capability(
return conn->caps.size;
}

void smtp_client_connection_accept_extra_capability(
struct smtp_client_connection *conn, const char *cap_name)
{
cap_name = p_strdup(conn->pool, cap_name);

if (!array_is_created(&conn->extra_capabilities))
p_array_init(&conn->extra_capabilities, conn->pool, 8);
array_append(&conn->extra_capabilities, &cap_name, 1);
}

const struct smtp_capability_extra *
smtp_client_connection_get_extra_capability(struct smtp_client_connection *conn,
const char *name)
{
const struct smtp_capability_extra *cap;

if (!array_is_created(&conn->caps.extra))
return NULL;

array_foreach(&conn->caps.extra, cap) {
if (strcasecmp(cap->name, name) == 0)
return cap;
}

return NULL;
}

/*
* Logging
*/
Expand Down Expand Up @@ -872,6 +899,42 @@ smtp_client_connection_starttls(struct smtp_client_connection *conn)
return smtp_client_connection_init_xclient(conn);
}

static bool
smtp_client_connection_has_extra_capability(struct smtp_client_connection *conn,
const char *cap_name)
{
const char *const *cap_idx;

if (!array_is_created(&conn->extra_capabilities))
return FALSE;
array_foreach(&conn->extra_capabilities, cap_idx) {
if (strcasecmp(*cap_idx, cap_name) == 0)
return TRUE;
}
return FALSE;
}

static void
smtp_client_connection_record_exta_capability(
struct smtp_client_connection *conn, const char *cap_name,
const char *const *params)
{
struct smtp_capability_extra cap_extra;
pool_t pool = conn->cap_pool;

if (!smtp_client_connection_has_extra_capability(conn, cap_name))
return;

if (!array_is_created(&conn->caps.extra))
p_array_init(&conn->caps.extra, pool, 4);

i_zero(&cap_extra);
cap_extra.name = p_strdup(pool, cap_name);
cap_extra.params = p_strarray_dup(pool, params);

array_append(&conn->caps.extra, &cap_extra, 1);
}

static void
smtp_client_connection_handshake_cb(const struct smtp_reply *reply,
struct smtp_client_connection *conn)
Expand Down Expand Up @@ -949,6 +1012,10 @@ smtp_client_connection_handshake_cb(const struct smtp_reply *reply,
conn->caps.xclient_args =
p_strarray_dup(conn->cap_pool, params);
break;
case SMTP_CAPABILITY_NONE:
smtp_client_connection_record_exta_capability(
conn, cap_name, params);
break;
default:
break;
}
Expand Down Expand Up @@ -1769,6 +1836,10 @@ smtp_client_connection_do_create(struct smtp_client *client, const char *name,
conn->set.my_hostname = p_strdup(pool, set->my_hostname);

conn->set.forced_capabilities |= set->forced_capabilities;
if (set->extra_capabilities != NULL) {
conn->set.extra_capabilities =
p_strarray_dup(pool, set->extra_capabilities);
}

if (set->rawlog_dir != NULL && *set->rawlog_dir != '\0')
conn->set.rawlog_dir = p_strdup_empty(pool, set->rawlog_dir);
Expand Down Expand Up @@ -1823,6 +1894,18 @@ smtp_client_connection_do_create(struct smtp_client *client, const char *name,
conn->set.peer_trusted = set->peer_trusted;
}


if (set != NULL && set->extra_capabilities != NULL) {
const char *const *extp;

p_array_init(&conn->extra_capabilities, pool,
str_array_length(set->extra_capabilities) + 8);
for (extp = set->extra_capabilities; *extp != NULL; extp++) {
const char *ext = p_strdup(pool, *extp);
array_append(&conn->extra_capabilities, &ext, 1);
}
}

i_assert(conn->set.my_hostname != NULL &&
*conn->set.my_hostname != '\0');

Expand Down
6 changes: 6 additions & 0 deletions src/lib-smtp/smtp-client-connection.h
Expand Up @@ -73,6 +73,12 @@ enum smtp_capability
smtp_client_connection_get_capabilities(struct smtp_client_connection *conn);
uoff_t smtp_client_connection_get_size_capability(
struct smtp_client_connection *conn);
void smtp_client_connection_accept_extra_capability(
struct smtp_client_connection *conn, const char *cap_name);
const struct smtp_capability_extra *
smtp_client_connection_get_extra_capability(struct smtp_client_connection *conn,
const char *name);

enum smtp_client_connection_state
smtp_client_connection_get_state(struct smtp_client_connection *conn);

Expand Down
2 changes: 2 additions & 0 deletions src/lib-smtp/smtp-client-private.h
Expand Up @@ -152,10 +152,12 @@ struct smtp_client_connection {

struct smtp_client_settings set;
char *password;
ARRAY_TYPE(const_string) extra_capabilities;

pool_t cap_pool;
struct {
enum smtp_capability standard;
ARRAY(struct smtp_capability_extra) extra;
const char **auth_mechanisms;
const char **xclient_args;
uoff_t size;
Expand Down
4 changes: 4 additions & 0 deletions src/lib-smtp/smtp-client.c
Expand Up @@ -35,6 +35,10 @@ struct smtp_client *smtp_client_init(const struct smtp_client_settings *set)
client->set.my_hostname = p_strdup(pool, set->my_hostname);

client->set.forced_capabilities = set->forced_capabilities;
if (set->extra_capabilities != NULL) {
client->set.extra_capabilities =
p_strarray_dup(pool, set->extra_capabilities);
}

client->set.dns_client = set->dns_client;
client->set.dns_client_socket_path =
Expand Down
2 changes: 2 additions & 0 deletions src/lib-smtp/smtp-client.h
Expand Up @@ -45,6 +45,8 @@ struct smtp_client_settings {
/* Capabilities that are assumed to be enabled no matter whether the
server indicates support. */
enum smtp_capability forced_capabilities;
/* Record these extra capabilities if returned in the EHLO response */
const char *const *extra_capabilities;

struct dns_client *dns_client;
const char *dns_client_socket_path;
Expand Down
7 changes: 7 additions & 0 deletions src/lib-smtp/smtp-common.h
Expand Up @@ -47,10 +47,17 @@ enum smtp_capability {

SMTP_CAPABILITY__ORCPT = BIT(24),
};

struct smtp_capability_name {
const char *name;
enum smtp_capability capability;
};

struct smtp_capability_extra {
const char *name;
const char *const *params;
};

extern const struct smtp_capability_name smtp_capability_names[];

enum smtp_capability smtp_capability_find_by_name(const char *cap_name);
Expand Down

0 comments on commit 55c07f5

Please sign in to comment.