helper.runInTransaction(agent, function() {
   dns.resolveTxt('example.com', function(err, data) {
     t.notOk(err)
     t.ok(Array.isArray(data))
     verifySegments(t, agent, 'dns.resolveTxt')
   })
 })
示例#2
0
文件: dns.js 项目: nocenter/beaker
export function resolveDatDNS (name, cb) {
  // is it a hash?
  if (DAT_HASH_REGEX.test(name)) {
    return cb(null, name)
  }

  // do a dns lookup
  debug('DNS TXT lookup for name:', name)
  dns.resolveTxt(name, (err, records) => {
    debug('DNS TXT results for', name, err || records)
    if (err) return cb(err)

    // scan the txt records for a dat URI
    for (var i=0; i < records.length; i++) {
      if (records[i][0].indexOf('dat://') === 0) {
        var urlp = url.parse(records[i][0])
        if (DAT_HASH_REGEX.test(urlp.host)) {
          debug('DNS resolved', name, 'to', urlp.host)
          return cb(null, urlp.host)
        }
        debug('DNS TXT record failed:', records[i], 'Must be a dat://{hash} url')
      }
    }

    cb({ code: 'ENOTFOUND' })
  })
}
示例#3
0
function discoverRemote(req, remoteDomain, callback) {
  dns.resolveTxt(API_SRV_PREFIX + remoteDomain, function (err, addresses) {
    if (err) {
      callback(null);
      return;
    }
    
    if (addresses.length == 0) {
      callback(null);
      return;
    }
    
    //TODO Iterate over all addresses
    var firstAddress = addresses[0];
    var txtRecord = splitTXTRecord(firstAddress);
    if (!txtRecord) {
      callback(null);
      return;
    }
    
    var host = txtRecord['host'];
    var port = txtRecord['port'];
    
    ping(host, port, function() {
      callback(null);
    }, function() {
      var protocol = txtRecord['protocol'];
      var path = txtRecord['path'];
      path = !path || path == '/' ? '' : path; 
      callback(protocol + '://' + host + ':' + port + path + MEDIA_PROXY_ENDPOINT);
    });
  });
}
示例#4
0
  /*
    Locates a Eureka host using DNS lookups. The DNS records are looked up by a naming
    convention and TXT records must be created according to the Eureka Wiki here:
    https://github.com/Netflix/eureka/wiki/Configuring-Eureka-in-AWS-Cloud

    Naming convention: txt.<REGION>.<HOST>
   */
  locateEurekaHostUsingDns(callback = noop) {
    const currentServiceUrl = this.currentServiceUrl;
    const { host } = url.parse(currentServiceUrl);
    const { ec2Region } = this.config.eureka;
    if (!ec2Region) {
      return callback(new Error(
        'EC2 region was undefined. ' +
        'config.eureka.ec2Region must be set to resolve Eureka using DNS records.'
      ));
    }
    dns.resolveTxt(`txt.${ec2Region}.${host}`, (err, addresses) => {
      if (err) {
        return callback(new Error(
          `Error resolving eureka server list for region [${ec2Region}] using DNS: [${err}]`
        ));
      }
      const random = Math.floor(Math.random() * addresses[0].length);
      dns.resolveTxt(`txt.${addresses[0][random]}`, (resolveErr, results) => {
        if (resolveErr) {
          this.logger.warn('Failed to locate DNS record for Eureka', resolveErr);
          callback(new Error(`Error locating eureka server using DNS: [${resolveErr}]`));
        }
        this.logger.debug('Found Eureka Server @ ', results);
        callback(null, [].concat(...results).shift());
      });
    });
  }
