~ubuntu-branches/debian/sid/openchange/sid

« back to all changes in this revision

Viewing changes to mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2012-04-12 20:07:57 UTC
  • mfrom: (11 sid)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20120412200757-k933d9trljmxj1l4
Tags: 1:1.0-4
* openchangeserver: Add dependency on openchangeproxy.
* Rebuild against newer version of Samba 4.
* Use dpkg-buildflags.
* Migrate to Git, update Vcs-Git header.
* Switch to debhelper 9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include "mapiproxy/dcesrv_mapiproxy.h"
29
29
#include "dcesrv_exchange_nsp.h"
30
30
 
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;
 
33
 
 
34
static struct exchange_nsp_session *dcesrv_find_nsp_session(struct GUID *uuid)
 
35
{
 
36
        struct exchange_nsp_session     *session, *found_session = NULL;
 
37
 
 
38
        for (session = nsp_session; !found_session && session; session = session->next) {
 
39
                if (GUID_equal(uuid, &session->uuid)) {
 
40
                        found_session = session;
 
41
                }
 
42
        }
 
43
 
 
44
        return found_session;
 
45
}
 
46
 
 
47
static struct emsabp_context *dcesrv_find_emsabp_context(struct GUID *uuid)
 
48
{
 
49
        struct exchange_nsp_session     *session;
 
50
        struct emsabp_context           *emsabp_ctx = NULL;
 
51
 
 
52
        session = dcesrv_find_nsp_session(uuid);
 
53
        if (session) {
 
54
                emsabp_ctx = (struct emsabp_context *)session->session->private_data;;
 
55
        }
 
56
 
 
57
        return emsabp_ctx;
 
58
}
33
59
 
34
60
/**
35
61
   \details exchange_nsp NspiBind (0x0) function, Initiates a NSPI
46
72
 
47
73
   \return MAPI_E_SUCCESS on success, otherwise a MAPI error
48
74
 */
49
 
static enum MAPISTATUS dcesrv_NspiBind(struct dcesrv_call_state *dce_call,
 
75
static void dcesrv_NspiBind(struct dcesrv_call_state *dce_call,
50
76
                                       TALLOC_CTX *mem_ctx,
51
77
                                       struct NspiBind *r)
52
78
{
55
81
        struct dcesrv_handle            *handle;
56
82
        struct policy_handle            wire_handle;
57
83
        struct exchange_nsp_session     *session;
58
 
        bool                            found = false;
59
84
 
60
85
        DEBUG(5, ("exchange_nsp: NspiBind (0x0)\n"));
61
86
 
62
87
        /* Step 0. Ensure incoming user is authenticated */
63
 
        if (!dcesrv_call_authenticated(dce_call)) {
 
88
        if (!dcesrv_call_authenticated(dce_call) && (r->in.dwFlags & fAnonymousLogin)) {
64
89
                DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
65
90
 
66
91
                wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
68
93
                *r->out.handle = wire_handle;
69
94
 
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);
73
97
        }
74
98
 
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);
80
104
        }
81
105
 
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);
85
109
 
86
110
                wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
88
112
                *r->out.handle = wire_handle;
89
113
 
90
114
                r->out.mapiuid = r->in.mapiuid;
91
 
                r->out.result = MAPI_E_LOGON_FAILED;
92
 
                return MAPI_E_LOGON_FAILED;
 
115
                DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, emsabp_tdb_ctx);
93
116
        }
94
117
 
95
118
        /* Step 3. Check if valid cpID has been supplied */
101
124
                *r->out.handle = wire_handle;
102
125
 
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);
106
128
        }
107
129
 
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);
 
132
        if (!guid) {
 
133
                DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, emsabp_ctx);
 
134
        }
111
135
 
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);
 
138
        if (!handle) {
 
139
                DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
 
140
        }
115
141
 
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;
120
145
 
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);
125
 
                        found = true;
126
 
                        break;
127
 
                }
 
147
        session = dcesrv_find_nsp_session(&handle->wire_handle.uuid);
 
148
        if (session) {
 
149
                mpm_session_increment_ref_count(session->session);
 
150
                DEBUG(5, ("  [unexpected]: existing nsp_session: %p; session: %p (ref++)\n", session, session->session));
128
151
        }
 
152
        else {
 
153
                DEBUG(0, ("Creating new session\n"));
129
154
 
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);
 
157
                if (!session) {
 
158
                        DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
 
159
                }
134
160
 
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);
 
164
                }
 
165
 
 
166
                session->uuid = handle->wire_handle.uuid;
138
167
 
139
168
                mpm_session_set_private_data(session->session, (void *) emsabp_ctx);
140
169
                mpm_session_set_destructor(session->session, emsabp_destructor);
