Why is Leopard annoying my users?

  • OK, I received an annoying report from an user this morning. If
    you turn the Leopard firewall on and run my application, Leopard
    presents the user the following dialog three (!) times:

        Do you want the application "QRecall.app" to accept
    incoming network
        connections?

        Clicking Deny may limit the application's behavior. This
    setting can be
        changed in the Firewall pane of the Security preferences.

    Poking around, I see these in /var/log/appfirewall.log

        Nov 19 16:45:37 james-bucaneks-power-mac-g5 Firewall[45]:
    QRecall is
        listening from 0.0.0.0:49286 uid = 501 proto=6 Nov 19 16:45:37
        james-bucaneks-power-mac-g5 Firewall[45]: QRecallScheduler
    is listening
        from 0.0.0.0:49287 uid = 501 proto=6 Nov 19 16:45:37
        james-bucaneks-power-mac-g5 Firewall[45]: QRecallMonitor is listening
        from 0.0.0.0:49288 uid = 501 proto=6

    My application is not a network service and is not creating any
    incoming TCP sockets. I *am* creating some named BSD sockets for
    distributed object communications (something I had to do to get
    the app to run on Leopard -- yes, there's plenty of irony here).

    Does anyone know what's causing this and how do I get it to stop?

    --
    James Bucanek
  • Might also ask that on the network list.

    Dave

    On Nov 19, 2007, at 4:34 PM, James Bucanek wrote:

    > OK, I received an annoying report from an user this morning. If you
    > turn the Leopard firewall on and run my application, Leopard
    > presents the user the following dialog three (!) times:
    >
    > Do you want the application "QRecall.app" to accept incoming
    > network
    > connections?
    >
    > Clicking Deny may limit the application's behavior. This setting
    > can be
    > changed in the Firewall pane of the Security preferences.
    >
    > Poking around, I see these in /var/log/appfirewall.log
    >
    > Nov 19 16:45:37 james-bucaneks-power-mac-g5 Firewall[45]: QRecall
    > is
    > listening from 0.0.0.0:49286 uid = 501 proto=6 Nov 19 16:45:37
    > james-bucaneks-power-mac-g5 Firewall[45]: QRecallScheduler is
    > listening
    > from 0.0.0.0:49287 uid = 501 proto=6 Nov 19 16:45:37
    > james-bucaneks-power-mac-g5 Firewall[45]: QRecallMonitor is
    > listening
    > from 0.0.0.0:49288 uid = 501 proto=6
    >
    > My application is not a network service and is not creating any
    > incoming TCP sockets. I *am* creating some named BSD sockets for
    > distributed object communications (something I had to do to get the
    > app to run on Leopard -- yes, there's plenty of irony here).
    >
    > Does anyone know what's causing this and how do I get it to stop?
  • on 2007-11-19 7:34 PM, James Bucanek at <subscriber...> wrote:

    > OK, I received an annoying report from an user this morning. If
    > you turn the Leopard firewall on and run my application, Leopard
    > presents the user the following dialog three (!) times:
    >
    > Do you want the application "QRecall.app" to accept
    > incoming network
    > connections?
    >
    > Clicking Deny may limit the application's behavior. This
    > setting can be
    > changed in the Firewall pane of the Security preferences.
    >
    > ....
    >
    > My application is not a network service and is not creating any
    > incoming TCP sockets. I *am* creating some named BSD sockets for
    > distributed object communications (something I had to do to get
    > the app to run on Leopard -- yes, there's plenty of irony here).
    >
    > Does anyone know what's causing this and how do I get it to stop?

    I've been researching this issue the last several days. I can't answer your
    question about the roles played by TCP sockets and BSD sockets, but I can
    give you some background based on what I've read. Basically, the latest
    version of Apple's support article (updated yesterday or the day before)
    about the new Leopard firewall says that this dialog is presented whenever a
    non-code signed application requests incoming access. So you apparently are
    requesting incoming access as far as Apple's new firewall system is
    concerned, and you're apparently doing so three times.

    The interesting question is, What happens when the user clicks Deny, or
    Allow?

    I'm not at all sure I've understood what I've turned up in my research -- so
    far, there are only a couple of competent online articles explaining what
    the new firewall is really doing. Apparently, according to my current
    understanding, if the user clicks Deny, the specific TCP/UDP port over which
    incoming access was requested is closed -- or remains closed -- in ipfw. If
    the user clicks Allow, the application is automatically "signed" by Apple
    and listed in the new Firewall exceptions list as an application that can
    either always allow or always deny incoming access. I don't believe clicking
    Allow in the dialog opens the corresponding port in ipfw.

    The ipfw service still exists in Leopard. In Tiger, it had a GUI for opening
    and closing specific ports in the System Preferences/Accounts/Firewall pane.
    That GUI is now gone in Leopard, and the new System
    Preferences/Security/Firewall pane controls a new application-level firewall
    service. The new Apple support article makes clear that ipfw rules trump
    application firewall settings in Leopard, but Apple no longer provides a GUI
    for controlling ipfw. You have to use Terminal or a third-party utility like
    WaterProof.

    I came upon this issue when I accidentally clicked Deny in one of these
    dialogs while installing a new version of Retrospect Client. Thereafter,
    Client wouldn't receive incoming connections from my Retrospect backup
    server, even though I later added it to the Firewall exceptions list
    manually and marked its internal backup service application 'pitond' to
    allow incoming connections in the Leopard Firewall pane. It turns out that,
    apparently, my clicking Deny had closed the TCP port (497) used by
    Retrospect Client and, as noted above, this ipfw setting trumped the new
    application Firewall setting that purportedly allowed access. I solved the
    problem by reinstalling Client, and a Client dialog asked whether to open
    the port, to which I replied affirmatively, and then the system asked
    whether to allow incoming access, to which I replied Allow, and now it
    works. Running Network Utility's Port Scan shows that port 497 is now open,
    and Retrospect tech support has confirmed that the Retrospect Client
    installer opens it (if you click the correct button). I presumably could
    have solved the problem by using Terminal to turn on port 497 explicitly,
    instead of running the installer again.

    --

    Bill Cheeseman - <bill...>
    Quechee Software, Quechee, Vermont, USA
    www.quecheesoftware.com

    PreFab Software - www.prefabsoftware.com
  • On 20 Nov 2007, at 00:34, James Bucanek wrote:

    > Poking around, I see these in /var/log/appfirewall.log
    >
    > Nov 19 16:45:37 james-bucaneks-power-mac-g5 Firewall[45]: QRecall
    > is
    > listening from 0.0.0.0:49286 uid = 501 proto=6 Nov 19 16:45:37
    > james-bucaneks-power-mac-g5 Firewall[45]: QRecallScheduler is
    > listening
    > from 0.0.0.0:49287 uid = 501 proto=6 Nov 19 16:45:37
    > james-bucaneks-power-mac-g5 Firewall[45]: QRecallMonitor is
    > listening
    > from 0.0.0.0:49288 uid = 501 proto=6
    >
    > My application is not a network service and is not creating any
    > incoming TCP sockets. I *am* creating some named BSD sockets for
    > distributed object communications (something I had to do to get the
    > app to run on Leopard -- yes, there's plenty of irony here).
    >
    > Does anyone know what's causing this and how do I get it to stop?

    Well regardless of whether or not you think your application isn't
    creating any TCP sockets, it clearly is; protocol 6 is TCP and the
    reason you're being pestered is that your programs are binding ports
    for listening on any address.

    Perhaps it's your DO set-up that needs altering here?  Maybe posting
    the code will help someone spot why it's trying to bind TCP sockets?

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • On Nov 20, 2007, at 02:34, James Bucanek wrote:

    > Poking around, I see these in /var/log/appfirewall.log
    >
    > Nov 19 16:45:37 james-bucaneks-power-mac-g5 Firewall[45]:
    > QRecall is
    > listening from 0.0.0.0:49286 uid = 501 proto=6 Nov 19 16:45:37
    > james-bucaneks-power-mac-g5 Firewall[45]: QRecallScheduler is
    > listening
    > from 0.0.0.0:49287 uid = 501 proto=6 Nov 19 16:45:37
    > james-bucaneks-power-mac-g5 Firewall[45]: QRecallMonitor is
    > listening
    > from 0.0.0.0:49288 uid = 501 proto=6
    >
    > My application is not a network service and is not creating any
    > incoming TCP sockets. I *am* creating some named BSD sockets for
    > distributed object communications (something I had to do to get the
    > app to run on Leopard -- yes, there's plenty of irony here).
    >
    > Does anyone know what's causing this and how do I get it to stop?

    Seems that your socket listen to to any interface on port 49287 and
    49288, while you really want to listen only to localhost. I guess
    that you need to configure the socket when you create the NSConnection.

    Best Regards,

    Nir Soffer
  • On 20 Nov 2007, at 13:18, Bill Cheeseman wrote:

    > Apparently, according to my current
    > understanding, if the user clicks Deny, the specific TCP/UDP port
    > over which
    > incoming access was requested is closed -- or remains closed -- in
    > ipfw

    No, this doesn't happen. The only time ipfw gets amended is when the
    user has selected the Stealth option, and then ipfw just blocks some
    ICMP.

    I can't explain your Retrospect problem, but ipfw had nothing to do
    with it.
  • Alastair Houghton <mailto:<alastair...> wrote
    (Tuesday, November 20, 2007 6:48 AM -0000):
    > Well regardless of whether or not you think your application isn't
    > creating any TCP sockets, it clearly is; protocol 6 is TCP and the
    > reason you're being pestered is that your programs are binding ports
    > for listening on any address.

    Exactly. Since I spend days trying to figure out how to create
    an interprocess Distributed Objects communications pipe that did
    *not* use TCP I'm feeling cheated.

    > Perhaps it's your DO set-up that needs altering here?  Maybe posting
    > the code will help someone spot why it's trying to bind TCP sockets?

    ... and ...

    Nir Soffer <mailto:<nirs...> wrote (Tuesday, November
    20, 2007 6:51 AM +0200):
    > Seems that your socket listen to to any interface on port 49287 and
    > 49288, while you really want to listen only to localhost. I guess that
    > you need to configure the socket when you create the NSConnection.

    But there's the rub: I spent a lot of work and time explicitly
    NOT creating a TCP socket.

    OK, here's the meat of the code that I use to create the
    server's distributed objects communications port using named sockets:

        NSPort* pipe = [[[NSSocketPort alloc] initWithProtocolFamily:AF_UNIX
                                                          socketType:SOCK_STREAM
                                                            protocol:0

    address:[self socketAddressData]]
        NSConnection* connection = [NSConnection
    connectionWithReceivePort:port sendPort:nil];

    And before anyone suggests using Mach ports, Mach ports won't
    work. These sockets are created so that client processes can
    communicate with a launchd daemon. Leopard Mach kernel namespace
    changes have made this impossible to do this using Mach ports.
    The recommended solution, according to technote 2083
    <http://developer.apple.com/technotes/tn2005/tn2083.html> is to
    use UNIX Domain Sockets. I do not want to use TCP sockets for a
    variety of security and performance reasons.

    And for anyone who has other questions about the code, here's
    the whole class:

    //
    //  QRUserBSDSocketPath.m
    //  Quantum Recall
    //
    //  Created by James Bucanek on 10/18/07.
    //  Copyright 2007 Dawn to Dusk Software. All rights reserved.
    //

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <unistd.h>

    #import "QRUserBSDSocketPath.h"

    #import "QuantumDefs.h"
    #import "QRPosixPath.h"
    #if !defined(NO_LOGGER)                // Compile only if the
    Logger class is available
    #import "FileManagerErrorLogger.h"
    #import "QRException.h"                // just for a property
    name, not for QRException
    #import "Logger.h"
    #endif

    @implementation QRUserBSDSocketPath

    + (QRUserBSDSocketPath*)schedulerSocketPath
    {
        return ([[[QRUserBSDSocketPath alloc]
    initWithName:kSchedulerConnectionName] autorelease]);
    }

    + (QRUserBSDSocketPath*)helperSocketPath
    {
        // Create a unique helper process socket name
        QRUserBSDSocketPath* path;
        do {
            NSString* name = [NSString
    stringWithFormat:kHelperConnectionName @".%x",random()&0x3fffffff];
            path = [[[QRUserBSDSocketPath alloc] initWithName:name] autorelease];
        } while ([path socketExists]);
        return (path);
    }

    - (id)initWithName:(NSString*)name
    {
        NSString* perUserFolder = [NSString stringWithFormat:@"QRecall.%d",getuid()];
        NSDictionary* createAttributes = [NSDictionary
    dictionaryWithObject:[NSNumber numberWithUnsignedLong:0700] // rwx------
                                                                      forKey:NSFilePosixPermissions];
        if ( (self=[super initWithName:perUserFolder
                                inPath:[QRPosixPath varTmpPath]
                        withAttributes:createAttributes])!=nil )
            {
            socketName = [name retain];
            [self create];                              // the
    socket's parent directory must always exist
            }
        return self;
    }

    - (void)dealloc
    {
        [socketName release];
        [super dealloc];
    }

    #pragma mark Properties

    - (NSString*)name
    {
        return (socketName);
    }

    - (NSString*)socketPath
    {
        return ([[self path] stringByAppendingPathComponent:socketName]);
    }

    - (NSData*)socketAddressData
    {
        // Create an BSD address structure that specifies the named
    socket in the file system
        struct sockaddr_un socketAddress;
        bzero(&socketAddress,sizeof(socketAddress));
        socketAddress.sun_len = sizeof(socketAddress);
        socketAddress.sun_family = AF_UNIX;
        strcpy(socketAddress.sun_path,[[self socketPath] cStringUsingEncoding:NSASCIIStringEncoding]);
    //  socketAddress.sun_len = SUN_LEN(&socketAddress);
        NSData* socketAddressData = [NSData dataWithBytes:&socketAddress
                                                    length:/*SUN_LEN(&socketAddress)*/sizeof(socketAddress)];
        return (socketAddressData);
    }

    #pragma mark Socket Utilities

    - (BOOL)socketExists
    {
        return ([[NSFileManager defaultManager]
    fileExistsAtPath:[self socketPath]]);
    }

    - (void)deleteSocket
    {
    #ifdef NO_LOGGER
        [[NSFileManager defaultManager] removeFileAtPath:[self
    socketPath] handler:nil];
    #else
        if (![[NSFileManager defaultManager] removeFileAtPath:[self
    socketPath] handler:[FileManagerErrorLogger errorLogger]])
            {
            LogLineIdentifier* lID = [Logger log:kLogError
    message:@"Unable to delete communications pipe"];
            [Logger log:kLogDetails inLine:lID key:kDetailsPath
    value:[self socketPath]];
            }
        else
            {
            [Logger log:kLogDebug format:@"%s %@",__func__,[self socketPath]];
            }
    #endif
    }

    #pragma mark Notifications

    - (void)portDidBecomeInvalidNotification:(NSNotification*)notification
    {
    #pragma unused(notification)
    #if !defined(NO_LOGGER)
        [Logger log:kLogDebug format:@"%s",__func__];
    #endif

        // The port that uses this BSD socket is no longer valid.
        // Delete the underlying pipe file.
        [self deleteSocket];
        [self autorelease];            // balance retain in
    -[QRUserBSDSocketPath createPort]
    }

    #pragma mark Communication ports

    - (NSConnection*)serverConnection
    {
        NSConnection* connection = nil;
        NSPort* port = [self createPort];
        if (port!=nil)
            connection = [NSConnection
    connectionWithReceivePort:port sendPort:nil];
        return (connection);
    }

    - (NSConnection*)clientConnection
    {
        NSConnection* connection = nil;
        NSPort* port = nil;
        if ([self socketExists])
            port = [self connectPort];
        if (port!=nil)
            connection = [NSConnection
    connectionWithReceivePort:nil sendPort:port];
        return (connection);
    }

    - (NSPort*)createPort
    {
        // This method creates the pipe file, binds to it, and
    returns it as an NSPort object.
        // It fails if the pipe file already exists.
        NSPort* pipe = [[[NSSocketPort alloc] initWithProtocolFamily:AF_UNIX
                                                          socketType:SOCK_STREAM
                                                            protocol:0

    address:[self socketAddressData]] autorelease];
        if (pipe!=nil)
            {
            // Creating this NSSocketPort will bind() the address,
    which creates a pipe file.
            // Listen for the NSPortDidBecomeInvalidNotification
    notification and delete the pipe file
            //  when it's no longer being used.
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                      selector:@selector(portDidBecomeInvalidNotification:)
                                                          name:NSPortDidBecomeInvalidNotification
                                                        object:pipe];
            [self retain];                      // retain until the
    notification is received

    #if !defined(NO_LOGGER)
            [Logger log:kLogDebug format:@"%s %@",__func__,[self socketPath]];
            }
        else
            {
            [Logger log:kLogDebug format:@"%s failed to create
    %@",__func__,[self socketPath]];
    #endif
            }

        return (pipe);
    }

    - (NSPort*)connectPort
    {
        // This method connects with an already existing socket in
    the file system.
        // It fails (returns nil) if the socket does not exist.
        NSPort* pipe = nil;
        if ([self socketExists])
            pipe = [[[NSSocketPort alloc] initRemoteWithProtocolFamily:AF_UNIX
                                                            socketType:SOCK_STREAM
                                                              protocol:0

    address:[self socketAddressData]] autorelease];
    #if !defined(NO_LOGGER)
        if (pipe!=nil)
            [Logger log:kLogDebug format:@"%s %@",__func__,[self socketPath]];
        else
            [Logger log:kLogDebug format:@"%s failed to connect
    %@",__func__,[self socketPath]];
    #endif

        return (pipe);
    }

    @end

    --
    James Bucanek
  • On 20 Nov 2007, at 15:52, James Bucanek wrote:

    > Alastair Houghton <mailto:<alastair...> wrote
    > (Tuesday, November 20, 2007 6:48 AM -0000):
    >> Well regardless of whether or not you think your application isn't
    >> creating any TCP sockets, it clearly is; protocol 6 is TCP and the
    >> reason you're being pestered is that your programs are binding ports
    >> for listening on any address.
    >
    > Exactly. Since I spend days trying to figure out how to create an
    > interprocess Distributed Objects communications pipe that did *not*
    > use TCP I'm feeling cheated.
    >
    >>
    > - (NSConnection*)clientConnection
    > {
    > NSConnection* connection = nil;
    > NSPort* port = nil;
    > if ([self socketExists])
    > port = [self connectPort];
    > if (port!=nil)
    > connection = [NSConnection connectionWithReceivePort:nil
    > sendPort:port];
    > return (connection);
    > }

    Could this (above) be the problem?  The docs for NSConnection say:

    "If receivePort is nil, the NSConnection object allocates and uses a
    new port of the same class as sendPort."

    It's just a guess, but I wonder if the issue might be that it's
    allocating a TCP socket rather than a UNIX domain socket... after all,
    it has no way to name a UNIX domain socket if it allocates a new
    NSSocketPort.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • Alastair Houghton <mailto:<alastair...> wrote
    (Tuesday, November 20, 2007 9:12 AM -0000):
    > Could this (above) be the problem?  The docs for NSConnection say:
    >
    > "If receivePort is nil, the NSConnection object allocates and uses a
    > new port of the same class as sendPort."
    >
    > It's just a guess, but I wonder if the issue might be that it's
    > allocating a TCP socket rather than a UNIX domain socket... after all,
    > it has no way to name a UNIX domain socket if it allocates a new
    > NSSocketPort.

    I'm beginning to suspect that you're correct. I think
    NSConnection is just creating a generic NSSocketPort, which
    defaults to a randomly assigned TCP socket, for the return
    communications path. I had assumed that it would simply have
    used the pipe for both -- but maybe that's not even possible.

    If that's the case, then one solution might be to create two
    pipes and specify both the receive and send ports for the NSConnection.

    I've got another thread on the MacNetworkProg list going that
    might suggest that I can go back to using Mach ports and avoid
    this whole mess.

    --
    James Bucanek
  • On 20 Nov 2007, at 18:06, James Bucanek wrote:

    > Alastair Houghton <mailto:<alastair...> wrote
    > (Tuesday, November 20, 2007 9:12 AM -0000):
    >> Could this (above) be the problem?  The docs for NSConnection say:
    >>
    >> "If receivePort is nil, the NSConnection object allocates and uses a
    >> new port of the same class as sendPort."
    >>
    >> It's just a guess, but I wonder if the issue might be that it's
    >> allocating a TCP socket rather than a UNIX domain socket... after
    >> all,
    >> it has no way to name a UNIX domain socket if it allocates a new
    >> NSSocketPort.
    >
    > I'm beginning to suspect that you're correct. I think NSConnection
    > is just creating a generic NSSocketPort, which defaults to a
    > randomly assigned TCP socket, for the return communications path. I
    > had assumed that it would simply have used the pipe for both -- but
    > maybe that's not even possible.
    >
    > If that's the case, then one solution might be to create two pipes
    > and specify both the receive and send ports for the NSConnection.

    Did you try specifying both the send and receive ports as the same
    NSSocketPort?  I know the docs imply that that won't work in one of
    the two directions, but I suspect the docs are wrong (they're probably
    assuming Mach ports, which are one-way things, whereas sockets are two-
    way).

    I think it's also true that you can work around the Mach port issue if
    you're careful.  There are some tech notes on the subject, I think.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • Alastair Houghton <mailto:<alastair...> wrote
    (Tuesday, November 20, 2007 11:09 AM -0000):

    > On 20 Nov 2007, at 18:06, James Bucanek wrote:
    >
    >> Alastair Houghton <mailto:<alastair...> wrote
    >> (Tuesday, November 20, 2007 9:12 AM -0000):
    >>> Could this (above) be the problem?  The docs for NSConnection say:
    >>>
    >>> "If receivePort is nil, the NSConnection object allocates and uses a
    >>> new port of the same class as sendPort."
    >>>
    >>> It's just a guess, but I wonder if the issue might be that it's
    >>> allocating a TCP socket rather than a UNIX domain socket...
    >>> after all,
    >>> it has no way to name a UNIX domain socket if it allocates a new
    >>> NSSocketPort.
    >>
    >> I'm beginning to suspect that you're correct. I think
    >> NSConnection is just creating a generic NSSocketPort, which
    >> defaults to a randomly assigned TCP socket, for the return
    >> communications path. I had assumed that it would simply have
    >> used the pipe for both -- but maybe that's not even possible.
    >>
    >> If that's the case, then one solution might be to create two
    >> pipes and specify both the receive and send ports for the NSConnection.
    >
    > Did you try specifying both the send and receive ports as the same
    > NSSocketPort?

    Yes, I tried it. No, it doesn't work.

    > I know the docs imply that that won't work in one of
    > the two directions, but I suspect the docs are wrong (they're probably
    > assuming Mach ports, which are one-way things, whereas sockets are
    > two-way).
    >
    > I think it's also true that you can work around the Mach port issue if
    > you're careful.  There are some tech notes on the subject, I think.

    Well, that's what I thought too. I'm pretty sure that I've use
    the same Mach port for both send/receive and I would have
    assumed that you could use the same UNIX socket for both send
    and receive. (I thought that from each end/process that a socket
    appears as a bidirectional pipe -- but maybe I'm wrong. It's
    actually been a very long time since I used UNIX sockets directly.)
    --
    James Bucanek
  • On 20 Nov 2007, at 18:35, James Bucanek <subscriber...> wrote:

    > Well, that's what I thought too. I'm pretty sure that I've use the
    > same Mach port for both send/receive and I would have assumed that
    > you could use the same UNIX socket for both send and receive.

    Well Mach ports are a bit different to a socket, because they're just
    endpoint names (like TCP/IP ports) rather than connection identifiers.
    So it clearly wouldn't work with Mach ports.

    > (I thought that from each end/process that a socket appears as a
    > bidirectional pipe -- but maybe I'm wrong. It's actually been a very
    > long time since I used UNIX sockets directly.)

    Yes, that's right. A UNIX socket is just like a named bidirectional
    pipe.

    That's why I thought it might work with the same port on both positions.

    Kind regards,

    Alastair

    --
    http://alastairs-place.net
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today