28
28
#include "mapiproxy/dcesrv_mapiproxy.h"
29
29
#include "dcesrv_exchange_nsp.h"
31
struct exchange_nsp_session *nsp_session = NULL;
32
TDB_CONTEXT *emsabp_tdb_ctx = NULL;
31
static struct exchange_nsp_session *nsp_session = NULL;
32
static TDB_CONTEXT *emsabp_tdb_ctx = NULL;
34
static struct exchange_nsp_session *dcesrv_find_nsp_session(struct GUID *uuid)
36
struct exchange_nsp_session *session, *found_session = NULL;
38
for (session = nsp_session; !found_session && session; session = session->next) {
39
if (GUID_equal(uuid, &session->uuid)) {
40
found_session = session;
47
static struct emsabp_context *dcesrv_find_emsabp_context(struct GUID *uuid)
49
struct exchange_nsp_session *session;
50
struct emsabp_context *emsabp_ctx = NULL;
52
session = dcesrv_find_nsp_session(uuid);
54
emsabp_ctx = (struct emsabp_context *)session->session->private_data;;
35
61
\details exchange_nsp NspiBind (0x0) function, Initiates a NSPI
68
93
*r->out.handle = wire_handle;
70
95
r->out.mapiuid = r->in.mapiuid;
71
r->out.result = MAPI_E_LOGON_FAILED;
72
return MAPI_E_LOGON_FAILED;
96
DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, NULL);
75
99
/* Step 1. Initialize the emsabp context */
76
100
emsabp_ctx = emsabp_init(dce_call->conn->dce_ctx->lp_ctx, emsabp_tdb_ctx);
77
101
if (!emsabp_ctx) {
78
102
smb_panic("unable to initialize emsabp context");
79
OPENCHANGE_RETVAL_IF(!emsabp_ctx, MAPI_E_FAILONEPROVIDER, NULL);
103
DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, NULL);
82
106
/* Step 2. Check if incoming user belongs to the Exchange organization */
83
if (emsabp_verify_user(dce_call, emsabp_ctx) == false) {
107
if ((emsabp_verify_user(dce_call, emsabp_ctx) == false) && (r->in.dwFlags & fAnonymousLogin)) {
84
108
talloc_free(emsabp_ctx);
86
110
wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
101
124
*r->out.handle = wire_handle;
103
126
r->out.mapiuid = r->in.mapiuid;
104
r->out.result = MAPI_E_UNKNOWN_CPID;
105
return MAPI_E_UNKNOWN_CPID;
127
DCESRV_NSP_RETURN(r, MAPI_E_UNKNOWN_CPID, emsabp_tdb_ctx);
108
130
/* Step 4. Retrieve OpenChange server GUID */
109
131
guid = (struct GUID *) samdb_ntds_objectGUID(emsabp_ctx->samdb_ctx);
110
OPENCHANGE_RETVAL_IF(!guid, MAPI_E_FAILONEPROVIDER, emsabp_ctx);
133
DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, emsabp_ctx);
112
136
/* Step 5. Fill NspiBind reply */
113
137
handle = dcesrv_handle_new(dce_call->context, EXCHANGE_HANDLE_NSP);
114
OPENCHANGE_RETVAL_IF(!handle, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
139
DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
116
142
handle->data = (void *) emsabp_ctx;
117
143
*r->out.handle = handle->wire_handle;
118
144
r->out.mapiuid = guid;
119
r->out.result = MAPI_E_SUCCESS;
121
146
/* Search for an existing session and increment ref_count, otherwise create it */
122
for (session = nsp_session; session; session = session->next) {
123
if ((mpm_session_cmp(session->session, dce_call) == true)) {
124
mpm_session_increment_ref_count(session->session);
147
session = dcesrv_find_nsp_session(&handle->wire_handle.uuid);
149
mpm_session_increment_ref_count(session->session);
150
DEBUG(5, (" [unexpected]: existing nsp_session: %p; session: %p (ref++)\n", session, session->session));
153
DEBUG(0, ("Creating new session\n"));
130
if (found == false) {
131
155
/* Step 6. Associate this emsabp context to the session */
132
156
session = talloc((TALLOC_CTX *)nsp_session, struct exchange_nsp_session);
133
OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
158
DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
135
DEBUG(0, ("Creating new session\n"));
136
161
session->session = mpm_session_init((TALLOC_CTX *)nsp_session, dce_call);
137
OPENCHANGE_RETVAL_IF(!session->session, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
162
if (!session->session) {
163
DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
166
session->uuid = handle->wire_handle.uuid;
139
168
mpm_session_set_private_data(session->session, (void *) emsabp_ctx);
140
169
mpm_session_set_destructor(session->session, emsabp_destructor);
167
196
/* Step 0. Ensure incoming user is authenticated */
168
197
if (!dcesrv_call_authenticated(dce_call)) {
169
198
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
170
return MAPI_E_LOGON_FAILED;
199
DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
173
202
/* Step 1. Retrieve handle and free if emsabp context and session are available */
174
203
h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
176
for (session = nsp_session; session; session = session->next) {
177
if ((mpm_session_cmp(session->session, dce_call) == true)) {
178
ret = mpm_session_release(session->session);
180
DLIST_REMOVE(nsp_session, session);
181
DEBUG(0, ("[%s:%d]: Session found and released\n",
182
__FUNCTION__, __LINE__));
184
DEBUG(0, ("[%s:%d]: Session found and ref_count decreased\n",
185
__FUNCTION__, __LINE__));
205
session = dcesrv_find_nsp_session(&r->in.handle->uuid);
207
ret = mpm_session_release(session->session);
209
DLIST_REMOVE(nsp_session, session);
210
DEBUG(0, ("[%s:%d]: Session found and released\n",
211
__FUNCTION__, __LINE__));
213
DEBUG(0, ("[%s:%d]: Session found and ref_count decreased\n",
214
__FUNCTION__, __LINE__));
218
DEBUG(5, (" nsp_session NOT found\n"));
192
222
r->out.result = (enum MAPISTATUS) 1;
194
return MAPI_E_SUCCESS;
224
DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL);
205
235
\return MAPI_E_SUCCESS on success
207
static enum MAPISTATUS dcesrv_NspiUpdateStat(struct dcesrv_call_state *dce_call,
209
struct NspiUpdateStat *r)
237
static void dcesrv_NspiUpdateStat(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct NspiUpdateStat *r)
211
DEBUG(3, ("exchange_nsp: NspiUpdateStat (0x2) not implemented\n"));
212
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
239
enum MAPISTATUS retval = MAPI_E_SUCCESS;
240
struct emsabp_context *emsabp_ctx = NULL;
241
uint32_t row, row_max;
242
TALLOC_CTX *local_mem_ctx;
243
struct PropertyTagArray_r *mids;
245
DEBUG(3, ("exchange_nsp: NspiUpdateStat (0x2)"));
247
/* Step 0. Ensure incoming user is authenticated */
248
if (!dcesrv_call_authenticated(dce_call)) {
249
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
250
DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
253
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
255
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
258
local_mem_ctx = talloc_zero(NULL, TALLOC_CTX);
260
/* Step 1. Sanity Checks (MS-NSPI Server Processing Rules) */
261
if (r->in.pStat->ContainerID && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
262
retval = MAPI_E_INVALID_BOOKMARK;
266
mids = talloc_zero(local_mem_ctx, struct PropertyTagArray_r);
267
if (emsabp_search(local_mem_ctx, emsabp_ctx, mids, NULL, r->in.pStat, 0) != MAPI_E_SUCCESS) {
271
row_max = mids->cValues;
274
if (r->in.pStat->CurrentRec == MID_CURRENT) {
275
/* Fractional positioning (3.1.1.4.2) */
276
row = r->in.pStat->NumPos * row_max / r->in.pStat->TotalRecs;
282
if (r->in.pStat->CurrentRec == MID_BEGINNING_OF_TABLE) {
285
else if (r->in.pStat->CurrentRec == MID_END_OF_TABLE) {
289
retval = MAPI_E_NOT_FOUND;
291
while (row < row_max) {
292
if ((uint32_t) mids->aulPropTag[row] == (uint32_t) r->in.pStat->CurrentRec) {
293
retval = MAPI_E_SUCCESS;
300
if (retval == MAPI_E_NOT_FOUND) {
306
if (-r->in.pStat->Delta > row) {
308
r->in.pStat->CurrentRec = mids->aulPropTag[row];
310
else if (r->in.pStat->Delta + row >= row_max) {
312
r->in.pStat->CurrentRec = MID_END_OF_TABLE;
315
row += r->in.pStat->Delta;
316
r->in.pStat->CurrentRec = mids->aulPropTag[row];
319
r->in.pStat->Delta = 0;
320
r->in.pStat->NumPos = row;
321
r->in.pStat->TotalRecs = row_max;
324
r->out.pStat = r->in.pStat;
326
DCESRV_NSP_RETURN(r, retval, local_mem_ctx);
217
330
\details exchange_nsp NspiQueryRows (0x3) function
223
336
\return MAPI_E_SUCCESS on success
225
static enum MAPISTATUS dcesrv_NspiQueryRows(struct dcesrv_call_state *dce_call,
227
struct NspiQueryRows *r)
338
static void dcesrv_NspiQueryRows(struct dcesrv_call_state *dce_call,
340
struct NspiQueryRows *r)
229
342
enum MAPISTATUS retval = MAPI_E_SUCCESS;
230
struct exchange_nsp_session *session;
231
343
struct emsabp_context *emsabp_ctx = NULL;
232
344
struct SPropTagArray *pPropTags;
233
345
struct SRowSet *pRows;
237
348
DEBUG(3, ("exchange_nsp: NspiQueryRows (0x3)\n"));
239
350
/* Step 0. Ensure incoming user is authenticated */
240
351
if (!dcesrv_call_authenticated(dce_call)) {
241
352
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
242
return MAPI_E_LOGON_FAILED;
245
for (session = nsp_session; session; session = session->next) {
246
if ((mpm_session_cmp(session->session, dce_call)) == true) {
247
emsabp_ctx = (struct emsabp_context *)session->session->private_data;
252
OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
353
DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
356
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
358
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
254
361
/* Step 1. Sanity Checks (MS-NSPI Server Processing Rules) */
255
if (r->in.pStat->ContainerID && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
362
if (r->in.pStat->ContainerID && r->in.lpETable == NULL && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
256
363
retval = MAPI_E_INVALID_BOOKMARK;
283
390
if (!MAPI_STATUS_IS_OK(retval)) {
286
394
if (ldb_res->count) {
287
pRows->cRows = ldb_res->count;
288
pRows->aRow = talloc_array(mem_ctx, struct SRow, ldb_res->count);
395
pRows->cRows = ldb_res->count - r->in.pStat->NumPos;
396
pRows->aRow = talloc_array(mem_ctx, struct SRow, pRows->cRows);
291
399
/* fetch required attributes for every entry found */
292
for (i = 0; i < ldb_res->count; i++) {
293
retval = emsabp_fetch_attrs_from_msg(mem_ctx, emsabp_ctx, &(pRows->aRow[i]),
400
for (i = r->in.pStat->NumPos; i < ldb_res->count; i++) {
401
retval = emsabp_fetch_attrs_from_msg(mem_ctx, emsabp_ctx, &(pRows->aRow[i-r->in.pStat->NumPos]),
294
402
ldb_res->msgs[i], 0, r->in.dwFlags, pPropTags);
295
403
if (!MAPI_STATUS_IS_OK(retval)) {
407
r->in.pStat->NumPos = r->in.pStat->Delta + pRows->cRows;
408
r->in.pStat->CurrentRec = MID_END_OF_TABLE;
409
r->in.pStat->TotalRecs = pRows->cRows;
410
r->in.pStat->Delta = 0;
300
412
/* Step 2.2 Fill ppRows for supplied table of MIds */
301
pRows->cRows = r->in.dwETableCount;
302
pRows->aRow = talloc_array(mem_ctx, struct SRow, r->in.dwETableCount);
303
for (i = 0; i < r->in.dwETableCount; i++) {
304
retval = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, &(pRows->aRow[i]), r->in.lpETable[i], r->in.dwFlags, pPropTags);
305
if (retval != MAPI_E_SUCCESS) {
414
if (r->in.pStat->NumPos < r->in.dwETableCount) {
415
pRows->cRows = r->in.dwETableCount - r->in.pStat->NumPos;
416
pRows->aRow = talloc_array(mem_ctx, struct SRow, pRows->cRows);
417
for (i = r->in.pStat->NumPos; i < r->in.dwETableCount; i++) {
418
retval = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, &(pRows->aRow[j]), r->in.lpETable[i], r->in.dwFlags, pPropTags);
419
if (retval != MAPI_E_SUCCESS) {
425
r->in.pStat->CurrentRec = MID_END_OF_TABLE;
426
r->in.pStat->TotalRecs = j;
427
r->in.pStat->Delta = 0;
311
430
/* Step 3. Fill output params */
312
431
*r->out.ppRows = pRows;
314
433
memcpy(r->out.pStat, r->in.pStat, sizeof (struct STAT));
315
r->out.pStat->TotalRecs = pRows->cRows;
316
r->out.pStat->NumPos = r->out.pStat->Delta + pRows->cRows;
317
r->out.pStat->CurrentRec = MID_END_OF_TABLE;
319
return MAPI_E_SUCCESS;
435
DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL);
322
437
r->out.pStat = r->in.pStat;
323
438
*r->out.ppRows = NULL;
324
r->out.result = retval;
439
DCESRV_NSP_RETURN(r, retval, NULL);
337
450
\return MAPI_E_SUCCESS on success
339
static enum MAPISTATUS dcesrv_NspiSeekEntries(struct dcesrv_call_state *dce_call,
452
static void dcesrv_NspiSeekEntries(struct dcesrv_call_state *dce_call,
340
453
TALLOC_CTX *mem_ctx,
341
454
struct NspiSeekEntries *r)
343
DEBUG(3, ("exchange_nsp: NspiSeekEntries (0x4) not implemented\n"));
344
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
456
enum MAPISTATUS retval = MAPI_E_SUCCESS, ret;
457
struct emsabp_context *emsabp_ctx = NULL;
459
struct PropertyTagArray_r *mids, *all_mids;
460
struct Restriction_r *seek_restriction;
462
DEBUG(3, ("exchange_nsp: NspiSeekEntries (0x4)\n"));
464
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
466
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
469
/* Step 1. Sanity Checks (MS-NSPI Server Processing Rules) */
470
if (r->in.pStat->ContainerID && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
471
retval = MAPI_E_INVALID_BOOKMARK;
475
if (!r->in.pTarget) {
476
retval = MAPI_E_INVALID_PARAMETER;
480
if (r->in.lpETable) {
481
all_mids = r->in.lpETable;
484
all_mids = talloc_zero(mem_ctx, struct PropertyTagArray_r);
485
emsabp_search(mem_ctx, emsabp_ctx, all_mids, NULL, r->in.pStat, 0);
488
/* find the records matching the qualifier */
489
seek_restriction = talloc_zero(mem_ctx, struct Restriction_r);
490
seek_restriction->rt = RES_PROPERTY;
491
seek_restriction->res.resProperty.relop = RELOP_GE;
492
seek_restriction->res.resProperty.ulPropTag = r->in.pTarget->ulPropTag;
493
seek_restriction->res.resProperty.lpProp = r->in.pTarget;
495
mids = talloc_zero(mem_ctx, struct PropertyTagArray_r);
496
if (emsabp_search(mem_ctx, emsabp_ctx, mids, seek_restriction, r->in.pStat, 0) != MAPI_E_SUCCESS) {
498
retval = MAPI_E_NOT_FOUND;
501
r->in.pStat->CurrentRec = MID_END_OF_TABLE;
502
r->in.pStat->NumPos = r->in.pStat->TotalRecs = all_mids->cValues;
503
for (row = 0; row < all_mids->cValues; row++) {
504
if (all_mids->aulPropTag[row] == mids->aulPropTag[0]) {
505
r->in.pStat->CurrentRec = mids->aulPropTag[0];
506
r->in.pStat->NumPos = row;
511
/* now we need to populate the rows, if properties were requested */
512
r->out.pStat = r->in.pStat;
513
if (!r->in.pPropTags || !r->in.pPropTags->cValues) {
514
*r->out.pRows = NULL;
518
r->out.pRows = talloc_zero(mem_ctx, struct SRowSet *);
519
r->out.pRows[0] = talloc_zero(mem_ctx, struct SRowSet);
520
r->out.pRows[0]->cRows = mids->cValues;
521
r->out.pRows[0]->aRow = talloc_array(mem_ctx, struct SRow, mids->cValues);
522
for (row = 0; row < mids->cValues; row++) {
523
ret = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, &(r->out.pRows[0]->aRow[row]),
524
mids->aulPropTag[row], fEphID, r->in.pPropTags);
527
DEBUG(5, ("failure looking up value %d\n", row));
534
DCESRV_NSP_RETURN(r, retval, NULL);
371
559
/* Step 0. Ensure incoming user is authenticated */
372
560
if (!dcesrv_call_authenticated(dce_call)) {
373
561
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
374
return MAPI_E_LOGON_FAILED;
377
for (session = nsp_session; session; session = session->next) {
378
if ((mpm_session_cmp(session->session, dce_call)) == true) {
379
emsabp_ctx = (struct emsabp_context *)session->session->private_data;
384
OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
562
DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
565
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
567
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
386
570
/* Step 1. Retrieve MIds array given search criterias */
387
571
ppOutMIds = talloc_zero(mem_ctx, struct PropertyTagArray_r);
452
634
\return MAPI_E_SUCCESS on success
454
static enum MAPISTATUS dcesrv_NspiDNToMId(struct dcesrv_call_state *dce_call,
636
static void dcesrv_NspiDNToMId(struct dcesrv_call_state *dce_call,
455
637
TALLOC_CTX *mem_ctx,
456
638
struct NspiDNToMId *r)
458
640
enum MAPISTATUS retval;
459
struct exchange_nsp_session *session;
460
641
struct emsabp_context *emsabp_ctx = NULL;
461
642
struct ldb_message *msg;
465
646
bool pbUseConfPartition;
468
648
DEBUG(3, ("exchange_nsp: NspiDNToMId (0x7)\n"));
470
650
/* Step 0. Ensure incoming user is authenticated */
471
651
if (!dcesrv_call_authenticated(dce_call)) {
472
652
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
473
return MAPI_E_LOGON_FAILED;
476
for (session = nsp_session; session; session = session->next) {
477
if ((mpm_session_cmp(session->session, dce_call)) == true) {
478
emsabp_ctx = (struct emsabp_context *)session->session->private_data;
483
OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
653
DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
656
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
658
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
485
661
r->out.ppMIds = talloc_array(mem_ctx, struct PropertyTagArray_r *, 2);
486
662
r->out.ppMIds[0] = talloc_zero(mem_ctx, struct PropertyTagArray_r);
538
712
\return MAPI_E_SUCCESS on success
540
static enum MAPISTATUS dcesrv_NspiGetProps(struct dcesrv_call_state *dce_call,
714
static void dcesrv_NspiGetProps(struct dcesrv_call_state *dce_call,
541
715
TALLOC_CTX *mem_ctx,
542
716
struct NspiGetProps *r)
544
718
enum MAPISTATUS retval;
545
struct exchange_nsp_session *session;
546
719
struct emsabp_context *emsabp_ctx = NULL;
722
struct SPropTagArray *pPropTags;
551
724
DEBUG(3, ("exchange_nsp: NspiGetProps (0x9)\n"));
553
726
/* Step 0. Ensure incoming user is authenticated */
554
727
if (!dcesrv_call_authenticated(dce_call)) {
555
728
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
556
return MAPI_E_LOGON_FAILED;
559
for (session = nsp_session; session; session = session->next) {
560
if ((mpm_session_cmp(session->session, dce_call)) == true) {
561
emsabp_ctx = (struct emsabp_context *)session->session->private_data;
566
OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
729
DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
732
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
734
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
568
737
MId = r->in.pStat->CurrentRec;
570
739
/* Step 1. Sanity Checks (MS-NSPI Server Processing Rules) */
571
740
if (r->in.pStat->ContainerID && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
572
retval = MAPI_E_INVALID_BOOKMARK;
573
r->out.result = retval;
741
DCESRV_NSP_RETURN(r, MAPI_E_INVALID_BOOKMARK, NULL);
577
744
/* Step 2. Fetch properties */
579
746
r->out.ppRows[0] = talloc_zero(r->out.ppRows, struct SRow);
580
747
r->out.ppRows[0]->ulAdrEntryPad = 0;
582
retval = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, r->out.ppRows[0], MId, r->in.dwFlags, r->in.pPropTags);
749
pPropTags = r->in.pPropTags;
751
pPropTags = talloc_zero(r, struct SPropTagArray);
752
pPropTags->cValues = 9;
753
pPropTags->aulPropTag = talloc_array(pPropTags, enum MAPITAGS, pPropTags->cValues + 1);
754
pPropTags->aulPropTag[0] = PR_ADDRTYPE_UNICODE;
755
pPropTags->aulPropTag[1] = PR_SMTP_ADDRESS_UNICODE;
756
pPropTags->aulPropTag[2] = PR_OBJECT_TYPE;
757
pPropTags->aulPropTag[3] = PR_DISPLAY_TYPE;
758
pPropTags->aulPropTag[4] = PR_ENTRYID;
759
pPropTags->aulPropTag[5] = PR_ORIGINAL_ENTRYID;
760
pPropTags->aulPropTag[6] = PR_SEARCH_KEY;
761
pPropTags->aulPropTag[7] = PR_INSTANCE_KEY;
762
pPropTags->aulPropTag[8] = PR_EMAIL_ADDRESS;
763
pPropTags->aulPropTag[pPropTags->cValues] = 0;
764
r->in.pPropTags = pPropTags;
767
retval = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, r->out.ppRows[0], MId, r->in.dwFlags, pPropTags);
583
768
if (retval != MAPI_E_SUCCESS) {
584
769
/* Is MId is not found, proceed as if no attributes were found */
585
770
if (retval == MAPI_E_INVALID_BOOKMARK) {
673
856
\return MAPI_E_SUCCESS on success
676
static enum MAPISTATUS dcesrv_NspiGetSpecialTable(struct dcesrv_call_state *dce_call,
678
struct NspiGetSpecialTable *r)
859
static void dcesrv_NspiGetSpecialTable(struct dcesrv_call_state *dce_call,
861
struct NspiGetSpecialTable *r)
680
struct exchange_nsp_session *session;
681
863
struct emsabp_context *emsabp_ctx = NULL;
684
865
DEBUG(3, ("exchange_nsp: NspiGetSpecialTable (0xC)\n"));
686
867
/* Step 0. Ensure incoming user is authenticated */
687
868
if (!dcesrv_call_authenticated(dce_call)) {
688
869
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
689
return MAPI_E_LOGON_FAILED;
692
for (session = nsp_session; session; session = session->next) {
693
if ((mpm_session_cmp(session->session, dce_call)) == true) {
694
emsabp_ctx = (struct emsabp_context *)session->session->private_data;
699
OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
870
DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
873
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
875
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
701
878
/* Step 1. (FIXME) We arbitrary set lpVersion to 0x1 */
702
879
r->out.lpVersion = talloc_zero(mem_ctx, uint32_t);
853
1032
\return MAPI_E_SUCCESS on success
856
static enum MAPISTATUS dcesrv_NspiResolveNames(struct dcesrv_call_state *dce_call,
858
struct NspiResolveNames *r)
1035
static void dcesrv_NspiResolveNames(struct dcesrv_call_state *dce_call,
1036
TALLOC_CTX *mem_ctx,
1037
struct NspiResolveNames *r)
860
DEBUG(3, ("exchange_nsp: NspiResolveNames (0x13) not implemented\n"));
861
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1039
enum MAPISTATUS retval = MAPI_E_SUCCESS;
1040
struct emsabp_context *emsabp_ctx = NULL;
1041
struct ldb_message *ldb_msg_ab;
1042
struct SPropTagArray *pPropTags;
1043
const char *purportedSearch;
1044
struct PropertyTagArray_r *pMIds = NULL;
1045
struct SRowSet *pRows = NULL;
1046
struct StringsArray_r *paStr;
1049
const char * const recipient_attrs[] = { "*", NULL };
1050
const char * const search_attr[] = { "mailNickName", "mail", "name",
1051
"displayName", "givenName",
1052
"sAMAccountName", "proxyAddresses" };
1054
DEBUG(3, ("exchange_nsp: NspiResolveNames (0x13)\n"));
1056
if (!dcesrv_call_authenticated(dce_call)) {
1057
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
1060
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
1062
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
1065
/* Step 1. Prepare in/out data */
1066
retval = emsabp_ab_container_by_id(mem_ctx, emsabp_ctx, r->in.pStat->ContainerID, &ldb_msg_ab);
1067
if (!MAPI_STATUS_IS_OK(retval)) {
1068
DCESRV_NSP_RETURN(r, MAPI_E_INVALID_BOOKMARK, NULL);
1071
purportedSearch = ldb_msg_find_attr_as_string(ldb_msg_ab, "purportedSearch", NULL);
1072
if (!purportedSearch) {
1073
DCESRV_NSP_RETURN(r, MAPI_E_INVALID_BOOKMARK, NULL);
1076
/* Set the default list of property tags if none were provided in input */
1077
if (!r->in.pPropTags) {
1078
pPropTags = set_SPropTagArray(mem_ctx, 0x7,
1079
PR_EMS_AB_CONTAINERID,
1083
PR_OFFICE_TELEPHONE_NUMBER,
1085
PR_OFFICE_LOCATION);
1087
pPropTags = r->in.pPropTags;
1090
/* Allocate output MIds */
1091
paStr = r->in.paStr;
1092
pMIds = talloc(mem_ctx, struct PropertyTagArray_r);
1093
pMIds->cValues = paStr->Count;
1094
pMIds->aulPropTag = (uint32_t *) talloc_array(mem_ctx, uint32_t, pMIds->cValues);
1095
pRows = talloc(mem_ctx, struct SRowSet);
1097
pRows->aRow = talloc_array(mem_ctx, struct SRow, pMIds->cValues);
1099
/* Step 2. Fetch AB container records */
1100
for (i = 0; i < paStr->Count; i++) {
1101
struct ldb_result *ldb_res;
1102
char *filter = talloc_strdup(mem_ctx, "");
1105
/* Build search filter */
1106
for (j = 0; j < ARRAY_SIZE(search_attr); j++) {
1107
char *attr_filter = talloc_asprintf(mem_ctx, "(%s=%s)", search_attr[j], paStr->Strings[i]);
1108
filter = talloc_strdup_append(filter, attr_filter);
1109
talloc_free(attr_filter);
1113
filter = talloc_asprintf(mem_ctx, "(&%s(|%s))", purportedSearch, filter);
1114
ret = ldb_search(emsabp_ctx->samdb_ctx, mem_ctx, &ldb_res,
1115
ldb_get_default_basedn(emsabp_ctx->samdb_ctx),
1116
LDB_SCOPE_SUBTREE, recipient_attrs, "%s", filter);
1118
/* Determine name resolution status and fetch object upon success */
1119
if (ret != LDB_SUCCESS || ldb_res->count == 0) {
1120
pMIds->aulPropTag[i] = MAPI_UNRESOLVED;
1121
} else if (ldb_res->count > 1) {
1122
pMIds->aulPropTag[i] = MAPI_AMBIGUOUS;
1124
pMIds->aulPropTag[i] = MAPI_RESOLVED;
1125
emsabp_fetch_attrs_from_msg(mem_ctx, emsabp_ctx, &pRows->aRow[pRows->cRows],
1126
ldb_res->msgs[0], 0, 0, pPropTags);
1131
*r->out.ppMIds = pMIds;
1133
*r->out.ppRows = pRows;
1136
DCESRV_NSP_RETURN(r, retval, NULL);
872
1147
\return MAPI_E_SUCCESS on success
875
static enum MAPISTATUS dcesrv_NspiResolveNamesW(struct dcesrv_call_state *dce_call,
877
struct NspiResolveNamesW *r)
1150
static void dcesrv_NspiResolveNamesW(struct dcesrv_call_state *dce_call,
1151
TALLOC_CTX *mem_ctx,
1152
struct NspiResolveNamesW *r)
879
1154
enum MAPISTATUS retval = MAPI_E_SUCCESS;
880
struct exchange_nsp_session *session;
881
1155
struct emsabp_context *emsabp_ctx = NULL;
882
1156
struct ldb_message *ldb_msg_ab;
883
1157
struct SPropTagArray *pPropTags;
884
1158
const char *purportedSearch;
885
1159
struct PropertyTagArray_r *pMIds = NULL;
886
1160
struct SRowSet *pRows = NULL;
887
struct WStringsArray_r *paWStr;
1161
struct StringsArrayW_r *paWStr;
891
1164
const char * const recipient_attrs[] = { "*", NULL };
892
1165
const char * const search_attr[] = { "mailNickName", "mail", "name",
893
1166
"displayName", "givenName", "sAMAccountName" };
895
1168
DEBUG(3, ("exchange_nsp: NspiResolveNamesW (0x14)\n"));
897
1170
/* Step 0. Ensure incoming user is authenticated */
898
if (!dcesrv_call_authenticated(dce_call)) {
1171
if (!dcesrv_call_authenticated(dce_call)) {
899
1172
DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
900
return MAPI_E_LOGON_FAILED;
903
for (session = nsp_session; session; session = session->next) {
904
if ((mpm_session_cmp(session->session, dce_call)) == true) {
905
emsabp_ctx = (struct emsabp_context *)session->session->private_data;
910
OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
1173
DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
1176
emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
1178
DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
912
1181
/* Step 1. Prepare in/out data */
913
1182
retval = emsabp_ab_container_by_id(mem_ctx, emsabp_ctx, r->in.pStat->ContainerID, &ldb_msg_ab);
914
OPENCHANGE_RETVAL_IF(!MAPI_STATUS_IS_OK(retval), MAPI_E_INVALID_BOOKMARK, NULL);
1183
if (!MAPI_STATUS_IS_OK(retval)) {
1184
DCESRV_NSP_RETURN(r, MAPI_E_INVALID_BOOKMARK, NULL);
916
1187
purportedSearch = ldb_msg_find_attr_as_string(ldb_msg_ab, "purportedSearch", NULL);
917
OPENCHANGE_RETVAL_IF(!purportedSearch, MAPI_E_INVALID_BOOKMARK, NULL);
1188
if (!purportedSearch) {
1189
DCESRV_NSP_RETURN(r, MAPI_E_INVALID_BOOKMARK, NULL);
919
1192
/* Set default list of property tags if none were provided in input */
920
1193
if (!r->in.pPropTags) {
1011
1284
switch (opnum) {
1012
1285
case NDR_NSPIBIND:
1013
retval = dcesrv_NspiBind(dce_call, mem_ctx, (struct NspiBind *)r);
1286
dcesrv_NspiBind(dce_call, mem_ctx, (struct NspiBind *)r);
1015
1288
case NDR_NSPIUNBIND:
1016
retval = dcesrv_NspiUnbind(dce_call, mem_ctx, (struct NspiUnbind *)r);
1289
dcesrv_NspiUnbind(dce_call, mem_ctx, (struct NspiUnbind *)r);
1018
1291
case NDR_NSPIUPDATESTAT:
1019
retval = dcesrv_NspiUpdateStat(dce_call, mem_ctx, (struct NspiUpdateStat *)r);
1292
dcesrv_NspiUpdateStat(dce_call, mem_ctx, (struct NspiUpdateStat *)r);
1021
1294
case NDR_NSPIQUERYROWS:
1022
retval = dcesrv_NspiQueryRows(dce_call, mem_ctx, (struct NspiQueryRows *)r);
1295
dcesrv_NspiQueryRows(dce_call, mem_ctx, (struct NspiQueryRows *)r);
1024
1297
case NDR_NSPISEEKENTRIES:
1025
retval = dcesrv_NspiSeekEntries(dce_call, mem_ctx, (struct NspiSeekEntries *)r);
1298
dcesrv_NspiSeekEntries(dce_call, mem_ctx, (struct NspiSeekEntries *)r);
1027
1300
case NDR_NSPIGETMATCHES:
1028
retval = dcesrv_NspiGetMatches(dce_call, mem_ctx, (struct NspiGetMatches *)r);
1301
dcesrv_NspiGetMatches(dce_call, mem_ctx, (struct NspiGetMatches *)r);
1030
1303
case NDR_NSPIRESORTRESTRICTION:
1031
retval = dcesrv_NspiResortRestriction(dce_call, mem_ctx, (struct NspiResortRestriction *)r);
1304
dcesrv_NspiResortRestriction(dce_call, mem_ctx, (struct NspiResortRestriction *)r);
1033
1306
case NDR_NSPIDNTOMID:
1034
retval = dcesrv_NspiDNToMId(dce_call, mem_ctx, (struct NspiDNToMId *)r);
1307
dcesrv_NspiDNToMId(dce_call, mem_ctx, (struct NspiDNToMId *)r);
1036
1309
case NDR_NSPIGETPROPLIST:
1037
retval = dcesrv_NspiGetPropList(dce_call, mem_ctx, (struct NspiGetPropList *)r);
1310
dcesrv_NspiGetPropList(dce_call, mem_ctx, (struct NspiGetPropList *)r);
1039
1312
case NDR_NSPIGETPROPS:
1040
retval = dcesrv_NspiGetProps(dce_call, mem_ctx, (struct NspiGetProps *)r);
1313
dcesrv_NspiGetProps(dce_call, mem_ctx, (struct NspiGetProps *)r);
1042
1315
case NDR_NSPICOMPAREMIDS:
1043
retval = dcesrv_NspiCompareMIds(dce_call, mem_ctx, (struct NspiCompareMIds *)r);
1316
dcesrv_NspiCompareMIds(dce_call, mem_ctx, (struct NspiCompareMIds *)r);
1045
1318
case NDR_NSPIMODPROPS:
1046
retval = dcesrv_NspiModProps(dce_call, mem_ctx, (struct NspiModProps *)r);
1319
dcesrv_NspiModProps(dce_call, mem_ctx, (struct NspiModProps *)r);
1048
1321
case NDR_NSPIGETSPECIALTABLE:
1049
retval = dcesrv_NspiGetSpecialTable(dce_call, mem_ctx, (struct NspiGetSpecialTable *)r);
1322
dcesrv_NspiGetSpecialTable(dce_call, mem_ctx, (struct NspiGetSpecialTable *)r);
1051
1324
case NDR_NSPIGETTEMPLATEINFO:
1052
retval = dcesrv_NspiGetTemplateInfo(dce_call, mem_ctx, (struct NspiGetTemplateInfo *)r);
1325
dcesrv_NspiGetTemplateInfo(dce_call, mem_ctx, (struct NspiGetTemplateInfo *)r);
1054
1327
case NDR_NSPIMODLINKATT:
1055
retval = dcesrv_NspiModLinkAtt(dce_call, mem_ctx, (struct NspiModLinkAtt *)r);
1328
dcesrv_NspiModLinkAtt(dce_call, mem_ctx, (struct NspiModLinkAtt *)r);
1057
1330
case NDR_NSPIDELETEENTRIES:
1058
retval = dcesrv_NspiDeleteEntries(dce_call, mem_ctx, (struct NspiDeleteEntries *)r);
1331
dcesrv_NspiDeleteEntries(dce_call, mem_ctx, (struct NspiDeleteEntries *)r);
1060
1333
case NDR_NSPIQUERYCOLUMNS:
1061
retval = dcesrv_NspiQueryColumns(dce_call, mem_ctx, (struct NspiQueryColumns *)r);
1334
dcesrv_NspiQueryColumns(dce_call, mem_ctx, (struct NspiQueryColumns *)r);
1063
1336
case NDR_NSPIGETNAMESFROMIDS:
1064
retval = dcesrv_NspiGetNamesFromIDs(dce_call, mem_ctx, (struct NspiGetNamesFromIDs *)r);
1337
dcesrv_NspiGetNamesFromIDs(dce_call, mem_ctx, (struct NspiGetNamesFromIDs *)r);
1066
1339
case NDR_NSPIGETIDSFROMNAMES:
1067
retval = dcesrv_NspiGetIDsFromNames(dce_call, mem_ctx, (struct NspiGetIDsFromNames *)r);
1340
dcesrv_NspiGetIDsFromNames(dce_call, mem_ctx, (struct NspiGetIDsFromNames *)r);
1069
1342
case NDR_NSPIRESOLVENAMES:
1070
retval = dcesrv_NspiResolveNames(dce_call, mem_ctx, (struct NspiResolveNames *)r);
1343
dcesrv_NspiResolveNames(dce_call, mem_ctx, (struct NspiResolveNames *)r);
1072
1345
case NDR_NSPIRESOLVENAMESW:
1073
retval = dcesrv_NspiResolveNamesW(dce_call, mem_ctx, (struct NspiResolveNamesW *)r);
1346
dcesrv_NspiResolveNamesW(dce_call, mem_ctx, (struct NspiResolveNamesW *)r);