MSMQ 3.0 too secure for you?
With lots of customers developing systems that use MSMQ across WANs, I find that I get a number of calls on problems getting messages through. Usually sending messages works a treat but pulling them back again doesn't. The main reason for this is the tightening up of MSMQ's use of RPC as documented in the Message Queuing security overview. The "Secured remote read" feature will need to be tweaked if you plan to work across forest boundaries - even if you don't, this problem can appear in development where the test machines are in different forests to the production servers. As the article says:
Message Queuing 3.0 cross-forest clients on Windows Server 2003 family computers in non-trusted domains will use the secure remote read interface. By default, the Message Queuing 3.0 server requires domain clients to establish an encrypted channel, and such a channel cannot be established between non-trusted domains. Thus remote read requests from such clients will be rejected. To modify this default behavior and allow the Message Queuing server to accept domain clients that do not establish an encrypted channel, create a DWORD value Security\NewRemoteReadServerAllowNoneSecurityClient in the registry and set it to 1.
No, I don't know why the registry value is so horrendously long.
Also, the article talks about the Security branch - make sure you use HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSMQ\Parameters\Security and NOT HKEY_LOCAL_MACHINE\SECURITY.
Update April 11th - This also seems to do the trick if you are using local accounts on machines in domains. That is, if you are logged in as a local admin, or the application/service is running under a local account, then you can't create a secure channel and so remote reads won't work. The workaround is to use domain accounts OR setNewRemoteReadServerAllowNoneSecurityClient=1.
Comments
Anonymous
February 14, 2008
Nine times out of ten this will not be the correct question. Whoever is asking REALLY means "How do IAnonymous
June 14, 2009
the above change to the security settings will apply only after restart.Anonymous
June 14, 2009
Hi Thesked, Yes, that's correct. I don't think that there are any registry changes that MSMQ (in common with most other services) monitors after startup. Cheers John Breakwell (MSFT)Anonymous
July 08, 2009
Hi John, Thank for this blog. I have already set the value in my registry but im still fail to view all the messages in the queue. I also set the "ANONYMOUS LOGON" to have Full control.Anonymous
July 09, 2009
Hi Julius, Could you please elaborate on what you are trying to do? How are you trying to access the messages in the queue - what format are you using for the queue name, for example? What errors were you getting - Access Denied? Where are the machines physically and what domains do they belong to? Cheers John Breakwell (MSFT)Anonymous
October 27, 2009
Hi John, thanks for your Twitter answer. I've found your blog a few days ago, but I've still a problem sending messages from a client (WinXP) to a MSMQ 3.0 server (Win2003). The machines are in different domains. I'm trying to send a message to a remote private queue. The MSMQ service is installed in workgroup mode. The path used from client is "Formatname:DIRECT=OS:xxprivate$test". I've set the registry key as well, but I think this only applies to reading operations. I always get the following Exception: "Queue Service not available" MessageQueueErrorCode = System.Messaging.MessageQueueErrorCode.ServiceNotAvailable I don't know what to do, because the product will be developed for a big enterprise and I've no impact on the AD. Cheers, JürgenAnonymous
October 27, 2009
The comment has been removedAnonymous
October 27, 2009
Hi John, I'm talking about different domains in different forest. The remote private queue security is wide open for both users "Everyone" and "Anonymous Logon". Both have nearly full control. I've read that in such a constellation no AD is involved and this is good, because there will be no trust setup for the participating domains. The code fragment looks like: [Test] public void TestSystemMessagingSend() { try { NotificationRequest request = GenerateNotificationRequest(); const string QUEUE_PATH = @"FormatName:DIRECT=OS:xxprivate$test"; Message message = new Message(request, new XmlMessageFormatter(new[] {typeof (NotificationRequest)})) { UseDeadLetterQueue = true, }; using (MessageQueue mq = new MessageQueue(QUEUE_PATH)) { mq.Send(message); mq.Close(); } } catch (MessageQueueException mqex) { Console.WriteLine("MessageQueueException!"); throw; } catch (Exception ex) { Console.WriteLine("Exception!"); throw; } } The Exception is thrown on Send(). Cheers, JürgenAnonymous
October 27, 2009
Hi Jürgen, If you are seeing ServiceNotAvailable on a Send() operation, then that means the sending application is unable to contact the LOCAL MSMQ queue manager. The destination machine takes no part as we are just trying to put a message in an outgoing queue, not deliver it. Is MSMQ installed and running on the local machine? Is the sender installed as an Independent client? (which options did you pick to install MSMQ?) Cheers John Breakwell (MSFT)Anonymous
October 27, 2009
Hi John, as far as I see we've localized the problem right now. On the test client machine was <b>no</b> MSMQ installed! I've installed it in workgroup mode as well and started it. Everything works fine now, BUT is there any possibility to send and / or recieve messages without installing MSMQ on every client machine? Cheers, JürgenAnonymous
October 28, 2009
Hi Jürgen, You need MSMQ installed at both ends. In theory you could write an application that put MSMQ shaped packets on the wire (the protocol has been published) and so avoid the need for an installed queue manager but that's a serious/hard-core endeavour. Cheers John Breakwell (MSFT)Anonymous
December 02, 2009
The comment has been removedAnonymous
December 02, 2009
Hi Jeff, If you have set security on the queue for Everyone and Anonymous Logon then you do not have a permissions problem. There are no security problems with message transfer between MSMQ 2.0 and 3.0. You don't say if you are sending messages to the remote queue or receiving them. Ths registry value only applies to receiving messages from remote queues. What errors do youy see? Cheers John Breakwell (MSFT)Anonymous
December 04, 2009
The comment has been removedAnonymous
December 04, 2009
Hi Jeff, As you have switched off queue-level security (with everyone/anonymous logon) then permissions shouldn't be a problem so I would suggest you are not addressing the queue correctly. What is the full address you are passing to the qInfo object? Cheers John BreakwellAnonymous
December 04, 2009
The opbject is created, and the properties are defined like so: set qInfo = server.CreateObject("MSMQ.MSMQQueueInfo") set mSend = server.CreateObject("MSMQ.MSMQMessage") qInfo.PathName = glscQueueNameDecoder qInfo.Label = glscQueueLabelDecoder These Global Constants are defined in an include page as follows: glscQueueNameDecoder = QueueServerName & "MIMEDecoderQueue" OHQueueServerName = "Parser2" glscQueueLabelDecoder = "MIME Decoder Queue" An apology here. This is not my code....Anonymous
December 04, 2009
I have tried passing in the following: 'glscQueueNameDecoder = "OS:Parser2MIMEDecoderQueue" glscQueueNameDecoder = "TCP:10.0.0.1MIMEDecoderQueue" But to no avail.Anonymous
December 04, 2009
Hi So the pathname to the queue is "Parser2MIMEDecoderQueue". Parser2 is the Windows 2003 server, yes? The MSMQ Queue Manager on the sender will lookup this address in Active Directory. If it cannot find Parser2 (as a computer object) or MIMEDecoderQueue (as a public queue object) then an error will be returned. Can you see both of these objects using "Active Directory: Users and Computers"? (You will need to enable "Advanced Features" and "Users, Groups, and Computers as containers"). I assume you have been setting queue permissions using Computer Management. You have said that the Windows 2000 and 2003 machines are both in the same domain but are they using the same DC server? Check the HKEY_LOCAL_MACHINESOFTWAREMicrosoftMSMQParametersMachineCacheCurrentMQISServer registry value. Cheers John Breakwell (MSFT)Anonymous
December 04, 2009
Hi Jeff, These won't work: 'glscQueueNameDecoder = "OS:Parser2MIMEDecoderQueue" glscQueueNameDecoder = "TCP:10.0.0.1MIMEDecoderQueue" because you are specifying a pathname (qInfo.PathName) but supplying a (incomplete) formatname (OS:Parser2MIMEDecoderQueue). The corresponding formatnames would be DIRECT=OS:Parser2MIMEDecoderQueue and DIRECT=TCP:10.0.0.1MIMEDecoderQueue. If you wanted to use those, the code would need to use "qInfo.FormatName" instead. Reference: http://blogs.msdn.com/johnbreakwell/archive/2009/02/26/difference-between-path-name-and-format-name-when-accessing-msmq-queues.aspx Cheers JohnAnonymous
December 04, 2009
The comment has been removedAnonymous
December 04, 2009
The comment has been removedAnonymous
December 05, 2009
Hi Jeff, Reinstalling MSMQ would fix this problem but it would mean having to recreate any queues on the Windows 2000 machine. You could try setting the MQIS Server to be used with the StaticMQISServer registry value.(http://technet.microsoft.com/en-us/library/cc938181.aspx). Make sure you use the correct syntax for the data. You might want to consider raising a support request with Microsoft too. Cheers John Breakwell (MSFT)Anonymous
December 07, 2009
The comment has been removedAnonymous
December 07, 2009
The comment has been removedAnonymous
December 08, 2009
Hi John, Is this registry setting works only for read/write operations? It helped me to be able to send message to the queue from one untrusted domain to another. I'm unable though to browse the private queues. public static MessageQueue[] GetPrivateQueuesByMachine(string machineName) {} gives "Access to Message Queing is denied" Looks like some Browse permission issue. It is installed in workgroup mode, and I do not have security tab enabled for Messaging in MMC. Thank youAnonymous
December 08, 2009
Hi Elena, The NewRemoteReadServerAllowNoneSecurityClient registry value is only for read operations. I don't understand how it assisted you with sending messages from one untrusted domain to another. For such cross-forest communication I direct people to these other blog posts: http://blogs.msdn.com/johnbreakwell/archive/2008/06/27/cross-forest-msmq-you-need-to-be-trusting.aspx http://blogs.msdn.com/johnbreakwell/archive/2008/02/14/how-do-i-send-msmq-messages-between-domains.aspx If you cannot see a Security tab in Computer Management then that is probably because the logged-in user does not have the "Get permissions" permission for that queue. Log in with an account with more permissions (such as a local admin) and change the permissions to something less restrictive for the account you are trying to use. Cheers John Breakwell (MSFT)Anonymous
December 22, 2009
John, I have a similar problem. I have a MSMQ Windows 2003 cluster. I have an ASP Page that gets an "Access is Denied" Error when it tries to call PeekCurrent(). The queue it is trying to Peek on has every user with full permissions. It can send messages to the queue just fine it just can't seem to peek. Other processes are able to peek on this queue. Any Ideas?Anonymous
December 22, 2009
Hi Mike, The important information I'll need is:
- where is the ASP page hosted?
- where is the queue hosted (I assume in a clustered resource)?
- what are the permissions on the queue - have you just used Everyone or did you add Anonymous Logon as well?
- where are the other processes that work hosted?
- what account are the working processes running under? Cheers John Breakwell (MSFT)
- Anonymous
December 22, 2009
The comment has been removed - Anonymous
December 22, 2009
Hi Mike, Typical - I missed (6) "Are the machines in same domain, different forests or different workgroups?" There are several boundaries that return "Access Denied" when making remote receive calls.
- The obvious one, queue level security
- Secure RPC, as documented on the above blog post (have you tried the registry value?)
- Firewalls that block the RPC protocol (http://blogs.msdn.com/johnbreakwell/archive/2008/07/10/getting-msmq-messages-out-of-windows-server-2008.aspx)
- Cross-forest security (http://blogs.msdn.com/johnbreakwell/archive/2008/06/27/cross-forest-msmq-you-need-to-be-trusting.aspx) If none of these apply to your situation, you may be better off raising a support call with Microsoft. Cheers John Breakwell (MSFT)
Anonymous
December 22, 2009
John, A machines are in the same domain. I did try the registry value to no avail. Thanks for your help. MikeAnonymous
December 23, 2009
Hi Mike, If you set Anonymous Logon to Full control and tried the NewRemoteReadServerAllowNoneSecurityClient registry value then there aren't any options I can think of left. In your test app, why don't you do a simple remote receive using a DIRECT format name? Also try using a private queue. Cheers JohnAnonymous
December 23, 2009
John, All of my requests use the DIRECT format name. I have tried both private and public queues. Just for fun, I took the apps from my application server and put them on the web server. For some reason they can't read from queues while on that machine either. I am baffeled. MikeAnonymous
December 23, 2009
Hi Mike, So you've narrowed it down to a problem with the machine. Could be a problem with the secure channel the machine sets up with a domain controller for security checks. Saw an incident like that with Windows XP: http://blogs.msdn.com/johnbreakwell/archive/2007/06/22/msmq-needs-the-secure-channel-to-be-open.aspx Cheers John Breakwell (MSFT)Anonymous
December 31, 2009
Hello Again John, I am still having the issue with the ASP pages in IIS 6. I built a new web server and now I am able to call peek current from that machine from any process (a VB script, an exe, windows service) except IIS. I have some additional information and wanted to see if it might help you suggest a solution. Everytime I try to call peek current from IIS (no matter what user I use: domain admin, anaymous), I get a failure audit in the securty log like this. Privileged Service Called: Server: NT Local Security Authority / Authentication Service Service: LsaRegisterLogonProcess() Primary User Name: <machine> Primary Domain: <domain> Primary Logon ID: (0x0,0x3E7) Client User Name: <user> Client Domain: <domain> Client Logon ID: (0x0,0x212569) Privileges: SeTcbPrivilege If I call peek current from another process (in this case a vb script) I get a success audit like this Privileged Service Called: Server: NT Local Security Authority / Authentication Service Service: LsaRegisterLogonProcess() Primary User Name: <machine> Primary Domain: <domain> Primary Logon ID: (0x0,0x3E7) Client User Name: <machine> Client Domain: <domain> Client Logon ID: (0x0,0x3E7) Privileges: SeTcbPrivilege The only difference I see is that IIS passes the anaymous account while the vb script passes the machine name. Does this ring any bells for you? MikeAnonymous
December 31, 2009
In addition, after I get the SeTcbPrivilege error I get an object access error Object Open: Object Server: SC Manager Object Type: SC_MANAGER OBJECT Object Name: ServicesActive Handle ID: - Operation ID: {0,10821284} Process ID: 528 Image File Name: C:WINDOWSsystem32services.exe Primary User Name: <machine> Primary Domain: <domain> Primary Logon ID: (0x0,0x3E7) Client User Name: <iis anaymous user> Client Domain: <machine> Client Logon ID: (0x0,0xA50FB9) Accesses: READ_CONTROL Connect to service controller Enumerate services Query service database lock state Privileges: - Restricted Sid Count: 0 Access Mask: 0x20015Anonymous
January 03, 2010
Hi Mike, So the problem with the initial web server have been resolved by replacing the machine. Now your non-IIS apps work properly on the web server when they didn't before. I take it the security log snippets are from the web server, yes? SeTcbPrivilege is the "To Act as Part of the Operating System" privilege. This issue sounds like a problem with the account used by IIS to communicate with MSMQ - the IIS 'guest' account is insufficient. In your ASP code, are you impersonating the user that is calling the page? Cheers John Breakwell (MSFT)Anonymous
January 05, 2010
John, Your assumptions are correct. Using the information you provided ("To Act as Part of the Operating System") I have got this to work. However, my procedures are quite odd. Here is how I can get this to work.
- Stop IIS
- Set the Identity on the Application Pool to "Local System"
- On the Virtual Directory, select Properties - Directory Security - and Edit 'Authentication and access control'
- Change the 'Anonymous Access' user to the Domain admin, enter the password, and ensure 'Integrated Windows Authentication' is checked. Click ok.
- Start IIS.
- Try to pull a message back from a queue (it should work) but I don't want IIS running as a domain admin. So I....
- Stop IIS
- On the Virtual Directory, select Properties - Directory Security - and Edit 'Authentication and access control'
- Change the 'Anonymous Access' user to the internet gust account user <Machine_Name>IUSER_<MachineName>, leave the password blank, and ensure 'Integrated Windows Authentication' is checked. Click ok.
- Start IIS.
- It works. Even after reboots. Now I will be the first to admit that these steps shouldn't do anything other than changing the identity on the App Pool to Local System, but for some reason it will only work if I enter the domain admin account, get it to work, and then change it back to the guest account. Thank you for all your help. If you would like more information I will check back and be happy to provide it. Mike
Anonymous
January 08, 2010
Hi Mike, I'll get one of my IIS colleagues to have a look. Cheers John Breakwell (MSFT)Anonymous
January 17, 2010
Hi Mike, Yes, my IIS colleagues can't see that you are doing anything more than change the identity on the App Pool. Defintely a strange problem. Cheers John Breakwell (MSFT)Anonymous
April 25, 2010
Hi! I tried your solution but it didn't help....
- I got MSMQ 3.0 on WinXP Prof SP3 and .NET Framework 3.5 SP1.
- I'm using private queues.
- I want to access with 2 apps, one on the same machine as the MSMQ (I use MessageQueue.Create(".\Private$\queueName"), and I can read and write without problems), and another app which might be on the same PC or in the local network, so I'm trying to access to the locally created queues with "FormatName:DIRECT=TCP:<ip>\private$\queueName" and I actuall can write in the queues, locally and remotely, with this path. The problem comes when I want to read, the queue has canWrite=true and canRead=false.. I'm trying it locally, so I'm using the loopback ip 127.0.0.1 which I think should work (because I'm able to write). I looked at the queue properties and everybody has any permission.. Any ideas? (I'm not using any authentication/encryption which doesn't apply by default) Thank you!