예제 #1
0
/*
 * Subtype 0x0004 - Set your client's capabilities.
 */
int
aim_locate_setcaps(OscarData *od, guint32 caps)
{
	FlapConnection *conn;
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	aim_tlvlist_add_caps(&tlvlist, 0x0005, caps);

	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, 0x0002, 0x004, 0x0000, snacid);

	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #2
0
void
flap_connection_send_version_with_cookie_and_clientinfo(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy, ClientInfo *ci, gboolean allow_multiple_logins)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;

	frame = flap_frame_new(od, 0x01, 1152 + length);

	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
	aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);

	if (ci->clientstring != NULL)
		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
	else {
		gchar *clientstring = oscar_get_clientstring();
		aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
		g_free(clientstring);
	}
	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
	aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));

	aim_tlvlist_write(&frame->data, &tlvlist);

	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);
}
예제 #3
0
/*
 * Attempt to send the contents of a given queue
 *
 * @return TRUE if the queue was completely emptied or was initially
 *         empty; FALSE if rate limiting prevented it from being
 *         emptied.
 */
static gboolean flap_connection_send_snac_queue(FlapConnection *conn, struct timeval now, GQueue *queue)
{
	while (!g_queue_is_empty(queue))
	{
		QueuedSnac *queued_snac;
		struct rateclass *rateclass;

		queued_snac = g_queue_peek_head(queue);

		rateclass = flap_connection_get_rateclass(conn, queued_snac->family, queued_snac->subtype);
		if (rateclass != NULL)
		{
			guint32 new_current;

			new_current = rateclass_get_new_current(conn, rateclass, &now);

			if (rateclass->dropping_snacs || new_current <= rateclass->alert)
				/* Not ready to send this SNAC yet--keep waiting. */
				return FALSE;

			rateclass->current = new_current;
			rateclass->last.tv_sec = now.tv_sec;
			rateclass->last.tv_usec = now.tv_usec;
		}

		flap_connection_send(conn, queued_snac->frame);
		g_free(queued_snac);
		g_queue_pop_head(queue);
	}

	/* We emptied the queue */
	return TRUE;
}
예제 #4
0
/*
 * Subtype 0x0006
 *
 * In AIM 3.5 protocol, the first stage of login is to request login from the
 * Authorizer, passing it the username for verification.  If the name is
 * invalid, a 0017/0003 is spit back, with the standard error contents.  If
 * valid, a 0017/0007 comes back, which is the signal to send it the main
 * login command (0017/0002).
 *
 */
int
aim_request_login(OscarData *od, FlapConnection *conn, const char *sn)
{
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !conn || !sn)
		return -EINVAL;

#ifdef USE_XOR_FOR_ICQ
	if (aim_snvalid_icq(sn))
		return goddamnicq(od, conn, sn);
#endif

	frame = flap_frame_new(od, 0x02, 10+2+2+strlen(sn)+8);

	snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0006, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0006, 0x0000, snacid);

	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);

	/* Tell the server we support SecurID logins. */
	aim_tlvlist_add_noval(&tlvlist, 0x004b);

	/* Unknown.  Sent in recent WinAIM clients.*/
	aim_tlvlist_add_noval(&tlvlist, 0x005a);

	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #5
0
/**
 * Subtype 0x000b
 *
 * Send SecurID response.
 */
int
aim_auth_securid_send(OscarData *od, const char *securid)
{
	FlapConnection *conn;
	FlapFrame *frame;
	aim_snacid_t snacid;
	int len;

	if (!od || !(conn = flap_connection_getbytype_all(od, SNAC_FAMILY_AUTH)) || !securid)
		return -EINVAL;

	len = strlen(securid);

	frame = flap_frame_new(od, 0x02, 10+2+len);

	snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_RESPONSE, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_RESPONSE, 0x0000, 0);

	byte_stream_put16(&frame->data, len);
	byte_stream_putstr(&frame->data, securid);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #6
