Outlook AutoDiscover redirect limit (0x800c8206)

Today I encountered something I’ve not seen before, and I am sure more people will encounter this. If a client is in an Active Directory site without an AutoDiscover serviceConnectionPoint (SCP), it will try to connect to all AutoDiscover instances in the organization simultaneously. If the user have been cross-forest migrated, a redirect response will come from each server, and if there are more than 8 of them, Outlook reaches a redirect limit and fails to AutoDiscover.

After a cross-forest migration, the targetAddress of the source Active Directory object will be set to an address in the routing domain. For example when you do migrate to Office 365 / Exchange Online, your user will get a tenant.mail.onmicrosoft.com address, in my case mailNickname@gwrnd.mail.onmicrosoft.com. After the migration, when requesting details from AutoDiscover On-Premise, the response will be a redirect to the Exchange Online autodiscover. The problem is that when SCP is enabled in Outlook, it will count each response On-Premise as a redirect. This means that if it requests from all of your AutoDiscover instances, it will fail (the limit is 10).

If you believe this is your issue, you can look for error code 0x800c8206 in “Test E-mail Autoconfiguration” in Outlook. If you find this error code, here is your solution.

Disable SCP on the client

Instead of having Outlook look for SCPs in AD, you can disable this feature by adding the following to the registry on the client.


[HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Outlook\AutoDiscover]
"ExcludeScpLookup"=dword:00000001

With this disabled, Outlook will work more like on the internet. It will look at the UserPrincipalName (UPN), and try autodiscover.goodworkaround.com if your UPN ends with @goodworkaround.com. The reason this helps is that it will only get one response On-premise, not one per AutoDiscover virtual directory.

Configure AutoDiscoverSiteScope

By default a CAS only serves its own site. You can use the cmdlet Set-ClientAccessServer -identity -AutodiscoverSiteScope Oslo,Beijing,Boston,Seattle to configure it to serve more sites. This can help if you for example have 4 datacenters with 3 AutoDiscover instances in each, and some sites in AD does not have an Exchange server. The sites with the Exchange server will try all of the 12 AutoDiscover instances, and fail because it reaches the limit. If you configure the site to only try one of the sites, it will succeed because it will only try 3 servers.

Reduce the number of AutoDiscover instances

Do you really need 12? Remember that this is a lightweight service, and you can have a CAS without AutoDiscover. If you can manage to have 8 or less AutoDiscover instances you are safe.

Hope this helps someone.

ADFS authentication customization

Active Directory Federation Services (ADFS) offers the possibility of a lot of customization. Because it’s C# based and running on IIS, you can do basically everything. However, most people want to add a two factor authentication or customizing the looks and feel. In this article we will first implement an additional shared password for all users, and then show how you can extend this functionallity to implement two factor authentication mechanism.

When doing these customizations, you will need to use forms authentication. This means I assume that you know how to configure this (your ADFS proxy server(s) are already configured like this). The files we will be modifying is FormsSignIn.aspx and FormsSignIn.aspx.cs.

The first thing you would want, is to add the following to your FormsSignIn.aspx file. This just adds the PIN text box, nothing else.

<tr>
	<td>
		<span class="Label">PIN</span>
	</td>
	<td>
		
	</td>
	<td>&nbsp;</td>
</tr>

After modifying the file, your login page should look something like the following.

When you hit enter og the Sign In-button, the method SubmitButton_Click defined in FormsSignIn.aspx.cs is called. By default, this just involves calling SignIn( UsernameTextBox.Text, PasswordTextBox.Text ) and catching an exception if the authentication fails, but we want more. Continue on editing FormsSignIn.aspx.cs, replacing SubmitButton_Click with the following modified version.

protected bool VerifyPIN(string username, string PIN)
{
	return PIN.Equals("12345")
}

