Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Jun 2001 15:19:52 -0400 (EDT)
From:      Robert Watson <rwatson@freebsd.org>
To:        Dima Dorfman <dima@unixfreak.org>
Cc:        arch@freebsd.org
Subject:   Re: Peer credentials on a Unix domain socket
Message-ID:  <Pine.NEB.3.96L.1010627150012.16165D-100000@fledge.watson.org>
In-Reply-To: <20010627070628.AB5F13E2F@bazooka.unixfreak.org>

next in thread | previous in thread | raw e-mail | index | archive | help

How does this solution compare with similar solutions on other platforms?


Robert N M Watson             FreeBSD Core Team, TrustedBSD Project
robert@fledge.watson.org      NAI Labs, Safeport Network Services

On Wed, 27 Jun 2001, Dima Dorfman wrote:

> Hi folks,
> 
> Currently, there is no reliable way for a server listening on a Unix
> domain socket to find out the credentials of its peer until the peer
> sends something over the socket.  Finding its credentials can be
> useful if the server only wants to accept connections from certain
> users.  We already have SCM_CREDS, which will send the peer's
> credentials along with a message, but this is *not* sufficient as it
> may be unacceptable for the server to wait until the peer sends
> something; think of DoS attacked.  Times don't help, either; think of
> SYN flood-like attacks.
> 
> I would like to propose implementing such a facility as a socket
> option, LOCAL_PEERCRED.  The payload would be am xucred structure with
> the effective credentials of the connect(2) caller.  Granted these may
> not be the credentials of the process using the socket (think
> descriptor passing), but it doesn't matter; if a process hands a
> descriptor off to something else, it should be trusting it not to
> abuse it (this is a feature: think of opening a privileged port and
> dropping privileges).
> 
> This has been discussed at least twice before, and nobody has a better
> idea.  Again, I would like to stress the two requirements: (1) the
> accept(2) caller must be able to reliably obtain the effective
> credentials of the connect(2) caller, and (2) the accept(2) caller
> must be able to do (1) without relying on the connect(2) caller to
> send data (SCM_CREDS doesn't meet (2)).
> 
> Patch attached.
> 
> Comments?  Suggestions?
> 
> Thanks in advance,
> 
> 					Dima Dorfman
> 					dima@unixfreak.org
> 
> 
> Index: sys/un.h
> ===================================================================
> RCS file: /stl/src/FreeBSD/src/sys/sys/un.h,v
> retrieving revision 1.17
> diff -u -r1.17 un.h
> --- sys/un.h	1999/12/29 04:24:49	1.17
> +++ sys/un.h	2001/06/27 06:51:18
> @@ -46,12 +46,16 @@
>  	char	sun_path[104];		/* path name (gag) */
>  };
>  
> +/* Socket options. */
> +#define LOCAL_PEERCRED		0x001		/* retrieve peer credentials */
> +
>  #ifdef _KERNEL
>  struct mbuf;
>  struct socket;
>  
>  int	uipc_usrreq __P((struct socket *so, int req, struct mbuf *m,
>  		struct mbuf *nam, struct mbuf *control));
> +int	uipc_ctloutput __P((struct socket *so, struct sockopt *sopt));
>  int	unp_connect2 __P((struct socket *so, struct socket *so2));
>  void	unp_dispose __P((struct mbuf *m));
>  int	unp_externalize __P((struct mbuf *rights));
> Index: sys/unpcb.h
> ===================================================================
> RCS file: /stl/src/FreeBSD/src/sys/sys/unpcb.h,v
> retrieving revision 1.11
> diff -u -r1.11 unpcb.h
> --- sys/unpcb.h	2000/05/26 02:06:59	1.11
> +++ sys/unpcb.h	2001/06/27 06:51:18
> @@ -80,7 +80,14 @@
>  	int	unp_cc;			/* copy of rcv.sb_cc */
>  	int	unp_mbcnt;		/* copy of rcv.sb_mbcnt */
>  	unp_gen_t unp_gencnt;		/* generation count of this instance */
> +	int	unp_flags;		/* flags */
> +	struct	xucred unp_peercred;	/* peer credentials, if applicable */
>  };
> +
> +/*
> + * Flags in unp_flags.
> + */
> +#define UNP_HAVEPC	0x001		/* unp_peercred filled in? */
>  
>  #define	sotounpcb(so)	((struct unpcb *)((so)->so_pcb))
>  
> Index: kern/uipc_proto.c
> ===================================================================
> RCS file: /stl/src/FreeBSD/src/sys/kern/uipc_proto.c,v
> retrieving revision 1.21
> diff -u -r1.21 uipc_proto.c
> --- kern/uipc_proto.c	1999/10/11 15:19:11	1.21
> +++ kern/uipc_proto.c	2001/06/27 06:51:18
> @@ -51,7 +51,7 @@
>  
>  static struct protosw localsw[] = {
>  { SOCK_STREAM,	&localdomain,	0,	PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS,
> -  0,		0,		0,		0,
> +  0,		0,		0,		&uipc_ctloutput,
>    0,
>    0,		0,		0,		0,
>    &uipc_usrreqs
> Index: kern/uipc_usrreq.c
> ===================================================================
> RCS file: /stl/src/FreeBSD/src/sys/kern/uipc_usrreq.c,v
> retrieving revision 1.66
> diff -u -r1.66 uipc_usrreq.c
> --- kern/uipc_usrreq.c	2001/05/25 16:59:07	1.66
> +++ kern/uipc_usrreq.c	2001/06/27 06:51:18
> @@ -434,6 +434,23 @@
>  	uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr,
>  	sosend, soreceive, sopoll
>  };
> +
> +int
> +uipc_ctloutput(so, sopt)
> +	struct socket *so;
> +	struct sockopt *sopt;
> +{
> +	struct unpcb *unp = sotounpcb(so);
> +	int error;
> +
> +	if (sopt->sopt_dir == SOPT_GET && sopt->sopt_name == LOCAL_PEERCRED &&
> +	    unp->unp_flags & UNP_HAVEPC)
> +		error = sooptcopyout(sopt, &unp->unp_peercred,
> +		    sizeof(unp->unp_peercred));
> +	else
> +		error = EOPNOTSUPP;
> +	return (error);
> +}
>  	
>  /*
>   * Both send and receive buffers are allocated PIPSIZ bytes of buffering
> @@ -654,6 +671,12 @@
>  			unp3->unp_addr = (struct sockaddr_un *)
>  				dup_sockaddr((struct sockaddr *)
>  					     unp2->unp_addr, 1);
> +		bzero(&unp3->unp_peercred, sizeof(unp3->unp_peercred));
> +		unp3->unp_peercred.cr_uid = p->p_ucred->cr_uid;
> +		unp3->unp_peercred.cr_ngroups = p->p_ucred->cr_ngroups;
> +		bcopy(p->p_ucred->cr_groups, unp3->unp_peercred.cr_groups,
> +		    sizeof(unp3->unp_peercred.cr_groups));
> +		unp3->unp_flags |= UNP_HAVEPC;
>  		so2 = so3;
>  	}
>  	error = unp_connect2(so, so2);
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-arch" in the body of the message
> 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.96L.1010627150012.16165D-100000>