0
/**
 * This sends an empty channel 4 FLAP.  This is sent to signify
 * that we're logging off.  This shouldn't really be necessary--
 * usually the AIM server will detect that the TCP connection has
 * been destroyed--but it's good practice.
 */
static void
flap_connection_send_close(OscarData *od, FlapConnection *conn)
{
	FlapFrame *frame;

	frame = flap_frame_new(od, 0x04, 0);
	flap_connection_send(conn, frame);
}
예제 #7
0
/**
 * This sends a channel 1 SNAC containing the FLAP version.
 * The FLAP version is sent by itself at the beginning of every
 * connection to a FLAP server.  It is always the very first
 * packet sent by both the server and the client after the SYN,
 * SYN/ACK, ACK handshake.
 */
void
flap_connection_send_version(OscarData *od, FlapConnection *conn)
{
	FlapFrame *frame;

	frame = flap_frame_new(od, 0x01, 4);
	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
	flap_connection_send(conn, frame);
}
예제 #8
0
/*
 * Subtype 0x0008
 */
int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange)
{
	static const char ck[] = {"create"};
	static const char lang[] = {"en"};
	static const char charset[] = {"us-ascii"};
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	frame = flap_frame_new(od, 0x02, 1152);

	snacid = aim_cachesnac(od, 0x000d, 0x0008, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, 0x000d, 0x0008, 0x0000, snacid);

	/* exchange */
	byte_stream_put16(&frame->data, exchange);

	/*
	 * This looks to be a big hack.  You'll note that this entire
	 * SNAC is just a room info structure, but the hard room name,
	 * here, is set to "create".
	 *
	 * Either this goes on the "list of questions concerning
	 * why-the-hell-did-you-do-that", or this value is completely
	 * ignored.  Without experimental evidence, but a good knowledge of
	 * AOL style, I'm going to guess that it is the latter, and that
	 * the value of the room name in create requests is ignored.
	 */
	byte_stream_put8(&frame->data, strlen(ck));
	byte_stream_putstr(&frame->data, ck);

	/*
	 * instance
	 *
	 * Setting this to 0xffff apparently assigns the last instance.
	 *
	 */
	byte_stream_put16(&frame->data, 0xffff);

	/* detail level */
	byte_stream_put8(&frame->data, 0x01);

	aim_tlvlist_add_str(&tlvlist, 0x00d3, name);
	aim_tlvlist_add_str(&tlvlist, 0x00d6, charset);
	aim_tlvlist_add_str(&tlvlist, 0x00d7, lang);

	/* tlvcount */
	byte_stream_put16(&frame->data, aim_tlvlist_count(tlvlist));
	aim_tlvlist_write(&frame->data, &tlvlist);

	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #9
0
/**
 * This sends an empty channel 5 FLAP.  This is used as a keepalive
 * packet in FLAP connections.  WinAIM 4.x and higher send these
 * _every minute_ to keep the connection alive.
 */
void
flap_connection_send_keepalive(OscarData *od, FlapConnection *conn)
{
	FlapFrame *frame;

	frame = flap_frame_new(od, 0x05, 0);
	flap_connection_send(conn, frame);

	/* clean out SNACs over 60sec old */
	aim_cleansnacs(od, 60);
}
예제 #10
0
/*
 * Part two of the ICQ hack.  Note the ignoring of the key.
 */
static int
goddamnicq2(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;
	int passwdlen;
	guint8 *password_encoded;
	guint32 distrib;

	passwdlen = strlen(password);
	password_encoded = (guint8 *)g_malloc(passwdlen+1);
	if (passwdlen > MAXICQPASSLEN)
		passwdlen = MAXICQPASSLEN;

	frame = flap_frame_new(od, 0x01, 1152);

	aim_encode_password(password, password_encoded);

	distrib = oscar_get_ui_info_int(
			od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
			ci->distrib);

	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
	aim_tlvlist_add_raw(&tlvlist, 0x0002, passwdlen, password_encoded);

	if (ci->clientstring != NULL)
		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
	else {
		gchar *clientstring = oscar_get_clientstring();
		aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
		g_free(clientstring);
	}
	aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
	aim_tlvlist_add_32(&tlvlist, 0x0014, distrib); /* distribution chan */
	aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
	aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);

	aim_tlvlist_write(&frame->data, &tlvlist);

	g_free(password_encoded);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #11
0
/**
 * This sends a channel 1 FLAP containing the FLAP version and
 * the authentication cookie.  This is sent when connecting to
 * any FLAP server after the initial connection to the auth
 * server.  It is always the very first packet sent by both the
 * server and the client after the SYN, SYN/ACK, ACK handshake.
 */
void
flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;

	frame = flap_frame_new(od, 0x01, 4 + 2 + 2 + length);
	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
	aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);
	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);
}
예제 #12
0
/*
 * Stubtypes 0x0005, 0x0006, 0x0007, and 0x0008 - Modify permit/deny lists.
 *
 * Changes your visibility depending on changetype:
 *
 *  AIM_VISIBILITYCHANGE_PERMITADD: Lets provided list of names see you
 *  AIM_VISIBILITYCHANGE_PERMIDREMOVE: Removes listed names from permit list
 *  AIM_VISIBILITYCHANGE_DENYADD: Hides you from provided list of names
 *  AIM_VISIBILITYCHANGE_DENYREMOVE: Lets list see you again
 *
 * list should be a list of
 * screen names in the form "Screen Name One&ScreenNameTwo&" etc.
 *
 * Equivelents to options in WinAIM:
 *   - Allow all users to contact me: Send an AIM_VISIBILITYCHANGE_DENYADD
 *      with only your name on it.
 *   - Allow only users on my Buddy List: Send an
 *      AIM_VISIBILITYCHANGE_PERMITADD with the list the same as your
 *      buddy list
 *   - Allow only the uesrs below: Send an AIM_VISIBILITYCHANGE_PERMITADD
 *      with everyone listed that you want to see you.
 *   - Block all users: Send an AIM_VISIBILITYCHANGE_PERMITADD with only
 *      yourself in the list
 *   - Block the users below: Send an AIM_VISIBILITYCHANGE_DENYADD with
 *      the list of users to be blocked
 *
 * XXX ye gods.
 */
