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("""), &i);
3232 } else if (c == '<') {
3233 replace_octstr_char(fragment, octstr_imm("<"), &i);
3234 } else if (c == '>') {
3235 replace_octstr_char(fragment, octstr_imm(">"), &i);
3236 } else if (c == '&') {
3237 replace_octstr_char(fragment, octstr_imm("&"), &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