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 * udbz@rz.uni-karlsruhe.de 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 "partition.h" 35#include "floppyd_io.h" 36 37#ifdef USE_FLOPPYD 38#include <sys/socket.h> 39#include <arpa/inet.h> 40#include <netdb.h> 41 42/* ######################################################################## */ 43 44typedef unsigned char Byte; 45typedef unsigned long Dword; 46 47const char* AuthErrors[] = { 48 "Auth success!", 49 "Auth failed: Packet oversized!", 50 "Auth failed: X-Cookie doesn't match!", 51 "Auth failed: Wrong transmission protocol version!", 52 "Auth failed: Device locked!" 53}; 54 55#include "byte_dword.h" 56#include "read_dword.h" 57 58static void write_dword(int handle, Dword parm) 59{ 60 Byte val[4]; 61 62 dword2byte(parm, val); 63 64 write(handle, val, 4); 65} 66 67 68/* ######################################################################## */ 69 70static int authenticate_to_floppyd(char fullauth, int sock, char *display, 71 int protoversion) 72{ 73 off_t filelen=0; 74 Byte buf[16]; 75 const char *command[] = { "xauth", "xauth", "extract", "-", 0, 0 }; 76 char *xcookie = NULL; 77 Dword errcode; 78 int bytesRead; 79 80 if (fullauth) { 81 command[4] = display; 82 83 filelen=strlen(display); 84 filelen += 100; 85 86 xcookie = (char *) safe_malloc(filelen+4); 87 filelen = safePopenOut(command, xcookie+4, filelen); 88 if(filelen < 1) 89 return AUTH_AUTHFAILED; 90 } 91 dword2byte(4,buf); 92 dword2byte(protoversion,buf+4); 93 write(sock, buf, 8); 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 109 if(bytesRead == 8) { 110 protoversion = read_dword(sock); 111 read_dword(sock); 112 } 113 114 fprintf(stderr, "Protocol Version=%d\n", protoversion); 115 116 if (fullauth) { 117 dword2byte(filelen, (Byte *) xcookie); 118 write(sock, xcookie, filelen+4); 119 120 if (read_dword(sock) != 4) { 121 return AUTH_PACKETOVERSIZE; 122 } 123 124 errcode = read_dword(sock); 125 } 126 127 return errcode; 128 129} 130 131 132/* ######################################################################## */ 133 134static int get_host_and_port(const char* name, char** hostname, char **display, 135 short* port) 136{ 137 char* newname = strdup(name); 138 char* p; 139 char* p2; 140 141 p = newname; 142 while (*p != '/' && *p) p++; 143 p2 = p; 144 if (*p) p++; 145 *p2 = 0; 146 147 *port = atoi(p); 148 if (*port == 0) { 149 *port = FLOPPYD_DEFAULT_PORT; 150 } 151 152 *display = strdup(newname); 153 154 p = newname; 155 while (*p != ':' && *p) p++; 156 p2 = p; 157 if (*p) p++; 158 *p2 = 0; 159 160 *port += atoi(p); /* add display number to the port */ 161 162 if (!*newname || strcmp(newname, "unix") == 0) { 163 free(newname); 164 newname = strdup("localhost"); 165 } 166 167 *hostname = newname; 168 return 1; 169} 170 171/* 172 * * Return the IP address of the specified host. 173 * */ 174static IPaddr_t getipaddress(char *ipaddr) 175{ 176 177 struct hostent *host; 178 IPaddr_t ip; 179 180 if (((ip = inet_addr(ipaddr)) == INADDR_NONE) && 181 (strcmp(ipaddr, "255.255.255.255") != 0)) { 182 183 if ((host = gethostbyname(ipaddr)) != NULL) { 184 memcpy(&ip, host->h_addr, sizeof(ip)); 185 } 186 187 endhostent(); 188 } 189 190#ifdef DEBUG 191 fprintf(stderr, "IP lookup %s -> 0x%08lx\n", ipaddr, ip); 192#endif 193 194 return (ip); 195} 196 197/* 198 * * Connect to the floppyd server. 199 * */ 200static int connect_to_server(IPaddr_t ip, short port) 201{ 202 203 struct sockaddr_in addr; 204 int sock; 205 206 /* 207 * Allocate a socket. 208 */ 209 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 210 return (-1); 211 } 212 213 /* 214 * Set the address to connect to. 215 */ 216 217 addr.sin_family = AF_INET; 218 addr.sin_port = htons(port); 219 addr.sin_addr.s_addr = ip; 220 221 /* 222 * Connect our socket to the above address. 223 */ 224 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 225 return (-1); 226 } 227 228 /* 229 * Set the keepalive socket option to on. 230 */ 231 { 232 int on = 1; 233 setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, 234 (char *)&on, sizeof(on)); 235 236 } 237 238 return (sock); 239} 240 241int main (int argc, char** argv) 242{ 243 char* hostname; 244 char* display; 245 char* name; 246 short port; 247 int sock; 248 int reply; 249 int rval; 250 int protoversion; 251 char fullauth = 0; 252 Byte opcode = OP_CLOSE; 253 254 if (argc < 2) { 255 puts("Usage: floppyd_installtest [-f] Connect-String\n" 256 "-f\tDo full X-Cookie-Authentication"); 257 return -1; 258 } 259 260 name = argv[1]; 261 if (strcmp(name, "-f") == 0) { 262 fullauth = 1; 263 name = argv[2]; 264 } 265 266 rval = get_host_and_port(name, &hostname, &display, &port); 267 268 if (!rval) return -1; 269 270 sock = connect_to_server(getipaddress(hostname), port); 271 272 if (sock == -1) { 273 fprintf(stderr, 274 "Can't connect to floppyd server on %s, port %i!\n", 275 hostname, port); 276 return -1; 277 } 278 279 protoversion = FLOPPYD_PROTOCOL_VERSION; 280 while(1) { 281 reply = authenticate_to_floppyd(fullauth, sock, display, 282 protoversion); 283 if(protoversion == FLOPPYD_PROTOCOL_VERSION_OLD) 284 break; 285 if(reply == AUTH_WRONGVERSION) { 286 /* fall back on old version */ 287 protoversion = FLOPPYD_PROTOCOL_VERSION_OLD; 288 continue; 289 } 290 break; 291 } 292 293 if (reply != 0) { 294 fprintf(stderr, 295 "Connection to floppyd failed:\n" 296 "%s\n", AuthErrors[reply]); 297 return -1; 298 } 299 300 free(hostname); 301 free(display); 302 303 write_dword(sock, 1); 304 write(sock, &opcode, 1); 305 306 close(sock); 307 308 return 0; 309} 310#endif 311