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