xref: /aosp_15_r20/external/mtools/floppyd_installtest.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1 /*  Copyright 1999 Peter Schlaile.
2  *  Copyright 1999-2002,2006,2007,2009 Alain Knaff.
3  *  This file is part of mtools.
4  *
5  *  Mtools is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  Mtools 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.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Small install-test utility to check if a floppyd-server is running on the
19  * X-Server-Host.
20  *
21  * written by:
22  *
23  * Peter Schlaile
24  *
25  * [email protected]
26  *
27  */
28 
29 #include "sysincludes.h"
30 #include "stream.h"
31 #include "mtools.h"
32 #include "msdos.h"
33 #include "scsi.h"
34 #include "floppyd_io.h"
35 
36 #ifdef USE_FLOPPYD
37 #include <sys/socket.h>
38 #include <arpa/inet.h>
39 #include <netdb.h>
40 
41 /* ######################################################################## */
42 
43 static const char* AuthErrors[] = {
44 	"Auth success!",
45 	"Auth failed: Packet oversized!",
46 	"Auth failed: X-Cookie doesn't match!",
47 	"Auth failed: Wrong transmission protocol version!",
48 	"Auth failed: Device locked!"
49 };
50 
51 #include "byte_dword.h"
52 #include "read_dword.h"
53 
write_dword(int handle,Dword parm)54 static int write_dword(int handle, Dword parm)
55 {
56 	Byte val[4];
57 
58 	dword2byte(parm, val);
59 
60 	if(write(handle, val, 4) < 4)
61 		return -1;
62 	return 0;
63 }
64 
65 
66 /* ######################################################################## */
67 
authenticate_to_floppyd(char fullauth,int sock,char * display,uint32_t protoversion)68 static uint32_t authenticate_to_floppyd(char fullauth, int sock, char *display,
69 					uint32_t protoversion)
70 {
71 	uint32_t filelen=0;
72 	Byte buf[16];
73 	const char *command[] = { "xauth", "xauth", "extract", "-", 0, 0 };
74 	char *xcookie = NULL;
75 	Dword errcode;
76 	uint32_t bytesRead;
77 	uint32_t cap=0;
78 
79 	if (fullauth) {
80 		command[4] = display;
81 
82 		filelen=(uint32_t)strlen(display);
83 		filelen += 100;
84 
85 		xcookie = (char *) safe_malloc(filelen+4);
86 		filelen = (uint32_t) safePopenOut(command, xcookie+4, filelen);
87 		if(filelen < 1)
88 		    return AUTH_AUTHFAILED;
89 	}
90 	dword2byte(4,buf);
91 	dword2byte(protoversion,buf+4);
92 	if(write(sock, buf, 8) < 8)
93 		return AUTH_IO_ERROR;
94 
95 	bytesRead = read_dword(sock);
96 
97 	if (bytesRead != 4 && bytesRead != 12) {
98 		return AUTH_WRONGVERSION;
99 	}
100 
101 
102 	errcode = read_dword(sock);
103 
104 	if (errcode != AUTH_SUCCESS) {
105 		return errcode;
106 	}
107 
108 	protoversion = FLOPPYD_PROTOCOL_VERSION_OLD;
109 	if(bytesRead >= 12) {
110 	    protoversion = read_dword(sock);
111 	    cap = read_dword(sock);
112 	}
113 
114 	fprintf(stderr, "Protocol Version=%d\n", protoversion);
115 	if(protoversion >= FLOPPYD_PROTOCOL_VERSION) {
116 	  fprintf(stderr, "Capabilities:%s%s\n",
117 		  (cap & FLOPPYD_CAP_EXPLICIT_OPEN) ? " ExplicitOpen" : "",
118 		  (cap & FLOPPYD_CAP_LARGE_SEEK) ? " LargeFiles" : "");
119 	}
120 
121 	if (fullauth) {
122 		dword2byte(filelen, (Byte *) xcookie);
123 		if(write(sock, xcookie, filelen+4) < (ssize_t)(filelen+4))
124 			return AUTH_IO_ERROR;
125 
126 		if (read_dword(sock) != 4) {
127 			return AUTH_PACKETOVERSIZE;
128 		}
129 
130 		errcode = read_dword(sock);
131 	}
132 
133 	return errcode;
134 
135 }
136 
137 
138 /* ######################################################################## */
139 
get_host_and_port(const char * name,char ** hostname,char ** display,uint16_t * port)140 static int get_host_and_port(const char* name, char** hostname, char **display,
141 			     uint16_t* port)
142 {
143 	char* newname = strdup(name);
144 	char* p;
145 	char* p2;
146 
147 	p = newname;
148 	while (*p != '/' && *p) p++;
149 	p2 = p;
150 	if (*p) p++;
151 	*p2 = 0;
152 
153 	*port = atou16(p);
154 	if (*port == 0) {
155 		*port = FLOPPYD_DEFAULT_PORT;
156 	}
157 
158 	*display = strdup(newname);
159 
160 	p = newname;
161 	while (*p != ':' && *p) p++;
162 	p2 = p;
163 	if (*p) p++;
164 	*p2 = 0;
165 
166 	*port += atoi(p);  /* add display number to the port */
167 
168 	if (!*newname || strcmp(newname, "unix") == 0) {
169 		free(newname);
170 		newname = strdup("localhost");
171 	}
172 
173 	*hostname = newname;
174 	return 1;
175 }
176 
177 /*
178  *  * Return the IP address of the specified host.
179  *  */
getipaddress(char * ipaddr)180 static in_addr_t getipaddress(char *ipaddr)
181 {
182 
183 	struct hostent  *host;
184 	in_addr_t        ip;
185 
186 	if (((ip = inet_addr(ipaddr)) == INADDR_NONE) &&
187 	    (strcmp(ipaddr, "255.255.255.255") != 0)) {
188 
189 		if ((host = gethostbyname(ipaddr)) != NULL) {
190 			memcpy(&ip, host->h_addr, sizeof(ip));
191 		}
192 
193 		endhostent();
194 	}
195 
196 #ifdef DEBUG
197 	fprintf(stderr, "IP lookup %s -> 0x%08lx\n", ipaddr, ip);
198 #endif
199 
200 	return (ip);
201 }
202 
203 /*
204  *  * Connect to the floppyd server.
205  *  */
connect_to_server(in_addr_t ip,uint16_t port)206 static int connect_to_server(in_addr_t ip, uint16_t port)
207 {
208 
209 	struct sockaddr_in      addr;
210 	int                     sock;
211 
212 	/*
213 	 * Allocate a socket.
214 	 */
215 	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
216 		return (-1);
217 	}
218 
219 	/*
220 	 * Set the address to connect to.
221 	 */
222 
223 	addr.sin_family = AF_INET;
224 	addr.sin_port = htons(port);
225 	addr.sin_addr.s_addr = ip;
226 
227         /*
228 	 * Connect our socket to the above address.
229 	 */
230 	if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
231 		return (-1);
232 	}
233 
234         /*
235 	 * Set the keepalive socket option to on.
236 	 */
237 	{
238 		int             on = 1;
239 		setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
240 			   (char *)&on, sizeof(on));
241 
242 	}
243 
244 	return (sock);
245 }
246 
main(int argc,char ** argv)247 int main (int argc, char** argv)
248 {
249 	char* hostname;
250 	char* display;
251 	char* name;
252 	uint16_t port;
253 	int sock;
254 	uint32_t reply;
255 	int rval;
256 	uint32_t protoversion;
257 	char fullauth = 0;
258 	Byte opcode = OP_CLOSE;
259 
260         if (argc < 2) {
261 	       puts("Usage: floppyd_installtest [-f] Connect-String\n"
262 		    "-f\tDo full X-Cookie-Authentication");
263 	       return -1;
264 	}
265 
266 	name = argv[1];
267 	if (strcmp(name, "-f") == 0) {
268 		fullauth = 1;
269 		name = argv[2];
270 	}
271 
272 	rval = get_host_and_port(name, &hostname, &display, &port);
273 
274 	if (!rval) return -1;
275 
276 	sock = connect_to_server(getipaddress(hostname), port);
277 
278 	if (sock == -1) {
279 		fprintf(stderr,
280 			"Can't connect to floppyd server on %s, port %i!\n",
281 			hostname, port);
282 		return -1;
283 	}
284 
285 	protoversion = FLOPPYD_PROTOCOL_VERSION;
286 	while(1) {
287 	    reply = authenticate_to_floppyd(fullauth, sock, display,
288 					    protoversion);
289 	    if(protoversion == FLOPPYD_PROTOCOL_VERSION_OLD)
290 		break;
291 	    if(reply == AUTH_WRONGVERSION) {
292 		/* fall back on old version */
293 		protoversion = FLOPPYD_PROTOCOL_VERSION_OLD;
294 		continue;
295 	    }
296 	    break;
297 	}
298 
299 	if (reply != 0) {
300 		fprintf(stderr,
301 			"Connection to floppyd failed:\n"
302 			"%s\n", AuthErrors[reply]);
303 		return -1;
304 	}
305 
306 	free(hostname);
307 	free(display);
308 
309 	if(write_dword(sock, 1) < 0) {
310 		fprintf(stderr,
311 			"Short write to floppyd:\n"
312 			"%s\n", strerror(errno));
313 	}
314 
315 	if(write(sock, &opcode, 1) < 0) {
316 		fprintf(stderr,
317 			"Short write to floppyd:\n"
318 			"%s\n", strerror(errno));
319 	}
320 
321 	close(sock);
322 
323 	return 0;
324 }
325 #endif
326