int aim_bos_changevisibility(OscarData *od, FlapConnection *conn, int changetype, const char *denylist)
{
	FlapFrame *frame;
	int packlen = 0;
	guint16 subtype;
	char *localcpy = NULL, *tmpptr = NULL;
	int i;
	int listcount;
	aim_snacid_t snacid;

	if (!denylist)
		return -EINVAL;

	if (changetype == AIM_VISIBILITYCHANGE_PERMITADD)
		subtype = 0x05;
	else if (changetype == AIM_VISIBILITYCHANGE_PERMITREMOVE)
		subtype = 0x06;
	else if (changetype == AIM_VISIBILITYCHANGE_DENYADD)
		subtype = 0x07;
	else if (changetype == AIM_VISIBILITYCHANGE_DENYREMOVE)
		subtype = 0x08;
	else
		return -EINVAL;

	localcpy = g_strdup(denylist);

	listcount = aimutil_itemcnt(localcpy, '&');
	packlen = aimutil_tokslen(localcpy, 99, '&') + listcount + 9;

	frame = flap_frame_new(od, 0x02, packlen);

	snacid = aim_cachesnac(od, 0x0009, subtype, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, 0x0009, subtype, 0x00, snacid);

	for (i = 0; (i < (listcount - 1)) && (i < 99); i++) {
		tmpptr = aimutil_itemindex(localcpy, i, '&');

		byte_stream_put8(&frame->data, strlen(tmpptr));
		byte_stream_putstr(&frame->data, tmpptr);

		g_free(tmpptr);
	}
	g_free(localcpy);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #13
0
/*
 * Subtype 0x0009 - Set directory profile data.
 *
 * This is not the same as aim_location_setprofile!
 * privacy: 1 to allow searching, 0 to disallow.
 *
 */
int aim_locate_setdirinfo(OscarData *od, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy)
{
	FlapConnection *conn;
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);

	if (first)
		aim_tlvlist_add_str(&tlvlist, 0x0001, first);
	if (last)
		aim_tlvlist_add_str(&tlvlist, 0x0002, last);
	if (middle)
		aim_tlvlist_add_str(&tlvlist, 0x0003, middle);
	if (maiden)
		aim_tlvlist_add_str(&tlvlist, 0x0004, maiden);

	if (state)
		aim_tlvlist_add_str(&tlvlist, 0x0007, state);
	if (city)
		aim_tlvlist_add_str(&tlvlist, 0x0008, city);

	if (nickname)
		aim_tlvlist_add_str(&tlvlist, 0x000c, nickname);
	if (zip)
		aim_tlvlist_add_str(&tlvlist, 0x000d, zip);

	if (street)
		aim_tlvlist_add_str(&tlvlist, 0x0021, street);

	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, 0x0002, 0x0009, 0x0000, NULL, 0);

	aim_putsnac(&frame->data, 0x0002, 0x0009, 0x0000, snacid);
	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #14
