Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

+ Added message body conversion: UTF-8 → UCS-2BE #54

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ AC_SUBST([LIBS])

# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([ctype.h errno.h arpa/inet.h netdb.h netinet/in.h netinet/in_systm.h limits.h sys/poll.h regex.h signal.h stdarg.h stdlib.h stdio.h string.h sys/param.h sys/socket.h sys/time.h unistd.h sys/utsname.h],,[AC_MSG_ERROR([missing required header (see above)])],)
AC_CHECK_HEADERS([ctype.h errno.h arpa/inet.h netdb.h netinet/in.h netinet/in_systm.h limits.h sys/poll.h regex.h signal.h stdarg.h stdlib.h stdio.h string.h sys/param.h sys/socket.h sys/time.h unistd.h sys/utsname.h iconv.h],,[AC_MSG_ERROR([missing required header (see above)])],)
AC_CHECK_HEADERS([getopt.h syslog.h])
AC_HEADER_SYS_WAIT
AC_HEADER_TIME
Expand All @@ -49,7 +49,7 @@ AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_SELECT_ARGTYPES
AC_CHECK_FUNCS([getchar gethostbyname gethostname getopt getpid gettimeofday memset ntohs regcomp select socket strchr strcmp strstr strtol uname],,[AC_MSG_ERROR([missing required function (see above)])])
AC_CHECK_FUNCS([getchar gethostbyname gethostname getopt getpid gettimeofday memset ntohs regcomp select socket strchr strcmp strstr strtol uname iconv],,[AC_MSG_ERROR([missing required function (see above)])])
AC_CHECK_FUNCS([calloc getdomainname getopt_long inet_ntop strncasecmp strcasestr syslog])

PKG_PROG_PKG_CONFIG
Expand Down
69 changes: 67 additions & 2 deletions src/header_f.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@