142
171
                DLIST_ADD_END(nsp_session, session, struct exchange_nsp_session *);
143
172
        }
144
173
 
145
 
        return MAPI_E_SUCCESS;
 
174
        DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL);
146
175
}
147
176
 
148
177
 
154
183
   \param mem_ctx pointer to the memory context
155
184
   \param r pointer to the NspiUnbind call structure
156
185
 */
157
 
static enum MAPISTATUS dcesrv_NspiUnbind(struct dcesrv_call_state *dce_call,
 
186
static void dcesrv_NspiUnbind(struct dcesrv_call_state *dce_call,
158
187
                                         TALLOC_CTX *mem_ctx,
159
188
                                         struct NspiUnbind *r)
160
189
{
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);
171
200
        }
172
201
 
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);
175
204
        if (h) {
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);
179
 
                                if (ret == true) {
180
 
                                        DLIST_REMOVE(nsp_session, session);
181
 
                                        DEBUG(0, ("[%s:%d]: Session found and released\n", 
182
 
                                                  __FUNCTION__, __LINE__));
183
 
                                } else {
184
 
                                        DEBUG(0, ("[%s:%d]: Session found and ref_count decreased\n",
185
 
                                                  __FUNCTION__, __LINE__));
186
 
                                }
187
 
                                break;
 
205
                session = dcesrv_find_nsp_session(&r->in.handle->uuid);
 
206
                if (session) {
 
207
                        ret = mpm_session_release(session->session);
 
208
                        if (ret == true) {
 
209
                                DLIST_REMOVE(nsp_session, session);
 
210
                                DEBUG(0, ("[%s:%d]: Session found and released\n", 
 
211
                                          __FUNCTION__, __LINE__));
 
212
                        } else {
 
213
                                DEBUG(0, ("[%s:%d]: Session found and ref_count decreased\n",
 
214
                                          __FUNCTION__, __LINE__));
188
215
                        }
189
216
                }
 
217
                else {
 
218
                        DEBUG(5, ("  nsp_session NOT found\n"));
 
219
                }
190
220
        }
191
221
 
192
222
        r->out.result = (enum MAPISTATUS) 1;
193
223
 
194
 
        return MAPI_E_SUCCESS;
 
224
        DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL);
195
225
}
196
226
 
197
227
 
204
234
 
205
235
   \return MAPI_E_SUCCESS on success
206
236
*/
207
 
static enum MAPISTATUS dcesrv_NspiUpdateStat(struct dcesrv_call_state *dce_call, 
208
 
                                             TALLOC_CTX *mem_ctx,
209
 
                                             struct NspiUpdateStat *r)
 
237
static void dcesrv_NspiUpdateStat(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct NspiUpdateStat *r)
210
238
{
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;
 
244
 
 
245
        DEBUG(3, ("exchange_nsp: NspiUpdateStat (0x2)"));
 
246
 
 
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);
 
251
        }
 
252
 
 
253
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
254
        if (!emsabp_ctx) {
 
255
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
256
        }
 
257
 
 
258
        local_mem_ctx = talloc_zero(NULL, TALLOC_CTX);
 
259
 
 
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;
 
263
                goto end;
 
264
        }
 
265
 
 
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) {
 
268
                row_max = 0;
 
269
        }
 
270
        else {
 
271
                row_max = mids->cValues;
 
272
        }
 
273
 
 
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;
 
277
                if (row > row_max) {
 
278
                        row = row_max;
 
279
                }
 
280
        }
 
281
        else {
 
282
                if (r->in.pStat->CurrentRec == MID_BEGINNING_OF_TABLE) {
 
283
                        row = 0;
 
284
                }
 
285
                else if (r->in.pStat->CurrentRec == MID_END_OF_TABLE) {
 
286
                        row = row_max;
 
287
                }
 
288
                else {
 
289
                        retval = MAPI_E_NOT_FOUND;
 
290
                        row = 0;
 
291
                        while (row < row_max) {
 
292
                                if ((uint32_t) mids->aulPropTag[row] == (uint32_t) r->in.pStat->CurrentRec) {
 
293
                                        retval = MAPI_E_SUCCESS;
 
294
                                        break;
 
295
                                }
 
296
                                else {
 
297
                                        row++;
 
298
                                }
 
299
                        }
 
300
                        if (retval == MAPI_E_NOT_FOUND) {
 
301
                                goto end;
 
302
                        }
 
303
                }
 
304
        }
 
305
 
 
306
        if (-r->in.pStat->Delta > row) {
 
307
                row = 0;
 
308
                r->in.pStat->CurrentRec = mids->aulPropTag[row];
 
309
        }
 
310
        else if (r->in.pStat->Delta + row >= row_max) {
 
311
                row = row_max;
 
312
                r->in.pStat->CurrentRec = MID_END_OF_TABLE;
 
313
        }
 
