Browse Source

init

master
Simon Vieille 1 year ago
commit
a75e5e12a9
No known key found for this signature in database
8 changed files with 489 additions and 0 deletions
  1. 2
    0
      .gitignore
  2. 290
    0
      index.js
  3. 17
    0
      package.json
  4. 59
    0
      src/console/input.js
  5. 37
    0
      src/console/output.js
  6. 53
    0
      src/cookie-bag.js
  7. 26
    0
      src/logger.js
  8. 5
    0
      src/preg-match.js

+ 2
- 0
.gitignore View File

@@ -0,0 +1,2 @@
login
node_modules/

+ 290
- 0
index.js View File

@@ -0,0 +1,290 @@
"use strict";

var Crawler = require("crawler");
var path = require('path');
var output = new(require('./src/console/output'));
var input = new(require('./src/console/input'))(process);
var pregMatch = require('./src/preg-match');
var logger = require('./src/logger.js');
var cookieBag = new(require('./src/cookie-bag.js'));

process.chdir(path.dirname(input.script));

var isDebugMode = input.has('debug');

if (!isDebugMode) {
process.on('uncaughtException', function() {
output.json({
error: true,
message: 'UncaughtException'
});

process.exit(1);
});
}

if (input.has('help')) {
output.write([
process.argv[0],
process.argv[1],
'[--crawler-debug]',
'[--crawler-info]',
'[--crawler-error]',
].join(' '));

process.exit(1);
}

var handlerCrawlerError = function(response, e) {
output.json({
error: true,
message: {
body: response.body,
response: response,
error: e,
},
}, true);
}

var handlerCrawlerException = function(e, done) {
if (isDebugMode) {
throw e;
} else {
done();

return output.json({
error: true,
message: e
});
}
}

var headers = function(crawler) {
var datas = {
'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'fr,fr-FR;q=0.5',
'Cookie': cookieBag.toString(),
};

if (crawler.storage.hasOwnProperty('referer')) {
datas['referer'] = crawler.storage.referer;
}

return datas;
}

var createCrawlerOptions = function(config) {
var options = {
maxConnections: 10,
retries: 1,
logger: logger,
jQuery: false,
};

config = config || {};

for (var i in config) {
options[i] = config[i];
}

return options;
}

var createCrawler = function(options) {
options = createCrawlerOptions(options || {});

if (!options.hasOwnProperty('callback') && options.hasOwnProperty('onSuccess')) {
options.callback = function(error, response, done) {
if (error) {
handlerCrawlerError(response, error);
} else {
try {
options.onSuccess(response, done);
} catch (e) {
return handlerCrawlerException(e, done);
}
}

done();
}
}

var c = new Crawler(options);

c.storage = {};

c.runCrawl = function(url) {
c.options.headers = headers(c);

return c.queue(url);
};

return c;
}

try {
var UrlRefreshRequester = createCrawler({
onSuccess: function(response) {
cookieBag.handleResponse(response);

var urlRefresh = pregMatch(/"urlRefresh":"([^"]+)"/, response.body)[1];

LoginFormRequester.runCrawl(urlRefresh);
},
});

var LoginFormRequester = createCrawler({
onSuccess: function(response) {
cookieBag.handleResponse(response);

var urlPost = pregMatch(/"urlPost":"([^"]+)"/, response.body)[1];
var urlLogin = pregMatch(/"urlLogin":"([^"]+)"/, response.body)[1];

var data = {
canary: pregMatch(/"canary":"([^"]+)"/, response.body)[1],
ctx: pregMatch(/ctx=(.+)/, urlLogin)[1],
hpgrequestid: pregMatch(/"sessionId":"([^"]+)"/, response.body)[1],
flowToken: pregMatch(/"sFT":"([^"]+)"/, response.body)[1],
f1: 'Suivant',
NewUser: 1,
CookieDisclosure: 1,
fspost: 0,
IsFidoSupported: 0,
FoundMSAs: null,
i2: 1,
i13: 0,
i17: '',
i18: '',
i19: 19471,
ps: 2,
psRNGCDefaultType: '',
psRNGCEntropy: '',
psRNGCSLK: '',
PPSX: '',
FoundMSAs: '',
type: 11,
LoginOptions: 3,
Irt: '',
IrtPartition: '',
hisRegion: '',
hisScaleUnit: '',
loginfmt: process.env.MS_OFFICE365_LOGIN,
login: process.env.MS_OFFICE365_LOGIN,
passwd: process.env.MS_OFFICE365_PASSWORD,
}

