Attached the patch for Debian stable, please let me know if I should create an MR towards https://salsa.debian.org/gnome-team/evolution-ews/-/tree/debian/3.38.3-1
From b1ef96f7daee840c4695a3ffccb3ea843cbd8068 Mon Sep 17 00:00:00 2001 From: Roger Meier <r.me...@siemens.com> Date: Mon, 13 Sep 2021 16:32:02 +0200 Subject: [PATCH] Contacts: Retrieve user S/MIME certificate
see https://gitlab.gnome.org/GNOME/evolution-ews/-/issues/3 --- src/EWS/addressbook/e-book-backend-ews.c | 335 +++++++++++++++++++++-- src/EWS/addressbook/ews-oab-decoder.c | 54 +++- src/EWS/common/e-ews-connection.c | 8 +- src/EWS/common/e-ews-item.c | 65 +++++ src/EWS/common/e-ews-item.h | 5 + 5 files changed, 431 insertions(+), 36 deletions(-) diff --git a/src/EWS/addressbook/e-book-backend-ews.c b/src/EWS/addressbook/e-book-backend-ews.c index 197d49fd..9bf75100 100644 --- a/src/EWS/addressbook/e-book-backend-ews.c +++ b/src/EWS/addressbook/e-book-backend-ews.c @@ -60,6 +60,10 @@ #define X_EWS_CHANGEKEY "X-EWS-CHANGEKEY" #define X_EWS_GAL_SHA1 "X-EWS-GAL-SHA1" #define X_EWS_PHOTO_CHECK_DATE "X-EWS-PHOTO-CHECK-DATE" /* YYYYMMDD of the last check for photo */ +#define X_EWS_CERT_KIND "X-EWS-CERT-KIND" + +#define E_EWS_CERT_KIND_USER "UserSMIMECertificate" +#define E_EWS_CERT_KIND_MSEX "MSExchangeCertificate" #define EWS_MAX_FETCH_COUNT 500 @@ -69,7 +73,19 @@ /* passing field uris for PhysicalAddress, PhoneNumbers causes error, so we * use Default view to fetch them. Thus the summary props just have attachments * and some additional properties that are not return with Default view */ -#define CONTACT_ITEM_PROPS "item:Attachments item:HasAttachments item:Body item:LastModifiedTime contacts:Manager contacts:Department contacts:SpouseName contacts:AssistantName contacts:BusinessHomePage contacts:Birthday" +#define CONTACT_ITEM_PROPS "item:Attachments "\ + "item:HasAttachments "\ + "item:Body "\ + "item:LastModifiedTime "\ + "contacts:Manager "\ + "contacts:Department "\ + "contacts:SpouseName "\ + "contacts:AssistantName "\ + "contacts:BusinessHomePage "\ + "contacts:Birthday" +#define CONTACT_ITEM_PROPS_10SP2 CONTACT_ITEM_PROPS " "\ + "contacts:UserSMIMECertificate "\ + "contacts:MSExchangeCertificate" struct _EBookBackendEwsPrivate { GRecMutex cnc_lock; @@ -551,6 +567,238 @@ ebews_populate_photo (EBookBackendEws *bbews, e_contact_photo_free (photo); } +static void +ebews_populate_cert (EBookBackendEws *bbews, + EContact *contact, + EEwsItem *item, + const gchar *kind, + GCancellable *cancellable, + GError **error) +{ + EVCardAttribute *attr; + EContactCert cert; + + g_return_if_fail (g_str_equal (kind, E_EWS_CERT_KIND_USER) || g_str_equal (kind, E_EWS_CERT_KIND_MSEX)); + + /* Support for certificates was added in Exchange 2010 SP2. */ + if (!e_ews_connection_satisfies_server_version (bbews->priv->cnc, E_EWS_EXCHANGE_2010_SP2)) + return; + + if (g_str_equal (kind, E_EWS_CERT_KIND_USER)) + cert.data = (gchar *) e_ews_item_get_user_certificate (item, &cert.length); + else + cert.data = (gchar *) e_ews_item_get_msexchange_certificate (item, &cert.length); + + if (!cert.data || !cert.length) + return; + + attr = e_vcard_attribute_new (NULL, EVC_KEY); + + e_vcard_append_attribute (E_VCARD (contact), attr); + + e_vcard_attribute_add_param_with_value ( + attr, + e_vcard_attribute_param_new (EVC_TYPE), + "X509"); + + e_vcard_attribute_add_param_with_value ( + attr, + e_vcard_attribute_param_new (EVC_ENCODING), + "b"); + + e_vcard_attribute_add_param_with_value ( + attr, + e_vcard_attribute_param_new (X_EWS_CERT_KIND), + kind); + + e_vcard_attribute_add_value_decoded (attr, cert.data, cert.length); +} + +static void +ebews_populate_user_cert (EBookBackendEws *bbews, + EContact *contact, + EEwsItem *item, + GCancellable *cancellable, + GError **error) +{ + ebews_populate_cert (bbews, contact, item, E_EWS_CERT_KIND_USER, cancellable, error); +} + +static void +ebews_populate_msex_cert (EBookBackendEws *bbews, + EContact *contact, + EEwsItem *item, + GCancellable *cancellable, + GError **error) +{ + ebews_populate_cert (bbews, contact, item, E_EWS_CERT_KIND_MSEX, cancellable, error); +} + +static EVCardAttribute * +ebews_find_cert_attribute (EContact *contact, + const gchar *kind, + gint fallback_index) +{ + GList *link; + EVCardAttribute *fallback_attr = NULL; + + for (link = e_vcard_get_attributes (E_VCARD (contact)); link; link = g_list_next (link)) { + EVCardAttribute *attr = link->data; + const gchar *attr_name; + + attr_name = e_vcard_attribute_get_name (attr); + + if (attr_name && g_ascii_strcasecmp (attr_name, EVC_KEY) == 0) { + GList *values; + gboolean is_x509 = FALSE; + + for (values = e_vcard_attribute_get_param (attr, EVC_TYPE); values && !is_x509; values = g_list_next (values)) { + is_x509 = values->data && g_ascii_strcasecmp ((gchar *) values->data, "X509") == 0; + } + + if (!is_x509) + continue; + + if (!fallback_attr) { + if (!fallback_index) { + fallback_attr = attr; + fallback_index = -1; + } else if (fallback_index > 0) { + fallback_index--; + } + } + + for (values = e_vcard_attribute_get_param (attr, X_EWS_CERT_KIND); values; values = g_list_next (values)) { + if (values->data && g_ascii_strcasecmp ((gchar *) values->data, kind) == 0) + return attr; + } + } + } + + return fallback_attr; +} + +static const gchar * +ebews_find_cert_base64_data (EContact *contact, + const gchar *kind, + gint fallback_index) +{ + EVCardAttribute *attr; + GList *values; + const gchar *base64_data; + + attr = ebews_find_cert_attribute (contact, kind, fallback_index); + if (!attr) + return NULL; + + values = e_vcard_attribute_get_values (attr); + base64_data = values ? values->data : NULL; + + if (base64_data && *base64_data) + return base64_data; + + return NULL; +} + +static void +ebews_set_cert (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *contact, + const gchar *kind, + gint fallback_index) +{ + const gchar *base64_data; + + /* Support for certificates was added in Exchange 2010 SP2. */ + if (!e_ews_connection_satisfies_server_version (bbews->priv->cnc, E_EWS_EXCHANGE_2010_SP2)) + return; + + base64_data = ebews_find_cert_base64_data (contact, kind, fallback_index); + if (!base64_data) + return; + + e_soap_message_start_element (message, kind, NULL, NULL); + e_ews_message_write_string_parameter (message, "Base64Binary", NULL, base64_data); + e_soap_message_end_element (message); +} + +static void +ebews_set_user_cert (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *contact) +{ + ebews_set_cert (bbews, message, contact, E_EWS_CERT_KIND_USER, 0); +} + + +static void +ebews_set_msex_cert (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *contact) +{ + ebews_set_cert (bbews, message, contact, E_EWS_CERT_KIND_MSEX, 1); +} + +static void +ebews_set_cert_changes (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *new, + EContact *old, + const gchar *kind, + gint fallback_index) +{ + const gchar *new_base64_data, *old_base64_data; + + /* The first pass */ + if (!message) + return; + + /* Support for certificates was added in Exchange 2010 SP2. */ + if (!e_ews_connection_satisfies_server_version (bbews->priv->cnc, E_EWS_EXCHANGE_2010_SP2)) + return; + + /* Intentionally search by kind in the old contact, the new can have added cert, which would not have set the kind yet */ + new_base64_data = ebews_find_cert_base64_data (new, kind, fallback_index); + old_base64_data = ebews_find_cert_base64_data (old, kind, -1); + + if (g_strcmp0 (new_base64_data, old_base64_data) == 0) + return; + + if (new_base64_data) { + e_ews_message_start_set_item_field (message, kind, "contacts", "Contact"); + e_soap_message_start_element (message, kind, NULL, NULL); + e_ews_message_write_string_parameter (message, "Base64Binary", NULL, new_base64_data); + e_soap_message_end_element (message); + e_ews_message_end_set_item_field (message); + } else { + e_ews_message_add_delete_item_field (message, kind, "contacts"); + } +} + +static void +ebews_set_user_cert_changes (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *new, + EContact *old, + gchar **out_new_change_key, + GCancellable *cancellable, + GError **error) +{ + ebews_set_cert_changes (bbews, message, new, old, E_EWS_CERT_KIND_USER, 0); +} + +static void +ebews_set_msex_cert_changes (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *new, + EContact *old, + gchar **out_new_change_key, + GCancellable *cancellable, + GError **error) +{ + ebews_set_cert_changes (bbews, message, new, old, E_EWS_CERT_KIND_MSEX, 1); +} + static void set_phone_number (EContact *contact, EContactField field, @@ -716,15 +964,17 @@ ebews_populate_emails (EBookBackendEws *bbews, } static void -ebews_set_item_id (ESoapMessage *message, - EContact *contact) +ebews_set_item_id (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *contact) { } static void -ebews_set_full_name (ESoapMessage *msg, - EContact *contact) +ebews_set_full_name (EBookBackendEws *bbews, + ESoapMessage *msg, + EContact *contact) { EContactName *name; @@ -765,22 +1015,25 @@ ebews_set_date_value (ESoapMessage *message, } static void -ebews_set_birth_date (ESoapMessage *message, - EContact *contact) +ebews_set_birth_date (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *contact) { ebews_set_date_value (message, contact, E_CONTACT_BIRTH_DATE, "Birthday"); } static void -ebews_set_anniversary (ESoapMessage *message, - EContact *contact) +ebews_set_anniversary (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *contact) { ebews_set_date_value (message, contact, E_CONTACT_ANNIVERSARY, "WeddingAnniversary"); } static void -ebews_set_photo (ESoapMessage *message, - EContact *contact) +ebews_set_photo (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *contact) { } @@ -811,8 +1064,9 @@ add_entry (ESoapMessage *msg, } static void -ebews_set_phone_numbers (ESoapMessage *msg, - EContact *contact) +ebews_set_phone_numbers (EBookBackendEws *bbews, + ESoapMessage *msg, + EContact *contact) { gint i; const gchar *include_hdr = "PhoneNumbers"; @@ -858,8 +1112,9 @@ add_physical_address (ESoapMessage *msg, } static void -ebews_set_address (ESoapMessage *msg, - EContact *contact) +ebews_set_address (EBookBackendEws *bbews, + ESoapMessage *msg, + EContact *contact) { gboolean include_hdr = TRUE; @@ -875,15 +1130,17 @@ ebews_set_address (ESoapMessage *msg, } static void -ebews_set_ims (ESoapMessage *message, - EContact *contact) +ebews_set_ims (EBookBackendEws *bbews, + ESoapMessage *message, + EContact *contact) { } static void -ebews_set_notes (ESoapMessage *msg, - EContact *contact) +ebews_set_notes (EBookBackendEws *bbews, + ESoapMessage *msg, + EContact *contact) { gchar *notes = e_contact_get (contact, E_CONTACT_NOTE); if (!notes) @@ -895,8 +1152,9 @@ ebews_set_notes (ESoapMessage *msg, } static void -ebews_set_emails (ESoapMessage *msg, - EContact *contact) +ebews_set_emails (EBookBackendEws *bbews, + ESoapMessage *msg, + EContact *contact) { const gchar *include_hdr = "EmailAddresses"; @@ -1470,7 +1728,8 @@ ebews_populate_givenname (EBookBackendEws *bbews, } static void -ebews_set_givenname (ESoapMessage *message, +ebews_set_givenname (EBookBackendEws *bbews, + ESoapMessage *message, EContact *contact) { /* Does nothing, the "GivenName" is filled by the "FullName" code */ @@ -1507,7 +1766,7 @@ static const struct field_element_mapping { /* set function for simple string type values */ const gchar * (*get_simple_prop_func) (EEwsItem *item); void (*populate_contact_func)(EBookBackendEws *bbews, EContact *contact, EEwsItem *item, GCancellable *cancellable, GError **error); - void (*set_value_in_soap_message) (ESoapMessage *message, EContact *contact); + void (*set_value_in_soap_message) (EBookBackendEws *bbews, ESoapMessage *message, EContact *contact); void (*set_changes) (EBookBackendEws *bbews, ESoapMessage *message, EContact *new, EContact *old, gchar **out_new_change_key, GCancellable *cancellable, GError **error); } mappings[] = { @@ -1538,6 +1797,8 @@ static const struct field_element_mapping { { E_CONTACT_GIVEN_NAME, ELEMENT_TYPE_COMPLEX, "GivenName", NULL, ebews_populate_givenname, ebews_set_givenname, ebews_set_givenname_changes}, { E_CONTACT_ANNIVERSARY, ELEMENT_TYPE_COMPLEX, "WeddingAnniversary", NULL, ebews_populate_anniversary, ebews_set_anniversary, ebews_set_anniversary_changes }, { E_CONTACT_PHOTO, ELEMENT_TYPE_COMPLEX, "Photo", NULL, ebews_populate_photo, ebews_set_photo, ebews_set_photo_changes }, + { E_CONTACT_X509_CERT, ELEMENT_TYPE_COMPLEX, "UserSMIMECertificate", NULL, ebews_populate_user_cert, ebews_set_user_cert, ebews_set_user_cert_changes }, + { E_CONTACT_X509_CERT, ELEMENT_TYPE_COMPLEX, "MSExchangeCertificate", NULL, ebews_populate_msex_cert, ebews_set_msex_cert, ebews_set_msex_cert_changes }, /* Should take of uid and changekey (REV) */ { E_CONTACT_UID, ELEMENT_TYPE_COMPLEX, "ItemId", NULL, ebews_populate_uid, ebews_set_item_id}, @@ -1578,12 +1839,19 @@ ebb_ews_write_dl_members (ESoapMessage *msg, e_soap_message_end_element (msg); /* Members */ } +typedef struct _CreateItemsData +{ + EBookBackendEws *bbews; + EContact *contact; +} CreateItemsData; + static gboolean ebb_ews_convert_dl_to_xml_cb (ESoapMessage *msg, gpointer user_data, GError **error) { - EContact *contact = user_data; + CreateItemsData *cid = user_data; + EContact *contact = cid->contact; EVCardAttribute *attribute; GList *values; @@ -1606,7 +1874,8 @@ ebb_ews_convert_contact_to_xml_cb (ESoapMessage *msg, gpointer user_data, GError **error) { - EContact *contact = user_data; + CreateItemsData *cid = user_data; + EContact *contact = cid->contact; gint i, element_type; /* Prepare Contact node in the SOAP message */ @@ -1627,7 +1896,7 @@ ebb_ews_convert_contact_to_xml_cb (ESoapMessage *msg, e_ews_message_write_string_parameter (msg, mappings[i].element_name, NULL, val); g_free (val); } else - mappings[i].set_value_in_soap_message (msg, contact); + mappings[i].set_value_in_soap_message (cid->bbews, msg, contact); } /* end of "Contact" */ @@ -2032,7 +2301,11 @@ ebb_ews_fetch_items_sync (EBookBackendEws *bbews, if (contact_item_ids) { EEwsAdditionalProps *add_props; add_props = e_ews_additional_props_new (); - add_props->field_uri = g_strdup (CONTACT_ITEM_PROPS); + + if (e_ews_connection_satisfies_server_version (bbews->priv->cnc, E_EWS_EXCHANGE_2010_SP2)) + add_props->field_uri = g_strdup (CONTACT_ITEM_PROPS_10SP2); + else + add_props->field_uri = g_strdup (CONTACT_ITEM_PROPS); ret = e_ews_connection_get_items_sync ( bbews->priv->cnc, EWS_PRIORITY_MEDIUM, @@ -3730,8 +4003,13 @@ ebb_ews_save_contact_sync (EBookMetaBackend *meta_backend, g_clear_object (&old_contact); g_clear_object (&book_cache); } else { + CreateItemsData cid; + + cid.bbews = bbews; + cid.contact = contact; + success = e_ews_connection_create_items_sync (bbews->priv->cnc, EWS_PRIORITY_MEDIUM, NULL, NULL, - fid, is_dl ? ebb_ews_convert_dl_to_xml_cb : ebb_ews_convert_contact_to_xml_cb, contact, + fid, is_dl ? ebb_ews_convert_dl_to_xml_cb : ebb_ews_convert_contact_to_xml_cb, &cid, &items, cancellable, error); } @@ -3970,6 +4248,7 @@ ebb_ews_get_backend_property (EBookBackend *book_backend, e_contact_field_name (E_CONTACT_BIRTH_DATE), e_contact_field_name (E_CONTACT_NOTE), e_contact_field_name (E_CONTACT_PHOTO), + e_contact_field_name (E_CONTACT_X509_CERT), NULL); g_string_free (buffer, TRUE); diff --git a/src/EWS/addressbook/ews-oab-decoder.c b/src/EWS/addressbook/ews-oab-decoder.c index cc734019..3374440d 100644 --- a/src/EWS/addressbook/ews-oab-decoder.c +++ b/src/EWS/addressbook/ews-oab-decoder.c @@ -140,21 +140,61 @@ ews_populate_string_list (EContact *contact, } static void -ews_populate_cert (EContact *contact, - EContactField field, - gpointer value, - gpointer user_data) +ews_populate_cert_data (EContact *contact, + GBytes *bytes) { - GSList *list = value; - GBytes *bytes = list->data; EContactCert cert; + if (!bytes || !g_bytes_get_size (bytes)) + return; + cert.data = (gpointer) g_bytes_get_data (bytes, &cert.length); cert.length = g_bytes_get_size (bytes); e_contact_set (contact, E_CONTACT_X509_CERT, &cert); } +static void +ews_populate_cert (EContact *contact, + EContactField field, + gpointer value, + gpointer user_data) +{ + GSList *link; + + for (link = value; link; link = g_slist_next (link)) { + GBytes *bytes = link->data; + + ews_populate_cert_data (contact, bytes); + } +} + +static void +ews_populate_user_cert (EContact *contact, + EContactField field, + gpointer value, + gpointer user_data) +{ + GBytes *bytes = value; + + ews_populate_cert_data (contact, bytes); +} + +static void +ews_populate_user_x509_cert (EContact *contact, + EContactField field, + gpointer value, + gpointer user_data) +{ + GSList *link; + + for (link = value; link; link = g_slist_next (link)) { + GBytes *bytes = link->data; + + ews_populate_cert_data (contact, bytes); + } +} + static void ews_populate_photo (EContact *contact, EContactField field, @@ -243,6 +283,8 @@ static const struct prop_field_mapping { {EWS_PT_THUMBNAIL_PHOTO, E_CONTACT_PHOTO, ews_populate_photo}, {EWS_PT_OFFICE_LOCATION, E_CONTACT_OFFICE, ews_populate_simple_string}, {EWS_PT_X509_CERT, E_CONTACT_X509_CERT, ews_populate_cert}, + {EWS_PT_USER_CERTIFICATE, E_CONTACT_X509_CERT, ews_populate_user_cert}, + {EWS_PT_USER_X509_CERTIFICATE, E_CONTACT_X509_CERT, ews_populate_user_x509_cert}, {EWS_PT_SEND_RICH_INFO, E_CONTACT_WANTS_HTML, ews_populate_simple_string}, }; diff --git a/src/EWS/common/e-ews-connection.c b/src/EWS/common/e-ews-connection.c index 1d318068..933d9237 100644 --- a/src/EWS/common/e-ews-connection.c +++ b/src/EWS/common/e-ews-connection.c @@ -6268,10 +6268,14 @@ e_ews_connection_resolve_names (EEwsConnection *cnc, e_soap_message_add_attribute (msg, "SearchScope", get_search_scope_str (scope), NULL, NULL); - if (fetch_contact_data) + if (fetch_contact_data) { e_soap_message_add_attribute (msg, "ReturnFullContactData", "true", NULL, NULL); - else + + if (e_ews_connection_satisfies_server_version (cnc, E_EWS_EXCHANGE_2010_SP2)) + e_soap_message_add_attribute (msg, "ContactDataShape", "AllProperties", NULL, NULL); + } else { e_soap_message_add_attribute (msg, "ReturnFullContactData", "false", NULL, NULL); + } if (parent_folder_ids) { e_soap_message_start_element (msg, "ParentFolderIds", "messages", NULL); diff --git a/src/EWS/common/e-ews-item.c b/src/EWS/common/e-ews-item.c index 73a82fd4..ce8fa4d3 100644 --- a/src/EWS/common/e-ews-item.c +++ b/src/EWS/common/e-ews-item.c @@ -52,6 +52,12 @@ struct _EEwsContactFields { gchar *givenname; gchar *middlename; gchar *notes; + + gsize msexchange_cert_len; + guchar *msexchange_cert; + + gsize user_cert_len; + guchar *user_cert; }; struct _EEwsTaskFields { @@ -337,6 +343,8 @@ ews_free_contact_fields (struct _EEwsContactFields *con_fields) g_free (con_fields->givenname); g_free (con_fields->middlename); g_free (con_fields->notes); + g_free (con_fields->msexchange_cert); + g_free (con_fields->user_cert); g_free (con_fields); } } @@ -827,6 +835,37 @@ parse_contact_field (EEwsItem *item, * with old servers (< 2010_SP2) we prefer use item:Body. */ priv->contact_fields->notes = e_soap_parameter_get_string_value (subparam); + } else if (!g_ascii_strcasecmp (name, "UserSMIMECertificate") || + !g_ascii_strcasecmp (name, "MSExchangeCertificate")) { + ESoapParameter *data_param; + guchar **out_bytes; + gsize *out_len; + + if (!g_ascii_strcasecmp (name, "UserSMIMECertificate")) { + out_bytes = &priv->contact_fields->user_cert; + out_len = &priv->contact_fields->user_cert_len; + } else { + out_bytes = &priv->contact_fields->msexchange_cert; + out_len = &priv->contact_fields->msexchange_cert_len; + } + + data_param = e_soap_parameter_get_first_child_by_name (subparam, "Base64Binary"); + if (data_param) { + gchar *base64_data; + + base64_data = e_soap_parameter_get_string_value (data_param); + if (base64_data && *base64_data) { + *out_bytes = g_base64_decode_inplace (base64_data, out_len); + if (!*out_len) { + g_free (*out_bytes); + + *out_len = 0; + *out_bytes = NULL; + } + } else { + g_free (base64_data); + } + } } } @@ -2698,6 +2737,32 @@ e_ews_item_get_notes (EEwsItem *item) return item->priv->contact_fields->notes; } +const guchar * +e_ews_item_get_user_certificate (EEwsItem *item, + gsize *out_len) +{ + g_return_val_if_fail (E_IS_EWS_ITEM (item), NULL); + g_return_val_if_fail (item->priv->contact_fields != NULL, NULL); + g_return_val_if_fail (out_len != NULL, NULL); + + *out_len = item->priv->contact_fields->user_cert_len; + + return item->priv->contact_fields->user_cert; +} + +const guchar * +e_ews_item_get_msexchange_certificate (EEwsItem *item, + gsize *out_len) +{ + g_return_val_if_fail (E_IS_EWS_ITEM (item), NULL); + g_return_val_if_fail (item->priv->contact_fields != NULL, NULL); + g_return_val_if_fail (out_len != NULL, NULL); + + *out_len = item->priv->contact_fields->msexchange_cert_len; + + return item->priv->contact_fields->msexchange_cert; +} + time_t e_ews_item_get_birthday (EEwsItem *item) { diff --git a/src/EWS/common/e-ews-item.h b/src/EWS/common/e-ews-item.h index fde46528..8a0dbbf5 100644 --- a/src/EWS/common/e-ews-item.h +++ b/src/EWS/common/e-ews-item.h @@ -419,6 +419,11 @@ const gchar * e_ews_item_get_surname (EEwsItem *item); const gchar * e_ews_item_get_givenname (EEwsItem *item); const gchar * e_ews_item_get_middlename (EEwsItem *item); const gchar * e_ews_item_get_notes (EEwsItem *item); +const guchar * e_ews_item_get_user_certificate (EEwsItem *item, + gsize *out_len); +const guchar * e_ews_item_get_msexchange_certificate + (EEwsItem *item, + gsize *out_len); /*Task fields*/ const gchar * e_ews_item_get_status (EEwsItem *item); -- 2.25.1