server: intialize aux_header buffer to null if the data is missing.
[tridge/openchange.git] / branches / plugfest / utils / mapiprofile.c
1 /*
2    Wrapper over the MAPI Profile API
3
4    OpenChange Project
5
6    Copyright (C) Julien Kerihuel 2007-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 #include "libmapi/libmapi.h"
23 #include <samba/popt.h>
24 #include <param.h>
25 #include "openchange-tools.h"
26
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <stdlib.h>
30 #include <signal.h>
31
32 #define DEFAULT_DIR                     "%s/.openchange"
33 #define DEFAULT_PROFDB                  "%s/.openchange/profiles.ldb"
34 #define DEFAULT_EXCHANGE_VERSION        "2000"
35
36 /**
37    MAPI version:
38    #- 0: use EcDoConnect (0x0) / EcDoRpc (0x2) RPC calls
39    #- 1: use EcDoConnectEx (0xA) / EcDoRpcExt2 (0xB) RPC calls
40    #- 2: Same as 1, but require sealed pipe
41  */
42 struct exchange_version {
43         const char      *name;
44         uint8_t         version;
45 };
46
47 static const struct exchange_version exchange_version[] = {
48         { DEFAULT_EXCHANGE_VERSION,     0 },
49         { "2003",                       1 },
50         { "2007",                       1 },
51         { "2010",                       2 },
52         { NULL,                         0 }
53 };
54
55 static bool mapiprofile_createdb(const char *profdb, const char *ldif_path)
56 {
57         enum MAPISTATUS retval;
58         
59         if (access(profdb, F_OK) == 0) {
60                 fprintf(stderr, "[ERROR] mapiprofile: %s already exists\n", profdb);
61                 return false;
62         }
63
64         retval = CreateProfileStore(profdb, ldif_path);
65         if (retval != MAPI_E_SUCCESS) {
66                 mapi_errstr("CreateProfileStore", GetLastError());
67                 return false;
68         }
69         return true;
70 }
71
72 static uint32_t callback(struct SRowSet *rowset, void *private)
73 {
74         uint32_t                i;
75         struct SPropValue       *lpProp;
76         FILE                    *fd;
77         uint32_t                index;
78         char                    entry[10];
79         const char              *label = (const char *)private;
80
81         printf("%s:\n", label);
82         for (i = 0; i < rowset->cRows; i++) {
83                 lpProp = get_SPropValue_SRow(&(rowset->aRow[i]), PR_DISPLAY_NAME);
84                 if (lpProp && lpProp->value.lpszA) {
85                         printf("\t[%u] %s\n", i, lpProp->value.lpszA);
86                 }
87         }
88         printf("\t[%u] cancel operation\n", i);
89         fd = fdopen(0, "r");
90 getentry:
91         printf("Enter username id [0]: ");
92         if (fgets(entry, 10, fd) == NULL) {
93                 printf("Failed to read string\n");
94                 exit(1);
95         }
96
97         index = atoi(entry);
98         if (index > i) {
99                 printf("Invalid id - Must be a value between 0 and %u\n", i);
100                 goto getentry;
101         }
102         
103         fclose(fd);
104         return (index);
105 }
106
107 const char *g_profname;
108 struct mapi_context *g_mapi_ctx;
109
110 static void signal_delete_profile(void)
111 {
112         enum MAPISTATUS retval;
113
114         fprintf(stderr, "CTRL-C caught ... Deleting profile\n");
115         if ((retval = DeleteProfile(g_mapi_ctx, g_profname)) != MAPI_E_SUCCESS) {
116                 mapi_errstr("DeleteProfile", GetLastError());
117         }
118
119         (void) signal(SIGINT, SIG_DFL);
120         exit (1);
121 }
122
123 static bool mapiprofile_create(const char *profdb, const char *profname,
124                                const char *pattern, const char *username, 
125                                const char *password, const char *address, 
126                                const char *language, const char *workstation,
127                                const char *domain, const char *realm,
128                                uint32_t flags, bool seal,
129                                bool opt_dumpdata, const char *opt_debuglevel,
130                                uint8_t exchange_version)
131 {
132         enum MAPISTATUS         retval;
133         struct mapi_context     *mapi_ctx;
134         struct mapi_session     *session = NULL;
135         TALLOC_CTX              *mem_ctx;
136         struct mapi_profile     profile;
137         const char              *locale;
138         uint32_t                cpid;
139         uint32_t                lcid;
140         char                    *exchange_version_str;
141         char                    *cpid_str;
142         char                    *lcid_str;
143
144         mem_ctx = talloc_named(NULL, 0, "mapiprofile_create");
145
146         retval = MAPIInitialize(&mapi_ctx, profdb);
147         if (retval != MAPI_E_SUCCESS) {
148                 mapi_errstr("MAPIInitialize", GetLastError());
149                 talloc_free(mem_ctx);
150                 return false;
151         }
152
153         /* catch CTRL-C */
154         g_profname = profname;
155         g_mapi_ctx = mapi_ctx;
156
157 #if defined (__FreeBSD__)
158         (void) signal(SIGINT, (sig_t) signal_delete_profile);
159 #elif defined (__SunOS)
160         (void) signal(SIGINT, signal_delete_profile);
161 #else
162         (void) signal(SIGINT, (sighandler_t) signal_delete_profile);
163 #endif
164
165         /* debug options */
166         SetMAPIDumpData(mapi_ctx, opt_dumpdata);
167
168         if (opt_debuglevel) {
169                 SetMAPIDebugLevel(mapi_ctx, atoi(opt_debuglevel));
170         }
171
172         /* Sanity check */
173         retval = OpenProfile(mapi_ctx, &profile, profname, NULL);
174         if (retval == MAPI_E_SUCCESS) {
175                 fprintf(stderr, "[ERROR] mapiprofile: profile \"%s\" already exists\n", profname);
176                 MAPIUninitialize(mapi_ctx);
177                 talloc_free(mem_ctx);
178                 return false;
179         }
180
181         retval = CreateProfile(mapi_ctx, profname, username, password, flags);
182         if (retval != MAPI_E_SUCCESS) {
183                 mapi_errstr("CreateProfile", GetLastError());
184                 talloc_free(mem_ctx);
185                 return false;
186         }
187
188         mapi_profile_add_string_attr(mapi_ctx, profname, "binding", address);
189         mapi_profile_add_string_attr(mapi_ctx, profname, "workstation", workstation);
190         mapi_profile_add_string_attr(mapi_ctx, profname, "domain", domain);
191         mapi_profile_add_string_attr(mapi_ctx, profname, "seal", (seal == true) ? "true" : "false");
192
193         exchange_version_str = talloc_asprintf(mem_ctx, "%d", exchange_version);
194         mapi_profile_add_string_attr(mapi_ctx, profname, "exchange_version", exchange_version_str);
195         talloc_free(exchange_version_str);
196
197         if (realm) {
198                 mapi_profile_add_string_attr(mapi_ctx, profname, "realm", realm);
199         }
200
201         locale = (const char *) (language) ? mapi_get_locale_from_language(language) : mapi_get_system_locale();
202
203         if (locale) {
204                 cpid = mapi_get_cpid_from_locale(locale);
205                 lcid = mapi_get_lcid_from_locale(locale);
206         }
207
208         if (!locale || !cpid || !lcid) {
209                 printf("Invalid Language supplied or unknown system language '%s\n'", language);
210                 printf("Deleting profile\n");
211                 if ((retval = DeleteProfile(mapi_ctx, profname)) != MAPI_E_SUCCESS) {
212                         mapi_errstr("DeleteProfile", GetLastError());
213                 }
214                 talloc_free(mem_ctx);
215                 return false;
216         }
217
218         cpid_str = talloc_asprintf(mem_ctx, "%d", cpid);
219         lcid_str = talloc_asprintf(mem_ctx, "0x%.4x", lcid);
220
221         mapi_profile_add_string_attr(mapi_ctx, profname, "codepage", cpid_str);
222         mapi_profile_add_string_attr(mapi_ctx, profname, "language", lcid_str);
223         mapi_profile_add_string_attr(mapi_ctx, profname, "method", lcid_str);
224
225         talloc_free(cpid_str);
226         talloc_free(lcid_str);
227
228         retval = MapiLogonProvider(mapi_ctx, &session, profname, password, PROVIDER_ID_NSPI);
229         if (retval != MAPI_E_SUCCESS) {
230                 mapi_errstr("MapiLogonProvider", GetLastError());
231                 printf("Deleting profile\n");
232                 if ((retval = DeleteProfile(mapi_ctx, profname)) != MAPI_E_SUCCESS) {
233                         mapi_errstr("DeleteProfile", GetLastError());
234                 }
235                 talloc_free(mem_ctx);
236                 return false;
237         }
238
239         if (pattern) {
240                 username = pattern;
241         }
242
243         retval = ProcessNetworkProfile(session, username, (mapi_profile_callback_t) callback, "Select a user id");
244         if (retval != MAPI_E_SUCCESS && retval != 0x1) {
245                 mapi_errstr("ProcessNetworkProfile", GetLastError());
246                 printf("Deleting profile\n");
247                 if ((retval = DeleteProfile(mapi_ctx, profname)) != MAPI_E_SUCCESS) {
248                         mapi_errstr("DeleteProfile", GetLastError());
249                 }
250                 talloc_free(mem_ctx);
251                 return false;
252         }
253
254         printf("Profile %s completed and added to database %s\n", profname, profdb);
255
256         talloc_free(mem_ctx);
257
258         MAPIUninitialize(mapi_ctx);
259
260         return true;
261 }
262
263 static void mapiprofile_delete(const char *profdb, const char *profname)
264 {
265         enum MAPISTATUS         retval;
266         struct mapi_context     *mapi_ctx;
267
268         if ((retval = MAPIInitialize(&mapi_ctx, profdb)) != MAPI_E_SUCCESS) {
269                 mapi_errstr("MAPIInitialize", GetLastError());
270                 exit (1);
271         }
272
273         if ((retval = DeleteProfile(mapi_ctx, profname)) != MAPI_E_SUCCESS) {
274                 mapi_errstr("DeleteProfile", GetLastError());
275                 exit (1);
276         }
277
278         printf("Profile %s deleted from database %s\n", profname, profdb);
279
280         MAPIUninitialize(mapi_ctx);
281 }
282
283
284 static void mapiprofile_rename(const char *profdb, const char *old_profname, const char *new_profname)
285 {
286         TALLOC_CTX              *mem_ctx;
287         enum MAPISTATUS         retval;
288         struct mapi_context     *mapi_ctx;
289         char                    *profname;
290
291         if ((retval = MAPIInitialize(&mapi_ctx, profdb)) != MAPI_E_SUCCESS) {
292                 mapi_errstr("MAPIInitialize", retval);
293                 exit (1);
294         }
295
296         mem_ctx = talloc_named(NULL, 0, "mapiprofile_rename");
297
298         if (!old_profname) {
299                 if ((retval = GetDefaultProfile(mapi_ctx, &profname)) != MAPI_E_SUCCESS) {
300                         mapi_errstr("GetDefaultProfile", retval);
301                         talloc_free(mem_ctx);
302                         exit (1);
303                 }
304         } else {
305                 profname = talloc_strdup(mem_ctx, old_profname);
306         }
307
308         if ((retval = RenameProfile(mapi_ctx, profname, new_profname)) != MAPI_E_SUCCESS) {
309                 mapi_errstr("RenameProfile", retval);
310                 talloc_free(profname);
311                 talloc_free(mem_ctx);
312                 exit (1);
313         }
314
315         talloc_free(profname);
316         talloc_free(mem_ctx);
317         MAPIUninitialize(mapi_ctx);
318 }
319
320
321 static void mapiprofile_set_default(const char *profdb, const char *profname)
322 {
323         enum MAPISTATUS         retval;
324         struct mapi_context     *mapi_ctx;
325
326         if ((retval = MAPIInitialize(&mapi_ctx, profdb)) != MAPI_E_SUCCESS) {
327                 mapi_errstr("MAPIInitialize", GetLastError());
328                 exit (1);
329         }
330
331         if ((retval = SetDefaultProfile(mapi_ctx, profname)) != MAPI_E_SUCCESS) {
332                 mapi_errstr("SetDefaultProfile", GetLastError());
333                 exit (1);
334         }
335
336         printf("Profile %s is now set the default one\n", profname);
337
338         MAPIUninitialize(mapi_ctx);
339 }
340
341 static void mapiprofile_get_default(const char *profdb)
342 {
343         enum MAPISTATUS         retval;
344         struct mapi_context     *mapi_ctx;
345         char                    *profname;
346
347         if ((retval = MAPIInitialize(&mapi_ctx, profdb)) != MAPI_E_SUCCESS) {
348                 mapi_errstr("MAPIInitialize", GetLastError());
349                 exit (1);
350         }
351         
352         if ((retval = GetDefaultProfile(mapi_ctx, &profname)) != MAPI_E_SUCCESS) {
353                 mapi_errstr("GetDefaultProfile", GetLastError());
354                 exit (1);
355         }
356
357         printf("Default profile is set to %s\n", profname);
358
359         talloc_free(profname);
360         MAPIUninitialize(mapi_ctx);
361 }
362
363 static void mapiprofile_get_fqdn(const char *profdb, 
364                                  const char *opt_profname, 
365                                  const char *password,
366                                  bool opt_dumpdata)
367 {
368         TALLOC_CTX              *mem_ctx;
369         enum MAPISTATUS         retval;
370         struct mapi_context     *mapi_ctx;
371         struct mapi_session     *session = NULL;
372         const char              *serverFQDN;
373         char                    *profname;
374
375         if ((retval = MAPIInitialize(&mapi_ctx, profdb)) != MAPI_E_SUCCESS) {
376                 mapi_errstr("MAPIInitialize", GetLastError());
377                 exit (1);
378         }
379
380         SetMAPIDumpData(mapi_ctx, opt_dumpdata);
381
382         mem_ctx = talloc_named(NULL, 0, "mapiprofile_get_fqdn");
383
384         if (!opt_profname) {
385                 if ((retval = GetDefaultProfile(mapi_ctx, &profname)) != MAPI_E_SUCCESS) {
386                         mapi_errstr("GetDefaultProfile", GetLastError());
387                         talloc_free(mem_ctx);
388                         exit (1);
389                 }
390         } else {
391                 profname = talloc_strdup(mem_ctx, (char *)opt_profname);
392         }
393
394         retval = MapiLogonProvider(mapi_ctx, &session, profname, password, PROVIDER_ID_NSPI);
395         talloc_free(profname);
396         talloc_free(mem_ctx);
397         if (retval != MAPI_E_SUCCESS) {
398                 mapi_errstr("MapiLogonProvider", GetLastError());
399                 exit (1);
400         }
401
402         retval = RfrGetFQDNFromLegacyDN(mapi_ctx, session, &serverFQDN);
403         if (retval != MAPI_E_SUCCESS) {
404                 mapi_errstr("RfrGetFQDNFromLegacyDN", GetLastError());
405                 exit (1);
406         }
407
408         printf("%s is at %s\n", mapi_ctx->session->profile->homemdb, serverFQDN);
409
410         MAPIUninitialize(mapi_ctx);
411 }
412
413 static void mapiprofile_list(const char *profdb)
414 {
415         enum MAPISTATUS         retval;
416         struct mapi_context     *mapi_ctx;
417         struct SRowSet          proftable;
418         uint32_t                count = 0;
419
420         if ((retval = MAPIInitialize(&mapi_ctx, profdb)) != MAPI_E_SUCCESS) {
421                 mapi_errstr("MAPIInitialize", GetLastError());
422                 exit (1);
423         }
424
425         memset(&proftable, 0, sizeof (struct SRowSet));
426         if ((retval = GetProfileTable(mapi_ctx, &proftable)) != MAPI_E_SUCCESS) {
427                 mapi_errstr("GetProfileTable", GetLastError());
428                 exit (1);
429         }
430
431         printf("We have %u profiles in the database:\n", proftable.cRows);
432
433         for (count = 0; count != proftable.cRows; count++) {
434                 const char      *name = NULL;
435                 uint32_t        dflt = 0;
436
437                 name = proftable.aRow[count].lpProps[0].value.lpszA;
438                 dflt = proftable.aRow[count].lpProps[1].value.l;
439
440                 if (dflt) {
441                         printf("\tProfile = %s [default]\n", name);
442                 } else {
443                         printf("\tProfile = %s\n", name);
444                 }
445
446         }
447
448         MAPIUninitialize(mapi_ctx);
449 }
450
451 static void mapiprofile_dump(const char *profdb, const char *opt_profname)
452 {
453         TALLOC_CTX              *mem_ctx;
454         enum MAPISTATUS         retval;
455         struct mapi_context     *mapi_ctx;
456         struct mapi_profile     profile;
457         char                    *profname;
458         char                    *exchange_version = NULL;
459
460         if ((retval = MAPIInitialize(&mapi_ctx, profdb)) != MAPI_E_SUCCESS) {
461                 mapi_errstr("MAPIInitialize", GetLastError());
462                 exit (1);
463         }
464
465         mem_ctx = talloc_named(NULL, 0, "mapiprofile_dump");
466
467         if (!opt_profname) {
468                 if ((retval = GetDefaultProfile(mapi_ctx, &profname)) != MAPI_E_SUCCESS) {
469                         mapi_errstr("GetDefaultProfile", GetLastError());
470                         talloc_free(mem_ctx);
471                         exit (1);
472                 }
473         } else {
474                 profname = talloc_strdup(mem_ctx, (const char *)opt_profname);
475         }
476
477         retval = OpenProfile(mapi_ctx, &profile, profname, NULL);
478         talloc_free(profname);
479
480         if (retval && (retval != MAPI_E_INVALID_PARAMETER)) {
481                 talloc_free(mem_ctx);
482                 mapi_errstr("OpenProfile", GetLastError());
483                 exit (1);
484         }
485
486         switch (profile.exchange_version) {
487         case 0x0:
488                 exchange_version = talloc_strdup(mem_ctx, "exchange 2000");
489                 break;
490         case 0x1:
491                 exchange_version = talloc_strdup(mem_ctx, "exchange 2003/2007");
492                 break;
493         case 0x2:
494                 exchange_version = talloc_strdup(mem_ctx, "exchange 2010");
495                 break;
496         default:
497                 printf("Error: unknown Exchange server\n");
498                 goto end;
499         }
500
501         printf("Profile: %s\n", profile.profname);
502         printf("\texchange server == %s\n", exchange_version);
503         printf("\tencryption      == %s\n", (profile.seal == true) ? "yes" : "no");
504         printf("\tusername        == %s\n", profile.username);
505         printf("\tpassword        == %s\n", profile.password);
506         printf("\tmailbox         == %s\n", profile.mailbox);
507         printf("\tworkstation     == %s\n", profile.workstation);
508         printf("\tdomain          == %s\n", profile.domain);
509         printf("\tserver          == %s\n", profile.server);
510
511 end:
512         talloc_free(mem_ctx);
513         MAPIUninitialize(mapi_ctx);
514 }
515
516 static void mapiprofile_attribute(const char *profdb, const char *opt_profname, 
517                                   const char *attribute)
518 {
519         TALLOC_CTX              *mem_ctx;
520         enum MAPISTATUS         retval;
521         struct mapi_context     *mapi_ctx;
522         struct mapi_profile     profile;
523         char                    *profname = NULL;
524         char                    **value = NULL;
525         unsigned int            count = 0;
526         unsigned int            i;
527
528         if ((retval = MAPIInitialize(&mapi_ctx, profdb)) != MAPI_E_SUCCESS) {
529                 mapi_errstr("MAPIInitialize", GetLastError());
530                 exit (1);
531         }
532
533         mem_ctx = talloc_named(NULL, 0, "mapiprofile_attribute");
534
535         if (!opt_profname) {
536                 if ((retval = GetDefaultProfile(mapi_ctx, &profname)) != MAPI_E_SUCCESS) {
537                         mapi_errstr("GetDefaultProfile", GetLastError());
538                         exit (1);
539                 }
540         } else {
541                 profname = talloc_strdup(mem_ctx, (const char *)opt_profname);
542         }
543
544         retval = OpenProfile(mapi_ctx, &profile, profname, NULL);
545         if (retval && (retval != MAPI_E_INVALID_PARAMETER)) {
546                 mapi_errstr("OpenProfile", GetLastError());
547                 talloc_free(profname);
548                 talloc_free(mem_ctx);
549                 exit (1);
550         }
551
552         if ((retval = GetProfileAttr(&profile, attribute, &count, &value))) {
553                 mapi_errstr("ProfileGetAttr", GetLastError());
554                 talloc_free(profname);
555                 talloc_free(mem_ctx);
556                 exit (1);
557         }
558
559         printf("Profile %s: results(%u)\n", profname, count);
560         for (i = 0; i < count; i++) {
561                 printf("\t%s = %s\n", attribute, value[i]);
562         }
563         MAPIFreeBuffer(value);
564         talloc_free(profname);
565         talloc_free(mem_ctx);
566
567         MAPIUninitialize(mapi_ctx);
568 }
569
570 static void show_help(poptContext pc, const char *param)
571 {
572         printf("%s argument missing\n", param);
573         poptPrintUsage(pc, stderr, 0);
574         exit (1);
575 }
576
577 int main(int argc, const char *argv[])
578 {
579         TALLOC_CTX      *mem_ctx;
580         int             error;
581         poptContext     pc;
582         int             opt;
583         int             i;
584         char            *default_path;
585         bool            found = false;
586         bool            create = false;
587         bool            delete = false;
588         bool            list = false;
589         bool            listlangs = false;
590         bool            dump = false;
591         bool            newdb = false;
592         bool            setdflt = false;
593         bool            getdflt = false;
594         bool            getfqdn = false;
595         bool            opt_dumpdata = false;
596         bool            opt_seal = false;
597         const char      *opt_debuglevel = NULL;
598         const char      *ldif = NULL;
599         const char      *address = NULL;
600         const char      *workstation = NULL;
601         const char      *domain = NULL;
602         const char      *realm = NULL;
603         const char      *username = NULL;
604         const char      *language = NULL;
605         const char      *pattern = NULL;
606         const char      *password = NULL;
607         const char      *profdb = NULL;
608         const char      *profname = NULL;
609         const char      *rename = NULL;
610         const char      *attribute = NULL;
611         const char      *opt_tmp = NULL;
612         const char      *version = NULL;
613         uint32_t        nopass = 0;
614         char            hostname[256];
615         int             retcode = EXIT_SUCCESS;
616
617         enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_ADDRESS, OPT_WORKSTATION,
618               OPT_DOMAIN, OPT_REALM, OPT_USERNAME, OPT_LANGUAGE, OPT_PASSWORD, 
619               OPT_CREATE_PROFILE, OPT_DELETE_PROFILE, OPT_LIST_PROFILE, OPT_DUMP_PROFILE, 
620               OPT_DUMP_ATTR, OPT_PROFILE_NEWDB, OPT_PROFILE_LDIF, OPT_LIST_LANGS,
621               OPT_PROFILE_SET_DFLT, OPT_PROFILE_GET_DFLT, OPT_PATTERN, OPT_GETFQDN,
622               OPT_NOPASS, OPT_RENAME_PROFILE, OPT_DUMPDATA, OPT_DEBUGLEVEL,
623               OPT_ENCRYPT_CONN, OPT_EXCHANGE_VERSION};
624
625         struct poptOption long_options[] = {
626                 POPT_AUTOHELP
627                 {"ldif", 'L', POPT_ARG_STRING, NULL, OPT_PROFILE_LDIF, "set the ldif path", "PATH"},
628                 {"getdefault", 'G', POPT_ARG_NONE, NULL, OPT_PROFILE_GET_DFLT, "get the default profile", NULL},
629                 {"default", 'S', POPT_ARG_NONE, NULL, OPT_PROFILE_SET_DFLT, "set the default profile", NULL},
630                 {"newdb", 'n', POPT_ARG_NONE, NULL, OPT_PROFILE_NEWDB, "create a new profile store", NULL},
631                 {"database", 'f', POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", "PATH"},
632                 {"profile", 'P', POPT_ARG_STRING, NULL, OPT_PROFILE, "set the profile name", "PROFILE"},
633                 {"address", 'I', POPT_ARG_STRING, NULL, OPT_ADDRESS, "set the exchange server IP address", "xxx.xxx.xxx.xxx"},
634                 {"workstation", 'M', POPT_ARG_STRING, NULL, OPT_WORKSTATION, "set the workstation", "WORKSTATION_NAME"},
635                 {"domain", 'D', POPT_ARG_STRING, NULL, OPT_DOMAIN, "set the domain/workgroup", "DOMAIN"},
636                 {"realm", 'R', POPT_ARG_STRING, NULL, OPT_REALM, "set the realm", "REALM"},
637                 {"encrypt", 'E', POPT_ARG_NONE, NULL, OPT_ENCRYPT_CONN, "enable encryption with Exchange server", NULL },
638                 {"exchange-version", 'v', POPT_ARG_STRING, NULL, OPT_EXCHANGE_VERSION, "specify Exchange server version", "2000" },
639                 {"username", 'u', POPT_ARG_STRING, NULL, OPT_USERNAME, "set the profile username", "USERNAME"},
640                 {"language", 'C', POPT_ARG_STRING, NULL, OPT_LANGUAGE, "set the user's language (if different from system one)", "LANGUAGE"},
641                 {"pattern", 's', POPT_ARG_STRING, NULL, OPT_PATTERN, "username to search for", "USERNAME"},
642                 {"password", 'p', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile password", "PASSWORD"},
643                 {"nopass", 0, POPT_ARG_NONE, NULL, OPT_NOPASS, "do not save password in the profile", NULL},
644                 {"create", 'c', POPT_ARG_NONE, NULL, OPT_CREATE_PROFILE, "create a profile in the database", NULL},
645                 {"delete", 'r', POPT_ARG_NONE, NULL, OPT_DELETE_PROFILE, "delete a profile in the database", NULL},
646                 {"rename", 'R', POPT_ARG_STRING, NULL, OPT_RENAME_PROFILE, "rename a profile in the database", NULL},
647                 {"list", 'l', POPT_ARG_NONE, NULL, OPT_LIST_PROFILE, "list existing profiles in the database", NULL},
648                 {"listlangs", 0, POPT_ARG_NONE, NULL, OPT_LIST_LANGS, "list all recognised languages", NULL},
649                 {"dump", 0, POPT_ARG_NONE, NULL, OPT_DUMP_PROFILE, "dump a profile entry", NULL},
650                 {"attr", 'a', POPT_ARG_STRING, NULL, OPT_DUMP_ATTR, "print an attribute value", "VALUE"},
651                 {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "dump the hex data", NULL},
652                 {"debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUGLEVEL, "set the debug level", "LEVEL"},
653                 {"getfqdn", 0, POPT_ARG_NONE, NULL, OPT_GETFQDN, "returns the DNS FQDN of the NSPI server matching the legacyDN", NULL},
654                 POPT_OPENCHANGE_VERSION
655                 { NULL, 0, POPT_ARG_NONE, NULL, 0, NULL, NULL }
656         };
657
658         mem_ctx = talloc_named(NULL, 0, "mapiprofile");
659
660         pc = poptGetContext("mapiprofile", argc, argv, long_options, 0);
661
662         while ((opt = poptGetNextOpt(pc)) != -1) {
663                 switch(opt) {
664                 case OPT_DUMPDATA:
665                         opt_dumpdata = true;
666                         break;
667                 case OPT_DEBUGLEVEL:
668                         opt_debuglevel = poptGetOptArg(pc);
669                         break;
670                 case OPT_PROFILE_LDIF:
671                         opt_tmp = poptGetOptArg(pc);
672                         ldif = talloc_strdup(mem_ctx, opt_tmp);
673                         free((void*)opt_tmp);
674                         opt_tmp = NULL;
675                         break;
676                 case OPT_PROFILE_NEWDB:
677                         newdb = true;
678                         break;
679                 case OPT_PROFILE_SET_DFLT:
680                         setdflt = true;
681                         break;
682                 case OPT_PROFILE_GET_DFLT:
683                         getdflt = true;
684                         break;
685                 case OPT_PROFILE_DB:
686                         opt_tmp = poptGetOptArg(pc);
687                         profdb = talloc_strdup(mem_ctx, opt_tmp); 
688                         free((void*)opt_tmp);
689                         opt_tmp = NULL;
690                         break;
691                 case OPT_PROFILE:
692                         profname = poptGetOptArg(pc);
693                         break;
694                 case OPT_ADDRESS:
695                         address = poptGetOptArg(pc);
696                         break;
697                 case OPT_WORKSTATION:
698                         opt_tmp = poptGetOptArg(pc);
699                         workstation = talloc_strdup(mem_ctx, opt_tmp);
700                         free((void*)opt_tmp);
701                         opt_tmp = NULL;
702                         break;
703                 case OPT_DOMAIN:
704                         domain = poptGetOptArg(pc);
705                         break;
706                 case OPT_REALM:
707                         realm = poptGetOptArg(pc);
708                         break;
709                 case OPT_ENCRYPT_CONN:
710                         opt_seal = true;
711                         break;
712                 case OPT_EXCHANGE_VERSION:
713                         opt_tmp = poptGetOptArg(pc);
714                         version = talloc_strdup(mem_ctx, opt_tmp);
715                         free((void *)opt_tmp);
716                         opt_tmp = NULL;
717                         break;
718                 case OPT_USERNAME:
719                         username = poptGetOptArg(pc);
720                         break;
721                 case OPT_LANGUAGE:
722                         opt_tmp = poptGetOptArg(pc);
723                         language = talloc_strdup(mem_ctx, opt_tmp);
724                         free((void*)opt_tmp);
725                         opt_tmp = NULL;
726                         break;
727                 case OPT_PATTERN:
728                         pattern = poptGetOptArg(pc);
729                         break;
730                 case OPT_PASSWORD:
731                         password = poptGetOptArg(pc);
732                         break;
733                 case OPT_NOPASS:
734                         nopass = 1;
735                         break;
736                 case OPT_CREATE_PROFILE:
737                         create = true;
738                         break;
739                 case OPT_DELETE_PROFILE:
740                         delete = true;
741                         break;
742                 case OPT_RENAME_PROFILE:
743                         rename = poptGetOptArg(pc);
744                         break;
745                 case OPT_LIST_PROFILE:
746                         list = true;
747                         break;
748                 case OPT_LIST_LANGS:
749                         listlangs = true;
750                         break;
751                 case OPT_DUMP_PROFILE:
752                         dump = true;
753                         break;
754                 case OPT_DUMP_ATTR:
755                         attribute = poptGetOptArg(pc);
756                         break;
757                 case OPT_GETFQDN:
758                         getfqdn = true;
759                         break;
760                 }
761         }
762
763         /* Sanity check on options */
764         if (!profdb) {
765                 default_path = talloc_asprintf(mem_ctx, DEFAULT_DIR, getenv("HOME"));
766                 error = mkdir(default_path, 0700);
767                 talloc_free(default_path);
768                 if ((error == -1) && (errno != EEXIST)) {
769                         perror("mkdir");
770                         retcode = EXIT_FAILURE;
771                         goto cleanup;
772                 }
773                 profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, 
774                                          getenv("HOME"));
775         }
776
777         if ((list == false) && (getfqdn == false) && (newdb == false) && (listlangs == false)
778             && (getdflt == false) && (dump == false) && (rename == NULL) && 
779             (!attribute) && (!profname || !profdb)) {
780                 poptPrintUsage(pc, stderr, 0);
781                 retcode = EXIT_FAILURE;
782                 goto cleanup;
783         }
784
785         if (newdb == true) {
786                 if (!ldif) {
787                         ldif = talloc_strdup(mem_ctx, mapi_profile_get_ldif_path());
788                 }
789                 if (!ldif) show_help(pc, "ldif");
790                 if (!mapiprofile_createdb(profdb, ldif)) {
791                         retcode = EXIT_FAILURE;
792                         goto cleanup;
793                 }
794         }
795
796         /* Process the code here */
797
798         if (!workstation) {
799                 gethostname(hostname, sizeof(hostname) - 1);
800                 hostname[sizeof(hostname) - 1] = 0;
801                 workstation = hostname;
802         }
803
804         if (create == true) {
805                 if (!profname) show_help(pc, "profile");
806                 if (!password) show_help(pc, "password");
807                 if (!username) show_help(pc, "username");
808                 if (!address) show_help(pc, "address");
809                 if (!domain) show_help(pc, "domain");
810
811                 if (!version) {
812                         version = talloc_strdup(mem_ctx, DEFAULT_EXCHANGE_VERSION);
813                 }
814
815                 for (i = 0; exchange_version[i].name; i++) {
816                         if (!strcasecmp(version, exchange_version[i].name)) {
817                                 version = talloc_strdup(mem_ctx, exchange_version[i].name);
818                                 found = true;
819                                 break;
820                         }
821                 }
822                 if (found == false) {
823                         printf("Invalid Exchange server version. Possible values are:\n");
824                         for (i = 0; exchange_version[i].name; i++) {
825                                 printf("\t[*] %s\n", exchange_version[i].name);
826                         }
827                         goto cleanup;
828                 }
829
830                 /* Force encrypt parameter if exchange2010 is specified */
831                 if (!strcasecmp(version, "2010")) {
832                         opt_seal = true;
833                 }
834                 talloc_free((void *)version);
835
836                 if (! mapiprofile_create(profdb, profname, pattern, username, password, address,
837                                          language, workstation, domain, realm, nopass, opt_seal, 
838                                          opt_dumpdata, opt_debuglevel,
839                                          exchange_version[i].version)) {
840                         retcode = EXIT_FAILURE;
841                         goto cleanup;
842                 }
843         }
844
845         if (rename) {
846                 mapiprofile_rename(profdb, profname, rename);
847         }
848
849         if (getfqdn == true) {
850                 mapiprofile_get_fqdn(profdb, profname, password, opt_dumpdata);
851         }
852
853         if (listlangs == true) {
854                 mapidump_languages_list();
855         }
856
857         if (setdflt == true) {
858                 mapiprofile_set_default(profdb, profname);
859         }
860
861         if (getdflt == true) {
862                 mapiprofile_get_default(profdb);
863         }
864
865         if (delete == true) {
866                 mapiprofile_delete(profdb, profname);
867         }
868
869         if (list == true) {
870                 mapiprofile_list(profdb);
871         }
872
873         if (dump == true) {
874                 mapiprofile_dump(profdb, profname);
875         }
876
877         if (attribute) {
878                 mapiprofile_attribute(profdb, profname, attribute);
879         }
880
881 cleanup:
882         free((void*)opt_debuglevel);
883         free((void*)profname);
884         free((void*)address);
885         free((void*)domain);
886         free((void*)realm);
887         free((void*)username);
888         free((void*)pattern);
889         free((void*)password);
890         free((void*)rename);
891         free((void*)attribute);
892
893         poptFreeContext(pc);
894         talloc_free(mem_ctx);
895
896         return retcode;
897 }