314
        else {
 
315
                row += r->in.pStat->Delta;
 
316
                r->in.pStat->CurrentRec = mids->aulPropTag[row];
 
317
        }
 
318
 
 
319
        r->in.pStat->Delta = 0;
 
320
        r->in.pStat->NumPos = row;
 
321
        r->in.pStat->TotalRecs = row_max;
 
322
 
 
323
end:
 
324
        r->out.pStat = r->in.pStat;
 
325
 
 
326
        DCESRV_NSP_RETURN(r, retval, local_mem_ctx);
213
327
}
214
328
 
215
 
 
216
329
/**
217
330
   \details exchange_nsp NspiQueryRows (0x3) function
218
331
 
222
335
 
223
336
   \return MAPI_E_SUCCESS on success
224
337
 */
225
 
static enum MAPISTATUS dcesrv_NspiQueryRows(struct dcesrv_call_state *dce_call,
226
 
                                            TALLOC_CTX *mem_ctx,
227
 
                                            struct NspiQueryRows *r)
 
338
static void dcesrv_NspiQueryRows(struct dcesrv_call_state *dce_call,
 
339
                                 TALLOC_CTX *mem_ctx,
 
340
                                 struct NspiQueryRows *r)
228
341
{
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;
234
 
        uint32_t                        i;
235
 
        bool                            found = false;
 
346
        uint32_t                        i, j;
236
347
 
237
348
        DEBUG(3, ("exchange_nsp: NspiQueryRows (0x3)\n"));
238
349
 
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;
243
 
        }
244
 
 
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;
248
 
                        found = true;
249
 
                }
250
 
        }
251
 
 
252
 
        OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
 
353
                DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
 
354
        }
 
355
 
 
356
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
357
        if (!emsabp_ctx) {
 
358
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
359
        }
253
360
 
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;
257
364
                goto failure;
258
365
        }
283
390
                if (!MAPI_STATUS_IS_OK(retval))  {
284
391
                        goto failure;
285
392
                }
 
393
 
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);
289
397
                }
290
398
 
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)) {
296
404
                                goto failure;
297
405
                        }
298
406
                }
 
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;
299
411
        } else {
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) {
306
 
                                goto failure;
 
413
                j = 0;
 
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) {
 
420
                                        goto failure;
 
421
                                }
 
422
                                j++;
307
423
                        }
308
424
                }
 
425
                r->in.pStat->CurrentRec = MID_END_OF_TABLE;
 
426
                r->in.pStat->TotalRecs = j;
 
427
                r->in.pStat->Delta = 0;
309
428
        }
310
429
 
311
430
        /* Step 3. Fill output params */
312
431
        *r->out.ppRows = pRows;
313
432
 
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;
318
 
 
319
 
        return MAPI_E_SUCCESS;
320
 
 
 
434
 
 
435
        DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL);
321
436
failure:
322
437
        r->out.pStat = r->in.pStat;
323
438
        *r->out.ppRows = NULL;
324
 
        r->out.result = retval;
325
 
 
326
 
        return retval;
 
439
        DCESRV_NSP_RETURN(r, retval, NULL);
327
440
}
328
441
 
329
442
 
336
449
 
337
450
   \return MAPI_E_SUCCESS on success
338
451
 */
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)
342
455
{
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;
 
458
        uint32_t                        row;
 
459
        struct PropertyTagArray_r       *mids, *all_mids;
 
460
        struct Restriction_r            *seek_restriction;
 
461
 
 
462
        DEBUG(3, ("exchange_nsp: NspiSeekEntries (0x4)\n"));
 
463
 
 
464
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
465
        if (!emsabp_ctx) {
 
466
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
467
        }
 
468
 
 
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;
 
472
                goto end;
 
473
        }
 
474
 
 
475
        if (!r->in.pTarget) {
 
476
                retval = MAPI_E_INVALID_PARAMETER;
 
477
                goto end;
 
478
        }
 
479
 
 
480
        if (r->in.lpETable) {
 
481
                all_mids = r->in.lpETable;
 
482
        }
 
483
        else {
 
484
                all_mids = talloc_zero(mem_ctx, struct PropertyTagArray_r);
 
485
                emsabp_search(mem_ctx, emsabp_ctx, all_mids, NULL, r->in.pStat, 0);
 
486
        }
 
487
 
 
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;
 
494
 
 
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) {
 
497
                mids = all_mids;
 
498
                retval = MAPI_E_NOT_FOUND;
 
499
        }
 
500
 
 
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;
 
507
                        break;
 
508
                }
 
509
        }
 
510
 
 
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;
 
515
                goto end;
 
516
        }
 