LoginRequester.options.form = data;

LoginRequester.runCrawl('https://login.microsoftonline.com' + urlPost)
}
});

var LoginRequester = createCrawler({
method: 'POST',
onSuccess: function(response) {
cookieBag.handleResponse(response);

var data = {
canary: pregMatch(/"canary":"([^"]+)"/, response.body)[1],
ctx: pregMatch(/"sCtx":"([^"]+)"/, response.body)[1],
hpgrequestid: pregMatch(/"sessionId":"([^"]+)"/, response.body)[1],
flowToken: pregMatch(/"sFT":"([^"]+)"/, response.body)[1],
LoginOptions: 1,
}

KmsiRequester.options.form = data;

KmsiRequester.runCrawl('https://login.microsoftonline.com/kmsi');
}
});

var KmsiRequester = createCrawler({
method: 'POST',
jQuery: true,
onSuccess: function(response) {
cookieBag.handleResponse(response);

var data = {
code: response.$('[name="code"]').val(),
id_token: response.$('[name="id_token"]').val(),
session_state: response.$('[name="session_state"]').val(),
correlation_id: response.$('[name="correlation_id"]').val(),
};

SiteRequester.options.form = data;
SiteRequester.storage.referer = 'https://login.microsoftonline.com/kmsi';
SiteRequester.runCrawl(process.env.MS_OFFICE365_SITE + '_forms/default.aspx');
}
});

var SiteRequester = createCrawler({
method: 'POST',
jQuery: true,
onSuccess: function(response, done) {
cookieBag.handleResponse(response);

if (SiteRequester.storage.hasOwnProperty('finish')) {
output.json({
rtFa: cookieBag.get('rtFa'),
FedAuth: cookieBag.get('FedAuth'),
}, true);

return;
}

if (SiteRequester.storage.hasOwnProperty('kmsi')) {
delete SiteRequester.storage.kmsi;

SiteRequester.storage.finish = true;

return KmsiRequester.options.onSuccess(response);
}

if (response.headers.hasOwnProperty('location')) {
SiteRequester.options.method = 'GET';

var location = response.headers.location;

SiteRequester.runCrawl(location);
} else {
var urlPost = response.$('form').attr('action');

var data = {
code: response.$('[name="code"]').val(),
id_token: response.$('[name="id_token"]').val(),
session_state: response.$('[name="session_state"]').val(),
correlation_id: response.$('[name="correlation_id"]').val(),
};

var params = urlPost.split('?')[1].split('&');

params.forEach(function(param) {
var name = pregMatch(/([a-zA-Z0-9_-]+)=/, param)[1];
var value = pregMatch(/=(.+)/, param)[1];

data[name] = decodeURIComponent(value);
});

SiteRequester.options.method = 'POST';
SiteRequester.options.form = data;
SiteRequester.storage.referer = 'https://login.microsoftonline.com/kmsi';
SiteRequester.storage.kmsi = true;
SiteRequester.runCrawl(urlPost);
}
},
});

UrlRefreshRequester.runCrawl(process.env.MS_OFFICE365_SITE);
} catch (e) {
if (isDebugMode) {
throw e;
} else {
output.json({
error: true,
message: e
});
}

process.exit(1);
}

+ 17
- 0
package.json View File

