How to validate the user while installing service as user account? - service

I am creating an installer using wix. I need to install a service as user account given in installation process. But, before installing the service how can i validate that the user and the password are valid and also have the enough privilages to install the service. Is there any way to do that??
Following code in wix helps me to install service.
<ServiceInstall Id="AServiceInstall" DisplayName="myservice" Name="myservice" ErrorControl="normal" Start="auto" Vital="yes" Type="ownProcess" Account="[ACCOUNT]" Password="[PASSWORD]">
<ServiceDependency Id="x"></ServiceDependency>
</ServiceInstall>

For validating complex user input I generally have to create a custom action to do it.
Here is an example dialog I have for validating the URL to a web service and making sure it is accessible:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<CustomAction Id="ValidateProxyService" BinaryKey="XXX.CommServer.CustomActions.dll" DllEntry="ValidateProxyService" Return="check" />
<UI>
<Dialog Id="XxxInquiryServiceDlg" Width="370" Height="270" Title="CommService Setup">
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.InstallDirDlgBannerBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="2" />
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="Configure the settings for the xxx." />
<Control Id="Title" Type="Text" X="15" Y="6" Width="210" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}Configure xxx" />
<Control Type="Text" Id="ProxyServiceLabel" Width="95" Height="10" X="11" Y="60" Text="XXX Proxy Service URL:" />
<Control Type="Edit" Id="ProxyServiceTextBox" Width="244" Height="15" X="112" Y="58" Property="XXX_PROXY_SERVICE_URL" />
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Publish Event="DoAction" Value="ValidateProxyService" Order="1">1</Publish>
</Control>
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
</Dialog>
</UI>
</Fragment>
</Wix>
Then the custom action I wrote:
[CustomAction]
public static ActionResult ValidateProxyService(Session session)
{
try
{
string proxyServiceUrl = session["XXX_PROXY_SERVICE_URL"];
string message;
if (string.IsNullOrWhiteSpace(proxyServiceUrl))
{
session["XXX_PROXY_SERVICE_VALID"] = string.Empty;
MessageBox.Show(
"The proxy service URL is required.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return ActionResult.Success;
}
else if (!ValidateUrl(proxyServiceUrl, out message))
{
if (MessageBox.Show(
message,
"Error",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Warning) == DialogResult.Cancel)
{
session["XXX_PROXY_SERVICE_VALID"] = string.Empty;
return ActionResult.Success;
}
}
session["XXX_PROXY_SERVICE_VALID"] = "1";
}
catch (Exception ex)
{
session.Log("An error occurred during ValidateProxyService: {0}", ex);
return ActionResult.Failure;
}
return ActionResult.Success;
}
The general overview of what is going on is the dialog asks for a URL and puts it in the XXX_PROXY_SERVICE_URL property. When you press the Next button on the dialog it will run the custom action. The custom action then reads the XXX_PROXY_SERVICE_URL and tests if it is valid and tries to load the page. If it is invalid or fails it unsets the XXX_PROXY_SERVICE_VALID property.
In the main UI for the installer I have:
<Publish Dialog="XXXServiceDlg" Control="Next" Event="NewDialog" Value="OtherDlg" Order="2">XXX_PROXY_SERVICE_VALID</Publish>
So it will not proceed to the next page without the service being valid.
A few caveats:
I am just displaying a warning dialog and asking them if they want to continue (yes/no) even though the input is invalid, in situations where the service is not accessible now but they still need to complete the installation.
I really would like to handle the message dialog using WIX dialogs. Since I can't get the handle of the installer window, using the MessageBox class tends to pop under the installer under some circumstances still unknown to me. I also think it would be cleaner to handle all of the UI in WIX.
Certain useful things to validate require administrator access. Which creates annoying usability implications when generating an MSI. To run the UI part of an MSI as an administrator will require it to be launched via command line with administrator access or to generate a bootstrapper (.exe) that is either told to run as administrator by the user or configured to launch with administrator access.
Some of the blanks that need to be filled in:
All of the missing details to using custom actions in WIX.
The exact method of checking if a user's credentials are valid and what their permissions are.
Once you figure out those two things it shouldn't be too difficult to adapt the strategy above to validate any arbitrary user input.

You may need to rephrase the question. The credentials you're talking about need enough privilege to run as a service - they are not used to install the service, as your question implies. The install itself will (or should!) ask for elevation on UAC systems and install the service for you.
The first part of validation is based on calling LogonUser(), something like this is a guide to the API usage.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx
There's also some discussion here:
How to validate domain credentials?

Related

Create logon token using BI Platform RESTful SDK

I'm attempting to create a logon token using the BOE BI Platform RESTful SDK v4.1 (using RESTClient).
A GET request to http://server:6405/biprws/logon/long/ returns:
<attrs xmlns="http://www.sap.com/rws/bip">
<attr name="userName" type="string" />
<attr name="password" type="string" />
<attr name="auth" type="string" possibilities="secEnterprise,secLDAP,secWinAD,secSAPR3">secEnterprise</attr>
</attrs>
A POST to http://server:6405/biprws/logon/long/ with a single header of Content-Type: application/xml and a payload of
<attrs xmlns="http://www.sap.com/rws/bip">
<attr name="userName" type="string">myAccount</attr>
<attr name="password" type="string">myPassword</attr>
<attr name="auth" type="string" possibilities="secEnterprise,secLDAP,secWinAD,secSAPR3">secWinAD</attr>
</attrs>
returns:
<error>
<error_code>FWM 00006</error_code>
<message>Active Directory Authentication failed to log you on. Please contact your system administrator to make sure you are a member of a valid mapped group and try again. If you are not a member of the default domain, enter your user name as UserName#DNS_DomainName, and then try again. (FWM 00006)</message>
</error>
I've also tried attr name="userName" type="string">myAccount#mycompany.org</attr>, but with the same results.
A POST to http://server:6405/biprws/logon/adsso returns:
<error>
<error_code>RWS 00057</error_code>
<message>Method not allowed (RWS 00057)</message>
</error>
The credentials work with BI Launchpad and the CMC.
What am I missing?
First, a disclaimer -- I've only done REST WinAD with SSO, not manual logon. So I can't be absolutely sure that my suggestions below will fix your problem.
The call to /biprws/logon/adsso requires a GET not a POST, but that will likely not work until you have SSO working.
There are a few settings that are required for WACS to use WinAD, with or without SSO. The file is here:
SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\java\pjs\services\RestWebService\biprws\WEB-INF\web.xml
You will see a section commented out, starting with:
<!-- Kerberos filter section starts
Uncomment this section. Then set the following parameters:
idm.realm
idm.princ
idm.keytab
idm.kdc
idm.allowUnsecured
The values for these parameters should equal what was set in your system for BI launch pad. This is in:
SAP BusinessObjects\tomcat\webapps\BOE\WEB-INF\config\custom\global.properties
The format of the file is different (global.properties is a simple properties file, but web.xml is xml). So you can't just copy/paste the section, but you can copy the individual values. For example, in global.properties, you might see:
idm.keytab=C:/WINDOWS/bosso.keytab
This would be done in web.xml as:
<init-param>
<param-name>idm.keytab</param-name>
<param-value>C:/WINDOWS/bosso.keytab</param-value>
<description>
The file containing the keytab that Kerberos will use for
user-to-service authentication. If unspecified, SSO will default
to using an in-memory keytab with a password specified in the
com.wedgetail.idm.sso.password environment variable.
</description>
</init-param>
Couple of references:
http://myinsightbi.blogspot.com/
https://techwriter79.wikispaces.com/file/view/sbo41sp5_bip_rest_ws_en.pdf

Accept facebook login into my REST API

I have a backend server (Java / Spring / Spring Security).
Currently when users from mobile app login, they simply submit their username/password and Spring Security creates a Session and assign it to the request with a JSESSIONID.
We would now also have a button on the mobile app "Login with Facebook". Here is my understanding of how it will work.
mobile app uses facebook SDK to get an "access_token"
mobile app retrive USer Profile from facebook (name,surname,email etc..)
mobile checks (against MY server) if the username is unique
If username unique, call MY REST api, with something like this /login/facebook POST over SSL and passing the access_token, email, username etc...)
my server then checks if the access_token is valid
GET graph.facebook.com/debug_token?
input_token={token-to-inspect}
&access_token={app-token-or-admin-token}
If yes, if the UID returned by facebook is already present in my local database, I signin the user as follow:
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(username, null, ROLE_USER));
If i don't find the UID, I just create a new user and login the user.
and from now on every request made to the server by the mobile will have the SESSION (created and attached by spring security) and the mobile app is authenticated
Could someone tell me if this is a good way of doing things ?
Should I stop using sessions and switch to Spring-Security-OAUTH2 ?
EDIT 1
Based on Dave advices here is the updated spring-security config:
<!- handle login by providing a token-->
<security:http pattern="/login/facebook" auto-config="false" use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint">
<security:custom-filter ref="facebookLoginFilter" position="FORM_LOGIN_FILTER"/>
<security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>
<bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg value="/login/facebook"></constructor-arg>
</bean>
<!-- handle basic username + password logins-->
<security:http auto-config="true" use-expressions="true" entry-point-ref="forbiddenEntryPoint">
<security:form-login login-processing-url="/security_check" authentication-failure-handler-ref="authFailureHandler"
default-target-url="/" always-use-default-target="true" authentication-success-handler-ref="authSuccessHandler" />
...
my others patterns..
...
</security:http>
<bean id="forbiddenEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<bean id="authSuccessHandler" class="my.package.AuthenticationSuccessHandlerImpl"/>
<bean id="authFailureHandler" class="my.package.AuthenticationFailureHandlerImpl"/>
<bean id="facebookLoginFilter" class="pl.jcommerce.ocean.web.ws.controller.FacebookLoginFilter">
<property name="requiresAuthenticationRequestMatcher" ref="loginRequestUrlHandler"></property>
<property name="authenticationManager" ref="authManager"></property>
</bean>
<security:authentication-manager id="authManager">
<security:authentication-provider ref="facebookAuthenticationProvider" />
</security:authentication-manager>
<security:authentication-manager>
<security:authentication-provider ref="webServiceUserAuthenticationProvider" />
</security:authentication-manager>
<bean id="loginRequestUrlHandler" class="org.springframework.security.web.util.matcher.RegexRequestMatcher">
<constructor-arg index="0" value="/login/facebook" />
<constructor-arg index="1" value="POST" />
<constructor-arg index="2" value="false" />
</bean>
Facebook is already using OAuth2 server side, and provides its own native SDK for clients, so I don't see any advantage in your case of using OAuth2 in your server as well, unless your use case extends beyond what you outline above. Spring OAuth2 also has client side support, but not in a native app, so I don't really see anything at all wrong in principle with your proposal. You didn't say in any detail where you would set the security context up in your server, and I think that might be an important detail -- it has to happen in the security filter chain in the right place to get the session to be updated.
I took a crack at implementing something like this based on Dave Syer's answer here along with the Spring Security Angular materials he put together. To see an example see my forked github repo, specifically the classes in the security package.

