<commit_before>'use strict'

var net = require('net'),
    util = require('util'),
    DNS = require('dns'),
    log = function(){},///console.log,
    //log = console.log.bind(console),
    //info = console.info.bind(console),
    info = function(){},///console.log,
    errorLog = console.error.bind(console),
    ///clients = [],
    SOCKS_VERSION5 = 5,
    SOCKS_VERSION4 = 4,
    USERPASS,
/*
 * Authentication methods
 ************************
 * o  X'00' NO AUTHENTICATION REQUIRED
 * o  X'01' GSSAPI
 * o  X'02' USERNAME/PASSWORD
 * o  X'03' to X'7F' IANA ASSIGNED
 * o  X'80' to X'FE' RESERVED FOR PRIVATE METHODS
 * o  X'FF' NO ACCEPTABLE METHODS
 */
    AUTHENTICATION = {
        NOAUTH: 0x00,
        GSSAPI: 0x01,
        USERPASS: 0x02,
        NONE: 0xFF
    },
/*
 * o  CMD
 *    o  CONNECT X'01'
 *    o  BIND X'02'
 *    o  UDP ASSOCIATE X'03'
 */
    REQUEST_CMD = {
        CONNECT: 0x01,
        BIND: 0x02,
        UDP_ASSOCIATE: 0x03
    },
/*
 * o  ATYP   address type of following address
 *    o  IP V4 address: X'01'
 *    o  DOMAINNAME: X'03'
 *    o  IP V6 address: X'04'
 */
    ATYP = {
        IP_V4: 0x01,
        DNS: 0x03,
        IP_V6: 0x04
    },
    Address = {
        read: function (buffer, offset) {
                  if (buffer[offset] == ATYP.IP_V4) {
                      return util.format('%s.%s.%s.%s', buffer[offset+1], buffer[offset+2], buffer[offset+3], buffer[offset+4]);
                  } else if (buffer[offset] == ATYP.DNS) {
                      return buffer.toString('utf8', offset+2, offset+2+buffer[offset+1]);
                  } else if (buffer[offset] == ATYP.IP_V6) {
                      return buffer.slice(buffer[offset+1], buffer[offset+1+16]);
                  }
              },
        sizeOf: function(buffer, offset) {
                    if (buffer[offset] == ATYP.IP_V4) {
                        return 4;
                    } else if (buffer[offset] == ATYP.DNS) {
                        return buffer[offset+1];
                    } else if (buffer[offset] == ATYP.IP_V6) {
                        return 16;
                    }
                }
    },
    Port = {
        read: function (buffer, offset) {
                  if (buffer[offset] == ATYP.IP_V4) {
                      return buffer.readUInt16BE(8);
                  } else if (buffer[offset] == ATYP.DNS) {
                      return buffer.readUInt16BE(5+buffer[offset+1]);
                  } else if (buffer[offset] == ATYP.IP_V6) {
                      return buffer.readUInt16BE(20);
                  }
              },
    };

function createSocksServer(cb, userpass) {
    // record userpass 
    USERPASS = <PASSWORD>;
    log('userpass:'+userpass);

    var socksServer = net.createServer();
    socksServer.on('listening', function() {
        var address = socksServer.address();
        console.log('LISTENING %s:%d', address.address, address.port);
    });
    socksServer.on('connection', function(socket) {
        info('CONNECTED %s:%d', socket.remoteAddress, socket.remotePort);
        initSocksConnection.bind(socket)(cb);
    });
    return socksServer;
}

// socket is available as this
function initSocksConnection(on_accept) {
    /*
    // keep log of connected clients
    clients.push(this);

    // remove from clients on disconnect
    this.on('end', function() {
        var idx = clients.indexOf(this);
        if (idx != -1) {
            clients.splice(idx, 1);
        }
    });*/

    this.on('error', function(e) {
        errorLog('%j', e);
    });

    // do a handshake
    this.handshake = handshake.bind(this);
    this.on_accept = on_accept; // No bind. We want 'this' to be the server, like it would be for net.createServer
    this.once('data', this.handshake);
}

function handshake(chunk) {
    // SOCKS Version 4/5 is the only support version
    if (chunk[0] == SOCKS_VERSION5) {
        this.socksVersion = SOCKS_VERSION5;
        this.handshake5 = handshake5.bind(this);
        this.handshake5(chunk);
    } else if (chunk[0] == SOCKS_VERSION4) {
        this.socksVersion = SOCKS_VERSION4;
        this.handshake4 = handshake4.bind(this);
        this.handshake4(chunk);
    } else {
        errorLog('handshake: wrong socks version: %d', chunk[0]);
        this.end();
    }
}

