client.c

00001 #include "log.h"
00002 #include "socket.h"
00003 #include "client.h"
00004 #include "collection.h"
00005 
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <errno.h>
00010 
00011 #include <sys/types.h>
00012 
00013 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00014 #include <unistd.h>
00015 #include <sys/socket.h>
00016 #include <netinet/in.h>
00017 #include <arpa/inet.h>
00018 #include <netdb.h>
00019 #endif
00020 
00021 #ifdef CP_USE_SSL
00022 #include <openssl/ssl.h>
00023 #include <openssl/err.h>
00024 
00025 #ifdef _WINDOWS
00026 #include <wincrypt.h>
00027 #endif /* _WINDOWS */
00028 
00029 #endif /* CP_USE_SSL */
00030 
00031 #ifdef CP_HAS_STRINGS_H
00032 #include <strings.h>
00033 #else
00034 #include "util.h"
00035 #endif /* CP_HAS_STRINGS_H */
00036 
00037 #ifdef _WINDOWS
00038 #include <Winsock2.h>
00039 #include <Ws2tcpip.h>
00040 #include <WS2SPI.H>
00041 #endif
00042 
00043 #ifdef CP_USE_SSL
00044 
00045 char *ssl_verification_error_str(int code)
00046 {
00047     switch (code)
00048     {
00049         case X509_V_OK:
00050         return "X509_V_OK the operation was successful.";
00051 
00052         case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00053         return
00054         "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT the issuer certificate could "
00055         "not be found";
00056 
00057         case X509_V_ERR_UNABLE_TO_GET_CRL:
00058         return 
00059         "X509_V_ERR_UNABLE_TO_GET_CRL the CRL of a certificate could "
00060         "not be found."; /* unused */
00061 
00062         case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
00063         return
00064         "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE the certificate signature"
00065         " could not be decrypted.";
00066 
00067         case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
00068         return
00069         "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE the CRL signature could "
00070         "not be decrypted"; /* unused */
00071 
00072         case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
00073         return
00074         "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY the public key in the "
00075         "certificate SubjectPublicKeyInfo could not be read.";
00076 
00077         case X509_V_ERR_CERT_SIGNATURE_FAILURE:
00078         return
00079         "X509_V_ERR_CERT_SIGNATURE_FAILURE the signature of the certificate "
00080         "is invalid.";
00081 
00082         case X509_V_ERR_CRL_SIGNATURE_FAILURE:
00083         return 
00084         "X509_V_ERR_CRL_SIGNATURE_FAILURE the signature of the "
00085         " certificate is invalid."; /* unused */
00086 
00087         case X509_V_ERR_CERT_NOT_YET_VALID:
00088         return
00089         "X509_V_ERR_CERT_NOT_YET_VALID the certificate is not yet valid: the "
00090         " notBefore date is after the current time.";
00091 
00092         case X509_V_ERR_CERT_HAS_EXPIRED:
00093         return
00094         "X509_V_ERR_CERT_HAS_EXPIRED the certificate has expired: the "
00095         "notAfter date is before the current time.";
00096 
00097         case X509_V_ERR_CRL_NOT_YET_VALID:
00098         return "X509_V_ERR_CRL_NOT_YET_VALID the CRL is not yet valid."; /* unused */
00099 
00100         case X509_V_ERR_CRL_HAS_EXPIRED:
00101         return "X509_V_ERR_CRL_HAS_EXPIRED the CRL has expired."; /* unused */
00102 
00103         case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00104         return
00105         "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD the certificate notBefore "
00106         "field contains an invalid time.";
00107 
00108         case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00109         return
00110         "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD the certificate notAfter "
00111         "field contains an invalid time.";
00112 
00113         case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
00114         return
00115         "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD the CRL lastUpdate field "
00116         "contains an invalid time."; /* unused */
00117 
00118         case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
00119         return
00120         "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD the CRL nextUpdate field "
00121         "contains an invalid time."; /* unused */
00122 
00123         case X509_V_ERR_OUT_OF_MEM:
00124         return
00125         "X509_V_ERR_OUT_OF_MEM an error occurred trying to allocate memory.";
00126 
00127         case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
00128         return
00129         "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT the passed certificate is self"
00130         " signed and the same certificate cannot be found in the list of "
00131         "trusted certificates.";
00132 
00133         case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
00134         return
00135         "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN the certificate chain could be "
00136         "built up using the untrusted certificates but the root could not be "
00137         "found locally.";
00138 
00139         case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
00140         return
00141         "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY the issuer certificate "
00142         "of a locally looked up certificate could not be found.";
00143 
00144         case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
00145         return
00146         "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE no signatures could be "
00147         "verified because the chain contains only one certificate and it is "
00148         "not self signed.";
00149 
00150         case X509_V_ERR_CERT_CHAIN_TOO_LONG:
00151         return
00152         "X509_V_ERR_CERT_CHAIN_TOO_LONG the certificate chain length is "
00153         "greater than the supplied maximum depth.";
00154 
00155         case X509_V_ERR_CERT_REVOKED:
00156         return
00157         "X509_V_ERR_CERT_REVOKED the certificate has been revoked."; /* unused */
00158 
00159         case X509_V_ERR_INVALID_CA:
00160         return
00161         "X509_V_ERR_INVALID_CA a CA certificate is invalid. Either it is not a"
00162         " CA or its extensions are not consistent with the supplied purpose.";
00163 
00164         case X509_V_ERR_PATH_LENGTH_EXCEEDED:
00165         return
00166         "X509_V_ERR_PATH_LENGTH_EXCEEDED the basicConstraints pathlength "
00167         "parameter has been exceeded.";
00168 
00169         case X509_V_ERR_INVALID_PURPOSE:
00170         return 
00171         "X509_V_ERR_INVALID_PURPOSE the supplied certificate cannot be used "
00172         "for the specified purpose.";
00173 
00174         case X509_V_ERR_CERT_UNTRUSTED:
00175         return
00176         "X509_V_ERR_CERT_UNTRUSTED the root CA is not marked as trusted for "
00177         "the specified purpose.";
00178 
00179         case X509_V_ERR_CERT_REJECTED:
00180         return
00181         "X509_V_ERR_CERT_REJECTED the root CA is marked to reject the "
00182         "specified purpose.";
00183 
00184         case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
00185         return 
00186         "X509_V_ERR_SUBJECT_ISSUER_MISMATCH the current candidate issuer "
00187         "certificate was rejected because its subject name did not match the "
00188         "issuer name of the current certificate.";
00189 
00190         case X509_V_ERR_AKID_SKID_MISMATCH:
00191         return
00192         "X509_V_ERR_AKID_SKID_MISMATCH the current candidate issuer certificate"
00193         " was rejected because its subject key identifier was present and did "
00194         "not match the authority key identifier of the current certificate.";
00195 
00196         case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
00197         return 
00198         "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH the current candidate issuer "
00199         "certificate was rejected because its"
00200         " issuer name and serial number was present and did not match the"
00201         " authority key identifier of the current certificate. Only displayed"
00202         " when the -issuer_checks option is set.";
00203 
00204         case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
00205         return
00206             "X509_V_ERR_KEYUSAGE_NO_CERTSIGN the current candidate issuer "
00207             "certificate was rejected because its"
00208             " keyUsage extension does not permit certificate signing.";
00209 
00210         case X509_V_ERR_APPLICATION_VERIFICATION: 
00211            return 
00212                "X509_V_ERR_APPLICATION_VERIFICATION "
00213                "server presented no certificate";
00214     }
00215 
00216     return "unknown verification error";
00217 }
00218 
00219 char *ssl_err_inf(int err)
00220 {
00221     switch (err)
00222     {
00223         case SSL_ERROR_NONE: return "SSL_ERROR_NONE"; break;
00224         case SSL_ERROR_ZERO_RETURN: return "SSL_ERROR_ZERO_RETURN"; break;
00225         case SSL_ERROR_WANT_READ: return "SSL_ERROR_WANT_READ"; break;
00226         case SSL_ERROR_WANT_WRITE: return "SSL_ERROR_WANT_WRITE"; break;
00227         case SSL_ERROR_WANT_CONNECT: return "SSL_ERROR_WANT_CONNECT"; break;
00228 #ifdef SSL_ERROR_WANT_ACCEPT
00229         case SSL_ERROR_WANT_ACCEPT: return "SSL_ERROR_WANT_ACCEPT"; break;
00230 #endif /* SSL_ERROR_WANT_ACCEPT */
00231         case SSL_ERROR_WANT_X509_LOOKUP: return "SSL_ERROR_WANT_X509_LOOKUP"; break;
00232         case SSL_ERROR_SYSCALL: return "SSL_ERROR_SYSCALL"; break;
00233         case SSL_ERROR_SSL: return "SSL_ERROR_SSL"; break;
00234     }
00235 
00236     return "unknown";
00237 }
00238 
00239 void cp_client_ssl_init()
00240 {
00241     cp_socket_ssl_init();
00242 }
00243 
00244 void cp_client_ssl_shutdown()
00245 {
00246     cp_socket_ssl_shutdown();
00247 }
00248 
00249 #endif
00250 
00251 #ifndef CP_HAS_GETHOSTBYNAME_R_6
00252 static cp_lock *cp_gethostbyname_lock = NULL;
00253 #endif
00254 
00255 void cp_client_init()
00256 {
00257 #ifndef CP_HAS_GETHOSTBYNAME_R_6
00258     if (cp_gethostbyname_lock == NULL)
00259     {
00260         cp_gethostbyname_lock = (cp_lock *) calloc(1, sizeof(cp_lock));
00261         if (cp_gethostbyname_lock == NULL)
00262             cp_fatal(CP_MEMORY_ALLOCATION_FAILURE, "can\'t allocate lock");
00263 
00264         if (cp_lock_init(cp_gethostbyname_lock, NULL))
00265             cp_fatal(CP_INITIALIZATION_FAILURE, "can\'t initialize lock");
00266     }
00267 #endif
00268     cp_socket_init();
00269 }
00270 
00271 void cp_client_shutdown()
00272 {
00273 #ifndef CP_HAS_GETHOSTBYNAME_R_6
00274     if (cp_gethostbyname_lock != NULL)
00275     {
00276         cp_lock_destroy(cp_gethostbyname_lock);
00277         free(cp_gethostbyname_lock);
00278         cp_gethostbyname_lock = NULL;
00279     }
00280 #endif
00281     cp_socket_shutdown();
00282 }
00283 
00284 static void delete_hostent(struct hostent *hp)
00285 {
00286     if (hp)
00287     {
00288 #ifndef CP_HAS_GETHOSTBYNAME_R_6
00289         int i;
00290 
00291         if (hp->h_name) free(hp->h_name);
00292 
00293         if (hp->h_aliases)
00294         {
00295             for (i = 0; hp->h_aliases[i]; i++)
00296                 free(hp->h_aliases[i]);
00297             free(hp->h_aliases);
00298         }
00299 
00300         if (hp->h_addr_list)
00301         {
00302             for (i = 0; hp->h_addr_list[i]; i++)
00303                 free(hp->h_addr_list[i]);
00304             free(hp->h_addr_list);
00305         }
00306 #endif
00307 
00308         free(hp);
00309     }
00310 }
00311 
00312 #ifdef CP_HAS_GETHOSTBYNAME_R_6
00313 #define RESOLVE_BUFLEN 0x1000
00314 static int resolve_addr(cp_client *client)
00315 {
00316     struct hostent *res = (struct hostent *) calloc(1, sizeof(struct hostent));
00317     struct hostent *result;
00318     char buf[RESOLVE_BUFLEN];
00319     int rc, err;
00320 
00321     rc = gethostbyname_r(client->host, res, buf, RESOLVE_BUFLEN, &result, &err);
00322     if (!(rc == 0 && result != NULL && err == 0))
00323     {
00324         free(res);
00325         rc = -1;
00326     }
00327     else
00328         client->hostspec = res;
00329 
00330     return rc;
00331 }
00332 
00333 #else /* CP_HAS_GETHOSTBYNAME_R_6 */
00334 
00335 struct hostent *hostentdup(struct hostent *src)
00336 {
00337     int i, count;
00338     struct hostent *dup = (struct hostent *) calloc(1, sizeof(struct hostent));
00339     if (src->h_name) dup->h_name = strdup(src->h_name);
00340     for (count = 0; src->h_aliases[count] != NULL; count++);
00341     dup->h_aliases = (char **) calloc(count + 1, sizeof(char *));
00342     if (count)
00343     {
00344         for (i = 0; i < count; i++)
00345             dup->h_aliases[i] = strdup(src->h_aliases[i]);
00346     }
00347     dup->h_aliases[count] = NULL;
00348     dup->h_addrtype = src->h_addrtype;
00349     dup->h_length = src->h_length;
00350     for (count = 0; src->h_addr_list[count] != NULL; count++);
00351     dup->h_addr_list = (char **) calloc(count + 1, sizeof(char *));
00352     if (count)
00353     {
00354         for (i = 0; i < count; i++)
00355         {
00356             dup->h_addr_list[i] = (char *) malloc(src->h_length);
00357             memcpy(dup->h_addr_list[i], src->h_addr_list[i], src->h_length);
00358         }
00359     }
00360     dup->h_addr_list[count] = NULL;
00361 
00362     return dup;
00363 }
00364 
00365 void print_addr(struct hostent *hp)
00366 {
00367     int i;
00368 
00369     printf("host %s: ", hp->h_name);
00370     for (i = 0; hp->h_addr_list[i] != NULL; i++)
00371         printf("addr[%d]: %s\n", i, inet_ntoa(*(struct in_addr *) hp->h_addr_list[i]));
00372 }
00373 
00374 static int resolve_addr(cp_client *sock)
00375 {
00376     int rc = 0;
00377     struct hostent* phostent;
00378 
00379     if ((rc = cp_lock_wrlock(cp_gethostbyname_lock)) != 0) return -1;
00380     phostent = gethostbyname(sock->host);
00381 
00382     if (phostent)
00383     {
00384         sock->hostspec = hostentdup(phostent);
00385         rc = 0;
00386     }
00387 
00388     cp_lock_unlock(cp_gethostbyname_lock);
00389 
00390     return rc;
00391 }
00392 
00393 #endif /* CP_HAS_GETHOSTBYNAME_R_6 */
00394 
00395 /* create a client socket */
00396 cp_client *cp_client_create(char *host, int port)
00397 {
00398     cp_client *client = calloc(1, sizeof(cp_client));
00399     if (client == NULL) return NULL;
00400     
00401     client->retry = DEFAULT_RETRIES;
00402     client->host = strdup(host);
00403     client->port = port;
00404 
00405     if ((resolve_addr(client)))
00406     {
00407         cp_client_destroy(client);
00408         return NULL;
00409     }
00410 
00411     client->fd = socket(PF_INET, SOCK_STREAM, 0);
00412     if (client->fd == -1)
00413     {
00414         cp_perror(CP_IO_ERROR, errno, "can\'t create socket");
00415         cp_client_destroy(client);
00416         return NULL;
00417     }
00418 
00419     return client;
00420 }
00421 
00422 #ifdef CP_USE_SSL
00423 cp_client *cp_client_create_ssl(char *host, 
00424                                 int port, 
00425                                 char *CA_file, 
00426                                 char *CA_path,
00427                                 int verification_mode)
00428 {
00429     cp_client *client = cp_client_create(host, port);
00430     if (client == NULL) return NULL;
00431 
00432     client->ctx = get_client_ssl_ctx(CA_file, CA_path);
00433     if (client->ctx == NULL)
00434     {
00435         cp_client_destroy(client);
00436         return NULL;
00437     }
00438     
00439     SSL_CTX_set_verify(client->ctx, verification_mode, NULL);
00440     SSL_CTX_set_mode(client->ctx, SSL_MODE_AUTO_RETRY);
00441 
00442     client->use_ssl = 1;
00443     client->ssl = SSL_new(client->ctx);
00444     SSL_set_fd(client->ssl, client->fd);
00445 
00446     return client;
00447 }
00448 #endif /* CP_USE_SSL */
00449 
00450 int cp_client_reopen(cp_client *client, char *host, int port)
00451 {
00452     cp_client_close(client);
00453 
00454     if (client->host) 
00455     {
00456         free(client->host);
00457         client->host = NULL;
00458     }
00459     if (client->hostspec) 
00460     {
00461         delete_hostent(client->hostspec); 
00462         client->hostspec = NULL;
00463     }
00464 
00465     if (client->addr) 
00466     {
00467         free(client->addr);
00468         client->addr = NULL;
00469     }
00470     
00471     client->host = strdup(host);
00472     client->port = port;
00473 
00474     if ((resolve_addr(client)))
00475     {
00476         cp_error(CP_IO_ERROR, "can\'t resolve address for %s", host);
00477         return -1;
00478     }
00479 
00480     client->fd = socket(PF_INET, SOCK_STREAM, 0);
00481     if (client->fd == -1)
00482     {
00483         cp_perror(CP_IO_ERROR, errno, "can\'t create socket");
00484         return -1;
00485     }
00486 
00487 #ifdef CP_USE_SSL
00488     if (client->use_ssl)
00489         SSL_set_fd(client->ssl, client->fd);
00490 #endif /* CP_USE_SSL */
00491 
00492     return cp_client_connect(client);
00493 }
00494 
00496 cp_client *cp_client_create_addr(struct sockaddr_in *addr)
00497 {
00498     cp_client *client = calloc(1, sizeof(cp_client));
00499     if (client == NULL) return NULL;
00500 
00501     client->retry = DEFAULT_RETRIES;
00502     client->addr = malloc(sizeof(struct sockaddr_in));
00503     if (client->addr == NULL)
00504     {
00505         free(client);
00506         return NULL;
00507     }
00508     *client->addr = *addr;
00509 
00510     return client;
00511 }
00512 
00514 void cp_client_set_timeout(cp_client *client, int sec, int usec)
00515 {
00516     client->timeout.tv_sec = sec;
00517     client->timeout.tv_usec = usec;
00518 }
00519 
00521 void cp_client_set_retry(cp_client *client, int retry_count)
00522 {
00523     client->retry = retry_count;
00524 }
00525 
00527 void cp_client_set_owner(cp_client *client, void *owner)
00528 {
00529     client->owner = owner;
00530 }
00531 
00532 #ifdef CP_USE_SSL
00533 int cp_client_connect_ssl(cp_client *client)
00534 {
00535     int rc = SSL_connect(client->ssl);
00536     if (rc <= 0)
00537     {
00538         int err = SSL_get_error(client->ssl, rc);
00539         const char *reason = ERR_reason_error_string(err);
00540 
00541         cp_error(CP_SSL_HANDSHAKE_FAILED, "can\'t connect to %s: %s", 
00542                  inet_ntoa(client->addr->sin_addr), 
00543                  reason ? reason : ssl_err_inf(err));
00544         if (rc == 0) rc = -1; //~~ ahem
00545     }
00546     else
00547     {
00548         client->server_certificate = SSL_get_peer_certificate(client->ssl);
00549 //      SSL_set_connect_state(client->ssl); //~~ necessary?
00550         if (client->server_certificate == NULL)
00551         {
00552             cp_error(CP_SSL_VERIFICATION_ERROR, 
00553                     "connecting to %s: server presented no certificate", 
00554                     inet_ntoa(client->addr->sin_addr));
00555             /* connection is up; client code should decide whether to 
00556              * continue or not. */
00557             return X509_V_ERR_APPLICATION_VERIFICATION; 
00558         }
00559         if ((rc = SSL_get_verify_result(client->ssl)) != X509_V_OK) /* certificate doesn't verify */
00560         {
00561             cp_error(CP_SSL_VERIFICATION_ERROR, 
00562                     "SSL_get_verify_result: %d\n", rc);
00563             return rc;
00564         }
00565     }
00566 
00567     return rc;
00568 }
00569 #endif /* CP_USE_SSL */
00570 
00572 int cp_client_connect(cp_client *client)
00573 {
00574     struct sockaddr_in addr;
00575     int rc = 0;
00576     int connected = 0;
00577     int retry = client->retry;
00578 
00579     if (client->addr == NULL && client->hostspec == NULL)
00580     {
00581         cp_error(CP_INITIALIZATION_FAILURE, "client socket not initialized");
00582         return CP_INITIALIZATION_FAILURE;
00583     }
00584 
00585     memset(&addr, 0, sizeof(struct sockaddr_in));
00586     addr.sin_family = client->hostspec->h_addrtype;
00587     addr.sin_port = htons(client->port);
00588 
00589     while (!connected && retry--)
00590     {
00591         if (client->addr)
00592         {
00593             rc = connect(client->fd, (struct sockaddr *) client->addr, 
00594                     sizeof(struct sockaddr_in));
00595             if (rc == 0) 
00596             {
00597                 connected = 1;
00598                 break;
00599             }
00600         }
00601 
00602         if (client->hostspec)
00603         {
00604             int i;
00605 
00606             for (i = 0; client->hostspec->h_addr_list[i] != NULL; i++)
00607             {
00608                 addr.sin_addr = 
00609                     *((struct in_addr *) client->hostspec->h_addr_list[i]);
00610                 rc = connect(client->fd, (struct sockaddr *) &addr, 
00611                              sizeof(struct sockaddr_in));
00612                 if (rc == 0)
00613                 {
00614                     if (client->addr == NULL)
00615                     {
00616                         client->addr = 
00617                             (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
00618                     }
00619                     if (client->addr == NULL)
00620                         cp_error(CP_MEMORY_ALLOCATION_FAILURE, "can\'t allocate address storage memory");
00621                     else
00622                         memcpy(client->addr, &addr, sizeof(struct sockaddr_in));
00623 
00624                     connected = 1;
00625                     break;
00626                 }
00627             }
00628         }
00629     }
00630 
00631 #ifdef CP_USE_SSL
00632     if (client->use_ssl && connected)
00633         rc = cp_client_connect_ssl(client);
00634 #endif
00635     
00636     if (connected && rc == 0)
00637         gettimeofday(&client->created, NULL);
00638 
00639     return rc;
00640 }
00641 
00642 
00643 #ifdef CP_USE_SSL
00644 int verify_host_name(X509 *cert, char *host)
00645 {
00646     char buf[0x100];
00647     X509_NAME *name = X509_get_subject_name(cert);
00648     X509_NAME_get_text_by_NID(name, NID_commonName, buf, 0x100);
00649 #ifdef __TRACE__
00650     DEBUGMSG("certificate for %s\n", buf);
00651 #endif
00652     return (strcasecmp(buf, host) == 0);
00653 }
00654 
00655 X509 *cp_client_get_server_certificate(cp_client *client)
00656 {
00657     return client->server_certificate;
00658 }
00659 
00661 int cp_client_verify_hostname(cp_client *client)
00662 {
00663     return verify_host_name(client->server_certificate, client->host);
00664 }
00665 #endif /* CP_USE_SSL */
00666 
00668 int cp_client_close(cp_client *client)
00669 {
00670     int rc = 0;
00671     
00672     if (client)
00673     {
00674 #ifdef CP_USE_SSL
00675         if (client->use_ssl)
00676         {
00677             rc = SSL_shutdown(client->ssl);
00678             if (!rc)
00679             {
00680                 shutdown(client->fd, SHUT_WR);
00681                 rc = SSL_shutdown(client->ssl);
00682             }
00683             if (client->server_certificate)
00684             {
00685                 X509_free(client->server_certificate);
00686                 client->server_certificate = NULL;
00687             }
00688         }
00689         else
00690 #endif /* CP_USE_SSL */
00691         rc = shutdown(client->fd, SHUT_RDWR);
00692         if (rc == -1) 
00693             cp_perror(CP_IO_ERROR, errno, 
00694                     "shutdown error on connection to %s",
00695                     inet_ntoa(client->addr->sin_addr)); //~~ do something
00696         rc = close(client->fd);
00697         if (rc == -1)
00698             cp_perror(CP_IO_ERROR, errno, 
00699                     "error closing connection to %s",
00700                     inet_ntoa(client->addr->sin_addr));
00701     }
00702 
00703     return rc;
00704 }
00705 
00707 void cp_client_destroy(cp_client *client)
00708 {
00709     if (client)
00710     {
00711         if (client->host) free(client->host);
00712         if (client->hostspec) delete_hostent(client->hostspec);
00713         if (client->addr) free(client->addr);
00714 #ifdef CP_USE_SSL
00715         if (client->use_ssl)
00716             SSL_free(client->ssl);
00717 #endif /* CP_USE_SSL */
00718         free(client);
00719     }
00720 }
00721 
00722 int cp_client_read(cp_client *client, char *buf, int len)
00723 {
00724     int rc;
00725 #ifdef CP_USE_SSL
00726     if (client->use_ssl)
00727         rc = SSL_read(client->ssl, buf, len);
00728     else
00729 #endif /* CP_USE_SSL */
00730 //  rc = read(client->fd, buf, len);
00731     rc = recv(client->fd, buf, len, 0);
00732     if (rc > 0) client->bytes_read += rc;
00733 
00734 #ifdef _TCP_DUMP
00735     if (rc > 0)
00736     {
00737         buf[rc] = '\0';
00738         fprintf(stderr, "--- TCP DUMP ---\r\n%s\r\n --- PMUD PCT --- \r\n", 
00739                 buf);
00740     }
00741 #endif
00742 
00743     return rc;
00744 }
00745 
00746 #define CHUNK 0x1000
00747 
00748 int cp_client_read_string(cp_client *client, cp_string *str, int len)
00749 {
00750     int rc;
00751     char buf[CHUNK];
00752     int read_len;
00753     int total = 0;
00754 
00755     while (len == 0 || total < len)
00756     {
00757         read_len = (len == 0 || (len - total) > CHUNK) ? CHUNK : len - total;
00758 #ifdef CP_USE_SSL
00759         if (client->use_ssl)
00760             rc = SSL_read(client->ssl, buf, read_len);
00761         else
00762 #endif /* CP_USE_SSL */
00763 //      rc = read(client->fd, buf, read_len);
00764         rc = recv(client->fd, buf, read_len, 0);
00765 
00766         if (rc <= 0) 
00767             break;
00768         else
00769             client->bytes_read += rc;
00770         cp_string_cat_bin(str, buf, rc);
00771         total += rc;
00772     }
00773     
00774     return total;
00775 }
00776 
00777 //~~ int cp_client_read_to(cp_client *client, char *buf, int len, char *marker)
00778 
00779 int cp_client_write(cp_client *client, char *buf, int len)
00780 {
00781     int rc;
00782 #ifdef CP_USE_SSL
00783     if (client->use_ssl)
00784     {
00785         rc = SSL_write(client->ssl, buf, len);
00786         if (rc <= 0)
00787         {
00788             int err = SSL_get_error(client->ssl, rc);
00789             const char *reason = ERR_reason_error_string(err);
00790             cp_error(CP_IO_ERROR, "write failed: %s", reason ? reason : ssl_err_inf(err));
00791         }
00792     }
00793     else
00794 #endif
00795     rc = send(client->fd, buf, len, 0);
00796 
00797     if (rc > 0) client->bytes_sent += rc;
00798 
00799     return rc;
00800 }
00801 
00802 int cp_client_write_string(cp_client *client, cp_string *str)
00803 {
00804     int rc;
00805     int total = 0;
00806     char *pos = cp_string_tocstr(str);
00807     int remaining = cp_string_len(str);
00808 
00809     while (total < cp_string_len(str))
00810     {
00811 #ifdef CP_USE_SSL
00812         if (client->use_ssl)
00813             rc = SSL_write(client->ssl, pos, remaining);
00814         else
00815 #endif /* CP_USE_SSL */
00816         rc = send(client->fd, pos, remaining, 0);
00817 
00818         if (rc <= 0) 
00819             break;
00820         else
00821             client->bytes_sent += rc;
00822 
00823         total += rc;
00824         remaining -= rc;
00825         pos = &pos[rc];
00826     }
00827     
00828     return total;
00829 }

Generated on Mon Dec 5 23:00:21 2011 for cprops by  doxygen 1.4.7