release 0.2.2
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
0.2.2
|
||||
=====
|
||||
- 12-Oct-2002: - '-d' commandline option supersedes condig file setting
|
||||
of debug_level.
|
||||
- reworked concept return status from functions - uses
|
||||
now symbolic values
|
||||
- added individual user passowrds for authentication
|
||||
|
||||
0.2.1
|
||||
=====
|
||||
- 28-Sep-2002: - Released version 0.2.1
|
||||
|
||||
@@ -1,3 +1,37 @@
|
||||
Release Notes for siproxd-0.2.2
|
||||
===============================
|
||||
- SIP Proxy for SIP based softphones hidden behind a masquerading firewall
|
||||
- Includes an RTP data stream proxy for *incomming* audio data
|
||||
(outgoing RTP data should be handled by IP masquerading by the firewall)
|
||||
- Port range to be used for incomming RTP traffic is configurable
|
||||
(-> easy to set up apropriate firewall rules for incomming traffic)
|
||||
- Multiple local users/hosts can be masqueraded simultaneously
|
||||
- Supports running in a chroot jail (configurable)
|
||||
- Supports changing user-ID after startup (if started as root)
|
||||
- All configuration done via one simple ascii configuration file
|
||||
- Proxy Authentication for registration of local clients (User Agents)
|
||||
- Logging to syslog in Daemon mode
|
||||
- Access control (IP based) for incomming traffic
|
||||
- RPM support (spec file)
|
||||
|
||||
Requirements:
|
||||
- pthreads
|
||||
- libosip 0.8.8
|
||||
|
||||
Currently tested on Linux 2.2.x (Redhat 6.0) and 2.4.x (Redhat 7.2),
|
||||
should run on others Linux distributions as well.
|
||||
|
||||
Interoperability (tested with softphones):
|
||||
- Linphone (http://www.linphone.org)
|
||||
- Kphone (http://www.wirlab.net/kphone/)
|
||||
|
||||
-----
|
||||
md5sum for siproxd-0.2.2.tar.gz:
|
||||
|
||||
GnuPG signature for siproxd-0.2.2.tar.gz archive:
|
||||
|
||||
|
||||
|
||||
Release Notes for siproxd-0.2.1
|
||||
===============================
|
||||
- SIP Proxy for SIP based softphones hidden behind a masquerading firewall
|
||||
@@ -26,9 +60,16 @@ Interoperability (tested with softphones):
|
||||
- Kphone (http://www.wirlab.net/kphone/)
|
||||
|
||||
-----
|
||||
md5sum for siproxd-0.2.1.tar.gz:
|
||||
md5sum for siproxd-0.2.1.tar.gz: 3d0a46587494dd8c308c85f16d6f5555
|
||||
|
||||
GnuPG signature for siproxd-0.2.1.tar.gz archive:
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.0.5 (GNU/Linux)
|
||||
|
||||
iEYEABECAAYFAj2U6d4ACgkQPOYHDi42pIq5ygCg3oavz9FHFTXNZT/R4YNECzEX
|
||||
IX4AnAtYcNxJJhLXEKcj2ziKKvkectL9
|
||||
=A3tF
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
TODOs, in random order:
|
||||
=======================
|
||||
|
||||
- client authentication for registration - multiple user feature
|
||||
|
||||
- redo return status (make then at least DEFINED constants)
|
||||
|
||||
- Documentation (yeah, yeah...)
|
||||
|
||||
- general security issues
|
||||
@@ -18,5 +14,5 @@ TODOs, in random order:
|
||||
- portability to other platforms / operating systems
|
||||
first goal: other Unixes
|
||||
|
||||
|
||||
- security tests for received SIP messages (function securitycheck)
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ dnl ******************************************************************
|
||||
dnl
|
||||
SPD_MAJOR_VERSION=0
|
||||
SPD_MINOR_VERSION=2
|
||||
SPD_MICRO_VERSION=1
|
||||
SPD_MICRO_VERSION=2
|
||||
SPD_VERSION=$SPD_MAJOR_VERSION.$SPD_MINOR_VERSION.$SPD_MICRO_VERSION
|
||||
|
||||
dnl *********************************************************************
|
||||
|
||||
@@ -93,6 +93,12 @@ rtp_timeout = 60
|
||||
# registration is supported -> same for all local clients)
|
||||
#
|
||||
#proxy_auth_passwd = password
|
||||
#
|
||||
# or use individual per user passwords stored ia file
|
||||
#
|
||||
#proxy_auth_pwfile = doc/siproxd_passwd.cfg
|
||||
#
|
||||
# 'proxy_auth_pwfile' has precedence over 'proxy_auth_passwd'
|
||||
|
||||
######################################################################
|
||||
# Debug level... (setting to -1 will enable everything)
|
||||
|
||||
+11
-9
@@ -47,7 +47,7 @@ int process_aclist (char *aclist, struct sockaddr_in from);
|
||||
*
|
||||
* returns a bitmask with ACCESSCTL_SIP, ACCESSCTL_REG
|
||||
*/
|
||||
int check_accesslist (struct sockaddr_in from) {
|
||||
int accesslist_check (struct sockaddr_in from) {
|
||||
int access = 0;
|
||||
|
||||
DEBUGC(DBCLASS_ACCESS,"deny list (SIP):%s",configuration.hosts_deny_sip);
|
||||
@@ -60,7 +60,7 @@ int check_accesslist (struct sockaddr_in from) {
|
||||
if ( (configuration.hosts_deny_sip !=NULL) &&
|
||||
(strcmp(configuration.hosts_deny_sip,"")!=0) ) {
|
||||
/* non-empty list -> check agains it */
|
||||
if (process_aclist(configuration.hosts_deny_sip, from)) {
|
||||
if (process_aclist(configuration.hosts_deny_sip, from)== STS_SUCCESS) {
|
||||
/* yup - this one is blacklisted */
|
||||
DEBUGC(DBCLASS_ACCESS,"caught by deny list");
|
||||
return 0;
|
||||
@@ -73,7 +73,7 @@ int check_accesslist (struct sockaddr_in from) {
|
||||
if ( (configuration.hosts_allow_sip !=NULL) &&
|
||||
(strcmp(configuration.hosts_allow_sip,"")!=0) ) {
|
||||
/* non-empty list -> check agains it */
|
||||
if (process_aclist(configuration.hosts_allow_sip, from)) {
|
||||
if (process_aclist(configuration.hosts_allow_sip, from)==STS_SUCCESS) {
|
||||
/* SIP access granted */
|
||||
DEBUGC(DBCLASS_ACCESS,"granted SIP access");
|
||||
access |= ACCESSCTL_SIP;
|
||||
@@ -88,7 +88,7 @@ int check_accesslist (struct sockaddr_in from) {
|
||||
if ( (configuration.hosts_allow_reg !=NULL) &&
|
||||
(strcmp(configuration.hosts_allow_reg,"")!=0) ) {
|
||||
/* non-empty list -> check agains it */
|
||||
if (process_aclist(configuration.hosts_allow_reg, from)) {
|
||||
if (process_aclist(configuration.hosts_allow_reg, from)==STS_SUCCESS) {
|
||||
/* SIP registration access granted */
|
||||
DEBUGC(DBCLASS_ACCESS,"granted REG/SIP access");
|
||||
access |= ACCESSCTL_REG | ACCESSCTL_SIP;
|
||||
@@ -97,7 +97,7 @@ int check_accesslist (struct sockaddr_in from) {
|
||||
access |= ACCESSCTL_REG;
|
||||
}
|
||||
|
||||
return (access);
|
||||
return access;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,9 @@ int check_accesslist (struct sockaddr_in from) {
|
||||
* checks for a match of the 'from' address with the supplies
|
||||
* access list.
|
||||
*
|
||||
* return 1 for MATCH, 0 otherwise
|
||||
* RETURNS
|
||||
* STS_SUCCESS for a match
|
||||
* STS_FAILURE for no match
|
||||
*/
|
||||
int process_aclist (char *aclist, struct sockaddr_in from) {
|
||||
int i;
|
||||
@@ -127,7 +129,7 @@ int process_aclist (char *aclist, struct sockaddr_in from) {
|
||||
p2=strchr(p1,'/');
|
||||
if (!p2) {
|
||||
ERROR("CONFIG: hosts_deny_sip - no mask separator found");
|
||||
return 0;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
memset(address,0,sizeof(address));
|
||||
memcpy(address,p1,p2-p1);
|
||||
@@ -159,8 +161,8 @@ int process_aclist (char *aclist, struct sockaddr_in from) {
|
||||
ntohl(from.sin_addr.s_addr) & bitmask);
|
||||
|
||||
if ( (ntohl(inaddr.s_addr) & bitmask) ==
|
||||
(ntohl(from.sin_addr.s_addr) & bitmask) ) return 1;
|
||||
(ntohl(from.sin_addr.s_addr) & bitmask) ) return STS_SUCCESS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
+128
-25
@@ -21,6 +21,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -46,42 +47,49 @@ extern struct siproxd_config configuration;
|
||||
/* local protorypes */
|
||||
static char *auth_generate_nonce(void);
|
||||
static int auth_check(proxy_authorization_t *proxy_auth);
|
||||
static char *auth_getpwd(char *username);
|
||||
|
||||
/*
|
||||
* perform proxy authentication
|
||||
*
|
||||
* sts = 0 : authentication ok / not needed
|
||||
* sts = 1 : authentication failed
|
||||
* sts = 2 : authentication needed
|
||||
* RETURNS
|
||||
* STS_SUCCESS : authentication ok / not needed
|
||||
* STS_FAILURE : authentication failed
|
||||
* STS_NEEDAUTH: authentication needed
|
||||
*/
|
||||
int authenticate_proxy(sip_t *request) {
|
||||
proxy_authorization_t *proxy_auth;
|
||||
|
||||
/* required by config ? (if not, return 0)*/
|
||||
/* required by config? */
|
||||
if (configuration.proxy_auth_realm==NULL) {
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
/* supplied by UA? (if not, return 1)*/
|
||||
/* supplied by UA? */
|
||||
msg_getproxy_authorization(request, 0, &proxy_auth);
|
||||
if (proxy_auth == NULL) {
|
||||
DEBUGC(DBCLASS_AUTH,"proxy-auth required, not supplied by UA");
|
||||
return 2;
|
||||
return STS_NEED_AUTH;
|
||||
}
|
||||
|
||||
|
||||
/* verify supplied authentication */
|
||||
if (auth_check(proxy_auth) == 0) {
|
||||
DEBUGC(DBCLASS_AUTH,"proxy-auth succeeded");
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
/* authentication failed */
|
||||
DEBUGC(DBCLASS_AUTH,"proxy-auth failed");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* includes proxy authentication header in SIP message
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS
|
||||
*/
|
||||
int auth_include_authrq(sip_t *response) {
|
||||
int sts;
|
||||
char str[256];
|
||||
@@ -103,12 +111,16 @@ int auth_include_authrq(sip_t *response) {
|
||||
|
||||
sts = msg_setproxy_authenticate(response, str);
|
||||
|
||||
DEBUGC(DBCLASS_AUTH," msg_setproxy_authenticate sts=%i",sts);
|
||||
DEBUGC(DBCLASS_AUTH,"msg_setproxy_authenticate sts=%i",sts);
|
||||
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* generates a nonce string
|
||||
*
|
||||
* RETURNS nonce string
|
||||
*/
|
||||
static char *auth_generate_nonce() {
|
||||
static char nonce[40];
|
||||
struct timeval tv;
|
||||
@@ -119,7 +131,7 @@ static char *auth_generate_nonce() {
|
||||
sprintf(nonce, "%8.8lx%8.8lx%8.8x%8.8x",
|
||||
tv.tv_sec, tv.tv_usec, rand(), rand() );
|
||||
|
||||
DEBUGC(DBCLASS_AUTH," created nonce=\"%s\"",nonce);
|
||||
DEBUGC(DBCLASS_AUTH,"created nonce=\"%s\"",nonce);
|
||||
return nonce;
|
||||
}
|
||||
|
||||
@@ -127,8 +139,9 @@ static char *auth_generate_nonce() {
|
||||
/*
|
||||
* verify the supplied authentication information from UA
|
||||
*
|
||||
* returns 0 if succeeded
|
||||
* returns 1 if failed
|
||||
* RETURNS
|
||||
* STS_SUCCESS if succeeded
|
||||
* STS_FAILURE if failed
|
||||
*/
|
||||
static int auth_check(proxy_authorization_t *proxy_auth) {
|
||||
char *password=NULL;
|
||||
@@ -172,11 +185,17 @@ static int auth_check(proxy_authorization_t *proxy_auth) {
|
||||
if (proxy_auth->response)
|
||||
Response=sgetcopy_unquoted_string(proxy_auth->response);
|
||||
|
||||
/* get password from configuration */
|
||||
if (configuration.proxy_auth_passwd)
|
||||
/* get password */
|
||||
if (configuration.proxy_auth_pwfile) {
|
||||
/* check in passwd file */
|
||||
password=auth_getpwd(Username);
|
||||
} else if (configuration.proxy_auth_passwd) {
|
||||
/* get password from configuration */
|
||||
password=configuration.proxy_auth_passwd;
|
||||
else
|
||||
password="";
|
||||
}
|
||||
|
||||
if (password == NULL) password="";
|
||||
|
||||
|
||||
DEBUGC(DBCLASS_BABBLE," username=\"%s\"",Username );
|
||||
DEBUGC(DBCLASS_BABBLE," realm =\"%s\"",Realm );
|
||||
@@ -192,14 +211,14 @@ static int auth_check(proxy_authorization_t *proxy_auth) {
|
||||
DigestCalcResponse(HA1, Nonce, NonceCount, CNonce, Qpop,
|
||||
"REGISTER", Uri, HA2, Lcl_Response);
|
||||
|
||||
DEBUGC(DBCLASS_BABBLE," calculated Response=\"%s\"", Lcl_Response);
|
||||
DEBUGC(DBCLASS_BABBLE,"calculated Response=\"%s\"", Lcl_Response);
|
||||
|
||||
if (strcmp(Lcl_Response, Response)==0) {
|
||||
DEBUGC(DBCLASS_AUTH," Authentication succeeded");
|
||||
sts = 0;
|
||||
DEBUGC(DBCLASS_AUTH,"Authentication succeeded");
|
||||
sts = STS_SUCCESS;
|
||||
} else {
|
||||
DEBUGC(DBCLASS_AUTH," Authentication failed");
|
||||
sts = 1;
|
||||
DEBUGC(DBCLASS_AUTH,"Authentication failed");
|
||||
sts = STS_FAILURE;
|
||||
}
|
||||
|
||||
/* free allocated memory from above */
|
||||
@@ -216,6 +235,90 @@ static int auth_check(proxy_authorization_t *proxy_auth) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lookup in the password file and return
|
||||
* the user specific password for 'username'
|
||||
*
|
||||
* RETURNS
|
||||
* password for user or NULL if not found
|
||||
*/
|
||||
static char *auth_getpwd(char *username) {
|
||||
typedef struct {
|
||||
char username[USERNAME_SIZE];
|
||||
char password[PASSWORD_SIZE];
|
||||
} auth_cache_t;
|
||||
|
||||
FILE *pwdfile;
|
||||
char buff[128];
|
||||
int i;
|
||||
static auth_cache_t *auth_cache=NULL;
|
||||
void *tmpptr;
|
||||
static int auth_cache_size=0;
|
||||
static int auth_cache_count=0;
|
||||
|
||||
if (auth_cache==NULL) {
|
||||
DEBUGC(DBCLASS_AUTH,"initialize password cache");
|
||||
pwdfile=fopen(configuration.proxy_auth_pwfile,"r");
|
||||
/* config file not found or unable to open for read */
|
||||
if (pwdfile==NULL) {
|
||||
ERROR ("could not open password file: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (fgets(buff,sizeof(buff),pwdfile) != NULL) {
|
||||
/* life insurance */
|
||||
buff[sizeof(buff)-1]='\0';
|
||||
|
||||
/* strip newline if present */
|
||||
if (buff[strlen(buff)-1]=='\n') buff[strlen(buff)-1]='\0';
|
||||
|
||||
/* strip emty lines */
|
||||
if (strlen(buff) == 0) continue;
|
||||
|
||||
/* strip comments and line with only whitespaces */
|
||||
for (i=0;i<strlen(buff);i++) {
|
||||
if ((buff[i] == ' ') && (buff[i] == '\t')) continue;
|
||||
if (buff[i] =='#') i=strlen(buff);
|
||||
break;
|
||||
}
|
||||
if (i == strlen(buff)) continue;
|
||||
|
||||
/* allocate space whenever needed */
|
||||
if (auth_cache_count >= auth_cache_size) {
|
||||
auth_cache_size+=10;
|
||||
tmpptr=realloc(auth_cache, auth_cache_size*sizeof(auth_cache_t));
|
||||
if (tmpptr != NULL) {
|
||||
auth_cache= (auth_cache_t *)tmpptr;
|
||||
} else {
|
||||
ERROR("realloc failed! this is not good");
|
||||
auth_cache_size-=10;
|
||||
return NULL;
|
||||
}
|
||||
} /* cnt > size */
|
||||
|
||||
i=sscanf(buff,"%s %s",auth_cache[auth_cache_count].username,
|
||||
auth_cache[auth_cache_count].password);
|
||||
/* if I got username & passwd, make it valid and increment counter */
|
||||
if (i == 2) auth_cache_count++;
|
||||
}
|
||||
|
||||
fclose(pwdfile);
|
||||
|
||||
} /* initialize cache */
|
||||
|
||||
/* search cache for user */
|
||||
DEBUGC(DBCLASS_AUTH,"searching password entry for user %s",username);
|
||||
for (i=0; i< auth_cache_count;i++) {
|
||||
if (strcmp(username, auth_cache[i].username)==0) {
|
||||
DEBUGC(DBCLASS_AUTH,"found password entry for user %s",username);
|
||||
return auth_cache[i].password;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_AUTH,"no password entry found for user %s",username);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
+65
-38
@@ -50,6 +50,9 @@ extern int sip_socket; /* sending SIP datagrams */
|
||||
/*
|
||||
* PROXY_REQUEST
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int proxy_request (sip_t *request) {
|
||||
int i;
|
||||
@@ -68,9 +71,9 @@ int proxy_request (sip_t *request) {
|
||||
|
||||
/* check for VIA loop, if yes, discard the request */
|
||||
sts=check_vialoop(request);
|
||||
if (sts !=0) {
|
||||
if (sts == STS_TRUE) {
|
||||
DEBUGC(DBCLASS_PROXY,"via loop detected, ignoring request");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
type = 0;
|
||||
@@ -78,7 +81,7 @@ int proxy_request (sip_t *request) {
|
||||
if (urlmap[i].active == 0) continue;
|
||||
|
||||
/* incomming request ('to' == 'masq') */
|
||||
if (compare_url(request->to->url, urlmap[i].masq_url)==0) {
|
||||
if (compare_url(request->to->url, urlmap[i].masq_url)==STS_SUCCESS) {
|
||||
type=REQTYP_INCOMMING;
|
||||
DEBUGC(DBCLASS_PROXY,"incomming request from %s@%s from outbound",
|
||||
request->from->url->username,
|
||||
@@ -87,7 +90,7 @@ int proxy_request (sip_t *request) {
|
||||
}
|
||||
|
||||
/* outgoing request ('from' == 'masq') */
|
||||
if (compare_url(request->from->url, urlmap[i].masq_url)==0) {
|
||||
if (compare_url(request->from->url, urlmap[i].masq_url)==STS_SUCCESS) {
|
||||
type=REQTYP_OUTGOING;
|
||||
DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound",
|
||||
request->from->url->username,
|
||||
@@ -134,6 +137,9 @@ int proxy_request (sip_t *request) {
|
||||
|
||||
/* add my Via header line (inbound interface)*/
|
||||
sts = proxy_add_myvia(request, 1);
|
||||
if (sts == STS_FAILURE) {
|
||||
WARN("adding my inbound via failed!");
|
||||
}
|
||||
|
||||
/* if this is CANCEL/BYE request, stop RTP proxying */
|
||||
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
||||
@@ -157,7 +163,8 @@ int proxy_request (sip_t *request) {
|
||||
if (contact != NULL) {
|
||||
for (i=0;i<URLMAP_SIZE;i++){
|
||||
if (urlmap[i].active == 0) continue;
|
||||
if (compare_url(contact->url, urlmap[i].true_url)==0) break;
|
||||
if (compare_url(contact->url, urlmap[i].true_url)==STS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
/* found a mapping entry */
|
||||
if (i<URLMAP_SIZE) {
|
||||
@@ -177,6 +184,9 @@ int proxy_request (sip_t *request) {
|
||||
|
||||
/* add my Via header line (outbound interface)*/
|
||||
sts = proxy_add_myvia(request, 0);
|
||||
if (sts == STS_FAILURE) {
|
||||
WARN("adding my outbound via failed!");
|
||||
}
|
||||
|
||||
/* if this is CANCEL/BYE request, stop RTP proxying */
|
||||
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
||||
@@ -193,7 +203,7 @@ int proxy_request (sip_t *request) {
|
||||
request->from->url->host);
|
||||
/* some clients seem to run amok when passing back a negative response */
|
||||
// proxy_gen_response(request, 403 /*forbidden*/);
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +241,7 @@ int proxy_request (sip_t *request) {
|
||||
sts = msg_2char(request, &buffer);
|
||||
if (sts != 0) {
|
||||
ERROR("proxy_request: msg_2char failed");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* send to destination */
|
||||
@@ -243,13 +253,16 @@ int proxy_request (sip_t *request) {
|
||||
|
||||
sipsock_send_udp(&sip_socket, addr, port, buffer, strlen(buffer), 1);
|
||||
free (buffer);
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PROXY_RESPONSE
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int proxy_response (sip_t *response) {
|
||||
int i;
|
||||
@@ -269,16 +282,16 @@ int proxy_response (sip_t *response) {
|
||||
|
||||
/* check for VIA loop, if yes, discard the request */
|
||||
sts=check_vialoop(response);
|
||||
if (sts !=0) {
|
||||
if (sts == STS_TRUE) {
|
||||
DEBUGC(DBCLASS_PROXY,"via loop detected, ignoring response");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* ALWAYS: remove my Via header line */
|
||||
sts = proxy_del_myvia(response);
|
||||
if (sts !=0) {
|
||||
if (sts == STS_FAILURE) {
|
||||
DEBUGC(DBCLASS_PROXY,"not addressed to my VIA, ignoring response");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* figure out if this is an request comming from the outside
|
||||
@@ -298,7 +311,7 @@ int proxy_response (sip_t *response) {
|
||||
|
||||
|
||||
/* incomming response ('from' == 'masq') */
|
||||
if (compare_url(response->from->url, urlmap[i].masq_url)==0) {
|
||||
if (compare_url(response->from->url, urlmap[i].masq_url)==STS_SUCCESS) {
|
||||
type=RESTYP_INCOMMING;
|
||||
DEBUGC(DBCLASS_PROXY,"incomming response for %s@%s from outbound",
|
||||
response->from->url->username,
|
||||
@@ -307,7 +320,7 @@ int proxy_response (sip_t *response) {
|
||||
}
|
||||
|
||||
/* outgoing response ('to' == 'masq') */
|
||||
if (compare_url(response->to->url, urlmap[i].masq_url)==0) {
|
||||
if (compare_url(response->to->url, urlmap[i].masq_url)==STS_SUCCESS) {
|
||||
type=RESTYP_OUTGOING;
|
||||
DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound",
|
||||
response->from->url->username,
|
||||
@@ -342,7 +355,8 @@ int proxy_response (sip_t *response) {
|
||||
if (contact != NULL) {
|
||||
for (i=0;i<URLMAP_SIZE;i++){
|
||||
if (urlmap[i].active == 0) continue;
|
||||
if (compare_url(contact->url, urlmap[i].true_url)==0) break;
|
||||
if (compare_url(contact->url, urlmap[i].true_url)==STS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
/* found a mapping entry */
|
||||
if (i<URLMAP_SIZE) {
|
||||
@@ -366,7 +380,7 @@ int proxy_response (sip_t *response) {
|
||||
DEBUGC(DBCLASS_PROXY,"response: refuse to proxy - UA not registered?");
|
||||
/* some clients seem to run amok when passing back a negative response */
|
||||
// proxy_gen_response(request, 403 /*forbidden*/);
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* get target address from VIA header */
|
||||
@@ -377,7 +391,7 @@ int proxy_response (sip_t *response) {
|
||||
sts = msg_2char(response, &buffer);
|
||||
if (sts != 0) {
|
||||
ERROR("proxy_request: msg_2char failed");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* send to destination */
|
||||
@@ -389,7 +403,7 @@ int proxy_response (sip_t *response) {
|
||||
|
||||
sipsock_send_udp(&sip_socket, addr, port, buffer, strlen(buffer), 1);
|
||||
free (buffer);
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -399,6 +413,10 @@ int proxy_response (sip_t *response) {
|
||||
* send an proxy generated response back to the client.
|
||||
* Only errors are reported from the proxy itself.
|
||||
* code = SIP result code to deliver
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int proxy_gen_response(sip_t *request, int code) {
|
||||
sip_t *response;
|
||||
@@ -410,7 +428,7 @@ int proxy_gen_response(sip_t *request, int code) {
|
||||
/* create the response template */
|
||||
if ((response=msg_make_template_reply(request, code))==NULL) {
|
||||
ERROR("proxy_response: error in msg_make_template_reply");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* we must check if first via has x.x.x.x address. If not, we must resolve it */
|
||||
@@ -418,7 +436,7 @@ int proxy_gen_response(sip_t *request, int code) {
|
||||
if (via == NULL)
|
||||
{
|
||||
ERROR("proxy_response: Cannot send response - no via field");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@@ -434,7 +452,7 @@ DEBUGC(DBCLASS_PROXY,"response=%p",response);
|
||||
sts = msg_2char(response, &buffer);
|
||||
if (sts != 0) {
|
||||
ERROR("proxy_response: msg_2char failed");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* send to destination */
|
||||
@@ -445,15 +463,18 @@ DEBUGC(DBCLASS_PROXY,"response=%p",response);
|
||||
msg_free(response);
|
||||
free(response);
|
||||
free (buffer);
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PROXY_ADD_MYVIA
|
||||
*
|
||||
*
|
||||
* interface == 0 -> outbound interface, else inbound interface
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int proxy_add_myvia (sip_t *request, int interface) {
|
||||
struct in_addr addr;
|
||||
@@ -472,18 +493,21 @@ int proxy_add_myvia (sip_t *request, int interface) {
|
||||
DEBUGC(DBCLASS_BABBLE,"adding VIA:%s",tmp);
|
||||
|
||||
sts = via_init(&via);
|
||||
if (sts!=0) return -1; /* allocation failed */
|
||||
if (sts!=0) return STS_FAILURE; /* allocation failed */
|
||||
sts = via_parse(via, tmp);
|
||||
if (sts!=0) return -1;
|
||||
if (sts!=0) return STS_FAILURE;
|
||||
list_add(request->vias,via,0);
|
||||
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PROXY_DEL_MYVIA
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int proxy_del_myvia (sip_t *response) {
|
||||
via_t *via;
|
||||
@@ -492,15 +516,15 @@ int proxy_del_myvia (sip_t *response) {
|
||||
DEBUGC(DBCLASS_PROXY,"deleting topmost VIA");
|
||||
via = list_get (response->vias, 0);
|
||||
|
||||
if ( !is_via_local(via) ) {
|
||||
if ( is_via_local(via) == STS_FALSE ) {
|
||||
ERROR("I'm trying to delete a VIA but it's not mine! host=%s",via->host);
|
||||
return -1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
sts = list_remove(response->vias, 0);
|
||||
via_free (via);
|
||||
free(via);
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -509,6 +533,9 @@ int proxy_del_myvia (sip_t *response) {
|
||||
*
|
||||
* rewrites the outgoing INVITATION packet
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
body_t *body;
|
||||
@@ -523,7 +550,7 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
sts = msg_getbody(mymsg, 0, &body);
|
||||
if (sts != 0) {
|
||||
ERROR("rewrite_invitation_body: no body found in message");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
sts = body_2char(body, &oldbody);
|
||||
@@ -532,7 +559,7 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
sts = sdp_parse (sdp, oldbody);
|
||||
if (sts != 0) {
|
||||
ERROR("rewrite_invitation_body: unable to sdp_parse body");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
{ /* just dump the buffer */
|
||||
@@ -583,13 +610,13 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
if (data_c == NULL) data_c = strstr (oldbody, "\rc=");
|
||||
if (data_c == NULL) {
|
||||
ERROR("did not find a c= line in the body");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
data_c += 3;
|
||||
/* can only rewrite IPV4 addresses by now */
|
||||
if (strncmp(data_c,"IN IP4 ",7)!=0) {
|
||||
ERROR("c= does not contain an IN IP4 address");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
data_c += 7; /* PTR to start of IP address */
|
||||
/* find the end of the IP address -> end of line */
|
||||
@@ -597,7 +624,7 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
if (data2_c == NULL) data2_c = strstr (oldbody, "\r");
|
||||
if (data2_c == NULL) {
|
||||
ERROR("did not find a CR/LF after c= line");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -607,20 +634,20 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
if (data_m == NULL) data_m = strstr (oldbody, "\rm=");
|
||||
if (data_m == NULL) {
|
||||
ERROR("did not find a m= line in the body");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
data_m += 3;
|
||||
/* check for audio media */
|
||||
if (strncmp(data_m,"audio ",6)!=0) {
|
||||
ERROR("m= does not contain audio");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
data_m += 6; /* PTR to start of port number */
|
||||
/* find the end of the IP address -> end of line */
|
||||
data2_m = strstr (data_m, " RTP/");
|
||||
if (data2_m == NULL) {
|
||||
ERROR("did not find RTP/ on m= line");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -702,5 +729,5 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
free(tmp2);
|
||||
}
|
||||
free(oldbody);
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
+23
-9
@@ -42,12 +42,16 @@ static int parse_config (FILE *configfile);
|
||||
|
||||
|
||||
/* try to open (witchever found first):
|
||||
<name>
|
||||
$HOME/.<name>rc
|
||||
/etc/<name>.conf
|
||||
/usr/etc/<name>.conf
|
||||
/usr/local/etc/<name>.conf
|
||||
*/
|
||||
* <name>
|
||||
* $HOME/.<name>rc
|
||||
* /etc/<name>.conf
|
||||
* /usr/etc/<name>.conf
|
||||
* /usr/local/etc/<name>.conf
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int read_config(char *name, int search) {
|
||||
int sts;
|
||||
FILE *configfile=NULL;
|
||||
@@ -89,7 +93,7 @@ int read_config(char *name, int search) {
|
||||
/* config file not found or unable to open for read */
|
||||
if (configfile==NULL) {
|
||||
ERROR ("could not open config file: %s", strerror(errno));
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
sts = parse_config(configfile);
|
||||
@@ -98,7 +102,13 @@ int read_config(char *name, int search) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* parse configuration file
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
static int parse_config (FILE *configfile) {
|
||||
char buff[128];
|
||||
char *ptr;
|
||||
@@ -128,11 +138,15 @@ static int parse_config (FILE *configfile) {
|
||||
{ "hosts_deny_sip", TYP_STRING, &configuration.hosts_deny_sip },
|
||||
{ "proxy_auth_realm", TYP_STRING, &configuration.proxy_auth_realm },
|
||||
{ "proxy_auth_passwd", TYP_STRING, &configuration.proxy_auth_passwd },
|
||||
{ "proxy_auth_pwfile", TYP_STRING, &configuration.proxy_auth_pwfile },
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
while (fgets(buff,sizeof(buff),configfile) != NULL) {
|
||||
/* life insurance */
|
||||
buff[sizeof(buff)-1]='\0';
|
||||
|
||||
/* strip newline if present */
|
||||
if (buff[strlen(buff)-1]=='\n') buff[strlen(buff)-1]='\0';
|
||||
|
||||
@@ -191,5 +205,5 @@ static int parse_config (FILE *configfile) {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
+27
-23
@@ -52,9 +52,11 @@ void register_init(void) {
|
||||
|
||||
/*
|
||||
* handles register requests and updates the URL mapping table
|
||||
* sts = 0 : successfully registered
|
||||
* sts = 1 : registration failed
|
||||
* sts = 2 : authentication needed
|
||||
*
|
||||
* RETURNS:
|
||||
* STS_SUCCESS : successfully registered
|
||||
* STS_FAILURE : registration failed
|
||||
* STS_NEED_AUTH : authentication needed
|
||||
*/
|
||||
int register_client(sip_t *my_msg) {
|
||||
int i, j, sts;
|
||||
@@ -64,20 +66,18 @@ int register_client(sip_t *my_msg) {
|
||||
url_t *url2_to, *url2_contact;
|
||||
header_t *expires_hdr;
|
||||
|
||||
/*
|
||||
do proxy authentication
|
||||
*/
|
||||
/* check for proxy authentication */
|
||||
sts = authenticate_proxy(my_msg);
|
||||
if (sts == 1) {
|
||||
if (sts == STS_FAILURE) {
|
||||
/* failed */
|
||||
WARN("proxy authentication failed for %s@%s",
|
||||
my_msg->to->url->username,my_msg->to->url->host);
|
||||
return (1);
|
||||
} else if (sts == 2) {
|
||||
return STS_FAILURE;
|
||||
} else if (sts == STS_NEED_AUTH) {
|
||||
/* needed */
|
||||
DEBUGC(DBCLASS_REG,"proxy authentication needed for %s@%s",
|
||||
my_msg->to->url->username,my_msg->to->url->host);
|
||||
return (2);
|
||||
return STS_NEED_AUTH;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -126,7 +126,7 @@ int register_client(sip_t *my_msg) {
|
||||
url2_to=urlmap[i].masq_url;
|
||||
url2_contact=urlmap[i].true_url;
|
||||
|
||||
if ( (compare_url(url1_to, url2_to)==0) &&
|
||||
if ( (compare_url(url1_to, url2_to)==STS_SUCCESS) &&
|
||||
(strcmp(url1_contact->username, url2_contact->username)==0) &&
|
||||
(strcmp(url1_contact->host, url2_contact->host )==0) ) {
|
||||
DEBUGC(DBCLASS_REG, "found entry for %s@%s at slot=%i, exp=%li",
|
||||
@@ -139,7 +139,7 @@ int register_client(sip_t *my_msg) {
|
||||
if ( (j < 0) && (i >= URLMAP_SIZE) ) {
|
||||
/* oops, no free entries left... */
|
||||
ERROR("URLMAP is full - registration failed");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
if (i >= URLMAP_SIZE) {
|
||||
@@ -164,7 +164,7 @@ int register_client(sip_t *my_msg) {
|
||||
/* update registration timeout */
|
||||
urlmap[i].expires=time_now+expires;
|
||||
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -198,9 +198,13 @@ void register_agemap(void) {
|
||||
|
||||
/*
|
||||
* send answer to a registration request.
|
||||
* flag = 0 -> positive answer (200)
|
||||
* flag = 1 -> negative answer (503)
|
||||
* flag = 2 -> proxy authentication needed (407)
|
||||
* flag = STS_SUCCESS -> positive answer (200)
|
||||
* flag = STS_FAILURE -> negative answer (503)
|
||||
* flag = STS_NEED_AUTH -> proxy authentication needed (407)
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int register_response(sip_t *request, int flag) {
|
||||
sip_t *response;
|
||||
@@ -214,13 +218,13 @@ int register_response(sip_t *request, int flag) {
|
||||
|
||||
/* ok -> 200, fail -> 503 */
|
||||
switch (flag) {
|
||||
case 0:
|
||||
case STS_SUCCESS:
|
||||
code = 200; /* OK */
|
||||
break;
|
||||
case 1:
|
||||
case STS_FAILURE:
|
||||
code = 503; /* failed */
|
||||
break;
|
||||
case 2:
|
||||
case STS_NEED_AUTH:
|
||||
code = 407; /* proxy authentication needed */
|
||||
break;
|
||||
default:
|
||||
@@ -231,7 +235,7 @@ int register_response(sip_t *request, int flag) {
|
||||
/* create the response template */
|
||||
if ((response=msg_make_template_reply(request, code))==NULL) {
|
||||
ERROR("register_response: error in msg_make_template_reply");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* insert the expiration header */
|
||||
@@ -250,7 +254,7 @@ int register_response(sip_t *request, int flag) {
|
||||
msg_getvia (response, 0, &via);
|
||||
if (via == NULL) {
|
||||
ERROR("register_response: Cannot send response - no via field");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* name resolution needed? */
|
||||
@@ -262,7 +266,7 @@ int register_response(sip_t *request, int flag) {
|
||||
sts = msg_2char(response, &buffer);
|
||||
if (sts != 0) {
|
||||
ERROR("register_response: msg_2char failed");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* send answer back */
|
||||
@@ -278,6 +282,6 @@ int register_response(sip_t *request, int flag) {
|
||||
msg_free(response);
|
||||
free(response);
|
||||
free(buffer);
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
+30
-16
@@ -72,6 +72,9 @@ void sighdl_alm(int sig) {/* do nothing, just wake up from select() */};
|
||||
|
||||
/*
|
||||
* initialize and create rtp_proxy thread
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
*/
|
||||
int rtpproxy_init( void ) {
|
||||
int sts;
|
||||
@@ -101,7 +104,7 @@ int rtpproxy_init( void ) {
|
||||
DEBUGC(DBCLASS_RTP,"detached, sts=%i", sts);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -197,12 +200,16 @@ DEBUGC(DBCLASS_RTP,"got data on sock=%i",rtp_proxytable[i].sock);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/******
|
||||
* helper routines to control the RTP proxy thread
|
||||
*/
|
||||
******/
|
||||
|
||||
/*
|
||||
* start an rtp stream on the proxy
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int rtp_start_fwd (call_id_t *callid,
|
||||
struct in_addr outbound_ipaddr, int *outboundport,
|
||||
@@ -210,13 +217,13 @@ int rtp_start_fwd (call_id_t *callid,
|
||||
int i, j;
|
||||
int sock, port;
|
||||
int freeidx;
|
||||
int sts=0;
|
||||
int sts=STS_SUCCESS;
|
||||
|
||||
if (configuration.rtp_proxy_enable == 0) return 0;
|
||||
if (configuration.rtp_proxy_enable == 0) return STS_SUCCESS;
|
||||
|
||||
if (callid == NULL) {
|
||||
ERROR("rtp_start_fwd: callid is NULL!");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_RTP,"starting RTP proxy stream for: %s@%s",
|
||||
@@ -247,7 +254,7 @@ int rtp_start_fwd (call_id_t *callid,
|
||||
DEBUGC(DBCLASS_RTP,"RTP stream already active (port=%i)",
|
||||
rtp_proxytable[j].outboundport);
|
||||
*outboundport=rtp_proxytable[j].outboundport;
|
||||
sts = 0;
|
||||
sts = STS_SUCCESS;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
}
|
||||
@@ -279,7 +286,7 @@ int rtp_start_fwd (call_id_t *callid,
|
||||
DEBUGC(DBCLASS_RTP,"RTP stream already active (port=%i)",
|
||||
rtp_proxytable[j].outboundport);
|
||||
*outboundport=rtp_proxytable[j].outboundport;
|
||||
sts = 0;
|
||||
sts = STS_SUCCESS;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
@@ -312,21 +319,21 @@ int rtp_start_fwd (call_id_t *callid,
|
||||
/* found an unused port? No -> RTP port pool fully allocated */
|
||||
if (port == 0) {
|
||||
ERROR("rtp_start_fwd: no RTP port available. Check rtp_port_* config!");
|
||||
sts = 1;
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* could bind to desired port? */
|
||||
if (sock == 0) {
|
||||
ERROR("rtp_start_fwd: unable to allocate outbound port!");
|
||||
sts = 1;
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* rtp_proxytable port pool full? */
|
||||
if (freeidx == -1) {
|
||||
ERROR("rtp_start_fwd: rtp_proxytable is full!");
|
||||
sts = 1;
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
@@ -362,16 +369,20 @@ unlock_and_exit:
|
||||
|
||||
/*
|
||||
* stop a rtp stream on the proxy
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int rtp_stop_fwd (call_id_t *callid) {
|
||||
int i;
|
||||
int sts=0;
|
||||
int sts=STS_SUCCESS;
|
||||
|
||||
if (configuration.rtp_proxy_enable == 0) return 0;
|
||||
if (configuration.rtp_proxy_enable == 0) return STS_SUCCESS;
|
||||
|
||||
if (callid == NULL) {
|
||||
ERROR("rtp_stop_fwd: callid is NULL!");
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_RTP,"stopping RTP proxy stream for: %s@%s",
|
||||
@@ -402,7 +413,7 @@ int rtp_stop_fwd (call_id_t *callid) {
|
||||
if (i>= RTPPROXY_SIZE) {
|
||||
DEBUGC(DBCLASS_RTP,"rtp_stop_fwd: can't find active stream for %s@%s",
|
||||
callid->number, callid->host);
|
||||
sts = 1;
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
@@ -432,6 +443,9 @@ unlock_and_exit:
|
||||
/*
|
||||
* some sockets have been newly created or removed -
|
||||
* recreate the FD set for next select operation
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success (always)
|
||||
*/
|
||||
int rtp_recreate_fdset(void) {
|
||||
int i;
|
||||
@@ -446,6 +460,6 @@ int rtp_recreate_fdset(void) {
|
||||
}
|
||||
}
|
||||
} /* for i */
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -36,11 +36,12 @@
|
||||
/*
|
||||
* do security and integrity checks on the received packet
|
||||
*
|
||||
* returns >0 if ok
|
||||
* 0 if the packed did not pass the checks
|
||||
* RETURNS
|
||||
* STS_SUCCESS if ok
|
||||
* STS_FAILURE if the packed did not pass the checks
|
||||
*/
|
||||
int securitycheck(char *sip_buffer, int size){
|
||||
int security_check(char *sip_buffer, int size){
|
||||
|
||||
/* TODO: still way to go here ... */
|
||||
return 1;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
+21
-13
@@ -51,7 +51,7 @@ PACKAGE"-"VERSION"-"BUILDSTR" (c) 2002 Thomas Ries\n" \
|
||||
"\nUsage: siproxd [options]\n\n" \
|
||||
"options:\n" \
|
||||
" --help (-h) help\n" \
|
||||
" --debug <pattern> (-d) set initial debug-pattern\n" \
|
||||
" --debug <pattern> (-d) set debug-pattern\n" \
|
||||
" --config <cfgfile> (-c) use the specified config file\n"\
|
||||
"";
|
||||
|
||||
@@ -71,6 +71,7 @@ int main (int argc, char *argv[])
|
||||
|
||||
char configfile[64]="siproxd"; /* basename of configfile */
|
||||
int config_search=1; /* search the config file */
|
||||
int cmdline_debuglevel=0;
|
||||
|
||||
/*
|
||||
* prepare default configuration
|
||||
@@ -110,8 +111,8 @@ int main (int argc, char *argv[])
|
||||
|
||||
case 'd': /* set debug level */
|
||||
DEBUGC(DBCLASS_CONFIG,"option: set debug level: %s",optarg);
|
||||
configuration.debuglevel=atoi(optarg);
|
||||
log_set_pattern(configuration.debuglevel);
|
||||
cmdline_debuglevel=atoi(optarg);
|
||||
log_set_pattern(cmdline_debuglevel);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -120,13 +121,20 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Init stuff
|
||||
*/
|
||||
if (read_config(configfile, config_search) != 0) exit(1);
|
||||
/* if a debug_level statement was in the config file, make sure
|
||||
the debug pattern is set after reading the config */
|
||||
/* read the config file */
|
||||
if (read_config(configfile, config_search) == STS_FAILURE) exit(1);
|
||||
|
||||
/* if a debug level > 0 has been given on the commandline use its
|
||||
value and not what is in the config file */
|
||||
if (cmdline_debuglevel != 0) {
|
||||
configuration.debuglevel=cmdline_debuglevel;
|
||||
}
|
||||
|
||||
/* set debug level as desired */
|
||||
log_set_pattern(configuration.debuglevel);
|
||||
|
||||
/* change user and group IDs */
|
||||
@@ -140,7 +148,7 @@ int main (int argc, char *argv[])
|
||||
|
||||
/* listen for incomming messages */
|
||||
sts=sipsock_listen();
|
||||
if (sts != 0) {
|
||||
if (sts == STS_FAILURE) {
|
||||
/* failure to allocate SIP socket... */
|
||||
ERROR("unable to bind to SIP listening socket - aborting");
|
||||
return 0;
|
||||
@@ -182,13 +190,13 @@ int main (int argc, char *argv[])
|
||||
|
||||
i=sipsock_read(&buff, sizeof(buff), &from);
|
||||
|
||||
/* evaluate the access lists */
|
||||
access=check_accesslist(from);
|
||||
/* evaluate the access lists (IP based filter)*/
|
||||
access=accesslist_check(from);
|
||||
if (access == 0) continue; /* there are no resources to free */
|
||||
|
||||
/* integrity checks */
|
||||
sts=securitycheck(buff, i);
|
||||
if (sts == 0) continue; /* there are no resources to free */
|
||||
sts=security_check(buff, i);
|
||||
if (sts != 0) continue; /* there are no resources to free */
|
||||
|
||||
/* parse the received message */
|
||||
sts=msg_init(&my_msg);
|
||||
@@ -214,7 +222,7 @@ int main (int argc, char *argv[])
|
||||
sts = register_response(my_msg, sts);
|
||||
} else {
|
||||
WARN("non-authorized registration attempt from %s",
|
||||
inet_ntoa(from.sin_addr));
|
||||
inet_ntoa(from.sin_addr));
|
||||
}
|
||||
|
||||
/* MSG is a request, add current via entry,
|
||||
|
||||
+33
-23
@@ -18,57 +18,57 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/* function returns STS_* status values vvv */
|
||||
|
||||
/* sock.c */
|
||||
int sipsock_listen (void);
|
||||
int sipsock_listen (void); // *
|
||||
int sipsock_wait(void);
|
||||
int sipsock_read(void *buf, size_t bufsize, struct sockaddr_in *from);
|
||||
int sipsock_send_udp(int *sock, struct in_addr addr, int port,
|
||||
int sipsock_send_udp(int *sock, struct in_addr addr, int port, // *
|
||||
char *buffer, int size, int allowdump);
|
||||
int sockbind(struct in_addr ipaddr, int localport);
|
||||
|
||||
/* register.c */
|
||||
void register_init(void);
|
||||
int register_client(sip_t *request);
|
||||
int register_client(sip_t *request); // *
|
||||
void register_agemap(void);
|
||||
int register_response(sip_t *request, int flag);
|
||||
int register_response(sip_t *request, int flag); // *
|
||||
|
||||
/* proxy.c */
|
||||
int proxy_request (sip_t *request);
|
||||
int proxy_response (sip_t *response);
|
||||
int proxy_gen_response(sip_t *request, int code);
|
||||
int proxy_add_myvia (sip_t *request, int interface);
|
||||
int proxy_del_myvia (sip_t *response);
|
||||
int proxy_rewrite_invitation_body(sip_t *mymsg);
|
||||
int proxy_request (sip_t *request); // *
|
||||
int proxy_response (sip_t *response); // *
|
||||
int proxy_gen_response(sip_t *request, int code); // *
|
||||
int proxy_add_myvia (sip_t *request, int interface); // *
|
||||
int proxy_del_myvia (sip_t *response); // *
|
||||
int proxy_rewrite_invitation_body(sip_t *mymsg); // *
|
||||
|
||||
/* utils.c */
|
||||
sip_t * msg_make_template_reply (sip_t * request, int code);
|
||||
int check_vialoop (sip_t *my_msg);
|
||||
int is_via_local (via_t *via);
|
||||
int get_ip_by_host(char *hostname, struct in_addr *addr);
|
||||
int compare_url(url_t *url1, url_t *url2);
|
||||
int check_vialoop (sip_t *my_msg); // *
|
||||
int is_via_local (via_t *via); // *
|
||||
int get_ip_by_host(char *hostname, struct in_addr *addr); // *
|
||||
int compare_url(url_t *url1, url_t *url2); // *
|
||||
void secure_enviroment (void);
|
||||
|
||||
/* readconf.c */
|
||||
int read_config(char *name, int search);
|
||||
int read_config(char *name, int search); // *
|
||||
|
||||
/* rtpproxy.c */
|
||||
int rtpproxy_init( void );
|
||||
int rtp_start_fwd (call_id_t *callid,
|
||||
int rtpproxy_init( void ); // *
|
||||
int rtp_start_fwd (call_id_t *callid, // *
|
||||
struct in_addr outbound_ipaddr, int *outboundport,
|
||||
struct in_addr lcl_client_ipaddr, int lcl_clientport);
|
||||
int rtp_stop_fwd (call_id_t *callid);
|
||||
int rtp_stop_fwd (call_id_t *callid); // *
|
||||
|
||||
/* accessctl.c */
|
||||
int check_accesslist (struct sockaddr_in from);
|
||||
int accesslist_check(struct sockaddr_in from);
|
||||
|
||||
/* security.c */
|
||||
int securitycheck(char *sip_buffer, int size);
|
||||
int security_check(char *sip_buffer, int size); // *
|
||||
|
||||
/* auth.c */
|
||||
int authenticate_proxy(sip_t *request);
|
||||
int auth_include_authrq(sip_t *response);
|
||||
int authenticate_proxy(sip_t *request); // *
|
||||
int auth_include_authrq(sip_t *response); // *
|
||||
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ struct siproxd_config {
|
||||
char *hosts_deny_sip;
|
||||
char *proxy_auth_realm;
|
||||
char *proxy_auth_passwd;
|
||||
char *proxy_auth_pwfile;
|
||||
};
|
||||
|
||||
|
||||
@@ -122,11 +123,20 @@ struct siproxd_config {
|
||||
#define DNS_CACHE_SIZE 32 // number of entries in internal DNS cache
|
||||
#define DNS_MAX_AGE 60 // maximum age of an cache entry (sec)
|
||||
#define HOSTNAME_SIZE 32 // max string length of a hostname
|
||||
#define USERNAME_SIZE 32 // max string length of a username (auth)
|
||||
#define PASSWORD_SIZE 32 // max string length of a password (auth)
|
||||
|
||||
|
||||
#define ACCESSCTL_SIP 1 // for access control - SIP allowed
|
||||
#define ACCESSCTL_REG 2 // --"-- - registrations allowed
|
||||
|
||||
/* symbolic return status */
|
||||
|
||||
#define STS_SUCCESS 0 // SUCCESS
|
||||
#define STS_TRUE 0 // TRUE
|
||||
#define STS_FAILURE 1 // FAILURE
|
||||
#define STS_FALSE 1 // FALSE
|
||||
#define STS_NEED_AUTH 1001 // need authentication
|
||||
|
||||
/*
|
||||
* optional hacks
|
||||
|
||||
+25
-8
@@ -49,20 +49,27 @@ static int listen_socket=0;
|
||||
/*
|
||||
* binds to SIP UDP socket for listening to incomming packets
|
||||
*
|
||||
* returns 0 on success
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int sipsock_listen (void) {
|
||||
struct in_addr ipaddr;
|
||||
|
||||
memset(&ipaddr, 0, sizeof(struct in_addr));
|
||||
listen_socket=sockbind(ipaddr, configuration.sip_listen_port);
|
||||
if (listen_socket==0) return 1; /* failure*/
|
||||
if (listen_socket==0) return STS_FAILURE; /* failure*/
|
||||
|
||||
DEBUGC(DBCLASS_NET,"bound listen socket %i",listen_socket);
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Wait for incomming SIP message. After a 5 sec timeout
|
||||
* this function returns with sts=0
|
||||
*
|
||||
* RETURNS >0 if data received, =0 if nothing received /T/O), -1 on error
|
||||
*/
|
||||
int sipsock_wait(void) {
|
||||
int sts;
|
||||
fd_set fdset;
|
||||
@@ -78,6 +85,12 @@ int sipsock_wait(void) {
|
||||
return sts;
|
||||
}
|
||||
|
||||
/*
|
||||
* read a message from SIP listen socket (UDP datagram)
|
||||
*
|
||||
* RETURNS number of bytes read
|
||||
* from is modified to return the sockaddr_in of the sender
|
||||
*/
|
||||
int sipsock_read(void *buf, size_t bufsize, struct sockaddr_in *from) {
|
||||
int count;
|
||||
socklen_t fromlen;
|
||||
@@ -94,6 +107,10 @@ int sipsock_read(void *buf, size_t bufsize, struct sockaddr_in *from) {
|
||||
|
||||
/*
|
||||
* sends an UDP datagram to the specified destination
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
*/
|
||||
int sipsock_send_udp(int *sock, struct in_addr addr, int port,
|
||||
char *buffer, int size, int allowdump) {
|
||||
@@ -105,7 +122,7 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
|
||||
*sock=socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (*sock == 0) {
|
||||
ERROR("socket() call failed:%s",strerror(errno));
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
DEBUGC(DBCLASS_NET,"allocated send socket %i",*sock);
|
||||
}
|
||||
@@ -126,12 +143,12 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
|
||||
if (sts == -1) {
|
||||
if (errno != ECONNREFUSED) {
|
||||
ERROR("sendto() call failed:%s",strerror(errno));
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
DEBUGC(DBCLASS_BABBLE,"sendto() call failed:%s",strerror(errno));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +157,7 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
|
||||
* generic routine to allocate and bind a socket to a specified
|
||||
* local address and port (UDP)
|
||||
*
|
||||
* returns socket number on success, zero on failure
|
||||
* RETURNS socket number on success, zero on failure
|
||||
*/
|
||||
int sockbind(struct in_addr ipaddr, int localport) {
|
||||
struct sockaddr_in my_addr;
|
||||
|
||||
+29
-11
@@ -48,6 +48,8 @@ extern int h_errno;
|
||||
|
||||
/*
|
||||
* create a reply template from an given SIP request
|
||||
*
|
||||
* RETURNS a pointer to sip_t
|
||||
*/
|
||||
sip_t *msg_make_template_reply (sip_t * request, int code) {
|
||||
sip_t *response;
|
||||
@@ -88,6 +90,10 @@ sip_t *msg_make_template_reply (sip_t * request, int code) {
|
||||
* check for a via loop.
|
||||
* It checks for the presense of a via entry that holds one of
|
||||
* my IP addresses and is *not* the topmost via.
|
||||
*
|
||||
* RETURNS
|
||||
* STS_TRUE if loop detected
|
||||
* STS_FALSE if no loop
|
||||
*/
|
||||
int check_vialoop (sip_t *my_msg) {
|
||||
int sts;
|
||||
@@ -104,13 +110,17 @@ int check_vialoop (sip_t *my_msg) {
|
||||
if (sts == 1) found_own_via=1;
|
||||
pos++;
|
||||
}
|
||||
return found_own_via;
|
||||
return (found_own_via)? STS_TRUE : STS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check if a given via_t is local. I.e. its address is owned
|
||||
* by my inbound or outbound interface
|
||||
*
|
||||
* RETURNS
|
||||
* STS_TRUE if the given VIA is one of my interfaces
|
||||
* STS_FALSE otherwise
|
||||
*/
|
||||
int is_via_local (via_t *via) {
|
||||
int sts;
|
||||
@@ -146,13 +156,17 @@ int is_via_local (via_t *via) {
|
||||
}
|
||||
}
|
||||
|
||||
return sts;
|
||||
return (sts)? STS_TRUE : STS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* resolve a hostname and return in_addr
|
||||
* handles its own little DNS cache.
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on failure
|
||||
*/
|
||||
int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
||||
int i, j;
|
||||
@@ -165,7 +179,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
||||
} dns_cache[DNS_CACHE_SIZE];
|
||||
static int cache_initialized=0;
|
||||
|
||||
if (hostname == NULL) return 1;
|
||||
if (hostname == NULL) return STS_FAILURE;
|
||||
|
||||
/* first time: initialize DNS cache */
|
||||
if (cache_initialized == 0) {
|
||||
@@ -193,7 +207,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
||||
memcpy(addr, &dns_cache[i].addr, sizeof(struct in_addr));
|
||||
DEBUGC(DBCLASS_DNS, "DNS lookup - from cache: %s -> %s",
|
||||
hostname, inet_ntoa(*addr));
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +216,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
||||
|
||||
if (hostentry==NULL) {
|
||||
ERROR("gethostbyname(%s) failed: %s",hostname,hstrerror(h_errno));
|
||||
return 1;
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
memcpy(addr, hostentry->h_addr, sizeof(struct in_addr));
|
||||
@@ -232,27 +246,30 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
||||
time(&dns_cache[i].timestamp);
|
||||
memcpy(&dns_cache[i].addr, addr, sizeof(struct in_addr));
|
||||
|
||||
return 0;
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* compares two URLs
|
||||
* returns 0 if equal, <0 if non equal, >0 if error
|
||||
* (by now, only hostname and username are compared)
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS if equal
|
||||
* STS_FAILURE if non equal or error
|
||||
*/
|
||||
int compare_url(url_t *url1, url_t *url2) {
|
||||
int sts;
|
||||
|
||||
if ((url1 == NULL) || (url2 == NULL)) return 1;
|
||||
if ((url1 == NULL) || (url2 == NULL)) return STS_FAILURE;
|
||||
|
||||
/* comparison of hosts should be based on IP addresses, no? */
|
||||
DEBUGC(DBCLASS_BABBLE, "comparng urls: %s@%s -> %s@%s",
|
||||
url1->username, url1->host, url2->username, url2->host);
|
||||
if ((strcmp(url1->username, url2->username)==0) &&
|
||||
(strcmp(url1->host, url2->host)==0)) {
|
||||
sts = 0;
|
||||
sts = STS_SUCCESS;
|
||||
} else {
|
||||
sts = -1;
|
||||
sts = STS_FAILURE;
|
||||
}
|
||||
|
||||
return sts;
|
||||
@@ -261,7 +278,8 @@ int compare_url(url_t *url1, url_t *url2) {
|
||||
|
||||
/*
|
||||
* Secure enviroment:
|
||||
* If running as root,change UID/GID to user as requested in config
|
||||
* If running as root, put myself into a chroot jail and
|
||||
* change UID/GID to user as requested in config file
|
||||
*/
|
||||
void secure_enviroment (void) {
|
||||
int sts;
|
||||
|
||||
Reference in New Issue
Block a user