Esempio n. 1
0
/* Find completed nodes and see if a handler has to be called. Passing
   a node isn't necessary if you want to start at the root, just pass
   NULL. This second argument is needed for recursive calls. */
int xt_handle(struct xt_parser *xt, struct xt_node *node, int depth)
{
	struct xt_node *c;
	xt_status st;
	int i;

	if (xt->root == NULL) {
		return 1;
	}

	if (node == NULL) {
		return xt_handle(xt, xt->root, depth);
	}

	if (depth != 0) {
		for (c = node->children; c; c = c->next) {
			if (!xt_handle(xt, c, depth > 0 ? depth - 1 : depth)) {
				return 0;
			}
		}
	}

	if (node->flags & XT_COMPLETE && !(node->flags & XT_SEEN)) {
		if (xt->handlers) {
			for (i = 0; xt->handlers[i].func; i++) {
				/* This one is fun! \o/ */

				/* If handler.name == NULL it means it should always match. */
				if ((xt->handlers[i].name == NULL ||
				     /* If it's not, compare. There should always be a name. */
				     g_strcasecmp(xt->handlers[i].name, node->name) == 0) &&
				    /* If handler.parent == NULL, it's a match. */
				    (xt->handlers[i].parent == NULL ||
				     /* If there's a parent node, see if the name matches. */
				     (node->parent ? g_strcasecmp(xt->handlers[i].parent, node->parent->name) == 0 :
				      /* If there's no parent, the handler should mention <root> as a parent. */
				      strcmp(xt->handlers[i].parent, "<root>") == 0))) {
					st = xt->handlers[i].func(node, xt->data);

					if (st == XT_ABORT) {
						return 0;
					} else if (st != XT_NEXT) {
						break;
					}
				}
			}
		}

		node->flags |= XT_SEEN;
	}

	return 1;
}
Esempio n. 2
0
static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition cond )
{
	struct im_connection *ic = data;
	struct jabber_data *jd = ic->proto_data;
	char buf[512];
	int st;
	
	if( jd->fd == -1 )
		return FALSE;
	
	if( jd->ssl )
		st = ssl_read( jd->ssl, buf, sizeof( buf ) );
	else
		st = read( jd->fd, buf, sizeof( buf ) );
	
	if( st > 0 )
	{
		/* Parse. */
		if( xt_feed( jd->xt, buf, st ) < 0 )
		{
			imcb_error( ic, "XML stream error" );
			imc_logout( ic, TRUE );
			return FALSE;
		}
		
		/* Execute all handlers. */
		if( !xt_handle( jd->xt, NULL, 1 ) )
		{
			/* Don't do anything, the handlers should have
			   aborted the connection already. */
			return FALSE;
		}
		
		if( jd->flags & JFLAG_STREAM_RESTART )
		{
			jd->flags &= ~JFLAG_STREAM_RESTART;
			jabber_start_stream( ic );
		}
		
		/* Garbage collection. */
		xt_cleanup( jd->xt, NULL, 1 );
		
		/* This is a bit hackish, unfortunately. Although xmltree
		   has nifty event handler stuff, it only calls handlers
		   when nodes are complete. Since the server should only
		   send an opening <stream:stream> tag, we have to check
		   this by hand. :-( */
		if( !( jd->flags & JFLAG_STREAM_STARTED ) && jd->xt && jd->xt->root )
		{
			if( g_strcasecmp( jd->xt->root->name, "stream:stream" ) == 0 )
			{
				jd->flags |= JFLAG_STREAM_STARTED;
				
				/* If there's no version attribute, assume
				   this is an old server that can't do SASL
				   authentication. */
				if( !sasl_supported( ic ) )
				{
					/* If there's no version= tag, we suppose
					   this server does NOT implement: XMPP 1.0,
					   SASL and TLS. */
					if( set_getbool( &ic->acc->set, "tls" ) )
					{
						imcb_error( ic, "TLS is turned on for this "
						          "account, but is not supported by this server" );
						imc_logout( ic, FALSE );
						return FALSE;
					}
					else
					{
						return jabber_init_iq_auth( ic );
					}
				}
			}
			else
			{
				imcb_error( ic, "XML stream error" );
				imc_logout( ic, TRUE );
				return FALSE;
			}
		}
	}
	else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) )
	{
		closesocket( jd->fd );
		jd->fd = -1;
		
		imcb_error( ic, "Error while reading from server" );
		imc_logout( ic, TRUE );
		return FALSE;
	}
	
	if( ssl_pending( jd->ssl ) )
		/* OpenSSL empties the TCP buffers completely but may keep some
		   data in its internap buffers. select() won't see that, but
		   ssl_pending() does. */
		return jabber_read_callback( data, fd, cond );
	else
		return TRUE;
}
Esempio n. 3
0
static storage_status_t xml_load_real( irc_t *irc, const char *my_nick, const char *password, xml_pass_st action )
{
	struct xml_parsedata xd[1];
	char *fn, buf[2048];
	int fd, st;
	struct xt_parser *xp = NULL;
	struct xt_node *node;
	storage_status_t ret = STORAGE_OTHER_ERROR;
	
	xd->irc = irc;
	strncpy( xd->given_nick, my_nick, MAX_NICK_LENGTH );
	xd->given_nick[MAX_NICK_LENGTH] = '\0';
	nick_lc( NULL, xd->given_nick );
	xd->given_pass = (char*) password;
	
	fn = g_strconcat( global.conf->configdir, xd->given_nick, ".xml", NULL );
	if( ( fd = open( fn, O_RDONLY ) ) < 0 )
	{
		ret = STORAGE_NO_SUCH_USER;
		goto error;
	}
	
	xp = xt_new( handlers, xd );
	while( ( st = read( fd, buf, sizeof( buf ) ) ) > 0 )
	{
		st = xt_feed( xp, buf, st );
		if( st != 1 )
			break;
	}
	close( fd );
	if( st != 0 )
		goto error;
	
	node = xp->root;
	if( node == NULL || node->next != NULL || strcmp( node->name, "user" ) != 0 )
		goto error;
	
	{
		char *nick = xt_find_attr( node, "nick" );
		char *pass = xt_find_attr( node, "password" );
		
		if( !nick || !pass )
		{
			goto error;
		}
		else if( ( st = md5_verify_password( xd->given_pass, pass ) ) != 0 )
		{
			ret = STORAGE_INVALID_PASSWORD;
			goto error;
		}
	}
	
	if( action == XML_PASS_CHECK_ONLY )
	{
		ret = STORAGE_OK;
		goto error;
	}
	
	/* DO NOT call xt_handle() before verifying the password! */
	if( xt_handle( xp, NULL, 1 ) == XT_HANDLED )
		ret = STORAGE_OK;
	
	handle_settings( node, &xd->irc->b->set );
	
error:
	xt_free( xp );
	g_free( fn );
	return ret;
}
Esempio n. 4
0
static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_action action)
{
	struct xml_parsedata xd[1];
	char *fn, buf[2048];
	int fd, st;
	struct xt_parser *xp = NULL;
	struct xt_node *node;
	storage_status_t ret = STORAGE_OTHER_ERROR;

	xd->irc = irc;
	strncpy(xd->given_nick, my_nick, MAX_NICK_LENGTH);
	xd->given_nick[MAX_NICK_LENGTH] = '\0';
	nick_lc(NULL, xd->given_nick);
	xd->given_pass = (char *) password;

	fn = g_strconcat(global.conf->configdir, xd->given_nick, ".xml", NULL);
	if ((fd = open(fn, O_RDONLY)) < 0) {
		if (errno == ENOENT) {
			ret = STORAGE_NO_SUCH_USER;
		} else {
			irc_rootmsg(irc, "Error loading user config: %s", g_strerror(errno));
		}
		goto error;
	}

	xp = xt_new(handlers, xd);
	while ((st = read(fd, buf, sizeof(buf))) > 0) {
		st = xt_feed(xp, buf, st);
		if (st != 1) {
			break;
		}
	}
	close(fd);
	if (st != 0) {
		goto error;
	}

	node = xp->root;
	if (node == NULL || node->next != NULL || strcmp(node->name, "user") != 0) {
		goto error;
	}

	if (action == XML_PASS_CHECK) {
		char *nick = xt_find_attr(node, "nick");
		char *pass = xt_find_attr(node, "password");
		char *backend = xt_find_attr(node, "auth_backend");

		if (!nick || !(pass || backend)) {
			goto error;
		}

		if (backend) {
			g_free(xd->irc->auth_backend);
			xd->irc->auth_backend = g_strdup(backend);
			ret = STORAGE_CHECK_BACKEND;
		} else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) {
			ret = STORAGE_INVALID_PASSWORD;
		} else {
			ret = STORAGE_OK;
		}
		goto error;
	}

	if (xt_handle(xp, NULL, 1) == XT_HANDLED) {
		ret = STORAGE_OK;
	}

	handle_settings(node, &xd->irc->b->set);

error:
	xt_free(xp);
	g_free(fn);
	return ret;
}