Security / Implementing a Secure Server with GDC |
This section provides an example of the source code to produce the port number for tunnelling with ssh.
Autoportfind.c/* Written by John A. Hobach, Dallas Texas, May 5th, 2004 The purpose of the application is to return a port number that will not be used for awhile. This port number can then be used by the Genero client for port forwarding. The operating system assigns ports in a round robin fashion so the port assigned is unlikely to be used again very soon. This will give the GDC time to start ssh and use that port. The OS will automatically skip ports in use. Revised 08/25/2004 Ver 2.1 to use bind() to get a port number assigned. It is assigned a port automatically from the operating system and we immediatly get it and return it. Revised 10/25/2005 Ver 2.2 to support returning a port number within a given range. This is accomplished by requesting ports from the OS until it is within the range specified. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #define USE_SOCKETS #include "util.h" char *progname; static char *ver="autoportfind - Version 2.2, 2005-10-20"; static char *help= "autoportfind [OPTION]\n" "\n" "Generate a port number for use with port forwarding.\n" "\n" " -e, --env\n" " Send FJSPORTFORWARD=<port> to stdout.\n" "\n" " -r Cycle through port assignments to determine which ports\n" " the OS assigns to ports when originating connections.\n" " -u n Upper limit. Request port numbers until one is returned\n" " below 'n'.\n" " -l n Lower limit. Request port numbers until one is returned\n" " above 'n'.\n" " -h Display this help message.\n" " -v Display the version number.\n" ; main(int argc, char **argv) { int sockfd, connected_socket, retval; int size, x, outofrange; int range_flag=0, env_flag=0; unsigned int port, startport, highest, lowest, cycle, direction, llimit=0, ulimit=~0; int reuse_addr=1; char **arg; struct sockaddr_in serv_addr; progname=argv[0]; arg=argv; while (--argc) { ++arg; if (!strcmp(*arg,"-r") || !strcmp(*arg,"--range")) { range_flag=1; } else if (!strcmp(*arg,"-e") || !strcmp(*arg,"--env")) { env_flag=1; } else if (!strcmp(*arg,"-u")) { ++arg; if (argc == 1 || *arg[0] == '-') { fprintf(stderr,"%s: Value missing for -u\n",progname); exit(1); } --argc; ulimit=atol(*arg); } else if (!strcmp(*arg,"-l")) { ++arg; if (argc == 1 || *arg[0] == '-') { fprintf(stderr,"%s: Value missing for -l\n",progname); exit(1); } --argc; llimit=atol(*arg);\ } else if (!strcmp(*arg,"-v")) { printf("%s\n",ver); exit(0); } else if (!strcmp(*arg,"-h") || !strcmp(*arg,"--help")) { printf("%s",help); exit(0); } else { fprintf(stderr,"%s:Unknown argument '%s'\n", progname, *arg); exit(1); } } lowest=~0; highest=0; startport=0; cycle=0; direction=1; do { outofrange=0; memset((char*) &serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_port=0; /* allow system to assign */ serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockfd < 0) { perror("socket"); close(sockfd); exit(1); } if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { perror("bind"); close(sockfd); exit(1); } size=sizeof(serv_addr); if (getsockname(sockfd, (struct sockaddr *) &serv_addr, &size) == -1) { perror("getsockname"); exit(errno); } if (range_flag) { port=ntohs(serv_addr.sin_port); if (!startport) startport=port; if (port > highest) highest=port; if (port < lowest) lowest=port; if (direction==0 && port <= startport) { cycle++; direction=1; } else if (direction==1 && port >= startport) { cycle++; direction=0; } } else { port=ntohs(serv_addr.sin_port); if (port > llimit && port < ulimit) { if (env_flag) printf("FJSPORTFORWARD="); printf("%d\n",ntohs(serv_addr.sin_port)); } else outofrange=1; } close(sockfd); } while ((range_flag && cycle < 3) || outofrange); if (range_flag) printf("Lowest port: %lu\nHighest port: %lu\n",lowest,highest); exit(0); } --- Util.h #ifndef UTIL_H #define UTIL_H #ifndef MAX # define MAX(a,b) a>b?a:b #endif #ifdef USE_SOCKETS # ifdef _WIN32 # include <winsock.h> # else # include <sys/types.h> # include <sys/socket.h> # include <netinet/in.h> /* struct sockaddr_in, ... */ # include <netinet/tcp.h> /* TCP_NODELAY, ... */ # include <arpa/inet.h> /* inet_addr, inet_ntoa, inet_aton */ # include <netdb.h> /* gethostbyname */ # endif #endif #ifdef _WIN32 # define SOCKLEN_T int #endif #ifdef __osf__ # define SOCKLEN_T int #endif #ifdef _AIX # ifdef USE_SOCKETS # include <sys/ioctl.h> # include <sys/time.h> # include <sys/select.h> # endif # define SOCKLEN_T socklen_t #endif #if defined (M_I386) /* SCO */ # ifdef USE_SOCKETS # include <sys/ioctl.h> # include <sys/time.h> # include <sys/select.h> # endif # define SOCKLEN_T int #endif #ifdef linux # define SOCKLEN_T socklen_t #endif #ifdef sun # if defined USE_SOCKETS # undef USE_SYS_SOCKIO # define USE_SYS_SOCKIO # endif # define SOCKLEN_T int #endif #ifdef __hpux # define SOCKLEN_T int #endif #ifndef SOCKLEN_T # define SOCKLEN_T size_t #endif #ifndef MSG_DONTWAIT # define MSG_DONTWAIT 0 #endif #endif