517
 
 
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);
 
525
                if (ret) {
 
526
                        retval = ret;
 
527
                        DEBUG(5, ("failure looking up value %d\n", row));
 
528
                        goto end;
 
529
                }
 
530
        }
 
531
 
 
532
end:
 
533
 
 
534
        DCESRV_NSP_RETURN(r, retval, NULL);
345
535
}
346
536
 
347
537
 
354
544
 
355
545
   \return MAPI_E_SUCCESS on success
356
546
 */
357
 
static enum MAPISTATUS dcesrv_NspiGetMatches(struct dcesrv_call_state *dce_call,
 
547
static void dcesrv_NspiGetMatches(struct dcesrv_call_state *dce_call,
358
548
                                             TALLOC_CTX *mem_ctx,
359
549
                                             struct NspiGetMatches *r)
360
550
{
361
551
        enum MAPISTATUS                 retval;
362
 
        struct exchange_nsp_session     *session;
363
552
        struct emsabp_context           *emsabp_ctx = NULL;
364
553
        struct PropertyTagArray_r       *ppOutMIds = NULL;
365
554
        uint32_t                        i;
366
 
        bool                            found = false;
367
555
        
368
556
 
369
557
        DEBUG(3, ("exchange_nsp: NspiGetMatches (0x5)\n"));
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;
375
 
        }
376
 
 
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;
380
 
                        found = true;
381
 
                }
382
 
        }
383
 
 
384
 
        OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
 
562
                DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
 
563
        }
 
564
 
 
565
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
566
        if (!emsabp_ctx) {
 
567
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
568
        }
385
569
 
386
570
        /* Step 1. Retrieve MIds array given search criterias */
387
571
        ppOutMIds = talloc_zero(mem_ctx, struct PropertyTagArray_r);
395
579
                *r->out.ppOutMIds = ppOutMIds;  
396
580
                r->out.ppRows = talloc(mem_ctx, struct SRowSet *);
397
581
                r->out.ppRows[0] = NULL;
398
 
                r->out.result = retval;
399
 
                
400
 
                return retval;
 
582
                DCESRV_NSP_RETURN(r, retval, NULL);
401
583
        }
402
584
 
403
585
        *r->out.ppOutMIds = ppOutMIds;
407
589
        r->out.ppRows[0] = talloc_zero(mem_ctx, struct SRowSet);
408
590
        r->out.ppRows[0]->cRows = ppOutMIds->cValues;
409
591
        r->out.ppRows[0]->aRow = talloc_array(mem_ctx, struct SRow, ppOutMIds->cValues);
410
 
        
411
592
 
412
593
        for (i = 0; i < ppOutMIds->cValues; i++) {
413
594
                retval = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, &(r->out.ppRows[0]->aRow[i]), 
414
595
                                            ppOutMIds->aulPropTag[i], fEphID, r->in.pPropTags);
415
 
                if (retval) goto failure;
 
596
                if (retval) {
 
597
                        DEBUG(5, ("failure looking up value %d\n", i));
 
598
                        goto failure;
 
599
                }
416
600
        }
417
601
 
418
 
        r->out.result = MAPI_E_SUCCESS;
419
 
 
420
 
        return MAPI_E_SUCCESS;
 
602
        DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL);
421
603
}
422
604
 
423
605
 
430
612
 
431
613
   \return MAPI_E_SUCCESS on success
432
614
 */
433
 
static enum MAPISTATUS dcesrv_NspiResortRestriction(struct dcesrv_call_state *dce_call,
 
615
static void dcesrv_NspiResortRestriction(struct dcesrv_call_state *dce_call,
434
616
                                                    TALLOC_CTX *mem_ctx,
435
617
                                                    struct NspiResortRestriction *r)
436
618
{
437
619
        DEBUG(3, ("exchange_nsp: NspiResortRestriction (0x6) not implemented\n"));
438
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
620
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
439
621
}
440
622
 
441
623
 
451
633
 
452
634
   \return MAPI_E_SUCCESS on success
453
635
 */
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)
457
639
{
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;
462
643
        uint32_t                        i;
463
644
        uint32_t                        MId;
464
645
        const char                      *dn;
465
646
        bool                            pbUseConfPartition;
466
 
        bool                            found = false;
467
647
 
468
648
        DEBUG(3, ("exchange_nsp: NspiDNToMId (0x7)\n"));
469
649
 
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;
474
 
        }
475
 
 
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;
479
 
                        found = true;
480
 
                }
481
 
        }
482
 
 
483
 
        OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
 
653
                DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
 
654
        }
 
655
 
 
656
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
657
        if (!emsabp_ctx) {
 
658
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
659
        }
484
660
        
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);
504
680
                }
505
681
        }
506
682
 
