<commit_before>// Auth against a flat file

var crypto = require('crypto');
var AUTH_COMMAND = 'AUTH';
var AUTH_METHOD_CRAM_MD5 = 'CRAM-MD5';
var AUTH_METHOD_LOGIN = 'LOGIN';
var LOGIN_STRING1 = 'VXNlcm5hbWU6'; //UserLogin: base64 coded
var LOGIN_STRING2 = 'UGFzc3dvcmQ6'; //Password: <PASSWORD>

exports.hook_capabilities = function (next, connection) {
    var config = this.config.get('auth_flat_file.ini', 'ini');
    var methods = (config.core && config.core.methods ) ? config.core.methods.split(',') : null;
    if(methods && methods.length > 0) {
        connection.capabilities.push('AUTH ' + methods.join(' '));
        connection.notes.allowed_auth_methods = methods;
    }
    next();
};

exports.hook_unrecognized_command = function (next, connection, params) {
    if(params[0] === AUTH_COMMAND && params[1]) {
        return this.select_auth_method(next, connection, params[1]);
    }
    else if (connection.notes.auth_method === AUTH_METHOD_CRAM_MD5 && connection.notes.auth_flat_file_ticket) {
        return this.auth_cram_md5 (next, connection, params);
    }
    else if (connection.notes.auth_method === AUTH_METHOD_LOGIN) {
        return this.auth_login(next, connection, params);
    }
    return next();
};

exports.check_user = function (next, connection, credentials, method) {
    if (!(credentials[0] && credentials[1])) {
        connection.respond(504, "Invalid AUTH string");
        connection.reset_transaction();
        return next(OK);
    }
    
    var config = this.config.get('auth_flat_file.ini', 'ini');
    if (!config.users[credentials[0]]) {
        connection.respond(535, "Authentication failed for " + credentials[0]);
        connection.reset_transaction();
        return next(OK);
    }
    
    var clear_pw = config.users[credentials[0]];
    var hmac_pw = clear_pw;

    if(method === AUTH_METHOD_CRAM_MD5) {
        var hmac = crypto.createHmac('md5', clear_pw);
        hmac.update(connection.notes.auth_flat_file_ticket);
        hmac_pw = hmac.digest('hex');
    }
    
    this.loginfo("comparing " + hmac_pw + ' to ' + credentials[1]);
    
    if (hmac_pw === credentials[1]) {
        connection.relaying = 1;
        connection.respond(235, "Authentication successful");
        connection.authheader = "(authenticated bits=0)\n";
    }
    else {
        connection.respond(535, "Authentication failed");
        connection.reset_transaction();
    }
    return next(OK);
};

exports.select_auth_method = function(next, connection, method) {
    if(connection.notes.allowed_auth_methods.indexOf(method) !== -1) {
        connection.notes.auth_method = method;
        if(method === AUTH_METHOD_LOGIN) {
            return this.auth_login(next, connection);
        }
        else if( method === AUTH_METHOD_CRAM_MD5) {
            return this.auth_cram_md5(next, connection);
        }
    }
    return next();
};
<commit_msg>Made easier to subclass<commit_after>// Auth against a flat file

var crypto = require('crypto');
var AUTH_COMMAND = 'AUTH';
var AUTH_METHOD_CRAM_MD5 = 'CRAM-MD5';
var AUTH_METHOD_LOGIN = 'LOGIN';
var LOGIN_STRING1 = 'VXNlcm5hbWU6'; //UserLogin: base64 coded
var LOGIN_STRING2 = 'UGFzc3dvcmQ6'; //Password: base64 coded

exports.hook_capabilities = function (next, connection) {
    var config = this.config.get('auth_flat_file.ini', 'ini');
    var methods = (config.core && config.core.methods ) ? config.core.methods.split(',') : null;
    if(methods && methods.length > 0) {
        connection.capabilities.push('AUTH ' + methods.join(' '));
        connection.notes.allowed_auth_methods = methods;
    }
    next();
};

exports.hook_unrecognized_command = function (next, connection, params) {
    if(params[0] === AUTH_COMMAND && params[1]) {
        return this.select_auth_method(next, connection, params[1]);
    }
    else if (connection.notes.authenticating &&
             connection.notes.auth_method === AUTH_METHOD_CRAM_MD5 &&
             connection.notes.auth_flat_file_ticket)
    {
        return this.auth_cram_md5(next, connection, params);
    }
    else if (connection.notes.authenticating &&
             connection.notes.auth_method === AUTH_METHOD_LOGIN)
    {
        return this.auth_login(next, connection, params);
    }
    return next();
};

exports.get_plain_passwd = function (user, cb) {
    var config = this.config.get('auth_flat_file.ini');
    if (config.users[user]) {
        return cb(config.users[user]);
    }
    return cb();
}

exports.check_plain_passwd = function (user, passwd, cb) {
    this.get_plain_passwd(user, function (plain_pw) {
        if (plain_pw === null) {
            return cb(false);
        }
        if (plain_pw === passwd) {
            return cb(true);
        }
        return cb(false);
    })
}

exports.check_cram_md5_passwd = function (ticket, user, passwd, cb) {
    this.get_plain_passwd(user, function (plain_pw) {
        if (plain_pw === null) {
            return cb(false);
        }
        
        var hmac = crypto.createHmac('md5', plain_pw);
        hmac.update(ticket);
        var hmac_pw = hmac.digest('hex');

        if (hmac_pw === passwd) {
            return cb(true);
        }
        return cb(false);
    })
}

exports.check_user = function (next, connection, credentials, method) {
    connection.notes.authenticating = false;
    if (!(credentials[0] && credentials[1])) {
        connection.respond(504, "Invalid AUTH string");
        connection.reset_transaction();
        return next(OK);
    }

    var passwd_ok = function (valid) {
        if (valid) {
            connection.relaying = 1;
            connection.respond(235, "Authentication successful");
            connection.authheader = "(authenticated bits=0)\n";
        }
        else {
            connection.respond(535, "Authentication failed");
            connection.reset_transaction();
        }
        return next(OK);
    }

    if (method === AUTH_METHOD_LOGIN) {
        this.check_plain_passwd(credentials[0], credentials[1], passwd_ok);
    }
    else if (method === AUTH_METHOD_CRAM_MD5) {
        this.check_cram_md5_passwd(connection.notes.auth_flat_file_ticket, credentials[0], credentials[1], passwd_ok);
    }
};

exports.select_auth_method = function(next, connection, method) {
    if(connection.notes.allowed_auth_methods.indexOf(method) !== -1) {
        connection.notes.authenticating = true;
        connection.notes.auth_method = method;
        if(method === AUTH_METHOD_LOGIN) {
            return this.auth_login(next, connection);
        }
        else if( method === AUTH_METHOD_CRAM_MD5) {
            return this.auth_cram_md5(next, connection);
        }
    }
    return next();
};

{'fraction_non_alphanumeric': 0.13261487801227362, 'fraction_numerical': 0.012572968118545127, 'mean_word_length': 2.9421828908554573, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '484510', 'n_tokens_mistral': 2111, 'n_tokens_neox': 2062, 'n_words': 399}