Replace deprecated talloc_init calls with talloc_named
[jelmer/openchange.git] / mapiproxy / servers / default / emsmdb / emsmdbp.c
1 /*
2    OpenChange Server implementation
3
4    EMSMDBP: EMSMDB Provider implementation
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 emsmdbp.c
24
25    \brief EMSMDB Provider implementation
26  */
27
28 #include "mapiproxy/dcesrv_mapiproxy.h"
29 #include "mapiproxy/libmapiproxy.h"
30 #include "dcesrv_exchange_emsmdb.h"
31
32 /**
33    \details Initialize the EMSMDBP context and open connections to
34    Samba databases.
35
36    \param lp_ctx pointer to the loadparm_context
37    
38    \return Allocated emsmdbp_context pointer on success, otherwise
39    NULL
40  */
41 _PUBLIC_ struct emsmdbp_context *emsmdbp_init(struct loadparm_context *lp_ctx)
42 {
43         TALLOC_CTX              *mem_ctx;
44         struct emsmdbp_context  *emsmdbp_ctx;
45         struct tevent_context   *ev;
46         char                    *configuration = NULL;
47         char                    *users = NULL;
48         int                     ret;
49
50         /* Sanity Checks */
51         if (!lp_ctx) return NULL;
52
53         mem_ctx = talloc_named(NULL, 0, "emsmdbp_init");
54
55         emsmdbp_ctx = talloc_zero(mem_ctx, struct emsmdbp_context);
56         if (!emsmdbp_ctx) {
57                 talloc_free(mem_ctx);
58                 return NULL;
59         }
60
61         emsmdbp_ctx->mem_ctx = mem_ctx;
62
63         ev = tevent_context_init(mem_ctx);
64         if (!ev) {
65                 talloc_free(mem_ctx);
66                 return NULL;
67         }
68
69         /* Save a pointer to the loadparm context */
70         emsmdbp_ctx->lp_ctx = lp_ctx;
71
72         /* Return an opaque context pointer on the configuration database */
73         configuration = private_path(mem_ctx, lp_ctx, "configuration.ldb");
74         emsmdbp_ctx->conf_ctx = ldb_init(mem_ctx, ev);
75         if (!emsmdbp_ctx->conf_ctx) {
76                 talloc_free(configuration);
77                 talloc_free(mem_ctx);
78                 return NULL;
79         }
80
81         ret = ldb_connect(emsmdbp_ctx->conf_ctx, configuration, LDB_FLG_RDONLY, NULL);
82         talloc_free(configuration);
83         if (ret != LDB_SUCCESS) {
84                 DEBUG(0, ("[%s:%d]: Connection to \"configuration.ldb\" failed\n", __FUNCTION__, __LINE__));
85                 talloc_free(mem_ctx);
86                 return NULL;
87         }
88
89         /* Return an opaque pointer on the users database */
90         users = private_path(mem_ctx, lp_ctx, "users.ldb");
91         emsmdbp_ctx->users_ctx = ldb_init(mem_ctx, ev);
92         if (!emsmdbp_ctx->users_ctx) {
93                 talloc_free(users);
94                 talloc_free(mem_ctx);
95                 return NULL;
96         }
97
98         ret = ldb_connect(emsmdbp_ctx->users_ctx, users, LDB_FLG_RDONLY, NULL);
99         talloc_free(users);
100         if (ret != LDB_SUCCESS) {
101                 DEBUG(0, ("[%s:%d]: Connection to \"users.ldb\" failed\n", __FUNCTION__, __LINE__));
102                 talloc_free(mem_ctx);
103                 return NULL;
104         }
105
106         return emsmdbp_ctx;
107 }
108
109
110 _PUBLIC_ bool emsmdbp_destructor(void *data)
111 {
112         struct emsmdbp_context  *emsmdbp_ctx = (struct emsmdbp_context *)data;
113
114         if (emsmdbp_ctx) {
115                 talloc_free(emsmdbp_ctx->mem_ctx);
116                 DEBUG(0, ("[%s:%d]: emsmdbp_ctx found and released\n", __FUNCTION__, __LINE__));
117                 return true;
118         }
119
120         return false;
121 }
122
123
124 /**
125    \details Check if the authenticated user belongs to the Exchange
126    organization and is enabled
127
128    \param dce_call pointer to the session context
129    \param emsmdbp_ctx pointer to the EMSMDBP context
130
131    \return true on success, otherwise false
132  */
133 _PUBLIC_ bool emsmdbp_verify_user(struct dcesrv_call_state *dce_call,
134                                   struct emsmdbp_context *emsmdbp_ctx)
135 {
136         int                     ret;
137         const char              *username = NULL;
138         int                     msExchUserAccountControl;
139         struct ldb_result       *res = NULL;
140         char                    *ldb_filter;
141         const char * const      recipient_attrs[] = { "msExchUserAccountControl", NULL };
142
143         username = dce_call->context->conn->auth_state.session_info->server_info->account_name;
144
145         ldb_filter = talloc_asprintf(emsmdbp_ctx->mem_ctx, "CN=%s", username);
146         ret = ldb_search(emsmdbp_ctx->users_ctx, emsmdbp_ctx->mem_ctx, &res,
147                          ldb_get_default_basedn(emsmdbp_ctx->users_ctx),
148                          LDB_SCOPE_SUBTREE, recipient_attrs, ldb_filter);
149         talloc_free(ldb_filter);
150
151         /* If the search failed */
152         if (ret != LDB_SUCCESS || !res->count) {
153                 return false;
154         }
155
156         /* If msExchUserAccountControl attribute is not found */
157         if (!res->msgs[0]->num_elements) {
158                 return false;
159         }
160
161         /* If the attribute exists check its value */
162         msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", 2);
163         if (msExchUserAccountControl == 2) {
164                 return false;
165         }
166
167         return true;
168 }
169
170
171 /**
172    \details Check if the user record which legacyExchangeDN points to
173    belongs to the Exchange organization and is enabled
174
175    \param dce_call pointer to the session context
176    \param emsmdbp_ctx pointer to the EMSMDBP context
177    \param legacyExchangeDN pointer to the userDN to lookup
178    \param msg pointer on pointer to the LDB message matching the record
179
180    \note Users can set msg to NULL if they do not intend to retrieve
181    the message
182
183    \return true on success, otherwise false
184  */
185 _PUBLIC_ bool emsmdbp_verify_userdn(struct dcesrv_call_state *dce_call,
186                                     struct emsmdbp_context *emsmdbp_ctx,
187                                     const char *legacyExchangeDN,
188                                     struct ldb_message **msg)
189 {
190         int                     ret;
191         int                     msExchUserAccountControl;
192         struct ldb_result       *res = NULL;
193         char                    *ldb_filter;
194         const char * const      recipient_attrs[] = { "*", NULL };
195
196         /* Sanity Checks */
197         if (!legacyExchangeDN) return false;
198
199         ldb_filter = talloc_asprintf(emsmdbp_ctx->mem_ctx, "(legacyExchangeDN=%s)", legacyExchangeDN);
200         ret = ldb_search(emsmdbp_ctx->users_ctx, emsmdbp_ctx->mem_ctx, &res,
201                          ldb_get_default_basedn(emsmdbp_ctx->users_ctx),
202                          LDB_SCOPE_SUBTREE, recipient_attrs, ldb_filter);
203         talloc_free(ldb_filter);
204
205         /* If the search failed */
206         if (ret != LDB_SUCCESS || !res->count) {
207                 return false;
208         }
209
210         /* Checks msExchUserAccountControl value */
211         msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", 2);
212         if (msExchUserAccountControl == 2) {
213                 return false;
214         }
215
216         if (msg) {
217                 *msg = res->msgs[0];
218         }
219
220         return true;
221 }