507
 
        r->out.result = MAPI_E_SUCCESS;
508
 
 
509
 
        return MAPI_E_SUCCESS;
 
683
        DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL);
510
684
}
511
685
 
512
686
 
519
693
 
520
694
   \return MAPI_E_SUCCESS on success
521
695
 */
522
 
static enum MAPISTATUS dcesrv_NspiGetPropList(struct dcesrv_call_state *dce_call,
 
696
static void dcesrv_NspiGetPropList(struct dcesrv_call_state *dce_call,
523
697
                                              TALLOC_CTX *mem_ctx,
524
698
                                              struct NspiGetPropList *r)
525
699
{
526
700
        DEBUG(3, ("exchange_nsp: NspiGetPropList (0x8) not implemented\n"));
527
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
701
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
528
702
}
529
703
 
530
704
 
537
711
 
538
712
   \return MAPI_E_SUCCESS on success
539
713
 */
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)
543
717
{
544
718
        enum MAPISTATUS                 retval;
545
 
        struct exchange_nsp_session     *session;
546
719
        struct emsabp_context           *emsabp_ctx = NULL;
547
720
        uint32_t                        MId;
548
 
        uint32_t                        i;
549
 
        bool                            found = false;
 
721
        int                             i;
 
722
        struct SPropTagArray            *pPropTags;
550
723
 
551
724
        DEBUG(3, ("exchange_nsp: NspiGetProps (0x9)\n"));
552
725
 
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;
557
 
        }
558
 
 
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;
562
 
                        found = true;
563
 
                }
564
 
        }
565
 
 
566
 
        OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
 
729
                DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
 
730
        }
 
731
 
 
732
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
733
        if (!emsabp_ctx) {
 
734
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
735
        }
567
736
 
568
737
        MId = r->in.pStat->CurrentRec;
569
738
        
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;
574
 
                return retval;
 
741
                DCESRV_NSP_RETURN(r, MAPI_E_INVALID_BOOKMARK, NULL);
575
742
        }
576
743
 
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;
581
748
 
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;
 
750
        if (!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;
 
765
        }
 
766
 
 
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) {
603
788
                        talloc_free(r->out.ppRows);
604
789
                        r->out.ppRows = NULL;
605
790
                }
606
 
                r->out.result = retval;
607
 
                return r->out.result;
 
791
                DCESRV_NSP_RETURN(r, retval, NULL);
608
792
        }
609
793
 
610
794
        /* Step 3. Properties are fetched. Provide proper return
617
801
                }
618
802
        }
619
803
 
620
 
        r->out.result = retval;
621
 
        return retval;
 
804
        DCESRV_NSP_RETURN(r, retval, NULL);
622
805
}
623
806
 
624
807
 
631
814
 
632
815
   \return MAPI_E_SUCCESS on success
633
816
*/
634
 
static enum MAPISTATUS dcesrv_NspiCompareMIds(struct dcesrv_call_state *dce_call,
 
817
static void dcesrv_NspiCompareMIds(struct dcesrv_call_state *dce_call,
635
818
                                              TALLOC_CTX *mem_ctx,
636
819
                                              struct NspiCompareMIds *r)
637
820
{
638
821
        DEBUG(3, ("exchange_nsp: NspiCompareMIds (0xA) not implemented\n"));
639
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
822
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
640
823
}
641
824
 
642
825
 
650
833
   \return MAPI_E_SUCCESS on success
651
834
 
652
835
 */
653
 
static enum MAPISTATUS dcesrv_NspiModProps(struct dcesrv_call_state *dce_call,
 
836
static void dcesrv_NspiModProps(struct dcesrv_call_state *dce_call,
654
837
                                           TALLOC_CTX *mem_ctx,
655
838
                                           struct NspiModProps *r)
656
839
{
657
840
        DEBUG(3, ("exchange_nsp: NspiModProps (0xB) not implemented\n"));
658
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
841
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
659
842
}
660
843
 
661
844
 
673
856
   \return MAPI_E_SUCCESS on success
674
857
 
675
858
 */
676
 
static enum MAPISTATUS dcesrv_NspiGetSpecialTable(struct dcesrv_call_state *dce_call,
677
 
                                                  TALLOC_CTX *mem_ctx,
678
 
                                                  struct NspiGetSpecialTable *r)
 
859
static void dcesrv_NspiGetSpecialTable(struct dcesrv_call_state *dce_call,
 
860
                                       TALLOC_CTX *mem_ctx,
 
861
                                       struct NspiGetSpecialTable *r)
679
862
{
680
 
        struct exchange_nsp_session     *session;
681
863
        struct emsabp_context           *emsabp_ctx = NULL;
682
 
        bool                            found = false;
683
864
 
684
865
        DEBUG(3, ("exchange_nsp: NspiGetSpecialTable (0xC)\n"));
685
866
 
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;
690
 
        }
691
 
 
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;
695
 
                        found = true;
696
 
                }
697
 
        }
