示例#1
0
文件: network.c 项目: Jimdo/stunnel
char *fd_getline(CLI *c, int fd) {
    char *line, *tmpline;
    int ptr=0, allocated=32;

    line=str_alloc(allocated);
    for(;;) {
        s_poll_init(c->fds);
        s_poll_add(c->fds, fd, 1, 0); /* read */
        switch(s_poll_wait(c->fds, c->opt->timeout_busy, 0)) {
        case -1:
            sockerror("fd_getline: s_poll_wait");
            str_free(line);
            longjmp(c->err, 1); /* error */
        case 0:
            s_log(LOG_INFO, "fd_getline: s_poll_wait:"
                " TIMEOUTbusy exceeded: sending reset");
            str_free(line);
            longjmp(c->err, 1); /* timeout */
        case 1:
            break; /* OK */
        default:
            s_log(LOG_ERR, "fd_getline: s_poll_wait: Unknown result");
            str_free(line);
            longjmp(c->err, 1); /* error */
        }
        if(allocated<ptr+1) {
            allocated*=2;
            line=str_realloc(line, allocated);
        }
        switch(readsocket(fd, line+ptr, 1)) {
        case -1: /* error */
            sockerror("fd_getline: readsocket");
            str_free(line);
            longjmp(c->err, 1);
        case 0: /* EOF */
            s_log(LOG_ERR, "fd_getline: Unexpected socket close");
            str_free(line);
            longjmp(c->err, 1);
        }
        if(line[ptr]=='\r')
            continue;
        if(line[ptr]=='\n')
            break;
        if(line[ptr]=='\0')
            break;
        if(++ptr>65536) { /* >64KB --> DoS protection */
            s_log(LOG_ERR, "fd_getline: Line too long");
            str_free(line);
            longjmp(c->err, 1);
        }
    }
    line[ptr]='\0';
    tmpline=str_dup(line);
    safestring(tmpline);
    s_log(LOG_DEBUG, " <- %s", tmpline);
    str_free(tmpline);
    return line;
}
示例#2
0
static int auth_user(CLI *c) {
    struct servent *s_ent;    /* structure for getservbyname */
    SOCKADDR_UNION ident;     /* IDENT socket name */
    int fd;                   /* IDENT socket descriptor */
    char name[STRLEN];
    int retval;
    int error;

    if(!c->opt->username)
        return 0; /* -u option not specified */
    if((fd=socket(c->peer_addr.addr[0].sa.sa_family, SOCK_STREAM, 0))<0) {
        sockerror("socket (auth_user)");
        return -1;
    }
    if(alloc_fd(fd))
        return -1;
    memcpy(&ident, &c->peer_addr.addr[0], sizeof(SOCKADDR_UNION));
    s_ent=getservbyname("auth", "tcp");
    if(s_ent) {
        ident.in.sin_port=s_ent->s_port;
    } else {
        s_log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.in.sin_port=htons(113);
    }
    if(connect(fd, &ident.sa, addr_len(ident))) {
        error=get_last_socket_error();
        if(error!=EINPROGRESS && error!=EWOULDBLOCK) {
            sockerror("ident connect (auth_user)");
            closesocket(fd);
            return -1;
        }
        if(connect_wait(c, fd, c->opt->timeout_connect)) { /* error */
            closesocket(fd);
            return -1;
        }
    }
    s_log(LOG_DEBUG, "IDENT server connected");
    if(fdprintf(c, fd, "%u , %u",
            ntohs(c->peer_addr.addr[0].in.sin_port),
            ntohs(c->opt->local_addr.addr[0].in.sin_port))<0) {
        sockerror("fdprintf (auth_user)");
        closesocket(fd);
        return -1;
    }
    if(fdscanf(c, fd, "%*[^:]: USERID :%*[^:]:%s", name)!=1) {
        s_log(LOG_ERR, "Incorrect data from IDENT server");
        closesocket(fd);
        return -1;
    }
    closesocket(fd);
    retval=strcmp(name, c->opt->username) ? -1 : 0;
    safestring(name);
    s_log(LOG_INFO, "IDENT resolved remote user to %s", name);
    return retval;
}
示例#3
0
文件: network.c 项目: Jimdo/stunnel
void fd_putline(CLI *c, int fd, const char *line) {
    char *tmpline;
    const char crlf[]="\r\n";
    int len;

    tmpline=str_printf("%s%s", line, crlf);
    len=strlen(tmpline);
    s_write(c, fd, tmpline, len);
    tmpline[len-2]='\0'; /* remove CRLF */
    safestring(tmpline);
    s_log(LOG_DEBUG, " -> %s", tmpline);
    str_free(tmpline);
}
示例#4
0
文件: network.c 项目: djs55/stunnel
void fdputline(CLI *c, int fd, char *line) {
    char tmpline[STRLEN];
    const char crlf[]="\r\n";
    int len;

    if(strlen(line)+2>=STRLEN) { /* 2 for crlf */
        s_log(LOG_ERR, "Line too long in fdputline");
        longjmp(c->err, 1);
    }
    safecopy(tmpline, line);
    safeconcat(tmpline, crlf);
    len=strlen(tmpline);
    write_blocking(c, fd, tmpline, len);
    tmpline[len-2]='\0'; /* remove CRLF */
    safestring(tmpline);
    s_log(LOG_DEBUG, " -> %s", tmpline);
}
示例#5
0
文件: network.c 项目: djs55/stunnel
void fdgetline(CLI *c, int fd, char *line) {
    char logline[STRLEN];
    s_poll_set fds;
    int ptr;

    for(ptr=0;;) {
        s_poll_zero(&fds);
        s_poll_add(&fds, fd, 1, 0); /* read */
        switch(s_poll_wait(&fds, c->opt->timeout_busy)) {
        case -1:
            sockerror("fdgetline: s_poll_wait");
            longjmp(c->err, 1); /* error */
        case 0:
            s_log(LOG_INFO, "fdgetline: s_poll_wait timeout");
            longjmp(c->err, 1); /* timeout */
        case 1:
            break; /* OK */
        default:
            s_log(LOG_ERR, "fdgetline: s_poll_wait unknown result");
            longjmp(c->err, 1); /* error */
        }
        switch(readsocket(fd, line+ptr, 1)) {
        case -1: /* error */
            sockerror("readsocket (fdgetline)");
            longjmp(c->err, 1);
        case 0: /* EOF */
            s_log(LOG_ERR, "Unexpected socket close (fdgetline)");
            longjmp(c->err, 1);
        }
        if(line[ptr]=='\r')
            continue;
        if(line[ptr]=='\n')
            break;
        if(!line[ptr])
            break;
        if(++ptr==STRLEN) {
            s_log(LOG_ERR, "Input line too long");
            longjmp(c->err, 1);
        }
    }
    line[ptr]='\0';
    safecopy(logline, line);
    safestring(logline);
    s_log(LOG_DEBUG, " <- %s", logline);
}
示例#6
0
static int verify_callback(int preverify_ok, X509_STORE_CTX *callback_ctx) {
        /* our verify callback function */
    SSL *ssl;
    CLI *c;
    char subject_name[STRLEN];

    /* retrieve application specific data */
    ssl=X509_STORE_CTX_get_ex_data(callback_ctx,
        SSL_get_ex_data_X509_STORE_CTX_idx());
    c=SSL_get_ex_data(ssl, cli_index);

    /* certificate name for logging */
    X509_NAME_oneline(X509_get_subject_name(callback_ctx->current_cert),
        subject_name, STRLEN);
    safestring(subject_name);

    s_log(LOG_DEBUG, "Starting certificate verification: depth=%d, %s",
        callback_ctx->error_depth, subject_name);
    if(!cert_check(c, callback_ctx, preverify_ok)) {
        s_log(LOG_WARNING, "Certificate check failed: depth=%d, %s",
            callback_ctx->error_depth, subject_name);
        return 0; /* reject connection */
    }
    if(!crl_check(c, callback_ctx)) {
        s_log(LOG_WARNING, "CRL check failed: depth=%d, %s",
            callback_ctx->error_depth, subject_name);
        return 0; /* reject connection */
    }
    if(c->opt->option.ocsp && !ocsp_check(c, callback_ctx)) {
        s_log(LOG_WARNING, "OCSP check failed: depth=%d, %s",
            callback_ctx->error_depth, subject_name);
        return 0; /* reject connection */
    }
    /* errnum=X509_STORE_CTX_get_error(ctx); */
    s_log(LOG_NOTICE, "Certificate accepted: depth=%d, %s",
        callback_ctx->error_depth, subject_name);
    return 1; /* accept connection */
}
示例#7
0
static int connect_local(CLI *c) { /* spawn local process */
#if defined (USE_WIN32) || defined (__vms)
    s_log(LOG_ERR, "LOCAL MODE NOT SUPPORTED ON WIN32 and OpenVMS PLATFORM");
    return -1;
#else /* USE_WIN32, __vms */
    char env[3][STRLEN], name[STRLEN], *portname;
    int fd[2], pid;
    X509 *peer;
#ifdef HAVE_PTHREAD_SIGMASK
    sigset_t newmask;
#endif

    if (c->opt->option.pty) {
        char tty[STRLEN];

        if(pty_allocate(fd, fd+1, tty, STRLEN)) {
            return -1;
        }
        s_log(LOG_DEBUG, "%s allocated", tty);
    } else {
        if(make_sockets(fd))
            return -1;
    }
    pid=fork();
    c->pid=(unsigned long)pid;
    switch(pid) {
    case -1:    /* error */
        closesocket(fd[0]);
        closesocket(fd[1]);
        ioerror("fork");
        return -1;
    case  0:    /* child */
        closesocket(fd[0]);
        dup2(fd[1], 0);
        dup2(fd[1], 1);
        if(!options.option.foreground)
            dup2(fd[1], 2);
        closesocket(fd[1]);
        safecopy(env[0], "REMOTE_HOST=");
        safeconcat(env[0], c->accepting_address);
        portname=strrchr(env[0], ':');
        if(portname) /* strip the port name */
            *portname='\0';
        putenv(env[0]);
        if(c->opt->option.transparent) {
            putenv("LD_PRELOAD=" LIBDIR "/libstunnel.so");
            /* For Tru64 _RLD_LIST is used instead */
            putenv("_RLD_LIST=" LIBDIR "/libstunnel.so:DEFAULT");
        }
        if(c->ssl) {
            peer=SSL_get_peer_certificate(c->ssl);
            if(peer) {
                safecopy(env[1], "SSL_CLIENT_DN=");
                X509_NAME_oneline(X509_get_subject_name(peer), name, STRLEN);
                safestring(name);
                safeconcat(env[1], name);
                putenv(env[1]);
                safecopy(env[2], "SSL_CLIENT_I_DN=");
                X509_NAME_oneline(X509_get_issuer_name(peer), name, STRLEN);
                safestring(name);
                safeconcat(env[2], name);
                putenv(env[2]);
                X509_free(peer);
            }
        }
#ifdef HAVE_PTHREAD_SIGMASK
        sigemptyset(&newmask);
        sigprocmask(SIG_SETMASK, &newmask, NULL);
#endif
        execvp(c->opt->execname, c->opt->execargs);
        ioerror(c->opt->execname); /* execv failed */
        _exit(1);
    default:
        break;
    }
    /* parent */
    s_log(LOG_INFO, "Local mode child started (PID=%lu)", c->pid);
    closesocket(fd[1]);
#ifdef FD_CLOEXEC
    fcntl(fd[0], F_SETFD, FD_CLOEXEC);
#endif
    return fd[0];
#endif /* USE_WIN32,__vms */
}
示例#8
0
std::string getExecutablePath() {
	
#if ARX_PLATFORM == ARX_PLATFORM_MACOSX
	
	uint32_t bufsize = 0;
	
	// Obtain required size
	_NSGetExecutablePath(NULL, &bufsize);
	
	std::vector<char> exepath(bufsize);
	
	if(_NSGetExecutablePath(&exepath.front(), &bufsize) == 0) {
		char exerealpath[MAXPATHLEN];
		if(realpath(&exepath.front(), exerealpath)) {
			return exerealpath;
		}
	}
	
	ARX_UNUSED(executablePath);
	
#elif defined(ARX_HAVE_WINAPI)
	
	std::vector<char> buffer;
	buffer.resize(MAX_PATH);
	if(GetModuleFileNameA(NULL, buffer.data(), buffer.size()) > 0) {
		return std::string(buffer.data(), buffer.size());
	}
	
#else
	
	// Try to get the path from OS-specific procfs entries
	#ifdef ARX_HAVE_READLINK
	std::vector<char> buffer(1024);
	// Linux
	if(try_readlink(buffer, "/proc/self/exe")) {
		return std::string(buffer.begin(), buffer.end());
	}
	// BSD
	if(try_readlink(buffer, "/proc/curproc/file")) {
		return std::string(buffer.begin(), buffer.end());
	}
	// Solaris
	if(try_readlink(buffer, "/proc/self/path/a.out")) {
		return std::string(buffer.begin(), buffer.end());
	}
	#endif
	
	// FreeBSD
	#if defined(ARX_HAVE_SYSCTL) && defined(CTL_KERN) && defined(KERN_PROC) \
	    && defined(KERN_PROC_PATHNAME) && ARX_PLATFORM == ARX_PLATFORM_BSD \
	    && defined(PATH_MAX)
	int mib[4];
	mib[0] = CTL_KERN;
	mib[1] = KERN_PROC;
	mib[2] = KERN_PROC_PATHNAME;
	mib[3] = -1;
	char pathname[PATH_MAX];
	size_t size = sizeof(pathname);
	int error = sysctl(mib, 4, pathname, &size, NULL, 0);
	if(error != -1 && size > 0 && size < sizeof(pathname)) {
		return safestring(pathname, size);
	}
	#endif
	
	// Solaris
	#ifdef ARX_HAVE_GETEXECNAME
	const char * execname = getexecname();
	if(execname != NULL) {
		return execname;
	}
	#endif
	
	// Fall back to argv[0] if possible
	if(executablePath != NULL) {
		std::string path(executablePath);
		if(path.find('/') != std::string::npos) {
			return path;
		}
	}
	
#endif
	
	// Give up - we couldn't determine the exe path.
	return std::string();
}
示例#9
0
文件: client.c 项目: l7s/stunnel
static int connect_local(CLI *c) { /* spawn local process */
    char *name, *portname;
    int fd[2], pid;
    X509 *peer;
#ifdef HAVE_PTHREAD_SIGMASK
    sigset_t newmask;
#endif

    if(c->opt->option.pty) {
        char tty[64];

        if(pty_allocate(fd, fd+1, tty))
            longjmp(c->err, 1);
        s_log(LOG_DEBUG, "TTY=%s allocated", tty);
    } else
        make_sockets(c, fd);

    pid=fork();
    c->pid=(unsigned long)pid;
    switch(pid) {
    case -1:    /* error */
        closesocket(fd[0]);
        closesocket(fd[1]);
        ioerror("fork");
        longjmp(c->err, 1);
    case  0:    /* child */
        closesocket(fd[0]);
        set_nonblock(fd[1], 0); /* switch back to blocking mode */
        /* dup2() does not copy FD_CLOEXEC flag */
        dup2(fd[1], 0);
        dup2(fd[1], 1);
        if(!global_options.option.foreground)
            dup2(fd[1], 2);
        closesocket(fd[1]); /* not really needed due to FD_CLOEXEC */
        name=str_dup(c->accepted_address);
        portname=strrchr(name, ':');
        if(portname) /* strip the port name */
            *portname='\0';
        putenv(str_printf("REMOTE_HOST=%s", name));
        if(c->opt->option.transparent_src) {
            putenv("LD_PRELOAD=" LIBDIR "/libstunnel.so");
            /* for Tru64 _RLD_LIST is used instead */
            putenv("_RLD_LIST=" LIBDIR "/libstunnel.so:DEFAULT");
        }
        if(c->ssl) {
            peer=SSL_get_peer_certificate(c->ssl);
            if(peer) {
                name=X509_NAME_oneline(X509_get_subject_name(peer), NULL, 0);
                safestring(name);
                putenv(str_printf("SSL_CLIENT_DN=%s", name));
                name=X509_NAME_oneline(X509_get_issuer_name(peer), NULL, 0);
                safestring(name);
                putenv(str_printf("SSL_CLIENT_I_DN=%s", name));
                X509_free(peer);
            }
        }
#ifdef HAVE_PTHREAD_SIGMASK
        sigemptyset(&newmask);
        sigprocmask(SIG_SETMASK, &newmask, NULL);
#endif
        execvp(c->opt->execname, c->opt->execargs);
        ioerror(c->opt->execname); /* execv failed */
        _exit(1);
    default: /* parent */
        s_log(LOG_INFO, "Local mode child started (PID=%lu)", c->pid);
        closesocket(fd[1]);
        return fd[0];
    }
}
示例#10
0
文件: client.c 项目: l7s/stunnel
static void auth_user(CLI *c) {
#ifndef _WIN32_WCE
    struct servent *s_ent;    /* structure for getservbyname */
#endif
    SOCKADDR_UNION ident;     /* IDENT socket name */
    char *line, *type, *system, *user;

    if(!c->opt->username)
        return; /* -u option not specified */
    c->fd=s_socket(c->peer_addr.addr[0].sa.sa_family, SOCK_STREAM,
        0, 1, "socket (auth_user)");
    if(c->fd<0)
        longjmp(c->err, 1);
    memcpy(&ident, &c->peer_addr.addr[0], sizeof ident);
#ifndef _WIN32_WCE
    s_ent=getservbyname("auth", "tcp");
    if(s_ent) {
        ident.in.sin_port=s_ent->s_port;
    } else
#endif
    {
        s_log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.in.sin_port=htons(113);
    }
    if(connect_blocking(c, &ident, addr_len(ident)))
        longjmp(c->err, 1);
    s_log(LOG_DEBUG, "IDENT server connected");
    fdprintf(c, c->fd, "%u , %u",
        ntohs(c->peer_addr.addr[0].in.sin_port),
        ntohs(c->opt->local_addr.addr[0].in.sin_port));
    line=fdgetline(c, c->fd);
    closesocket(c->fd);
    c->fd=-1; /* avoid double close on cleanup */
    type=strchr(line, ':');
    if(!type) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *type++='\0';
    system=strchr(type, ':');
    if(!system) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *system++='\0';
    if(strcmp(type, " USERID ")) {
        s_log(LOG_ERR, "Incorrect INETD response type");
        str_free(line);
        longjmp(c->err, 1);
    }
    user=strchr(system, ':');
    if(!user) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *user++='\0';
    while(*user==' ') /* skip leading spaces */
        ++user;
    if(strcmp(user, c->opt->username)) {
        safestring(user);
        s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT (user %s)",
            c->accepted_address, user);
        str_free(line);
        longjmp(c->err, 1);
    }
    s_log(LOG_INFO, "IDENT authentication passed");
    str_free(line);
}
示例#11
0
static int auth_user(CLI *c) {
    struct servent *s_ent;    /* structure for getservbyname */
    struct sockaddr_in ident; /* IDENT socket name */
    int fd;                   /* IDENT socket descriptor */
    char name[STRLEN];
    int retval;

    if(!c->opt->username)
        return 0; /* -u option not specified */
    if((fd=socket(AF_INET, SOCK_STREAM, 0))<0) {
        sockerror("socket (auth_user)");
        return -1;
    }
    alloc_fd(fd);
    memcpy(&ident, &c->addr, sizeof(ident));
    s_ent=getservbyname("auth", "tcp");
    if(!s_ent) {
        log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.sin_port=htons(113);
    } else {
        ident.sin_port=s_ent->s_port;
    }
    if(connect(fd, (struct sockaddr *)&ident, sizeof(ident))<0) {
        switch(get_last_socket_error()) {
        case EINPROGRESS: /* retry */
            log(LOG_DEBUG, "connect #1 (auth_user): EINPROGRESS: retrying");
            break;
        case EWOULDBLOCK: /* retry */
            log(LOG_DEBUG, "connect #1 (auth_user): EWOULDBLOCK: retrying");
            break;
        default:
            sockerror("connect #1 (auth_user)");
            closesocket(fd);
            return -1;
        }
        if(waitforsocket(fd, 1 /* write */, c->opt->timeout_busy)<1) {
            closesocket(fd);
            return -1;
        }
        if(connect(fd, (struct sockaddr *)&ident, sizeof(ident))<0) {
            switch(get_last_socket_error()) {
            case EINVAL: /* WIN32 is strange... */
                log(LOG_DEBUG, "connect #2 (auth_user): EINVAL: ok");
            case EISCONN: /* ok */
                break; /* success */
            default:
                sockerror("connect #2 (auth_user))");
                closesocket(fd);
                return -1;
            }
        }
    }
    log(LOG_DEBUG, "IDENT server connected");
    if(fdprintf(c, fd, "%u , %u",
            ntohs(c->addr.sin_port), ntohs(c->opt->localport))<0) {
        sockerror("fdprintf (auth_user)");
        closesocket(fd);
        return -1;
    }
    if(fdscanf(c, fd, "%*[^:]: USERID :%*[^:]:%s", name)!=1) {
        log(LOG_ERR, "Incorrect data from IDENT server");
        closesocket(fd);
        return -1;
    }
    closesocket(fd);
    retval=strcmp(name, c->opt->username) ? -1 : 0;
    safestring(name);
    log(LOG_INFO, "IDENT resolved remote user to %s", name);
    return retval;
}
示例#12
0
NOEXPORT int connect_local(CLI *c) { /* spawn local process */
    char *name, host[40];
    int fd[2], pid;
    X509 *peer;
#ifdef HAVE_PTHREAD_SIGMASK
    sigset_t newmask;
#endif

    if(c->opt->option.pty) {
        char tty[64];

        if(pty_allocate(fd, fd+1, tty))
            longjmp(c->err, 1);
        s_log(LOG_DEBUG, "TTY=%s allocated", tty);
    } else
        if(make_sockets(fd))
            longjmp(c->err, 1);

    pid=fork();
    c->pid=(unsigned long)pid;
    switch(pid) {
    case -1:    /* error */
        closesocket(fd[0]);
        closesocket(fd[1]);
        ioerror("fork");
        longjmp(c->err, 1);
    case  0:    /* child */
        closesocket(fd[0]);
        set_nonblock(fd[1], 0); /* switch back to blocking mode */
        /* dup2() does not copy FD_CLOEXEC flag */
        dup2(fd[1], 0);
        dup2(fd[1], 1);
        if(!global_options.option.foreground)
            dup2(fd[1], 2);
        closesocket(fd[1]); /* not really needed due to FD_CLOEXEC */

        if(!getnameinfo(&c->peer_addr.sa, c->peer_addr_len,
                host, 40, NULL, 0, NI_NUMERICHOST)) {
            /* just don't set these variables if getnameinfo() fails */
            putenv(str_printf("REMOTE_HOST=%s", host));
            if(c->opt->option.transparent_src) {
#ifndef LIBDIR
#define LIBDIR "."
#endif
#ifdef MACH64
                putenv("LD_PRELOAD_32=" LIBDIR "/libstunnel.so");
                putenv("LD_PRELOAD_64=" LIBDIR "/" MACH64 "/libstunnel.so");
#elif __osf /* for Tru64 _RLD_LIST is used instead */
                putenv("_RLD_LIST=" LIBDIR "/libstunnel.so:DEFAULT");
#else
                putenv("LD_PRELOAD=" LIBDIR "/libstunnel.so");
#endif
            }
        }

        if(c->ssl) {
            peer=SSL_get_peer_certificate(c->ssl);
            if(peer) {
                name=X509_NAME_oneline(X509_get_subject_name(peer), NULL, 0);
                safestring(name);
                putenv(str_printf("SSL_CLIENT_DN=%s", name));
                name=X509_NAME_oneline(X509_get_issuer_name(peer), NULL, 0);
                safestring(name);
                putenv(str_printf("SSL_CLIENT_I_DN=%s", name));
                X509_free(peer);
            }
        }
#ifdef HAVE_PTHREAD_SIGMASK
        sigemptyset(&newmask);
        sigprocmask(SIG_SETMASK, &newmask, NULL);
#endif
        signal(SIGCHLD, SIG_DFL);
        signal(SIGHUP, SIG_DFL);
        signal(SIGUSR1, SIG_DFL);
        signal(SIGPIPE, SIG_DFL);
        signal(SIGTERM, SIG_DFL);
        signal(SIGQUIT, SIG_DFL);
        signal(SIGINT, SIG_DFL);
        execvp(c->opt->execname, c->opt->execargs);
        ioerror(c->opt->execname); /* execvp failed */
        _exit(1);
    default: /* parent */
        s_log(LOG_INFO, "Local mode child started (PID=%lu)", c->pid);
        closesocket(fd[1]);
        return fd[0];
    }
}
示例#13
0
文件: log.c 项目: mtrojnar/stunnel
void s_log(int level, const char *format, ...) {
    va_list ap;
    char *text, *stamp, *id;
    struct LIST *tmp;
#ifdef USE_WIN32
    DWORD libc_error;
#else
    int libc_error;
#endif
    int socket_error;
    time_t gmt;
    struct tm *timeptr;
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
    struct tm timestruct;
#endif
    TLS_DATA *tls_data;

    tls_data=tls_get();
    if(!tls_data) {
        tls_data=tls_alloc(NULL, NULL, "log");
        s_log(LOG_ERR, "INTERNAL ERROR: Uninitialized TLS at %s, line %d",
            __FILE__, __LINE__);
    }

    /* performance optimization: skip the trivial case early */
    if(log_mode==LOG_MODE_CONFIGURED && level>tls_data->opt->log_level)
        return;

    libc_error=get_last_error();
    socket_error=get_last_socket_error();

    /* format the id to be logged */
    time(&gmt);
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
    timeptr=localtime_r(&gmt, &timestruct);
#else
    timeptr=localtime(&gmt);
#endif
    stamp=str_printf("%04d.%02d.%02d %02d:%02d:%02d",
        timeptr->tm_year+1900, timeptr->tm_mon+1, timeptr->tm_mday,
        timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
    id=str_printf("LOG%d[%s]", level, tls_data->id);

    /* format the text to be logged */
    va_start(ap, format);
    text=str_vprintf(format, ap);
    va_end(ap);
    safestring(text);

    CRYPTO_THREAD_read_lock(stunnel_locks[LOCK_LOG_MODE]);
    if(log_mode==LOG_MODE_BUFFER) { /* save the text to log it later */
        CRYPTO_THREAD_write_lock(stunnel_locks[LOCK_LOG_BUFFER]);
        tmp=str_alloc_detached(sizeof(struct LIST));
        tmp->next=NULL;
        tmp->opt=tls_data->opt;
        tmp->level=level;
        tmp->stamp=stamp;
        str_detach(tmp->stamp);
        tmp->id=id;
        str_detach(tmp->id);
        tmp->text=text;
        str_detach(tmp->text);
        if(tail)
            tail->next=tmp;
        else
            head=tmp;
        tail=tmp;
        CRYPTO_THREAD_write_unlock(stunnel_locks[LOCK_LOG_BUFFER]);
    } else { /* ready log the text directly */
        log_raw(tls_data->opt, level, stamp, id, text);
        str_free(stamp);
        str_free(id);
        str_free(text);
    }
    CRYPTO_THREAD_read_unlock(stunnel_locks[LOCK_LOG_MODE]);

    set_last_error(libc_error);
    set_last_socket_error(socket_error);
}
示例#14
0
static void auth_user(CLI * c, char *accepted_address)
{
	struct servent *s_ent;	
	SOCKADDR_UNION ident;	
	char *line, *type, *system, *user;

	if (!c->opt->username)
		return;		
	if (c->peer_addr.sa.sa_family == AF_UNIX) {
		s_log(LOG_INFO, "IDENT not supported on Unix sockets");
		return;
	}
	c->fd = s_socket(c->peer_addr.sa.sa_family, SOCK_STREAM,
			 0, 1, "socket (auth_user)");
	if (c->fd < 0)
		longjmp(c->err, 1);
	memcpy(&ident, &c->peer_addr, c->peer_addr_len);
	s_ent = getservbyname("auth", "tcp");
	if (s_ent) {
		ident.in.sin_port = s_ent->s_port;
	} else {
		s_log(LOG_WARNING, "Unknown service 'auth': using default 113");
		ident.in.sin_port = htons(113);
	}
	if (connect_blocking(c, &ident, addr_len(&ident)))
		longjmp(c->err, 1);
	s_log(LOG_DEBUG, "IDENT server connected");
	fd_printf(c, c->fd, "%u , %u",
		  ntohs(c->peer_addr.in.sin_port),
		  ntohs(c->opt->local_addr.in.sin_port));
	line = fd_getline(c, c->fd);
	closesocket(c->fd);
	c->fd = -1;		
	type = strchr(line, ':');
	if (!type) {
		s_log(LOG_ERR, "Malformed IDENT response");
		str_free(line);
		longjmp(c->err, 1);
	}
	*type++ = '\0';
	system = strchr(type, ':');
	if (!system) {
		s_log(LOG_ERR, "Malformed IDENT response");
		str_free(line);
		longjmp(c->err, 1);
	}
	*system++ = '\0';
	if (strcmp(type, " USERID ")) {
		s_log(LOG_ERR, "Incorrect INETD response type");
		str_free(line);
		longjmp(c->err, 1);
	}
	user = strchr(system, ':');
	if (!user) {
		s_log(LOG_ERR, "Malformed IDENT response");
		str_free(line);
		longjmp(c->err, 1);
	}
	*user++ = '\0';
	while (*user == ' ')	
		++user;
	if (strcmp(user, c->opt->username)) {
		safestring(user);
		s_log(LOG_WARNING,
		      "Connection from %s REFUSED by IDENT (user %s)",
		      accepted_address, user);
		str_free(line);
		longjmp(c->err, 1);
	}
	s_log(LOG_INFO, "IDENT authentication passed");
	str_free(line);
}