1# -- 2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/ 3# -- 4# This software comes with ABSOLUTELY NO WARRANTY. For details, see 5# the enclosed file COPYING for license information (GPL). If you 6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt. 7# -- 8 9package Kernel::System::Auth::Sync::LDAP; 10 11use strict; 12use warnings; 13 14use Net::LDAP; 15use Net::LDAP::Util qw(escape_filter_value); 16 17our @ObjectDependencies = ( 18 'Kernel::Config', 19 'Kernel::System::Encode', 20 'Kernel::System::Group', 21 'Kernel::System::Log', 22 'Kernel::System::User', 23); 24 25sub new { 26 my ( $Type, %Param ) = @_; 27 28 # allocate new hash for object 29 my $Self = {}; 30 bless( $Self, $Type ); 31 32 # Debug 0=off 1=on 33 $Self->{Debug} = 0; 34 35 # get config object 36 my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); 37 38 # get ldap preferences 39 if ( !$ConfigObject->Get( 'AuthSyncModule::LDAP::Host' . $Param{Count} ) ) { 40 $Kernel::OM->Get('Kernel::System::Log')->Log( 41 Priority => 'error', 42 Message => "Need AuthSyncModule::LDAP::Host$Param{Count} in Kernel/Config.pm", 43 ); 44 return; 45 } 46 if ( !defined $ConfigObject->Get( 'AuthSyncModule::LDAP::BaseDN' . $Param{Count} ) ) { 47 $Kernel::OM->Get('Kernel::System::Log')->Log( 48 Priority => 'error', 49 Message => "Need AuthSyncModule::LDAP::BaseDN$Param{Count} in Kernel/Config.pm", 50 ); 51 return; 52 } 53 if ( !$ConfigObject->Get( 'AuthSyncModule::LDAP::UID' . $Param{Count} ) ) { 54 $Kernel::OM->Get('Kernel::System::Log')->Log( 55 Priority => 'error', 56 Message => "Need AuthSyncModule::LDAP::UID$Param{Count} in Kernel/Config.pm", 57 ); 58 return; 59 } 60 $Self->{Count} = $Param{Count} || ''; 61 $Self->{Die} = $ConfigObject->Get( 'AuthSyncModule::LDAP::Die' . $Param{Count} ); 62 $Self->{Host} = $ConfigObject->Get( 'AuthSyncModule::LDAP::Host' . $Param{Count} ); 63 $Self->{BaseDN} = $ConfigObject->Get( 'AuthSyncModule::LDAP::BaseDN' . $Param{Count} ); 64 $Self->{UID} = $ConfigObject->Get( 'AuthSyncModule::LDAP::UID' . $Param{Count} ); 65 $Self->{SearchUserDN} = $ConfigObject->Get( 'AuthSyncModule::LDAP::SearchUserDN' . $Param{Count} ) || ''; 66 $Self->{SearchUserPw} = $ConfigObject->Get( 'AuthSyncModule::LDAP::SearchUserPw' . $Param{Count} ) || ''; 67 $Self->{GroupDN} = $ConfigObject->Get( 'AuthSyncModule::LDAP::GroupDN' . $Param{Count} ) 68 || ''; 69 $Self->{AccessAttr} = $ConfigObject->Get( 'AuthSyncModule::LDAP::AccessAttr' . $Param{Count} ) 70 || 'memberUid'; 71 $Self->{UserAttr} = $ConfigObject->Get( 'AuthSyncModule::LDAP::UserAttr' . $Param{Count} ) 72 || 'DN'; 73 $Self->{DestCharset} = $ConfigObject->Get( 'AuthSyncModule::LDAP::Charset' . $Param{Count} ) 74 || 'utf-8'; 75 76 # ldap filter always used 77 $Self->{AlwaysFilter} = $ConfigObject->Get( 'AuthSyncModule::LDAP::AlwaysFilter' . $Param{Count} ) || ''; 78 79 # Net::LDAP new params 80 if ( $ConfigObject->Get( 'AuthSyncModule::LDAP::Params' . $Param{Count} ) ) { 81 $Self->{Params} = $ConfigObject->Get( 'AuthSyncModule::LDAP::Params' . $Param{Count} ); 82 } 83 else { 84 $Self->{Params} = {}; 85 } 86 87 return $Self; 88} 89 90sub Sync { 91 my ( $Self, %Param ) = @_; 92 93 # check needed stuff 94 if ( !$Param{User} ) { 95 $Kernel::OM->Get('Kernel::System::Log')->Log( 96 Priority => 'error', 97 Message => 'Need User!' 98 ); 99 return; 100 } 101 $Param{User} = $Self->_ConvertTo( $Param{User}, 'utf-8' ); 102 103 my $RemoteAddr = $ENV{REMOTE_ADDR} || 'Got no REMOTE_ADDR env!'; 104 105 # remove leading and trailing spaces 106 $Param{User} =~ s{ \A \s* ( [^\s]+ ) \s* \z }{$1}xms; 107 108 # just in case for debug! 109 if ( $Self->{Debug} > 0 ) { 110 $Kernel::OM->Get('Kernel::System::Log')->Log( 111 Priority => 'notice', 112 Message => "User: '$Param{User}' tried to sync (REMOTE_ADDR: $RemoteAddr)", 113 ); 114 } 115 116 # ldap connect and bind (maybe with SearchUserDN and SearchUserPw) 117 my $LDAP = Net::LDAP->new( $Self->{Host}, %{ $Self->{Params} } ); 118 if ( !$LDAP ) { 119 if ( $Self->{Die} ) { 120 die "Can't connect to $Self->{Host}: $@"; 121 } 122 123 $Kernel::OM->Get('Kernel::System::Log')->Log( 124 Priority => 'error', 125 Message => "Can't connect to $Self->{Host}: $@", 126 ); 127 return; 128 } 129 my $Result; 130 if ( $Self->{SearchUserDN} && $Self->{SearchUserPw} ) { 131 $Result = $LDAP->bind( 132 dn => $Self->{SearchUserDN}, 133 password => $Self->{SearchUserPw} 134 ); 135 } 136 else { 137 $Result = $LDAP->bind(); 138 } 139 if ( $Result->code() ) { 140 $Kernel::OM->Get('Kernel::System::Log')->Log( 141 Priority => 'error', 142 Message => 'First bind failed! ' . $Result->error(), 143 ); 144 return; 145 } 146 147 # build filter 148 my $Filter = "($Self->{UID}=" . escape_filter_value( $Param{User} ) . ')'; 149 150 # prepare filter 151 if ( $Self->{AlwaysFilter} ) { 152 $Filter = "(&$Filter$Self->{AlwaysFilter})"; 153 } 154 155 # perform user search 156 $Result = $LDAP->search( 157 base => $Self->{BaseDN}, 158 filter => $Filter, 159 ); 160 if ( $Result->code() ) { 161 $Kernel::OM->Get('Kernel::System::Log')->Log( 162 Priority => 'error', 163 Message => "Search failed! ($Self->{BaseDN}) filter='$Filter' " . $Result->error(), 164 ); 165 return; 166 } 167 168 # get whole user dn 169 my $UserDN; 170 for my $Entry ( $Result->all_entries() ) { 171 $UserDN = $Entry->dn(); 172 } 173 174 # log if there is no LDAP user entry 175 if ( !$UserDN ) { 176 177 # failed login note 178 $Kernel::OM->Get('Kernel::System::Log')->Log( 179 Priority => 'notice', 180 Message => "User: $Param{User} sync failed, no LDAP entry found!" 181 . "BaseDN='$Self->{BaseDN}', Filter='$Filter', (REMOTE_ADDR: $RemoteAddr).", 182 ); 183 184 # take down session 185 $LDAP->unbind(); 186 return; 187 } 188 189 # get needed objects 190 my $UserObject = $Kernel::OM->Get('Kernel::System::User'); 191 my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); 192 193 # get current user id 194 my $UserID = $UserObject->UserLookup( 195 UserLogin => $Param{User}, 196 Silent => 1, 197 ); 198 199 # system permissions 200 my %PermissionsEmpty = 201 map { $_ => 0 } @{ $ConfigObject->Get('System::Permission') }; 202 203 # get group object 204 my $GroupObject = $Kernel::OM->Get('Kernel::System::Group'); 205 206 # get system groups and create lookup 207 my %SystemGroups = $GroupObject->GroupList( Valid => 1 ); 208 my %SystemGroupsByName = reverse %SystemGroups; 209 210 # get system roles and create lookup 211 my %SystemRoles = $GroupObject->RoleList( Valid => 1 ); 212 my %SystemRolesByName = reverse %SystemRoles; 213 214 # sync user from ldap 215 my $UserSyncMap = $ConfigObject->Get( 'AuthSyncModule::LDAP::UserSyncMap' . $Self->{Count} ); 216 if ($UserSyncMap) { 217 218 # get whole user dn 219 my %SyncUser; 220 for my $Entry ( $Result->all_entries() ) { 221 for my $Key ( sort keys %{$UserSyncMap} ) { 222 223 # detect old config setting 224 if ( $Key =~ m{ \A (?: Firstname | Lastname | Email ) }xms ) { 225 $Key = 'User' . $Key; 226 $Kernel::OM->Get('Kernel::System::Log')->Log( 227 Priority => 'error', 228 Message => 'Old config setting detected, please use the new one ' 229 . 'from Kernel/Config/Defaults.pm (User* has been added!).', 230 ); 231 } 232 233 my $AttributeNames = $UserSyncMap->{$Key}; 234 if ( ref $AttributeNames ne 'ARRAY' ) { 235 $AttributeNames = [$AttributeNames]; 236 } 237 ATTRIBUTE_NAME: 238 for my $AttributeName ( @{$AttributeNames} ) { 239 if ( $AttributeName =~ /^_/ ) { 240 $SyncUser{$Key} = substr( $AttributeName, 1 ); 241 last ATTRIBUTE_NAME; 242 } 243 elsif ( $Entry->get_value($AttributeName) ) { 244 $SyncUser{$Key} = $Entry->get_value($AttributeName); 245 last ATTRIBUTE_NAME; 246 } 247 } 248 249 # e. g. set utf-8 flag 250 $SyncUser{$Key} = $Self->_ConvertFrom( 251 $SyncUser{$Key}, 252 'utf-8', 253 ); 254 } 255 if ( $Entry->get_value('userPassword') ) { 256 $SyncUser{UserPw} = $Entry->get_value('userPassword'); 257 258 # e. g. set utf-8 flag 259 $SyncUser{UserPw} = $Self->_ConvertFrom( 260 $SyncUser{UserPw}, 261 'utf-8', 262 ); 263 } 264 } 265 266 # add new user 267 if ( %SyncUser && !$UserID ) { 268 $UserID = $UserObject->UserAdd( 269 UserTitle => 'Mr/Mrs', 270 UserLogin => $Param{User}, 271 %SyncUser, 272 UserType => 'User', 273 ValidID => 1, 274 ChangeUserID => 1, 275 ); 276 if ( !$UserID ) { 277 $Kernel::OM->Get('Kernel::System::Log')->Log( 278 Priority => 'error', 279 Message => "Can't create user '$Param{User}' ($UserDN) in RDBMS!", 280 ); 281 282 # take down session 283 $LDAP->unbind(); 284 return; 285 } 286 else { 287 $Kernel::OM->Get('Kernel::System::Log')->Log( 288 Priority => 'notice', 289 Message => "Initial data for '$Param{User}' ($UserDN) created in RDBMS.", 290 ); 291 292 # sync initial groups 293 my $UserSyncInitialGroups = $ConfigObject->Get( 294 'AuthSyncModule::LDAP::UserSyncInitialGroups' . $Self->{Count} 295 ); 296 if ($UserSyncInitialGroups) { 297 GROUP: 298 for my $Group ( @{$UserSyncInitialGroups} ) { 299 300 # only for valid groups 301 if ( !$SystemGroupsByName{$Group} ) { 302 $Kernel::OM->Get('Kernel::System::Log')->Log( 303 Priority => 'notice', 304 Message => 305 "Invalid group '$Group' in " 306 . "'AuthSyncModule::LDAP::UserSyncInitialGroups" 307 . "$Self->{Count}'!", 308 ); 309 next GROUP; 310 } 311 312 $GroupObject->PermissionGroupUserAdd( 313 GID => $SystemGroupsByName{$Group}, 314 UID => $UserID, 315 Permission => { 316 rw => 1, 317 }, 318 UserID => 1, 319 ); 320 } 321 } 322 } 323 } 324 325 # update user attributes (only if changed) 326 elsif (%SyncUser) { 327 328 # get user data 329 my %UserData = $UserObject->GetUserData( User => $Param{User} ); 330 331 # check for changes 332 my $AttributeChange; 333 ATTRIBUTE: 334 for my $Attribute ( sort keys %SyncUser ) { 335 next ATTRIBUTE if defined $SyncUser{$Attribute} && $SyncUser{$Attribute} eq $UserData{$Attribute}; 336 $AttributeChange = 1; 337 last ATTRIBUTE; 338 } 339 340 if ($AttributeChange) { 341 $UserObject->UserUpdate( 342 %UserData, 343 UserID => $UserID, 344 UserLogin => $Param{User}, 345 %SyncUser, 346 UserType => 'User', 347 ChangeUserID => 1, 348 ); 349 } 350 } 351 } 352 353 # variable to store group permissions from ldap 354 my %GroupPermissionsFromLDAP; 355 356 # sync ldap group 2 otrs group permissions 357 my $UserSyncGroupsDefinition = $ConfigObject->Get( 358 'AuthSyncModule::LDAP::UserSyncGroupsDefinition' . $Self->{Count} 359 ); 360 if ($UserSyncGroupsDefinition) { 361 362 # read and remember groups from ldap 363 GROUPDN: 364 for my $GroupDN ( sort keys %{$UserSyncGroupsDefinition} ) { 365 366 # search if we are allowed to 367 my $Filter; 368 if ( $Self->{UserAttr} eq 'DN' ) { 369 $Filter = "($Self->{AccessAttr}=" . escape_filter_value($UserDN) . ')'; 370 } 371 else { 372 $Filter = "($Self->{AccessAttr}=" . escape_filter_value( $Param{User} ) . ')'; 373 } 374 my $Result = $LDAP->search( 375 base => $GroupDN, 376 filter => $Filter, 377 ); 378 if ( $Result->code() ) { 379 $Kernel::OM->Get('Kernel::System::Log')->Log( 380 Priority => 'error', 381 Message => "Search failed! ($GroupDN) filter='$Filter' " . $Result->error(), 382 ); 383 next GROUPDN; 384 } 385 386 # extract it 387 my $Valid; 388 for my $Entry ( $Result->all_entries() ) { 389 $Valid = $Entry->dn(); 390 } 391 392 # log if there is no LDAP entry 393 if ( !$Valid ) { 394 395 # failed login note 396 $Kernel::OM->Get('Kernel::System::Log')->Log( 397 Priority => 'notice', 398 Message => "User: $Param{User} not in " 399 . "GroupDN='$GroupDN', Filter='$Filter'! (REMOTE_ADDR: $RemoteAddr).", 400 ); 401 next GROUPDN; 402 } 403 404 # remember group permissions 405 my %SyncGroups = %{ $UserSyncGroupsDefinition->{$GroupDN} }; 406 SYNCGROUP: 407 for my $SyncGroup ( sort keys %SyncGroups ) { 408 409 # only for valid groups 410 if ( !$SystemGroupsByName{$SyncGroup} ) { 411 $Kernel::OM->Get('Kernel::System::Log')->Log( 412 Priority => 'notice', 413 Message => 414 "Invalid group '$SyncGroup' in " 415 . "'AuthSyncModule::LDAP::UserSyncGroupsDefinition" 416 . "$Self->{Count}'!", 417 ); 418 next SYNCGROUP; 419 } 420 421 # set/overwrite remembered permissions 422 423 # if rw permission exists, discard all other permissions 424 if ( $SyncGroups{$SyncGroup}->{rw} ) { 425 $GroupPermissionsFromLDAP{ $SystemGroupsByName{$SyncGroup} } = { 426 rw => 1, 427 }; 428 next SYNCGROUP; 429 } 430 431 # remember permissions as provided 432 $GroupPermissionsFromLDAP{ $SystemGroupsByName{$SyncGroup} } = { 433 %PermissionsEmpty, 434 %{ $SyncGroups{$SyncGroup} }, 435 }; 436 } 437 } 438 } 439 440 # sync ldap attribute 2 otrs group permissions 441 my $UserSyncAttributeGroupsDefinition = $ConfigObject->Get( 442 'AuthSyncModule::LDAP::UserSyncAttributeGroupsDefinition' . $Self->{Count} 443 ); 444 if ($UserSyncAttributeGroupsDefinition) { 445 446 # build filter 447 my $Filter = "($Self->{UID}=" . escape_filter_value( $Param{User} ) . ')'; 448 449 # perform search 450 $Result = $LDAP->search( 451 base => $Self->{BaseDN}, 452 filter => $Filter, 453 ); 454 if ( $Result->code() ) { 455 $Kernel::OM->Get('Kernel::System::Log')->Log( 456 Priority => 'error', 457 Message => "Search failed! ($Self->{BaseDN}) filter='$Filter' " . $Result->error(), 458 ); 459 } 460 else { 461 my %SyncConfig = %{$UserSyncAttributeGroupsDefinition}; 462 for my $Attribute ( sort keys %SyncConfig ) { 463 464 my %AttributeValues = %{ $SyncConfig{$Attribute} }; 465 ATTRIBUTEVALUE: 466 for my $AttributeValue ( sort keys %AttributeValues ) { 467 468 for my $Entry ( $Result->all_entries() ) { 469 470 # Check if configured value exists in values of group attribute 471 # If yes, add sync groups to the user 472 my $GotValue; 473 my @Values = $Entry->get_value($Attribute); 474 VALUE: 475 for my $Value (@Values) { 476 next VALUE if $Value !~ m{ \A \Q$AttributeValue\E \z }xmsi; 477 $GotValue = 1; 478 last VALUE; 479 } 480 next ATTRIBUTEVALUE if !$GotValue; 481 482 # remember group permissions 483 my %SyncGroups = %{ $AttributeValues{$AttributeValue} }; 484 SYNCGROUP: 485 for my $SyncGroup ( sort keys %SyncGroups ) { 486 487 # only for valid groups 488 if ( !$SystemGroupsByName{$SyncGroup} ) { 489 $Kernel::OM->Get('Kernel::System::Log')->Log( 490 Priority => 'notice', 491 Message => 492 "Invalid group '$SyncGroup' in " 493 . "'AuthSyncModule::LDAP::UserSyncAttributeGroupsDefinition" 494 . "$Self->{Count}'!", 495 ); 496 next SYNCGROUP; 497 } 498 499 # set/overwrite remembered permissions 500 501 # if rw permission exists, discard all other permissions 502 if ( $SyncGroups{$SyncGroup}->{rw} ) { 503 $GroupPermissionsFromLDAP{ $SystemGroupsByName{$SyncGroup} } = { 504 rw => 1, 505 }; 506 next SYNCGROUP; 507 } 508 509 # remember permissions as provided 510 $GroupPermissionsFromLDAP{ $SystemGroupsByName{$SyncGroup} } = { 511 %PermissionsEmpty, 512 %{ $SyncGroups{$SyncGroup} }, 513 }; 514 } 515 } 516 } 517 } 518 } 519 } 520 521 # Compare group permissions from LDAP with current user group permissions. 522 my %GroupPermissionsChanged; 523 524 if (%GroupPermissionsFromLDAP) { 525 526 PERMISSIONTYPE: 527 for my $PermissionType ( @{ $ConfigObject->Get('System::Permission') } ) { 528 529 # get current permission for type 530 my %GroupPermissions = $GroupObject->PermissionUserGroupGet( 531 UserID => $UserID, 532 Type => $PermissionType, 533 ); 534 535 GROUPID: 536 for my $GroupID ( sort keys %SystemGroups ) { 537 538 my $OldPermission = $GroupPermissions{$GroupID} ? 1 : 0; 539 540 # Set the new permission (from LDAP) if exist, if not set it to a default value 541 # regularly 0 but it LDAP has rw permission set it to 1 as PermissionUserGroupGet() 542 # gets all system permissions to 1 if stored permission is rw. 543 my $NewPermission = $GroupPermissionsFromLDAP{$GroupID}->{$PermissionType} 544 || $GroupPermissionsFromLDAP{$GroupID}->{rw} ? 1 : 0; 545 546 # Skip permission if is identical as in the DB 547 next GROUPID if $OldPermission == $NewPermission; 548 549 # Remember the LDAP permission if they are not identical as in the DB. 550 $GroupPermissionsChanged{$GroupID} = $GroupPermissionsFromLDAP{$GroupID}; 551 } 552 } 553 } 554 555 # update changed group permissions 556 if (%GroupPermissionsChanged) { 557 for my $GroupID ( sort keys %GroupPermissionsChanged ) { 558 559 $Kernel::OM->Get('Kernel::System::Log')->Log( 560 Priority => 'notice', 561 Message => "User: '$Param{User}' sync ldap group $SystemGroups{$GroupID}!", 562 ); 563 $GroupObject->PermissionGroupUserAdd( 564 GID => $GroupID, 565 UID => $UserID, 566 Permission => $GroupPermissionsChanged{$GroupID} || \%PermissionsEmpty, 567 UserID => 1, 568 ); 569 } 570 } 571 572 # variable to store role permissions from ldap 573 my %RolePermissionsFromLDAP; 574 575 # sync ldap group 2 otrs role permissions 576 my $UserSyncRolesDefinition = $ConfigObject->Get( 577 'AuthSyncModule::LDAP::UserSyncRolesDefinition' . $Self->{Count} 578 ); 579 if ($UserSyncRolesDefinition) { 580 581 # read and remember roles from ldap 582 GROUPDN: 583 for my $GroupDN ( sort keys %{$UserSyncRolesDefinition} ) { 584 585 # search if we're allowed to 586 my $Filter; 587 if ( $Self->{UserAttr} eq 'DN' ) { 588 $Filter = "($Self->{AccessAttr}=" . escape_filter_value($UserDN) . ')'; 589 } 590 else { 591 $Filter = "($Self->{AccessAttr}=" . escape_filter_value( $Param{User} ) . ')'; 592 } 593 my $Result = $LDAP->search( 594 base => $GroupDN, 595 filter => $Filter, 596 ); 597 if ( $Result->code() ) { 598 $Kernel::OM->Get('Kernel::System::Log')->Log( 599 Priority => 'error', 600 Message => "Search failed! ($GroupDN) filter='$Filter' " . $Result->error(), 601 ); 602 next GROUPDN; 603 } 604 605 # extract it 606 my $Valid; 607 for my $Entry ( $Result->all_entries() ) { 608 $Valid = $Entry->dn(); 609 } 610 611 # log if there is no LDAP entry 612 if ( !$Valid ) { 613 614 # failed login note 615 $Kernel::OM->Get('Kernel::System::Log')->Log( 616 Priority => 'notice', 617 Message => "User: $Param{User} not in " 618 . "GroupDN='$GroupDN', Filter='$Filter'! (REMOTE_ADDR: $RemoteAddr).", 619 ); 620 next GROUPDN; 621 } 622 623 # remember role permissions 624 my %SyncRoles = %{ $UserSyncRolesDefinition->{$GroupDN} }; 625 SYNCROLE: 626 for my $SyncRole ( sort keys %SyncRoles ) { 627 628 # only for valid roles 629 if ( !$SystemRolesByName{$SyncRole} ) { 630 $Kernel::OM->Get('Kernel::System::Log')->Log( 631 Priority => 'notice', 632 Message => 633 "Invalid role '$SyncRole' in " 634 . "'AuthSyncModule::LDAP::UserSyncRolesDefinition" 635 . "$Self->{Count}'!", 636 ); 637 next SYNCROLE; 638 } 639 640 # set/overwrite remembered permissions 641 $RolePermissionsFromLDAP{ $SystemRolesByName{$SyncRole} } = 642 $SyncRoles{$SyncRole}; 643 } 644 } 645 } 646 647 # sync ldap attribute 2 otrs role permissions 648 my $UserSyncAttributeRolesDefinition = $ConfigObject->Get( 649 'AuthSyncModule::LDAP::UserSyncAttributeRolesDefinition' . $Self->{Count} 650 ); 651 if ($UserSyncAttributeRolesDefinition) { 652 653 # build filter 654 my $Filter = "($Self->{UID}=" . escape_filter_value( $Param{User} ) . ')'; 655 656 # perform search 657 $Result = $LDAP->search( 658 base => $Self->{BaseDN}, 659 filter => $Filter, 660 ); 661 if ( $Result->code() ) { 662 $Kernel::OM->Get('Kernel::System::Log')->Log( 663 Priority => 'error', 664 Message => "Search failed! ($Self->{BaseDN}) filter='$Filter' " . $Result->error(), 665 ); 666 } 667 else { 668 my %SyncConfig = %{$UserSyncAttributeRolesDefinition}; 669 for my $Attribute ( sort keys %SyncConfig ) { 670 671 my %AttributeValues = %{ $SyncConfig{$Attribute} }; 672 ATTRIBUTEVALUE: 673 for my $AttributeValue ( sort keys %AttributeValues ) { 674 675 for my $Entry ( $Result->all_entries() ) { 676 677 # Check if configured value exists in values of role attribute 678 # If yes, add sync roles to the user 679 my $GotValue; 680 my @Values = $Entry->get_value($Attribute); 681 VALUE: 682 for my $Value (@Values) { 683 next VALUE if $Value !~ m{ \A \Q$AttributeValue\E \z }xmsi; 684 $GotValue = 1; 685 last VALUE; 686 } 687 next ATTRIBUTEVALUE if !$GotValue; 688 689 # remember role permissions 690 my %SyncRoles = %{ $AttributeValues{$AttributeValue} }; 691 SYNCROLE: 692 for my $SyncRole ( sort keys %SyncRoles ) { 693 694 # only for valid roles 695 if ( !$SystemRolesByName{$SyncRole} ) { 696 $Kernel::OM->Get('Kernel::System::Log')->Log( 697 Priority => 'notice', 698 Message => 699 "Invalid role '$SyncRole' in " 700 . "'AuthSyncModule::LDAP::UserSyncAttributeRolesDefinition" 701 . "$Self->{Count}'!", 702 ); 703 next SYNCROLE; 704 } 705 706 # set/overwrite remembered permissions 707 $RolePermissionsFromLDAP{ $SystemRolesByName{$SyncRole} } = 708 $SyncRoles{$SyncRole}; 709 } 710 } 711 } 712 } 713 } 714 } 715 716 # compare role permissions from ldap with current user role permissions and update if necessary 717 if (%RolePermissionsFromLDAP) { 718 719 # get current user roles 720 my %UserRoles = $GroupObject->PermissionUserRoleGet( 721 UserID => $UserID, 722 ); 723 724 ROLEID: 725 for my $RoleID ( sort keys %SystemRoles ) { 726 727 # if old and new permission for role matches, do nothing 728 if ( 729 ( $UserRoles{$RoleID} && $RolePermissionsFromLDAP{$RoleID} ) 730 || 731 ( !$UserRoles{$RoleID} && !$RolePermissionsFromLDAP{$RoleID} ) 732 ) 733 { 734 next ROLEID; 735 } 736 737 $Kernel::OM->Get('Kernel::System::Log')->Log( 738 Priority => 'notice', 739 Message => "User: '$Param{User}' sync ldap role $SystemRoles{$RoleID}!", 740 ); 741 $GroupObject->PermissionRoleUserAdd( 742 UID => $UserID, 743 RID => $RoleID, 744 Active => $RolePermissionsFromLDAP{$RoleID} || 0, 745 UserID => 1, 746 ); 747 } 748 } 749 750 # take down session 751 $LDAP->unbind(); 752 753 return $Param{User}; 754} 755 756sub _ConvertTo { 757 my ( $Self, $Text, $Charset ) = @_; 758 759 return if !defined $Text; 760 761 # get encode object 762 my $EncodeObject = $Kernel::OM->Get('Kernel::System::Encode'); 763 764 if ( !$Charset || !$Self->{DestCharset} ) { 765 $EncodeObject->EncodeInput( \$Text ); 766 return $Text; 767 } 768 769 # convert from input charset ($Charset) to directory charset ($Self->{DestCharset}) 770 return $EncodeObject->Convert( 771 Text => $Text, 772 From => $Charset, 773 To => $Self->{DestCharset}, 774 ); 775} 776 777sub _ConvertFrom { 778 my ( $Self, $Text, $Charset ) = @_; 779 780 return if !defined $Text; 781 782 # get encode object 783 my $EncodeObject = $Kernel::OM->Get('Kernel::System::Encode'); 784 785 if ( !$Charset || !$Self->{DestCharset} ) { 786 $EncodeObject->EncodeInput( \$Text ); 787 return $Text; 788 } 789 790 # convert from directory charset ($Self->{DestCharset}) to input charset ($Charset) 791 return $EncodeObject->Convert( 792 Text => $Text, 793 From => $Self->{DestCharset}, 794 To => $Charset, 795 ); 796} 797 7981; 799