0
/*
 * Subtype 0x000b - Huh? What is this?
 */
int aim_locate_000b(OscarData *od, const char *sn)
{
	FlapConnection *conn;
	FlapFrame *frame;
	aim_snacid_t snacid;

		return -EINVAL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)) || !sn)
		return -EINVAL;

	frame = flap_frame_new(od, 0x02, 10+1+strlen(sn));

	snacid = aim_cachesnac(od, 0x0002, 0x000b, 0x0000, NULL, 0);

	aim_putsnac(&frame->data, 0x0002, 0x000b, 0x0000, snacid);
	byte_stream_put8(&frame->data, strlen(sn));
	byte_stream_putstr(&frame->data, sn);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #15
0
/*
 * Subtype 0x000f
 *
 * XXX pass these in better
 *
 */
int
aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy)
{
	FlapConnection *conn;
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	/* ?? privacy ?? */
	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);

	if (interest1)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest1);
	if (interest2)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest2);
	if (interest3)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest3);
	if (interest4)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest4);
	if (interest5)
		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest5);

	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, 0x0002, 0x000f, 0x0000, NULL, 0);

	aim_putsnac(&frame->data, 0x0002, 0x000f, 0x0000, 0);
	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #16
0
/*
 * Subtype 0x0004
 *
 * Gives BOS your profile.
 *
 * profile_encoding and awaymsg_encoding MUST be set if profile or
 * away are set, respectively, and their value may or may not be
 * restricted to a few choices.  I am currently aware of:
 *
 * us-ascii		Just that
 * unicode-2-0		UCS2-BE
 *
 * profile_len and awaymsg_len MUST be set similarly, and they MUST
 * be the length of their respective strings in bytes.
 *
 * To get the previous behavior of awaymsg == "" un-setting the away
 * message, set awaymsg non-NULL and awaymsg_len to 0 (this is the
 * obvious equivalent).
 *
 */
