pidentd  3.0.19
About: implementation of the RFC1413 identification server (more or less complete rewrite compared to version 2)
  Fossies Dox: pidentd-3.0.19.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

k_sunos510.c
Go to the documentation of this file.
1 /*
2 ** k_sunos510.c - SunOS 5.10 kernel access functions
3 **
4 ** Copyright (c) 1995-2003 Casper Dik <Casper.Dik@Holland.Sun.COM>
5 ** Copyright (c) 1997 Peter Eriksson <pen@lysator.liu.se>
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it as you wish - as long as you don't claim that you wrote
9 ** it.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 **
15 */
16 
17 #include "config.h"
18 
19 #include <unistd.h>
20 #include <string.h>
21 #include <stddef.h>
22 
23 #include <stdio.h>
24 #include <nlist.h>
25 #include <math.h>
26 
27 #define _KMEMUSER
28 #define _KERNEL
29 
30 #include <sys/cred_impl.h>
31 #include <kvm.h>
32 
33 /* some definition conflicts. but we must define _KERNEL */
34 
35 #define ffs kernel_ffs
36 #define ka_init kernel_ka_init
37 #define getbuf kernel_ka_init
38 #define exit kernel_exit
39 #define strsignal kernel_strsignal
40 #define mutex_init kernel_mutex_init
41 #define mutex_destroy kernel_mutex_destroy
42 #define sema_init kernel_sema_init
43 #define sema_destroy kernel_sema_destroy
44 
45 #include <syslog.h>
46 
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <sys/signal.h>
50 #include <sys/param.h>
51 #include <netinet/in.h>
52 
53 #include <sys/fcntl.h>
54 #include <sys/cred.h>
55 #include <sys/file.h>
56 #include <sys/stream.h>
57 #include <sys/dlpi.h>
58 #include <net/if_types.h>
59 #include <inet/common.h>
60 #include <netinet/ip6.h>
61 #include <inet/ip.h>
62 #include <inet/tcp.h>
63 #include <inet/ipclassifier.h>
64 #include <netinet/ip6.h>
65 #include <net/if.h>
66 
68 
69 #if !defined(IN6_V4_MAPPED_TO_INADDR)
70 
71 #define IPv6_2_IPv4(v6, v4) \
72  ((v4)->s_addr = *((uint32_t *) \
73  (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)))
74 
75 #else /* defined(IN6_V4_MAPPED_TO_INADDR) */
76 
77 #define IPv6_2_IPv4(v6, v4) IN6_V4MAPPED_TO_INADDR((struct in6_addr *)v6, v4)
78 
79 #endif /* defined(IN6_V4MAPPED_TO_INADDR) */
80 
81 #define FANOUT_OFFSET(n) (kip->hash_table + (n) * sizeof(connf_t) + \
82  offsetof(connf_t, connf_head))
83 
84 #undef exit
85 #undef strsignal
86 #undef mutex_init
87 #undef mutex_destroy
88 #undef sema_init
89 #undef sema_destroy
90 #undef ffs
91 #undef ka_init
92 #undef getbuf
93 
94 #undef SEMA_HELD
95 #undef RW_LOCK_HELD
96 #undef RW_READ_HELD
97 #undef RW_WRITE_HELD
98 #undef MUTEX_HELD
99 
100 #include "pidentd.h"
101 
102 #define N_FANOUT 0
103 #define N_HASH_SIZE 1
104 
105 struct kainfo
106 {
107  kvm_t *kd;
108  uint_t hash_size;
109  unsigned long hash_table;
110  struct nlist nl[3];
111 };
112 
113 
114 /*
115 ** Make sure we are running on a supported OS version
116 */
117 int
118 ka_init(void)
119 {
120  char osinfo_current[256];
121 
122  if (osinfo_get(osinfo_current) == NULL)
123  return -1;
124 
125  return strcmp(osinfo_build, osinfo_current);
126 }
127 
128 /*
129 ** Get a piece of kernel memory with error handling.
130 ** Returns 1 if call succeeded, else 0 (zero).
131 */
132 static int
133 getbuf(kvm_t *kd, off_t addr, char *buf, size_t len, char *what)
134 {
135  int i;
136  ssize_t status;
137 
138 
139  i = 0;
140  while (i < 5 && (status = kvm_read(kd, addr, buf, len)) < 0)
141  ++i;
142 
143  if (status < 0)
144  return 0;
145 
146  return 1;
147 }
148 
149 
150 /*
151 ** Open kernel devices, lookup kernel symbols etc...
152 */
153 int
154 ka_open(void **misc)
155 {
156  struct kainfo *kp;
157 
158 
159  kp = s_malloc(sizeof(*kp));
160 
161  /*
162  ** Open the kernel memory device
163  */
164  if ((kp->kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
165  {
166  syslog(LOG_ERR, "kvm_open: %m");
167  s_free(kp);
168  return -1;
169  }
170 
171 
172  kp->nl[0].n_name = "ipcl_conn_fanout";
173  kp->nl[1].n_name = "ipcl_conn_fanout_size";
174  kp->nl[2].n_name = NULL;
175 
176  /*
177  ** Extract offsets to the needed variables in the kernel
178  */
179  if (kvm_nlist(kp->kd, kp->nl) != 0)
180  {
181  syslog(LOG_ERR, "kvm_nlist: %m");
182  kvm_close(kp->kd);
183  s_free(kp);
184  return -1;
185  }
186 
187  /*
188  * Read the two kernel values we need but won't change
189  */
190  if (!getbuf(kp->kd, kp->nl[N_HASH_SIZE].n_value, (char *) &kp->hash_size,
191  sizeof(kp->hash_size), kp->nl[N_HASH_SIZE].n_name) ||
192  !getbuf(kp->kd, kp->nl[N_FANOUT].n_value, (char *) &kp->hash_table,
193  sizeof(kp->hash_table), kp->nl[N_FANOUT].n_name)) {
194  kvm_close(kp->kd);
195  s_free(kp);
196  syslog(LOG_ERR, "getbuf: can't get needed symbols");
197  return -1;
198  }
199 
200  *misc = (void *) kp;
201  return 0;
202 }
203 
204 
205 
206 /*
207 ** Return the user number for the connection owner
208 */
209 int
210 ka_lookup(void *vp, struct kernel *kp)
211 {
212  struct kainfo *kip;
213  unsigned short uslp, usfp;
214  unsigned int offset;
215  file_t tf;
216  unsigned long zero = 0;
217  uint32_t *locaddr, *raddr;
218  struct proc *procp;
219  char *faddr;
220  int fport;
221  char *laddr;
222  int lport;
223  struct stdata *std;
224  conn_t *connfp;
225  queue_t *q;
226  char *iphash;
227  cred_t cr;
228  conn_t con;
229  uint_t ports;
230  uint16_t *pptr = (uint16_t *)&ports;
231 
232  kip = (struct kainfo *) vp;
233 
234  faddr = (char *) SGADDRP(kp->remote);
235  laddr = (char *) SGADDRP(kp->local);
236  fport = SGPORT(kp->remote);
237  lport = SGPORT(kp->local);
238 
239  /* XXX: the V4_PART macros don't work and port to well to this */
240  iphash = SGFAM(kp->remote) == AF_INET ? faddr : faddr + 12;
241 
242  usfp = fport;
243  uslp = lport;
244 
245  /*
246  * All tcp connections are in one single hash table; IPV4 connections
247  * over AF_INET6 sockets do not show up in the normal tcp hash tables
248  *
249  * First we need to find the hash entry in the tcp table;
250  * then we need to follow the chain and get the TCP entry.
251  */
252 
253  pptr[0] = fport;
254  pptr[1] = lport;
255  /* XXX: need to change in build 46 */
256  offset = (unsigned)ntohl(*(uint_t *)iphash) ^
257  (ports >> 24) ^ (ports >> 16) ^ (ports >> 8) ^ ports;
258 
259  offset %= kip->hash_size;
260 
261  if (!getbuf(kip->kd, FANOUT_OFFSET(offset), (char*) &connfp, sizeof(connfp),
262  "ipcl_conn_fanout[hash]"))
263  return -1;
264 
265  if (connfp == NULL) {
266  syslog(LOG_DEBUG, "k_getuid: tcp hash miss");
267  return -1;
268  }
269 
270  while (connfp != NULL) {
271 
272  if (!getbuf(kip->kd, (unsigned long) connfp, (char *) &con, sizeof(con),
273  "struct conn_s"))
274  return -1;
275 
276  if (uslp == con.conn_lport && usfp == con.conn_fport) {
277  if (SGFAM(kp->remote) == AF_INET) {
278  struct in_addr fv4, lv4;
279  IPv6_2_IPv4(&con.conn_srcv6, &lv4);
280  IPv6_2_IPv4(&con.conn_remv6, &fv4);
281  if (memcmp(&lv4, laddr, 4) == 0 && memcmp(&fv4, faddr, 4) == 0)
282  break;
283  } else if (memcmp(&con.conn_srcv6, laddr, SGSIZE(kp->local))
284  == 0 &&
285  memcmp(&con.conn_remv6, faddr, SGSIZE(kp->remote))
286  == 0) {
287  break;
288  }
289  }
290 
291  connfp = con.conn_next;
292  }
293 
294  if (connfp == NULL)
295  return -1;
296 
297  if (!getbuf(kip->kd, (off_t) con.conn_cred, (char *) &cr,
298  sizeof(cr), "cred"))
299  return -1;
300 
301  kp->ruid = cr.cr_ruid;
302  kp->euid = cr.cr_uid;
303 
304  return (1);
305 }
SGPORT
#define SGPORT(sag)
Definition: sockaddr.h:57
s_free
void s_free(void *p)
Definition: safeio.c:153
kainfo
Definition: k_aix42.c:73
kvm_nlist
int kvm_nlist(kvm_t *kd, struct nlist *nl)
pidentd.h
kernel::remote
struct sockaddr_gen remote
Definition: kernel.h:29
kvm_t
Definition: pkvm.h:18
kainfo::hash_size
uint_t hash_size
Definition: k_sunos510.c:108
kainfo::kd
int kd
Definition: k_aix42.c:75
kernel::local
struct sockaddr_gen local
Definition: kernel.h:28
ipcl_conn_fanout_size
uint_t ipcl_conn_fanout_size
Definition: k_sunos510.c:67
s_malloc
void * s_malloc(size_t size)
Definition: safeio.c:132
N_FANOUT
#define N_FANOUT
Definition: k_sunos510.c:102
FANOUT_OFFSET
#define FANOUT_OFFSET(n)
Definition: k_sunos510.c:81
kernel::euid
uid_t euid
Definition: kernel.h:35
kvm_close
int kvm_close(kvm_t *kd)
osinfo_get
char * osinfo_get(char *buf)
Definition: support.c:39
kvm_open
kvm_t * kvm_open(const char *namelist, const char *corefile, const char *swapfile, int flag, const char *errstr)
kernel::ruid
uid_t ruid
Definition: kernel.h:36
kainfo::hash_table
unsigned long hash_table
Definition: k_sunos510.c:109
SGFAM
#define SGFAM(sag)
Definition: sockaddr.h:54
ka_lookup
int ka_lookup(void *vp, struct kernel *kp)
Definition: k_sunos510.c:210
ka_init
#define ka_init
Definition: k_sunos510.c:36
SGADDRP
#define SGADDRP(sag)
Definition: sockaddr.h:58
N_HASH_SIZE
#define N_HASH_SIZE
Definition: k_sunos510.c:103
IPv6_2_IPv4
#define IPv6_2_IPv4(v6, v4)
Definition: k_sunos510.c:71
getbuf
#define getbuf
Definition: k_sunos510.c:37
osinfo_build
char osinfo_build[]
kernel
Definition: kernel.h:25
SGSIZE
#define SGSIZE(sag)
Definition: sockaddr.h:55
kvm_read
ssize_t kvm_read(kvm_t *kd, off_t addr, void *buf, size_t len)
kainfo::nl
struct nlist nl[4]
Definition: k_bsd42.c:74
ka_open
int ka_open(void **misc)
Definition: k_sunos510.c:154