1 /*
2 ** ident-tester.c           A small daemon that can be used to test Ident
3 **                          servers
4 **
5 ** Author: Peter Eriksson <pen@lysator.liu.se>, 10 Aug 1992
6 */
7 
8 #if HAVE_CONFIG_H
9 # include "config.h"
10 #endif
11 
12 #include <stdio.h>
13 #include <errno.h>
14 #if HAVE_SYS_TYPES_H
15 # include <sys/types.h>
16 #endif
17 #if HAVE_UNISTD_H
18 # include <unistd.h>
19 #endif
20 #if HAVE_NETDB_H
21 # include <netdb.h>
22 #endif
23 #if HAVE_SYS_SOCKET_H
24 # include <sys/socket.h>
25 #endif
26 #if HAVE_SYSLOG_H
27 # include <syslog.h>
28 #endif
29 
30 #define IN_LIBIDENT_SRC
31 #include "ident.h"
32 
33 /*
34 ** Lookups the name of the connecting host, or the IP number as a string.
35 ** buf should be at least NI_MAXHOST bytes-long.
36 */
gethost(const struct sockaddr * addr,socklen_t addrlen,char * buf)37 int gethost (const struct sockaddr *addr, socklen_t addrlen, char *buf)
38 {
39   return getnameinfo(addr, addrlen, buf, NI_MAXHOST, NULL, 0, 0);
40 }
41 
getport(const struct sockaddr * addr)42 int getport (const struct sockaddr *addr)
43 {
44   switch (addr->sa_family)
45   {
46     case AF_INET:
47       return ntohs(((struct sockaddr_in *)addr)->sin_port);
48 #ifdef AF_INET6
49     case AF_INET6:
50       return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
51 #endif
52   }
53   return -1;
54 }
55 
56 int
main(int argc,char * argv[])57 main (int argc, char *argv[])
58 {
59   struct sockaddr_storage laddr, faddr;
60   int len, res, lport, fport;
61   ident_t *id;
62   char *identifier, *opsys, *charset, hs[NI_MAXHOST];
63 
64 
65   printf("Welcome to the IDENT server tester, version 2.0\r\n");
66   printf("(Linked with libident %s)\r\n\r\n", id_version);
67 
68   fflush(stdout);
69 
70   len = sizeof(faddr);
71   if (getpeername(0, (struct sockaddr *) &faddr, &len))
72   {
73      perror("getpeername()");
74      return 1;
75   }
76 
77   len = sizeof(laddr);
78   if (getsockname(0, (struct sockaddr *) &laddr, &len))
79   {
80     perror("getsockname()");
81     return 1;
82   }
83 
84   res = gethost((struct sockaddr *)&faddr, sizeof(faddr), hs);
85   if (res == EAI_SYSTEM)
86   {
87     perror("getnameinfo()");
88     return 1;
89   }
90   else if (res != 0)
91   {
92     fprintf(stderr, "getnameinfo(): %s\r\n", gai_strerror (res));
93     return 1;
94   }
95 
96   printf("Connecting to Ident server at %s...\r\n", hs);
97   fflush(stdout);
98 
99 #ifdef LOG_LOCAL3
100   openlog("tidentd", 0, LOG_LOCAL3);
101 #else
102   openlog("tidentd", 0);
103 #endif
104 
105   id = id_open_addr((struct sockaddr *)&laddr, (struct sockaddr *)&faddr,
106 			NULL);
107   if (!id)
108   {
109       if (errno)
110       {
111 	  int saved_errno = errno;
112 
113 	  perror("Connection denied");
114 	  fflush(stderr);
115 
116 	  errno = saved_errno;
117 	  syslog(LOG_DEBUG, "Error: id_open_addr(): host=%s, error=%m", hs);
118       }
119       else
120 	  printf("Connection denied.\r\n");
121       return 0;
122   }
123 
124   fport = getport((struct sockaddr *)&faddr);
125   lport = getport((struct sockaddr *)&laddr);
126   printf("Querying for lport %d, fport %d....\r\n", lport, fport);
127   fflush(stdout);
128 
129   errno = 0;
130   if (id_query(id, fport, lport, 0) < 0)
131   {
132       if (errno)
133       {
134 	  int saved_errno = errno;
135 
136 	  perror("id_query()");
137 	  fflush(stderr);
138 
139 	  errno = saved_errno;
140 	  syslog(LOG_DEBUG, "Error: id_query(): host=%s, error=%m", hs);
141 
142       }
143       else
144 	  printf("Query failed.\r\n");
145 
146     return 0;
147   }
148 
149   printf("Reading response data...\r\n");
150   fflush(stdout);
151 
152   res = id_parse(id, NULL, &lport, &fport, &identifier, &opsys, &charset);
153 
154   switch (res)
155   {
156     default:
157 	if (errno)
158 	{
159 	    int saved_errno = errno;
160 
161 	    perror("id_parse()");
162 	    errno = saved_errno;
163 	    syslog(LOG_DEBUG, "Error: id_parse(): host=%s, error=%m", hs);
164 	}
165 	else
166 	    printf("Error: Invalid response (empty response?).\r\n");
167 	break;
168 
169     case -2:
170 	syslog(LOG_DEBUG, "Error: id_parse(): host=%s, Parse Error: %s", hs,
171 		   identifier ? identifier : "<no information available>");
172 	if (identifier)
173 	    printf("Parse error on reply:\r\n  \"%s\"\r\n", identifier);
174 	else
175 	    printf("Unidentifiable parse error on reply.\r\n");
176 	break;
177 
178     case -3:
179 	syslog(LOG_DEBUG, "Error: id_parse(): host=%s, Illegal reply type: %s",
180 		   hs, identifier);
181 	printf("Parse error in reply: Illegal reply type: %s\r\n", identifier);
182 	break;
183 
184     case 0:
185 	syslog(LOG_DEBUG, "Error: id_parse(): host=%s, NotReady", hs);
186 	printf("Not ready. This should not happen...\r\n");
187 	break;
188 
189     case 2:
190 	syslog(LOG_DEBUG, "Reply: Error: host=%s, error=%s", hs, identifier);
191 
192 	printf("Error response is:\r\n");
193 	printf("   Lport........ %d\r\n", lport);
194 	printf("   Fport........ %d\r\n", fport);
195 	printf("   Error........ %s\r\n", identifier);
196 	break;
197 
198     case 1:
199       if (charset)
200 	syslog(LOG_INFO,
201 	       "Reply: Userid: host=%s, opsys=%s, charset=%s, userid=%s",
202 	       hs, opsys, charset, identifier);
203       else
204 	syslog(LOG_INFO, "Reply: Userid: host=%s, opsys=%s, userid=%s",
205 	       hs, opsys, identifier);
206 
207       printf("Userid response is:\r\n");
208       printf("   Lport........ %d\r\n", lport);
209       printf("   Fport........ %d\r\n", fport);
210       printf("   Opsys........ %s\r\n", opsys);
211       printf("   Charset...... %s\r\n", charset ? charset : "<not specified>");
212       printf("   Identifier... %s\r\n", identifier);
213 
214       if (id_query(id, getport((struct sockaddr *)&faddr),
215                        getport((struct sockaddr *)&laddr), 0) >= 0)
216       {
217 	if (id_parse(id, NULL,
218 		     &lport, &fport,
219 		     &identifier,
220 		     &opsys,
221 		     &charset) == 1)
222 	  printf("   Multiquery... Enabled\r\n");
223       }
224   }
225 
226   fflush(stdout);
227   return 0;
228 }
229