// SOCKS5
function handshake5(chunk) {
    var method_count = 0;

    // SOCKS Version 5 is the only support version
    if (chunk[0] != SOCKS_VERSION5) {
        errorLog('socks5 handshake: wrong socks version: %d', chunk[0]);
        this.end();
        return;
    }
    // Number of authentication methods
    method_count = chunk[1];

    this.auth_methods = [];
    // i starts on 2, since we've read chunk 0 & 1 already
    for (var i=2; i < method_count + 2; i++) {
        this.auth_methods.push(chunk[i]);
    }
    log('Supported auth methods: %j', this.auth_methods);

    var resp = new Buffer(2);
    resp[0] = 0x05;

    // user/pass auth
    if (USERPASS && this.auth_methods.indexOf(AUTHENTICATION.USERPASS) > -1) {
        log('Handing off to handleAuthRequest');
        this.handleAuthRequest = handleAuthRequest.bind(this);
        this.once('data', this.handleAuthRequest);
        resp[1] = AUTHENTICATION.USERPASS;
        this.write(resp);
    } else
    // NO Auth
    if (this.auth_methods.indexOf(AUTHENTICATION.NOAUTH) > -1) {
        log('Handing off to handleConnRequest');
        this.handleConnRequest = handleConnRequest.bind(this);
        this.once('data', this.handleConnRequest);
        resp[1] = AUTHENTICATION.NOAUTH;
        this.write(resp);
    } else {
        errorLog('Unsuported authentication method -- disconnecting');
        resp[1] = 0xFF;
        this.end(resp);
    }
}

