Skip to content

Instantly share code, notes, and snippets.

@oogali
Created May 31, 2013 15:22
Show Gist options
  • Save oogali/5685713 to your computer and use it in GitHub Desktop.
Save oogali/5685713 to your computer and use it in GitHub Desktop.
Testing SIP INVITEs -- I think I used this to prank Vonage users w/ATA-186s back in the day
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <md5.h>
#define WWW_AUTH 1
#define PROXY_AUTH 2
#define ACK 10
#define OK 11
#define CANCEL 12
extern int errno;
extern int h_errno;
char *our_ip, *our_username, *our_realm, *our_passwd, our_host[256], current_method[64];
int our_port, cseq, pktstatus, our_uid;
long callid, tag;
void process_pktstatus(char *incoming, int incominglen)
{
char tmp[4];
int i, offset;
offset = 8;
i = offset;
while (((incoming[i] != ' ') && (i != incominglen))) {
tmp[i - offset] = incoming[i];
i++;
}
tmp[i - offset] = '\0';
pktstatus = atoi(tmp);
printf("Got a SIP 2.0 packet with a status code of %d\n\n\n", pktstatus);
}
int process_message(char *incoming, int incominglen)
{
int i, offset;
char from[512], to[512], dest[512], msg[2048];
char *ptr;
offset = 8;
i = offset;
while(((incoming[i] != ' ') && (i != incominglen))) {
dest[i - offset] = incoming[i];
i++;
}
dest[i - offset] = '\0';
ptr = strstr(incoming, "From:");
if (ptr == NULL) {
printf("Could not find From: in packet\n");
} else {
offset = 6;
i = offset;
while(((ptr[i] != '\r') && (i != incominglen))) {
from[i - offset] = ptr[i];
i++;
}
from[i - offset] = '\0';
}
ptr = strstr(incoming, "To:");
if (ptr == NULL) {
printf("Could not find To: in packet\n");
} else {
offset = 4;
i = offset;
while(((ptr[i] != '\r') && (i != incominglen))) {
to[i - offset] = ptr[i];
i++;
}
to[i - offset] = '\0';
}
ptr = strstr(incoming, "\r\n\r\n");
if (ptr == NULL) {
printf("Could not find start of message in packet\n");
} else {
offset = 4;
i = offset;
while(i != incominglen && i != (sizeof(msg) - 1)) {
msg[i - offset] = ptr[i];
i++;
}
msg[i - offset] = '\0';
}
if (from && to && dest && msg) {
printf("Message sent from %s to %s (%s):\n", from, to, dest);
printf("%s\n", msg);
return 0;
} else {
return -1;
}
}
int send_pkt(int s, char *pkt, struct sockaddr_in sin)
{
int len, slen;
len = strlen(pkt);
slen = sendto(s, pkt, len, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr));
if (slen != len) {
perror("sendto");
exit(-1);
}
printf("Sent %d bytes to %s:%d\n", slen, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
printf("%s\n", pkt);
return(slen);
}
void send_reply(int s, char *incoming, int incominglen, struct sockaddr_in sin, int reply, char *method)
{
char rcvd_callid[256], *pkt, from[256], *ptr, contact[256], to[256], via[4096], tmp[255], tmp2[8];
int i, j, k, offset, vias = 0;
ptr = strstr(incoming, "Via:");
if (ptr == NULL) {
printf("Could not find Via: in packet\n");
} else {
i = 0;
j = 0;
while (i != incominglen) {
if (ptr[i] == 'V' && ptr[i + 1] == 'i' && ptr[i + 2] == 'a' && ptr[i + 3] == ':') {
while(ptr[i] != '\r') {
via[j] = ptr[i];
i++;
j++;
}
vias++;
via[j] = '\0';
if (vias == 1) {
offset = 17;
k = offset;
while((via[k] != ';' && via[k] != ':' && via[k] != '\r') && ((k - offset) < sizeof(tmp))) {
tmp[k - offset] = via[k];
k++;
}
if (strcmp(tmp, our_host) == 0 && strcmp(tmp, our_ip) == 0) {
tmp[k - offset] = '\0';
sin.sin_addr.s_addr = inet_addr(tmp);
offset = k;
if (via[k] == ':') {
k++; offset++;
while(via[k] != ';' && via[k] != '\r') {
tmp2[k - offset] = via[k];
k++;
}
sin.sin_port = htons(atoi(tmp2));
}
}
strncat(via, ";received=", sizeof(via));
strncat(via, our_ip, sizeof(via));
j += strlen(";received=") + strlen(our_ip);
}
via[j] = '\r';
j++;
via[j] = '\n';
j++;
}
i++;
}
via[j - 2] = '\0';
}
ptr = strstr(incoming, "From:");
if (ptr == NULL) {
printf("Could not find From: in packet\n");
} else {
offset = 6;
i = offset;
while(((ptr[i] != '\r') && (i != incominglen))) {
from[i - offset] = ptr[i];
i++;
}
from[i - offset] = '\0';
}
ptr = strstr(incoming, "To:");
if (ptr == NULL) {
printf("Could not find To: in packet\n");
} else {
offset = 4;
i = offset;
while(((ptr[i] != '\r') && (i != incominglen))) {
to[i - offset] = ptr[i];
i++;
}
to[i - offset] = '\0';
}
ptr = strstr(incoming, "Contact:");
if (ptr == NULL) {
printf("Could not find Contact: in packet\n");
} else {
offset = 9;
i = offset;
while(((ptr[i] != '\r') && (i != incominglen))) {
contact[i - offset] = ptr[i];
i++;
}
contact[i - offset] = '\0';
}
ptr = strstr(incoming, "Call-ID:");
if (ptr != NULL) {
offset = 9;
i = offset;
while(incoming[i] != '\r' && i != incominglen) {
rcvd_callid[i - offset] = ptr[i];
i++;
}
rcvd_callid[i - offset] = '\0';
} else {
snprintf(rcvd_callid, sizeof(rcvd_callid), "%d@%s", callid, our_host);
}
if (from && rcvd_callid) {
switch(reply) {
case ACK:
asprintf(&pkt, "ACK sip:%d@%s SIP/2.0\nVia: SIP/2.0/UDP %s:%d\nFrom: %s\nTo: %s\nContact: %s\nCall-Id: %s\nCSeq: %d %s\n\n", our_uid, our_ip, our_ip, our_port, from, to, contact, rcvd_callid, cseq, method);
break;
case OK:
asprintf(&pkt, "SIP/2.0 200 OK\n%s\nFrom: %s\nTo: %s;tag=%ld\nContact: %d@%s\nCall-Id: %s\nCSeq: %d %s\nContent-Length: 0\n\n", via, from, to, tag, our_uid, our_ip, rcvd_callid, cseq, method);
break;
case CANCEL:
asprintf(&pkt, "CANCEL %s SIP/2.0\nVia: SIP/2.0/UDP %s:%d\nFrom: %s\nTo: %s;tag=%ld\nContact: %d@%s\nCall-Id: %s\nCSeq: %d %s\nContent-Length: 0\n\n", to, our_host, our_port, from, to, tag, our_uid, our_ip, rcvd_callid, cseq, method);
break;
default:
printf("Unknown reply packet specified.\n");
break;
}
if (pkt != NULL) {
send_pkt(s, pkt, sin);
free(pkt);
}
}
}
void get_current_cseq(char *incoming, int incominglen)
{
int i, offset;
char tmp[16], *ptr;
ptr = strstr(incoming, "CSeq:");
if (ptr != NULL) {
offset = 6;
i = offset;
while(ptr[i] != ' ' && i != incominglen) {
tmp[i - offset] = ptr[i];
i++;
}
tmp[i - offset] = '\0';
cseq = atoi(tmp);
// printf("Current CSeq is set to %d\n", cseq);
}
}
int recv_pkt(int s, char *incoming, int incominglen, struct sockaddr_in sin)
{
int len, rlen;
len = sizeof(struct sockaddr);
bzero(incoming, incominglen);
rlen = recvfrom(s, incoming, incominglen, 0, (struct sockaddr *)&sin, &len);
if (rlen > 0) {
printf("Received %d bytes from %s:%d\n", rlen, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
printf("%s\n", incoming);
}
get_current_cseq(incoming, rlen);
if (incoming[0] == 'S' && incoming[1] == 'I' && incoming[2] == 'P' && incoming[3] == '/' && incoming[4] == '2' && incoming[5] == '.' && incoming[6] == '0') {
process_pktstatus(incoming, rlen);
} else if (incoming[0] == 'M' && incoming[1] == 'E' && incoming[2] == 'S' && incoming[3] == 'S' && incoming[4] == 'A' && incoming[5] == 'G' && incoming[6] == 'E') {
if (process_message(incoming, rlen) == 0) {
strncpy(current_method, "MESSAGE", sizeof(current_method));
send_reply(s, incoming, rlen, sin, OK, "MESSAGE");
}
} else if (incoming[0] == 'B' && incoming[1] == 'Y' && incoming[2] == 'E') {
strncpy(current_method, "BYE", sizeof(current_method));
send_reply(s, incoming, rlen, sin, ACK, "BYE");
}
return(rlen);
}
int send_register(int s, struct sockaddr_in sin, char *authc, char *authz, char *incoming, int type)
{
char *ptr, *pkt;
int i = 0, slen = 0, offset;
char realm[256], nonce[256];
char stage1_md5[33], stage2_md5[33], stage3_md5[33], uri[512];
MD5_CTX ctx;
ptr = strstr(incoming, authc);
if (ptr != NULL) {
ptr = strstr(incoming, "realm");
while(ptr[i] != '"') {
i++;
}
i++;
offset = i;
while(ptr[i] != '"') {
realm[i - offset] = ptr[i];
i++;
}
realm[i - offset] = '\0';
i = 0;
ptr = strstr(incoming, "nonce");
while(ptr[i] != '"') {
i++;
}
i++;
offset = i;
while(ptr[i] != '"') {
nonce[i - offset] = ptr[i];
i++;
}
nonce[i - offset] = '\0';
MD5Init(&ctx);
MD5Update(&ctx, our_username, strlen(our_username));
MD5Update(&ctx, ":", 1);
MD5Update(&ctx, realm, strlen(realm));
MD5Update(&ctx, ":", 1);
MD5Update(&ctx, our_passwd, strlen(our_passwd));
MD5End(&ctx, stage1_md5);
if (type == PROXY_AUTH)
snprintf(uri, sizeof(uri), "sip:%s@%s", our_username, our_realm);
else if (type == WWW_AUTH)
snprintf(uri, sizeof(uri), "sip:%s", our_realm);
else
snprintf(uri, sizeof(uri), "UNKNOWNAUTHMETHOD");
MD5Init(&ctx);
MD5Update(&ctx, current_method, strlen(current_method));
MD5Update(&ctx, ":", 1);
MD5Update(&ctx, uri, strlen(uri));
MD5End(&ctx, stage2_md5);
MD5Init(&ctx);
MD5Update(&ctx, stage1_md5, strlen(stage1_md5));
MD5Update(&ctx, ":", 1);
MD5Update(&ctx, nonce, strlen(nonce));
MD5Update(&ctx, ":", 1);
MD5Update(&ctx, stage2_md5, strlen(stage2_md5));
MD5End(&ctx, stage3_md5);
cseq++;
asprintf(&pkt, "%s sip:%s SIP/2.0\nVia: SIP/2.0/UDP %s:%d\nFrom: sip:%s@%s\nTo: sip:%s@%s\nContact: sip:%ld@%s\nCall-Id: %ld@%s\nCSeq: %d %s\n%s: DIGEST username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\n\n", current_method, our_realm, our_ip, our_port, our_username, our_realm, our_username, our_realm, our_uid, our_ip, callid, our_host, cseq, current_method, authz, our_username, realm, nonce, uri, stage3_md5);
if (pkt == NULL) {
perror("asprintf");
return(-1);
}
slen = send_pkt(s, pkt, sin);
free(pkt);
}
return(slen);
}
int main(int argc, char **argv)
{
struct sockaddr_in isin, osin;
int s;
char *pkt, incoming[1024];
struct hostent *he;
if (argc != 8) {
printf("%s <my ip> <my port> <sip server> <sip port> <username> <realm> <password>\n", argv[0]);
return(-1);
}
our_uid = getuid();
asprintf(&our_ip, argv[1]);
if (our_ip == NULL) {
perror("asprintf");
return(-1);
}
our_port = atoi(argv[2]);
if (our_port <= 0) {
perror("atoi");
return(-1);
}
asprintf(&our_username, argv[5]);
if (our_username == NULL) {
perror("asprintf");
return(-1);
}
asprintf(&our_realm, argv[6]);
if (our_realm == NULL) {
perror("asprintf");
return(-1);
}
asprintf(&our_passwd, argv[7]);
if (our_passwd == NULL) {
perror("asprintf");
return(-1);
}
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0) {
perror("socket");
return(-1);
}
isin.sin_family = AF_INET;
isin.sin_addr.s_addr = inet_addr(our_ip);
isin.sin_port = htons(our_port);
if (bind(s, (struct sockaddr *)&isin, sizeof(struct sockaddr)) != 0) {
perror("bind");
return(-1);
}
if (inet_addr(argv[3]) == INADDR_NONE) {
he = gethostbyname(argv[3]);
if (he == NULL) {
herror("gethostbyname");
return(-1);
}
memcpy((char *)&osin.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
} else {
osin.sin_addr.s_addr = inet_addr(argv[3]);
}
osin.sin_family = AF_INET;
osin.sin_port = htons(atoi(argv[4]));
srandomdev();
cseq = 1;
callid = random();
tag = random();
if (gethostname(our_host, sizeof(our_host)) != 0) {
perror("gethostname");
return(-1);
}
asprintf(&pkt, "INVITE sip:asterisk@%s;user=phone SIP/2.0\nVia: SIP/2.0/UDP %s:%d\nFrom: sip:%s@%s\nTo: sip:asterisk@%s;user=phone\nContact: sip:%ld@%s\nCall-Id: %ld@%s\nCSeq: %d INVITE\n\n", inet_ntoa(osin.sin_addr), our_ip, our_port, our_username, our_realm, inet_ntoa(osin.sin_addr), our_uid, our_ip, callid, our_host, cseq);
if (pkt == NULL) {
perror("asprintf");
return(-1);
}
strncpy(current_method, "INVITE", sizeof(current_method));
send_pkt(s, pkt, osin);
free(pkt);
while(1) {
recv_pkt(s, incoming, sizeof(incoming), osin);
switch(pktstatus) {
case 400:
send_reply(s, incoming, sizeof(incoming), osin, CANCEL, current_method);
break;
case 401:
send_register(s, osin, "WWW-Authenticate", "Authorization", incoming, WWW_AUTH);
break;
case 407:
send_register(s, osin, "Proxy-Authenticate", "Proxy-Authentication", incoming, PROXY_AUTH);
break;
case 200:
send_reply(s, incoming, sizeof(incoming), osin, ACK, current_method);
break;
case 100:
default:
}
}
close(s);
free(our_realm);
free(our_username);
free(our_passwd);
free(our_ip);
return 0;
}
@oogali
Copy link
Author

oogali commented May 31, 2013

$ ls -la sip/rfc/send-invite.c
-rw-r--r--  1 missnglnk  staff  12292 Aug 13  2003 sip/rfc/send-invite.c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment