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