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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <strings.h>
31 #include <sys/socket.h>
32 
33 #include <bsm/audit.h>
34 #include <bsm/libbsm.h>
35 #include <bsm/audit_private.h>
36 #include <generic.h>
37 
38 static int do_ipv6_address(struct sockaddr_in6 *, struct sockaddr_in6 *);
39 static int do_ipv4_address(struct sockaddr_in *, struct sockaddr_in *);
40 
41 int
42 audit_settid(int fd)
43 {
44 	struct sockaddr_in6 peer;
45 	struct sockaddr_in6 sock;
46 	int peerlen = sizeof (peer);
47 	int socklen = sizeof (sock);
48 	int rv;
49 
50 	if (cannot_audit(0)) {
51 		return (0);
52 	}
53 
54 	/* get peer name */
55 	if (getpeername(fd, (struct sockaddr *)&peer, (socklen_t *)&peerlen)
56 		< 0) {
57 		return (1);
58 	}
59 
60 	/* get sock name */
61 	if (getsockname(fd, (struct sockaddr *)&sock, (socklen_t *)&socklen)
62 		< 0) {
63 		return (1);
64 	}
65 
66 	if (peer.sin6_family == AF_INET6)
67 		rv = do_ipv6_address(&peer, &sock);
68 	else
69 		rv = do_ipv4_address((struct sockaddr_in *)&peer,
70 			(struct sockaddr_in *)&sock);
71 
72 	return (rv);
73 }
74 
75 static int
76 do_ipv6_address(struct sockaddr_in6 *peer, struct sockaddr_in6 *sock)
77 {
78 	auditinfo_addr_t ai;
79 
80 	/* get audit characteristics of process */
81 	if (getaudit_addr(&ai, sizeof (ai)) < 0) {
82 		return (errno);
83 	}
84 
85 	/*
86 	 * if terminal ID already set, i.e. non-zero, then just return
87 	 */
88 	if (ai.ai_termid.at_port ||
89 	    ai.ai_termid.at_addr[0] ||
90 	    ai.ai_termid.at_addr[1] ||
91 	    ai.ai_termid.at_addr[2] ||
92 	    ai.ai_termid.at_addr[3]) {
93 		return (0);
94 	}
95 
96 	ai.ai_termid.at_port = ((peer->sin6_port<<16) | (sock->sin6_port));
97 	ai.ai_termid.at_type = AU_IPv6;
98 	bcopy(&peer->sin6_addr, ai.ai_termid.at_addr, 16);
99 
100 	if (setaudit_addr(&ai, sizeof (ai)) < 0) {
101 		return (errno);
102 	}
103 
104 	return (0);
105 }
106 
107 static int
108 do_ipv4_address(struct sockaddr_in *peer, struct sockaddr_in *sock)
109 {
110 	auditinfo_t ai;
111 
112 	/* get audit characteristics of process */
113 	if (getaudit(&ai) < 0) {
114 		return (errno);
115 	}
116 
117 	/*
118 	 * if terminal ID already set, i.e. non-zero, then just return
119 	 */
120 	if (ai.ai_termid.port || ai.ai_termid.machine) {
121 		return (0);
122 	}
123 
124 	ai.ai_termid.port = (peer->sin_port<<16 | sock->sin_port);
125 	ai.ai_termid.machine = (uint32_t)peer->sin_addr.s_addr;
126 
127 	if (setaudit(&ai) < 0) {
128 		return (errno);
129 	}
130 
131 	return (0);
132 }
133