Category Archives: IT

ownCloud vs Ubuntu 22.04 LTS

owncloudHad issues getting the ownCloud client to work after doing an inplace upgrade from Ubuntu 20.04 LTS to 22.04LTS. Read various other articles that didn’t really help me. Most did point to the official ownCloud repository and in there is a file called install.sh, looking at that this would do all the tasks required to get the repository working and install the ownCloud client as well. After doing this, without uninstalling the current non working client, it was working. The only thing was that I had to disable and enable the “Launch on Startup” option and it was done. It is safe to say that the client in Ubuntu’s own repository will also get updated at some point in time and it becomes a non issue. Below are the steps performed.

  • Download the install.sh file via a webbrowser (you can of course use wget as well): https://download.owncloud.com/desktop/ownCloud/stable/latest/linux/Ubuntu_22.04/INSTALL.sh
  • Open the terminal and executed the following command in the folder where the INSTALL.sh file was downloaded): sudo sh .\INSTALL.sh
  • Start the ownCloud client
  • Disable and Enable the “Launch on Startup” setting on the Settings tab.

Update Your CO

If you ever come across the fact that the address info in Office 365 does not reflect your AD in respect to the country then the subject probably tells you what to do.

We don’t have many but there are international moves that occur within the company. Not that long ago somebody attended us that their country information on the Office 365 portal didn’t match. This whilst his on premise information within Active Directory did.

It seems like the value that is used via Azure AD Connect is the value present in ‘co’ within Active Directory. When using the normal management tools if the value in the directory got updated it would change both ‘c’ as well as ‘co’ entries (both represent ‘country’). However if updates occur via scripting in Powershell if the value of ‘c’ got updated, the value of ‘co’ remained the same. So if you come across this you probably have an automation running somewhere as did we that changes address information when needed make sure you update both.

Nostalgia

In a flair of …… I backed the ZX Spectrum Next Issue 2, essentially my start into computing with in 1984 the ZX Spectrum 48K (rubber keyed version). As only other system I’ve owned the 128K Toastrack model which in hindsight I should not have sold as their value is more than what I paid for in those days and back then I sold it for 150 Dutch Guilders, like 70 Euro’s (not counting inflation).

Roundcube on Synology

