setuid_socket_wrap.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 259 行

C
259
字号
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ *//* * setuid_socket_wrap.c * * ./a.out [-s [tag,][addr]:[port]]* [-d [tag,][addr]:[port]]*  *         [-r [tag,]proto]* -- program args * * Where: -s = stream socket, -d datagram socket and -r means raw socket. * */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#ifndef EXEC_PROGRAM#  define EXEC_PROGRAM "/bin/echo"#endif#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <ctype.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#ifndef INADDR_NONE#define INADDR_NONE 0xffffffff#endifstruct sock_list {    struct sock_list *next;    int fd;    int type;    int protocol;    struct sockaddr_in addr;    char *arg;};int parse_addr(addr, str)    struct sockaddr_in *addr;    char *str;{    int port = 0;    char *cp;    struct hostent *hp;    struct servent *se;    if ((cp = strrchr(str, (int)':')) != NULL)        *cp++ = '\0';    if (cp) {        if (!isdigit((int)cp[0])) {            if ((se = getservbyname(cp, "tcp")) != NULL) {                port = ntohs(se->s_port);	    } else {		fprintf(stderr, "unknown port %s\n", cp);		return -1;	    }        } else {            port = atoi(cp);        }    }    if (port < 0 || port > 0xffff) {	fprintf(stderr, "bad port number %d\n", port);        return -1;    }        bzero(addr, sizeof(*addr));    addr->sin_family = AF_INET;    addr->sin_port = htons(port);    if (*str == '\000') {	addr->sin_addr.s_addr = INADDR_ANY;    } else {	if ((addr->sin_addr.s_addr = inet_addr(str)) == INADDR_NONE) {	    if ((hp = gethostbyname(str)) == NULL) {		fprintf(stderr, "\"%s\" unknown host or address!\n", str);		return -1;	    } else {		bcopy(hp->h_addr_list[0], &addr->sin_addr.s_addr,hp->h_length);	    }	}    }    return 0;}struct sock_list *new_entry(type, argstr)    int type;    char *argstr;{    struct sock_list *sle;    char *cp;        sle = (struct sock_list *)malloc(sizeof(struct sock_list));    if (!sle)	return NULL;    sle->next = NULL;    sle->fd = -1;    if ((cp = strchr(argstr, (int)',')) != NULL) {	*cp++ = '\0';	sle->arg = argstr;	argstr = cp;    } else {	sle->arg = "-fd";    }    sle->type = type;    switch (type) {        case SOCK_RAW: {	    struct protoent *pe;	    pe = getprotobyname(argstr);	    if (!pe) {		fprintf(stderr, "Unknown protocol: %s\n", argstr);		free(sle);		return NULL;	    }	    sle->protocol = pe->p_proto;	    break;	}        case SOCK_STREAM:        case SOCK_DGRAM:	    sle->protocol = 0;	    if (parse_addr(&sle->addr, argstr) < 0) {		free(sle);		return NULL;	    }	    break;    }    return sle;}int open_socket(sle)    struct sock_list *sle;{    sle->fd = socket(AF_INET, sle->type, sle->protocol);    if (sle->fd < 0) {	perror("socket");	return -1;    }    if (sle->type != SOCK_RAW) {#if 0	printf("binding fd %d to %s:%d\n", sle->fd,	       inet_ntoa(sle->addr.sin_addr), ntohs(sle->addr.sin_port));#endif	if (bind(sle->fd, (struct sockaddr *)&sle->addr, sizeof(sle->addr))<0){	    perror("bind");	    close(sle->fd);	    return -1;	}    }    return sle->fd;}int main(argc, argv)    int argc;    char *argv[];{    struct sock_list *sl = NULL, *sltmp = NULL;    int count = 0;    int c;    while ((c = getopt(argc, argv, "s:d:r:")) != EOF)	switch (c) {	case 's':	    sltmp = new_entry(SOCK_STREAM, optarg);	    if (!sltmp) {		exit(1);	    }	    sltmp->next = sl;	    sl = sltmp;	    count++;	    break;	case 'd':	    sltmp = new_entry(SOCK_DGRAM, optarg);	    if (!sltmp) {		exit(1);	    }	    sltmp->next = sl;	    sl = sltmp;	    count++;	    break;	case 'r':	    sltmp = new_entry(SOCK_RAW, optarg);	    if (!sltmp) {		exit(1);	    }	    sltmp->next = sl;	    sl = sltmp;	    count++;	    break;	default:	    exit(1);	}    argc -= optind;    argv += optind;    for(sltmp = sl; sltmp != NULL; sltmp = sltmp->next)	if (open_socket(sltmp) < 0) {	    fprintf(stderr, "failed to create socket!\n");	    exit(1);	}    setuid(getuid());        {	int i;	char **newargv;	char *run_prog = EXEC_PROGRAM;	char *run_prog_name;	newargv = (char **)malloc((1 + 2*count + argc + 1) * sizeof(char*));	if ((run_prog_name = strrchr(run_prog, (int)'/')) == NULL)	    run_prog_name = run_prog;	else	    run_prog_name++;	i = 0;	newargv[i++] = run_prog_name;	for (; argc; argc--, argv++, i++)	    newargv[i] = *argv;	for(sltmp = sl; sltmp != NULL; ) {	    char *fd_str = (char *)malloc(8);	    if (!fd_str) exit(1);	    sprintf(fd_str, "%d", sltmp->fd);	    if (sltmp->arg && *(sltmp->arg))		newargv[i++] = sltmp->arg;	    newargv[i++] = fd_str;	    sl = sltmp;	    sltmp = sltmp->next;	    free(sl);	}	newargv[i] = (char *)NULL;	execv(run_prog, newargv);	perror("exec");	exit(1);    }    exit(0);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?