Add support for EcDoRpc GetAddressTypes (0x49) and OptionsData (0x6f) to server.
authorBrad Hards <bradh@openchange.org>
Sat, 1 May 2010 02:46:07 +0000 (02:46 +0000)
committerBrad Hards <bradh@openchange.org>
Sat, 1 May 2010 02:46:07 +0000 (02:46 +0000)
This is completely driven by the server provisioning - no hard coding.

This makes a binary incompatible change, so if you get crashes, please try a
clean rebuild.

Makefile
mapiproxy/libmapiserver/libmapiserver.h
mapiproxy/libmapiserver/libmapiserver_oxomsg.c [new file with mode: 0644]
mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.c
mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.h
mapiproxy/servers/default/emsmdb/oxomsg.c [new file with mode: 0644]

index ce0aabaf171fc9e2a853db65638a9fad0dd0db16..1e9eb61b55972f9cebd557598e319e24bb26fbef 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -917,7 +917,8 @@ mapiproxy/libmapiserver.$(SHLIBEXT).$(PACKAGE_VERSION):     mapiproxy/libmapiserver/
                                                        mapiproxy/libmapiserver/libmapiserver_oxctabl.po        \
                                                        mapiproxy/libmapiserver/libmapiserver_oxcmsg.po         \
                                                        mapiproxy/libmapiserver/libmapiserver_oxcnotif.po       \
-                                                       mapiproxy/libmapiserver/libmapiserver_oxorule.po         \
+                                                       mapiproxy/libmapiserver/libmapiserver_oxomsg.po         \
+                                                       mapiproxy/libmapiserver/libmapiserver_oxorule.po        \
                                                        ndr_mapi.po                             \
                                                        gen_ndr/ndr_exchange.po
        @$(CC) -o $@ $(DSOOPT) -Wl,-soname,libmapiserver.$(SHLIBEXT).$(LIBMAPIPROXY_SO_VERSION) $^ $(LIBS)
@@ -1127,6 +1128,7 @@ mapiproxy/servers/exchange_emsmdb.$(SHLIBEXT):    mapiproxy/servers/default/emsmdb/
                                                mapiproxy/servers/default/emsmdb/oxctabl.po                     \
                                                mapiproxy/servers/default/emsmdb/oxcmsg.po                      \
                                                mapiproxy/servers/default/emsmdb/oxcnotif.po                    \
+                                               mapiproxy/servers/default/emsmdb/oxomsg.po                      \
                                                mapiproxy/servers/default/emsmdb/oxorule.po                     
        @echo "Linking $@"
        @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION) \
index 3f2334a57ff7f78fe5e6b4c0b13bfb19feacdd7e..628e6372af865706afd5afa46ac3521421415bf3 100644 (file)
  */
 #define        SIZE_DFLT_ROPGETRECEIVEFOLDER           8
 
+/**
+   \details GetAddressTypes has fixed response size for:
+   -# cValues: uint16_t
+   -# size: uint16_t
+ */
+#define        SIZE_DFLT_ROPGETADDRESSTYPES            4
+
+/**
+   \details OptionsData has fixed response size for:
+   -# Reserved: uint8_t
+   -# OptionsInfo: uint16_t part of SBinary_short
+   -# HelpFileSize: uint16_t
+ */
+#define        SIZE_DFLT_ROPOPTIONSDATA                5
+
 /**
    \details FindRow has fixed response size for:
    -# RowNoLongerVisible: uint8_t
@@ -211,6 +226,10 @@ uint16_t libmapiserver_RopQueryPosition_size(struct EcDoRpc_MAPI_REPL *);
 uint16_t libmapiserver_RopSeekRow_size(struct EcDoRpc_MAPI_REPL *);
 uint16_t libmapiserver_RopFindRow_size(struct EcDoRpc_MAPI_REPL *);
 
+/* definitions from libmapiserver_oxomsg.c */
+uint16_t libmapiserver_RopGetAddressTypes_size(struct EcDoRpc_MAPI_REPL *);
+uint16_t libmapiserver_RopOptionsData_size(struct EcDoRpc_MAPI_REPL *);
+
 /* definitions from libmapiserver_oxorule.c */
 uint16_t libmapiserver_RopGetRulesTable_size(void);
 
