Wednesday, January 1, 2014

Secure a WCF REST Service with an X509 Certificate, hosted on IIS

Sometimes, we want to expose some API (services) publicly. In order to secure the service, we can go with standard user name/password authentication. We can also add extra security by validating client IP. Services can also be secured by enabling X509 Certificate authentication if it is meant for closed user group or few partners. There are many other options to secured the services.

In this article, we will discuss how to enable X509 authentication in WCF 
RESTFull service that is hosted on IIS.

Here are the steps:
  1. Create certificates
  2. Configure the web.config
  3. Configure the IIS
  4. Sample client application

1. Create certificates

Ideally the certificates should be obtained from the trusted certificate authority. But in the development environment, we can create it using makecert.exe that comes with Visual Studio. 

We need one certificate for the server and one certificate for each unique client. For this example, we will create two certificates one for the server and one for the client. Visit here to know more about makecert.exe.

makecert -sv srvr.pvk srvr.cer -n CN=testServer
makecert -sv client1.pvk client1.cer -n CN=testClient1

Generate Pfx file from pvk file. Visit here for more.

pvk2pfx -pvk srvr.pvk -pi password -spc srvr.cer  -pfx srvr.pfx
pvk2pfx -pvk client1.pvk -pi password -spc client1.cer  -pfx client1.pfx

Once we have both the certificate files ready, we have to register them.

In the server:
Import srvr.pfx into LocalMachine -> Personal, Certificates 
Import client1.cer into LocalMachine -> Trusted People, Certificates

In the client
Import client1.pfx into LocalMachine -> Personal, Certificates 

We might have to import both the files in the systems' LocalMachine -> Trusted Root Certificate Authorities. This is not required in case of valid certificates.

2.  Configure the web.config

Once the certificates are ready, we have to configure the WCF service to set security mode is Transport and client credential type is Certificate as mentioned below:
<system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="webSecureBinding">
          <security mode="Transport">
            <transport clientCredentialType="Certificate"/>
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="securedBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="webBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="RestServerWcf.Service" behaviorConfiguration="securedBehavior">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="webSecureBinding" behaviorConfiguration="webBehavior" contract="RestServerWcf.IService"/>
      </service>
    </services>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>


3. Configure the IIS

We also have to configure IIS for SSL (https). First lets add new binding for https. Open the IIS, select the web site and click on Bindings at right hand side:

Add new binding:

Configure SSL Settings, click on SSL Settings:
And finally set the Require SSL:


4. Sample client application

Once, we are done with all the configuration then lets build sample client application to consume the services
// Generate request
HttpWebRequest request = WebRequest.Create(@"https://server/service.svc/json/customers") as HttpWebRequest;

// Find the certificate from the local store
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, "Client", false);
X509Certificate cer1 = new X509Certificate(collection[0]);

// Add the certificate into the request            
request.ClientCertificates.Add(cer1);

// Hit the service and get the response
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

Done. 

Tuesday, June 29, 2010

Find IP to Host name

Dos command

nbtstat -a ipaddress

ping -a ipaddress

Wednesday, March 25, 2009

Change the owner of object in SQL Server 2000

UPDATE [dbname].dbo.sysobjects SET uid=6 WHERE uid = 1

To get user id:
select DISTINCT o.name, o.uid from dbo.sysusers o left join master.dbo.syslogins l on l.sid = o.sid where ((o.issqlrole != 1 and o.isapprole != 1 and o.status != 0) or (o.sid = 0x00) and o.hasdbaccess = 1)and o.isaliased != 1 order by o.name

If it throws the error 
'Ad hoc updates to system catalogs are not enabled. The system administrator must reconfigure SQL Server to allow this.'

Then change the configuration
exec sp_configure 'allow updates',1
RECONFIGURE WITH OVERRIDE
and then try again.

Find objects in database

To find perticular object in database:

SELECT name, owner= user_name(uid) FROM [dbname].dbo.sysobjects WHERE type= 'U' order by name 

Type:

C = CHECK constraint
D = Default or DEFAULT constraint
F = FOREIGN KEY constraint
FN = Scalar function
IF = Inlined table-function
K = PRIMARY KEY or UNIQUE constraint
L = Log
P = Stored procedure
R = Rule
RF = Replication filter stored procedure
S = System table
TF = Table function
TR = Trigger
U = User table
V = View
X = Extended stored procedure

Grant objects permission to users in SQL Server 2000

GRANT
    { ALL [ PRIVILEGES ] |
permission [ ,...n ] }
    {
        [
( column [ ,...n ] ) ] ON { table | view }
        | ON {
table | view } [ ( column [ ,...n ] ) ]
        | ON {
stored_procedure | extended_procedure }
        | ON {
user_defined_function }
    }
TO user
 [ ,...n

Arguments:

ALL

Specifies that all applicable permissions are being granted

permission

Is an object permission that is being granted.  

For table, table-valued function, or a view: 

SELECT, INSERT, DELETE, REFERENCES, or UPDATE. A column-list can be supplied along with SELECT and UPDATE permissions. If a column-list is not supplied with SELECT and UPDATE permissions, then the permission applies to all the columns in the table, view, or table-valued function.

For stored procedure: EXECUTE. 

column

Is the name of a column in the current database for which permissions are being granted.

table

Is the name of the table in the current database for which permissions are being granted.

view

Is the name of the view in the current database for which permissions are being granted.

stored_procedure

Is the name of the stored procedure in the current database for which permissions are being granted.

extended_procedure

Is the name of the extended stored procedure for which permissions are being granted.

user_defined_function

Is the name of the user-defined function for which permissions are being granted.

user

Is name of user whom permission should be granted. 

Example:

To grant a permission to table employee in database Emp to user hitesh :

GRANT ALL ON [emp].[employee] TO [hitesh]


Sunday, March 15, 2009

Reuse the object using Object Pool

There are some requirement that we need to instantiate the object again and again. New object always takes some resource (in memory). Our normal practice is, create a object and dispose (it happens automatically when go out of scope) it once no longer required. It is ok if number of objects creation are not more. 

But there are some situations where we can hold the object instead of disposing it and reuse it again. 

Hence, I have created generic object pool, which tries to get the object from pool. If pool is empty it creates new and return. One can push object back to pool once no longer in use. 

Create generic object pool class
public class ObjectPool where T : class, new()
{
Stack queue;

public ObjectPool()
{
queue = new Stack();
}

public ObjectPool(int capacity)
{
queue = new Stack(capacity);
}

To pop the object from pool. It creates new object if couldn't found from pool 
public T Pop()
{
T retObj = null;
lock (queue)
{
if (queue.Count > 0)
retObj = queue.Pop();
}

if (retObj == null)
retObj = new T();
return retObj;
}

To push back the object into pool for reuse
public void Push(T obj)
{
if (obj == null) return;

lock (queue)
{
queue.Push(obj);
}
}

To get the number of objects in pool

public int Length
{
get
{ return queue.Count; }
}
}

Friday, March 13, 2009

SQL Server 2005: Shrink and Truncate Log file size

USE
GO
DBCC SHRINKFILE(<Logical Name of Transaction Log>, 1)
BACKUP<Database Name> LOG WITH TRUNCATE_ONLY

1 (second parameter of DBCC SHRINKFILE) is target size of file in megabytes.

It won’t take backup of log file. Hence log will be lost. Make sure to take backup if you really want log.