2005-03-23 05:55:16 +00:00
|
|
|
/*
|
|
|
|
* Mbuni - Open Source MMS Gateway
|
|
|
|
*
|
|
|
|
* Email2MMS and MM4 (incoming) interface
|
|
|
|
*
|
|
|
|
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
|
|
|
*
|
|
|
|
* Paul Bagyenda <bagyenda@dsmagic.com>
|
|
|
|
*
|
|
|
|
* This program is free software, distributed under the terms of
|
|
|
|
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
2005-03-10 08:01:02 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
#include "mms_queue.h"
|
2005-09-01 10:26:36 +00:00
|
|
|
#include "mmsc_cfg.h"
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2005-09-01 10:26:36 +00:00
|
|
|
static MmscSettings *settings;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
static Octstr *xfrom;
|
|
|
|
static Octstr *xto;
|
|
|
|
static Octstr *xproxy;
|
|
|
|
|
|
|
|
enum {TPLMN, TEMAIL, TOTHER} ttype;
|
|
|
|
|
|
|
|
static int find_own(int i, int argc, char *argv[]);
|
2005-09-07 10:10:41 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
static void fixup_recipient(void);
|
|
|
|
static void fixup_sender(void);
|
|
|
|
|
2006-02-17 11:48:33 +00:00
|
|
|
static mCfg *cfg;
|
2005-03-10 08:01:02 +00:00
|
|
|
static List *proxyrelays;
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int cfidx;
|
|
|
|
Octstr *fname;
|
2005-07-04 09:14:47 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
MIMEEntity *mm;
|
|
|
|
MmsMsg *msg;
|
|
|
|
|
|
|
|
Octstr *email;
|
2006-02-28 10:36:36 +00:00
|
|
|
Octstr *home_mmsc = NULL;
|
2006-10-12 15:21:46 +00:00
|
|
|
List *headers;
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
mms_lib_init();
|
|
|
|
|
|
|
|
srandom(time(NULL));
|
|
|
|
|
|
|
|
cfidx = get_and_set_debugs(argc, argv, find_own);
|
|
|
|
|
|
|
|
if (argv[cfidx] == NULL)
|
|
|
|
fname = octstr_imm("mmsc.conf");
|
|
|
|
else
|
|
|
|
fname = octstr_create(argv[cfidx]);
|
|
|
|
|
2006-02-17 11:48:33 +00:00
|
|
|
cfg = mms_cfg_read(fname);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-02-17 11:48:33 +00:00
|
|
|
if (cfg == NULL)
|
2005-03-10 08:01:02 +00:00
|
|
|
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
|
|
|
|
|
|
|
|
octstr_destroy(fname);
|
|
|
|
|
|
|
|
info(0, "----------------------------------------");
|
|
|
|
info(0, " MMSC Email2MMS Tool version %s starting", MMSC_VERSION);
|
2005-07-04 09:14:47 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
/* Load settings. */
|
2005-09-01 10:26:36 +00:00
|
|
|
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-02-17 11:48:33 +00:00
|
|
|
mms_cfg_destroy(cfg);
|
2006-01-11 05:29:21 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
if (!settings)
|
|
|
|
panic(0, "No global MMSC configuration!");
|
|
|
|
|
|
|
|
if (!xto || !xfrom)
|
|
|
|
panic(0, "usage: %s -f from -t to!", argv[0]);
|
|
|
|
|
|
|
|
/* normalize recipient address, then if phone number,
|
|
|
|
* check whether we are allowed to process.
|
|
|
|
*/
|
|
|
|
fixup_recipient();
|
|
|
|
fixup_sender();
|
|
|
|
|
2006-02-28 10:36:36 +00:00
|
|
|
if (xto && ttype == TPLMN) /* Get the home mmsc domain for this recipient. */
|
|
|
|
home_mmsc = settings->mms_resolvefuncs->mms_resolve(xto,
|
|
|
|
settings->mms_resolver_module_data,
|
|
|
|
settings, proxyrelays);
|
|
|
|
if (!xto ||
|
|
|
|
(ttype == TPLMN && (!home_mmsc ||
|
|
|
|
!is_allowed_host(home_mmsc,
|
|
|
|
settings->email2mmsrelay_hosts)))) {
|
|
|
|
error(0, " Not allowed to send to this recipient %s, resolved mmsc=%s!",
|
|
|
|
xto ? octstr_get_cstr(xto) : "(null)",
|
|
|
|
home_mmsc ? octstr_get_cstr(home_mmsc) : "(null)");
|
2006-01-11 05:29:21 +00:00
|
|
|
mms_lib_shutdown();
|
2005-03-10 08:01:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
email = octstr_read_pipe(stdin);
|
|
|
|
|
|
|
|
if (!email || octstr_len(email) == 0) {
|
|
|
|
error(0, "Empty email message!");
|
2006-01-11 05:29:21 +00:00
|
|
|
mms_lib_shutdown();
|
2005-03-10 08:01:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mm = mime_octstr_to_entity(email)) == NULL) {
|
|
|
|
error(0, "Unable to decode mime entity!");
|
2006-01-11 05:29:21 +00:00
|
|
|
mms_lib_shutdown();
|
2005-03-10 08:01:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
octstr_destroy(email);
|
|
|
|
|
|
|
|
/* Take the entity, recode it --> remove base64 stuff, split headers. */
|
|
|
|
unbase64_mimeparts(mm);
|
|
|
|
unpack_mimeheaders(mm);
|
|
|
|
|
2005-07-08 12:32:27 +00:00
|
|
|
/* Delete some headers... */
|
2006-10-12 15:21:46 +00:00
|
|
|
headers = _x_mime_entity_headers(mm);
|
|
|
|
http_header_remove_all(headers, "Received");
|
|
|
|
http_header_remove_all(headers, "X-MimeOLE");
|
|
|
|
http_header_remove_all(headers, "X-Mailer");
|
|
|
|
mime_replace_headers(mm, headers);
|
|
|
|
http_destroy_headers(headers);
|
2005-07-08 12:32:27 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
/* Now convert from mime to MMS message. */
|
|
|
|
msg = mms_frommime(mm);
|
|
|
|
mime_entity_destroy(mm);
|
|
|
|
|
|
|
|
if (!msg) {
|
|
|
|
error(0, "Unable to create MM!");
|
2006-01-11 05:29:21 +00:00
|
|
|
mms_lib_shutdown();
|
2005-03-10 08:01:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(mms_messagetype(msg)) {
|
|
|
|
case MMS_MSGTYPE_SEND_REQ:
|
2006-02-28 10:36:36 +00:00
|
|
|
if (ttype != TPLMN)
|
|
|
|
error(0, "Not allowed to send to non-phone recipient, to=%s!", octstr_get_cstr(xto));
|
2006-10-12 15:21:46 +00:00
|
|
|
|
2006-02-28 10:36:36 +00:00
|
|
|
else {
|
2006-10-12 15:21:46 +00:00
|
|
|
List *lto = gwlist_create();
|
2005-03-10 08:01:02 +00:00
|
|
|
Octstr *qf;
|
|
|
|
Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
|
|
|
|
Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID"));
|
|
|
|
Octstr *dreport = mms_get_header_value(msg,
|
|
|
|
octstr_imm("X-Mms-Delivery-Report"));
|
|
|
|
char *err;
|
|
|
|
Octstr *rto;
|
|
|
|
int dlr;
|
|
|
|
|
|
|
|
octstr_format_append(xto, "/TYPE=PLMN");
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_append(lto, xto);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
if (dreport &&
|
|
|
|
octstr_case_compare(dreport, octstr_imm("Yes")) == 0)
|
|
|
|
dlr = 1;
|
|
|
|
else
|
|
|
|
dlr = 0;
|
|
|
|
|
2005-04-14 11:27:23 +00:00
|
|
|
qf = mms_queue_add(xfrom, lto, NULL, xproxy, NULL,
|
|
|
|
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
|
|
|
|
NULL, NULL,
|
2005-09-07 10:10:41 +00:00
|
|
|
NULL, NULL,
|
2006-05-03 13:52:40 +00:00
|
|
|
NULL,
|
2005-04-14 11:27:23 +00:00
|
|
|
dlr,
|
|
|
|
octstr_get_cstr(settings->global_queuedir),
|
|
|
|
settings->host_alias);
|
2005-03-10 08:01:02 +00:00
|
|
|
if (qf) {
|
|
|
|
|
|
|
|
info(0, "Email2MMS Queued message to %s from %s (via %s) => %s",
|
|
|
|
octstr_get_cstr(xto), octstr_get_cstr(xfrom),
|
|
|
|
xproxy ? octstr_get_cstr(xproxy) : "(None)", octstr_get_cstr(qf));
|
|
|
|
octstr_destroy(qf);
|
|
|
|
|
|
|
|
/* Queue our response to the chap. */
|
|
|
|
err = "Ok";
|
|
|
|
} else
|
|
|
|
err = "Error-transient-failure";
|
|
|
|
if (xproxy) {
|
|
|
|
MmsMsg *mresp;
|
|
|
|
List *xlto;
|
|
|
|
mresp = mms_sendconf(err, octstr_get_cstr(msgid),
|
|
|
|
transid ? octstr_get_cstr(transid) : "001",
|
2005-03-21 16:11:51 +00:00
|
|
|
0,MS_1_1);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
rto = octstr_format("system-user@%S", xproxy);
|
2006-10-12 15:21:46 +00:00
|
|
|
xlto = gwlist_create();
|
|
|
|
gwlist_append(xlto, rto);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2005-04-14 11:27:23 +00:00
|
|
|
qf = mms_queue_add(settings->system_user, xlto, NULL,
|
2005-03-10 08:01:02 +00:00
|
|
|
xproxy, NULL,
|
|
|
|
0, time(NULL) + settings->default_msgexpiry,
|
2005-04-14 11:27:23 +00:00
|
|
|
mresp, NULL,
|
|
|
|
NULL, NULL,
|
2005-09-07 10:10:41 +00:00
|
|
|
NULL, NULL,
|
2006-05-03 13:52:40 +00:00
|
|
|
NULL,
|
2005-04-14 11:27:23 +00:00
|
|
|
0,
|
|
|
|
octstr_get_cstr(settings->global_queuedir),
|
|
|
|
settings->host_alias);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(xlto, (gwlist_item_destructor_t *)octstr_destroy);
|
2005-03-10 08:01:02 +00:00
|
|
|
mms_destroy(mresp);
|
|
|
|
octstr_destroy(qf);
|
|
|
|
}
|
|
|
|
|
|
|
|
mms_log("Received", xfrom, lto,
|
2005-03-21 16:11:51 +00:00
|
|
|
-1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL,NULL);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(lto,NULL);
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_destroy(transid);
|
|
|
|
octstr_destroy(msgid);
|
|
|
|
if (dreport)
|
|
|
|
octstr_destroy(dreport);
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_MSGTYPE_SEND_CONF:
|
|
|
|
{
|
|
|
|
Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID"));
|
|
|
|
Octstr *qf = mms_getqf_fromtransid(transid);
|
|
|
|
|
|
|
|
octstr_destroy(transid);
|
|
|
|
if (qf) {
|
|
|
|
MmsEnvelope *e = mms_queue_readenvelope(octstr_get_cstr(qf),
|
|
|
|
octstr_get_cstr(settings->mm4_queuedir),
|
|
|
|
1);
|
|
|
|
if (!e)
|
|
|
|
warning(0, "Received confirm MMS but cannot find message %s [%s] in queue!",
|
|
|
|
octstr_get_cstr(transid),
|
|
|
|
octstr_get_cstr(qf));
|
|
|
|
else {
|
|
|
|
MmsEnvelopeTo *t;
|
|
|
|
int i, n;
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0, n = gwlist_len(e->to); i<n; i++)
|
|
|
|
if ((t = gwlist_get(e->to, i)) != NULL)
|
2005-03-10 08:01:02 +00:00
|
|
|
t->process = 0; /* Should make it go away. */
|
|
|
|
mms_queue_update(e);
|
|
|
|
info(0, "Email2MMS received send conf from proxy %s to %s from %s => %s",
|
|
|
|
octstr_get_cstr(xproxy), octstr_get_cstr(xto),
|
|
|
|
octstr_get_cstr(xfrom),
|
|
|
|
octstr_get_cstr(qf));
|
|
|
|
}
|
|
|
|
|
|
|
|
} else
|
|
|
|
warning(0, "Received confirm MMS but cannot find message %s in queue!",
|
|
|
|
octstr_get_cstr(transid));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MMS_MSGTYPE_DELIVERY_IND:
|
2006-02-28 10:36:36 +00:00
|
|
|
if (ttype != TPLMN) /* We only send to phones from this interface */
|
2005-03-10 08:01:02 +00:00
|
|
|
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
2006-02-28 10:36:36 +00:00
|
|
|
else {
|
2006-10-12 15:21:46 +00:00
|
|
|
List *lto = gwlist_create();
|
2005-03-10 08:01:02 +00:00
|
|
|
Octstr *qf;
|
2005-04-14 11:27:23 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
octstr_format_append(xto, "/TYPE=PLMN");
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_append(lto, xto);
|
2005-04-14 11:27:23 +00:00
|
|
|
qf = mms_queue_add(xfrom, lto, NULL,
|
2005-03-10 08:01:02 +00:00
|
|
|
xproxy, NULL,
|
2005-04-14 11:27:23 +00:00
|
|
|
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
|
2005-09-07 10:10:41 +00:00
|
|
|
NULL, NULL,
|
|
|
|
NULL, NULL,
|
2006-05-03 13:52:40 +00:00
|
|
|
NULL,
|
2005-04-14 11:27:23 +00:00
|
|
|
0,
|
|
|
|
octstr_get_cstr(settings->global_queuedir),
|
|
|
|
settings->host_alias);
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(lto, NULL);
|
2005-03-10 08:01:02 +00:00
|
|
|
if (qf) {
|
|
|
|
info(0, "Email2MMS Queued DLR from proxy %s to %s from %s => %s",
|
|
|
|
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
|
|
|
|
octstr_get_cstr(qf));
|
|
|
|
|
|
|
|
octstr_destroy(qf);
|
|
|
|
}
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(lto, NULL);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_MSGTYPE_READ_REC_IND:
|
|
|
|
|
|
|
|
mms_convert_readrec2readorig(msg);
|
|
|
|
|
|
|
|
/* Fall through. */
|
|
|
|
case MMS_MSGTYPE_READ_ORIG_IND:
|
2006-02-28 10:36:36 +00:00
|
|
|
if (ttype != TPLMN) /* We only send to phones from this interface */
|
2005-03-10 08:01:02 +00:00
|
|
|
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
2006-02-28 10:36:36 +00:00
|
|
|
else {
|
2006-10-12 15:21:46 +00:00
|
|
|
List *lto = gwlist_create();
|
2005-03-10 08:01:02 +00:00
|
|
|
Octstr *qf;
|
|
|
|
|
|
|
|
octstr_format_append(xto, "/TYPE=PLMN");
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_append(lto, xto);
|
2005-04-14 11:27:23 +00:00
|
|
|
qf = mms_queue_add(xfrom, lto, NULL,
|
2005-03-10 08:01:02 +00:00
|
|
|
xproxy, NULL,
|
2005-04-14 11:27:23 +00:00
|
|
|
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
|
|
|
|
NULL, NULL,
|
2005-09-07 10:10:41 +00:00
|
|
|
NULL, NULL,
|
2006-05-03 13:52:40 +00:00
|
|
|
NULL,
|
2005-04-14 11:27:23 +00:00
|
|
|
0,
|
|
|
|
octstr_get_cstr(settings->global_queuedir),
|
|
|
|
settings->host_alias);
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(lto, NULL);
|
2005-03-10 08:01:02 +00:00
|
|
|
if (qf) {
|
|
|
|
info(0, "Email2MMS Queued read report from proxy %s to %s from %s => %s",
|
|
|
|
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
|
|
|
|
octstr_get_cstr(qf));
|
|
|
|
|
|
|
|
octstr_destroy(qf);
|
|
|
|
}
|
|
|
|
|
2005-04-14 11:27:23 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(lto, NULL);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
int x = mms_messagetype(msg);
|
|
|
|
warning(0, "Unexpected message type: %d=>%s",
|
|
|
|
x,
|
|
|
|
mms_message_type_to_cstr(x));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-02-28 10:36:36 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
mms_destroy(msg);
|
2006-01-11 05:29:21 +00:00
|
|
|
mms_lib_shutdown();
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int find_own(int i, int argc, char *argv[])
|
|
|
|
{
|
|
|
|
if (argv[i][1] == 'f')
|
|
|
|
if (i + 1 < argc) {
|
|
|
|
xfrom = octstr_create(argv[i+1]);
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
else if (argv[i][1] == 't') /* recipient. */
|
|
|
|
if (i + 1 < argc) {
|
|
|
|
xto = octstr_create(argv[i+1]);
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
else if (argv[i][1] == 'p') /* Proxy name if any. */
|
|
|
|
if (i + 1 < argc) {
|
|
|
|
xproxy = octstr_create(argv[i+1]);
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void fixup_recipient(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
Octstr *typ = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
if (!xto) xto = octstr_imm("");
|
|
|
|
i = octstr_search_char(xto, '@', 0);
|
|
|
|
if (i>0)
|
|
|
|
octstr_delete(xto, i, octstr_len(xto));
|
|
|
|
|
|
|
|
i = octstr_search(xto, octstr_imm("/TYPE="), 0);
|
|
|
|
if (i > 0) {
|
|
|
|
typ = octstr_copy(xto, i+1, octstr_len(xto));
|
|
|
|
octstr_delete(xto, i, octstr_len(xto));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isphonenum(xto) &&
|
|
|
|
(!typ || octstr_str_compare(typ, "TYPE=PLMN") == 0)) { /* A phone number. */
|
|
|
|
normalize_number(octstr_get_cstr(settings->unified_prefix), &xto);
|
|
|
|
ttype = TPLMN;
|
|
|
|
} else { /* For now everything else is email. */
|
|
|
|
ttype = TEMAIL;
|
|
|
|
}
|
|
|
|
octstr_destroy(typ);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fixup_sender(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
if (!xfrom) xfrom = octstr_imm("");
|
|
|
|
i = octstr_search_char(xfrom, '@', 0);
|
|
|
|
if (i>0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
i = octstr_search(xfrom, octstr_imm("/TYPE="), 0);
|
|
|
|
if (i > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (isphonenum(xfrom))
|
|
|
|
octstr_append(xfrom, octstr_imm("/TYPE=PLMN"));
|
|
|
|
else
|
|
|
|
octstr_append(xfrom, octstr_imm("@unknown"));
|
|
|
|
}
|