Exemplo n.º 1
0
void redemption_new_session(CryptoContext & cctx, char const * config_filename)
{
    char text[256];
    char source_ip[256];
    int target_port = 0;
    char real_target_ip[256];

    union
    {
        struct sockaddr s;
        struct sockaddr_storage ss;
        struct sockaddr_in s4;
        struct sockaddr_in6 s6;
    } u;
    int sock_len = sizeof(u);

    Inifile ini;
    { ConfigurationLoader cfg_loader(ini.configuration_holder(), config_filename); }

    init_signals();
    snprintf(text, 255, "redemption_%8.8x_main_term", unsigned(getpid()));

    getpeername(0, &u.s, reinterpret_cast<socklen_t *>(&sock_len));
    strcpy(source_ip, inet_ntoa(u.s4.sin_addr));

    union
    {
        struct sockaddr s;
        struct sockaddr_storage ss;
        struct sockaddr_in s4;
        struct sockaddr_in6 s6;
    } localAddress;
    socklen_t addressLength = sizeof(localAddress);

    int sck = 0;
    if (-1 == getsockname(sck, &localAddress.s, &addressLength)){
        LOG(LOG_INFO, "getsockname failed error=%s", strerror(errno));
        _exit(1);
    }

    target_port = localAddress.s4.sin_port;
    strcpy(real_target_ip, inet_ntoa(localAddress.s4.sin_addr));

    if (ini.get<cfg::globals::enable_ip_transparent>()) {
        const int source_port = 0;
        char target_ip[256];
        strcpy(target_ip, inet_ntoa(localAddress.s4.sin_addr));
        int fd = open("/proc/net/ip_conntrack", O_RDONLY);
        // source and dest are inverted because we get the information we want from reply path rule
        int res = parse_ip_conntrack(fd, target_ip, source_ip, target_port, source_port, real_target_ip, sizeof(real_target_ip));
        if (res){
            LOG(LOG_WARNING, "Failed to get transparent proxy target from ip_conntrack");
        }
        close(fd);
    }


    ini.set_acl<cfg::globals::host>(source_ip);
    ini.set_acl<cfg::globals::target>(real_target_ip);

    if (ini.get<cfg::debug::session>()){
        LOG(LOG_INFO, "Setting new session socket to %d\n", sck);
    }

    int nodelay = 1;
    if (0 == setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&nodelay), sizeof(nodelay))){
        Session session(sck, ini, cctx);

        if (ini.get<cfg::debug::session>()){
            LOG(LOG_INFO, "Session::end of Session(%u)", sck);
        }

        shutdown(sck, 2);
        close(sck);
    }
    else {
        LOG(LOG_INFO, "Failed to set socket TCP_NODELAY option on client socket");
    }

}
Exemplo n.º 2
0
void redemption_new_session()
{
    char text[256];
    char source_ip[256];
    int source_port = 0;
    char target_ip[256];
    int target_port = 0;
    char real_target_ip[256];

    union
    {
        struct sockaddr s;
        struct sockaddr_storage ss;
        struct sockaddr_in s4;
        struct sockaddr_in6 s6;
    } u;
    int sock_len = sizeof(u);

    Inifile ini;
    ConfigurationLoader cfg_loader(ini, CFG_PATH "/" RDPPROXY_INI);

    init_signals();
    snprintf(text, 255, "redemption_%8.8x_main_term", getpid());

    getpeername(0, &u.s, (socklen_t *)&sock_len);
    strcpy(source_ip, inet_ntoa(u.s4.sin_addr));

    union
    {
        struct sockaddr s;
        struct sockaddr_storage ss;
        struct sockaddr_in s4;
        struct sockaddr_in6 s6;
    } localAddress;
    socklen_t addressLength = sizeof(localAddress);

    int sck = 0;
    if (-1 == getsockname(sck, &localAddress.s, &addressLength)){
        LOG(LOG_INFO, "getsockname failed error=%s", strerror(errno));
        _exit(1);
    }

    target_port = localAddress.s4.sin_port;
    strcpy(real_target_ip, inet_ntoa(localAddress.s4.sin_addr));

    if (ini.globals.enable_ip_transparent) {
        strcpy(target_ip, inet_ntoa(localAddress.s4.sin_addr));
        int fd = open("/proc/net/ip_conntrack", O_RDONLY);
        // source and dest are inverted because we get the information we want from reply path rule
        int res = parse_ip_conntrack(fd, target_ip, source_ip, target_port, source_port, real_target_ip, sizeof(real_target_ip));
        if (res){
            LOG(LOG_WARNING, "Failed to get transparent proxy target from ip_conntrack");
        }
        close(fd);
    }


    ini.context_set_value(AUTHID_HOST, source_ip);
    ini.context_set_value(AUTHID_TARGET, real_target_ip);

    if (ini.debug.session){
        LOG(LOG_INFO, "Setting new session socket to %d\n", sck);
    }

    int nodelay = 1;
    if (0 == setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay))){
        wait_obj front_event(sck);

        Session session(front_event, sck, &ini);

        if (ini.debug.session){
            LOG(LOG_INFO, "Session::end of Session(%u)", sck);
        }

        shutdown(sck, 2);
        close(sck);
    }
    else {
        LOG(LOG_INFO, "Failed to set socket TCP_NODELAY option on client socket");
    }

}
Exemplo n.º 3
0
    virtual Server_status start(int incoming_sck)
    {
        union
        {
            struct sockaddr s;
            struct sockaddr_storage ss;
            struct sockaddr_in s4;
            struct sockaddr_in6 s6;
        } u;
        unsigned int sin_size = sizeof(u);
        memset(&u, 0, sin_size);

        int sck = accept(incoming_sck, &u.s, &sin_size);
        if (-1 == sck) {
            LOG(LOG_INFO, "Accept failed on socket %u (%s)", incoming_sck, strerror(errno));
            _exit(1);
        }

        char source_ip[256];
        strcpy(source_ip, inet_ntoa(u.s4.sin_addr));
        const int source_port = ntohs(u.s4.sin_port);
        /* start new process */
        const pid_t pid = fork();
        switch (pid) {
        case 0: /* child */
            {
                close(incoming_sck);

                Inifile ini;
                ini.set<cfg::debug::config>(this->debug_config);
                { ConfigurationLoader cfg_loader(ini, this->config_filename.c_str()); }

                if (ini.get<cfg::globals::wab_agent_alternate_shell>().empty()) {
                    ini.set<cfg::globals::wab_agent_alternate_shell>(
                        this->parametersHldr.get_agent_alternate_shell()
                    );
                }

                ini.get_ref<cfg::crypto::key0>().setmem(this->parametersHldr.get_crypto_key_0());
                ini.get_ref<cfg::crypto::key1>().setmem(this->parametersHldr.get_crypto_key_1());

                if (ini.get<cfg::debug::session>()){
                    LOG(LOG_INFO, "Setting new session socket to %d\n", sck);
                }

                union
                {
                    struct sockaddr s;
                    struct sockaddr_storage ss;
                    struct sockaddr_in s4;
                    struct sockaddr_in6 s6;
                } localAddress;
                socklen_t addressLength = sizeof(localAddress);


                if (-1 == getsockname(sck, &localAddress.s, &addressLength)){
                    LOG(LOG_INFO, "getsockname failed error=%s", strerror(errno));
                    _exit(1);
                }

                char target_ip[256];
                const int target_port = ntohs(localAddress.s4.sin_port);
//                strcpy(real_target_ip, inet_ntoa(localAddress.s4.sin_addr));
                strcpy(target_ip, inet_ntoa(localAddress.s4.sin_addr));

                if (0 != strcmp(source_ip, "127.0.0.1")){
                    // do not log early messages for localhost (to avoid tracing in watchdog)
                    LOG(LOG_INFO, "src=%s sport=%d dst=%s dport=%d", source_ip, source_port, target_ip, target_port);
                }

                char real_target_ip[256];
                if (ini.get<cfg::globals::enable_ip_transparent>() &&
                    (0 != strcmp(source_ip, "127.0.0.1"))) {
                    int fd = open("/proc/net/ip_conntrack", O_RDONLY);
                    // source and dest are inverted because we get the information we want from reply path rule
                    int res = parse_ip_conntrack(fd, target_ip, source_ip, target_port, source_port, real_target_ip, sizeof(real_target_ip), 1);
                    if (res){
                        LOG(LOG_WARNING, "Failed to get transparent proxy target from ip_conntrack: %d", fd);
                    }
                    close(fd);

                    if (setgid(this->gid) != 0){
                        LOG(LOG_WARNING, "Changing process group to %u failed with error: %s\n", this->gid, strerror(errno));
                        _exit(1);
                    }
                    if (setuid(this->uid) != 0){
                        LOG(LOG_WARNING, "Changing process group to %u failed with error: %s\n", this->gid, strerror(errno));
                        _exit(1);
                    }

                    LOG(LOG_INFO, "src=%s sport=%d dst=%s dport=%d", source_ip, source_port, real_target_ip, target_port);
                }
                else {
                    ::memset(real_target_ip, 0, sizeof(real_target_ip));
                }

                int nodelay = 1;
                if (0 == setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay))){
                    // Create session file
                    int child_pid = getpid();
                    char session_file[256];
                    sprintf(session_file, "%s/redemption/session_%d.pid", PID_PATH, child_pid);
                    int fd = open(session_file, O_WRONLY | O_CREAT, S_IRWXU);
                    if (fd == -1) {
                        LOG(LOG_ERR, "Writing process id to SESSION ID FILE failed. Maybe no rights ?:%d:%d\n", errno, strerror(errno));
                        _exit(1);
                    }
                    char text[256];
                    const size_t lg = snprintf(text, 255, "%d", child_pid);
                    if (write(fd, text, lg) == -1) {
                        LOG(LOG_ERR, "Couldn't write pid to %s: %s", PID_PATH "/redemption/session_<pid>.pid", strerror(errno));
                        _exit(1);
                    }
                    close(fd);

                    // Launch session
                    if (0 != strcmp(source_ip, "127.0.0.1")){
                        // do not log early messages for localhost (to avoid tracing in watchdog)
                        LOG(LOG_INFO,
                            "New session on %u (pid=%u) from %s to %s",
                            (unsigned)sck, (unsigned)child_pid, source_ip, (real_target_ip[0] ? real_target_ip : target_ip));
                    }
                    ini.set_acl<cfg::globals::host>(source_ip);
//                    ini.context_set_value(AUTHID_TARGET, real_target_ip);
                    ini.set_acl<cfg::globals::target>(target_ip);
                    if (ini.get<cfg::globals::enable_ip_transparent>()
                        &&  strncmp(target_ip, real_target_ip, strlen(real_target_ip))) {
                        ini.set_acl<cfg::context::real_target_device>(real_target_ip);
                    }
                    Session session(sck, ini);

                    // Suppress session file
                    unlink(session_file);

                    if (ini.get<cfg::debug::session>()){
                        LOG(LOG_INFO, "Session::end of Session(%u)", sck);
                    }

                    shutdown(sck, 2);
                    close(sck);
                }
                else {
                    LOG(LOG_ERR, "Failed to set socket TCP_NODELAY option on client socket");
                }
                return START_WANT_STOP;
            }
            break;
        default: /* father */
            {
                close(sck);
            }
            break;
        case -1:
            // error forking
            LOG(LOG_ERR, "Error creating process for new session : %s\n", strerror(errno));
            break;
        }
        return START_FAILED;
    }
