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