698
 
 
699
 
        OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
 
870
                DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
 
871
        }
 
872
 
 
873
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
874
        if (!emsabp_ctx) {
 
875
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
876
        }
700
877
 
701
878
        /* Step 1. (FIXME) We arbitrary set lpVersion to 0x1 */
702
879
        r->out.lpVersion = talloc_zero(mem_ctx, uint32_t);
704
881
 
705
882
        /* Step 2. Allocate output SRowSet and call associated emsabp function */
706
883
        r->out.ppRows = talloc_zero(mem_ctx, struct SRowSet *);
707
 
        OPENCHANGE_RETVAL_IF(!r->out.ppRows, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
 
884
        if (!r->out.ppRows) {
 
885
                DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
 
886
        }
708
887
        r->out.ppRows[0] = talloc_zero(mem_ctx, struct SRowSet);
709
 
        OPENCHANGE_RETVAL_IF(!r->out.ppRows[0], MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
 
888
        if (!r->out.ppRows[0]) {
 
889
                DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
 
890
        }
710
891
 
711
892
        switch (r->in.dwFlags) {
712
893
        case NspiAddressCreationTemplates:
722
903
        default:
723
904
                talloc_free(r->out.ppRows);
724
905
                talloc_free(r->out.ppRows[0]);
725
 
                return MAPI_E_NO_SUPPORT;
 
906
                DCESRV_NSP_RETURN(r, MAPI_E_NO_SUPPORT, NULL);
726
907
        }
727
 
 
728
 
        return r->out.result;
729
908
}
730
909
 
731
910
 
739
918
   \return MAPI_E_SUCCESS on success
740
919
 
741
920
 */
742
 
static enum MAPISTATUS dcesrv_NspiGetTemplateInfo(struct dcesrv_call_state *dce_call,
743
 
                                                  TALLOC_CTX *mem_ctx,
744
 
                                                  struct NspiGetTemplateInfo *r)
 
921
static void dcesrv_NspiGetTemplateInfo(struct dcesrv_call_state *dce_call,
 
922
                                       TALLOC_CTX *mem_ctx,
 
923
                                       struct NspiGetTemplateInfo *r)
745
924
{
746
925
        DEBUG(3, ("exchange_nsp: NspiGetTemplateInfo (0xD) not implemented\n"));
747
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
926
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
748
927
}
749
928
 
750
929
 
758
937
   \return MAPI_E_SUCCESS on success
759
938
 
760
939
 */
761
 
static enum MAPISTATUS dcesrv_NspiModLinkAtt(struct dcesrv_call_state *dce_call,
762
 
                                             TALLOC_CTX *mem_ctx,
763
 
                                             struct NspiModLinkAtt *r)
 
940
static void dcesrv_NspiModLinkAtt(struct dcesrv_call_state *dce_call,
 
941
                                  TALLOC_CTX *mem_ctx,
 
942
                                  struct NspiModLinkAtt *r)
764
943
{
765
944
        DEBUG(3, ("exchange_nsp: NspiModLinkAtt (0xE) not implemented\n"));
766
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
945
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
767
946
}
768
947
 
769
948
 
777
956
   \return MAPI_E_SUCCESS on success
778
957
 
779
958
 */
780
 
static enum MAPISTATUS dcesrv_NspiDeleteEntries(struct dcesrv_call_state *dce_call,
781
 
                                                TALLOC_CTX *mem_ctx,
782
 
                                                struct NspiDeleteEntries *r)
 
959
static void dcesrv_NspiDeleteEntries(struct dcesrv_call_state *dce_call,
 
960
                                     TALLOC_CTX *mem_ctx,
 
961
                                     struct NspiDeleteEntries *r)
783
962
{
784
963
        DEBUG(3, ("exchange_nsp: NspiDeleteEntries (0xF) not implemented\n"));
785
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
964
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
786
965
}
787
966
 
788
967
 
796
975
   \return MAPI_E_SUCCESS on success
797
976
 
798
977
 */
799
 
static enum MAPISTATUS dcesrv_NspiQueryColumns(struct dcesrv_call_state *dce_call,
800
 
                                               TALLOC_CTX *mem_ctx,
801
 
                                               struct NspiQueryColumns *r)
 
978
static void dcesrv_NspiQueryColumns(struct dcesrv_call_state *dce_call,
 
979
                                    TALLOC_CTX *mem_ctx,
 
980
                                    struct NspiQueryColumns *r)
802
981
{
803
982
        DEBUG(3, ("exchange_nsp: NspiQueryColumns (0x10) not implemented\n"));
804
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
983
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
805
984
}
806
985
 
807
986
 
815
994
   \return MAPI_E_SUCCESS on success
816
995
 
817
996
 */
818
 
static enum MAPISTATUS dcesrv_NspiGetNamesFromIDs(struct dcesrv_call_state *dce_call,
819
 
                                                  TALLOC_CTX *mem_ctx,
820
 
                                                  struct NspiGetNamesFromIDs *r)
 
997
static void dcesrv_NspiGetNamesFromIDs(struct dcesrv_call_state *dce_call,
 
998
                                       TALLOC_CTX *mem_ctx,
 
999
                                       struct NspiGetNamesFromIDs *r)
821
1000
{
822
1001
        DEBUG(3, ("exchange_nsp: NspiGetNamesFromIDs (0x11) not implemented\n"));
823
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
1002
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
824
1003
}
825
1004
 
826
1005
 
834
1013
   \return MAPI_E_SUCCESS on success
835
1014
 
836
1015
 */
837
 
static enum MAPISTATUS dcesrv_NspiGetIDsFromNames(struct dcesrv_call_state *dce_call,
838
 
                                                  TALLOC_CTX *mem_ctx,
839
 
                                                  struct NspiGetIDsFromNames *r)
 
1016
static void dcesrv_NspiGetIDsFromNames(struct dcesrv_call_state *dce_call,
 
1017
                                       TALLOC_CTX *mem_ctx,
 
1018
                                       struct NspiGetIDsFromNames *r)
840
1019
{
841
1020
        DEBUG(3, ("exchange_nsp: NspiGetIDsFromNames (0x12) not implemented\n"));
842
 
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
1021
        DCESRV_NSP_RETURN(r, DCERPC_FAULT_OP_RNG_ERROR, NULL);
843
1022
}
844
1023
 
845
1024
 
853
1032
   \return MAPI_E_SUCCESS on success
854
1033
 
855
1034
 */
856
 
static enum MAPISTATUS dcesrv_NspiResolveNames(struct dcesrv_call_state *dce_call,
857
 
                                               TALLOC_CTX *mem_ctx,
858
 
                                               struct NspiResolveNames *r)
 
1035
static void dcesrv_NspiResolveNames(struct dcesrv_call_state *dce_call,
 
1036
                                    TALLOC_CTX *mem_ctx,
 
1037
                                    struct NspiResolveNames *r)
859
1038
{
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;
 
1047
        uint32_t                        i;
 
1048
        int                             ret;
 
1049
        const char * const              recipient_attrs[] = { "*", NULL };
 
1050
        const char * const              search_attr[] = { "mailNickName", "mail", "name",
 
1051
                                                          "displayName", "givenName", 
 
1052
                                                          "sAMAccountName", "proxyAddresses" };
 
1053
 
 
1054
        DEBUG(3, ("exchange_nsp: NspiResolveNames (0x13)\n"));
 
1055
 
 
1056
        if (!dcesrv_call_authenticated(dce_call)) {
 
1057
                DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
 
1058
        }
 
1059
 
 
1060
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
1061
        if (!emsabp_ctx) {
 
1062
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
1063
        }
 
1064
 
 
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);
 
1069
        }
 