Exemplo n.º 4
0
    Server_status start(int incoming_sck) override
    {
        union
        {
            struct sockaddr s;
            struct sockaddr_storage ss;
            struct sockaddr_in s4;
            struct sockaddr_in6 s6;
        } u;
        unsigned int sin_size = sizeof(u);
        memset(&u, 0, sin_size);

        int sck = accept(incoming_sck, &u.s, &sin_size);
        if (-1 == sck) {
            LOG(LOG_INFO, "Accept failed on socket %d (%s)", incoming_sck, strerror(errno));
            _exit(1);
        }

        char source_ip[256];
        strcpy(source_ip, inet_ntoa(u.s4.sin_addr));
        REDEMPTION_DIAGNOSTIC_PUSH
        REDEMPTION_DIAGNOSTIC_GCC_IGNORE("-Wold-style-cast") // only to release
        const int source_port = ntohs(u.s4.sin_port);
        REDEMPTION_DIAGNOSTIC_POP
        /* start new process */
        const pid_t pid = fork();
        switch (pid) {
        case 0: /* child */
        // TODO: see exit status of child, we could use it to diagnose session behaviours
        // TODO: we could probably use some session launcher object here. Something like
        // an abstraction layer that would manage either forking of threading behavior
        // this would also likely have some effect on network ressources management
        // (that means the select() on ressources could be managed by that layer)
            {
                close(incoming_sck);

                Inifile ini;
                ini.set<cfg::font>(Font(app_path(AppPath::DefaultFontFile)));
                ini.set<cfg::debug::config>(this->debug_config);
                configuration_load(ini.configuration_holder(), this->config_filename);

                if (ini.get<cfg::debug::session>()){
                    LOG(LOG_INFO, "Setting new session socket to %d\n", sck);
                }

                union
                {
                    struct sockaddr s;
                    struct sockaddr_storage ss;
                    struct sockaddr_in s4;
                    struct sockaddr_in6 s6;
                } localAddress;
                socklen_t addressLength = sizeof(localAddress);


                if (-1 == getsockname(sck, &localAddress.s, &addressLength)){
                    LOG(LOG_INFO, "getsockname failed error=%s", strerror(errno));
                    _exit(1);
                }

                char target_ip[256];
                REDEMPTION_DIAGNOSTIC_PUSH
                REDEMPTION_DIAGNOSTIC_GCC_IGNORE("-Wold-style-cast") // only to release
                const int target_port = ntohs(localAddress.s4.sin_port);
                REDEMPTION_DIAGNOSTIC_POP
//                strcpy(real_target_ip, inet_ntoa(localAddress.s4.sin_addr));
                strcpy(target_ip, inet_ntoa(localAddress.s4.sin_addr));

                if (0 != strcmp(source_ip, "127.0.0.1")){
                    // do not log early messages for localhost (to avoid tracing in watchdog)
                    LOG(LOG_INFO, "Redemption " VERSION);
                    LOG(LOG_INFO, "src=%s sport=%d dst=%s dport=%d", source_ip, source_port, target_ip, target_port);
                }

                char real_target_ip[256];
                if (ini.get<cfg::globals::enable_transparent_mode>() &&
                    (0 != strcmp(source_ip, "127.0.0.1"))) {
                    int fd = open("/proc/net/ip_conntrack", O_RDONLY);
                    // source and dest are inverted because we get the information we want from reply path rule
                    int res = parse_ip_conntrack(fd, target_ip, source_ip, target_port, source_port, real_target_ip, sizeof(real_target_ip), 1);
                    if (res){
                        LOG(LOG_WARNING, "Failed to get transparent proxy target from ip_conntrack: %d", fd);
                    }
                    close(fd);

                    if (setgid(this->gid) != 0){
                        LOG(LOG_ERR, "Changing process group to %u failed with error: %s\n", this->gid, strerror(errno));
                        _exit(1);
                    }
                    if (setuid(this->uid) != 0){
                        LOG(LOG_ERR, "Changing process user to %u failed with error: %s\n", this->uid, strerror(errno));
                        _exit(1);
                    }

                    LOG(LOG_INFO, "src=%s sport=%d dst=%s dport=%d", source_ip, source_port, real_target_ip, target_port);
                }
                else {
                    ::memset(real_target_ip, 0, sizeof(real_target_ip));
                }

                int nodelay = 1;
                if (0 == setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay))){
                    // Create session file
                    int child_pid = getpid();
                    char session_file[256];
                    sprintf(session_file, "%s/redemption/session_%d.pid", app_path(AppPath::Pid), child_pid);
                    int fd = open(session_file, O_WRONLY | O_CREAT, S_IRWXU);
                    if (fd == -1) {
                        LOG(LOG_ERR, "Writing process id to SESSION ID FILE failed. Maybe no rights ?:%d:%s\n", errno, strerror(errno));
                        _exit(1);
                    }
                    char text[256];
                    const size_t lg = snprintf(text, 255, "%d", child_pid);
                    if (write(fd, text, lg) == -1) {
                        LOG(LOG_ERR, "Couldn't write pid to %s/redemption/session_<pid>.pid: %s", app_path(AppPath::Pid), strerror(errno));
                        _exit(1);
                    }
                    close(fd);

                    // Launch session
                    if (0 != strcmp(source_ip, "127.0.0.1")){
                        // do not log early messages for localhost (to avoid tracing in watchdog)
                        LOG(LOG_INFO,
                            "New session on %d (pid=%d) from %s to %s",
                            sck, child_pid, source_ip, (real_target_ip[0] ? real_target_ip : target_ip));
                    }
                    ini.set_acl<cfg::globals::host>(source_ip);
//                    ini.context_set_value(AUTHID_TARGET, real_target_ip);
                    ini.set_acl<cfg::globals::target>(target_ip);
                    if (ini.get<cfg::globals::enable_transparent_mode>()
                        &&  strncmp(target_ip, real_target_ip, strlen(real_target_ip))) {
                        ini.set_acl<cfg::context::real_target_device>(real_target_ip);
                    }
                    Session session(sck, ini, this->cctx, this->rnd, this->fstat);

                    // Suppress session file
                    unlink(session_file);

                    if (ini.get<cfg::debug::session>()){
                        LOG(LOG_INFO, "Session::end of Session(%d)", sck);
                    }

                    shutdown(sck, 2);
                    close(sck);
                }
                else {
                    LOG(LOG_ERR, "Failed to set socket TCP_NODELAY option on client socket");
                }
                _exit(0);
            }
            break;
        default: /* father */
            {
                close(sck);
            }
            break;
        case -1:
            // error forking
            LOG(LOG_ERR, "Error creating process for new session : %s\n", strerror(errno));
            break;
        }
        return START_FAILED;
    }