main.c

  1/*!
  2 * @file main.c
  3 *
  4 * vim: expandtab:ts=2:sts=2:sw=2
  5 *
  6 * @authors
  7 * Copyright (C) 2020 Anoxinon e.V.
  8 *
  9 * @copyright
 10 * This file is part of xmppc.
 11 *
 12 * xmppc is free software: you can redistribute it and/or modify
 13 * it under the terms of the GNU General Public License as published by
 14 * the Free Software Foundation, either version 3 of the License, or
 15 * (at your option) any later version.
 16 *
 17 * xmppc is distributed in the hope that it will be useful,
 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20 * GNU General Public License for more details.
 21 *
 22 * You should have received a copy of the GNU General Public License
 23 * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 24 *
 25 * German
 26 *
 27 * Diese Datei ist Teil von xmppc.
 28 *
 29 * xmppc ist Freie Software: Sie können es unter den Bedingungen
 30 * der GNU General Public License, wie von der Free Software Foundation,
 31 * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
 32 * veröffentlichten Version, weiter verteilen und/oder modifizieren.
 33 *
 34 * xmppc wird in der Hoffnung, dass es nützlich sein wird, aber
 35 * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
 36 * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
 37 * Siehe die GNU General Public License für weitere Details.
 38 *
 39 * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
 40 * Programm erhalten haben. Wenn nicht, siehe <https://www.gnu.org/licenses/>.
 41 */
 42
 43/*!
 44 * @mainpage xmppc - XMPP command line
 45 *
 46 * @section whatIsXmppc What is xmppc
 47 *
 48 * xmppc is a command line program for XMPP (https://xmpp.org/).
 49 * The program has been written for the Debian GNU/Linux system (https://www.debian.org/).
 50 *
 51 * @section build Build
 52 *
 53 * @subsection dependencies Dependencies
 54 *
 55 * - The GNU C Library (glibc) - 2.28-10
 56 * - GLib - 2.58.3
 57 * - XMPP library libstrophe - 0.9.2-2
 58 * - GPGME (GnuPG Made Easy) - 1.12.0-6
 59 *
 60 * @subsection compile Compile
 61 *
 62 * @code{.bash}
 63 * ./bootstrap.sh
 64 * ./configure
 65 * make
 66 * @endcode
 67 *
 68 * @subsection documentation Documentation
 69 * @code{.bash}
 70 * cd doc
 71 * make
 72 * @endcode
 73 * @section usage Usage
 74 *
 75 * @code{.bash}
 76 * xmppc --jid <jabberid> --pwd <secret> --mode <mode> <command> <command args>
 77 * @endcode
 78 *
 79 * @code{.bash}
 80 * xmppc --jid user@domain.tld --pwd "my secret" --mode pgp chat friend@domain.tld "Hello!"
 81 * xmppc --jid user@domain.tld --pwd $(pass XMPP/domain/user) --mode omemo list
 82 * @endcode
 83 *
 84 *
 85 * @section development Development
 86 *
 87 * - \subpage module
 88 *
 89 */
 90
 91/*!
 92 * \page module Modules
 93 *
 94 * \section account Account
 95 * \section roster Roster
 96 * \section message Message
 97 * \section muc Multi-User-Chat
 98 * \section omemo OMEMO
 99 * XEP-0384: OMEMO Encryption (Version 0.3.0 (2018-07-31)). xmppc can use used
100 * to request the users OMEMO Device ID List and displays the Fingerprints of
101 * the keys.
102 *
103 * @code{.bash}
104 * xmppc --jid user@domain.tld --pwd $(pass domain.tld/user) --mode omemo
105 * @endcode
106 *
107 * @code{.bash}
108 * xmppc --jid user@domain.tld --pwd $(pass domain.tld/user) --mode omemo| gpg --clear-sign --sign-with 123ABC_MY_OPENPGP_KEY_1234 > omemo.asc
109 * @endcode
110 *
111 *
112 * \section pgp PGP
113 * XEP-0027: Current Jabber OpenPGP Usage
114 * (https://xmpp.org/extensions/xep-0027.html) is obsolete, but there are still
115 * clients which supports XEP-0027 instead of XEP-0373 / XEP-0374. This module
116 * supports sending of OpenPGP encrypted messages via XMPP's XEP-0027.
117 *
118 * @code{.bash}
119 * xmppc --jid user@domain.tld --pwd "my secret" --mode pgp friend@domain.tld "Hello!"
120 * @endcode
121 *
122 * xmppc use GnuPG's GPGME API use lookup the own key and the key of the
123 * recipient. Those two keys will be used to encrypt the message.
124 *
125 * Details \subpage module-pgp
126 *
127 */
128
129#include "config.h"
130#include <assert.h>
131#include <getopt.h>
132#include <stdarg.h>
133#include <stdio.h>
134#include <stdlib.h>
135#include <string.h>
136#include <strophe.h>
137
138#include "xmppc.h"
139#include "mode/account.h"
140#include "mode/message.h"
141#include "mode/muc.h"
142#include "mode/omemo.h"
143#include "mode/roster.h"
144#include "mode/pgp.h"
145#include "mode/openpgp.h"
146#include "mode/monitor.h"
147
148/*!
149 * @brief The callback structure.
150 *
151 * This struct is used to call the "execution"-function of the mode module (e.g
152 * account_execute_command, roster_execute_command, ...).
153 *
154 * @authors DebxWoody
155 * @since 0.0.2
156 * @version 1
157 *
158 */
159
160typedef struct {
161  /*! Size of arguments */
162  int argc;
163  /*! Array of C-Strings (arguments) with size of argc */
164  char **argv;
165  /*! Pointer to Execute-Handler */
166  ExecuteHandler callback;
167  /*! XMPPC context object */
168  xmppc_t *xmppc;
169} callback_t;
170
171/*!
172 * @brief Mode Mapping.
173 *
174 * This struct is used to provider the mapping of the mode name (name via
175 * command line interface of the user (e.g. -m account). The technical ID of the
176 * mode which is defined via enum xmppc_mode_t and the pointer of function which
177 * should be used to handle those mode.
178 *
179 * @authors DebxWoody
180 * @since 0.0.2
181 * @version 1
182 */
183
184struct mode_mapping {
185  const char *name;
186  xmppc_mode_t mode;
187  ExecuteHandler callback;
188};
189
190/*!
191 * @brief Mode mapping table.
192 *
193 * Mapping of mode's string, enum and function.
194 *
195 * @authors DebxWoody
196 * @since 0.0.2
197 * @version 1
198 *
199 */
200
201static struct mode_mapping map[] = {
202  /*!
203  * Account Mode Mapping
204  * @since 0.0.2
205  * @version 1
206  */
207  {"account", ACCOUNT, account_execute_command},
208  /*!
209  * roster Mode Mapping
210  * @since 0.0.2
211  * @version 1
212  */
213  {"roster", ROSTER, roster_execute_command},
214  /*!
215  * Message Mode Mapping
216  * @since 0.0.2
217  * @version 1
218  */
219  {"message", MESSAGE, message_execute_command},
220  /*!
221  * MUC Mode Mapping
222  * @since 0.0.2
223  * @version 1
224  */
225  {"muc", MUC, muc_execute_command},
226  /*!
227  * OMEMO Mode Mapping
228  * @since 0.0.2
229  * @version 1
230  */
231  {"omemo", OMEMO, omemo_execute_command},
232  /*!
233  * PGP Mode Mapping
234  * @since 0.0.2
235  * @version 1
236  */
237  {"pgp", PGP, pgp_execute_command},
238  /*!
239  * XEP-0373: OpenPGP for XMPP
240  */
241  {"openpgp", OPENPGP, openpgp_execute_command},
242  /*!
243  * Monitor
244  */
245  {"monitor", MONITOR, monitor_execute_command},
246  // End of Map
247  {NULL, 0}
248};
249
250/*!
251 * \brief Connection Handler Callback of libstrophe.
252 *
253 * This function will be called by libstrophe.
254 *
255 * \param conn See libstrophe documentation
256 * \param status See libstrophe documentation
257 * \param error See libstrophe documentation
258 * \param stream_error See libstrophe documentation
259 *
260 * \param userdata callback_t object for the mode request by user.
261 *
262 * @authors DebxWoody
263 * @since 0.0.2
264 * @version 1
265 *
266 */
267
268void conn_handler(xmpp_conn_t *const conn, const xmpp_conn_event_t status,
269                  const int error, xmpp_stream_error_t *const stream_error,
270                  void *const userdata) {
271  callback_t *callback = (callback_t *)userdata;
272
273  if (status == XMPP_CONN_CONNECT) {
274    logInfo(callback->xmppc, "Connected\n");
275    callback->callback(callback->xmppc, callback->argc, callback->argv);
276  } else {
277    xmpp_stop(xmpp_conn_get_context(conn));
278  }
279}
280
281static void _show_help();
282
283/*!
284 * \brief C-Main function
285 *
286 * - Parse argv arguments of the command line.
287 * - Checks jid and password for xmpp logging
288 * - Checks mode requested by user
289 * - All other arguments will be used as mode parameters
290 *
291 * \param argc Arguments counter
292 * \param argv Arguments vector
293 * \returns Exit Code
294 *
295 * @authors DebxWoody
296 * @since 0.0.2
297 * @version 2
298 */
299
300int main(int argc, char *argv[]) {
301#if XMPPC_DEVELOPMENT
302  printf("!!! WARNING: XMPPC is running in development mode !!!\n");
303#endif
304
305  INIT_XMPPC(xmppc);
306
307  static int verbose_flag = 0;
308  int c = 0;
309  xmppc_mode_t mode = UNKOWN;
310  char *jid = NULL;
311  char *pwd = NULL;
312
313  static struct option long_options[] = {
314      /* These options set a flag. */
315      {"verbose", no_argument, &verbose_flag, 1},
316      {"help", no_argument, 0, 'h'},
317      {"config", required_argument, 0, 'c'},
318      {"jid", required_argument, 0, 'j'},
319      {"pwd", required_argument, 0, 'p'},
320      {"mode", required_argument, 0, 'm'},
321      {"file", required_argument, 0, 'f'},
322      {0, 0, 0, 0}};
323  while (c > -1) {
324    int option_index = 0;
325
326    c = getopt_long(argc, argv, "hvj:p:m:", long_options, &option_index);
327    if (c > -1) {
328      switch (c) {
329      case 'h':
330        _show_help();
331        return EXIT_SUCCESS;
332
333      case 'c':
334        printf("option -c with value `%s'\n", optarg);
335        break;
336
337      case 'f':
338        printf("option -f with value `%s'\n", optarg);
339        break;
340
341      case 'j':
342        jid = malloc(strlen(optarg) + 1);
343        strcpy(jid, optarg);
344        break;
345
346      case 'p':
347        pwd = malloc(strlen(optarg) + 1);
348        strcpy(pwd, optarg);
349        break;
350
351      case 'm':
352        for(int i = 0; map[i].name;i++ ) {
353          if (strcmp(optarg, map[i].name) == 0) {
354            mode = map[i].mode;
355            break;
356          }
357        }
358        break;
359
360      case 'v':
361        verbose_flag++;
362        break;
363
364      case '?':
365        break;
366
367      default:
368        abort();
369      }
370    }
371  }
372
373  int paramc = argc- optind;
374  char* paramv[paramc];
375
376  for (int i = optind; i < argc; i++) {
377    char* x= malloc(strlen(argv[i])+1 *sizeof(char)  );
378    strcpy(x,argv[i]);
379    paramv[i-optind] = x;
380  }
381  xmppc_context(&xmppc, verbose_flag);
382
383  logInfo(&xmppc, "Connecting... \n");
384  xmppc_connect(&xmppc, jid, pwd);
385
386  ExecuteHandler handler = NULL;
387        for(int i = 0; map[i].name;i++ ) {
388          if (mode ==  map[i].mode) {
389            handler = map[i].callback;
390            break;
391          }
392        }
393
394  callback_t callback = {paramc, paramv, handler, &xmppc};
395
396  xmpp_connect_client(xmppc.conn, NULL, 0, conn_handler, &callback);
397
398  xmpp_run(xmppc.ctx);
399  xmpp_conn_release(xmppc.conn);
400  xmpp_ctx_free(xmppc.ctx);
401  xmpp_shutdown();
402
403  return EXIT_SUCCESS;
404}
405
406static void _show_help() {
407#ifdef XMPPC_DEVELOPMENT
408  printf("%s - Development\n", PACKAGE_STRING);
409#else
410  printf("%s\n", PACKAGE_STRING);
411#endif
412  printf("Usage: xmppc --jid <jid> --pwd <pwd> --mode <mode> <command> <parameters>\n");
413  printf("Options:\n");
414  printf("  -h / --help             Display this information.\n");
415  printf("  -j / --jid <jid>        Jabber ID\n");
416  printf("  -p / --pwd <password>   Passwort\n");
417  printf("  -m / --mode <mode>      xmppc mode\n");
418  printf("\n");
419  printf("Modes:\n");
420  printf("  -m --mode roster      xmppc roster mode\n");
421  printf("    list                  List all contacts\n");
422  printf("    export                Exports all contacts\n");
423  printf("\n");
424  printf("  -m --mode message     xmppc message mode\n");
425  printf("    chat <jid> <message>  Sending unencrypted message to jid\n");
426  printf("\n");
427  printf("  -m --mode pgp         xmppc pgp mode (XEP-0027) \n");
428  printf("    chat <jid> <message>  Sending pgp encrypted message to jid\n");
429  printf("\n");
430  printf("  -m --mode omemo       xmppc omemo mode\n");
431  printf("    list                  List the device IDs and fingerprints\n");
432  printf("\n");
433  printf("  -m --mode openpgp          xmppc openpgp mode (XEP-0373)\n");
434  printf("    signcrypt <jid> <message>  Sending pgp signed and encrypted message to jid\n");
435  printf("\n");
436  printf("  -m --mode monitor     Monitot mode");
437  printf("    stanza              Stanza Monitor\n");
438  printf("    monitor             microblog Monitor microblog (XEP-0277: Microblogging over XMPP)\n");
439  printf("\n");
440  printf("\n");
441  printf("Examples:\n");
442  printf("  Usage: xmppc --jid user@domain.tld --pwd \"secret\" --mode roster list\n");
443  printf("  Usage: xmppc --jid user@domain.tld --pwd \"secret\" --mode pgp chat friend@domain.tld \"Hello\"\n");
444
445}