diff -urbN smeserver-samba-0.1.0/createlinks smeserver-samba-0.1.0-072416-update/createlinks --- smeserver-samba-0.1.0/createlinks 2016-07-29 20:46:38.899060240 -0700 +++ smeserver-samba-0.1.0-072416-update/createlinks 2016-07-29 21:31:49.086060261 -0700 @@ -2,54 +2,136 @@ use esmith::Build::CreateLinks qw(:all); +#==================================================== +#DEFAULTS +#==================================================== +my $schemaPath='/home/e-smith/files/server-resources/schema/'; -safe_symlink("../daemontools", "root/etc/rc.d/init.d/supervise/smb"); +#==================================================== +#SERVER-MANAGER +#==================================================== ##Set server-manager links #my $panel = "manager"; #panel_link("workgroup", $panel); -##Define events that templates2expand expands smb.conf -templates2events("/etc/samba/smb.conf", qw( - provision-domain-controller - bootstrap-initialize-samba)); - -##Define events that templates2expand expands krb5.conf -templates2events("/etc/krb5.conf", qw( - provision-domain-controller - bootstrap-initialize-samba)); -##Links for provision-domain-controller event +#==================================================== +#EVENTS +#==================================================== + +#---------------------------------------------------- +#provision-domain-controller +#---------------------------------------------------- +$event = "provision-domain-controller"; + +#Define action links $event = "provision-domain-controller"; -event_link("adjust-samba-down", $event, "01"); event_link("initialize-default-databases", $event, "01"); event_link("provision-domain-controller", $event, "01"); event_link("samba-reset-defaults", $event, "02"); -event_link("samba-create-domain-admins", $event,"03"); -event_link("adjust-samba-up", $event, "50"); +event_link("AD-schema-modify", $event,"30"); +event_link("samba-create-domain-admins", $event, "60"); -##Links for user-create -$event = "user-create"; -event_link("user-create-AD", $event, "04"); +#Define templates2expand +templates2events('/etc/samba/smb.conf',$event); +templates2events('/etc/krb5.conf',$event); +templates2events($schemaPath.'extendedADAttributes.ldif',$event); +templates2events($schemaPath.'koozaliADClass.ldif',$event); +templates2events($schemaPath.'modifyADSchema.ldif',$event); +templates2events($schemaPath.'setupAdmins.ldif',$event); + +#Define services2adjust +event_services($event, ( + 'smb' => 'sighup' + )); + +#---------------------------------------------------- +#bootstrap-proviision-dc +#---------------------------------------------------- +$event = "bootstrap-provision-dc"; -##Links for adjust-samba event -$event = "adjust-samba"; -event_link("adjust-samba-down", $event, "20"); -event_link("adjust-samba-up", $event, "30"); - -##Links for bootstrap-intialize-samba event -$event = "bootstrap-initialize-samba"; -event_link("provision-domain-controller", $event, "02"); +#Define action links +event_link("provision-domain-controller", $event, "01"); event_link("samba-reset-defaults", $event, "02"); -event_link("samba-create-domain-admins", $event,"03"); +event_link("AD-schema-modify", $event,"30"); +event_link("samba-create-domain-admins", $event, "60"); +#Define templates2expand +templates2events('/etc/samba/smb.conf',$event); +templates2events('/etc/krb5.conf',$event); +templates2events($schemaPath.'extendedADAttributes.ldif',$event); +templates2events($schemaPath.'koozaliADClass.ldif',$event); +templates2events($schemaPath.'modifyADSchema.ldif',$event); +templates2events($schemaPath.'setupAdmins.ldif',$event); + +#---------------------------------------------------- +#user-create +#---------------------------------------------------- +$event = "user-create"; + +#Define action links +event_link("user-create-AD", $event, "04"); -##Link smb to daemontools +#---------------------------------------------------- +#group-create +#---------------------------------------------------- +$event = "group-create"; + +#Define action links +event_link("group-create-AD", $event, "04"); + +#---------------------------------------------------- +#post-upgrade +#---------------------------------------------------- +$event = 'post-upgrade'; + +#Define templates2expand +templates2events('/etc/samba/smb.conf',$event); +templates2events('/etc/krb5.conf',$event); +templates2events($schemaPath.'extendedADAttributes.ldif',$event); +templates2events($schemaPath.'koozaliADClass.ldif',$event); +templates2events($schemaPath.'modifyADSchema.ldif',$event); +templates2events($schemaPath.'setupAdmins.ldif',$event); + +#---------------------------------------------------- +#post-install +#---------------------------------------------------- +$event = 'post-install'; + +#Define templates2expand +templates2events('/etc/samba/smb.conf',$event); +templates2events('/etc/krb5.conf',$event); +templates2events($schemaPath.'extendedADAttributes.ldif',$event); +templates2events($schemaPath.'koozaliADClass.ldif',$event); +templates2events($schemaPath.'modifyADSchema.ldif',$event); +templates2events($schemaPath.'setupAdmins.ldif',$event); + + +#==================================================== +#SERVICE SETUP +#==================================================== +#Link smb to daemontools safe_symlink("daemontools", "root/etc/rc.d/init.d/smb"); safe_symlink("/var/service/smb", "root/service/smb"); +safe_symlink("../daemontools", "root/etc/rc.d/init.d/supervise/smb"); ##Run level links to smb service safe_symlink("/etc/rc.d/init.d/supervise/smb", "root/etc/rc.d/rc7.d/S91smb"); safe_symlink("/etc/rc.d/init.d/supervise/smb", "root/etc/rc.d/rc6.d/K35smb"); safe_symlink("/etc/rc.d/init.d/supervise/smb", "root/etc/rc.d/rc1.d/K35smb"); safe_symlink("/etc/rc.d/init.d/supervise/smb", "root/etc/rc.d/rc0.d/K35smb"); + +#==================================================== +#MISC +#==================================================== +#Create template-begin files and empty config files schema templates +foreach (qw(extendedADAttributes.ldif + koozaliADClass.ldif + modifyADSchema.ldif + setupAdmins.ldif)) +{ + safe_touch("root/$schemaPath/$_"); + safe_touch("root/etc/e-smith/templates/$schemaPath/$_/template-begin"); +} + diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/events/actions/AD-schema-modify smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/AD-schema-modify --- smeserver-samba-0.1.0/root/etc/e-smith/events/actions/AD-schema-modify 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/AD-schema-modify 2016-07-05 23:31:44.000000000 -0700 @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w +#------------------------------------------------------------ +#This action modifies the Active Directory with +#attributes specific to Koozali SME Server +# +#Copyright 2016 Koozali Foundation, Inc. +#06/30/2016: G.Zartman +# +#The code contained herein can be distributed under the same +#license as Perl +#------------------------------------------------------------ +use strict; +use warnings; + +##Pull arguments +my $event = $ARGV [0] || 'none'; + +##Set a few path vars to abbreviate the systems commands +my $ldifs = '/home/e-smith/files/server-resources/schema/'; +my $ad = '/var/lib/samba/private/sam.ldb'; + +warn "Extending Active Directory:\n"; + +##Add Attributes +warn "Attributes: quota and smeCustom\n"; +my $addAttributes = '/usr/bin/ldbadd -H ' . + "$ad " . + $ldifs . 'extendedADAttributes.ldif ' . + '--option="dsdb:schema update allowed"=true'; +system ($addAttributes); + + +##Create Koozali Object Class for new attributes +my $addKoozaliClass = '/usr/bin/ldbadd -H ' . + "$ad " . + $ldifs . 'koozaliADClass.ldif ' . + '--option="dsdb:schema update allowed"=true'; +system ($addKoozaliClass); + + +##Apply User class updates +warn "Attempting to register User Class\n"; +my $modifyUserClass = '/usr/bin/ldbmodify -H ' . + "$ad " . + $ldifs . 'modifyADSchema.ldif ' . + '--option="dsdb:schema update allowed"=true'; + +system ($modifyUserClass); diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/events/actions/group-create-AD smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/group-create-AD --- smeserver-samba-0.1.0/root/etc/e-smith/events/actions/group-create-AD 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/group-create-AD 2016-07-02 10:45:54.000000000 -0700 @@ -0,0 +1,90 @@ +#!/usr/bin/perl -w + +#------------------------------------------------------------ +#This action creates an Active Directory group +# +#Command format: +# +# group-create-AD event username data: +# +# event : calling event name +# username : unique groupname +# data : Hash reference to user data to populate the AD +# with. See esmith::AD::Groups->attributes() for +# supported group attributes +# +# +#Note: This action uses the samba-tool utility to add a new +# group the the Active Directory. Samba-tool does not +# exit very gracefully if it has a problem, so this +# action may throw some really funky error messages +# +#Copyright 2016 Koozali Foundation, Inc. +#07/02/2016: G.Zartman +# +#The code contained herein can be distributed under the same +#license as Perl +# +#TODO +# +#------------------------------------------------------------- +package esmith::thisaction; + +use strict; +use warnings; +use esmith::ConfigDB; +use esmith::AD::Group; +no warnings ('qw'); + +use Data::Dumper; #For debugging + +##Pull arguments +my $event = $ARGV [0] || ''; +my $groupName = $ARGV [1] || ''; +my $data = $ARGV [2] || ''; #Hash ref + +die "group-create-AD error: groupname not found in action arguments\n" + unless ($groupName); + +##Check AD to see if group exists. If it already exists, then exit +my $ad = esmith::AD::Group->new(); +die "group-create-AD error: Group already exists in Active Directory.\n" + if ($ad->doesGroupExist($groupName)); + +##Validate the group data passed as hash. If nothing is passed, ignore +if (ref($data) eq 'HASH') { + foreach my $key (keys %$data) { + unless ($ad->validData->{$key}) { + warn "Ignoring $key attribute for update -- Not supported.\n"; + delete $data->{$key}; + } + } +} + +##Build Active Directory group create command +my $adPassword = $ad->getADPass(); +my $addGroup = "/usr/bin/samba-tool group add $groupName " . + "-U ad_admin\%$adPassword"; + +system ($addGroup); +die ("Unable to add group $groupName to Active Directory\n") if ($? == -1); + +##Make group a Posix Group +unless ($ad->setPosixGroup($groupName)) { + warn ("Unable to set posix objectClass in AD for $groupName.\n"); +} + +##Build Unix Attributes +my $GID = $ad->createGID($groupName) || ''; +my %posix = ('gidNumber' => $GID); + +##Merge Unix Attributes with any Extended Attributes and save to AD +my $mergedData = \%posix; +if (ref($data) eq 'HASH') { + $mergedData = {%posix,%$data}; +} + +$ad->setManyAttr($groupName,$mergedData) || + warn("Unable update attributes for group $groupName.\n"); + +1; diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/events/actions/provision-domain-controller smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/provision-domain-controller --- smeserver-samba-0.1.0/root/etc/e-smith/events/actions/provision-domain-controller 2016-07-29 20:46:38.899060240 -0700 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/provision-domain-controller 2016-07-11 01:30:48.000000000 -0700 @@ -3,8 +3,8 @@ #------------------------------------------------------------ #This action provisions a Samba 4 active directory domain # -#Copyright 2014 Koozali Foundation, Inc. -#11/15/2014: G.Zartman +#Copyright 2016 Koozali Foundation, Inc. +#07/14/2016: G.Zartman # #The code contained herein can be distributed under the same #license as Perl @@ -13,6 +13,7 @@ use strict; use warnings; use esmith::ConfigDB; +use esmith::util; use esmith::AD; ##Pull arguments @@ -21,6 +22,12 @@ die 'Samba provisioning error: Missing admin password' unless ($adminPass); +##Make sure samba deamons are down +esmith::util::serviceControl( + NAME => 'smb', + ACTION => 'stop' + ); + ##Pull domain name from config dbase. This is the samba realm my $cdb = esmith::ConfigDB->open; my $domainName = $cdb->get('DomainName')->value || @@ -29,12 +36,6 @@ die 'Samba provisioning error: Workgroup not defined'; my $realm = $workGroup . "." . $domainName; -##Bail if Samba has already been initialized -if ($event eq 'bootstrap-initialize-samba' && - $cdb->get_prop('bootstrap-console','Samba') eq 'initialized') { - exit(); -} - ##Remove existing smb.conf file or the provision will error out unlink ('/etc/samba/smb.conf') if (-e '/etc/samba/smb.conf'); @@ -58,7 +59,7 @@ ##Initialize Samba Domain -warn "Samba domain: Provisining Active Directory."; +warn "Samba domain: Provisioning Active Directory\n"; my $provision = "/usr/bin/samba-tool domain provision --server-role=dc " . "--domain=$workGroup " . "--realm=$realm " . @@ -91,10 +92,8 @@ system ($set_admin_pass); die "Samba domain error: Unable to SME Server admin password.\n" if ($? == -1); -##Set samba key to initialized in bootstrap-console so it doesn't initialize again -if ($event eq 'bootstrap-initialize-samba') { +##Set samba dbase key indicating Samba has been provisioned per the current configuration +$cdb->set_prop('smb','provisioned','yes') || + warn "Unable to set provisioned property for smb dbase key"; - $cdb->set_prop('bootstrap-console','Samba','initialized') || - warn "Unable to set Samba key in $event"; -} 1; diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/events/actions/samba-create-domain-admins smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/samba-create-domain-admins --- smeserver-samba-0.1.0/root/etc/e-smith/events/actions/samba-create-domain-admins 2016-07-29 20:46:38.900060240 -0700 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/samba-create-domain-admins 2016-07-11 01:27:00.000000000 -0700 @@ -1,60 +1,49 @@ #!/usr/bin/perl -w #------------------------------------------------------------ -#This action creates standard domain administrator accounts -#for the SME Server +#This action domain administrator accounts Koozali SME +#Server # -#Copyright 2014 Koozali Foundation, Inc. -#11/15/2014: G.Zartman +#Copyright 2016 Koozali Foundation, Inc. +#06/30/2016: G.Zartman # #The code contained herein can be distributed under the same #license as Perl #------------------------------------------------------------ - - use strict; use warnings; use esmith::ConfigDB; use esmith::AD; ##Pull arguments -my $event = $ARGV [0]; -my $AdminPass = $ARGV [1]; +my $event = $ARGV [0] || ''; +my $AdminPass = $ARGV [1] || ''; die 'Samba provisioning error: Missing admin password' unless ($AdminPass); -##Bail if called by bootstrap-initialize-samba and it has already been run -my $cdb = esmith::ConfigDB->open; -if ($event eq 'bootstrap-initialize-samba' && - $cdb->get_prop('bootstrap-console','Samba') eq 'initialized') { - exit(); -} - - -##Create admin and root accounts in AD and add to Domain Admin +##Create admin accounts in AD my $add_admin = "/usr/bin/samba-tool user create " . "admin $AdminPass " . "-U Administrator\%$AdminPass"; system ($add_admin); warn "Unable create admin Samba user\n" if ($? == -1); -my $add_root = "/usr/bin/samba-tool user create " . - "root $AdminPass " . - "-U Administrator\%$AdminPass"; -system ($add_root); -warn "Unable to create root Samba user\n" if ($? == -1); - -##Create ad_admin account and add it to domain admins for runtime access to acive directory +##Create ad_admin account for runtime access to active directory my $add_ad_admin = "/usr/bin/samba-tool user create " . "ad_admin " . esmith::AD::getADPass() . " " . "-U Administrator\%$AdminPass"; system ($add_ad_admin); die "Samba provisioning error: Unable to create ad_admin user in Active Directory.\n" if ($? == -1); -my $add_members = "/usr/bin/samba-tool group addmembers " . - "\'Domain Admins\' ". - "root,admin,ad_admin " . - "-U Administrator\%$AdminPass"; -system ($add_members); -warn "Unable to add admin and root users to Domain Admins group\n" if ($? == -1); + +##Enumerate admin accounts and update domain admins group +warn "Enumerating admin accounts\n"; +my $ldifs = '/home/e-smith/files/server-resources/schema/'; +my $ad = '/var/lib/samba/private/sam.ldb'; +my $modifyUserClass = '/usr/bin/ldbmodify -H ' . + "$ad " . + $ldifs . 'setupAdmins.ldif ' . + '--option="dsdb:schema update allowed"=true'; + +system ($modifyUserClass); 1; diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/events/actions/user-create-AD smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/user-create-AD --- smeserver-samba-0.1.0/root/etc/e-smith/events/actions/user-create-AD 2016-07-29 20:46:38.900060240 -0700 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/events/actions/user-create-AD 2016-07-02 12:44:56.000000000 -0700 @@ -1,19 +1,23 @@ #!/usr/bin/perl -w #------------------------------------------------------------ -#This action creates an Active Directory user given a username -#from the accountsDB. +#This action creates an Active Directory user # #Command format: # -# user-account-AD event username data: +# user-create-AD event username data: # # event : calling event name # username : unique username # data : Hash reference to user data to populate the AD # with. See the note below for # -#Copyright 2015 Koozali Foundation, Inc. +#Note: This action uses the samba-tool utility to add a new +# user the the Active Directory. Samba-tool does not exit +# very gracefully if it has a problem, so this action may +# throw some really funky error messages. +# +#Copyright 2016 Koozali Foundation, Inc. #06/23/2016: G.Zartman # #The code contained herein can be distributed under the same @@ -21,12 +25,6 @@ # #TODO # -#- We need to look at some kind of interm solution to use -# acccountsDB in the short term until we figure out where we are -# storing user data long term on SME. For now, we'll build a -# hash of data from the accounts dbase, but also provide a means -# to pass the data to this action with a hashref, which is the -# preferred method for AD. #- For the hash reference, let's scrub it with the # esmith::AD::User::ValidData method #- Consider setting the displayName attribute as well, otherwise @@ -48,7 +46,7 @@ ##Pull arguments my $event = $ARGV [0] || ''; my $userName = $ARGV [1] || ''; -my $data = $ARGV [2] || ''; #Hash ref +my $data = $ARGV [2] || {}; #Hash ref die "user-create-AD error: username not found in action arguments\n" unless ($userName); @@ -111,7 +109,6 @@ delete $data->{'loginShell'}; } - ##Create AD User my $adPassword = $ad->getADPass(); my $addUser = "/usr/bin/samba-tool user create $userName " . @@ -121,7 +118,7 @@ '--description="Koozali User:" ' . "-U ad_admin\%$adPassword"; system ($addUser); -die ("Unable to add user #userName to Active Directory\n") if ($? == -1); +die ("Unable to add user $userName to Active Directory\n") if ($? == -1); ##Make user a Posix User unless ($ad->setPosixUser($userName)) { @@ -140,8 +137,7 @@ $mergedData = {%posix,%$data}; } -$ad->setManyAttr($userName,\%posix) || - warn("Unable update user attributes for $userName.\n"); - +$ad->setManyAttr($userName,$mergedData) || + warn("Unable update attributes for user $userName.\n"); 1; diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/etc/krb5.conf/20default_realm smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/etc/krb5.conf/20default_realm --- smeserver-samba-0.1.0/root/etc/e-smith/templates/etc/krb5.conf/20default_realm 2014-11-19 23:32:12.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/etc/krb5.conf/20default_realm 2016-06-30 22:16:57.000000000 -0700 @@ -1,5 +1,8 @@ { - my $default_realm = $krb5{defaultRealm} || $DomainName; + my $workgroup = $smb{Workgroup} || 'sme-server'; + my $realm = $smb{realm} || $workgroup . "." . $DomainName; + + my $default_realm = $smb{realm} || $workgroup . "." .$DomainName; "default_realm = $default_realm"; } diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/etc/smb.conf/14dnsForwarder smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/etc/smb.conf/14dnsForwarder --- smeserver-samba-0.1.0/root/etc/e-smith/templates/etc/smb.conf/14dnsForwarder 2014-11-19 23:32:12.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/etc/smb.conf/14dnsForwarder 2016-07-27 23:05:39.298060111 -0700 @@ -1,5 +1,5 @@ { - my $dns_forwarder = $smb{DNSForwarder} || '127.0.0.2'; + my $dns_forwarder = $smb{DNSForwarder} || '127.0.0.4'; "dns forwarder = $dns_forwarder"; diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/00setup smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/00setup --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/00setup 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/00setup 2016-07-05 20:14:38.000000000 -0700 @@ -0,0 +1,9 @@ +{my $workgroup = $smb{Workgroup} || 'sme-server'; + my $domain = $DomainName || 'undefined'; + + my @realm_parts = (($workgroup),(split(/\./,$domain))); + + my @dc_parts = map {'DC=' . $_} @realm_parts; + $DC = join (',',@dc_parts); + $OUT = "";} + diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/10quota smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/10quota --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/10quota 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/10quota 2016-07-05 20:14:38.000000000 -0700 @@ -0,0 +1,12 @@ +dn: CN=quota,CN=Schema,CN=Configuration,{$DC} +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.19937.1.1.1 +cn: quota +name: quota +ldapDisplayName: quota +description: User Quotas +attributeSyntax: 2.5.5.5 +oMSyntax: 22 +isSingleValued: TRUE +- diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/20smeCustom smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/20smeCustom --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/20smeCustom 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/extendedADAttributes.ldif/20smeCustom 2016-07-05 20:14:38.000000000 -0700 @@ -0,0 +1,15 @@ + + +dn: CN=smeCustom,CN=Schema,CN=Configuration,{$DC} +objectClass: top +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.19937.1.1.1 +cn: smeCustom +name: smeCustom +ldapDisplayName: smeCustom +description: Custom Property and Values for Koozali +attributeSyntax: 2.5.5.5 +oMSyntax: 22 +isSingleValued: FALSE +- + diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/koozaliADClass.ldif/00setup smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/koozaliADClass.ldif/00setup --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/koozaliADClass.ldif/00setup 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/koozaliADClass.ldif/00setup 2016-07-05 23:24:34.000000000 -0700 @@ -0,0 +1,9 @@ +{my $workgroup = $smb{Workgroup} || 'sme-server'; + my $domain = $DomainName || 'undefined'; + + my @realm_parts = (($workgroup),(split(/\./,$domain))); + + my @dc_parts = map {'DC=' . $_} @realm_parts; + $DC = join (',',@dc_parts); + $OUT = "";} + diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/koozaliADClass.ldif/20classSchema smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/koozaliADClass.ldif/20classSchema --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/koozaliADClass.ldif/20classSchema 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/koozaliADClass.ldif/20classSchema 2016-07-11 00:54:49.000000000 -0700 @@ -0,0 +1,14 @@ +dn: CN=koozaliUser,CN=Schema,CN=Configuration,{$DC} +objectClass: top +objectClass: classSchema +governsID: 1.3.6.1.4.1.19937.1.2.1 +cn: koozaliUser +name: koozaliUser +ldapDisplayName: koozaliUser +subClassOf: posixAccount +objectClassCategory: 3 +mayContain: quota +mayContain: smeCustom +defaultObjectCategory: CN=koozaliUser,CN=Schema,CN=Configuration,{$DC} +possSuperiors: top +- diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/modifyADSchema.ldif/00setup smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/modifyADSchema.ldif/00setup --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/modifyADSchema.ldif/00setup 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/modifyADSchema.ldif/00setup 2016-07-05 20:17:28.000000000 -0700 @@ -0,0 +1,9 @@ +{my $workgroup = $smb{Workgroup} || 'sme-server'; + my $domain = $DomainName || 'undefined'; + + my @realm_parts = (($workgroup),(split(/\./,$domain))); + + my @dc_parts = map {'DC=' . $_} @realm_parts; + $DC = join (',',@dc_parts); + $OUT = "";} + diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/modifyADSchema.ldif/10updateSchema smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/modifyADSchema.ldif/10updateSchema --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/modifyADSchema.ldif/10updateSchema 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/modifyADSchema.ldif/10updateSchema 2016-07-11 00:53:56.000000000 -0700 @@ -0,0 +1,5 @@ +dn: CN=User,CN=Schema,CN=Configuration,{$DC} +changetype: modify +add: auxiliaryClass +auxiliaryClass: koozaliUser +- diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/00setup smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/00setup --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/00setup 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/00setup 2016-07-05 19:47:46.000000000 -0700 @@ -0,0 +1,9 @@ +{my $workgroup = $smb{Workgroup} || 'sme-server'; + my $domain = $DomainName || 'undefined'; + + my @realm_parts = (($workgroup),(split(/\./,$domain))); + + my @dc_parts = map {'DC=' . $_} @realm_parts; + $DC = join (',',@dc_parts); + $OUT = "";} + diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/20setupAdmin smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/20setupAdmin --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/20setupAdmin 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/20setupAdmin 2016-07-11 00:53:42.000000000 -0700 @@ -0,0 +1,20 @@ + +dn: CN=admin,CN=Users,{$DC} +changetype: modify +add: objectClass +objectClass: posixAccount +- +add: objectClass +objectClass: koozaliUser +- +add: uidNumber +uidNumber: 5000 +- +add: gidNumber +gidNumber:513 +- +add: loginShell +loginShell:/sbin/e-smith/console +- +add: unixHomeDirectory +unixHomeDirectory: /home/e-smith diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/30setupAd_Admin smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/30setupAd_Admin --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/30setupAd_Admin 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/30setupAd_Admin 2016-07-11 00:53:32.000000000 -0700 @@ -0,0 +1,21 @@ + + +dn: CN=ad_admin,CN=Users,{$DC} +changetype: modify +add: objectClass +objectClass: posixAccount +- +add: objectClass +objectClass: koozaliUser +- +add: uidNumber +uidNumber: 5001 +- +add: gidNumber +gidNumber:513 +- +add: loginShell +loginShell:/sbin/nologin +- +add: unixHomeDirectory +unixHomeDirectory: /home/e-smith diff -urbN smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/40updateDomainAdmins smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/40updateDomainAdmins --- smeserver-samba-0.1.0/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/40updateDomainAdmins 1969-12-31 16:00:00.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/etc/e-smith/templates/home/e-smith/files/server-resources/schema/setupAdmins.ldif/40updateDomainAdmins 2016-07-11 00:42:32.000000000 -0700 @@ -0,0 +1,9 @@ + +dn: CN=Domain Admins,CN=Users,{$DC} +changetype: modify +- +add: member +member: CN=admin,CN=Users,DC=sme-server,DC=development,DC=com +- +add: member +member: CN=ad_admin,CN=Users,DC=sme-server,DC=development,DC=com diff -urbN smeserver-samba-0.1.0/root/usr/share/perl5/vendor_perl/esmith/AD/Group.pm smeserver-samba-0.1.0-072416-update/root/usr/share/perl5/vendor_perl/esmith/AD/Group.pm --- smeserver-samba-0.1.0/root/usr/share/perl5/vendor_perl/esmith/AD/Group.pm 2015-02-12 21:15:46.000000000 -0800 +++ smeserver-samba-0.1.0-072416-update/root/usr/share/perl5/vendor_perl/esmith/AD/Group.pm 2016-07-11 04:41:16.000000000 -0700 @@ -1,10 +1,10 @@ package esmith::AD::Group; use strict; -use Net::LDAP; +use base 'esmith::AD'; +use esmith::AD::User; no warnings ('qw'); - =head1 NAME esmith::AD::Group -- Sub-Class to the Koozali esmith::AD API @@ -14,42 +14,90 @@ use esmith::AD my $ad = esmith::AD->new(); - my @groups = $ad->groups; + my @groups = $ad->listGroups; =head1 DESCRIPTION - -This module provides esmith::AD methods related to group management in -the Koozali Active Directory. Like the parent class, esmith::AD, this -module uses Net::LDAP to communicate with the Active Directory. Methods -provided in this module abstract Net::LDAP so that knowledge of this -module is not required. +This module provide esmith::AD::Group methods for management of users +stored in the Koozali SME Server Active Directory. These methods are +the preferred methods to interact with user objects in the Active +Directory. Many methods in this class inherit functionality from the +esmith::AD parent class and provide run-time binding of LDAP query +elements to these parent methods. Methods provided in this module +abstract Net::LDAP so that knowledge of this module is not required. =cut sub new { my ($class, %params) = @_; - my $queryElements = { + + #Define runtime LDAP query parameters + my $base = { + 'default' => '&(objectClass=group)(!(objectClass=computer))' + }; + my $set = { 'all' => '', - 'builtin' => "(!(objectClass=posixAccount))", - 'koozali' => "(objectClass=posixAccount)", - 'member' => '', - 'noMachine' => "(!(objectClass=computer))", - 'object' => "&(objectClass=group)", + 'builtin' => '(!(objectClass=posixAccount))', + 'koozali' => '(objectClass=posixAccount)', 'single' => '' }; - my $objectClass = ['top','group','posixAccount']; + my $type = { + 'posix' => ['top','group','posixAccount'] + }; + + my $attribute = { + 'default' => 'sAMAccountName', + 'dn' => 'DN' + }; my $self = { - 'query' => $queryElements, - 'objectClass' => $objectClass + 'base' => $base, + 'set' => $set, + 'attribute' => $attribute, + 'type' => $type }; + #Bless parameters into the class bless ($self, $class); + return ($self); } =head2 Methods + +=head3 addUserToGroup() + +This method adds a user to a group given a username and group name. +The method returns 1 of successful and 0 if something went wrong. + +Usage: $ad->addUserToGroup('username','groupname') + +=cut + +sub addUserToGroup { + my ($self,$user,$group) = @_; + return 0 unless ($user && $group); + + my $ad2 = esmith::AD::User->new(); + return 0 unless ($ad2->doesUserExist($user)); + + #Verify Group exists so we don't run a bunch of bogus AD queries. + return 0 unless ($self->doesGroupExist($group)); + + my $groupMembers = $self->getGroupAttr($group,'member','all') || ''; + unless ($groupMembers) {$groupMembers = [];} + + my $memberAddDN = $self->getObjectDN($user); + + push(@$groupMembers, $memberAddDN) + unless grep{$_ == $memberAddDN} @$groupMembers; + + if ($self->setAttr($group,'member',$groupMembers)) {return(1);} + else {return (0)} + +} + + =head3 attributes() This method returns a list of Active Directory group attributes managed @@ -79,14 +127,14 @@ sub createGID { my ($self,$group) = @_; - die $self->error("Groupname not specified.\n") unless $group; + return (0) unless $group; #Pull SID from the AD return (0) unless (my $SID = $self->getSID($group)); - #Return GID = RID + 2000 + #Return GID = RID + 4000 my $RID = (split(/-/,$SID))[7]; - return($RID+2000); + return($RID+4000); } =head3 doesGroupExist($groupname) @@ -102,10 +150,12 @@ sub doesGroupExist { my ($self,$group) = @_; - my @groups = $self->listGroups('all'); + return 0 unless $group; + + my ($groupRecord) = $self->queryObjects($group); - if(grep { $group eq $_ } @groups) { return (1); } - else{ return(0); } + if(defined $groupRecord) {return (1);} + else{return(0);} } =head3 getGID($groupname) @@ -117,142 +167,154 @@ =cut -sub getGID { ##TO DO - my ($self,$name) = @_; +sub getGID { + my ($self,$group)=@_; + + return 0 unless $group; + + my ($record) = $self->queryObjects($group); + die $self->error("Unable to find \"$group\" in the Active Directory.\n") + unless ($record); - die $self->error("Groupname not specified.\n") unless $name; + my $GID = $record->get_value('gidNumber') || ''; -###FIX ME: We are now pulling the GID from the AD + die $self->error("Unable to retrieve GID for $group\n") + unless ($GID); - return(); + return($GID); } -=head3 getGroupAttr($group,$attr) +=head3 getGroupAttr($group,$attr,$set) This method returns the value of the specified attribute for a group -listed in the Active Directory. +listed in the Active Directory. Some attributes could be multi-value +attributes. By default this method will return the first value of a +multi-value attribute in scalar contact unless you tell the method to +return all value. -Usage: $value = $ad->getGroupAttr('group','attribute'); +Usage: $single_value = $ad->getGroupAttr('group','attribute'); + $multi_value_ref = $ad->getGroupAttr('group',attribute','all'); =cut sub getGroupAttr { - my($self,$group,$attr)=@_; + my($self,$group,$attr,$set)=@_; + + return 0 unless $group; #Check that the search attribute is supported die $self->error("Attribute \"$attr\" not supported\n") unless ($self->validData->{$attr}); - #Get attribute value from the Active Directory - my $value = $self->getADRecord($group)->{$attr} || ''; - + #Query AD + my ($record) = $self->queryObjects($group); + die $self->error("Unable to find \"$group\" in Active Directory.\n") + unless ($record); + + #Pull attribute value single or all + if ($set eq 'all') { + my $valueRef = $record->get_value($attr,asref => 1) || ''; + return ($valueRef); + } + else { + my $value = $record->get_value($attr) || ''; return ($value); + } } =head3 getMembers($group) -###FIX ME: Rewrite -This method returns a list group membersthe value of the specified attribute for a group -listed in the Active Directory. +This method returns a list of members of a specified group. The user +needs to be aware of what he is asking this method to report because +Active Directory allows nested groups (i.e., groups that are members of +a group). In most cases, if you ask this method for members of a group +designed by this API, then it will return a list of users that are members +of the designed group. In the future, we may add logic to delinate user +members versus nested group members, but for now we are going to be lazy +and just report what is in Active Directory. -Usage: $value = $ad->getGroupAttr('group','attribute'); +Usage: @group_mambers = $ad->getMembers('group_name'); =cut -sub getMembers { ##TO DO -- May want to change to just "getMembers" +sub getMembers { + my($self,$group)=@_; - my($self,$group,$attr)=@_; + return (0) unless $group; - #Check that the search attribute is supported - die $self->error("Attribute \"$attr\" not supported\n") - unless (grep {$attr eq $_} ($self->attributes('group'))); + #Get group members as an array ref + my $memberDN = $self->getGroupAttr($group,'member','all') || ''; - #Get attribute value from the Active Directory - my $value = ($self->getADRecord('group',$group))->{$attr} || ''; - - return ($value); + #AD returns the DN for group members, so we need to generate names + my ($sam,@members); + foreach (@$memberDN) { + $sam = $self->getName($_) || ''; + push (@members,$sam) unless ($sam eq ''); + } + return (@members); } =head3 listGroups($type) This method returns a list of groups based upon the type of group specified as a parameter to the method. Valid types include: + - builtin: Groups defined during the Active Directory provisioning (e.g., Administrator); - koozali: Groups defined in the Koozali API. - all: All groups. -If the method doesn't recieve a valid type, then it will return a list -of all groups in the Active Directory +If the method doesn't receive a valid type, then it will return a +list of all groups in the Active Directory +Usage: + use esmith::AD::Group; + + my $ad = esmith::AD::Group->new(); + my @groups = $ad->listGroups('buildin'); =cut sub listGroups { - my ($self, $type) = @_; + my ($self, $set) = @_; - return($self->listObjects($type)); + return($self->listObjects($set)); } -=head3 queryMembers($set,$value) -###FIX ME: Need to rewire -This method is an alias method to the esmith::AD::listObjects method. -It returns a list of usernames from the Active Directory, and also -subsets of users: +=head3 removeUserFromGroup() - - builtin: Users defined during the Active Directory - provisioning (e.g., Administrator); - - koozali: Users defined in the Koozali API. - - all: All users (default). +This method removes a user from a group given a username and group name. +The method returns 1 of successful and 0 if something went wrong. -Usage: - use esmith::AD::User; - my $ad = esmith::AD::User->new(); - my @users = $ad->listUsers('koozali'); +Usage: $ad->removeUserFromGroupp('username','groupname') =cut -sub queryMembers { - my ($self,$set,$value)=@_; - - my $queryFilter = $self->buildQuery('member',$set,$value) || ''; - - return ($self->runQuery($queryFilter)); -} - +sub removeUserFromGroup { + my ($self,$user,$group) = @_; + return 0 unless ($user && $group); -=head3 queryObjects($set,$value) + my $ad2 = esmith::AD::User->new(); + return 0 unless ($ad2->doesUserExist($user)); -###FIX ME: Need to rewire -This method is an alias method to the esmith::AD::listObjects method. -It returns a list of usernames from the Active Directory, and also -subsets of users: + #Verify Group exists so we don't run a bunch of bogus AD queries. + return 0 unless ($self->doesGroupExist($group)); - - builtin: Users defined during the Active Directory - provisioning (e.g., Administrator); - - koozali: Users defined in the Koozali API. - - all: All users (default). + my $groupMembers = $self->getGroupAttr($group,'member','all') || ''; + return (1) unless ($groupMembers); #group is empty already -Usage: - use esmith::AD::User; - my $ad = esmith::AD::User->new(); - my @users = $ad->listUsers('koozali'); - -=cut + my $memberRemoveDN = $self->getObjectDN($user); -sub queryObjects { - my ($self,$set,$value)=@_; + my @newMembers = grep {$_ ne $memberRemoveDN} @$groupMembers; - my $class = 'object'; - if (defined $value) {$class = 'single'}; + if ($self->setAttr($group,'member',\@newMembers)) {return(1);} + else {return (0)} - my $queryFilter = $self->buildQuery($class,$set,$value) || ''; - - return ($self->runQuery($queryFilter)); } -=head3 setGroupAttr($group,$attr,$value) + +=head3 setGroupAttr($group,$attr,$value)** This method sets or modifies an attribute value for the specified groupname. @@ -264,24 +326,7 @@ sub setGroupAttr { my ($self,$group,$attr,$value) = @_; - if ($self->setAttr($group,{$attr=>$value})) { return(1); } - else { - die->error("Unable to modify \"$attr\" for groupname \"$group\".\n"); - } -} - -=head3 setGroupMembers($group,\@members) - -###FIX ME: NEED TO REWITE -This method sets or modifies an attribute value for the specified -groupname. - -Usage: $ad->setGroupAttr('groupname','attribute','value') - -=cut - -sub setGroupMembers { ##TO DO - my ($self,$group,$attr,$value) = @_; + return 0 unless $group; if ($self->setAttr($group,{$attr=>$value})) { return(1); } else { @@ -289,9 +334,7 @@ } } - - -=head3 setPostixGroup ($group) +=head3 setPosixGroup ($group) This method designates a group as a Posix Group. The Posix group type represents the groups managed by Koozali and are those groups that are @@ -302,9 +345,11 @@ =cut sub setPosixGroup { - my ($self,$name) = @_; + my ($self,$group) = @_; + + return 0 unless $group; - return($self->setPosix($name)); + return($self->setPosix($group)); } =head3 validData() @@ -319,12 +364,15 @@ sub validData { my $self = shift; - return ({}); + return ({ + 'member' => 1, + 'gidNumber' => 1 + }); } =head1 COPYRIGHT -Copyright (c) 2014 Koozali Foundation, Inc. +Copyright (c) 2016 Koozali Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. diff -urbN smeserver-samba-0.1.0/root/usr/share/perl5/vendor_perl/esmith/AD/User.pm smeserver-samba-0.1.0-072416-update/root/usr/share/perl5/vendor_perl/esmith/AD/User.pm --- smeserver-samba-0.1.0/root/usr/share/perl5/vendor_perl/esmith/AD/User.pm 2016-07-29 20:46:38.901060240 -0700 +++ smeserver-samba-0.1.0-072416-update/root/usr/share/perl5/vendor_perl/esmith/AD/User.pm 2016-07-11 04:35:26.000000000 -0700 @@ -15,6 +15,7 @@ my $ad = esmith::AD::User->new(); my @users = $ad->listUsers; + =head1 DESCRIPTION This module provide esmith::AD::User methods for management of users stored @@ -41,7 +42,7 @@ }; my $type = { 'posix' => ['top','person','organizationalPerson', - 'user','posixAccount'] + 'user','posixAccount','koozali'] }; my $attribute = { @@ -80,8 +81,53 @@ return (keys %dataHash); } +=head3 createAutoPseudonyms($username) + +This method creates dot and bar pseudonyms for a user and then +adds them as an attribute to the user object. + +Usage: my $uid = $ad->createAutoPseudonyms($username); + +=cut + +sub createAutoPseudonyms { + my ($self,$user) = @_; + + return 0 unless $user; + + #Query AD + my ($record) = $self->queryObjects($user); + die $self->error("Unable to find \"$user\" in the Active Directory.\n") + unless ($record); + + #Pull first and last name. Exit if either isn't set, as we can't + #build a pseudonym without both. + my $firstName = $record->get_value('givenName') || ''; + my $lastName = $record->get_value('sn') || ''; + return (0) if ($firstName eq '' || $lastName eq ''); + + #Get ProxyAddresses attribute as list reference or create it + my $proxyAddresses = $record->get_value('proxyAddresses'); + unless (ref($proxyAddresses) eq 'ARRAY') {$proxyAddresses = [];} + + my $dotPseudonym = 'sme:' . $firstName . '.' . $lastName; + push(@$proxyAddresses, $dotPseudonym) + unless grep{$_ eq $dotPseudonym} @$proxyAddresses; + + my $barPseudonym = 'sme:' . $firstName . '_' . $lastName; + push(@$proxyAddresses, $barPseudonym) + unless grep{$_ eq $barPseudonym} @$proxyAddresses; + + + foreach (@$proxyAddresses) {print $_ . "\n";} + if ($self->setAttr($user,'proxyAddresses',$proxyAddresses)) { + return(1); + } + else {print "had a problem"; return (0)} +} + -=head3 createUID($name)* +=head3 createUID($username) This method calculates a unix UID for an Active Directory user based upon the SID for the Active Directory object. @@ -93,18 +139,17 @@ sub createUID { my ($self,$name) = @_; - die $self->error("Username not specified in createUID method.\n") - unless $name; + return 0 unless $name; #Pull SID from the AD return (0) unless (my $SID = $self->getSID($name)); - #Return UID = RID + 2000 + #Return UID = RID + 4000 my $RID = (split(/-/,$SID))[7]; - return($RID+2000); + return($RID+4000); } -=head3 doesUserExist($username)* +=head3 doesUserExist($username) This method checks the Active Directory for the existance of a username passed as a parameter to the method. The method returns 1 if the username exists in @@ -117,75 +162,110 @@ sub doesUserExist { my ($self,$user) = @_; + return 0 unless $user; + my ($userRecord) = $self->queryObjects($user); if (defined $userRecord) {return(1);} else {return(0);} } + =head3 getUID($username) This method returns the unix UID for a user from the Active Directory. -Usage: my $uid = $ad->UID('username'); +Usage: my $uid = $ad->getUID('username'); =cut sub getUID { my ($self,$user)=@_; -###FIX ME: Pull UID from AD instead of calculating it. + return 0 unless $user; + + my ($record) = $self->queryObjects($user); + + die $self->error("Unable to find \"$user\" in the Active Directory.\n") + unless ($record); + + my $UID = $record->get_value('uidNumber') || ''; + + die $self->error("Unable to retrieve UID for $user\n") + unless ($UID); - return(); + return($UID); } -=head3 getUserAttr($username,$attr) +=head3 getUserAttr($username,$attr,$set) This method returns the value of the specified attribute for a user -listed in the Active Directory. +listed in the Active Directory. Some attributes could be multi-value +attributes. By default this method will return the first value of a +multi-value attribute in scalar contact unless you tell the method to +return all values. If all values are specified, this method returns +an array reference to the list of values. -Usage: $value = $ad->getUserAttr('username','attribute'); +Usage: $single_value = $ad->getUserAttr('username','attribute'); + $multi_ref = $ad->getGroupAttr('username','attribute','all); =cut sub getUserAttr { - my($self,$username,$attr)=@_; + my($self,$user,$attr,$set)=@_; + + return 0 unless $user; ##Check that the search attribute is supported die $self->error("Attribute \"$attr\" not supported.\n") - unless (grep {$attr eq $_} ($self->attributes('user'))); + unless ($self->attributes($attr)); + + ##Query AD + my ($record) = $self->queryObjects($user); + die $self->error("Unable to find \"$user\" in the Active Directory.\n") + unless ($record); - #Get attribute value from the Active Directory - my $value = ($self->getADRecord($username))->{$attr} || ''; + #Pull attribute value single or all + if ($set eq 'all') { + my $valueRef = $record->get_value($attr) || ''; + if (ref ($valueRef) eq "ARRAY") {return($valueRef);} + else {return([$valueRef]);} + } + else { + my $value = $record->get_value($attr) || ''; return ($value); + } } + =head3 getUserGroups($username) -This method returns a list of the Active Directory groups that a user -is a member of. +This returns a list of groups the user is a member of. -Usage: @ad_groups=$ad->getUserGroups('username'); +Usage: @user_groups = $ad->getUserGroups('username'); =cut -sub getUserGroups { ##TO DO - my ($self,$user) = @_; +sub getUserGroups { + my($self,$user)=@_; - #Lookup entry in the active directory - my ($record) = $self->query('user',$user); + return (0) unless $user; - die $self->error("Unable to find \"$user\" in the Active Directory.\n") - unless ($record); + #Get getups + my $memberDN = $self->getUserAttr($user,'memberOf','all') || ''; - #Get memberOf values from AD record object - my @results = $record->get_value('memberOf'); - - return (map {(split(/[=,]/,$_))[1]} @results); + #AD returns the DN for group members, so we need to generate names + my ($sam,@groups); + foreach (@$memberDN) { + $sam = $self->getName($_) || ''; + push (@groups,$sam) unless ($sam eq ''); + } + return (@groups); } -=head3 getUserStatus($username)* + +=head3 getUserStatus($username) This method returns user account status, enabled or disabled, for a specified username. @@ -197,12 +277,63 @@ sub getUserStatus { my ($self,$user)=@_; + return 0 unless $user; + return ($self->getStatus($user)); } -=head3 listUsers($set)* -This method returns a list of usernames in the active directory +=head3 isUserInGroup($username,$group) + +This method returns true a user exists in a group, otherwise it returns +false. + +Usage: $is_user_in_group = $ad->isUserInGroup('username','groupname'); + +=cut + +sub isUserInGroup { + my ($self,$user,$group)=@_; + + return (0) unless ($user && $group); + + #my @groups = $self->getUserGroups('root'); + + my @groups = $self->getUserGroups($user); + + if (grep {$_ eq $group} @groups) {return(1);} + else {return(0);} +} + +=head3 listPseudonyms + +This method returns a list all Koozali User pseudonyms in the Active Directory +including the admin account. + +Usage: my @pseudonyms = $ad->listPseudonyms(); + +=cut + +sub listPseudonyms { + +my ($self) = @_; + + #Pull all Koozali accounts + my @adRecords = $self->queryObjects('koozali'); + + my (@proxyAddresses, @pseudonyms) = (); + foreach (@adRecords) { + @proxyAddresses = $_->get_value('proxyAddresses'); + push(@pseudonyms, (grep(!/sme/,(map{split/:/,$_}@proxyAddresses)))); + @proxyAddresses = (); + } + return(@pseudonyms); +} + + +=head3 listUsers($set) + +This method returns a list of usernames in the Active Directory depending upon the search set sent to the method. Valid search sets include: @@ -224,7 +355,7 @@ return($self->listObjects($set)); } -=head3 setPosixUser($user) * +=head3 setPosixUser($user) This method designates a user as a Posix User. The Posix user type represents the users managed by Koozali and displayed in the @@ -239,55 +370,9 @@ sub setPosixUser { my ($self,$name) = @_; - return($self->setPosix($name)); -} - - -=head3 setUserGroups($username,$groupRef) - -This mthod sets the groups that a user is a member of give the username -and an array reference to the group names a user is a member of. - -=cut - -sub setUserGroups {###TO DO - my ($self,$name,$groupRef) = @_; + return 0 unless $name; - #Check input parameters - die $self->error("Username not specified.\n") unless ($name); - die $self->error("List of user groups not specified for $name\n") - unless (ref($groupRef) eq 'ARRAY'); - - my @groups = @$groupRef; - - #Verify that groups exist in the AD - - #Call connect as we'll need this Net::LDAP object later - my $ad = $self->connect(); - - #Query AD using Net::LDAP syntax, as we called connect - my $query=$ad->search( - base => 'DC=domain,DC=com', - filter => "&(cn=$name)(objectClass=user)" - ); - if($query->code()) { - die $self->error("Active Directory query error: ") . - ($query->server_error); - } - die $self->error("Unable to query \"$name\" from the Active Directory.\n") - unless (my $entry = $query->entry()); - - #Modify Active Directory record and return true if successful, else die - #with error message from the Active Directory if update failed - - #$entry->replace(%dataHash); - my $result = $entry->update($ad); - - if($result->code()) { - die $self->error("Could not update \"$name\": ") . - ($result->server_error); - } - return (1); + return($self->setPosix($name)); } =head3 validData() @@ -316,11 +401,13 @@ 'mail' => 1, 'name' => 1, 'physicalDeliveryOfficeName' => 1, + 'proxyAddresses' => 1, 'sn' => 1, 'telephoneNumber' => 1, 'title' => 1, 'uidNumber' => 1, 'unixHomeDirectory' => 1, + 'quota' => 1, 'wWWHomePage' => 1 }); } diff -urbN smeserver-samba-0.1.0/root/usr/share/perl5/vendor_perl/esmith/AD.pm smeserver-samba-0.1.0-072416-update/root/usr/share/perl5/vendor_perl/esmith/AD.pm --- smeserver-samba-0.1.0/root/usr/share/perl5/vendor_perl/esmith/AD.pm 2016-07-29 20:46:38.902060240 -0700 +++ smeserver-samba-0.1.0-072416-update/root/usr/share/perl5/vendor_perl/esmith/AD.pm 2016-07-25 18:10:03.000000000 -0700 @@ -4,7 +4,6 @@ use Net::LDAP; use MIME::Base64(); use esmith::ConfigDB; -use esmith::AccountsDB; #This package is to aid in debugging. Can remove use Data::Dumper; @@ -71,7 +70,7 @@ my $user_status = $ad->getUserStatus; -=head3 getADRecord {$name) +=head3 getADRecord($name) This method returns a hash reference of attribute/value pairs from the Active Directory for attributes supported by this method, @@ -90,7 +89,7 @@ die $self->error("Object name not specified.\n") unless $name; #Query record from AD - my ($record) = $self->queryObjects('single',$name); + my ($record) = $self->queryObjects($name); #Verify that we found a record in the AD die $self->error("Unable to find \"$name\" in the Active Directory.\n") @@ -98,12 +97,34 @@ #Build a hash of supported attributes and values my @attributes = $self->attributes; + my %adRecord = map {$_ => ($record->get_value($_))||''} @attributes; return (\%adRecord); } -=head3 SID($name) + +=head3 getName($dn) + +This method returns an object sAMAccountName given an object DN. + +Usage: $sAMAccountName= = $ad->getName(DN); + +=cut + +sub getName { + my ($self,$dn) = @_; + + return (0) unless $dn; + + my @dnParts = split (/\,/,$dn); + my ($cn,$name) = split (/=/,$dnParts[0]); + + return ($name); +} + + +=head3 getSID($name) This method retrieves the SID for a specified Active Directory object name, decrypts it, and then returns it. This method must be @@ -209,27 +230,6 @@ } - - -=head3 queryMembers($set,$value) - -###FIX ME: Need to rewite POD -This method is an alias method to the esmith::AD::listObjects method. -It returns a list of usernames from the Active Directory, and also -subsets of users: - -=cut - -sub queryMembers { - my ($self,$set,$value)=@_; - - ##Need to rewrite this to use the queryObjectsmethod - my $queryFilter = $self->BuildQuery('member',$set,$value) || ''; - - return ($self->runQuery($queryFilter)); -} - - =head3 queryObjects($self,$value,$attribute,$base) This is the primary query method for this API and returns Net::LDAP record @@ -244,12 +244,13 @@ - all: All user account records in the active directory - buildin: Builtin user account records. Example: Administrator - - koozali: All user accoun records defined in this UI. These are the typical + - koozali: All user account records defined in this UI. These are the typical user accounts setup in the server-manager for via the commandline. -To search for a single user record, set $value to the Active Directory attribute -value for the record you'd like to search for. The default search attribute is -the username (e.g., sAMAccountName). +To search for a single, set $value to the Active Directory attribute value for +the record you'd like to search for. This method will automatically runtime +bind to the correct object type (i.e., users, groups, OUs, DNS). The default +search attribute is the username (e.g., sAMAccountName). This method can also search for single records given other AD attributes, but other search attributes must be defined in child classes. See child @@ -294,7 +295,6 @@ $searchValue = $setValue; }; - ##Build Query Filter my $queryFilter = $self->{'base'}->{"$base"} . $self->{'set'}->{"$set"}; @@ -349,19 +349,24 @@ sub setManyAttr { my ($self,$name,$attrRef) = @_; + return 0 unless ($name && $attrRef); + #Don't allow this method from this class - die $self->error("Must call this method on a esmith::AD child object.\n") + die $self->error("Must call this method on a esmith::AD child object\n") if (ref($self) eq 'esmith::AD'); #Check to make sure we have enough data to perform an update - die $self->error("Entity to modify not specified.\n") unless ($name); die $self->error("No attributes set to modify for $name\n") unless (ref($attrRef) eq 'HASH'); #Validate that we support the attributes for update foreach my $key (keys %$attrRef) { unless ($self->validData->{$key}) { - warn "Ignoring $key attribute for update -- Not supported.\n"; + warn "Ignoring $key attribute for update -- Not supported\n"; + delete $attrRef->{$key}; + } + if ($attrRef->{$key} eq '') { + warn "Ignoring $key attribute since it is blank\n"; delete $attrRef->{$key}; } } @@ -377,7 +382,7 @@ return (1); } -=head3 setPosix($type,$name) * +=head3 setPosix($type,$name) This method designates an Active Directory object as a Posix object given and object sAMAccount name (e.g., username). @@ -552,12 +557,12 @@ my ($self)=@_; my $realm = $self->realm; - my @elements = split (/\./, $realm); + my @realmParts = split (/\./, $realm); - my $base = ''; - foreach (@elements) {$base .= "DC=" . $_ . ","}; + my @dnParts = map {'DC=' . $_} @realmParts; + my $base = join (',' , @dnParts); - return(substr ($base,0,-1)); + return ($base); } #------------------------------------------------------------ @@ -588,6 +593,21 @@ } #------------------------------------------------------------ +#Method: getObjectDN() +# This method builds and object DN for user and group +# objects in the Active Directory. +#----------------------------------------------------------- +sub getObjectDN { + my ($self,$name)=@_; + + return 0 unless $name; + + my $base = $self->baseDN; + + return('CN=' . $name . ',' . 'CN=Users,' . $base); +} + +#------------------------------------------------------------ #Method: realm() # This method returns the realm which is the SME # domain name stored in the configuration dbase