/*

2009-01-28 v1 Thomas Eckhardt <tafe at unkelhaeusser dot net>

Adobe Flash:
HTTP policy files may no longer be used to authorize socket connections. 
Prior to version 9,0,115,0, an HTTP policy file, served from the master 
location of /crossdomain.xml on port 80, could be used to authorize a 
socket connection to any port 1024 or greater on the same host.

*/

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>

#define LISTENPORT 843
#define LISTENBACKLOG 7
#define UNPRIVUSER 1
static char XMLMSG[512] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <cross-domain-policy xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd\">\n        <allow-access-from domain=\"*\" to-ports=\"*\" secure=\"false\" />\n        <site-control permitted-cross-domain-policies=\"master-only\" />\n    </cross-domain-policy>\n";

int main (int argc, char **argv) {

  int sockfd = -1;
  int client = -1;
  int childpid = 0;
  struct sockaddr_in addr;
  socklen_t clientsize;

  sockfd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sockfd != -1) {
    addr.sin_family = PF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(LISTENPORT);

    if ( bind(sockfd, (struct sockaddr *) &addr, sizeof(addr) ) != -1 ) {
      if( listen(sockfd, LISTENBACKLOG) != -1) {
	/* drop priv & fork */
        signal(SIGHUP, SIG_IGN);
	if (setgid( UNPRIVUSER ) == -1) { perror("can't setgid()"); }
        if (setuid( UNPRIVUSER ) == -1) { perror("can't setuid()"); }
        if ((childpid = fork()) < 0) { perror("can't fork");
        } else {
	  if (childpid > 0) { exit(0); } /* parent */
        }

        clientsize = sizeof(addr);
        for (;;) {
	   if ( (client = accept(sockfd, (struct sockaddr *)&addr, &clientsize)) != -1 ) {
	     if ( send(client, XMLMSG, sizeof(XMLMSG), MSG_DONTWAIT) == -1 ) { perror("send failed"); }
	     close(client);
	   } else { perror("error accepting connection"); }
        } /* endless loop end ;) */
      } else { perror("could not listen to socket"); }
    } else { perror("could not bind to socket"); }

    /* we will never get there, but to be complete .. :> */
    close (sockfd);

  } else { perror("could not open socket"); }

  return 0;
}

