1 1.1 agc /*- 2 1.1 agc * Copyright (c) 1998-2004 Dag-Erling Codan Smrgrav 3 1.1 agc * All rights reserved. 4 1.1 agc * 5 1.1 agc * Redistribution and use in source and binary forms, with or without 6 1.1 agc * modification, are permitted provided that the following conditions 7 1.1 agc * are met: 8 1.1 agc * 1. Redistributions of source code must retain the above copyright 9 1.1 agc * notice, this list of conditions and the following disclaimer 10 1.1 agc * in this position and unchanged. 11 1.1 agc * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 agc * notice, this list of conditions and the following disclaimer in the 13 1.1 agc * documentation and/or other materials provided with the distribution. 14 1.1 agc * 3. The name of the author may not be used to endorse or promote products 15 1.1 agc * derived from this software without specific prior written permission 16 1.1 agc * 17 1.1 agc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.1 agc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 1.1 agc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.1 agc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 1.1 agc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 1.1 agc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 1.1 agc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 1.1 agc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 1.1 agc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 1.1 agc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 agc */ 28 1.1 agc 29 1.1 agc #include "free2net.h" 30 1.1 agc 31 1.1 agc #include <sys/cdefs.h> 32 1.1 agc __FBSDID("$FreeBSD: src/lib/libfetch/common.c,v 1.48.4.2 2006/11/11 00:16:07 des Exp $"); 33 1.1 agc 34 1.1 agc #include <sys/param.h> 35 1.1 agc #include <sys/socket.h> 36 1.1 agc #include <sys/time.h> 37 1.1 agc #include <sys/uio.h> 38 1.1 agc #include <netinet/in.h> 39 1.1 agc 40 1.1 agc #include <errno.h> 41 1.1 agc #include <netdb.h> 42 1.1 agc #include <pwd.h> 43 1.1 agc #include <stdarg.h> 44 1.1 agc #include <stdlib.h> 45 1.1 agc #include <stdio.h> 46 1.1 agc #include <string.h> 47 1.1 agc #include <unistd.h> 48 1.1 agc 49 1.1 agc #include "fetch.h" 50 1.1 agc #include "common.h" 51 1.1 agc 52 1.1 agc 53 1.1 agc /*** Local data **************************************************************/ 54 1.1 agc 55 1.1 agc /* 56 1.1 agc * Error messages for resolver errors 57 1.1 agc */ 58 1.1 agc static struct fetcherr _netdb_errlist[] = { 59 1.1 agc #ifdef EAI_NODATA 60 1.1 agc { EAI_NODATA, FETCH_RESOLV, "Host not found" }, 61 1.1 agc #endif 62 1.1 agc { EAI_AGAIN, FETCH_TEMP, "Transient resolver failure" }, 63 1.1 agc { EAI_FAIL, FETCH_RESOLV, "Non-recoverable resolver failure" }, 64 1.1 agc { EAI_NONAME, FETCH_RESOLV, "No address record" }, 65 1.1 agc { -1, FETCH_UNKNOWN, "Unknown resolver error" } 66 1.1 agc }; 67 1.1 agc 68 1.1 agc /* End-of-Line */ 69 1.1 agc static const char ENDL[2] = "\r\n"; 70 1.1 agc 71 1.1 agc 72 1.1 agc /*** Error-reporting functions ***********************************************/ 73 1.1 agc 74 1.1 agc /* 75 1.1 agc * Map error code to string 76 1.1 agc */ 77 1.1 agc static struct fetcherr * 78 1.1 agc _fetch_finderr(struct fetcherr *p, int e) 79 1.1 agc { 80 1.1 agc while (p->num != -1 && p->num != e) 81 1.1 agc p++; 82 1.1 agc return (p); 83 1.1 agc } 84 1.1 agc 85 1.1 agc /* 86 1.1 agc * Set error code 87 1.1 agc */ 88 1.1 agc void 89 1.1 agc _fetch_seterr(struct fetcherr *p, int e) 90 1.1 agc { 91 1.1 agc p = _fetch_finderr(p, e); 92 1.1 agc fetchLastErrCode = p->cat; 93 1.1 agc snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string); 94 1.1 agc } 95 1.1 agc 96 1.1 agc /* 97 1.1 agc * Set error code according to errno 98 1.1 agc */ 99 1.1 agc void 100 1.1 agc _fetch_syserr(void) 101 1.1 agc { 102 1.1 agc switch (errno) { 103 1.1 agc case 0: 104 1.1 agc fetchLastErrCode = FETCH_OK; 105 1.1 agc break; 106 1.1 agc case EPERM: 107 1.1 agc case EACCES: 108 1.1 agc case EROFS: 109 1.1 agc case EAUTH: 110 1.1 agc case ENEEDAUTH: 111 1.1 agc fetchLastErrCode = FETCH_AUTH; 112 1.1 agc break; 113 1.1 agc case ENOENT: 114 1.1 agc case EISDIR: /* XXX */ 115 1.1 agc fetchLastErrCode = FETCH_UNAVAIL; 116 1.1 agc break; 117 1.1 agc case ENOMEM: 118 1.1 agc fetchLastErrCode = FETCH_MEMORY; 119 1.1 agc break; 120 1.1 agc case EBUSY: 121 1.1 agc case EAGAIN: 122 1.1 agc fetchLastErrCode = FETCH_TEMP; 123 1.1 agc break; 124 1.1 agc case EEXIST: 125 1.1 agc fetchLastErrCode = FETCH_EXISTS; 126 1.1 agc break; 127 1.1 agc case ENOSPC: 128 1.1 agc fetchLastErrCode = FETCH_FULL; 129 1.1 agc break; 130 1.1 agc case EADDRINUSE: 131 1.1 agc case EADDRNOTAVAIL: 132 1.1 agc case ENETDOWN: 133 1.1 agc case ENETUNREACH: 134 1.1 agc case ENETRESET: 135 1.1 agc case EHOSTUNREACH: 136 1.1 agc fetchLastErrCode = FETCH_NETWORK; 137 1.1 agc break; 138 1.1 agc case ECONNABORTED: 139 1.1 agc case ECONNRESET: 140 1.1 agc fetchLastErrCode = FETCH_ABORT; 141 1.1 agc break; 142 1.1 agc case ETIMEDOUT: 143 1.1 agc fetchLastErrCode = FETCH_TIMEOUT; 144 1.1 agc break; 145 1.1 agc case ECONNREFUSED: 146 1.1 agc case EHOSTDOWN: 147 1.1 agc fetchLastErrCode = FETCH_DOWN; 148 1.1 agc break; 149 1.1 agc default: 150 1.1 agc fetchLastErrCode = FETCH_UNKNOWN; 151 1.1 agc } 152 1.1 agc snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno)); 153 1.1 agc } 154 1.1 agc 155 1.1 agc 156 1.1 agc /* 157 1.1 agc * Emit status message 158 1.1 agc */ 159 1.1 agc void 160 1.1 agc _fetch_info(const char *fmt, ...) 161 1.1 agc { 162 1.1 agc va_list ap; 163 1.1 agc 164 1.1 agc va_start(ap, fmt); 165 1.1 agc vfprintf(stderr, fmt, ap); 166 1.1 agc va_end(ap); 167 1.1 agc fputc('\n', stderr); 168 1.1 agc } 169 1.1 agc 170 1.1 agc 171 1.1 agc /*** Network-related utility functions ***************************************/ 172 1.1 agc 173 1.1 agc /* 174 1.1 agc * Return the default port for a scheme 175 1.1 agc */ 176 1.1 agc int 177 1.1 agc _fetch_default_port(const char *scheme) 178 1.1 agc { 179 1.1 agc struct servent *se; 180 1.1 agc 181 1.1 agc if ((se = getservbyname(scheme, "tcp")) != NULL) 182 1.1 agc return (ntohs(se->s_port)); 183 1.1 agc if (strcasecmp(scheme, SCHEME_FTP) == 0) 184 1.1 agc return (FTP_DEFAULT_PORT); 185 1.1 agc if (strcasecmp(scheme, SCHEME_HTTP) == 0) 186 1.1 agc return (HTTP_DEFAULT_PORT); 187 1.1 agc return (0); 188 1.1 agc } 189 1.1 agc 190 1.1 agc /* 191 1.1 agc * Return the default proxy port for a scheme 192 1.1 agc */ 193 1.1 agc int 194 1.1 agc _fetch_default_proxy_port(const char *scheme) 195 1.1 agc { 196 1.1 agc if (strcasecmp(scheme, SCHEME_FTP) == 0) 197 1.1 agc return (FTP_DEFAULT_PROXY_PORT); 198 1.1 agc if (strcasecmp(scheme, SCHEME_HTTP) == 0) 199 1.1 agc return (HTTP_DEFAULT_PROXY_PORT); 200 1.1 agc return (0); 201 1.1 agc } 202 1.1 agc 203 1.1 agc 204 1.1 agc /* 205 1.1 agc * Create a connection for an existing descriptor. 206 1.1 agc */ 207 1.1 agc conn_t * 208 1.1 agc _fetch_reopen(int sd) 209 1.1 agc { 210 1.1 agc conn_t *conn; 211 1.1 agc 212 1.1 agc /* allocate and fill connection structure */ 213 1.1 agc if ((conn = calloc(1, sizeof(*conn))) == NULL) 214 1.1 agc return (NULL); 215 1.1 agc conn->sd = sd; 216 1.1 agc ++conn->ref; 217 1.1 agc return (conn); 218 1.1 agc } 219 1.1 agc 220 1.1 agc 221 1.1 agc /* 222 1.1 agc * Bump a connection's reference count. 223 1.1 agc */ 224 1.1 agc conn_t * 225 1.1 agc _fetch_ref(conn_t *conn) 226 1.1 agc { 227 1.1 agc 228 1.1 agc ++conn->ref; 229 1.1 agc return (conn); 230 1.1 agc } 231 1.1 agc 232 1.1 agc 233 1.1 agc /* 234 1.1 agc * Bind a socket to a specific local address 235 1.1 agc */ 236 1.1 agc int 237 1.1 agc _fetch_bind(int sd, int af, const char *addr) 238 1.1 agc { 239 1.1 agc struct addrinfo hints, *res, *res0; 240 1.1 agc 241 1.1 agc memset(&hints, 0, sizeof(hints)); 242 1.1 agc hints.ai_family = af; 243 1.1 agc hints.ai_socktype = SOCK_STREAM; 244 1.1 agc hints.ai_protocol = 0; 245 1.1 agc if (getaddrinfo(addr, NULL, &hints, &res0) != 0) 246 1.1 agc return (-1); 247 1.1 agc for (res = res0; res; res = res->ai_next) 248 1.1 agc if (bind(sd, res->ai_addr, res->ai_addrlen) == 0) 249 1.1 agc return (0); 250 1.1 agc return (-1); 251 1.1 agc } 252 1.1 agc 253 1.1 agc 254 1.1 agc /* 255 1.1 agc * Establish a TCP connection to the specified port on the specified host. 256 1.1 agc */ 257 1.1 agc conn_t * 258 1.1 agc _fetch_connect(const char *host, int port, int af, int verbose) 259 1.1 agc { 260 1.1 agc conn_t *conn; 261 1.1 agc char pbuf[10]; 262 1.1 agc const char *bindaddr; 263 1.1 agc struct addrinfo hints, *res, *res0; 264 1.1 agc int sd, err; 265 1.1 agc 266 1.1 agc DEBUG(fprintf(stderr, "---> %s:%d\n", host, port)); 267 1.1 agc 268 1.1 agc if (verbose) 269 1.1 agc _fetch_info("looking up %s", host); 270 1.1 agc 271 1.1 agc /* look up host name and set up socket address structure */ 272 1.1 agc snprintf(pbuf, sizeof(pbuf), "%d", port); 273 1.1 agc memset(&hints, 0, sizeof(hints)); 274 1.1 agc hints.ai_family = af; 275 1.1 agc hints.ai_socktype = SOCK_STREAM; 276 1.1 agc hints.ai_protocol = 0; 277 1.1 agc if ((err = getaddrinfo(host, pbuf, &hints, &res0)) != 0) { 278 1.1 agc _netdb_seterr(err); 279 1.1 agc return (NULL); 280 1.1 agc } 281 1.1 agc bindaddr = getenv("FETCH_BIND_ADDRESS"); 282 1.1 agc 283 1.1 agc if (verbose) 284 1.1 agc _fetch_info("connecting to %s:%d", host, port); 285 1.1 agc 286 1.1 agc /* try to connect */ 287 1.1 agc for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) { 288 1.1 agc if ((sd = socket(res->ai_family, res->ai_socktype, 289 1.1 agc res->ai_protocol)) == -1) 290 1.1 agc continue; 291 1.1 agc if (bindaddr != NULL && *bindaddr != '\0' && 292 1.1 agc _fetch_bind(sd, res->ai_family, bindaddr) != 0) { 293 1.1 agc _fetch_info("failed to bind to '%s'", bindaddr); 294 1.1 agc close(sd); 295 1.1 agc continue; 296 1.1 agc } 297 1.1 agc if (connect(sd, res->ai_addr, res->ai_addrlen) == 0) 298 1.1 agc break; 299 1.1 agc close(sd); 300 1.1 agc } 301 1.1 agc freeaddrinfo(res0); 302 1.1 agc if (sd == -1) { 303 1.1 agc _fetch_syserr(); 304 1.1 agc return (NULL); 305 1.1 agc } 306 1.1 agc 307 1.1 agc if ((conn = _fetch_reopen(sd)) == NULL) { 308 1.1 agc _fetch_syserr(); 309 1.1 agc close(sd); 310 1.1 agc } 311 1.1 agc return (conn); 312 1.1 agc } 313 1.1 agc 314 1.1 agc 315 1.1 agc /* 316 1.1 agc * Enable SSL on a connection. 317 1.1 agc */ 318 1.1 agc int 319 1.1 agc _fetch_ssl(conn_t *conn, int verbose) 320 1.1 agc { 321 1.1 agc 322 1.1 agc #ifdef WITH_SSL 323 1.1 agc /* Init the SSL library and context */ 324 1.1 agc if (!SSL_library_init()){ 325 1.1 agc fprintf(stderr, "SSL library init failed\n"); 326 1.1 agc return (-1); 327 1.1 agc } 328 1.1 agc 329 1.1 agc SSL_load_error_strings(); 330 1.1 agc 331 1.1 agc conn->ssl_meth = SSLv23_client_method(); 332 1.1 agc conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth); 333 1.1 agc SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY); 334 1.1 agc 335 1.1 agc conn->ssl = SSL_new(conn->ssl_ctx); 336 1.1 agc if (conn->ssl == NULL){ 337 1.1 agc fprintf(stderr, "SSL context creation failed\n"); 338 1.1 agc return (-1); 339 1.1 agc } 340 1.1 agc SSL_set_fd(conn->ssl, conn->sd); 341 1.1 agc if (SSL_connect(conn->ssl) == -1){ 342 1.1 agc ERR_print_errors_fp(stderr); 343 1.1 agc return (-1); 344 1.1 agc } 345 1.1 agc 346 1.1 agc if (verbose) { 347 1.1 agc X509_NAME *name; 348 1.1 agc char *str; 349 1.1 agc 350 1.1 agc fprintf(stderr, "SSL connection established using %s\n", 351 1.1 agc SSL_get_cipher(conn->ssl)); 352 1.1 agc conn->ssl_cert = SSL_get_peer_certificate(conn->ssl); 353 1.1 agc name = X509_get_subject_name(conn->ssl_cert); 354 1.1 agc str = X509_NAME_oneline(name, 0, 0); 355 1.1 agc printf("Certificate subject: %s\n", str); 356 1.1 agc free(str); 357 1.1 agc name = X509_get_issuer_name(conn->ssl_cert); 358 1.1 agc str = X509_NAME_oneline(name, 0, 0); 359 1.1 agc printf("Certificate issuer: %s\n", str); 360 1.1 agc free(str); 361 1.1 agc } 362 1.1 agc 363 1.1 agc return (0); 364 1.1 agc #else 365 1.1 agc /* LINTED */ 366 1.1 agc (void)conn; 367 1.1 agc /* LINTED */ 368 1.1 agc (void)verbose; 369 1.1 agc fprintf(stderr, "SSL support disabled\n"); 370 1.1 agc return (-1); 371 1.1 agc #endif 372 1.1 agc } 373 1.1 agc 374 1.1 agc 375 1.1 agc /* 376 1.1 agc * Read a character from a connection w/ timeout 377 1.1 agc */ 378 1.1 agc ssize_t 379 1.1 agc _fetch_read(conn_t *conn, char *buf, size_t len) 380 1.1 agc { 381 1.1 agc struct timeval now, timeout, wait; 382 1.1 agc fd_set readfds; 383 1.1 agc ssize_t rlen, total; 384 1.1 agc int r; 385 1.1 agc 386 1.1 agc if (fetchTimeout) { 387 1.1 agc FD_ZERO(&readfds); 388 1.1 agc gettimeofday(&timeout, NULL); 389 1.1 agc timeout.tv_sec += fetchTimeout; 390 1.1 agc } 391 1.1 agc 392 1.1 agc total = 0; 393 1.1 agc while (len > 0) { 394 1.1 agc while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) { 395 1.1 agc FD_SET(conn->sd, &readfds); 396 1.1 agc gettimeofday(&now, NULL); 397 1.1 agc wait.tv_sec = timeout.tv_sec - now.tv_sec; 398 1.1 agc wait.tv_usec = timeout.tv_usec - now.tv_usec; 399 1.1 agc if (wait.tv_usec < 0) { 400 1.1 agc wait.tv_usec += 1000000; 401 1.1 agc wait.tv_sec--; 402 1.1 agc } 403 1.1 agc if (wait.tv_sec < 0) { 404 1.1 agc errno = ETIMEDOUT; 405 1.1 agc _fetch_syserr(); 406 1.1 agc return (-1); 407 1.1 agc } 408 1.1 agc errno = 0; 409 1.1 agc r = select(conn->sd + 1, &readfds, NULL, NULL, &wait); 410 1.1 agc if (r == -1) { 411 1.1 agc if (errno == EINTR && fetchRestartCalls) 412 1.1 agc continue; 413 1.1 agc _fetch_syserr(); 414 1.1 agc return (-1); 415 1.1 agc } 416 1.1 agc } 417 1.1 agc #ifdef WITH_SSL 418 1.1 agc if (conn->ssl != NULL) 419 1.1 agc rlen = SSL_read(conn->ssl, buf, len); 420 1.1 agc else 421 1.1 agc #endif 422 1.1 agc rlen = read(conn->sd, buf, len); 423 1.1 agc if (rlen == 0) 424 1.1 agc break; 425 1.1 agc if (rlen < 0) { 426 1.1 agc if (errno == EINTR && fetchRestartCalls) 427 1.1 agc continue; 428 1.1 agc return (-1); 429 1.1 agc } 430 1.1 agc len -= rlen; 431 1.1 agc buf += rlen; 432 1.1 agc total += rlen; 433 1.1 agc } 434 1.1 agc return (total); 435 1.1 agc } 436 1.1 agc 437 1.1 agc 438 1.1 agc /* 439 1.1 agc * Read a line of text from a connection w/ timeout 440 1.1 agc */ 441 1.1 agc #define MIN_BUF_SIZE 1024 442 1.1 agc 443 1.1 agc int 444 1.1 agc _fetch_getln(conn_t *conn) 445 1.1 agc { 446 1.1 agc char *tmp; 447 1.1 agc size_t tmpsize; 448 1.1 agc ssize_t len; 449 1.1 agc char c; 450 1.1 agc 451 1.1 agc if (conn->buf == NULL) { 452 1.1 agc if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) { 453 1.1 agc errno = ENOMEM; 454 1.1 agc return (-1); 455 1.1 agc } 456 1.1 agc conn->bufsize = MIN_BUF_SIZE; 457 1.1 agc } 458 1.1 agc 459 1.1 agc conn->buf[0] = '\0'; 460 1.1 agc conn->buflen = 0; 461 1.1 agc 462 1.1 agc do { 463 1.1 agc len = _fetch_read(conn, &c, 1); 464 1.1 agc if (len == -1) 465 1.1 agc return (-1); 466 1.1 agc if (len == 0) 467 1.1 agc break; 468 1.1 agc conn->buf[conn->buflen++] = c; 469 1.1 agc if (conn->buflen == conn->bufsize) { 470 1.1 agc tmp = conn->buf; 471 1.1 agc tmpsize = conn->bufsize * 2 + 1; 472 1.1 agc if ((tmp = realloc(tmp, tmpsize)) == NULL) { 473 1.1 agc errno = ENOMEM; 474 1.1 agc return (-1); 475 1.1 agc } 476 1.1 agc conn->buf = tmp; 477 1.1 agc conn->bufsize = tmpsize; 478 1.1 agc } 479 1.1 agc } while (c != '\n'); 480 1.1 agc 481 1.1 agc conn->buf[conn->buflen] = '\0'; 482 1.1 agc DEBUG(fprintf(stderr, "<<< %s", conn->buf)); 483 1.1 agc return (0); 484 1.1 agc } 485 1.1 agc 486 1.1 agc 487 1.1 agc /* 488 1.1 agc * Write to a connection w/ timeout 489 1.1 agc */ 490 1.1 agc ssize_t 491 1.1 agc _fetch_write(conn_t *conn, const char *buf, size_t len) 492 1.1 agc { 493 1.1 agc struct iovec iov; 494 1.1 agc 495 1.1 agc iov.iov_base = __DECONST(char *, buf); 496 1.1 agc iov.iov_len = len; 497 1.1 agc return _fetch_writev(conn, &iov, 1); 498 1.1 agc } 499 1.1 agc 500 1.1 agc /* 501 1.1 agc * Write a vector to a connection w/ timeout 502 1.1 agc * Note: can modify the iovec. 503 1.1 agc */ 504 1.1 agc ssize_t 505 1.1 agc _fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt) 506 1.1 agc { 507 1.1 agc struct timeval now, timeout, wait; 508 1.1 agc fd_set writefds; 509 1.1 agc ssize_t wlen, total; 510 1.1 agc int r; 511 1.1 agc 512 1.1 agc if (fetchTimeout) { 513 1.1 agc FD_ZERO(&writefds); 514 1.1 agc gettimeofday(&timeout, NULL); 515 1.1 agc timeout.tv_sec += fetchTimeout; 516 1.1 agc } 517 1.1 agc 518 1.1 agc total = 0; 519 1.1 agc while (iovcnt > 0) { 520 1.1 agc while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) { 521 1.1 agc FD_SET(conn->sd, &writefds); 522 1.1 agc gettimeofday(&now, NULL); 523 1.1 agc wait.tv_sec = timeout.tv_sec - now.tv_sec; 524 1.1 agc wait.tv_usec = timeout.tv_usec - now.tv_usec; 525 1.1 agc if (wait.tv_usec < 0) { 526 1.1 agc wait.tv_usec += 1000000; 527 1.1 agc wait.tv_sec--; 528 1.1 agc } 529 1.1 agc if (wait.tv_sec < 0) { 530 1.1 agc errno = ETIMEDOUT; 531 1.1 agc _fetch_syserr(); 532 1.1 agc return (-1); 533 1.1 agc } 534 1.1 agc errno = 0; 535 1.1 agc r = select(conn->sd + 1, NULL, &writefds, NULL, &wait); 536 1.1 agc if (r == -1) { 537 1.1 agc if (errno == EINTR && fetchRestartCalls) 538 1.1 agc continue; 539 1.1 agc return (-1); 540 1.1 agc } 541 1.1 agc } 542 1.1 agc errno = 0; 543 1.1 agc #ifdef WITH_SSL 544 1.1 agc if (conn->ssl != NULL) 545 1.1 agc wlen = SSL_write(conn->ssl, 546 1.1 agc iov->iov_base, iov->iov_len); 547 1.1 agc else 548 1.1 agc #endif 549 1.1 agc wlen = writev(conn->sd, iov, iovcnt); 550 1.1 agc if (wlen == 0) { 551 1.1 agc /* we consider a short write a failure */ 552 1.1 agc errno = EPIPE; 553 1.1 agc _fetch_syserr(); 554 1.1 agc return (-1); 555 1.1 agc } 556 1.1 agc if (wlen < 0) { 557 1.1 agc if (errno == EINTR && fetchRestartCalls) 558 1.1 agc continue; 559 1.1 agc return (-1); 560 1.1 agc } 561 1.1 agc total += wlen; 562 1.1 agc while (iovcnt > 0 && wlen >= (ssize_t)iov->iov_len) { 563 1.1 agc wlen -= iov->iov_len; 564 1.1 agc iov++; 565 1.1 agc iovcnt--; 566 1.1 agc } 567 1.1 agc if (iovcnt > 0) { 568 1.1 agc iov->iov_len -= wlen; 569 1.2 agc iov->iov_base = (__DECONST(char *, iov->iov_base)) + wlen; 570 1.1 agc } 571 1.1 agc } 572 1.1 agc return (total); 573 1.1 agc } 574 1.1 agc 575 1.1 agc 576 1.1 agc /* 577 1.1 agc * Write a line of text to a connection w/ timeout 578 1.1 agc */ 579 1.1 agc int 580 1.1 agc _fetch_putln(conn_t *conn, const char *str, size_t len) 581 1.1 agc { 582 1.1 agc struct iovec iov[2]; 583 1.1 agc int ret; 584 1.1 agc 585 1.1 agc DEBUG(fprintf(stderr, ">>> %s\n", str)); 586 1.1 agc iov[0].iov_base = __DECONST(char *, str); 587 1.1 agc iov[0].iov_len = len; 588 1.1 agc iov[1].iov_base = __DECONST(char *, ENDL); 589 1.1 agc iov[1].iov_len = sizeof(ENDL); 590 1.1 agc if (len == 0) 591 1.1 agc ret = _fetch_writev(conn, &iov[1], 1); 592 1.1 agc else 593 1.1 agc ret = _fetch_writev(conn, iov, 2); 594 1.1 agc if (ret == -1) 595 1.1 agc return (-1); 596 1.1 agc return (0); 597 1.1 agc } 598 1.1 agc 599 1.1 agc 600 1.1 agc /* 601 1.1 agc * Close connection 602 1.1 agc */ 603 1.1 agc int 604 1.1 agc _fetch_close(conn_t *conn) 605 1.1 agc { 606 1.1 agc int ret; 607 1.1 agc 608 1.1 agc if (--conn->ref > 0) 609 1.1 agc return (0); 610 1.1 agc ret = close(conn->sd); 611 1.1 agc free(conn->buf); 612 1.1 agc free(conn); 613 1.1 agc return (ret); 614 1.1 agc } 615 1.1 agc 616 1.1 agc 617 1.1 agc /*** Directory-related utility functions *************************************/ 618 1.1 agc 619 1.1 agc int 620 1.1 agc _fetch_add_entry(struct url_ent **p, int *size, int *len, 621 1.1 agc const char *name, struct url_stat *us) 622 1.1 agc { 623 1.1 agc struct url_ent *tmp; 624 1.1 agc 625 1.1 agc if (*p == NULL) { 626 1.1 agc *size = 0; 627 1.1 agc *len = 0; 628 1.1 agc } 629 1.1 agc 630 1.1 agc if (*len >= *size - 1) { 631 1.1 agc tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p)); 632 1.1 agc if (tmp == NULL) { 633 1.1 agc errno = ENOMEM; 634 1.1 agc _fetch_syserr(); 635 1.1 agc return (-1); 636 1.1 agc } 637 1.1 agc *size = (*size * 2 + 1); 638 1.1 agc *p = tmp; 639 1.1 agc } 640 1.1 agc 641 1.1 agc tmp = *p + *len; 642 1.1 agc snprintf(tmp->name, PATH_MAX, "%s", name); 643 1.1 agc bcopy(us, &tmp->stat, sizeof(*us)); 644 1.1 agc 645 1.1 agc (*len)++; 646 1.1 agc (++tmp)->name[0] = 0; 647 1.1 agc 648 1.1 agc return (0); 649 1.1 agc } 650 1.1 agc 651 1.1 agc 652 1.1 agc /*** Authentication-related utility functions ********************************/ 653 1.1 agc 654 1.1 agc static const char * 655 1.1 agc _fetch_read_word(FILE *f) 656 1.1 agc { 657 1.1 agc static char word[1024]; 658 1.1 agc 659 1.1 agc if (fscanf(f, " %1024s ", word) != 1) 660 1.1 agc return (NULL); 661 1.1 agc return (word); 662 1.1 agc } 663 1.1 agc 664 1.1 agc /* 665 1.1 agc * Get authentication data for a URL from .netrc 666 1.1 agc */ 667 1.1 agc int 668 1.1 agc _fetch_netrc_auth(struct url *url) 669 1.1 agc { 670 1.1 agc char fn[PATH_MAX]; 671 1.1 agc const char *word; 672 1.1 agc char *p; 673 1.1 agc FILE *f; 674 1.1 agc 675 1.1 agc if ((p = getenv("NETRC")) != NULL) { 676 1.1 agc if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) { 677 1.1 agc _fetch_info("$NETRC specifies a file name " 678 1.1 agc "longer than PATH_MAX"); 679 1.1 agc return (-1); 680 1.1 agc } 681 1.1 agc } else { 682 1.1 agc if ((p = getenv("HOME")) != NULL) { 683 1.1 agc struct passwd *pwd; 684 1.1 agc 685 1.1 agc if ((pwd = getpwuid(getuid())) == NULL || 686 1.1 agc (p = pwd->pw_dir) == NULL) 687 1.1 agc return (-1); 688 1.1 agc } 689 1.1 agc if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn)) 690 1.1 agc return (-1); 691 1.1 agc } 692 1.1 agc 693 1.1 agc if ((f = fopen(fn, "r")) == NULL) 694 1.1 agc return (-1); 695 1.1 agc while ((word = _fetch_read_word(f)) != NULL) { 696 1.1 agc if (strcmp(word, "default") == 0) { 697 1.1 agc DEBUG(_fetch_info("Using default .netrc settings")); 698 1.1 agc break; 699 1.1 agc } 700 1.1 agc if (strcmp(word, "machine") == 0 && 701 1.1 agc (word = _fetch_read_word(f)) != NULL && 702 1.1 agc strcasecmp(word, url->host) == 0) { 703 1.1 agc DEBUG(_fetch_info("Using .netrc settings for %s", word)); 704 1.1 agc break; 705 1.1 agc } 706 1.1 agc } 707 1.1 agc if (word == NULL) 708 1.1 agc goto ferr; 709 1.1 agc while ((word = _fetch_read_word(f)) != NULL) { 710 1.1 agc if (strcmp(word, "login") == 0) { 711 1.1 agc if ((word = _fetch_read_word(f)) == NULL) 712 1.1 agc goto ferr; 713 1.1 agc if (snprintf(url->user, sizeof(url->user), 714 1.1 agc "%s", word) > (int)sizeof(url->user)) { 715 1.1 agc _fetch_info("login name in .netrc is too long"); 716 1.1 agc url->user[0] = '\0'; 717 1.1 agc } 718 1.1 agc } else if (strcmp(word, "password") == 0) { 719 1.1 agc if ((word = _fetch_read_word(f)) == NULL) 720 1.1 agc goto ferr; 721 1.1 agc if (snprintf(url->pwd, sizeof(url->pwd), 722 1.1 agc "%s", word) > (int)sizeof(url->pwd)) { 723 1.1 agc _fetch_info("password in .netrc is too long"); 724 1.1 agc url->pwd[0] = '\0'; 725 1.1 agc } 726 1.1 agc } else if (strcmp(word, "account") == 0) { 727 1.1 agc if ((word = _fetch_read_word(f)) == NULL) 728 1.1 agc goto ferr; 729 1.1 agc /* XXX not supported! */ 730 1.1 agc } else { 731 1.1 agc break; 732 1.1 agc } 733 1.1 agc } 734 1.1 agc fclose(f); 735 1.1 agc return (0); 736 1.1 agc ferr: 737 1.1 agc fclose(f); 738 1.1 agc return (-1); 739 1.1 agc } 740