Commit bf383acf authored by smorlat's avatar smorlat

linphonecsh and linphonec use a unix socket by default, for security reasons


git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@259 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
parent 365b3cb3
......@@ -6,6 +6,7 @@ linphone-3.1.0 -- January 19, 2009
* set a user friendly gtk theme by default on windows
* linphonec can compile and work without libreadline
* enable translations on windows
* enable lookups of SRV records
* bugfixing as usual
linphone-3.0.0 -- October 13, 2008
......
......@@ -1243,7 +1243,7 @@ static int lpc_cmd_status(LinphoneCore *lc, char *args){
if (strstr(args,"register")){
if (cfg){
if (linphone_proxy_config_is_registered(cfg)){
linphonec_out("identity=%s duration=%i\n",
linphonec_out("registered, identity=%s duration=%i\n",
linphone_proxy_config_get_identity(cfg),
linphone_proxy_config_get_expires(cfg));
}else if (linphone_proxy_config_register_enabled(cfg)){
......@@ -1268,7 +1268,7 @@ static int lpc_cmd_status(LinphoneCore *lc, char *args){
linphonec_out("hook=offhook\n");
break;
case GSTATE_CALL_OUT_CONNECTED:
linphonec_out("hook=%s duration=%i\n", linphonec_get_callee(),
linphonec_out("Call out, hook=%s duration=%i\n", linphonec_get_callee(),
linphone_core_get_current_call_duration(lc));
break;
case GSTATE_CALL_IN_CONNECTED:
......
......@@ -47,6 +47,8 @@
#else
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/stat.h>
#endif
......@@ -130,6 +132,7 @@ static bool_t vcap_enabled=FALSE;
static bool_t display_enabled=FALSE;
static bool_t preview_enabled=FALSE;
static bool_t show_general_state=FALSE;
static bool_t unix_socket=FALSE;
static int tcp_port=0; /* see --tcp: tcp port to listen for commands */
LPC_AUTH_STACK auth_stack;
static int trace_level = 0;
......@@ -138,6 +141,10 @@ static char configfile_name[PATH_MAX];
static char *sipAddr = NULL; /* for autocall */
static ortp_socket_t client_sock=-1;
char prompt[PROMPT_MAX_LEN];
char sock_unix_path[128]={0};
static ortp_thread_t net_reader_th;
static bool_t net_reader_run=FALSE;
static ortp_socket_t server_sock;
LinphoneCoreVTable linphonec_vtable = {
show:(ShowInterfaceCb) stub,
......@@ -366,43 +373,60 @@ static void start_prompt_reader(void){
}
static ortp_socket_t create_server_socket(int port){
ortp_socket_t server_sock;
char service[12];
int tmp,err;
/*setup the server socket */
struct addrinfo *ai=NULL;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_INET;
snprintf(service,sizeof(service),"%i",port);
getaddrinfo("127.0.0.1",service,&hints,&ai);
if (ai==NULL){
fprintf(stderr,"getaddrinfo failed on port %s",service);
exit(-1);
}
server_sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
tmp=1;
err=setsockopt(server_sock,SOL_SOCKET,SO_REUSEADDR,(void*)&tmp,sizeof(tmp));
if (err<0) fprintf(stderr,"Error in setsockopt(): %s\n",getSocketError());
if (bind(server_sock,ai->ai_addr,ai->ai_addrlen)!=0){
fprintf(stderr,"Failed to bind command socket.");
exit(-1);
ortp_socket_t sock;
if (!unix_socket){
char service[12];
/*setup the server socket */
struct addrinfo *ai=NULL;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_INET;
snprintf(service,sizeof(service),"%i",port);
getaddrinfo("127.0.0.1",service,&hints,&ai);
if (ai==NULL){
fprintf(stderr,"getaddrinfo failed on port %s",service);
exit(-1);
}
sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (bind(sock,ai->ai_addr,ai->ai_addrlen)!=0){
fprintf(stderr,"Failed to bind command socket.\n");
exit(-1);
}
listen(sock,1);
}else{
#ifndef WIN32
struct sockaddr_un sa;
sock=socket(AF_UNIX,SOCK_STREAM,0);
sa.sun_family=AF_UNIX;
snprintf(sock_unix_path,sizeof(sock_unix_path)-1,"/tmp/linphonec-%i",getuid());
strncpy(sa.sun_path,sock_unix_path,sizeof(sa.sun_path)-1);
unlink(sock_unix_path);/*in case we didn't finished properly previous time */
fchmod(sock,S_IRUSR|S_IWUSR);
if (bind(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
fprintf(stderr,"Failed to bind command unix socket.\n");
exit(-1);
}
listen(sock,1);
printf("Listening from unix socket %s\n",sock_unix_path);
#else
fprintf(stderr,"Window pipe implementation not written yet.\n");
#endif
}
listen(server_sock,1);
return server_sock;
return sock;
}
static void *tcp_thread(void*p){
static void *net_thread(void*p){
char tmp[250];
ortp_socket_t server_sock;
struct sockaddr_storage ss;
#ifndef WIN32
struct sockaddr_un su;
#endif
socklen_t ssize;
bool_t run=TRUE;
server_sock=create_server_socket(tcp_port);
if (server_sock==-1) return NULL;
while(run){
while(net_reader_run){
while(client_sock!=-1){ /*sleep until the last command is finished*/
#ifndef WIN32
usleep(20000);
......@@ -410,15 +434,20 @@ static void *tcp_thread(void*p){
Sleep(20);
#endif
}
ssize=sizeof(ss);
if ((client_sock=accept(server_sock,(struct sockaddr*)&ss,&ssize))!=-1){
if (!unix_socket){
ssize=sizeof(ss);
client_sock=accept(server_sock,(struct sockaddr*)&ss,&ssize);
}else{
ssize=sizeof(su);
client_sock=accept(server_sock,(struct sockaddr*)&su,&ssize);
}
if (client_sock!=-1){
int len;
/*now read from the client */
if ((len=recv(client_sock,tmp,sizeof(tmp)-1,0))>0){
ortp_mutex_lock(&prompt_mutex);
tmp[len]='\0';
strcpy(received_prompt,tmp);
if (strcmp(received_prompt,"quit")==0) run=FALSE;
printf("Receiving command '%s'\n",received_prompt);fflush(stdout);
have_prompt=TRUE;
ortp_mutex_unlock(&prompt_mutex);
......@@ -428,15 +457,27 @@ static void *tcp_thread(void*p){
client_sock=-1;
}
}else{
if (net_reader_run) fprintf(stderr,"accept() failed: %s\n",getSocketError());
}
}
return NULL;
}
static void start_tcp_reader(void){
ortp_thread_t th;
static void start_net_reader(void){
ms_mutex_init(&prompt_mutex,NULL);
ortp_thread_create(&th,NULL,tcp_thread,NULL);
net_reader_run=TRUE;
ortp_thread_create(&net_reader_th,NULL,net_thread,NULL);
}
static void stop_net_reader(void){
net_reader_run=FALSE;
close(server_sock);
if (sock_unix_path[0]!=0){
unlink(sock_unix_path);
}
/*ortp_thread_join(net_reader_th,NULL);*/
}
#endif
......@@ -446,14 +487,14 @@ char *linphonec_readline(char *prompt){
return readline(prompt);
#else
static bool_t prompt_reader_started=FALSE;
static bool_t tcp_reader_started=FALSE;
static bool_t net_reader_started=FALSE;
if (!prompt_reader_started){
start_prompt_reader();
prompt_reader_started=TRUE;
}
if (tcp_port>0 && !tcp_reader_started){
start_tcp_reader();
tcp_reader_started=TRUE;
if ((tcp_port>0 || unix_socket) && !net_reader_started){
start_net_reader();
net_reader_started=TRUE;
}
fprintf(stdout,"%s",prompt);
fflush(stdout);
......@@ -632,6 +673,9 @@ linphonec_finish(int exit_status)
#ifdef HAVE_READLINE
linphonec_finish_readline();
#endif
if (net_reader_run)
stop_net_reader();
linphone_core_uninit (&linphonec);
if (mylogfile != NULL && mylogfile != stdout)
......@@ -1006,6 +1050,10 @@ linphonec_parse_cmdline(int argc, char **argv)
}
if (tcp_port==0) tcp_port=DEFAULT_TCP_PORT;
}
else if (strncmp ("--pipe", argv[arg_num], 6) == 0)
{
unix_socket=1;
}
else if (old_arg_num == arg_num)
{
fprintf (stderr, "ERROR: bad arguments\n");
......
......@@ -29,6 +29,8 @@
#else
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#endif
#include "ortp/ortp.h"
......@@ -36,27 +38,77 @@
#define DEFAULT_TCP_PORT "32333"
#define DEFAULT_REPLY_SIZE 4096
#define STATUS_REGISTERED (1<<0)
#define STATUS_REGISTERING (1<<1)
#define STATUS_DIALING (1<<2)
#define STATUS_AUTOANSWER (1<<3)
#define STATUS_IN_CONNECTED (1<<4) /* incoming call accepted */
#define STATUS_OUT_CONNECTED (1<<5) /*outgoing call accepted */
static int tcp=0;
static int make_status_value(const char *status_string){
int ret=0;
if (strstr(status_string,"registered, identity=")){
ret|=STATUS_REGISTERED;
}
if (strstr(status_string,"registered=-1")){
ret|=STATUS_REGISTERING;
}
if (strstr(status_string,"autoanswer=1")){
ret|=STATUS_AUTOANSWER;
}
if (strstr(status_string,"dialing")){
ret|=STATUS_DIALING;
}
if (strstr(status_string,"Call out")){
ret|=STATUS_OUT_CONNECTED;
}
if (strstr(status_string,"hook=answered")){
ret|=STATUS_IN_CONNECTED;
}
return ret;
}
static int send_command(const char *command, const char * port, char *reply, int reply_len, int print_errors){
ortp_socket_t sock;
struct addrinfo *ai=NULL;
struct addrinfo hints;
int err;
int i;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_INET;
hints.ai_socktype=SOCK_STREAM;
err=getaddrinfo("127.0.0.1",port,&hints,&ai);
if (err!=0){
if (print_errors) fprintf(stderr,"ERROR: getaddrinfo failed: error %i\n", err);
return -1;
}
sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (connect(sock,ai->ai_addr,ai->ai_addrlen)!=0){
if (print_errors) fprintf(stderr,"ERROR: Failed to connect socket.\n");
int err;
if (tcp){
struct addrinfo *ai=NULL;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_INET;
hints.ai_socktype=SOCK_STREAM;
err=getaddrinfo("127.0.0.1",port,&hints,&ai);
if (err!=0){
if (print_errors) fprintf(stderr,"ERROR: getaddrinfo failed: error %i\n", err);
return -1;
}
sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (connect(sock,ai->ai_addr,ai->ai_addrlen)!=0){
if (print_errors) fprintf(stderr,"ERROR: Failed to connect socket.\n");
freeaddrinfo(ai);
return -1;
}
freeaddrinfo(ai);
}else{
#ifndef WIN32
struct sockaddr_un sa;
char path[128];
sock=socket(AF_UNIX,SOCK_STREAM,0);
sa.sun_family=AF_UNIX;
snprintf(path,sizeof(path)-1,"/tmp/linphonec-%i",getuid());
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
if (connect(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
if (print_errors) fprintf(stderr,"ERROR: Failed to connect socket: %s\n",getSocketError());
return -1;
}
#else
fprintf(stderr,"ERROR: windows pipes communication not yet implemented.\n");
return -1;
#endif
}
freeaddrinfo(ai);
if (send(sock,command,strlen(command),0)<0){
if (print_errors) fprintf(stderr,"ERROR: Fail to send command to remote linphonec\n");
close_socket(sock);
......@@ -96,8 +148,10 @@ static void spawn_linphonec(int argc, char *argv[]){
pid_t pid;
j=0;
args[j++]="linphonec";
args[j++]="--tcp";
args[j++]=DEFAULT_TCP_PORT;
if (tcp){
args[j++]="--tcp";
args[j++]=DEFAULT_TCP_PORT;
}else args[j++]="--pipe";
args[j++]="-c";
args[j++]="/dev/null";
for(i=0;i<argc;++i){
......@@ -195,9 +249,17 @@ static int dial_execute(int argc, char *argv[]){
static int status_execute(int argc, char *argv[]){
char cmd[512];
char reply[DEFAULT_REPLY_SIZE];
int err;
if (argc==1){
snprintf(cmd,sizeof(cmd),"status %s",argv[0]);
return send_generic_command(cmd,TRUE);
err=send_command(cmd,DEFAULT_TCP_PORT,reply,sizeof(reply),TRUE);
if (err==0) {
printf("%s",reply);
err=make_status_value(reply);
}
return err;
}else{
print_usage();
}
......@@ -212,12 +274,15 @@ int main(int argc, char *argv[]){
}
ortp_init();
for(argi=1;argi<argc;++argi){
if (strcmp(argv[argi],"init")==0){
if (strcmp(argv[argi],"--tcp")==0){
tcp=1;
}else if (strcmp(argv[argi],"init")==0){
/*check if there is running instance*/
if (send_generic_command("help",0)==0){
fprintf(stderr,"A running linphonec has been found, not spawning a second one.\n");
}
spawn_linphonec(argc-argi-1,&argv[argi+1]);
if (tcp) fprintf(stderr,"WARNING: using --tcp is unsafe: unprivilegied users can make calls.\n");
return 0;
}else if (strcmp(argv[argi],"generic")==0){
if (argi+1<argc){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment