Help please :)

ok so I’m trying to integrate openfire to smf 2.0 I have it configured correctly now but it seems I cant login and im getting

User Login Failed. PLAIN authentication

in the info.log file

Any ideas would be great.

What is smf and where are you trying to login? In Admin Console or with a client?

Simple Machines forum http://www.simplemachines.org/ neither client or admin console are working

When you say you have it configured, what do you mean? Did you just setup plain Openfire server with a database (embedded or other sql) and try to connect? Or have you done some integration with smf customization? Where do you get this error “User Login Failed. PLAIN authentication”? In the Admin Console? Do you login with ‘admin’ username?

Ok what i did first is setup open fire with an emeded database then i used the db integration guide for openfire and configured my openfire.xml file after doing that i started my openfire server back up and it imported the tables into my smf database for openfire then I realised I did not setup the openfire.xml correctly after viewing the logs so I had to go back and edit the ofproperty table in the database then once I sorted that out correctly my last error is User Login Failed. PLAIN authentication Ill post my openfire.xml file in a second.

<?xml version="1.0" encoding="UTF-8"?>

9090

9091

en

org.jivesoftware.database.DefaultConnectionProvider

com.mysql.jdbc.Driver

jdbc:mysql://MYSERVER:3306/DBNAME

DBUSER

DBPASS

select 1

true

true

5

25

1.0

true

com.mysql.jdbc.Driver

jdbc:mysql://MYSERVER/DB?user=DBUSER&password=DBPASS</con nectionString>

org.jivesoftware.openfire.auth.JDBCAuthProvider

org.jivesoftware.openfire.user.JDBCUserProvider

SELECT passwd FROM smf_members WHERE member_name=?

sha1

SELECT CONCAT(first_name,’ ',last_name),email_address FROM smf_members WHERE member_name=?

SELECT COUNT(*) FROM smf_members

SELECT member_name FROM smf_members

SELECT member_name FROM smf_members WHERE

member_name

CONCAT(first_name,’ ',last_name)

email_address

true

ten ten

Oh, i’m noob in the db integration field, so can’t help much here

well thanks for trying appriciate it was happy someone even responded.

could this be casued by smf using sha1 + salt ? anyhelp is mucho appriciated.

bump

Yeah, if it uses a hashed password you’ll need to use sha1 rather than plain in Openfire for the passwordType.

If you need support for salt I’m afraid you’ll need to edit JDBCAuthProvider.java. I did that to add md5+salt support; you need a line like:

JiveGlobals.migrateProperty(“jdbcAuthProvider.saltSQL”); // md5salt

near the top, which will let you set a saltSQL value (a SQL select to grab the salt) in the XML, inside the jdbcQuthProvider tag. Then you need to modify the authenticate method to have:

String userPassword;

String userSalt;

try {

userPassword = getPasswordValue(username);

userSalt = getSaltValue(username);

}

You’ll see where, the userPassword parts are already there. Farther down in the long set of conditionals you’ll need to add something like:

else if (passwordType == PasswordType.md5salt) {

password = StringUtils.hash(password + userSalt, “MD5”);

}

You may need to modify the setPassword method in a similar manner, too, if you need openfire to be able to set passwords.

Down in the passwordType enum, add:

md5salt;

Not forgetting to change the semicolon on the preceeding entry to a comma.

Except obviously make change md5 to sha1 as appropriate.

I *think *those were all the changes I made. The auth code is actually very easy to follow, so if I missed something you can probably figure it out. May also need to put the salt before the password text rather than after it when you hash it—depends on how smf does things.

EDIT:

Whoops, you also need to declare a private saltSQL var at the top:

private String saltSQL;

and actually load the value of that variable, under the comment that says “Load SQL statements”

saltSQL = JiveGlobals.getProperty(“jdbcAuthProvider.saltSQL”);

EDIT AGAIN:

I have been asked to fill in a bit of detail about the getSaltValue() method, which I overlooked when I initialliy made this post.

It’s just an ugly (chiefly in the sense that it makes no attempt at code reuse), hackish copy of getPasswordValue() with every case of “password” replaced with “salt” and the SQL value that it executes replaced with saltSQL from above. I’ll paste it below for reference, in case I’m missing anything else (I stress again, there’s almost certainly a more elegant way to do this than simply duplicating most of getPasswordValue(), but this *will *work):

private String getSaltValue(String username) throws UserNotFoundException {

    String salt = null;

    Connection con = null;

    PreparedStatement pstmt = null;

    ResultSet rs = null;

    if (username.contains("@")) {

        // Check that the specified domain matches the server's domain

        int index = username.indexOf("@");

        String domain = username.substring(index + 1);

        if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {

            username = username.substring(0, index);

        } else {

            // Unknown domain.

            throw new UserNotFoundException();

        }

    }

    try {

        con = getConnection();

        pstmt = con.prepareStatement(saltSQL);

        pstmt.setString(1, username);

        rs = pstmt.executeQuery();

        // If the query had no results, the username and password

        // did not match a user record. Therefore, throw an exception.

        if (!rs.next()) {

            throw new UserNotFoundException();

        }

        salt = rs.getString(1);

    }

    catch (SQLException e) {

        Log.error("Exception in JDBCAuthProvider", e);

        throw new UserNotFoundException();

    }

    finally {  

        DbConnectionManager.closeConnection(rs, pstmt, con);

    }

    return salt;

}

Note that this is all for use if you’re storing your salt separately from your hashed password (in a different column, say); otherwise, you’ll need more logic in both getPasswordValue() and getSaltValue(), and you may not (probably won’t, in fact) need to even have different SQL for the two.

The best way to do it in either case would be to *not *do what I did and instead get both values from getPasswordValue() or some similar method; I can’t remember whether there was a reason I did it the way I did, though I know I was in a hurry.