/* add the given header(s) below the request line */
void insert_header(char *mes, char *header, int first) {
char *ins, *backup;

char *ins, *backup, *hp, *dhp, *ehp;
int max_headers = 100, hcount = 0, c, i;
struct hline **hlist = malloc(sizeof(struct hline *) * max_headers);

if (first) {
ins = strchr(mes, '\n');
if (ins == NULL) {
Expand All @@ -43,6 +45,69 @@ void insert_header(char *mes, char *header, int first) {
strncpy(ins, header, strlen(header));
strncpy(ins + strlen(header), backup, strlen(backup)+1);
free(backup);

// deduplicate headers
hp = strstr(mes, "\r\n");
if (hp)
hp += 2;

while (hp && *hp) {
if (hcount == max_headers) {
max_headers *= 2;
hlist = realloc(hlist, sizeof(struct hline *) * max_headers);
}
c = i = hcount++;

hlist[i] = malloc(sizeof(struct hline));
hlist[i]->begin = hp;

ehp = strstr(hp, "\r\n");
if (ehp) {
if (ehp == hp) {
hp = NULL;
continue;
}
*ehp = 0;
hlist[i]->len = ehp - hp + 2;
}
else
hlist[i]->len = hp - mes + strlen(mes);

dhp = strchr(hp, ':');
if (dhp)
hlist[i]->namelen = dhp - hp;
else
hlist[i]->namelen = 0;

if (ehp) {
*ehp = 0x0D;
hp = ehp + 2;
}
else
hp = NULL;

i = 0;
while (i < c) {
if ((hlist[i]->namelen == hlist[c]->namelen) && !strncmp(hlist[i]->begin, hlist[c]->begin, hlist[c]->namelen)) {
if (hp) {
memmove(hlist[c]->begin, hp, hp - mes + strlen(mes) + 1);
hp = hlist[c]->begin;
}
else
strcpy(hlist[c]->begin, "\r\n\0");

--hcount;
free(hlist[c]);
i = c;
}
else
++i;
}
}

for (i = 0; i < hcount; i++)
free(hlist[i]);
free(hlist);
}

/* add a Via Header Field in the message. */
Expand Down
6 changes: 6 additions & 0 deletions src/header_f.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@

#include "shoot.h"

struct hline
{
char *begin;
int namelen, len;
};

void insert_header(char *mes, char *header, int first);

void add_via(char *mes);
Expand Down
16 changes: 5 additions & 11 deletions src/request.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,11 @@ void create_msg(int action, char *req_buff, char *repl_buff, char *username, int
FROM_STR, fqdn, lport, c);
}
req_buff += strlen(req_buff);
if (mes_body) {
len = strlen(mes_body);
}
else {
if (mes_body)
len = mes_body->len;
else
len = SIPSAK_MES_STR_LEN + strlen(username);
}

sprintf(req_buff, "%s%u\r\n", CON_LEN_STR, len);
req_buff += strlen(req_buff);
if (con_dis) {
Expand All @@ -212,12 +211,7 @@ void create_msg(int action, char *req_buff, char *repl_buff, char *username, int
}
sprintf(req_buff, "\r\n");
req_buff += 2;
if (mes_body) {
sprintf(req_buff,
"%s",
mes_body);
}
else {
if (!mes_body) {
sprintf(req_buff, "%s%s", SIPSAK_MES_STR, username);
req_buff += strlen(req_buff) - 1;
*(req_buff) = '.';
Expand Down
5 changes: 4 additions & 1 deletion src/shoot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1037,8 +1037,11 @@ void shoot(char *buf, int buff_size)
/* prevents a strange error */
regcomp(&(regexps.authexp), "^SIP/[0-9]\\.[0-9] 40[17] ", REG_EXTENDED|REG_NOSUB|REG_ICASE);
insert_auth(request, received);
if (verbose > 2)
if (verbose > 2) {
printf("\nreceived:\n%s\n", received);
if (mes_body)
printf("<UCS-2BE encoded body>\n");
}
new_transaction(request, response);
continue;
} /* if auth...*/
Expand Down
27 changes: 19 additions & 8 deletions src/sipsak.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#ifdef HAVE_SYSLOG_H
# include <syslog.h>
#endif
#include <iconv.h>

#include "helper.h"
#include "header_f.h"
Expand Down Expand Up @@ -424,14 +425,24 @@ int main(int argc, char *argv[])
namebeg=str_to_int(0, optarg);
break;
case 'B':
mes_body=str_alloc(strlen(optarg) + 1);
strncpy(mes_body, optarg, strlen(optarg));
{
iconv_t cd;
char *inbuf = optarg, *outbuf;
size_t inbytes = strlen(optarg), outbytes = inbytes * 2;
mes_body = malloc(sizeof(struct bytearray));
mes_body->data = outbuf = str_alloc(outbytes);
mes_body->len = outbytes;
cd = iconv_open("UCS-2BE", "UTF-8"); // FIX: source charset should be picked from locale
iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes);
iconv_close(cd);
mes_body->len -= outbytes; // some UTF-8 characters 1-byte long, some 2-byte long. All UCS-2 chars 2-byte long
break;
}
case 'c':
backup=str_alloc(strlen(optarg)+1);
strncpy(backup, optarg, strlen(optarg));
parse_uri(backup, &scheme, &user, &host, &port);
if (scheme == NULL) {
if (scheme == NULL) {
fprintf(stderr, "error: missing scheme in From URI\n");
exit_code(2, __PRETTY_FUNCTION__, "missing scheme in From URI");
}
Expand Down Expand Up @@ -464,9 +475,9 @@ int main(int argc, char *argv[])
strncpy(backup, optarg, strlen(optarg));
parse_uri(backup, &scheme, &user, &host, &port);
if (scheme == NULL) {
fprintf(stderr, "error: REGISTER Contact uri doesn't not contain "
"sip:, sips:, *, or is not empty\n");
exit_code(2, __PRETTY_FUNCTION__, "unsupported Contact for registration");
fprintf(stderr, "error: REGISTER Contact uri doesn't not contain "
"sip:, sips:, *, or is not empty\n");
exit_code(2, __PRETTY_FUNCTION__, "unsupported Contact for registration");
}
/*else if (user == NULL) {
fprintf(stderr, "error: missing username in Contact uri\n");
Expand Down Expand Up @@ -1056,7 +1067,7 @@ int main(int argc, char *argv[])
srand(time(0) ^ (getpid() + (getpid() << 15)));

if (processes > 1) {
if (signal(SIGCHLD , sigchld_handler) == SIG_ERR ) {
if (signal(SIGCHLD , sigchld_handler) == SIG_ERR ) {
fprintf(stderr, "error: Could not install SIGCHLD handler\n");
exit_code(2, __PRETTY_FUNCTION__, "failed to install SIGCHLD handler");
}
Expand All @@ -1069,7 +1080,7 @@ int main(int argc, char *argv[])
}

if (pid == 0){
/* child */
/* child */
upp = (nameend - namebeg + 1) / processes;
namebeg = namebeg + upp * i;
nameend = namebeg + upp;
Expand Down
8 changes: 7 additions & 1 deletion src/sipsak.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,11 @@ SSL* ssl;
# endif
#endif

struct bytearray {
char *data;
size_t len;
};

/* lots of global variables. ugly but makes life easier. */
unsigned long address;
unsigned int nonce_count, transport;
Expand All @@ -331,10 +336,11 @@ int file_b, uri_b, trace, via_ins, usrloc, redirects, rand_rem, replace_b;
int empty_contact, nagios_warn, fix_crlf, timing, outbound_proxy;
int timer_t1, timer_t2, timer_final, sysl;
char *username, *domainname, *password, *replace_str, *hostname, *contact_uri;
char *mes_body, *con_dis, *auth_username, *from_uri, *headers, *authhash, *local_ip;
char *con_dis, *auth_username, *from_uri, *headers, *authhash, *local_ip;
char fqdn[FQDN_SIZE];
char target_dot[INET_ADDRSTRLEN], source_dot[INET_ADDRSTRLEN];
char *request, *response, *received, *transport_str;
regex_t* regex;
struct bytearray *mes_body;

#endif
43 changes: 32 additions & 11 deletions src/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -679,35 +679,50 @@ void create_sockets(struct sipsak_con_data *cd) {
void send_message(char* mes, struct sipsak_con_data *cd,
struct sipsak_counter *sc, struct sipsak_sr_time *srt) {
struct timezone tz;
int ret = -1;

int ret = -1, len = strlen(mes), flen = len;
char *tmsg;

if (cd->dontsend == 0) {
if (verbose > 2) {
printf("\nrequest:\n%s", mes);
if (mes_body)
flen += mes_body->len;

tmsg = str_alloc(flen);
memcpy(tmsg, mes, len);

if (verbose > 2)
printf("\nrequest [%d bytes]:\n%s", flen, mes);

if (mes_body) {
if (verbose > 2)
printf("<UCS-2BE encoded body>\n");
memcpy(tmsg + len, mes_body->data, mes_body->len);
}

/* lets fire the request to the server and store when we did */
if (cd->csock == -1) {
dbg("\nusing un-connected socket for sending\n");
ret = sendto(cd->usock, mes, strlen(mes), 0, (struct sockaddr *) &(cd->adr), sizeof(struct sockaddr));
ret = sendto(cd->usock, tmsg, flen, 0, (struct sockaddr *) &(cd->adr), sizeof(struct sockaddr));
}
else {
dbg("\nusing connected socket for sending\n");
#ifdef WITH_TLS_TRANSP
if (transport == SIP_TLS_TRANSPORT) {
# ifdef USE_GNUTLS
ret = gnutls_record_send(tls_session, mes, strlen(mes));
ret = gnutls_record_send(tls_session, tmsg, flen);
# else /* USE_GNUTLS */
# ifdef USE_OPENSSL
# endif /* USE_OPENSSL */
# endif /* USE_GNUTLS */
}
else {
#endif /* TLS_TRANSP */
ret = send(cd->csock, mes, strlen(mes), 0);
ret = send(cd->csock, tmsg, flen, 0);
#ifdef WITH_TLS_TRANSP
}
#endif /* TLS_TRANSP */
}
free(tmsg);

(void)gettimeofday(&(srt->sendtime), &tz);
if (ret==-1) {
if (verbose)
Expand All @@ -717,8 +732,8 @@ void send_message(char* mes, struct sipsak_con_data *cd,
}
#ifdef HAVE_INET_NTOP
if (verbose > 2) {
printf("\nsend to: %s:%s:%i\n", transport_str, target_dot, rport);
}
printf("\nsend to: %s:%s:%i [%d bytes]\n", transport_str, target_dot, rport, ret);
}
#endif
sc->send_counter++;
}
Expand Down Expand Up @@ -936,6 +951,7 @@ int recv_message(char *buf, int size, int inv_trans,
int ret = 0;
int sock = 0;
double tmp_delay;
char *ehp;
#ifdef HAVE_INET_NTOP
struct sockaddr_in peer_adr;
socklen_t psize = sizeof(peer_adr);
Expand Down Expand Up @@ -1042,6 +1058,11 @@ int recv_message(char *buf, int size, int inv_trans,
#endif // RAW_SUPPORT
if (ret > 0) {
*(buf+ ret) = '\0';

// Cut off binary message body
if (mes_body && (ehp = strstr(buf, "\r\n\r\n")))
ehp[4] = 0;

if (transport != SIP_UDP_TRANSPORT) {
if (verbose > 0)
printf("\nchecking message for completeness...\n");
Expand Down Expand Up @@ -1083,8 +1104,8 @@ int recv_message(char *buf, int size, int inv_trans,
}
#ifdef HAVE_INET_NTOP
if ((verbose > 2) && (getpeername(sock, (struct sockaddr *)&peer_adr, &psize) == 0) && (inet_ntop(peer_adr.sin_family, &peer_adr.sin_addr, &source_dot[0], INET_ADDRSTRLEN) != NULL)) {
printf("\nreceived from: %s:%s:%i\n", transport_str,
source_dot, ntohs(peer_adr.sin_port));
printf("\nreceived from: %s:%s:%i [%d bytes]\n", transport_str,
source_dot, ntohs(peer_adr.sin_port), ret);
}
else if (verbose > 1 && trace == 0 && usrloc == 0)
printf(":\n");
Expand Down