wzp
2021-05-13 7d694a9113118daec5be7ac224dab46a3b20f106
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
'use strict';
 
var url = require('url');
var httpreq = require('httpreq');
var ntlm = require('./ntlm');
var _ = require('underscore');
var http = require('http');
var https = require('https');
 
exports.method = function(method, options, finalCallback){
    if(!options.workstation) options.workstation = '';
    if(!options.domain) options.domain = '';
 
    // extract non-ntlm-options:
    var httpreqOptions = _.omit(options, 'url', 'username', 'password', 'workstation', 'domain');
 
    // is https?
    var isHttps = false;
    var reqUrl = url.parse(options.url);
    if(reqUrl.protocol == 'https:') isHttps = true;
 
    // set keepaliveAgent (http or https):
    var keepaliveAgent;
 
    if(isHttps){
        keepaliveAgent = new https.Agent({keepAlive: true});
    }else{
        keepaliveAgent = new http.Agent({keepAlive: true});
    }
 
    // build type1 request:
 
    function sendType1Message (callback) {
        var type1msg = ntlm.createType1Message(options);
 
        var type1options = {
            headers:{
                'Connection' : 'keep-alive',
                'Authorization': type1msg
            },
            timeout: options.timeout || 0,
            agent: keepaliveAgent,
            allowRedirects: false // don't redirect in httpreq, because http could change to https which means we need to change the keepaliveAgent
        };
 
        // pass along timeout and ca:
        if(httpreqOptions.timeout) type1options.timeout = httpreqOptions.timeout;
        if(httpreqOptions.ca) type1options.ca = httpreqOptions.ca;
 
        // send type1 message to server:
        httpreq.get(options.url, type1options, callback);
    }
 
    function sendType3Message (res, callback) {
        // catch redirect here:
        if(res.headers.location) {
            options.url = res.headers.location;
            return exports[method](options, finalCallback);
        }
 
 
        if(!res.headers['www-authenticate'])
            return callback(new Error('www-authenticate not found on response of second request'));
 
        // parse type2 message from server:
        var type2msg = ntlm.parseType2Message(res.headers['www-authenticate']);
 
        // create type3 message:
        var type3msg = ntlm.createType3Message(type2msg, options);
 
        // build type3 request:
        var type3options = {
            headers: {
                'Connection': 'Close',
                'Authorization': type3msg
            },
            allowRedirects: false,
            agent: keepaliveAgent
        };
 
        // pass along other options:
        type3options.headers = _.extend(type3options.headers, httpreqOptions.headers);
        type3options = _.extend(type3options, _.omit(httpreqOptions, 'headers'));
 
        // send type3 message to server:
        httpreq[method](options.url, type3options, callback);
    }
 
 
    sendType1Message(function (err, res) {
        if(err) return finalCallback(err);
        setImmediate(function () { // doesn't work without setImmediate()
            sendType3Message(res, finalCallback);
        });
    });
 
};
 
['get', 'put', 'patch', 'post', 'delete', 'options'].forEach(function(method){
    exports[method] = exports.method.bind(exports, method);
});
 
exports.ntlm = ntlm; //if you want to use the NTML functions yourself