1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <strings.h>
30 #include <sys/socket.h>
31 
32 #include <bsm/audit.h>
33 #include <bsm/libbsm.h>
34 #include <bsm/audit_private.h>
35 #include <generic.h>
36 
37 static int do_ipv6_address(struct sockaddr_in6 *, struct sockaddr_in6 *);
38 static int do_ipv4_address(struct sockaddr_in *, struct sockaddr_in *);
39 
40 int
audit_settid(int fd)41 audit_settid(int fd)
42 {
43 	struct sockaddr_in6 peer;
44 	struct sockaddr_in6 sock;
45 	int peerlen = sizeof (peer);
46 	int socklen = sizeof (sock);
47 	int rv;
48 
49 	if (cannot_audit(0)) {
50 		return (0);
51 	}
52 
53 	/* get peer name */
54 	if (getpeername(fd, (struct sockaddr *)&peer, (socklen_t *)&peerlen)
55 		< 0) {
56 		return (1);
57 	}
58 
59 	/* get sock name */
60 	if (getsockname(fd, (struct sockaddr *)&sock, (socklen_t *)&socklen)
61 		< 0) {
62 		return (1);
63 	}
64 
65 	if (peer.sin6_family == AF_INET6)
66 		rv = do_ipv6_address(&peer, &sock);
67 	else
68 		rv = do_ipv4_address((struct sockaddr_in *)&peer,
69 			(struct sockaddr_in *)&sock);
70 
71 	return (rv);
72 }
73 
74 static int
do_ipv6_address(struct sockaddr_in6 * peer,struct sockaddr_in6 * sock)75 do_ipv6_address(struct sockaddr_in6 *peer, struct sockaddr_in6 *sock)
76 {
77 	auditinfo_addr_t ai;
78 
79 	/* get audit characteristics of process */
80 	if (getaudit_addr(&ai, sizeof (ai)) < 0) {
81 		return (errno);
82 	}
83 
84 	/*
85 	 * if terminal ID already set, i.e. non-zero, then just return
86 	 */
87 	if (ai.ai_termid.at_port ||
88 	    ai.ai_termid.at_addr[0] ||
89 	    ai.ai_termid.at_addr[1] ||
90 	    ai.ai_termid.at_addr[2] ||
91 	    ai.ai_termid.at_addr[3]) {
92 		return (0);
93 	}
94 
95 	ai.ai_termid.at_port = ((peer->sin6_port<<16) | (sock->sin6_port));
96 	ai.ai_termid.at_type = AU_IPv6;
97 	bcopy(&peer->sin6_addr, ai.ai_termid.at_addr, 16);
98 
99 	if (setaudit_addr(&ai, sizeof (ai)) < 0) {
100 		return (errno);
101 	}
102 
103 	return (0);
104 }
105 
106 static int
do_ipv4_address(struct sockaddr_in * peer,struct sockaddr_in * sock)107 do_ipv4_address(struct sockaddr_in *peer, struct sockaddr_in *sock)
108 {
109 	auditinfo_t ai;
110 
111 	/* get audit characteristics of process */
112 	if (getaudit(&ai) < 0) {
113 		return (errno);
114 	}
115 
116 	/*
117 	 * if terminal ID already set, i.e. non-zero, then just return
118 	 */
119 	if (ai.ai_termid.port || ai.ai_termid.machine) {
120 		return (0);
121 	}
122 
123 	ai.ai_termid.port = (peer->sin_port<<16 | sock->sin_port);
124 	ai.ai_termid.machine = (uint32_t)peer->sin_addr.s_addr;
125 
126 	if (setaudit(&ai) < 0) {
127 		return (errno);
128 	}
129 
130 	return (0);
131 }
132