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)  

support.c
Go to the documentation of this file.
1 /*
2 ** support.c - Miscellaneous support functions.
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 <string.h>
20 #include <errno.h>
21 #include <syslog.h>
22 #include <pwd.h>
23 
24 #include <sys/types.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 
28 #include "pidentd.h"
29 
30 #ifdef HAVE_UNAME
31 #include <sys/utsname.h>
32 #endif
33 
34 
35 /*
36 ** Get the OS name and version number
37 */
38 char *
39 osinfo_get(char *buf)
40 {
41 #ifdef HAVE_UNAME
42  struct utsname ub;
43 
44  if (uname(&ub) < 0)
45  return NULL;
46 #ifndef _AIX
47  sprintf(buf, "%s %s", ub.sysname, ub.release);
48 #else
49  sprintf(buf, "%s %s.%s", ub.sysname, ub.version, ub.release);
50 #endif
51 #else
52  strcpy(buf, "<unknown>");
53 #endif
54 
55  return buf;
56 }
57 
58 
59 
60 /*
61 ** Classify what type of socket the file descript "fd" is
62 */
63 int
64 socktype(int fd)
65 {
66  struct sockaddr_in remote_sin, local_sin;
67  socklen_t len;
68  int code;
69 
70 
71  /* Try to get the local socket adress and port number */
72  len = sizeof(local_sin);
73  code = getsockname(fd, (struct sockaddr *) &local_sin, &len);
74  if (code < 0)
75  {
76  if (errno == ENOTSOCK || errno == EINVAL)
77  /* Not a TCP/IP socket */
78  return SOCKTYPE_NOTSOCKET;
79  else
80  return -1;
81  }
82 
83 
84  /* Try to get the remote socket adress and port number */
85  len = sizeof(remote_sin);
86  code = getpeername(fd, (struct sockaddr *) &remote_sin, &len);
87  if (code < 0)
88  {
89  if (errno == ENOTCONN)
90  /* Locally bound TCP socket, awaiting connections */
91  return SOCKTYPE_LISTEN;
92  else
93  return -1;
94  }
95 
96  /* Established TCP connection */
97  return SOCKTYPE_CONNECTED;
98 }
99 
100 
101 
102 /*
103 ** A slightly safer strtok_r() function
104 */
105 char *
106 s_strtok_r(char *s, const char *d, char **bp)
107 {
108  char *cp;
109 
110 
111  if (d == NULL || bp == NULL)
112  return NULL;
113 
114  if (s == NULL)
115  s = *bp;
116 
117  if (s == NULL)
118  return NULL;
119 
120  s += strspn(s, d);
121  if (*s == '\0')
122  return NULL;
123 
124  cp = s;
125  s = strpbrk(cp, d);
126  if (s == NULL)
127  *bp = strchr(cp, 0);
128  else
129  {
130  *s++ = '\0';
131  *bp = s;
132  }
133 
134  return cp;
135 }
136 
137 
138 
139 
140 #if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R)
143 
144 static void
146 {
148 }
149 
150 static char *
151 strcopy(const char *str, char **buf, size_t *avail)
152 {
153  char *start;
154  size_t len;
155 
156 
157  if (str == NULL)
158  return NULL;
159 
160  len = strlen(str)+1;
161  if (len > *avail)
162  return NULL;
163 
164  start = *buf;
165 
166  memcpy(*buf, str, len);
167  *avail -= len;
168  *buf += len;
169 
170  return start;
171 }
172 #endif
173 
174 
175 int
176 s_getpwnam_r(const char *name,
177  struct passwd *pwd,
178  char *buffer, size_t bufsize,
179  struct passwd **result)
180 {
181 #ifdef HAVE_GETPWNAM_R
182  int code;
183 
184 
185  memset(pwd, 0, sizeof(*pwd));
186  memset(buffer, 0, bufsize);
187 
188 #ifdef HAVE_UI_GETPW /* Unix International / Solaris / UnixWare */
189 
190  while ((*result = getpwnam_r(name, pwd, buffer, bufsize)) == NULL &&
191  errno == EINTR)
192  ;
193 
194  if (*result == NULL)
195  code = errno;
196  else
197  code = 0;
198 
199 #elif HAVE_DCE_GETPW /* DCE/CMA */
200 
201  while ((code = getpwnam_r(name, pwd, buffer, bufsize)) != 0 &&
202  errno == EINTR)
203  ;
204  if (code == 0)
205  *result = pwd;
206  else
207  code = errno;
208 
209 #else /* Posix version */
210 
211  while ((code = getpwnam_r(name, pwd, buffer, bufsize, result)) == EINTR)
212  ;
213 
214 #endif
215 
216  return code;
217 
218 #else /* No reentrant getpw*_r calls available */
219 
220  struct passwd *pp;
221 
223 
225 
226  pp = getpwnam(name);
227  if (pp == NULL)
228  {
230  *result = NULL;
231  return -1;
232  }
233 
234  memset(pwd, 0, sizeof(*pwd));
235 
236  pwd->pw_name = strcopy(pp->pw_name, &buffer, &bufsize);
237  pwd->pw_passwd = strcopy(pp->pw_passwd, &buffer, &bufsize);
238  pwd->pw_uid = pp->pw_uid;
239  pwd->pw_gid = pp->pw_gid;
240  pwd->pw_gecos = strcopy(pp->pw_gecos, &buffer, &bufsize);
241  pwd->pw_dir = strcopy(pp->pw_dir, &buffer, &bufsize);
242  pwd->pw_shell = strcopy(pp->pw_shell, &buffer, &bufsize);
243 
244  *result = pwd;
245 
247  return 0;
248 #endif
249 }
250 
251 
252 
253 int
254 s_getpwuid_r(uid_t uid,
255  struct passwd *pwd,
256  char *buffer, size_t bufsize,
257  struct passwd **result)
258 {
259 #ifdef HAVE_GETPWUID_R
260  int code;
261 
262 
263  memset(pwd, 0, sizeof(*pwd));
264  memset(buffer, 0, bufsize);
265 
266 #ifdef HAVE_UI_GETPW /* Unix International / Solaris / UnixWare */
267 
268  while ((*result = getpwuid_r(uid, pwd, buffer, bufsize)) == NULL &&
269  errno == EINTR)
270  ;
271 
272  if (*result == NULL)
273  code = errno;
274  else
275  code = 0;
276 
277 #elif HAVE_DCE_GETPW /* DCE/CMA */
278 
279  while ((code = getpwuid_r(uid, pwd, buffer, bufsize)) != 0 &&
280  errno == EINTR)
281  ;
282  if (code == 0)
283  *result = pwd;
284  else
285  code = errno;
286 
287 #else /* Posix version */
288 
289  while ((code = getpwuid_r(uid, pwd, buffer, bufsize, result)) == EINTR)
290  ;
291 
292 #endif
293 
294  return code;
295 
296 #else
297  struct passwd *pp;
298 
301 
302  pp = getpwuid(uid);
303  if (pp == NULL)
304  {
306 
307  *result = NULL;
308  return -1;
309  }
310 
311  memset(pwd, 0, sizeof(*pwd));
312 
313  pwd->pw_name = strcopy(pp->pw_name, &buffer, &bufsize);
314  pwd->pw_passwd = strcopy(pp->pw_passwd, &buffer, &bufsize);
315  pwd->pw_uid = pp->pw_uid;
316  pwd->pw_gid = pp->pw_gid;
317  pwd->pw_gecos = strcopy(pp->pw_gecos, &buffer, &bufsize);
318  pwd->pw_dir = strcopy(pp->pw_dir, &buffer, &bufsize);
319  pwd->pw_shell = strcopy(pp->pw_shell, &buffer, &bufsize);
320 
321  *result = pwd;
322 
324 
325  return 0;
326 #endif
327 }
328 
329 
330 
331 int
332 s_strcasecmp(const char *s1, const char *s2)
333 {
334  int i;
335 
336  while ((i = (*s1 - *s2)) == 0 && *s1)
337  {
338  ++s1;
339  ++s2;
340  }
341 
342  return i;
343 }
344 
345 
346 
347 void
348 s_openlog(const char *ident, int logopt, int facility)
349 {
350  openlog(ident, logopt
351 #ifdef LOG_DAEMON
352  , facility
353 #endif
354  );
355 }
356 
357 
358 #ifdef LOG_KERN
359 static struct logfacname
360 {
361  const char *name;
362  int code;
363 } facility[] =
364 {
365  { "kern", LOG_KERN },
366  { "user", LOG_USER },
367  { "mail", LOG_MAIL },
368  { "daemon", LOG_DAEMON },
369  { "auth", LOG_AUTH },
370  { "syslog", LOG_SYSLOG },
371  { "lpr", LOG_LPR },
372 #ifdef LOG_NEWS
373  { "news", LOG_NEWS },
374 #endif
375 #ifdef LOG_UUCP
376  { "uucp", LOG_UUCP },
377 #endif
378 #ifdef LOG_CRON
379  { "cron", LOG_CRON },
380 #endif
381  { "local0", LOG_LOCAL0 },
382  { "local1", LOG_LOCAL1 },
383  { "local2", LOG_LOCAL2 },
384  { "local3", LOG_LOCAL3 },
385  { "local4", LOG_LOCAL4 },
386  { "local5", LOG_LOCAL5 },
387  { "local6", LOG_LOCAL6 },
388  { "local7", LOG_LOCAL7 },
389  { NULL, -1 }
390 };
391 
392 
393 int
394 syslog_str2fac(const char *name)
395 {
396  int i;
397 
398  if (name == NULL)
399  return -1;
400 
401  for (i = 0; facility[i].name != NULL &&
402  s_strcasecmp(facility[i].name, name) != 0; i++)
403  ;
404 
405  return facility[i].code;
406 }
407 
408 #else /* !LOG_KERN */
409 
410 int
411 syslog_str2fac(const char *name)
412 {
413  return 0;
414 }
415 #endif
416 
417 
418 #ifdef LOG_EMERG
419 static struct loglevname
420 {
421  const char *name;
422  int level;
423 } level[] =
424 {
425  { "emerg", LOG_EMERG },
426  { "alert", LOG_ALERT },
427  { "crit", LOG_CRIT },
428  { "err", LOG_ERR },
429  { "warning", LOG_WARNING },
430  { "notice", LOG_NOTICE },
431  { "info", LOG_INFO },
432  { "debug", LOG_DEBUG },
433 
434  { NULL, -1 }
435 };
436 
437 
438 int
439 syslog_str2lev(const char *name)
440 {
441  int i;
442 
443  if (name == NULL)
444  return -1;
445 
446  for (i = 0; level[i].name != NULL &&
447  s_strcasecmp(level[i].name, name) != 0; i++)
448  ;
449 
450  return level[i].level;
451 }
452 
453 #else /* !LOG_KERN */
454 
455 int
456 syslog_str2fac(const char *name)
457 {
458  return 0;
459 }
460 #endif
461 
462 
463 
464 /*
465 ** An MT-safe version of inet_ntoa() for IPv4/inet_ntop() for IPv6 (is safe)
466 */
467 const char *
469  char *buf,
470  size_t bufsize)
471 {
472 
473 #ifdef HAVE_IPV6
474  return inet_ntop(SGFAM(*ia), SGADDRP(*ia), buf, bufsize);
475 #else
476  unsigned char *bp;
477 
478  bp = (unsigned char *) SGADDRP(*ia);
479 
480  if (s_snprintf(buf, bufsize, "%u.%u.%u.%u", bp[0], bp[1], bp[2], bp[3]) < 0)
481  return NULL;
482 
483  return buf;
484 #endif
485 }
pwd_once
static int pwd_once
Definition: support.c:142
pthread_mutex_init
int pthread_mutex_init(pthread_mutex_t *, pthread_mutexattr_t)
pwd_lock_init
static void pwd_lock_init(void)
Definition: support.c:145
s_getpwnam_r
int s_getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
Definition: support.c:176
pthread_once
int pthread_once(pthread_once_t *, void(*)(void))
s_snprintf
int s_snprintf(char *buf, size_t bufsize, const char *format,...)
Definition: safeio.c:269
SOCKTYPE_CONNECTED
#define SOCKTYPE_CONNECTED
Definition: support.h:24
strcopy
static char * strcopy(const char *str, char **buf, size_t *avail)
Definition: support.c:151
syslog_str2fac
int syslog_str2fac(const char *name)
Definition: support.c:411
pidentd.h
socktype
int socktype(int fd)
Definition: support.c:64
PTHREAD_ONCE_INIT
#define PTHREAD_ONCE_INIT
Definition: cma_thr.h:56
s_strcasecmp
int s_strcasecmp(const char *s1, const char *s2)
Definition: support.c:332
pwd_lock
static int pwd_lock
Definition: support.c:141
s_strtok_r
char * s_strtok_r(char *s, const char *d, char **bp)
Definition: support.c:106
osinfo_get
char * osinfo_get(char *buf)
Definition: support.c:39
cma_t_handle
Definition: hp_pthread.h:26
sockaddr_gen
#define sockaddr_gen
Definition: sockaddr.h:53
SOCKTYPE_LISTEN
#define SOCKTYPE_LISTEN
Definition: support.h:23
SGFAM
#define SGFAM(sag)
Definition: sockaddr.h:54
pthread_mutex_unlock
int pthread_mutex_unlock(pthread_mutex_t *)
pthread_mutex_lock
int pthread_mutex_lock(pthread_mutex_t *)
s_inet_ntox
const char * s_inet_ntox(struct sockaddr_in *ia, char *buf, size_t bufsize)
Definition: support.c:468
SGADDRP
#define SGADDRP(sag)
Definition: sockaddr.h:58
syslog_str2lev
int syslog_str2lev(const char *name)
SOCKTYPE_NOTSOCKET
#define SOCKTYPE_NOTSOCKET
Definition: support.h:22
pthread_once_t
Definition: hp_pthread.h:41
s_openlog
void s_openlog(const char *ident, int logopt, int facility)
Definition: support.c:348
s_getpwuid_r
int s_getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
Definition: support.c:254
errno
#define errno
Definition: hp_pthread.h:23