Beispiel #1
0
void
msn_userlist_rem_buddy(MsnUserList *userlist, const char *who)
{
	MsnUser *user = NULL;

	g_return_if_fail(userlist != NULL);
	g_return_if_fail(userlist->session != NULL);
	g_return_if_fail(who != NULL);

	user = msn_userlist_find_user(userlist, who);

	msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_FL);

	/* delete the contact from address book via soap action */
	if (user != NULL) {
		if (0 /*not ready yet*/ && userlist->session->passport_info.email_enabled) {
			MsnUserlistABData *ab = g_new0(MsnUserlistABData, 1);
			ab->session = userlist->session;
			ab->uid = g_strdup(user->uid); /* Not necessary? */
			purple_request_yes_no(userlist->session->account,
				_("Delete Buddy from Address Book?"),
				_("Do you want to delete this buddy from your address book as well?"),
				user->passport, 0, userlist->session->account, user->passport,
				NULL, ab,
				G_CALLBACK(userlist_ab_delete_cb), G_CALLBACK(userlist_ab_delete_cb));
		} else
			msn_delete_contact(userlist->session, user);
	}
}
Beispiel #2
0
static void auth_old_cb(JabberStream *js, const char *from,
                        JabberIqType type, const char *id,
                        PurpleXmlNode *packet, gpointer data)
{
	JabberIq *iq;
	PurpleXmlNode *query, *x;
	const char *pw = purple_connection_get_password(js->gc);

	if (type == JABBER_IQ_ERROR) {
		PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
		char *msg = jabber_parse_error(js, packet, &reason);
		purple_connection_error(js->gc, reason, msg);
		g_free(msg);
	} else if (type == JABBER_IQ_RESULT) {
		query = purple_xmlnode_get_child(packet, "query");
		if (js->stream_id && *js->stream_id &&
				purple_xmlnode_get_child(query, "digest")) {
			char *s, *hash;

			iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
			query = purple_xmlnode_get_child(iq->node, "query");
			x = purple_xmlnode_new_child(query, "username");
			purple_xmlnode_insert_data(x, js->user->node, -1);
			x = purple_xmlnode_new_child(query, "resource");
			purple_xmlnode_insert_data(x, js->user->resource, -1);

			x = purple_xmlnode_new_child(query, "digest");
			s = g_strdup_printf("%s%s", js->stream_id, pw);
			hash = jabber_calculate_data_hash(s, strlen(s), "sha1");
			purple_xmlnode_insert_data(x, hash, -1);
			g_free(hash);
			g_free(s);
			jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
			jabber_iq_send(iq);
		} else if ((x = purple_xmlnode_get_child(query, "crammd5"))) {
			/* For future reference, this appears to be a custom OS X extension
			 * to non-SASL authentication.
			 */
			const char *challenge;
			gchar digest[33];
			PurpleCipher *hmac;
			PurpleHash *md5;
			gssize diglen;

			/* Calculate the MHAC-MD5 digest */
			md5 = purple_md5_hash_new();
			hmac = purple_hmac_cipher_new(md5);
			challenge = purple_xmlnode_get_attrib(x, "challenge");
			purple_cipher_set_key(hmac, (guchar *)pw, strlen(pw));
			purple_cipher_append(hmac, (guchar *)challenge, strlen(challenge));
			diglen = purple_cipher_digest_to_str(hmac, digest, 33);
			g_object_unref(hmac);
			g_object_unref(md5);

			g_return_if_fail(diglen > 0);

			/* Create the response query */
			iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
			query = purple_xmlnode_get_child(iq->node, "query");

			x = purple_xmlnode_new_child(query, "username");
			purple_xmlnode_insert_data(x, js->user->node, -1);
			x = purple_xmlnode_new_child(query, "resource");
			purple_xmlnode_insert_data(x, js->user->resource, -1);

			x = purple_xmlnode_new_child(query, "crammd5");

			purple_xmlnode_insert_data(x, digest, 32);

			jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
			jabber_iq_send(iq);

		} else if(purple_xmlnode_get_child(query, "password")) {
			PurpleAccount *account = purple_connection_get_account(js->gc);
			if(!jabber_stream_is_ssl(js) && !purple_account_get_bool(account,
						"auth_plain_in_clear", FALSE)) {
				char *msg = g_strdup_printf(_("%s requires plaintext authentication over an unencrypted connection.  Allow this and continue authentication?"),
											purple_account_get_username(account));
				purple_request_yes_no(js->gc, _("Plaintext Authentication"),
						_("Plaintext Authentication"),
						msg,
						1,
						purple_request_cpar_from_account(account),
						account, allow_plaintext_auth,
						disallow_plaintext_auth);
				g_free(msg);
				return;
			}
			finish_plaintext_authentication(js);
		} else {
			purple_connection_error(js->gc,
				PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
				_("Server does not use any supported authentication method"));
			return;
		}
	}
}
Beispiel #3
0
static JabberSaslState
jabber_auth_start_cyrus(JabberStream *js, xmlnode **reply, char **error)
{
	PurpleAccount *account;
	const char *clientout = NULL;
	char *enc_out;
	unsigned coutlen = 0;
	sasl_security_properties_t secprops;
	gboolean again;
	gboolean plaintext = TRUE;

	/* Set up security properties and options */
	secprops.min_ssf = 0;
	secprops.security_flags = SASL_SEC_NOANONYMOUS;

	account = purple_connection_get_account(js->gc);

	if (!jabber_stream_is_ssl(js)) {
		secprops.max_ssf = -1;
		secprops.maxbufsize = 4096;
		plaintext = purple_account_get_bool(account, "auth_plain_in_clear", FALSE);
		if (!plaintext)
			secprops.security_flags |= SASL_SEC_NOPLAINTEXT;
	} else {
		secprops.max_ssf = 0;
		secprops.maxbufsize = 0;
		plaintext = TRUE;
	}
	secprops.property_names = 0;
	secprops.property_values = 0;

	do {
		again = FALSE;

		js->sasl_state = sasl_client_new("xmpp", js->serverFQDN, NULL, NULL, js->sasl_cb, 0, &js->sasl);
		if (js->sasl_state==SASL_OK) {
			sasl_setprop(js->sasl, SASL_SEC_PROPS, &secprops);
			purple_debug_info("sasl", "Mechs found: %s\n", js->sasl_mechs->str);
			js->sasl_state = sasl_client_start(js->sasl, js->sasl_mechs->str, NULL, &clientout, &coutlen, &js->current_mech);
		}
		switch (js->sasl_state) {
			/* Success */
			case SASL_OK:
			case SASL_CONTINUE:
				break;
			case SASL_NOMECH:
				/* No mechanisms have offered to help */

				/* Firstly, if we don't have a password try
				 * to get one
				 */

				if (!purple_account_get_password(account)) {
					purple_account_request_password(account, G_CALLBACK(auth_pass_cb), G_CALLBACK(auth_no_pass_cb), js->gc);
					return JABBER_SASL_STATE_CONTINUE;

				/* If we've got a password, but aren't sending
				 * it in plaintext, see if we can turn on
				 * plaintext auth
				 */
				/* XXX Should we just check for PLAIN/LOGIN being offered mechanisms? */
				} else if (!plaintext) {
					char *msg = g_strdup_printf(_("%s may require plaintext authentication over an unencrypted connection.  Allow this and continue authentication?"),
							purple_account_get_username(account));
					purple_request_yes_no(js->gc, _("Plaintext Authentication"),
							_("Plaintext Authentication"),
							msg,
							1, account, NULL, NULL, account,
							allow_cyrus_plaintext_auth,
							disallow_plaintext_auth);
					g_free(msg);
					return JABBER_SASL_STATE_CONTINUE;

				} else
					js->auth_fail_count++;

				if (js->auth_fail_count == 1 &&
					(js->sasl_mechs->str && g_str_equal(js->sasl_mechs->str, "GSSAPI"))) {
					/* If we tried GSSAPI first, it failed, and it was the only method we had to try, try jabber:iq:auth
					 * for compatibility with iChat 10.5 Server and other jabberd based servers.
					 *
					 * iChat Server 10.5 and certain other corporate servers offer SASL GSSAPI by default, which is often
					 * not configured on the client side, and expects a fallback to jabber:iq:auth when it (predictably) fails.
					 *
					 * Note: xep-0078 points out that using jabber:iq:auth after a sasl failure is wrong. However,
					 * I believe this refers to actual authentication failure, not a simple lack of concordant mechanisms.
					 * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers
					 * which would connect without issue otherwise. -evands
					 */
					js->auth_mech = NULL;
					jabber_auth_start_old(js);
					return JABBER_SASL_STATE_CONTINUE;
				}

				break;

				/* Fatal errors. Give up and go home */
			case SASL_BADPARAM:
			case SASL_NOMEM:
				*error = g_strdup(_("SASL authentication failed"));
				break;

				/* For everything else, fail the mechanism and try again */
			default:
				purple_debug_info("sasl", "sasl_state is %d, failing the mech and trying again\n", js->sasl_state);

				js->auth_fail_count++;

				/*
				 * DAA: is this right?
				 * The manpage says that "mech" will contain the chosen mechanism on success.
				 * Presumably, if we get here that isn't the case and we shouldn't try again?
				 * I suspect that this never happens.
				 */
				/*
				 * SXW: Yes, this is right. What this handles is the situation where a
				 * mechanism, say GSSAPI, is tried. If that mechanism fails, it may be
				 * due to mechanism specific issues, so we want to try one of the other
				 * supported mechanisms. This code handles that case
				 */
				if (js->current_mech && *js->current_mech) {
					char *pos;
					if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) {
						g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str, strlen(js->current_mech));
					}
					/* Remove space which separated this mech from the next */
					if ((js->sasl_mechs->str)[0] == ' ') {
						g_string_erase(js->sasl_mechs, 0, 1);
					}
					again = TRUE;
				}

				sasl_dispose(&js->sasl);
		}
	} while (again);

	if (js->sasl_state == SASL_CONTINUE || js->sasl_state == SASL_OK) {
		xmlnode *auth = xmlnode_new("auth");
		xmlnode_set_namespace(auth, NS_XMPP_SASL);
		xmlnode_set_attrib(auth, "mechanism", js->current_mech);

		xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
		xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");

		if (clientout) {
			if (coutlen == 0) {
				xmlnode_insert_data(auth, "=", -1);
			} else {
				enc_out = purple_base64_encode((unsigned char*)clientout, coutlen);
				xmlnode_insert_data(auth, enc_out, -1);
				g_free(enc_out);
			}
		}

		*reply = auth;
		return JABBER_SASL_STATE_CONTINUE;
	} else {
		return JABBER_SASL_STATE_FAIL;
	}
}
Beispiel #4
0
/**
 * This is where we do a bit more than merely prompt the user.
 * Now we have some real data to tell us the state of their requested username
 * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\
 */
