xref: /illumos-gate/usr/src/cmd/smbsrv/bind-helper/bind-helper.c (revision c5bab7026b8e0ac44b25ee08507ea360f177d844)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
14  */
15 
16 /*
17  * This program is installed with an RBAC exec_attr
18  * that allows it to bind a reserved address.
19  * (Or just make it setuid root.)
20  *
21  * To grant privileges to the program using RBAC,
22  * add the following line to /etc/security/exec_attr
23  *	Forced Privilege:solaris:cmd:::\
24  *	/usr/lib/smbsrv/bind-helper:\
25  *	privs=net_privaddr,sys_smb\
26  *
27  * Args: family address port
28  * Does a bind on fileno(stdin)
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 
41 int
42 main(int argc, char **argv)
43 {
44 	struct sockaddr sa;
45 	/* LINTED E_BAD_PTR_CAST_ALIGN */
46 	struct sockaddr_in  *sin  = (struct sockaddr_in *)&sa;
47 	/* LINTED E_BAD_PTR_CAST_ALIGN */
48 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
49 	int rc, err = 0;
50 
51 	if (argc < 4) {
52 		(void) fprintf(stderr, "usage: %s family address port\n",
53 		    argv[0]);
54 		exit(1);
55 	}
56 
57 	(void) memset(&sa, 0, sizeof (sa));
58 	sa.sa_family = atoi(argv[1]);
59 	switch (sa.sa_family) {
60 	case AF_INET:
61 		rc = inet_pton(AF_INET, argv[2], &sin->sin_addr);
62 		sin->sin_port = htons(atoi(argv[3]));
63 		break;
64 	case AF_INET6:
65 		rc = inet_pton(AF_INET6, argv[2], &sin6->sin6_addr);
66 		sin6->sin6_port = htons(atoi(argv[3]));
67 		break;
68 	default:
69 		rc = 0;
70 		break;
71 	}
72 
73 	if (rc > 0)
74 		err = 0;
75 	else if (rc == 0)
76 		err = EINVAL;
77 	else if (rc < 0)
78 		err = errno;
79 	if (err != 0) {
80 		(void) fprintf(stderr, "%s: bad proto addr %s %s %s\n",
81 		    argv[0], argv[1], argv[2], argv[3]);
82 		exit(1);
83 	}
84 
85 	if (bind(0, &sa, sizeof (sa)) < 0) {
86 		err = errno;
87 		(void) fprintf(stderr, "%s: bind: %s\n",
88 		    argv[0], strerror(err));
89 		exit(2);
90 	}
91 	exit(0);
92 }
93