int
aim_locate_setprofile(OscarData *od,
				  const char *profile_encoding, const gchar *profile, const int profile_len,
				  const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len)
{
	FlapConnection *conn;
	FlapFrame *frame;
	aim_snacid_t snacid;
	GSList *tlvlist = NULL;
	char *encoding;
	static const char defencoding[] = {"text/aolrtf; charset=\"%s\""};

	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
		return -EINVAL;

	if (!profile && !awaymsg)
		return -EINVAL;

	if ((profile && profile_encoding == NULL) || (awaymsg && awaymsg_len && awaymsg_encoding == NULL)) {
		return -EINVAL;
	}

	/* Build the packet first to get real length */
	if (profile) {
		/* no + 1 here because of %s */
		encoding = g_malloc(strlen(defencoding) + strlen(profile_encoding));
		snprintf(encoding, strlen(defencoding) + strlen(profile_encoding), defencoding, profile_encoding);
		aim_tlvlist_add_str(&tlvlist, 0x0001, encoding);
		aim_tlvlist_add_raw(&tlvlist, 0x0002, profile_len, (const guchar *)profile);
		g_free(encoding);
	}

	/*
	 * So here's how this works:
	 *   - You are away when you have a non-zero-length type 4 TLV stored.
	 *   - You become unaway when you clear the TLV with a zero-length
	 *       type 4 TLV.
	 *   - If you do not send the type 4 TLV, your status does not change
	 *       (that is, if you were away, you'll remain away).
	 */
	if (awaymsg) {
		if (awaymsg_len) {
			encoding = g_malloc(strlen(defencoding) + strlen(awaymsg_encoding));
			snprintf(encoding, strlen(defencoding) + strlen(awaymsg_encoding), defencoding, awaymsg_encoding);
			aim_tlvlist_add_str(&tlvlist, 0x0003, encoding);
			aim_tlvlist_add_raw(&tlvlist, 0x0004, awaymsg_len, (const guchar *)awaymsg);
			g_free(encoding);
		} else
			aim_tlvlist_add_noval(&tlvlist, 0x0004);
	}

	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist));

	snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, 0x0002, 0x004, 0x0000, snacid);

	aim_tlvlist_write(&frame->data, &tlvlist);
	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #17
0
/*
 * Subtype 0x0002
 *
 * This is the initial login request packet.
 *
 * NOTE!! If you want/need to make use of the aim_sendmemblock() function,
 * then the client information you send here must exactly match the
 * executable that you're pulling the data from.
 *
 * Java AIM 1.1.19:
 *   clientstring = "AOL Instant Messenger (TM) version 1.1.19 for Java built 03/24/98, freeMem 215871 totalMem 1048567, i686, Linus, #2 SMP Sun Feb 11 03:41:17 UTC 2001 2.4.1-ac9, IBM Corporation, 1.1.8, 45.3, Tue Mar 27 12:09:17 PST 2001"
 *   clientid = 0x0001
 *   major  = 0x0001
 *   minor  = 0x0001
 *   point = (not sent)
 *   build  = 0x0013
 *   unknown= (not sent)
 *
 * AIM for Linux 1.1.112:
 *   clientstring = "AOL Instant Messenger (SM)"
 *   clientid = 0x1d09
 *   major  = 0x0001
 *   minor  = 0x0001
 *   point = 0x0001
 *   build  = 0x0070
 *   unknown= 0x0000008b
 *   serverstore = 0x01
 *
 * @param truncate_pass Truncate the password to 8 characters.  This
 *        usually happens for AOL accounts.  We are told that we
 *        should truncate it if the 0x0017/0x0007 SNAC contains
 *        a TLV of type 0x0026 with data 0x0000.
 * @param allow_multiple_logins Allow multiple logins? If TRUE, the AIM
 *        server will prompt the user when multiple logins occur. If
 *        FALSE, existing connections (on other clients) will be
 *        disconnected automatically as we connect.
 */
int
aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;
	guint8 digest[16];
	aim_snacid_t snacid;
	size_t password_len;
	guint32 distrib;

	if (!ci || !sn || !password)
		return -EINVAL;

#ifdef USE_XOR_FOR_ICQ
	/* If we're signing on an ICQ account then use the older, XOR login method */
	if (aim_snvalid_icq(sn))
		return goddamnicq2(od, conn, sn, password, ci);
