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

« back to all changes in this revision

Viewing changes to mapiproxy/libmapistore/mapistore_replica_mapping.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:
 
1
/*
 
2
   OpenChange Storage Abstraction Layer library
 
3
 
 
4
   OpenChange Project
 
5
 
 
6
   Copyright (C) Wolfgang Sourdeau 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 <string.h>
 
23
 
 
24
#include "mapistore.h"
 
25
#include "mapistore_errors.h"
 
26
#include "mapistore_private.h"
 
27
#include <dlinklist.h>
 
28
#include "libmapi/libmapi_private.h"
 
29
 
 
30
#include <tdb.h>
 
31
 
 
32
static void mapistore_replica_mapping_set_next_replid(struct tdb_context *, uint16_t);
 
33
static uint16_t mapistore_replica_mapping_get_next_replid(struct tdb_context *);
 
34
 
 
35
/* Special repl ids:
 
36
   - 0x01 is for server replica
 
37
   - 0x02 is for GetLocalReplicaIDs */
 
38
 
 
39
/**
 
40
   \details Search the replica_mapping record matching the username
 
41
 
 
42
   \param mstore_ctx pointer to the mapistore context
 
43
   \param username the username to lookup
 
44
 
 
45
   \return pointer to the tdb_wrap structure on success, otherwise NULL
 
46
 */
 
47
static struct replica_mapping_context_list *mapistore_replica_mapping_search(struct mapistore_context *mstore_ctx, const char *username)
 
48
{
 
49
        struct replica_mapping_context_list     *el;
 
50
 
 
51
        /* Sanity checks */
 
52
        if (!mstore_ctx) return NULL;
 
53
        if (!mstore_ctx->replica_mapping_list) return NULL;
 
54
        if (!username) return NULL;
 
55
 
 
56
        for (el = mstore_ctx->replica_mapping_list; el; el = el->next) {
 
57
                if (el && el->username && !strcmp(el->username, username)) {
 
58
                        return el;
 
59
                }
 
60
        }
 
61
 
 
62
        return NULL;
 
63
}
 
64
 
 
65
/**
 
66
   \details Open connection to replica_mapping database for a given user
 
67
 
 
68
   \param mstore_ctx pointer to the mapistore context
 
69
   \param username name for which the replica_mapping database has to be
 
70
   created
 
71
 
 
72
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 
73
 */
 
74
 
 
75
static int context_list_destructor(struct replica_mapping_context_list *rmctx)
 
76
{
 
77
        tdb_close(rmctx->tdb);
 
78
 
 
79
        return 1;
 
80
}
 
81
 
 
82
_PUBLIC_ enum mapistore_error mapistore_replica_mapping_add(struct mapistore_context *mstore_ctx, const char *username, struct replica_mapping_context_list **rmctxp)
 
83
{
 
84
        TALLOC_CTX                              *mem_ctx;
 
85
        struct replica_mapping_context_list     *rmctx;
 
86
        char                                    *dbpath = NULL;
 
87
 
 
88
        /* Sanity checks */
 
89
        MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
 
90
        MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL);
 
91
 
 
92
        /* Step 1. Search if the context already exists */
 
93
        rmctx = mapistore_replica_mapping_search(mstore_ctx, username);
 
94
        *rmctxp = rmctx;
 
95
        MAPISTORE_RETVAL_IF(rmctx, MAPISTORE_SUCCESS, NULL);
 
96
 
 
97
        mem_ctx = talloc_named(NULL, 0, "mapistore_replica_mapping_init");
 
98
        rmctx = talloc_zero(mstore_ctx->replica_mapping_list, struct replica_mapping_context_list);
 
99
 
 
100
        /* Step 1. Open/Create the replica_mapping database */
 
101
        dbpath = talloc_asprintf(mem_ctx, "%s/%s/" MAPISTORE_DB_REPLICA_MAPPING, 
 
102
                                 mapistore_get_mapping_path(), username);
 
103
        rmctx->tdb = tdb_open(dbpath, 0, 0, O_RDWR|O_CREAT, 0600);
 
104
        if (!rmctx->tdb) {
 
105
                DEBUG(3, ("[%s:%d]: %s (%s)\n", __FUNCTION__, __LINE__, strerror(errno), dbpath));
 
106
                talloc_free(rmctx);
 
107
                talloc_free(mem_ctx);
 
108
                return MAPISTORE_ERR_DATABASE_INIT;
 
109
        }
 
110
        talloc_set_destructor(rmctx, context_list_destructor);
 
111
        rmctx->username = talloc_strdup(rmctx, username);
 
112
        rmctx->ref_count = 0;
 
113
        DLIST_ADD_END(mstore_ctx->replica_mapping_list, rmctx, struct replica_mapping_context_list *);
 
114
 
 
115
        *rmctxp = rmctx;
 
116
 
 
117
        talloc_free(mem_ctx);
 
118
 
 
119
        return MAPISTORE_SUCCESS;
 
