const SyncConnector = require('./sync-connector'); const ssh = require('node-ssh'); const ldap = require('./ldapjs-extra'); class SyncSamba extends SyncConnector { async init() { let sambaConfig = await this.$.SambaConfig.findOne({ fields: [ 'host', 'sshUser', 'sshPassword', 'adUser', 'adPassword', 'userDn' ] }); if (!sambaConfig) return false; let client = new ssh.NodeSSH(); await client.connect({ host: sambaConfig.host, username: sambaConfig.sshUser, password: sambaConfig.sshPassword }); let adClient = ldap.createClient({ url: `ldaps://${sambaConfig.host}:636`, tlsOptions: {rejectUnauthorized: false} }); await adClient.bind(sambaConfig.adUser, sambaConfig.adPassword); Object.assign(this, { sambaConfig, client, adClient }); return true; } async deinit() { if (!this.client) return; await this.client.dispose(); await this.adClient.unbind(); } async sync(info, userName, password) { let {client} = this; if (info.hasAccount) { try { await client.exec('samba-tool user create', [ userName, '--uid-number', `${info.uidNumber}`, '--mail-address', info.corporateMail, '--random-password' ]); await client.exec('samba-tool user setexpiry', [ userName, '--noexpiry' ]); await client.exec('mkhomedir_helper', [ userName, '0027' ]); } catch (e) {} await client.exec('samba-tool user enable', [ userName ]); if (password) { await client.exec('samba-tool user setpassword', [ userName, '--newpassword', password ]); } } else { try { await client.exec('samba-tool user disable', [ userName ]); console.log(` -> '${userName}' disabled on Samba`); } catch (e) {} } } /** * Gets enabled users from Samba. * * Summary of userAccountControl flags: * https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties * * @param {Set} usersToSync */ async getUsers(usersToSync) { let { sambaConfig, adClient } = this; let opts = { scope: 'sub', attributes: ['sAMAccountName'], filter: '(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))' }; let res = await adClient.search(sambaConfig.userDn, opts); await new Promise((resolve, reject) => { res.on('error', err => { if (err.name === 'NoSuchObjectError') err = new Error(`Object '${sambaConfig.userDn}' does not exist`); reject(err); }); res.on('searchEntry', e => { usersToSync.add(e.object.sAMAccountName); }); res.on('end', resolve); }); } } SyncConnector.connectors.push(SyncSamba); module.exports = SyncSamba;