server: intialize aux_header buffer to null if the data is missing.
[tridge/openchange.git] / branches / plugfest / mapiproxy / libmapistore / database / mapistoredb.c
1 /*
2    OpenChange Storage Abstraction Layer library
3
4    OpenChange Project
5
6    Copyright (C) Julien Kerihuel 2010-2011
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 #include "mapiproxy/libmapistore/mapistore_errors.h"
23 #include "mapiproxy/libmapistore/mapistore.h"
24 #include "mapiproxy/libmapistore/mapistore_private.h"
25
26 /**
27    \file mapistoredb.c
28
29    \brief MAPIStore database provisioning interface
30  */
31
32 int lpcfg_server_role(struct loadparm_context *lp_ctx);
33
34 /**
35    \details Initialize the mapistore database context
36
37    \param mem_ctx pointer to the memory context
38    \param path string pointer to the mapistore database location
39
40    If path if NULL use the default mapistore database path instead.
41
42    \return Allocated mapistore database context on success, otherwise NULL
43  */
44 struct mapistoredb_context *mapistoredb_init(TALLOC_CTX *mem_ctx,
45                                              const char *path)
46 {
47         struct mapistoredb_context      *mdb_ctx;
48         char                            **domaindn;
49         char                            *full_path;
50         struct stat                     sb;
51         int                             i;
52         int                             ret;
53
54         /* Sanity checks */
55         if (path == NULL) {
56                 path = MAPISTORE_DBPATH;
57         }
58
59         /* Ensure the path is valid */
60         if (stat(path, &sb) == -1) {
61                 perror(path);
62                 return NULL;
63         }
64
65         /* Step 1. Initialize mapistoredb context */
66         mdb_ctx = talloc_zero(mem_ctx, struct mapistoredb_context);
67         mdb_ctx->param = talloc_zero(mem_ctx, struct mapistoredb_conf);
68         if (!mdb_ctx->param) {
69                 DEBUG(5, ("! [%s:%d][%s]: Failed to allocate memory for mdb_ctx->param", __FILE__, __LINE__, __FUNCTION__));
70                 talloc_free(mdb_ctx);
71                 return NULL;
72         }
73
74         /* Step 2. Initialize Samba loadparm context and load default values */
75         mdb_ctx->lp_ctx = loadparm_init(mdb_ctx);
76         lpcfg_load_default(mdb_ctx->lp_ctx);
77
78         /* Step 3. Initialize tevent structure */
79         mdb_ctx->ev = tevent_context_init(mdb_ctx);
80
81         /* Step 4. Open a wrapped connection on the mapistore database */
82         full_path = talloc_asprintf(mem_ctx, "%s/mapistore.ldb", path);
83         mdb_ctx->ldb_ctx = mapistore_ldb_wrap_connect(mdb_ctx, mdb_ctx->ev, full_path, 0);
84         talloc_free(full_path);
85         if (!mdb_ctx->ldb_ctx) {
86                 DEBUG(5, ("! [%s:%d][%s]: Failed to open wrapped connection over mapistore.ldb\n", __FILE__, __LINE__, __FUNCTION__));
87                 talloc_free(mdb_ctx);
88                 return NULL;
89         }
90
91         /* Step 5. Retrieve default values from smb.conf */
92         mdb_ctx->param->netbiosname = strlower_talloc(mdb_ctx->param, lpcfg_netbios_name(mdb_ctx->lp_ctx));
93         mdb_ctx->param->dnsdomain = strlower_talloc(mdb_ctx->param, lpcfg_realm(mdb_ctx->lp_ctx));
94         mdb_ctx->param->domain = strlower_talloc(mdb_ctx->param, lpcfg_sam_name(mdb_ctx->lp_ctx));
95
96         switch (lpcfg_server_role(mdb_ctx->lp_ctx)) {
97         case ROLE_DOMAIN_CONTROLLER:
98                 domaindn = str_list_make(mdb_ctx->param, mdb_ctx->param->dnsdomain, ".");
99                 strlower_m(domaindn[0]);
100                 mdb_ctx->param->domaindn = talloc_asprintf(mdb_ctx->param, "DC_%s", domaindn[0]);
101                 for (i = 1; domaindn[i]; i++) {
102                         strlower_m(domaindn[i]);
103                         mdb_ctx->param->domaindn = talloc_asprintf_append_buffer(mdb_ctx->param->domaindn, ",DC=%s", domaindn[i]);
104                 }
105                 talloc_free(domaindn);
106                 break;
107         default:
108                 mdb_ctx->param->domaindn = talloc_asprintf(mdb_ctx->param, "CN=%s", mdb_ctx->param->domain);
109                 break;
110         }
111
112         mdb_ctx->param->serverdn = talloc_asprintf(mdb_ctx->param, TMPL_MDB_SERVERDN,
113                                                    mdb_ctx->param->netbiosname,
114                                                    mdb_ctx->param->domaindn);
115         mdb_ctx->param->firstorg = talloc_strdup(mdb_ctx->param, DFLT_MDB_FIRSTORG);
116         mdb_ctx->param->firstou = talloc_strdup(mdb_ctx->param, DFLT_MDB_FIRSTOU);
117         mdb_ctx->param->firstorgdn = talloc_asprintf(mdb_ctx->param, TMPL_MDB_FIRSTORGDN,
118                                                      mdb_ctx->param->firstou,
119                                                      mdb_ctx->param->firstorg,
120                                                      mdb_ctx->param->serverdn);
121         mdb_ctx->param->db_path = talloc_asprintf(mdb_ctx->param, "%s/mapistore.ldb", path);
122         mdb_ctx->param->mstore_path = talloc_asprintf(mdb_ctx->param, "%s/mapistore", path);
123
124         /* Step 6. Initialize mapistore */
125         if (stat(mdb_ctx->param->mstore_path, &sb) == -1) {
126                 ret = mkdir(mdb_ctx->param->mstore_path, 0700);
127                 if (ret == -1) {
128                         perror(mdb_ctx->param->mstore_path);
129                         talloc_free(mdb_ctx);
130                         return NULL;
131                 }
132         }
133
134         mapistore_set_database_path(mdb_ctx->param->db_path);
135         mapistore_set_mapping_path(mdb_ctx->param->mstore_path);
136         mdb_ctx->mstore_ctx = mapistore_init(mdb_ctx, NULL);
137         if (!mdb_ctx->mstore_ctx) {
138                 DEBUG(5, ("! [%s:%d][%s]: Failed to initialize mapistore context\n", __FILE__, __LINE__, __FUNCTION__));
139                 talloc_free(mdb_ctx);
140                 return NULL;
141         }
142
143         return mdb_ctx;
144 }
145
146
147 /**
148    \details Free a mapistore database context
149
150    \param mdb_ctx the context to free (from mapistoredb_init())
151  */
152 void mapistoredb_release(struct mapistoredb_context *mdb_ctx)
153 {
154         if (!mdb_ctx) {
155                 DEBUG(5, ("! [%s:%d][%s]: Invalid mapistore database context\n", __FILE__, __LINE__, __FUNCTION__));
156                 return;
157         }
158
159         talloc_free(mdb_ctx->lp_ctx);
160         talloc_free(mdb_ctx->param);
161         talloc_free(mdb_ctx);
162 }
163
164
165 /**
166    \details Get a mapistore URI for a system/special folder from
167    backend
168
169    \param mdb_ctx pointer to the mapistore database context
170    \param username the username for which we want to retrieve the uri
171    \param uri the uri namespace to query
172    \param namespace_uri the namespace uri to return
173
174    \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
175  */
176 enum MAPISTORE_ERROR mapistoredb_get_mapistore_uri(struct mapistoredb_context *mdb_ctx,
177                                                    enum MAPISTORE_DFLT_FOLDERS index,
178                                                    const char *namespace_uri,
179                                                    const char *username,
180                                                    char **uri)
181 {
182         enum MAPISTORE_ERROR    retval;
183         char                    *_uri;
184
185         /* Sanity checks */
186         if (!mdb_ctx || !mdb_ctx->mstore_ctx) {
187                 DEBUG(5, ("! [%s:%d][%s]: Invalid mapistore database context\n", __FILE__, __LINE__, __FUNCTION__));
188                 return MAPISTORE_ERR_INVALID_CONTEXT;
189         }
190         if (!namespace_uri || !username) {
191                 DEBUG(5, ("! [%s:%d][%s]: Invalid parameter\n", __FILE__, __LINE__, __FUNCTION__));
192                 return MAPISTORE_ERR_INVALID_PARAMETER;
193         }
194
195         retval = mapistore_create_uri(mdb_ctx->mstore_ctx, index, namespace_uri, username, &_uri);
196         if (retval == MAPISTORE_SUCCESS) {
197                 *uri = _uri;
198         }
199
200         return retval;
201 }
202
203
204 /** TODO: this is a copy of code in mapistore_mstoredb.c */
205 static bool write_ldif_string_to_store(struct ldb_context *ldb_ctx, const char *ldif_string)
206 {
207         struct ldb_ldif *ldif;
208         int             ret;
209         
210         while ((ldif = ldb_ldif_read_string(ldb_ctx, (const char **)&ldif_string))) {
211                 ret = ldb_msg_normalize(ldb_ctx, ldif, ldif->msg, &ldif->msg);
212                 if (ret != LDB_SUCCESS) {
213                         ldb_ldif_read_free(ldb_ctx, ldif);
214                         return false;
215                 }
216                 ret = ldb_add(ldb_ctx, ldif->msg);
217                 if (ret != LDB_SUCCESS) {
218                         ldb_ldif_read_free(ldb_ctx, ldif);
219                         return false;
220                 }
221                 ldb_ldif_read_free(ldb_ctx, ldif);
222         }
223         
224         return true;
225 }
226
227
228 /**
229    \details Default provisioning for mapistore.ldb database
230
231    \param mdb_ctx pointer to the mapistore database context
232    
233    \return MAPISTORE_SUCCESS on success, otherwise a non-zero MAPISTORE_ERROR
234  */
235 enum MAPISTORE_ERROR mapistoredb_provision(struct mapistoredb_context *mdb_ctx)
236 {
237         char    *ldif_str;
238
239         /* Sanity checks */
240         if (!mdb_ctx || !mdb_ctx->ldb_ctx) return MAPISTORE_ERR_NOT_INITIALIZED;
241
242         /* Step 1. Add database schema */
243         if (write_ldif_string_to_store(mdb_ctx->ldb_ctx, MDB_INIT_LDIF_TMPL) == false) {
244                 DEBUG(5, ("! [%s:%d][%s]: Failed to add database schema\n", __FILE__, __LINE__, __FUNCTION__));
245                 return MAPISTORE_ERR_DATABASE_OPS;
246         }
247
248         /* Step 2. Add RootDSE schema */
249         ldif_str = talloc_asprintf(mdb_ctx, MDB_ROOTDSE_LDIF_TMPL,
250                                    mdb_ctx->param->firstou,
251                                    mdb_ctx->param->firstorg,
252                                    mdb_ctx->param->serverdn,
253                                    mdb_ctx->param->serverdn);
254         if (write_ldif_string_to_store(mdb_ctx->ldb_ctx, ldif_str) == false) {
255                 DEBUG(5, ("! [%s:%d][%s]: Failed to add RootDSE schema\n", __FILE__, __LINE__, __FUNCTION__));
256                 talloc_free(ldif_str);
257                 return MAPISTORE_ERR_DATABASE_OPS;
258         }
259         talloc_free(ldif_str);
260
261         /* Step 3. Provision Server object responsible for maintaining
262          * the Replica identifier */
263         ldif_str = talloc_asprintf(mdb_ctx, MDB_SERVER_LDIF_TMPL,
264                                    mdb_ctx->param->serverdn,
265                                    mdb_ctx->param->netbiosname,
266                                    mdb_ctx->param->firstorg,
267                                    mdb_ctx->param->serverdn,
268                                    mdb_ctx->param->firstorg,
269                                    mdb_ctx->param->firstou,
270                                    mdb_ctx->param->firstorg,
271                                    mdb_ctx->param->serverdn,
272                                    mdb_ctx->param->firstou);
273         if (write_ldif_string_to_store(mdb_ctx->ldb_ctx, ldif_str) == false) {
274                 DEBUG(5, ("! [%s:%d][%s]: Failed to provision server object\n", __FILE__, __LINE__, __FUNCTION__));
275                 talloc_free(ldif_str);
276                 return MAPISTORE_ERR_DATABASE_OPS;
277         }
278         talloc_free(ldif_str);
279
280         return MAPISTORE_SUCCESS;
281 }