Installer cannot start the service under User

Installer installs windows service.
I provide form to user to select one of accounts to start the service:
Local service
Local System
Network System
User account
When I select User and enter Domain\Administrator account + pwd during the installation, service cannot be started.
When I select Local Service it started ok. After this I can change manually account to the same Domain\Administrator account and it started ok.
Why such different behavior?
How I can start service during the installation under any users' account?
Take a look at the Util Extensions User element. You can set the CreateUser attribute to no, the Name attribute to the [PROPERTY] that you are using in your UI for UserName Input and the LogonAsService attribute to yes. This will instruct WiX to grant your user the LogOnAsService right without having to write a custom action to call ntrights.exe.
Here's a sample as requested:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="*" Name="Setup" Language="1033" Version="1.0.0.0" Manufacturer="test" UpgradeCode="5c6b0f52-d024-4f1b-bfae-2dbb96b3ef15">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<UIRef Id="WixUI_Minimal" />
<Feature Id="ProductFeature" Title="Setup" Level="1">
<ComponentRef Id="serviceComponent" />
</Feature>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Setup">
<Component Id="serviceComponent" Guid="380bbddd-daa7-0744-517b-37da768f5570">
<File Id="serviceFile" Source="$(var.WindowsService.TargetPath)" KeyPath="yes" />
<ServiceInstall Id="serviceInstall" Name="WindowsService" DisplayName="WindowsService" Start="auto" Type="ownProcess" ErrorControl="ignore" Account=".\serviceaccount" Password="p2Ekutrekac34ph2" />
<ServiceControl Id="serviceControl" Name="WindowsService" Start="install" Stop="both" Remove="both" Wait="no" />
<util:User Id="user" CreateUser ="yes" Name ="serviceaccount" Password="p2Ekutrekac34ph2" LogonAsService="yes" UpdateIfExists="yes" RemoveOnUninstall="yes" PasswordNeverExpires="yes" FailIfExists="no" Domain="[ComputerName]" CanNotChangePassword="yes" Disabled="no" PasswordExpired="no"/>
</Component>
</Directory>
</Directory>
</Directory>
</Product>
</Wix>
You need to make sure that the selected user account has the right to log on as a service. It doesn't matter if you are an Administrator, you cannot install services for an user without giving him the log on right.
If setting this policy works, you also need to do it dynamically during install. A solution is to use ntrights.exe as a custom action. This custom action can use your custom properties which contains the user account information.
In case anyone wonders why the code from #Christopher Painter his answer didn't work. I had similar code that didn't work with error 1923.
Error 1923. Service '' () could not be installed. Verify that you have sufficient privileges to install system services.
MSI (s) (10:08) [15:55:00:161]: Product: '' (64 bit) -- Error 1923. Service '' () could not be installed. Verify that you have sufficient privileges to install system services.
Until I found that services.msc dialog needs to be closed during installation.
No idea why, but it works.
During development services.msc was open all the time, so I never noticed.

