Files
2021-04-09 15:17:30 +01:00

1165 lines
52 KiB
JavaScript

//Author Cody Thomas, @its_a_feature_
ObjC.import("Foundation");
ObjC.import("stdio");
ObjC.import('OpenDirectory');
//for all of these, there is a switch to use ObjC calls vs terminal calls
currApp = Application.currentApplication();
currApp.includeStandardAdditions = true;
// Lookup tables for doing OpenDirectory queries via LDAP
var object_class = {
"AttributeTypes": "dsRecTypeStandard:AttributeTypes",
"AFPServer": "dsRecTypeStandard:AFPServer",
"Aliases": "dsRecTypeStandard:Aliases",
"Augments": "dsRecTypeStandard:Augments",
"Automount": "dsRecTypeStandard:Automount",
"AutomountMap": "dsRecTypeStandard:AutomountMap",
"AutoServerSetup": "dsRecTypeStandard:AutoServerSetup",
"Bootp": "dsRecTypeStandard:Bootp",
"CertificateAuthorities": "dsRecTypeStandard:CertificateAuthorities",
"ComputerLists": "dsRecTypeStandard:ComputerLists",
"ComputerGroups": "dsRecTypeStandard:ComputerGroups",
"Computers": "dsRecTypeStandard:Computers",
"Configuration": "dsRecTypeStandard:Config",
"Ethernets": "dsRecTypeStandard:Ethernets",
"FileMakerServers": "dsRecTypeStandard:FileMakerServers",
"FTPServer": "dsRecTypeStandard:FTPServer",
"Groups": "dsRecTypeStandard:Groups",
"HostServices": "dsRecTypeStandard:HostServices",
"Hosts": "dsRecTypeStandard:Hosts",
"LDAPServer": "dsRecTypeStandard:LDAPServer",
"Locations": "dsRecTypeStandard:Locations",
"Mounts": "dsRecTypeStandard:Mounts",
"NFS": "dsRecTypeStandard:NFS",
"NetDomains": "dsRecTypeStandard:NetDomains",
"NetGroups": "dsRecTypeStandard:NetGroups",
"Networks": "dsRecTypeStandard:Networks",
"PasswordServer": "dsRecTypeStandard:PasswordServer",
"People": "dsRecTypeStandard:People",
"Plugins": "dsRecTypeStandard:Plugins",
"PresetComputers": "dsRecTypeStandard:PresetComputers",
"PresetComputerGroups": "dsRecTypeStandard:PresetComputerGroups",
"PresetComputerLists": "dsRecTypeStandard:PresetComputerLists",
"PresetGroups": "dsRecTypeStandard:PresetGroups",
"PresetUsers": "dsRecTypeStandard:PresetUsers",
"PrintService": "dsRecTypeStandard:PrintService",
"PrintServiceUser": "dsRecTypeStandard:PrintServiceUser",
"Printers": "dsRecTypeStandard:Printers",
"Protocols": "dsRecTypeStandard:Protocols",
"QTSServer": "dsRecTypeStandard:QTSServer",
"RecordTypes": "dsRecTypeStandard:RecordTypes",
"Resources": "dsRecTypeStandard:Resources",
"RPC": "dsRecTypeStandard:RPC",
"SMBServer": "dsRecTypeStandard:SMBServer",
"Server": "dsRecTypeStandard:Server",
"Services": "dsRecTypeStandard:Services",
"SharePoints": "dsRecTypeStandard:SharePoints",
"UserAuthenticationData": "dsRecTypeStandard:UserAuthenticationData",
"Users": "dsRecTypeStandard:Users",
"WebServer": "dsRecTypeStandard:WebServer",
}
var match_type = {
"Any": 0x01,//$.kODMatchAny,
"BeginsWith": 0x2002,//$.kODMatchInsensitiveBeginsWith,
"EndsWith": 0x2003,//$.kODMatchInsensitiveEndsWith,
"Contains": 0x2004,//$.kODMatchInsensitiveContains,
"EqualTo": 0x2001,//$.kODMatchInsensitiveEqualTo,
"LessThan": 0x2007,//$.kODMatchLessThan,
"GreaterThan": 0x2006,//$.kODMatchGreaterThan
}
var attributes_list = {
"all": ["", "dsAttributesAll"],
"*": ["", "dsAttributesAll"],
"accountpolicydata": ["accountPolicyData", "dsAttrTypeNative:"],
"accountexpires": ["accountExpires", "dsAttrTypeNative:"],
"admincount": ["adminCount", "dsAttrTypeNative:"],
"adminlimits": ["AdminLimits", "dsAttrTypeStandard:"],
"altsecurityidentities": ["AltSecurityIdentities", "dsAttrTypeStandard:"], //x509
"afp_guestaccess": ["afp_guestaccess", "dsAttrTypeNative:"],
"afp_name": ["afp_name", "dsAttrTypeNative:"],
"afp_shared": ["afp_shared", "dsAttrTypeNative:"],
"authenticationhint": ["AuthenticationHint", "dsAttrtypeStandard:"],
"badpasswordtime": ["badPasswordTime", "dsAttrTypeNative:"],
"badpwdcount": ["badPwdCount", "dsAttrTypeNative:"],
"bootfile": ["BootFile", "dsAttrTypeStandard:"],
"bootparams": ["BootParams", "dsAttrTypeStandard:"],
"cacertificiate": ["CACertificate", "dsAttrTypeStandard:"],
"capacity": ["Capacity", "dsAttrTypeStandard:"],
"category": ["Category", "dsAttrtypeStandard:"],
"certificaterevocationlist": ["CertificateRevocationList", "dsAttrTypeStandard:"],
"codepage": ["codePage", "dsAttrTypeNative:"],
"comment": ["Comment", "dsAttrTypeStandard:"],
"contactguid": ["ContactGUID", "dsAttrtypeStandard:"],
"countrycode": ["countryCode", "dsAttrTypeNative:"],
"creationtimestamp": ["CreationTimestamp", "dsAttrTypeStandard:"],
"crosscertificatepair": ["CrossCertificatePair", "dsAttrTypeStandard:"],
"cn": ["cn", "dsAttrTypeNative:"],
"fullname": ["FullName", ""], //have to use realname
"displayname": ["displayName", "dsAttrTypeNative:"],
"distinguishedname": ["distinguishedName", "dsAttrTypeNative:"],
"directory_path": ["directory_path", "dsAttrTypeNative:"],
"dnsdomain": ["DNSDomain", "dsAttrTypeStandard:"],
"dnsnameserver": ["DNSNameServer", "dsAttrTypeStandard:"],
"dscorepropagationdata": ["dsCorePropagationData", "dsAttrTypeNative:"],
"emailaddress": ["EMailAddress", "dsAttrTypeStandard:"],
"enetaddress": ["ENetAddress", "dsAttrTypeNative:"],
"expire": ["Expire", "dsAttrTypeStandard:"],
"firstname": ["FirstName", "dsAttrTypeStandard:"],
"ftp_name": ["ftp_name", "dsAttrTypeNative:"],
"generateduid": ["GeneratedUID", "dsAttrTypeStandard:"],
"grouptype": ["groupType", "dsAttrTypeNative:"],
"hardwareuuid": ["HardwareUUID", "dsAttrTypeStandard:"],
"heimdalsrpkey": ["HeimdalSRPKey", "dsAttrTypeNative:"],
"ishidden": ["IsHidden", "dsAttrTypeNative:"],
"instancetype": ["instanceType", "dsAttrTypeNative:"],
"iscriticalsystemobject": ["isCriticalSystemObject", "dsAttrTypeNative:"],
"jobtitle": ["JobTitle", "dsAttrTypeStandard:"],
"kerberoskeys": ["KerberosKeys", "dsAttrTypeNative:"],
"kerberosservices": ["KerberosServices", "dsAttrTypeStandard:"], //host, afpserver, cifs, vnc, etc
"lastname": ["LastName", "dsAttrTypeStandard:"],
"lastlogoff": ["lastLogoff", "dsAttrTypeNative:"],
"lastlogon": ["lastLogon", "dsAttrTypeNative:"],
"lastlogontimestamp": ["lastLogonTimestamp", "dsAttrTypeNative:"],
"localpolicyglags": ["localPolicyFlags", "dsAttrTypeNative:"],
"logoncount": ["logonCount", "dsAttrTypeNative:"],
"logonhours": ["logonHours", "dsAttrTypeNative:"],
"ldapsearchbasesuffix": ["LDAPSearchBaseSuffix", "dsAttrtypeStandard:"],
"automountmap": ["AutomountMap", "dsAttrTypeStandard:"],
"applemetanodelocation": ["AppleMetaNodeLocation", "dsAttrTypeStandard:"],
"applemetarecordname": ["AppleMetaRecordName", "dsAttrTypeStandard:"],
"machineserves": ["MachineServes", "dsAttrTypeStandard:"],
"mcxflags": ["MCXFlags", "dsAttrTypeStandard:"],
"mcxsettings": ["MCXSettings", "dsAttrTypeStandard:"],
"middlename": ["MiddleName", "dsAttrTypeStandard:"],
"member": ["member", "dsAttrTypeNative:"],
"memberof": ["memberOf", "dsAttrTypeNative:"],
"members": ["members", "dsAttrTypeNative:"],
"msdfsr-computerreferencebl": ["msDFSR-ComputerReferenceBL", "dsAttrTypeNative:"],
"msds-generationid": ["msDS-GenerationId", "dsAttrTypeNative:"],
"msds-supportedencryptiontypes":["msDS-SupportedEncryptionTypes", "dsAttrTypeNative:"],
"modificationtimestamp": ["ModificationTimestamp", "dsAttrTypeStandard:"],
"name": ["name", "dsAttrTypeNative:"],
"networkaddress": ["networkAddress", "dsAttrTypeNative:"],
"networkview": ["NetworkView", "dsAttrTypeStandard:"],
"nfshomedirectory": ["NFSHomeDirectory", "dsAttrTypeStandard:"],
"nodesaslrealm": ["NodeSASLRealm", "dsAttrTypeStandard:"],
"note": ["Note", "dsAttrTypeStandard:"],//says this is for last name attribute???
"objectclass": ["objectClass", "dsAttrTypeNative:"],
"objectcategory": ["objectCategory", "dsAttrTypeNative:"],
"objectguid": ["objectGUID", "dsAttrTypeNative:"],
"objectsid": ["objectSid", "dsAttrTypeNative:"],
"olcdatabase": ["OLCDatabase", "dsAttrTypeStandard:"],
"olcdatabaseindex": ["OLCDatabaseIndex", "dsAttrTypeStandard:"],
"olcsyncrepl": ["OLCSyncRepl", "dsAttrTypeStandard:"],
"operatingsystem": ["operatingSystem", "dsAttrTypeNative:"],
"operatingsystemversion": ["operatingSystemVersion", "dsAttrTypeNative:"],
"owner": ["Owner", "dsAttrTypeStandard:"],
"ownerguid": ["OwnerGUID", "dsAttrTypeStandard:"],
"password": ["Password", "dsAttrTypeStandard:"],
"passwordplus": ["PasswordPlus", "dsAttrTypeStandard:"],//indicates authentication redirection
"passwordpolicyoptions": ["PasswordPolicyOptions", "dsAttrTypeStandard:"],
"passwordserverlist": ["PasswordServerList", "dsAttrTypeStandard:"],
"passwordserverlocation": ["PasswordServerLocation", "dsAttrTypeStandard:"],
"port": ["Port", "dsAttrTypeStandard:"],//which port a service is on
"presetuserisadmin": ["PresetUserIsAdmin", "dsAttrTypeStandard:"],
"primarycomputerguid": ["PrimaryComputerGUID", "dsAttrTypeStandard:"],
"primarycomputerlist": ["PrimaryComputerList", "dsAttrTypeStandard:"],
"primarygroupid": ["PrimaryGroupID", "dsAttrTypeStandard:"],
"profiles": ["Profiles", "dsAttrTypeStandard:"],
"profilestimestamp": ["ProfilesTimestamp", "dsAttrTypeStandard:"],
"realname": ["RealName", "dsAttrTypeStandard:"], //Yes, fullname maps to realname because... apple
"realuserid": ["RealUserID", "dsAttrTypeStandard:"],
"relativednprefix": ["RelativeDNPrefix", "dsAttrTypeStandard:"],//relative distinguished name,
"ridsetreferences": ["rIDSetReferences", "dsAttrTypeNative:"],
"samaccountname": ["sAMAccountName", "dsAttrTypeNative:"],
"samaccounttype": ["sAMAccountType", "dsAttrTypeNative:"],
"serverreferencebl": ["serverReferenceBL", "dsAttrTypeNative:"],
"serviceprincipalname": ["servicePrincipalName", "dsAttrTypeNative:"],
"shadowhashdata": ["ShadowHashData", "dsAttrTypeNative:"],
"smbacctflags": ["SMBAccountFlags", "dsAttrTypeStandard:"],//account control flag
"smbgrouprid": ["SMBGroupRID", "dsAttrTypeStandard:"], //define PDC SMB interaction with DirectoryService
"smbhome": ["SMBHome", "dsAttrTypeStandard:"],//UNC address of a windows home directory mount point
"smbhomedrive": ["SMBHomeDrive", "dsAttrTypeStandard:"],
"smbprimarygroupsid": ["SMBPrimaryGroupSID", "dsAttrTypeStandard:"],
"smbpasswordlastset": ["SMBPasswordLastSet", "dsAttrTypeStandard:"],// used in SMB interaction
"smbprofilepath": ["SMBProfilePath", "dsAttrTypeStandard:"],//defines desktop management info
"smbrid": ["SMBRID", "dsAttrTypeStandard:"], //used in SMB interaction
"smbscriptpath": ["SMBScriptPath", "dsAttrTypeStandard:"],//define SMB login script path
"smbsid": ["SMBSID", "dsAttrTypeStandard:"], //define SMB Security ID
"smbuserworkstations": ["SMBUserWorkstations", "dsAttrTypeStandard:"],//list of workstations a user can log in from
"smblogofftime": ["SMBLogoffTime", "dsAttrTypeStandard:"],
"smblogontime": ["SMBLogonTime", "dsAttrTypeStandard:"],
"smb_createmask": ["smb_createmask", "dsAttrTypeNative:"],
"smb_directorymask": ["smb_directorymask", "dsAttrTypeNative:"],
"smb_guestaccess": ["smb_guestaccess", "dsAttrTypeNative:"],
"smb_name": ["smb_name", "dsAttrTypeNative:"],
"smb_shared": ["smb_shared", "dsAttrTypeNative:"],
"servicetype": ["ServiceType", "dsAttrTypeStandard:"],//define SMB login script path
"serviceslocator": ["ServicesLocator", "dsAttrTypeStandard:"],
"setupadvertising": ["SetupAssistantAdvertising", "dsAttrTypeStandard:"],//raw service type of a service, ex: http or https for kODRecordTypeWebServer
"sharepoint_account_uuid": ["sharepoint_account_uuid", "dsAttrTypeNative:"],
"sharepoint_group_id": ["sharepoint_group_id", "dsAttrTypeNative:"],
"showinadvancedviewonly": ["showInAdvancedViewOnly", "dsAttrTypeNative:"],
"uniqueid": ["UniqueID", "dsAttrTypeStandard:"], //user's 32bit ID in legacy manner
"unlockoptions": ["unlockOptions", "dsAttrTypeNative:"],
"url": ["URL", "dsAttrTypeStandard:"],
"users": ["users", "dsAttrTypeNative:"],
"usnchanged": ["uSNChanged", "dsAttrTypeNative:"],
"usncreated": ["uSNCreated", "dsAttrTypeNative:"],
"useraccountcontrol": ["userAccountControl", "dsAttrTypeNative:"],
"usercertificate": ["UserCertificate", "dsAttrTypeStandard:"],
"userpkcs12data": ["UserPKCS12Data", "dsAttrTypeStandard:"],
"usershell": ["UserShell", "dsAttrTypeStandard:"],
"usersmimecertificate": ["UserSMIMECertificate", "dsAttrTypeStandard:"],
"webloguri": ["WeblogURI", "dsAttrTypeStandard:"],//URI of a user's weblog
"whenchanged": ["whenChanged", "dsAttrTypeNative:"],
"whencreated": ["whenCreated", "dsAttrTypeNative:"],
"_writers_usercertificate": ["_writers_UserCertificate", "dsAttrTypeNative:"],
"_writers_hint": ["_writers_hint", "dsAttrTypeNative:"],
"_writers_passwd": ["_writers_passwd", "dsAttrTypeNative:"],
"_writers_unlockoptions": ["_writers_unlockOptions", "dsAttrTypeNative:"],
"_writers_usercertificate": ["_writers_UserCertificate", "dsAttrTypeNative:"],
"xmlplist": ["XMLPlist", "dsAttrTypeStandard:"],//specify an XML Property List
"protocolnumber": ["ProtocolNumber", "dsAttrTypeStandard:"],
"rpcnumber": ["RPCNumber", "dsAttrTypeStandard:"],
"networknumber": ["NetworkNumber", "dsAttrTypeStandard:"],
"accesscontrolentry": ["AccessControlEntry", "dsAttrTypeStandard:"],
"authenticationauthority": ["AuthenticationAuthority", "dsAttrTypeStandard:"], //specify mechanism used to verify or set a user's password
"authorityrevocationlist": ["AuthorityRevocationList", "dsAttrTypeStandard:"],
"automountinformation": ["AutomountInformation", "dsAttrTypeStandard:"],
"computers": ["Computers", "dsAttrTypeStandard:"],
"dnsname": ["DNSName", "dsAttrTypeStandard:"],
"group": ["Group", "dsAttrTypeStandard:"],//store a list of groups
"groupmembers": ["GroupMembers", "dsAttrTypeStandard:"], //specify GUID values of members of a group that are not groups
"groupmembership": ["GroupMembership", "dsAttrTypeStandard:"], //specify list of users that belong to a given group
"groupservices": ["GroupServices", "dsAttrTypeStandard:"],//XML plist to define group's services,
"homedirectory": ["HomeDirectory", "dsAttrTypeStandard:"],
"imhandle": ["IMHandle", "dsAttrTypeStandard:"],//user's instant messaging handles
"ipaddress": ["IPAddress", "dsAttrTypeStandard:"],
"ipv6address": ["IPv6Address", "dsAttrTypeStandard:"],
"kdcauthkey": ["KDCAuthKey", "dsAttrTypeStandard:"],//store a KDC master key
"kdcconfigdata": ["KDCConfigData", "dsAttrTypeStandard:"],
"keywords": ["Keywords", "dsAttrTypeStandard:"],
"ldapreadreplicas": ["LDAPReadReplicas", "dsAttrTypeStandard:"],//list of LDAP server URLs that can be used to read directory data
"ldapwritereplicas": ["LDAPWriteReplicas", "dsAttrTypeStandard:"],
"linkedidentity": ["LinkedIdentity", "dsAttrTypeNative:"],
"localerelay": ["LocaleRelay", "dsAttrTypeStandard:"],
"localesubnets": ["LocaleSubnets", "dsAttrTypeStandard:"],
"nestedgroups": ["NestedGroups", "dsAttrTypeStandard:"], //specify list of nested group GUID values in a group attribute
"netgroups": ["NetGroups", "dsAttrTypeStandard:"],//specify a list of net groups that a user or host record is a member of
"nickname": ["NickName", "dsAttrTypeStandard:"],
"organizationinfo": ["OrganizationInfo", "dsAttrTypeStandard:"],
"organizationname": ["OrganizationName", "dsAttrTypeStandard:"],
"pgppublickey": ["PGPPublicKey", "dsAttrTypeStandard:"],
"protocols": ["Protocols", "dsAttrTypeStandard:"],
"recordname": ["RecordName", "dsAttrTypeStandard:"],
"record_daemon_version": ["record_daemon_version", "dsAttrTypeNative:"],
"relationships": ["Relationships", "dsAttrTypeStandard:"],
"resourceinfo": ["ResourceInfo", "dsAttrTypeStandard:"],
"resourcetype": ["ResourceType", "dsAttrTypeStandard:"],
"authcredential": ["AuthCredential", "dsAttrTypeStandard:"],//stores an authentication credential used to authenticate to a directory
"daterecordcreated": ["DateRecordCreated", "dsAttrTypeStandard:"],
"kerberosflags": ["KerberosFlags", "dsAttrTypeNative:"],
"kerberosrealm": ["KerberosRealm", "dsAttrTypeStandard:"],
"ntdomaincomputeraccount": ["NTDomainComputerAccount", "dsAttrTypeStandard:"],//support kerberos SMB server services
"primaryntdomain": ["PrimaryNTDomain", "dsAttrTypeStandard:"],
"pwdagingpolicy": ["PwdAgingPolicy", "dsAttrTypeStandard:"],//record's password aging policy
"readonlynode": ["ReadOnlyNode", "dsAttrTypeStandard:"],
"authmethod": ["AuthMethod", "dsAttrTypeStandard:"],//specify a record's authentication method
"recordtype": ["RecordType", "dsAttrTypeStandard:"], //specify type of a record or directory node
"advertisedservices": ["AdvertisedServices", "dsAttrTypeStandard:"],//specify (Bounjour) advertised services
"networkinterfaces": ["NetworkInterfaces", "dsAttrTypeStandard:"],
"primarylocale": ["PrimaryLocale", "dsAttrTypeStandard:"]
}
var node_list = {
"network": 0x2205,//$.kODNodeTypeNetwork,
"local": 0x2200,//$.kODNodeTypeLocalNodes,
"config": 0x2202,//$.kODNodeTypeConfigure,
"contacts": 0x2204,//$.kODNodeTypeContacts
}
// helper functions to actually do the OD queries and return results
function Get_OD_ObjectClass({objectclass="Users", match="Any", value=null, max_results=0, query_attributes="All", return_attributes=[null], nodetype='network'} = {}){
//gets all attributes for all local users
var session = Ref();
var node = Ref();
var query = Ref();
session = $.ODSession.defaultSession;
//console.log(session);
var fixed_return_attributes = [];
for(var i in return_attributes){
if(return_attributes[i] != null){
ret_attr_lower = return_attributes[i].toLowerCase();
if(attributes_list.hasOwnProperty(ret_attr_lower)){
fixed_return_attributes.push(attributes_list[ret_attr_lower][1] + attributes_list[ret_attr_lower][0]);
}
}else{
fixed_return_attributes.push(null);
}
}
if(fixed_return_attributes.length == 1){
fixed_return_attributes = fixed_return_attributes[0];
}
if(attributes_list.hasOwnProperty(query_attributes.toLowerCase())){
query_attr_lower = query_attributes.toLowerCase();
query_attributes = attributes_list[query_attr_lower][1] + attributes_list[query_attr_lower][0];
}
else{
console.log("query attribute " + query_attributes + " not found");
return;
}
//console.log(fixed_return_attributes);
node = $.ODNode.nodeWithSessionTypeError(session, node_list[nodetype], null);
//console.log("about to print subnode names\n");
//console.log(ObjC.deepUnwrap($.ODNodeCopySubnodeNames(node, $())));
//console.log("about to print supported attributes\n");
//console.log(JSON.stringify([ObjC.deepUnwrap($.ODNodeCopySupportedAttributes(node, object_class[objectclass], $()))], null, 2));
//https://developer.apple.com/documentation/opendirectory/odquery/1391709-querywithnode?language=objc
//console.log("about to print supported record types\n");
//console.log(JSON.stringify([ObjC.deepUnwrap($.ODNodeCopySupportedRecordTypes(node, $()))], null, 2));
query = $.ODQuery.queryWithNodeForRecordTypesAttributeMatchTypeQueryValuesReturnAttributesMaximumResultsError(
node,
object_class[objectclass], //(objectclass) https://developer.apple.com/documentation/opendirectory/opendirectory_functions/record_types?language=objc
query_attributes, //set to recordname that we're looking to match
match_type[match], //( equals, beginsWith, contains, etc) https://developer.apple.com/documentation/opendirectory/opendirectory_functions/match_types?language=objc
value, // input query (like admin)
fixed_return_attributes,
max_results, //maximum number of results, 0=all
$()); //error
var results = query.resultsAllowingPartialError(false, null);
//results;
//console.log(results);
var output = {};
output[objectclass] = {};
for(var i = 0; i < results.count; i++){
var error = Ref();
var attributes = results.objectAtIndex(i).recordDetailsForAttributesError($(),error);
var keys = attributes.allKeys;
output[objectclass][i] = {};
for(var j = 0; j < keys.count; j++){
var key = ObjC.unwrap(keys.objectAtIndex(j));
var array = attributes.valueForKey(keys.objectAtIndex(j));
var array_length = parseInt($.CFArrayGetCount(array));
var val = [];
for(var k = 0; k < array_length; k++){
if(!array.objectAtIndex(k).isKindOfClass($.NSString.class)){
//console.log(array.objectAtIndex(k).base64EncodedStringWithOptions(null).js);
val.push(array.objectAtIndex(k).base64EncodedStringWithOptions(null).js);
}else{
//console.log(array.objectAtIndex(k));
val.push(array.objectAtIndex(k).js);
}
}
//var val = ObjC.deepUnwrap(attributes.valueForKey(keys.objectAtIndex(j)));
output[objectclass][i][key] = val;
}
}
return output;
}
function Get_OD_Node_Configuration({node="all"} = {}){
let session = $.ODSession.defaultSession;
let names = session.nodeNamesAndReturnError($());
//console.log(names);
names = ObjC.deepUnwrap(names);
let configuration = {};
for(let i in names){
//console.log(names[i]);
let config = session.configurationForNodename(names[i]);
configuration[names[i]] = {};
if(config.nodeName.js !== undefined){
configuration[names[i]]['nodeName'] = config.nodeName.js;
}
configuration[names[i]]['trustAccount'] = ObjC.deepUnwrap(config.trustAccount);
configuration[names[i]]['trustKerberosPrincipal'] = ObjC.deepUnwrap(config.trustKerberosPrincipal);
configuration[names[i]]['trustMetaAccount'] = ObjC.deepUnwrap(config.trustMetaAccount);
configuration[names[i]]['trustType'] = ObjC.deepUnwrap(config.trustType);
configuration[names[i]]['trustUsesKerberosKeytab'] = config.trustUsesKerberosKeytab;
configuration[names[i]]['trustUsesMutualAuthentication'] = ObjC.deepUnwrap(config.trustUsesMutualAuthentication);
configuration[names[i]]['trustUsesSystemKeychain'] = ObjC.deepUnwrap(config.trustUsesSystemKeychain);
if(config.defaultModuleEntries !== undefined){
configuration[names[i]]['defaultMappings'] = ObjC.deepUnwrap(config.defaultModuleEntries);
}
if(config.authenticationModuleEntries !== undefined){
configuration[names[i]]['authenticationModuleEntries'] = config.authenticationModuleEntries;
}
configuration[names[i]]['virtualSubnodes'] = ObjC.deepUnwrap(config.virtualSubnodes);
configuration[names[i]]['templateName'] = ObjC.deepUnwrap(config.templateName);
configuration[names[i]]['preferredDestinationHostName'] = ObjC.deepUnwrap(config.preferredDestinationHostName);
configuration[names[i]]['preferredDestinationHostPort'] = ObjC.deepUnwrap(config.preferredDestinationHostPort);
if(config.discoveryModuleEntries !== undefined){
configuration[names[i]]['discoveryModuleEntries'] = ObjC.deepUnwrap(config.discoveryModuleEntries);
}
}
//node = $.ODNode.nodeWithSessionTypeError(session, $.kODNodeTypeLocalNodes, null);
node = $.ODNode.nodeWithSessionTypeError(session, 0x2200, null);
//var policies = $.ODNodeCopyAccountPolicies(node, $());
let policies = node.accountPoliciesAndReturnError($());
if(policies.js !== undefined){
configuration['Local_policies'] = ObjC.deepUnwrap(policies);
}
//node = $.ODNode.nodeWithSessionTypeError(session, $.kODNodeTypeNetwork, null);
node = $.ODNode.nodeWithSessionTypeError(session, 0x2205, null);
//var policies = $.ODNodeCopyAccountPolicies(node, $());
policies = node.accountPoliciesAndReturnError($());
if(policies.js !== undefined){
configuration['Network_policies'] = ObjC.deepUnwrap(policies);
}
return JSON.stringify(configuration, null, 2);
}
// main functions
function ConvertTo_SID({API=true, object=".\\root", type="Users",help=false} = {}){
//goes from "Domain\User" or "Domain\Group" or "Domain\Computer" to SID
//type should be: Users, Groups, or Computers
if(help){
var output = "";
output += "\\nConvert Users, Groups, Or Computers to domain or local SIDs.";
output += "\\n\"object\" should be either \".\\\\localthing\" or \"NETBIOSDOMAIN\\\\thing\"";
output += "\\n\"type\" should be \"Users\", \"Groups\", or \"Computers\"";
output += "\\ncalled: ConvertTo_SID({object:\".\\\\root\",type:\"Users\"});";
return output;
}
command = "";
splitObject = object.split('\\');
if (splitObject.length != 2)
{
return "Invalid format for the object. Should be DOMAIN\\object\n";
}
if (API == true) {
//Use ObjC calls
if(object.includes(".")){
//we need to do a local query instead
var fixed_query = object.split("\\").slice(1);
var query = Get_OD_ObjectClass({objectclass:type, max_results:1, value:fixed_query, match:"EqualTo", query_attributes:"RecordName", return_attributes:["SMBSID"], nodetype:"local"});
}else{
var query = Get_OD_ObjectClass({objectclass:type, max_results:1, value:object, match:"EqualTo", query_attributes:"RecordName", return_attributes:["SMBSID"]});
}
try{
var sid = query[type][0]["dsAttrTypeStandard:SMBSID"][0];
return sid;
}catch(err){
return "No such object";
}
}
else{
//use command-line functionality
if (splitObject[0] == ".")
{ //do a local query
command = "dscl . read \"/" + type + "/" + splitObject[1] + "\" SMBSID";
}
else{
command = "dscl \"/Active Directory/" + splitObject[0] +
"/All Domains\" read \"/" + type + "/" + splitObject[1] + "\" SMBSID";
}
//output will either have SMBSID: S-1-5... or No Such Key: SMBSID if user exists
try{
output = currApp.doShellScript(command);
if (output.indexOf("SMBSID: S-") != -1)
return output.split(" ")[1].trim();
else
return "No such key";
}
catch(err){
//<dscl_cmd> DS Error: -14136 (eDSRecordNotFound) if object doesn't exist
return err.toString();
}
}
}
function ConvertFrom_SID({API=true, sid="S-1-5-21-3278496235-3004902057-1244587532-512", type="Users",help=false} = {}){
//goes from S-1-5-21-... to "Domain\User", "Domain\Group", or "Domain\Computer"
if(help){
var output = "";
output += "\\nConvert Users, Groups, or Computers from SIDs to names";
output += "\\n\"sid\" should be a full SID value in quotes for either a User, Group, or Computer. No other type is currently supported.";
output += "\\n\"type\" should be \"Users\",\"Groups\", or \"Computers\"";
output += "\\ncalled: ConvertFrom_SID({sid:\"S-1-5-21-3278496235-3004902057-1244587532-512\",type:\"Users\"})";
return output;
}
command = "";
domain = Get_CurrentNETBIOSDomain(API);
if (!domain){
return "Failed to get domain.";
}
if (API == true){
var query = Get_OD_ObjectClass({objectclass:type, max_results:1, value:sid, match:"EqualTo", query_attributes:"SMBSID", return_attributes:["RecordName"]});
try{
var name = query[type][0]["dsAttrTypeStandard:RecordName"][0];
return name;
}catch(err){
return "No such object";
}
}
else{
command = "dscl \"/Active Directory/" + domain + "/All Domains\"" +
" search /" + type + " SMBSID " + sid;
try{
output = currApp.doShellScript(command);
//example output:
//root SMBSID = (
//"S-1-5-18"
//)
//check to make sure we actually got a result
if (output){
user = output.split("\n")[0].split("\t")[0].trim();
return user;
}
return "Command executed returned no output: " + command;
}
catch(err){
return err.toString();
}
}
}
function Get_DomainUser({API=true, user, attribute, requested_domain,limit=0, help=false} = {}){
//returns all users or specific user objects in AD
//can specify different properties they want returned
if(help){
var output = "";
output += "\\nList all domain users or get information on a specific user. If no user is specified, list all users.";
output += "\\n\"user\" should be a domain name.";
output += "\\n\"attribute\" should be a comma separated list of attributes to select from the returned user. This only works in conjunction with a specific user, not when listing out all users.";
output += "\\n\"requested_domain\" should be the NETBIOS domain name to query. Most often this will be left blank and auto filled by the function.";
output += "\\ncalled: Get_DomainUser() <--- list out all domain users";
output += "\\ncalled: Get_DomainUser({user:\"bob\",attribute:\"name, SMBSID\"});";
output += "\\nNote: cannot currently query outside of the current forest";
return output;
}
if (API == true){
if(user){
if(attribute){
var query = Get_OD_ObjectClass({value:user, match:"Contains", query_attributes:"recordname", return_attributes:attribute.split(", "), max_results:limit});
}else{
var query = Get_OD_ObjectClass({value:user, match:"Contains", query_attributes:"recordname", max_results:limit});
}
return JSON.stringify(query, null, 2);
}
if(attribute){
var query = Get_OD_ObjectClass({return_attributes:attribute.split(", "), max_results:limit});
return JSON.stringify(query, null, 2);
}
return JSON.stringify(Get_OD_ObjectClass({max_results:limit}), null, 2);
}
else{
domain = requested_domain ? requested_domain : Get_CurrentNETBIOSDomain(API);
if(user){
command = "dscl \"/Active Directory/" + domain + "/All Domains\" read /Users/" + user;
if(attribute){
command += " " + attribute;
}
}
else{
command = "dscl \"/Active Directory/" + domain + "/All Domains\" ls /Users";
if(attribute){
command += " " + attribute;
}
}
try{
//console.log(command);
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Get_DomainUserViaAttribute({API=true, value, attribute, return_attributes_list=[null],limit=0, help=false} = {}){
if(help){
return "Queries Users for the `attribute` which contains `value` and returns all matching object's attributes specified in `return_attributes_list`."
}
if (API == true){
let query = Get_OD_ObjectClass({value:value, match:"Contains", query_attributes:attribute, max_results:limit, return_attributes:return_attributes_list});
return JSON.stringify(query, null, 2);
} else{
return "Only API supported";
}
}
function Get_LocalUser({API=true, user, attribute, limit=0, help=false} = {}){
//returns all users or specific user objects in AD
//can specify different properties they want returned
if(help){
var output = "";
output += "\\nList all local users or get information on a specific user. If no user is specified, list all users.";
output += "\\n\"user\" should be a local user's name.";
output += "\\n\"attributes\" should be a comma separated list of attributes to select from the returned user. This only works in conjunction with a specific user, not when listing out all users.";
output += "\\ncalled: Get_LocalUser() <--- list out all local users";
output += "\\ncalled: Get_LocalUser({user:\"bob\",attribute:\"name, SMBSID\"});";
return output;
}
if (API == true){
if(user){
if(attribute){
var query = Get_OD_ObjectClass({value:user, match:"Contains", query_attributes:"recordname", return_attributes:attribute.split(","), max_results:limit, nodetype:"local"});
}else{
var query = Get_OD_ObjectClass({value:user, match:"Contains", query_attributes:"recordname", max_results:limit, nodetype:"local"});
}
return JSON.stringify(query, null, 2);
}
if(attribute){
var query = Get_OD_ObjectClass({return_attributes:attribute.split(","), max_results:limit, nodetype:"local"});
return JSON.stringify(query, null, 2);
}
return JSON.stringify(Get_OD_ObjectClass({max_results:limit, nodetype:"local"}), null, 2);
}
else{
if(user){
command = "dscl . read /Users/" + user;
if(attribute){
command += " " + attribute;
}
}
else{
command = "dscl . ls /Users";
if(attribute){
command += " " + attribute;
}
}
try{
//console.log(command);
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Get_DomainComputer({API=true, computer, attribute, limit=0, requested_domain,help=false} = {}){
//returns all computers or specific computer objects in AD
if(help){
var output = "";
output += "\\nList all domain computers or get information on a specific computer. If no computer is specified, list all computer.";
output += "\\n\"computer\" should be a domain computer name.";
output += "\\n\"attributes\" should be a comma separated list of attributes to select from the returned computer. This only works in conjunction with a specific computer, not when listing out all computers.";
output += "\\n\"requested_domain\" should be the NETBIOS domain name to query. Most often this will be left blank and auto filled by the function.";
output += "\\ncalled: Get_DomainComputer() <--- list out all domain computers";
output += "\\ncalled: Get_DomainComputer({computer:\"testmac$\",attribute:\"name\"});";
return output;
}
if (API == true){
if(computer){
if(attribute){
var query = Get_OD_ObjectClass({objectclass:"Computers", value:computer, match:"Contains", query_attributes:"recordname", return_attributes:attribute.split(","), max_results:limit});
}else{
var query = Get_OD_ObjectClass({objectclass:"Computers", value:computer, match:"Contains", query_attributes:"recordname", max_results:limit});
}
return JSON.stringify(query, null, 2);
}
if(attribute){
var query = Get_OD_ObjectClass({objectclass:"Computers", return_attributes:attribute.split(","), max_results:limit});
return JSON.stringify(query, null, 2);
}
return JSON.stringify(Get_OD_ObjectClass({objectclass:"Computers", max_results:limit}), null, 2);
}
else{
domain = requested_domain ? requested_domain : Get_CurrentNETBIOSDomain(API);
if(computer){
command = "dscl \"/Active Directory/" + domain + "/All Domains\" read \"/Computers/" + computer + "\"";
if(attribute){
command += " " + attribute;
}
}
else{
command = "dscl \"/Active Directory/" + domain + "/All Domains\" ls /Computers";
if(attribute){
command += " " + attribute;
}
}
try{
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Get_DomainComputerViaAttribute({API=true, value, attribute, limit=0, return_attributes_list=[null],help=false} = {}){
//returns all computers or specific computer objects in AD
if(help){
return "Queries Computers for the `attribute` which contains `value` and returns all matching object's attributes specified in `return_attributes_list`."
}
if (API == true){
let query = Get_OD_ObjectClass({objectclass:"Computers", value:value, match:"Contains", query_attributes:attribute, max_results:limit, return_attributes:return_attributes_list});
return JSON.stringify(query, null, 2);
} else{
return "Only API supported";
}
}
function Get_LDAPSearch({API=false, currDomain, remoteDomain, numResults=0, query="", attribute,help=false} = {}){
if(help){
var output = "";
output += "\\nExecute a customized LDAP search query";
output += "\\n\"currDomain\" should be the domain to query. Ex: in ldap://currDomain.";
output += "\\n\"remoteDomain\" should be the search base, typically the same as the currDomain, so it can be left out.";
output += "\\n\"numResults\" specifies how many results to return where 0 indicates all results.";
output += "\\n\"query\" is the LDAP query.";
output += "\\n\"attributes\" is a comma separated list of attributes to selet from the query results.";
output += "\\ncalled: Get_LDAPSearch({query=\"(objectclass=user)\"})";
return output;
}
if(API == true){
return "API method not implemented yet";
}
else{
domain = currDomain ? currDomain : Get_CurrentDomain(API);
adjust = remoteDomain ? remoteDomain.split(".") : domain.split(".");
rdomain = "";
for(var i = 0; i < adjust.length; i++){
rdomain += "DC=" + adjust[i];
if(i+1 < adjust.length){
rdomain += ","
}
}
command = "ldapsearch -H ldap://" + domain + " -b " + rdomain + " -z " + numResults + " \"" + query + "\" ";
if(attribute){
command += attribute;
}
//console.log(command);
try{
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Get_DomainOU({API=false, OU, attribute, requested_domain,help=false} = {}){
//search for all OUs or specific OU objects in AD
if(help){
var output = "";
output += "\\nList all domain OUs or get information on a specific OU. If no OU is specified, list all OUs.";
output += "\\n\"OU\" should be a domain OU name.";
output += "\\n\"attributes\" should be a comma separated list of attributes to select from the returned OU. This only works in conjunction with a specific OU, not when listing out all OUs.";
output += "\\n\"requested_domain\" should be the NETBIOS domain name to query. Most often this will be left blank and auto filled by the function.";
output += "\\ncalled: Get_DomainOU() <--- list out all domain computers";
output += "\\ncalled: Get_DomainOU({OU:\"Domain Controllers\"});";
return output;
}
if (API == true){
return "API method not implemented yet";
}
else{
domain = requested_domain ? requested_domain : Get_CurrentNETBIOSDomain(API);
if(OU){
command = "dscl \"/Active Directory/" + domain + "/All Domains\" read \"/OrganizationalUnit/" + OU + "\"";
if(attribute){
command += " " + attribute;
}
}
else{
command = "dscl \"/Active Directory/" + domain + "/All Domains\" ls /OrganizationalUnit";
if(attribute){
command += " " + attribute;
}
}
try{
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Get_DomainSID({API=true,help=false} = {}){
//returns SID for current domain or specified domain
if(help){
var output = "";
output += "\\nGets the SID of the domain by truncating the SID for the \"Domain Admins\" group.";
output += "\\ncalled: Get_DomainSID()";
return output;
}
if(API == true){
var domain = Get_CurrentNETBIOSDomain(API);
var search_value = domain + "\\Domain Computers";
var domain_computers = Get_OD_ObjectClass({objectclass:"Groups", max_results:1, value:search_value, match:"Contains", query_attributes:"RecordName", return_attributes:["SMBSID"]});
var sid = domain_computers["Groups"][0]["dsAttrTypeStandard:SMBSID"][0];
var sid_array = sid.split("-");
return sid_array.slice(0, sid_array.length-1).join("-");
}
else{
command = "dsmemberutil getsid -G \"Domain Admins\"";
try{
output = currApp.doShellScript(command);
return output.slice(0,-4); //take off the last -512 on the SID that's specific to Domain Admins group
}
catch(err){
return err.toString();
}
}
}
function Get_DomainGroup({API=true, group, attribute, requested_domain,help=false,verbose=false, limit=0} = {}){
//returns all groups or specific groups in an AD
if(help){
var output = "";
output += "\\nList all domain groups or get information on a specific group. If no group is specified, list all groups.";
output += "\\n\"group\" should be a domain group name.";
output += "\\n\"attributes\" should be a comma separated list of attributes to select from the returned group. This only works in conjunction with a specific group, not when listing out all group.";
output += "\\n\"requested_domain\" should be the NETBIOS domain name to query. Most often this will be left blank and auto filled by the function.";
output += "\\ncalled: Get_DomainGroup() <--- list out all domain groups";
output += "\\ncalled: Get_DomainGroup({group:\"Domain Admins\",attribute:\"GroupMembership\"});";
return output;
}
if(API == true){
if(group){
if(attribute){
var query = Get_OD_ObjectClass({objectclass:"Groups", value:group, match:"Contains", query_attributes:"recordname", return_attributes:attribute.split(","), max_results:limit});
}else{
var query = Get_OD_ObjectClass({objectclass:"Groups", value:group, match:"Contains", query_attributes:"recordname", max_results:limit});
}
return JSON.stringify(query, null, 2);
}
if(attribute){
var query = Get_OD_ObjectClass({objectclass:"Groups", return_attributes:attribute.split(","), max_results:limit});
return JSON.stringify(query, null, 2);
}
return JSON.stringify(Get_OD_ObjectClass({objectclass:"Groups", max_results:limit}), null, 2);
}
else{
domain = requested_domain ? requested_domain : Get_CurrentNETBIOSDomain(API);
if(group){
if(verbose){
command = "dscl \"/Active Directory/" + domain + "/All Domains\" read \"/Groups/" + group + "\"";
if(attribute){
command += " " + attribute;
}
}else{
command = "dscacheutil -q group -a name \"" + group + "\"";
}
}
else{
command = "dscl \"/Active Directory/" + domain + "/All Domains\" ls /Groups";
if(attribute){
command += " " + attribute;
}
}
try{
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Get_LocalGroup({API=true, group, attribute,help=false, verbose=false, limit=0} = {}){
//returns all groups or specific groups in an AD
if(help){
var output = "";
output += "\\nList all local groups or get information on a specific group. If no group is specified, list all groups.";
output += "\\n\"group\" should be a local group name.";
output += "\\n\"verbose\" get more verbose output with dscl instead of dscacheutil"
output += "\\n\"attributes\" should be a comma separated list of attributes to select from the returned group. This only works in conjunction with a specific group, not when listing out all groups, and only when verbose is true.";
output += "\\ncalled: Get_LocalGroup() <--- list out all domain groups";
output += "\\ncalled: Get_LocalGroup({group:\"admin\",attributes:\"GroupMembership\"});";
output += "\\ncalled: Get_LocalGroup({attribute:\"GroupMembership\", verbose:true}); <--- get a mapping of all groups and their GroupMembership";
return output;
}
if(API == true){
if(group){
if(attribute){
var query = Get_OD_ObjectClass({objectclass:"Groups", value:group, match:"Contains", query_attributes:"recordname", return_attributes:attribute.split(","), max_results:limit, nodetype:"local"});
}else{
var query = Get_OD_ObjectClass({objectclass:"Groups", value:group, match:"Contains", query_attributes:"recordname", max_results:limit, nodetype:"local"});
}
return JSON.stringify(query, null, 2);
}
if(attribute){
var query = Get_OD_ObjectClass({objectclass:"Groups", return_attributes:attribute.split(","), max_results:limit, nodetype:"local"});
return JSON.stringify(query, null, 2);
}
return JSON.stringify(Get_OD_ObjectClass({objectclass:"Groups", max_results:limit, nodetype:"local"}), null, 2);
}
else{
if(group){
if(verbose){
command = "dscl . read \"/Groups/" + group + "\"";
if(attribute){
command += " " + attribute;
}
}
else{
command = "dscacheutil -q group -a name " + group;
}
}
else{
if(verbose){
command = "dscl . ls /Groups";
if(attribute){
command += " " + attribute;
}
}
else{
command = "dscacheutil -q group";
}
}
try{
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Get_DomainGroupMember({API=true, group="Domain Admins", domain,help=false, limit=0} = {}){
if(help){
var output = "";
output += "\\nGet all the members of a specific domain group";
output += "\\n\"group\" should be a specific domain group to query.";
output += "\\n\"domain\" is the NETBIOS domain name to query, but if not specified, the function will figure it out.";
output += "\\ncalled: Get_DomainGroupMember({group:\"Domain Admins\"});";
return output;
}
//return members of a specific domain group
if(!domain){
domain = Get_CurrentNETBIOSDomain(API);
}
if (API == true){
return Get_DomainGroup({group:group, attribute:"distinguishedName,member,memberOf,nestedgroups,groupmembership", limit:limit});
}
else{
try{
if(group){
command = "dscl \"/Active Directory/" + domain + "/All Domains\" read \"/Groups/" + group + "\" GroupMembership";
}
else{
command = "dscl \"/Active Directory/" + domain + "/All Domains\" ls /Groups GroupMembership";
}
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Get_LocalGroupMember({API=true, group,help=false, limit=0} = {}){
if(help){
var output = "";
output += "\\nGet all the members of a specific local group";
output += "\\n\"group\" should be a specific local group to query.";
output += "\\ncalled: Get_LocalGroupMember({group:\"admin\"});";
return output;
}
if (API == true){
return Get_LocalGroup({group:group, attribute:"GroupMembership,nestedGroups,member,memberOf,nestedgroups",limit:limit});
}
else{
try{
if(group){
command = "dscl . read \"/Groups/" + group + "\" GroupMembership";
}
else{
command = "dscl . ls /Groups GroupMembership"
}
output = currApp.doShellScript(command);
return output;
}
catch(err){
return err.toString();
}
}
}
function Search_LocalGroup({API=false, attribute="GroupMembership", value="", help=false} = {}){
if(help){
var output = "";
output += "\\nSearch a specific group attribute for a specific value";
output += "\\n\"attribute\" is a specific group attribute to search through, default is \"GroupMembership\"";
output += "\\n\"value\" is the value to search for";
output += "\\ncalled: Search_LocalGroups({attribute:\"GroupMembership\", value:\"username\"});";
return output;
}
if (API == true){
return "API method not implemented yet";
}
else{
try{
command = "dscl . -search /Groups " + attribute + " " + value;
output = currApp.doShellScript(command);
return output;
}catch(err){
return err.toString();
}
}
}
function Search_DomainGroup({API=false, attribute="GroupMembership", value="", help=false, domain} = {}){
if(help){
var output = "";
output += "\\nSearch a specific group attribute for a specific value";
output += "\\n\"attribute\" is a specific group attribute to search through, default is \"GroupMembership\"";
output += "\\n\"value\" is the value to search for";
output += "\\ncalled: Search_DomainGroups({attribute:\"GroupMembership\", value:\"username\"});";
return output;
}
if(!domain){
domain = Get_CurrentNETBIOSDomain(API);
}
if (API == true){
return "API method not implemented yet";
}
else{
command = "dscl \"/Active Directory/" + domain + "/All Domains\" -search /Groups " + attribute + " " + value;
try{
output = currApp.doShellScript(command);
return output;
}
catch(error){
return error.toString();
}
}
}
function Search_LocalUser({API=false, attribute="UserShell", value="/bin/bash", help=false} = {}){
if(help){
var output = "";
output += "\\nSearch local users attribute for a specific value";
output += "\\n\"attribute\" is a specific user attribute to search through, default is \"UserShell\"";
output += "\\n\"value\" is the value to search for, default is \"/bin/bash\"";
output += "\\ncalled: Search_LocalUsers({attribute:\"UserShell\", value:\"/bin/bash\"});";
return output;
}
if (API == true){
return "API method not implemented yet";
}
else{
try{
command = "dscl . -search /Users " + attribute + " " + value;
output = currApp.doShellScript(command);
return output;
}catch(err){
return err.toString();
}
}
}
function Search_DomainUser({API=false, attribute="", value="", help=false, domain} = {}){
if(help){
var output = "";
output += "\\nSearch a specific group attribute for a specific value";
output += "\\n\"attribute\" is a specific user attribute to search through, default is \"\"";
output += "\\n\"value\" is the value to search for";
output += "\\ncalled: Search_DomainUsers({attribute:\"\", value:\"username\"});";
return output;
}
if(!domain){
domain = Get_CurrentNETBIOSDomain(API);
}
if (API == true){
return "API method not implemented yet";
}
else{
command = "dscl \"/Active Directory/" + domain + "/All Domains\" -search /Users " + attribute + " " + value;
try{
output = currApp.doShellScript(command);
return output;
}
catch(error){
return error.toString();
}
}
}
////////////////////////////////////////////////
///////// HELPER FUNCTIONS /////////////////////
////////////////////////////////////////////////
function Get_CurrentDomain(API=true,help=false){
if(help){
var output = "";
output += "\\nGet the fully qualified current domain";
output += "\\ncalled: Get_CurrentDomain();";
return output;
}
if(API == true){
var config = Get_OD_Node_Configuration();
var keys = Object.keys(config);
for(var i in keys){
if(config[keys[i]]['nodeName'] != "Contacts" && config[keys[i]]['nodeName'] != "Search" && config[keys[i]]['nodeName']){
return config[keys[i]]['trustKerberosPrincipal'].split("@")[1];
}
}
return "No domain found";
}
else{
try{
output = currApp.doShellScript("dsconfigad -show");
//Active Directory Forest = forest.tld
//Active Directory Domain = domain.tld
//Computer Account = computer-name
//a bunch of others with (something = something) format
//Look into Advanced Options - Administrative
// preferred domain controller, allowed admin group
components = output.split("\r");
domain = components[1].split("=")[1].trim();
return domain;
}
catch(err){
return err.toString();
}
}
}
function Get_CurrentNETBIOSDomain(API=true,help=false){
if(help){
let output = "";
output += "\\nGet the NETBIOS name of the current domain";
output += "\\ncalled: Get_CurrentNETBIOSDomain();";
return output;
}
if(API == true){
let config = Get_OD_Node_Configuration();
let keys = Object.keys(config);
for(let i in keys){
if(config[keys[i]].hasOwnProperty('nodeName') && config[keys[i]]['nodeName'] != "Contacts" && config[keys[i]]['nodeName'] != "Search"){
return config[keys[i]]['nodeName'];
}
}
return "No Domain Found";
}
else{
try{
let output = currApp.doShellScript("echo show com.apple.opendirectoryd.ActiveDirectory | scutil");
//<dictionary>{
//DomainForestName : test.local
//DomainGuid : 01FDCACC-C89D-45B8-8829-3BAB54490F6C
//DomainNameDns : test.local
//DomainNameFlat : TEST
//MachineRole : 3
//NodeName: /Active Directory/TEST
//TrustAccount : testmac$
//}
components = output.split("\r");
domain = components[4].split(":")[1].trim();
return domain;
}
catch(err){
return err.toString();
}
}
}
function Get_Forest(API=false,help=false){
if(help){
var output = "";
output += "\\nGet the fully qualified forest name";
output += "\\ncalled: Get_Forest();";
return output;
}
if(API == true){
return "API method not implemented yet";
}
else{
try{
output = currApp.doShellScript("dsconfigad -show");
//Active Directory Forest = forest.tld
//Active Directory Domain = domain.tld
//Computer Account = computer-name
//a bunch of others with (something = something) format
//Look into Advanced Options - Administrative
// preferred domain controller, allowed admin group
components = output.split("\r");
forest = components[0].split("=")[1].trim();
return forest;
}
catch(err){
return err.toString();
}
}
}