Re: Liberating locked up ports
Re: Liberating locked up ports
- Subject: Re: Liberating locked up ports
- From: "Peter Sichel" <email@hidden>
- Date: Tue, 28 Jan 2003 09:10:55 -0500
>
What is it going to take to get a good solution to this problem? As
>
it stands at the moment, a lot of developers are having to jump
>
through flaming hoops to implement less than good solutions to a
>
problem that could be fixed by Apple removing a single digit number
>
of lines of code from the kernel (I think it is 4 lines, 2 for TCP
>
and 2 for UDP, but it is a while since I looked).
All true, but this debate was waged and lost two years ago.
There are reasonable solutions for BSD Sockets using a SUID root
helper app. Apple needs to publish better sample code, but there
are some examples available.
Here's how I do it...
- Peter
//
// main.c
// OpenICMP
//
// Created by psichel on 3 Sep 2001.
// I have removed the copyright from this small sample so that
// other developers might use it freely. BSD descriptor passing
// is documented in Steven's Unix Network Programming and APUE.
//
// Requires Mac OS X 10.1 or later
// (BSD descriptor passing doesn't work in 10.0)
#include <sys/types.h>
#include <sys/socket.h> // struct msghdr
#include <sys/uio.h> // struct iovec
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#import <netinet/in.h> // sockaddr_in{} and other Internet defs
const int kFDSize = sizeof(int);
int SendFD( int channel, int fd );
int ReceiveFD( int channel );
// Open an ICMP socket and return it using BSD Descriptor Passing.
// By making this tiny program SUID root, a non-privileged application
// can gain access to ICMP.
//
// The caller opens a stream pipe, maps the pipe to be our
// STDIN and STDOUT, and then does a fork followed by exec (NSTask)
// We just open an ICMP socket and return it via sendmsg to STDOUT_FILENO.
//
// A future version could use command line arguments to specify
// what type of socket is desired.
int
main(int argc, char* argv[])
{
int newfd;
if (argc == 2 && !strcmp(argv[1], "-identify")) {
// identify ourself so we can be authorized
// ...
}
}
else if (argc == 2 && !strcmp(argv[1], "-icmp")) {
// assume we are executing as SUID root
// get a raw socket
newfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if ( SendFD(STDOUT_FILENO, newfd ) == 0 ) {
perror( "failed to send fd" );
return 1;
}
close(newfd); // we're done with descriptor
}
return 0;
}
typedef unsigned int uint32_t;
int
SendFD( int channel, int fd )
{
char buff[kFDSize];
struct iovec iov[1];
struct msghdr msg = {0};
struct data {
struct cmsghdr cmsg;
int fd;
} data;
int struct_data_size = sizeof(struct cmsghdr) + sizeof(int);
memset( &data, 0, sizeof( data ));
iov[0].iov_base = buff;
iov[0].iov_len = kFDSize;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
data.cmsg.cmsg_level = SOL_SOCKET;
data.cmsg.cmsg_type = SCM_RIGHTS;
data.cmsg.cmsg_len = struct_data_size;
data.fd = fd;
msg.msg_control = (caddr_t) &data;
msg.msg_controllen = struct_data_size;
// [PAS] interpret negative fd as resultCode and send it in msg buff
bzero(buff, kFDSize);
if (fd < 0) {
data.fd = 0;
memcpy(buff, &fd, kFDSize);
}
if ( sendmsg( channel, &msg, 0 ) == -1 ) return 0;
return 1;
}
int
ReceiveFD( int channel )
{
char buff[kFDSize];
int fd = 0;
struct iovec iov[1];
struct msghdr msg = {0};
int resultCode;
struct data {
struct cmsghdr cmsg;
int fd;
char padding[12];
} data;
memset( &data, 0, sizeof( data ));
iov[0].iov_base = buff;
iov[0].iov_len = kFDSize;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = (caddr_t) &data;
msg.msg_controllen = sizeof( struct data );
if ( recvmsg( channel, &msg, 0 ) == -1 ) return -1;
fd = data.fd;
if( (uint32_t) msg.msg_controllen < sizeof( struct cmsghdr ) +
sizeof( int )) {
errno = EIO; // bit vague I know...
return -1;
}
// [PAS] if buff is <0 pass back as result code
memcpy(&resultCode, &buff, kFDSize);
if (resultCode < 0) fd = resultCode;
return fd;
}
_______________________________________________
macnetworkprog mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/macnetworkprog
Do not post admin requests to the list. They will be ignored.