406 lines
11 KiB
C
406 lines
11 KiB
C
/*
|
|
* 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)
|
|
*/
|
|
|
|
#include <signal.h>
|
|
#include "mms_queue.h"
|
|
#include "mms_util.h"
|
|
|
|
static MmsBoxSettings *settings;
|
|
|
|
static Octstr *xfrom;
|
|
static Octstr *xto;
|
|
static Octstr *xproxy;
|
|
|
|
enum {TPLMN, TEMAIL, TOTHER} ttype;
|
|
|
|
static int find_own(int i, int argc, char *argv[]);
|
|
static int isphonenum(Octstr *s);
|
|
static void fixup_recipient(void);
|
|
static void fixup_sender(void);
|
|
|
|
static Cfg *cfg;
|
|
static List *proxyrelays;
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int cfidx;
|
|
Octstr *fname;
|
|
CfgGroup *grp;
|
|
Octstr *log, *alog;
|
|
long loglevel;
|
|
MIMEEntity *mm;
|
|
MmsMsg *msg;
|
|
|
|
Octstr *email;
|
|
|
|
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]);
|
|
|
|
cfg = cfg_create(fname);
|
|
|
|
if (cfg_read(cfg) == -1)
|
|
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);
|
|
|
|
grp = cfg_get_single_group(cfg, octstr_imm("core"));
|
|
log = cfg_get(grp, octstr_imm("log-file"));
|
|
if (log != NULL) {
|
|
if (cfg_get_integer(&loglevel, grp, octstr_imm("log-level")) == -1)
|
|
loglevel = 0;
|
|
log_open(octstr_get_cstr(log), loglevel, GW_NON_EXCL);
|
|
octstr_destroy(log);
|
|
}
|
|
|
|
|
|
/* Get access log and open it. */
|
|
alog = cfg_get(grp, octstr_imm("access-log"));
|
|
if (alog) {
|
|
alog_open(octstr_get_cstr(alog), 1, 1);
|
|
octstr_destroy(alog);
|
|
}
|
|
|
|
/* Load proxy relays. */
|
|
|
|
proxyrelays = mms_proxy_relays(cfg);
|
|
|
|
/* Load settings. */
|
|
settings = mms_load_mmsbox_settings(cfg);
|
|
|
|
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();
|
|
|
|
if (!xto ||
|
|
(ttype == TPLMN && !does_prefix_match(settings->email2mmsrelay_prefixes, xto))) {
|
|
error(0, " Not allowed to send to this recipient %s!",
|
|
xto ? octstr_get_cstr(xto) : "(null)");
|
|
return -1;
|
|
}
|
|
|
|
|
|
email = octstr_read_pipe(stdin);
|
|
|
|
if (!email || octstr_len(email) == 0) {
|
|
error(0, "Empty email message!");
|
|
return -1;
|
|
}
|
|
|
|
if ((mm = mime_octstr_to_entity(email)) == NULL) {
|
|
error(0, "Unable to decode mime entity!");
|
|
return -1;
|
|
}
|
|
octstr_destroy(email);
|
|
|
|
/* Take the entity, recode it --> remove base64 stuff, split headers. */
|
|
unbase64_mimeparts(mm);
|
|
unpack_mimeheaders(mm);
|
|
|
|
/* Now convert from mime to MMS message. */
|
|
msg = mms_frommime(mm);
|
|
mime_entity_destroy(mm);
|
|
|
|
if (!msg) {
|
|
error(0, "Unable to create MM!");
|
|
return -1;
|
|
}
|
|
|
|
switch(mms_messagetype(msg)) {
|
|
case MMS_MSGTYPE_SEND_REQ:
|
|
if (ttype != TPLMN ||/* We only send to phones from this interface */
|
|
!does_prefix_match(settings->email2mmsrelay_prefixes,
|
|
xto)) {
|
|
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
|
} else {
|
|
List *lto = list_create();
|
|
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");
|
|
list_append(lto, xto);
|
|
|
|
if (dreport &&
|
|
octstr_case_compare(dreport, octstr_imm("Yes")) == 0)
|
|
dlr = 1;
|
|
else
|
|
dlr = 0;
|
|
|
|
qf = mms_queue_add(xfrom, lto, msgid, NULL, xproxy, NULL,
|
|
0, time(NULL) + settings->default_msgexpiry, msg, NULL, dlr,
|
|
octstr_get_cstr(settings->global_queuedir));
|
|
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",
|
|
0,MS_1_1);
|
|
|
|
rto = octstr_format("system-user@%S", xproxy);
|
|
xlto = list_create();
|
|
list_append(xlto, rto);
|
|
|
|
qf = mms_queue_add(settings->system_user, xlto, msgid, NULL,
|
|
xproxy, NULL,
|
|
0, time(NULL) + settings->default_msgexpiry,
|
|
mresp, NULL, 0,
|
|
octstr_get_cstr(settings->global_queuedir));
|
|
|
|
list_destroy(xlto, (list_item_destructor_t *)octstr_destroy);
|
|
mms_destroy(mresp);
|
|
octstr_destroy(qf);
|
|
}
|
|
|
|
mms_log("Received", xfrom, lto,
|
|
-1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL,NULL);
|
|
|
|
list_destroy(lto,NULL);
|
|
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;
|
|
|
|
for (i = 0, n = list_len(e->to); i<n; i++)
|
|
if ((t = list_get(e->to, i)) != NULL)
|
|
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:
|
|
if (ttype != TPLMN ||/* We only send to phones from this interface */
|
|
!does_prefix_match(settings->email2mmsrelay_prefixes,
|
|
xto)) {
|
|
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
|
} else {
|
|
List *lto = list_create();
|
|
Octstr *qf;
|
|
Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
|
|
|
|
octstr_format_append(xto, "/TYPE=PLMN");
|
|
list_append(lto, xto);
|
|
qf = mms_queue_add(xfrom, lto, msgid, NULL,
|
|
xproxy, NULL,
|
|
0, time(NULL) + settings->default_msgexpiry, msg, NULL, 0,
|
|
octstr_get_cstr(settings->global_queuedir));
|
|
list_destroy(lto, NULL);
|
|
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);
|
|
}
|
|
|
|
octstr_destroy(msgid);
|
|
list_destroy(lto, NULL);
|
|
}
|
|
break;
|
|
|
|
case MMS_MSGTYPE_READ_REC_IND:
|
|
|
|
mms_convert_readrec2readorig(msg);
|
|
|
|
/* Fall through. */
|
|
case MMS_MSGTYPE_READ_ORIG_IND:
|
|
if (ttype != TPLMN ||/* We only send to phones from this interface */
|
|
!does_prefix_match(settings->email2mmsrelay_prefixes,
|
|
xto)) {
|
|
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
|
} else {
|
|
List *lto = list_create();
|
|
Octstr *qf;
|
|
Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
|
|
|
|
octstr_format_append(xto, "/TYPE=PLMN");
|
|
list_append(lto, xto);
|
|
qf = mms_queue_add(xfrom, lto, msgid, NULL,
|
|
xproxy, NULL,
|
|
0, time(NULL) + settings->default_msgexpiry, msg, NULL,0,
|
|
octstr_get_cstr(settings->global_queuedir));
|
|
list_destroy(lto, NULL);
|
|
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);
|
|
}
|
|
|
|
octstr_destroy(msgid);
|
|
list_destroy(lto, NULL);
|
|
}
|
|
default:
|
|
{
|
|
int x = mms_messagetype(msg);
|
|
warning(0, "Unexpected message type: %d=>%s",
|
|
x,
|
|
mms_message_type_to_cstr(x));
|
|
break;
|
|
}
|
|
}
|
|
mms_destroy(msg);
|
|
|
|
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 int isphonenum(Octstr *s)
|
|
{
|
|
int i = 0, n = octstr_len(s);
|
|
char *cs;
|
|
|
|
if (s && octstr_len(s) >= 1 &&
|
|
octstr_get_cstr(s)[0] == '+')
|
|
i++;
|
|
for ( cs = octstr_get_cstr(s); i<n; i++)
|
|
if (!gw_isdigit(cs[i]))
|
|
return 0;
|
|
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"));
|
|
}
|