Possible lack of permission check

Hello,

I recently wrote a test application which I run on my personal iPhone. The two-thirds of the application are written in Rust and the other one-third is written in Swift with SwiftUI. When I run the core Rust application on my MacBook I get a permission prompt (expected) when the application requests a TCP socket to listen over the local network. When I run the exact same code on the iPhone no permission prompt is shown the application is just allowed UDP broadcast access over the local wifi and TCP listen over the local wifi without any "Local Network" permission. I feel like this should at least be behind a permission prompt like on macOS, am I right?

Replies

On the iOS side, working on local networks requires the Local Network privilege. For more background on that, see the Local Network Privacy FAQ.

macOS does not support the Local Network privilege, and neither does the iOS simulator. So I wouldn’t expect to see a local network prompt there. However, macOS does support the application firewall (System Preferences > Security & Privacy > Firewall), which may present authorisation prompts if your app attempts to listen for incoming connections.

Are you perhaps mixing these things up?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for your reply. I think you mis-understood part of my problem. I of course do have Firewall enabled on macOS so that's why I get the local prompts (which I expect) but you didn't understand that I'm NOT using any simulator or Xcode preview I actually meant "running on my personal iPhone" I can even tell you that it is an iPhone 13 Pro running latest iOS 15.5 and the application Rust core component is built using target "aarch64-apple-ios" (aarch64 is the processor architecture for most Apple devices now). So I really meant that on my personal iPhone (and that is not a simulator, it's an actual physical device), my application is allowed to open TCP listen sockets and send UDP broadcast packets on the local wifi network WITHOUT any permission requirement (not even "Local Network")!

Is this more clear now?

my application is allowed to open TCP listen sockets and send UDP broadcast packets on the local wifi network WITHOUT any permission requirement (not even "Local Network")!

Opening TCP listening sockets is not an operation protected by LNP. See LNP FAQ-2.

Sending UDP broadcast packets should trigger LNP, and it certainly did the last time I tried it [1]. Are you sure those packets are going out on the ‘wire’?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Which, admittedly, was a while ago, because LNP was a really hot issue back in the iOS 14 timeframe but has quietened down a lot recently.

Opening TCP listening sockets is not an operation protected by LNP. See LNP FAQ-2.

Yeah I just read that on the FAQ you sent to me, which I find strange considering that listening for TCP on the local network technically accesses the local network.

Sending UDP broadcast packets should trigger LNP, and it certainly did the last time I tried it [1].

That part is surprising because according the FAQ you sent me I should be disallowed to do this completely because I didn't pay for the 100$ a year and UDP broadcast requires a special entitlement but in my case it requires nothing the only flags I've enabled in my Info.plist are:

  • "Supports Document Browser" -> Internet said this was required to support the Files app on iOS (linked with the second permission).
  • "Supports opening documents in place" -> Allows editing of all configuration files and lua scripts directly on the iPhone and allows viewing core application logs on the iPhone.
  • "Application supports iTunes file sharing" -> Allows my mac Finder to put lua files and other configuration files directly in the application documents directory.

Are you sure those packets are going out on the ‘wire’?

Well I'm sure these packets are sent otherwise how could I see the UDP packet from the client app running on my Mac?

Let me give you a part of the low-level network code so you can see by yourself (the actual code is in Rust but I tried to translate it to C):

pub const DEFAULT_PORT: u16 = 4026;

let packet = [/* some bytes here */];
let socket = UdpSocket::unbounded(Domain::IpV4).unwrap();
socket.set_broadcast(true).unwrap();
if let Err(e) = self.socket.send_to(&packet, (Ipv4Addr::BROADCAST, DEFAULT_PORT)) {
    eprintln!("Failed to send broadcast auto-discover packet: {}", e);
}

Here is my translation in C (using BSD names):

#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>

#define DEFAULT_PORT 4026
char packet[] = {0, 1, 3}; //This is just for example; the actual packet is more complicated.
int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int flag = 1;
setsockopt(s, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(int));
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = (in_port_t)htons(DEFAULT_PORT);
addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
if (sendto(s, &packet, 3, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
    fprintf(stderr, "Failed to send broadcast auto-discover packet");