Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

138 lines (129 sloc) 3.683 kb
#include "die.h"
#include "env.h"
#include "str.h"
#include "stralloc.h"
static stralloc realsender;
static int decode_srs(const char *s)
{
/* Format: SRS0=HHH=TT=DOMAIN=USER@example.com */
/* Format: SRS1=HHH=forward.com==HHH=TT=DOMAIN=USER@example.com */
char sep;
int at;
int sep1;
int sep2;
if ((sep = *s++) == 0)
return 0;
if (s[at = str_rchr(s,'@')] == 0)
return 0;
for (sep2 = at - 1; sep2 > 1 && s[sep2] != '='; sep2--)
;
/* s+sep2 = "=USER@..." */
for (sep1 = sep2 - 1; sep1 > 1 && s[sep1] != '='; sep1--)
;
/* s+sep1 = "=DOMAIN=USER@..." */
if (sep2 <= 0)
return 0;
++sep1;
++sep2;
if (!stralloc_copyb(&realsender,s+sep2,at-sep2)) die_nomem();
if (!stralloc_append(&realsender,"@")) die_nomem();
if (!stralloc_catb(&realsender,s+sep1,sep2-sep1-1)) die_nomem();
if (!stralloc_0(&realsender)) die_nomem();
return 1;
}
static int is_hex(int ch)
{
return (ch >= '0' && ch <= '9')
|| (ch >= 'a' && ch <= 'f')
|| (ch >= 'A' && ch <= 'F');
}
static int is_batv_tag(const char *s, int len)
{
/* The BATV standard says the PRVS tag is KDDDSSSSSS, where K and D
* are decimal digits, and S is hexadecimal. However most tags found
* in the wild only contain DDDSSSSSS. There is also appears to be an
* alternate format of DDDSSSSSSSS. This routine handles all of them
* simply by looking for a string of hexadecimal characters at least 9
* characters long. */
if (len >= 9) {
for (; len > 0; --len, ++s) {
if (!is_hex(*s))
return 0;
}
return 1;
}
return 0;
}
static int decode_prvs(const char *s)
{
/* The BATV standard says the user part should have the format
* "tag-type=tag-val=loc-core" where "loc-core" is the original local
* address, but all the examples I could find in actual use had the
* last two parts reversed. What a mess. So, I have to check if
* either the first or second part is a valid prvs tag, and use the
* other one. */
int at;
int sep;
if (s[at = str_rchr(s,'@')] == 0)
return 0;
/* Format: prvs=TAG=USER@example.com */
for (sep = 5; sep < at && s[sep] != '='; ++sep)
;
if (sep >= at)
return 0;
if (is_batv_tag(s+5,sep-5)) {
if (!stralloc_copys(&realsender,s+sep+1)) die_nomem();
if (!stralloc_0(&realsender)) die_nomem();
return 1;
}
/* Format: prvs=USER=TAG@example.com */
for (sep = at - 1; sep > 5 && s[sep] != '='; --sep)
;
if (is_batv_tag(s + sep + 1, at - sep - 1)) {
if (!stralloc_copyb(&realsender,s+5,sep-5)) die_nomem();
if (!stralloc_cats(&realsender,s+at)) die_nomem();
if (!stralloc_0(&realsender)) die_nomem();
return 1;
}
return 0;
}
static int decode_btv1(const char* s)
{
/* Other implementations of BATV use "btv1" instead of "prvs" and two
* equal signs instead of one as a delimiter, and a different tag value. */
int at;
int sep;
if (s[at = str_rchr(s,'@')] == 0)
return 0;
/* Format: btv1==DDDSSSSSSSS==USER@example.com */
if (s[4] == '=' && s[5] == '=') {
for (sep = at - 1; sep > 6; --sep) {
if (s[sep] == '=' && s[sep+1] == '=') {
if (is_batv_tag(s+6,sep-6)) {
if (!stralloc_copys(&realsender,s+sep+2)) die_nomem();
if (!stralloc_0(&realsender)) die_nomem();
return 1;
}
break;
}
}
}
return 0;
}
const char *get_sender(void)
{
const char *s;
if ((s = env_get("SENDER")) != 0) {
if ((str_start(s,"SRS0")
|| str_start(s,"SRS1"))
&& decode_srs(s))
s = realsender.s;
else if (str_start(s, "prvs=")
&& decode_prvs(s))
s = realsender.s;
else if (str_start(s, "btv1=")
&& decode_btv1(s))
s = realsender.s;
}
return s;
}
Jump to Line
Something went wrong with that request. Please try again.