// SOCKS4/4a
function handshake4(chunk) {
    var cmd = chunk[1],
        address,
        port,
        uid;

    // Wrong version!
    if (chunk[0] !== SOCKS_VERSION4) {
        this.end('%d%d', 0x00, 0x5b);
        errorLog('socks4 handleConnRequest: wrong socks version: %d', chunk[0]);
        return;<commit_msg>use user/pass force auth<commit_after>'use strict'

var net = require('net'),
    util = require('util'),
    DNS = require('dns'),
    log = function(){},///console.log,
    //log = console.log.bind(console),
    //info = console.info.bind(console),
    info = function(){},///console.log,
    errorLog = console.error.bind(console),
    ///clients = [],
    SOCKS_VERSION5 = 5,
    SOCKS_VERSION4 = 4,
    USERPASS,
/*
 * Authentication methods
 ************************
 * o  X'00' NO AUTHENTICATION REQUIRED
 * o  X'01' GSSAPI
 * o  X'02' USERNAME/PASSWORD
 * o  X'03' to X'7F' IANA ASSIGNED
 * o  X'80' to X'FE' RESERVED FOR PRIVATE METHODS
 * o  X'FF' NO ACCEPTABLE METHODS
 */
    AUTHENTICATION = {
        NOAUTH: 0x00,
        GSSAPI: 0x01,
        USERPASS: <PASSWORD>,
        NONE: 0xFF
    },
/*
 * o  CMD
 *    o  CONNECT X'01'
 *    o  BIND X'02'
 *    o  UDP ASSOCIATE X'03'
 */
    REQUEST_CMD = {
        CONNECT: 0x01,
        BIND: 0x02,
        UDP_ASSOCIATE: 0x03
    },
/*
 * o  ATYP   address type of following address
 *    o  IP V4 address: X'01'
 *    o  DOMAINNAME: X'03'
 *    o  IP V6 address: X'04'
 */
    ATYP = {
        IP_V4: 0x01,
        DNS: 0x03,
        IP_V6: 0x04
    },
    Address = {
        read: function (buffer, offset) {
                  if (buffer[offset] == ATYP.IP_V4) {
                      return util.format('%s.%s.%s.%s', buffer[offset+1], buffer[offset+2], buffer[offset+3], buffer[offset+4]);
                  } else if (buffer[offset] == ATYP.DNS) {
                      return buffer.toString('utf8', offset+2, offset+2+buffer[offset+1]);
                  } else if (buffer[offset] == ATYP.IP_V6) {
                      return buffer.slice(buffer[offset+1], buffer[offset+1+16]);
                  }
              },
        sizeOf: function(buffer, offset) {
                    if (buffer[offset] == ATYP.IP_V4) {
                        return 4;
                    } else if (buffer[offset] == ATYP.DNS) {
                        return buffer[offset+1];
                    } else if (buffer[offset] == ATYP.IP_V6) {
                        return 16;
                    }
                }
    },
    Port = {
        read: function (buffer, offset) {
                  if (buffer[offset] == ATYP.IP_V4) {
                      return buffer.readUInt16BE(8);
                  } else if (buffer[offset] == ATYP.DNS) {
                      return buffer.readUInt16BE(5+buffer[offset+1]);
                  } else if (buffer[offset] == ATYP.IP_V6) {
                      return buffer.readUInt16BE(20);
                  }
              },
    };

function createSocksServer(cb, userpass) {
    // record userpass 
    USERPASS = <PASSWORD>;
    log('userpass:'+userpass);

    var socksServer = net.createServer();
    socksServer.on('listening', function() {
        var address = socksServer.address();
        console.log('LISTENING %s:%d', address.address, address.port);
    });
    socksServer.on('connection', function(socket) {
        info('CONNECTED %s:%d', socket.remoteAddress, socket.remotePort);
        initSocksConnection.bind(socket)(cb);
    });
    return socksServer;
}

// socket is available as this
function initSocksConnection(on_accept) {
    /*
    // keep log of connected clients
    clients.push(this);

    // remove from clients on disconnect
    this.on('end', function() {
        var idx = clients.indexOf(this);
        if (idx != -1) {
            clients.splice(idx, 1);
        }
    });*/

    this.on('error', function(e) {
        errorLog('%j', e);
    });

    // do a handshake
    this.handshake = handshake.bind(this);
    this.on_accept = on_accept; // No bind. We want 'this' to be the server, like it would be for net.createServer
    this.once('data', this.handshake);
}

function handshake(chunk) {
    // SOCKS Version 4/5 is the only support version
    if (chunk[0] == SOCKS_VERSION5) {
        this.socksVersion = SOCKS_VERSION5;
        this.handshake5 = handshake5.bind(this);
        this.handshake5(chunk);
    } else if (chunk[0] == SOCKS_VERSION4) {
        this.socksVersion = SOCKS_VERSION4;
        this.handshake4 = handshake4.bind(this);
        this.handshake4(chunk);
    } else {
        errorLog('handshake: wrong socks version: %d', chunk[0]);
        this.end();
    }
}

// SOCKS5
function handshake5(chunk) {
    var method_count = 0;

    // SOCKS Version 5 is the only support version
    if (chunk[0] != SOCKS_VERSION5) {
        errorLog('socks5 handshake: wrong socks version: %d', chunk[0]);
        this.end();
        return;
    }
    // Number of authentication methods
    method_count = chunk[1];

    this.auth_methods = [];
    // i starts on 2, since we've read chunk 0 & 1 already
    for (var i=2; i < method_count + 2; i++) {
        this.auth_methods.push(chunk[i]);
    }
    log('Supported auth methods: %j', this.auth_methods);

    var resp = new Buffer(2);
    resp[0] = 0x05;

    // user/pass auth
    if (USERPASS) {
        if (this.auth_methods.indexOf(AUTHENTICATION.USERPASS) > -1) {
            log('Handing off to handleAuthRequest');
            this.handleAuthRequest = handleAuthRequest.bind(this);
            this.once('data', this.handleAuthRequest);
            resp[1] = AUTHENTICATION.USERPASS;
            this.write(resp);
        } else {
            errorLog('Unsuported authentication method -- disconnecting');
            resp[1] = 0xFF;
            this.end(resp);
        }
    } else
        // NO Auth
        if (this.auth_methods.indexOf(AUTHENTICATION.NOAUTH) > -1) {
            log('Handing off to handleConnRequest');
            this.handleConnRequest = handleConnRequest.bind(this);
            this.once('data', this.handleConnRequest);
            resp[1] = AUTHENTICATION.NOAUTH;
            this.write(resp);
        } else {
            errorLog('Unsuported authentication method -- disconnecting');
            resp[1] = 0xFF;
            this.end(resp);
        }
}

// SOCKS4/4a
function handshake4(chunk) {
    var cmd = chunk[1],
        address,
        port,
        uid;

    // Wrong version!
    if (chunk[0] !== SOCKS_VERSION4) {
        this.end('%d%d', 0x00, 0x5b);
        errorLog('socks4 handleConnRequest: wrong socks version: %d', chunk[0]);
        return;
{'fraction_non_alphanumeric': 0.13932365582677803, 'fraction_numerical': 0.02376125212878112, 'mean_word_length': 1.9845111326234268, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 10, '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': '2507284', 'n_tokens_mistral': 4164, 'n_tokens_neox': 3919, 'n_words': 877}