コード例 #1
0
ファイル: splashd.c プロジェクト: arjan/NoCatSplash
int main (int argc, char **argv) {
    GMainLoop  *loop;
    GIOChannel *sock;

    /* Initialize signal handlers */
    signal(SIGPIPE, SIG_IGN);
    signal(SIGINT,  handle_sigint);

    /* read nocat.conf */
    read_conf_file( NC_CONF_PATH "/nocat.conf" );

    initialize_driver();

    /* initialize the firewall */
    fw_init( nocat_conf );

    /* initialize the peer table */
    peer_tab = g_hash_new();

    /* initialize the listen socket */
    sock = http_bind_socket( 
	    CONF("GatewayAddr"), CONFd("GatewayPort"), CONFd("ListenQueue") );

    /* initialize the main loop and handlers */
    loop = g_main_new(FALSE);
    g_io_add_watch( sock, G_IO_IN,  (GIOFunc) handle_accept, NULL );
    g_timeout_add( 30000, (GSourceFunc) check_peers, NULL );
    g_timeout_add( 1000, (GSourceFunc) check_sigint, loop );
    
    /* Go! */
    g_message("starting main loop");
    g_main_run( loop );
    g_message("exiting main loop");
    return 0;
}
コード例 #2
0
ファイル: firewall.c プロジェクト: AllardJ/Tomato
peer *peer_new ( GHashTable *conf, const gchar *ip ) {
    peer *p;
    gchar *hw;
    g_assert( ip != NULL );
    if (CONFd("Verbosity") >= 5) g_message("peer_new: Creating new peer object for %s.", ip);
    
    // Find & Set MAC address.
    if ( (hw = find_peer_arp( ip )) == NULL ){
        if (CONFd("Verbosity") >= 5)
            g_message( "peer_new: No MAC Address found for peer %s, not allocated!", ip );
        return NULL;
    }
    p = g_new0( peer, 1 );
    g_strncpy(p->hw, hw, strlen(hw)+1 );

    // Set IP address.
    g_strncpy( p->ip, ip, strlen(ip)+1 );
    
    // Set connection time.
    p->connected = time( NULL );
    p->token[0] = '\0';
    //peer_extend_timeout(conf, p);
    p->idle_check =0;
    p->name = NULL;
    p->session_id = NULL;
    p->acct_input_octets=0;
    p->acct_output_octets=0;
    p->acct_session_start=0;
    p->missing_count=0;
    p->auth_check =0;
    p->password = NULL;
	p->expire =0;
    return p;
}
コード例 #3
0
ファイル: http.c プロジェクト: AllardJ/Tomato
GHashTable *http_parse_header (http_request *h, gchar *req) {
    GHashTable *head = g_hash_new();
    gchar **lines, **items, *key, *val, *p, prefix[50];
    guint i;

    h->method = NULL;
    h->uri    = NULL;
    h->header = head;
    
    if (req == NULL)
	return head;
    
    lines = g_strsplit( req, "\r\n", 0 );

    if (lines == NULL || lines[0] == NULL)
	return head;

    items = g_strsplit( lines[0], " ", 3 );

    h->method = g_strdup( items[0] );
    h->uri    = g_strdup( items[1] );
    // if (CONFd("Verbosity") >= 8) g_message( "http_parse_header: method_len: %d, uri_len: %d", strlen(h->method), strlen(h->uri));
    if (CONFd("Verbosity") >= 8) g_message( "http_parse_header: Method: %s", h->method );
    if (CONFd("Verbosity") >= 8) g_message( "http_parse_header: URI: %s", url_decode(h->uri) );
    g_strfreev( items );

    for (i = 1; lines[i] != NULL && lines[i][0] != '\0'; i++ ) {
	key = lines[i];
	val = strchr(key, ':');
	if (val != NULL) {
	    /* Separate the key from the value */
	    *val = '\0';

	    /* Normalize key -- lowercase every after 1st char */
	    for (p = key + 1; *p != '\0'; p++)
		*p = tolower(*p);

	    /* Strip ": " plus leading and trailing space from val */
	    g_strchomp( val += 2 ); // ": "

	    //if ( strcmp(key, "Referer" )== 0) {
	    //    if (CONFd("Verbosity") >= 8) g_message("http_parse_header: Referer: %s", url_decode(val) );
	    //} 
            //else {
	        if (CONFd("Verbosity") >= 8) {
                    g_snprintf(prefix, 50, "http_parse_header: %s: ", key);
                    syslog_message(prefix, url_decode(val), strlen(url_decode(val)) );
                }
	        g_hash_set( head, key, val );
	    //}
	}
    }

    g_strfreev( lines );
    h->header = head;
    return head;
}
コード例 #4
0
ファイル: http.c プロジェクト: AllardJ/Tomato
gboolean http_request_ok (http_request *h) {
    guint hdr_len = http_get_hdr_len( h->buffer->str );
    guint c_len;

    if (hdr_len != 0) {
	if(CONFd("Verbosity") >= 8) g_warning( "http_request_ok: hdr_len %d", hdr_len );

	if ( HEADER("Content-length") && (c_len=atoi(HEADER("Content-length")) <= (h->buffer->len - hdr_len)) ) {
	    if(CONFd("Verbosity") >= 8) g_warning( "http_request_ok: Parsing query from HTTP-Content." );
	    http_parse_query( h, &(h->buffer->str[hdr_len]) );
	    h->complete++;
	    if(CONFd("Verbosity") >= 8) g_warning( "http_request_ok: Query parsing finished, exiting." );
	    return TRUE;
	}
	else if (HEADER("Content-length") && (CONFd("Verbosity") >= 8)) 
            g_warning( "http_request_ok: HEADER was OK, but CONTENT reading failed." );
	else if(CONFd("Verbosity") >= 8) 
            g_warning( "http_request_ok: No Content-length header, parsing query from URI." );
	http_parse_query( h, NULL );
	if (!h->query) {
          if (CONFd("Verbosity") >= 8) g_message("http_request_ok: No QUERY found.");
        }
	else if (CONFd("Verbosity") >= 8) {
	    GString *z;
            z = g_hash_as_string( h->query );
            g_debug( "http_request_ok: Query: %s", z->str );
            g_string_free(z, 1);
        }
	h->complete++;
	if(CONFd("Verbosity") >= 8) g_warning( "http_request_ok: Query parsing finished, exiting." );
	return TRUE;
    }
    if(CONFd("Verbosity") >= 6) g_warning( "http_request_ok: Request not HTTP: <CR><LF><CR><LF> (header_end) NOT found" );
    return FALSE;
}
コード例 #5
0
ファイル: splashd.c プロジェクト: xunmengdeganjue/nocatsplash
int main (int argc, char **argv) {
    GMainLoop  *loop;
    GIOChannel *sock;

    /* read nocat.conf */
    read_conf_file( NC_CONF_PATH "/nocat.conf" );

    if (argc < 2 || strncmp(argv[1], "-D", 2) != 0)
        daemonize();

    /* initalize the log */
    initialize_log();

    /* set network parameters */
    set_network_defaults( nocat_conf );

    /* initialize the gateway type driver */
    initialize_driver();

    /* initialize the firewall */
    fw_init( nocat_conf );

    /* initialize the peer table */
    peer_tab = g_hash_new();

    /* initialize the listen socket */
    sock = http_bind_socket(
               CONF("GatewayAddr"), CONFd("GatewayPort"), CONFd("ListenQueue") );

    /* initialize the main loop and handlers */
    loop = g_main_new(FALSE);
    g_io_add_watch( sock, G_IO_IN,  (GIOFunc) handle_accept, NULL );
    g_timeout_add( 30000, (GSourceFunc) check_peers, NULL );
    g_timeout_add( 1000, (GSourceFunc) check_exit_signal, loop );

    /* Go! */
    g_message("starting main loop");
    g_main_run( loop );
    g_message("exiting main loop");
    return 0;
}
コード例 #6
0
ファイル: http.c プロジェクト: AllardJ/Tomato
GHashTable *parse_query_string( gchar *query ) {
    GHashTable *data = g_hash_new();
    gchar **items, *key, *val, prefix[50];
    guint i;

    if (!query)
	return data;

    items = g_strsplit( query, "&", 0 );
    for ( i = 0; items[i] != NULL; i++ ) {
	key = items[i];
	if (key == NULL)
	    break;

	val = strchr( key, '=' );
	if (val != NULL)
	    *(val++) = '\0';
	else
	    val = "1";

	key = url_decode( key );	
	val = url_decode( val );	
	/* Irving - fix from Yurgi - check to see if the key is already in the
	   hash table.  This deals with keys that are set twice by web sites */
	if(g_hash_table_lookup_extended( data, key, NULL, NULL ) == FALSE ) {
		g_hash_set( data, key, val );
		if(CONFd("Verbosity") >= 8) {
                     g_snprintf(prefix, 50, "parse_query_string: %s=", key);
                     syslog_message(prefix, val, strlen(val));
                }
	}
	else
		if(CONFd("Verbosity") >= 8) g_message("parse_query_string: DUPLICATE key %s=%s, discarded.", key, val);

	g_free( key );
	g_free( val );
    }
    g_strfreev(items);

    return data;
}
コード例 #7
0
ファイル: http.c プロジェクト: AllardJ/Tomato
GHashTable *http_parse_query (http_request *h, gchar *post) {
    gchar *q = NULL;

    g_assert( h != NULL );

    if (h->uri != NULL) {
	if(CONFd("Verbosity") >= 9) g_message( "http_parse_query: URI: %s", url_decode(h->uri) );
	q = strchr( h->uri, '?' );
    }

    if (post != NULL) {
	h->query = parse_query_string( post );
    } else if (q != NULL) {
	h->query = parse_query_string( q + 1 );
    } else {
	h->query = NULL;
    }

    if (q != NULL)
	*q = '\0'; /* remove the query string from the URI */

    return h->query;
}
コード例 #8
0
ファイル: firewall.c プロジェクト: AllardJ/Tomato
static int fw_exec( fw_action *act, GHashTable *conf ) {
    GHashTable *data;
    GPtrArray *env;
    gchar *cmd, **arg, **n;

    data = g_hash_dup( conf );
    //
    // Than add specifics about this particular client, if any
    if (act->p != NULL) {
	g_hash_set( data, "IP",    act->p->ip );
	g_hash_set( data, "MAC",   act->p->hw );
	g_hash_set( data, "Class", "Public" );
    }

    cmd = conf_string( conf, act->cmd );
    cmd = parse_template( cmd, data );
    if (CONFd("Verbosity") >= 5) g_message("Got command %s from action %s", cmd, act->cmd );
    arg = g_strsplit( cmd, " ", 0 );

    // prime the environment with our existing environment
    env = g_ptr_array_new();
    for ( n = environ; *n != NULL; n++ )
	g_ptr_array_add( env, *n );

    // Then add everything from the conf file
    g_hash_table_foreach( data, (GHFunc) fw_exec_add_env, env );

    // Add a closing NULL so execve knows where to lay off.
    g_ptr_array_add( env, NULL );

    /* We're not cleaning up memory references because 
     * hopefully the exec won't fail... */
    execve( *arg, arg, (char **)env->pdata );
    g_error( "execve %s failed: %m", cmd ); // Shouldn't happen.
    return -1;
}
コード例 #9
0
ファイル: http.c プロジェクト: AllardJ/Tomato
guint http_request_read (http_request *h) {
    gchar *buf = g_new( gchar, BUFSIZ + 1 );
/*
    GIOStatus r;
    GError *err = NULL;
*/
    GIOError r;
    guint s, times, n = 0, t = 0;
    gchar *c_len_hdr = NULL;
    guint hdr_len = 0, c_len = 0, tot_req_size = 0;
    struct timeval tv;
    fd_set fdset;

    FD_ZERO(&fdset);
    FD_SET(g_io_channel_unix_get_fd(h->sock), &fdset);
    tv.tv_sec = 0;
    buf[0] = '\0';
    buf[BUFSIZ] = '\0';

    //    for (t = 0, n = BUF_SIZ; n == BUF_SIZ &&
    //      h->buffer->len < MAX_REQUEST_SIZE; t += n ) {
    // BPsmythe: The above (original) loop will never execute
    // more than once unless the size of the buffer read in (n)
    // is equal to the constant BUF_SIZE.  What is desired is
    // to keep looping until there is nothing left to read.
    // The for was changed to look for the end of the headers.
    // FIXME: We should use the newer g_io_channel_read_char
    //
    // TJaqua: Added buffer overflow checking, content read loop from 0.93pre2, and fixed up the timeouts, logging and error exits

    if (CONFd("Verbosity") >= 7) g_message("http_request_read: READING request from peer %s (on %s, fd: %d)", h->peer_ip, h->sock_ip, g_io_channel_unix_get_fd(h->sock));
    if (CONFd("Verbosity") >= 9) g_message("http_request_read: entering HEADER read loop (BUFSIZE=%u)", BUFSIZ);
    for (times=MAX_REQ_TIMEOUTS; !hdr_len && (times > 0); t += n ) {
	n=0;
/*
	r = g_io_channel_read_chars( h->sock, buf, BUFSIZ, &n, &err );
	if (r == G_IO_STATUS_ERROR || err != NULL) {
	    g_message( "http_request_read: Socket IO ERROR: %s, exiting!", err->message );
	    g_error_free(err);
*/
	r = g_io_channel_read( h->sock, buf, BUFSIZ, &n);
	if (r != G_IO_ERROR_NONE) {
	    g_warning( "http_request_read: Socket IO ERROR: %m, exiting!" );
	    g_free(buf);
	    return 0;
	}

	if (CONFd("Verbosity") >= 9) g_message("http_request_read: HEADER loop read %u bytes", n);
	buf[n] = '\0';
	if (n && CONFd("Verbosity") >= 11) syslog_message("RAW_HDR_BUF: ", buf, n);

	if(strlen(buf) < n-1) g_warning("http_request_read: Trailing data past string in buffer was DICARDED!");
	if (h->buffer->len == MAX_REQUEST_SIZE)
	    g_warning("http_request_read: header buffer full (%u bytes, %u bytes discarded!)", MAX_REQUEST_SIZE, n);
	else if (n <= (MAX_REQUEST_SIZE - h->buffer->len)) {
	    if(CONFd("Verbosity") >= 11) g_message("http_request_read: APPENDING buffer to HEADER.");
	    if(n) g_string_append(h->buffer, buf);
	    else if (CONFd("Verbosity") >= 6) g_message("http_request_read: No data in buffer.");
	    //if(CONFd("Verbosity") >= 11) g_message("http_request_read: Partial HEADER (%u bytes) is: %s", h->buffer->len, h->buffer->str);
	}
	else {
	    if(CONFd("Verbosity") >= 6) g_warning("http_request_read: header buffer full (%u bytes, %u bytes discarded!)", 
                                                  MAX_REQUEST_SIZE, n - (MAX_REQUEST_SIZE - h->buffer->len));
	    buf[MAX_REQUEST_SIZE - h->buffer->len] = '\0';
	    g_string_append(h->buffer, buf);
	}
        times--;

        // BPsmythe: Check for the end of the headers.
	if (hdr_len = http_get_hdr_len(h->buffer->str)) {
	        if (CONFd("Verbosity") >= 6) g_message("http_request_read: HEADER END found, length: %u", hdr_len );
        }
	else {
	    if(!times) { 
                if(CONFd("Verbosity") >= 6) {
                    g_message("http_request_read: ERROR: HEADER END not found after %d tries, exiting!", MAX_REQ_TIMEOUTS);
	            if (!t) g_message("http_request_read: Empty HTTP-request header.");
	            else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n);
	        }
		//Should I send a FIN packet to shutdown the socket?
                g_free(buf);
	        return 0;
            }
	    if(CONFd("Verbosity") >= 11) g_message("http_request_read: Waiting for next I/O on socket, (%d more tries).", times);
            tv.tv_usec = REQ_TIMEOUT;
	    while(times && !(s = select (g_io_channel_unix_get_fd(h->sock)+1, &fdset, NULL, NULL, &tv))) {
                times--;
	        if (CONFd("Verbosity") >= 7)  g_message("http_request_read: HEADER select timeout, %d more tries", times);
                tv.tv_usec = REQ_TIMEOUT;
            }
	    if(s<0) {
	        g_warning("http_request_read: ERROR in select, exiting!");
		g_free(buf);
		return 0;
	    }
	    else if(!times) { 
                if(CONFd("Verbosity") >= 6) {
                    g_message("http_request_read: ERROR: Too many TIMEOUTS waiting for HEADER end!");
	            if (!t) g_message("http_request_read: Empty HTTP-request header.");
	            else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n);
	        }
		//Should I send a FIN packet to shutdown the socket?
                g_free(buf);
	        return 0;
            }
            else if(CONFd("Verbosity") >= 11) g_message("http_request_read: Recieved I/O on socket.");
	}
    }

    if (CONFd("Verbosity") >= 10) syslog_message("RAW_HEADER: ", h->buffer->str, h->buffer->len);
    
    // Read the content length from the header
    http_parse_header( h, h->buffer->str );

    if( (HEADER("Content-length")) && (c_len = atoi(HEADER("Content-length"))) ) {
        if (CONFd("Verbosity") >= 9) g_message("http_request_read: entering CONTENT read loop to read %u bytes.", c_len);
        tot_req_size = hdr_len + c_len;
        for (times=MAX_REQ_TIMEOUTS; (t < tot_req_size) && (times > 0); t += n ) {
	    if (CONFd("Verbosity") >= 9) g_message("http_request_read: %u bytes of %u total.", t, tot_req_size );
	    n=0;
/*
	    r = g_io_channel_read_chars( h->sock, buf, BUFSIZ, &n, &err );
	    if (r == G_IO_STATUS_ERROR || err != NULL) {
	        g_message( "http_request_read: Socket-IO ERROR: %s, exiting!", err->message );
	        g_error_free(err);
*/
	    r = g_io_channel_read( h->sock, buf, BUFSIZ, &n);
	    if (r != G_IO_ERROR_NONE) {
	        g_warning( "http_request_read: Socket-IO ERROR: %m, exiting!" );
	        g_free(buf);
	        return 0;
	    }

	    if (CONFd("Verbosity") >= 9) g_message("http_request_read: CONTENT loop read %d bytes", n );
	    buf[n] = '\0';
	    if (n && CONFd("Verbosity") >= 11) syslog_message("RAW_CON_BUF: ", buf, n); 

	    if (h->buffer->len == MAX_REQUEST_SIZE) {
	        if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Maximum request length EXCEEDED (%u bytes discarded! Continuing to read out content.)", n);
            }
	    else if (h->buffer->len == tot_req_size) {
	        if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Content length EXCEEDED (%u bytes discarded! Shouldn't happen!)", n);
            }
            else if (h->buffer->len + n >= MAX_REQUEST_SIZE) {
	        if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Max buffer length EXCEEDED (%u bytes discarded! Continuing to read out content.)", 
                                                       n - (MAX_REQUEST_SIZE - h->buffer->len));
                buf[MAX_REQUEST_SIZE - h->buffer->len] = '\0';
	        g_string_append(h->buffer, buf);
            }
	    else if (n <= (tot_req_size - h->buffer->len)) {
	        if(CONFd("Verbosity") >= 11) g_message("http_request_read: APPENDING buffer to CONTENT.");
	        if(n) g_string_append(h->buffer, buf);
	        else if (CONFd("Verbosity") >= 6) g_message("http_request_read: No data in buffer.");
	    }
	    else {
	        if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Content length EXCEEDED (%u bytes added, %u bytes discarded!)", 
                                                       tot_req_size - h->buffer->len, n - (tot_req_size - h->buffer->len));
	        buf[tot_req_size - h->buffer->len] = '\0';
	        g_string_append(h->buffer, buf);
	    }
            times--;

            // TJaqua: Check for the end of the content.
	    if ((t+n) >= tot_req_size) {
                if (CONFd("Verbosity") >= 6) g_message("http_request_read: CONTENT end reached, length: %u", tot_req_size);
            }
	    else {
                if (!times) {
                    if(CONFd("Verbosity") >= 6) {
                        g_message("http_request_read: ERROR: CONTENT END not found after %d tries, exiting!", MAX_REQ_TIMEOUTS);
	                if (t == hdr_len) g_message("http_request_read: Empty CONTENT, socket may have stalled.");
	                else g_message("http_request_read: CONTENT unfinished, %u bytes read.", t+n);
	            }
                    //Should I send a FIN packet to shutdown the socket?
                    g_free(buf);
                    //We still got the header, though, so return it.
                    g_string_truncate(h->buffer, hdr_len);
	            return hdr_len;
                }
	        if(CONFd("Verbosity") >= 11) g_message("http_request_read: Waiting for next I/O on socket.");
                tv.tv_usec = REQ_TIMEOUT;
	        while (times && !(s = select (g_io_channel_unix_get_fd(h->sock)+1, &fdset, NULL, NULL, &tv))) {
                    times--;
	            if (CONFd("Verbosity") >= 7)  g_message("http_request_read: CONTENT select timeout, %d more tries", times);
                    tv.tv_usec = REQ_TIMEOUT;
                }
	        if(s<0) {
	            g_warning("http_request_read: ERROR in select, exiting!");
		    g_free(buf);
                    //We still got the header, though, so return it.
                    g_string_truncate(h->buffer, hdr_len);
	            return hdr_len;
	        }
                else if (!times) {
                    if(CONFd("Verbosity") >= 6) {
                        g_message("http_request_read: ERROR: Too many TIMEOUTS waiting for CONTENT end!");
	                if (t == hdr_len) g_message("http_request_read: Empty CONTENT, socket may have stalled.");
	                else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n);
	            }
                    //Should I send a FIN packet to shutdown the socket?
                    g_free(buf);
                    //We still got the header, though, so return it.
                    g_string_truncate(h->buffer, hdr_len);
	            return hdr_len;
                }
                else if (CONFd("Verbosity") >= 11) g_message("http_request_read: Received I/O on socket.");
	    }
        }
        if (CONFd("Verbosity") >= 10) syslog_message("RAW_CONTENT: ", &(h->buffer->str[hdr_len]), h->buffer->len - hdr_len); 
        if (t<tot_req_size) 
	    g_message("http_request_read: CONTENT unfinished - should not happen!");
    }

    if (CONFd("Verbosity") >= 6) g_message("http_request_read: FINISHED read (%u bytes total), exiting.", t);
    g_free(buf);
    return t;
}