示例#5
0
server.get('/check/:ip/:endpoint', function(req, res) {
    var fs = require('fs');
    var file = 'public/lists.json';
    var lists = require('./public/lists');
    var list_in_config = false;

    for (var i = 0; i < lists.length; i++) { 
        if (lists[i].endpoint == req.params.endpoint) {
          list_in_config = true;
          break;
        }
    }

    if (!list_in_config) {
      res.json({ 'error': 'Unknown List'});
    }

    dns.resolveTxt(rbl_hostname(req.params.ip, req.params.endpoint), function (err, addresses) {

        if (err) {
          if (err.code === 'ENOTFOUND') {
            // Not listed.
            res.json({ listed: false });
            return;
          } else {
            res.json({ 'error': 'Unable to look up address' });
          }
        }
        res.json({ 'listed': addresses });
    });
});
示例#6
0
module.exports = function(addr) {
    if (typeof addr !== 'string')
        return Q(addr);
    if (! addr.match(/^dnstxt/i))
        return Q(addr);

    debug ('processing', addr);
    addr = addr.replace(/^dnstxt:\/\//, '')
    var end = addr.split('/').splice(1).join('/');
    addr = addr.replace(/\/.*/, '');

    var d = Q.defer();
    dns.resolveTxt(addr, function (err, addresses) {
        if (err) {
            debug ('rejecting error', err);
            return d.reject(err);
        }
        if (!addresses || !addresses.length
            || !addresses[0] || !addresses[0].length) {
            debug('rejecting, addresses is malformed', addresses)

            return d.reject (addresses)
        }

        var ret = addresses[0][0]
        if (end)
            ret += '/' + end;

        debug ('resolving', ret);
        return d.resolve(ret);
    });

    return d.promise;
}
示例#7
0
 prepareDns(DnsServer.testResolveTXT(txt), function() {
   dns.resolveTxt("vertx.io", function(err, records) {
     vassert.assertTrue("Unexpected number of response records: " + records.length, 
       1 === records.length);
     vassert.assertTrue("Unexpected result: " + records[0], txt === records[0]);
     vassert.testComplete();
   });
 });
示例#8
0
  dns.resolveSrv(`_mongodb._tcp.${lookupAddress}`, (err, addresses) => {
    if (err) return callback(err);

    if (addresses.length === 0) {
      return callback(new MongoParseError('No addresses found at host'));
    }

    for (let i = 0; i < addresses.length; i++) {
      if (!matchesParentDomain(addresses[i].name, result.hostname, result.domainLength)) {
        return callback(
          new MongoParseError('Server record does not share hostname with parent URI')
        );
      }
    }

    // Convert the original URL to a non-SRV URL.
    result.protocol = 'mongodb';
    result.host = addresses.map(address => `${address.name}:${address.port}`).join(',');

    // Default to SSL true if it's not specified.
    if (
      !('ssl' in options) &&
      (!result.search || !('ssl' in result.query) || result.query.ssl === null)
    ) {
      result.query.ssl = true;
    }

    // Resolve TXT record and add options from there if they exist.
    dns.resolveTxt(lookupAddress, (err, record) => {
      if (err) {
        if (err.code !== 'ENODATA') {
          return callback(err);
        }
        record = null;
      }

      if (record) {
        if (record.length > 1) {
          return callback(new MongoParseError('Multiple text records not allowed'));
        }

        record = qs.parse(record[0].join(''));
        if (Object.keys(record).some(key => key !== 'authSource' && key !== 'replicaSet')) {
          return callback(
            new MongoParseError('Text record must only set `authSource` or `replicaSet`')
          );
        }

        Object.assign(result.query, record);
      }

      // Set completed options back into the URL object.
      result.search = qs.stringify(result.query);

      const finalString = URL.format(result);
      parseConnectionString(finalString, options, callback);
    });
  });
示例#9
0
TEST(function test_resolveTxt(done) {
  var req = dns.resolveTxt('google.com', function(err, records) {
    if (err) throw err;
    assert.equal(records.length, 1);
    assert.equal(records[0].indexOf('v=spf1'), 0);
    done();
  });

  checkWrap(req);
});
示例#10
0
TEST(function test_resolveTxt(done) {
  const req = dns.resolveTxt('google.com', function(err, records) {
    assert.ifError(err);
    assert.strictEqual(records.length, 1);
    assert.ok(util.isArray(records[0]));
    assert.strictEqual(records[0][0].indexOf('v=spf1'), 0);
    done();
  });

  checkWrap(req);
});
示例#11
0
TEST(function test_resolveTxt_failure(done) {
  var req = dns.resolveTxt('something.invalid', function(err, result) {
    assert.ok(err instanceof Error);
    assert.strictEqual(err.errno, 'ENOTFOUND');

    assert.strictEqual(result, undefined);

    done();
  });

  checkWrap(req);
});
示例#12
0
 scriptLoader.on('command', ['wiki', 'wikipedia'], function (event) {
     if (event.params.length > 0) {
         dns.resolveTxt(event.params.join('_') + '.wp.dg.cx', function (error, txt) {
             if (!error) {
                 event.channel.reply(event.user, txt[0]);
             } else {
                 event.channel.reply(event.user, 'There were no results matching the query.');
                 scriptLoader.debug('[wiki] %s', error);
             }
         });
     } else {
         event.user.notice('Use: !wikipedia <term>');
     }
 });
示例#13
0
    namespace.run(function () {
      namespace.set('test', 2020);
      t.equal(namespace.get('test'), 2020, "state has been mutated");

      dns.resolveTxt('newrelic.com', function (err, addresses) {
        t.notOk(err, "lookup succeeded");
        t.ok(addresses.length > 0, "some results were found");

        t.equal(namespace.get('test'), 2020,
                "mutated state has persisted to dns.resolveTxt's callback");

        t.end();
      });
    });
示例#14
0
 dns.resolveTxt(`txt.${ec2Region}.${host}`, (err, addresses) => {
   if (err) {
     return callback(new Error(
       `Error resolving eureka server list for region [${ec2Region}] using DNS: [${err}]`
     ));
   }
   const random = Math.floor(Math.random() * addresses[0].length);
   dns.resolveTxt(`txt.${addresses[0][random]}`, (resolveErr, results) => {
     if (resolveErr) {
       this.logger.warn('Failed to locate DNS record for Eureka', resolveErr);
       callback(new Error(`Error locating eureka server using DNS: [${resolveErr}]`));
     }
     this.logger.debug('Found Eureka Server @ ', results);
     callback(null, [].concat(...results).shift());
   });
 });
示例#15
0
TEST(function test_resolveTxt_failure(done) {
  dnsPromises.resolveTxt(addresses.INVALID_HOST)
    .then(common.mustNotCall())
    .catch(common.expectsError({ errno: 'ENOTFOUND' }));

  const req = dns.resolveTxt(addresses.INVALID_HOST, function(err, result) {
    assert.ok(err instanceof Error);
    assert.strictEqual(err.errno, 'ENOTFOUND');

    assert.strictEqual(result, undefined);

    done();
  });

  checkWrap(req);
});
示例#16
0
TEST(async function test_resolveTxt(done) {
  function validateResult(result) {
    assert.ok(Array.isArray(result[0]));
    assert.strictEqual(result.length, 1);
    assert(result[0][0].startsWith('v=spf1'));
  }

  validateResult(await dnsPromises.resolveTxt(addresses.TXT_HOST));

  const req = dns.resolveTxt(addresses.TXT_HOST, function(err, records) {
    assert.ifError(err);
    validateResult(records);
    done();
  });

  checkWrap(req);
});
示例#17
0
module.exports = (domain, opts, callback) => {
  dns.resolveTxt(domain, (err, records) => {
    if (err) {
      return callback(err, null)
    }

    // TODO: implement recursive option

    for (const record of records) {
      if (record[0].startsWith('dnslink=')) {
        return callback(null, record[0].substr(8, record[0].length - 1))
      }
    }

    callback(new Error('domain does not have a txt dnslink entry'))
  })
}
示例#18
0
exports.get_dns_results = function (zone, ip, done) {
    var plugin = this;
    var query = ip.split('.').reverse().join('.') + '.' + zone;
    // plugin.logdebug(plugin, "query: " + query);

    var timer = setTimeout(function () {
        return done(new Error('timeout'), zone, null);
    }, (plugin.cfg.main.timeout || 4) * 1000);

    dns.resolveTxt(query, function (err, addrs) {
        clearTimeout(timer);
        if (err) {
            plugin.logerror(plugin, "error: " + err + ' running: '+query);
            return done(err, zone);
        }

        if (!addrs || !addrs[0]) {
            return done(new Error('no results for ' + query), zone);
        }

        var first = addrs[0];
        if (Array.isArray(first)) {
            // node 0.11 returns TXT records as an array of labels
            first = addrs[0].join('');  // concatenate the labels
        }

        plugin.logdebug(plugin, zone + " answers: " + addrs);
        var result;

        if (zone === 'origin.asn.cymru.com') {
            result = plugin.parse_cymru(first);
        }
        else if (zone === 'asn.routeviews.org') {
            result = plugin.parse_routeviews(addrs);
        }
        else if (zone === 'origin.asn.spameatingmonkey.net') {
            result = plugin.parse_monkey(first);
        }
        else {
            plugin.logerror(plugin, "unrecognized ASN provider: " + zone);
        }

        return done(null, zone, result);
    });
};
示例#19
0
      specify( '20161025 1e100.net', function( done ) {

        var selector = '20161025'
        var domain = '1e100.net'
        var dkimDomain = selector + '._domainkey.' + domain
        var keyData = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuoesoDYpDnaUGZFoCElFKAkhbPoqBCfkmz3LqSfdAkye2DpoxlBx+qybWdYXe55mCWPeVUIk10Z/H9uriY4enbpmUM0t3mhgyrxuKwJtFg0YgQ0WGpMKecYjhYkt+pcHy7J11BrYh6lHx7mXf5SxuoOF1B6rG1MTzgBKDQqHsBvfz9xZSsNA5HW41EHu4dxRz/QLvzJYegLac8p6oU7l8O/yaVAse0DpgkVu+adfDV+flDq+nohyt2CJ+XHHdbIpE3cb01wp4Znz05zcYaTJd6WIQuis9sjGpS8sDEhY2gZkJVE2jvk1/mObTsyJuVuORapZnXO740owXe8Pvxq7uQIDAQAB'

        dns.resolveTxt( dkimDomain, ( error, records ) => {
          if( error ) return done( error )
          records = records.map(( record ) => record.join( '' ) )
          console.log( records )
          records = records.map( DKIMKey.parse )
          console.log( records )
          assert.strictEqual( records[0].key.toString( 'base64' ), keyData )
          assert.strictEqual( records[0].type, 'rsa' )
          done()
        })

      })
/**
 * Verifies if selected settings are valid (private key matches the publick key listed in DNS)
 *
 * @param {Function} callback Callback function with the result
 */
function verifyKeys(options, callback) {
    var domain = punycode.toASCII([options.keySelector, '_domainkey', options.domainName].join('.'));
    dns.resolveTxt(domain, function(err, result) {
        if (err) {
            return callback(err);
        }

        if (!result || !result.length) {
            return callback(new Error('Selector not found (%s)', domain));
        }

        var data = {};
        [].concat(result[0] || []).join('').split(/;/).forEach(function(row) {
            var key, val;
            row = row.split('=');
            key = (row.shift() || '').toString().trim();
            val = (row.join('=') || '').toString().trim();
            data[key] = val;
        });

        if (!data.p) {
            return callback(new Error('DNS TXT record does not seem to be a DKIM value', domain));
        }

        var pubKey = '-----BEGIN PUBLIC KEY-----\n' + data.p.replace(/.{78}/g, '$&\n') + '\n-----END PUBLIC KEY-----';

        try {
            var sign = crypto.createSign('RSA-SHA256');
            sign.update('nodemailer');
            var signature = sign.sign(options.privateKey, 'hex');
            var verifier = crypto.createVerify('RSA-SHA256');
            verifier.update('nodemailer');

            if (verifier.verify(pubKey, signature, 'hex')) {
                return callback(null, true);
            } else {
                return callback(new Error('Verification failed, keys do not match'));
            }
        } catch (E) {
            callback(E);
        }
    });
}
示例#21
0
      specify( '20171004 dialogflow.com', function( done ) {

        var selector = '20171004'
        var domain = 'dialogflow.com'
        var dkimDomain = selector + '._domainkey.' + domain
        var keyData = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzI5iaG0vxFScisTDRt9c/id87RBk8+3XK7WTvX8JhTuMwQGkrEsAVSRwj+RACDikGgNoWKO1ozBtGSSXRbwbkhytOWp2QJ75lAi1U/cNHFGZ5a3Vf7OjCB7/QiO4M0euPXZwfb5ya1OhxSCAReYHXkRzmkSjh5jRtPdhdXMJPkCw7Kcg3gQRkThPJ5FvAOYMlHUox4pXbp6H6VQnMvk8qahEhbxc+mv8zqgpBtwqndVE6BREOgku/GAXf8wcdm4Ns4I7XixTCmC40C9aePGL04cQiFt78hdsEsyWFe3uz0Rh5MTh1Z2m5Dk9FVHb384w1462ue61VVNNzl+LXASXiwIDAQAB'

        dns.resolveTxt( dkimDomain, ( error, records ) => {
          if( error ) return done( error )
          records = records.map(( record ) => record.join( '' ) )
          console.log( records )
          records = records.map( DKIMKey.parse )
          console.log( records )
          assert.strictEqual( records[0].key.toString( 'base64' ), keyData )
          assert.strictEqual( records[0].version, 'DKIM1' )
          assert.strictEqual( records[0].type, 'rsa' )
          done()
        })

      })
示例#22
0
 dns.resolveMx(params[0], function (err, addresses) {
     message += '\nMX: ';
     message += err || JSON.stringify(addresses, null, 2).replace(/[\r\n]/g, '');
     dns.resolveTxt(params[0], function (err, addresses) {
         message += '\nTxt: ';
         message += err || JSON.stringify(addresses, null, 2).replace(/[\r\n]/g, '');
         dns.resolveSrv(params[0], function (err, addresses) {
             message += '\nSrv: ';
             message += err || JSON.stringify(addresses, null, 2).replace(/[\r\n]/g, '');
             dns.resolveNs(params[0], function (err, addresses) {
                 message += '\nNS: ';
                 message += err || JSON.stringify(addresses, null, 2).replace(/[\r\n]/g, '');
                 dns.resolveCname(params[0], function (err, addresses) {
                     message += '\nCName: ';
                     message += err || JSON.stringify(addresses, null, 2).replace(/[\r\n]/g, '');
                     stanza.c('body').t(message);
                     client.send(stanza);
                 });
             });
         });
     });
 });
示例#23
0
 return new Promise((resolve, reject) => {
   dns.resolveTxt(`${owner}.${domain}`, (err, records) => {
     if (err && err.code === 'ENOTFOUND') {
       resolve([])
     } else if (err) {
       reject(err)
     } else {
       resolve(
         records
           .map(record => {
             const [attribute, value] = record[0].split('=')
             return {
               attribute,
               value,
               method: attribute.split('-').pop(),
               uri: value,
             }
           })
           .sort(compareAltConnections)
       )
     }
   })
 })
示例#24
0
exports.get_dns_results = function (zone, ip, done) {
  const plugin = this;
  const query = ip.split('.').reverse().join('.') + '.' + zone;
  // plugin.logdebug(plugin, "query: " + query);

  // only run the callback once
  let calledDone = false;
  function doneOnce () {
    if (calledDone) return;
    calledDone = true;
    return done.apply(plugin, arguments);
  }

  const timer = setTimeout(() => {
    return doneOnce(new Error(zone + ' timeout'), zone, null);
  }, (plugin.cfg.main.timeout || 4) * 1000);

  dns.resolveTxt(query, function (err, addrs) {
    clearTimeout(timer);
    if (calledDone) return;
    if (err) {
      plugin.logerror(plugin, "error: " + err + ' running: ' + query);
      return doneOnce(err, zone);
    }

    if (!addrs || !addrs[0]) {
      return doneOnce(new Error('no results for ' + query), zone);
    }

    const first = addrs[0];

    plugin.logdebug(plugin, zone + " answers: " + first);
    const result = plugin.get_result(zone, first);

    return doneOnce(null, zone, result);
  })
}
示例#25
0
 this.generate(addr.name, function(err, info) {
   if(!err) {
     var full = format(info.record, addr.domain);
     dns.resolveTxt(full, function(err, txts) {
       if(!err) {
         var result = txts[0][0],
             id = result.match(/(^|;)id=([a-zA-Z0-9]+)/)[2];
         toxdns.decrypt(id, info.id, function(err, addr) {
           if(!err) {
             if(callback) {
               callback(undefined, addr);
             }
           } else if(callback) {
             callback(err);
           }
         });
       } else if(callback) {
         callback(err);
       }
     });
   } else if(callback) {
     callback(err);
   }
 });
  dns.resolveSrv(srvAddress, (err, addresses) => {
    if (err) return callback(err);

    if (addresses.length === 0) {
      return callback(new MongoParseError('No addresses found at host'));
    }

    for (let i = 0; i < addresses.length; i++) {
      if (!matchesParentDomain(addresses[i].name, result.hostname, result.domainLength)) {
        return callback(
          new MongoParseError('Server record does not share hostname with parent URI')
        );
      }
    }

    let base = result.auth ? `mongodb://${result.auth}@` : `mongodb://`;
    let connectionStrings = addresses.map(
      (address, i) =>
        i === 0 ? `${base}${address.name}:${address.port}` : `${address.name}:${address.port}`
    );

    let connectionString = `${connectionStrings.join(',')}/`;
    let connectionStringOptions = [];

    // Add the default database if needed
    if (result.path) {
      let defaultDb = result.path.slice(1);
      if (defaultDb.indexOf('?') !== -1) {
        defaultDb = defaultDb.slice(0, defaultDb.indexOf('?'));
      }

      connectionString += defaultDb;
    }

    // Default to SSL true
    if (!options.ssl && (!result.search || result.query['ssl'] == null)) {
      connectionStringOptions.push('ssl=true');
    }

    // Keep original uri options
    if (result.search) {
      connectionStringOptions.push(result.search.replace('?', ''));
    }

    dns.resolveTxt(result.host, (err, record) => {
      if (err) {
        if (err.code !== 'ENODATA') {
          return callback(err);
        }
        record = null;
      }

      if (record) {
        if (record.length > 1) {
          return callback(new MongoParseError('Multiple text records not allowed'));
        }

        record = record[0];
        record = record.length > 1 ? record.join('') : record[0];
        if (record.indexOf('authSource') === -1 && record.indexOf('replicaSet') === -1) {
          return callback(
            new MongoParseError('Text record must only set `authSource` or `replicaSet`')
          );
        }

        connectionStringOptions.push(record);
      }

      // Add any options to the connection string
      if (connectionStringOptions.length) {
        connectionString += `?${connectionStringOptions.join('&')}`;
      }

      parseConnectionString(connectionString, callback);
    });
  });
示例#27
0
    client.addListener('message', function(from, to, message) {
        var params = message.split(' ').slice(1).join(' ');

        if (to == client.nick) { // Handling private messages
            to = from;
        }

        /**********************************************************[ !help ]**/

        if (message.match(/^!help/)) {
            var help = "RobotIRC 0.1.2 supports the following commands:\n" +
                "!alexa     => Get Alexa traffic rank for a domain or URL\n" +
                "!date      => Display server local time\n" +
                "!expand    => Expand a shortened URL\n" +
                "!headers   => Display HTTP headers for queried URL\n" +
                "!resolve   => Get A records (IPv4) and AAAA records (IPv6) for queried domain\n" +
                "!reverse   => Get reverse (PTR) records from IPv4 or IPv6 addresses\n" +
                "!wikipedia => Query Wikipedia for an article summary\n";

            client.say(to, help);
        }

        /*********************************************************[ !alexa ]**/

        if (message.match(/^!alexa/)) {
            alexa(params, function(error, result) {
                if (!error && typeof result.rank != "undefined") {
                    client.say(to, "Alexa Traffic Rank for " + result.idn.slice(0, -1) + ": " + result.rank);
                }
            });
        }

        /**********************************************************[ !date ]**/

        if (message.match(/^!date/)) {
            client.say(to, Date());
        }

        /********************************************************[ !expand ]**/

        if (message.match(/^!expand/)) {
            request({
                    method: "HEAD",
                    url: params,
                    followAllRedirects: true
                },
                function(error, response) {
                    if (!error && response.statusCode == 200) {
                        client.say(to, response.request.href);
                    }
                });
        }

        /*******************************************************[ !headers ]**/

        if (message.match(/^!headers/)) {
            request(params, function(error, response, body) {
                if (!error && response.statusCode == 200) {
                    for (var item in response.headers) {
                        client.say(to, item + ": " + response.headers[item] + "\n");
                    }
                }
            });
        }

        /*******************************************************[ !resolve ]**/

        if (message.match(/^!resolve/)) {
            dns.resolve4(params, function(error, addresses) {
                if (!error) {
                    for (var item in addresses) {
                        client.say(to, addresses[item] + "\n");
                    }
                }
                dns.resolve6(params, function(error, addresses) {
                    if (!error) {
                        for (var item in addresses) {
                            client.say(to, addresses[item] + "\n");
                        }
                    }
                });
            });
        }

        /*******************************************************[ !reverse ]**/

        if (message.match(/^!reverse/)) {
            if (net.isIP(params)) {
                dns.reverse(params, function(error, domains) {
                    if (!error) {
                        client.say(to, domains[0]);
                    }
                });
            }
        }

        /*****************************************************[ !wikipedia ]**/

        if (message.match(/^!wikipedia/)) {
            params.split(' ').join('_');

            dns.resolveTxt(params + ".wp.dg.cx", function(error, txt) {
                if (!error) {
                    client.say(to, txt[0]);
                }
            });
        }
    });
示例#28
0
文件: spf.js 项目: Illirgway/Haraka
SPF.prototype.check_host = function (ip, domain, mail_from, cb) {
    var self = this;
    domain = domain.toLowerCase();
    if (mail_from) {
        mail_from = mail_from.toLowerCase();
    }
    else {
        mail_from = 'postmaster@' + domain;
    }
    this.ipaddr = ipaddr.parse(ip);
    this.ip_ver = this.ipaddr.kind();
    if (this.ip_ver === 'ipv6') {
        this.ip = this.ipaddr.toString();
    }
    else {
        this.ip = ip;
    }
    this.domain = domain;
    this.mail_from = mail_from;

    this.log_debug('ip=' + ip + ' domain=' + domain + ' mail_from=' + mail_from);
    // Get the SPF record for domain
    dns.resolveTxt(domain, function (err, txt_rrs) {
        if (err) {
            self.log_debug('error looking up TXT record: ' + err.message);
            switch (err.code) {
                case 'ENOTFOUND':
                case 'ENODATA':
                case dns.NXDOMAIN:  return cb(null, self.SPF_NONE);
                default:            return cb(null, self.SPF_TEMPERROR);
            }
        }

        var spf_record;
        for (var i=0; i < txt_rrs.length; i++) {
            var match = /^(v=spf1(?:$|\s.+$))/i.exec(txt_rrs[i]);
            if (match) {
                if (!spf_record) {
                    self.log_debug('found SPF record for domain ' + domain + ': ' + match[1]);
                    spf_record = match[1].replace(/\s+/, ' ').toLowerCase();
                }
                else {
                    // We've already found an MX record
                    self.log_debug('found additional SPF record for domain ' + domain + ': ' + match[1]);
                    return cb(null, self.SPF_PERMERROR);
                }                
            }
            else {
                self.log_debug('discarding TXT record: ' + txt_rrs[i]);
            }
        }

        if (!spf_record) {
            // No SPF record found?
            return cb(null, self.SPF_NONE);
        }

        // Store the SPF record we used in the object
        self.spf_record = spf_record;

        // Validate SPF record and build call chain
        var mech_array = [];
        var mod_array = [];
        var mech_regexp1 = /^([-+~?])?(all|a|mx|ptr)$/;
        var mech_regexp2 = /^([-+~?])?(a|mx|ptr|ip4|ip6|include|exists)((?::[^\/ ]+(?:\/\d+(?:\/\/\d+)?)?)|\/\d+(?:\/\/\d+)?)$/;
        var mod_regexp = /^([^ =]+)=([a-z0-9._-]+)$/;
        var split = spf_record.split(' ');
        for (var i=1; i<split.length; i++) {
            // Skip blanks
            if (!split[i]) continue;
            var match;
            if (match = (mech_regexp1.exec(split[i]) || mech_regexp2.exec(split[i]))) {
                // match[1] = qualifier
                // match[2] = mechanism
                // match[3] = optional args
                if (!match[1]) match[1] = '+'; 
                self.log_debug('found mechanism: ' + match);
                // Validate IP addresses
                if (match[2] === 'ip4' || match[2] === 'ip6') {
                    var ip_split = /^:([^\/ ]+)(?:\/([^ ]+))?$/.exec(match[3]);
                    // Make sure the IP address is valid
                    if(!ip_split || (ip_split && !ipaddr.isValid(ip_split[1]))) {
                        self.log_debug('invalid IP address: ' + ip_split[1]);
                        return cb(null, self.SPF_PERMERROR);
                    }
                } else {
                    // Validate macro strings
                    if (match[3] && /%[^{%+-]/.exec(match[3])) {
                        self.log_debug('invalid macro string');
                        return cb(null, self.SPF_PERMERROR);
                    }
                    if (match[3]) {
                        // Expand macros
                        match[3] = self.expand_macros(match[3]);
                    }
                }

                var obj = {};
                obj[match[2]] = [ match[1], match[3] ];
                mech_array.push(obj);
            }
            else if (match = mod_regexp.exec(split[i])) {
                self.log_debug('found modifier: ' + match);
                // match[1] = modifier
                // match[2] = name
                // Make sure we have a method
                if (!self['mod_' + match[1]]) {
                    self.log_debug('skipping unknown modifier: ' + match[1]);
                }
                else {
                    var obj = {};
                    obj[match[1]] = match[2];
                    mod_array.push(obj);
                }
            }
            else {
                // Syntax error
                self.log_debug('syntax error: ' + split[i]);
                return cb(null, self.SPF_PERMERROR);
            }
        }

        self.log_debug('SPF record for \'' + self.domain + '\' validated OK');

        // Set-up modifier run chain
        var mod_chain_caller = function (err, result) {
            // Throw any errors
            if (err) throw err;
            // Check limits
            if (self.count > self.LIMIT) {
                self.log_debug('lookup limit reached');
                return cb(null, self.SPF_PERMERROR);
            } 
            // Return any result that is not SPF_NONE
            if (result && result !== self.SPF_NONE) {
                return cb(err, result);
            }
            if (!mod_array.length) {
                return cb(null, self.SPF_NEUTRAL);
            }
            var next_in_chain = mod_array.shift();
            var func = Object.keys(next_in_chain);
            var args = next_in_chain[func];
            self.log_debug('running modifier: ' + func + ' args=' + args + ' domain=' + self.domain);
            self['mod_' + func](args, mod_chain_caller);
        }

        // Run all the mechanisms first
        var mech_chain_caller = function (err, result) {
            // Throw any errors
            if (err) throw err;
            // Check limits
            if (self.count > self.LIMIT) {
                self.log_debug('lookup limit reached');
                return cb(null, self.SPF_PERMERROR);
            }
            // If we have a result other than SPF_NONE
            if (result && result !== self.SPF_NONE) {
                return cb(err, result);
            }
            // Return default if no more mechanisms to run
            if (!mech_array.length) {
                // Now run any modifiers
                if (mod_array.length) {
                    return mod_chain_caller();
                }
                else {
                    return cb(null, self.SPF_NEUTRAL);
                }
            }
            var next_in_chain = mech_array.shift();
            var func = Object.keys(next_in_chain);
            var args = next_in_chain[func];
            self.log_debug('running mechanism: ' + func + ' args=' + args + ' domain=' + self.domain);
            self['mech_' + func](((args && args.length) ? args[0] : null), ((args && args.length) ? args[1] : null), mech_chain_caller);
        }
        // Start the chain
        mech_chain_caller();
    });
}
示例#29
0
文件: dkim.js 项目: MinePay/Haraka
DKIMObject.prototype.end = function () {
    if (this.run_cb) return;

    var bh = this.bh.digest('base64');
    this.debug(this.identity + ':' +
               ' bodyhash=' + this.fields.bh +
               ' computed=' + bh);
    if (bh !== this.fields.bh) {
        return this.result('body hash did not verify', 'fail');
    }

    // Now we canonicalize the specified headers
    for (var h=0; h<this.signed_headers.length; h++) {
        var header = this.signed_headers[h];
        this.debug(this.identity + ': canonicalize header: ' + header);
        if (this.header_idx[header]) {
            // RFC 6376 section 5.4.2, read headers from bottom to top
            var this_header = this.header_idx[header].pop();
            if (this_header) {
                // Skip this signature if dkim-signature is specified
                if (header === 'dkim-signature') {
                    var h_md5 = md5(this_header);
                    if (h_md5 === this.sig_md5) {
                        this.debug(this.identity + ': skipped our own DKIM-Signature');
                        continue;
                    }
                }
                if (this.headercanon === 'simple') {
                    this.verifier.update(this_header);
                }
                else if (this.headercanon === 'relaxed') {
                    var hc = this.header_canon_relaxed(this_header);
                    this.verifier.update(hc);
                }
            }
        }
    }

    // Now add in our original DKIM-Signature header without the b= and trailing CRLF
    var our_sig = this.sig.replace(/b=([^;]+)/,'b=');
    if (this.headercanon === 'relaxed') {
        our_sig = this.header_canon_relaxed(our_sig);
    }
    our_sig = our_sig.replace(/\r\n$/,'');
    this.verifier.update(our_sig);

    // Do the DNS lookup to retrieve the public key
    var self = this;
    var timeout = false;
    var timer = setTimeout(function () {
        timeout = true;
        return self.result('DNS timeout', 'tempfail');
    }, this.timeout * 1000);
    var lookup = this.fields.s + '._domainkey.' + this.fields.d;
    this.debug(this.identity + ': DNS lookup ' + lookup + ' (timeout=' + this.timeout + 's)');
    dns.resolveTxt(lookup, function (err, res) {
        if (timeout) return;
        clearTimeout(timer);
        if (err) {
            switch (err.code) {
                case dns.NOTFOUND:
                case dns.NODATA:
                case dns.NXDOMAIN:
                    return self.result('no key for signature', 'invalid');
                default:
                    self.debug(self.identity + ': DNS lookup error: ' + err.code);
                    return self.result('key unavailable', 'tempfail');
            }
        }
        if (!res) return self.result('no key for signature', 'invalid');
        for (var r=0; r<res.length; r++) {
            var record = res[r];
            // Node 0.11.x compatibility
            if (Array.isArray(record)) {
                record = record.join('');
            }
            if (record.indexOf('p=') === -1) {
                self.debug(self.identity + ': ignoring TXT record: ' + record);
                continue;
            }
            self.debug(self.identity + ': got DNS record: ' + record);
            var rec = record.replace(/\r?\n/g, '').replace(/\s+/g,'');
            var split = rec.split(';');
            for (var j=0; j<split.length; j++) {
                var split2 = split[j].split('=');
                if (split2[0]) self.dns_fields[split2[0]] = split2[1];
            }

            // Validate
            if (!self.dns_fields.v || self.dns_fields.v !== 'DKIM1') {
                return self.result('invalid version', 'invalid');
            }
            if (self.dns_fields.g) {
                if (self.dns_fields.g !== '*') {
                    var s = self.dns_fields.g;
                    // Escape any special regexp characters
                    s = s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
                    // Make * a non-greedy match against anything except @
                    s = s.replace('\\*','[^@]*?');
                    var reg = new RegExp('^' + s + '@');
                    self.debug(self.identity + ': matching ' + self.dns_fields.g +
                                      ' against i=' + self.fields.i + ' regexp=' + reg.toString());
                    if (!reg.test(self.fields.i)) {
                        return self.result('inapplicable key', 'invalid');
                    }
                }
            }
            else {
                return self.result('inapplicable key', 'invalid');
            }
            if (self.dns_fields.h) {
                var hashes = self.dns_fields.h.split(':');
                for (var k=0; k<hashes.length; k++) {
                    var hash = hashes[k].trim();
                    if (self.fields.a.indexOf(hash) === -1) {
                        return self.result('inappropriate hash algorithm', 'invalid');
                    }
                }
            }
            if (self.dns_fields.k) {
                if (self.fields.a.indexOf(self.dns_fields.k) === -1) {
                    return self.result('inappropriate key type', 'invalid');
                }
            }
            if (self.dns_fields.t) {
                var flags = self.dns_fields.t.split(':');
                for (var f=0; f<flags.length; f++) {
                    var flag = flags[f].trim();
                    if (flag === 'y') {
                        // Test mode
                        self.test_mode = true;
                    }
                    else if (flag === 's') {
                        // 'i' and 'd' domain much match exactly
                        var j = self.fields.i;
                        j = j.substr(j.indexOf('@')+1, j.length);
                        if (j !== self.fields.d) {
                            return self.result('domain mismatch', 'invalid');
                        }
                    }
                }
            }
            if (!self.dns_fields.p) return self.result('key revoked', 'invalid');

            // crypto.verifier requires the key in PEM format
            self.public_key = '-----BEGIN PUBLIC KEY-----\r\n' +
                              self.dns_fields.p.replace(/(.{1,76})/g, '$1\r\n') +
                              '-----END PUBLIC KEY-----\r\n';

            var verified;
            try {
                verified = self.verifier.verify(self.public_key, self.fields.b, 'base64');
                self.debug(self.identity + ': verified=' + verified);
            }
            catch (e) {
                self.debug(self.identity + ': verification error: ' + e.message);
                return self.result('verification error', 'invalid');
            }
            return self.result(null, ((verified) ? 'pass' : 'fail'));
        }
        // We didn't find a valid DKIM record for this signature
        return self.result('no key for signature', 'invalid');
    });
};
示例#30
0
    dns.resolveSrv(srvAddress, function(err, addresses) {
      if (err) return callback(err);

      if (addresses.length === 0) {
        return callback(new Error('No addresses found at host'));
      }

      for (var i = 0; i < addresses.length; i++) {
        if (!matchesParentDomain(addresses[i].name, result.hostname, result.domainLength)) {
          return callback(new Error('srv record does not share hostname with parent uri'));
        }
      }

      var base = result.auth ? 'mongodb://' + result.auth + '@' : 'mongodb://';
      var connectionStrings = addresses.map(function(address, i) {
        if (i === 0) return base + address.name + ':' + address.port;
        else return address.name + ':' + address.port;
      });

      var connectionString = connectionStrings.join(',') + '/';
      var connectionStringOptions = [];

      // Default to SSL true
      if (!options.ssl && !result.search) {
        connectionStringOptions.push('ssl=true');
      } else if (!options.ssl && result.search && !result.search.match('ssl')) {
        connectionStringOptions.push('ssl=true');
      }

      // Keep original uri options
      if (result.search) {
        connectionStringOptions.push(result.search.replace('?', ''));
      }

      dns.resolveTxt(result.host, function(err, record) {
        if (err && err.code !== 'ENODATA') return callback(err);
        if (err && err.code === 'ENODATA') record = null;

        if (record) {
          if (record.length > 1) {
            return callback(new Error('multiple text records not allowed'));
          }

          record = record[0];
          if (record.length > 1) record = record.join('');
          else record = record[0];

          if (!record.includes('authSource') && !record.includes('replicaSet')) {
            return callback(new Error('text record must only set `authSource` or `replicaSet`'));
          }

          connectionStringOptions.push(record);
        }

        // Add any options to the connection string
        if (connectionStringOptions.length) {
          connectionString += '?' + connectionStringOptions.join('&');
        }

        parseHandler(connectionString, options, callback);
      });
    });