コード例 #1
0
ファイル: relay-server.c プロジェクト: weechat/weechat
int
relay_server_sock_cb (const void *pointer, void *data, int fd)
{
    struct t_relay_server *server;
    struct sockaddr_in client_addr;
    struct sockaddr_in6 client_addr6;
    struct sockaddr_un client_addr_unix;

    socklen_t client_addr_size;
    void *ptr_addr;
    int client_fd, flags, set, max_clients, num_clients_on_port;
    char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1];
    char unix_address[sizeof (client_addr_unix.sun_path)];
    char *ptr_ip_address, *relay_password, *relay_totp_secret;

    /* make C compiler happy */
    (void) data;
    (void) fd;

    client_fd = -1;
    relay_password = NULL;
    relay_totp_secret = NULL;

    server = (struct t_relay_server *)pointer;

    if (server->ipv6)
    {
        ptr_addr = &client_addr6;
        client_addr_size = sizeof (struct sockaddr_in6);
    }
    else if (server->ipv4)
    {
        ptr_addr = &client_addr;
        client_addr_size = sizeof (struct sockaddr_in);
    }
    else
    {
        ptr_addr = &client_addr_unix;
        client_addr_size = sizeof (struct sockaddr_un);
    }

    memset (ptr_addr, 0, client_addr_size);

    client_fd = accept (server->sock, (struct sockaddr *)ptr_addr,
                        &client_addr_size);
    if (client_fd < 0)
    {
        if (server->unix_socket)
        {
            weechat_printf (NULL,
                            _("%s%s: cannot accept client on path %s (%s): "
                              "error %d %s"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            server->path, server->protocol_string,
                            errno, strerror (errno));
        }
        else
        {
            weechat_printf (NULL,
                            _("%s%s: cannot accept client on port %d (%s): "
                              "error %d %s"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            server->port, server->protocol_string,
                            errno, strerror (errno));
        }
        goto error;
    }

    /* check if relay password is empty and if it is not allowed */
    relay_password = weechat_string_eval_expression (
        weechat_config_string (relay_config_network_password),
        NULL, NULL, NULL);
    if (!weechat_config_boolean (relay_config_network_allow_empty_password)
        && (!relay_password || !relay_password[0]))
    {
        weechat_printf (NULL,
                        _("%s%s: cannot accept client because relay password "
                          "is empty, and option "
                          "relay.network.allow_empty_password is off"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME);
        goto error;
    }

    if (server->protocol == RELAY_PROTOCOL_WEECHAT)
    {
        /*
         * TOTP can be enabled only as second factor, in addition to the
         * password (only for weechat protocol)
         */
        relay_totp_secret = weechat_string_eval_expression (
            weechat_config_string (relay_config_network_totp_secret),
            NULL, NULL, NULL);
        if ((!relay_password || !relay_password[0])
            && relay_totp_secret && relay_totp_secret[0])
        {
            weechat_printf (NULL,
                            _("%s%s: Time-based One-Time Password (TOTP) "
                              "can be enabled only as second factor, if the "
                              "password is not empty"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME);
            goto error;
        }
        if (!relay_config_check_network_totp_secret (
                NULL, NULL, NULL,
                weechat_config_string (relay_config_network_totp_secret)))
        {
            goto error;
        }
    }

    /* check if we have reached the max number of clients on this port */
    max_clients = weechat_config_integer (relay_config_network_max_clients);
    if (max_clients > 0)
    {
        num_clients_on_port = relay_client_count_active_by_port (server->port);
        if (num_clients_on_port >= max_clients)
        {
            weechat_printf (
                NULL,
                NG_("%s%s: client not allowed (max %d client is "
                    "allowed at same time)",
                    "%s%s: client not allowed (max %d clients are "
                    "allowed at same time)",
                    max_clients),
                weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                max_clients);
            goto error;
        }
    }

    /* get the IP address */
    ptr_ip_address = NULL;
    if (server->ipv6)
    {
        if (inet_ntop (AF_INET6,
                       &(client_addr6.sin6_addr),
                       ipv6_address,
                       INET6_ADDRSTRLEN))
        {
            ptr_ip_address = ipv6_address;

            if (strncmp (ptr_ip_address, "::ffff:", 7) == 0)
            {
                /* actually an IPv4-mapped IPv6 address, so skip "::ffff:" */
                ptr_ip_address += 7;
            }
        }
    }
    else if (server->ipv4)
    {
        if (inet_ntop (AF_INET,
                       &(client_addr.sin_addr),
                       ipv4_address,
                       INET_ADDRSTRLEN))
        {
            ptr_ip_address = ipv4_address;
        }
    }
    else
    {
        strncpy (unix_address, client_addr_unix.sun_path,
                 sizeof (unix_address));
        ptr_ip_address = unix_address;
    }

    /* check if IP is allowed, if not, just close socket */
    if (relay_config_regex_allowed_ips
        && (regexec (relay_config_regex_allowed_ips, ptr_ip_address, 0, NULL, 0) != 0))
    {
        if (weechat_relay_plugin->debug >= 1)
        {
            weechat_printf (NULL,
                            _("%s%s: IP address \"%s\" not allowed for relay"),
                            weechat_prefix ("error"),
                            RELAY_PLUGIN_NAME,
                            ptr_ip_address);
        }
        goto error;
    }

    /* set non-blocking mode for socket */
    flags = fcntl (client_fd, F_GETFL);
    if (flags == -1)
        flags = 0;
    fcntl (client_fd, F_SETFL, flags | O_NONBLOCK);

    /* set socket option SO_REUSEADDR */
    set = 1;
    if (setsockopt (client_fd, SOL_SOCKET, SO_REUSEADDR,
                    (void *) &set, sizeof (set)) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot set socket option \"%s\" to %d: "
                          "error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        "SO_REUSEADDR", set, errno, strerror (errno));
        goto error;
    }

    /* add the client */
    relay_client_new (client_fd, ptr_ip_address, server);

    goto end;

error:
    if (client_fd >= 0)
        close (client_fd);

end:
    if (relay_password)
        free (relay_password);
    if (relay_totp_secret)
        free (relay_totp_secret);

    return WEECHAT_RC_OK;
}
コード例 #2
0
int
relay_server_sock_cb (void *data, int fd)
{
    struct t_relay_server *server;
    struct sockaddr_in client_addr;
    struct sockaddr_in6 client_addr6;
    socklen_t client_addr_size;
    void *ptr_addr;
    int client_fd, flags, set;
    char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1];
    char *ptr_ip_address;

    /* make C compiler happy */
    (void) fd;

    server = (struct t_relay_server *)data;

    if (server->ipv6)
    {
        ptr_addr = &client_addr6;
        client_addr_size = sizeof (struct sockaddr_in6);
    }
    else
    {
        ptr_addr = &client_addr;
        client_addr_size = sizeof (struct sockaddr_in);
    }

    memset (ptr_addr, 0, client_addr_size);

    client_fd = accept (server->sock, (struct sockaddr *)ptr_addr,
                        &client_addr_size);
    if (client_fd < 0)
    {
        dogechat_printf (NULL,
                        _("%s%s: cannot accept client on port %d (%s): error %d %s"),
                        dogechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        server->port, server->protocol_string,
                        errno, strerror (errno));
        return DOGECHAT_RC_OK;
    }

    ptr_ip_address = NULL;
    if (server->ipv6)
    {
        if (inet_ntop (AF_INET6,
                       &(client_addr6.sin6_addr),
                       ipv6_address,
                       INET6_ADDRSTRLEN))
        {
            ptr_ip_address = ipv6_address;

            if (strncmp (ptr_ip_address, "::ffff:", 7) == 0)
            {
                /* actually an IPv4-mapped IPv6 address, so skip "::ffff:" */
                ptr_ip_address += 7;
            }
        }
    }
    else
    {
        if (inet_ntop (AF_INET,
                       &(client_addr.sin_addr),
                       ipv4_address,
                       INET_ADDRSTRLEN))
        {
            ptr_ip_address = ipv4_address;
        }
    }

    /* check if IP is allowed, if not, just close socket */
    if (relay_config_regex_allowed_ips
        && (regexec (relay_config_regex_allowed_ips, ptr_ip_address, 0, NULL, 0) != 0))
    {
        if (dogechat_relay_plugin->debug >= 1)
        {
            dogechat_printf (NULL,
                            _("%s%s: IP address \"%s\" not allowed for relay"),
                            dogechat_prefix ("error"),
                            RELAY_PLUGIN_NAME,
                            ptr_ip_address);
        }
        close (client_fd);
        return DOGECHAT_RC_OK;
    }

    /* set non-blocking mode for socket */
    flags = fcntl (client_fd, F_GETFL);
    if (flags == -1)
        flags = 0;
    fcntl (client_fd, F_SETFL, flags | O_NONBLOCK);

    /* set socket option SO_REUSEADDR */
    set = 1;
    if (setsockopt (client_fd, SOL_SOCKET, SO_REUSEADDR,
                    (void *) &set, sizeof (set)) < 0)
    {
        dogechat_printf (NULL,
                        _("%s%s: cannot set socket option \"%s\" to %d: "
                          "error %d %s"),
                        dogechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        "SO_REUSEADDR", set, errno, strerror (errno));
        close (client_fd);
        return DOGECHAT_RC_OK;
    }

    /* add the client */
    relay_client_new (client_fd, ptr_ip_address, server);

    return DOGECHAT_RC_OK;
}
コード例 #3
0
ファイル: relay-server.c プロジェクト: munkee/weechat
int
relay_server_sock_cb (void *data, int fd)
{
    struct t_relay_server *server;
    struct sockaddr_in client_addr;
    socklen_t client_length;
    int client_fd;
    char ipv4_address[INET_ADDRSTRLEN + 1], *ptr_address;

    /* make C compiler happy */
    (void) fd;

    server = (struct t_relay_server *)data;

    client_length = sizeof (client_addr);
    memset (&client_addr, 0, client_length);

    client_fd = accept (server->sock, (struct sockaddr *) &client_addr,
                        &client_length);
    if (client_fd < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot accept client on port %d (%s%s%s)"),
                        weechat_prefix ("error"),
                        RELAY_PLUGIN_NAME,
                        server->port,
                        relay_protocol_string[server->protocol],
                        (server->protocol_args) ? "." : "",
                        (server->protocol_args) ? server->protocol_args : "");
        return WEECHAT_RC_OK;
    }

    ptr_address = NULL;
    if (inet_ntop (AF_INET,
                   &(client_addr.sin_addr),
                   ipv4_address,
                   INET_ADDRSTRLEN))
    {
        ptr_address = ipv4_address;
    }

    /* check if IP is allowed, if not, just close socket */
    if (relay_config_regex_allowed_ips
        && (regexec (relay_config_regex_allowed_ips, ptr_address, 0, NULL, 0) != 0))
    {
        if (weechat_relay_plugin->debug >= 2)
        {
            weechat_printf (NULL,
                            _("%s%s: IP address \"%s\" not allowed for relay"),
                            weechat_prefix ("error"),
                            RELAY_PLUGIN_NAME,
                            ptr_address);
        }
        close (client_fd);
        return WEECHAT_RC_OK;
    }

    relay_client_new (client_fd, ptr_address, server);

    return WEECHAT_RC_OK;
}