DSN (write): NOT OK(SQLSTATE[HY000] [2002No such file or directory) .

This is what you see when you try to configure a RoundCube installation on a virtual host within webstation on a Synology NAS using MariaDB 10 as a backend database (maybe 5 as well, as I’m not using that).

The solution is to modify the PHP profile you created for RoundCube (or if you didn’t create a specific one maybe do so now in order to avoid issues with other virtual hosts on the platform).

On the advanced settings window of your PHP profile, choose the ‘core’ tab and modify the below two settings in order to get your RoundCube installation connected to your backend database:

  • mysqli.default_socket – /run/mysqld/mysqld10.sock
  • pdo_mysql.default.socket – /run/mysqld/mysqld10.sock

Kace 2000 Model Specific

The following script can be handy if you want to deploy certain computer model specific software within a scripted installation on Dell Kace 2000. It might be usefull for other things as well (Windows Deployment Services maybe) if you want to check if it applies before applying the software or script.

@ECHO OFF
REM Obtain Computer Model information from WMI, this is done in two ways, check output for
REM both to which applies best, for example 'model' works best with HP and 'version' works
REM best with Lenovo. If something  applies to all computers from a single brand 'Manufacturer'
REM can be used.

REM Version 1.1, Added support for model and manufacturer

set model=
set version=
set manufacturer=

for /F "tokens=2 delims='='" %%j in ('wmic computersystem get model /value') do set model=%%j
for /F "tokens=2 delims='='" %%j in ('wmic csproduct get version /value') do set version=%%j
for /F "tokens=2 delims='='" %%j in ('wmic computersystem get manufacturer /value') do set manufacturer=%%j

REM Enter the Computer Models for which the package should apply below, one per line
REM Change the 'if' statement to what works to detect the right hardware, the above 'wmic'
REM commands can be run on the hardware to determine what is the best option.

If "%model%" == "HP EliteBook 2560p" GOTO INSTALL
If "%model%" == "HP EliteBook 8460p" GOTO INSTALL
If "%model%" == "HP EliteBook 8560p" GOTO INSTALL

GOTO GOODBYE

:INSTALL

REM Enter Command Line for Silent Installation below

launcher /S

EXIT

:GOODBYE

EXIT

If you want to check what to use, just putting the wmic commands into a batch file should give you the right amount of info which of the checks would work for the computer you want to deploy:

@echo off
wmic computersystem get model /value
wmic csproduct get version /value
wmic computersystem get manufacturer /value

Sophos UTM User Portal misconfiguration

While testing a Sophos UTM (formerly known as an Astaro Security Gateway) trying to get the user portal configured on port 443 I locked myself completely out of the system. It caused all websites that where configured by the Web Application Firewall to show the userportal and the admin interface was no longer functioning after it was restarted. So my only option to gain access was on console level. For this I followed steps 1 to 16 of this support article on the Sophos website.

  • Shutdown the UTM.
  • Ensure both a monitor and a keyboard are connected the UTM if it is a physical device. In case of a hypervisor, this will have to supply a console option.
  • Power on the UTM, wait until the GRUB boot loader starts …… and then press the ‘Esc’ key before the short timeout expires.
  • Highlight (do not press enter/return and use only the arrow keys) the version of software the UTM is running that does not mention either ‘previous’ or ‘rescue’.
  • Press the ‘e’ key on the keyboard.
  • Highlight (again do not press enter) the second option in the list shown on screen that starts with the word ‘kernel’.
  • Press the ‘e’ key on the keyboard.
  • Type: ” init=/bin/bash” at the end of the line (with a space before init).
  • Press enter and wait for the screen to reload.
  • Press the ‘b’ key on the keyboard. The UTM will boot up.
  • Type: “passwd loginuser”
  • Enter and re-enter a new password for the ‘loginuser’ account.
  • Type: “passwd root”
  • Enter and re-enter a new password for the root account.
  • Press Ctrl+Alt+Del on the keyboard. The UTM will reboot.
  • Login as root with the newly set password

After these 16 Steps are taken and I’ve logged on as the “root” user and looking around a bit I figured out what I think is the userportal and shut it down with the following command:

  • sh /var/mdw/scripts/uma stop

After running this command the WebAdmin interface was accessible again and I changed the configuration of the User Portal which caused the problem and rebooted the UTM after which everything returned to normal operations.

Mail Statistics for specific OU

Got a request if we could deliver how much mail is sent and received for a certain group of users in a specific organization unit over time. For the received mail they wanted to see what came from external or internal. Created a script for this that either can get daily statistics so it can be automated/scheduled or by entering certain dates generate a one time only version. It uses the transactionlogs in Exchange and in a default deployment that means you can go back for only 30 days. This is used against an Exchange 2013 Organization, there has been no testing against older versions of Exchange Server. A scripting language isn’t the greatest tool to start crunching numbers as it tends to be slow. As such would not suggest to use this in a larger deployment but rather use tooling that is build for this task. In a small deployment and for the task I created it for it works fine. It will run in automated fashion for a few months providing data for a specific project to reduce mail within the company and then shut down again (until the exercise might be repeated)…

#requires -version 3

<#
Program  : ExchangeMailStatistics.ps1 - Get Exchange Send and DELIVER statistics from scanning the transactionlog
Author   : Eugene Dullaard (https://eugene.dullaard.nl/?p=685)
Date     : 02-Mar-2015
           - Initial Script

Warning:
- Better not use in large deployments or run it per server otherwise completion of script might take a day or more

To Do's:
- You should modify the values under 'User needs to modify below variables' so they represent
  the requirements and environment

This script will retrieve transaction logs from designated exchange servers and will retrieve how many mails have been
send or delivered for a specific OU in AD.

It will create temp files (which you can optionally keep) and some fixed files which are configurable within the script.
#>

#Fixed variables
$Date            = [STRING]((get-date -Format s).split("T"))[0]
                                                        #Sortable date of today for filenames
#====================================
#User needs to modify below variables
#====================================

$StartDate       = "02/20/2015 00:00:00"                #Start Date of TransactionLog Scan, ignore if $Scripted is enabled
$EndDate         = "02/21/2015 00:00:00"                #End Date of TransactionLog Scan, ignore if $Scripted is enabled.

$Scheduled        = $false                              #If true the above $StartDate and $Enddate are not used, instead
                                                        #it will calculate today-2 as $StartDate and today-1 as $EndDate.
                                                        #Script should run daily at the same time.

$CASServerPS     = "https://<cas-server>/powershell"    #Host for implicit remoting Exchange.
$MailboxServers  = "<mailbox-server1>","<mailbox-server2>","<mailbox-server3>"
                                                        #Mailbox Servers to scan TransactionLogs on.
$SenderDomain    = "@domain.tld"                        #Sender domain in use can be a part of a name as well (-match).
$UserSearchBase  = "OU=Users,OU=Corp,DC=domain,DC=tld"  #LDAP SearchBase for user accounts.
$KeepTempFiles   = $true                                #Keep per server transactionlogfiles for other/later use if $true

#===============
#Start of Script
#===============

#Override certain variables in case $Scripted is enabled
if ($Scheduled -eq $true) {
  $StartDate = [DateTime]::Today.AddDays(-3)
  $EndDate = [DateTime]::Today.AddDays(-2)
  $Year = $StartDate.Year ; $Month = "{0:00}" -f $StartDate.Month ; $Day = "{0:00}" -f $StartDate.Day
  $Date = "$Year-$Month-$Day"
}

#Outputdata
$FileSubmitTotals          = ".\totals.$Date.submit.csv"
$FileDeliverInternalTotals = ".\totals.$Date.internal.deliver.csv"
$FileDeliverExternalTotals = ".\totals.$Date.external.deliver.csv"

#Get User objects from AD
$UserData = (Get-ADUser -Filter * -SearchBase $UserSearchBase -Properties ProxyAddresses | Select-Object Name,ProxyAddresses)

#Initialize remoting to Exchange Server
#Import-PSSession (New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $CASServerPS)

#==========================================================================
#Data-Collection and storage in CSV format for Submitted and DELIVERd mails
#==========================================================================

Write-Host "Data-retrieval" -ForegroundColor Green
Write-Host "=============="

#Create Datafile(s) to be parsed later, capturing send and DELIVER data per server and for usage beyond this script
#Per Server Data, so to scan if a user belongs to that server to avoid duplicate entries
$MailboxServers | ForEach-Object {

  $MailboxServer = $_
  Write-Host "$_ by SUBMIT"
  Out-File -InputObject "Sender" -FilePath .\$MailboxServer.$Date.submit.csv
  Get-MessageTrackingLog -Start $StartDate -End $EndDate -ResultSize Unlimited -EventID SUBMIT -Server $MailboxServer | `
    Select-Object Sender | ForEach-Object {
      $Sender = $_.Sender
      Out-File -InputObject "$Sender" -FilePath .\$MailboxServer.$Date.submit.csv -Append
    }
  Write-Host "$_ by DELIVER"
  Out-File -InputObject "Sender,Recipient" -FilePath .\$MailboxServer.$Date.deliver.csv
  Get-MessageTrackingLog -Start $StartDate -End $EndDate -ResultSize Unlimited -EventID DELIVER -Server $MailboxServer | `
    Select-Object Sender,Recipients | ForEach-Object {
      $Sender = $_.Sender
      $_.Recipients | ForEach-Object {
        Out-File -InputObject "$Sender,$_" -FilePath .\$MailboxServer.$Date.deliver.csv -Append
      }
    }
}

#===========================================================
#Data-Analysis SUBMIT for Name and amount of submitted mails
#===========================================================

Write-Host ""
Write-Host "Data-Analysis on SUBMIT" -ForegroundColor Green
Write-Host "======================="

$HashData = @{}         # Holds the name and amount of mails

$MailboxServers | ForEach-Object {
  Write-Host $_

  #Retrieve data for server from export file
  $Data = Import-Csv .\$_.$Date.submit.csv | Group-Object Sender | Select-Object Count,Name

  #Sanitize data so it discards non-user data and add to Output File
  $Data | ForEach-Object {
    $MailAddress = $_.Name
    #Get corresponding AD account
    $ADUser = ($UserData | Where-Object {$_.ProxyAddresses -match $MailAddress})
    #Check if account exists and if so add it to hash table using name and count
    if ($ADUser -ne $null) {
      if ($HashData[$ADUser.Name] -eq $null) {
        $HashData[$ADUser.Name] = $_.Count
      }
      else {
        $HashData[$ADuser.Name] = $HashData[$ADUser.Name] + $_.Count
      }
    }
  }
}

#Output collected data to CSV file
Write-Host ""
Write-Host "Writing SUBMIT data to $FileSubmitTotals"
$HashData.GetEnumerator() | ForEach-Object {New-Object -TypeName PSObject -Property @{Count=$_.Value;Name=$_.Name}} | `
  Export-CSV -Path $FileSubmitTotals -NoTypeInformation

#===========================================================
#Data-Analysis DELIVER for Name and amount of DELIVERd mails
#===========================================================

Write-Host ""
Write-Host "Data-Analysis on DELIVER" -ForegroundColor Green
Write-Host "========================"

$HashDataInternal = @{}       # Holds the Name and amount of internal sourced mails
$HashDataExternal = @{}       # Holds the Name and amount of external sourced mails

$MailboxServers | ForEach-Object {
  Write-Host $_

  #Retrieve MailboxUsers for Server
  $MailBoxUsers = (Get-Mailbox -Server $_ | Select-Object Name)

  #Retrieve data for server from export file
  $Data = Import-Csv .\$_.$Date.deliver.csv

  #Sanatize data to discard any non-user data and add to Output File
  $Data | ForEach-Object {
    $MailAddress = $_.Recipient

    #Get corresponding AD account
    $ADUser = ($UserData | Where-Object {$_.ProxyAddresses -match $MailAddress})
    if ($ADUser -ne $null) {

      #Check if user has a mailbox on this server
      $MailBoxUser = ($MailboxUsers | Where-Object {$_.Name -match $ADUser.Name})

      #After above checks add it to the internal or external hash table depending on sender
      if ($MailBoxUser -ne $null) {

        #Check if Sender is internal or external and add 1 to the appropiate hashtable
        if ($_.Sender -match $SenderDomain) {
          if ($HashDataInternal[$ADUser.Name] -eq $null) {
            $HashDataInternal[$ADUser.Name] = 1
          }
          else {
            $HashDataInternal[$ADuser.Name]++
          }
        }
        else {
          if ($HashDataExternal[$ADUser.Name] -eq $null) {
            $HashDataExternal[$ADUser.Name] = 1
          }
          else {
            $HashDataExternal[$ADuser.Name]++
          }
        }
      }
    }
  }
}

#Output collected data to CSV file
Write-Host ""
Write-Host "Writing internal DELIVER data to $FileDeliverInternalTotals"
$HashDataInternal.GetEnumerator() | ForEach-Object {New-Object -TypeName PSObject -Property @{Count=$_.Value;Name=$_.Name}} | `
  Export-CSV -Path $FileDeliverInternalTotals -NoTypeInformation
Write-Host ""
Write-Host "Writing external DELIVER data to $FileDeliverExternalTotals"
$HashDataExternal.GetEnumerator() | ForEach-Object {New-Object -TypeName PSObject -Property @{Count=$_.Value;Name=$_.Name}} | `
  Export-CSV -Path $FileDeliverExternalTotals -NoTypeInformation

#=================================================================
#Cleanup or rename of temp files depending on $KeepTempFiles value
#=================================================================
Write-Host ""
Write-Host "Cleanup" -ForegroundColor Green
Write-Host "======="
if ($KeepTempFiles -eq $false) {Write-Host "Deleting Temp Files"}
$MailboxServers | ForEach-Object {
  if ($KeepTempFiles -eq $false) {
    Remove-Item .\$_.$Date.submit.csv
    Remove-Item .\$_.$Date.deliver.csv
  }
}
Write-Host ""
Write-Host "End" -ForegroundColor Red
Write-Host "==="

CRM 2013 Claims-based authentication

http://www.microsoft.com/en-us/download/details.aspx?id=41701

crmOn the above link you can download the “Configuring Claims-based Authentication for Microsoft Dynamics CRM Server” manual from Microsoft’s Download Center. I’ve only ran through the process of configuring claims-based authentication internally but still came across a few things in that I had to adjust compared to the document that was downloaded. Unfortunately Microsoft doesn’t allow you to make comments in the Download Center as they do on other websites they host.

1) In the chapter “Configure the AD FS server for claims” on page 29, you need to enter userPrincipalName or User-Principal-Name, not User Principal Name as stated in the document. If you type the first it will change into the second option, but taking over what was mentioned in the document will lead to the an “Invalid Argument” error and within the URL you will find ErrorCode=0x80040203.

2) With the above you have AD FS Management already open so go to AD FS -> Service -> Certificates and make sure there are no self-signed certificates there, I had to change the token-decrypting and token-signing certificates for which I used the ADFS Website certificate and this certificate is also used in the Claims-Based authentication wizard as they have to match (or other wise your encryption/decryption will fail), which was what led me looking for these settings in the first place. Errors that are found in the URL included : “The issuer of the security token was not recognized by the IssuerNameRegistry. To accept security tokens from this issuer, configure the IssuerNameRegistry to return a valid name for this issuer.” or “An encrypted security token was received at the relying party which could not be decrypted. Configure the relying party with a suitable decryption certificate.” with the thumbprint of the certificate in there.

For the rest the document is good, however you need to read it very carefully as it is easy to overlook something. And with everything IT it is either 1 or 0. It works or it doesn’t.

Comodo vs. Microsoft

As stated in the previous post, there where some issues with the Comodo Positive SSL implementation. Those where caused by the webserver supplying an incorrect certificate chain so verification failed on certain platforms, among those anything using Android as well as Firefox certificate stores.

https

A correct certificate chain shows the following certificates:

  • AddTrust External CA Root
  • COMODO RSA Certification Authority
  • COMODO RSA Domain Validation Secure Server CA
  • <your own identidy> on this website being *.dullaard.nl

However when looking at the Windows certificate store it showed the following on the two servers I tested with:

  • COMODO
  • COMODO RSA Domain Validation Secure Server CA
  • <your own identity> on this website being *.dullaard.nl

And as this is published by any service using certificates any products actually verifying the whole chain will end up with a certificate failure. What essentially needs to be done is to fix the Windows certificate store to show you the first chain and not the second, as that resolves all the issues with Android, Firefox and maybe some others as well.

Comodo supplies the right certificates on their website, but I didn’t use that approach. When looking at the chain through Firefox (running on Ubuntu 14.04) it shows the chain as it should be, it also allows you to export the certificates in the chain. Those certificates I’ve imported into the Windows certificate store. The upper one has to go into the Trusted Root Certification Authorities container, the two others have to go into the Intermediate Certification Authorities container. I then noticed that it still didn’t show properly and searching by serial number I found a certificate in the Trusted Root Certification Authorities container that I exported and then removed. Once this was done it showed up correctly and errors on both Firefox and Android are gone.

Adding photos in AD

Within Active Directory of Microsoft there is a thumbnailPhoto entry where you can place a small photo. These pictures should preferably be 96 by 96 pixels and not larger than 10kb. You might create those photos from an already existing source and batch process them with something like Irfanview so they become the right size. There are several tools available to import them into Active Directory and they will also resize the picture, but it is possible to do this with PowerShell as well. The features are explained in the source code itself. In short it will read the pictures from a single source where the name of the picture should be similar to the logon name of the user and it will check if pictures are not exceeding the above mentioned limits. If successful the source picture is deleted, if not it is kept and a report is sent which can trigger a person to see what is wrong with the picture.

#requires -version 2

<#
Program  : ADPhotoImport.ps1
Author   : Eugene Dullaard
Date     : 14-Jul-2014
           - Initial Script

This script will import pictures from a source into Active Directory's
thumbnailPhoto field from a fixed content source.

Requirements:

Photo : 96x96 pixels and smaller than 10Kb
        filename in the format of <username>.jpg

Features :

- Content source is leading, it will search AD accounts by the name of the
  picture. The name without the extension of the picture should be matching
  SAMAccountName in Active Directory and can include dots, for example user
  account ab.user its picture should be ab.user.jpg.
- Check properties of picture before importing so that they comply with above
  requirements, wrong pictures will be added to an output report which is
  send after the script finishes.
- Remove photo once processed, keeping content source clean and allow for
  updating of existing pictures.
- If pictures exist and the corresponding account cannot be found this will
  be added to the output report. In this case the picture will not be removed.
- Runs with both a Content source as well as a Searchbase for the accounts.
- Searchbase will be searched recursively. Picture folder will not as it
  should delete the pictures once they've been processed. You should keep
  any existing source or have a seperate one if pictures need to be kept.
- Screen output for operator to see output while looking at the progress.
- Reporting errors will allow automated use of this script and corrective
  measures taken afterwards.
#>

#Variables (Change these to suit your environment)

$Content = "\\Server\Share\Folder"        # Content Source (Drive/UNC Path)
$Accounts = "OU=Users,DC=domain,DC=tld"   # User Accounts OU
$MailSender = "photoimport@domain.tld"    # Report Sent from mail address
$ReportAddress = "name@domain.tld"        # Report Sent to mail address
$SMTPServer = "mailserver.domain.tld"     # Mail server for relaying message

#Preliminaries

  Import-Module ActiveDirectory
  Add-Type -AssemblyName System.Drawing

  #Generate List of Photos in Content Source
  $Photos = Get-ChildItem $Content -Filter *.jpg

  #Report Header
  $Report = "Error report on ADPhotoImport
==============================
  
Maximum picture dimensions are 96 x 96 pixels, maximum size is 10Kb.

"
  $ReportCheck = $Report.Length           # Used to check for added entries

#Start processing the List of Photos (Main Loop)

$Photos | % {

  # Reset variables
  $ErrorStatus = $false
  $Basename = $_.BaseName
  Write-Host "==========================================="
  Write-Host "Processing : $Basename"

  # Check picture dimensions and size, if in error add to log and show on screen
  $jpg = New-Object System.Drawing.Bitmap $_.FullName
  if ($jpg.height -gt 96) {
    $Report = $Report + "$_ `t Pixel height exceeded.`n"
    Write-Host "Error..... : Pixel height exceeded" -ForegroundColor Red
    $ErrorStatus = $true
  }
  if ($jpg.width -gt 96) {
    $Report = $Report + "$_ `t Pixel width exceeded.`n"
    Write-Host "Error..... : Pixel width exceeded" -ForegroundColor Red
    $ErrorStatus = $true
  }
  if ($_.length -gt 10240) {
    $Report = $Report + "$_ `t Size limitation exceeded.`n"
    Write-Host "Error..... : File size exceeded" -ForegroundColor Red
    $ErrorStatus = $true
  }
  $jpg.Dispose()

  # Check for AD Account, if not existing add to log.
  $user = Get-ADUser -SearchBase $Accounts -Filter {(SAMAccountName -eq $BaseName)}
  if ($user -eq $null) {
    $Report = $Report + "$_ `t No AD user has been found.`n"
    Write-Host "Error..... : No matching user account" -ForegroundColor Red
    $ErrorStatus = $true
  }

  # If no errors are found, insert/replace picture and delete from content source
  if ($ErrorStatus -eq $false) {
    [byte[]]$photo = Get-Content $_.FullName -Encoding Byte
    Set-ADUser $_.BaseName -Replace @{thumbnailPhoto=$photo}
    Remove-Item $_.FullName
  }
 
} # End Main Loop

# Check Report Change, if changed send report
If ($Report.Length -ne $ReportCheck) {
  Send-MailMessage -From $MailSender -To $ReportAddress -Subject "AD Photo Import Error Report" `
    -SmtpServer $SMTPServer -Body $Report
}

Update: In order to see which accounts do not have a thumbnail photo you can enter the following command in PowerShell:

Get-ADUser -Filter * -SearchBase "OU=Users,DC=domain,DC=tld" -properties thumbnailPhoto | ? {!$_.thumbnailPhoto} | select Name,SAMAccountName

If you want to see a list of who has a thumbnail photo remove the ‘!’ in the code line above.