Пример #1
0
/* This one is actually pretty simple... Might get more calls if we can't write 
   the whole request at once. */
static gboolean http_connected( gpointer data, int source, b_input_condition cond )
{
	struct http_request *req = data;
	int st;
	
	if( source < 0 )
		goto error;
	
	if( req->inpa > 0 )
		b_event_remove( req->inpa );
	
	sock_make_nonblocking( req->fd );
	
	if( req->ssl )
	{
		st = ssl_write( req->ssl, req->request + req->bytes_written,
		                req->request_length - req->bytes_written );
		if( st < 0 )
		{
			if( ssl_errno != SSL_AGAIN )
			{
				ssl_disconnect( req->ssl );
				goto error;
			}
		}
	}
	else
	{
		st = write( source, req->request + req->bytes_written,
		                    req->request_length - req->bytes_written );
		if( st < 0 )
		{
			if( !sockerr_again() )
			{
				closesocket( req->fd );
				goto error;
			}
		}
	}
	
	if( st > 0 )
		req->bytes_written += st;
	
	if( req->bytes_written < req->request_length )
		req->inpa = b_input_add( source,
		                         req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_WRITE,
	        	                 http_connected, req );
	else
		req->inpa = b_input_add( source, B_EV_IO_READ, http_incoming_data, req );
	
	return FALSE;
	
error:
	if( req->status_string == NULL )
		req->status_string = g_strdup( "Error while writing HTTP request" );
	
	req->func( req );
	http_free( req );
	return FALSE;
}
Пример #2
0
static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
{
	struct scd *conn = data;
	
	if( source == -1 )
	{
		conn->func( conn->data, 0, NULL, cond );
		g_free( conn );
		return FALSE;
	}
	
	ssl_init();
	
	gnutls_init( &conn->session, GNUTLS_CLIENT );
	if( conn->verify )
		gnutls_session_set_ptr( conn->session, (void *) conn->hostname );
#if GNUTLS_VERSION_NUMBER < 0x020c00
	gnutls_transport_set_lowat( conn->session, 0 );
#endif
	gnutls_set_default_priority( conn->session );
	gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, xcred );
	
	sock_make_nonblocking( conn->fd );
	gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) GNUTLS_STUPID_CAST conn->fd );
	
	return ssl_handshake( data, source, cond );
}
Пример #3
0
static gboolean ssl_connected(gpointer data, gint source, b_input_condition cond)
{
    struct scd *conn = data;

    if (conn->verify) {
        /* Right now we don't have any verification functionality for OpenSSL. */
        conn->func(conn->data, 1, NULL, cond);
        if (source >= 0) {
            closesocket(source);
        }
        ssl_conn_free(conn);

        return FALSE;
    }

    if (source == -1) {
        goto ssl_connected_failure;
    }

    if (!initialized) {
        ssl_init();
    }


    if (ssl_ctx == NULL) {
        goto ssl_connected_failure;
    }

    conn->ssl = SSL_new(ssl_ctx);
    if (conn->ssl == NULL) {
        goto ssl_connected_failure;
    }

    /* We can do at least the handshake with non-blocking I/O */
    sock_make_nonblocking(conn->fd);
    SSL_set_fd(conn->ssl, conn->fd);

    if (conn->hostname && !g_ascii_isdigit(conn->hostname[0])) {
        SSL_set_tlsext_host_name(conn->ssl, conn->hostname);
    }

    return ssl_handshake(data, source, cond);

ssl_connected_failure:
    conn->func(conn->data, 0, NULL, cond);
    ssl_disconnect(conn);
    return FALSE;

}
Пример #4
0
static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb)
{
	struct sockaddr_in *sin;
	struct sockaddr_in me;
	int fd = -1;

	if (!(sin = gaim_gethostbyname(host, port))) {
		g_free(phb);
		return -1;
	}

	if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) {
		g_free(phb);
		return -1;
	}

	sock_make_nonblocking(fd);
	
	if( global.conf->iface_out )
	{
		me.sin_family = AF_INET;
		me.sin_port = 0;
		me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
		
		if( bind( fd, (struct sockaddr *) &me, sizeof( me ) ) != 0 )
			event_debug( "bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out );
	}
	
	event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
	
	if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0 && !sockerr_again()) {
		closesocket(fd);
		g_free(phb);
		
		return -1;
	} else {
		phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
		phb->fd = fd;
		
		return fd;
	}
}
Пример #5
0
irc_t *irc_new(int fd)
{
	irc_t *irc;
	struct sockaddr_storage sock;
	socklen_t socklen = sizeof(sock);
	char *host = NULL, *myhost = NULL;
	irc_user_t *iu;
	GSList *l;
	set_t *s;
	bee_t *b;

	irc = g_new0(irc_t, 1);

	irc->fd = fd;
	sock_make_nonblocking(irc->fd);

	irc->r_watch_source_id = b_input_add(irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc);

	irc->status = USTATUS_OFFLINE;
	irc->last_pong = gettime();

	irc->nick_user_hash = g_hash_table_new(g_str_hash, g_str_equal);
	irc->watches = g_hash_table_new(g_str_hash, g_str_equal);

	irc->iconv = (GIConv) - 1;
	irc->oconv = (GIConv) - 1;

	if (global.conf->hostname) {
		myhost = g_strdup(global.conf->hostname);
	} else if (getsockname(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) {
		char buf[NI_MAXHOST + 1];

		if (getnameinfo((struct sockaddr *) &sock, socklen, buf,
		                NI_MAXHOST, NULL, 0, 0) == 0) {
			myhost = g_strdup(ipv6_unwrap(buf));
		}
	}

	if (getpeername(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) {
		char buf[NI_MAXHOST + 1];

		if (getnameinfo((struct sockaddr *) &sock, socklen, buf,
		                NI_MAXHOST, NULL, 0, 0) == 0) {
			host = g_strdup(ipv6_unwrap(buf));
		}
	}

	if (host == NULL) {
		host = g_strdup("localhost.localdomain");
	}
	if (myhost == NULL) {
		myhost = g_strdup("localhost.localdomain");
	}

	if (global.conf->ping_interval > 0 && global.conf->ping_timeout > 0) {
		irc->ping_source_id = b_timeout_add(global.conf->ping_interval * 1000, irc_userping, irc);
	}

	irc_connection_list = g_slist_append(irc_connection_list, irc);

	b = irc->b = bee_new();
	b->ui_data = irc;
	b->ui = &irc_ui_funcs;

	s = set_add(&b->set, "allow_takeover", "true", set_eval_bool, irc);
	s = set_add(&b->set, "away_devoice", "true", set_eval_bw_compat, irc);
	s->flags |= SET_HIDDEN;
	s = set_add(&b->set, "away_reply_timeout", "3600", set_eval_int, irc);
	s = set_add(&b->set, "charset", "utf-8", set_eval_charset, irc);
	s = set_add(&b->set, "default_target", "root", NULL, irc);
	s = set_add(&b->set, "display_namechanges", "false", set_eval_bool, irc);
	s = set_add(&b->set, "display_timestamps", "true", set_eval_bool, irc);
	s = set_add(&b->set, "handle_unknown", "add_channel", NULL, irc);
	s = set_add(&b->set, "last_version", "0", NULL, irc);
	s->flags |= SET_HIDDEN;
	s = set_add(&b->set, "nick_format", "%-@nick", NULL, irc);
	s = set_add(&b->set, "nick_lowercase", "false", set_eval_bool, irc);
	s = set_add(&b->set, "nick_underscores", "false", set_eval_bool, irc);
	s = set_add(&b->set, "offline_user_quits", "true", set_eval_bool, irc);
	s = set_add(&b->set, "ops", "both", set_eval_irc_channel_ops, irc);
	s = set_add(&b->set, "paste_buffer", "false", set_eval_bool, irc);
	s->old_key = g_strdup("buddy_sendbuffer");
	s = set_add(&b->set, "paste_buffer_delay", "200", set_eval_int, irc);
	s->old_key = g_strdup("buddy_sendbuffer_delay");
	s = set_add(&b->set, "password", NULL, set_eval_password, irc);
	s->flags |= SET_NULL_OK | SET_PASSWORD;
	s = set_add(&b->set, "private", "true", set_eval_bool, irc);
	s = set_add(&b->set, "query_order", "lifo", NULL, irc);
	s = set_add(&b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc);
	s->flags |= SET_HIDDEN;
	s = set_add(&b->set, "show_offline", "false", set_eval_bw_compat, irc);
	s->flags |= SET_HIDDEN;
	s = set_add(&b->set, "self_messages", "true", set_eval_self_messages, irc);
	s = set_add(&b->set, "simulate_netsplit", "true", set_eval_bool, irc);
	s = set_add(&b->set, "timezone", "local", set_eval_timezone, irc);
	s = set_add(&b->set, "to_char", ": ", set_eval_to_char, irc);
	s = set_add(&b->set, "typing_notice", "false", set_eval_bool, irc);
	s = set_add(&b->set, "utf8_nicks", "false", set_eval_utf8_nicks, irc);

	irc->root = iu = irc_user_new(irc, ROOT_NICK);
	iu->host = g_strdup(myhost);
	iu->fullname = g_strdup(ROOT_FN);
	iu->f = &irc_user_root_funcs;

	iu = irc_user_new(irc, NS_NICK);
	iu->host = g_strdup(myhost);
	iu->fullname = g_strdup(ROOT_FN);
	iu->f = &irc_user_root_funcs;

	irc->user = g_new0(irc_user_t, 1);
	irc->user->host = g_strdup(host);

	conf_loaddefaults(irc);

	/* Evaluator sets the iconv/oconv structures. */
	set_eval_charset(set_find(&b->set, "charset"), set_getstr(&b->set, "charset"));

	irc_write(irc, ":%s NOTICE * :%s", irc->root->host, "BitlBee-IRCd initialized, please go on");
	if (isatty(irc->fd)) {
		irc_write(irc, ":%s NOTICE * :%s", irc->root->host,
		          "If you read this, you most likely accidentally "
		          "started BitlBee in inetd mode on the command line. "
		          "You probably want to run it in (Fork)Daemon mode. "
		          "See doc/README for more information.");
	}

	g_free(myhost);
	g_free(host);

	/* libpurple doesn't like fork()s after initializing itself, so this
	   is the right moment to initialize it. */
#ifdef WITH_PURPLE
	nogaim_init();
#endif

	/* SSL library initialization also should be done after the fork, to
	   avoid shared CSPRNG state. This is required by NSS, which refuses to
	   work if a fork is detected */
	ssl_init();

	for (l = irc_plugins; l; l = l->next) {
		irc_plugin_t *p = l->data;
		if (p->irc_new) {
			p->irc_new(irc);
		}
	}

	return irc;
}
Пример #6
0
static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb)
{
	struct sockaddr_in me;
	int fd = -1;
	
	if (phb->gai_cur == NULL)
	{
		int ret;
		char port[6];
		struct addrinfo hints;
	
		g_snprintf(port, sizeof(port), "%d", port_);
	
		memset(&hints, 0, sizeof(struct addrinfo));
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
	
		if (!(ret = getaddrinfo(host, port, &hints, &phb->gai)))
			phb->gai_cur = phb->gai;
		else
			event_debug("gai(): %s\n", gai_strerror(ret));
	}
	
	for (; phb->gai_cur; phb->gai_cur = phb->gai_cur->ai_next)
	{
		if ((fd = socket(phb->gai_cur->ai_family, phb->gai_cur->ai_socktype, phb->gai_cur->ai_protocol)) < 0) {
			event_debug( "socket failed: %d\n", errno);
			continue;
		}

		sock_make_nonblocking(fd);

		if (global.conf->iface_out)
		{
			me.sin_family = AF_INET;
			me.sin_port = 0;
			me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
				
			if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0)
				event_debug("bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out);
		}

		event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port_, fd);
	
		if (connect(fd, phb->gai_cur->ai_addr, phb->gai_cur->ai_addrlen) < 0 && !sockerr_again()) {
			event_debug( "connect failed: %s\n", strerror(errno));
			closesocket(fd);
			fd = -1;
			continue;
		} else {
			phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb);
			phb->fd = fd;
			
			break;
		}
	}
	
	if(fd < 0 && host)
		g_free(phb);

	return fd;
}