Dapeng Li's Blog

Friday, December 30, 2011

 

Friends, meet me at WordPress


I had moved my blog to WordPress.com earlier 2011, you can find most of the recent posts at dapengli.wordpress.com.

Saturday, January 16, 2010

 

Hibernate to swap file in Ubuntu 9.1 [still open]


Recently I'm trying to make hibernation work on Ubuntu 9.1 (Karmic) on my Asus N10E.

I'm totally new to Linux and I followed this post to install Ubuntu Netbook Remix and Windows 7 side by side. It's a good tutorial and I followed another link in that post to create a swap file instead of swap partition.

Everything works fine, and I'm pretty amazed by the shutdown speed and suspend/wake up speed, lighting fast indeed. However, hibernation doesn't seem to work, when I chose hibernate, the only thing it does is lock the screen.

I followed this link to check kern.log after trying a hibernation, and found "Swap header not found!" in the log.

I thought I found the cause is the swap file, as in this post, on the second page, another member gave updated information on Ubuntu 9.1, on swap-offset and Grub2.

Here's what I did:

mount | grep " / " (Note your /dev/... on /)
sudo blkid -g
sudo blkid (Note UUID of /dev/... that corresponds to "/", we will use it in resume=UUID= below.)
sudo filefrag -v /swapfile | grep "First block:" (this doesn't work on Karmic)

Then I installed libx86.
sudo swap-offset /mnt/3G.swap to get the offset (my swap file is /mnt/3G.swap)
gksudo gedit /boot/grub/menu.lst & (this doesn't work in Karmic either)

I follow the instruction and created 07_hibernation under /etc/grub.d/
menuentry "Ubuntu 9.10 Hibernation, Linux 2.6.31-14-generic" {
set root=(hd0,3)
search --no-floppy --fs-uuid --set d3b0cf1a-99ca-43c1-a058-d7c38c0b6171
linux /boot/vmlinuz-2.6.31-14-generic root=UUID=d3b0cf1a-99ca-43c1-a058-d7c38c0b6171 ro resume=UUID=d3b0cf1a-99ca-43c1-a058-d7c38c0b6171 resume_offset=1544
initrd /boot/initrd.img-2.6.31-14-generic
}

I replaced UUID and resume_offset from the results of running the commands earlier.
sudo update-grub -y (doesn't work in Karmic)
sudo update-grub
sudo update-initramfs -u

Then I checked /boot/grub/grub.cfg and saw the new boot entry created there.

Reboot.

Unfortunately, boot from the new entry doesn't work for me, I got the display:
"Begin: Running /scripts/local-premount ..."
Then system seems stop and nothing more happens.

Labels:


Saturday, June 27, 2009

 

Add custom security header in WCF


In a recent project I'm working on, we're supposed to call an external web service with request’s header like this:

<soapenv:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext" soapenv:mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username>****Username Here****</wsse:Username>
<wsse:Password>****Password Here****</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
As regularly, in Visual Studio 2008 I added a service reference to the web service, then write code to call it using the auto-generated proxy:
Proxy client = new Proxy();
client.DoSomething();
But I got this error message from the service:
System.ServiceModel.FaultException : WSEC5075E: No security token found which satisfies any one of AuthMethods.

So I tried to add name and password to the proxy client before making the call:
Proxy client = new Proxy();
client.ClientCredentials.UserName.UserName = “Username”;
client.ClientCredentials.UserName.Password = “Password”;
client.DoSomething();
Same error as above. After some googling, I think updating the binding config might do the trick.
Updated from:
<system.serviceModel>
<bindings>
<binding name="serviceBinding" ....>
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</bindings>
</system.serviceModel>
to:
<system.serviceModel>
<bindings>
<binding name="serviceBinding" ....>
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</bindings>
</system.serviceModel>
OK, Something different returned from the service:
System.ServiceModel.Security.MessageSecurityException : An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.
----> System.ServiceModel.FaultException : com.ibm.wsspi.wssecurity.SoapSecurityException: The Application Server expected a Security header with the http://schemas.xmlsoap.org/ws/2003/06/secext or http://schemas.xmlsoap.org/ws/2002/07/secext or http://schemas.xmlsoap.org/ws/2002/04/secext namespace, but it was not found.

Seems to be the header is not what the service was expecting, but how can I set the header like that? Google lead me to this post, the author seems have the similar problem, I followed his instruction and added the following:
BindingElementCollection elements = client.Endpoint.Binding.CreateBindingElements();
elements.Find<SecurityBindingElement>().IncludeTimestamp = false;
client.Endpoint.Binding = new CustomBinding(elements);
But my error still the same. I used Charles to see the raw request and response:
Request header:
<s:Header>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-4c248cea-1a3d-4a27-99f0-29ee659ed975-1">
<o:Username>
abc
</o:Username>
<o:Password o:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
123
</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
The user name and password are in the request, seems only the namespace is not matching the service’s expectation. To verify that, I updated the namespace of security header in the above request in Charles and submitted again, yes! The service is responding correctly. I had no experience in WSE, but guess is that our service is sticking to an earlier version of WS-Security, and rejecting requests with namespace defined in newer versions after that. Maybe that’s why the code above works in the post author’s situation but not mine, maybe.

Found the problem, but how can I update the namespace in the header? Through configuration? Programming?

As one answer in this post said: “Do not define security at all in your client and add the whole security header inside a message inspector.”, this guy seems had given this suggestions in multiple posts and I hadn’t found anything more helpful than that, so I might give a try to write a WCF message inspector.

I found what I want here.
Here’s the code:
        /// <summary>
/// Custom Endpoint Behavior
/// </summary>
public class AddWseSecurityHeaderEndpointBehavior : IEndpointBehavior
{
private readonly string userName;
private readonly string password;

public AddWseSecurityHeaderEndpointBehavior(string userName, string password)
{
this.userName = userName;
this.password = password;
}

#region IEndpointBehavior Members

public void AddBindingParameters(ServiceEndpoint endpoint,
BindingParameterCollection bindingParameters)
{ }

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
AddWseSecurityHeaderMessageInspector inspector =
new AddWseSecurityHeaderMessageInspector(userName, password);

clientRuntime.MessageInspectors.Add(inspector);
}

public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{ }

public void Validate(ServiceEndpoint endpoint)
{ }

#endregion
}

/// <summary>
/// Custom Message Inspector to add WSE security header to the request before sending
/// </summary>
internal class AddWseSecurityHeaderMessageInspector : IClientMessageInspector, IDispatchMessageInspector
{
private readonly string userName;
private readonly string password;

public AddWseSecurityHeaderMessageInspector(string userName, string password)
{
this.userName = userName;
this.password = password;
}

#region IClientMessageInspector Members

public void AfterReceiveReply(ref Message reply, object correlationState)
{ }

public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
CustomWseSecurityHeader securityHeader =
new CustomWseSecurityHeader(userName, password);

request.Headers.Add(securityHeader);
return request;
}

#endregion

#region IDispatchMessageInspector Members

public object AfterReceiveRequest(ref Message request, IClientChannel channel,
InstanceContext instanceContext)
{
return null;
}

public void BeforeSendReply(ref Message reply, object correlationState)
{ }

#endregion
}

/// <summary>
/// Custom WSE security header
/// </summary>
internal class CustomWseSecurityHeader : MessageHeader
{
private readonly string userName;
private readonly string password;

public CustomWseSecurityHeader(string userName, string password)
{
this.userName = userName;
this.password = password;
}

protected override void OnWriteHeaderContents(XmlDictionaryWriter writer,
MessageVersion messageVersion)
{
writer.WriteStartElement("UsernameToken", Namespace);
writer.WriteElementString("Username", Namespace, userName);
writer.WriteElementString("Password", Namespace, password);
writer.WriteEndElement();
}

public override string Name
{
get { return "Security"; }
}

public override string Namespace
{
get { return "http://schemas.xmlsoap.org/ws/2003/06/secext"; }
}

public override bool MustUnderstand
{
get { return true; }
}
}
Before making calls with the proxy, add our custom endpoint behavior, we don’t need to set the username and password (we’ve done that in the custom header):
Proxy client = new Proxy();

AddWseSecurityHeaderEndpointBehavior customEndpointBehavior =
new AddWseSecurityHeaderEndpointBehavior(userName, password);

client.Endpoint.Behaviors.Add(customEndpointBehavior);

client.DoSomething();
Also as we’re setting username and password in our custom header, we need to change the mode attribute of security element (under binding) to Transport.

Note: Once you've figured out what's the problem with the request message format, you might want to close Charles. Or you will see certificate errors because Charles will act as the middle man between your proxy and the service, the certificate you'll see from the proxy's perspective is issue by Charles, which is not a trusted root CA in your computer.
Firstly, I got confused when I access the web service address from Firefox directly it's displaying, while in IE 8 it says the "The security certificate presented by this website was not issued by a trusted certificate authority.", I can't see the certificate in IE. Then I open that address in Safari, similar prompt, but this time I got a chance to see the service certificate, and see the issuer is Charles.
 

I don't even remember I have this blog!


It's almost 5 years since the first post on this blog, when I was in college preparing for GRE.

Yeah... Lots of memories, time to move on.

I have been a software developer for about 4 years after leaving college, I guess my impulse to write something is more than being annoyed but try to write something that might be useful for some people.

Hopefully, good luck.

Friday, October 22, 2004

 

first try


First day using a blog, hoping to having more fun in the future!
Now only 1 day to GRE test, this feeling 's not so good, keep working...

Archives

October 2004   June 2009   January 2010   December 2011  

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]