Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 
     23 #include "curl_setup.h"
     24 
     25 #ifndef CURL_DISABLE_DICT
     26 
     27 #ifdef HAVE_NETINET_IN_H
     28 #include <netinet/in.h>
     29 #endif
     30 #ifdef HAVE_NETDB_H
     31 #include <netdb.h>
     32 #endif
     33 #ifdef HAVE_ARPA_INET_H
     34 #include <arpa/inet.h>
     35 #endif
     36 #ifdef HAVE_NET_IF_H
     37 #include <net/if.h>
     38 #endif
     39 #ifdef HAVE_SYS_IOCTL_H
     40 #include <sys/ioctl.h>
     41 #endif
     42 
     43 #ifdef HAVE_SYS_PARAM_H
     44 #include <sys/param.h>
     45 #endif
     46 
     47 #ifdef HAVE_SYS_SELECT_H
     48 #include <sys/select.h>
     49 #endif
     50 
     51 #include "urldata.h"
     52 #include <curl/curl.h>
     53 #include "transfer.h"
     54 #include "sendf.h"
     55 #include "escape.h"
     56 #include "progress.h"
     57 #include "dict.h"
     58 #include "strcase.h"
     59 #include "curl_memory.h"
     60 /* The last #include file should be: */
     61 #include "memdebug.h"
     62 
     63 /*
     64  * Forward declarations.
     65  */
     66 
     67 static CURLcode dict_do(struct connectdata *conn, bool *done);
     68 
     69 /*
     70  * DICT protocol handler.
     71  */
     72 
     73 const struct Curl_handler Curl_handler_dict = {
     74   "DICT",                               /* scheme */
     75   ZERO_NULL,                            /* setup_connection */
     76   dict_do,                              /* do_it */
     77   ZERO_NULL,                            /* done */
     78   ZERO_NULL,                            /* do_more */
     79   ZERO_NULL,                            /* connect_it */
     80   ZERO_NULL,                            /* connecting */
     81   ZERO_NULL,                            /* doing */
     82   ZERO_NULL,                            /* proto_getsock */
     83   ZERO_NULL,                            /* doing_getsock */
     84   ZERO_NULL,                            /* domore_getsock */
     85   ZERO_NULL,                            /* perform_getsock */
     86   ZERO_NULL,                            /* disconnect */
     87   ZERO_NULL,                            /* readwrite */
     88   ZERO_NULL,                            /* connection_check */
     89   PORT_DICT,                            /* defport */
     90   CURLPROTO_DICT,                       /* protocol */
     91   PROTOPT_NONE | PROTOPT_NOURLQUERY      /* flags */
     92 };
     93 
     94 static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
     95 {
     96   char *newp = NULL;
     97   char *dictp;
     98   char *ptr;
     99   size_t len;
    100   char ch;
    101   int olen = 0;
    102 
    103   CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
    104   if(!newp || result)
    105     return NULL;
    106 
    107   dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
    108   if(dictp) {
    109     /* According to RFC2229 section 2.2, these letters need to be escaped with
    110        \[letter] */
    111     for(ptr = newp;
    112         (ch = *ptr) != 0;
    113         ptr++) {
    114       if((ch <= 32) || (ch == 127) ||
    115           (ch == '\'') || (ch == '\"') || (ch == '\\')) {
    116         dictp[olen++] = '\\';
    117       }
    118       dictp[olen++] = ch;
    119     }
    120     dictp[olen] = 0;
    121   }
    122   free(newp);
    123   return dictp;
    124 }
    125 
    126 static CURLcode dict_do(struct connectdata *conn, bool *done)
    127 {
    128   char *word;
    129   char *eword;
    130   char *ppath;
    131   char *database = NULL;
    132   char *strategy = NULL;
    133   char *nthdef = NULL; /* This is not part of the protocol, but required
    134                           by RFC 2229 */
    135   CURLcode result = CURLE_OK;
    136   struct Curl_easy *data = conn->data;
    137   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
    138 
    139   char *path = data->state.path;
    140   curl_off_t *bytecount = &data->req.bytecount;
    141 
    142   *done = TRUE; /* unconditionally */
    143 
    144   if(conn->bits.user_passwd) {
    145     /* AUTH is missing */
    146   }
    147 
    148   if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
    149      strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
    150      strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
    151 
    152     word = strchr(path, ':');
    153     if(word) {
    154       word++;
    155       database = strchr(word, ':');
    156       if(database) {
    157         *database++ = (char)0;
    158         strategy = strchr(database, ':');
    159         if(strategy) {
    160           *strategy++ = (char)0;
    161           nthdef = strchr(strategy, ':');
    162           if(nthdef) {
    163             *nthdef = (char)0;
    164           }
    165         }
    166       }
    167     }
    168 
    169     if((word == NULL) || (*word == (char)0)) {
    170       infof(data, "lookup word is missing\n");
    171       word = (char *)"default";
    172     }
    173     if((database == NULL) || (*database == (char)0)) {
    174       database = (char *)"!";
    175     }
    176     if((strategy == NULL) || (*strategy == (char)0)) {
    177       strategy = (char *)".";
    178     }
    179 
    180     eword = unescape_word(data, word);
    181     if(!eword)
    182       return CURLE_OUT_OF_MEMORY;
    183 
    184     result = Curl_sendf(sockfd, conn,
    185                         "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    186                         "MATCH "
    187                         "%s "    /* database */
    188                         "%s "    /* strategy */
    189                         "%s\r\n" /* word */
    190                         "QUIT\r\n",
    191 
    192                         database,
    193                         strategy,
    194                         eword
    195                         );
    196 
    197     free(eword);
    198 
    199     if(result) {
    200       failf(data, "Failed sending DICT request");
    201       return result;
    202     }
    203     Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
    204                         -1, NULL); /* no upload */
    205   }
    206   else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
    207           strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
    208           strncasecompare(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
    209 
    210     word = strchr(path, ':');
    211     if(word) {
    212       word++;
    213       database = strchr(word, ':');
    214       if(database) {
    215         *database++ = (char)0;
    216         nthdef = strchr(database, ':');
    217         if(nthdef) {
    218           *nthdef = (char)0;
    219         }
    220       }
    221     }
    222 
    223     if((word == NULL) || (*word == (char)0)) {
    224       infof(data, "lookup word is missing\n");
    225       word = (char *)"default";
    226     }
    227     if((database == NULL) || (*database == (char)0)) {
    228       database = (char *)"!";
    229     }
    230 
    231     eword = unescape_word(data, word);
    232     if(!eword)
    233       return CURLE_OUT_OF_MEMORY;
    234 
    235     result = Curl_sendf(sockfd, conn,
    236                         "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    237                         "DEFINE "
    238                         "%s "     /* database */
    239                         "%s\r\n"  /* word */
    240                         "QUIT\r\n",
    241                         database,
    242                         eword);
    243 
    244     free(eword);
    245 
    246     if(result) {
    247       failf(data, "Failed sending DICT request");
    248       return result;
    249     }
    250     Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
    251                         -1, NULL); /* no upload */
    252   }
    253   else {
    254 
    255     ppath = strchr(path, '/');
    256     if(ppath) {
    257       int i;
    258 
    259       ppath++;
    260       for(i = 0; ppath[i]; i++) {
    261         if(ppath[i] == ':')
    262           ppath[i] = ' ';
    263       }
    264       result = Curl_sendf(sockfd, conn,
    265                           "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
    266                           "%s\r\n"
    267                           "QUIT\r\n", ppath);
    268       if(result) {
    269         failf(data, "Failed sending DICT request");
    270         return result;
    271       }
    272 
    273       Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL);
    274     }
    275   }
    276 
    277   return CURLE_OK;
    278 }
    279 #endif /*CURL_DISABLE_DICT*/
    280