120
}
 
121
 
 
122
/* _PUBLIC_ enum mapistore_error mapistore_replica_mapping_add(struct mapistore_context *mstore_ctx, const char *username) */
 
123
/* { */
 
124
/*      TALLOC_CTX                      *mem_ctx; */
 
125
/*      char                            *dbpath = NULL; */
 
126
 
 
127
/*      /\* Sanity checks *\/ */
 
128
/*      MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL); */
 
129
/*      MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL); */
 
130
 
 
131
/*      mem_ctx = talloc_named(NULL, 0, "mapistore_replica_mapping_add"); */
 
132
 
 
133
/*      /\* Step 1. Open/Create the replica_mapping database *\/ */
 
134
/*      dbpath = talloc_asprintf(mem_ctx, "%s/%s/" MAPISTORE_DB_REPLICA_MAPPING, */
 
135
/*                               mapistore_get_mapping_path(), username); */
 
136
/*      mstore_ctx->replica_mapping_ctx = tdb_wrap_open(mstore_ctx, dbpath, 0, 0, O_RDWR|O_CREAT, 0600); */
 
137
/*      talloc_free(dbpath); */
 
138
/*      if (!mstore_ctx->replica_mapping_ctx) { */
 
139
/*              DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, strerror(errno))); */
 
140
/*              talloc_free(mem_ctx); */
 
141
/*              return MAPISTORE_ERR_DATABASE_INIT; */
 
142
/*      } */
 
143
/*      if (mapistore_replica_mapping_get_next_replid(mstore_ctx->replica_mapping_ctx->tdb) == 0xffff) { */
 
144
/*              mapistore_replica_mapping_set_next_replid(mstore_ctx->replica_mapping_ctx->tdb, 0x3); */
 
145
/*      } */
 
146
 
 
147
/*      talloc_free(mem_ctx); */
 
148
 
 
149
/*      return MAPI_E_SUCCESS; */
 
150
/* } */
 
151
 
 
152
static void mapistore_replica_mapping_set_next_replid(struct tdb_context *tdb, uint16_t replid) {
 
153
        TDB_DATA        key;
 
154
        TDB_DATA        replid_data;
 
155
        void            *mem_ctx;
 
156
        int             ret, op;
 
157
 
 
158
        mem_ctx = talloc_zero(NULL, void);
 
159
 
 
160
        /* GUID to ReplID */
 
161
        key.dptr = (unsigned char *) "next_replid";
 
162
        key.dsize = strlen((const char *) key.dptr);
 
163
 
 
164
        replid_data.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%.4x", replid);
 
165
        replid_data.dsize = strlen((const char *) replid_data.dptr);
 
166
 
 
167
        ret = tdb_exists(tdb, key);
 
168
        op = (ret) ? TDB_MODIFY : TDB_INSERT;   
 
169
        tdb_store(tdb, key, replid_data, op);
 
170
 
 
171
        talloc_free(mem_ctx);
 
172
}
 
173
 
 
174
static uint16_t mapistore_replica_mapping_get_next_replid(struct tdb_context *tdb) {
 
175
        TDB_DATA        key;
 
176
        TDB_DATA        replid_data;
 
177
        int             ret;
 
178
        char            *tmp_data;
 
179
        uint16_t        replid;
 
180
 
 
181
        /* GUID to ReplID */
 
182
        key.dptr = (unsigned char *) "next_replid";
 
183
        key.dsize = strlen((const char *) key.dptr);
 
184
 
 
185
        ret = tdb_exists(tdb, key);
 
186
        if (!ret) {
 
187
                return 0xffff;
 
188
        }
 
189
 
 
190
        replid_data = tdb_fetch(tdb, key);
 
191
 
 
192
        tmp_data = talloc_strndup(NULL, (char *) replid_data.dptr, replid_data.dsize);
 
193
        replid = strtoul(tmp_data, NULL, 16);
 
194
        talloc_free(tmp_data);
 
195
 
 
196
        return replid;
 
197
}
 
198
 
 
199
static void mapistore_replica_mapping_add_pair(struct tdb_context *tdb, const struct GUID *guidP, uint16_t replid)
 
200
{
 
201
        TDB_DATA        guid_key;
 
202
        TDB_DATA        replid_key;
 
203
        void            *mem_ctx;
 
204
 
 
205
        mem_ctx = talloc_zero(NULL, void);
 
206
 
 
207
        /* GUID to ReplID */
 
208
        guid_key.dptr = (unsigned char *) GUID_string(mem_ctx, guidP);
 
209
        guid_key.dsize = strlen((const char *) guid_key.dptr);
 
210
 
 
211
        replid_key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%.4x", replid);
 
212
        replid_key.dsize = strlen((const char *) replid_key.dptr);
 
213
 
 
214
        tdb_store(tdb, guid_key, replid_key, TDB_INSERT);
 
215
        tdb_store(tdb, replid_key, guid_key, TDB_INSERT);
 
216
 
 
217
        talloc_free(mem_ctx);
 
218
}
 
