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