- Add doxygen comments for all OpenChange server modules
[jelmer/openchange.git] / mapiproxy / servers / default / nspi / dcesrv_exchange_nsp.c
1 /*
2    MAPI Proxy - Exchange NSPI Server
3
4    OpenChange Project
5
6    Copyright (C) Julien Kerihuel 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /**
23    \file dcesrv_exchange_nsp.c
24
25    \brief OpenChange NSPI Server implementation
26  */
27
28 #include "mapiproxy/dcesrv_mapiproxy.h"
29 #include "mapiproxy/libmapiproxy.h"
30 #include "dcesrv_exchange_nsp.h"
31
32 struct exchange_nsp_session     *nsp_session = NULL;
33
34 /**
35    \details exchange_nsp NspiBind (0x0) function, Initiates a NSPI
36    session with the client.
37
38    This function checks if the user is an Exchange user and input
39    parameters like codepage are valid. If it passes the tests, the
40    function initializes an emsabp context and returns to the client a
41    valid policy_handle and expected reply parameters.
42
43    \param dce_call pointer to the session context
44    \param mem_ctx pointer to the memory context
45    \param r pointer to the NspiBind call structure
46
47    \return MAPI_E_SUCCESS on success, otherwise a MAPI error
48  */
49 static enum MAPISTATUS dcesrv_NspiBind(struct dcesrv_call_state *dce_call,
50                                        TALLOC_CTX *mem_ctx,
51                                        struct NspiBind *r)
52 {
53         struct GUID                     *guid = (struct GUID *) NULL;
54         struct emsabp_context           *emsabp_ctx;
55         struct dcesrv_handle            *handle;
56         struct policy_handle            wire_handle;
57         struct exchange_nsp_session     *session;
58
59         DEBUG(5, ("exchange_nsp: NspiBind (0x0)\n"));
60
61         /* Step 0. Ensure incoming user is authenticated */
62         if (!NTLM_AUTH_IS_OK(dce_call)) {
63                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
64
65                 wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
66                 wire_handle.uuid = GUID_zero();
67                 *r->out.handle = wire_handle;
68
69                 r->out.mapiuid = r->in.mapiuid;
70                 r->out.result = MAPI_E_LOGON_FAILED;
71                 return MAPI_E_LOGON_FAILED;             
72         }
73         
74         /* Step 1. Initialize the emsabp context */
75         emsabp_ctx = emsabp_init(dce_call->conn->dce_ctx->lp_ctx);
76         OPENCHANGE_RETVAL_IF(!emsabp_ctx, MAPI_E_FAILONEPROVIDER, NULL);
77
78         /* Step 2. Check if incoming user belongs to the Exchange organization */
79         if (emsabp_verify_user(dce_call, emsabp_ctx) == false) {
80                 talloc_free(emsabp_ctx);
81
82                 wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
83                 wire_handle.uuid = GUID_zero();
84                 *r->out.handle = wire_handle;
85
86                 r->out.mapiuid = r->in.mapiuid;
87                 r->out.result = MAPI_E_LOGON_FAILED;
88                 return MAPI_E_LOGON_FAILED;
89         }
90
91         /* Step 3. Check if valid cpID has been supplied */
92         if (emsabp_verify_codepage(dce_call->conn->dce_ctx->lp_ctx, 
93                                    emsabp_ctx, r->in.pStat->CodePage) == false) {
94                 talloc_free(emsabp_ctx);
95
96                 wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
97                 wire_handle.uuid = GUID_zero();
98                 *r->out.handle = wire_handle;
99
100                 r->out.mapiuid = r->in.mapiuid;
101                 r->out.result = MAPI_E_UNKNOWN_CPID;
102                 return MAPI_E_UNKNOWN_CPID;
103         }
104
105         /* Step 4. Retrieve OpenChange server GUID */
106         guid = emsabp_get_server_GUID(dce_call->conn->dce_ctx->lp_ctx, emsabp_ctx);
107         OPENCHANGE_RETVAL_IF(!guid, MAPI_E_FAILONEPROVIDER, emsabp_ctx);
108
109         /* Step 5. Fill NspiBind reply */
110         handle = dcesrv_handle_new(dce_call->context, EXCHANGE_HANDLE_NSP);
111         OPENCHANGE_RETVAL_IF(!handle, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
112
113         handle->data = (void *) emsabp_ctx;
114         *r->out.handle = handle->wire_handle;
115         r->out.mapiuid = guid;
116         r->out.result = MAPI_E_SUCCESS;
117
118         /* Step 6. Associate this emsabp context to the session */
119         session = talloc((TALLOC_CTX *)nsp_session, struct exchange_nsp_session);
120         OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
121
122         session->session = mpm_session_init((TALLOC_CTX *)nsp_session, dce_call);
123         OPENCHANGE_RETVAL_IF(!session->session, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
124
125         mpm_session_set_private_data(session->session, (void *) emsabp_ctx);
126         mpm_session_set_destructor(session->session, emsabp_destructor);
127
128         DLIST_ADD_END(nsp_session, session, struct exchange_nsp_session *);
129
130         return MAPI_E_SUCCESS;
131 }
132
133
134 /**
135    \details exchange_nsp NspiUnbind (0x1) function, Terminates a NSPI
136    session with the client
137
138    \param dce_call pointer to the session context
139    \param mem_ctx pointer to the memory context
140    \param r pointer to the NspiUnbind call structure
141  */
142 static enum MAPISTATUS dcesrv_NspiUnbind(struct dcesrv_call_state *dce_call,
143                                          TALLOC_CTX *mem_ctx,
144                                          struct NspiUnbind *r)
145 {
146         struct dcesrv_handle            *h;
147         struct exchange_nsp_session     *session;
148
149         DEBUG(5, ("exchange_nsp: NspiUnbind (0x1)\n"));
150
151         /* Step 0. Ensure incoming user is authenticated */
152         if (!NTLM_AUTH_IS_OK(dce_call)) {
153                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
154                 return MAPI_E_LOGON_FAILED;
155         }
156
157         /* Step 1. Retrieve handle and free if emsabp context and session are available */
158         h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
159         if (h) {
160                 for (session = nsp_session; session; session = session->next) {
161                         if ((mpm_session_cmp(session->session, dce_call) == true)) {
162                                 mpm_session_release(session->session);
163                                 DLIST_REMOVE(nsp_session, session);
164                                 DEBUG(6, ("[%s:%d]: Session found and released\n", __FUNCTION__, __LINE__));
165                         }
166                 }
167         }
168
169         r->out.result = 1;
170
171         return MAPI_E_SUCCESS;
172 }
173
174
175 /**
176    \details exchange_nsp NspiUpdateStat (0x2) function
177
178    \param dce_call pointer to the session context
179    \param mem_ctx pointer to the memory context
180    \param r pointer to the NspiUpdateStat request data
181
182    \return MAPI_E_SUCCESS on success
183 */
184 static enum MAPISTATUS dcesrv_NspiUpdateStat(struct dcesrv_call_state *dce_call, 
185                                              TALLOC_CTX *mem_ctx,
186                                              struct NspiUpdateStat *r)
187 {
188         DEBUG(3, ("exchange_nsp: NspiUpdateStat (0x2) not implemented\n"));
189         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
190 }
191
192
193 /**
194    \details exchange_nsp NspiQueryRows (0x3) function
195
196    \param dce_call pointer to the session context
197    \param mem_ctx pointer to the memory context
198    \param r pointer to the NspiQueryRows request data
199
200    \return MAPI_E_SUCCESS on success
201  */
202 static enum MAPISTATUS dcesrv_NspiQueryRows(struct dcesrv_call_state *dce_call,
203                                             TALLOC_CTX *mem_ctx,
204                                             struct NspiQueryRows *r)
205 {
206         DEBUG(3, ("exchange_nsp: NspiQueryRows (0x3) not implemented\n"));
207         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
208 }
209
210
211 /**
212    \details exchange_nsp NspiSeekEntries (0x4) function
213
214    \param dce_call pointer to the session context
215    \param mem_ctx pointer to the memory context
216    \param r pointer to the NspiSeekEntries request data
217
218    \return MAPI_E_SUCCESS on success
219  */
220 static enum MAPISTATUS dcesrv_NspiSeekEntries(struct dcesrv_call_state *dce_call,
221                                               TALLOC_CTX *mem_ctx,
222                                               struct NspiSeekEntries *r)
223 {
224         DEBUG(3, ("exchange_nsp: NspiSeekEntries (0x4) not implemented\n"));
225         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
226 }
227
228
229 /**
230    \details exchange_nsp NspiGetMatches (0x5) function
231
232    \param dce_call pointer to the session context
233    \param mem_ctx pointer to the memory context
234    \param r pointer to the NspiGetMatches request data
235
236    \return MAPI_E_SUCCESS on success
237  */
238 static enum MAPISTATUS dcesrv_NspiGetMatches(struct dcesrv_call_state *dce_call,
239                                              TALLOC_CTX *mem_ctx,
240                                              struct NspiGetMatches *r)
241 {
242         DEBUG(3, ("exchange_nsp: NspiGetMatches (0x5) not implemented\n"));
243         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
244 }
245
246
247 /**
248    \details exchange_nsp NspiResortRestriction (0x6) function
249
250    \param dce_call pointer to the session context
251    \param mem_ctx pointer to the memory context
252    \param r pointer to the NspiResortRestriction request data
253
254    \return MAPI_E_SUCCESS on success
255  */
256 static enum MAPISTATUS dcesrv_NspiResortRestriction(struct dcesrv_call_state *dce_call,
257                                                     TALLOC_CTX *mem_ctx,
258                                                     struct NspiResortRestriction *r)
259 {
260         DEBUG(3, ("exchange_nsp: NspiResortRestriction (0x6) not implemented\n"));
261         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
262 }
263
264
265 /**
266    \details exchange_nsp NspiDNToMId (0x7) function
267
268    \param dce_call pointer to the session context
269    \param mem_ctx pointer to the memory context
270    \param r pointer to the NspiDNToMId request data
271
272    \return MAPI_E_SUCCESS on success
273  */
274 static enum MAPISTATUS dcesrv_NspiDNToMId(struct dcesrv_call_state *dce_call,
275                                           TALLOC_CTX *mem_ctx,
276                                           struct NspiDNToMId *r)
277 {
278         DEBUG(3, ("exchange_nsp: NspiDNToMId (0x7) not implemented\n"));
279         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
280 }
281
282
283 /**
284    \details exchange_nsp NspiGetPropList (0x8) function
285
286    \param dce_call pointer to the session context
287    \param mem_ctx pointer to the memory context
288    \param r pointer to the NspiGetPropList request data
289
290    \return MAPI_E_SUCCESS on success
291  */
292 static enum MAPISTATUS dcesrv_NspiGetPropList(struct dcesrv_call_state *dce_call,
293                                               TALLOC_CTX *mem_ctx,
294                                               struct NspiGetPropList *r)
295 {
296         DEBUG(3, ("exchange_nsp: NspiGetPropList (0x8) not implemented\n"));
297         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
298 }
299
300
301 /**
302    \details exchange_nsp NspiGetProps (0x9) function
303
304    \param dce_call pointer to the session context
305    \param mem_ctx pointer to the memory context
306    \param r pointer to the NspiGetProps request data
307
308    \return MAPI_E_SUCCESS on success
309  */
310 static enum MAPISTATUS dcesrv_NspiGetProps(struct dcesrv_call_state *dce_call,
311                                            TALLOC_CTX *mem_ctx,
312                                            struct NspiGetProps *r)
313 {
314         DEBUG(3, ("exchange_nsp: NspiGetProps (0x9) not implemented\n"));
315         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
316 }
317
318
319 /**
320    \details exchange_nsp NspiCompareMIds (0xA) function
321
322    \param dce_call pointer to the session context
323    \param mem_ctx pointer to the memory context
324    \param r pointer to the NspiCompareMIds request data
325
326    \return MAPI_E_SUCCESS on success
327 */
328 static enum MAPISTATUS dcesrv_NspiCompareMIds(struct dcesrv_call_state *dce_call,
329                                               TALLOC_CTX *mem_ctx,
330                                               struct NspiCompareMIds *r)
331 {
332         DEBUG(3, ("exchange_nsp: NspiCompareMIds (0xA) not implemented\n"));
333         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
334 }
335
336
337 /**
338    \details exchange_nsp NspiModProps (0xB) function
339
340    \param dce_call pointer to the session context
341    \param mem_ctx pointer to the memory context
342    \param r pointer to the NspiModProps request data
343
344    \return MAPI_E_SUCCESS on success
345
346  */
347 static enum MAPISTATUS dcesrv_NspiModProps(struct dcesrv_call_state *dce_call,
348                                            TALLOC_CTX *mem_ctx,
349                                            struct NspiModProps *r)
350 {
351         DEBUG(3, ("exchange_nsp: NspiModProps (0xB) not implemented\n"));
352         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
353 }
354
355
356 /**
357    \details exchange_nsp NspiGetSpecialTable (0xC) function
358
359    \param dce_call pointer to the session context
360    \param mem_ctx pointer to the memory context
361    \param r pointer to the NspiGetSpecialTable request data
362
363    \return MAPI_E_SUCCESS on success
364
365  */
366 static enum MAPISTATUS dcesrv_NspiGetSpecialTable(struct dcesrv_call_state *dce_call,
367                                                   TALLOC_CTX *mem_ctx,
368                                                   struct NspiGetSpecialTable *r)
369 {
370         DEBUG(3, ("exchange_nsp: NspiGetSpecialTable (0xC) not implemented\n"));
371         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
372 }
373
374
375 /**
376    \details exchange_nsp NspiGetTemplateInfo (0xD) function
377
378    \param dce_call pointer to the session context
379    \param mem_ctx pointer to the memory context
380    \param r pointer to the NspiGetTemplateInfo request data
381
382    \return MAPI_E_SUCCESS on success
383
384  */
385 static enum MAPISTATUS dcesrv_NspiGetTemplateInfo(struct dcesrv_call_state *dce_call,
386                                                   TALLOC_CTX *mem_ctx,
387                                                   struct NspiGetTemplateInfo *r)
388 {
389         DEBUG(3, ("exchange_nsp: NspiGetTemplateInfo (0xD) not implemented\n"));
390         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
391 }
392
393
394 /**
395    \details exchange_nsp NspiModLinkAtt (0xE) function
396
397    \param dce_call pointer to the session context
398    \param mem_ctx pointer to the memory context
399    \param r pointer to the NspiModLinkAtt request data
400
401    \return MAPI_E_SUCCESS on success
402
403  */
404 static enum MAPISTATUS dcesrv_NspiModLinkAtt(struct dcesrv_call_state *dce_call,
405                                              TALLOC_CTX *mem_ctx,
406                                              struct NspiModLinkAtt *r)
407 {
408         DEBUG(3, ("exchange_nsp: NspiModLinkAtt (0xE) not implemented\n"));
409         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
410 }
411
412
413 /**
414    \details exchange_nsp NspiDeleteEntries (0xF) function
415
416    \param dce_call pointer to the session context
417    \param mem_ctx pointer to the memory context
418    \param r pointer to the NspiDeleteEntries request data
419
420    \return MAPI_E_SUCCESS on success
421
422  */
423 static enum MAPISTATUS dcesrv_NspiDeleteEntries(struct dcesrv_call_state *dce_call,
424                                                 TALLOC_CTX *mem_ctx,
425                                                 struct NspiDeleteEntries *r)
426 {
427         DEBUG(3, ("exchange_nsp: NspiDeleteEntries (0xF) not implemented\n"));
428         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
429 }
430
431
432 /**
433    \details exchange_nsp NspiQueryColumns (0x10) function
434
435    \param dce_call pointer to the session context
436    \param mem_ctx pointer to the memory context
437    \param r pointer to the NspiQueryColumns request data
438
439    \return MAPI_E_SUCCESS on success
440
441  */
442 static enum MAPISTATUS dcesrv_NspiQueryColumns(struct dcesrv_call_state *dce_call,
443                                                TALLOC_CTX *mem_ctx,
444                                                struct NspiQueryColumns *r)
445 {
446         DEBUG(3, ("exchange_nsp: NspiQueryColumns (0x10) not implemented\n"));
447         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
448 }
449
450
451 /**
452    \details exchange_nsp NspiGetNamesFromIDs (0x11) function
453
454    \param dce_call pointer to the session context
455    \param mem_ctx pointer to the memory context
456    \param r pointer to the NspiGetNamesFromIDs request data
457
458    \return MAPI_E_SUCCESS on success
459
460  */
461 static enum MAPISTATUS dcesrv_NspiGetNamesFromIDs(struct dcesrv_call_state *dce_call,
462                                                   TALLOC_CTX *mem_ctx,
463                                                   struct NspiGetNamesFromIDs *r)
464 {
465         DEBUG(3, ("exchange_nsp: NspiGetNamesFromIDs (0x11) not implemented\n"));
466         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
467 }
468
469
470 /**
471    \details exchange_nsp NspiGetIDsFromNames (0x12) function
472
473    \param dce_call pointer to the session context
474    \param mem_ctx pointer to the memory context
475    \param r pointer to the NspiGetIDsFromNames request data
476
477    \return MAPI_E_SUCCESS on success
478
479  */
480 static enum MAPISTATUS dcesrv_NspiGetIDsFromNames(struct dcesrv_call_state *dce_call,
481                                                   TALLOC_CTX *mem_ctx,
482                                                   struct NspiGetIDsFromNames *r)
483 {
484         DEBUG(3, ("exchange_nsp: NspiGetIDsFromNames (0x12) not implemented\n"));
485         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
486 }
487
488
489 /**
490    \details exchange_nsp NspiResolveNames (0x13) function
491
492    \param dce_call pointer to the session context
493    \param mem_ctx pointer to the memory context
494    \param r pointer to the NspiResolveNames request data
495
496    \return MAPI_E_SUCCESS on success
497
498  */
499 static enum MAPISTATUS dcesrv_NspiResolveNames(struct dcesrv_call_state *dce_call,
500                                                TALLOC_CTX *mem_ctx,
501                                                struct NspiResolveNames *r)
502 {
503         DEBUG(3, ("exchange_nsp: NspiResolveNames (0x13) not implemented\n"));
504         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
505 }
506
507
508 /**
509    \details exchange_nsp NspiResolveNamesW (0x14) function
510
511    \param dce_call pointer to the session context
512    \param mem_ctx pointer to the memory context
513    \param r pointer to the NspiResolveNamesW request data
514
515    \return MAPI_E_SUCCESS on success
516
517  */
518 static enum MAPISTATUS dcesrv_NspiResolveNamesW(struct dcesrv_call_state *dce_call,
519                                                 TALLOC_CTX *mem_ctx,
520                                                 struct NspiResolveNamesW *r)
521 {
522         DEBUG(3, ("exchange_nsp: NspiResolveNamesW (0x14) not implemented\n"));
523         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
524 }
525
526
527 /**
528    \details Dispatch incoming NSPI call to the correct OpenChange
529    server function.
530
531    \param dce_call pointer to the session context
532    \param mem_ctx pointer to the memory context
533    \param r generic pointer on NSPI data
534    \param mapiproxy pointer to the mapiproxy structure controlling 
535    mapiproxy behavior
536
537    \return NT_STATUS_OK
538  */
539 static NTSTATUS dcesrv_exchange_nsp_dispatch(struct dcesrv_call_state *dce_call,
540                                              TALLOC_CTX *mem_ctx,
541                                              void *r, struct mapiproxy *mapiproxy)
542 {
543         enum MAPISTATUS                         retval;
544         const struct ndr_interface_table        *table;
545         uint16_t                                opnum;
546
547         table = (const struct ndr_interface_table *) dce_call->context->iface->private;
548         opnum = dce_call->pkt.u.request.opnum;
549
550         /* Sanity checks */
551         if (!table) return NT_STATUS_UNSUCCESSFUL;
552         if (table->name && strcmp(table->name, NDR_EXCHANGE_NSP_NAME)) return NT_STATUS_UNSUCCESSFUL;
553
554         switch (opnum) {
555         case NDR_NSPIBIND:
556                 retval = dcesrv_NspiBind(dce_call, mem_ctx, (struct NspiBind *)r);
557                 break;
558         case NDR_NSPIUNBIND:
559                 retval = dcesrv_NspiUnbind(dce_call, mem_ctx, (struct NspiUnbind *)r);
560                 break;
561         case NDR_NSPIUPDATESTAT:
562                 retval = dcesrv_NspiUpdateStat(dce_call, mem_ctx, (struct NspiUpdateStat *)r);
563                 break;
564         case NDR_NSPIQUERYROWS:
565                 retval = dcesrv_NspiQueryRows(dce_call, mem_ctx, (struct NspiQueryRows *)r);
566                 break;
567         case NDR_NSPISEEKENTRIES:
568                 retval = dcesrv_NspiSeekEntries(dce_call, mem_ctx, (struct NspiSeekEntries *)r);
569                 break;
570         case NDR_NSPIGETMATCHES:
571                 retval = dcesrv_NspiGetMatches(dce_call, mem_ctx, (struct NspiGetMatches *)r);
572                 break;
573         case NDR_NSPIRESORTRESTRICTION:
574                 retval = dcesrv_NspiResortRestriction(dce_call, mem_ctx, (struct NspiResortRestriction *)r);
575                 break;
576         case NDR_NSPIDNTOMID:
577                 retval = dcesrv_NspiDNToMId(dce_call, mem_ctx, (struct NspiDNToMId *)r);
578                 break;
579         case NDR_NSPIGETPROPLIST:
580                 retval = dcesrv_NspiGetPropList(dce_call, mem_ctx, (struct NspiGetPropList *)r);
581                 break;
582         case NDR_NSPIGETPROPS:
583                 retval = dcesrv_NspiGetProps(dce_call, mem_ctx, (struct NspiGetProps *)r);
584                 break;
585         case NDR_NSPICOMPAREMIDS:
586                 retval = dcesrv_NspiCompareMIds(dce_call, mem_ctx, (struct NspiCompareMIds *)r);
587                 break;
588         case NDR_NSPIMODPROPS:
589                 retval = dcesrv_NspiModProps(dce_call, mem_ctx, (struct NspiModProps *)r);
590                 break;
591         case NDR_NSPIGETSPECIALTABLE:
592                 retval = dcesrv_NspiGetSpecialTable(dce_call, mem_ctx, (struct NspiGetSpecialTable *)r);
593                 break;
594         case NDR_NSPIGETTEMPLATEINFO:
595                 retval = dcesrv_NspiGetTemplateInfo(dce_call, mem_ctx, (struct NspiGetTemplateInfo *)r);
596                 break;
597         case NDR_NSPIMODLINKATT:
598                 retval = dcesrv_NspiModLinkAtt(dce_call, mem_ctx, (struct NspiModLinkAtt *)r);
599                 break;
600         case NDR_NSPIDELETEENTRIES:
601                 retval = dcesrv_NspiDeleteEntries(dce_call, mem_ctx, (struct NspiDeleteEntries *)r);
602                 break;
603         case NDR_NSPIQUERYCOLUMNS:
604                 retval = dcesrv_NspiQueryColumns(dce_call, mem_ctx, (struct NspiQueryColumns *)r);
605                 break;
606         case NDR_NSPIGETNAMESFROMIDS:
607                 retval = dcesrv_NspiGetNamesFromIDs(dce_call, mem_ctx, (struct NspiGetNamesFromIDs *)r);
608                 break;
609         case NDR_NSPIGETIDSFROMNAMES:
610                 retval = dcesrv_NspiGetIDsFromNames(dce_call, mem_ctx, (struct NspiGetIDsFromNames *)r);
611                 break;
612         case NDR_NSPIRESOLVENAMES:
613                 retval = dcesrv_NspiResolveNames(dce_call, mem_ctx, (struct NspiResolveNames *)r);
614                 break;
615         case NDR_NSPIRESOLVENAMESW:
616                 retval = dcesrv_NspiResolveNamesW(dce_call, mem_ctx, (struct NspiResolveNamesW *)r);
617                 break;
618         }
619
620         return NT_STATUS_OK;
621 }
622
623
624 /**
625    \details Initialize the NSPI OpenChange server
626
627    \param dce_ctx pointer to the server context
628
629    \return NT_STATUS_OK on success, otherwise NT_STATUS_NO_MEMORY
630  */
631 static NTSTATUS dcesrv_exchange_nsp_init(struct dcesrv_context *dce_ctx)
632 {
633         /* Initialize exchange_nsp session */
634         nsp_session = talloc_zero(dce_ctx, struct exchange_nsp_session);
635         if (!nsp_session) return NT_STATUS_NO_MEMORY;
636         nsp_session->session = NULL;
637
638         return NT_STATUS_OK;
639 }
640
641
642 /**
643    \details Terminates the NSPI connection and release the associated
644    session and context if still available. This case occurs when the
645    client doesn't call NspiUnbind but quit unexpectedly.
646
647    \param server_id reference to the server identifier structure
648    \param context_id the connection context identifier
649
650    \return NT_STATUS_OK on success
651  */
652 static NTSTATUS dcesrv_exchange_nsp_unbind(struct server_id server_id, uint32_t context_id)
653 {
654         struct exchange_nsp_session     *session;
655
656         for (session = nsp_session; session; session = session->next) {
657                 if ((mpm_session_cmp_sub(session->session, server_id, context_id) == true)) {
658                         mpm_session_release(session->session);
659                         DLIST_REMOVE(nsp_session, session);
660                         DEBUG(6, ("[%s:%d]: Session found and released\n", __FUNCTION__, __LINE__));
661                         return NT_STATUS_OK;
662                 }
663         }
664
665         return NT_STATUS_OK;
666 }
667
668
669 /**
670    \details Entry point for the default OpenChange NSPI server
671
672    \return NT_STATUS_OK on success, otherwise NTSTATUS error
673  */
674 NTSTATUS samba_init_module(void)
675 {
676         struct mapiproxy_module server;
677         NTSTATUS                ret;
678
679         /* Fill in our name */
680         server.name = "exchange_nsp";
681         server.status = MAPIPROXY_DEFAULT;
682         server.description = "OpenChange NSPI server";
683         server.endpoint = "exchange_nsp";
684
685         /* Fill in all the operations */
686         server.init = dcesrv_exchange_nsp_init;
687         server.unbind = dcesrv_exchange_nsp_unbind;
688         server.dispatch = dcesrv_exchange_nsp_dispatch;
689         server.push = NULL;
690         server.pull = NULL;
691         server.ndr_pull = NULL;
692
693         /* Register ourselves with the MAPIPROXY server subsystem */
694         ret = mapiproxy_server_register(&server);
695         if (!NT_STATUS_IS_OK(ret)) {
696                 DEBUG(0, ("Failed to register the 'exchange_nsp' default mapiproxy server!\n"));
697                 return ret;
698         }
699
700         return ret;
701 }