⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.c

📁 SSL加密库源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    request_init(&request,
        RQ_DAEMON, c->opt->servname, RQ_FILE, c->local_rfd.fd, 0);
    fromhost(&request);
    result=hosts_access(&request);
    leave_critical_section(CRIT_NTOA);

    if (!result) {
        log(LOG_WARNING, "Connection from %s:%d REFUSED by libwrap",
            c->accepting_address, ntohs(c->addr.sin_port));
        log(LOG_DEBUG, "See hosts_access(5) for details");
        return -1; /* FAILED */
    }
#endif
    return 0; /* OK */
}

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;
}

static int connect_local(CLI *c) { /* spawn local process */
#if defined (USE_WIN32) || defined (__vms)
    log(LOG_ERR, "LOCAL MODE NOT SUPPORTED ON WIN32 and OpenVMS PLATFORM");
    return -1;
#else /* USE_WIN32, __vms */
    char env[3][STRLEN], name[STRLEN];
    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;
        }
        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);
        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 */
    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 */
}

#ifndef USE_WIN32

static int make_sockets(int fd[2]) { /* make a pair of connected sockets */
#ifdef INET_SOCKET_PAIR
    struct sockaddr_in addr;
    int addrlen;
    int s; /* temporary socket awaiting for connection */

    if((s=socket(AF_INET, SOCK_STREAM, 0))<0) {
        sockerror("socket#1");
        return -1;
    }
    if((fd[1]=socket(AF_INET, SOCK_STREAM, 0))<0) {
        sockerror("socket#2");
        return -1;
    }
    addrlen=sizeof(addr);
    memset(&addr, 0, addrlen);
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
    addr.sin_port=0; /* dynamic port allocation */
    if(bind(s, (struct sockaddr *)&addr, addrlen))
        log_error(LOG_DEBUG, get_last_socket_error(), "bind#1");
    if(bind(fd[1], (struct sockaddr *)&addr, addrlen))
        log_error(LOG_DEBUG, get_last_socket_error(), "bind#2");
    if(listen(s, 5)) {
        sockerror("listen");
        return -1;
    }
    if(getsockname(s, (struct sockaddr *)&addr, &addrlen)) {
        sockerror("getsockname");
        return -1;
    }
    if(connect(fd[1], (struct sockaddr *)&addr, addrlen)) {
        sockerror("connect");
        return -1;
    }
    if((fd[0]=accept(s, (struct sockaddr *)&addr, &addrlen))<0) {
        sockerror("accept");
        return -1;
    }
    closesocket(s); /* don't care about the result */
#else
    if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
        sockerror("socketpair");
        return -1;
    }
#endif
    return 0;
}
#endif

static int connect_remote(CLI *c) { /* connect to remote host */
    struct sockaddr_in addr;
    u32 *list;
    int error;
    int s; /* destination socket */
    u16 dport;
   
    memset(&addr, 0, sizeof(addr));
    addr.sin_family=AF_INET;

    if(c->opt->option.delayed_lookup) {
        if(name2nums(c->opt->remote_address, "127.0.0.1",
                &c->resolved_addresses, &dport)==0) {
            /* No host resolved */
            return -1;
        }
        list=c->resolved_addresses;
    } else { /* Use pre-resolved addresses */
        list=c->opt->remotenames;
        dport=c->opt->remoteport;
    }

    /* connect each host from the list */
    for(; *list+1; list++) { /* same as (signed)*list!=-1 */
        if((s=socket(AF_INET, SOCK_STREAM, 0))<0) {
            sockerror("remote socket");
            return -1;
        }
        if(alloc_fd(s))
            return -1;

        if(c->bind_ip) { /* explicit local bind or transparent proxy */
            addr.sin_addr.s_addr=c->bind_ip;
            addr.sin_port=htons(0);
            if(bind(s, (struct sockaddr *)&addr, sizeof(addr))<0) {
                sockerror("bind transparent");
                closesocket(s);
                return -1;
            }
        }

        /* try to connect for the 1st time */
        addr.sin_port=dport;
        addr.sin_addr.s_addr=*list;
        safe_ntoa(c->connecting_address, addr.sin_addr);
        log(LOG_DEBUG, "%s connecting %s:%d", c->opt->servname,
            c->connecting_address, ntohs(addr.sin_port));
        if(!connect(s, (struct sockaddr *)&addr, sizeof(addr)))
            return s; /* no error -> success */
        error=get_last_socket_error();
        switch(error) {
        case EINPROGRESS: /* retry */
            log(LOG_DEBUG, "remote connect #1: EINPROGRESS: retrying");
            break;
        case EWOULDBLOCK: /* retry */
            log(LOG_DEBUG, "remote connect #1: EWOULDBLOCK: retrying");
            break;
        default:
            log(LOG_ERR, "remote connect #1 (%s:%d): %s (%d)",
                c->connecting_address, ntohs(addr.sin_port),
                my_strerror(error), error);
            closesocket(s);
            continue; /* Next IP */
        }

        /* wait until the connecting socket is ready for write */
        if(waitforsocket(s, 1 /* write */, c->opt->timeout_busy)<1) {
            closesocket(s);
            continue; /* timeout or error */
        }

        /* try to connect for the 2nd time */
        if(!connect(s, (struct sockaddr *)&addr, sizeof(addr)))
            return s; /* no error -> success */
        error=get_last_socket_error();
        switch(error) {
        case EINVAL: /* WIN32 is strange... */
            log(LOG_DEBUG, "remote connect #2: EINVAL: ok");
        case EISCONN: /* ok */
            return s; /* success */
        default:
            log(LOG_ERR, "remote connect #2 (%s:%d): %s (%d)",
                c->connecting_address, ntohs(addr.sin_port),
                my_strerror(error), error);
            closesocket(s);
            continue; /* Next IP */
        }
    }
    return -1;
}

static void reset(int fd, char *txt) {
    /* Set lingering on a socket if needed*/
    struct linger l;

    l.l_onoff=1;
    l.l_linger=0;
    if(setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&l, sizeof(l)))
        log_error(LOG_DEBUG, get_last_socket_error(), txt);
}

/* End of client.c */

⌨️ 快捷键说明

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