Email alert when build fails in CruiseControl.Net

I have setup a Continuous Integration environment using CruiseControl.Net. I want to know how an email can be sent to a person at the time of a build failure.
Thanks in Advance.
You can use an <email> block within your <publishers> block.
Our system looks like this:
<publishers>
<xmllogger />
<email from="cruise#ourcompany.com" mailhost="mail.ourcompany.com" includeDetails="TRUE" mailport="25" useSSL="FALSE">
<users>
<user name="Mr Happy" group="buildmaster" address="mrhappy#ourcompany.com" />
<user name="Mr Strong" group="buildmaster" address="mrstrong#ourcompany.com" />
</users>
<groups>
<group name="buildmaster" notification="change" />
</groups>
<converters>
<regexConverter find="$" replace="#ourcompany.com" />
</converters>
<modifierNotificationTypes>
<NotificationType>Failed</NotificationType>
<NotificationType>Fixed</NotificationType>
</modifierNotificationTypes>
</email>
</publishers>
NB, we use an <svn> source control block to get latest source and trigger a build. The <regexConverter> section takes the svn user and adds "#ourcompany.com" to the end to form an email address.
You will need the details for an SMTP server to send the email. I believe it is possible to use gmail for this, but our company has its own SMTP server.
With this system, the "build masters" (Mr Happy and Mr Strong) will get an email whenever the build status changes, and anyone who has committed code into SVN will get an email when the build their code causes fails or is fixed.
The <xmllogger/> section is necessary as by default (if you have no <publishers> section), there is an XML logger publisher. This logs the information for the web interface.

Configure Webmatrix for Windows Users

I create asp .net page and i have use windows user to authenticate.
<authentication mode="Windows" />
I create simply page with one label and display information.
if (Page.User.Identity.IsAuthenticated)
{
Label1.Text = "Authenticated = 'TRUE'<br/>";
Label1.Text = Page.User.Identity.Name;
}
else
{
Label1.Text = "Authenticated = 'FALSE'<br/>";
}
I often get Authenticated = 'FALSE'
How configure web.config and WebMatrix to take user from Windows?
Probably you published your web site without changing authentication on the corresponding virtual directory of IIS.
You should deactivate "Anonymous" authentication and activate "Windows" authentication. The existence of <authentication mode="Windows" /> line in web.config is not enough for IIS. Moreover "Windows" authentication must be installed of cause (see for example this for more information).
try
<appSettings>
<add key="enableSimpleMembership" value="false" />
</appSettings>