1 /* 2 * Copyright (C) 2001, 2002, and 2003 Roy Keene 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * 18 * email: dact@rkeene.org 19 */ 20 21 22 /* 23 * Network related functions 24 */ 25 #include "dact.h" 26 #include "net.h" 27 #ifdef HAVE_SYS_TYPES_H 28 #include <sys/types.h> 29 #endif 30 #ifdef HAVE_SYS_STAT_H 31 #include <sys/stat.h> 32 #endif 33 #include <stdarg.h> 34 #ifdef HAVE_UNISTD_H 35 #include <unistd.h> 36 #endif 37 #include <fcntl.h> 38 39 #ifndef NO_NETWORK 40 #ifdef HAVE_SYS_SOCKET_H 41 #include <sys/socket.h> 42 #endif 43 #ifdef HAVE_NETINET_IN_H 44 #include <netinet/in.h> 45 #endif 46 #ifdef HAVE_ARPA_INET_H 47 #include <arpa/inet.h> 48 #endif 49 #ifdef HAVE_STDLIB_H 50 #include <stdlib.h> 51 #endif 52 #ifdef HAVE_STRING_H 53 #include <string.h> 54 #endif 55 #ifdef HAVE_NETDB_H 56 #include <netdb.h> 57 #endif 58 #ifdef HAVE_ERRNO_H 59 #include <errno.h> 60 #endif 61 #ifdef HAVE_STDIO_H 62 #include <stdio.h> 63 #endif 64 #ifdef HAVE_WINSOCK2_H 65 #include <winsock2.h> 66 #endif 67 #include "parse.h" 68 #include "crc.h" 69 70 #ifndef O_BINARY 71 #define O_BINARY 0x0 72 #endif 73 #ifndef S_IFSOCK 74 #define S_IFSOCK 0140000 75 #endif 76 77 78 struct dact_url_info { 79 char *url; 80 int flags; 81 mode_t mode; 82 }; 83 struct dact_url_info dact_urls[256]; 84 85 /* 86 * Create a listening port on tcp port PORT 87 */ 88 int createlisten(int port) 89 { 90 struct sockaddr_in localname; 91 int sockFd; 92 sockFd=socket(AF_INET,SOCK_STREAM,IPPROTO_IP); 93 localname.sin_family=AF_INET; 94 localname.sin_port=htons(port); 95 localname.sin_addr.s_addr=INADDR_ANY; 96 if (bind(sockFd,(struct sockaddr *) & localname,sizeof(localname))==-1) { perror("bind");return(-1); } 97 if (listen(sockFd,1024)==-1) { perror("listen"); return(-1); } 98 return(sockFd); 99 } 100 101 102 /* 103 * Close that socket, yeah. 104 */ 105 void closeconnection(int sockfd) { 106 shutdown(sockfd, 1); 107 close(sockfd); 108 } 109 110 int createconnection_tcp(char *host, int port) { 111 int sockid; 112 struct hostent *hostinfo; 113 struct sockaddr_in sock; 114 115 if (dact_nonetwork) return(-EPERM); 116 117 #ifdef HAVE_INET_ATON 118 if (!inet_aton(host,&sock.sin_addr)) { 119 #elif HAVE_INET_ADDR 120 if ( (sock.sin_addr.s_addr=inet_addr(host) )==-1) { 121 #else 122 { 123 #endif 124 if ((hostinfo=gethostbyname(host))==NULL) return(-EPERM); 125 memcpy(&sock.sin_addr.s_addr,hostinfo->h_addr_list[0],hostinfo->h_length); 126 } 127 128 sock.sin_family=AF_INET; 129 sock.sin_port=htons(port); 130 if ((sockid=socket(AF_INET, SOCK_STREAM, 0))<0) { 131 CHECKPOINT; 132 return(-EIO); 133 } 134 if (connect(sockid, (struct sockaddr *) &sock, sizeof(sock))<0) { 135 PERROR("connect"); 136 CHECKPOINT; 137 close(sockid); 138 return(-EIO); 139 } 140 CHECKPOINT; 141 return(sockid); 142 } 143 144 int open_net(const char *pathname, int flags, mode_t mode) { 145 char scheme[5], host[512], file[1024]; 146 char username[128], password[128]; 147 char *read_buf, *read_buf_s=NULL; 148 char *smallbuf, *tmpbuf; 149 int port, fd, x, ftpfd=-1, retrmode=0; 150 151 if (!parse_url(pathname,scheme,username,password,host,&port,file)) { 152 if ((fd=createconnection_tcp(host,port))<0) return(-1); 153 154 switch (ELFCRC(0, scheme, strlen(scheme))) { 155 case 457648: /* http */ 156 if ((flags&O_WRONLY)==O_WRONLY || (flags&O_RDWR)==O_RDWR) { 157 close(fd); 158 return(-1); 159 } 160 read_buf_s=read_buf=malloc(50); 161 write(fd, "GET ", 4); 162 write(fd, file, strlen(file)); 163 write(fd, " HTTP/1.0\nHost: ",16); 164 write(fd, host, strlen(host)); 165 write(fd, "\n", 1); 166 if (strcmp(username, "")) { 167 smallbuf=malloc(strlen(password)+strlen(username)+3); 168 smallbuf[0]=0; 169 strcat(smallbuf,username); 170 strcat(smallbuf,":"); 171 strcat(smallbuf,password); 172 tmpbuf=mime64(smallbuf); 173 write(fd, "Authorization: Basic ", 21); 174 write(fd, tmpbuf, strlen(tmpbuf)); 175 free(tmpbuf); 176 free(smallbuf); 177 write(fd, "\n", 1); 178 } 179 write(fd, "\n", 1); 180 x=read(fd, read_buf, 50); 181 strsep(&read_buf," "); 182 if (strncmp("200 ",read_buf,4) && strncmp("302 ",read_buf,4)) { 183 free(read_buf_s); 184 close(fd); 185 return(-ENOENT); 186 } 187 retrmode=read_buf[0]; 188 read_buf=read_buf_s; 189 read_buf[4]=0; 190 while (1) { 191 read(fd, read_buf, 1); 192 if (read_buf[0]==read_buf[2]&&read_buf[0]=='\n') break; 193 if (!strncmp(":noi", read_buf, 4) && retrmode=='3') { 194 tmpbuf=smallbuf=malloc(512); 195 read(fd, read_buf, 1); 196 read(fd, smallbuf, 510); 197 close(fd); 198 return(open_net(strsep(&smallbuf,"\r\n"),flags,mode)); 199 free(tmpbuf); 200 } 201 read_buf[3]=read_buf[2]; 202 read_buf[2]=read_buf[1]; 203 read_buf[1]=read_buf[0]; 204 } 205 206 free(read_buf_s); 207 208 if (dact_urls[fd].url!=NULL) free(dact_urls[fd].url); 209 dact_urls[fd].url=strdup(pathname); 210 dact_urls[fd].flags=flags; 211 dact_urls[fd].mode=mode; 212 return(fd); 213 break; 214 case 28080: /* ftp */ 215 if ((flags&O_RDWR)==O_RDWR) { 216 close(fd); 217 return(-1); 218 } 219 220 read_buf_s=read_buf=malloc(1024); 221 read_buf[0]=0; 222 223 while (1) { 224 if ((x=read(fd, read_buf, 1024))<1024) { 225 if (x<0) { 226 free(read_buf_s); 227 return(-EIO); 228 } 229 /* It's waiting for input... */ 230 } 231 read_buf[x]=0; 232 233 while ((smallbuf=strsep(&read_buf,"\n"))!=NULL) { 234 switch (ELFCRC(0, smallbuf, 4)) { 235 case 231456: /* 550 */ 236 if (ftpfd!=-1) close(ftpfd); 237 close(fd); 238 free(read_buf_s); 239 return(-ENOENT); 240 break; 241 case 230944: /* 530 */ 242 if (ftpfd!=-1) close(ftpfd); 243 close(fd); 244 free(read_buf_s); 245 return(-EIO); 246 break; 247 case 231504: /* 553 */ 248 if (ftpfd!=-1) close(ftpfd); 249 close(fd); 250 free(read_buf_s); 251 return(-EPERM); 252 break; 253 case 218400: /* 220 */ 254 write(fd, "USER ", 5); 255 if (strcmp(username,"")) { 256 write(fd, username, strlen(username)); 257 } else { 258 write(fd, "anonymous", 9); 259 } 260 write(fd, "\n", 1); 261 break; 262 case 222768: /* 331 */ 263 write(fd, "PASS ", 5); 264 if (strcmp(password,"")) { 265 write(fd, password, strlen(password)); 266 } else { 267 write(fd, "user@host.com", 13); 268 } 269 write(fd, "\n", 1); 270 break; 271 case 218512: /* 227 */ 272 strsep(&smallbuf,"("); 273 host[0]=0; 274 for (x=0;x<4;x++) { 275 strncat(host,strsep(&smallbuf,","),5); 276 strcat(host,"."); 277 } 278 host[strlen(host)-1]=0; 279 port=(atoi(strsep(&smallbuf,","))<<8)+atoi(strsep(&smallbuf,")\n\r ")); 280 write(fd, "TYPE I\n", 7); 281 break; 282 case 217888: 283 if ((flags&O_RDONLY)==O_RDONLY) write(fd,"RETR ",5); 284 if ((flags&O_WRONLY)==O_WRONLY) write(fd,"STOR ",5); 285 write(fd, file, strlen(file)); 286 write(fd, "\n", 1); 287 if ((ftpfd=createconnection_tcp(host,port))<0) { 288 close(fd); 289 return(-ENOENT); 290 } 291 break; 292 case 215072: /* 150 */ 293 if (dact_urls[ftpfd].url!=NULL) free(dact_urls[ftpfd].url); 294 dact_urls[ftpfd].url=strdup(pathname); 295 dact_urls[ftpfd].flags=flags; 296 dact_urls[ftpfd].mode=mode; 297 return(ftpfd); 298 break; 299 case 218656: /* 230 */ 300 write(fd, "PASV\n", 5); 301 break; 302 default: 303 #ifdef DEBUG_FTP 304 PRINT_LINE; fprintf(stderr, "dact: Unknown cmd %i (%s)\n",ELFCRC(0,smallbuf,4),smallbuf); 305 #endif 306 break; 307 } 308 } 309 read_buf=read_buf_s; 310 } 311 312 313 break; 314 } 315 316 free(read_buf_s); 317 close(fd); 318 } else { 319 fd=open(pathname,flags|O_BINARY,mode); 320 if (dact_urls[fd].url!=NULL) free(dact_urls[fd].url); 321 dact_urls[fd].url=strdup(pathname); 322 dact_urls[fd].flags=flags; 323 dact_urls[fd].mode=mode; 324 return(fd); 325 } 326 327 return(-1); 328 } 329 330 off_t lseek_net(int filedes, off_t offset, int whence) { 331 struct stat file_status; 332 int newfd; 333 334 fstat(filedes, &file_status); 335 if ((file_status.st_mode&S_IFSOCK)==S_IFSOCK) { 336 if (whence==SEEK_END) return(-1); 337 if (offset!=0 || whence!=SEEK_SET) return(-1); /* For now ... */ 338 if (dact_urls[filedes].url==NULL) return(-1); 339 if ((newfd=open_net(dact_urls[filedes].url,dact_urls[filedes].flags,dact_urls[filedes].mode))<0) return(-1); 340 close(filedes); 341 dup2(newfd,filedes); 342 return(0); 343 } 344 return(lseek(filedes,offset,whence)); 345 } 346 347 #else 348 #ifndef O_BINARY 349 #define O_BINARY 0x0 350 #endif 351 352 int createlisten(int port) { return(-1); } 353 void closeconnection(int sockfd) { return; } 354 int createconnection_tcp(char *host, int port) { return(-1); } 355 int open_net(const char *pathname, int flags, mode_t mode) { 356 return(open(pathname,flags|O_BINARY,mode)); 357 } 358 off_t lseek_net(int filedes, off_t offset, int whence) { 359 return(lseek(filedes,offset,whence)); 360 } 361 #endif |