6 Copyright (C) Julien Kerihuel 2008
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "mapiproxy/dcesrv_mapiproxy.h"
23 #include "mapiproxy/dcesrv_mapiproxy_proto.h"
26 \file dcesrv_mapiproxy_nspi.c
28 \brief NSPI hook functions
32 \details Retrieve the servername from a DN string
34 \param dn the DN string
36 \return a talloc'd server name
38 static char *x500_get_servername(const char *dn)
47 pdn = strcasestr(dn, SERVERNAME);
48 if (pdn == NULL) return NULL;
50 pdn += strlen(SERVERNAME);
51 servername = strsep(&pdn, "/");
53 return (talloc_strdup(NULL, servername));
58 \details This function replaces network address from the binding
59 strings returned by Exchange for the PR_EMS_AB_NETWORK_ADDRESS
60 property and limit the binding strings scope to ncacn_ip_tcp.
62 \param dce_call pointer to the session context
63 \param r pointer to the NspiGetProps structure
65 \return true on success, otherwise false
67 bool mapiproxy_NspiGetProps(struct dcesrv_call_state *dce_call, struct NspiGetProps *r)
71 struct SPropTagArray *SPropTagArray = NULL;
73 struct StringArray_r *slpstr;
74 struct SPropValue *lpProp;
77 if (!r->out.ppRows) return false;
78 if (!(*r->out.ppRows)->cValues) return false;
80 /* Step 1. Find PR_EMS_AB_NETWORK_ADDRESS index */
82 SPropTagArray = r->in.pPropTags;
83 for (i = 0; i < SPropTagArray->cValues; i++) {
84 if (SPropTagArray->aulPropTag[i] == PR_EMS_AB_NETWORK_ADDRESS) {
89 if (propID == -1) return false;
91 /* Step 2. Retrieve the SLPSTRArray */
92 SRow = *r->out.ppRows;
93 lpProp = &SRow->lpProps[propID];
95 if (!lpProp) return false;
96 if (lpProp->ulPropTag != PR_EMS_AB_NETWORK_ADDRESS) return false;
98 slpstr = &(lpProp->value.MVszA);
100 /* Step 3. Modify Exchange binding strings and only return ncacn_ip_tcp */
102 slpstr->lppszA[0] = talloc_asprintf(dce_call, "ncacn_ip_tcp:%s.%s",
103 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx),
104 lpcfg_realm(dce_call->conn->dce_ctx->lp_ctx));
105 slpstr->lppszA[0] = strlower_talloc(dce_call, slpstr->lppszA[0]);
112 \details This function replaces the Exchange server name with
113 mapiproxy netbios name for the PR_EMS_AB_HOME_MDB property and
114 saves the original name in a global variable for further usage -
115 such as mapiproxy_NspiDNToMId.
117 \param dce_call pointer to the session context
118 \param r pointer to the NspiQueryRows structure
120 \sa mapiproxy_NspiDNToMId
122 bool mapiproxy_NspiQueryRows(struct dcesrv_call_state *dce_call, struct NspiQueryRows *r)
124 struct dcesrv_mapiproxy_private *private;
126 uint32_t propID = -1;
127 struct SPropTagArray *SPropTagArray = NULL;
128 struct SRowSet *SRowSet;
129 struct SPropValue *lpProp;
133 private = dce_call->context->private_data;
136 if (!r->out.ppRows) return false;
137 if (!(*r->out.ppRows)->cRows) return false;
138 if (!r->in.pPropTags) return false;
140 /* Step 1. Find PR_EMS_AB_HOME_MDB index */
142 SPropTagArray = r->in.pPropTags;
143 for (i = 0; i < SPropTagArray->cValues; i++) {
144 if (SPropTagArray->aulPropTag[i] == PR_EMS_AB_HOME_MDB) {
149 if (propID == -1) return false;
151 /* Retrieve the lpszA */
152 SRowSet = *r->out.ppRows;
153 lpProp = &(SRowSet->aRow->lpProps[propID]);
155 if (!lpProp) return false;
156 if (lpProp->ulPropTag != PR_EMS_AB_HOME_MDB) return false;
158 if (private->exchname) {
159 if (strstr(lpProp->value.lpszA, private->exchname)) {
160 lpProp->value.lpszA = string_sub_talloc((TALLOC_CTX *) dce_call, lpProp->value.lpszA, private->exchname,
161 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
164 lpszA = talloc_strdup(dce_call, lpProp->value.lpszA);
165 if ((exchname = x500_get_servername(lpszA))) {
166 private->exchname = talloc_strdup(NULL, exchname);
167 lpProp->value.lpszA = string_sub_talloc((TALLOC_CTX *) dce_call, lpProp->value.lpszA, exchname,
168 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
169 talloc_free(exchname);
179 \details This function looks if the server DN string in the request
180 holds the mapiproxy netbios name and replaces it with the original
181 Exchange server one fetched from NspiQueryRows or NspiGetProps.
183 \param dce_call pointer to the session context
184 \param r pointer to the NspiDNToMId structure
186 \return true on success or false if no occurrence of the mapiproxy
187 netbios name was found.
189 bool mapiproxy_NspiDNToMId(struct dcesrv_call_state *dce_call, struct NspiDNToMId *r)
191 struct dcesrv_mapiproxy_private *private;
192 const char *proxyname;
195 private = dce_call->context->private_data;
196 proxyname = lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx);
198 if (!private->exchname) return false;
200 for (i = 0; i < r->in.pNames->Count; i++) {
201 if (strstr(r->in.pNames->Strings[i], proxyname)) {
202 r->in.pNames->Strings[i] = string_sub_talloc((TALLOC_CTX *) dce_call, r->in.pNames->Strings[i], proxyname, private->exchname);