zxid

 view release on metacpan or  search on metacpan

zxbusprod.c  view on Meta::CPAN

   int siz = nonce + 2 + len + *zlen;
   ROUND_UP(siz, nonce);        /* Round up to block size */
   p = ZX_ALLOC(cf->ctx, siz);
   if (nonce)
     zx_rand(p, nonce);
   p[nonce] = (len >> 8) & 0xff;
   p[nonce+1] = len & 0xff;
   if (len) {
     memcpy(p+nonce+2, sig, len);
     ZX_FREE(cf->ctx, sig);
   }
   memcpy(p+nonce+2+len, zbuf, *zlen);
   ZX_FREE(cf->ctx, zbuf);
   *zlen += nonce + 2 + len;
   return p;
 }

 /*() Write a line to a log, taking care of all formalities of locking and
 * observing all special options for signing and encryption of the logs.
 * Not usually called directly (but you can if you want to), this is the
 * work horse behind zxbus().
 *
 * cf::  ZXID configuration object, used for memory allocation.
 * c_path:: Path to the log file, as C string
 * encflags:: Encryption flags. See LOG_ERR or LOG_ACT configuration options in zxidconf.h
 * n:: length of log data
 * logbuf:: The data that should be logged
 */

 /* Called by: */
 void zxbus_write_line(zxid_conf* cf, char* c_path, int encflags, int n, const char* logbuf)
 {
   EVP_PKEY* log_sign_pkey;
   struct rsa_st* rsa_pkey;
   struct aes_key_st aes_key;
   int len = 0, blen, zlen;
   char sigletter = 'P';
   char encletter = 'P';
   char* p;
   char* sig = 0;
   char* zbuf;
   char* b64;
   char sigbuf[28+4];   /* Space for "SP " and sha1 */
   char keybuf[16];
   char ivec[16];
   if (n == -2)
     n = strlen(logbuf);
   if (encflags & 0x70) {          /* Encrypt check */
     zbuf = zx_zlib_raw_deflate(cf->ctx, n-1, logbuf, &zlen);
     switch (encflags & 0x06) {     /* Sign check */
     case 0x02:      /* Sx plain sha1 */
       sigletter = 'S';
       sig = ZX_ALLOC(cf->ctx, 20);
       SHA1((unsigned char*)zbuf, zlen, (unsigned char*)sig);
       len = 20;
       break;
     case 0x04:      /* Rx RSA-SHA1 signature */
       sigletter = 'R';
       LOCK(cf->mx, "logsign-wrln");      
       if (!(log_sign_pkey = cf->log_sign_pkey))
	 log_sign_pkey = cf->log_sign_pkey = zxid_read_private_key(cf, "logsign-nopw-cert.pem");
       UNLOCK(cf->mx, "logsign-wrln");      
       if (!log_sign_pkey)
	 break;
len = zxsig_data(cf->ctx, zlen, zbuf, &sig, log_sign_pkey, "enc log line", 0);
       break;
     case 0x06:      /* Dx DSA-SHA1 signature */
       ERR("DSA-SHA1 sig not implemented in encrypted mode. Use RSA-SHA1 or none. %x", encflags);
       break;
     case 0: break;  /* Px no signing */
     }

     switch (encflags & 0x70) {
     case 0x10:  /* xZ RFC1951 zip + safe base64 */
       encletter = 'Z';
       zbuf = zxbus_alloc_zbuf(cf, &zlen, zbuf, len, sig, 0);
       break;
     case 0x20:  /* xA RSA-AES */
       encletter = 'A';
       zbuf = zxbus_alloc_zbuf(cf, &zlen, zbuf, len, sig, 16);
       zx_rand(keybuf, 16);
       AES_set_encrypt_key((unsigned char*)keybuf, 128, &aes_key);
       memcpy(ivec, zbuf, sizeof(ivec));
       AES_cbc_encrypt((unsigned char*)zbuf+16, (unsigned char*)zbuf+16, zlen-16, &aes_key, (unsigned char*)ivec, 1);
       ROUND_UP(zlen, 16);        /* Round up to block size */

       LOCK(cf->mx, "logenc-wrln");
       if (!cf->log_enc_cert)
	 cf->log_enc_cert = zxid_read_cert(cf, "logenc-nopw-cert.pem");
       rsa_pkey = zx_get_rsa_pub_from_cert(cf->log_enc_cert, "log_enc_cert");
       UNLOCK(cf->mx, "logenc-wrln");
       if (!rsa_pkey)
	 break;

       len = RSA_size(rsa_pkey);
       sig = ZX_ALLOC(cf->ctx, len);
       if (RSA_public_encrypt(16, (unsigned char*)keybuf, (unsigned char*)sig, rsa_pkey, RSA_PKCS1_OAEP_PADDING) < 0) {
	 ERR("RSA enc fail %x", encflags);
	 zx_report_openssl_err("zxbus rsa enc");
	 return;
       }
       p = ZX_ALLOC(cf->ctx, 2 + len + zlen);
       p[0] = (len >> 8) & 0xff;
       p[1] = len & 0xff;
       memcpy(p+2, sig, len);
       memcpy(p+2+len, zbuf, zlen);
       ZX_FREE(cf->ctx, sig);
       ZX_FREE(cf->ctx, zbuf);
       zbuf = p;
       zlen += 2 + len;
       break;
     case 0x30:  /* xT RSA-3DES */
       encletter = 'T';
       ERR("Enc not implemented %x", encflags);
       break;
     case 0x40:  /* xB AES */
       encletter = 'B';
       zbuf = zxbus_alloc_zbuf(cf, &zlen, zbuf, len, sig, 16);
       if (!cf->log_symkey[0])
	 zx_get_symkey(cf, "logenc.key", cf->log_symkey);
       AES_set_encrypt_key((unsigned char*)cf->log_symkey, 128, &aes_key);
       memcpy(ivec, zbuf, sizeof(ivec));
       AES_cbc_encrypt((unsigned char*)zbuf+16, (unsigned char*)zbuf+16, zlen-16, &aes_key, (unsigned char*)ivec, 1);
       ROUND_UP(zlen, 16);        /* Round up to block size */
       break;
     case 0x50:  /* xU 3DES */
       encletter = 'U';
       ERR("Enc not implemented %x", encflags);
       break;
     default:
       ERR("Enc not implemented %x", encflags);
       break;
     }

     blen = SIMPLE_BASE64_LEN(zlen) + 3 + 1;
     b64 = ZX_ALLOC(cf->ctx, blen);
     b64[0] = sigletter;
     b64[1] = encletter;
     b64[2] = ' ';
     p = base64_fancy_raw(zbuf, zlen, b64+3, safe_basis_64, 1<<31, 0, 0, '.');
     blen = p-b64 + 1;
     *p = '\n';
     write2_or_append_lock_c_path(c_path, 0, 0, blen, b64, "zxbus enc", SEEK_END, O_APPEND);
     return;
   }

   /* Plain text, possibly signed. */

   switch (encflags & 0x06) {
   case 0x02:   /* SP plain sha1 */
     strcpy(sigbuf, "SP ");
     sha1_safe_base64(sigbuf+3, n-1, logbuf);
     sigbuf[3+27] = ' ';
     len = 3+27+1;
     p = sigbuf;
     break;
   case 0x04:   /* RP RSA-SHA1 signature */
     LOCK(cf->mx, "logsign-wrln");      
     if (!(log_sign_pkey = cf->log_sign_pkey))
       log_sign_pkey = cf->log_sign_pkey = zxid_read_private_key(cf, "logsign-nopw-cert.pem");
     UNLOCK(cf->mx, "logsign-wrln");
     if (!log_sign_pkey)
       break;
zlen = zxsig_data(cf->ctx, n-1, logbuf, &zbuf, log_sign_pkey, "log line", 0);
     len = SIMPLE_BASE64_LEN(zlen) + 4;
     sig = ZX_ALLOC(cf->ctx, len);
     strcpy(sig, "RP ");
     p = base64_fancy_raw(zbuf, zlen, sig+3, safe_basis_64, 1<<31, 0, 0, '.');
     len = p-sig + 1;
     *p = ' ';
     p = sig;
     break;
   case 0x06:   /* DP DSA-SHA1 signature */
     ERR("DSA-SHA1 signature not implemented %x", encflags);
     break;
   case 0:      /* Plain logging, no signing, no encryption. */
     len = 5;
     p = "PP - ";
     break;
   }
   write2_or_append_lock_c_path(c_path, len, p, n, logbuf, "zxbus sig", SEEK_END, O_APPEND);
   if (sig)
     ZX_FREE(cf->ctx, sig);
 }

 /*() Helper function for formatting all kinds of logs. */

 static int zxbus_fmt(zxid_conf* cf,   /* 1 */
		      int len, char* logbuf,
		      struct timeval* ourts,  /* 2 null allowed, will use current time */
		      struct timeval* srcts,  /* 3 null allowed, will use start of unix epoch... */
		      const char* ipport,     /* 4 null allowed, -:- or cf->ipport if not given */
		      struct zx_str* entid,   /* 5 null allowed, - if not given */
		      struct zx_str* msgid,   /* 6 null allowed, - if not given */
		      struct zx_str* a7nid,   /* 7 null allowed, - if not given */
		      struct zx_str* nid,     /* 8 null allowed, - if not given */
		      const char* sigval,     /* 9 null allowed, - if not given */
		      const char* res,        /* 10 */
		      const char* op,         /* 11 */
		      const char* arg,        /* 12 null allowed, - if not given */
		      const char* fmt,        /* 13 null allowed as format, ends the line */
		      va_list ap)
 {
   int n;
   char* p;
   char sha1_name[28];
   struct tm ot;
   struct tm st;
   struct timeval ourtsdefault;
   struct timeval srctsdefault;

   /* Prepare values */

   if (!ourts) {
     ourts = &ourtsdefault;
     GETTIMEOFDAY(ourts, 0);
   }
   if (!srcts) {
     srcts = &srctsdefault;
     srctsdefault.tv_sec = 0;

zxbusprod.c  view on Meta::CPAN

   if (!he) {
     ERR("hostname(%s) did not resolve(%d) bu->s(%s) host_len=%d %d host(%.*s) %p port(%s) %p", bu->m, h_errno, bu->s, host_len, MIN(host_len, ZXBUS_BUF_SIZE-2), host_len, host, host, port, port);
     exit(5);
   }

   memset(&sin, 0, sizeof(sin));
   sin.sin_family = AF_INET;
   sin.sin_port = htons(atoi(port+1));
   memcpy(&(sin.sin_addr.s_addr), he->h_addr, sizeof(sin.sin_addr.s_addr));

   if ((bu->fd = (fdtype)socket(AF_INET, SOCK_STREAM, 0)) == (fdtype)-1) {
     ERR("Unable to create socket(AF_INET, SOCK_STREAM, 0) %d %s", errno, STRERROR(errno));
     return 0;
   }

 #if 0
   nonblock(bu->fd);
   if (nkbuf)
     setkernelbufsizes(bu->fd, nkbuf, nkbuf);
 #endif

   D("connecting(%x) hs(%s)", bu->fd, bu->s);
   if ((connect((SOCKET)bu->fd, (struct sockaddr*)&sin, sizeof(sin)) == -1) && (errno != EINPROGRESS)) {
     ERR("Connection to %s failed: %d %s", bu->s, errno, STRERROR(errno));
     goto errout;
   }

   D("connected(%x) at TCP layer hs(%s)", bu->fd, bu->s);

   if (tls) {
 #ifdef USE_OPENSSL
     if (!cf->ssl_ctx) {
       SSL_load_error_strings();
       SSL_library_init();
 #if 0
       cf->ssl_ctx = SSL_CTX_new(SSLv23_method());
 #else
       cf->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
 #endif
     }
     if (!cf->ssl_ctx) {
       ERR("TLS/SSL connection to(%s) can not be made. SSL context initialization problem", bu->s);
       zx_report_openssl_err("open_bus_url-ssl_ctx");
       goto errout;
     } else {
       if (errmac_debug>1) {
	D("OpenSSL header-version(%lx) lib-version(%lx)(%s) %s %s %s %s", OPENSSL_VERSION_NUMBER, SSLeay(), SSLeay_version(SSLEAY_VERSION), SSLeay_version(SSLEAY_CFLAGS), SSLeay_version(SSLEAY_BUILT_ON), SSLeay_version(SSLEAY_PLATFORM), SSLeay_version(SSLEA...
	SSL_CTX_set_info_callback(cf->ssl_ctx, zx_ssl_info_cb);
      }
      SSL_CTX_set_mode(cf->ssl_ctx, SSL_MODE_AUTO_RETRY);  /* R/W only return when complete. */
      /* Verification strategy: do not attempt verification at SSL layer. Instead
       * check the result afterwards against metadata based cert. */
      SSL_CTX_set_verify(cf->ssl_ctx, SSL_VERIFY_NONE,0);
      //SSL_CTX_set_verify(cf->ssl_ctx, SSL_VERIFY_PEER,0);
      //SSL_CTX_set_cert_verify_callback(cf->ssl_ctx, zxbus_cert_verify_cb, cf);
      /*SSL_CTX_load_verify_locations() SSL_CTX_set_client_CA_list(3) SSL_CTX_set_cert_store(3) */
      LOCK(cf->mx, "logenc wrln");
      if (!cf->enc_cert)
	cf->enc_cert = zxid_read_cert(cf, "enc-nopw-cert.pem");
      if (!cf->enc_pkey)
	cf->enc_pkey = zxid_read_private_key(cf, "enc-nopw-cert.pem");
      UNLOCK(cf->mx, "logenc wrln");
      if (!SSL_CTX_use_certificate(cf->ssl_ctx, cf->enc_cert)) {
	ERR("TLS/SSL connection to(%s) can not be made. SSL certificate problem", bu->s);
	zx_report_openssl_err("open_bus_url-cert");
	goto errout;
      }
      if (!SSL_CTX_use_PrivateKey(cf->ssl_ctx, cf->enc_pkey)) {
	ERR("TLS/SSL connection to(%s) can not be made. SSL private key problem", bu->s);
	zx_report_openssl_err("open_bus_url-privkey");
	goto errout;
      }
      if (!SSL_CTX_check_private_key(cf->ssl_ctx)) {
	ERR("TLS/SSL connection to(%s) can not be made. SSL certificate-private key consistency problem", bu->s);
	zx_report_openssl_err("open_bus_url-chk-privkey");
	goto errout;
      }
      /*SSL_CTX_add_extra_chain_cert(cf->ssl_ctx, ca_cert);*/
    }
    bu->ssl = SSL_new(cf->ssl_ctx);
    if (!bu->ssl) {
      ERR("TLS/SSL connection to(%s) can not be made. SSL object initialization problem", bu->s);
      zx_report_openssl_err("open_bus_url-ssl");
      goto errout;
    }
    if (!SSL_set_fd(bu->ssl, (int)bu->fd)) {
      ERR("TLS/SSL connection to(%s) can not be made. SSL fd(%x) initialization problem", bu->s, bu->fd);
      zx_report_openssl_err("open_bus_url-set_fd");
      goto sslerrout;
    }
    
    switch (vfy_err = SSL_get_error(bu->ssl, SSL_connect(bu->ssl))) {
    case SSL_ERROR_NONE: break;
      /*case SSL_ERROR_WANT_ACCEPT:  documented, but undeclared */
    case SSL_ERROR_WANT_READ:
    case SSL_ERROR_WANT_CONNECT:
    case SSL_ERROR_WANT_WRITE:
    default:
      ERR("TLS/SSL connection to(%s) can not be made. SSL connect or handshake problem (%ld)", bu->s, vfy_err);
      zx_report_openssl_err("open_bus_url-ssl_connect");
      send((SOCKET)bu->fd, SSL_ENCRYPTED_HINT, sizeof(SSL_ENCRYPTED_HINT)-1, 0);
      goto sslerrout;
    }

    if (errmac_debug>1) D("SSL_version(%s) cipher(%s)",SSL_get_version(bu->ssl),SSL_get_cipher(bu->ssl));

    vfy_err = SSL_get_verify_result(bu->ssl);
    switch (vfy_err) {
    case X509_V_OK: break;
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
      D("TLS/SSL connection to(%s) made, but certificate err. (%ld)", bu->s, vfy_err);
      zx_report_openssl_err("open_bus_url-verify_res");
      break;
    default:
      ERR("TLS/SSL connection to(%s) made, but certificate not acceptable. (%ld)", bu->s, vfy_err);
      zx_report_openssl_err("open_bus_url-verify_res");
      goto sslerrout;
    }

    if (!(peer_cert = SSL_get_peer_certificate(bu->ssl))) {
      ERR("TLS/SSL connection to(%s) made, but peer did not send certificate", bu->s);
      zx_report_openssl_err("open_bus_url-peer_cert");
      goto sslerrout;
    }
    meta = zxid_get_ent(cf, bu->eid);
    if (!meta) {
      ERR("Unable to find metadata for eid(%s) in verify peer cert", bu->eid);
      goto sslerrout;
    }
    if (!meta->enc_cert) {
      ERR("Metadata for eid(%s) does not contain enc cert", bu->eid);
      goto sslerrout;
    }



( run in 2.291 seconds using v1.01-cache-2.11-cpan-ad19def0cd9 )