1070
 
 
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);
 
1074
        }
 
1075
 
 
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,
 
1080
                                              PR_OBJECT_TYPE,
 
1081
                                              PR_DISPLAY_TYPE,
 
1082
                                              PR_DISPLAY_NAME,
 
1083
                                              PR_OFFICE_TELEPHONE_NUMBER,
 
1084
                                              PR_COMPANY_NAME,
 
1085
                                              PR_OFFICE_LOCATION);
 
1086
        } else {
 
1087
                pPropTags = r->in.pPropTags;
 
1088
        }
 
1089
 
 
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);
 
1096
        pRows->cRows = 0;
 
1097
        pRows->aRow = talloc_array(mem_ctx, struct SRow, pMIds->cValues);
 
1098
 
 
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, "");
 
1103
                int                     j;
 
1104
 
 
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);
 
1110
                }
 
1111
 
 
1112
                /* Search AD */
 
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);
 
1117
 
 
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;
 
1123
                } else {
 
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);
 
1127
                        pRows->cRows++;
 
1128
                }
 
1129
        }
 
1130
 
 
1131
        *r->out.ppMIds = pMIds;
 
1132
        if (pRows->cRows) {
 
1133
                *r->out.ppRows = pRows;
 
1134
        }
 
1135
 
 
1136
        DCESRV_NSP_RETURN(r, retval, NULL);
862
1137
}
863
1138
 
864
1139
 
872
1147
   \return MAPI_E_SUCCESS on success
873
1148
 