static void msim_username_is_available_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
{
    MsimMessage *msg;
    gchar *username;
    MsimMessage *body;
    gint userid;

    purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");

    msg = (MsimMessage *)data;
    g_return_if_fail(MSIM_SESSION_VALID(session));
    g_return_if_fail(msg != NULL);

    username = msim_msg_get_string(msg, "user");
    body = msim_msg_get_dictionary(userinfo, "body");

    if (!body) {
        purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username);
        purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
                                       "An error occurred while trying to set the username.\n"
                                       "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
                                       "fuseaction=profile.username to set your username.");
        return;
    }

    userid = msim_msg_get_integer(body, "UserID");

    purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username, userid);
    msim_msg_free(body);
    msim_msg_free(msg);

    /* The response for a free username will ONLY have the UserName in it..
     * thus making UserID return 0 when we msg_get_integer it */
    if (userid == 0) {
        /* This username is currently unused */
        purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n");
        msim_username_to_set = g_strdup(username);
        g_free(username);
        purple_request_yes_no(session->gc,
                              _("MySpaceIM - Username Available"),
                              _("This username is available. Would you like to set it?"),
                              _("ONCE SET, THIS CANNOT BE CHANGED!"),
                              0,
                              session->account,
                              NULL,
                              NULL,
                              session->gc,
                              G_CALLBACK(msim_set_username_confirmed_cb),
                              G_CALLBACK(msim_do_not_set_username_cb));
    } else {
        /* Looks like its in use or we have an invalid response */
        purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n");
        purple_request_input(session->gc, _("MySpaceIM - Please Set a Username"),
                             _("This username is unavailable."),
                             _("Please try another username:"******"", FALSE, FALSE, NULL,
                             _("OK"), G_CALLBACK(msim_check_username_availability_cb),
                             _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
                             session->account,
                             NULL,
                             NULL,
                             session->gc);
    }
}