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)  

request.c
Go to the documentation of this file.
1 /*
2 ** request.c - Handle an IDENT protocol request
3 **
4 ** Copyright (c) 1997 Peter Eriksson <pen@lysator.liu.se>
5 **
6 ** This program is free software; you can redistribute it and/or
7 ** modify it as you wish - as long as you don't claim that you wrote
8 ** it.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 */
14 
15 #include "config.h"
16 
17 #include <stdio.h>
18 #include <ctype.h>
19 #include <errno.h>
20 #include <syslog.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 
27 #include "pidentd.h"
28 
31 int request_timeout = 120; /* 2 minutes */
32 
33 int requests_max = 0;
37 
38 
39 static int
41  char *buf,
42  struct sockaddr_gen *remote_addr)
43 {
44  struct kernel *kp;
45  int local_port, remote_port;
46  socklen_t len;
47  char *cmd, *bp;
48 
49 
50  if (debug)
51  fprintf(stderr, "handle_request: fd#%d: '%s'\n", fd, buf);
52 
53  if (sscanf(buf, " %d , %d", &local_port, &remote_port) == 2)
54  {
55  if (local_port < 1 || local_port > 65535 ||
56  remote_port < 1 || remote_port > 65535)
57  {
58  send_error(fd,
59  local_port, remote_port,
60  "INVALID-PORT",
61  remote_addr);
62  return 0;
63  }
64 
65  kp = kernel_alloc();
66  kp->remote = *remote_addr;
67  SGPORT(kp->remote) = htons(remote_port);
68 
69  len = sizeof(kp->local);
70  if (s_getsockname(fd, (struct sockaddr *) &kp->local, &len) < 0)
71  {
72  syslog(LOG_ERR, "s_getsockname(%d): %m", fd);
73  kernel_free(kp);
74  return -1;
75  }
76 
77  SGPORT(kp->local) = htons(local_port);
78 
79  kernel_query(kp);
80 
81  if (debug)
82  {
83  fprintf(stderr, "kernel_query, status = %d\n", kp->status);
84  if (kp->status == 1)
85  {
86  if (kp->ruid != NO_UID)
87  fprintf(stderr, "\truid = %ld\n", (long) kp->ruid);
88  if (kp->euid != NO_UID)
89  fprintf(stderr, "\teuid = %ld\n", (long) kp->euid);
90  if (kp->pid != NO_PID)
91  fprintf(stderr, "\tpid = %ld\n", (long) kp->pid);
92  if (kp->cmd)
93  fprintf(stderr, "\tcmd = %s\n", kp->cmd);
94  if (kp->argv)
95  fprintf(stderr, "\targv = %s\n", kp->argv);
96  }
97  }
98 
99  switch (kp->status)
100  {
101  case 1:
102  send_result(fd, kp);
103  break;
104 
105  case 0:
106  send_error(fd,
107  local_port, remote_port,
108  "NO-USER",
109  remote_addr);
110  break;
111 
112  default:
113  send_error(fd,
114  local_port, remote_port,
115  "UNKNOWN-ERROR",
116  remote_addr);
117  }
118 
119  kernel_free(kp);
120  return 0;
121  }
122 
123  if (extensions_enabled)
124  {
125  cmd = s_strtok_r(buf, " ", &bp);
126  if (cmd == NULL)
127  goto Fail;
128 
129  if (strcasecmp("version", cmd) == 0)
130  {
131  send_version(fd, remote_addr);
132  return 0;
133  }
134 
135  if (strcasecmp("quit", cmd) == 0)
136  return -1;
137  }
138 
139  Fail:
140  send_error(fd, 0, 0, "UNKNOWN-ERROR", remote_addr);
141  return -1;
142 }
143 
144 
145 static void
146 timeout_handler(void *arg)
147 {
148  struct request *rp = (struct request *) arg;
149 
150  if (debug)
151  fprintf(stderr, "timeout_handler(%08lx)\n", (unsigned long) arg);
152 
153  if (rp != NULL)
154  shutdown(rp->fd, 2);
155 }
156 
157 
158 
159 void *
160 request_thread(void *vp)
161 {
162  struct request *rp = (struct request *) vp;
163  struct timeout *tp = NULL;
164  char buf[1024];
165  size_t len;
166  ssize_t got, pos;
167 
168 
169 
170  if (debug)
171  fprintf(stderr, "request_thread: fd#%d: start\n", rp->fd);
172 
173  len = 0;
174  pos = 0;
175  if (request_timeout > 0)
177 
178  do
179  {
180  if (len >= sizeof(buf)-1)
181  {
182  syslog(LOG_NOTICE,
183  "request_thread: fd #%d: input buffer full: closing down",
184  rp->fd);
185  goto Exit;
186  }
187 
188  got = s_read(rp->fd, buf+len, sizeof(buf)-len-1);
189  if (got < 0)
190  {
191  syslog(LOG_ERR, "request_thread: read(%d, ..., %d) failed: %m",
192  rp->fd, sizeof(buf)-len-1);
193  goto Exit;
194  }
195 
196  if (got == 0)
197  {
198  if (debug)
199  fprintf(stderr, "s_read(%d, ...): returned 0\n", rp->fd);
200  goto Exit;
201  }
202 
203  len += got;
204 
205  /* Locate end of request line */
206  while (pos < len && !(buf[pos] == '\n' || buf[pos] == '\r'))
207  ++pos;
208 
209  if (pos < len || got == 0)
210  {
211  if (got > 0 || pos > 0)
212  {
213  buf[pos] = '\0';
214  if (handle_request(rp->fd, buf, &rp->addr) != 0)
215  goto Exit;
216 
217  if (!multiquery_enabled)
218  goto Exit;
219 
220  if (tp)
222 
223  ++pos; /* Skip NUL */
224  }
225 
226  /* Skip any additional SPC/CR/LF characters */
227  while (pos < len && isspace((unsigned char) buf[pos]))
228  ++pos;
229  if (pos < len)
230  memcpy(buf, buf+pos, len-pos);
231  len = pos = (len-pos);
232  }
233  } while (got > 0);
234 
235  Exit:
236  if (tp)
237  timeout_cancel(tp);
238 
239  if (debug)
240  fprintf(stderr, "request_thread: fd#%d: terminating\n", rp->fd);
241 
242  s_close(rp->fd);
243  s_free(rp);
244 
245  if (requests_max > 0)
246  {
248  if (requests_cur == requests_max)
250 
251  requests_cur--;
253  }
254  return NULL;
255 }
256 
257 
258 
259 
260 int
261 request_run(int fd, int nofork)
262 {
263  struct request *rip;
264  pthread_t tid;
265 
266 
267  rip = s_malloc(sizeof(*rip));
268  rip->fd = fd;
269 
270  rip->addr_len = sizeof(rip->addr);
271  if (s_getpeername(fd, (struct sockaddr *) &rip->addr, &rip->addr_len) < 0)
272  {
273  syslog(LOG_ERR, "s_getpeername(%d): %m", fd);
274  s_free(rip);
275  close(fd);
276  return EXIT_FAILURE;
277  }
278 
279  if (nofork)
280  {
281  request_thread(rip);
282  return EXIT_SUCCESS;
283  }
284  else
285  {
286  if (requests_max > 0)
287  {
289  while (requests_cur >= requests_max)
291 
292  requests_cur++;
294  }
295 
296  if (pthread_create(&tid,
298  &request_thread, (void *) rip) < 0)
299  {
300  syslog(LOG_ERR, "pthread_create(request_thread) failed: %m");
301  return EXIT_FAILURE;
302  }
303  }
304 
305  return EXIT_SUCCESS;
306 }
307 
308 
309 int
311 {
314  requests_cur = 0;
315 
316  return 0;
317 }
SGPORT
#define SGPORT(sag)
Definition: sockaddr.h:57
s_getsockname
int s_getsockname(int fd, struct sockaddr *sin, socklen_t *len)
Definition: safeio.c:199
s_free
void s_free(void *p)
Definition: safeio.c:153
pthread_mutex_init
int pthread_mutex_init(pthread_mutex_t *, pthread_mutexattr_t)
send_version
void send_version(int fd, struct sockaddr_in *remote_addr)
Definition: send.c:167
extensions_enabled
int extensions_enabled
Definition: request.c:29
pthread_cond_init
int pthread_cond_init(pthread_cond_t *, pthread_condattr_t)
requests_mtx
int requests_mtx
Definition: request.c:35
kernel_query
void kernel_query(struct kernel *kp)
Definition: kernel.c:189
send_result
void send_result(int fd, struct kernel *kp)
Definition: send.c:86
request_timeout
int request_timeout
Definition: request.c:31
kernel_free
void kernel_free(struct kernel *kp)
Definition: kernel.c:70
pthread_create
int pthread_create(pthread_t *, pthread_attr_t, void *(*)(void *), void *)
requests_cv
int requests_cv
Definition: request.c:36
pidentd.h
kernel::remote
struct sockaddr_gen remote
Definition: kernel.h:29
request_run
int request_run(int fd, int nofork)
Definition: request.c:261
request_init
int request_init(void)
Definition: request.c:310
kernel::local
struct sockaddr_gen local
Definition: kernel.h:28
timeout_create
struct timeout * timeout_create(int timeout, void(*fun)(void *arg), void *arg)
Definition: timeout.c:255
NO_UID
#define NO_UID
Definition: pidentd.h:55
s_close
int s_close(int fd)
Definition: safeio.c:113
timeout
Definition: timeout.h:21
s_malloc
void * s_malloc(size_t size)
Definition: safeio.c:132
s_getpeername
int s_getpeername(int fd, struct sockaddr *sin, socklen_t *len)
Definition: safeio.c:214
request
Definition: request.h:21
request::addr
struct sockaddr_gen addr
Definition: request.h:24
pthread_cond_wait
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *)
s_strtok_r
char * s_strtok_r(char *s, const char *d, char **bp)
Definition: support.c:106
kernel_alloc
struct kernel * kernel_alloc(void)
Definition: kernel.c:49
kernel::euid
uid_t euid
Definition: kernel.h:35
debug
int debug
Definition: gen_osinfo.c:23
timeout_cancel
int timeout_cancel(struct timeout *tp)
Definition: timeout.c:280
kernel::ruid
uid_t ruid
Definition: kernel.h:36
NO_PID
#define NO_PID
Definition: pidentd.h:52
multiquery_enabled
int multiquery_enabled
Definition: request.c:30
cma_t_handle
Definition: hp_pthread.h:26
request_thread
void * request_thread(void *vp)
Definition: request.c:160
sockaddr_gen
#define sockaddr_gen
Definition: sockaddr.h:53
pthread_mutex_unlock
int pthread_mutex_unlock(pthread_mutex_t *)
kernel::pid
pid_t pid
Definition: kernel.h:38
kernel::cmd
char * cmd
Definition: kernel.h:39
pthread_mutex_lock
int pthread_mutex_lock(pthread_mutex_t *)
timeout_reset
int timeout_reset(struct timeout *tp, int timeout)
Definition: timeout.c:271
s_read
ssize_t s_read(int fd, char *buf, size_t len)
Definition: safeio.c:98
handle_request
static int handle_request(int fd, char *buf, struct sockaddr_in *remote_addr)
Definition: request.c:40
kernel::argv
char * argv
Definition: kernel.h:40
timeout_handler
static void timeout_handler(void *arg)
Definition: request.c:146
kernel::status
int status
Definition: kernel.h:34
request::fd
int fd
Definition: request.h:23
cattr_detached
int cattr_detached
Definition: main.c:47
request::addr_len
socklen_t addr_len
Definition: request.h:25
pthread_cond_signal
int pthread_cond_signal(pthread_cond_t *)
send_error
void send_error(int fd, int l_port, int r_port, const char *what, struct sockaddr_in *remote_addr)
Definition: send.c:63
EXIT_SUCCESS
#define EXIT_SUCCESS
Definition: system.h:40
requests_max
int requests_max
Definition: request.c:33
kernel
Definition: kernel.h:25
EXIT_FAILURE
#define EXIT_FAILURE
Definition: system.h:44
requests_cur
int requests_cur
Definition: request.c:34