2
Public Folders Administration Tool
6
Copyright (C) Julien Kerihuel 2007
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.
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.
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/>.
22
#include "libmapi/libmapi.h"
23
#include "libmapiadmin/libmapiadmin.h"
24
#include <samba/popt.h>
27
#include "openchangepfadmin.h"
28
#include "openchange-tools.h"
30
static int32_t get_aclrights(const char *permission)
34
if (!permission) return -1;
36
for (i = 0; aclrights[i].name != NULL; i++) {
37
if (!strcmp(permission, aclrights[i].name)) {
38
return aclrights[i].value;
44
static void list_aclrights(void)
48
printf("Valid permissions:\n");
49
for (i = 0; aclrights[i].name != NULL; i++) {
50
printf("\t%s\n", aclrights[i].name);
54
static int32_t check_IPF_class(const char *dirclass)
58
if (!dirclass) return -1;
60
for (i = 0; IPF_class[i]; i++) {
61
if (!strcmp(dirclass, IPF_class[i])) {
69
static void list_IPF_class(void)
73
printf("Valid IPF Classes:\n");
74
for (i = 0; IPF_class[i] != NULL; i++) {
75
printf("\t%s\n", IPF_class[i]);
79
static bool get_child_folders_pf(TALLOC_CTX *mem_ctx, mapi_object_t *parent, mapi_id_t folder_id, int count)
81
enum MAPISTATUS retval;
83
mapi_object_t obj_folder;
84
mapi_object_t obj_htable;
85
struct SPropTagArray *SPropTagArray;
86
struct SRowSet rowset;
88
const uint32_t *child;
93
mapi_object_init(&obj_folder);
94
retval = OpenFolder(parent, folder_id, &obj_folder);
95
if (retval != MAPI_E_SUCCESS) return false;
97
mapi_object_init(&obj_htable);
98
retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
99
if (retval != MAPI_E_SUCCESS) return false;
101
SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
102
PR_DISPLAY_NAME_UNICODE,
104
PR_FOLDER_CHILD_COUNT);
105
retval = SetColumns(&obj_htable, SPropTagArray);
106
MAPIFreeBuffer(SPropTagArray);
107
if (retval != MAPI_E_SUCCESS) return false;
109
while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
110
for (index = 0; index < rowset.cRows; index++) {
111
fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
112
name = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME_UNICODE);
113
child = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_FOLDER_CHILD_COUNT);
115
for (i = 0; i < count; i++) {
118
printf("|---+ %-15s\n", name);
120
ret = get_child_folders_pf(mem_ctx, &obj_folder, *fid, count + 1);
121
if (ret == false) return ret;
129
static enum MAPISTATUS openchangepfadmin_getdir(TALLOC_CTX *mem_ctx,
130
mapi_object_t *obj_container,
131
mapi_object_t *obj_child,
134
enum MAPISTATUS retval;
135
struct SPropTagArray *SPropTagArray;
136
struct SRowSet rowset;
137
mapi_object_t obj_htable;
142
mapi_object_init(&obj_htable);
143
retval = GetHierarchyTable(obj_container, &obj_htable, 0, NULL);
144
MAPI_RETVAL_IF(retval, GetLastError(), NULL);
146
SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
147
PR_DISPLAY_NAME_UNICODE,
149
retval = SetColumns(&obj_htable, SPropTagArray);
150
MAPIFreeBuffer(SPropTagArray);
151
if (retval != MAPI_E_SUCCESS) return MAPI_E_NOT_FOUND;
153
while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
154
for (index = 0; index < rowset.cRows; index++) {
155
fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
156
name = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME_UNICODE);
158
if (name && fid && !strcmp(name, folder)) {
159
retval = OpenFolder(obj_container, *fid, obj_child);
160
MAPI_RETVAL_IF(retval, GetLastError(), NULL);
161
return MAPI_E_SUCCESS;
166
errno = MAPI_E_NOT_FOUND;
167
return MAPI_E_NOT_FOUND;
170
static enum MAPISTATUS openchangepfadmin_mkdir(mapi_object_t *obj_container,
175
enum MAPISTATUS retval;
176
mapi_object_t obj_folder;
177
struct SPropValue props[1];
178
uint32_t prop_count = 0;
180
mapi_object_init(&obj_folder);
181
retval = CreateFolder(obj_container, FOLDER_GENERIC, name, comment, OPEN_IF_EXISTS, &obj_folder);
182
MAPI_RETVAL_IF(retval, GetLastError(), NULL);
185
set_SPropValue_proptag(&props[0], PR_CONTAINER_CLASS, (const void *) type);
188
retval = SetProps(&obj_folder, 0, props, prop_count);
189
mapi_object_release(&obj_folder);
190
MAPI_RETVAL_IF(retval, GetLastError(), NULL);
193
return MAPI_E_SUCCESS;
196
static enum MAPISTATUS openchangepfadmin_rmdir(TALLOC_CTX *mem_ctx,
197
mapi_object_t *obj_container,
200
enum MAPISTATUS retval;
201
mapi_object_t obj_folder;
203
mapi_object_init(&obj_folder);
205
retval = openchangepfadmin_getdir(mem_ctx, obj_container, &obj_folder, name);
206
MAPI_RETVAL_IF(retval, GetLastError(), NULL);
208
retval = EmptyFolder(&obj_folder);
209
MAPI_RETVAL_IF(retval, GetLastError(), NULL);
211
retval = DeleteFolder(obj_container, mapi_object_get_id(&obj_folder),
213
MAPI_RETVAL_IF(retval, GetLastError(), NULL);
215
mapi_object_release(&obj_folder);
217
return MAPI_E_SUCCESS;
220
int main(int argc, const char *argv[])
223
enum MAPISTATUS retval;
224
struct mapi_context *mapi_ctx;
225
struct mapi_session *session = NULL;
226
mapi_object_t obj_store;
227
mapi_object_t obj_ipm_subtree;
228
mapi_object_t obj_folder;
232
const char *opt_profdb = NULL;
233
char *opt_profname = NULL;
234
const char *opt_password = NULL;
235
const char *opt_comment = NULL;
236
const char *opt_dirclass = NULL;
237
const char *opt_adduser = NULL;
238
const char *opt_rmuser = NULL;
239
const char *opt_apassword = NULL;
240
const char *opt_adesc = NULL;
241
const char *opt_acomment = NULL;
242
const char *opt_afullname = NULL;
243
const char *opt_addright = NULL;
244
bool opt_rmright = false;
245
const char *opt_modright = NULL;
246
const char *opt_folder = NULL;
247
const char *opt_debug = NULL;
248
const char *opt_username = NULL;
249
int32_t opt_permission = -1;
250
bool opt_ipm_list = false;
251
bool opt_mkdir = false;
252
bool opt_rmdir = false;
253
bool opt_dumpdata = false;
255
enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_PASSWORD, OPT_IPM_LIST,
256
OPT_MKDIR, OPT_RMDIR, OPT_COMMENT, OPT_DIRCLASS, OPT_ACL,
257
OPT_ADDUSER, OPT_RMUSER, OPT_DEBUG, OPT_APASSWORD, OPT_ADESC,
258
OPT_ACOMMENT, OPT_AFULLNAME, OPT_ADDRIGHT, OPT_RMRIGHT,
259
OPT_MODRIGHT, OPT_USERNAME, OPT_FOLDER, OPT_DUMPDATA};
261
struct poptOption long_options[] = {
263
{"database", 'f', POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", "PATH"},
264
{"profile", 'p', POPT_ARG_STRING, NULL, OPT_PROFILE, "set the profile name", "PROFILE"},
265
{"password", 'P', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile password", "PASSWORD"},
266
{"apassword", 0, POPT_ARG_STRING, NULL, OPT_APASSWORD, "set the account password", "PASSWORD"},
267
{"adesc", 0, POPT_ARG_STRING, NULL, OPT_ADESC, "set the account description", "DESCRIPTION"},
268
{"acomment", 0, POPT_ARG_STRING, NULL, OPT_ACOMMENT, "set the account comment", "COMMENT"},
269
{"afullname", 0, POPT_ARG_STRING, NULL, OPT_AFULLNAME, "set the account full name", "NAME"},
270
{"list",0, POPT_ARG_NONE, NULL, OPT_IPM_LIST, "list IPM subtree directories", NULL},
271
{"mkdir", 0, POPT_ARG_NONE, NULL, OPT_MKDIR, "create a Public Folder directory", NULL},
272
{"rmdir", 0, POPT_ARG_NONE, NULL, OPT_RMDIR, "delete a Public Folder directory", NULL},
273
{"comment", 0, POPT_ARG_STRING, NULL, OPT_COMMENT, "set the folder comment", "COMMENT"},
274
{"dirclass", 0, POPT_ARG_STRING, NULL, OPT_DIRCLASS, "set the folder class", "CLASS"},
275
{"adduser", 0, POPT_ARG_STRING, NULL, OPT_ADDUSER, "add Exchange user", "USERNAME"},
276
{"rmuser", 0, POPT_ARG_STRING, NULL, OPT_RMUSER, "delete Exchange user", "USERNAME"},
277
{"addright", 0, POPT_ARG_STRING, NULL, OPT_ADDRIGHT, "add MAPI permissions to PF folder", "RIGHT"},
278
{"rmright", 0, POPT_ARG_NONE, NULL, OPT_RMRIGHT, "remove MAPI permissions to PF folder", NULL},
279
{"modright", 0, POPT_ARG_STRING, NULL, OPT_MODRIGHT, "modify MAPI permissions to PF folder", "RIGHT"},
280
{"debuglevel", 0, POPT_ARG_STRING, NULL, OPT_DEBUG, "set debug level", "LEVEL"},
281
{"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "Dump the hex data", NULL},
282
{"folder", 0, POPT_ARG_STRING, NULL, OPT_FOLDER, "specify the Public Folder directory", "FOLDER"},
283
{"username", 0, POPT_ARG_STRING, NULL, OPT_USERNAME, "specify the username to use", "USERNAME"},
284
POPT_OPENCHANGE_VERSION
285
{ NULL, 0, POPT_ARG_NONE, NULL, 0, NULL, NULL }
288
mem_ctx = talloc_named(NULL, 0, "openchangepfadmin");
290
pc = poptGetContext("openchangepfadmin", argc, argv, long_options, 0);
292
while ((opt = poptGetNextOpt(pc)) != -1) {
295
opt_debug = poptGetOptArg(pc);
301
opt_profdb = poptGetOptArg(pc);
304
opt_profname = talloc_strdup(mem_ctx, poptGetOptArg(pc));
307
opt_password = poptGetOptArg(pc);
319
opt_comment = poptGetOptArg(pc);
322
opt_dirclass = poptGetOptArg(pc);
325
opt_adduser = poptGetOptArg(pc);
328
opt_rmuser = poptGetOptArg(pc);
331
opt_apassword = poptGetOptArg(pc);
334
opt_adesc = poptGetOptArg(pc);
337
opt_acomment = poptGetOptArg(pc);
340
opt_afullname = poptGetOptArg(pc);
343
opt_addright = poptGetOptArg(pc);
349
opt_modright = poptGetOptArg(pc);
352
opt_folder = poptGetOptArg(pc);
355
opt_username = poptGetOptArg(pc);
362
/* Sanity check on options */
364
if ((opt_mkdir == true && !opt_folder) || (opt_rmdir == true && !opt_folder) ||
365
(opt_addright && !opt_folder) || (opt_rmright == true && !opt_folder) ||
366
(opt_modright && !opt_folder)) {
367
printf("You need to specify a directory with --folder option\n");
371
if ((opt_addright && !opt_username) || (opt_rmright == true && !opt_username) ||
372
(opt_modright && !opt_username)) {
373
printf("You need to specify a username with --username option\n");
377
/* dirclass sanity check */
379
if (check_IPF_class(opt_dirclass) == -1) {
386
opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
390
* Initialize MAPI subsystem
392
retval = MAPIInitialize(&mapi_ctx, opt_profdb);
393
if (retval != MAPI_E_SUCCESS) {
394
mapi_errstr("MAPIInitialize", GetLastError());
399
SetMAPIDumpData(mapi_ctx, opt_dumpdata);
402
SetMAPIDebugLevel(mapi_ctx, atoi(opt_debug));
406
* If no profile is specified, try to load the default one
410
retval = GetDefaultProfile(mapi_ctx, &opt_profname);
411
if (retval != MAPI_E_SUCCESS) {
412
mapi_errstr("GetDefaultProfile", GetLastError());
417
retval = MapiLogonEx(mapi_ctx, &session, opt_profname, opt_password);
418
talloc_free(opt_profname);
419
if (retval != MAPI_E_SUCCESS) {
420
mapi_errstr("MapiLogonEx", GetLastError());
425
* User management operations
429
struct mapiadmin_ctx *mapiadmin_ctx;
431
mapiadmin_ctx = mapiadmin_init(session);
432
mapiadmin_ctx->username = opt_adduser;
433
mapiadmin_ctx->password = opt_apassword;
434
mapiadmin_ctx->description = opt_adesc;
435
mapiadmin_ctx->comment = opt_acomment;
436
mapiadmin_ctx->fullname = opt_afullname;
438
retval = mapiadmin_user_add(mapiadmin_ctx);
439
mapi_errstr("mapiadmin_user_add", GetLastError());
440
if (retval != MAPI_E_SUCCESS) {
443
printf("username: %s\n", mapiadmin_ctx->username);
444
printf("password: %s\n", mapiadmin_ctx->password);
448
struct mapiadmin_ctx *mapiadmin_ctx;
450
mapiadmin_ctx = mapiadmin_init(session);
451
mapiadmin_ctx->username = opt_rmuser;
453
retval = mapiadmin_user_del(mapiadmin_ctx);
454
mapi_errstr("mapiadmin_user_del", GetLastError());
458
* Open Public Folder Store
461
mapi_object_init(&obj_store);
462
retval = OpenPublicFolder(session, &obj_store);
463
if (retval != MAPI_E_SUCCESS) {
464
mapi_errstr("OpenPublicFolder", GetLastError());
468
/* Open IPM Subtree (All Public Folders) */
469
retval = GetDefaultPublicFolder(&obj_store, &id_pf, olFolderPublicIPMSubtree);
470
if (retval != MAPI_E_SUCCESS) {
474
mapi_object_init(&obj_ipm_subtree);
475
retval = OpenFolder(&obj_store, id_pf, &obj_ipm_subtree);
476
if (retval != MAPI_E_SUCCESS) {
477
mapi_errstr("OpenFolder", GetLastError());
481
/* create directory */
482
if (opt_mkdir == true) {
483
retval = openchangepfadmin_mkdir(&obj_ipm_subtree, opt_folder, opt_comment, opt_dirclass);
484
if (retval != MAPI_E_SUCCESS) {
485
mapi_errstr("mkdir", GetLastError());
490
/* remove directory */
491
if (opt_rmdir == true) {
492
retval = openchangepfadmin_rmdir(mem_ctx, &obj_ipm_subtree, opt_folder);
493
if (retval != MAPI_E_SUCCESS) {
494
mapi_errstr("rmdir", GetLastError());
500
/* add permissions */
502
if ((opt_permission = get_aclrights(opt_addright)) == -1) {
503
printf("Invalid permission\n");
507
mapi_object_init(&obj_folder);
508
retval = openchangepfadmin_getdir(mem_ctx, &obj_ipm_subtree, &obj_folder, opt_folder);
509
if (retval != MAPI_E_SUCCESS) {
510
printf("Invalid directory\n");
513
retval = AddUserPermission(&obj_folder, opt_username, opt_permission);
514
if (retval != MAPI_E_SUCCESS) {
515
mapi_errstr("AddUserPermission", GetLastError());
516
mapi_object_release(&obj_folder);
519
mapi_object_release(&obj_folder);
521
printf("Permission %s added for %s on folder %s\n", opt_addright, opt_username, opt_folder);
524
/* remove permissions */
525
if (opt_rmright == true) {
526
mapi_object_init(&obj_folder);
527
retval = openchangepfadmin_getdir(mem_ctx, &obj_ipm_subtree, &obj_folder, opt_folder);
528
if (retval != MAPI_E_SUCCESS) {
529
printf("Invalid directory\n");
532
retval = RemoveUserPermission(&obj_folder, opt_username);
533
if (retval != MAPI_E_SUCCESS) {
534
mapi_errstr("RemoveUserPermission", GetLastError());
535
mapi_object_release(&obj_folder);
538
mapi_object_release(&obj_folder);
539
printf("Permission removed for %s on folder %s\n", opt_username, opt_folder);
542
/* modify permissions */
544
opt_permission = get_aclrights(opt_modright);
545
if (opt_permission == -1) {
546
printf("Invalid permission\n");
550
mapi_object_init(&obj_folder);
551
retval = openchangepfadmin_getdir(mem_ctx, &obj_ipm_subtree, &obj_folder, opt_folder);
552
if (retval != MAPI_E_SUCCESS) {
553
printf("Invalid directory\n");
556
retval = ModifyUserPermission(&obj_folder, opt_username, opt_permission);
557
if (retval != MAPI_E_SUCCESS) {
558
mapi_errstr("ModifyUserPermission", GetLastError());
559
mapi_object_release(&obj_folder);
562
mapi_object_release(&obj_folder);
564
printf("Permission changed to %s for %s on folder %s\n", opt_modright, opt_username, opt_folder);
567
/* list directories */
568
if (opt_ipm_list == true) {
569
printf("+ All Public Folders\n");
570
get_child_folders_pf(mem_ctx, &obj_ipm_subtree, id_pf, 0);
574
* Uninitialize MAPI subsystem
577
mapi_object_release(&obj_store);
579
MAPIUninitialize(mapi_ctx);
580
talloc_free(mem_ctx);