Google Apps for Domains Having Serious Issues

Many people, including myself, seem to be having major issues with Google Apps for domains at the moment; starting last Friday (7th), my Nexus One logged itself out of Google Talk and refused to log back in, the Pidgin IM client on my desktop did the same and even the Google Talk client is showing the same symptoms.

In addition, the problem appears to affect Gmail notifications on my phone (I’m having to manually refresh it to sync changes to my mailbox) and I can’t download anything from the Android Marketplace. In the last few hours the problem seems to have spread to Gmail itself and I can no longer log into Google Talk through my inbox either.

The problem appears to have coincided with the changes made by Google to reintegrate the domain for UK-based users (due to a prior legal challenge many UK users had to make do with a address), which could simply be a coincidence, but either way it’s a massive PITA.

Some users have tried factory resets of their phones, removing and re-adding Google Apps features to their domains and even creating new Gmail accounts and re-associating their various services with them so as to make them accessible via their phones, though this isn’t recommended as it has some nasty side-effects such as making you re-buy any purchased Marketplace Apps.

The worst part of it all is that Google appear to be silent on the matter; there are a large number of threads on their support forums now covering most of the issues (with varying degrees of literacy and general coherence) but no official (or unofficial) word on what the cause of the problem might be and/or what the outlook is with regards to a fix.

Update – 12/05/2010: Well, after 5 days without Google Talk (and therefore without “push” email and the Android market), full service has been restored; to me at least. Let’s hope it doesn’t happen again any time soon.

On DRM And The Future of PC Games

Much has been made in the last couple of days of the fact that warez scene group Skidrow have “cracked” Ubisoft’s Assassin’s Creed 2, however, this isn’t really a crack of the DRM at all, it simply internalises the server emulation that non-scene groups had already put together so it’s not as much hassle to play.

That said, ultimately you can’t crack Ubisoft’s new DRM any more than you can “crack” World of Warcraft; they are serving parts of the game from their servers and unless you either obtain a copy of that data and emulate the server (which isn’t really a crack) you can’t get around it. It’s not as simple as just bypassing a CD check or setting a function to always return true, they’re actually shipping a partial game and as long as their customers will bear it (although given their awful server uptime they’re not helping themselves out) they’ll keep doing it and probably push it even further.

Once games move into the SAAS realm you can say goodbye to owning *any* part of a game you “buy” as all you’ll have is the MMO-esque client application and everything else will be delivered over the wire, doubtless with “Premium” subscriptions available if you want priority access to the game servers to minimize lag & waiting time before you can play.

I think we can all agree that this is a really bad place for PC games to be headed.

Get failed sshd logons from Windows Eventlog Part 2

In answer to my question about a more efficient means of filtering by timestamp with FilterXPath, I’ve worked out how to do it “properly”; it’s not as fast as I was hoping, but it’s still taken the execution time down from 20 to 2 minutes so I can’t complain too much. I’ve also modded the script to deal with cases where Password Authentication is disabled and so you don’t get “Failed Password” events logged, just “Invalid User” or “No supported authentication methods available” instead.

The time value for comparison is in milliseconds, so 604800000 for 7 days, 86400000 for 24 hours, etc.

