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