Back to index

avfs  1.0.1
socket.c
Go to the documentation of this file.
00001 /* 
00002    socket handling routines
00003    Copyright (C) 1998-2001, Joe Orton <joe@light.plus.com>, 
00004    except where otherwise indicated.
00005 
00006    Portions are:
00007    Copyright (C) 1999-2000 Tommi Komulainen <Tommi.Komulainen@iki.fi>
00008    Originally under GPL in Mutt, http://www.mutt.org/
00009    Relicensed under LGPL for neon, http://www.webdav.org/neon/
00010 
00011    This library is free software; you can redistribute it and/or
00012    modify it under the terms of the GNU Library General Public
00013    License as published by the Free Software Foundation; either
00014    version 2 of the License, or (at your option) any later version.
00015    
00016    This library is distributed in the hope that it will be useful,
00017    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019    Library General Public License for more details.
00020 
00021    You should have received a copy of the GNU Library General Public
00022    License along with this library; if not, write to the Free
00023    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00024    MA 02111-1307, USA
00025 
00026    The sock_readline() function is:
00027 
00028    Copyright (c) 1999 Eric S. Raymond
00029 
00030    Permission is hereby granted, free of charge, to any person
00031    obtaining a copy of this software and associated documentation
00032    files (the "Software"), to deal in the Software without
00033    restriction, including without limitation the rights to use, copy,
00034    modify, merge, publish, distribute, sublicense, and/or sell copies
00035    of the Software, and to permit persons to whom the Software is
00036    furnished to do so, subject to the following conditions:
00037 
00038    The above copyright notice and this permission notice shall be
00039    included in all copies or substantial portions of the Software.
00040 
00041    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00042    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00043    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00044    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00045    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00046    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00047    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00048    DEALINGS IN THE SOFTWARE.
00049 
00050 */
00051 
00052 #include "config.h"
00053 
00054 #include <sys/types.h>
00055 #ifdef HAVE_SYS_TIME_H
00056 #include <sys/time.h>
00057 #endif
00058 
00059 #ifdef WIN32
00060 #include <WinSock2.h>
00061 #else
00062 #include <sys/socket.h>
00063 #include <netinet/in.h>
00064 #include <netdb.h>
00065 #endif /* WIN32 */
00066 
00067 #ifdef HAVE_ARPA_INET_H
00068 #include <arpa/inet.h>
00069 #endif
00070 
00071 #include <sys/stat.h>
00072 
00073 #ifdef HAVE_SYS_SELECT_H
00074 #include <sys/select.h>
00075 #endif
00076 
00077 #include <errno.h>
00078 
00079 #include <fcntl.h>
00080 #include <stdio.h>
00081 #ifdef HAVE_STRING_H
00082 #include <string.h>
00083 #endif
00084 #ifdef HAVE_STRINGS_H
00085 #include <strings.h>
00086 #endif 
00087 #ifdef HAVE_STDLIB_H
00088 #include <stdlib.h>
00089 #endif /* HAVE_STDLIB_H */
00090 #ifdef HAVE_UNISTD_H
00091 #include <unistd.h>
00092 #endif /* HAVE_UNISTD_H */
00093 
00094 #include "neon_i18n.h"
00095 #include "string_utils.h"
00096 #include "http_utils.h"
00097 #include "nsocket.h"
00098 #include "ne_alloc.h"
00099 
00100 static sock_progress progress_cb = NULL;
00101 static sock_notify notify_cb = NULL;
00102 static void *progress_ud, *notify_ud;
00103 
00104 #if defined(BEOS_PRE_BONE)
00105 #define NEON_WRITE(a,b,c) send(a,b,c,0)
00106 #define NEON_READ(a,b,c) recv(a,b,c,0)
00107 #define NEON_CLOSE(s) closesocket(s)
00108 #elif defined(WIN32)
00109 #define NEON_WRITE(a,b,c) send(a,b,c,0)
00110 #define NEON_READ(a,b,c) recv(a,b,c,0)
00111 #define NEON_CLOSE(s) closesocket(s)
00112 #else /* really Unix! */
00113 #define NEON_WRITE(a,b,c) write(a,b,c)
00114 #define NEON_READ(a,b,c) read(a,b,c)
00115 #define NEON_CLOSE(s) close(s)
00116 #endif
00117 
00118 #ifdef ENABLE_SSL
00119 #include <openssl/ssl.h>
00120 #include <openssl/err.h>
00121 
00122 /* Whilst the OpenSSL interface *looks* like it is not thread-safe, it
00123  * appears to do horrible gymnastics to maintain per-thread global
00124  * variables for error reporting. UGH! */
00125 #define ERROR_SSL_STRING (ERR_reason_error_string(ERR_get_error()))
00126 
00127 #endif
00128 
00129 /* BeOS doesn't have fd==sockets on anything pre-bone, so see if
00130  * we need to drop back to our old ways... 
00131  */
00132 #ifdef __BEOS__
00133   #ifndef BONE_VERSION /* if we have BONE this isn't an issue... */
00134     #define BEOS_PRE_BONE
00135   #endif
00136 #endif
00137 
00138 struct nsocket_s {
00139     int fd;
00140     const char *error; /* Store error string here */
00141 #ifdef ENABLE_SSL
00142     SSL *ssl;
00143     SSL_CTX *default_ctx;
00144 #endif
00145 #ifdef BEOS_PRE_BONE
00146 #define MAX_PEEK_BUFFER 1024
00147     char peeked_bytes[MAX_PEEK_BUFFER];
00148     char *peeked_bytes_curpos;
00149     int peeked_bytes_avail;
00150 #endif
00151 };
00152 
00153 struct nssl_context_s {
00154 #ifdef ENABLE_SSL
00155     SSL_CTX *ctx;
00156 #endif
00157     nssl_accept cert_accept;
00158     void *accept_ud; /* userdata for callback */
00159 
00160     /* private key prompt callback */
00161     nssl_key_prompt key_prompt;
00162     void *key_userdata;
00163     const char *key_file;
00164 };
00165     
00166 void sock_register_progress(sock_progress cb, void *userdata)
00167 {
00168     progress_cb = cb;
00169     progress_ud = userdata;
00170 }
00171 
00172 void sock_register_notify(sock_notify cb, void *userdata)
00173 {
00174     notify_cb = cb;
00175     notify_ud = userdata;
00176 }
00177 
00178 void sock_call_progress(off_t progress, off_t total)
00179 {
00180     if (progress_cb) {
00181        (*progress_cb)(progress_ud, progress, total);
00182     }
00183 }
00184 
00185 int sock_init(void)
00186 {
00187 #ifdef WIN32
00188     WORD wVersionRequested;
00189     WSADATA wsaData;
00190     int err;
00191     
00192     wVersionRequested = MAKEWORD(2, 2);
00193     
00194     err = WSAStartup(wVersionRequested, &wsaData);
00195     if (err != 0)
00196        return -1;
00197 
00198 #endif
00199 
00200 #ifdef ENABLE_SSL
00201     SSL_load_error_strings();
00202     SSL_library_init();
00203 
00204     DEBUG(DEBUG_SOCKET, "Initialized SSL.\n");
00205 #endif
00206 
00207     return 0;
00208 }
00209 
00210 void sock_exit(void)
00211 {
00212 #ifdef WIN32
00213     WSACleanup();
00214 #endif 
00215 }
00216 
00217 /* sock_read is read() with a timeout of SOCKET_READ_TIMEOUT. */
00218 int sock_read(nsocket *sock, char *buffer, size_t count) 
00219 {
00220     int ret;
00221 
00222     if (count == 0) {
00223        DEBUG(DEBUG_SOCKET, "Passing 0 to sock_read is probably bad.\n");
00224        /* But follow normal read() semantics anyway... */
00225        return 0;
00226     }
00227 
00228     ret = sock_block(sock, SOCKET_READ_TIMEOUT);
00229     if (ret == 0) {
00230        /* Got data */
00231        do {
00232 #ifdef ENABLE_SSL
00233            if (sock->ssl) {
00234               ret = SSL_read(sock->ssl, buffer, count);
00235            } else {
00236 #endif
00237 #ifndef BEOS_PRE_BONE
00238               ret = NEON_READ(sock->fd, buffer, count);
00239 #else
00240               if (sock->peeked_bytes_avail > 0) {
00241                   /* simply return the peeked bytes.... */
00242                   if (count >= sock->peeked_bytes_avail){
00243                      /* we have room */
00244                      strncpy(buffer, sock->peeked_bytes_curpos, 
00245                             sock->peeked_bytes_avail);
00246                      ret = sock->peeked_bytes_avail;
00247                      sock->peeked_bytes_avail = 0;
00248                   } else {
00249                      strncpy(buffer, sock->peeked_bytes_curpos, count);
00250                      sock->peeked_bytes_curpos += count;
00251                      sock->peeked_bytes_avail -= count;
00252                      ret = count;
00253                   }
00254               } else {
00255                   ret = recv(sock->fd, buffer, count, 0);
00256               }
00257 #endif
00258 #ifdef ENABLE_SSL
00259            }
00260 #endif
00261        } while (ret == -1 && errno == EINTR);
00262        if (ret < 0) {
00263            sock->error = strerror(errno);
00264            ret = SOCK_ERROR;
00265        } else if (ret == 0) {
00266            /* This might not or might not be an error depending on
00267                the context. */
00268            sock->error = _("Connection was closed by server");
00269            DEBUG(DEBUG_SOCKET, "read returned zero.\n");
00270            ret = SOCK_CLOSED;
00271        }
00272     }
00273     return ret;
00274 }
00275 
00276 /* sock_peek is recv(...,MSG_PEEK) with a timeout of SOCKET_TIMEOUT.
00277  * Returns length of data read or SOCK_* on error */
00278 int sock_peek(nsocket *sock, char *buffer, size_t count) 
00279 {
00280     int ret;
00281     ret = sock_block(sock, SOCKET_READ_TIMEOUT);
00282     if (ret < 0) {
00283        return ret;
00284     }
00285     /* Got data */
00286 #ifdef ENABLE_SSL
00287     if (sock->ssl) {
00288        ret = SSL_peek(sock->ssl, buffer, count);
00289        /* TODO: This is the fetchmail fix as in sock_readline.
00290         * Do we really need it? */
00291        if (ret == 0) {
00292            if (sock->ssl->shutdown) {
00293               return SOCK_CLOSED;
00294            }
00295            if (0 != ERR_get_error()) {
00296               sock->error = ERROR_SSL_STRING;
00297               return SOCK_ERROR;
00298            }
00299        }
00300     } else {
00301 #endif
00302     do {
00303 #ifndef BEOS_PRE_BONE
00304        ret = recv(sock->fd, buffer, count, MSG_PEEK);
00305 #else /* we're on BeOS pre-BONE so we need to use the buffer... */
00306        if (sock->peeked_bytes_avail > 0) {
00307            /* we've got some from last time!!! */
00308            if (count >= sock->peeked_bytes_avail) {
00309               strncpy(buffer, sock->peeked_bytes_curpos, sock->peeked_bytes_avail);
00310               ret = sock->peeked_bytes_avail;
00311            } else {
00312               strncpy(buffer, sock->peeked_bytes_curpos, count);
00313               ret = count;
00314            }
00315        } else {
00316            if (count > MAX_PEEK_BUFFER)
00317               count = MAX_PEEK_BUFFER;
00318            ret = recv(sock->fd, buffer, count, 0);
00319            sock->peeked_bytes_avail = ret;
00320            strncpy(sock->peeked_bytes, buffer, ret);
00321            sock->peeked_bytes_curpos = sock->peeked_bytes;
00322        }
00323 #endif
00324     } while (ret == -1 && errno == EINTR);
00325 #ifdef ENABLE_SSL
00326     }
00327 #endif
00328     /* According to the Single Unix Spec, recv() will return
00329      * zero if the socket has been closed the other end. */
00330     if (ret == 0) {
00331        ret = SOCK_CLOSED;
00332     } else if (ret < 0) {
00333        sock->error = strerror(errno);
00334        ret = SOCK_ERROR;
00335     } 
00336     return ret;
00337 }
00338 
00339 /* Blocks waiting for read input on the given socket for the given time.
00340  * Returns:
00341  *    0 if data arrived
00342  *    SOCK_TIMEOUT if data did not arrive before timeout
00343  *    SOCK_ERROR on error
00344  */
00345 int sock_block(nsocket *sock, int timeout) 
00346 {
00347     struct timeval tv;
00348     fd_set fds;
00349     int ret;
00350 
00351 #ifdef ENABLE_SSL
00352     if (sock->ssl) {
00353        /* There may be data already available in the 
00354         * SSL buffers */
00355        if (SSL_pending(sock->ssl)) {
00356            return 0;
00357        }
00358        /* Otherwise, we should be able to select on
00359         * the socket as per normal. Probably? */
00360     }
00361 #endif
00362 #ifdef BEOS_PRE_BONE
00363     if (sock->peeked_bytes_avail > 0) {
00364         return 0;
00365     }
00366 #endif
00367 
00368     /* Init the fd set */
00369     FD_ZERO(&fds);
00370     FD_SET(sock->fd, &fds);
00371     /* Set the timeout */
00372     tv.tv_sec = timeout;
00373     tv.tv_usec = 0;
00374     do {
00375        ret = select(sock->fd+1, &fds, NULL, NULL, &tv);
00376     } while (ret == -1 && errno == EINTR);
00377 
00378     switch(ret) {
00379     case 0:
00380        return SOCK_TIMEOUT;
00381     case -1:
00382        sock->error = strerror(errno);
00383        return SOCK_ERROR;
00384     default:
00385        return 0;
00386     }
00387 }
00388 
00389 /* Send the given line down the socket with CRLF appended. 
00390  * Returns 0 on success or SOCK_* on failure. */
00391 int sock_sendline(nsocket *sock, const char *line) 
00392 {
00393     char *buffer;
00394     int ret;
00395     CONCAT2(buffer, line, "\r\n");
00396     ret = sock_send_string(sock, buffer);
00397     free(buffer);
00398     return ret;
00399 }
00400 
00401 int sock_readfile_blocked(nsocket *sock, off_t length,
00402                        sock_block_reader reader, void *userdata) 
00403 {
00404     char buffer[BUFSIZ];
00405     int ret;
00406     off_t done = 0;
00407     do {
00408        ret = sock_read(sock, buffer, BUFSIZ);
00409        if (ret < 0) {
00410            if (length == -1 && ret == SOCK_CLOSED) {
00411               /* Not an error condition. */
00412               return 0;
00413            }
00414            return ret;
00415        } 
00416        done += ret;
00417        sock_call_progress(done, length);
00418        (*reader)(userdata, buffer, ret);
00419     } while ((length == -1) || (done < length));
00420     return 0;
00421 }
00422 
00423 
00424 /* Send a block of data down the given fd.
00425  * Returns 0 on success or SOCK_* on failure */
00426 int sock_fullwrite(nsocket *sock, const char *data, size_t length) 
00427 {
00428     ssize_t wrote;
00429 
00430 #ifdef ENABLE_SSL
00431     if (sock->ssl) {
00432        /* joe: ssl.h says SSL_MODE_ENABLE_PARTIAL_WRITE must 
00433         * be enabled to have SSL_write return < length... 
00434         * so, SSL_write should never return < length. */
00435        wrote = SSL_write(sock->ssl, data, length);
00436        if (wrote >= 0 && wrote < length) {
00437            DEBUG(DEBUG_SOCKET, "SSL_write returned less than length!\n");
00438            sock->error = ERROR_SSL_STRING;
00439            return SOCK_ERROR;
00440        }
00441     } else {
00442 #endif
00443        const char *pnt = data;
00444        size_t sent = 0;
00445 
00446        while (sent < length) {
00447            wrote = NEON_WRITE(sock->fd, pnt, length-sent);
00448            if (wrote < 0) {
00449               if (errno == EINTR) {
00450                   continue;
00451               } else if (errno == EPIPE) {
00452                   return SOCK_CLOSED;
00453               } else {
00454                   sock->error = strerror(errno);
00455                   return SOCK_ERROR;
00456               }
00457            }
00458            sent += wrote;
00459            pnt += wrote;
00460 #ifdef ENABLE_SSL
00461        }
00462 #endif
00463     }
00464     return 0;
00465 }
00466 
00467 /* Sends the given string down the given socket.
00468  * Returns 0 on success or -1 on failure. */
00469 int sock_send_string(nsocket *sock, const char *data) 
00470 {
00471     return sock_fullwrite(sock, data, strlen(data));
00472 }
00473 
00474 /* This is from from Eric Raymond's fetchmail (SockRead() in socket.c)
00475  * since I wouldn't have a clue how to do it properly.
00476  * This function is Copyright 1999 (C) Eric Raymond.
00477  * Modifications Copyright 2000 (C) Joe Orton
00478  */
00479 int sock_readline(nsocket *sock, char *buf, int len)
00480 {
00481     char *newline, *bp = buf;
00482     int n;
00483 
00484     do {
00485        /* 
00486         * The reason for these gymnastics is that we want two things:
00487         * (1) to read \n-terminated lines,
00488         * (2) to return the true length of data read, even if the
00489         *     data coming in has embedded NULS.
00490         */
00491 #ifdef ENABLE_SSL
00492 
00493        if (sock->ssl) {
00494            /* Hack alert! */
00495            /* OK...  SSL_peek works a little different from MSG_PEEK
00496               Problem is that SSL_peek can return 0 if there is no
00497               data currently available.  If, on the other hand, we
00498               loose the socket, we also get a zero, but the SSL_read
00499               then SEGFAULTS!  To deal with this, we'll check the
00500               error code any time we get a return of zero from
00501               SSL_peek.  If we have an error, we bail.  If we don't,
00502               we read one character in SSL_read and loop.  This
00503               should continue to work even if they later change the
00504               behavior of SSL_peek to "fix" this problem...  :-(*/
00505            DEBUG(DEBUG_SOCKET, "SSL readline... \n");
00506            if ((n = SSL_peek(sock->ssl, bp, len)) < 0) {
00507               sock->error = ERROR_SSL_STRING;
00508               return(-1);
00509            }
00510            if (0 == n) {
00511               /* SSL_peek says no data...  Does he mean no data
00512                  or did the connection blow up?  If we got an error
00513                  then bail! */
00514               DEBUG(DEBUG_SOCKET, "SSL_Peek says no data!\n");
00515               /* Check properly to see if the connection has closed */
00516               if (sock->ssl->shutdown) {
00517                   DEBUG(DEBUG_SOCKET, "SSL says shutdown.");
00518                   return SOCK_CLOSED;
00519               } else if (0 != (n = ERR_get_error())) {
00520                   DEBUG(DEBUG_SOCKET, "SSL error occured.\n");
00521                   sock->error = ERROR_SSL_STRING;
00522                   return -1;
00523               }
00524                   
00525               /* We didn't get an error so read at least one
00526                  character at this point and loop */
00527               n = 1;
00528               /* Make sure newline start out NULL!  We don't have a
00529                * string to pass through the strchr at this point yet
00530                * */
00531               newline = NULL;
00532            } else if ((newline = memchr(bp, '\n', n)) != NULL)
00533               n = newline - bp + 1;
00534            n = SSL_read(sock->ssl, bp, n);
00535            DEBUG(DEBUG_SOCKET, "SSL_read returned %d\n", n);
00536            if (n == -1) {
00537               sock->error = ERROR_SSL_STRING;
00538               return(-1);
00539            }
00540            /* Check for case where our single character turned out to
00541             * be a newline...  (It wasn't going to get caught by
00542             * the strchr above if it came from the hack...). */
00543            if (NULL == newline && 1 == n && '\n' == *bp) {
00544               /* Got our newline - this will break
00545                             out of the loop now */
00546               newline = bp;
00547            }
00548        } else {
00549 #endif
00550            if ((n = sock_peek(sock, bp, len)) <= 0)
00551               return n;
00552            if ((newline = memchr(bp, '\n', n)) != NULL)
00553               n = newline - bp + 1;
00554            if ((n = sock_read(sock, bp, n)) < 0)
00555               return n;
00556 #ifdef ENABLE_SSL
00557        }
00558 #endif
00559        bp += n;
00560        len -= n;
00561        if (len < 1) {
00562            sock->error = _("Line too long");
00563            return SOCK_FULL;
00564        }
00565     } while (!newline && len);
00566     *bp = '\0';
00567     return bp - buf;
00568 }
00569 
00570 /*** End of ESR-copyrighted section ***/
00571 
00572 /* Reads readlen bytes from fd and write to sock.
00573  * If readlen == -1, then it reads from srcfd until EOF.
00574  * Returns number of bytes written to destfd, or -1 on error.
00575  */
00576 int sock_transfer(int fd, nsocket *sock, off_t readlen) 
00577 {
00578     char buffer[BUFSIZ];
00579     size_t curlen; /* total bytes yet to read from srcfd */
00580     off_t sumwrlen; /* total bytes written to destfd */
00581 
00582     if (readlen == -1) {
00583        curlen = BUFSIZ; /* so the buffer size test works */
00584     } else {
00585        curlen = readlen; /* everything to do */
00586     }
00587     sumwrlen = 0; /* nowt done yet */
00588 
00589     while (curlen > 0) {
00590        int rdlen, wrlen;
00591 
00592        /* Get a chunk... if the number of bytes that are left to read
00593         * is less than the buffer size, only read that many bytes. */
00594        rdlen = read(fd, buffer, (readlen==-1)?BUFSIZ:(min(BUFSIZ, curlen)));
00595        sock_call_progress(sumwrlen, readlen);
00596        if (rdlen < 0) { 
00597            if (errno == EPIPE) {
00598               return SOCK_CLOSED;
00599            } else {
00600               sock->error = strerror(errno);
00601               return SOCK_ERROR;
00602            }
00603        } else if (rdlen == 0) { 
00604            /* End of file... get out of here */
00605            break;
00606        }
00607        if (readlen != -1)
00608            curlen -= rdlen;
00609 
00610        /* Otherwise, we have bytes!  Write them to destfd */
00611        
00612        wrlen = sock_fullwrite(sock, buffer, rdlen);
00613        if (wrlen < 0) { 
00614            return wrlen;
00615        }
00616 
00617        sumwrlen += rdlen;
00618     }
00619     sock_call_progress(sumwrlen, readlen);
00620     return sumwrlen;
00621 }
00622 
00623 /* Reads buflen bytes into buffer until it's full.
00624  * Returns 0 on success, -1 on error */
00625 int sock_fullread(nsocket *sock, char *buffer, int buflen) 
00626 {
00627     char *pnt; /* current position within buffer */
00628     int len;
00629     pnt = buffer;
00630     while (buflen > 0) {
00631        len = sock_read(sock, pnt, buflen);
00632        if (len < 0) return len;
00633        buflen -= len;
00634        pnt += len;
00635     }
00636     return 0;
00637 }
00638 
00639 /* Do a name lookup on given hostname, writes the address into
00640  * given address buffer. Return -1 on failure.
00641  */
00642 int sock_name_lookup(const char *hostname, struct in_addr *addr) 
00643 {
00644     struct hostent *hp;
00645     unsigned long laddr;
00646     
00647     if (notify_cb)
00648        (*notify_cb)(notify_ud, sock_namelookup, hostname);
00649     
00650     /* TODO?: a possible problem here, is that if we are passed an
00651      * invalid IP address e.g. "500.500.500.500", then this gets
00652      * passed to gethostbyname and returned as "Host not found".
00653      * Arguably wrong, but maybe difficult to detect correctly what is
00654      * an invalid IP address and what is a hostname... can hostnames
00655      * begin with a numeric character? */
00656     laddr = (unsigned long)inet_addr(hostname);
00657     if ((int)laddr == -1) {
00658        /* inet_addr failed. */
00659        hp = gethostbyname(hostname);
00660        if (hp == NULL) {
00661 #if 0
00662            /* Need to get this back somehow, but we don't have 
00663             * an nsocket * yet... */
00664            switch(h_errno) {
00665            case HOST_NOT_FOUND:
00666               sock->error = _("Host not found");
00667               break;
00668            case TRY_AGAIN:
00669               sock->error = _("Host not found (try again later?)");
00670               break;
00671            case NO_ADDRESS:
00672               sock->error = _("Host exists but has no address.");
00673               break;
00674            case NO_RECOVERY:
00675            default:
00676               sock->error = _("Non-recoverable error in resolver library.");
00677               break;
00678            }
00679 #endif
00680            return SOCK_ERROR;
00681        }
00682        memcpy(addr, hp->h_addr, hp->h_length);
00683     } else {
00684        addr->s_addr = laddr;
00685     }
00686     return 0;
00687 }
00688 
00689 static nsocket *create_sock(int fd)
00690 {
00691     nsocket *sock = ne_calloc(sizeof *sock);
00692 #ifdef ENABLE_SSL
00693     sock->default_ctx = SSL_CTX_new(SSLv23_client_method());
00694 #endif
00695     sock->fd = fd;
00696     return sock;
00697 }
00698 
00699 /* Opens a socket to the given port at the given address.
00700  * Returns -1 on failure, or the socket on success. 
00701  * portnum must be in HOST byte order */
00702 nsocket *sock_connect_u(const struct in_addr addr, 
00703                      unsigned short int portnum, 
00704                      int call_fe) 
00705 {
00706     struct sockaddr_in sa;
00707     int fd;
00708 
00709     /* Create the socket */
00710     fd = socket(AF_INET, SOCK_STREAM, 0);
00711     if (fd < 0)
00712        return NULL;
00713     /* Connect the nsocket */
00714     sa.sin_family = AF_INET;
00715     sa.sin_port = htons(portnum); /* host -> net byte orders */
00716     sa.sin_addr = addr;
00717     if (call_fe && notify_cb) (*notify_cb)(notify_ud, sock_connecting, NULL);
00718     if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
00719        (void) NEON_CLOSE(fd);
00720        return NULL;
00721     }
00722     if (call_fe && notify_cb) (*notify_cb)(notify_ud, sock_connected, NULL);
00723     /* Success - return the nsocket */
00724     return create_sock(fd);
00725 }
00726 
00727 nsocket *sock_accept(int listener) 
00728 {
00729     int fd = accept(listener, NULL, NULL);
00730     if (fd > 0) {
00731        return create_sock(fd);
00732     } else {
00733        return NULL;
00734     }
00735 }
00736 
00737 int sock_get_fd(nsocket *sock)
00738 {
00739     return sock->fd;
00740 }
00741 
00742 nsocket *sock_connect(const struct in_addr addr, 
00743                     unsigned short int portnum) {
00744     return sock_connect_u(addr, portnum, 1);
00745 }
00746 
00747 nssl_context *sock_create_ssl_context(void)
00748 {
00749     nssl_context *ctx = ne_calloc(sizeof *ctx);
00750 #ifdef ENABLE_SSL
00751     ctx->ctx = SSL_CTX_new(SSLv23_client_method());
00752 #endif
00753     return ctx;
00754 }
00755 
00756 void sock_destroy_ssl_context(nssl_context *ctx)
00757 {
00758 #ifdef ENABLE_SSL
00759     SSL_CTX_free(ctx->ctx);
00760 #endif
00761     free(ctx);
00762 }
00763 
00764 #ifdef ENABLE_SSL
00765 void sock_disable_tlsv1(nssl_context *c)
00766 {
00767     SSL_CTX_set_options(c->ctx, SSL_OP_NO_TLSv1);
00768 }
00769 void sock_disable_sslv2(nssl_context *c)
00770 {
00771     SSL_CTX_set_options(c->ctx, SSL_OP_NO_SSLv2);
00772 
00773 }
00774 void sock_disable_sslv3(nssl_context *c)
00775 {
00776     SSL_CTX_set_options(c->ctx, SSL_OP_NO_SSLv3);
00777 }
00778 
00779 /* The callback neon installs with OpenSSL for giving the private key
00780  * prompt.  FIXME: WTH is 'rwflag'? */
00781 static int key_prompt_cb(char *buf, int len, int rwflag, void *userdata)
00782 {
00783     nssl_context *ctx = userdata;
00784     int ret;
00785     ret = ctx->key_prompt(ctx->key_userdata, ctx->key_file, buf, len);
00786     if (ret)
00787        return -1;
00788     /* Obscurely OpenSSL requires the callback to return the length of
00789      * the password, this seems a bit weird so we don't expose this in
00790      * the neon API. */
00791     return strlen(buf);
00792 }
00793 
00794 void sock_set_key_prompt(nssl_context *ctx, 
00795                       nssl_key_prompt prompt, void *userdata)
00796 {
00797     SSL_CTX_set_default_passwd_cb(ctx->ctx, key_prompt_cb);
00798     SSL_CTX_set_default_passwd_cb_userdata(ctx->ctx, ctx);
00799     ctx->key_prompt = prompt;
00800     ctx->key_userdata = userdata;
00801 }
00802 
00803 #else
00804 void sock_disable_tlsv1(nssl_context *c) {}
00805 void sock_disable_sslv2(nssl_context *c) {}
00806 void sock_disable_sslv3(nssl_context *c) {}
00807 void sock_set_key_prompt(nssl_context *c, nssl_key_prompt p, void *u) {}
00808 #endif
00809 
00810 int sock_make_secure(nsocket *sock, nssl_context *ctx)
00811 {
00812 #ifdef ENABLE_SSL
00813     int ret;
00814     SSL_CTX *ssl_ctx;
00815 
00816     if (ctx) {
00817        ssl_ctx = ctx->ctx;
00818     } else {
00819        ssl_ctx = sock->default_ctx;
00820     }
00821 
00822     sock->ssl = SSL_new(ssl_ctx);
00823     if (!sock->ssl) {
00824        sock->error = ERROR_SSL_STRING;
00825        /* Usually goes wrong because: */
00826        fprintf(stderr, "Have you called sock_init()!?\n");
00827        return SOCK_ERROR;
00828     }
00829     
00830     SSL_set_fd(sock->ssl, sock->fd);
00831     
00832     ret = SSL_connect(sock->ssl);
00833     if (ret == -1) {
00834        sock->error = ERROR_SSL_STRING;
00835        SSL_free(sock->ssl);
00836        sock->ssl = NULL;
00837        return SOCK_ERROR;
00838     }
00839 
00840 #if 0
00841     /* Tommi Komulainen <Tommi.Komulainen@iki.fi> has donated his SSL
00842      * cert verification from the mutt IMAP/SSL code under the
00843      * LGPL... it will plug in here */
00844     ret = sock_check_certicate(sock);
00845     if (ret) {
00846        SSL_shutdown(sock->ssl);
00847        SSL_free(sock->ssl);
00848        sock->ssl = NULL;
00849        return ret;
00850     }
00851 #endif
00852 
00853     if (notify_cb) (*notify_cb)(notify_ud, sock_secure_details, 
00854                               SSL_get_version(sock->ssl));
00855     DEBUG(DEBUG_SOCKET, "SSL connected: version %s\n", 
00856           SSL_get_version(sock->ssl));
00857     return 0;
00858 #else
00859     sock->error = _("This application does not have SSL support.");
00860     return SOCK_ERROR;
00861 #endif
00862 }
00863 
00864 const char *sock_get_error(nsocket *sock)
00865 {
00866     return sock->error;
00867 }
00868 
00869 /* Closes given nsocket */
00870 int sock_close(nsocket *sock) {
00871     int ret;
00872 #ifdef ENABLE_SSL
00873     if (sock->ssl) {
00874        SSL_shutdown(sock->ssl);
00875        SSL_free(sock->ssl);
00876     }
00877     SSL_CTX_free(sock->default_ctx);
00878 #endif
00879     ret = NEON_CLOSE(sock->fd);
00880     free(sock);
00881     return ret;
00882 }
00883 
00884 /* FIXME: get error messages back to the caller. */   
00885 int sock_set_client_cert(nssl_context *ctx, const char *cert, const char *key)
00886 {
00887 #ifdef ENABLE_SSL
00888     if (SSL_CTX_use_certificate_file(ctx->ctx, cert, SSL_FILETYPE_PEM) <= 0) {
00889        DEBUG(DEBUG_SOCKET, "Could not load cert file.\n");
00890        return -1;
00891     }
00892     
00893     /* The cert file can contain the private key too, apparently. Not
00894      * sure under what circumstances this is sensible, but hey. */
00895     if (key == NULL)
00896        key = cert;
00897     
00898     /* Set this so the callback can tell the user what's going on. */
00899     ctx->key_file = key;
00900     
00901     if (SSL_CTX_use_PrivateKey_file(ctx->ctx, key, SSL_FILETYPE_PEM) <= 0) {
00902        DEBUG(DEBUG_SOCKET, "Could not load private key file.\n");
00903        return -1;
00904     }
00905 
00906     /* Sanity check. */
00907     if (!SSL_CTX_check_private_key(ctx->ctx)) {
00908        DEBUG(DEBUG_SOCKET, "Private key does not match certificate.\n");
00909        return -1;
00910     }
00911 
00912     return 0;
00913 #else
00914     return -1;
00915 #endif
00916 }
00917 
00918 /* Returns HOST byte order port of given name */
00919 int sock_service_lookup(const char *name) {
00920     struct servent *ent;
00921     ent = getservbyname(name, "tcp");
00922     if (ent == NULL) {
00923        return 0;
00924     } else {
00925        return ntohs(ent->s_port);
00926     }
00927 }