1 /* $MirOS: src/libexec/identd/openbsd.c,v 1.2 2005/03/06 19:24:01 tg Exp $ */
2 /* $OpenBSD: openbsd.c,v 1.19 2004/09/16 08:25:05 deraadt Exp $ */
3 
4 /*
5  * This program is in the public domain and may be used freely by anyone
6  * who wants to.
7  *
8  * Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
9  *
10  * This version elminates the kmem search in favour of a kernel sysctl to
11  * get the user id associated with a connection - Bob Beck <beck@obtuse.com>
12  */
13 
14 #include <sys/param.h>
15 #include <sys/socket.h>
16 #include <sys/socketvar.h>
17 #include <sys/sysctl.h>
18 
19 #include <stdio.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <syslog.h>
23 
24 #include <netinet/in.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/tcp.h>
27 #include <netinet/ip_var.h>
28 #include <netinet/tcp_timer.h>
29 #include <netinet/tcp_var.h>
30 
31 #include <arpa/inet.h>
32 
33 #include "identd.h"
34 
35 __RCSID("$MirOS: src/libexec/identd/openbsd.c,v 1.2 2005/03/06 19:24:01 tg Exp $");
36 
37 /*
38  * Return the user number for the connection owner
39  */
40 int
k_getuid(struct in_addr * faddr,int fport,struct in_addr * laddr,int lport,uid_t * uid)41 k_getuid(struct in_addr *faddr, int fport, struct in_addr *laddr,
42     int lport, uid_t *uid)
43 {
44 	int mib[] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_IDENT };
45 	struct sockaddr_in *fin, *lin;
46 	struct tcp_ident_mapping tir;
47 	int error = 0;
48 	size_t i;
49 
50 	memset(&tir, 0, sizeof (tir));
51 	tir.faddr.ss_len = (sizeof (struct sockaddr_storage) & 0xff);
52 	tir.laddr.ss_len = (sizeof (struct sockaddr_storage) &0xff);
53 	tir.faddr.ss_family = AF_INET;
54 	tir.laddr.ss_family = AF_INET;
55 	fin = (struct sockaddr_in *) &tir.faddr;
56 	lin = (struct sockaddr_in *) &tir.laddr;
57 
58 	memcpy(&fin->sin_addr, faddr, sizeof (struct in_addr));
59 	memcpy(&lin->sin_addr, laddr, sizeof (struct in_addr));
60 	fin->sin_port = fport;
61 	lin->sin_port = lport;
62 	i = sizeof (tir);
63 	error = sysctl(mib, sizeof (mib) / sizeof (int), &tir, &i, NULL, 0);
64 	if (!error && tir.ruid != -1) {
65 		*uid = tir.ruid;
66 		return (0);
67 	}
68 	if (error == -1)
69 		syslog(LOG_DEBUG, "sysctl failed (%m)");
70 
71 	return (-1);
72 }
73 
74 /*
75  * Return the user number for the connection owner
76  * New minty IPv6 version.
77  */
78 int
k_getuid6(struct sockaddr_in6 * faddr,int fport,struct sockaddr_in6 * laddr,int lport,uid_t * uid)79 k_getuid6(struct sockaddr_in6 *faddr, int fport, struct sockaddr_in6 *laddr,
80     int lport, uid_t *uid)
81 {
82 	int mib[] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_IDENT };
83 	struct sockaddr_in6 *fin, *lin;
84 	struct tcp_ident_mapping tir;
85 	int error = 0;
86 	size_t i;
87 
88 	memset(&tir, 0, sizeof (tir));
89 	fin = (struct sockaddr_in6 *) &tir.faddr;
90 	lin = (struct sockaddr_in6 *) &tir.laddr;
91 
92 	memcpy(fin, faddr, faddr->sin6_len);
93 	memcpy(lin, laddr, laddr->sin6_len);
94 	fin->sin6_port = fport;
95 	lin->sin6_port = lport;
96 	i = sizeof (tir);
97 	error = sysctl(mib, sizeof (mib) / sizeof (int), &tir, &i, NULL, 0);
98 	if (!error && tir.ruid != -1) {
99 		*uid = tir.ruid;
100 		return (0);
101 	}
102 	if (error == -1)
103 		syslog(LOG_DEBUG, "sysctl failed (%m)");
104 
105 	return (-1);
106 }
107