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_next_mach.c
Go to the documentation of this file.
1 /*
2 ** k_next_mach.c - NeXTstep 3 kernel access functions.
3 **
4 ** This program is in the public domain and may be used freely by anyone
5 ** who wants to.
6 **
7 ** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
8 */
9 
10 #include "config.h"
11 
12 #include <stdio.h>
13 #include <errno.h>
14 #include <ctype.h>
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <netdb.h>
18 #include <nlist.h>
19 #include <pwd.h>
20 #include <signal.h>
21 #include <syslog.h>
22 
23 #include "pkvm.h"
24 
25 #include <sys/socket.h>
26 #include <sys/socketvar.h>
27 
28 #include <sys/ioctl.h>
29 
30 /* FIXME: check for features? */
31 #ifndef NeXT31
32 # define KERNEL
33 # define KERNEL_FEATURES
34 #else
35 # define KERNEL_FILE
36 #endif
37 
38 #include <sys/file.h>
39 
40 #ifndef NeXT31
41 # undef KERNEL
42 # undef KERNEL_FEATURES
43 #else
44 # undef KERNEL_FILE
45 #endif
46 
47 #include <sys/user.h>
48 
49 #include <net/if.h>
50 #include <net/route.h>
51 #include <netinet/in.h>
52 #include <netinet/in_systm.h>
53 #include <netinet/ip.h>
54 #include <netinet/tcp.h>
55 #include <netinet/tcp_timer.h>
56 #include <netinet/tcp_var.h>
57 
58 #include <netinet/in_pcb.h>
59 #include <netinet/ip_var.h>
60 
61 #include "pidentd.h"
62 
63 
64 struct kainfo
65 {
66  kvm_t *kd;
67  struct nlist nl[4];
68 };
69 
70 
71 #define N_FILE 0
72 #define N_NFILE 1
73 #define N_TCB 2
74 
75 
76 
77 
78 int
79 ka_init(void)
80 {
81 #if 0
82  char osinfo_current[256];
83 
84  if (osinfo_get(osinfo_current) == NULL)
85  return -1;
86 
87  return strcmp(osinfo_build, osinfo_current);
88 #endif
89  return 0;
90 }
91 
92 
93 
94 int
95 ka_open(void **misc)
96 {
97  int rcode;
98  struct kainfo *kp;
99 
100 
101  kp = s_malloc(sizeof(*kp));
102 
103  /*
104  ** Open the kernel memory device
105  */
106  if ((kp->kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
107  {
108  if (debug)
109  perror("kvm_open");
110 
111  syslog(LOG_ERR, "kvm_open: %m");
112  s_free(kp);
113  return -1;
114  }
115 
116  kp->nl[0].n_un.n_name = "_file_list";
117  kp->nl[1].n_un.n_name = "_max_file";
118  kp->nl[2].n_un.n_name = "_tcb";
119  kp->nl[3].n_un.n_name = NULL;
120 
121  /*
122  ** Extract offsets to the needed variables in the kernel
123  */
124  if ((rcode = kvm_nlist(kp->kd, kp->nl)) != 0)
125  {
126  if (debug)
127  fprintf(stderr, "kvm_nlist: returned %d\n", rcode);
128 
129  syslog(LOG_ERR, "kvm_nlist, rcode = %d: %m", rcode);
130  kvm_close(kp->kd);
131  s_free(kp);
132  return -1;
133  }
134 
135  *misc = (void *) kp;
136  return 0;
137 }
138 
139 
140 /*
141 ** Get a piece of kernel memory with error handling.
142 ** Returns 1 if call succeeded, else 0 (zero).
143 */
144 static int
146  off_t addr,
147  void *buf,
148  size_t len,
149  char *what)
150 {
151  if (kvm_read(kd, addr, buf, len) < 0)
152  {
153  syslog(LOG_INFO, "getbuf: kvm_read(%08x, %lu) - %s : %m",
154  addr, (unsigned long) len, what);
155 
156  return 0;
157  }
158 
159  return 1;
160 }
161 
162 
163 
164 /*
165 ** Traverse the inpcb list until a match is found
166 ** Returns NULL if no match.
167 */
168 
169 static struct socket *
171  struct inpcb *pcbp,
172  struct in_addr *faddr,
173  int fport,
174  struct in_addr *laddr,
175  int lport)
176 {
177  struct inpcb *head;
178  int limiter = 65536;
179 
180  if (pcbp == NULL)
181  return NULL; /* Someone gave us a duff one here */
182 
183  head = pcbp->inp_prev;
184  do
185  {
186  if (pcbp->inp_faddr.s_addr == faddr->s_addr &&
187  pcbp->inp_laddr.s_addr == laddr->s_addr &&
188  pcbp->inp_fport == fport &&
189  pcbp->inp_lport == lport)
190  return pcbp->inp_socket;
191 
192  if (--limiter <= 0)
193  break;
194 
195  } while (pcbp->inp_next != head &&
196  getbuf(kd, (off_t) pcbp->inp_next,
197  pcbp, sizeof(struct inpcb), "tcblist"));
198 
199  return NULL; /* Not found */
200 }
201 
202 
203 /*
204 ** Return the user number for the connection owner
205 */
206 int
207 ka_lookup(void *vp, struct kernel *kp)
208 {
209  struct in_addr *faddr;
210  int fport;
211  struct in_addr *laddr;
212  int lport;
213 
214  struct kainfo *kip;
215  struct ucred ucb;
216  struct socket *sockp;
217  int nfile;
218  struct inpcb tcb;
219  struct file file_entry;
220  void *addr;
221 
222  kip = (struct kainfo *) vp;
223 
224  faddr = &kp->remote.sin_addr;
225  laddr = &kp->local.sin_addr;
226  fport = kp->remote.sin_port;
227  lport = kp->local.sin_port;
228 
229  /* -------------------- TCP PCB LIST -------------------- */
230  if (!getbuf(kip->kd,
231  (off_t) kip->nl[N_TCB].n_value,
232  &tcb, sizeof(tcb), "tcb"))
233  return -1;
234 
235  tcb.inp_prev = (struct inpcb *) kip->nl[N_TCB].n_value;
236  sockp = getlist(kip->kd, &tcb, faddr, fport, laddr, lport);
237 
238  if (sockp == NULL)
239  return 0;
240 
241  /* -------------------- FILE DESCRIPTOR TABLE -------------------- */
242  /* So now we hit the fun Mach kernel structures */
243  if (!getbuf(kip->kd,
244  (off_t) kip->nl[N_FILE].n_value,
245  &addr, sizeof(addr), "&file_table"))
246  return -1;
247 
248  /* We only use nfile as a failsafe in case something goes wrong! */
249  if (!getbuf(kip->kd,
250  (off_t) kip->nl[N_NFILE].n_value,
251  &nfile, sizeof(nfile), "nfile"))
252  return -1;
253 
254  file_entry.links.next = addr;
255  /* ------------------- SCAN FILE TABLE ------------------------ */
256  do
257  {
258  if (!getbuf(kip->kd,
259  (off_t) file_entry.links.next,
260  &file_entry, sizeof(file_entry), "struct file"))
261  return -1;
262 
263  if (file_entry.f_count == 0)
264  continue;
265 
266  if (file_entry.f_type == DTYPE_SOCKET &&
267  (struct socket *) file_entry.f_data == sockp)
268  {
269  if (!getbuf(kip->kd,
270  (off_t) file_entry.f_cred,
271  &ucb, sizeof(ucb), "ucb"))
272  return -1;
273 
274  kp->ruid = ucb.cr_ruid;
275  kp->euid = ucb.cr_uid;
276 
277  return 1;
278  }
279  } while ((file_entry.links.next != addr) && (--nfile));
280 
281  return -1;
282 }
ka_init
int ka_init(void)
Definition: k_next_mach.c:79
s_free
void s_free(void *p)
Definition: safeio.c:153
kainfo
Definition: k_aix42.c:73
ka_lookup
int ka_lookup(void *vp, struct kernel *kp)
Definition: k_next_mach.c:207
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::kd
int kd
Definition: k_aix42.c:75
getlist
static struct socket * getlist(kvm_t *kd, struct inpcb *pcbp, struct in_addr *faddr, int fport, struct in_addr *laddr, int lport)
Definition: k_next_mach.c:170
kernel::local
struct sockaddr_gen local
Definition: kernel.h:28
s_malloc
void * s_malloc(size_t size)
Definition: safeio.c:132
N_TCB
#define N_TCB
Definition: k_next_mach.c:73
kernel::euid
uid_t euid
Definition: kernel.h:35
kvm_close
int kvm_close(kvm_t *kd)
N_FILE
#define N_FILE
Definition: k_next_mach.c:71
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)
debug
int debug
Definition: gen_osinfo.c:23
kernel::ruid
uid_t ruid
Definition: kernel.h:36
ka_open
int ka_open(void **misc)
Definition: k_next_mach.c:95
getbuf
static int getbuf(kvm_t *kd, off_t addr, void *buf, size_t len, char *what)
Definition: k_next_mach.c:145
N_NFILE
#define N_NFILE
Definition: k_next_mach.c:72
pkvm.h
osinfo_build
char osinfo_build[]
kernel
Definition: kernel.h:25
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