protected void SubmitButton_Click( object sender, EventArgs e )
{
	try
	{
		if(!VerifyPIN(UsernameTextBox.Text, PINTextBox) {
			ErrorTextLabel.Visible = true;
			ErrorTextLabel.Text = "Wrong PIN"
			return;
		}

		// PIN was ok, let's continue with SignIn
		SignIn( UsernameTextBox.Text, PasswordTextBox.Text );
	}
	catch ( AuthenticationFailedException ex )
	{
		HandleError( ex.Message );
	}
}

After changing this, the PIN for all users must be 12345, or they will not be able to log on. Now this does not seem to handy, i understand, but at this point you can instead of checking whether the PIN is 12345, check against a database, a web service, a radius service or other One-Time Password services. Just put whatever you need in the VerifyPIN function. I’ll make an article on it some day.

DirSync reports cd-error when litigation hold is enabled

Just experienced a problem with a Exchange 2010 SP3 Hybrid environment, with Office 365 wave 15. When In-place Hold is activated (typically for eDiscovery), DirSync returns cd-error when exporting the user attributes to Active Directory. This will not affect the functionallity, but will give you events in the Event Viewer telling you the following.

Executing export run profile on source MA failed for System.ManagementPropertyData. Failed to export objects:
dn="CN=User account,OU=User accounts,DC=goodw,DC=goodworkaround,DC=com",error-type=cd-error,error-code=87

If you open miisclient.exe (please do not do this if you do know know FIM!), you will see the cd-error on the SourceAD Management Agent, on the Export run profile. Digging further down will show you “Parameter incorrect”, and digging even further down, shows you that you are unable to export the attribute msExchUserHoldPolicies.

Doing some quick searches gives you this, telling you that this is a new attribute in Exchange 2013. Go ahead and extend the Active Directory schema to Exchange 2013, and you should see this error go away.

Eject DVD iso from Hyper-V 2012 using PowerShell

Very short article this one. Ever tried googling/binging for how to eject the dvd-drive in Hyper-V 2012 using PowerShell? It is actually very easy and logical, and also documented in the examples.

The following Get-Help cmdlet shows you how to do this.

# Get-Help Set-VMDvdDrive -examples

Basically do the following to eject ALL your dvd-drives (first line), or use the second line to eject all dvd drives that have mounted an ISO from the E:\Install directory. You can of course also use the third line to eject from a single VM.

# Get-VM | Get-VMDvdDrive | Set-VMDvdDrive -path $null
# Get-VM | Get-VMDvdDrive | where{if($_.Path) {$_.Path.ToLower().StartsWith("e:\install\")}} | Set-VMDvdDrive -path $null
# Get-VM dc1.marius.local | Get-VMDvdDrive | Set-VMDvdDrive -path $null

Drupal 7 on Lighttpd with rewrite

Apache is a well known web server that I have used quite a lot. It does however have it’s problems. First of all Apache is a memory hog of dimensions and is not working very well on low memory servers like Virtual Private Servers (VPS). Second it’s quite very mainstream so some security holes are discovered. And third, it is very big and therefore also very slow.

As I have currently been experimenting with a VPS, I have been working on making Drupal 7 working properly on Lighttpd, with pretty URLs / mod_rewrite enabled with quite good results. I have found no best practices for running Drupal on Lighttpd, so here is my configuration.

My setup

Operating System Debian 6 – 64 bit
Web server Lighttpd 1.4.28
PHP version 5.3
PHP modules imagick, mysql, mysqli, cgi-fcgi, gd, curl, iconv, mcrypt, pdo, pdo_mysql

Configuring lighttpd with php and rewrite

server.modules = (
        "mod_access",
        "mod_alias",
        "mod_compress",
        "mod_redirect",
        "mod_rewrite",
        "mod_fastcgi"
)

server.document-root        = "/var/www"
server.upload-dirs          = ( "/var/cache/lighttpd/uploads" )
server.errorlog             = "/var/log/lighttpd/error.log"
server.pid-file             = "/var/run/lighttpd.pid"
server.username             = "www-data"
server.groupname            = "www-data"

index-file.names            = ( "index.php", "index.html",
                                "index.htm", "default.htm",
                               " index.lighttpd.html" )

url.access-deny             = ( "~", ".inc" )

static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

include_shell "/usr/share/lighttpd/use-ipv6.pl"

dir-listing.encoding        = "utf-8"
server.dir-listing          = "disable"

compress.cache-dir          = "/var/cache/lighttpd/compress/"
compress.filetype           = ( "application/x-javascript", "text/css", "text/html", "text/plain" )

include_shell "/usr/share/lighttpd/create-mime.assign.pl"
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"

fastcgi.server = ( ".php" => ((
                "bin-path" => "/usr/bin/php5-cgi",
                "socket" => "/tmp/php.socket"
        ))
)

There are some changes from the default configuration file. First of all the modules mod_rewrite and mod_fastcgi is enabled. Then PHP is configured as a fastcgi server module.

The site configuration

$HTTP["host"] =~ "^goodworkaround\.com$" {
        server.document-root = "/home/marius/websites/drupal7/"
        server.errorlog = "/var/log/lighttpd/goodworkaround.com.error.log"
        accesslog.filename = "/var/log/lighttpd/goodworkaround.com.access.log"
        server.error-handler-404 = "/e404.php"

        url.rewrite-if-not-file += (
                "^/([^.?]*)\?(.*)$" => "/index.php?q=$1&$2",
                "^/([^.?]*)$" => "/index.php?q=$1",
                "([a-zA-Z\-\.\/\?\=\&]*)" => "/index.php"
        )
}

The important part here is the rewrite rules that you will need to make pretty URLs work. This is my own creation, so please refer to this page if you copy it and post it somewhere. 😉

This rewrite rule will work with things like overlay, image styles etc, all with pretty URLs enabled.

Have fun!

MySQL takes forever to connect – what is happening?

Just experienced a problem with a MySQL installation, which made all eksternal connections (not to localhost) take a very long time to open, making the MySQL server reach the connection limit and rendering it completely useless.

The problem was that the primary DNS server had died. Apparently MySQL uses reverse DNS when checking connections, by default. This can be turned of my adding skip-name-resolve to the [mysqld] section of the /etc/mysql/my.cnf configuration file and restarting the service.

Setuid on scripts

Running scripts as another user might sound like a trivial task, as this is what setuid is supposed to solve. However, if you create a bash script, a php script or another type of script you will soon discover that they do not respond to the setuid flag. This is mainly because of security and the fact that the scripting languages usually have not implemented the setuid functionality at all.

The easiest way of accomplishing this is to create a wrapper program that runs your script for you. C is a good language for this. The following file is an example on how to run a php as setuid.

Wrapper.c

#include 
#include 
#include 

int main(void) {
    system("/usr/bin/php /home/www-config/bin/createConfig.php");
    return 0;
}

The script can be compiled with cc Wrapper.c -o Wrapper, if you have gcc installed. After compiling, you will need to set the setuid flag on the executable by issuing the chmod u+s Wrapper command. Now you can issue ./Wrapper to run the php script given.

Let’s pretend we have a Linux system with two users good and workaround. Log onto the system as user workaround and create compile Wrapper.c. After issuing chmod u+s Wrapper, do a ls -al and you should see something like the following:

total 40
drwxr-xr-x   4 workaround  workaround    136 Sep 21 11:04 .
drwxr-xr-x  22 workaround  workaround    748 Sep 21 11:03 ..
-rwsr-xr-x   1 workaround  workaround  12588 Sep 21 11:04 Wrapper
-rw-r--r--   1 workaround  workaround    195 Sep 21 11:04 Wrapper.c

Note the highlighted s in the permissions of the Wrapper file, this is the setuid flag. Now log into the good user and run this script. This will now be run as the workaround user, since the setuid flag is set and the file is owned by the workaround user.

You might be tempted to take the script name as an argument. Do not do this, as this severly decreases the security! If you really want to do simething like this, please use predefined commands and give the command line argument as the “command number 3”. This way no malicious user can execute all commands through this script.

For more information, I would recommend this article.

Privilege separation from the www-data user

So, I got a question down in the comment section and will respond to it here for better formatting 🙂 I have the following 3 files.

/home/www-config/bin/createConfig.php

<?php
mkdir("/home/www-config/mytestfolder");
?>

/home/www-config/bin/createConfig.c

#include 
#include 
#include 

int main(void) {
    system("/usr/bin/php /home/www-config/bin/createConfig.php");
    return 0;
}

/home/marius/public_html/test/index.php

<?php
exec("/home/www-config/bin/createConfig");
?>

I have compiled the createConfig.c file and set the setuid bit, as explained in the guide.

ls -al

marius@debiansrv:~/public_html/test$ ls -al /home/www-config/bin/
drwxr-xr-x 2 www-config www-config 4096 Oct 11 11:14 .
drwxr-xr-x 3 www-config www-config 4096 Oct 11 11:14 ..
-rwsr-xr-x 1 www-config www-config 6618 Sep 20 23:08 createConfig
-rwx------ 1 www-config www-config  163 Sep 20 23:08 createConfig.c
-rwx------ 1 www-config www-config   51 Oct 11 11:09 createConfig.php

Here is the output of ls -l before and after I use my browser to visit ~/marius/test/.

ls -l /home/www-config

# Before going to the url
drwxr-xr-x 2 www-config www-config 4096 Oct 11 11:14 bin

# After
drwxr-xr-x 2 www-config www-config 4096 Oct 11 11:14 bin
drwxr-xr-x 2 www-config www-data   4096 Oct 11 11:18 mytestfolder

I also tested this with the root user, which also worked.

Currently the best workaround for the AC3 DTS problem in Lion

This is now quite old and Plex and VLC have updated their API.

As many people have discovered the DTS sound subsystem is badly broken in Mac OS X 10.6.8, 10.7.0 and 10.7.1. When playing videos with AC3 encoded suround sound, the sound subsystem continues to pump out DTS encoded noise through it’s digital ports (spdif and hdmi). You can work around this problem by either restarting or putting the mac to sleep and waking it again.

One possibilty (which I actually currently use) is the nightly builds. These are not guaranteed to work, but the DTS issue have been resolved in these.

However, the best way i found to fix this problem is the following.

  1. Stop playback
  2. Open a Terminal (or ssh into the box)
  3. Run the command sudo killall coreaudiod && sleep 5 && say good workaround (you will be asked for your password)
  4. Start playback

In xbmc it looks although you need to stop the playback, run the command and then start the playback all over.

For the lazy people

Why bother to remember a command and type your password? Do the following.

  1. Open a Terminal
  2. Run the command sudo nano /bin/fixsound
  3. Paste the following file (see the box), and hit Ctrl + O to write the file and Ctrl + X to close it
  4. Run the command sudo chmod 6755 /bin/fixsound

/bin/fixsound

#!/bin/bash
sudo killall coreaudiod && sleep 5 && say good workaround

You should now be able to run the command fixsound to fix your sound!

Dynamic routing in Linux and BSD

Dynamic routing are becomming more and more common these days, but not on the server side. Actually, Windows 2008 Server no longer supports Open Shortest Path First (OSPF), even though 2003 server did. The most common way of implementing dynamic routing in larger networks, are in the Wide Area Network (WAN) between firewalls. In this guide I will show how to use OSPF in Linux by using the Quagga Software Routing Suite.

As usual I use Debian linux, so let’s start by installing Quagga.

apt-get install quagga

That was not very hard. Let’s take a look at the different configuration files located in /etc/quagga/.

/etc/quagga/daemons

This file enables and disables the different services available in the routing suite. There are several supported protocols such as RIP, BGP and OSPF.

zebra=yes
bgpd=no
ospfd=yes
ospf6d=no
ripd=no
ripngd=no
isisd=no

/etc/quagga/zebra.conf

Zebra is the service that transfers configuration from Quagga to the operating system. Zebra takes care of updating interface addresses, routing tables, hostname, etc.

!
hostname server01
log file /var/log/quagga/zebra.log
password cliSecretPassword
!
interface bond0
    ip address 10.0.0.5/24
    multicast
!
interface eth0
!
interface eth1
!
interface lo

As you can clearly see from this configuration file, the server has hostname server01 and has bonded the eth0 and eth1 to a new bond0 interface.

/etc/quagga/ospfd.conf

This file configures the OSPF service. This is not a very advanced setup.

!
service advanced-vty
log file /var/log/quagga/ospfd.log
!
interface bond0
        ip ospf authentication message-digest
        ip ospf message-digest-key 1 md5 SECRETPASS
!

# Loopback
#interface lo
#    ip ospf priority 0
#!

router ospf
        redistribute static
        network 10.0.0.0/24 area 0.0.0.0
        area 0.0.0.0 authentication message-digest

Here the OSPF service is instructed to join area 0.0.0.0 with key 1 set as SECRETPASS. Also, the service redistributes all static routes. In this example, the server is a stub area.

I will be posting more configuration later.