#endif

	frame = flap_frame_new(od, 0x02, 1152);

	snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0002, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0002, 0x0000, snacid);

	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);

	/* Truncate ICQ and AOL passwords, if necessary */
	password_len = strlen(password);
	if (oscar_util_valid_name_icq(sn) && (password_len > MAXICQPASSLEN))
		password_len = MAXICQPASSLEN;
	else if (truncate_pass && password_len > 8)
		password_len = 8;

	aim_encode_password_md5(password, password_len, key, digest);

	distrib = oscar_get_ui_info_int(
			od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
			ci->distrib);

	aim_tlvlist_add_raw(&tlvlist, 0x0025, 16, digest);

#ifndef USE_OLD_MD5
	aim_tlvlist_add_noval(&tlvlist, 0x004c);
#endif

	if (ci->clientstring != NULL)
		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
	else {
		gchar *clientstring = oscar_get_clientstring();
		aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
		g_free(clientstring);
	}
	aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
	aim_tlvlist_add_32(&tlvlist, 0x0014, distrib);
	aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
	aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);

	/*
	 * If set, old-fashioned buddy lists will not work. You will need
	 * to use SSI.
	 */
	aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));

	aim_tlvlist_write(&frame->data, &tlvlist);

	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #18
0
/**
 * This sends a channel 2 FLAP containing a SNAC.  The SNAC family and
 * subtype are looked up in the rate info for this connection, and if
 * sending this SNAC will induce rate limiting then we delay sending
 * of the SNAC by putting it into an outgoing holding queue.
 *
 * @param data The optional bytestream that makes up the data portion
 *        of this SNAC.  For empty SNACs this should be NULL.
 * @param high_priority If TRUE, the SNAC will be queued normally if
 *        needed. If FALSE, it will be queued separately, to be sent
 *        only if all high priority SNACs have been sent.
 */
void
flap_connection_send_snac_with_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data, gboolean high_priority)
{
	FlapFrame *frame;
	guint32 length;
	gboolean enqueue = FALSE;
	struct rateclass *rateclass;

	length = data != NULL ? data->offset : 0;

	frame = flap_frame_new(od, 0x02, 10 + length);
	aim_putsnac(&frame->data, family, subtype, snacid);

	if (length > 0)
	{
		byte_stream_rewind(data);
		byte_stream_putbs(&frame->data, data, length);
	}

	if (conn->queued_timeout != 0)
		enqueue = TRUE;
	else if ((rateclass = flap_connection_get_rateclass(conn, family, subtype)) != NULL)
	{
		struct timeval now;
		guint32 new_current;

		gettimeofday(&now, NULL);
		new_current = rateclass_get_new_current(conn, rateclass, &now);

		if (rateclass->dropping_snacs || new_current <= rateclass->alert)
		{
			purple_debug_info("oscar", "Current rate for conn %p would be %u, but we alert at %u; enqueueing\n", conn, new_current, rateclass->alert);

			enqueue = TRUE;
		}
		else
		{
			rateclass->current = new_current;
			rateclass->last.tv_sec = now.tv_sec;
			rateclass->last.tv_usec = now.tv_usec;
		}
	}

	if (enqueue)
	{
		/* We've been sending too fast, so delay this message */
		QueuedSnac *queued_snac;

		queued_snac = g_new(QueuedSnac, 1);
		queued_snac->family = family;
		queued_snac->subtype = subtype;
		queued_snac->frame = frame;

		if (high_priority) {
			if (!conn->queued_snacs)
				conn->queued_snacs = g_queue_new();
			g_queue_push_tail(conn->queued_snacs, queued_snac);
		} else {
			if (!conn->queued_lowpriority_snacs)
				conn->queued_lowpriority_snacs = g_queue_new();
			g_queue_push_tail(conn->queued_lowpriority_snacs, queued_snac);
		}

		if (conn->queued_timeout == 0)
			conn->queued_timeout = purple_timeout_add(500, flap_connection_send_queued, conn);

		return;
	}

	flap_connection_send(conn, frame);
}