@@ -0,0 +1,17 @@
{
"name": "sharepoint-webdav-oauth2-bot",
"version": "1.0.0",
"description": "sharepoint-webdav-oauth2-bot",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Simon Vieille <simon@deblan.fr>",
"license": "ISC",
"dependencies": {
"class.extend": "^0.9.2",
"crawler": "^1.1.2",
"minimist": "^1.2.0",
"trim": "0.0.1"
}
}

+ 59
- 0
src/console/input.js View File

@@ -0,0 +1,59 @@
"use strict";

var Minimist = require('minimist');
var Class = require('class.extend');

var Input = Class.extend('Input', {
/**
* Constructor.
*
* @param object process
*/
init: function(process) {
this.args = Minimist(process.argv.slice(2));
this.node = process.argv[0];
this.script = process.argv[1];
},

/**
* Return the value of the given name argument.
*
* @param string name
* @param mixed default
*
* @return mixed
*/
get: function(name, defaultValue) {
if (this.has(name)) {
return this.args[name];
}

if (defaultValue !== undefined) {
return defaultValue;
}

return null;
},

/**
* Check the given argument name exists.
*
* @param string name
*
* @return boolean
*/
has: function(name) {
return this.args.hasOwnProperty(name);
},

/**
* Return if args is empty.
*
* @return boolean
*/
empty: function() {
return Object.keys(this.args).length === 1;
},
});

module.exports = Input;

+ 37
- 0
src/console/output.js View File

@@ -0,0 +1,37 @@
"use strict";

var Class = require('class.extend');

var Output = Class.extend('Output', {
/**
* Convert and print data to json.
*
* @param mixed data
*/
json: function(data, pretty) {
data = JSON.stringify(
data,
function(key, value) {
if (value === undefined) {
return null;
}

return value;
},
pretty ? 2 : null
);

return this.write(data);
},

/**
* Print data.
*
* @param mixed data
*/
write: function(data) {
console.log(data);
}
});

module.exports = Output;

+ 53
- 0
src/cookie-bag.js View File

@@ -0,0 +1,53 @@
var trim = require('trim');

var CookieBag = function() {
this.bag = [];
}

CookieBag.prototype.add = function(name, value) {
this.bag[name] = name + '=' + value;
}

CookieBag.prototype.get = function(name) {
var str = this.bag[name] || null;

if (!str) {
return;
}

var index = str.indexOf('=');

return str.substr(index + 1);
}

CookieBag.prototype.toString = function() {
var data = [];

for (var i in this.bag) {
data.push(this.bag[i]);
}

return data.join('; ');
}

CookieBag.prototype.handleResponse = function(response) {
var headers = response.headers || {};
var cookies = headers['set-cookie'] || [];
var that = this;

cookies.forEach(function(cookie) {
var def = cookie.split(';')[0];
var index = def.indexOf('=');

var name = def.substr(0, index);
var value = def.substr(index + 1);

that.add(name, value);
});
}

CookieBag.prototype.clean = function() {
this.bag = [];
}

module.exports = CookieBag;

+ 26
- 0
src/logger.js View File

@@ -0,0 +1,26 @@
var output = new(require('./console/output'));
var input = new(require('./console/input'))(process);

var logCrawlerDebug = input.has('crawler-debug');
var logCrawlerInfo = input.has('crawler-info');
var logCrawlerError = input.has('crawler-error');

var writeLog = function(level, message) {
return output.write('[' + level.toUpperCase() + '] ' + message);
}

module.exports = {
log: function(level, message) {
if (level === 'debug' && logCrawlerDebug) {
return writeLog(level, message);
}

if (level === 'info' && logCrawlerInfo) {
return writeLog(level, message);
}

if (level === 'error' && logCrawlerError) {
return writeLog(level, message);
}
},
};

+ 5
- 0
src/preg-match.js View File

@@ -0,0 +1,5 @@
var pregMatch = function(regex, content) {
return content.match(regex);
}

module.exports = pregMatch;

Loading…
Cancel
Save