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  * wap_push_ppg.c: General logic of a push proxy gateway.
59  *
60  * This module implements following WAP Forum specifications:
61  *      WAP-151-PPGService-19990816-a (called afterwards PPG),
62  *      WAP-164-PAP-19991108-a (PAP),
63  *      WAP-164_100-PAP-20000218-a (PAP implementation note).
64  *
65  * We refer following WAP Forum specifications:
66  *      WAP-145-PushMessage-19990816-a (push message)
67  *      WAP-200-WDP-20001212-a (WDP)
68  *      WAP-203-WSP-20000504-a (WSP)
69  *      WAP-189-PushOTA-20000217-a (OTA).
70  *
71  * In addition, RFCs 1521 and 2045 are referred.
72  *
73  * By Aarno Syv�nen for Wapit Ltd, Wiral Ltd and Global Networks Inc.
74  */
75 
76 #include <time.h>
77 #include <ctype.h>
78 
79 #include "wap_push_ppg.h"
80 #include "wap/wap_events.h"
81 #include "wap/wsp_caps.h"
82 #include "wml_compiler.h"
83 #include "wap-appl.h"
84 #include "wap/wsp.h"
85 #include "wap/wsp_strings.h"
86 #include "wap_push_si_compiler.h"
87 #include "wap_push_sl_compiler.h"
88 #include "wap_push_pap_compiler.h"
89 #include "wap_push_pap_mime.h"
90 #include "wap_push_ppg_pushuser.h"
91 
92 enum {
93     TIME_EXPIRED = 0,
94     TIME_TOO_EARLY = 1,
95     NO_CONSTRAINTS = 2
96 };
97 
98 /*
99  * Default values for configuration variables
100  */
101 enum {
102     DEFAULT_HTTP_PORT = 8080,
103     NO_HTTPS_PORT = -1,
104     DEFAULT_NUMBER_OF_PUSHES = 100,
105     PI_TRUSTED = 1,
106     SSL_CONNECTION_OFF = 0,
107     DEFAULT_NUMBER_OF_USERS = 1024,
108     USER_CONFIGURATION_NOT_ADDED = 0
109 };
110 
111 enum { USER_CONFIGURATION_ADDED = 1 };
112 
113 #define DEFAULT_PPG_URL "/wappush"
114 
115 /*****************************************************************************
116  *
117  * Internal data structures
118  *
119  * Give the status of the push ppg module:
120  *
121  *	limbo
122  *		not running at all
123  *	running
124  *		operating normally
125  *	terminating
126  *		waiting for operations to terminate, returning to limbo
127  */
128 static enum {limbo, running, terminating} run_status = limbo;
129 
130 /*
131  * The external event queue for this module
132  */
133 static List *ppg_queue = NULL;
134 
135 /*
136  * The internal event queue for this module (allowing listening of many ports)
137  */
138 static List *pap_queue = NULL;
139 
140 /*
141  * List of ppg session machines (it is, of currently active sessions)
142  */
143 static List *ppg_machines = NULL;
144 
145 /*
146  * List of currently active unit pushes (we need a threadsafe storage for them,
147  * because pushes can be cancelled and queried):
148  */
149 static List *ppg_unit_pushes = NULL;
150 
151 /*
152  * Counter to store our internal push id.
153  */
154 static Counter *push_id_counter = NULL;
155 
156 /*
157  * We need a mapping between HTTPClient structures, used by http library, and
158  * push ids, used by ppg.
159  */
160 static Dict *http_clients = NULL;
161 
162 /*
163  * Mapping between urls used by pi and push ids used by ppg.
164  */
165 static Dict *urls = NULL;
166 
167 /*
168  * Push content packed for compilers (wml, si, sl, co).
169  */
170 struct content {
171     Octstr *body;
172     Octstr *type;
173     Octstr *charset;
174 };
175 
176 static wap_dispatch_func_t *dispatch_to_ota;
177 static wap_dispatch_func_t *dispatch_to_appl;
178 
179 /*
180  * Configurable variables of ppg core group (for general configuration of a
181  * ppg), with some default values.
182  */
183 
184 static Octstr *ppg_url = NULL ;
185 static long ppg_port = DEFAULT_HTTP_PORT;
186 
187 #ifdef HAVE_LIBSSL
188 static long ppg_ssl_port = NO_HTTPS_PORT;
189 #endif
190 
191 static long number_of_pushes = DEFAULT_NUMBER_OF_PUSHES;
192 static int trusted_pi = PI_TRUSTED;
193 static long number_of_users = DEFAULT_NUMBER_OF_USERS;
194 static Octstr *ppg_deny_ip = NULL;
195 static Octstr *ppg_allow_ip = NULL;
196 static int user_configuration = USER_CONFIGURATION_NOT_ADDED;
197 static Octstr *global_sender = NULL;
198 static Octstr *ppg_default_smsc = NULL;
199 #ifdef HAVE_LIBSSL
200 static Octstr *ssl_server_cert_file = NULL;
201 static Octstr *ssl_server_key_file = NULL;
202 #endif
203 static Octstr *ppg_dlr_url = NULL;
204 static Octstr *ppg_smsbox_id = NULL;
205 static Octstr *service_name = NULL;
206 
207 struct PAPEvent {
208     HTTPClient *client;
209     Octstr *ip;
210     Octstr *url;
211     List *push_headers;
212     Octstr *mime_content;
213     List *cgivars;
214 };
215 
216 typedef struct PAPEvent PAPEvent;
217 
218 
219 /*****************************************************************************
220  *
221  * Prototypes of internal functions
222  *
223  * Event handling
224  */
225 static void ota_read_thread(void *arg);
226 static void http_read_thread(void *arg);
227 
228 #ifdef HAVE_LIBSSL
229 static void https_read_thread(void *arg);
230 #endif
231 
232 static void handle_internal_event(WAPEvent *e);
233 static void pap_request_thread(void *arg);
234 static int handle_push_message(HTTPClient **c, WAPEvent *ppg_event, int status);
235 static PAPEvent *pap_event_create(Octstr *ip, Octstr *url, List *push_headers,
236                                   Octstr *mime_content, List *cgivars,
237                                   HTTPClient *client);
238 static void pap_event_destroy(PAPEvent *p);
239 static void pap_event_destroy_item(void *p);
240 static void pap_event_unpack(PAPEvent *p, Octstr **ip, Octstr **url,
241                              List **push_headers, Octstr **mime_content,
242                              List **cgivars, HTTPClient **client);
243 
244 /*
245  * Constructors and destructors for machines.
246  */
247 static PPGSessionMachine *session_machine_create(WAPAddrTuple *tuple,
248                                                      WAPEvent *e);
249 static void session_machine_destroy(void *p);
250 static PPGPushMachine *push_machine_create(WAPEvent *e,
251     WAPAddrTuple *tuple);
252 static void push_machine_destroy(void *pm);
253 static void push_machines_list_destroy(List *pl);
254 
255 /*
256  * Communicating other modules (ota and appl)
257  */
258 static void create_session(WAPEvent *e, PPGPushMachine *pm);
259 static void request_confirmed_push(long last, PPGPushMachine *pm,
260                                    PPGSessionMachine *sm);
261 static void request_unit_push(long last, PPGPushMachine *pm);
262 static void request_push(long last, PPGPushMachine *sm);
263 static int response_push_connection(WAPEvent *e, PPGSessionMachine *sm);
264 static HTTPClient *response_push_message(PPGPushMachine *pm, long code,
265                                          int status);
266 
267 /*
268  * Functions to find machines using various identifiers, and related help
269  * functions.
270  */
271 static PPGSessionMachine *session_find_using_pi_client_address(Octstr *addr);
272 static PPGPushMachine *find_ppg_push_machine_using_pid(PPGSessionMachine *sm,
273                                                    long pid);
274 static PPGPushMachine *find_ppg_push_machine_using_pi_push_id(
275     PPGSessionMachine *sm, Octstr *pi_push_id);
276 static PPGPushMachine *find_unit_ppg_push_machine_using_pi_push_id(
277     Octstr *pi_push_id);
278 static int push_has_pi_push_id(void *a, void *b);
279 static int push_has_pid(void *a, void *b);
280 static int session_has_pi_client_address(void *a, void *b);
281 static int session_has_addr(void *a, void *b);
282 static int session_has_sid(void *a, void *b);
283 
284 /*
285  * Main logic of PPG.
286  */
287 static int check_capabilities(List *requested, List *assumed);
288 static int transform_message(WAPEvent **e, WAPAddrTuple **tuple,
289                              List *push_headers, int connected, Octstr **type);
290 static long check_x_wap_application_id_header(List **push_headers);
291 static int pap_convert_content(struct content *content);
292 static int pap_get_content(struct content *content);
293 static int select_bearer_network(WAPEvent **e);
294 static int delivery_time_constraints(WAPEvent *e, PPGPushMachine *pm);
295 static void deliver_confirmed_push(long last, PPGPushMachine *pm,
296                                    PPGSessionMachine *sm);
297 static PPGPushMachine *deliver_unit_push(long last, PPGPushMachine *pm,
298     PPGSessionMachine *sm, int session_exists);
299 static int store_push_data(PPGPushMachine **pm, PPGSessionMachine *sm,
300                            WAPEvent *e, WAPAddrTuple *tuple, int cless);
301 static PPGPushMachine *update_push_data_with_attribute(PPGSessionMachine **sm,
302     PPGPushMachine *pm, long reason, long status);
303 static void remove_push_data(PPGSessionMachine *sm, PPGPushMachine *pm,
304                              int cless);
305 static void remove_session_data(PPGSessionMachine *sm, int status);
306 static void remove_pushless_session(PPGSessionMachine *sm);
307 static PPGSessionMachine *store_session_data(PPGSessionMachine *sm,
308     WAPEvent *e, WAPAddrTuple *tuple, int *session_exists);
309 static PPGSessionMachine *update_session_data_with_headers(
310     PPGSessionMachine *sm, PPGPushMachine *pm);
311 static void deliver_pending_pushes(PPGSessionMachine *sm, int last);
312 static PPGPushMachine *abort_delivery(PPGSessionMachine *sm, int status);
313 static PPGSessionMachine *update_session_data(PPGSessionMachine *sm, long sid,
314                                               long port, List *caps);
315 static int confirmation_requested(WAPEvent *e);
316 static int cless_accepted(WAPEvent *e, PPGSessionMachine *sm);
317 
318 /*
319  * Header functions
320  */
321 static int headers_acceptable(List *push_headers, Octstr **content_header);
322 static int type_is(Octstr *content_header, char *required_type);
323 static int get_mime_boundary(List *push_headers, Octstr *content_header,
324                              Octstr **boundary);
325 static void change_header_value(List **push_headers, char *name, char *value);
326 static void remove_mime_headers(List **push_headers);
327 static void remove_link_headers(List **push_headers);
328 static void remove_x_kannel_headers(List **push_headers);
329 
330 /*
331  * Communicating with pi.
332  */
333 static void send_bad_message_response(HTTPClient **c, Octstr *body_fragment,
334                                       int code, int status);
335 static HTTPClient *send_push_response(WAPEvent *e, int status);
336 static void send_to_pi(HTTPClient **c, Octstr *reply_body, int status);
337 static void tell_fatal_error(HTTPClient **c, WAPEvent *e, Octstr *url,
338                              int status, int code);
339 
340 /*
341  * PPG core authentication (not related to any particular user).
342  */
343 static int read_ppg_config(Cfg *cfg);
344 static int ip_allowed_by_ppg(Octstr *ip);
345 
346 /*
347  * Interface to various compilers
348  */
349 static Octstr *convert_wml_to_wmlc(struct content *content);
350 static Octstr *convert_si_to_sic(struct content *content);
351 static Octstr *convert_sl_to_slc(struct content *content);
352 
353 /*
354  * Setting values for controlling sms level. (Pap control document enables
355  * some control, but not enough.)
356  */
357 
358 static Octstr *set_smsc_id(List *headers, Octstr *username, int trusted_pi);
359 static Octstr *set_dlr_url(List *headers, Octstr *username, int trusted_pi);
360 static long set_dlr_mask(List *headers, Octstr *dlr_url);
361 static Octstr *set_smsbox_id(List *headers, Octstr *username, int trusted_pi);
362 static Octstr *set_service_name(void);
363 
364 /*
365  * Various utility functions
366  */
367 static Octstr *set_time(void);
368 static int deliver_before_test_cleared(Octstr *before, struct tm now);
369 static int deliver_after_test_cleared(Octstr *after, struct tm now);
370 static void session_machine_assert(PPGSessionMachine *sm);
371 static void push_machine_assert(PPGPushMachine *pm);
372 static Octstr *tell_ppg_name(void);
373 static Octstr *describe_code(long code);
374 static long ota_abort_to_pap(long reason);
375 static int content_transformable(List *push_headers);
376 static WAPAddrTuple *set_addr_tuple(Octstr *address, long cliport, long servport,
377                                     long address_type, List *push_headers);
378 static WAPAddrTuple *addr_tuple_change_cliport(WAPAddrTuple *tuple, long port);
379 static void initialize_time_item_array(long time_data[], struct tm now);
380 static int date_item_compare(Octstr *before, long time_data, long pos);
381 static long parse_appid_header(Octstr **assigned_code);
382 static Octstr *escape_fragment(Octstr *fragment);
383 static int coriented_deliverable(long code);
384 static int is_phone_number(long type_of_address);
385 static void replace_octstr_char(Octstr *os1, Octstr *os2, long *pos);
386 
387 /*****************************************************************************
388  *
389  * EXTERNAL FUNCTIONS
390  */
391 
392 enum {
393     TYPE_HTTP = 0,
394     TYPE_HTTPS = 1
395 };
396 
wap_push_ppg_init(wap_dispatch_func_t * ota_dispatch,wap_dispatch_func_t * appl_dispatch,Cfg * cfg)397 void wap_push_ppg_init(wap_dispatch_func_t *ota_dispatch,
398                        wap_dispatch_func_t *appl_dispatch, Cfg *cfg)
399 {
400     user_configuration = read_ppg_config(cfg);
401     if (user_configuration != USER_CONFIGURATION_NOT_ADDED) {
402         ppg_queue = gwlist_create();
403         gwlist_add_producer(ppg_queue);
404         pap_queue = gwlist_create();
405         gwlist_add_producer(pap_queue);
406         push_id_counter = counter_create();
407         ppg_machines = gwlist_create();
408         ppg_unit_pushes = gwlist_create();
409 
410         dispatch_to_ota = ota_dispatch;
411         dispatch_to_appl = appl_dispatch;
412 
413         http_open_port(ppg_port, TYPE_HTTP);
414 #ifdef HAVE_LIBSSL
415         if (ppg_ssl_port != NO_HTTPS_PORT)
416             http_open_port(ppg_ssl_port, TYPE_HTTPS);
417 #endif
418         http_clients = dict_create(number_of_pushes, NULL);
419         urls = dict_create(number_of_pushes, NULL);
420 
421         gw_assert(run_status == limbo);
422         run_status = running;
423         gwthread_create(ota_read_thread, NULL);
424         gwthread_create(http_read_thread, NULL);
425 #ifdef HAVE_LIBSSL
426         if (ppg_ssl_port != NO_HTTPS_PORT)
427             gwthread_create(https_read_thread, NULL);
428 #endif
429         gwthread_create(pap_request_thread, NULL);
430     }
431 }
432 
wap_push_ppg_shutdown(void)433 void wap_push_ppg_shutdown(void)
434 {
435      if (user_configuration != USER_CONFIGURATION_NOT_ADDED) {
436          gw_assert(run_status == running);
437          run_status = terminating;
438          gwlist_remove_producer(ppg_queue);
439          gwlist_remove_producer(pap_queue);
440          octstr_destroy(ppg_url);
441          ppg_url = NULL;
442          http_close_all_ports();
443          dict_destroy(http_clients);
444          dict_destroy(urls);
445          wap_push_ppg_pushuser_list_destroy();
446          octstr_destroy(ppg_deny_ip);
447          octstr_destroy(ppg_allow_ip);
448          octstr_destroy(global_sender);
449          octstr_destroy(service_name);
450          octstr_destroy(ppg_default_smsc);
451          octstr_destroy(ppg_dlr_url);
452          octstr_destroy(ppg_smsbox_id);
453 
454          gwthread_join_every(http_read_thread);
455 #ifdef HAVE_LIBSSL
456          if (ppg_ssl_port != NO_HTTPS_PORT)
457             gwthread_join_every(https_read_thread);
458 #endif
459          gwthread_join_every(ota_read_thread);
460          gwthread_join_every(pap_request_thread);
461 
462          gwlist_destroy(ppg_queue, wap_event_destroy_item);
463          gwlist_destroy(pap_queue, pap_event_destroy_item);
464          counter_destroy(push_id_counter);
465 
466          debug("wap.push.ppg", 0, "PPG: %ld push session machines left.",
467                gwlist_len(ppg_machines));
468          gwlist_destroy(ppg_machines, session_machine_destroy);
469 
470          debug("wap_push_ppg", 0, "PPG: %ld unit pushes left",
471                gwlist_len(ppg_unit_pushes));
472          gwlist_destroy(ppg_unit_pushes, push_machine_destroy);
473      }
474 }
475 
wap_push_ppg_dispatch_event(WAPEvent * e)476 void wap_push_ppg_dispatch_event(WAPEvent *e)
477 {
478     gw_assert(run_status == running);
479     gwlist_produce(ppg_queue, e);
480 }
481 
482 /*
483  * We cannot know port the client is using when it establish the connection.
484  * However, we must link session creation with a pending push request. Only
485  * data available is the client address, so we check it here.
486  * Return non-NULL (pointer to the session machine found), if we have one.
487  */
wap_push_ppg_have_push_session_for(WAPAddrTuple * tuple)488 PPGSessionMachine *wap_push_ppg_have_push_session_for(WAPAddrTuple *tuple)
489 {
490     PPGSessionMachine *sm;
491 
492     gw_assert(tuple);
493     sm = gwlist_search(ppg_machines, tuple->remote->address, session_has_addr);
494 
495     return sm;
496 }
497 
498 /*
499  * Now initiators are identified by their session id. Return non-NULL (pointer
500  * to the session machine found), if we have one. This function are used after
501  * wsp has indicated session establishment, giving us a session id.
502  */
wap_push_ppg_have_push_session_for_sid(long sid)503 PPGSessionMachine *wap_push_ppg_have_push_session_for_sid(long sid)
504 {
505     PPGSessionMachine *sm;
506 
507     gw_assert(sid >= 0);
508     sm = gwlist_search(ppg_machines, &sid, session_has_sid);
509 
510     return sm;
511 }
512 
513 /*****************************************************************************
514  *
515  * INTERNAL FUNCTIONS
516  *
517  * Read general ppg configuration and configuration specific for users (to the
518  * list 'users').
519  * Return 1 when an user ppg group is present, 0 otherwise (and panic
520  * if we have not trusted ppg and no user groups).
521  */
522 
read_ppg_config(Cfg * cfg)523 static int read_ppg_config(Cfg *cfg)
524 {
525      CfgGroup *grp;
526      List *list;
527 
528      if (cfg == NULL)
529          return USER_CONFIGURATION_NOT_ADDED;
530 
531      grp = cfg_get_single_group(cfg, octstr_imm("ppg"));
532      if ((ppg_url = cfg_get(grp, octstr_imm("ppg-url"))) == NULL)
533          ppg_url = octstr_imm("/wappush");
534      cfg_get_integer(&ppg_port, grp, octstr_imm("ppg-port"));
535      cfg_get_integer(&number_of_pushes, grp, octstr_imm("concurrent-pushes"));
536      cfg_get_bool(&trusted_pi, grp, octstr_imm("trusted-pi"));
537      cfg_get_integer(&number_of_users, grp, octstr_imm("users"));
538      ppg_deny_ip = cfg_get(grp, octstr_imm("ppg-deny-ip"));
539      ppg_allow_ip = cfg_get(grp, octstr_imm("ppg-allow-ip"));
540      if ((global_sender = cfg_get(grp, octstr_imm("global-sender"))) == NULL)
541          global_sender = octstr_format("%s", "1234");
542      ppg_default_smsc = cfg_get(grp, octstr_imm("default-smsc"));
543      ppg_dlr_url = cfg_get(grp, octstr_imm("default-dlr-url"));
544      ppg_smsbox_id = cfg_get(grp, octstr_imm("ppg-smsbox-id"));
545      if ((service_name = cfg_get(grp, octstr_imm("service-name"))) == NULL)
546          service_name = octstr_format("%s", "ppg");
547 
548 #ifdef HAVE_LIBSSL
549      cfg_get_integer(&ppg_ssl_port, grp, octstr_imm("ppg-ssl-port"));
550      ssl_server_cert_file = cfg_get(grp, octstr_imm("ssl-server-cert-file"));
551      ssl_server_key_file = cfg_get(grp, octstr_imm("ssl-server-key-file"));
552      if (ppg_ssl_port != NO_HTTPS_PORT) {
553         if (ssl_server_cert_file == NULL || ssl_server_key_file == NULL)
554             panic(0, "cannot continue without server cert and/or key files");
555         use_global_server_certkey_file(ssl_server_cert_file, ssl_server_key_file);
556      }
557      octstr_destroy(ssl_server_cert_file);
558      octstr_destroy(ssl_server_key_file);
559 #endif
560 
561      /* If pi is trusted, ignore possible user groups. */
562      if (trusted_pi) {
563         cfg_destroy(cfg);
564         return USER_CONFIGURATION_ADDED;
565      }
566 
567      /* But if it is not, we cannot continue without user groups.*/
568      if ((list = cfg_get_multi_group(cfg, octstr_imm("wap-push-user")))
569               == NULL) {
570          panic(0, "No user group but ppg not trusted, stopping");
571          gwlist_destroy(list, NULL);
572          cfg_destroy(cfg);
573          return USER_CONFIGURATION_NOT_ADDED;
574      }
575 
576      if (!wap_push_ppg_pushuser_list_add(list, number_of_pushes,
577                                          number_of_users)) {
578          panic(0, "unable to create users configuration list, exiting");
579          return USER_CONFIGURATION_NOT_ADDED;
580      }
581 
582      cfg_destroy(cfg);
583      return USER_CONFIGURATION_ADDED;
584 }
585 
ip_allowed_by_ppg(Octstr * ip)586 static int ip_allowed_by_ppg(Octstr *ip)
587 {
588     if (ip == NULL)
589         return 0;
590 
591     if (trusted_pi)
592         return 1;
593 
594     if (ppg_deny_ip == NULL && ppg_allow_ip == NULL) {
595         warning(0, "Your ppg core configuration lacks allowed and denied"
596                    " ip lists");
597         return 1;
598     }
599 
600     if (ppg_deny_ip)
601         if (octstr_compare(ppg_deny_ip, octstr_imm("*.*.*.*")) == 0) {
602             panic(0, "Your ppg core configuration deny all ips, exiting");
603             return 0;
604         }
605 
606     if (ppg_allow_ip)
607         if (octstr_compare(ppg_allow_ip, octstr_imm("*.*.*.*")) == 0) {
608             warning(0, "Your ppg core configuration allow all ips");
609             return 1;
610         }
611 
612     if (ppg_deny_ip)
613         if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(ppg_deny_ip, ip,
614 	        octstr_imm(";"), octstr_imm("."))) {
615             error(0, "ip found from denied list");
616             return 0;
617         }
618 
619     if (ppg_allow_ip)
620         if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(ppg_allow_ip, ip,
621 	        octstr_imm(";"), octstr_imm("."))) {
622             debug("wap.push.ppg.pushuser", 0, "PPG: ip_allowed_by_ppg: ip found"
623                   " from allowed list");
624             return 1;
625         }
626 
627     warning(0, "did not found ip from any of core lists, deny it");
628     return 0;
629 }
630 
631 /*
632  * Event handling functions
633  */
ota_read_thread(void * arg)634 static void ota_read_thread (void *arg)
635 {
636     WAPEvent *e;
637 
638     while (run_status == running && (e = gwlist_consume(ppg_queue)) != NULL) {
639         handle_internal_event(e);
640     }
641 }
642 
643 /*
644  * Pap event functions handle only copy pointers. They do not allocate memory.
645  */
pap_event_create(Octstr * ip,Octstr * url,List * push_headers,Octstr * mime_content,List * cgivars,HTTPClient * client)646 static PAPEvent *pap_event_create(Octstr *ip, Octstr *url, List *push_headers,
647                                   Octstr *mime_content, List *cgivars,
648                                   HTTPClient *client)
649 {
650     PAPEvent *p;
651 
652     p = gw_malloc(sizeof(PAPEvent));
653     p->ip = ip;
654     p->url = url;
655     p->push_headers = push_headers;
656     p->mime_content = mime_content;
657     p->cgivars = cgivars;
658     p->client = client;
659 
660     return p;
661 }
662 
pap_event_destroy(PAPEvent * p)663 static void pap_event_destroy(PAPEvent *p)
664 {
665     if (p == NULL)
666         return;
667 
668     gw_free(p);
669 }
670 
pap_event_destroy_item(void * p)671 static void pap_event_destroy_item(void *p)
672 {
673     pap_event_destroy(p);
674 }
675 
pap_event_unpack(PAPEvent * p,Octstr ** ip,Octstr ** url,List ** push_headers,Octstr ** mime_content,List ** cgivars,HTTPClient ** client)676 static void pap_event_unpack(PAPEvent *p, Octstr **ip, Octstr **url,
677                              List **push_headers, Octstr **mime_content,
678                              List **cgivars, HTTPClient **client)
679 {
680     *ip = p->ip;
681     *url = p->url;
682     *push_headers = p->push_headers;
683     *mime_content = p->mime_content;
684     *cgivars = p->cgivars;
685     *client = p->client;
686 }
687 
http_read_thread(void * arg)688 static void http_read_thread(void *arg)
689 {
690     PAPEvent *p;
691     Octstr *ip;
692     Octstr *url;
693     List *push_headers;
694     Octstr *mime_content;
695     List *cgivars;
696     HTTPClient *client;
697 
698     while (run_status == running) {
699         client = http_accept_request(ppg_port, &ip, &url, &push_headers,
700                                      &mime_content, &cgivars);
701         if (client == NULL)
702 	        break;
703 
704         p = pap_event_create(ip, url, push_headers, mime_content, cgivars,
705                              client);
706         gwlist_produce(pap_queue, p);
707     }
708 }
709 
710 #ifdef HAVE_LIBSSL
https_read_thread(void * arg)711 static void https_read_thread(void *arg)
712 {
713     PAPEvent *p;
714     Octstr *ip;
715     Octstr *url;
716     List *push_headers;
717     Octstr *mime_content;
718     List *cgivars;
719     HTTPClient *client;
720 
721     while (run_status == running) {
722         client = http_accept_request(ppg_ssl_port, &ip, &url, &push_headers,
723                                      &mime_content, &cgivars);
724         if (client == NULL)
725 	    break;
726 
727         p = pap_event_create(ip, url, push_headers, mime_content, cgivars,
728                              client);
729         gwlist_produce(pap_queue, p);
730     }
731 }
732 #endif
733 
734 /*
735  * Authorization failure as such causes a challenge to the client (as required
736  * by rfc 2617, chapter 1).
737  * We store HTTPClient data structure corresponding a given push id, so that
738  * we can send responses to the rigth address.
739  * Pap chapter 14.4.1 states that we must return http status 202 after we have
740  * accepted PAP message, even if it is unparsable. So only the non-existing
741  * service error and some authorisation failures are handled at HTTP level.
742  * When a phone number was unacceptable, we return a PAP level error, because
743  * we cannot know this error before parsing the document.
744  */
745 
pap_request_thread(void * arg)746 static void pap_request_thread(void *arg)
747 {
748     WAPEvent *ppg_event;
749     PAPEvent *p;
750     size_t push_len;
751     Octstr *pap_content = NULL;
752     Octstr *push_data = NULL;
753     Octstr *rdf_content = NULL;
754     Octstr *mime_content = NULL;
755     Octstr *plos = NULL;               /* a temporary variable*/
756     Octstr *boundary = NULL;
757     Octstr *content_header = NULL;     /* Content-Type MIME header */
758     Octstr *url = NULL;
759     Octstr *ip = NULL;
760     Octstr *not_found = NULL;
761     Octstr *username = NULL;
762     int compiler_status,
763         http_status;
764     List *push_headers,                /* MIME headers themselves */
765          *content_headers,             /* Headers from the content entity, see
766                                           pap chapters 8.2, 13.1. Rfc 2045
767                                           grammar calls these MIME-part-hea-
768                                           ders */
769          *cgivars;
770     HTTPClient *client;
771     Octstr *dlr_url;
772 
773     http_status = 0;
774     url = ip = mime_content = username = NULL;
775 
776     while (run_status == running && (p = gwlist_consume(pap_queue)) != NULL) {
777 
778         http_status = HTTP_NOT_FOUND;
779         pap_event_unpack(p, &ip, &url, &push_headers, &mime_content,
780                          &cgivars, &client);
781 
782         if (octstr_compare(url, ppg_url) != 0) {
783             error(0,  "Request <%s> from <%s>: service not found",
784                   octstr_get_cstr(url), octstr_get_cstr(ip));
785             debug("wap.push.ppg", 0, "your configuration uses %s",
786                   octstr_get_cstr(ppg_url));
787             not_found = octstr_imm("Service not specified\n");
788             http_send_reply(client, http_status, push_headers, not_found);
789             goto ferror;
790         }
791 
792         http_status = HTTP_UNAUTHORIZED;
793 
794         if (!ip_allowed_by_ppg(ip)) {
795             error(0,  "Request <%s> from <%s>: ip forbidden, closing the"
796                   " client", octstr_get_cstr(url), octstr_get_cstr(ip));
797             http_close_client(client);
798             goto ferror;
799         }
800 
801         if (!trusted_pi && user_configuration) {
802 	    if (!wap_push_ppg_pushuser_authenticate(client, cgivars, ip,
803                                                     push_headers, &username)) {
804 	             error(0,  "Request <%s> from <%s>: authorisation failure",
805                        octstr_get_cstr(url), octstr_get_cstr(ip));
806                  goto ferror;
807             }
808         } else {                        /* J�rg, this wont disappear again */
809 	    username = octstr_imm("");
810 	}
811 
812         http_status = HTTP_ACCEPTED;
813         info(0, "PPG: Accept request <%s> from <%s>", octstr_get_cstr(url),
814              octstr_get_cstr(ip));
815 
816         if (octstr_len(mime_content) == 0) {
817 	    warning(0, "PPG: No MIME content received, the request"
818                     " unacceptable");
819             send_bad_message_response(&client, octstr_imm("No MIME content"),
820                                       PAP_BAD_REQUEST, http_status);
821             if (client == NULL)
822 	            break;
823             goto ferror;
824         }
825 
826         if (!push_headers) {
827             warning(0, "PPG: No push headers received , the request"
828                     " unacceptable");
829             send_bad_message_response(&client, octstr_imm("No push headers"),
830                                       PAP_BAD_REQUEST, http_status);
831             if (client == NULL)
832 	            break;
833             goto ferror;
834         }
835         octstr_destroy(ip);
836 
837         http_remove_hop_headers(push_headers);
838         remove_mime_headers(&push_headers);
839         remove_link_headers(&push_headers);
840 
841         if (!headers_acceptable(push_headers, &content_header)) {
842 	        warning(0,  "PPG: Unparsable push headers, the request"
843                     " unacceptable");
844             send_bad_message_response(&client, content_header, PAP_BAD_REQUEST,
845                                       http_status);
846             if (client == NULL)
847 	            break;
848 	        goto herror;
849         }
850 
851         if (get_mime_boundary(push_headers, content_header, &boundary) == -1) {
852 	        warning(0, "PPG: No MIME boundary, the request unacceptable");
853             send_bad_message_response(&client, content_header, PAP_BAD_REQUEST,
854                                       http_status);
855             if (client == NULL)
856 	            break;
857 	        goto berror;
858         }
859 
860         gw_assert(mime_content);
861         if (!mime_parse(boundary, mime_content, &pap_content, &push_data,
862                         &content_headers, &rdf_content)) {
863             send_bad_message_response(&client, mime_content, PAP_BAD_REQUEST,
864                                       http_status);
865             if (client == NULL)
866 	            break;
867             warning(0, "PPG: unable to parse mime content, the request"
868                     " unacceptable");
869             goto clean;
870         } else {
871 	        debug("wap.push.ppg", 0, "PPG: http_read_thread: pap multipart"
872                   " accepted");
873         }
874 
875         push_len = octstr_len(push_data);
876         http_header_remove_all(push_headers, "Content-Type");
877 	http_append_headers(push_headers, content_headers);
878         change_header_value(&push_headers, "Content-Length",
879             octstr_get_cstr(plos = octstr_format("%d", push_len)));
880         octstr_destroy(plos);
881         octstr_destroy(content_header);
882 	http_destroy_headers(content_headers);
883 
884         ppg_event = NULL;
885         if ((compiler_status = pap_compile(pap_content, &ppg_event)) == -2) {
886 	    send_bad_message_response(&client, pap_content, PAP_BAD_REQUEST,
887                                        http_status);
888             if (client == NULL)
889 	        break;
890             warning(0, "PPG: pap control entity erroneous, the request"
891                     " unacceptable");
892             goto no_compile;
893         } else if (compiler_status == -1) {
894             send_bad_message_response(&client, pap_content, PAP_BAD_REQUEST,
895                                       http_status);
896             if (client == NULL)
897 	        break;
898             warning(0, "PPG: non implemented pap feature requested, the"
899                     " request unacceptable");
900             goto no_compile;
901         } else {
902 	    if (!dict_put_once(http_clients,
903 		    ppg_event->u.Push_Message.pi_push_id, client)) {
904                 warning(0, "PPG: duplicate push id, the request unacceptable");
905 	        tell_fatal_error(&client, ppg_event, url, http_status,
906                                  PAP_DUPLICATE_PUSH_ID);
907                 if (client == NULL)
908 	            break;
909                 goto not_acceptable;
910 	    }
911 
912             dict_put(urls, ppg_event->u.Push_Message.pi_push_id, url);
913 
914             if (is_phone_number(ppg_event->u.Push_Message.address_type)) {
915                 if (!trusted_pi && user_configuration &&
916                         !wap_push_ppg_pushuser_client_phone_number_acceptable(
917                         username, ppg_event->u.Push_Message.address_value)) {
918                     tell_fatal_error(&client, ppg_event, url, http_status,
919                                     PAP_FORBIDDEN);
920                     if (client == NULL)
921 	                break;
922 	                goto not_acceptable;
923 	            }
924             }
925 
926             debug("wap.push.ppg", 0, "PPG: http_read_thread: pap control"
927                   " entity compiled ok");
928             ppg_event->u.Push_Message.push_data = octstr_duplicate(push_data);
929             ppg_event->u.Push_Message.smsc_id = set_smsc_id(push_headers, username,
930                                                             trusted_pi);
931             dlr_url = set_dlr_url(push_headers, username, trusted_pi);
932             ppg_event->u.Push_Message.dlr_url = dlr_url;
933             ppg_event->u.Push_Message.dlr_mask = set_dlr_mask(push_headers, dlr_url);
934             ppg_event->u.Push_Message.smsbox_id = set_smsbox_id(push_headers, username,
935                                                                 trusted_pi);
936             ppg_event->u.Push_Message.service_name = set_service_name();
937             remove_x_kannel_headers(&push_headers);
938             ppg_event->u.Push_Message.push_headers = http_header_duplicate(push_headers);
939 
940             if (!handle_push_message(&client, ppg_event, http_status)) {
941 	        if (client == NULL)
942 		    break;
943                 goto no_transform;
944             }
945         }
946 
947         pap_event_destroy(p);
948         http_destroy_headers(push_headers);
949         http_destroy_cgiargs(cgivars);
950         octstr_destroy(username);
951         octstr_destroy(mime_content);
952         octstr_destroy(pap_content);
953         octstr_destroy(push_data);
954         octstr_destroy(rdf_content);
955         octstr_destroy(boundary);
956         boundary = rdf_content = push_data = pap_content = mime_content = username = NULL;
957         continue;
958 
959 no_transform:
960         pap_event_destroy(p);
961         http_destroy_headers(push_headers);
962         http_destroy_cgiargs(cgivars);
963         octstr_destroy(username);
964         octstr_destroy(mime_content);
965         octstr_destroy(pap_content);
966         octstr_destroy(push_data);
967         octstr_destroy(rdf_content);
968         octstr_destroy(boundary);
969         boundary = rdf_content = push_data = pap_content = mime_content = username = NULL;
970         continue;
971 
972 no_compile:
973         pap_event_destroy(p);
974         http_destroy_headers(push_headers);
975         http_destroy_cgiargs(cgivars);
976         octstr_destroy(username);
977         octstr_destroy(mime_content);
978         octstr_destroy(push_data);
979         octstr_destroy(rdf_content);
980         octstr_destroy(boundary);
981         octstr_destroy(url);
982         url = boundary = rdf_content = push_data = mime_content = username = NULL;
983         continue;
984 
985 not_acceptable:
986         pap_event_destroy(p);
987         http_destroy_headers(push_headers);
988         http_destroy_cgiargs(cgivars);
989         octstr_destroy(username);
990         octstr_destroy(mime_content);
991         octstr_destroy(pap_content);
992         octstr_destroy(push_data);
993         octstr_destroy(rdf_content);
994         octstr_destroy(boundary);
995         octstr_destroy(url);
996         url = boundary = rdf_content = push_data = pap_content = mime_content = username = NULL;
997         continue;
998 
999 clean:
1000         pap_event_destroy(p);
1001         http_destroy_headers(push_headers);
1002         http_destroy_headers(content_headers);
1003         octstr_destroy(pap_content);
1004         octstr_destroy(push_data);
1005         octstr_destroy(rdf_content);
1006         octstr_destroy(content_header);
1007         octstr_destroy(boundary);
1008         octstr_destroy(url);
1009         url = boundary = content_header = rdf_content = push_data = pap_content = NULL;
1010         continue;
1011 
1012 ferror:
1013         pap_event_destroy(p);
1014         http_destroy_headers(push_headers);
1015         http_destroy_cgiargs(cgivars);
1016         octstr_destroy(username);
1017         octstr_destroy(url);
1018         octstr_destroy(ip);
1019         octstr_destroy(mime_content);
1020         mime_content = ip = url = username = NULL;
1021         continue;
1022 
1023 herror:
1024         pap_event_destroy(p);
1025         http_destroy_headers(push_headers);
1026         http_destroy_cgiargs(cgivars);
1027         octstr_destroy(username);
1028         octstr_destroy(url);
1029         url = username = NULL;
1030         continue;
1031 
1032 berror:
1033         pap_event_destroy(p);
1034         http_destroy_headers(push_headers);
1035         http_destroy_cgiargs(cgivars);
1036         octstr_destroy(username);
1037         octstr_destroy(mime_content);
1038         octstr_destroy(content_header);
1039         octstr_destroy(boundary);
1040         octstr_destroy(url);
1041         url = boundary = content_header = mime_content = username = NULL;
1042         continue;
1043     }
1044 }
1045 
1046 /*
1047  * Operations needed when push proxy gateway receives a new push message are
1048  * defined in ppg Chapter 6. We create machines when error, too, because we
1049  * must then have a reportable message error state.
1050  * Output: current HTTP Client state.
1051  * Return 1 if the push content was OK, 0 if it was not transformable.
1052  */
1053 
handle_push_message(HTTPClient ** c,WAPEvent * e,int status)1054 static int handle_push_message(HTTPClient **c, WAPEvent *e, int status)
1055 {
1056     int cless,
1057         session_exists,
1058         bearer_supported,
1059         dummy,
1060         constraints,
1061         message_transformable,
1062         coriented_possible;
1063 
1064     long coded_appid_value;
1065 
1066     PPGPushMachine *pm;
1067     PPGSessionMachine *sm;
1068     WAPAddrTuple *tuple=NULL;
1069     Octstr *cliaddr=NULL;
1070     Octstr *type=NULL;
1071 
1072     List *push_headers;
1073 
1074     push_headers = e->u.Push_Message.push_headers;
1075     cliaddr = e->u.Push_Message.address_value;
1076     session_exists = 0;
1077 
1078     sm = session_find_using_pi_client_address(cliaddr);
1079     coded_appid_value = check_x_wap_application_id_header(&push_headers);
1080     cless = cless_accepted(e, sm);
1081     message_transformable = transform_message(&e, &tuple, push_headers, cless,
1082                                               &type);
1083 
1084     if (!sm && !cless) {
1085         sm = store_session_data(sm, e, tuple, &session_exists);
1086     }
1087 
1088     if (!store_push_data(&pm, sm, e, tuple, cless)) {
1089         warning(0, "PPG: handle_push_message: duplicate push id");
1090         *c = response_push_message(pm, PAP_DUPLICATE_PUSH_ID, status);
1091         goto no_start;
1092     }
1093 
1094     if (!message_transformable) {
1095 	pm = update_push_data_with_attribute(&sm, pm,
1096         PAP_TRANSFORMATION_FAILURE, PAP_UNDELIVERABLE1);
1097         if (tuple != NULL)
1098 	    *c = response_push_message(pm, PAP_TRANSFORMATION_FAILURE, status);
1099         else
1100 	    *c = response_push_message(pm, PAP_ADDRESS_ERROR, status);
1101         goto no_transformation;
1102     }
1103 
1104     dummy = 0;
1105     pm = update_push_data_with_attribute(&sm, pm, dummy, PAP_PENDING);
1106 
1107     bearer_supported = select_bearer_network(&e);
1108     if (!bearer_supported) {
1109         pm = update_push_data_with_attribute(&sm, pm, dummy,
1110             PAP_UNDELIVERABLE2);
1111         *c = response_push_message(pm, PAP_REQUIRED_BEARER_NOT_AVAILABLE, status);
1112 	    goto no_start;
1113     }
1114 
1115     if ((constraints = delivery_time_constraints(e, pm)) == TIME_EXPIRED) {
1116         pm = update_push_data_with_attribute(&sm, pm, PAP_FORBIDDEN,
1117                                              PAP_EXPIRED);
1118         *c = response_push_message(pm, PAP_FORBIDDEN, status);
1119 	    goto no_start;
1120     }
1121 
1122 /*
1123  * If time is to early for delivering the push message, we do not remove push
1124  * data. We response PI here, so that "accepted for processing" means "no
1125  * error messages to come".
1126  */
1127 
1128     *c = response_push_message(pm, PAP_ACCEPTED_FOR_PROCESSING, status);
1129     info(0, "PPG: handle_push_message: push message accepted for processing");
1130 
1131     if (constraints == TIME_TOO_EARLY)
1132 	    goto store_push;
1133 
1134     if (constraints == NO_CONSTRAINTS) {
1135 	http_header_mark_transformation(pm->push_headers, pm->push_data, type);
1136         if (sm)
1137             sm = update_session_data_with_headers(sm, pm);
1138 
1139         if (!confirmation_requested(e)) {
1140             pm = deliver_unit_push(NOT_LAST, pm, sm, session_exists);
1141             goto unit_push_delivered;
1142 	}
1143 
1144         if (session_exists) {
1145             deliver_confirmed_push(NOT_LAST, pm, sm);
1146         } else {
1147             coriented_possible = coriented_deliverable(coded_appid_value);
1148 	    http_header_remove_all(e->u.Push_Message.push_headers,
1149                                    "Content-Type");
1150             if (coriented_possible) {
1151                 create_session(e, pm);
1152             } else {
1153                 warning(0, "PPG: handle_push_message: wrong app id for confirmed"
1154                         " push session creation");
1155                 *c = response_push_message(pm, PAP_BAD_REQUEST, status);
1156             }
1157         }
1158     }
1159 
1160     wap_addr_tuple_destroy(tuple);
1161     octstr_destroy(type);
1162     wap_event_destroy(e);
1163     return 1;
1164 
1165 unit_push_delivered:
1166     wap_addr_tuple_destroy(tuple);
1167     remove_push_data(sm, pm, cless);
1168     octstr_destroy(type);
1169     wap_event_destroy(e);
1170     return 1;
1171 
1172 store_push:
1173     wap_addr_tuple_destroy(tuple);
1174     octstr_destroy(type);
1175     wap_event_destroy(e);
1176     return 1;
1177 
1178 no_transformation:
1179     wap_addr_tuple_destroy(tuple);
1180     remove_push_data(sm, pm, cless);
1181     if (sm)
1182         remove_pushless_session(sm);
1183     wap_event_destroy(e);
1184     return 0;
1185 
1186 no_start:
1187     wap_addr_tuple_destroy(tuple);
1188     octstr_destroy(type);
1189     remove_push_data(sm, pm, cless);
1190     if (sm)
1191         remove_pushless_session(sm);
1192     wap_event_destroy(e);
1193     return 1;
1194 }
1195 
1196 /*
1197  * These events come from OTA layer
1198  */
handle_internal_event(WAPEvent * e)1199 static void handle_internal_event(WAPEvent *e)
1200 {
1201     long sid,
1202          pid,
1203          reason,
1204          port;
1205     int http_status;
1206     PPGPushMachine *pm;
1207     PPGSessionMachine *sm;
1208     WAPAddrTuple *tuple;
1209     List *caps;
1210 
1211     http_status = HTTP_OK;
1212     switch (e->type) {
1213 /*
1214  * Pap, Chapter 11.1.3 states that if client is incapable, we should abort the
1215  * push and inform PI. We do this here.
1216  * In addition, we store session id used as an alias for address tuple and do
1217  * all pushes pending for this initiator (or abort them).
1218  */
1219     case Pom_Connect_Ind:
1220          debug("wap.push.ppg", 0, "PPG: handle_internal_event: connect"
1221                " indication from OTA");
1222          sid = e->u.Pom_Connect_Ind.session_id;
1223          tuple = e->u.Pom_Connect_Ind.addr_tuple;
1224          port = tuple->remote->port;
1225          caps = e->u.Pom_Connect_Ind.requested_capabilities;
1226 
1227          sm = wap_push_ppg_have_push_session_for(tuple);
1228          sm = update_session_data(sm, sid, port, caps);
1229 
1230          if (!response_push_connection(e, sm)) {
1231 	     pm = abort_delivery(sm, http_status);
1232              wap_event_destroy(e);
1233              return;
1234          }
1235 
1236 /*
1237  * hard-coded until we have bearer control implemented
1238  */
1239          deliver_pending_pushes(sm, NOT_LAST);
1240          wap_event_destroy(e);
1241     break;
1242 
1243     case Pom_Disconnect_Ind:
1244         debug("wap.push.ppg", 0, "PPG: handle_internal_event: disconnect"
1245               " indication from OTA");
1246         sm = wap_push_ppg_have_push_session_for_sid(
1247                  e->u.Pom_Disconnect_Ind.session_handle);
1248         remove_session_data(sm, http_status);
1249         wap_event_destroy(e);
1250     break;
1251 
1252 /*
1253  * Only the client can close a session. So we leave session open, even when
1254  * there are no active pushes. Note that we do not store PAP attribute very
1255  * long time. Point is that result notification message, if asked, will rep-
1256  * ort this fact to PI, after which there is no need to store it any more.
1257  */
1258     case Po_ConfirmedPush_Cnf:
1259         debug("wap.push.ppg", 0, "PPG: handle_internal_event: push"
1260               " confirmation from OTA");
1261         sid = e->u.Po_ConfirmedPush_Cnf.session_handle;
1262         pid = e->u.Po_ConfirmedPush_Cnf.server_push_id;
1263 
1264         sm = wap_push_ppg_have_push_session_for_sid(sid);
1265         pm = find_ppg_push_machine_using_pid(sm, pid);
1266         pm = update_push_data_with_attribute(&sm, pm, PAP_CONFIRMED,
1267                                              PAP_DELIVERED2);
1268         wap_event_destroy(e);
1269         remove_push_data(sm, pm, 0);
1270     break;
1271 
1272 /*
1273  * Again, PAP attribute will be reported to PI by using result notification.
1274  */
1275     case Po_PushAbort_Ind:
1276         debug("wap.push.ppg", 0, "PPG: handle_internal_event: abort"
1277               " indication from OTA");
1278         sid = e->u.Po_PushAbort_Ind.session_handle;
1279         pid = e->u.Po_PushAbort_Ind.push_id;
1280 
1281         sm = wap_push_ppg_have_push_session_for_sid(sid);
1282         pm = find_ppg_push_machine_using_pid(sm, pid);
1283         session_machine_assert(sm);
1284         push_machine_assert(pm);
1285         reason = e->u.Po_PushAbort_Ind.reason;
1286         pm = update_push_data_with_attribute(&sm, pm, reason, PAP_ABORTED);
1287         remove_session_data(sm, http_status);
1288         wap_event_destroy(e);
1289     break;
1290 
1291 /*
1292  * FIXME TRU: Add timeout (a mandatory feature!)
1293  */
1294     default:
1295         debug("wap.ppg", 0, "PPG: handle_internal_event: an unhandled event");
1296         wap_event_dump(e);
1297         wap_event_destroy(e);
1298     break;
1299     }
1300 }
1301 
1302 /*
1303  * Functions related to various ppg machine types.
1304  *
1305  * We do not set session id here: it is told to us by wsp.
1306  */
session_machine_create(WAPAddrTuple * tuple,WAPEvent * e)1307 static PPGSessionMachine *session_machine_create(WAPAddrTuple *tuple,
1308                                                  WAPEvent *e)
1309 {
1310     PPGSessionMachine *m;
1311 
1312     gw_assert(e->type == Push_Message);
1313 
1314     m = gw_malloc(sizeof(PPGSessionMachine));
1315 
1316     #define INTEGER(name) m->name = 0;
1317     #define OCTSTR(name) m->name = NULL;
1318     #define ADDRTUPLE(name) m->name = NULL;
1319     #define PUSHMACHINES(name) m->name = gwlist_create();
1320     #define CAPABILITIES(name) m->name = NULL;
1321     #define MACHINE(fields) fields
1322     #include "wap_ppg_session_machine.def"
1323 
1324     m->pi_client_address = octstr_duplicate(e->u.Push_Message.address_value);
1325     m->addr_tuple = wap_addr_tuple_duplicate(tuple);
1326     m->assumed_capabilities =
1327         wsp_cap_duplicate_list(e->u.Push_Message.pi_capabilities);
1328     m->preferconfirmed_value = PAP_CONFIRMED;
1329 
1330     gwlist_append(ppg_machines, m);
1331     debug("wap.push.ppg", 0, "PPG: Created PPGSessionMachine %ld",
1332           m->session_id);
1333 
1334     return m;
1335 }
1336 
session_machine_destroy(void * p)1337 static void session_machine_destroy(void *p)
1338 {
1339     PPGSessionMachine *sm;
1340 
1341     if (p == NULL)
1342         return;
1343 
1344     sm = p;
1345     debug("wap.push.ppg", 0, "PPG: destroying PPGSEssionMachine %ld",
1346           sm->session_id);
1347 
1348     #define OCTSTR(name) octstr_destroy(sm->name);
1349     #define ADDRTUPLE(name) wap_addr_tuple_destroy(sm->name);
1350     #define INTEGER(name) sm->name = 0;
1351     #define PUSHMACHINES(name) push_machines_list_destroy(sm->name);
1352     #define CAPABILITIES(name) wsp_cap_destroy_list(sm->name);
1353     #define MACHINE(fields) fields
1354     #include "wap_ppg_session_machine.def"
1355     gw_free(sm);
1356 }
1357 
1358 /*
1359  * FIXME: PPG's trust policy (flags authenticated and trusted).
1360  * We return pointer to the created push machine and push id it uses.
1361  */
push_machine_create(WAPEvent * e,WAPAddrTuple * tuple)1362 static PPGPushMachine *push_machine_create(WAPEvent *e, WAPAddrTuple *tuple)
1363 {
1364     PPGPushMachine *m;
1365 
1366     m = gw_malloc(sizeof(PPGPushMachine));
1367 
1368     #define INTEGER(name) m->name = 0;
1369     #define OCTSTR(name) m->name = NULL;
1370     #define OPTIONAL_OCTSTR(name) m->name = NULL;
1371     #define ADDRTUPLE(name) m->name = NULL;
1372     #define CAPABILITIES m->name = NULL;
1373     #define HTTPHEADER(name) m->name = NULL;
1374     #define MACHINE(fields) fields
1375     #include "wap_ppg_push_machine.def"
1376 
1377     m->addr_tuple = wap_addr_tuple_duplicate(tuple);
1378     m->pi_push_id = octstr_duplicate(e->u.Push_Message.pi_push_id);
1379     m->push_id = counter_increase(push_id_counter);
1380     m->delivery_method = e->u.Push_Message.delivery_method;
1381     m->deliver_after_timestamp =
1382         octstr_duplicate(e->u.Push_Message.deliver_after_timestamp);
1383     m->priority = e->u.Push_Message.priority;
1384     m->push_headers = http_header_duplicate(e->u.Push_Message.push_headers);
1385     m->push_data = octstr_duplicate(e->u.Push_Message.push_data);
1386 
1387     m->address_type = e->u.Push_Message.address_type;
1388     if (e->u.Push_Message.smsc_id != NULL)
1389         m->smsc_id = octstr_duplicate(e->u.Push_Message.smsc_id);
1390     else
1391         m->smsc_id = NULL;
1392     if (e->u.Push_Message.dlr_url != NULL)
1393         m->dlr_url = octstr_duplicate(e->u.Push_Message.dlr_url);
1394     else
1395         m->dlr_url = NULL;
1396     m->dlr_mask = e->u.Push_Message.dlr_mask;
1397     if (e->u.Push_Message.smsbox_id != NULL)
1398         m->smsbox_id = octstr_duplicate(e->u.Push_Message.smsbox_id);
1399     else
1400         m->smsbox_id = NULL;
1401     m->service_name = octstr_duplicate(e->u.Push_Message.service_name);
1402 
1403     m->progress_notes_requested = e->u.Push_Message.progress_notes_requested;
1404     if (e->u.Push_Message.progress_notes_requested)
1405         m->ppg_notify_requested_to =
1406             octstr_duplicate(e->u.Push_Message.ppg_notify_requested_to);
1407 
1408     debug("wap.push.ppg", 0, "PPG: push machine %ld created", m->push_id);
1409 
1410     return m;
1411 }
1412 
1413 /*
1414  * Contrary to the normal Kannel style, we do not remove from a list here.
1415  * That is because we now have two different push lists.
1416  */
push_machine_destroy(void * p)1417 static void push_machine_destroy(void *p)
1418 {
1419     PPGPushMachine *pm;
1420 
1421     if (p == NULL)
1422         return;
1423 
1424     pm = p;
1425 
1426     debug("wap.push.ppg", 0, "PPG: destroying push machine %ld",
1427           pm->push_id);
1428     #define OCTSTR(name) octstr_destroy(pm->name);
1429     #define OPTIONAL_OCTSTR(name) octstr_destroy(pm->name);
1430     #define INTEGER(name)
1431     #define ADDRTUPLE(name) wap_addr_tuple_destroy(pm->name);
1432     #define CAPABILITIES(name) wap_cap_destroy_list(pm->name);
1433     #define HTTPHEADER(name) http_destroy_headers(pm->name);
1434     #define MACHINE(fields) fields
1435     #include "wap_ppg_push_machine.def"
1436 
1437     gw_free(p);
1438 }
1439 
push_machines_list_destroy(List * machines)1440 static void push_machines_list_destroy(List *machines)
1441 {
1442     if (machines == NULL)
1443         return;
1444 
1445     gwlist_destroy(machines, push_machine_destroy);
1446 }
1447 
session_has_addr(void * a,void * b)1448 static int session_has_addr(void *a, void *b)
1449 {
1450     Octstr *cliaddr;
1451     PPGSessionMachine *sm;
1452 
1453     cliaddr = b;
1454     sm = a;
1455 
1456     return octstr_compare(sm->addr_tuple->remote->address, cliaddr) == 0;
1457 }
1458 
session_has_sid(void * a,void * b)1459 static int session_has_sid(void *a, void *b)
1460 {
1461      PPGSessionMachine *sm;
1462      long *sid;
1463 
1464      sid = b;
1465      sm = a;
1466 
1467      return *sid == sm->session_id;
1468 }
1469 
1470 /*
1471  * Here session machine address tuples have connection-oriented ports, because
1472  * these are used when establishing the connection an doing pushes. But session
1473  * creation request must be to the the connectionless push port of the client.
1474  * So we change ports here.
1475  */
create_session(WAPEvent * e,PPGPushMachine * pm)1476 static void create_session(WAPEvent *e, PPGPushMachine *pm)
1477 {
1478     WAPEvent *ota_event;
1479     List *push_headers;
1480     Octstr *smsc_id;
1481     Octstr *dlr_url;
1482     Octstr *smsbox_id;
1483     Octstr *service_name;
1484 
1485     gw_assert(e->type == Push_Message);
1486     push_machine_assert(pm);
1487 
1488     push_headers = http_header_duplicate(e->u.Push_Message.push_headers);
1489     smsc_id = octstr_duplicate(e->u.Push_Message.smsc_id);
1490     dlr_url = octstr_duplicate(e->u.Push_Message.dlr_url);
1491     smsbox_id = octstr_duplicate(e->u.Push_Message.smsbox_id);
1492     service_name = octstr_duplicate(e->u.Push_Message.service_name);
1493 
1494     ota_event = wap_event_create(Pom_SessionRequest_Req);
1495     ota_event->u.Pom_SessionRequest_Req.addr_tuple =
1496         addr_tuple_change_cliport(pm->addr_tuple,
1497                                   CONNECTIONLESS_PUSH_CLIPORT);
1498     ota_event->u.Pom_SessionRequest_Req.push_headers = push_headers;
1499     ota_event->u.Pom_SessionRequest_Req.push_id = pm->push_id;
1500     ota_event->u.Pom_SessionRequest_Req.address_type = pm->address_type;
1501     if (smsc_id != NULL)
1502         ota_event->u.Pom_SessionRequest_Req.smsc_id = smsc_id;
1503     else
1504         ota_event->u.Pom_SessionRequest_Req.smsc_id = NULL;
1505     if (dlr_url != NULL)
1506         ota_event->u.Pom_SessionRequest_Req.dlr_url = dlr_url;
1507     else
1508         ota_event->u.Pom_SessionRequest_Req.dlr_url = NULL;
1509     ota_event->u.Pom_SessionRequest_Req.dlr_mask = e->u.Push_Message.dlr_mask;
1510     if (smsbox_id != NULL)
1511         ota_event->u.Pom_SessionRequest_Req.smsbox_id = smsbox_id;
1512     else
1513         ota_event->u.Pom_SessionRequest_Req.smsbox_id = NULL;
1514     ota_event->u.Pom_SessionRequest_Req.service_name = service_name;
1515 
1516     dispatch_to_ota(ota_event);
1517 }
1518 
1519 /*
1520  * We store data to push machine, because it is possible that we do not have
1521  * a session when push request happens.
1522  */
request_confirmed_push(long last,PPGPushMachine * pm,PPGSessionMachine * sm)1523 static void request_confirmed_push(long last, PPGPushMachine *pm,
1524                                    PPGSessionMachine *sm)
1525 {
1526     WAPEvent *ota_event;
1527     List *push_headers;
1528 
1529     gw_assert(last == 0 || last == 1);
1530     push_machine_assert(pm);
1531     session_machine_assert(sm);
1532 
1533     push_headers = http_header_duplicate(pm->push_headers);
1534 
1535     ota_event = wap_event_create(Po_ConfirmedPush_Req);
1536     ota_event->u.Po_ConfirmedPush_Req.server_push_id = pm->push_id;
1537     ota_event->u.Po_ConfirmedPush_Req.push_headers = push_headers;
1538     ota_event->u.Po_ConfirmedPush_Req.authenticated = pm->authenticated;
1539     ota_event->u.Po_ConfirmedPush_Req.trusted = pm->trusted;
1540     ota_event->u.Po_ConfirmedPush_Req.last = last;
1541 
1542     if (pm->push_data != NULL)
1543         ota_event->u.Po_ConfirmedPush_Req.push_body =
1544             octstr_duplicate(pm->push_data);
1545     else
1546         ota_event->u.Po_ConfirmedPush_Req.push_body = NULL;
1547 
1548     ota_event->u.Po_ConfirmedPush_Req.session_handle = sm->session_id;
1549     debug("wap.push.ota", 0, "PPG: confirmed push request to OTA");
1550 
1551     dispatch_to_ota(ota_event);
1552 }
1553 
1554 /*
1555  * There is to types of unit push requests: requesting ip services and sms
1556  * services. Address type tells the difference.
1557  */
request_unit_push(long last,PPGPushMachine * pm)1558 static void request_unit_push(long last, PPGPushMachine *pm)
1559 {
1560     WAPEvent *ota_event;
1561     List *push_headers;
1562 
1563     gw_assert(last == 0 || last == 1);
1564     push_machine_assert(pm);
1565 
1566     push_headers = http_header_duplicate(pm->push_headers);
1567 
1568     ota_event = wap_event_create(Po_Unit_Push_Req);
1569     ota_event->u.Po_Unit_Push_Req.addr_tuple =
1570         wap_addr_tuple_duplicate(pm->addr_tuple);
1571     ota_event->u.Po_Unit_Push_Req.push_id = pm->push_id;
1572     ota_event->u.Po_Unit_Push_Req.push_headers = push_headers;
1573     ota_event->u.Po_Unit_Push_Req.authenticated = pm->authenticated;
1574     ota_event->u.Po_Unit_Push_Req.trusted = pm->trusted;
1575     ota_event->u.Po_Unit_Push_Req.last = last;
1576 
1577     ota_event->u.Po_Unit_Push_Req.address_type = pm->address_type;
1578     if (pm->smsc_id != NULL)
1579         ota_event->u.Po_Unit_Push_Req.smsc_id = octstr_duplicate(pm->smsc_id);
1580     else
1581         ota_event->u.Po_Unit_Push_Req.smsc_id = NULL;
1582     if (pm->dlr_url != NULL)
1583         ota_event->u.Po_Unit_Push_Req.dlr_url = octstr_duplicate(pm->dlr_url);
1584     else
1585         ota_event->u.Po_Unit_Push_Req.dlr_url = NULL;
1586     ota_event->u.Po_Unit_Push_Req.dlr_mask = pm->dlr_mask;
1587     if (pm->smsbox_id != NULL)
1588         ota_event->u.Po_Unit_Push_Req.smsbox_id = octstr_duplicate(pm->smsbox_id);
1589     else
1590         ota_event->u.Po_Unit_Push_Req.smsbox_id = NULL;
1591     if (pm->service_name != NULL)
1592         ota_event->u.Po_Unit_Push_Req.service_name = octstr_duplicate(pm->service_name);
1593 
1594     ota_event->u.Po_Unit_Push_Req.push_body = octstr_duplicate(pm->push_data);
1595 
1596     dispatch_to_ota(ota_event);
1597     debug("wap.push.ppg", 0, "PPG: OTA request for unit push");
1598 }
1599 
request_push(long last,PPGPushMachine * pm)1600 static void request_push(long last, PPGPushMachine *pm)
1601 {
1602     WAPEvent *ota_event;
1603     List *push_headers;
1604 
1605     gw_assert(last == 0 || last == 1);
1606     push_machine_assert(pm);
1607 
1608     push_headers = http_header_duplicate(pm->push_headers);
1609 
1610     ota_event = wap_event_create(Po_Push_Req);
1611     ota_event->u.Po_Push_Req.push_headers = push_headers;
1612     ota_event->u.Po_Push_Req.authenticated = pm->authenticated;
1613     ota_event->u.Po_Push_Req.trusted = pm->trusted;
1614     ota_event->u.Po_Push_Req.last = last;
1615 
1616     if (pm->push_data != NULL)
1617         ota_event->u.Po_Push_Req.push_body =
1618             octstr_duplicate(pm->push_data);
1619     else
1620         ota_event->u.Po_Push_Req.push_body = NULL;
1621 
1622     ota_event->u.Po_Push_Req.session_handle = pm->session_id;
1623     debug("wap.push.ppg", 0, "PPG: OTA request for push");
1624 
1625     dispatch_to_ota(ota_event);
1626 }
1627 
1628 
1629 /*
1630  * According to pap, Chapter 11, capabilities can be
1631  *
1632  *                a) queried by PI
1633  *                b) told to PI when a client is subscribing
1634  *                c) assumed
1635  *
1636  * In case c) we got capabilities from third part of the push message (other
1637  * cases PI knows what it is doing), and we check is the client capable to
1638  * handle the message.
1639  * Requested capabilities are client capabilities, assumed capabilities are
1640  * PI capabilities. If there is no assumed capabilities, PI knows client capab-
1641  * ilities by method a) or method b).
1642  * Returns 1, if the client is capable, 0 when it is not.
1643  */
1644 
response_push_connection(WAPEvent * e,PPGSessionMachine * sm)1645 static int response_push_connection(WAPEvent *e, PPGSessionMachine *sm)
1646 {
1647     WAPEvent *appl_event;
1648 
1649     gw_assert(e->type == Pom_Connect_Ind);
1650 
1651     if (sm->assumed_capabilities != NULL && check_capabilities(
1652             e->u.Pom_Connect_Ind.requested_capabilities,
1653             sm->assumed_capabilities) == 0)
1654        return 0;
1655 
1656     appl_event = wap_event_create(Pom_Connect_Res);
1657     appl_event->u.Pom_Connect_Res.negotiated_capabilities =
1658         wsp_cap_duplicate_list(e->u.Pom_Connect_Ind.requested_capabilities);
1659     appl_event->u.Pom_Connect_Res.session_id = e->u.Pom_Connect_Ind.session_id;
1660 
1661     dispatch_to_appl(appl_event);
1662 
1663     return 1;
1664 }
1665 
1666 /*
1667  * Push response, from pap, Chapter 9.3.
1668  * Inputs error code, in PAP format.
1669  * Return the current value of HTTPClient.
1670  */
response_push_message(PPGPushMachine * pm,long code,int status)1671 static HTTPClient *response_push_message(PPGPushMachine *pm, long code, int status)
1672 {
1673     WAPEvent *e;
1674     HTTPClient *c;
1675 
1676     push_machine_assert(pm);
1677 
1678     e = wap_event_create(Push_Response);
1679     e->u.Push_Response.pi_push_id = octstr_duplicate(pm->pi_push_id);
1680     e->u.Push_Response.sender_name = tell_ppg_name();
1681     e->u.Push_Response.reply_time = set_time();
1682     e->u.Push_Response.code = code;
1683     e->u.Push_Response.desc = describe_code(code);
1684 
1685     c = send_push_response(e, status);
1686 
1687     return c;
1688 }
1689 
1690 
check_capabilities(List * requested,List * assumed)1691 static int check_capabilities(List *requested, List *assumed)
1692 {
1693     int is_capable;
1694 
1695     is_capable = 1;
1696 
1697     return is_capable;
1698 }
1699 
1700 /*
1701  * Time of creation of the response (pap, chapter 9.3). We convert UNIX time
1702  * to ISO8601, it is, YYYY-MM-DDThh:mm:ssZ, T and Z being literal strings (we
1703  * use gw_gmtime to turn UNIX time to broken time).
1704  */
set_time(void)1705 static Octstr *set_time(void)
1706 {
1707     Octstr *current_time;
1708     struct tm now;
1709 
1710     now = gw_gmtime(time(NULL));
1711     current_time = octstr_format("%04d-%02d-%02dT%02d:%02d:%02dZ",
1712                                  now.tm_year + 1900, now.tm_mon + 1,
1713                                  now.tm_mday, now.tm_hour, now.tm_min,
1714                                  now.tm_sec);
1715 
1716     return current_time;
1717 }
1718 
session_machine_assert(PPGSessionMachine * sm)1719 static void session_machine_assert(PPGSessionMachine *sm)
1720 {
1721     gw_assert(sm);
1722     gw_assert(sm->session_id >= 0);
1723     gw_assert(sm->addr_tuple);
1724     gw_assert(sm->pi_client_address);
1725 }
1726 
push_machine_assert(PPGPushMachine * pm)1727 static void push_machine_assert(PPGPushMachine *pm)
1728 {
1729     gw_assert(pm);
1730     gw_assert(pm->pi_push_id);
1731     gw_assert(pm->push_id >= 0);
1732     gw_assert(pm->session_id >= 0);
1733     gw_assert(pm->addr_tuple);
1734     gw_assert(pm->trusted == 1 || pm->trusted == 0);
1735     gw_assert(pm->authenticated  == 1 || pm->authenticated == 0);
1736 }
1737 
1738 /*
1739  * Message transformations performed by PPG are defined in ppg, 6.1.2.1. Ppg,
1740  * chapter 6.1.1, states that we MUST reject a push having an erroneous PAP
1741  * push message element. So we must validate it even when we do not compile
1742  * it.
1743  * If message content was not si or sl, we pass it without modifications.
1744  * We do not do any (formally optional, but phones may disagree) header
1745  * conversions to the binary format here, these are responsibility of our OTA
1746  * module (gw/wap_push_ota.c).
1747  * FIXME: Remove all headers which default values are known to the client.
1748  *
1749  * Return
1750  *    a) message, either transformed or not (if there is no-transform cache
1751  *       directive, wml code is erroneous or content was not si or sl.)
1752  *    b) The transformed gw address. Use here global-sender, when the bearer
1753  *       is SMS (some SMS centers would require this).
1754  *    c) the transformed message content type
1755  *
1756  * Returned flag tells was the transformation (if any) successful or not. Error
1757  * flag is returned when there is no push headers, there is no Content-Type header
1758  * or push content does not compile. We should have checked existence of push
1759  * headers earlier, but let us be careful.
1760  */
transform_message(WAPEvent ** e,WAPAddrTuple ** tuple,List * push_headers,int cless_accepted,Octstr ** type)1761 static int transform_message(WAPEvent **e, WAPAddrTuple **tuple,
1762                              List *push_headers, int cless_accepted, Octstr **type)
1763 {
1764     int message_deliverable;
1765     struct content content;
1766     Octstr *cliaddr;
1767     long cliport,
1768          servport,
1769          address_type;
1770 
1771     gw_assert((**e).type == Push_Message);
1772     if ((**e).u.Push_Message.push_headers == NULL)
1773         goto herror;
1774 
1775     cliaddr = (**e).u.Push_Message.address_value;
1776     push_headers = (**e).u.Push_Message.push_headers;
1777 
1778     if (!cless_accepted) {
1779         cliport = CONNECTED_CLIPORT;
1780         servport = CONNECTED_SERVPORT;
1781     } else {
1782         cliport = CONNECTIONLESS_PUSH_CLIPORT;
1783         servport = CONNECTIONLESS_SERVPORT;
1784     }
1785 
1786     address_type = (**e).u.Push_Message.address_type;
1787     *tuple = set_addr_tuple(cliaddr, cliport, servport, address_type, push_headers);
1788 
1789     if (!content_transformable(push_headers))
1790         goto no_transform;
1791 
1792     content.charset = NULL;
1793     content.type = NULL;
1794 
1795     content.body = (**e).u.Push_Message.push_data;
1796     if (content.body == NULL)
1797         goto no_transform;
1798 
1799     content.type = http_header_find_first(push_headers, "Content-Transfer-Encoding");
1800     if (content.type) {
1801 	octstr_strip_blanks(content.type);
1802 	debug("wap.push.ppg", 0, "PPG: Content-Transfer-Encoding is \"%s\"",
1803 	      octstr_get_cstr (content.type));
1804 	message_deliverable = pap_get_content(&content);
1805 
1806         if (message_deliverable) {
1807 	    change_header_value(&push_headers, "Content-Transfer-Encoding",
1808                                 "binary");
1809 	} else {
1810 	    goto error;
1811 	}
1812     }
1813 
1814     octstr_destroy(content.type);
1815     http_header_get_content_type(push_headers, &content.type, &content.charset);
1816     message_deliverable = pap_convert_content(&content);
1817 
1818     if (content.type == NULL)
1819         goto error;
1820 
1821     if (message_deliverable) {
1822         *type = content.type;
1823     } else {
1824         goto error;
1825     }
1826 
1827     (**e).u.Push_Message.push_data = content.body;
1828     octstr_destroy(content.charset);
1829 
1830     debug("wap.push.ppg", 0, "PPG: transform_message: push message content"
1831           " and headers valid");
1832     return 1;
1833 
1834 herror:
1835     warning(0, "PPG: transform_message: no push headers, cannot accept");
1836     octstr_destroy(content.type);
1837     return 0;
1838 
1839 error:
1840     warning(0, "PPG: transform_message: push content erroneous, cannot"
1841             " accept");
1842     octstr_destroy(content.type);
1843     octstr_destroy(content.charset);
1844     return 0;
1845 
1846 no_transform:
1847     warning(0, "PPG: transform_message: push content non transformable");
1848     return 1;
1849 }
1850 
1851 /*
1852  * Transform X-WAP-Application headers as per ppg 6.1.2.1. Note that missing
1853  * header means that wml.ua is assumed.
1854  * Return coded value (starting with 0), when the id was not wml.ua
1855  *        -1, when id was wml.ua (or no application id was present)
1856  *        -2, when error
1857  */
check_x_wap_application_id_header(List ** push_headers)1858 static long check_x_wap_application_id_header(List **push_headers)
1859 {
1860     Octstr *appid_content;
1861     long coded_value;
1862     Octstr *cos;
1863 
1864     if (*push_headers == NULL)
1865         return -2;
1866 
1867     appid_content = http_header_find_first(*push_headers,
1868         "X-WAP-Application-Id");
1869 
1870     if (appid_content == NULL) {
1871         octstr_destroy(appid_content);
1872         return -1;
1873     }
1874 
1875     if ((coded_value = parse_appid_header(&appid_content)) < 0) {
1876         octstr_destroy(appid_content);
1877         return -2;
1878     }
1879 
1880     if (coded_value == 2) {
1881         octstr_destroy(appid_content);
1882         http_header_remove_all(*push_headers, "X-WAP-Application-Id");
1883         return -1;
1884     }
1885 
1886     cos = octstr_format("%ld", coded_value);
1887     http_header_remove_all(*push_headers, "X-WAP-Application-Id");
1888     http_header_add(*push_headers, "X-WAP-Application-Id", octstr_get_cstr(cos));
1889 
1890     octstr_destroy(appid_content);
1891     octstr_destroy(cos);
1892 
1893     return coded_value;
1894 }
1895 
1896 /*
1897  * Check do we have a no-transform cache directive amongst the headers.
1898  */
content_transformable(List * push_headers)1899 static int content_transformable(List *push_headers)
1900 {
1901     List *cache_directives;
1902     long i;
1903     Octstr *header_name,
1904            *header_value;
1905 
1906     gw_assert(push_headers);
1907 
1908     cache_directives = http_header_find_all(push_headers, "Cache-Control");
1909     if (gwlist_len(cache_directives) == 0) {
1910         http_destroy_headers(cache_directives);
1911         return 1;
1912     }
1913 
1914     i = 0;
1915     while (i < gwlist_len(cache_directives)) {
1916         http_header_get(cache_directives, i, &header_name, &header_value);
1917         if (octstr_compare(header_value, octstr_imm("no-transform")) == 0) {
1918             http_destroy_headers(cache_directives);
1919             octstr_destroy(header_name);
1920             octstr_destroy(header_value);
1921 	    return 0;
1922         }
1923         ++i;
1924     }
1925 
1926     http_destroy_headers(cache_directives);
1927     octstr_destroy(header_name);
1928     octstr_destroy(header_value);
1929 
1930     return 1;
1931 }
1932 
1933 /*
1934  * Convert push content to compact binary format (this can be wmlc, sic, slc
1935  * or coc). Current status wml, sl and si compiled, others passed.
1936  */
convert_wml_to_wmlc(struct content * content)1937 static Octstr *convert_wml_to_wmlc(struct content *content)
1938 {
1939     Octstr *wmlc;
1940 
1941     if (wml_compile(content->body, content->charset, &wmlc, NULL) == 0)
1942         return wmlc;
1943     warning(0, "PPG: wml compilation failed");
1944     return NULL;
1945 }
1946 
convert_si_to_sic(struct content * content)1947 static Octstr *convert_si_to_sic(struct content *content)
1948 {
1949     Octstr *sic;
1950 
1951     if (si_compile(content->body, content->charset, &sic) == 0)
1952         return sic;
1953     warning(0, "PPG: si compilation failed");
1954     return NULL;
1955 }
1956 
convert_sl_to_slc(struct content * content)1957 static Octstr *convert_sl_to_slc(struct content *content)
1958 {
1959     Octstr *slc;
1960 
1961     if (sl_compile(content->body, content->charset, &slc) == 0)
1962         return slc;
1963     warning(0, "PPG: sl compilation failed");
1964     return NULL;
1965 }
1966 
1967 
extract_base64(struct content * content)1968 static Octstr *extract_base64(struct content *content)
1969 {
1970     Octstr *orig = octstr_duplicate(content->body);
1971     octstr_base64_to_binary(orig);
1972     return orig;
1973 }
1974 
1975 static struct {
1976     char *type;
1977     char *result_type;
1978     Octstr *(*convert) (struct content *);
1979 } converters[] = {
1980     { "text/vnd.wap.wml",
1981       "application/vnd.wap.wmlc",
1982       convert_wml_to_wmlc },
1983     { "text/vnd.wap.si",
1984       "application/vnd.wap.sic",
1985       convert_si_to_sic },
1986     { "text/vnd.wap.sl",
1987       "application/vnd.wap.slc",
1988       convert_sl_to_slc}
1989 };
1990 
1991 #define NUM_CONVERTERS ((long) (sizeof(converters) / sizeof(converters[0])))
1992 
1993 static struct {
1994     char *transfer_encoding;
1995     Octstr *(*extract) (struct content *);
1996 } extractors[] = {
1997     { "base64",
1998       extract_base64 }
1999 };
2000 
2001 #define NUM_EXTRACTORS ((long) (sizeof(extractors) / sizeof(extractors[0])))
2002 
2003 /*
2004  * Compile wap defined contents, accept others without modifications. Push
2005  * message 6.3 states that push content can be any MIME accepted content type.
2006  */
pap_convert_content(struct content * content)2007 static int pap_convert_content(struct content *content)
2008 {
2009     long i;
2010     Octstr *new_body;
2011 
2012     for (i = 0; i < NUM_CONVERTERS; i++) {
2013         if (octstr_compare(content->type,
2014 	        octstr_imm(converters[i].type)) == 0) {
2015 	    new_body = converters[i].convert(content);
2016             if (new_body == NULL)
2017 	        return 0;
2018             octstr_destroy(content->body);
2019             content->body = new_body;
2020             octstr_destroy(content->type);
2021             content->type = octstr_create(converters[i].result_type);
2022             return 1;
2023         }
2024     }
2025 
2026     return 1;
2027 }
2028 
2029 /*
2030  * MIME specifies a number of content transfer encodings.
2031  * This function tries to get the original version of the
2032  * content.
2033  */
pap_get_content(struct content * content)2034 static int pap_get_content(struct content *content)
2035 {
2036     long i;
2037     Octstr *new_body;
2038 
2039     for (i = 0; i < NUM_EXTRACTORS; i++) {
2040         if (octstr_case_compare(content->type,
2041 	        octstr_imm(extractors[i].transfer_encoding)) == 0) {
2042 
2043 	        new_body = extractors[i].extract(content);
2044             if (new_body == NULL)
2045 	        return 0;
2046             octstr_destroy(content->body);
2047             content->body = new_body;
2048 	    octstr_destroy(content->type);
2049 	    content->type = NULL;
2050             return 1;
2051         }
2052     }
2053 
2054     return 1;
2055 }
2056 
2057 /*
2058  * Bearer and network types are defined in wdp, Appendix C. Any means any net-
2059  * work supporting IPv4 or IPv6.
2060  */
2061 static char *bearers[] = {
2062    "Any",
2063    "SMS",
2064    "CSD",
2065    "GPRS",
2066    "Packet Data",
2067    "CDPD"
2068 };
2069 
2070 #define NUMBER_OF_BEARERS sizeof(bearers)/sizeof(bearers[0])
2071 
2072 static char *networks[] = {
2073     "Any",
2074     "GSM",
2075     "IS-95 CDMA",
2076     "ANSI-136",
2077     "AMPS",
2078     "PDC",
2079     "IDEN",
2080     "PHS",
2081     "TETRA"
2082 };
2083 
2084 #define NUMBER_OF_NETWORKS sizeof(networks)/sizeof(networks[0])
2085 
2086 /*
2087  * We support networks using IP as a bearer and GSM using SMS as bearer, so we
2088  * must reject others. Default bearer is IP, it is (currently) not-SMS. After
2089  * the check we change meaning of the bearer_required-attribute: it will tell
2090  * do we use WAP over SMS.
2091  */
select_bearer_network(WAPEvent ** e)2092 int select_bearer_network(WAPEvent **e)
2093 {
2094     Octstr *bearer,
2095            *network;
2096     int bearer_required,
2097         network_required;
2098     size_t i,
2099            j;
2100 
2101     gw_assert((**e).type == Push_Message);
2102 
2103     bearer_required = (**e).u.Push_Message.bearer_required;
2104     network_required = (**e).u.Push_Message.network_required;
2105     bearer = octstr_imm("Any");
2106     network = octstr_imm("Any");
2107 
2108     if (!bearer_required || !network_required)
2109         return 1;
2110 
2111     if (bearer_required)
2112         bearer = (**e).u.Push_Message.bearer;
2113     if (network_required)
2114         network = (**e).u.Push_Message.network;
2115 
2116     for (i = 0; i < NUMBER_OF_NETWORKS ; ++i) {
2117         if (octstr_case_compare(network, octstr_imm(networks[i])) == 0)
2118 	        break;
2119     }
2120     for (j = 0; j < NUMBER_OF_BEARERS ; ++j) {
2121         if (octstr_case_compare(bearer, octstr_imm(bearers[j])) == 0)
2122 	        break;
2123     }
2124     if (i == NUMBER_OF_NETWORKS || j == NUMBER_OF_BEARERS)
2125         return 0;
2126 
2127     return 1;
2128 }
2129 
session_has_pi_client_address(void * a,void * b)2130 static int session_has_pi_client_address(void *a, void *b)
2131 {
2132     Octstr *caddr;
2133     PPGSessionMachine *sm;
2134 
2135     caddr = b;
2136     sm = a;
2137 
2138     return octstr_compare(caddr, sm->pi_client_address) == 0;
2139 }
2140 
2141 /*
2142  * PI client address is composed of a client specifier and a PPG specifier (see
2143  * ppg, chapter 7). So it is equivalent with gw address quadruplet.
2144  */
session_find_using_pi_client_address(Octstr * caddr)2145 PPGSessionMachine *session_find_using_pi_client_address(Octstr *caddr)
2146 {
2147     PPGSessionMachine *sm;
2148 
2149     sm = gwlist_search(ppg_machines, caddr, session_has_pi_client_address);
2150 
2151     return sm;
2152 }
2153 
2154 /*
2155  * Give PPG a human readable name.
2156  */
tell_ppg_name(void)2157 static Octstr *tell_ppg_name(void)
2158 {
2159      return octstr_format("%S; WAP/1.3 (" GW_NAME "/%s)", get_official_name(),
2160                           GW_VERSION);
2161 }
2162 
2163 /*
2164  * Delivery time constraints are a) deliver before and b) deliver after. It is
2165  * possible that service required is after some time and before other. So we
2166  * test first condition a). Note that 'now' satisfy both constraints.
2167  * Returns: 0 delivery time expired
2168  *          1 too early to send the message
2169  *          2 no constraints
2170  */
delivery_time_constraints(WAPEvent * e,PPGPushMachine * pm)2171 static int delivery_time_constraints(WAPEvent *e, PPGPushMachine *pm)
2172 {
2173     Octstr *before,
2174            *after;
2175     struct tm now;
2176 
2177     gw_assert(e->type == Push_Message);
2178 
2179     before = e->u.Push_Message.deliver_before_timestamp;
2180     after = pm->deliver_after_timestamp;
2181     now = gw_gmtime(time(NULL));
2182 
2183     if (!deliver_before_test_cleared(before, now)) {
2184         info(0, "PPG: delivery deadline expired, dropping the push message");
2185         return 0;
2186     }
2187 
2188     if (!deliver_after_test_cleared(after, now)) {
2189         debug("wap.push.ppg", 0, "PPG: too early to push the message,"
2190               " waiting");
2191         return 1;
2192     }
2193 
2194     return 2;
2195 }
2196 
2197 /*
2198  * Give verbose description of the result code. Conversion table for descrip-
2199  * tion.
2200  */
2201 struct description_t {
2202     long reason;
2203     char *description;
2204 };
2205 
2206 typedef struct description_t description_t;
2207 
2208 static description_t pap_desc[] = {
2209     { PAP_OK, "The request succeeded"},
2210     { PAP_ACCEPTED_FOR_PROCESSING, "The request has been accepted for"
2211                                    " processing"},
2212     { PAP_BAD_REQUEST, "Not understood due to malformed syntax"},
2213     { PAP_FORBIDDEN, "Request was refused"},
2214     { PAP_ADDRESS_ERROR, "The client specified not recognised"},
2215     { PAP_CAPABILITIES_MISMATCH, "Capabilities assumed by PI were not"
2216                                  "  acceptable for the client specified"},
2217     { PAP_DUPLICATE_PUSH_ID, "Push id supplied was not unique"},
2218     { PAP_INTERNAL_SERVER_ERROR, "Server could not fulfill the request due"
2219                                  " to an internal error"},
2220     { PAP_TRANSFORMATION_FAILURE, "PPG was unable to perform a transformation"
2221                                   " of the message"},
2222     { PAP_REQUIRED_BEARER_NOT_AVAILABLE, "Required bearer not available"},
2223     { PAP_SERVICE_FAILURE, "The service failed. The client may re-attempt"
2224                            " the operation"},
2225     { PAP_CLIENT_ABORTED, "The client aborted the operation. No reason given"},
2226     { WSP_ABORT_USERREQ, "Wsp requested abort"},
2227     { WSP_ABORT_USERRFS, "Wsp refused push message. Do not try again"},
2228     { WSP_ABORT_USERPND, "Push message cannot be delivered to intended"
2229                          " destination by the wsp"},
2230     { WSP_ABORT_USERDCR, "Push message discarded due to resource shortage in"
2231                          " wsp"},
2232     { WSP_ABORT_USERDCU, "Content type of the push message cannot be"
2233                          " processed by the wsp"}
2234 };
2235 
2236 static size_t desc_tab_size = sizeof(pap_desc) / sizeof(pap_desc[0]);
2237 
describe_code(long code)2238 static Octstr *describe_code(long code)
2239 {
2240     Octstr *desc;
2241     size_t i;
2242 
2243     for (i = 0; i < desc_tab_size; i++) {
2244         if (pap_desc[i].reason == code) {
2245             desc = octstr_create(pap_desc[i].description);
2246             return desc;
2247         }
2248     }
2249 
2250     return octstr_imm("unknown PAP code");
2251 }
2252 
2253 /*
2254  * Remove push data from the list of connectionless pushes, if cless is true,
2255  * otherwise from the list of pushes belonging to session machine sm.
2256  */
remove_push_data(PPGSessionMachine * sm,PPGPushMachine * pm,int cless)2257 static void remove_push_data(PPGSessionMachine *sm, PPGPushMachine *pm,
2258                              int cless)
2259 {
2260     push_machine_assert(pm);
2261 
2262     if (cless) {
2263         gwlist_delete_equal(ppg_unit_pushes, pm);
2264     } else {
2265         session_machine_assert(sm);
2266         gwlist_delete_equal(sm->push_machines, pm);
2267     }
2268 
2269     push_machine_destroy(pm);
2270 }
2271 
2272 /*
2273  * If cless is true, store push to the list connectionless pushes, otherwise
2274  * in the push list of the session machine sm.
2275  * We must create a push machine even when an error occurred, because this is
2276  * used for storing the relevant pap error state and other data for this push.
2277  * There should not be any duplicate push ids here (this is tested by http_
2278  * read_thread), but let us be carefull.
2279  * Return a pointer the push machine newly created and a flag telling was the
2280  * push id duplicate.
2281  */
store_push_data(PPGPushMachine ** pm,PPGSessionMachine * sm,WAPEvent * e,WAPAddrTuple * tuple,int cless)2282 static int store_push_data(PPGPushMachine **pm, PPGSessionMachine *sm,
2283                            WAPEvent *e, WAPAddrTuple *tuple, int cless)
2284 {
2285     Octstr *pi_push_id;
2286     int duplicate_push_id;
2287 
2288     gw_assert(e->type == Push_Message);
2289 
2290     pi_push_id = e->u.Push_Message.pi_push_id;
2291 
2292     duplicate_push_id = 0;
2293     if (((!cless) &&
2294        (find_ppg_push_machine_using_pi_push_id(sm, pi_push_id) != NULL)) ||
2295        ((cless) &&
2296        (find_unit_ppg_push_machine_using_pi_push_id(pi_push_id) != NULL)))
2297        duplicate_push_id = 1;
2298 
2299     *pm = push_machine_create(e, tuple);
2300 
2301     if (duplicate_push_id)
2302         return !duplicate_push_id;
2303 
2304     if (!cless) {
2305        gwlist_append(sm->push_machines, *pm);
2306        debug("wap.push.ppg", 0, "PPG: store_push_data: push machine %ld"
2307              " appended to push list of sm machine %ld", (*pm)->push_id,
2308              sm->session_id);
2309     } else {
2310        gwlist_append(ppg_unit_pushes, *pm);
2311        debug("wap.push.ppg", 0, "PPG: store_push_data: push machine %ld"
2312              " appended to unit push list", (*pm)->push_id);
2313     }
2314 
2315     return !duplicate_push_id;
2316 }
2317 
2318 /*
2319  * Deliver confirmed push. Note that if push is confirmed, PAP attribute is up-
2320  * dated only after an additional event (confirmation, abort or time-out).
2321  */
deliver_confirmed_push(long last,PPGPushMachine * pm,PPGSessionMachine * sm)2322 static void deliver_confirmed_push(long last, PPGPushMachine *pm,
2323                                    PPGSessionMachine *sm)
2324 {
2325     request_confirmed_push(last, pm, sm);
2326 }
2327 
2328 /*
2329  * Ppg, chapter 6.1.2.2 , subchapter delivery, says that if push is unconform-
2330  * ed, we can use either Po-Unit-Push.req or Po-Push.req primitive. We use Po-
2331  * Push.req, if have an already established session (other words, sm != NULL).
2332  * In addition, update PAP attribute. Return pointer to the updated push mach-
2333  * ine.
2334  */
deliver_unit_push(long last,PPGPushMachine * pm,PPGSessionMachine * sm,int session_exists)2335 static PPGPushMachine *deliver_unit_push(long last, PPGPushMachine *pm,
2336     PPGSessionMachine *sm, int session_exists)
2337 {
2338     push_machine_assert(pm);
2339 
2340     if (!session_exists)
2341         request_unit_push(last, pm);
2342     else
2343         request_push(last, pm);
2344 
2345     pm = update_push_data_with_attribute(&sm, pm, PAP_UNCONFIRMED,
2346                                          PAP_DELIVERED1);
2347     info(0, "PPG: unconfirmed push delivered to OTA");
2348 
2349     return pm;
2350 }
2351 
2352 /*
2353  * Deliver all pushes queued by session machine sm (it is, make a relevant OTA
2354  * request). Update PAP attribute, if push is unconfirmed.
2355  */
deliver_pending_pushes(PPGSessionMachine * sm,int last)2356 static void deliver_pending_pushes(PPGSessionMachine *sm, int last)
2357 {
2358     PPGPushMachine *pm;
2359     long i;
2360 
2361     session_machine_assert(sm);
2362     gw_assert(gwlist_len(sm->push_machines) > 0);
2363 
2364     i = 0;
2365     while (i < gwlist_len(sm->push_machines)) {
2366         pm = gwlist_get(sm->push_machines, i);
2367         push_machine_assert(pm);
2368 
2369         if (pm->delivery_method == PAP_UNCONFIRMED) {
2370             request_push(last, pm);
2371             pm = update_push_data_with_attribute(&sm, pm, PAP_UNCONFIRMED,
2372                  PAP_DELIVERED1);
2373             remove_push_data(sm, pm, sm == NULL);
2374         } else {
2375 	        request_confirmed_push(last, pm, sm);
2376             ++i;
2377         }
2378     }
2379 }
2380 
2381 /*
2382  * Abort all pushes queued by session machine sm. In addition, update PAP
2383  * attribute and notify PI.
2384  */
abort_delivery(PPGSessionMachine * sm,int status)2385 static PPGPushMachine *abort_delivery(PPGSessionMachine *sm, int status)
2386 {
2387     PPGPushMachine *pm;
2388     long reason,
2389          code;
2390 
2391     session_machine_assert(sm);
2392 
2393     pm = NULL;
2394     reason = PAP_ABORT_USERPND;
2395     code = PAP_CAPABILITIES_MISMATCH;
2396 
2397     while (gwlist_len(sm->push_machines) > 0) {
2398         pm = gwlist_get(sm->push_machines, 0);
2399         push_machine_assert(pm);
2400 
2401         pm = update_push_data_with_attribute(&sm, pm, reason, PAP_ABORTED);
2402         response_push_message(pm, code, status);
2403 
2404         remove_push_data(sm, pm, sm == NULL);
2405     }
2406 
2407     return pm;
2408 }
2409 
2410 /*
2411  * Remove a session, even if it have active pushes. These are aborted, and we
2412  * must inform PI about this. Client abort codes are defined in pap, 9.14.5,
2413  * which refers to wsp, Appendix A, table 35.
2414  */
remove_session_data(PPGSessionMachine * sm,int status)2415 static void remove_session_data(PPGSessionMachine *sm, int status)
2416 {
2417     long code;
2418     PPGPushMachine *pm;
2419 
2420     session_machine_assert(sm);
2421 
2422     code = PAP_ABORT_USERPND;
2423 
2424     while (gwlist_len(sm->push_machines) > 0) {
2425         pm = gwlist_get(sm->push_machines, 0);
2426         response_push_message(pm, code, status);
2427         remove_push_data(sm, pm, sm == NULL);
2428     }
2429 
2430     gwlist_delete_equal(ppg_machines, sm);
2431     session_machine_destroy(sm);
2432 }
2433 
2434 /*
2435  * Remove session, if it has no active pushes.
2436  */
remove_pushless_session(PPGSessionMachine * sm)2437 static void remove_pushless_session(PPGSessionMachine *sm)
2438 {
2439     session_machine_assert(sm);
2440 
2441     if (gwlist_len(sm->push_machines) == 0) {
2442         gwlist_delete_equal(ppg_machines, sm);
2443         session_machine_destroy(sm);
2444     }
2445 }
2446 
2447 /*
2448  * If session machine not exist, create a session machine and store session
2449  * data. If session exists, ignore.
2450  * Return pointer to the session machine, and a flag did we have a session
2451  * before executing this function. (Session data is needed to implement the
2452  * PAP attribute. It does not mean that a session exists.)
2453  */
store_session_data(PPGSessionMachine * sm,WAPEvent * e,WAPAddrTuple * tuple,int * session_exists)2454 static PPGSessionMachine *store_session_data(PPGSessionMachine *sm,
2455     WAPEvent *e, WAPAddrTuple *tuple, int *session_exists)
2456 {
2457     gw_assert(e->type == Push_Message);
2458 
2459     if (sm == NULL) {
2460         sm = session_machine_create(tuple, e);
2461         *session_exists = 0;
2462     } else
2463         *session_exists = 1;
2464 
2465     return sm;
2466 }
2467 
update_session_data_with_headers(PPGSessionMachine * sm,PPGPushMachine * pm)2468 static PPGSessionMachine *update_session_data_with_headers(
2469     PPGSessionMachine *sm, PPGPushMachine *pm)
2470 {
2471     gwlist_delete_matching(sm->push_machines, &pm->push_id, push_has_pid);
2472     gwlist_append(sm->push_machines, pm);
2473 
2474     return sm;
2475 }
2476 
2477 /*
2478  * Ppg 6.1.2.2, subchapter delivery, states that if the delivery method is not
2479  * confirmed or unconfirmed, PPG may select an implementation specific type of
2480  * the  primitive. We use an unconfirmed push, if QoS is notspecified, and
2481  * confirmed one, when it is preferconfirmed (we do support confirmed push).
2482  */
confirmation_requested(WAPEvent * e)2483 static int confirmation_requested(WAPEvent *e)
2484 {
2485     gw_assert(e->type == Push_Message);
2486 
2487     return e->u.Push_Message.delivery_method == PAP_CONFIRMED ||
2488            e->u.Push_Message.delivery_method == PAP_PREFERCONFIRMED;
2489 }
2490 
push_has_pid(void * a,void * b)2491 static int push_has_pid(void *a, void *b)
2492 {
2493     long *pid;
2494     PPGPushMachine *pm;
2495 
2496     pid = b;
2497     pm = a;
2498 
2499     return *pid == pm->push_id;
2500 }
2501 
find_ppg_push_machine_using_pid(PPGSessionMachine * sm,long pid)2502 static PPGPushMachine *find_ppg_push_machine_using_pid(PPGSessionMachine *sm,
2503                                                    long pid)
2504 {
2505     PPGPushMachine *pm;
2506 
2507     gw_assert(pid >= 0);
2508     session_machine_assert(sm);
2509 
2510     pm = gwlist_search(sm->push_machines, &pid, push_has_pid);
2511 
2512     return pm;
2513 }
2514 
push_has_pi_push_id(void * a,void * b)2515 static int push_has_pi_push_id(void *a, void *b)
2516 {
2517     Octstr *pi_push_id;
2518     PPGPushMachine *pm;
2519 
2520     pi_push_id = b;
2521     pm = a;
2522 
2523     return octstr_compare(pm->pi_push_id, pi_push_id) == 0;
2524 }
2525 
find_ppg_push_machine_using_pi_push_id(PPGSessionMachine * sm,Octstr * pi_push_id)2526 static PPGPushMachine *find_ppg_push_machine_using_pi_push_id(
2527     PPGSessionMachine *sm, Octstr *pi_push_id)
2528 {
2529     PPGPushMachine *pm;
2530 
2531     gw_assert(pi_push_id);
2532     session_machine_assert(sm);
2533 
2534     pm = gwlist_search(sm->push_machines, pi_push_id, push_has_pi_push_id);
2535 
2536     return pm;
2537 }
2538 
find_unit_ppg_push_machine_using_pi_push_id(Octstr * pi_push_id)2539 static PPGPushMachine *find_unit_ppg_push_machine_using_pi_push_id(
2540     Octstr *pi_push_id)
2541 {
2542     PPGPushMachine *pm;
2543 
2544     gw_assert(pi_push_id);
2545     pm = gwlist_search(ppg_unit_pushes, pi_push_id, push_has_pi_push_id);
2546 
2547     return pm;
2548 }
2549 
2550 /*
2551  * Store a new value of the push attribute into a push machine. It is to be
2552  * found from the list of unit pushes, if connectionless push was asked
2553  * (sm == NULL), otherwise from the the push list of the session machine sm.
2554  * Returns updated push machine and session machine (this one has an updated
2555  * push machines list).
2556  */
update_push_data_with_attribute(PPGSessionMachine ** sm,PPGPushMachine * qm,long reason,long status)2557 static PPGPushMachine *update_push_data_with_attribute(PPGSessionMachine **sm,
2558     PPGPushMachine *qm, long reason, long status)
2559 {
2560     push_machine_assert(qm);
2561 
2562     switch (status) {
2563     case PAP_UNDELIVERABLE1:
2564          qm->message_state = PAP_UNDELIVERABLE;
2565          qm->code = PAP_BAD_REQUEST;
2566     break;
2567 
2568     case PAP_UNDELIVERABLE2:
2569         qm->code = reason;
2570         qm->message_state = PAP_UNDELIVERABLE;
2571         qm->desc = describe_code(reason);
2572     break;
2573 
2574     case PAP_ABORTED:
2575         qm->message_state = status;
2576         qm->code = ota_abort_to_pap(reason);
2577         qm->event_time = set_time();
2578         qm->desc = describe_code(reason);
2579     break;
2580 
2581     case PAP_DELIVERED1:
2582         qm->message_state = PAP_DELIVERED;
2583         qm->delivery_method = PAP_UNCONFIRMED;
2584         qm->event_time = set_time();
2585     break;
2586 
2587     case PAP_DELIVERED2:
2588         qm->message_state = PAP_DELIVERED;
2589         qm->delivery_method = PAP_CONFIRMED;
2590         qm->event_time = set_time();
2591     break;
2592 
2593     case PAP_EXPIRED:
2594         qm->message_state = PAP_EXPIRED;
2595         qm->event_time = set_time();
2596         qm->desc = describe_code(reason);
2597     break;
2598 
2599     case PAP_PENDING:
2600         qm->message_state = PAP_PENDING;
2601     break;
2602 
2603     default:
2604         error(0, "WAP_PUSH_PPG: update_push_data_with_attribute: Non"
2605               " existing push machine status: %ld", status);
2606     break;
2607     }
2608 
2609     if (*sm != NULL){
2610         gwlist_delete_matching((**sm).push_machines, &qm->push_id, push_has_pid);
2611         gwlist_append((**sm).push_machines, qm);
2612         gwlist_delete_equal(ppg_machines, *sm);
2613         gwlist_append(ppg_machines, *sm);
2614     } else {
2615         gwlist_delete_matching(ppg_unit_pushes, &qm->push_id, push_has_pid);
2616         gwlist_append(ppg_unit_pushes, qm);
2617     }
2618 
2619     return qm;
2620 }
2621 
2622 /*
2623  * Store session id, client port and caps list received from application layer.
2624  */
update_session_data(PPGSessionMachine * m,long sid,long port,List * caps)2625 static PPGSessionMachine *update_session_data(PPGSessionMachine *m,
2626                                               long sid, long port, List *caps)
2627 {
2628     session_machine_assert(m);
2629     gw_assert(sid >= 0);
2630 
2631     m->session_id = sid;
2632     m->addr_tuple->remote->port = port;
2633     m->client_capabilities = wsp_cap_duplicate_list(caps);
2634 
2635     gwlist_delete_equal(ppg_machines, m);
2636     gwlist_append(ppg_machines, m);
2637 
2638     return m;
2639 }
2640 
2641 /*
2642  * Convert OTA abort codes (ota 6.3.3) to corresponding PAP status codes. These
2643  * are defined in pap 9.14.5.
2644  */
ota_abort_to_pap(long reason)2645 static long ota_abort_to_pap(long reason)
2646 {
2647     long offset;
2648 
2649     offset = reason - 0xEA;
2650     reason = 5026 + offset;
2651 
2652     return reason;
2653 }
2654 
2655 /*
2656  * Accept connectionless push when PI wants connectionless push and there is
2657  * no sessions open.
2658  */
cless_accepted(WAPEvent * e,PPGSessionMachine * sm)2659 static int cless_accepted(WAPEvent *e, PPGSessionMachine *sm)
2660 {
2661     gw_assert(e->type == Push_Message);
2662     return (e->u.Push_Message.delivery_method == PAP_UNCONFIRMED ||
2663            e->u.Push_Message.delivery_method == PAP_NOT_SPECIFIED) &&
2664            (sm == NULL);
2665 }
2666 
2667 /*
2668  * Application ids start with 0 and -1 means that default (wml.ua) was used.
2669  */
coriented_deliverable(long appid_code)2670 static int coriented_deliverable(long appid_code)
2671 {
2672     return appid_code > -1;
2673 }
2674 
2675 /*
2676  * Compare PAP message timestamp, in PAP message format, and stored in octstr,
2677  * to gm (UTC) broken time. Return true, if before is after now, or if the
2678  * service in question was not requested by PI. PAP time format is defined in
2679  * pap, chapter 9.2.
2680  */
2681 
initialize_time_item_array(long time_data[],struct tm now)2682 static void initialize_time_item_array(long time_data[], struct tm now)
2683 {
2684     time_data[0] = now.tm_year + 1900;
2685     time_data[1] = now.tm_mon + 1;
2686     time_data[2] = now.tm_mday;
2687     time_data[3] = now.tm_hour;
2688     time_data[4] = now.tm_min;
2689     time_data[5] = now.tm_sec;
2690 }
2691 
date_item_compare(Octstr * condition,long time_data,long pos)2692 static int date_item_compare(Octstr *condition, long time_data, long pos)
2693 {
2694     long data;
2695 
2696     if (octstr_parse_long(&data, condition, pos, 10) < 0) {
2697         return 0;
2698     }
2699     if (data < time_data) {
2700         return -1;
2701     }
2702     if (data > time_data) {
2703         return 1;
2704     }
2705 
2706     return 0;
2707 }
2708 
2709 /*
2710  * We do not accept timestamps equalling now. Return true, if the service was
2711  * not requested.
2712  */
deliver_before_test_cleared(Octstr * before,struct tm now)2713 static int deliver_before_test_cleared(Octstr *before, struct tm now)
2714 {
2715     long time_data[6];
2716     long j;
2717 
2718     if (before == NULL)
2719         return 1;
2720 
2721     initialize_time_item_array(time_data, now);
2722     if (date_item_compare(before, time_data[0], 0) == 1)
2723         return 1;
2724     if (date_item_compare(before, time_data[0], 0) == -1)
2725         return 0;
2726 
2727     for (j = 5; j < octstr_len(before); j += 3) {
2728         if (date_item_compare(before, time_data[(j-5)/3 + 1], j) == 1)
2729             return 1;
2730         if (date_item_compare(before, time_data[(j-5)/3 + 1], j) == -1)
2731             return 0;
2732     }
2733 
2734     return 0;
2735 }
2736 
2737 /*
2738  * Ditto. Return true, if after is before now (or the service was not request-
2739  * ed). Do not accept timestamps equalling now.
2740  */
deliver_after_test_cleared(Octstr * after,struct tm now)2741 static int deliver_after_test_cleared(Octstr *after, struct tm now)
2742 {
2743     long time_data[6];
2744     long j;
2745 
2746     if (after == NULL)
2747         return 1;
2748 
2749     initialize_time_item_array(time_data, now);
2750     if (date_item_compare(after, time_data[0], 0) == -1)
2751         return 1;
2752     if (date_item_compare(after, time_data[0], 0) == 1)
2753         return 0;
2754 
2755     for (j = 5; j < octstr_len(after); j += 3) {
2756         if (date_item_compare(after, time_data[(j-5)/3 + 1], j) == -1)
2757             return 1;
2758         if (date_item_compare(after, time_data[(j-5)/3 + 1], j) == 1)
2759             return 0;
2760     }
2761 
2762     return 0;
2763 }
2764 
2765 /*
2766  * We exchange here server and client addresses and ports, because our WDP,
2767  * written for pull, exchange them, too. Similarly server address INADDR_ANY is
2768  * used for compability reasons, when the bearer is ip. When it is SMS, the
2769  * server address is global-sender.
2770  */
set_addr_tuple(Octstr * address,long cliport,long servport,long address_type,List * push_headers)2771 static WAPAddrTuple *set_addr_tuple(Octstr *address, long cliport, long servport,
2772                                     long address_type, List *push_headers)
2773 {
2774     Octstr *cliaddr;
2775     Octstr *from = NULL;
2776     WAPAddrTuple *tuple;
2777 
2778     gw_assert(address);
2779 
2780     if (address_type == ADDR_PLMN) {
2781         from = http_header_value(push_headers, octstr_imm("X-Kannel-From"));
2782         cliaddr = from ? from : global_sender;
2783     } else {
2784         cliaddr = octstr_imm("0.0.0.0");
2785     }
2786 
2787     tuple = wap_addr_tuple_create(address, cliport, cliaddr, servport);
2788 
2789     octstr_destroy(from);
2790     http_header_remove_all(push_headers, "X-Kannel-From");
2791 
2792     return tuple;
2793 }
2794 
2795 /*
2796  * We are not interested about parsing URI fully - we check only does it cont-
2797  * ain application id reserved by WINA or the part containing assigned code.
2798  * Otherwise (regardless of it being an URI or assigned code) we simply pass
2799  * it forward.
2800  * These are defined by WINA at http://www.openmobilealliance.org/tech/
2801  * omna/omna-push-app-id.htm. We recognize both well-known and registered
2802  * values. X-wap-application is not added, it is considired a default.
2803  */
2804 
2805 static char *wina_uri[] =
2806 {   "*",
2807     "push.sia",
2808     "wml.ua",
2809     "wta.ua",
2810     "mms.ua",
2811     "push.syncml",
2812     "loc.ua",
2813     "syncml.dm",
2814     "drm.ua",
2815     "emn.ua",
2816     "wv.ua",
2817     "x-wap-microsoft:localcontent.ua",
2818     "x-wap-microsoft:IMclient.ua",
2819     "x-wap-docomo:imode.mail.ua",
2820     "x-wap-docomo:imode.mr.ua",
2821     "x-wap-docomo:imode.mf.ua",
2822     "x-motorola:location.ua",
2823     "x-motorola:now.ua",
2824     "x-motorola:otaprov.ua",
2825     "x-motorola:browser.ua",
2826     "x-motorola:splash.ua",
2827     "x-wap-nai:mvsw.command",
2828     "x-wap-openwave:iota.ua",
2829     "x-wap-docomo:imode.mail2.ua",
2830     "x-oma-nec:otaprov.ua",
2831     "x-oma-nokia:call.ua"
2832 };
2833 
2834 #define NUMBER_OF_WINA_URIS sizeof(wina_uri)/sizeof(wina_uri[0])
2835 
2836 /*
2837  * X-Wap-Application-Id header is defined in Push Message, chapter 6.2.2.1.
2838  * First check do we a header with an app-encoding field and a coded value.
2839  * If not, try to find push application id from table of wina approved values.
2840  * Return coded value value of application id in question, or an error code:
2841  *        -1, no coded value (but defaults may be applied)
2842  *         0, * (meaning any application acceptable)
2843  *         greater or equal as 1: code for this application id
2844  */
parse_appid_header(Octstr ** appid_content)2845 static long parse_appid_header(Octstr **appid_content)
2846 {
2847     long pos,
2848          coded_value;
2849     size_t i;
2850 
2851     if ((pos = octstr_search(*appid_content, octstr_imm(";"), 0)) >= 0) {
2852         octstr_delete(*appid_content, pos,
2853                       octstr_len(octstr_imm(";app-encoding=")));
2854         octstr_delete(*appid_content, 0, pos);         /* the URI part */
2855 	    return -1;
2856     }
2857 
2858     i = 0;
2859     while (i < NUMBER_OF_WINA_URIS) {
2860         if ((pos = octstr_case_search(*appid_content,
2861                 octstr_imm(wina_uri[i]), 0)) >= 0)
2862             break;
2863         ++i;
2864     }
2865 
2866     if (i == NUMBER_OF_WINA_URIS) {
2867         octstr_destroy(*appid_content);
2868         *appid_content = octstr_format("%ld", 2);      /* assigned number */
2869         return -1;                                     /* for wml ua */
2870     }
2871 
2872     octstr_delete(*appid_content, 0, pos);             /* again the URI */
2873     if ((coded_value = wsp_string_to_application_id(*appid_content)) >= 0) {
2874         octstr_destroy(*appid_content);
2875         *appid_content = octstr_format("%ld", coded_value);
2876         return coded_value;
2877     }
2878 
2879     return -1;
2880 }
2881 
addr_tuple_change_cliport(WAPAddrTuple * tuple,long port)2882 static WAPAddrTuple *addr_tuple_change_cliport(WAPAddrTuple *tuple, long port)
2883 {
2884     WAPAddrTuple *dubble;
2885 
2886     if (tuple == NULL)
2887         return NULL;
2888 
2889     dubble = wap_addr_tuple_create(tuple->remote->address,
2890                                    port,
2891                                    tuple->local->address,
2892                                    tuple->local->port);
2893 
2894     return dubble;
2895 }
2896 
2897 /*
2898  * Pi uses multipart/related content type when communicating with ppg. (see
2899  * pap, Chapter 8) and subtype application/xml.
2900  * Check if push headers are acceptable according this rule. In addition,
2901  * return the field value of Content-Type header, if any and error string if
2902  * none (this string is used by send_bad_message_response).
2903  */
headers_acceptable(List * push_headers,Octstr ** content_header)2904 static int headers_acceptable(List *push_headers, Octstr **content_header)
2905 {
2906     gw_assert(push_headers);
2907     *content_header = http_header_find_first(push_headers, "Content-Type");
2908 
2909     if (*content_header == NULL) {
2910         *content_header = octstr_format("%s", "no content type header found");
2911         goto error;
2912     }
2913 
2914     if (!type_is(*content_header, "multipart/related")) {
2915         goto error;
2916     }
2917 
2918     if (!type_is(*content_header, "application/xml")) {
2919         goto error;
2920     }
2921 
2922     return 1;
2923 
2924 error:
2925     warning(0, "PPG: headers_acceptable: got unacceptable push headers");
2926     return 0;
2927 }
2928 
2929 /*
2930  * Content-Type header field is defined in rfc 1521, chapter 4. We are looking
2931  * after type multipart/related or "multipart/related" and parameter
2932  * type=application/xml or type="application/xml", as required by pap, chapter
2933  * 8.
2934  */
type_is(Octstr * content_header,char * name)2935 static int type_is(Octstr *content_header, char *name)
2936 {
2937     Octstr *quoted_type,
2938            *osname;
2939 
2940     osname = octstr_imm(name);
2941     if (octstr_case_search(content_header, osname, 0) >= 0)
2942         return 1;
2943 
2944     quoted_type = octstr_format("\"%S\"", osname);
2945 
2946     if (octstr_case_search(content_header, quoted_type, 0) >= 0) {
2947         octstr_destroy(quoted_type);
2948         return 1;
2949     }
2950 
2951     octstr_destroy(quoted_type);
2952     return 0;
2953 }
2954 
2955 /*
2956  * Again looking after a parameter, this time of type boundary=XXX or boundary=
2957  * "XXX".
2958  */
get_mime_boundary(List * push_headers,Octstr * content_header,Octstr ** boundary)2959 static int get_mime_boundary(List *push_headers, Octstr *content_header,
2960                              Octstr **boundary)
2961 {
2962     long pos;
2963     Octstr *bos;
2964     int c, quoted = 0;
2965     long bstart;
2966 
2967     pos = 0;
2968     if ((pos = octstr_case_search(content_header,
2969                                   bos = octstr_imm("boundary="), 0)) < 0) {
2970         warning(0, "PPG: get_mime_boundary: no boundary specified");
2971         return -1;
2972     }
2973 
2974     pos += octstr_len(bos);
2975     if (octstr_get_char(content_header, pos) == '"') {
2976         ++pos;
2977         quoted = 1;
2978     }
2979 
2980     bstart = pos;
2981     while ((c = octstr_get_char(content_header, pos)) != -1) {
2982         if (c == ';' || (quoted && c == '"') || (!quoted && c == ' '))
2983              break;
2984         ++pos;
2985     }
2986     *boundary = octstr_copy(content_header, bstart, pos - bstart);
2987 
2988     return 0;
2989 }
2990 
change_header_value(List ** push_headers,char * name,char * value)2991 static void change_header_value(List **push_headers, char *name, char *value)
2992 {
2993     http_header_remove_all(*push_headers, name);
2994     http_header_add(*push_headers, name, value);
2995 }
2996 
2997 /*
2998  * Some application level protocols may use MIME headers. This may cause problems
2999  * to them. (MIME version is a mandatory header).
3000  */
remove_mime_headers(List ** push_headers)3001 static void remove_mime_headers(List **push_headers)
3002 {
3003     http_header_remove_all(*push_headers, "MIME-Version");
3004 }
3005 
3006 /*
3007  * There are headers used only for HTTP POST pi->ppg. (For debugging, mainly.)
3008  */
remove_link_headers(List ** push_headers)3009 static void remove_link_headers(List **push_headers)
3010 {
3011     http_header_remove_all(*push_headers, "Host");
3012 }
3013 
3014 /*
3015  * X-Kannel headers are used to control Kannel ppg.
3016  */
remove_x_kannel_headers(List ** push_headers)3017 static void remove_x_kannel_headers(List **push_headers)
3018 {
3019     http_header_remove_all(*push_headers, "X-Kannel-SMSC");
3020     http_header_remove_all(*push_headers, "X-Kannel-DLR-Url");
3021     http_header_remove_all(*push_headers, "X-Kannel-DLR-Mask");
3022     http_header_remove_all(*push_headers, "X-Kannel-Smsbox-Id");
3023 }
3024 
3025 /*
3026  * Badmessage-response element is redefined in pap, implementation note,
3027  * chapter 5. Do not add to the document a fragment being NULL or empty.
3028  * Return current status of HTTPClient.
3029  */
send_bad_message_response(HTTPClient ** c,Octstr * fragment,int code,int status)3030 static void send_bad_message_response(HTTPClient **c, Octstr *fragment,
3031                                       int code, int status)
3032 {
3033     Octstr *reply_body;
3034 
3035     reply_body = octstr_format("%s",
3036         "<?xml version=\"1.0\"?>"
3037         "<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP 1.0//EN\""
3038                    " \"http://www.wapforum.org/DTD/pap_1.0.dtd\">"
3039         "<pap>"
3040              "<badmessage-response code=\"");
3041     octstr_format_append(reply_body, "%d", code);
3042     octstr_format_append(reply_body, "%s", "\""
3043                   " desc=\"");
3044     octstr_format_append(reply_body, "%s", "Not understood due to malformed"
3045                                            " syntax");
3046     octstr_format_append(reply_body, "%s", "\"");
3047 
3048     if (fragment != NULL && octstr_len(fragment) != 0) {
3049         octstr_format_append(reply_body, "%s", " bad-message-fragment=\"");
3050         octstr_format_append(reply_body, "%S", escape_fragment(fragment));
3051         octstr_format_append(reply_body, "%s", "\"");
3052     }
3053 
3054     octstr_format_append(reply_body, "%s", ">"
3055               "</badmessage-response>"
3056          "</pap>");
3057 
3058     debug("wap.push.ppg", 0, "PPG: send_bad_message_response: telling pi");
3059     send_to_pi(c, reply_body, status);
3060 
3061     octstr_destroy(fragment);
3062 }
3063 
3064 /*
3065  * Push response is defined in pap, chapter 9.3. Mapping between push ids and
3066  * http clients is done by using http_clients. We remove (push id, http client)
3067  * pair from the dictionary after the mapping has been done.
3068  * Return current status of HTTPClient.
3069  */
send_push_response(WAPEvent * e,int status)3070 static HTTPClient *send_push_response(WAPEvent *e, int status)
3071 {
3072     Octstr *reply_body,
3073            *url;
3074     HTTPClient *c;
3075 
3076     gw_assert(e->type == Push_Response);
3077     url = dict_get(urls, e->u.Push_Response.pi_push_id);
3078     dict_remove(urls, e->u.Push_Response.pi_push_id);
3079 
3080     reply_body = octstr_format("%s",
3081         "<?xml version=\"1.0\"?>"
3082         "<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP 1.0//EN\""
3083                    " \"http://www.wapforum.org/DTD/pap_1.0.dtd\">"
3084         "<pap>"
3085              "<push-response push-id=\"");
3086     octstr_format_append(reply_body, "%S", e->u.Push_Response.pi_push_id);
3087     octstr_format_append(reply_body, "%s", "\"");
3088 
3089     if (e->u.Push_Response.sender_name != NULL) {
3090         octstr_format_append(reply_body, "%s",
3091                    " sender-name=\"");
3092         octstr_format_append(reply_body, "%S",
3093             e->u.Push_Response.sender_name);
3094         octstr_format_append(reply_body, "%s", "\"");
3095     }
3096 
3097     if (e->u.Push_Response.reply_time != NULL) {
3098         octstr_format_append(reply_body, "%s",
3099                    " reply-time=\"");
3100         octstr_format_append(reply_body, "%S",
3101             e->u.Push_Response.reply_time);
3102         octstr_format_append(reply_body, "%s", "\"");
3103     }
3104 
3105     if (url != NULL) {
3106         octstr_format_append(reply_body, "%s",
3107                    " sender-address=\"");
3108         octstr_format_append(reply_body, "%S", url);
3109         octstr_format_append(reply_body, "%s", "\"");
3110     }
3111 
3112     octstr_format_append(reply_body, "%s", ">"
3113              "<response-result code =\"");
3114     octstr_format_append(reply_body, "%d", e->u.Push_Response.code);
3115     octstr_format_append(reply_body, "%s", "\"");
3116 
3117     if (e->u.Push_Response.desc != NULL) {
3118         octstr_format_append(reply_body, "%s", " desc=\"");
3119         octstr_format_append(reply_body, "%S", e->u.Push_Response.desc);
3120         octstr_format_append(reply_body, "\"");
3121     }
3122 
3123     octstr_format_append(reply_body, "%s", ">"
3124               "</response-result>"
3125               "</push-response>"
3126           "</pap>");
3127 
3128     octstr_destroy(url);
3129 
3130     c = dict_get(http_clients, e->u.Push_Response.pi_push_id);
3131     dict_remove(http_clients, e->u.Push_Response.pi_push_id);
3132 
3133     debug("wap.push.ppg", 0, "PPG: send_push_response: telling pi");
3134     send_to_pi(&c, reply_body, status);
3135 
3136     wap_event_destroy(e);
3137     return c;
3138 }
3139 
3140 /*
3141  * Ppg notifies pi about duplicate push id by sending a push response document
3142  * to it. Note that we never put the push id to the dict in this case.
3143  * Return current c value.
3144  */
tell_fatal_error(HTTPClient ** c,WAPEvent * e,Octstr * url,int status,int code)3145 static void tell_fatal_error(HTTPClient **c, WAPEvent *e, Octstr *url,
3146                              int status, int code)
3147 {
3148     Octstr *reply_body,
3149            *dos,                      /* temporaries */
3150            *tos,
3151            *sos;
3152 
3153     gw_assert(e->type == Push_Message);
3154     reply_body = octstr_format("%s",
3155         "<?xml version=\"1.0\"?>"
3156         "<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP 1.0//EN\""
3157                    " \"http://www.wapforum.org/DTD/pap_1.0.dtd\">"
3158         "<pap>"
3159              "<push-response push-id=\"");
3160     octstr_format_append(reply_body, "%S", e->u.Push_Message.pi_push_id);
3161     octstr_format_append(reply_body, "%s", "\"");
3162 
3163     octstr_format_append(reply_body, "%s",
3164                    " sender-name=\"");
3165     octstr_format_append(reply_body, "%S", tos = tell_ppg_name());
3166     octstr_format_append(reply_body, "%s", "\"");
3167 
3168     octstr_format_append(reply_body, "%s",
3169                    " reply-time=\"");
3170     octstr_format_append(reply_body, "%S", sos = set_time());
3171     octstr_format_append(reply_body, "%s", "\"");
3172 
3173     octstr_format_append(reply_body, "%s",
3174                    " sender-address=\"");
3175     octstr_format_append(reply_body, "%S", url);
3176     octstr_format_append(reply_body, "%s", "\"");
3177 
3178     octstr_format_append(reply_body, "%s", ">"
3179              "<response-result code =\"");
3180     octstr_format_append(reply_body, "%d", code);
3181     octstr_format_append(reply_body, "%s", "\"");
3182 
3183     octstr_format_append(reply_body, "%s", " desc=\"");
3184     octstr_format_append(reply_body, "%S", dos = describe_code(code));
3185     octstr_format_append(reply_body, "\"");
3186 
3187     octstr_format_append(reply_body, "%s", ">"
3188               "</response-result>"
3189               "</push-response>"
3190          "</pap>");
3191 
3192     debug("wap.push.ppg", 0, "PPG: tell_fatal_error: %s", octstr_get_cstr(dos));
3193     send_to_pi(c, reply_body, status);
3194 
3195     octstr_destroy(dos);
3196     octstr_destroy(tos);
3197     octstr_destroy(sos);
3198     wap_event_destroy(e);
3199 }
3200 
3201 /*
3202  * Does the HTTP reply to pi. Test has HTTPClient disappeared.
3203  * Return current c value.
3204  */
send_to_pi(HTTPClient ** c,Octstr * reply_body,int status)3205 static void send_to_pi(HTTPClient **c, Octstr *reply_body, int status) {
3206     List *reply_headers;
3207 
3208     reply_headers = http_create_empty_headers();
3209     http_header_add(reply_headers, "Content-Type", "application/xml");
3210 
3211     if (*c != NULL)
3212         http_send_reply(*c, status, reply_headers, reply_body);
3213 
3214     octstr_destroy(reply_body);
3215     http_destroy_headers(reply_headers);
3216 }
3217 
3218 /*
3219  * Escape characters not allowed in the value of an attribute. Pap does not
3220  * define escape sequences for message fragments; try common xml ones.
3221  */
3222 
escape_fragment(Octstr * fragment)3223 static Octstr *escape_fragment(Octstr *fragment)
3224 {
3225     long i;
3226     int c;
3227 
3228     i = 0;
3229     while (i < octstr_len(fragment)) {
3230         if ((c = octstr_get_char(fragment, i)) == '"') {
3231             replace_octstr_char(fragment, octstr_imm("&quot;"), &i);
3232         } else if (c == '<') {
3233             replace_octstr_char(fragment, octstr_imm("&lt;"), &i);
3234         } else if (c == '>') {
3235             replace_octstr_char(fragment, octstr_imm("&gt;"), &i);
3236         } else if (c == '&') {
3237             replace_octstr_char(fragment, octstr_imm("&amp;"), &i);
3238         }
3239         ++i;
3240     }
3241 
3242     return fragment;
3243 }
3244 
is_phone_number(long address_type)3245 static int is_phone_number(long address_type)
3246 {
3247     return address_type == ADDR_PLMN;
3248 }
3249 
replace_octstr_char(Octstr * os1,Octstr * os2,long * pos)3250 static void replace_octstr_char(Octstr *os1, Octstr *os2, long *pos)
3251 {
3252     octstr_delete(os1, *pos, 1);
3253     octstr_insert(os1, os2, *pos);
3254     *pos += octstr_len(os2) - 1;
3255 }
3256 
3257 /*
3258  * Check if we have an explicit routing information
3259  *       a) first check x-kannel header
3260  *       b) then ppg user specific routing (if there is any groups; we have none,
3261  *          if pi is trusted)
3262  *       c) then global ppg routing
3263  *       d) if all these failed, return NULL
3264  */
set_smsc_id(List * headers,Octstr * username,int trusted_pi)3265 static Octstr *set_smsc_id(List *headers, Octstr *username, int trusted_pi)
3266 {
3267     Octstr *smsc_id = NULL;
3268 
3269     smsc_id = http_header_value(headers, octstr_imm("X-Kannel-SMSC"));
3270     if (smsc_id) {
3271         return smsc_id;
3272     }
3273 
3274     if (!trusted_pi)
3275         smsc_id = wap_push_ppg_pushuser_smsc_id_get(username);
3276 
3277     smsc_id = smsc_id ?
3278         smsc_id : (ppg_default_smsc ? octstr_duplicate(ppg_default_smsc) : NULL);
3279 
3280     return smsc_id;
3281 }
3282 
3283 /*
3284  * Checking for dlr url, using  following order:
3285  *       a) first check X-Kannel header
3286  *       b) then ppg user specific dlr url (if there is any user group; if pi is
3287  *          trusted, there are none.)
3288  *       c) then global ppg dlr url
3289  *       d) if all these failed, return NULL
3290  */
set_dlr_url(List * headers,Octstr * username,int trusted_pi)3291 static Octstr *set_dlr_url(List *headers, Octstr *username, int trusted_pi)
3292 {
3293     Octstr *dlr_url = NULL;
3294 
3295     dlr_url = http_header_value(headers, octstr_imm("X-Kannel-DLR-Url"));
3296     if (dlr_url) {
3297         return dlr_url;
3298     }
3299 
3300     if (!trusted_pi)
3301         dlr_url = wap_push_ppg_pushuser_dlr_url_get(username);
3302 
3303     dlr_url = dlr_url ?
3304         dlr_url : (ppg_dlr_url ? octstr_duplicate(ppg_dlr_url) : NULL);
3305 
3306     return dlr_url;
3307 }
3308 
3309 /*
3310  * Checking for dlr mask. Mask without dlr url is of course useless.
3311  * We reject (some) non-meaningfull values of dlr_mask. Value indic-
3312  * ating rejection is 0.
3313  */
set_dlr_mask(List * headers,Octstr * dlr_url)3314 static long set_dlr_mask(List *headers, Octstr *dlr_url)
3315 {
3316     Octstr *dlrmaskos;
3317     long dlr_mask;
3318     long masklen;
3319 
3320     dlrmaskos = http_header_value(headers, octstr_imm("X-Kannel-DLR-Mask"));
3321     if (dlrmaskos == NULL) {
3322         return 0;
3323     }
3324 
3325     if ((masklen = octstr_parse_long(&dlr_mask, dlrmaskos, 0, 10)) != -1 &&
3326              masklen == octstr_len(dlrmaskos) &&
3327              dlr_mask >= -1 && dlr_mask <= 31) {
3328          octstr_destroy(dlrmaskos);
3329          return dlr_mask;
3330     }
3331 
3332     warning(0, "unparsable dlr mask, rejected");
3333     octstr_destroy(dlrmaskos);
3334     return 0;
3335 }
3336 
3337 /*
3338  * Checking for dlr smsbox id, using  following order:
3339  *       a) first check X-Kannel header
3340  *       b) then ppg user specific smsbox id, if there is any group; if pi
3341  *          is trusted, there are none
3342  *       c) then global ppg smsbox id
3343  *       d) if all these failed, return NULL
3344  */
3345 
set_smsbox_id(List * headers,Octstr * username,int trusted_pi)3346 static Octstr *set_smsbox_id(List *headers, Octstr *username, int trusted_pi)
3347 {
3348     Octstr *smsbox_id = NULL;
3349 
3350     smsbox_id = http_header_value(headers, octstr_imm("X-Kannel-Smsbox-Id"));
3351     if (smsbox_id != NULL) {
3352         return smsbox_id;
3353     }
3354 
3355     if (!trusted_pi)
3356         smsbox_id = wap_push_ppg_pushuser_smsbox_id_get(username);
3357 
3358     smsbox_id = smsbox_id ?
3359         smsbox_id : (ppg_smsbox_id ? octstr_duplicate(ppg_smsbox_id) : NULL);
3360 
3361     return smsbox_id;
3362 
3363 }
3364 
3365 /*
3366  * Service is ppg core group only configuration variable
3367  */
set_service_name(void)3368 static Octstr *set_service_name(void)
3369 {
3370     return octstr_duplicate(service_name);
3371 }
3372 
3373 
3374 
3375 
3376