#sshd failed logon attempt finder
#Adam Beardwood 12/02/2010
#v1.0 - Initial Release
#v1.1 - Dramatically improved event gathering speed and added handling for non-password authentication failures
#Get all SSH events from the last 7 days from the Application eventlog (this may take some time)
$events = Get-WinEvent -LogName Application -FilterXPath "*[System[Provider[@Name='sshd'] and TimeCreated[timediff(@SystemTime) <= 604800000]]]"
#Create array to store IPs
$ips = @()
foreach($event in $events){
	#Convert the event data to XML so we can access the EventData (Otherwise there's no way to access the event message contents with "unregistered" eventids)
	$event = [xml]$event.ToXml()
	#Thin the herd a little and only process useful messages
	if($event.Event.EventData.Data.Contains("Invalid user") -or $event.Event.EventData.Data.Contains("Failed Password") -or $event.Event.EventData.Data.Contains("No supported authentication methods available")){
	#Do regex search of the message data for IP addresses and if found, add them to the $ips array
	$ip = $event.Event.EventData.Data
	$regex = [regex]"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
	$ip = $($($regex.matches($ip)).Captures).Value
	$ips = $ips + $ip
$date = get-date -Format yyyy-MM-dd
$file = new-item -type file "SSHLog-$date.txt" -force
add-content $file $($ips | select -uniq)

Get with the program, Adobe

Almost 2 months after Adobe released a patch for Acrobat Reader 9.3.0 to resolve the highly critical remote execution vulnerability, they’re still offering 9.3.0 as the only option for download:

So unless you run the Adobe Updater immediately after install (Which seems to have issues with UAC on my Windows 7 machine unless you explicitly launch Reader as an Administrator), or make the effort to find the patch to 9.3.1, your machine is going to be at risk every time you open a PDF.

It’s not the first time they’ve done it, either.

Get failed sshd logons from Windows Eventlog

This script grabs IP addresses of the last 7 days worth (Customisable) of failed logon attempts for sshd from the Windows event log. This is handy if you use a Windows-based OpenSSH package like copSSH and want to be able to generate a list of all the people making random attempts to logon to your machine for adding to a blacklist or firewall rule.

#Get all SSH events from the last 7 days from the Application eventlog (this may take some time). Change "adddays(-7)" to alter the timeframe.
$events = Get-WinEvent -LogName Application -FilterXPath "*[System[Provider[@Name='sshd']]]" | ?{$_.timecreated -gt $((get-date).adddays(-7))}
#Create array to store IPs
$ips = @()
foreach($event in $events){
	#Convert the event data to XML so we can access the EventData (Otherwise there's no way to access the event message contents with "unregistered" eventids)
	$event = [xml]$event.ToXml()
	#Thin the herd a little and only process "Failed Password" messages
	if($event.Event.EventData.Data.Contains("Failed password")){
	#Do regex search of the message data for IP addresses and if found, add them to the $ips array
	$ip = $event.Event.EventData.Data
	$regex = [regex]"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
	$ip = $($($regex.matches($ip)).Captures).Value
	$ips = $ips + $ip
$date = get-date -Format yyyy-MM-dd
$file = new-item -type file "SSHLog-$date.txt" -force
#Add unique IPs to output file
add-content $file $($ips | select -uniq)

If anyone has a better way to filter Get-Eventlog using FilterXPath by date as well as something else (Provider in this case) rather than having to get the whole thing and “where” it after, please let me know. I know I *should* be able to do it, but I could never get it to work properly (I think it was a timestamp formatting issue) and the documentation is a bit spartan.

On IT and Friday Afternooons

It’s a curious feature of “Nine to Five” IT departments that Friday afternoons are always a write-off; not because of laziness or the typical end-of-week malaise, but because nobody is willing to risk making a change that could break something and leave them with Friday night overtime or even a full weekend of work.

As a result of this, a full 10% of the working week is wasted (well, 10% more than would be otherwise) playing flash games and messing around with remote controlled helicopters…for example. The problem is that there’s no easy solution, if you send everyone home on a Friday lunchtime, then it just means Friday morning is wasted – and the same obviously applies to having Friday off entirely or working Saturday mornings.

Clearly what’s needed is some kind of useful, read-only task that takes about 4 hours and can be done weekly without being too soul-destroying (I’m not spending every Friday afternoon writing documentation, that’s for sure). When I discover something I’ll let you know.

Powershell & DHCP Scopes

Really quick one this; I had a DHCP server with 136 scopes on it that I needed to disable and so the following script was born. It takes 1 argument – the hostname of the DHCP server in question; leave blank for localhost:

#DHCP Server-wide scope disabler
#Adam Beardwood 16/02/2010
#v1.0 - Initial Release
Disables all DHCP scopes on the specified server
DNS name or IP of server to work with
	[Parameter(Mandatory=$false,ParameterSetName="Server",ValueFromPipelineByPropertyName=$true,Position=0,Helpmessage="DNS name or IP of server to work with")]$Server = "localhost"
$Server = "\\$Server"
$scopes = netsh dhcp server $server show scope
foreach($scope in $scopes){
$regex = [regex]"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
$ip = $scope | foreach {$regex.Matches($_) | foreach {$_.Captures[0].Value}}
if($ip -ne $null){
& netsh dhcp server $server scope $ip[0] set state 0

Sophos/Utimaco Safeguard Auto-Sync Script

Those of you who have used Safeguard will know that for reasons known only to the Germans, Utimaco decided not to provide any way to automatically sync Safeguard with your AD domain(s) without resorting to a rather buggy API. They provide some example code for VBScript, but if you want to do it in Powershell instead, look no further:

#Safeguard Directory Synchronisation Tool
#Adam Beardwood 04/02/2010
#v1.0 - Initial Release
#Load Safeguard .NET Assembly for use
[void] [System.Reflection.Assembly]::LoadWithPartialName("Utimaco.SafeGuard.AdministrationConsole.Scripting")
#---Declare Variables---
#DateTime Stamp
$DTS = date -format yyyy-MM-dd--hh-mm
#Root DSN to bind connection to
$dsn = "DC=mydomain,DC=local"
#Location for Log File
$logFileName = "D:\Scripts\SGSync."+$DTS+".log"
#Sync Group Membership
$membership = 1
#Sync Account State
$accountState = 1
#Relocate Move Objects if they have been relocated to another sync'd OU
$takeCareOfMovedObjects = 1
if($args[0] -ne $null){$Debug = $True}else{$Debug = $False}
#---End Variables---
#---Define Functions---
#Function to send email alert on Sync completion
Function SendEmail ($Errs){
$smtpServer = "smtp.mydomain.local"
The Safeguard Enterprise Automated Sync process ran. The following errors occurred:
$(foreach($item in $Errs){$item;"`r"})
$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mail.Attachment($logFileName)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "SGE AD Sync<_SGSync@mydomain.local>"
$msg.Subject = "SGE Sync Process"
if($Debug){write-host "Email sent, also," $Errs}
#Function to actually sync Safeguard
Function SGSync ($OU){
$adsStartContainer = $OU+","+$dsn
if($Debug){write-host "Syncing:" $adsStartContainer}
[ref] $Outcome = $ScriptingDirectory.SynchronizeDirectory($dsn, $adsStartContainer, 1, $logFileName, $membership, $accountState, $takeCareOfMovedObjects)
if($Debug){write-host "Start OU:" $Result}
$Result = $Scripting.GetLastError($Outcome)
if($Debug){write-host "GetLastError returns:" $Result}
#---End Functions---
#Create scripting objects, authenticate to directory and then initialise the sync process
if($Debug){write-host "Synchronization of Users & Computers ... Started"}
try{$Scripting = new-object Utimaco.SafeGuard.AdministrationConsole.Scripting.Base}
catch{write-host "An Error Occurred While Attempting To Load Safeguard Directory Synchronisation Libraries. Quitting...";exit 0}
if($Debug){write-host "Created Base Object"}
$ScriptingDirectory = $Scripting.CreateDirectoryClassInstance()
if($Debug){write-host "Created Directory Object"}
$Result = $Scripting.Initialize()
if($Debug){write-host "Init API:" $Result}
$Result = $Scripting.AuthenticateService()
if($Debug){write-host "Authenticate:" $Result}
$Result = $ScriptingDirectory.Initialize()
if($Debug){write-host "Init SGD:" $Result}
#---Sync the following OUs---
SGSync("OU=An OU")
SGSync("OU=Another OU")
#Free up resources
$Result = $ScriptingDirectory.FreeResources()
if($Debug){write-host "Finalize SGD:" $Result}
$Result = $Scripting.FreeResources()
if($Debug){write-host "Finalize API:" $Result}
#Get errors from the generated log file
$Errs = select-string -pattern "Failure" -path $logFileName
#Send email alert
if($Errs -ne $null){SendEmail $Errs}
if($Debug){write-host "Synchronization of Users & Computers...End"}

Obviously this has to be run on a machine which has the Safeguard .NET assemblies installed (Management Console or Server packages)

ISA Server & Powershell

I’ve recently been trying to find a way to work with ISA 2006 using powershell; it’s not as straightforward as I would have hoped as all the docs are for C and Vbscript and they’re not exactly full of information anyway. That said, a few people seem to have been managing so I dived in and came up with this; it’s a Powershell script to add IP address ranges (In my case, just single addresses) from a text file to an ISA Network object (for the purposes of blacklisting). Requires Powershell v2 and needs to be run on an ISA server. For the record, the ISA API is horrible.

Adds specified IP address ranges to a given Network in ISA
.PARAMETER network
Network Name to edit
Path to file containing list of IPs to add
	[Parameter(Mandatory=$true,ParameterSetName="path",ValueFromPipelineByPropertyName=$true,Position=1,Helpmessage="Path to file containing list of IPs to add")]$path
	[Parameter(Mandatory=$true,ParameterSetName="network",ValueFromPipelineByPropertyName=$true,Position=0,Helpmessage="Network Name to edit")]$network
#Create ISA COM Objects
$root = new-object -comObject "FPC.Root" -strict
#Get our array (well, there is only one in this case)
$server = $root.Arrays | Select-Object -first 1
#Get IPRangeSet for the required network
$ipranges = $server.NetworkConfiguration.Networks.item($network).IpRangeSet
$file = gc $path
foreach($ip in $file){
	$flag = 0
	foreach($iprange in $ipranges){
		if($iprange.ip_from -match $ip){$flag = 1}
	if($flag -ne 1){$ipranges.add($ip,$ip)}