#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xos.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifdef X_POSIX_C_SOURCE
#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
#include <signal.h>
#undef _POSIX_C_SOURCE
#else
#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
#include <signal.h>
#else
#define _POSIX_SOURCE
#include <signal.h>
#undef _POSIX_SOURCE
#endif
#endif
#include <X11/Xproto.h>
#include <X11/ICE/ICElib.h>
#include <X11/ICE/ICEmsg.h>
#include <X11/ICE/ICEproto.h>
#include <X11/PM/PM.h>
#include <X11/PM/PMproto.h>
#include "xfwp.h"
#include "pm.h"
#include "transport.h"
#include "misc.h"
void FWPprocessMessages(
IceConn iceConn,
IcePointer * client_data,
int opcode,
unsigned long length,
Bool swap)
{
switch (opcode)
{
case PM_GetProxyAddr:
{
pmGetProxyAddrMsg *pMsg;
char *pData, *pStart;
char *serviceName = NULL, *serverAddress = NULL;
char *hostAddress = NULL, *startOptions = NULL;
char *authName = NULL, *authData = NULL;
int authLen;
struct clientDataStruct * program_data;
char * listen_port_string;
int pm_send_msg_len;
pmGetProxyAddrReplyMsg * pReply;
char * pReplyData;
struct hostent * hostptr;
struct sockaddr_in server_sockaddr_in;
struct sockaddr_in dummy_sockaddr_in;
char * server_name_base;
char * config_failure = "unrecognized server or permission denied";
char * tmp_str;
int rule_number = -1;
char * colon;
char * tmpAddress = NULL;
program_data = (struct clientDataStruct *) client_data;
#if 0
CHECK_AT_LEAST_SIZE (iceConn, global_data.major_opcode, opcode,
length, SIZEOF (pmGetProxyAddrMsg), IceFatalToProtocol);
#endif
IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrMsg),
pmGetProxyAddrMsg, pMsg, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return;
}
authLen = swap ? lswaps (pMsg->authLen) : pMsg->authLen;
pData = pStart;
SKIP_STRING (pData, swap);
SKIP_STRING (pData, swap);
SKIP_STRING (pData, swap);
SKIP_STRING (pData, swap);
if (authLen > 0)
{
SKIP_STRING (pData, swap);
pData += (authLen + PAD64 (authLen));
}
CHECK_COMPLETE_SIZE (iceConn, global_data.major_opcode, opcode,
length, pData - pStart + SIZEOF (pmGetProxyAddrMsg),
pStart, IceFatalToProtocol);
pData = pStart;
EXTRACT_STRING (pData, swap, serviceName);
EXTRACT_STRING (pData, swap, serverAddress);
EXTRACT_STRING (pData, swap, hostAddress);
EXTRACT_STRING (pData, swap, startOptions);
if (authLen > 0)
{
EXTRACT_STRING (pData, swap, authName);
authData = (char *) malloc (authLen);
memcpy (authData, pData, authLen);
}
#ifdef DEBUG
(void) fprintf (stderr,
"Got GetProxyAddr, serviceName = %s, serverAddr = %s\n",
serviceName, serverAddress);
(void) fprintf (stderr,
"\thostAddr = %s, options = %s, authLen = %d\n",
hostAddress, startOptions, authLen);
if (authLen > 0)
(void) fprintf (stderr, "\tauthName = %s\n", authName);
#endif
if ((tmp_str = strdup (serverAddress)) == NULL)
{
(void) fprintf(stderr, "malloc - serverAddress copy\n");
goto sendFailure;
}
server_name_base = strtok(tmp_str, ":");
if ((hostptr = gethostbyname(server_name_base)) == NULL)
{
(void) fprintf(stderr, "gethostbyname (%s) failed\n", server_name_base);
goto sendFailure;
}
memset(&server_sockaddr_in, 0, sizeof(server_sockaddr_in));
memset(&dummy_sockaddr_in, 0, sizeof(dummy_sockaddr_in));
memcpy((char *) &server_sockaddr_in.sin_addr,
hostptr->h_addr,
hostptr->h_length);
memcpy((char *) &dummy_sockaddr_in.sin_addr,
hostptr->h_addr,
hostptr->h_length);
if ((doConfigCheck(&dummy_sockaddr_in,
&server_sockaddr_in,
global_data.config_info,
FINDPROXY,
&rule_number)) == FAILURE)
{
(void) fprintf(stderr, "xfindproxy failed config check\n");
sendFailure:
pm_send_msg_len = STRING_BYTES(config_failure)
+ STRING_BYTES(NULL);
IceGetHeaderExtra(iceConn,
program_data->major_opcode,
PM_GetProxyAddrReply,
SIZEOF(pmGetProxyAddrReplyMsg),
WORD64COUNT (pm_send_msg_len),
pmGetProxyAddrReplyMsg,
pReply,
pReplyData);
pReply->status = PM_Failure;
STORE_STRING(pReplyData, NULL);
STORE_STRING(pReplyData, config_failure);
IceFlush(iceConn);
free(tmp_str);
return;
}
colon = strchr (serverAddress, ':');
if (colon)
{
struct hostent *hostent;
*colon = '\0';
hostent = gethostbyname (serverAddress);
*colon = ':';
if (hostent && hostent->h_name) {
tmpAddress = (char *) malloc (strlen (hostent->h_name) +
strlen (colon) + 1);
(void) sprintf (tmpAddress, "%s%s", hostent->h_name, colon);
serverAddress = tmpAddress;
}
}
if ((doCheckServerList(serverAddress,
&listen_port_string,
program_data->config_info->num_servers)) == FAILURE)
{
if ((doSetupRemClientListen(&listen_port_string,
program_data,
serverAddress)) == FAILURE)
{
goto sendFailure;
}
}
if (tmpAddress)
free (tmpAddress);
pm_send_msg_len = STRING_BYTES(listen_port_string)
+ STRING_BYTES(NULL);
IceGetHeaderExtra(iceConn,
program_data->major_opcode,
PM_GetProxyAddrReply,
SIZEOF(pmGetProxyAddrReplyMsg),
WORD64COUNT (pm_send_msg_len),
pmGetProxyAddrReplyMsg,
pReply,
pReplyData);
pReply->status = PM_Success;
STORE_STRING(pReplyData, listen_port_string);
STORE_STRING(pReplyData, NULL);
IceFlush(iceConn);
program_data->config_info->select_timeout.tv_sec =
program_data->config_info->client_listen_timeout;
break;
}
case ICE_Error:
{
iceErrorMsg *pMsg;
char *pStart;
CHECK_AT_LEAST_SIZE (iceConn, global_data.major_opcode, ICE_Error,
length, sizeof(iceErrorMsg), IceFatalToProtocol);
IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
iceErrorMsg, pMsg, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return;
}
if (swap)
{
pMsg->errorClass = lswaps (pMsg->errorClass);
pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
}
(void) fprintf(stderr, "Proxy Manager reported ICE Error:\n");
(void) fprintf(stderr, "\tclass = 0x%x, offending minor opcode = %d\n",
pMsg->errorClass, pMsg->offendingMinorOpcode);
(void) fprintf(stderr, "\tseverity = %d, sequence = %ld\n",
pMsg->severity, (long)pMsg->offendingSequenceNum);
IceDisposeCompleteMessage (iceConn, pStart);
break;
}
default:
break;
}
}
Bool
FWPHostBasedAuthProc (
char * hostname)
{
return True;
}
Status
FWPprotocolSetupProc(
IceConn iceConn,
int major_version,
int minor_version,
char * vendor,
char * release,
IcePointer * clientDataRet,
char ** failureReasonRet)
{
struct clientDataStruct * client_data;
if ((client_data = (struct clientDataStruct *)
malloc (sizeof (struct clientDataStruct))) == NULL)
{
(void) fprintf(stderr, "malloc - client data object\n");
return (0);
}
client_data->config_info = global_data.config_info;
client_data->nfds = global_data.nfds;
client_data->rinit = global_data.rinit;
client_data->winit = global_data.winit;
client_data->major_opcode = global_data.major_opcode;
*clientDataRet = client_data;
return (1);
}
int
doSetupPMListen(
char * pm_port,
int * size_pm_listen_array,
int ** pm_listen_array,
IceListenObj ** listen_objects,
int * nfds,
fd_set * rinit)
{
int num_fds_returned;
char errormsg[256];
int fd_counter;
IceListenObj * temp_obj;
if (!IceListenForWellKnownConnections(pm_port,
&num_fds_returned,
listen_objects,
256,
errormsg))
{
(void) fprintf(stderr, "IceListenForWellKnowConnections error: %s\n",
errormsg);
return 0;
}
*pm_listen_array = (int *) malloc (num_fds_returned * sizeof (int *));
if (!pm_listen_array)
{
(void) fprintf (stderr, "malloc - pm_listen_array\n");
return 0;
}
*size_pm_listen_array = num_fds_returned;
for (fd_counter = 0; fd_counter < num_fds_returned; fd_counter++)
{
temp_obj = *listen_objects;
IceSetHostBasedAuthProc(temp_obj[fd_counter], FWPHostBasedAuthProc);
(*pm_listen_array)[fd_counter] =
IceGetListenConnectionNumber(temp_obj[fd_counter]);
FD_SET((*pm_listen_array)[fd_counter], rinit);
*nfds = max(*nfds, (*pm_listen_array)[fd_counter] + 1);
}
return 1;
}
static IceIOErrorHandler prev_handler;
static void
MyIoErrorHandler (
IceConn ice_conn)
{
if (prev_handler)
(*prev_handler) (ice_conn);
}
void
doInstallIOErrorHandler (void)
{
IceIOErrorHandler default_handler;
prev_handler = IceSetIOErrorHandler (NULL);
default_handler = IceSetIOErrorHandler (MyIoErrorHandler);
if (prev_handler == default_handler)
prev_handler = NULL;
#ifdef X_NOT_POSIX
signal(SIGPIPE, SIG_IGN);
#else
{
struct sigaction act;
(void) sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
(void) sigaction(SIGPIPE, &act, NULL);
}
#endif
}