diff --git a/mapiproxy/libmapiserver/libmapiserver_oxomsg.c b/mapiproxy/libmapiserver/libmapiserver_oxomsg.c
new file mode 100644 (file)
index 0000000..70e45b8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+   libmapiserver - MAPI library for Server side
+
+   OpenChange Project
+
+   Copyright (C) Brad Hards 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+   \file libmapiserver_oxomsg.c
+
+   \brief OXOMSG Rops
+ */
+
+#include "libmapiserver.h"
+
+#include <string.h>
+
+/**
+   \details Calculate GetAddressTypes (0x49) Rop size
+
+   \param response pointer to the GetAddressTypes EcDoRpc_MAPI_REPL structure
+
+   \return Size of GetAddressTypes response
+ */
+_PUBLIC_ uint16_t libmapiserver_RopGetAddressTypes_size(struct EcDoRpc_MAPI_REPL *response)
+{
+       uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
+
+       if (!response || response->error_code) {
+               return size;
+       }
+
+       size += SIZE_DFLT_ROPGETADDRESSTYPES;
+       /* The length of the strings is variable, but given by the size parameter */
+       size += response->u.mapi_AddressTypes.size;
+
+       return size;
+}
+
+/**
+   \details Calculate OptionsData (0x6f) Rop size
+
+   \param response pointer to the OptionsData EcDoRpc_MAPI_REPL structure
+
+   \return Size of OptionsData response
+ */
+_PUBLIC_ uint16_t libmapiserver_RopOptionsData_size(struct EcDoRpc_MAPI_REPL *response)
+{
+       uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
+
+       if (!response || response->error_code) {
+               return size;
+       }
+
+       size += SIZE_DFLT_ROPOPTIONSDATA;
+       size += response->u.mapi_OptionsData.OptionsInfo.cb;
+       size += response->u.mapi_OptionsData.HelpFileSize;
+       if (response->u.mapi_OptionsData.HelpFileSize != 0) {
+               size += strlen(response->u.mapi_OptionsData.HelpFileName.HelpFileName) + 1;
+       }
+
+       return size;
+}
index 9bcf2dbf931da59788792b03ef346d47226b66f1..7515e89875f6ad8c915d6f267be3c0c687e7740f 100644 (file)
@@ -108,6 +108,7 @@ static enum MAPISTATUS dcesrv_EcDoConnect(struct dcesrv_call_state *dce_call,
        }
 
        emsmdbp_ctx->szUserDN = talloc_strdup(emsmdbp_ctx, r->in.szUserDN);
+       emsmdbp_ctx->userLanguage = r->in.ulLcidString;
 
        /* Step 4. Retrieve the display name of the user */
        r->out.szDisplayName = ldb_msg_find_attr_as_string(msg, "displayName", NULL);
@@ -386,6 +387,18 @@ static enum MAPISTATUS dcesrv_EcDoRpc(struct dcesrv_call_state *dce_call,
                                                                    &(mapi_response->mapi_repl[idx]),
                                                                    mapi_response->handles, &size);
                        break;
+               case op_MAPI_AddressTypes:
+                       retval = EcDoRpc_RopGetAddressTypes(mem_ctx, emsmdbp_ctx,
+                                                           &(mapi_request->mapi_req[i]),
+                                                           &(mapi_response->mapi_repl[idx]),
+                                                           mapi_response->handles, &size);
+                       break;
+               case op_MAPI_OptionsData:
+                       retval = EcDoRpc_RopOptionsData(mem_ctx, emsmdbp_ctx,
+                                                       &(mapi_request->mapi_req[i]),
+                                                       &(mapi_response->mapi_repl[idx]),
+                                                       mapi_response->handles, &size);
+                       break;
                case op_MAPI_Logon:
                        retval = EcDoRpc_RopLogon(mem_ctx, emsmdbp_ctx,
                                                  &(mapi_request->mapi_req[i]),
index 8a085777de18aa27198dcbb692ac338ce6e320f8..4f5a4ab16f7ae848364cc75a999be6268f9f2097 100644 (file)
@@ -44,6 +44,7 @@
 struct emsmdbp_context {
        char                            *szUserDN;
        char                            *szDisplayName;
+       uint32_t                        userLanguage;
        struct loadparm_context         *lp_ctx;
        void                            *oc_ctx;
        struct ldb_context              *samdb_ctx;
@@ -174,6 +175,10 @@ enum MAPISTATUS EcDoRpc_RopQueryPosition(TALLOC_CTX *, struct emsmdbp_context *,
 enum MAPISTATUS EcDoRpc_RopSeekRow(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
 enum MAPISTATUS EcDoRpc_RopFindRow(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
 
+/* definition from oxomsg.c */
+enum MAPISTATUS        EcDoRpc_RopGetAddressTypes(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
+enum MAPISTATUS        EcDoRpc_RopOptionsData(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
+
 /* definitions from oxorule.c */
 enum MAPISTATUS EcDoRpc_RopGetRulesTable(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
 
diff --git a/mapiproxy/servers/default/emsmdb/oxomsg.c b/mapiproxy/servers/default/emsmdb/oxomsg.c
new file mode 100644 (file)
index 0000000..dccdbec
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+   OpenChange Server implementation
+
+   EMSMDBP: EMSMDB Provider implementation
+
+   Copyright (C) Brad Hards <bradh@openchange.org> 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+   \file oxomsg.c
+
+   \brief Server-side message routines and Rops
+ */
+
+#include "mapiproxy/libmapiserver/libmapiserver.h"
+#include "dcesrv_exchange_emsmdb.h"
+
+/* Get the organisation name (like "First Organization") as a DN. */
+static bool mapiserver_get_org_dn(struct emsmdbp_context *emsmdbp_ctx,
+                                           struct ldb_dn **basedn)
+{
+       int                     ret;
+       struct ldb_result       *res = NULL;
+
+       ret = ldb_search(emsmdbp_ctx->samdb_ctx, emsmdbp_ctx, &res,
+                        ldb_get_config_basedn(emsmdbp_ctx->samdb_ctx),
+                         LDB_SCOPE_SUBTREE, NULL,
+                        "(|(objectClass=msExchOrganizationContainer))");
+
+       /* If the search failed */
+        if (ret != LDB_SUCCESS) {
+               DEBUG(1, ("exchange_emsmdb: [OXOMSG] mapiserver_get_org_dn ldb_search failure.\n"));
+               return false;
+        }
+        /* If we didn't get the expected entry */
+       if (res->count != 1) {
+               DEBUG(1, ("exchange_emsmdb: [OXOMSG] mapiserver_get_org_dn unexpected entry count: %i (expected 1).\n", res->count));
+               return false;
+       }
+       
+       *basedn = ldb_dn_new(emsmdbp_ctx, emsmdbp_ctx->samdb_ctx,
+                            ldb_msg_find_attr_as_string(res->msgs[0], "distinguishedName", NULL));
+       return true;
+}
+/**
+   \details EcDoRpc GetAddressTypes (0x49) Rop. This operation gets
+   the valid address types (e.g. "SMTP", "X400", "EX")
+
+   \param mem_ctx pointer to the memory context
+   \param emsmdbp_ctx pointer to the emsmdb provider context
+   \param mapi_req pointer to the AddressTypes EcDoRpc_MAPI_REQ
+   \param mapi_repl pointer to the AddressTypes EcDoRpc_MAPI_REPL
+   \param handles pointer to the MAPI handles array
+   \param size pointer to the mapi_response size to update
+
+   \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS EcDoRpc_RopGetAddressTypes(TALLOC_CTX *mem_ctx,
+                                                   struct emsmdbp_context *emsmdbp_ctx,
+                                                   struct EcDoRpc_MAPI_REQ *mapi_req,
+                                                   struct EcDoRpc_MAPI_REPL *mapi_repl,
+                                                   uint32_t *handles, uint16_t *size)
+{
+       enum MAPISTATUS         retval = MAPI_E_SUCCESS;
+       int                     ret;
+       struct ldb_result       *res = NULL;
+       const char * const      attrs[] = { "msExchTemplateRDNs", NULL };
+        uint32_t                j;
+       struct ldb_dn           *basedn = 0;
+       
+       DEBUG(4, ("exchange_emsmdb: [OXOMSG] AddressTypes (0x49)\n"));
+
+       /* Sanity checks */
+       OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+       OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
+       OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
+       OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
+       OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
+
+       mapiserver_get_org_dn(emsmdbp_ctx, &basedn);
+       ldb_dn_add_child_fmt(basedn, "CN=ADDRESSING");
+       ldb_dn_add_child_fmt(basedn, "CN=ADDRESS-TEMPLATES");
+
+       ret = ldb_search(emsmdbp_ctx->samdb_ctx, emsmdbp_ctx, &res, basedn,
+                         LDB_SCOPE_SUBTREE, attrs, "CN=%x", emsmdbp_ctx->userLanguage);
+        /* If the search failed */
+        if (ret != LDB_SUCCESS) {
+               DEBUG(1, ("exchange_emsmdb: [OXOMSG] AddressTypes ldb_search failure.\n"));
+               return MAPI_E_CORRUPT_STORE;
+        }
+        /* If we didn't get the expected entry */
+       if (res->count != 1) {
+               DEBUG(1, ("exchange_emsmdb: [OXOMSG] AddressTypes unexpected entry count: %i (expected 1).\n", res->count));
+               return MAPI_E_CORRUPT_STORE;
+       }
+       /* If we didn't get the expected number of elements in our record */
+       if (res->msgs[0]->num_elements != 1) {
+               DEBUG(1, ("exchange_emsmdb: [OXOMSG] AddressTypes unexpected element count: %i (expected 1).\n", res->msgs[0]->num_elements));
+               return MAPI_E_CORRUPT_STORE;
+       }
+       /* If we didn't get at least one address type, things are probably bad. It _could_ be allowable though. */
+       if (res->msgs[0]->elements[0].num_values < 1) {
+               DEBUG(1, ("exchange_emsmdb: [OXOMSG] AddressTypes unexpected values count: %i (expected 1).\n", res->msgs[0]->num_elements));
+       }
+
+       /* If we got to here, it looks sane. Build the reply message. */
+       mapi_repl->opnum = mapi_req->opnum;
+       mapi_repl->handle_idx = mapi_req->handle_idx;
+       mapi_repl->error_code = retval;
+       mapi_repl->u.mapi_AddressTypes.cValues = res->msgs[0]->elements[0].num_values;
+       mapi_repl->u.mapi_AddressTypes.size = 0;
+       mapi_repl->u.mapi_AddressTypes.transport = talloc_array(mem_ctx, struct mapi_LPSTR, mapi_repl->u.mapi_AddressTypes.cValues);
+       for (j = 0; j < mapi_repl->u.mapi_AddressTypes.cValues; ++j) {
+               const char *addr_type;
+               addr_type = (const char *)res->msgs[0]->elements[0].values[j].data;
+               mapi_repl->u.mapi_AddressTypes.transport[j].lppszA = talloc_asprintf(mem_ctx, "%s", addr_type);
+               mapi_repl->u.mapi_AddressTypes.size += (strlen(mapi_repl->u.mapi_AddressTypes.transport[j].lppszA) + 1);
+       }
+       *size = libmapiserver_RopGetAddressTypes_size(mapi_repl);
+
+       handles[mapi_repl->handle_idx] = handles[mapi_req->handle_idx];
+
+       return retval;
+}
+
+
+/**
+   \details EcDoRpc OptionsData (0x6f) Rop. This doesn't really do anything,
+   but could be used to provide HelpData if we wanted to do something like that
+   later.
+
+   \param mem_ctx pointer to the memory context
+   \param emsmdbp_ctx pointer to the emsmdb provider context
+   \param mapi_req pointer to the OptionsData EcDoRpc_MAPI_REQ
+   \param mapi_repl pointer to the OptionsData EcDoRpc_MAPI_REPL
+   \param handles pointer to the MAPI handles array
+   \param size pointer to the mapi_response size to update
+
+   \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS EcDoRpc_RopOptionsData(TALLOC_CTX *mem_ctx,
+                                               struct emsmdbp_context *emsmdbp_ctx,
+                                               struct EcDoRpc_MAPI_REQ *mapi_req,
+                                               struct EcDoRpc_MAPI_REPL *mapi_repl,
+                                               uint32_t *handles, uint16_t *size)
+{
+       enum MAPISTATUS         retval = MAPI_E_SUCCESS;
+
+       DEBUG(4, ("exchange_emsmdb: [OXOMSG] OptionsData (0x6f)\n"));
+
+       /* Sanity checks */
+       OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+       OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
+       OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
+       OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
+       OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
+       
+       mapi_repl->opnum = mapi_req->opnum;
+       mapi_repl->handle_idx = mapi_req->handle_idx;
+       mapi_repl->error_code = retval;
+       mapi_repl->u.mapi_OptionsData.Reserved = 0x00;
+       mapi_repl->u.mapi_OptionsData.OptionsInfo.cb = 0x0000;
+       mapi_repl->u.mapi_OptionsData.OptionsInfo.lpb = talloc_array(mem_ctx, uint8_t, mapi_repl->u.mapi_OptionsData.OptionsInfo.cb);
+       mapi_repl->u.mapi_OptionsData.HelpFileSize = 0x0000;
+       mapi_repl->u.mapi_OptionsData.HelpFile = talloc_array(mem_ctx, uint8_t, mapi_repl->u.mapi_OptionsData.HelpFileSize);
+
+       *size = libmapiserver_RopOptionsData_size(mapi_repl);
+
+       handles[mapi_repl->handle_idx] = handles[mapi_req->handle_idx];
+
+       return retval;
+}
+