Kannel: Open Source WAP and SMS gateway  svn-r5335
smsbox.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * smsbox.c - main program of the smsbox
59  */
60 
61 #include <errno.h>
62 #include <unistd.h>
63 #include <signal.h>
64 #include <string.h>
65 #include <inttypes.h>
66 
67 /* libxml & xpath things */
68 #include <libxml/tree.h>
69 #include <libxml/parser.h>
70 #include <libxml/xpath.h>
71 #include <libxml/xpathInternals.h>
72 
73 #include "gwlib/gwlib.h"
74 #include "gwlib/gw-regex.h"
75 #include "gwlib/gw-timer.h"
76 
77 #include "msg.h"
78 #include "sms.h"
79 #include "dlr.h"
80 #include "bb.h"
81 #include "shared.h"
82 #include "heartbeat.h"
83 #include "html.h"
84 #include "urltrans.h"
85 #include "ota_prov_attr.h"
86 #include "ota_prov.h"
87 #include "ota_compiler.h"
88 #include "xml_shared.h"
89 
90 #ifdef HAVE_SECURITY_PAM_APPL_H
91 #include <security/pam_appl.h>
92 #endif
93 
94 
95 #define SENDSMS_DEFAULT_CHARS "0123456789 +-"
96 
97 #define O_DESTROY(a) { if(a) octstr_destroy(a); a = NULL; }
98 
99 #define ACCOUNT_MAX_LEN 64
100 
101 /* Defaults for the HTTP request queueing inside http_queue_thread */
102 #define HTTP_MAX_RETRIES 0
103 #define HTTP_RETRY_DELAY 10 /* in sec. */
104 #define HTTP_MAX_PENDING 512 /* max requests handled in parallel */
105 
106 /* Timer item structure for HTTP retrying */
107 typedef struct TimerItem {
109  void *id;
110 } TimerItem;
111 
112 /* have we received restart cmd from bearerbox? */
113 volatile sig_atomic_t restart = 0;
114 
115 static Cfg *cfg;
116 static long bb_port;
117 static int bb_ssl = 0;
118 static long sendsms_port = 0;
119 static Octstr *sendsms_interface = NULL;
120 static Octstr *smsbox_id = NULL;
121 static Octstr *sendsms_url = NULL;
122 static Octstr *sendota_url = NULL;
123 static Octstr *xmlrpc_url = NULL;
124 static Octstr *bb_host;
125 static Octstr *accepted_chars = NULL;
126 static int only_try_http = 0;
129 static char *sendsms_number_chars;
130 static Octstr *global_sender = NULL;
134 static Octstr *reply_emptymessage = NULL;
135 static int mo_recode = 0;
138 static regex_t *white_list_regex = NULL;
139 static regex_t *black_list_regex = NULL;
142 static Octstr *ppg_service_name = NULL;
143 
144 static List *smsbox_requests = NULL; /* the inbound request queue */
145 static List *smsbox_http_requests = NULL; /* the outbound HTTP request queue */
146 
147 /* Timerset for the HTTP retry mechanism. */
148 static Timerset *timerset = NULL;
149 
150 /* Maximum requests that we handle in parallel */
152 
153 /* for delayed HTTP answers.
154  * Dict key is uuid, value is HTTPClient pointer
155  * of open transaction
156  */
157 
158 static int immediate_sendsms_reply = 0;
159 static Dict *client_dict = NULL;
160 static List *sendsms_reply_hdrs = NULL;
161 
162 /***********************************************************************
163  * Communication with the bearerbox.
164  */
165 
166 
167 /*
168  * Identify ourself to bearerbox for smsbox-specific routing inside bearerbox.
169  * Do this even while no smsbox-id is given to unlock the sender thread in
170  * bearerbox.
171  */
172 static void identify_to_bearerbox(void)
173 {
174  Msg *msg;
175 
176  msg = msg_create(admin);
177  msg->admin.command = cmd_identify;
178  msg->admin.boxc_id = octstr_duplicate(smsbox_id);
180 }
181 
182 /*
183  * Handle delayed reply to HTTP sendsms client, if any
184  */
186 {
188  Octstr *os, *answer;
189  char id[UUID_STR_LEN + 1];
190  int status;
191 
192  uuid_unparse(msg->ack.id, id);
193  os = octstr_create(id);
194  debug("sms.http", 0, "Got ACK (%ld) of %s", msg->ack.nack, octstr_get_cstr(os));
196  if (client == NULL) {
197  debug("sms.http", 0, "No client - multi-send or ACK to pull-reply");
198  octstr_destroy(os);
199  return;
200  }
201  /* XXX this should be fixed so that we really wait for DLR
202  * SMSC accept/deny before doing this - but that is far
203  * more slower, a bit more complex, and is done later on
204  */
205 
206  switch (msg->ack.nack) {
207  case ack_success:
209  answer = octstr_create("0: Accepted for delivery");
210  break;
211  case ack_buffered:
213  answer = octstr_create("3: Queued for later delivery");
214  break;
215  case ack_failed:
217  answer = octstr_create("Not routable. Do not try again.");
218  break;
219  case ack_failed_tmp:
221  answer = octstr_create("Temporal failure, try again later.");
222  break;
223  default:
224  error(0, "Strange reply from bearerbox!");
226  answer = octstr_create("Temporal failure, try again later.");
227  break;
228  }
229 
231 
232  octstr_destroy(answer);
233  octstr_destroy(os);
234 }
235 
236 
237 /*
238  * Read an Msg from the bearerbox and send it to the proper receiver
239  * via a List. At the moment all messages are sent to the smsbox_requests
240  * List.
241  */
243 {
244  time_t start, t;
245  int secs;
246  int total = 0;
247  int ret;
248  Msg *msg;
249 
250  start = t = time(NULL);
251  while (program_status != shutting_down) {
252  /* block infinite for reading messages */
254  if (ret == -1) {
255  if (program_status != shutting_down) {
256  error(0, "Bearerbox is gone, restarting");
258  restart = 1;
259  }
260  break;
261  } else if (ret == 1) /* timeout */
262  continue;
263  else if (msg == NULL) /* just to be sure, may not happens */
264  break;
265 
266  if (msg_type(msg) == admin) {
267  if (msg->admin.command == cmd_shutdown) {
268  info(0, "Bearerbox told us to die");
270  } else if (msg->admin.command == cmd_restart) {
271  info(0, "Bearerbox told us to restart");
272  restart = 1;
274  }
275  /*
276  * XXXX here should be suspend/resume, add RSN
277  */
278  msg_destroy(msg);
279  } else if (msg_type(msg) == sms) {
280  if (total == 0)
281  start = time(NULL);
282  total++;
284  } else if (msg_type(msg) == ack) {
287  msg_destroy(msg);
288  } else {
289  warning(0, "Received other message than sms/admin, ignoring!");
290  msg_destroy(msg);
291  }
292  }
293  secs = difftime(time(NULL), start);
294  info(0, "Received (and handled?) %d requests in %d seconds "
295  "(%.2f per second)", total, secs, (float)total / secs);
296 }
297 
298 
299 /***********************************************************************
300  * Send Msg to bearerbox for delivery to phone, possibly split it first.
301  */
302 
303 /*
304  * Counter for catenated SMS messages. The counter that can be put into
305  * the catenated SMS message's UDH headers is actually the lowest 8 bits.
306  */
308 
309 /*
310  * Send a message to the bearerbox for delivery to a phone. Use
311  * configuration from `trans' to format the message before sending.
312  * Return >= 0 for success & count of splitted sms messages,
313  * -1 for failure. Does not destroy the msg.
314  */
315 static int send_message(URLTranslation *trans, Msg *msg)
316 {
317  int max_msgs;
318  Octstr *header, *footer, *suffix, *split_chars, *dlr_url;
319  int catenate;
320  unsigned long msg_sequence, msg_count;
321  List *list;
322  Msg *part;
323 
324  gw_assert(msg != NULL);
325  gw_assert(msg_type(msg) == sms);
326 
327  if (trans != NULL)
328  max_msgs = urltrans_max_messages(trans);
329  else
330  max_msgs = 1;
331 
332  if (max_msgs == 0) {
333  info(0, "No reply sent, denied.");
334  return 0;
335  }
336 
337  /*
338  * Encode our smsbox-id to the msg structure.
339  * This will allow bearerbox to return specific answers to the
340  * same smsbox, mainly for DLRs and SMS proxy modes.
341  */
342  if (smsbox_id != NULL) {
343  msg->sms.boxc_id = octstr_duplicate(smsbox_id);
344  }
345 
346  /*
347  * Empty message? Two alternatives have to be handled:
348  * a) it's a HTTP sms-service reply: either ignore it or
349  * substitute the "empty" warning defined
350  * b) it's a sendsms HTTP interface call: leave the message empty
351  */
352  if (octstr_len(msg->sms.msgdata) == 0 && msg->sms.sms_type == mt_reply) {
353  if (trans != NULL && urltrans_omit_empty(trans))
354  return 0;
355  else
356  msg->sms.msgdata = octstr_duplicate(reply_emptymessage);
357  }
358 
359  if (trans == NULL) {
360  header = NULL;
361  footer = NULL;
362  suffix = NULL;
363  split_chars = NULL;
364  catenate = 0;
365  } else {
366  header = urltrans_header(trans);
367  footer = urltrans_footer(trans);
368  suffix = urltrans_split_suffix(trans);
369  split_chars = urltrans_split_chars(trans);
370  catenate = urltrans_concatenation(trans);
371  dlr_url = urltrans_dlr_url(trans);
372 
373  /*
374  * If there hasn't been yet any DLR-URL set in the message
375  * and we have configured values from the URLTranslation,
376  * hence the 'group = sms-service' context group, then use
377  * them in the message.
378  */
379  if (octstr_len(msg->sms.dlr_url) == 0 && dlr_url != NULL) {
380  octstr_destroy(msg->sms.dlr_url);
381  msg->sms.dlr_url = octstr_duplicate(dlr_url);
382  if (!DLR_IS_ENABLED(msg->sms.dlr_mask))
383  msg->sms.dlr_mask = urltrans_dlr_mask(trans);
384  }
385  }
386 
387  if (catenate)
388  msg_sequence = counter_increase(catenated_sms_counter) & 0xFF;
389  else
390  msg_sequence = 0;
391 
392  /*
393  * Avoid sms_split() if no part manipulations will be performed, in order to
394  * avoid the XXX TODO issue in extract_msgdata_part_by_coding().
395  */
396  if (header == NULL && footer == NULL && suffix == NULL && split_chars == NULL) {
397  list = gwlist_create();
399  } else {
400  list = sms_split(msg, header, footer, suffix, split_chars, catenate,
401  msg_sequence, max_msgs, sms_max_length);
402  }
403  msg_count = gwlist_len(list);
404 
405  debug("sms", 0, "message length %ld, sending %ld messages",
406  octstr_len(msg->sms.msgdata), msg_count);
407 
408  /*
409  * In order to get catenated msgs work properly, we
410  * have moved catenation to bearerbox.
411  * So here we just need to put splitted msgs into one again and send
412  * to bearerbox that will care about catenation.
413  */
414  if (catenate) {
415  Msg *new_msg = msg_duplicate(msg);
416  octstr_delete(new_msg->sms.msgdata, 0, octstr_len(new_msg->sms.msgdata));
417  while((part = gwlist_extract_first(list)) != NULL) {
418  octstr_append(new_msg->sms.msgdata, part->sms.msgdata);
419  msg_destroy(part);
420  }
421  write_to_bearerbox(new_msg);
422  } else {
423  /* msgs are the independent parts so sent those as is */
424  while ((part = gwlist_extract_first(list)) != NULL)
425  write_to_bearerbox(part);
426  }
427 
428  gwlist_destroy(list, NULL);
429 
430  return msg_count;
431 }
432 
433 
434 /***********************************************************************
435  * Stuff to remember which receiver belongs to which HTTP query.
436  * This also includes HTTP request data to queue a failed HTTP request
437  * into the smsbox_http_request queue which is then handled by the
438  * http_queue_thread thread on a re-scheduled time basis.
439  */
440 
441 
444 
445 
446 struct receiver {
449  int method; /* the HTTP method to use */
450  Octstr *url; /* the after pattern URL */
452  Octstr *body; /* body content of the request */
453  unsigned long retries; /* number of performed retries */
454 };
455 
456 /*
457  * Again no urltranslation when we got an answer to wap push - it can only be dlr.
458  */
459 static void *remember_receiver(Msg *msg, URLTranslation *trans, int method,
460  Octstr *url, List *headers, Octstr *body,
461  unsigned int retries)
462 {
463  struct receiver *receiver;
464 
466  receiver = gw_malloc(sizeof(*receiver));
467 
468  receiver->msg = msg_create(sms);
469 
470  receiver->msg->sms.sender = octstr_duplicate(msg->sms.sender);
471  receiver->msg->sms.receiver = octstr_duplicate(msg->sms.receiver);
472  /* ppg_service_name should always be not NULL here */
473  if (trans != NULL && (msg->sms.service == NULL || ppg_service_name == NULL ||
474  octstr_compare(msg->sms.service, ppg_service_name) != 0)) {
475  receiver->msg->sms.service = octstr_duplicate(urltrans_name(trans));
476  } else {
477  receiver->msg->sms.service = octstr_duplicate(msg->sms.service);
478  }
479  receiver->msg->sms.smsc_id = octstr_duplicate(msg->sms.smsc_id);
480  /* to remember if it's a DLR http get */
481  receiver->msg->sms.sms_type = msg->sms.sms_type;
482 
483  receiver->trans = trans;
484 
485  /* remember the HTTP request if we need to queue this */
491 
492  return receiver;
493 }
494 
495 
496 static void get_receiver(void *id, Msg **msg, URLTranslation **trans, int *method,
497  Octstr **url, List **headers, Octstr **body,
498  unsigned long *retries)
499 {
500  struct receiver *receiver;
501 
502  receiver = id;
503  *msg = receiver->msg;
504  *trans = receiver->trans;
505  *method = receiver->method;
506  *url = receiver->url;
507  *headers = receiver->http_headers;
508  *body = receiver->body;
510  gw_free(receiver);
512 }
513 
514 
515 static long outstanding_requests(void)
516 {
518 }
519 
520 
521 /***********************************************************************
522  * Thread for receiving reply from HTTP query and sending it to phone.
523  */
524 
525 
526 static void strip_prefix_and_suffix(Octstr *html, Octstr *prefix,
527  Octstr *suffix)
528 {
529  long prefix_end, suffix_start;
530 
531  if (prefix == NULL || suffix == NULL)
532  return;
533  prefix_end = octstr_case_search(html, prefix, 0);
534  if (prefix_end == -1)
535  return;
536  prefix_end += octstr_len(prefix);
537  suffix_start = octstr_case_search(html, suffix, prefix_end);
538  if (suffix_start == -1)
539  return;
540  octstr_delete(html, 0, prefix_end);
541  octstr_truncate(html, suffix_start - prefix_end);
542 }
543 
544 
545 static void get_x_kannel_from_headers(List *headers, Octstr **from,
546  Octstr **to, Octstr **udh,
547  Octstr **user, Octstr **pass,
548  Octstr **smsc, int *mclass, int *mwi,
549  int *coding, int *compress,
550  int *validity, int *deferred,
551  int *dlr_mask, Octstr **dlr_url,
552  Octstr **account, int *pid, int *alt_dcs,
553  int *rpi, Octstr **binfo, int *priority, Octstr **meta_data)
554 {
555  Octstr *name, *val;
556  long l;
557 
558  for(l=0; l<gwlist_len(headers); l++) {
559  http_header_get(headers, l, &name, &val);
560 
561  if (octstr_case_compare(name, octstr_imm("X-Kannel-From")) == 0) {
562  *from = octstr_duplicate(val);
564  }
565  else if (octstr_case_compare(name, octstr_imm("X-Kannel-To")) == 0) {
566  *to = octstr_duplicate(val);
567  octstr_strip_blanks(*to);
568  }
569  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Username")) == 0) {
570  if (user != NULL) {
571  *user = octstr_duplicate(val);
572  octstr_strip_blanks(*user);
573  }
574  }
575  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Password")) == 0) {
576  if (pass != NULL) {
577  *pass = octstr_duplicate(val);
578  octstr_strip_blanks(*pass);
579  }
580  }
581  else if (octstr_case_compare(name, octstr_imm("X-Kannel-SMSC")) == 0) {
582  if (smsc != NULL) {
583  *smsc = octstr_duplicate(val);
584  octstr_strip_blanks(*smsc);
585  }
586  }
587  else if (octstr_case_compare(name, octstr_imm("X-Kannel-UDH")) == 0) {
588  *udh = octstr_duplicate(val);
589  octstr_strip_blanks(*udh);
590  if (octstr_hex_to_binary(*udh) == -1) {
591  if (octstr_url_decode(*udh) == -1) {
592  warning(0, "Invalid UDH received in X-Kannel-UDH");
593  octstr_destroy(*udh);
594  *udh = NULL;
595  }
596  }
597  }
598  else if (octstr_case_compare(name, octstr_imm("X-Kannel-DLR-URL")) == 0) {
599  *dlr_url = octstr_duplicate(val);
601  }
602  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Account")) == 0) {
603  *account = octstr_duplicate(val);
605  }
606  else if (octstr_case_compare(name, octstr_imm("X-Kannel-BInfo")) == 0) {
607  *binfo = octstr_duplicate(val);
608  octstr_strip_blanks(*binfo);
609  }
610  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Coding")) == 0) {
611  sscanf(octstr_get_cstr(val),"%d", coding);
612  }
613  else if (octstr_case_compare(name, octstr_imm("X-Kannel-PID")) == 0) {
614  sscanf(octstr_get_cstr(val),"%d", pid);
615  }
616  else if (octstr_case_compare(name, octstr_imm("X-Kannel-MWI")) == 0) {
617  sscanf(octstr_get_cstr(val),"%d", mwi);
618  }
619  else if (octstr_case_compare(name, octstr_imm("X-Kannel-MClass")) == 0) {
620  sscanf(octstr_get_cstr(val),"%d", mclass);
621  }
622  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Alt-DCS")) == 0) {
623  sscanf(octstr_get_cstr(val),"%d", alt_dcs);
624  }
625  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Compress")) == 0) {
626  sscanf(octstr_get_cstr(val),"%d", compress);
627  }
628  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Validity")) == 0) {
629  sscanf(octstr_get_cstr(val),"%d", validity);
630  }
631  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Deferred")) == 0) {
632  sscanf(octstr_get_cstr(val),"%d", deferred);
633  }
634  else if (octstr_case_compare(name, octstr_imm("X-Kannel-DLR-Mask")) == 0) {
635  sscanf(octstr_get_cstr(val),"%d", dlr_mask);
636  }
637  else if (octstr_case_compare(name, octstr_imm("X-Kannel-RPI")) == 0) {
638  sscanf(octstr_get_cstr(val),"%d", rpi);
639  }
640  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Priority")) == 0) {
641  sscanf(octstr_get_cstr(val),"%d", priority);
642  }
643  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Meta-Data")) == 0) {
644  *meta_data = octstr_duplicate(val);
646  }
648  octstr_destroy(val);
649  }
650 }
651 
652 /* requesttype = mt_reply or mt_push. for example, auth is only read on mt_push
653  * parse body and populate fields, including replacing body for <ud> value and
654  * type to text/plain */
655 static void get_x_kannel_from_xml(int requesttype , Octstr **type, Octstr **body,
656  List *headers, Octstr **from,
657  Octstr **to, Octstr **udh,
658  Octstr **user, Octstr **pass,
659  Octstr **smsc, int *mclass, int *mwi,
660  int *coding, int *compress,
661  int *validity, int *deferred,
662  int *dlr_mask, Octstr **dlr_url,
663  Octstr **account, int *pid, int *alt_dcs,
664  int *rpi, List **tolist, Octstr **charset,
665  Octstr **binfo, int *priority, Octstr **meta_data)
666 {
667  xmlDocPtr doc = NULL;
668  xmlXPathContextPtr xpathCtx = NULL;
669  xmlXPathObjectPtr xpathObj = NULL;
670  xmlChar *xml_string;
671  Octstr *text = NULL, *tmp = NULL;
672 
673  if (*body == NULL)
674  return;
675 
676  debug("sms", 0, "XMLParsing: XML: <%s>", octstr_get_cstr(*body));
677 
678  /* ok, start parsing */
679  doc = xmlParseMemory(octstr_get_cstr(*body), octstr_len(*body));
680  if (doc == NULL) {
681  error(0, "XMLParsing: Could not parse xmldoc: <%s>", octstr_get_cstr(*body));
682  return;
683  }
684  xpathCtx = xmlXPathNewContext(doc);
685  if (xpathCtx == NULL) {
686  error(0, "XMLParsing: Could not create xpath context.");
687  xmlFreeDoc(doc);
688  return;
689  }
690 
691 #define XPATH_SEARCH_OCTSTR(path, var, nostrip) \
692  do { \
693  xpathObj = xmlXPathEvalExpression(BAD_CAST path, xpathCtx); \
694  if (xpathObj != NULL && !xmlXPathNodeSetIsEmpty(xpathObj->nodesetval)) { \
695  xml_string = xmlXPathCastToString(xpathObj); \
696  O_DESTROY(var); \
697  var = octstr_create((const char*) xml_string); \
698  if(nostrip == 0) \
699  octstr_strip_blanks(var); \
700  xmlFree(xml_string); \
701  } \
702  if (xpathObj != NULL) xmlXPathFreeObject(xpathObj); \
703  } while(0)
704 
705 #define XPATH_SEARCH_NUMBER(path, var) \
706  do { \
707  xpathObj = xmlXPathEvalExpression(BAD_CAST path, xpathCtx); \
708  if (xpathObj != NULL && !xmlXPathNodeSetIsEmpty(xpathObj->nodesetval)) { \
709  var = xmlXPathCastToNumber(xpathObj); \
710  } \
711  if (xpathObj != NULL) xmlXPathFreeObject(xpathObj); \
712  } while(0)
713 
714  /* auth */
715  xpathObj = xmlXPathEvalExpression(BAD_CAST "/message/submit/from", xpathCtx);
716  if (xpathObj != NULL && !xmlXPathNodeSetIsEmpty(xpathObj->nodesetval)) {
717  xmlXPathFreeObject(xpathObj);
718  if(requesttype == mt_push) {
719  /* user */
720  XPATH_SEARCH_OCTSTR("/message/submit/from/user", *user, 0);
721  XPATH_SEARCH_OCTSTR("/message/submit/from/username", *user, 0);
722 
723  /* pass */
724  XPATH_SEARCH_OCTSTR("/message/submit/from/pass", *pass, 0);
725  XPATH_SEARCH_OCTSTR("/message/submit/from/password", *pass, 0);
726  }
727 
728  /* account */
729  XPATH_SEARCH_OCTSTR("/message/submit/from/account", *account, 0);
730 
731  /* binfo */
732  XPATH_SEARCH_OCTSTR("/message/submit/from/binfo", *binfo, 0);
733  }
734 
735  XPATH_SEARCH_OCTSTR("/message/submit/oa/number", *from, 0);
736 
737  /* to (da/number) Multiple tags */
738  xpathObj = xmlXPathEvalExpression(BAD_CAST "/message/submit/da/number/text()", xpathCtx);
739  if (xpathObj != NULL && !xmlXPathNodeSetIsEmpty(xpathObj->nodesetval)) {
740  int i;
741 
742  *tolist = gwlist_create();
743  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
744  if (xpathObj->nodesetval->nodeTab[i]->type != XML_TEXT_NODE)
745  continue;
746  xml_string = xmlXPathCastNodeToString(xpathObj->nodesetval->nodeTab[i]);
747  tmp = octstr_create((const char*) xpathObj->nodesetval->nodeTab[i]->content);
748  xmlFree(xml_string);
749  octstr_strip_blanks(tmp);
750  gwlist_append(*tolist, tmp);
751  }
752  }
753  if (xpathObj != NULL)
754  xmlXPathFreeObject(xpathObj);
755 
756  /* udh */
757  XPATH_SEARCH_OCTSTR("/message/submit/udh", *udh, 0);
758  if(*udh != NULL && octstr_hex_to_binary(*udh) == -1)
759  octstr_url_decode(*udh);
760 
761  /* smsc */
762  XPATH_SEARCH_OCTSTR("/message/submit/smsc", *smsc, 0);
763  if (*smsc == NULL)
764  XPATH_SEARCH_OCTSTR("/message/submit/to", *smsc, 0);
765 
766  /* pid */
767  XPATH_SEARCH_NUMBER("/message/submit/pid", *pid);
768 
769  /* rpi */
770  XPATH_SEARCH_NUMBER("/message/submit/rpi", *rpi);
771 
772  /* dcs* (dcs/ *) */
773  /* mclass (dcs/mclass) */
774  XPATH_SEARCH_NUMBER("/message/submit/dcs/mclass", *mclass);
775  /* mwi (dcs/mwi) */
776  XPATH_SEARCH_NUMBER("/message/submit/dcs/mwi", *mwi);
777  /* coding (dcs/coding) */
778  XPATH_SEARCH_NUMBER("/message/submit/dcs/coding", *coding);
779  /* compress (dcs/compress) */
780  XPATH_SEARCH_NUMBER("/message/submit/dcs/compress", *compress);
781  /* alt-dcs (dcs/alt-dcs) */
782  XPATH_SEARCH_NUMBER("/message/submit/dcs/alt-dcs", *alt_dcs);
783 
784 
785  /* statusrequest* (statusrequest/ *) */
786  /* dlr-mask (statusrequest/dlr-mask) */
787  XPATH_SEARCH_NUMBER("/message/submit/statusrequest/dlr-mask", *dlr_mask);
788  /* dlr-url */
789  XPATH_SEARCH_OCTSTR("/message/submit/statusrequest/dlr-url", *dlr_url, 0);
790 
791  /* validity (vp/delay) */
792  XPATH_SEARCH_NUMBER("/message/submit/vp/delay", *validity);
793 
794  /* deferred (timing/delay) */
795  XPATH_SEARCH_NUMBER("/message/submit/timing/delay", *deferred);
796 
797  /* priority */
798  XPATH_SEARCH_NUMBER("/message/submit/priority", *priority);
799 
800  /* meta_data */
801  XPATH_SEARCH_OCTSTR("/message/submit/meta-data", *meta_data, 0);
802 
803  /* charset from <?xml...encoding=?> */
804  O_DESTROY(*charset);
805  if (doc->encoding != NULL)
806  *charset = octstr_create((const char*) doc->encoding);
807  else
808  *charset = octstr_create("UTF-8");
809 
810  /* text */
811  /* first try to receive type, default text */
812  tmp = NULL;
813  XPATH_SEARCH_OCTSTR("/message/submit/ud/@type", tmp, 0);
814  /* now receive message body */
815  XPATH_SEARCH_OCTSTR("/message/submit/ud", text, 0);
816  if (text != NULL) {
817  if (tmp != NULL && octstr_str_case_compare(tmp, "binary") == 0)
819  else
821  }
822  octstr_destroy(tmp);
823 
824  octstr_truncate(*body, 0);
825  if(text != NULL) {
828  }
829 
830  O_DESTROY(*type);
831  *type = octstr_create("text/plain");
832 
833  if (xpathCtx != NULL)
834  xmlXPathFreeContext(xpathCtx);
835  if (doc != NULL)
836  xmlFreeDoc(doc);
837 }
838 
839 
841  Octstr *replytext, Octstr *from, Octstr *to, Octstr *udh,
842  int mclass, int mwi, int coding, int compress,
843  int validity, int deferred,
844  Octstr *dlr_url, int dlr_mask, int pid, int alt_dcs,
845  int rpi, Octstr *smsc, Octstr *account,
846  Octstr *charset, Octstr *binfo, int priority, Octstr *meta_data)
847 {
848  msg->sms.msgdata = replytext;
849  msg->sms.time = time(NULL);
850 
851  if (charset)
852  msg->sms.charset = charset;
853 
854  if (dlr_url != NULL) {
856  octstr_destroy(msg->sms.dlr_url);
857  msg->sms.dlr_url = dlr_url;
858  } else {
859  warning(0, "Tried to change dlr_url to '%s', denied.",
862  }
863  }
864 
865  if (smsc != NULL) {
867  octstr_destroy(msg->sms.smsc_id);
868  msg->sms.smsc_id = smsc;
869  } else {
870  warning(0, "Tried to change SMSC to '%s', denied.",
871  octstr_get_cstr(smsc));
872  octstr_destroy(smsc);
873  }
874  }
875 
876  if (from != NULL) {
878  octstr_destroy(msg->sms.sender);
879  msg->sms.sender = from;
880  } else {
881  warning(0, "Tried to change sender to '%s', denied.",
884  }
885  }
886  if (to != NULL) {
888  octstr_destroy(msg->sms.receiver);
889  msg->sms.receiver = to;
890  } else {
891  warning(0, "Tried to change receiver to '%s', denied.",
892  octstr_get_cstr(to));
893  octstr_destroy(to);
894  }
895  }
896  if (udh != NULL) {
898  octstr_destroy(msg->sms.udhdata);
899  msg->sms.udhdata = udh;
900  } else {
901  warning(0, "Tried to set UDH field, denied.");
902  O_DESTROY(udh);
903  }
904  }
905  if (mclass != SMS_PARAM_UNDEFINED) {
907  msg->sms.mclass = mclass;
908  else
909  warning(0, "Tried to set MClass field, denied.");
910  }
911  if (pid != SMS_PARAM_UNDEFINED) {
913  msg->sms.pid = pid;
914  else
915  warning(0, "Tried to set PID field, denied.");
916  }
917  if (rpi != SMS_PARAM_UNDEFINED) {
919  msg->sms.rpi = rpi;
920  else
921  warning(0, "Tried to set RPI field, denied.");
922  }
923  if (alt_dcs != SMS_PARAM_UNDEFINED) {
925  msg->sms.alt_dcs = alt_dcs;
926  else
927  warning(0, "Tried to set Alt-DCS field, denied.");
928  }
929  if (mwi != SMS_PARAM_UNDEFINED) {
931  msg->sms.mwi = mwi;
932  else
933  warning(0, "Tried to set MWI field, denied.");
934  }
935  if (coding != SMS_PARAM_UNDEFINED) {
937  msg->sms.coding = coding;
938  else
939  warning(0, "Tried to set Coding field, denied.");
940  }
941  if (compress != SMS_PARAM_UNDEFINED) {
943  msg->sms.compress = compress;
944  else
945  warning(0, "Tried to set Compress field, denied.");
946  }
947  /* Compatibility Mode */
948  if (msg->sms.coding == DC_UNDEF) {
949  if(octstr_len(udh))
950  msg->sms.coding = DC_8BIT;
951  else
952  msg->sms.coding = DC_7BIT;
953  }
954  if (validity != SMS_PARAM_UNDEFINED) {
956  msg->sms.validity = validity * 60 + time(NULL);
957  else
958  warning(0, "Tried to change validity to '%d', denied.", validity);
959  }
960  if (deferred != SMS_PARAM_UNDEFINED) {
962  msg->sms.deferred = deferred * 60 + time(NULL);
963  else
964  warning(0, "Tried to change deferred to '%d', denied.", deferred);
965  }
966  if (dlr_mask != SMS_PARAM_UNDEFINED) {
968  msg->sms.dlr_mask = dlr_mask;
969  } else
970  warning(0, "Tried to change dlr_mask to '%d', denied.", dlr_mask);
971  }
972  if (account) {
974  msg->sms.account = account;
975  } else {
976  warning(0, "Tried to change account to '%s', denied.",
979  }
980  }
981  if (binfo) {
983  msg->sms.binfo = binfo;
984  } else {
985  warning(0, "Tried to change billing info to '%s', denied.",
986  octstr_get_cstr(binfo));
987  octstr_destroy(binfo);
988  }
989  }
990  if (priority != SMS_PARAM_UNDEFINED) {
992  msg->sms.priority = priority;
993  else
994  warning(0, "Tried to change priority to '%d', denied.", priority);
995  }
996  if (meta_data != NULL) {
998  octstr_destroy(msg->sms.meta_data);
999  msg->sms.meta_data = meta_data;
1000  } else {
1001  warning(0, "Tried to set Meta-Data field, denied.");
1003  }
1004  }
1005 }
1006 
1007 
1008 /***********************************************************************
1009  * Thread to handle failed HTTP requests and retries to deliver the
1010  * information to the HTTP server. The thread uses the smsbox_http_requests
1011  * queue that is spooled by url_result_thread in case the HTTP requests
1012  * fails.
1013  */
1014 
1015 static void http_queue_thread(void *arg)
1016 {
1017  void *id;
1018  Msg *msg;
1020  Octstr *req_url;
1021  List *req_headers;
1022  Octstr *req_body;
1023  unsigned long retries;
1024  int method;
1025  TimerItem *i;
1026 
1027  while ((i = gwlist_consume(smsbox_http_requests)) != NULL) {
1028  /*
1029  * The timer thread has injected the item to retry the
1030  * HTTP call again now.
1031  */
1032 
1033  debug("sms.http",0,"HTTP: Queue contains %ld outstanding requests",
1035 
1036  /*
1037  * Get all required HTTP request data from the queue and reconstruct
1038  * the id pointer for later lookup in url_result_thread.
1039  */
1040  get_receiver(i->id, &msg, &trans, &method, &req_url, &req_headers, &req_body, &retries);
1041 
1043  gw_free(i);
1044 
1045  if (retries < max_http_retries) {
1046  id = remember_receiver(msg, trans, method, req_url, req_headers, req_body, ++retries);
1047 
1048  debug("sms.http",0,"HTTP: Retrying request <%s> (%ld/%ld)",
1050 
1051  /* re-queue this request to the HTTPCaller list */
1052  http_start_request(caller, method, req_url, req_headers, req_body,
1053  1, id, NULL);
1054  }
1055 
1056  msg_destroy(msg);
1057  octstr_destroy(req_url);
1058  http_destroy_headers(req_headers);
1059  octstr_destroy(req_body);
1060  }
1061 }
1062 
1063 
1064 static void url_result_thread(void *arg)
1065 {
1066  Octstr *final_url, *req_body, *type, *replytext;
1067  List *reply_headers;
1068  int status, method;
1069  void *id;
1070  Msg *msg;
1072  Octstr *req_url;
1073  List *req_headers;
1074  Octstr *text_html, *text_plain, *text_wml, *text_xml;
1075  Octstr *octet_stream;
1076  unsigned long retries;
1077  unsigned int queued; /* indicate if processes reply is re-queued */
1078  TimerItem *item;
1079 
1080  Octstr *reply_body, *charset, *alt_charset;
1081  Octstr *udh, *from, *to, *dlr_url, *account, *smsc, *binfo, *meta_data;
1082  int dlr_mask, mclass, mwi, coding, compress, pid, alt_dcs, rpi;
1083  int validity, deferred, priority;
1084 
1085  text_html = octstr_imm("text/html");
1086  text_wml = octstr_imm("text/vnd.wap.wml");
1087  text_plain = octstr_imm("text/plain");
1088  text_xml = octstr_imm("text/xml");
1089  octet_stream = octstr_imm("application/octet-stream");
1090 
1091  for (;;) {
1092  queued = 0;
1093  id = http_receive_result(caller, &status, &final_url, &reply_headers, &reply_body);
1095  if (id == NULL)
1096  break;
1097 
1098  from = to = udh = smsc = dlr_url = account = binfo = charset
1099  = alt_charset = meta_data = NULL;
1100  mclass = mwi = compress = pid = alt_dcs = rpi = dlr_mask =
1101  validity = deferred = priority = SMS_PARAM_UNDEFINED;
1102  coding = DC_7BIT;
1103 
1104  get_receiver(id, &msg, &trans, &method, &req_url, &req_headers, &req_body, &retries);
1105 
1106  if (status == HTTP_OK || status == HTTP_ACCEPTED) {
1107 
1108  if (msg->sms.sms_type == report_mo) {
1109  /* we are done */
1110  goto requeued;
1111  }
1112 
1113  http_header_get_content_type(reply_headers, &type, &charset);
1114  if (octstr_case_compare(type, text_html) == 0 ||
1115  octstr_case_compare(type, text_wml) == 0) {
1116  if (trans != NULL)
1119  replytext = html_to_sms(reply_body);
1120  octstr_strip_blanks(replytext);
1121  get_x_kannel_from_headers(reply_headers, &from, &to, &udh,
1122  NULL, NULL, &smsc, &mclass, &mwi,
1123  &coding, &compress, &validity,
1124  &deferred, &dlr_mask, &dlr_url,
1125  &account, &pid, &alt_dcs, &rpi,
1126  &binfo, &priority, &meta_data);
1127  } else if (octstr_case_compare(type, text_plain) == 0) {
1128  replytext = octstr_duplicate(reply_body);
1129  octstr_destroy(reply_body);
1130  reply_body = NULL;
1131  get_x_kannel_from_headers(reply_headers, &from, &to, &udh,
1132  NULL, NULL, &smsc, &mclass, &mwi,
1133  &coding, &compress, &validity,
1134  &deferred, &dlr_mask, &dlr_url,
1135  &account, &pid, &alt_dcs, &rpi,
1136  &binfo, &priority, &meta_data);
1137  } else if (octstr_case_compare(type, text_xml) == 0) {
1138  replytext = octstr_duplicate(reply_body);
1139  octstr_destroy(reply_body);
1140  reply_body = NULL;
1141  get_x_kannel_from_xml(mt_reply, &type, &replytext, reply_headers,
1142  &from, &to, &udh, NULL, NULL, &smsc, &mclass, &mwi,
1143  &coding, &compress, &validity, &deferred, &dlr_mask,
1144  &dlr_url, &account, &pid, &alt_dcs, &rpi, NULL, &charset,
1145  &binfo, &priority, &meta_data);
1146  } else if (octstr_case_compare(type, octet_stream) == 0) {
1147  replytext = octstr_duplicate(reply_body);
1148  octstr_destroy(reply_body);
1149  coding = DC_8BIT;
1150  reply_body = NULL;
1151  get_x_kannel_from_headers(reply_headers, &from, &to, &udh,
1152  NULL, NULL, &smsc, &mclass, &mwi,
1153  &coding, &compress, &validity,
1154  &deferred, &dlr_mask, &dlr_url,
1155  &account, &pid, &alt_dcs, &rpi,
1156  &binfo, &priority, &meta_data);
1157  } else {
1159  }
1160 
1161  /*
1162  * If there was a charset specified in the HTTP response,
1163  * we're not going to touch the encoding. Otherwise check if
1164  * we have a defined alt-charset for this sms-service.
1165  */
1166  if (octstr_len(charset) == 0 &&
1167  (alt_charset = urltrans_alt_charset(trans)) != NULL) {
1170  }
1171 
1172  /*
1173  * Ensure now that we transcode to our internal encoding.
1174  */
1175  if (sms_charset_processing(charset, replytext, coding) == -1) {
1177  }
1179  } else if (max_http_retries > retries) {
1180  item = gw_malloc(sizeof(TimerItem));
1182  item->id = remember_receiver(msg, trans, method, req_url,
1183  req_headers, req_body, retries);
1185  queued++;
1186  goto requeued;
1187  } else
1189 
1190  if (final_url == NULL)
1191  final_url = octstr_imm("");
1192  if (reply_body == NULL)
1193  reply_body = octstr_imm("");
1194 
1195  if (msg->sms.sms_type != report_mo) {
1196  fill_message(msg, trans, replytext, from, to, udh, mclass,
1197  mwi, coding, compress, validity, deferred, dlr_url,
1198  dlr_mask, pid, alt_dcs, rpi, smsc, account, charset,
1199  binfo, priority, meta_data);
1200 
1201  alog("SMS HTTP-request sender:%s request: '%s' url: '%s' reply: %d '%s'",
1202  octstr_get_cstr(msg->sms.receiver),
1203  (msg->sms.msgdata != NULL) ? octstr_get_cstr(msg->sms.msgdata) : "",
1204  octstr_get_cstr(final_url), status,
1205  (status == HTTP_OK) ? "<< successful >>" : octstr_get_cstr(reply_body));
1206  } else {
1207  octstr_destroy(replytext);
1208  }
1209 
1210 requeued:
1211  octstr_destroy(final_url);
1212  http_destroy_headers(reply_headers);
1213  octstr_destroy(reply_body);
1214  octstr_destroy(req_url);
1215  http_destroy_headers(req_headers);
1216  octstr_destroy(req_body);
1217 
1218  if (msg->sms.sms_type != report_mo && !queued) {
1219  if (send_message(trans, msg) < 0)
1220  error(0, "failed to send message to phone");
1221  }
1222  msg_destroy(msg);
1223  }
1224 }
1225 
1226 
1227 /***********************************************************************
1228  * Thread to receive SMS messages from bearerbox and obeying the requests
1229  * in them. HTTP requests are started in the background (another thread
1230  * will deal with the replies) and other requests are fulfilled directly.
1231  */
1232 
1233 
1234 /*
1235  * Perform the service requested by the user: translate the request into
1236  * a pattern, if it is an URL, start its fetch and return 0, otherwise
1237  * return the string in `*result' and return 1. Return -1 for errors.
1238  * If we are translating url for ppg dlr, we do not use trans data
1239  * structure defined for sms services. This is indicated by trans = NULL.
1240  */
1241 static int obey_request(Octstr **result, URLTranslation *trans, Msg *msg)
1242 {
1243  Octstr *pattern, *xml, *tmp;
1244  List *request_headers;
1245  void *id;
1246  struct tm tm;
1247  char p[22];
1248  int type;
1249  FILE *f;
1250 
1251  gw_assert(msg != NULL);
1252  gw_assert(msg_type(msg) == sms);
1253 
1254  if (msg->sms.sms_type == report_mo)
1256  else
1257  type = urltrans_type(trans);
1258 
1259  pattern = urltrans_get_pattern(trans, msg);
1260  gw_assert(pattern != NULL);
1261 
1262  switch (type) {
1263  case TRANSTYPE_TEXT:
1264  debug("sms", 0, "formatted text answer: <%s>",
1265  octstr_get_cstr(pattern));
1266  *result = pattern;
1267  alog("SMS request sender:%s request: '%s' fixed answer: '%s'",
1268  octstr_get_cstr(msg->sms.receiver),
1269  octstr_get_cstr(msg->sms.msgdata),
1270  octstr_get_cstr(pattern));
1271  break;
1272 
1273  case TRANSTYPE_FILE:
1274  *result = octstr_read_file(octstr_get_cstr(pattern));
1275  octstr_destroy(pattern);
1276  alog("SMS request sender:%s request: '%s' file answer: '%s'",
1277  octstr_get_cstr(msg->sms.receiver),
1278  octstr_get_cstr(msg->sms.msgdata),
1279  octstr_get_cstr(*result));
1280  break;
1281 
1282  case TRANSTYPE_EXECUTE:
1284  debug("sms.exec", 0, "executing sms-service '%s'",
1285  octstr_get_cstr(pattern));
1286  if ((f = popen(octstr_get_cstr(pattern), "r")) != NULL) {
1287  octstr_destroy(pattern);
1288  *result = octstr_read_pipe(f);
1289  pclose(f);
1291  alog("SMS request sender:%s request: '%s' file answer: '%s'",
1292  octstr_get_cstr(msg->sms.receiver),
1293  octstr_get_cstr(msg->sms.msgdata),
1294  octstr_get_cstr(*result));
1295  } else {
1296  error(0, "popen failed for '%s': %d: %s",
1297  octstr_get_cstr(pattern), errno, strerror(errno));
1298  *result = NULL;
1299  octstr_destroy(pattern);
1300  return -1;
1301  }
1302  break;
1303 
1304  /*
1305  * No Kannel headers when we are sending dlrs to wap push
1306  */
1307  case TRANSTYPE_GET_URL:
1308  request_headers = http_create_empty_headers();
1309  http_header_add(request_headers, "User-Agent", GW_NAME "/" GW_VERSION);
1310  if (trans != NULL) {
1311  if (urltrans_send_sender(trans)) {
1312  http_header_add(request_headers, "X-Kannel-From",
1313  octstr_get_cstr(msg->sms.receiver));
1314  }
1315  }
1316 
1317  id = remember_receiver(msg, trans, HTTP_METHOD_GET, pattern, request_headers, NULL, 0);
1319  http_start_request(caller, HTTP_METHOD_GET, pattern, request_headers,
1320  NULL, 1, id, NULL);
1321  octstr_destroy(pattern);
1322  http_destroy_headers(request_headers);
1323  *result = NULL;
1324  return 0;
1325  break;
1326 
1327  case TRANSTYPE_POST_URL:
1328  request_headers = http_create_empty_headers();
1329  http_header_add(request_headers, "User-Agent", GW_NAME "/" GW_VERSION);
1330  if (msg->sms.coding == DC_8BIT)
1331  http_header_add(request_headers, "Content-Type", "application/octet-stream");
1332  else if(msg->sms.coding == DC_UCS2)
1333  http_header_add(request_headers, "Content-Type", "text/plain; charset=\"UTF-16BE\"");
1334  else {
1335  Octstr *header;
1336  header = octstr_create("text/plain");
1337  if (msg->sms.charset) {
1338  octstr_append(header, octstr_imm("; charset=\""));
1339  octstr_append(header, msg->sms.charset);
1340  octstr_append(header, octstr_imm("\""));
1341  } else {
1342  octstr_append(header, octstr_imm("; charset=\"UTF-8\""));
1343  }
1344  http_header_add(request_headers, "Content-Type", octstr_get_cstr(header));
1345  O_DESTROY(header);
1346  }
1347  if (urltrans_send_sender(trans))
1348  http_header_add(request_headers, "X-Kannel-From",
1349  octstr_get_cstr(msg->sms.receiver));
1350  http_header_add(request_headers, "X-Kannel-To",
1351  octstr_get_cstr(msg->sms.sender));
1352 
1353  tm = gw_gmtime(msg->sms.time);
1354  sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d",
1355  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
1356  tm.tm_hour, tm.tm_min, tm.tm_sec);
1357  http_header_add(request_headers, "X-Kannel-Time", p);
1358 
1359  tm = gw_gmtime(time(NULL));
1360  sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d",
1361  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
1362  tm.tm_hour, tm.tm_min, tm.tm_sec);
1363  http_header_add(request_headers, "Date", p); /* HTTP RFC 14.18 */
1364 
1365  if (octstr_len(msg->sms.udhdata)) {
1366  Octstr *os;
1367  os = octstr_duplicate(msg->sms.udhdata);
1368  octstr_url_encode(os);
1369  http_header_add(request_headers, "X-Kannel-UDH", octstr_get_cstr(os));
1370  octstr_destroy(os);
1371  }
1372  if (octstr_len(msg->sms.smsc_id)) {
1373  Octstr *os;
1374  os = octstr_duplicate(msg->sms.smsc_id);
1375  http_header_add(request_headers, "X-Kannel-SMSC", octstr_get_cstr(os));
1376  octstr_destroy(os);
1377  }
1378 
1379  if (msg->sms.mclass != SMS_PARAM_UNDEFINED) {
1380  Octstr *os;
1381  os = octstr_format("%d",msg->sms.mclass);
1382  http_header_add(request_headers, "X-Kannel-MClass", octstr_get_cstr(os));
1383  octstr_destroy(os);
1384  }
1385  if (msg->sms.pid != SMS_PARAM_UNDEFINED) {
1386  Octstr *os;
1387  os = octstr_format("%d",msg->sms.pid);
1388  http_header_add(request_headers, "X-Kannel-PID", octstr_get_cstr(os));
1389  octstr_destroy(os);
1390  }
1391  if (msg->sms.rpi != SMS_PARAM_UNDEFINED) {
1392  Octstr *os;
1393  os = octstr_format("%d",msg->sms.rpi);
1394  http_header_add(request_headers, "X-Kannel-RPI", octstr_get_cstr(os));
1395  octstr_destroy(os);
1396  }
1397  if (msg->sms.alt_dcs != SMS_PARAM_UNDEFINED) {
1398  Octstr *os;
1399  os = octstr_format("%d",msg->sms.alt_dcs);
1400  http_header_add(request_headers, "X-Kannel-Alt-DCS", octstr_get_cstr(os));
1401  octstr_destroy(os);
1402  }
1403  if (msg->sms.mwi != SMS_PARAM_UNDEFINED) {
1404  Octstr *os;
1405  os = octstr_format("%d",msg->sms.mwi);
1406  http_header_add(request_headers, "X-Kannel-MWI", octstr_get_cstr(os));
1407  octstr_destroy(os);
1408  }
1409  if (msg->sms.coding != SMS_PARAM_UNDEFINED) {
1410  Octstr *os;
1411  os = octstr_format("%d",msg->sms.coding);
1412  http_header_add(request_headers, "X-Kannel-Coding", octstr_get_cstr(os));
1413  octstr_destroy(os);
1414  }
1415  if (msg->sms.compress != SMS_PARAM_UNDEFINED) {
1416  Octstr *os;
1417  os = octstr_format("%d",msg->sms.compress);
1418  http_header_add(request_headers, "X-Kannel-Compress", octstr_get_cstr(os));
1419  octstr_destroy(os);
1420  }
1421  if (msg->sms.validity != SMS_PARAM_UNDEFINED) {
1422  Octstr *os;
1423  os = octstr_format("%d", (msg->sms.validity - time(NULL)) / 60);
1424  http_header_add(request_headers, "X-Kannel-Validity", octstr_get_cstr(os));
1425  octstr_destroy(os);
1426  }
1427  if (msg->sms.deferred != SMS_PARAM_UNDEFINED) {
1428  Octstr *os;
1429  os = octstr_format("%d", (msg->sms.deferred - time(NULL)) / 60);
1430  http_header_add(request_headers, "X-Kannel-Deferred", octstr_get_cstr(os));
1431  octstr_destroy(os);
1432  }
1433  if (octstr_len(msg->sms.service)) {
1434  http_header_add(request_headers, "X-Kannel-Service", octstr_get_cstr(msg->sms.service));
1435  }
1436  if (octstr_len(msg->sms.binfo)) {
1437  http_header_add(request_headers, "X-Kannel-BInfo", octstr_get_cstr(msg->sms.binfo));
1438  }
1439  if (octstr_len(msg->sms.meta_data)) {
1440  http_header_add(request_headers, "X-Kannel-Meta-Data", octstr_get_cstr(msg->sms.meta_data));
1441  }
1442 
1443  id = remember_receiver(msg, trans, HTTP_METHOD_POST, pattern,
1444  request_headers, msg->sms.msgdata, 0);
1446  http_start_request(caller, HTTP_METHOD_POST, pattern, request_headers,
1447  msg->sms.msgdata, 1, id, NULL);
1448  octstr_destroy(pattern);
1449  http_destroy_headers(request_headers);
1450  *result = NULL;
1451  return 0;
1452  break;
1453 
1454  case TRANSTYPE_POST_XML:
1455 
1456  /* XXX The first two chars are beeing eaten somewhere and
1457  * only sometimes - something must be ungry */
1458 
1459 #define OCTSTR_APPEND_XML(xml, tag, text) \
1460  octstr_format_append(xml, " \t\t<" tag ">%s</" tag ">\n", (text?octstr_get_cstr(text):""))
1461 
1462 #define OCTSTR_APPEND_XML_OCTSTR(xml, tag, text) \
1463  do { \
1464  xmlDocPtr tmp_doc = xmlNewDoc(BAD_CAST "1.0"); \
1465  xmlChar *xml_escaped = NULL; \
1466  if (text != NULL) xml_escaped = xmlEncodeEntitiesReentrant(tmp_doc, BAD_CAST octstr_get_cstr(text)); \
1467  octstr_format_append(xml, " \t\t<" tag ">%s</" tag ">\n", (xml_escaped != NULL ? (char*)xml_escaped : "")); \
1468  if (xml_escaped != NULL) xmlFree(xml_escaped); \
1469  xmlFreeDoc(tmp_doc); \
1470  } while(0)
1471 
1472 #define OCTSTR_APPEND_XML_NUMBER(xml, tag, value) \
1473  octstr_format_append(xml, " \t\t<" tag ">%ld</" tag ">\n", (long) value)
1474 
1475  request_headers = http_create_empty_headers();
1476  http_header_add(request_headers, "User-Agent", GW_NAME "/" GW_VERSION);
1477  if (msg->sms.coding == DC_UCS2) {
1478  http_header_add(request_headers, "Content-Type",
1479  "text/xml; charset=\"ISO-8859-1\""); /* for account and other strings */
1480  } else {
1481  Octstr *header;
1482  header = octstr_create("text/xml");
1483  if(msg->sms.charset) {
1484  octstr_append(header, octstr_imm("; charset=\""));
1485  octstr_append(header, msg->sms.charset);
1486  octstr_append(header, octstr_imm("\""));
1487  }
1488  http_header_add(request_headers, "Content-Type", octstr_get_cstr(header));
1489  O_DESTROY(header);
1490  }
1491 
1492  tm = gw_gmtime(time(NULL));
1493  sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d",
1494  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
1495  tm.tm_hour, tm.tm_min, tm.tm_sec);
1496  http_header_add(request_headers, "Date", p); /* HTTP RFC 14.18 */
1497 
1498  xml = octstr_create("");
1499  octstr_append(xml, octstr_imm("<?xml version=\"1.0\" encoding=\""));
1500  if (msg->sms.coding == DC_UCS2 || msg->sms.charset == NULL)
1501  octstr_append(xml, octstr_imm("ISO-8859-1"));
1502  else
1503  octstr_append(xml, msg->sms.charset);
1504  octstr_append(xml, octstr_imm("\"?>\n"));
1505 
1506  /*
1507  * XXX damn windows that breaks with this :
1508  * octstr_append(xml, octstr_imm("<!DOCTYPE message SYSTEM \"SMSmessage.dtd\">\n"));
1509  */
1510  octstr_append(xml, octstr_imm("<message cid=\"1\">\n"));
1511  octstr_append(xml, octstr_imm("\t<submit>\n"));
1512 
1513  /* oa */
1514  if (urltrans_send_sender(trans)) {
1515  tmp = octstr_create("");
1516  OCTSTR_APPEND_XML_OCTSTR(tmp, "number", msg->sms.receiver);
1517  OCTSTR_APPEND_XML(xml, "oa", tmp);
1518  octstr_destroy(tmp);
1519  }
1520 
1521  /* da */
1522  tmp = octstr_create("");
1523  OCTSTR_APPEND_XML_OCTSTR(tmp, "number", msg->sms.sender);
1524  OCTSTR_APPEND_XML(xml, "da", tmp);
1525  octstr_destroy(tmp);
1526 
1527  /* udh */
1528  if (octstr_len(msg->sms.udhdata)) {
1529  Octstr *t;
1530  t = octstr_duplicate(msg->sms.udhdata);
1531  octstr_url_encode(t);
1532  OCTSTR_APPEND_XML_OCTSTR(xml, "udh", t);
1533  octstr_destroy(t);
1534  }
1535 
1536  /* ud */
1537  if (octstr_len(msg->sms.msgdata)) {
1538  octstr_url_encode(msg->sms.msgdata);
1539  OCTSTR_APPEND_XML_OCTSTR(xml, "ud", msg->sms.msgdata);
1540  }
1541 
1542  /* pid */
1543  if (msg->sms.pid != SMS_PARAM_UNDEFINED)
1544  OCTSTR_APPEND_XML_NUMBER(xml, "pid", msg->sms.pid);
1545 
1546  /* rpi */
1547  if (msg->sms.rpi != SMS_PARAM_UNDEFINED)
1548  OCTSTR_APPEND_XML_NUMBER(xml, "rpi", msg->sms.rpi);
1549 
1550  /* dcs */
1551  tmp = octstr_create("");
1552  if (msg->sms.coding != SMS_PARAM_UNDEFINED)
1553  OCTSTR_APPEND_XML_NUMBER(tmp, "coding", msg->sms.coding);
1554  if (msg->sms.mclass != SMS_PARAM_UNDEFINED)
1555  OCTSTR_APPEND_XML_NUMBER(tmp, "mclass", msg->sms.mclass);
1556  if (msg->sms.alt_dcs != SMS_PARAM_UNDEFINED)
1557  OCTSTR_APPEND_XML_NUMBER(tmp, "alt-dcs", msg->sms.alt_dcs);
1558  if (msg->sms.mwi != SMS_PARAM_UNDEFINED)
1559  OCTSTR_APPEND_XML_NUMBER(tmp, "mwi", msg->sms.mwi);
1560  if (msg->sms.compress != SMS_PARAM_UNDEFINED)
1561  OCTSTR_APPEND_XML_NUMBER(tmp, "compress", msg->sms.compress);
1562  if (octstr_len(tmp))
1563  OCTSTR_APPEND_XML(xml, "dcs", tmp);
1564  octstr_destroy(tmp);
1565 
1566  /* deferred (timing/delay) */
1567  tmp = octstr_create("");
1568  if(msg->sms.deferred != SMS_PARAM_UNDEFINED)
1569  OCTSTR_APPEND_XML_NUMBER(tmp, "delay", (msg->sms.deferred - time(NULL)) / 60);
1570  if(octstr_len(tmp))
1571  OCTSTR_APPEND_XML(xml, "timing", tmp);
1572  octstr_destroy(tmp);
1573 
1574  /* validity (vp/delay) */
1575  tmp = octstr_create("");
1576  if(msg->sms.validity != SMS_PARAM_UNDEFINED)
1577  OCTSTR_APPEND_XML_NUMBER(tmp, "delay", (msg->sms.validity - time(NULL)) / 60);
1578  if(octstr_len(tmp))
1579  OCTSTR_APPEND_XML(xml, "vp", tmp);
1580  octstr_destroy(tmp);
1581 
1582  /* time (at) */
1583  tm = gw_gmtime(msg->sms.time);
1584  tmp = octstr_format("<year>%04d</year><month>%02d</month>"
1585  "<day>%02d</day><hour>%02d</hour><minute>%02d</minute>"
1586  "<second>%02d</second><timezone>0</timezone>",
1587  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
1588  tm.tm_hour, tm.tm_min, tm.tm_sec);
1589  OCTSTR_APPEND_XML(xml, "at", tmp);
1590  octstr_destroy(tmp);
1591 
1592  /* smsc */
1593  if (octstr_len(msg->sms.smsc_id)) {
1594  tmp = octstr_create("");
1595  if (octstr_len(msg->sms.smsc_id))
1596  OCTSTR_APPEND_XML_OCTSTR(tmp, "account", msg->sms.smsc_id);
1597  if (octstr_len(tmp))
1598  OCTSTR_APPEND_XML(xml, "from", tmp);
1599  O_DESTROY(tmp);
1600  }
1601 
1602  /* service = to/service */
1603  if (octstr_len(msg->sms.service)) {
1604  tmp = octstr_create("");
1605  OCTSTR_APPEND_XML_OCTSTR(tmp, "service", msg->sms.service);
1606  if (octstr_len(tmp))
1607  OCTSTR_APPEND_XML(xml, "to", tmp);
1608  O_DESTROY(tmp);
1609  }
1610 
1611  /* meta_data */
1612  if (octstr_len(msg->sms.meta_data)) {
1613  OCTSTR_APPEND_XML_OCTSTR(xml, "meta-data", msg->sms.meta_data);
1614  }
1615 
1616  /* End XML */
1617  octstr_append(xml, octstr_imm("\t</submit>\n"));
1618  octstr_append(xml, octstr_imm("</message>\n"));
1619 
1620  if (msg->sms.msgdata != NULL)
1621  octstr_destroy(msg->sms.msgdata);
1622 
1623  msg->sms.msgdata = xml;
1624 
1625  debug("sms", 0, "XMLBuild: XML: <%s>", octstr_get_cstr(msg->sms.msgdata));
1626  id = remember_receiver(msg, trans, HTTP_METHOD_POST, pattern,
1627  request_headers, msg->sms.msgdata, 0);
1629  http_start_request(caller, HTTP_METHOD_POST, pattern, request_headers,
1630  msg->sms.msgdata, 1, id, NULL);
1631  octstr_destroy(pattern);
1632  http_destroy_headers(request_headers);
1633  *result = NULL;
1634  return 0;
1635  break;
1636 
1637  case TRANSTYPE_SENDSMS:
1638  error(0, "Got URL translation type SENDSMS for incoming message.");
1639  alog("SMS request sender:%s request: '%s' FAILED bad translation",
1640  octstr_get_cstr(msg->sms.receiver),
1641  octstr_get_cstr(msg->sms.msgdata));
1642  octstr_destroy(pattern);
1643  return -1;
1644  break;
1645 
1646  default:
1647  error(0, "Unknown URL translation type %d", urltrans_type(trans));
1648  alog("SMS request sender:%s request: '%s' FAILED unknown translation",
1649  octstr_get_cstr(msg->sms.receiver),
1650  octstr_get_cstr(msg->sms.msgdata));
1651  octstr_destroy(pattern);
1652  return -1;
1653  break;
1654  }
1655 
1656  return 1;
1657 }
1658 
1659 static void obey_request_thread(void *arg)
1660 {
1661  Msg *msg, *mack, *reply_msg;
1662  Octstr *tmp, *reply;
1663  URLTranslation *trans;
1664  Octstr *p;
1665  int ret, dreport=0;
1666 
1667  while ((msg = gwlist_consume(smsbox_requests)) != NULL) {
1668 
1669  if (msg->sms.sms_type == report_mo)
1670  dreport = 1;
1671  else
1672  dreport = 0;
1673 
1674  /* Recode to UTF-8 the MO message if possible */
1675  if (mo_recode && msg->sms.coding == DC_UCS2) {
1676  Octstr *text;
1677 
1678  text = octstr_duplicate(msg->sms.msgdata);
1679  if (octstr_recode(octstr_imm("UTF-8"), octstr_imm("UTF-16BE"), text) == 0) {
1680  info(0, "MO message converted from UCS-2 to UTF-8");
1681  octstr_destroy(msg->sms.msgdata);
1682  msg->sms.msgdata = octstr_duplicate(text);
1683  msg->sms.charset = octstr_create("UTF-8");
1684  msg->sms.coding = DC_7BIT;
1685  }
1687  }
1688 
1689  if (octstr_len(msg->sms.sender) == 0 ||
1690  octstr_len(msg->sms.receiver) == 0) {
1691  error(0, "smsbox_req_thread: no sender/receiver, dump follows:");
1692  msg_dump(msg, 0);
1693  /*
1694  * Send NACK to bearerbox, otherwise message remains in store file.
1695  */
1696  mack = msg_create(ack);
1697  mack->ack.nack = ack_failed;
1698  mack->ack.time = msg->sms.time;
1699  uuid_copy(mack->ack.id, msg->sms.id);
1700  write_to_bearerbox(mack);
1701 
1702  msg_destroy(msg);
1703  continue;
1704  }
1705 
1706  /* create ack message to be sent afterwards */
1707  mack = msg_create(ack);
1708  mack->ack.nack = ack_success;
1709  mack->ack.time = msg->sms.time;
1710  uuid_copy(mack->ack.id, msg->sms.id);
1711 
1712  /*
1713  * no smsbox services when we are doing ppg dlr - so trans would be
1714  * NULL in this case.
1715  */
1716  if (dreport) {
1717  if (msg->sms.service == NULL || (msg->sms.service != NULL &&
1718  ppg_service_name != NULL &&
1719  octstr_compare(msg->sms.service, ppg_service_name) == 0)) {
1720  trans = NULL;
1721  } else {
1723  }
1724 
1725  info(0, "Starting delivery report <%s> from <%s>",
1726  octstr_get_cstr(msg->sms.service),
1727  octstr_get_cstr(msg->sms.sender));
1728 
1729  } else {
1730  trans = urltrans_find(translations, msg);
1731  if (trans == NULL) {
1732  warning(0, "No translation found for <%s> from <%s> to <%s>",
1733  octstr_get_cstr(msg->sms.msgdata),
1734  octstr_get_cstr(msg->sms.sender),
1735  octstr_get_cstr(msg->sms.receiver));
1736  sms_swap(msg);
1737  goto error;
1738  }
1739 
1740  info(0, "Starting to service <%s> from <%s> to <%s>",
1741  octstr_get_cstr(msg->sms.msgdata),
1742  octstr_get_cstr(msg->sms.sender),
1743  octstr_get_cstr(msg->sms.receiver));
1744 
1745  /*
1746  * Transcode to an alt-charset encoding if requested for sms-service.
1747  * This ensures that legacy systems using Kannel 1.4.1 which used
1748  * latin1 as internal encoding can issue the same content to the
1749  * application servers.
1750  */
1751  tmp = urltrans_alt_charset(trans);
1752  if (tmp != NULL && msg->sms.coding == DC_7BIT) {
1753  if (charset_convert(msg->sms.msgdata, "UTF-8", octstr_get_cstr(tmp)) != 0) {
1754  error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave as is.",
1755  "UTF-8", octstr_get_cstr(tmp));
1756  }
1757  }
1758 
1759  /*
1760  * now, we change the sender (receiver now 'cause we swap them later)
1761  * if faked-sender or similar set. Note that we ignore if the
1762  * replacement fails.
1763  */
1764  tmp = octstr_duplicate(msg->sms.sender);
1765 
1766  p = urltrans_faked_sender(trans);
1767  if (p != NULL) {
1768  octstr_destroy(msg->sms.sender);
1769  msg->sms.sender = octstr_duplicate(p);
1770  } else if (global_sender != NULL) {
1771  octstr_destroy(msg->sms.sender);
1772  msg->sms.sender = octstr_duplicate(global_sender);
1773  } else {
1774  octstr_destroy(msg->sms.sender);
1775  msg->sms.sender = octstr_duplicate(msg->sms.receiver);
1776  }
1777  octstr_destroy(msg->sms.receiver);
1778  msg->sms.receiver = tmp;
1779  msg->sms.sms_type = mt_reply;
1780  }
1781 
1782  /* TODO: check if the sender is approved to use this service */
1783 
1784  if (msg->sms.service == NULL && trans != NULL)
1785  msg->sms.service = octstr_duplicate(urltrans_name(trans));
1786  ret = obey_request(&reply, trans, msg);
1787  if (ret != 0) {
1788  if (ret == -1) {
1789 error:
1790  error(0, "request failed");
1791  /* XXX this can be something different, according to
1792  urltranslation */
1794  trans = NULL; /* do not use any special translation */
1795  }
1796  if (!dreport) {
1797  /* create reply message */
1798  reply_msg = msg_create(sms);
1799  reply_msg->sms.sms_type = mt_reply;
1800  reply_msg->sms.sender = msg->sms.sender;
1801  msg->sms.sender = NULL;
1802  reply_msg->sms.receiver = msg->sms.receiver;
1803  msg->sms.receiver = NULL;
1804  reply_msg->sms.smsc_id = msg->sms.smsc_id;
1805  msg->sms.smsc_id = NULL;
1806  reply_msg->sms.msgdata = reply;
1807  reply_msg->sms.time = time(NULL); /* set current time */
1808 
1809  /* send message */
1810  if (send_message(trans, reply_msg) < 0)
1811  error(0, "request_thread: failed");
1812 
1813  /* cleanup */
1814  msg_destroy(reply_msg);
1815  }
1816  }
1817 
1818  write_to_bearerbox(mack); /* implicit msg_destroy */
1819 
1820  msg_destroy(msg);
1821  }
1822 }
1823 
1824 
1825 /***********************************************************************
1826  * HTTP sendsms interface.
1827  */
1828 
1829 
1830 #ifdef HAVE_SECURITY_PAM_APPL_H /*Module for pam authentication */
1831 
1832 /*
1833  * Use PAM (Pluggable Authentication Module) to check sendsms authentication.
1834  */
1835 
1836 typedef const struct pam_message pam_message_type;
1837 
1838 static const char *PAM_username;
1839 static const char *PAM_password;
1840 
1841 static int PAM_conv (int num_msg, pam_message_type **msg,
1842  struct pam_response **resp,
1843  void *appdata_ptr)
1844 {
1845  int count = 0, replies = 0;
1846  struct pam_response *repl = NULL;
1847  int size = sizeof(struct pam_response);
1848 
1849 #define GET_MEM \
1850  repl = gw_realloc(repl, size); \
1851  size += sizeof(struct pam_response)
1852 #define COPY_STRING(s) (s) ? gw_strdup(s) : NULL
1853 
1854  for (count = 0; count < num_msg; count++) {
1855  switch (msg[count]->msg_style) {
1856  case PAM_PROMPT_ECHO_ON:
1857  GET_MEM;
1858  repl[replies].resp_retcode = PAM_SUCCESS;
1859  repl[replies++].resp = COPY_STRING(PAM_username);
1860  /* PAM frees resp */
1861  break;
1862 
1863  case PAM_PROMPT_ECHO_OFF:
1864  GET_MEM;
1865  repl[replies].resp_retcode = PAM_SUCCESS;
1866  repl[replies++].resp = COPY_STRING(PAM_password);
1867  /* PAM frees resp */
1868  break;
1869 
1870  case PAM_TEXT_INFO:
1871  warning(0, "unexpected message from PAM: %s", msg[count]->msg);
1872  break;
1873 
1874  case PAM_ERROR_MSG:
1875  default:
1876  /* Must be an error of some sort... */
1877  error(0, "unexpected error from PAM: %s", msg[count]->msg);
1878  gw_free(repl);
1879  return PAM_CONV_ERR;
1880  }
1881  }
1882  if (repl)
1883  *resp = repl;
1884  return PAM_SUCCESS;
1885 }
1886 
1887 static struct pam_conv PAM_conversation = {
1888  &PAM_conv,
1889  NULL
1890 };
1891 
1892 
1893 static int authenticate(const char *login, const char *passwd)
1894 {
1895  pam_handle_t *pamh;
1896  int pam_error;
1897 
1898  PAM_username = login;
1899  PAM_password = passwd;
1900 
1901  pam_error = pam_start("kannel", login, &PAM_conversation, &pamh);
1902  if (pam_error != PAM_SUCCESS ||
1903  (pam_error = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
1904  pam_end(pamh, pam_error);
1905  return 0;
1906  }
1907  pam_end(pamh, PAM_SUCCESS);
1908  info(0, "sendsms used by <%s>", login);
1909  return 1;
1910 }
1911 
1912 
1913 /*
1914  * Check for matching username and password for requests.
1915  * Return an URLTranslation if successful NULL otherwise.
1916  */
1917 
1918 static int pam_authorise_user(List *list)
1919 {
1920  Octstr *val, *user = NULL;
1921  char *pwd, *login;
1922  int result;
1923 
1924  if ((user = http_cgi_variable(list, "user")) == NULL &&
1925  (user = http_cgi_variable(list, "username"))==NULL)
1926  return 0;
1927  login = octstr_get_cstr(user);
1928 
1929  if ((val = http_cgi_variable(list, "password")) == NULL &&
1930  (val = http_cgi_variable(list, "pass")) == NULL)
1931  return 0;
1932 
1933  pwd = octstr_get_cstr(val);
1934  result = authenticate(login, pwd);
1935 
1936  return result;
1937 }
1938 
1939 #endif /* HAVE_SECURITY_PAM_APPL_H */
1940 
1941 
1942 
1943 
1945 {
1946  char id[UUID_STR_LEN + 1];
1947  Octstr *stored_uuid;
1948 
1949  gw_assert(msg != NULL);
1951 
1952  uuid_unparse(msg->sms.id, id);
1953  stored_uuid = octstr_create(id);
1954 
1955  debug("sms.http", 0, "Stored UUID %s", octstr_get_cstr(stored_uuid));
1956 
1957  /* this octstr is then used to store the HTTP client into
1958  * client_dict, if need to, in sendsms_thread */
1959 
1960  return stored_uuid;
1961 }
1962 
1963 
1964 
1966  HTTPClient *client,
1967  Octstr *from, Octstr *to, Octstr *text,
1968  Octstr *charset, Octstr *udh, Octstr *smsc,
1969  int mclass, int mwi, int coding, int compress,
1970  int validity, int deferred,
1971  int *status, int dlr_mask, Octstr *dlr_url,
1972  Octstr *account, int pid, int alt_dcs, int rpi,
1973  List *receiver, Octstr *binfo, int priority, Octstr *meta_data)
1974 {
1975  Msg *msg = NULL;
1976  Octstr *newfrom = NULL;
1977  Octstr *returnerror = NULL;
1978  Octstr *receiv;
1979  Octstr *stored_uuid = NULL;
1980  List *failed_id = NULL;
1981  List *allowed = NULL;
1982  List *denied = NULL;
1983  int no_recv, ret = 0, i;
1984 
1985  /*
1986  * Multi-cast messages with several receivers in 'to' are handled
1987  * in a loop. We only change sms.time and sms.receiver within the
1988  * loop below, because everything else is identical for all receivers.
1989  * If receiver is not null, to list is already present on it
1990  */
1991  if (receiver == NULL) {
1993  }
1994  no_recv = gwlist_len(receiver);
1995 
1996  /*
1997  * check if UDH length is legal, or otherwise discard the
1998  * message, to prevent intentional buffer overflow schemes
1999  */
2000  if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
2001  returnerror = octstr_create("UDH field misformed, rejected");
2002  goto field_error;
2003  }
2004  if (udh != NULL && octstr_len(udh) > MAX_SMS_OCTETS) {
2005  returnerror = octstr_create("UDH field is too long, rejected");
2006  goto field_error;
2007  }
2008 
2009  /*
2010  * Check for white and black lists, first for the URLTranlation
2011  * lists and then for the global lists.
2012  *
2013  * Set the 'allowed' and 'denied' lists accordingly to process at
2014  * least all allowed receiver messages. This is a constrain
2015  * walk through all disallowing rules within the lists.
2016  */
2017  allowed = gwlist_create();
2018  denied = gwlist_create();
2019 
2020  for (i = 0; i < no_recv; i++) {
2021  receiv = gwlist_get(receiver, i);
2022 
2023  /*
2024  * Check if there are any illegal characters in the 'to' scheme
2025  */
2026  if (strspn(octstr_get_cstr(receiv), sendsms_number_chars) < octstr_len(receiv)) {
2027  info(0,"Illegal characters in 'to' string ('%s') vs '%s'",
2029  gwlist_append_unique(denied, receiv, octstr_item_match);
2030  }
2031 
2032  /*
2033  * First of all fill the two lists systematically by the rules,
2034  * then we will revise the lists.
2035  */
2036  if (urltrans_white_list(t) &&
2037  numhash_find_number(urltrans_white_list(t), receiv) < 1) {
2038  info(0, "Number <%s> is not in white-list, message discarded",
2039  octstr_get_cstr(receiv));
2040  gwlist_append_unique(denied, receiv, octstr_item_match);
2041  } else {
2042  gwlist_append_unique(allowed, receiv, octstr_item_match);
2043  }
2044 
2045  if (urltrans_white_list_regex(t) &&
2046  gw_regex_match_pre(urltrans_white_list_regex(t), receiv) == 0) {
2047  info(0, "Number <%s> is not in white-list-regex, message discarded",
2048  octstr_get_cstr(receiv));
2049  gwlist_append_unique(denied, receiv, octstr_item_match);
2050  } else {
2051  gwlist_append_unique(allowed, receiv, octstr_item_match);
2052  }
2053 
2054  if (urltrans_black_list(t) &&
2055  numhash_find_number(urltrans_black_list(t), receiv) == 1) {
2056  info(0, "Number <%s> is in black-list, message discarded",
2057  octstr_get_cstr(receiv));
2058  gwlist_append_unique(denied, receiv, octstr_item_match);
2059  } else {
2060  gwlist_append_unique(allowed, receiv, octstr_item_match);
2061  }
2062 
2063  if (urltrans_black_list_regex(t) &&
2064  gw_regex_match_pre(urltrans_black_list_regex(t), receiv) == 1) {
2065  info(0, "Number <%s> is in black-list-regex, message discarded",
2066  octstr_get_cstr(receiv));
2067  gwlist_append_unique(denied, receiv, octstr_item_match);
2068  } else {
2069  gwlist_append_unique(allowed, receiv, octstr_item_match);
2070  }
2071 
2072  if (white_list &&
2073  numhash_find_number(white_list, receiv) < 1) {
2074  info(0, "Number <%s> is not in global white-list, message discarded",
2075  octstr_get_cstr(receiv));
2076  gwlist_append_unique(denied, receiv, octstr_item_match);
2077  } else {
2078  gwlist_append_unique(allowed, receiv, octstr_item_match);
2079  }
2080 
2081  if (white_list_regex &&
2082  gw_regex_match_pre(white_list_regex, receiv) == 0) {
2083  info(0, "Number <%s> is not in global white-list-regex, message discarded",
2084  octstr_get_cstr(receiv));
2085  gwlist_append_unique(denied, receiv, octstr_item_match);
2086  } else {
2087  gwlist_append_unique(allowed, receiv, octstr_item_match);
2088  }
2089 
2090  if (black_list &&
2091  numhash_find_number(black_list, receiv) == 1) {
2092  info(0, "Number <%s> is in global black-list, message discarded",
2093  octstr_get_cstr(receiv));
2094  gwlist_append_unique(denied, receiv, octstr_item_match);
2095  } else {
2096  gwlist_append_unique(allowed, receiv, octstr_item_match);
2097  }
2098 
2099  if (black_list_regex &&
2100  gw_regex_match_pre(black_list_regex, receiv) == 1) {
2101  info(0, "Number <%s> is in global black-list-regex, message discarded",
2102  octstr_get_cstr(receiv));
2103  gwlist_append_unique(denied, receiv, octstr_item_match);
2104  } else {
2105  gwlist_append_unique(allowed, receiv, octstr_item_match);
2106  }
2107 
2108  /* Have allowed for receiver */
2109  if (urltrans_allowed_prefix(t) &&
2110  does_prefix_match(urltrans_allowed_prefix(t), receiv) != 1) {
2111  gwlist_append_unique(denied, receiv, octstr_item_match);
2112  } else {
2113  gwlist_append_unique(allowed, receiv, octstr_item_match);
2114  }
2115 
2117  gw_regex_match_pre(urltrans_allowed_prefix_regex(t), receiv) == 0) {
2118  gwlist_append_unique(denied, receiv, octstr_item_match);
2119  } else {
2120  gwlist_append_unique(allowed, receiv, octstr_item_match);
2121  }
2122 
2123  /* Have denied for receiver */
2124  if (urltrans_denied_prefix(t) &&
2125  does_prefix_match(urltrans_denied_prefix(t), receiv) == 1) {
2126  gwlist_append_unique(denied, receiv, octstr_item_match);
2127  } else {
2128  gwlist_append_unique(allowed, receiv, octstr_item_match);
2129  }
2130 
2132  gw_regex_match_pre(urltrans_denied_prefix_regex(t), receiv) != 0) {
2133  gwlist_append_unique(denied, receiv, octstr_item_match);
2134  } else {
2135  gwlist_append_unique(allowed, receiv, octstr_item_match);
2136  }
2137  }
2138 
2139  /*
2140  * Now we have to revise the 'allowed' and 'denied' lists by walking
2141  * the 'denied' list and check if items are also present in 'allowed',
2142  * then we will discard them from 'allowed'.
2143  */
2144  for (i = 0; i < gwlist_len(denied); i++) {
2145  receiv = gwlist_get(denied, i);
2146  gwlist_delete_matching(allowed, receiv, octstr_item_match);
2147  }
2148 
2149  /* have all receivers been denied by list rules?! */
2150  if (gwlist_len(allowed) == 0) {
2151  returnerror = octstr_create("Number(s) has/have been denied by white/black lists, "
2152  "or allowed/denied rules.");
2153  goto field_error;
2154  }
2155 
2156  if (urltrans_faked_sender(t) != NULL) {
2157  /* discard previous from */
2159  } else if (octstr_len(from) > 0) {
2160  newfrom = octstr_duplicate(from);
2161  } else if (urltrans_default_sender(t) != NULL) {
2163  } else if (global_sender != NULL) {
2164  newfrom = octstr_duplicate(global_sender);
2165  } else {
2166  returnerror = octstr_create("Sender missing and no global set, rejected");
2167  goto field_error;
2168  }
2169 
2170  info(0, "sendsms sender:<%s:%s> (%s) to:<%s> msg:<%s>",
2172  octstr_get_cstr(newfrom),
2173  octstr_get_cstr(client_ip),
2174  ( to == NULL ? "multi-cast" : octstr_get_cstr(to) ),
2175  ( text == NULL ? "" : octstr_get_cstr(text) ));
2176 
2177  /*
2178  * Create the msg structure and fill the types. Note that sms.receiver
2179  * and sms.time are set in the multi-cast support loop below.
2180  */
2181  msg = msg_create(sms);
2182 
2183  msg->sms.service = octstr_duplicate(urltrans_name(t));
2184  msg->sms.sms_type = mt_push;
2185  msg->sms.sender = octstr_duplicate(newfrom);
2186  if (octstr_len(account)) {
2188  octstr_search_chars(account, octstr_imm("[]\n\r"), 0) == -1) {
2189  msg->sms.account = account ? octstr_duplicate(account) : NULL;
2190  } else {
2191  returnerror = octstr_create("Account field misformed or too long, rejected");
2192  goto field_error;
2193  }
2194  }
2195  msg->sms.msgdata = text ? octstr_duplicate(text) : octstr_create("");
2196  msg->sms.udhdata = udh ? octstr_duplicate(udh) : octstr_create("");
2197 
2198  if (octstr_len(binfo))
2199  msg->sms.binfo = octstr_duplicate(binfo);
2200 
2201  if (octstr_len(dlr_url)) {
2202  if (octstr_len(dlr_url) < 8) { /* http(s):// */
2203  returnerror = octstr_create("DLR-URL field misformed, rejected");
2204  goto field_error;
2205  } else {
2206  Octstr *tmp;
2207  tmp = octstr_copy(dlr_url, 0, 7);
2208  if (octstr_case_compare(tmp, octstr_imm("http://")) == 0) {
2209  msg->sms.dlr_url = octstr_duplicate(dlr_url);
2210  } else {
2211  O_DESTROY(tmp);
2212  tmp = octstr_copy(dlr_url, 0, 8);
2213  if (octstr_case_compare(tmp, octstr_imm("https://")) != 0) {
2214  returnerror = octstr_create("DLR-URL field misformed, rejected");
2215  O_DESTROY(tmp);
2216  goto field_error;
2217  }
2218 #ifdef HAVE_LIBSSL
2219  msg->sms.dlr_url = octstr_duplicate(dlr_url);
2220 #else /* HAVE_LIBSSL */
2221  else {
2222  warning(0, "DLR-URL with https but SSL not supported, url is <%s>",
2224  }
2225 #endif /* HAVE_LIBSSL */
2226  }
2227  O_DESTROY(tmp);
2228  }
2229  } else {
2230  msg->sms.dlr_url = octstr_create("");
2231  }
2232 
2233  if (dlr_mask < -1 || dlr_mask > 66) { /* 01000010 */
2234  returnerror = octstr_create("DLR-Mask field misformed, rejected");
2235  goto field_error;
2236  }
2237  msg->sms.dlr_mask = dlr_mask;
2238 
2239  if (mclass < -1 || mclass > 3) {
2240  returnerror = octstr_create("MClass field misformed, rejected");
2241  goto field_error;
2242  }
2243  msg->sms.mclass = mclass;
2244 
2245  if (pid < -1 || pid > 255) {
2246  returnerror = octstr_create("PID field misformed, rejected");
2247  goto field_error;
2248  }
2249  msg->sms.pid = pid;
2250 
2251  if (rpi < -1 || rpi > 2) {
2252  returnerror = octstr_create("RPI field misformed, rejected");
2253  goto field_error;
2254  }
2255  msg->sms.rpi = rpi;
2256 
2257  if (alt_dcs < -1 || alt_dcs > 1) {
2258  returnerror = octstr_create("Alt-DCS field misformed, rejected");
2259  goto field_error;
2260  }
2261  msg->sms.alt_dcs = alt_dcs;
2262 
2263  if (mwi < -1 || mwi > 7) {
2264  returnerror = octstr_create("MWI field misformed, rejected");
2265  goto field_error;
2266  }
2267  msg->sms.mwi = mwi;
2268 
2269  if (coding < -1 || coding > 2) {
2270  returnerror = octstr_create("Coding field misformed, rejected");
2271  goto field_error;
2272  }
2273  msg->sms.coding = coding;
2274 
2275  if (compress < -1 || compress > 1) {
2276  returnerror = octstr_create("Compress field misformed, rejected");
2277  goto field_error;
2278  }
2279  msg->sms.compress = compress;
2280 
2281  /* Compatibility Mode */
2282  if (msg->sms.coding == DC_UNDEF) {
2283  if (octstr_len(udh))
2284  msg->sms.coding = DC_8BIT;
2285  else
2286  msg->sms.coding = DC_7BIT;
2287  }
2288 
2289  if (validity < -1) {
2290  returnerror = octstr_create("Validity field misformed, rejected");
2291  goto field_error;
2292  } else if (validity != SMS_PARAM_UNDEFINED)
2293  msg->sms.validity = validity * 60 + time(NULL);
2294 
2295  if (deferred < -1) {
2296  returnerror = octstr_create("Deferred field misformed, rejected");
2297  goto field_error;
2298  } else if (deferred != SMS_PARAM_UNDEFINED)
2299  msg->sms.deferred = deferred * 60 + time(NULL);
2300 
2301  if (priority != SMS_PARAM_UNDEFINED && (priority < 0 || priority > 3)) {
2302  returnerror = octstr_create("Priority field misformed, rejected");
2303  goto field_error;
2304  }
2305 
2307  msg->sms.priority = urltrans_forced_priority(t);
2308  info(0, "send-sms request priority ignored, "
2309  "as priority forced to %d", urltrans_forced_priority(t));
2310  } else if (urltrans_max_priority(t) != SMS_PARAM_UNDEFINED &&
2311  priority > urltrans_max_priority(t)) {
2312  msg->sms.priority = urltrans_max_priority(t);
2313  info(0, "send-sms request priority ignored, "
2314  "as priority max to %d", urltrans_max_priority(t));
2315  } else {
2316  msg->sms.priority = priority;
2317  }
2318 
2319  /* new smsc-id argument - we should check this one, if able,
2320  but that's advanced logics -- Kalle */
2321 
2322  if (urltrans_forced_smsc(t)) {
2323  msg->sms.smsc_id = octstr_duplicate(urltrans_forced_smsc(t));
2324  if (smsc)
2325  info(0, "send-sms request smsc id ignored, "
2326  "as smsc id forced to %s",
2328  } else if (smsc) {
2329  msg->sms.smsc_id = octstr_duplicate(smsc);
2330  } else if (urltrans_default_smsc(t)) {
2331  msg->sms.smsc_id = octstr_duplicate(urltrans_default_smsc(t));
2332  } else
2333  msg->sms.smsc_id = NULL;
2334 
2335  if (sms_charset_processing(charset, msg->sms.msgdata, msg->sms.coding) == -1) {
2336  returnerror = octstr_create("Charset or body misformed, rejected");
2337  goto field_error;
2338  }
2339 
2340  msg->sms.meta_data = octstr_duplicate(meta_data);
2341 
2342  msg->sms.receiver = NULL;
2343 
2344  /*
2345  * All checks are done, now add multi-cast request support by
2346  * looping through 'allowed'. This should work for any
2347  * number of receivers within 'to'. If the message fails append
2348  * it to 'failed_id'.
2349  */
2350  failed_id = gwlist_create();
2351 
2352  if (!immediate_sendsms_reply) {
2353  stored_uuid = store_uuid(msg);
2354  dict_put(client_dict, stored_uuid, client);
2355  }
2356 
2357  while ((receiv = gwlist_extract_first(allowed)) != NULL) {
2358 
2359  O_DESTROY(msg->sms.receiver);
2360  msg->sms.receiver = octstr_duplicate(receiv);
2361 
2362  msg->sms.time = time(NULL);
2363  /* send the message and return number of splits */
2364  ret = send_message(t, msg);
2365 
2366  if (ret == -1) {
2367  /* add the receiver to the failed list */
2368  gwlist_append(failed_id, receiv);
2369  } else {
2370  /* log the sending as successful for this particular message */
2371  alog("send-SMS request added - sender:%s:%s %s target:%s request: '%s'",
2373  octstr_get_cstr(newfrom), octstr_get_cstr(client_ip),
2374  octstr_get_cstr(receiv),
2375  udh == NULL ? ( text == NULL ? "" : octstr_get_cstr(text) ) : "<< UDH >>");
2376  }
2377  }
2378 
2379  if (gwlist_len(failed_id) > 0)
2380  goto transmit_error;
2381 
2382  *status = HTTP_ACCEPTED;
2383  returnerror = octstr_create("Sent.");
2384 
2385  /*
2386  * Append all denied receivers to the returned body in case this is
2387  * a multi-cast send request
2388  */
2389  if (gwlist_len(denied) > 0) {
2390  octstr_format_append(returnerror, " Denied receivers are:");
2391  while ((receiv = gwlist_extract_first(denied)) != NULL) {
2392  octstr_format_append(returnerror, " %s", octstr_get_cstr(receiv));
2393  }
2394  }
2395 
2396  /*
2397  * Append number of splits to returned body.
2398  * This may be used by the calling client.
2399  */
2400  if (ret > 1)
2401  octstr_format_append(returnerror, " Message splits: %d", ret);
2402 
2403 cleanup:
2404  octstr_destroy(stored_uuid);
2405  gwlist_destroy(failed_id, NULL);
2406  gwlist_destroy(allowed, NULL);
2407  gwlist_destroy(denied, NULL);
2409  octstr_destroy(newfrom);
2410  msg_destroy(msg);
2411 
2412  return returnerror;
2413 
2414 
2415 field_error:
2416  alog("send-SMS request failed - %s", octstr_get_cstr(returnerror));
2418 
2419  goto cleanup;
2420 
2421 transmit_error:
2422  error(0, "sendsms_request: failed");
2424  returnerror = octstr_create("Sending failed.");
2425 
2427  dict_remove(client_dict, stored_uuid);
2428 
2429  /*
2430  * Append all receivers to the returned body in case this is
2431  * a multi-cast send request
2432  */
2433  if (no_recv > 1) {
2434  octstr_format_append(returnerror, " Failed receivers are:");
2435  while ((receiv = gwlist_extract_first(failed_id)) != NULL) {
2436  octstr_format_append(returnerror, " %s", octstr_get_cstr(receiv));
2437  }
2438  }
2439 
2440  goto cleanup;
2441 }
2442 
2443 
2444 /*
2445  * new authorisation, usable by POST and GET
2446  */
2448  Octstr *client_ip)
2449 {
2450  URLTranslation *t = NULL;
2451 
2452  if (username == NULL || password == NULL)
2453  return NULL;
2454 
2455  if ((t = urltrans_find_username(translations, username))==NULL)
2456  return NULL;
2457 
2459  return NULL;
2460  else {
2463 
2464  if (is_allowed_ip(allow_ip, deny_ip, client_ip) == 0) {
2465  warning(0, "Non-allowed connect tried by <%s> from <%s>, ignored",
2467  return NULL;
2468  }
2469  }
2470 
2471  info(0, "sendsms used by <%s>", octstr_get_cstr(username));
2472  return t;
2473 }
2474 
2475 /*
2476  * Authentication whith the database of Kannel.
2477  * Check for matching username and password for requests.
2478  * Return an URLTranslation if successful NULL otherwise.
2479  */
2481 {
2482  Octstr *pass, *user = NULL;
2483 
2484  if ((user = http_cgi_variable(list, "username")) == NULL)
2485  user = http_cgi_variable(list, "user");
2486 
2487  if ((pass = http_cgi_variable(list, "password")) == NULL)
2488  pass = http_cgi_variable(list, "pass");
2489 
2490  return authorise_username(user, pass, client_ip);
2491 }
2492 
2493 
2494 static URLTranslation *authorise_user(List *list, Octstr *client_ip)
2495 {
2496 #ifdef HAVE_SECURITY_PAM_APPL_H
2497  URLTranslation *t;
2498 
2500  if (t != NULL) {
2501  if (pam_authorise_user(list))
2502  return t;
2503  else
2504  return NULL;
2505  } else
2506  return default_authorise_user(list, client_ip);
2507 #else
2508  return default_authorise_user(list, client_ip);
2509 #endif
2510 }
2511 
2512 
2513 /*
2514  * Create and send an SMS message from an HTTP request.
2515  * Args: args contains the CGI parameters
2516  */
2517 static Octstr *smsbox_req_sendsms(List *args, Octstr *client_ip, int *status,
2518  HTTPClient *client)
2519 {
2520  URLTranslation *t = NULL;
2521  Octstr *tmp_string;
2522  Octstr *from, *to, *charset, *text, *udh, *smsc, *dlr_url, *account;
2523  Octstr *binfo, *meta_data;
2524  int dlr_mask, mclass, mwi, coding, compress, validity, deferred, pid;
2525  int alt_dcs, rpi, priority;
2526 
2527  from = to = udh = text = smsc = account = dlr_url = charset = binfo = meta_data = NULL;
2528  mclass = mwi = coding = compress = validity = deferred = dlr_mask =
2529  pid = alt_dcs = rpi = priority = SMS_PARAM_UNDEFINED;
2530 
2531  /* check the username and password */
2532  t = authorise_user(args, client_ip);
2533  if (t == NULL) {
2535  return octstr_create("Authorization failed for sendsms");
2536  }
2537 
2538  udh = http_cgi_variable(args, "udh");
2539  text = http_cgi_variable(args, "text");
2540  charset = http_cgi_variable(args, "charset");
2541  smsc = http_cgi_variable(args, "smsc");
2542  from = http_cgi_variable(args, "from");
2543  to = http_cgi_variable(args, "to");
2544  account = http_cgi_variable(args, "account");
2545  binfo = http_cgi_variable(args, "binfo");
2546  dlr_url = http_cgi_variable(args, "dlr-url");
2547  if(dlr_url == NULL) { /* deprecated dlrurl without "-" */
2548  dlr_url = http_cgi_variable(args, "dlrurl");
2549  if(dlr_url != NULL)
2550  warning(0, "<dlrurl> field used and deprecated. Please use dlr-url instead.");
2551  }
2552  tmp_string = http_cgi_variable(args, "dlr-mask");
2553  if(tmp_string == NULL) { /* deprecated dlrmask without "-" */
2554  tmp_string = http_cgi_variable(args, "dlrmask");
2555  if(tmp_string != NULL)
2556  warning(0, "<dlrmask> field used and deprecated. Please use dlr-mask instead.");
2557  }
2558  if(tmp_string != NULL)
2559  sscanf(octstr_get_cstr(tmp_string),"%d", &dlr_mask);
2560 
2561  tmp_string = http_cgi_variable(args, "mclass");
2562  if(tmp_string != NULL)
2563  sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
2564 
2565  tmp_string = http_cgi_variable(args, "pid");
2566  if(tmp_string != NULL)
2567  sscanf(octstr_get_cstr(tmp_string),"%d", &pid);
2568 
2569  tmp_string = http_cgi_variable(args, "rpi");
2570  if(tmp_string != NULL)
2571  sscanf(octstr_get_cstr(tmp_string),"%d", &rpi);
2572 
2573  tmp_string = http_cgi_variable(args, "alt-dcs");
2574  if(tmp_string != NULL)
2575  sscanf(octstr_get_cstr(tmp_string),"%d", &alt_dcs);
2576 
2577  tmp_string = http_cgi_variable(args, "mwi");
2578  if(tmp_string != NULL)
2579  sscanf(octstr_get_cstr(tmp_string),"%d", &mwi);
2580 
2581  tmp_string = http_cgi_variable(args, "coding");
2582  if(tmp_string != NULL)
2583  sscanf(octstr_get_cstr(tmp_string),"%d", &coding);
2584 
2585  tmp_string = http_cgi_variable(args, "compress");
2586  if(tmp_string != NULL)
2587  sscanf(octstr_get_cstr(tmp_string),"%d", &compress);
2588 
2589  tmp_string = http_cgi_variable(args, "validity");
2590  if(tmp_string != NULL)
2591  sscanf(octstr_get_cstr(tmp_string),"%d", &validity);
2592 
2593  tmp_string = http_cgi_variable(args, "deferred");
2594  if(tmp_string != NULL)
2595  sscanf(octstr_get_cstr(tmp_string),"%d", &deferred);
2596 
2597  tmp_string = http_cgi_variable(args, "priority");
2598  if(tmp_string != NULL)
2599  sscanf(octstr_get_cstr(tmp_string),"%d", &priority);
2600 
2601  meta_data = http_cgi_variable(args, "meta-data");
2602 
2603  /*
2604  * we required "to" to be defined
2605  */
2606  if (to == NULL) {
2607  error(0, "%s got insufficient headers (<to> is NULL)",
2610  return octstr_create("Missing receiver number, rejected");
2611  }
2612  else if (octstr_len(to) == 0) {
2613  error(0, "%s got empty <to> cgi variable", octstr_get_cstr(sendsms_url));
2615  return octstr_create("Empty receiver number not allowed, rejected");
2616  }
2617 
2618  return smsbox_req_handle(t, client_ip, client, from, to, text, charset, udh,
2619  smsc, mclass, mwi, coding, compress, validity,
2620  deferred, status, dlr_mask, dlr_url, account,
2621  pid, alt_dcs, rpi, NULL, binfo, priority, meta_data);
2622 
2623 }
2624 
2625 
2626 /*
2627  * Create and send an SMS message from an HTTP request.
2628  * Args: args contains the CGI parameters
2629  */
2630 static Octstr *smsbox_sendsms_post(List *headers, Octstr *body,
2631  Octstr *client_ip, int *status,
2632  HTTPClient *client)
2633 {
2634  URLTranslation *t = NULL;
2635  Octstr *user, *pass, *ret, *type;
2636  List *tolist;
2637  Octstr *text_html, *text_plain, *text_wml, *text_xml, *octet_stream;
2638  Octstr *text;
2639  Octstr *from, *to, *udh, *smsc, *charset, *dlr_url, *account, *binfo, *meta_data;
2640  int dlr_mask, mclass, mwi, coding, compress, validity, deferred;
2641  int pid, alt_dcs, rpi, priority;
2642 
2643  text_html = octstr_imm("text/html");
2644  text_wml = octstr_imm("text/vnd.wap.wml");
2645  text_plain = octstr_imm("text/plain");
2646  text_xml = octstr_imm("text/xml");
2647  octet_stream = octstr_imm("application/octet-stream");
2648 
2649  user = pass = ret = type = NULL;
2650  tolist = NULL;
2651  from = to = udh = smsc = account = dlr_url = charset = binfo = meta_data = NULL;
2652  mclass = mwi = coding = compress = validity = deferred = dlr_mask =
2653  pid = alt_dcs = rpi = priority = SMS_PARAM_UNDEFINED;
2654 
2656  if (octstr_case_compare(type, text_html) == 0 ||
2657  octstr_case_compare(type, text_wml) == 0) {
2658  text = html_to_sms(body);
2660  body = text;
2661  get_x_kannel_from_headers(headers, &from, &to, &udh,
2662  &user, &pass, &smsc, &mclass, &mwi,
2663  &coding, &compress, &validity,
2664  &deferred, &dlr_mask, &dlr_url,
2665  &account, &pid, &alt_dcs, &rpi,
2666  &binfo, &priority, &meta_data);
2667  } else if (octstr_case_compare(type, text_plain) == 0 ||
2668  octstr_case_compare(type, octet_stream) == 0) {
2669  get_x_kannel_from_headers(headers, &from, &to, &udh,
2670  &user, &pass, &smsc, &mclass, &mwi,
2671  &coding, &compress, &validity,
2672  &deferred, &dlr_mask, &dlr_url,
2673  &account, &pid, &alt_dcs, &rpi,
2674  &binfo, &priority, &meta_data);
2675  } else if (octstr_case_compare(type, text_xml) == 0) {
2676  get_x_kannel_from_xml(mt_push, &type, &body, headers,
2677  &from, &to, &udh, &user, &pass, &smsc, &mclass,
2678  &mwi, &coding, &compress, &validity, &deferred,
2679  &dlr_mask, &dlr_url, &account, &pid, &alt_dcs,
2680  &rpi, &tolist, &charset, &binfo, &priority, &meta_data);
2681  } else {
2683  ret = octstr_create("Invalid content-type");
2684  goto error;
2685  }
2686 
2687  /* check the username and password */
2688  t = authorise_username(user, pass, client_ip);
2689  if (t == NULL) {
2691  ret = octstr_create("Authorization failed for sendsms");
2692  }
2693  else if (to == NULL && tolist == NULL) {
2694  error(0, "%s got insufficient headers (<to> and <tolist> are NULL)",
2697  ret = octstr_create("Missing receiver(s) number(s), rejected");
2698  }
2699  else if (to != NULL && octstr_len(to) == 0) {
2700  error(0, "%s got empty <to> cgi variable", octstr_get_cstr(sendsms_url));
2702  ret = octstr_create("Empty receiver number not allowed, rejected");
2703  }
2704  else {
2706  octstr_imm("application/octet-stream")) == 0) {
2707  if (coding == DC_UNDEF)
2708  coding = DC_8BIT; /* XXX Force UCS-2 with DC Field */
2709  } else if (octstr_case_compare(type,
2710  octstr_imm("text/plain")) == 0) {
2711  if (coding == DC_UNDEF)
2712  coding = DC_7BIT;
2713  } else {
2714  error(0, "%s got weird content type %s", octstr_get_cstr(sendsms_url),
2717  ret = octstr_create("Unsupported content-type, rejected");
2718  }
2719 
2720  if (ret == NULL)
2721  ret = smsbox_req_handle(t, client_ip, client, from, to, body, charset,
2722  udh, smsc, mclass, mwi, coding, compress,
2723  validity, deferred, status, dlr_mask,
2724  dlr_url, account, pid, alt_dcs, rpi, tolist,
2725  binfo, priority, meta_data);
2726 
2727  }
2728  octstr_destroy(user);
2729  octstr_destroy(pass);
2731  octstr_destroy(to);
2732  octstr_destroy(udh);
2733  octstr_destroy(smsc);
2736  octstr_destroy(binfo);
2738 error:
2741  return ret;
2742 }
2743 
2744 
2745 /*
2746  * Create and send an SMS message from a XML-RPC request.
2747  * Answer with a valid XML-RPC response for a successful request.
2748  *
2749  * function signature: boolean sms.send(struct)
2750  *
2751  * The <struct> MUST contain at least <member>'s with name 'username',
2752  * 'password', 'to' and MAY contain additional <member>'s with name
2753  * 'from', 'account', 'smsc', 'udh', 'dlrmask', 'dlrurl'. All values
2754  * are of type string.
2755  */
2756 static Octstr *smsbox_xmlrpc_post(List *headers, Octstr *body,
2757  Octstr *client_ip, int *status)
2758 {
2759  Octstr *ret, *type;
2760  Octstr *charset;
2761  Octstr *output;
2764 
2765  charset = NULL;
2766  ret = NULL;
2767 
2768  /*
2769  * check if the content type is valid for this request
2770  */
2772  if (octstr_case_compare(type, octstr_imm("text/xml")) != 0) {
2773  error(0, "Unsupported content-type '%s'", octstr_get_cstr(type));
2775  ret = octstr_format("Unsupported content-type '%s'", octstr_get_cstr(type));
2776  } else {
2777 
2778  /*
2779  * parse the body of the request and check if it is a valid XML-RPC
2780  * structure
2781  */
2782  msg = xmlrpc_parse_call(body);
2783 
2785  ((output = xmlrpc_parse_error(msg)) != NULL)) {
2786  /* parse failure */
2787  error(0, "%s", octstr_get_cstr(output));
2789  ret = octstr_format("%s", octstr_get_cstr(output));
2790  octstr_destroy(output);
2791  } else {
2792 
2793  /*
2794  * at least the structure has been valid, now check for the
2795  * required methodName and the required variables
2796  */
2798  octstr_imm("sms.send")) != 0) {
2799  error(0, "Unknown method name '%s'", octstr_get_cstr(method_name));
2801  ret = octstr_format("Unkown method name '%s'",
2803  } else {
2804 
2805  /*
2806  * TODO: check for the required struct members
2807  */
2808 
2809  }
2810  }
2811 
2813  }
2814 
2815  return ret;
2816 }
2817 
2818 
2819 /*
2820  * Create and send an SMS OTA (auto configuration) message from an HTTP
2821  * request. If cgivar "text" is present, use it as a xml configuration source,
2822  * otherwise read the configuration from the configuration file.
2823  * Args: list contains the CGI parameters
2824  */
2825 static Octstr *smsbox_req_sendota(List *list, Octstr *client_ip, int *status,
2826  HTTPClient *client)
2827 {
2828  Octstr *id, *from, *phonenumber, *smsc, *ota_doc, *doc_type, *account;
2829  CfgGroup *grp;
2830  Octstr *returnerror;
2831  Octstr *stored_uuid = NULL;
2832  List *grplist;
2833  Octstr *p;
2834  URLTranslation *t;
2835  Msg *msg;
2836  int ret, ota_type;
2837 
2838  id = phonenumber = smsc = account = NULL;
2839 
2840  /* check the username and password */
2841  t = authorise_user(list, client_ip);
2842  if (t == NULL) {
2844  return octstr_create("Authorization failed for sendota");
2845  }
2846 
2847  if ((phonenumber = http_cgi_variable(list, "to")) == NULL) {
2848  if ((phonenumber = http_cgi_variable(list, "phonenumber")) == NULL) {
2849  error(0, "%s needs a valid phone number.", octstr_get_cstr(sendota_url));
2851  return octstr_create("Wrong sendota args.");
2852  }
2853  }
2854 
2855  if (urltrans_faked_sender(t) != NULL) {
2857  } else if ((from = http_cgi_variable(list, "from")) != NULL &&
2858  octstr_len(from) > 0) {
2860  } else if (urltrans_default_sender(t) != NULL) {
2862  } else if (global_sender != NULL) {
2864  } else {
2866  return octstr_create("Sender missing and no global set, rejected");
2867  }
2868 
2869  /* check does we have an external XML source for configuration */
2870  if ((ota_doc = http_cgi_variable(list, "text")) != NULL) {
2871  Octstr *sec, *pin;
2872 
2873  /*
2874  * We are doing the XML OTA compiler mode for this request
2875  */
2876  debug("sms", 0, "OTA service with XML document");
2877  ota_doc = octstr_duplicate(ota_doc);
2878  if ((doc_type = http_cgi_variable(list, "type")) == NULL)
2879  doc_type = octstr_format("%s", "settings");
2880  else
2881  doc_type = octstr_duplicate(doc_type);
2882  if ((sec = http_cgi_variable(list, "sec")) == NULL)
2883  sec = octstr_create("USERPIN");
2884  else
2885  sec = octstr_duplicate(sec);
2886  if ((pin = http_cgi_variable(list, "pin")) == NULL)
2887  pin = octstr_create("12345");
2888  else
2889  pin = octstr_duplicate(pin);
2890 
2891  if ((ret = ota_pack_message(&msg, ota_doc, doc_type, from,
2892  phonenumber, sec, pin)) < 0) {
2894  msg_destroy(msg);
2895  if (ret == -2)
2896  return octstr_create("Erroneous document type, cannot"
2897  " compile\n");
2898  else if (ret == -1)
2899  return octstr_create("Erroneous ota source, cannot compile\n");
2900  }
2901 
2902  goto send;
2903 
2904  } else {
2905 
2906  /*
2907  * We are doing the ota-settings or ota-bookmark group mode
2908  * for this request.
2909  *
2910  * Check if a ota-setting ID has been given and decide which OTA
2911  * properties to be send to the client otherwise try to find a
2912  * ota-bookmark ID. If none is found then send the default
2913  * ota-setting group, which is the first within the config file.
2914  */
2915  id = http_cgi_variable(list, "otaid");
2916 
2917  grplist = cfg_get_multi_group(cfg, octstr_imm("ota-setting"));
2918  while (grplist && (grp = gwlist_extract_first(grplist)) != NULL) {
2919  p = cfg_get(grp, octstr_imm("ota-id"));
2920  if (id == NULL || (p != NULL && octstr_compare(p, id) == 0)) {
2921  ota_type = 1;
2922  goto found;
2923  }
2924  octstr_destroy(p);
2925  }
2926  gwlist_destroy(grplist, NULL);
2927 
2928  grplist = cfg_get_multi_group(cfg, octstr_imm("ota-bookmark"));
2929  while (grplist && (grp = gwlist_extract_first(grplist)) != NULL) {
2930  p = cfg_get(grp, octstr_imm("ota-id"));
2931  if (id == NULL || (p != NULL && octstr_compare(p, id) == 0)) {
2932  ota_type = 0;
2933  goto found;
2934  }
2935  octstr_destroy(p);
2936  }
2937  gwlist_destroy(grplist, NULL);
2938 
2939  if (id != NULL)
2940  error(0, "%s can't find any ota-setting or ota-bookmark group with ota-id '%s'.",
2942  else
2943  error(0, "%s can't find any ota-setting group.", octstr_get_cstr(sendota_url));
2946  return octstr_create("Missing ota-setting or ota-bookmark group.");
2947  }
2948 
2949 found:
2950  octstr_destroy(p);
2951  gwlist_destroy(grplist, NULL);
2952 
2953  /* tokenize the OTA settings or bookmarks group and return the message */
2954  if (ota_type)
2955  msg = ota_tokenize_settings(grp, from, phonenumber);
2956  else
2957  msg = ota_tokenize_bookmarks(grp, from, phonenumber);
2958 
2959 send:
2960  /* we still need to check if smsc is forced for this */
2961  smsc = http_cgi_variable(list, "smsc");
2962  if (urltrans_forced_smsc(t)) {
2963  msg->sms.smsc_id = octstr_duplicate(urltrans_forced_smsc(t));
2964  if (smsc)
2965  info(0, "send-sms request smsc id ignored, as smsc id forced to %s",
2967  } else if (smsc) {
2968  msg->sms.smsc_id = octstr_duplicate(smsc);
2969  } else if (urltrans_default_smsc(t)) {
2970  msg->sms.smsc_id = octstr_duplicate(urltrans_default_smsc(t));
2971  } else
2972  msg->sms.smsc_id = NULL;
2973 
2974  account = http_cgi_variable(list, "account");
2975  if (octstr_len(account) > 0)
2976  msg->sms.account = octstr_duplicate(account);
2977 
2978  octstr_dump(msg->sms.msgdata, 0);
2979 
2980  info(0, "%s <%s> <%s>", octstr_get_cstr(sendota_url),
2981  id ? octstr_get_cstr(id) : "<default>", octstr_get_cstr(phonenumber));
2982 
2983  if (!immediate_sendsms_reply) {
2984  stored_uuid = store_uuid(msg);
2985  dict_put(client_dict, stored_uuid, client);
2986  }
2987 
2988  ret = send_message(t, msg);
2989 
2990  if (ret == -1) {
2991  error(0, "sendota_request: failed");
2993  returnerror = octstr_create("Sending failed.");
2994  dict_remove(client_dict, stored_uuid);
2995  } else {
2996  *status = HTTP_ACCEPTED;
2997  returnerror = octstr_create("Sent.");
2998  }
2999 
3000  msg_destroy(msg);
3001  octstr_destroy(stored_uuid);
3002 
3003  return returnerror;
3004 }
3005 
3006 
3007 /*
3008  * Create and send an SMS OTA (auto configuration) message from an HTTP POST
3009  * request. Take the X-Kannel-foobar HTTP headers as parameter information.
3010  * Args: list contains the CGI parameters
3011  *
3012  * We still care about passed GET variable, in case the X-Kannel-foobar
3013  * parameters are not used but the POST contains the XML body itself.
3014  */
3015 static Octstr *smsbox_sendota_post(List *headers, Octstr *body,
3016  Octstr *client_ip, int *status,
3017  HTTPClient *client)
3018 {
3019  Octstr *name, *val, *ret;
3020  Octstr *from, *to, *id, *user, *pass, *smsc;
3021  Octstr *type, *charset, *doc_type, *ota_doc, *sec, *pin;
3022  Octstr *stored_uuid = NULL;
3023  URLTranslation *t;
3024  Msg *msg;
3025  long l;
3026  int r;
3027 
3028  id = from = to = user = pass = smsc = NULL;
3029  doc_type = ota_doc = sec = pin = NULL;
3030 
3031  /*
3032  * process all special HTTP headers
3033  *
3034  * XXX can't we do this better?
3035  * Obviously http_header_find_first() does this
3036  */
3037  for (l = 0; l < gwlist_len(headers); l++) {
3038  http_header_get(headers, l, &name, &val);
3039 
3040  if (octstr_case_compare(name, octstr_imm("X-Kannel-OTA-ID")) == 0) {
3041  id = octstr_duplicate(val);
3042  octstr_strip_blanks(id);
3043  }
3044  else if (octstr_case_compare(name, octstr_imm("X-Kannel-From")) == 0) {
3045  from = octstr_duplicate(val);
3047  }
3048  else if (octstr_case_compare(name, octstr_imm("X-Kannel-To")) == 0) {
3049  to = octstr_duplicate(val);
3050  octstr_strip_blanks(to);
3051  }
3052  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Username")) == 0) {
3053  user = octstr_duplicate(val);
3054  octstr_strip_blanks(user);
3055  }
3056  else if (octstr_case_compare(name, octstr_imm("X-Kannel-Password")) == 0) {
3057  pass = octstr_duplicate(val);
3058  octstr_strip_blanks(pass);
3059  }
3060  else if (octstr_case_compare(name, octstr_imm("X-Kannel-SMSC")) == 0) {
3061  smsc = octstr_duplicate(val);
3062  octstr_strip_blanks(smsc);
3063  }
3064  else if (octstr_case_compare(name, octstr_imm("X-Kannel-SEC")) == 0) {
3065  sec = octstr_duplicate(val);
3066  octstr_strip_blanks(sec);
3067  }
3068  else if (octstr_case_compare(name, octstr_imm("X-Kannel-PIN")) == 0) {
3069  pin = octstr_duplicate(val);
3070  octstr_strip_blanks(pin);
3071  }
3072  }
3073 
3074  /* apply defaults */
3075  if (!sec)
3076  sec = octstr_imm("USERPIN");
3077  if (!pin)
3078  pin = octstr_imm("1234");
3079 
3080  /* check the username and password */
3081  t = authorise_username(user, pass, client_ip);
3082  if (t == NULL) {
3084  ret = octstr_create("Authorization failed for sendota");
3085  }
3086  /* let's see if we have at least a target msisdn */
3087  else if (to == NULL) {
3088  error(0, "%s needs a valid phone number.", octstr_get_cstr(sendota_url));
3090  ret = octstr_create("Wrong sendota args.");
3091  } else {
3092 
3093  if (urltrans_faked_sender(t) != NULL) {
3095  }
3096  else if (from != NULL && octstr_len(from) > 0) {
3097  }
3098  else if (urltrans_default_sender(t) != NULL) {
3100  }
3101  else if (global_sender != NULL) {
3103  }
3104  else {
3106  ret = octstr_create("Sender missing and no global set, rejected");
3107  goto error;
3108  }
3109 
3110  /*
3111  * get the content-type of the body document
3112  */
3114 
3116  octstr_imm("application/x-wap-prov.browser-settings")) == 0) {
3117  doc_type = octstr_format("%s", "settings");
3118  }
3119  else if (octstr_case_compare(type,
3120  octstr_imm("application/x-wap-prov.browser-bookmarks")) == 0) {
3121  doc_type = octstr_format("%s", "bookmarks");
3122  }
3123  else if (octstr_case_compare(type,
3124  octstr_imm("text/vnd.wap.connectivity-xml")) == 0) {
3125  doc_type = octstr_format("%s", "oma-settings");
3126  }
3127 
3128  if (doc_type == NULL) {
3129  error(0, "%s got weird content type %s", octstr_get_cstr(sendota_url),
3132  ret = octstr_create("Unsupported content-type, rejected");
3133  } else {
3134 
3135  /*
3136  * ok, this is want we expect
3137  * now lets compile the whole thing
3138  */
3139  ota_doc = octstr_duplicate(body);
3140 
3141  if ((r = ota_pack_message(&msg, ota_doc, doc_type, from, to, sec, pin)) < 0) {
3143  msg_destroy(msg);
3144  if (r == -2) {
3145  ret = octstr_create("Erroneous document type, cannot"
3146  " compile\n");
3147  goto error;
3148  }
3149  else if (r == -1) {
3150  ret = octstr_create("Erroneous ota source, cannot compile\n");
3151  goto error;
3152  }
3153  }
3154 
3155  /* we still need to check if smsc is forced for this */
3156  if (urltrans_forced_smsc(t)) {
3157  msg->sms.smsc_id = octstr_duplicate(urltrans_forced_smsc(t));
3158  if (smsc)
3159  info(0, "send-sms request smsc id ignored, as smsc id forced to %s",
3161  } else if (smsc) {
3162  msg->sms.smsc_id = octstr_duplicate(smsc);
3163  } else if (urltrans_default_smsc(t)) {
3164  msg->sms.smsc_id = octstr_duplicate(urltrans_default_smsc(t));
3165  } else
3166  msg->sms.smsc_id = NULL;
3167 
3168  info(0, "%s <%s> <%s>", octstr_get_cstr(sendota_url),
3169  id ? octstr_get_cstr(id) : "XML", octstr_get_cstr(to));
3170 
3171 
3172  if (!immediate_sendsms_reply) {
3173  stored_uuid = store_uuid(msg);
3174  dict_put(client_dict, stored_uuid, client);
3175  }
3176 
3177  r = send_message(t, msg);
3178 
3179  if (r == -1) {
3180  error(0, "sendota_request: failed");
3182  ret = octstr_create("Sending failed.");
3184  dict_remove(client_dict, stored_uuid);
3185  } else {
3186  *status = HTTP_ACCEPTED;
3187  ret = octstr_create("Sent.");
3188  }
3189 
3190  msg_destroy(msg);
3191  octstr_destroy(stored_uuid);
3192 
3193  }
3194  }
3195 
3196 error:
3197  octstr_destroy(user);
3198  octstr_destroy(pass);
3199  octstr_destroy(smsc);
3200 
3201  return ret;
3202 }
3203 
3204 
3205 static void sendsms_thread(void *arg)
3206  {
3207  HTTPClient *client;
3208  Octstr *ip, *url, *body, *answer;
3209  List *hdrs, *args;
3210  int status;
3211 
3212  for (;;) {
3213  /* reset request wars */
3214  ip = url = body = answer = NULL;
3215  hdrs = args = NULL;
3216 
3217  client = http_accept_request(sendsms_port, &ip, &url, &hdrs, &body, &args);
3218  if (client == NULL)
3219  break;
3220 
3221  info(0, "smsbox: Got HTTP request <%s> from <%s>",
3223 
3224  /*
3225  * determine which kind of HTTP request this is any
3226  * call the necessary routine for it
3227  */
3228 
3229  /* sendsms */
3230  if (octstr_compare(url, sendsms_url) == 0) {
3231  /*
3232  * decide if this is a GET or POST request and let the
3233  * related routine handle the checking
3234  */
3235  if (body == NULL)
3236  answer = smsbox_req_sendsms(args, ip, &status, client);
3237  else
3238  answer = smsbox_sendsms_post(hdrs, body, ip, &status, client);
3239  }
3240  /* XML-RPC */
3241  else if (octstr_compare(url, xmlrpc_url) == 0) {
3242  /*
3243  * XML-RPC request needs to have a POST body
3244  */
3245  if (body == NULL) {
3246  answer = octstr_create("Incomplete request.");
3248  } else
3249  answer = smsbox_xmlrpc_post(hdrs, body, ip, &status);
3250  }
3251  /* sendota */
3252  else if (octstr_compare(url, sendota_url) == 0) {
3253  if (body == NULL)
3254  answer = smsbox_req_sendota(args, ip, &status, client);
3255  else
3256  answer = smsbox_sendota_post(hdrs, body, ip, &status, client);
3257  }
3258  /* add aditional URI compares here */
3259  else {
3260  answer = octstr_create("Unknown request.");
3262  }
3263 
3264  debug("sms.http", 0, "Status: %d Answer: <%s>", status,
3265  octstr_get_cstr(answer));
3266 
3267  octstr_destroy(ip);
3269  http_destroy_headers(hdrs);
3270  octstr_destroy(body);
3271  http_destroy_cgiargs(args);
3272 
3275  else {
3276  debug("sms.http", 0, "Delayed reply - wait for bearerbox");
3277  }
3278  octstr_destroy(answer);
3279  }
3280 
3281 }
3282 
3283 
3284 /***********************************************************************
3285  * Main program. Configuration, signal handling, etc.
3286  */
3287 
3288 static void signal_handler(int signum) {
3289  /* On some implementations (i.e. linuxthreads), signals are delivered
3290  * to all threads. We only want to handle each signal once for the
3291  * entire box, and we let the gwthread wrapper take care of choosing
3292  * one.
3293  */
3294  if (!gwthread_shouldhandlesignal(signum))
3295  return;
3296 
3297  switch (signum) {
3298  case SIGINT:
3299  case SIGTERM:
3300  if (program_status != shutting_down) {
3301  error(0, "SIGINT received, aborting program...");
3303  }
3304  break;
3305 
3306  case SIGHUP:
3307  warning(0, "SIGHUP received, catching and re-opening logs");
3308  log_reopen();
3309  alog_reopen();
3310  break;
3311 
3312  /*
3313  * It would be more proper to use SIGUSR1 for this, but on some
3314  * platforms that's reserved by the pthread support.
3315  */
3316  case SIGQUIT:
3317  warning(0, "SIGQUIT received, reporting memory usage.");
3318  gw_check_leaks();
3319  break;
3320  }
3321 }
3322 
3323 
3324 static void setup_signal_handlers(void) {
3325  struct sigaction act;
3326 
3327  act.sa_handler = signal_handler;
3328  sigemptyset(&act.sa_mask);
3329  act.sa_flags = 0;
3330  sigaction(SIGINT, &act, NULL);
3331  sigaction(SIGTERM, &act, NULL);
3332  sigaction(SIGQUIT, &act, NULL);
3333  sigaction(SIGHUP, &act, NULL);
3334  sigaction(SIGPIPE, &act, NULL);
3335 }
3336 
3337 
3338 
3340 {
3341  CfgGroup *grp;
3342  Octstr *logfile;
3343  Octstr *p;
3344  long lvl, value;
3345  Octstr *http_proxy_host = NULL;
3346  long http_proxy_port = -1;
3347  int http_proxy_ssl = 0;
3348  List *http_proxy_exceptions = NULL;
3349  Octstr *http_proxy_username = NULL;
3350  Octstr *http_proxy_password = NULL;
3351  Octstr *http_proxy_exceptions_regex = NULL;
3352  int ssl = 0;
3353  int lf, m;
3354  long max_req;
3355 
3357  bb_ssl = 0;
3359  logfile = NULL;
3360  lvl = 0;
3361  lf = m = 1;
3362 
3363  /*
3364  * first we take the port number in bearerbox and other values from the
3365  * core group in configuration file
3366  */
3367 
3368  grp = cfg_get_single_group(cfg, octstr_imm("core"));
3369 
3370  cfg_get_integer(&bb_port, grp, octstr_imm("smsbox-port"));
3371 #ifdef HAVE_LIBSSL
3372  cfg_get_bool(&bb_ssl, grp, octstr_imm("smsbox-port-ssl"));
3373 #endif /* HAVE_LIBSSL */
3374 
3375  cfg_get_integer(&http_proxy_port, grp, octstr_imm("http-proxy-port"));
3376 #ifdef HAVE_LIBSSL
3377  cfg_get_bool(&http_proxy_ssl, grp, octstr_imm("http-proxy-ssl"));
3378 #endif /* HAVE_LIBSSL */
3379 
3380  http_proxy_host = cfg_get(grp,
3381  octstr_imm("http-proxy-host"));
3382  http_proxy_username = cfg_get(grp,
3383  octstr_imm("http-proxy-username"));
3384  http_proxy_password = cfg_get(grp,
3385  octstr_imm("http-proxy-password"));
3386  http_proxy_exceptions = cfg_get_list(grp,
3387  octstr_imm("http-proxy-exceptions"));
3388  http_proxy_exceptions_regex = cfg_get(grp,
3389  octstr_imm("http-proxy-exceptions-regex"));
3390 
3391 #ifdef HAVE_LIBSSL
3392  conn_config_ssl(grp);
3393 #endif
3394 
3395  /*
3396  * get the remaining values from the smsbox group
3397  */
3398  grp = cfg_get_single_group(cfg, octstr_imm("smsbox"));
3399  if (grp == NULL)
3400  panic(0, "No 'smsbox' group in configuration");
3401 
3402  smsbox_id = cfg_get(grp, octstr_imm("smsbox-id"));
3403 
3404  p = cfg_get(grp, octstr_imm("bearerbox-host"));
3405  if (p != NULL) {
3407  bb_host = p;
3408  }
3409  cfg_get_integer(&bb_port, grp, octstr_imm("bearerbox-port"));
3410 #ifdef HAVE_LIBSSL
3411  if (cfg_get_bool(&ssl, grp, octstr_imm("bearerbox-port-ssl")) != -1)
3412  bb_ssl = ssl;
3413 #endif /* HAVE_LIBSSL */
3414 
3415  cfg_get_bool(&mo_recode, grp, octstr_imm("mo-recode"));
3416  if(mo_recode < 0)
3417  mo_recode = 0;
3418 
3419  reply_couldnotfetch= cfg_get(grp, octstr_imm("reply-couldnotfetch"));
3420  if (reply_couldnotfetch == NULL)
3421  reply_couldnotfetch = octstr_create("Could not fetch content, sorry.");
3422 
3423  reply_couldnotrepresent= cfg_get(grp, octstr_imm("reply-couldnotfetch"));
3424  if (reply_couldnotrepresent == NULL)
3425  reply_couldnotrepresent = octstr_create("Result could not be represented "
3426  "as an SMS message.");
3427  reply_requestfailed= cfg_get(grp, octstr_imm("reply-requestfailed"));
3428  if (reply_requestfailed == NULL)
3429  reply_requestfailed = octstr_create("Request Failed");
3430 
3431  reply_emptymessage= cfg_get(grp, octstr_imm("reply-emptymessage"));
3432  if (reply_emptymessage == NULL)
3433  reply_emptymessage = octstr_create("<Empty reply from service provider>");
3434 
3435  {
3436  Octstr *os;
3437  os = cfg_get(grp, octstr_imm("white-list"));
3438  if (os != NULL) {
3440  octstr_destroy(os);
3441  }
3442 
3443  os = cfg_get(grp, octstr_imm("white-list-regex"));
3444  if (os != NULL) {
3445  if ((white_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
3446  panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
3447  octstr_destroy(os);
3448  }
3449 
3450  os = cfg_get(grp, octstr_imm("black-list"));
3451  if (os != NULL) {
3453  octstr_destroy(os);
3454  }
3455  os = cfg_get(grp, octstr_imm("black-list-regex"));
3456  if (os != NULL) {
3457  if ((black_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
3458  panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
3459  octstr_destroy(os);
3460  }
3461  }
3462 
3463  cfg_get_integer(&sendsms_port, grp, octstr_imm("sendsms-port"));
3464 
3465  /* check if want to bind to a specific interface */
3466  sendsms_interface = cfg_get(grp, octstr_imm("sendsms-interface"));
3467 
3468  cfg_get_integer(&sms_max_length, grp, octstr_imm("sms-length"));
3469 
3470 #ifdef HAVE_LIBSSL
3471  cfg_get_bool(&ssl, grp, octstr_imm("sendsms-port-ssl"));
3472 #endif /* HAVE_LIBSSL */
3473 
3474  /*
3475  * load the configuration settings for the sendsms and sendota URIs
3476  * else assume the default URIs, st.
3477  */
3478  if ((sendsms_url = cfg_get(grp, octstr_imm("sendsms-url"))) == NULL)
3479  sendsms_url = octstr_imm("/cgi-bin/sendsms");
3480  if ((xmlrpc_url = cfg_get(grp, octstr_imm("xmlrpc-url"))) == NULL)
3481  xmlrpc_url = octstr_imm("/cgi-bin/xmlrpc");
3482  if ((sendota_url = cfg_get(grp, octstr_imm("sendota-url"))) == NULL)
3483  sendota_url = octstr_imm("/cgi-bin/sendota");
3484 
3485  global_sender = cfg_get(grp, octstr_imm("global-sender"));
3486  accepted_chars = cfg_get(grp, octstr_imm("sendsms-chars"));
3489  logfile = cfg_get(grp, octstr_imm("log-file"));
3490 
3491  cfg_get_integer(&lvl, grp, octstr_imm("log-level"));
3492 
3493  if (logfile != NULL) {
3494  info(0, "Starting to log to file %s level %ld",
3495  octstr_get_cstr(logfile), lvl);
3496  log_open(octstr_get_cstr(logfile), lvl, GW_NON_EXCL);
3497  octstr_destroy(logfile);
3498  }
3499  if ((p = cfg_get(grp, octstr_imm("syslog-level"))) != NULL) {
3500  long level;
3501  Octstr *facility;
3502  if ((facility = cfg_get(grp, octstr_imm("syslog-facility"))) != NULL) {
3504  octstr_destroy(facility);
3505  }
3506  if (octstr_compare(p, octstr_imm("none")) == 0) {
3507  log_set_syslog(NULL, 0);
3508  } else if (octstr_parse_long(&level, p, 0, 10) > 0) {
3509  log_set_syslog("smsbox", level);
3510  }
3511  octstr_destroy(p);
3512  } else {
3513  log_set_syslog(NULL, 0);
3514  }
3515  if (global_sender != NULL) {
3516  info(0, "Service global sender set as '%s'",
3518  }
3519 
3520  /* should smsbox reply to sendsms immediate or wait for bearerbox ack */
3521  cfg_get_bool(&immediate_sendsms_reply, grp, octstr_imm("immediate-sendsms-reply"));
3522 
3523  /* determine which timezone we use for access logging */
3524  if ((p = cfg_get(grp, octstr_imm("access-log-time"))) != NULL) {
3525  lf = (octstr_case_compare(p, octstr_imm("gmt")) == 0) ? 0 : 1;
3526  octstr_destroy(p);
3527  }
3528 
3529  /* should predefined markers be used, ie. prefixing timestamp */
3530  cfg_get_bool(&m, grp, octstr_imm("access-log-clean"));
3531 
3532  /* open access-log file */
3533  if ((p = cfg_get(grp, octstr_imm("access-log"))) != NULL) {
3534  info(0, "Logging accesses to '%s'.", octstr_get_cstr(p));
3535  alog_open(octstr_get_cstr(p), lf, m ? 0 : 1);
3536  octstr_destroy(p);
3537  }
3538 
3539  /* HTTP queueing values */
3540  cfg_get_integer(&max_http_retries, grp, octstr_imm("http-request-retry"));
3541  cfg_get_integer(&http_queue_delay, grp, octstr_imm("http-queue-delay"));
3542 
3543  if (sendsms_port > 0) {
3545  if (only_try_http)
3546  error(0, "Failed to open HTTP socket, ignoring it");
3547  else
3548  panic(0, "Failed to open HTTP socket");
3549  } else {
3550  info(0, "Set up send sms service at port %ld", sendsms_port);
3552  }
3553  }
3554 
3555  /* set maximum allowed MO/DLR requests in parallel */
3556  if (cfg_get_integer(&max_req, grp, octstr_imm("max-pending-requests")) == -1)
3557  max_req = HTTP_MAX_PENDING;
3559 
3560  if (cfg_get_integer(&value, grp, octstr_imm("http-timeout")) == 0)
3561  http_set_client_timeout(value);
3562 
3563  /*
3564  * Reading the name we are using for ppg services from ppg core group
3565  */
3566  if ((grp = cfg_get_single_group(cfg, octstr_imm("ppg"))) != NULL) {
3567  if ((ppg_service_name = cfg_get(grp, octstr_imm("service-name"))) == NULL)
3569  }
3570 
3571  if (http_proxy_host != NULL && http_proxy_port > 0) {
3572  http_use_proxy(http_proxy_host, http_proxy_port, http_proxy_ssl,
3573  http_proxy_exceptions, http_proxy_username,
3574  http_proxy_password, http_proxy_exceptions_regex);
3575  }
3576 
3577  octstr_destroy(http_proxy_host);
3578  octstr_destroy(http_proxy_username);
3579  octstr_destroy(http_proxy_password);
3580  octstr_destroy(http_proxy_exceptions_regex);
3581  gwlist_destroy(http_proxy_exceptions, octstr_destroy_item);
3582 
3583  return cfg;
3584 }
3585 
3586 
3587 static int check_args(int i, int argc, char **argv) {
3588  if (strcmp(argv[i], "-H")==0 || strcmp(argv[i], "--tryhttp")==0) {
3589  only_try_http = 1;
3590  } else
3591  return -1;
3592 
3593  return 0;
3594 }
3595 
3596 
3597 int main(int argc, char **argv)
3598 {
3599  int cf_index;
3600  Octstr *filename;
3601  double heartbeat_freq = DEFAULT_HEARTBEAT;
3602 
3603  gwlib_init();
3604  cf_index = get_and_set_debugs(argc, argv, check_args);
3605 
3607 
3608  if (argv[cf_index] == NULL)
3609  filename = octstr_create("kannel.conf");
3610  else
3611  filename = octstr_create(argv[cf_index]);
3612  cfg = cfg_create(filename);
3613 
3614  if (cfg_read(cfg) == -1)
3615  panic(0, "Couldn't read configuration from `%s'.", octstr_get_cstr(filename));
3616 
3618 
3619  report_versions("smsbox");
3620 
3621  init_smsbox(cfg);
3622 
3623  if (max_http_retries > 0) {
3624  info(0, "Using HTTP request queueing with %ld retries, %lds delay.",
3626  }
3627 
3628  debug("sms", 0, "----------------------------------------------");
3629  debug("sms", 0, GW_NAME " smsbox version %s starting", GW_VERSION);
3630 
3632  if (translations == NULL)
3633  panic(0, "urltrans_create failed");
3634  if (urltrans_add_cfg(translations, cfg) == -1)
3635  panic(0, "urltrans_add_cfg failed");
3636 
3637  client_dict = dict_create(32, NULL);
3639  http_header_add(sendsms_reply_hdrs, "Content-type", "text/html");
3640  http_header_add(sendsms_reply_hdrs, "Pragma", "no-cache");
3641  http_header_add(sendsms_reply_hdrs, "Cache-Control", "no-cache");
3642 
3643 
3655 
3656  connect_to_bearerbox(bb_host, bb_port, bb_ssl, NULL /* bb_our_host */);
3657  /* XXX add our_host if required */
3658 
3659  if (0 > heartbeat_start(write_to_bearerbox, heartbeat_freq,
3661  info(0, GW_NAME "Could not start heartbeat.");
3662  }
3663 
3666 
3667  info(0, GW_NAME " smsbox terminating.");
3668 
3678 
3680  alog_close();
3705  if (white_list_regex != NULL) gw_regex_destroy(white_list_regex);
3706  if (black_list_regex != NULL) gw_regex_destroy(black_list_regex);
3708  cfg_destroy(cfg);
3709 
3712 
3713  /*
3714  * Just sleep for a while to get bearerbox chance to restart.
3715  * Otherwise we will fail while trying to connect to bearerbox!
3716  */
3717  if (restart) {
3718  gwthread_sleep(10.0);
3719  /* now really restart */
3720  restart_box(argv);
3721  }
3722 
3723  log_close_all();
3724  gwlib_shutdown();
3725 
3726  return 0;
3727 }
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
Definition: dict.c:192
int urltrans_add_cfg(URLTranslationList *trans, Cfg *cfg)
Definition: urltrans.c:230
static Octstr * dlr_mask
Definition: test_ppg.c:106
static void get_x_kannel_from_xml(int requesttype, Octstr **type, Octstr **body, List *headers, Octstr **from, Octstr **to, Octstr **udh, Octstr **user, Octstr **pass, Octstr **smsc, int *mclass, int *mwi, int *coding, int *compress, int *validity, int *deferred, int *dlr_mask, Octstr **dlr_url, Octstr **account, int *pid, int *alt_dcs, int *rpi, List **tolist, Octstr **charset, Octstr **binfo, int *priority, Octstr **meta_data)
Definition: smsbox.c:655
void gw_timerset_destroy(Timerset *set)
Definition: gw-timer.c:203
void msg_dump(Msg *msg, int level)
Definition: msg.c:152
List * http_headers
Definition: smsbox.c:451
regex_t * urltrans_black_list_regex(URLTranslation *t)
Definition: urltrans.c:940
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
Octstr * urltrans_deny_ip(URLTranslation *t)
Definition: urltrans.c:890
#define OCTSTR_APPEND_XML(xml, tag, text)
URLTranslation * urltrans_find(URLTranslationList *trans, Msg *msg)
Definition: urltrans.c:257
Octstr * urltrans_suffix(URLTranslation *t)
Definition: urltrans.c:805
#define MAX_SMS_OCTETS
Definition: sms.h:129
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
static URLTranslation * default_authorise_user(List *list, Octstr *client_ip)
Definition: smsbox.c:2480
#define OCTSTR_APPEND_XML_NUMBER(xml, tag, value)
Octstr * urltrans_forced_smsc(URLTranslation *t)
Definition: urltrans.c:875
int size
Definition: wsasm.c:84
void http_header_get(List *headers, long i, Octstr **name, Octstr **value)
Definition: http.c:2902
int octstr_str_case_compare(const Octstr *ostr, const char *str)
Definition: octstr.c:986
long octstr_search_chars(const Octstr *ostr, const Octstr *chars, long pos)
Definition: octstr.c:1052
Octstr * urltrans_alt_charset(URLTranslation *t)
Definition: urltrans.c:855
static Octstr * reply_requestfailed
Definition: smsbox.c:133
static int coding
Definition: mtbatch.c:102
static Octstr * smsbox_req_handle(URLTranslation *t, Octstr *client_ip, HTTPClient *client, Octstr *from, Octstr *to, Octstr *text, Octstr *charset, Octstr *udh, Octstr *smsc, int mclass, int mwi, int coding, int compress, int validity, int deferred, int *status, int dlr_mask, Octstr *dlr_url, Octstr *account, int pid, int alt_dcs, int rpi, List *receiver, Octstr *binfo, int priority, Octstr *meta_data)
Definition: smsbox.c:1965
Numhash * urltrans_black_list(URLTranslation *t)
Definition: urltrans.c:935
int urltrans_forced_priority(URLTranslation *t)
Definition: urltrans.c:975
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2886
static Octstr * method_name
Definition: test_http.c:86
regex_t * urltrans_white_list_regex(URLTranslation *t)
Definition: urltrans.c:930
gw_assert(wtls_machine->packet_to_send !=NULL)
int ssl
Octstr * urltrans_footer(URLTranslation *t)
Definition: urltrans.c:850
void http_caller_signal_shutdown(HTTPCaller *caller)
Definition: http.c:913
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
void counter_destroy(Counter *counter)
Definition: counter.c:110
static void obey_request_thread(void *arg)
Definition: smsbox.c:1659
void gwlist_append(List *list, void *item)
Definition: list.c:179
static void strip_prefix_and_suffix(Octstr *html, Octstr *prefix, Octstr *suffix)
Definition: smsbox.c:526
Octstr * urltrans_default_smsc(URLTranslation *t)
Definition: urltrans.c:880
Octstr * urltrans_password(URLTranslation *t)
Definition: urltrans.c:870
#define XPATH_SEARCH_OCTSTR(path, var, nostrip)
void semaphore_destroy(Semaphore *semaphore)
Definition: gw-semaphore.c:104
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1504
struct tm gw_gmtime(time_t t)
Definition: protected.c:137
Definition: msg.h:109
List * cfg_get_list(CfgGroup *grp, Octstr *varname)
Definition: cfg.c:790
void log_reopen(void)
Definition: log.c:297
static void read_messages_from_bearerbox(void)
Definition: smsbox.c:242
void gwlist_produce(List *list, void *item)
Definition: list.c:411
static long sms_max_length
Definition: smsbox.c:128
static long max_http_retries
Definition: smsbox.c:140
long gwlist_len(List *list)
Definition: list.c:166
int restart_box(char **argv)
Definition: shared.c:279
int octstr_recode(Octstr *tocode, Octstr *fromcode, Octstr *orig)
Definition: octstr.c:2576
static void client(int port)
Definition: test_udp.c:77
Octstr * octstr_read_pipe(FILE *f)
Definition: octstr.c:1580
program_status
Definition: shared.h:79
static HTTPCaller * caller
Definition: smsbox.c:442
Octstr * urltrans_allowed_prefix(URLTranslation *t)
Definition: urltrans.c:895
void * gwlist_get(List *list, long pos)
Definition: list.c:292
Octstr * urltrans_split_chars(URLTranslation *t)
Definition: urltrans.c:830
Timer * gw_timer_create(Timerset *set, List *outputlist, void(*callback)(void *))
Definition: gw-timer.c:255
Octstr * urltrans_faked_sender(URLTranslation *t)
Definition: urltrans.c:815
void * id
Definition: smsbox.c:109
static Octstr * sendota_url
Definition: smsbox.c:122
static Octstr * smsbox_req_sendsms(List *args, Octstr *client_ip, int *status, HTTPClient *client)
Definition: smsbox.c:2517
int read_from_bearerbox(Msg **msg, double seconds)
Definition: shared.c:220
static void sendsms_thread(void *arg)
Definition: smsbox.c:3205
#define ACCOUNT_MAX_LEN
Definition: smsbox.c:99
int octstr_url_decode(Octstr *ostr)
Definition: octstr.c:1746
#define BB_DEFAULT_HOST
Definition: bb.h:67
msg_type
Definition: msg.h:73
static Octstr * sendsms_url
Definition: smsbox.c:121
Octstr * url
Definition: smsbox.c:450
int type
Definition: smsc_cimd2.c:215
static Dict * client_dict
Definition: smsbox.c:159
#define cfg_get(grp, varname)
Definition: cfg.h:86
static List * smsbox_requests
Definition: smsbox.c:144
#define DC_8BIT
Definition: sms.h:111
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
regex_t * urltrans_denied_prefix_regex(URLTranslation *t)
Definition: urltrans.c:910
Octstr * urltrans_dlr_url(URLTranslation *t)
Definition: urltrans.c:965
void http_header_get_content_type(List *headers, Octstr **type, Octstr **charset)
Definition: http.c:3225
static void delayed_http_reply(Msg *msg)
Definition: smsbox.c:185
int method
Definition: smsbox.c:449
static Octstr * smsbox_xmlrpc_post(List *headers, Octstr *body, Octstr *client_ip, int *status)
Definition: smsbox.c:2756
Octstr * urltrans_username(URLTranslation *t)
Definition: urltrans.c:865
#define msg_create(type)
Definition: msg.h:136
static void setup_signal_handlers(void)
Definition: smsbox.c:3324
unsigned long counter_decrease(Counter *counter)
Definition: counter.c:155
int gwthread_shouldhandlesignal(int signal)
void numhash_destroy(Numhash *table)
Definition: numhash.c:275
static long outstanding_requests(void)
Definition: smsbox.c:515
Octstr * urltrans_denied_prefix(URLTranslation *t)
Definition: urltrans.c:905
void octstr_strip_blanks(Octstr *text)
Definition: octstr.c:1346
static Octstr * smsbox_sendota_post(List *headers, Octstr *body, Octstr *client_ip, int *status, HTTPClient *client)
Definition: smsbox.c:3015
static regex_t * black_list_regex
Definition: smsbox.c:139
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
List * sms_split(Msg *orig, Octstr *header, Octstr *footer, Octstr *nonlast_suffix, Octstr *split_chars, int catenate, unsigned long msg_sequence, int max_messages, int max_octets)
Definition: sms.c:309
int xmlrpc_parse_status(XMLRPCDocument *xrdoc)
Definition: xmlrpc.c:1348
void gwthread_join_every(gwthread_func_t *func)
static URLTranslation * authorise_username(Octstr *username, Octstr *password, Octstr *client_ip)
Definition: smsbox.c:2447
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
Octstr * charset
Definition: test_ota.c:68
Msg * msg
Definition: smsbox.c:447
static Octstr * smsbox_id
Definition: smsbox.c:120
static struct pid_list * found
static Octstr * sendsms_interface
Definition: smsbox.c:119
int is_allowed_ip(Octstr *allow_ip, Octstr *deny_ip, Octstr *ip)
Definition: utils.c:815
Cfg * cfg_create(Octstr *filename)
Definition: cfg.c:318
Numhash * numhash_create(const char *seek_url)
Definition: numhash.c:313
unsigned char * username
Definition: test_cimd2.c:99
Octstr * http_cgi_variable(List *list, char *name)
Definition: http.c:2836
void heartbeat_stop(long hb_thread)
Definition: heartbeat.c:160
static long http_queue_delay
Definition: smsbox.c:141
int cfg_read(Cfg *cfg)
Definition: cfg.c:452
void semaphore_down(Semaphore *semaphore)
Definition: gw-semaphore.c:132
regex_t * urltrans_allowed_prefix_regex(URLTranslation *t)
Definition: urltrans.c:900
void http_destroy_headers(List *headers)
Definition: http.c:2879
static Octstr * reply_couldnotfetch
Definition: smsbox.c:131
Timerset * gw_timerset_create(void)
Definition: gw-timer.c:190
static Octstr * from
Definition: mtbatch.c:95
Octstr * urltrans_header(URLTranslation *t)
Definition: urltrans.c:845
Definition: msg.h:108
void http_start_request(HTTPCaller *caller, int method, Octstr *url, List *headers, Octstr *body, int follow, void *id, Octstr *certkeyfile)
Definition: http.c:1760
void http_destroy_cgiargs(List *args)
Definition: http.c:2818
#define xmlrpc_parse_call(post_body)
Definition: xmlrpc.h:161
#define INFINITE_TIME
Definition: shared.h:73
unsigned char * password
Definition: test_cimd2.c:100
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Definition: http.c:2695
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
static Octstr * smsbox_sendsms_post(List *headers, Octstr *body, Octstr *client_ip, int *status, HTTPClient *client)
Definition: smsbox.c:2630
Definition: http.h:142
Definition: msg.h:79
void log_close_all(void)
Definition: log.c:341
Definition: cfg.c:164
static Octstr * accepted_chars
Definition: smsbox.c:125
void * dict_remove(Dict *dict, Octstr *key)
Definition: dict.c:307
int does_prefix_match(Octstr *prefix, Octstr *number)
Definition: utils.c:850
int numhash_find_number(Numhash *table, Octstr *nro)
Definition: numhash.c:218
Counter * counter_create(void)
Definition: counter.c:94
static int check_args(int i, int argc, char **argv)
Definition: smsbox.c:3587
void cfg_destroy(Cfg *cfg)
Definition: cfg.c:331
static regex_t * white_list_regex
Definition: smsbox.c:138
int urltrans_dlr_mask(URLTranslation *t)
Definition: urltrans.c:970
void * gwlist_extract_first(List *list)
Definition: list.c:305
static Cfg * init_smsbox(Cfg *cfg)
Definition: smsbox.c:3339
static Octstr * dlr_url
Definition: test_ppg.c:107
static URLTranslationList * translations
Definition: smsbox.c:127
void conn_config_ssl(CfgGroup *grp)
Definition: conn.c:1546
HTTPClient * http_accept_request(int port, Octstr **client_ip, Octstr **url, List **headers, Octstr **body, List **cgivars)
Definition: http.c:2571
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1527
void gwlist_remove_producer(List *list)
Definition: list.c:401
#define HTTP_MAX_RETRIES
Definition: smsbox.c:102
static Octstr * bb_host
Definition: smsbox.c:124
char * text
Definition: smsc_cimd2.c:921
static int send_message(URLTranslation *trans, Msg *msg)
Definition: smsbox.c:315
List * http_create_empty_headers(void)
Definition: http.c:2872
void connect_to_bearerbox(Octstr *host, int port, int ssl, Octstr *our_host)
Definition: shared.c:108
static long retries
Definition: test_ppg.c:116
static Octstr * xmlrpc_url
Definition: smsbox.c:123
static int mo_recode
Definition: smsbox.c:135
static Semaphore * max_pending_requests
Definition: smsbox.c:151
static void fill_message(Msg *msg, URLTranslation *trans, Octstr *replytext, Octstr *from, Octstr *to, Octstr *udh, int mclass, int mwi, int coding, int compress, int validity, int deferred, Octstr *dlr_url, int dlr_mask, int pid, int alt_dcs, int rpi, Octstr *smsc, Octstr *account, Octstr *charset, Octstr *binfo, int priority, Octstr *meta_data)
Definition: smsbox.c:840
static Timerset * timerset
Definition: smsbox.c:148
Definition: dict.c:116
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
long octstr_case_search(const Octstr *haystack, const Octstr *needle, long pos)
Definition: octstr.c:1102
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:645
#define SENDSMS_DEFAULT_CHARS
Definition: smsbox.c:95
static Octstr * deny_ip
Definition: bb_udp.c:112
static Octstr * reply_couldnotrepresent
Definition: smsbox.c:132
int octstr_item_match(void *item, void *pattern)
Definition: octstr.c:1661
void uuid_copy(uuid_t dst, const uuid_t src)
Definition: gw_uuid.c:150
void msg_destroy(Msg *msg)
Definition: msg.c:132
char * name
Definition: smsc_cimd2.c:212
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
Definition: octstr.c:903
#define HTTP_RETRY_DELAY
Definition: smsbox.c:103
#define HTTP_MAX_PENDING
Definition: smsbox.c:104
void warning(int err, const char *fmt,...)
Definition: log.c:660
List * octstr_split_words(const Octstr *ostr)
Definition: octstr.c:1602
Octstr * urltrans_default_sender(URLTranslation *t)
Definition: urltrans.c:810
void log_set_syslog_facility(char *facility)
Definition: log.c:278
Octstr * xmlrpc_get_call_name(XMLRPCDocument *call)
Definition: xmlrpc.c:1056
URLTranslation * trans
Definition: smsbox.c:448
void alog_open(char *fname, int use_localtm, int use_markers)
Definition: accesslog.c:129
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
volatile sig_atomic_t restart
Definition: smsbox.c:113
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
int urltrans_omit_empty(URLTranslation *t)
Definition: urltrans.c:840
char filename[FILENAME_MAX+1]
Definition: log.c:171
#define gwthread_create(func, arg)
Definition: gwthread.h:90
static List * sendsms_reply_hdrs
Definition: smsbox.c:160
int sms_charset_processing(Octstr *charset, Octstr *body, int coding)
Definition: sms.c:419
static int method
Definition: test_http.c:76
#define octstr_create(cstr)
Definition: octstr.h:125
void octstr_destroy_item(void *os)
Definition: octstr.c:336
Octstr * html_to_sms(Octstr *html)
Definition: html.c:283
#define O_DESTROY(a)
Definition: smsbox.c:97
Octstr * urltrans_split_suffix(URLTranslation *t)
Definition: urltrans.c:835
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
void gwthread_sleep(double seconds)
void log_set_syslog(const char *ident, int syslog_level)
Definition: log.c:284
Octstr * body
Definition: smsbox.c:452
unsigned long retries
Definition: smsbox.c:453
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
int urltrans_send_sender(URLTranslation *t)
Definition: urltrans.c:960
int urltrans_type(URLTranslation *t)
Definition: urltrans.c:795
static Octstr * allow_ip
Definition: bb_udp.c:111
Timer * timer
Definition: smsbox.c:108
static Counter * num_outstanding_requests
Definition: smsbox.c:443
int urltrans_accept_x_kannel_headers(URLTranslation *t)
Definition: urltrans.c:950
static Octstr * ppg_service_name
Definition: smsbox.c:142
static Numhash * black_list
Definition: smsbox.c:137
#define UUID_STR_LEN
Definition: gw_uuid.h:19
#define ALL_HEARTBEATS
Definition: heartbeat.h:68
static URLTranslation * authorise_user(List *list, Octstr *client_ip)
Definition: smsbox.c:2494
#define http_receive_result(caller, status, final_url, headers, body)
Definition: http.h:394
void gw_timer_elapsed_destroy(Timer *timer)
Definition: gw-timer.c:284
Octstr * octstr_read_file(const char *filename)
Definition: octstr.c:1548
void close_connection_to_bearerbox(void)
Definition: shared.c:122
void alog_reopen(void)
Definition: accesslog.c:85
Numhash * urltrans_white_list(URLTranslation *t)
Definition: urltrans.c:925
Octstr * urltrans_allow_ip(URLTranslation *t)
Definition: urltrans.c:885
int http_open_port_if(int port, int ssl, Octstr *interface)
Definition: http.c:2483
void report_versions(const char *boxname)
Definition: utils.c:539
int log_open(char *filename, int level, enum excl_state excl)
Definition: log.c:375
void semaphore_up(Semaphore *semaphore)
Definition: gw-semaphore.c:118
static Cfg * cfg
Definition: smsbox.c:115
void http_close_all_ports(void)
Definition: http.c:2526
static Numhash * white_list
Definition: smsbox.c:136
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
struct TimerItem TimerItem
void dict_destroy(Dict *dict)
Definition: dict.c:215
#define XPATH_SEARCH_NUMBER(path, var)
long gwlist_delete_matching(List *list, void *pat, gwlist_item_matches_t *matches)
Definition: list.c:240
void gwlist_append_unique(List *list, void *item, int(*cmp)(void *, void *))
Definition: list.c:190
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:759
#define DEFAULT_HEARTBEAT
Definition: heartbeat.h:67
static Octstr * reply_emptymessage
Definition: smsbox.c:134
void write_to_bearerbox(Msg *pmsg)
Definition: shared.c:142
Definition: octstr.c:118
long heartbeat_start(hb_send_func_t *send_func, double freq, hb_load_func_t *load_func)
Definition: heartbeat.c:126
URLTranslationList * urltrans_create(void)
Definition: urltrans.c:184
void * gwlist_consume(List *list)
Definition: list.c:427
static Octstr * store_uuid(Msg *msg)
Definition: smsbox.c:1944
void alog(const char *fmt,...)
Definition: accesslog.c:206
static void signal_handler(int signum)
Definition: smsbox.c:3288
void http_use_proxy(Octstr *hostname, int port, int ssl, List *exceptions, Octstr *username, Octstr *password, Octstr *exceptions_regex)
Definition: http.c:268
URLTranslation * urltrans_find_service(URLTranslationList *trans, Msg *msg)
Definition: urltrans.c:270
URLTranslation * urltrans_find_username(URLTranslationList *trans, Octstr *name)
Definition: urltrans.c:286
#define xmlrpc_destroy_call(call)
Definition: xmlrpc.h:165
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:742
int sms_swap(Msg *msg)
Definition: sms.c:201
void gw_timer_elapsed_start(Timer *timer, int interval, void *data)
Definition: gw-timer.c:352
#define panic
Definition: log.h:87
static long sendsms_port
Definition: smsbox.c:118
static Octstr * smsbox_req_sendota(List *list, Octstr *client_ip, int *status, HTTPClient *client)
Definition: smsbox.c:2825
Definition: cfg.c:73
int octstr_hex_to_binary(Octstr *ostr)
Definition: octstr.c:494
int urltrans_max_messages(URLTranslation *t)
Definition: urltrans.c:820
static int immediate_sendsms_reply
Definition: smsbox.c:158
static long bb_port
Definition: smsbox.c:116
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
Definition: octstr.c:749
HTTPCaller * http_caller_create(void)
Definition: http.c:897
void alog_close(void)
Definition: accesslog.c:111
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2507
void gwlib_shutdown(void)
Definition: gwlib.c:94
List * http_header_duplicate(List *headers)
Definition: http.c:2969
static List * smsbox_http_requests
Definition: smsbox.c:145
Msg * ota_tokenize_settings(CfgGroup *grp, Octstr *from, Octstr *receiver)
Definition: ota_prov.c:259
#define gwlist_create()
Definition: list.h:136
static void get_x_kannel_from_headers(List *headers, Octstr **from, Octstr **to, Octstr **udh, Octstr **user, Octstr **pass, Octstr **smsc, int *mclass, int *mwi, int *coding, int *compress, int *validity, int *deferred, int *dlr_mask, Octstr **dlr_url, Octstr **account, int *pid, int *alt_dcs, int *rpi, Octstr **binfo, int *priority, Octstr **meta_data)
Definition: smsbox.c:545
void octstr_truncate(Octstr *ostr, int new_len)
Definition: octstr.c:1327
static Counter * catenated_sms_counter
Definition: smsbox.c:307
void http_caller_destroy(HTTPCaller *caller)
Definition: http.c:907
Msg * ota_tokenize_bookmarks(CfgGroup *grp, Octstr *from, Octstr *receiver)
Definition: ota_prov.c:540
void gwlib_init(void)
Definition: gwlib.c:78
#define DC_UNDEF
Definition: sms.h:109
static void url_result_thread(void *arg)
Definition: smsbox.c:1064
Definition: msg.h:107
Octstr * urltrans_prefix(URLTranslation *t)
Definition: urltrans.c:800
static void identify_to_bearerbox(void)
Definition: smsbox.c:172
void urltrans_destroy(URLTranslationList *trans)
Definition: urltrans.c:196
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:639
static void http_queue_thread(void *arg)
Definition: smsbox.c:1015
void gwlist_add_producer(List *list)
Definition: list.c:383
#define BB_DEFAULT_SMSBOX_PORT
Definition: bb.h:68
void http_set_client_timeout(long timeout)
Definition: http.c:1751
static Octstr * url
Definition: test_xmlrpc.c:84
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406
static void * remember_receiver(Msg *msg, URLTranslation *trans, int method, Octstr *url, List *headers, Octstr *body, unsigned int retries)
Definition: smsbox.c:459
int get_and_set_debugs(int argc, char **argv, int(*find_own)(int index, int argc, char **argv))
Definition: utils.c:626
#define DLR_IS_ENABLED(dlr)
Definition: dlr.h:81
static int bb_ssl
Definition: smsbox.c:117
static int only_try_http
Definition: smsbox.c:126
int urltrans_max_priority(URLTranslation *t)
Definition: urltrans.c:980
Octstr * urltrans_name(URLTranslation *t)
Definition: urltrans.c:860
Semaphore * semaphore_create(long n)
Definition: gw-semaphore.c:81
static char * sendsms_number_chars
Definition: smsbox.c:129
Definition: list.c:102
static Octstr * alt_charset
Definition: opensmppbox.c:129
static Octstr * lf
Definition: smsc_smasi.c:222
static Octstr * account
Definition: mtbatch.c:94
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
Octstr * urltrans_get_pattern(URLTranslation *t, Msg *request)
Definition: urltrans.c:756
#define OCTSTR_APPEND_XML_OCTSTR(xml, tag, text)
static int start
static int obey_request(Octstr **result, URLTranslation *trans, Msg *msg)
Definition: smsbox.c:1241
Octstr * xmlrpc_parse_error(XMLRPCDocument *xrdoc)
Definition: xmlrpc.c:1356
int urltrans_concatenation(URLTranslation *t)
Definition: urltrans.c:825
int ota_pack_message(Msg **msg, Octstr *ota_doc, Octstr *doc_type, Octstr *from, Octstr *phone_number, Octstr *sec, Octstr *pin)
Definition: ota_prov.c:207
void octstr_url_encode(Octstr *ostr)
Definition: octstr.c:1673
static void get_receiver(void *id, Msg **msg, URLTranslation **trans, int *method, Octstr **url, List **headers, Octstr **body, unsigned long *retries)
Definition: smsbox.c:496
static Octstr * global_sender
Definition: smsbox.c:130
#define DC_UCS2
Definition: sms.h:112
static Octstr * meta_data
Definition: mtbatch.c:101
static void reply(HTTPClient *c, List *push_headers)
int charset_convert(Octstr *string, char *charset_from, char *charset_to)
Definition: charset.c:589
#define DC_7BIT
Definition: sms.h:110
int main(int argc, char **argv)
Definition: smsbox.c:3597
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.