/* * This is designed to be run from asterisk when a call comes in. It * takes two command-line arguments, the first being the (numeric) * caller-ID the call is showing and the second being the extension * being called. * * We just send a small burst of packets to SS20. (A burst, in case of * packet loss.) */ static const char * const target_strings[] = { "98.124.61.90/37867", "2607:f2c0:fffd:1020::90/37867", 0 }; static const char * const sigkeyfile = "/home/mouse/phone-alert/key"; static const char * const failfile = "/home/mouse/phone-alert/fail"; #include #include #include #include #include #include #include #include #include // XXX Linux #include #include #include #include typedef struct skind SKIND; typedef struct taddr TADDR; struct taddr { struct sockaddr *sa; socklen_t salen; int kx; } ; struct skind { int af; int type; int proto; int sock; } ; static char *callerid; static int calleridlen; static char *extension; static int extensionlen; static int reps = 5; static struct timeval now; static int serial; static TADDR *targets; static int ntargets; static SKIND *kinds; static int nkinds; static void *sigkey; static int sigkeylen; static unsigned char *packet; static int packetlen; static unsigned char *xorbuf; static int po_clid; static int po_ext; static int po_sig; static void fail(const char *, ...) __attribute__((__format__(__printf__,1,2),__noreturn__)); static void fail(const char *fmt, ...) { va_list ap; char *s; int l; int fd; va_start(ap,fmt); l = vasprintf(&s,fmt,ap); va_end(ap); fd = open(failfile,O_WRONLY|O_CREAT|O_TRUNC,0666); if (fd >= 0) { if (l > 0) write(fd,s,l); close(fd); } exit(1); } static void handleargs(int ac, char **av) { if (ac < 3) exit(1); callerid = strdup(av[1]); extension = strdup(av[2]); } static void prepare(void) { struct stat stb; struct addrinfo hints; struct addrinfo *ai0; struct addrinfo *ai; int i; int j; int e; int k; char *hs; char *ps; i = open(sigkeyfile,O_RDONLY,0); if (i < 0) fail("%s: open: %s",sigkeyfile,strerror(errno)); if (fstat(i,&stb) < 0) { /* can this happen? maybe EIO.... */ fail("fstat %s: %s",sigkeyfile,strerror(errno)); } if (stb.st_size > 65536) { sigkeylen = 65536; } else { sigkeylen = stb.st_size; } if (sigkeylen < 4) fail("%s: too short (%d)",sigkeyfile,sigkeylen); sigkey = malloc(sigkeylen); j = read(i,sigkey,sigkeylen); if (j < 0) fail("%s: read: %s",sigkeyfile,strerror(errno)); if (j != sigkeylen) fail("%s: read: got %d, expected %d",sigkeyfile,j,sigkeylen); close(i); ntargets = 0; nkinds = 0; for (i=0;target_strings[i];i++) { hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_canonname = 0; hints.ai_addr = 0; hints.ai_next = 0; hs = strdup(target_strings[i]); ps = index(hs,'/'); if (! ps) fail("no / in `%s'",hs); *ps++ = '\0'; ai0 = 0; e = getaddrinfo(hs,ps,&hints,&ai0); free(hs); if (e) fail("looking up %s: %s",target_strings[i],gai_strerror(e)); for (ai=ai0;ai;ai=ai->ai_next) { for (k=nkinds-1;k>=0;k--) { if ( (kinds[k].af == ai->ai_family) && (kinds[k].type == ai->ai_socktype) && (kinds[k].proto == ai->ai_protocol) ) break; } if (k < 0) { k = nkinds ++; kinds = realloc(kinds,nkinds*sizeof(*kinds)); kinds[k].af = ai->ai_family; kinds[k].type = ai->ai_socktype; kinds[k].proto = ai->ai_protocol; kinds[k].sock = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol); } j = ntargets ++; targets = realloc(targets,ntargets*sizeof(*targets)); targets[j].sa = malloc(ai->ai_addrlen); targets[j].salen = ai->ai_addrlen; bcopy(ai->ai_addr,targets[j].sa,ai->ai_addrlen); targets[j].kx = k; } freeaddrinfo(ai0); } if (ntargets < 1) fail("no targets to send to"); gettimeofday(&now,0); serial = 0; calleridlen = strlen(callerid) & 0xff; extensionlen = strlen(extension) & 0xff; po_clid = 1 + 7 + 1 + 1; po_ext = po_clid + calleridlen; po_sig = po_ext + extensionlen; packetlen = po_sig + 32; packet = malloc(packetlen); xorbuf = malloc(packetlen); } static void do_xor(int len, const unsigned char *src, unsigned char xb) { int i; for (i=len-1;i>=0;i--) xorbuf[i] = src[i] ^ xb; } static void build_packet(int rep) { void *h; unsigned char hash1[32]; packet[0] = rep; packet[1] = now.tv_sec >> 24; packet[2] = (now.tv_sec >> 16) & 0xff; packet[3] = (now.tv_sec >> 8) & 0xff; packet[4] = now.tv_sec & 0xff; packet[5] = (now.tv_usec >> 16) & 0xff; packet[6] = (now.tv_usec >> 8) & 0xff; packet[7] = now.tv_usec & 0xff; packet[8] = calleridlen; packet[9] = extensionlen; bcopy(callerid,packet+po_clid,calleridlen); bcopy(extension,packet+po_ext,extensionlen); h = sha256_init(); sha256_process_bytes(h,sigkey,sigkeylen); do_xor(po_sig,packet,0x6b); sha256_process_bytes(h,xorbuf,po_sig); sha256_process_bytes(h,sigkey,sigkeylen); sha256_result(h,&hash1[0]); h = sha256_init(); sha256_process_bytes(h,sigkey,sigkeylen); sha256_process_bytes(h,&hash1[0],32); do_xor(po_sig,packet,0xc4); sha256_process_bytes(h,xorbuf,po_sig); sha256_process_bytes(h,sigkey,sigkeylen); sha256_result(h,&packet[po_sig]); } static void sendthem(void) { int rep; int t; int s; for (rep=0;rep=0;t--) { s = kinds[targets[t].kx].sock; if (s < 0) continue; sendto(s,packet,packetlen,0,targets[t].sa,targets[t].salen); } sleep(1); } } int main(int, char **); int main(int ac, char **av) { handleargs(ac,av); prepare(); sendthem(); exit(0); }