1 /*
2 ** id_parse.c                    Receive and parse a reply from an IDENT server
3 **
4 ** Author: Peter Eriksson <pen@lysator.liu.se>
5 ** Fiddling: P�r Emanuelsson <pell@lysator.liu.se>
6 */
7 
8 #if HAVE_CONFIG_H
9 # include "config.h"
10 #endif
11 
12 #include <stdio.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <ctype.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #if HAVE_SYS_TYPES_H
19 # include <sys/types.h>
20 #endif
21 #if HAVE_UNISTD_H
22 # include <unistd.h>
23 #endif
24 #if HAVE_SYS_SELECT_H
25 # include <sys/select.h>
26 #else
27 # if HAVE_SYS_TIME_H
28 #  include <sys/time.h>
29 # endif
30 #endif
31 
32 #define IN_LIBIDENT_SRC
33 #include "ident.h"
34 
35 
id_parse(ident_t * id,struct timeval * timeout,int * lport,int * fport,char ** identifier,char ** opsys,char ** charset)36 int id_parse (ident_t *id, struct timeval *timeout, int *lport, int *fport,
37 		char **identifier, char **opsys, char **charset)
38 {
39     char c, *cp, *tmp_charset;
40     fd_set rs;
41     int pos, res=0, lp, fp;
42 
43     errno = 0;
44 
45     tmp_charset = 0;
46 
47     if (!id)
48 	return -1;
49     if (lport)
50 	*lport = 0;
51     if (fport)
52 	*fport = 0;
53     if (identifier)
54 	*identifier = 0;
55     if (opsys)
56 	*opsys = 0;
57     if (charset)
58 	*charset = 0;
59 
60     pos = strlen(id->buf);
61 
62     if (timeout)
63     {
64 	FD_ZERO(&rs);
65 	FD_SET(id->fd, &rs);
66 
67 	res = select(FD_SETSIZE, &rs, NULL, NULL, timeout);
68 	if (res < 0)
69 	    return -1;
70 
71 	if (res == 0)
72 	{
73 	    errno = ETIMEDOUT;
74 	    return -1;
75 	}
76     }
77 
78     /* Every octal value is allowed except 0, \n and \r */
79     while (pos < sizeof(id->buf) &&
80 	   (res = read(id->fd, id->buf + pos, 1)) == 1 &&
81 	   id->buf[pos] != '\n' && id->buf[pos] != '\r')
82 	pos++;
83 
84     if (res < 0)
85 	return -1;
86 
87     if (res == 0)
88     {
89 	errno = ENOTCONN;
90 	return -1;
91     }
92 
93     if (id->buf[pos] != '\n' && id->buf[pos] != '\r')
94 	return 0;		/* Not properly terminated string */
95 
96     id->buf[pos++] = '\0';
97 
98     /*
99     ** Get first field (<lport> , <fport>)
100     */
101     cp = id_strtok(id->buf, ":", &c);
102     if (!cp)
103 	return -2;
104 
105     if (sscanf(cp, " %d , %d", &lp, &fp) != 2)
106     {
107 	if (identifier)
108 	{
109 	    *identifier = id_strdup(cp);
110 	    if (*identifier == NULL)
111 	        return -4;
112 	}
113 	return -2;
114     }
115 
116     if (lport)
117 	*lport = lp;
118     if (fport)
119 	*fport = fp;
120 
121     /*
122     ** Get second field (USERID or ERROR)
123     */
124     cp = id_strtok((char *)0, ":", &c);
125     if (!cp)
126 	return -2;
127 
128     if (strcmp(cp, "ERROR") == 0)
129     {
130 	cp = id_strtok((char *)0, "\n\r", &c);
131 	if (!cp)
132 	    return -2;
133 
134 	if (identifier)
135 	{
136 	    *identifier = id_strdup(cp);
137 	    if (*identifier == NULL)
138 	        return -4;
139 	}
140 
141 	return 2;
142     }
143     else if (strcmp(cp, "USERID") == 0)
144     {
145 	/*
146 	** Get first subfield of third field <opsys>
147 	*/
148 	cp = id_strtok((char *) 0, ",:", &c);
149 	if (!cp)
150 	    return -2;
151 
152 	if (opsys)
153 	{
154 	    *opsys = id_strdup(cp);
155 	    if (*opsys == NULL)
156 	        return -4;
157 	}
158 
159 	/*
160 	** We have a second subfield (<charset>)
161 	*/
162 	if (c == ',')
163 	{
164 	    cp = id_strtok((char *)0, ":", &c);
165 	    if (!cp)
166 		return -2;
167 
168 	    tmp_charset = cp;
169 	    if (charset)
170 	    {
171 		*charset = id_strdup(cp);
172 		if (*charset == NULL)
173 		    return -4;
174 	    }
175 
176 	    /*
177 	    ** We have even more subfields - ignore them
178 	    */
179 	    if (c == ',')
180 		id_strtok((char *)0, ":", &c);
181 	}
182 
183 	if (tmp_charset && strcmp(tmp_charset, "OCTET") == 0)
184 	    cp = id_strtok((char *)0, (char *)0, &c);
185 	else
186 	    cp = id_strtok((char *)0, "\n\r", &c);
187 
188 	if (identifier && cp)
189 	{
190 	    *identifier = id_strdup(cp);
191 	    if (*identifier == NULL)
192 	        return -4;
193 	}
194 	return 1;
195     }
196     else
197     {
198 	if (identifier)
199 	{
200 	    *identifier = id_strdup(cp);
201 	    if (*identifier == NULL)
202 	        return -4;
203 	}
204 	return -3;
205     }
206 }
207