141828Sdillon/* 241828Sdillon * Copyright (c) 1992, 1993 341828Sdillon * The Regents of the University of California. All rights reserved. 441828Sdillon * All rights reserved. 541828Sdillon * 641828Sdillon * This code is derived from software donated to Berkeley by 741828Sdillon * Jan-Simon Pendry. 841828Sdillon * 941828Sdillon * Modified by Duncan Barclay. 1041828Sdillon * 1141828Sdillon * Redistribution and use in source and binary forms, with or without 1241828Sdillon * modification, are permitted provided that the following conditions 1341828Sdillon * are met: 1441828Sdillon * 1. Redistributions of source code must retain the above copyright 1541828Sdillon * notice, this list of conditions and the following disclaimer. 1641828Sdillon * 2. Redistributions in binary form must reproduce the above copyright 1741828Sdillon * notice, this list of conditions and the following disclaimer in the 1841828Sdillon * documentation and/or other materials provided with the distribution. 1941828Sdillon * 4. Neither the name of the University nor the names of its contributors 2041828Sdillon * may be used to endorse or promote products derived from this software 2141828Sdillon * without specific prior written permission. 2241828Sdillon * 2341828Sdillon * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2441828Sdillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2541828Sdillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2641828Sdillon * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2741828Sdillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2841828Sdillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2941828Sdillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3041828Sdillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3141828Sdillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3241828Sdillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3341828Sdillon * SUCH DAMAGE. 3441828Sdillon * 3541828Sdillon * @(#)pt_tcp.c 8.3 (Berkeley) 3/27/94 3641828Sdillon * 3741828Sdillon * pt_tcp.c,v 1.1.1.1 1994/05/26 06:34:34 rgrimes Exp 3841828Sdillon */ 3941828Sdillon 40129862Sstefanf#include <sys/cdefs.h> 41129862Sstefanf__FBSDID("$FreeBSD$"); 42129862Sstefanf 4341828Sdillon#include <stdio.h> 4441828Sdillon#include <unistd.h> 4541828Sdillon#include <stdlib.h> 4641828Sdillon#include <errno.h> 47129863Sstefanf#include <string.h> 4841828Sdillon#include <sys/types.h> 4941828Sdillon#include <sys/param.h> 5041828Sdillon#include <sys/syslog.h> 5141828Sdillon#include <sys/socket.h> 5241828Sdillon#include <netinet/in.h> 5341828Sdillon#include <arpa/inet.h> 5441828Sdillon#include <netdb.h> 5541828Sdillon 5641828Sdillon#include "portald.h" 5741828Sdillon 5841828Sdillon/* 5941828Sdillon * Key will be tcplisten/host/port 6041828Sdillon * 6141828Sdillon * Create a TCP socket bound to the requested host and port. 6241828Sdillon * If the host is "ANY" the receving address will be set to INADDR_ANY. 6341828Sdillon * If the port is 0 the caller must find out the returned port number 6441828Sdillon * using a call to getsockname. 6541828Sdillon * 6641828Sdillon * XXX! The owner of the socket will be root rather then the user. This 6741828Sdillon * may cause remote auth (identd) to return unexpected results. 6841828Sdillon * 6941828Sdillon */ 70166157Srodrigcint portal_tcplisten(struct portal_cred *pcr, char *key, char **v, 71166157Srodrigc int kso __unused, int *fdp) 7241828Sdillon{ 7341828Sdillon char host[MAXHOSTNAMELEN]; 7441828Sdillon char port[MAXHOSTNAMELEN]; 7541828Sdillon char *p = key + (v[1] ? strlen(v[1]) : 0); 7641828Sdillon char *q; 7741828Sdillon struct hostent *hp; 7841828Sdillon struct servent *sp; 79166157Srodrigc struct in_addr **ipp = NULL; 8041828Sdillon struct in_addr *ip[2]; 8141828Sdillon struct in_addr ina; 8241828Sdillon u_short s_port; 8341828Sdillon int any = 0; 8441828Sdillon struct sockaddr_in sain; 8541828Sdillon 8641828Sdillon q = strchr(p, '/'); 87166157Srodrigc if (q == 0 || q - p >= (int)sizeof(host)) 8841828Sdillon return (EINVAL); 8941828Sdillon *q = '\0'; 9041828Sdillon snprintf(host, sizeof(host), "%s", p); 9141828Sdillon p = q + 1; 9241828Sdillon 9341828Sdillon q = strchr(p, '/'); 9441828Sdillon if (q) 9541828Sdillon *q = '\0'; 9641828Sdillon if (strlen(p) >= sizeof(port)) 9741828Sdillon return (EINVAL); 9841828Sdillon snprintf(port, sizeof(port), "%s", p); 9941828Sdillon 10041828Sdillon if (strcmp(host, "ANY") == 0) { 10141828Sdillon any = 1; 10241828Sdillon } else { 10341828Sdillon hp = gethostbyname(host); 10441828Sdillon if (hp != 0) { 10541828Sdillon ipp = (struct in_addr **) hp->h_addr_list; 10641828Sdillon } else { 10741828Sdillon ina.s_addr = inet_addr(host); 10841828Sdillon if (ina.s_addr == INADDR_NONE) 10941828Sdillon return (EINVAL); 11041828Sdillon ip[0] = &ina; 11141828Sdillon ip[1] = 0; 11241828Sdillon ipp = ip; 11341828Sdillon } 11441828Sdillon } 11541828Sdillon#ifdef DEBUG 11641828Sdillon if (any) 11741828Sdillon printf("INADDR_ANY to be used for hostname\n"); 11841828Sdillon else 11941828Sdillon printf("inet address for %s is %s\n", host, inet_ntoa(*ipp[0])); 12041828Sdillon#endif 12141828Sdillon 12241828Sdillon sp = getservbyname(port, "tcp"); 12341828Sdillon if (sp != NULL) { 12441828Sdillon s_port = (u_short) sp->s_port; 12541828Sdillon } else { 12641828Sdillon s_port = strtoul(port, &p, 0); 12741828Sdillon if (*p != '\0') 12841828Sdillon return (EINVAL); 12941828Sdillon s_port = htons(s_port); 13041828Sdillon } 13141828Sdillon if ((ntohs(s_port) != 0) && 13241828Sdillon (ntohs(s_port) <= IPPORT_RESERVED) && 13341828Sdillon (pcr->pcr_uid != 0)) 13441828Sdillon return (EPERM); 13541828Sdillon#ifdef DEBUG 13641828Sdillon printf("port number for %s is %d\n", port, ntohs(s_port)); 13741828Sdillon#endif 13841828Sdillon 13941828Sdillon memset(&sain, 0, sizeof(sain)); 14041828Sdillon sain.sin_len = sizeof(sain); 14141828Sdillon sain.sin_family = AF_INET; 14241828Sdillon sain.sin_port = s_port; 14341828Sdillon 14441828Sdillon if (any) { 14541828Sdillon int so; 14641828Sdillon int sock; 14741828Sdillon 14841828Sdillon so = socket(AF_INET, SOCK_STREAM, 0); 14941828Sdillon if (so < 0) { 15041828Sdillon syslog(LOG_ERR, "socket: %m"); 15141828Sdillon return (errno); 15241828Sdillon } 15341828Sdillon 15441828Sdillon sain.sin_addr.s_addr = INADDR_ANY; 15541828Sdillon if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { 15641828Sdillon listen(so, 1); 15741828Sdillon if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { 15841828Sdillon syslog(LOG_ERR, "accept: %m"); 15941828Sdillon (void) close(so); 16041828Sdillon return (errno); 16141828Sdillon } 16241828Sdillon *fdp = sock; 16341828Sdillon (void) close(so); 16441828Sdillon return (0); 16541828Sdillon } 16641828Sdillon syslog(LOG_ERR, "bind: %m"); 16741828Sdillon (void) close(so); 16841828Sdillon return (errno); 16941828Sdillon } 17041828Sdillon 17141828Sdillon while (ipp[0]) { 17241828Sdillon int so; 17341828Sdillon int sock; 17441828Sdillon 17541828Sdillon so = socket(AF_INET, SOCK_STREAM, 0); 17641828Sdillon if (so < 0) { 17741828Sdillon syslog(LOG_ERR, "socket: %m"); 17841828Sdillon return (errno); 17941828Sdillon } 18041828Sdillon 18141828Sdillon sain.sin_addr = *ipp[0]; 18241828Sdillon if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { 18341828Sdillon listen(so, 1); 18441828Sdillon if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { 18541828Sdillon syslog(LOG_ERR, "accept: %m"); 18641828Sdillon (void) close(so); 18741828Sdillon return (errno); 18841828Sdillon } 18941828Sdillon *fdp = sock; 19041828Sdillon (void) close(so); 19141828Sdillon return (0); 19241828Sdillon } 19341828Sdillon (void) close(so); 19441828Sdillon 19541828Sdillon ipp++; 19641828Sdillon } 19741828Sdillon 19841828Sdillon syslog(LOG_ERR, "bind: %m"); 19941828Sdillon return (errno); 20041828Sdillon 20141828Sdillon} 202