874
1149
 */
875
 
static enum MAPISTATUS dcesrv_NspiResolveNamesW(struct dcesrv_call_state *dce_call,
876
 
                                                TALLOC_CTX *mem_ctx,
877
 
                                                struct NspiResolveNamesW *r)
 
1150
static void dcesrv_NspiResolveNamesW(struct dcesrv_call_state *dce_call,
 
1151
                                     TALLOC_CTX *mem_ctx,
 
1152
                                     struct NspiResolveNamesW *r)
878
1153
{
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;
888
1162
        uint32_t                        i;
889
1163
        int                             ret;
890
 
        bool                            found = false;
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"));
896
1169
 
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;
901
 
        }
902
 
 
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;
906
 
                        found = true;
907
 
                }
908
 
        }
909
 
 
910
 
        OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
 
1173
                DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
 
1174
        }
 
1175
 
 
1176
        emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
 
1177
        if (!emsabp_ctx) {
 
1178
                DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
 
1179
        }
911
1180
 
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);
 
1185
        }
915
1186
 
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);
 
1190
        }
918
1191
 
919
1192
        /* Set default list of property tags if none were provided in input */
920
1193
        if (!r->in.pPropTags) {
943
1216
        for (i = 0; i < paWStr->Count; i++) {
944
1217
                struct ldb_result       *ldb_res;
945
1218
                char                    *filter = talloc_strdup(mem_ctx, "");
946
 
                uint32_t                j;
 
1219
                int                     j;
947
1220
 
948
1221
                /* Build search filter */
949
1222
                for (j = 0; j < ARRAY_SIZE(search_attr); j++) {
976
1249
                *r->out.ppRows = pRows;
977
1250
        }
978
1251
 
979
 
        r->out.result = retval;
980
 
        return retval;
 
1252
        DCESRV_NSP_RETURN(r, retval, NULL);
981
1253
}
982
1254
 
983
1255
 
997
1269
                                             TALLOC_CTX *mem_ctx,
998
1270
                                             void *r, struct mapiproxy *mapiproxy)
999
1271
{
1000
 
        enum MAPISTATUS                         retval;
1001
1272
        const struct ndr_interface_table        *table;
1002
1273
        uint16_t                                opnum;
1003
1274
 
 
1275
        DEBUG (0, ("dcesrv_exchange_nsp_dispatch\n"));
 
1276
 
1004
1277
        table = (const struct ndr_interface_table *) dce_call->context->iface->private_data;
1005
1278
        opnum = dce_call->pkt.u.request.opnum;
1006
1279
 
1010
1283
 
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);
1014
1287
                break;
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);
1017
1290
                break;
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);
1020
1293
                break;
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);
1023
1296
                break;
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);
1026
1299
                break;
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);
1029
1302
                break;
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);
1032
1305
                break;
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);
1035
1308
                break;
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);
1038
1311
                break;
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);
1041
1314
                break;
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);
1044
1317
                break;
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);
1047
1320
                break;
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);
1050
1323
                break;
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);
1053
1326
                break;
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);
1056
1329
                break;
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);
1059
1332
                break;
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);
1062
1335
                break;
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);
1065
1338
                break;
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);
1068
1341
                break;
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);
1071
1344
                break;
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);
1074
1347
                break;
1075
1348
        }
1076
1349
 
1087
1360
 */
1088
1361
static NTSTATUS dcesrv_exchange_nsp_init(struct dcesrv_context *dce_ctx)
1089
1362
{
 
1363
        DEBUG (0, ("dcesrv_exchange_nsp_init\n"));
1090
1364
        /* Initialize exchange_nsp session */
1091
1365
        nsp_session = talloc_zero(dce_ctx, struct exchange_nsp_session);
1092
1366
        if (!nsp_session) return NT_STATUS_NO_MEMORY;
1114
1388
 */
1115
1389
static NTSTATUS dcesrv_exchange_nsp_unbind(struct server_id server_id, uint32_t context_id)
1116
1390
{
1117
 
        struct exchange_nsp_session     *session;
1118
 
 
1119
 
        for (session = nsp_session; session; session = session->next) {
1120
 
                if ((mpm_session_cmp_sub(session->session, server_id, context_id) == true)) {
1121
 
                        mpm_session_release(session->session);
1122
 
                        DLIST_REMOVE(nsp_session, session);
1123
 
                        DEBUG(6, ("[%s:%d]: Session found and released\n", __FUNCTION__, __LINE__));
1124
 
                        return NT_STATUS_OK;
1125
 
                }
1126
 
        }
1127
 
 
 
1391
        DEBUG (0, ("dcesrv_exchange_nsp_unbind\n"));
1128
1392
        return NT_STATUS_OK;
1129
1393
}
1130
1394