2017-01-16 20:59:50 +01:00
/ * Copyright ( c ) Citrix Systems , Inc .
2013-06-24 13:41:48 +02:00
* All rights reserved .
*
* Redistribution and use in source and binary forms ,
* with or without modification , are permitted provided
* that the following conditions are met :
*
* * Redistributions of source code must retain the above
* copyright notice , this list of conditions and the
* following disclaimer .
* * Redistributions in binary form must reproduce the above
* copyright notice , this list of conditions and the
* following disclaimer in the documentation and / or other
* materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ,
* INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY ,
* WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
* /
using System ;
using System.Collections.Generic ;
using XenAdmin.Core ;
using XenAdmin.Network ;
using XenAPI ;
using System.ComponentModel ;
using System.Globalization ;
using System.Text.RegularExpressions ;
namespace XenAdmin.Actions
{
public class EnableAdAction : AsyncAction
{
private static readonly log4net . ILog log = log4net . LogManager . GetLogger ( System . Reflection . MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
private readonly string domain ;
private readonly string user ;
private readonly string password ;
2018-07-27 19:18:05 +02:00
public EnableAdAction ( IXenConnection connection , string domain , string user , string password , bool hideFromHistory )
: base ( connection , string . Format ( Messages . ENABLING_AD_ON , Helpers . GetName ( connection ) . Ellipsise ( 50 ) ) , Messages . ENABLING_AD , hideFromHistory )
2013-06-24 13:41:48 +02:00
{
if ( string . IsNullOrEmpty ( domain ) )
throw new ArgumentException ( "domain" ) ;
if ( string . IsNullOrEmpty ( user ) )
throw new ArgumentException ( "user" ) ;
if ( password = = null )
throw new ArgumentNullException ( "password" ) ;
2018-07-27 19:18:05 +02:00
var pool = Helpers . GetPool ( connection ) ;
if ( pool ! = null )
Pool = pool ;
else
Host = Helpers . GetMaster ( connection ) ;
2013-06-24 13:41:48 +02:00
this . domain = domain ;
this . user = user ;
this . password = password ;
}
private static Regex AuthFailedReg = new Regex ( @"^([1-9]+) \(0x.*\).*" ) ;
protected override void Run ( )
{
2018-07-27 19:18:05 +02:00
log . DebugFormat ( "Enabling AD on pool '{0}'" , Helpers . GetName ( Connection ) . Ellipsise ( 50 ) ) ;
2013-06-24 13:41:48 +02:00
Dictionary < string , string > config = new Dictionary < string , string > ( ) ;
config [ "domain" ] = domain ; // NB this line is now redundant, it is here to support the old now-superseded way of passing in the domain
config [ "user" ] = user ;
config [ "pass" ] = password ;
try
{
2018-07-27 19:18:05 +02:00
var pool = Helpers . GetPoolOfOne ( Connection ) ;
2016-06-02 16:09:01 +02:00
try
{
//CA-48122: Call disable just in case it was not disabled properly
2018-07-27 19:18:05 +02:00
Pool . disable_external_auth ( Session , pool . opaque_ref , new Dictionary < string , string > ( ) ) ;
2016-06-02 16:09:01 +02:00
}
catch ( Exception ex )
{
log . Debug ( "Tried to disable AD before enabling it, but it has failed. Ignoring it, because in this case we are executing disable on best effort basis only." , ex ) ;
}
2018-07-27 19:18:05 +02:00
Pool . enable_external_auth ( Session , pool . opaque_ref , config , domain , Auth . AUTH_TYPE_AD ) ;
2013-06-24 13:41:48 +02:00
}
catch ( Failure f )
{
// CA-37255 CA-38369 CA-39485
// We can get errors from likewise that correspond to an error in WinError.h
// By and large they are useless to the user so we log the details for support and show something more friendly.
if ( f . ErrorDescription [ 0 ] = = Failure . AUTH_ENABLE_FAILED & & f . ErrorDescription . Count > 2 )
{
Match m = AuthFailedReg . Match ( f . ErrorDescription [ 2 ] ) ;
if ( ! m . Success )
throw f ;
int errorId ;
if ( ! int . TryParse ( m . Groups [ 1 ] . Value , NumberStyles . Integer , CultureInfo . InvariantCulture , out errorId ) )
throw f ;
Win32Exception winErr = new Win32Exception ( errorId ) ;
log . ErrorFormat ( "Received error from likewise when attempting to join domain: {0}" , winErr ) ;
}
XenRef < Host > hostref = new XenRef < Host > ( f . ErrorDescription [ 1 ] ) ;
Host host = Connection . Resolve ( hostref ) ;
if ( host = = null )
2018-07-27 19:18:05 +02:00
throw ;
if ( f . ErrorDescription [ 0 ] = = Failure . POOL_AUTH_ENABLE_FAILED_WRONG_CREDENTIALS )
2013-06-24 13:41:48 +02:00
throw new CredentialsFailure ( f . ErrorDescription ) ;
2018-07-27 19:18:05 +02:00
throw new Exception ( string . Format ( Messages . AD_FAILURE_WITH_HOST , f . Message , host . Name ( ) ) ) ;
2013-06-24 13:41:48 +02:00
}
Description = Messages . COMPLETED ;
}
/// <summary>
/// Exception thrown when enabling AD authentication fails due to wrong supplied credentials
/// </summary>
public class CredentialsFailure : Failure
{
public CredentialsFailure ( List < string > err )
: base ( err )
{
}
}
}
}