219
 
 
220
static enum mapistore_error mapistore_replica_mapping_search_guid(struct tdb_context *tdb, const struct GUID *guidP, uint16_t *replidP)
 
221
{
 
222
        TDB_DATA        guid_key;
 
223
        TDB_DATA        replid_key;
 
224
        void            *mem_ctx;
 
225
        int             ret;
 
226
 
 
227
        mem_ctx = talloc_zero(NULL, void);
 
228
 
 
229
        guid_key.dptr = (unsigned char *) GUID_string(mem_ctx, guidP);
 
230
        guid_key.dsize = strlen((const char *) guid_key.dptr);
 
231
 
 
232
        ret = tdb_exists(tdb, guid_key);
 
233
        if (!ret) {
 
234
                talloc_free(mem_ctx);
 
235
                return MAPISTORE_ERROR;
 
236
        }
 
237
 
 
238
        replid_key = tdb_fetch(tdb, guid_key);
 
239
        *replidP = strtoul((char *) replid_key.dptr + 2, NULL, 16);
 
240
 
 
241
        talloc_free(mem_ctx);
 
242
 
 
243
        return MAPISTORE_SUCCESS;
 
244
}
 
245
 
 
246
/**
 
247
   \details Search a replica guid in the database, creates it if it does not exist
 
248
 
 
249
   \param mstore_ctx pointer to the mapistore context
 
250
   \param guidP the replica guid
 
251
   \param replidP pointer to the returned replica id
 
252
 
 
253
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 
254
 */
 
255
_PUBLIC_ enum mapistore_error mapistore_replica_mapping_guid_to_replid(struct mapistore_context *mstore_ctx, const char *username, const struct GUID *guidP, uint16_t *replidP)
 
256
{
 
257
        int             ret;
 
258
        uint16_t        new_replid;
 
259
        struct replica_mapping_context_list *list;
 
260
 
 
261
        ret = mapistore_replica_mapping_add(mstore_ctx, username, &list);
 
262
        MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERROR, NULL);
 
263
        MAPISTORE_RETVAL_IF(!list, MAPISTORE_ERROR, NULL);
 
264
 
 
265
        ret = mapistore_replica_mapping_search_guid(list->tdb, guidP, replidP);
 
266
        if (ret == MAPISTORE_SUCCESS) {
 
267
                return ret;
 
268
        }
 
269
 
 
270
        new_replid = mapistore_replica_mapping_get_next_replid(list->tdb);
 
271
        if (new_replid == 0xffff) { /* should never occur */
 
272
                DEBUG(0, ("%s: FATAL: next replica id is not configured for this database\n", __FUNCTION__));
 
273
                return MAPISTORE_ERROR;
 
274
        }
 
275
 
 
276
        mapistore_replica_mapping_add_pair(list->tdb, guidP, new_replid);
 
277
        mapistore_replica_mapping_set_next_replid(list->tdb, new_replid + 1);
 
278
 
 
279
        *replidP = new_replid;
 
280
 
 
281
        return MAPISTORE_SUCCESS;
 
282
}
 
283
 
 
284
/**
 
285
   \details Search a replica id in the database
 
286
 
 
287
   \param mstore_ctx pointer to the mapistore context
 
288
   \param replid the replica id
 
289
   \param guidP pointer to the returned replica guid
 
290
 
 
291
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 
292
 */
 
293
_PUBLIC_ enum mapistore_error mapistore_replica_mapping_replid_to_guid(struct mapistore_context *mstore_ctx, const char *username, uint16_t replid, struct GUID *guidP)
 
294
{
 
295
        void                                    *mem_ctx;
 
296
        TDB_DATA                                guid_key, replid_key;
 
297
        int                                     ret;
 
298
        struct replica_mapping_context_list     *list;
 
299
 
 
300
        ret = mapistore_replica_mapping_add(mstore_ctx, username, &list);
 
301
        MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERROR, NULL);
 
302
        MAPISTORE_RETVAL_IF(!list, MAPISTORE_ERROR, NULL);
 
303
 
 
304
        mem_ctx = talloc_zero(NULL, void);
 
305
 
 
306
        replid_key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%.4x", replid);
 
307
        replid_key.dsize = strlen((const char *) replid_key.dptr);
 
308
 
 
309
        ret = tdb_exists(list->tdb, replid_key);
 
310
        if (!ret) {
 
311
                talloc_free(mem_ctx);
 
312
                return MAPISTORE_ERROR;
 
313
        }
 
314
 
 
315
        guid_key = tdb_fetch(list->tdb, replid_key);
 
316
        GUID_from_string((char *) guid_key.dptr, guidP);
 
317
 
 
318
        talloc_free(mem_ctx);
 
319
 
 
320
        return MAPISTORE_SUCCESS;
 
321
}