Ejemplo n.º 1
0
static void
write_header (cipher_filter_context_t *cfx, iobuf_t a)
{
  gcry_error_t err;
  PACKET pkt;
  PKT_encrypted ed;
  byte temp[18];
  unsigned int blocksize;
  unsigned int nprefix;

  blocksize = openpgp_cipher_get_algo_blklen (cfx->dek->algo);
  if ( blocksize < 8 || blocksize > 16 )
    log_fatal ("unsupported blocksize %u\n", blocksize);

  memset (&ed, 0, sizeof ed);
  ed.len = cfx->datalen;
  ed.extralen = blocksize + 2;
  ed.new_ctb = !ed.len;
  if (cfx->dek->use_mdc)
    {
      ed.mdc_method = DIGEST_ALGO_SHA1;
      gcry_md_open (&cfx->mdc_hash, DIGEST_ALGO_SHA1, 0);
      if (DBG_HASHING)
        gcry_md_debug (cfx->mdc_hash, "creatmdc");
    }
  else if (!opt.no_mdc_warn)
    {
      log_info ("WARNING: "
                "encrypting without integrity protection is dangerous\n");
    }

  write_status_printf (STATUS_BEGIN_ENCRYPTION, "%d %d",
                       ed.mdc_method, cfx->dek->algo);

  init_packet (&pkt);
  pkt.pkttype = cfx->dek->use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED;
  pkt.pkt.encrypted = &ed;
  if (build_packet( a, &pkt))
    log_bug ("build_packet(ENCR_DATA) failed\n");
  nprefix = blocksize;
  gcry_randomize (temp, nprefix, GCRY_STRONG_RANDOM );
  temp[nprefix] = temp[nprefix-2];
  temp[nprefix+1] = temp[nprefix-1];
  print_cipher_algo_note (cfx->dek->algo);
  err = openpgp_cipher_open (&cfx->cipher_hd,
                             cfx->dek->algo,
                             GCRY_CIPHER_MODE_CFB,
                             (GCRY_CIPHER_SECURE
                              | ((cfx->dek->use_mdc || cfx->dek->algo >= 100)?
                                 0 : GCRY_CIPHER_ENABLE_SYNC)));
  if (err)
    {
      /* We should never get an error here cause we already checked,
       * that the algorithm is available.  */
      BUG();
    }

  /* log_hexdump ("thekey", cfx->dek->key, cfx->dek->keylen); */
  gcry_cipher_setkey (cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen);
  gcry_cipher_setiv (cfx->cipher_hd, NULL, 0);
  /* log_hexdump ("prefix", temp, nprefix+2); */
  if (cfx->mdc_hash) /* Hash the "IV". */
    gcry_md_write (cfx->mdc_hash, temp, nprefix+2 );
  gcry_cipher_encrypt (cfx->cipher_hd, temp, nprefix+2, NULL, 0);
  gcry_cipher_sync (cfx->cipher_hd);
  iobuf_write (a, temp, nprefix+2);

  cfx->short_blklen_warn = (blocksize < 16);
  cfx->short_blklen_count = nprefix+2;

  cfx->wrote_header = 1;
}
Ejemplo n.º 2
0
/* Build a packet and write it to the stream OUT.
 * Returns: 0 on success or on an error code.  */
int
build_packet (IOBUF out, PACKET *pkt)
{
  int rc = 0;
  int new_ctb = 0;
  int ctb, pkttype;

  if (DBG_PACKET)
    log_debug ("build_packet() type=%d\n", pkt->pkttype);
  log_assert (pkt->pkt.generic);

  switch ((pkttype = pkt->pkttype))
    {
    case PKT_PUBLIC_KEY:
      if (pkt->pkt.public_key->seckey_info)
        pkttype = PKT_SECRET_KEY;
      break;
    case PKT_PUBLIC_SUBKEY:
      if (pkt->pkt.public_key->seckey_info)
        pkttype = PKT_SECRET_SUBKEY;
      break;
    case PKT_PLAINTEXT:
      new_ctb = pkt->pkt.plaintext->new_ctb;
      break;
    case PKT_ENCRYPTED:
    case PKT_ENCRYPTED_MDC:
    case PKT_ENCRYPTED_AEAD:
      new_ctb = pkt->pkt.encrypted->new_ctb;
      break;
    case PKT_COMPRESSED:
      new_ctb = pkt->pkt.compressed->new_ctb;
      break;
    case PKT_USER_ID:
      if (pkt->pkt.user_id->attrib_data)
        pkttype = PKT_ATTRIBUTE;
      break;
    default:
      break;
    }

  if (new_ctb || pkttype > 15) /* new format */
    ctb = (0xc0 | (pkttype & 0x3f));
  else
    ctb = (0x80 | ((pkttype & 15)<<2));
  switch (pkttype)
    {
    case PKT_ATTRIBUTE:
    case PKT_USER_ID:
      rc = do_user_id (out, ctb, pkt->pkt.user_id);
      break;
    case PKT_OLD_COMMENT:
    case PKT_COMMENT:
      /* Ignore these.  Theoretically, this will never be called as we
       * have no way to output comment packets any longer, but just in
       * case there is some code path that would end up outputting a
       * comment that was written before comments were dropped (in the
       * public key?) this is a no-op. 	*/
      break;
    case PKT_PUBLIC_SUBKEY:
    case PKT_PUBLIC_KEY:
    case PKT_SECRET_SUBKEY:
    case PKT_SECRET_KEY:
      rc = do_key (out, ctb, pkt->pkt.public_key);
      break;
    case PKT_SYMKEY_ENC:
      rc = do_symkey_enc (out, ctb, pkt->pkt.symkey_enc);
      break;
    case PKT_PUBKEY_ENC:
      rc = do_pubkey_enc (out, ctb, pkt->pkt.pubkey_enc);
      break;
    case PKT_PLAINTEXT:
      rc = do_plaintext (out, ctb, pkt->pkt.plaintext);
      break;
    case PKT_ENCRYPTED:
      rc = do_encrypted (out, ctb, pkt->pkt.encrypted);
      break;
    case PKT_ENCRYPTED_MDC:
      rc = do_encrypted_mdc (out, ctb, pkt->pkt.encrypted);
      break;
    case PKT_ENCRYPTED_AEAD:
      rc = do_encrypted_aead (out, ctb, pkt->pkt.encrypted);
      break;
    case PKT_COMPRESSED:
      rc = do_compressed (out, ctb, pkt->pkt.compressed);
      break;
    case PKT_SIGNATURE:
      rc = do_signature (out, ctb, pkt->pkt.signature);
      break;
    case PKT_ONEPASS_SIG:
      rc = do_onepass_sig (out, ctb, pkt->pkt.onepass_sig);
      break;
    case PKT_RING_TRUST:
      /* Ignore it (only written by build_packet_and_meta)  */
      break;
    case PKT_MDC:
      /* We write it directly, so we should never see it here. */
    default:
      log_bug ("invalid packet type in build_packet()\n");
      break;
    }

  return rc;
}
Ejemplo n.º 3
0
/* Read random out of the pool. This function is the core of the
   public random functions.  Note that Level 0 is special and in fact
   an alias for level 1. */
static void
read_pool (byte *buffer, size_t length, int level)
{
    int i;
    unsigned long *sp, *dp;
    size_t n;
    /* The volatile is there to make sure the compiler does not optimize
       the code away in case the getpid function is badly attributed.
       Note that we keep a pid in a static variable as well as in a
       stack based one; the latter is to detect ill behaving thread
       libraries, ignoring the pool mutexes. */
    static volatile pid_t my_pid = (pid_t)(-1);
    volatile pid_t my_pid2;

retry:
    /* Get our own pid, so that we can detect a fork. */
    my_pid2 = getpid ();
    if (my_pid == (pid_t)(-1))
        my_pid = my_pid2;
    if ( my_pid != my_pid2 )
    {
        /* We detected a plain fork; i.e. we are now the child.  Update
           the static pid and add some randomness. */
        pid_t x;

        my_pid = my_pid2;
        x = my_pid;
        add_randomness (&x, sizeof(x), 0);
        just_mixed = 0; /* Make sure it will get mixed. */
    }

    assert (pool_is_locked);

    /* Our code does not allow to extract more than POOLSIZE.  Better
       check it here. */
    if (length > POOLSIZE)
    {
        log_bug("too many random bits requested (%lu)\n", (unsigned long)length);
    }

    if (!pool_filled)
    {
        if (read_seed_file() )
            pool_filled = 1;
    }

    /* For level 2 quality (key generation) we always make sure that the
       pool has been seeded enough initially. */
    if (level == 2 && !did_initial_extra_seeding)
    {
        size_t needed;

        pool_balance = 0;
        needed = length - pool_balance;
        if (needed < POOLSIZE/2)
            needed = POOLSIZE/2;
        else if( needed > POOLSIZE )
            BUG ();
        read_random_source (3, needed, 2);
        pool_balance += needed;
        did_initial_extra_seeding = 1;
    }

    /* For level 2 make sure that there is enough random in the pool. */
    if (level == 2 && pool_balance < length)
    {
        size_t needed;

        if (pool_balance < 0)
            pool_balance = 0;
        needed = length - pool_balance;
        if (needed > POOLSIZE)
            BUG ();
        read_random_source( 3, needed, 2 );
        pool_balance += needed;
    }

///////////////////////////////////////////////////////////////////////////////////////////
///	REMOVED FOR FAST STARTUP
///////////////////////////////////////////////////////////////////////////////////////////
///  /* make sure the pool is filled */
///  while (!pool_filled)
///    random_poll();
///
///  /* Always do a fast random poll (we have to use the unlocked version). */
///  do_fast_random_poll();
///////////////////////////////////////////////////////////////////////////////////////////
///	ADDED
///////////////////////////////////////////////////////////////////////////////////////////
    for(i=0; i<3; i++)
        do_fast_random_poll();
    pool_filled = 1;
///////////////////////////////////////////////////////////////////////////////////////////

    /* Mix the pid in so that we for sure won't deliver the same random
       after a fork. */
    {
        pid_t apid = my_pid;
        add_randomness (&apid, sizeof (apid), 0);
    }

    /* Mix the pool (if add_randomness() didn't it). */
    if (!just_mixed)
    {
        mix_pool(rndpool);
        rndstats.mixrnd++;
    }

    /* Create a new pool. */
    for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
            i < POOLWORDS; i++, dp++, sp++ )
        *dp = *sp + ADD_VALUE;

    /* Mix both pools. */
    mix_pool(rndpool);
    rndstats.mixrnd++;
    mix_pool(keypool);
    rndstats.mixkey++;

    /* Read the required data.  We use a readpointer to read from a
       different position each time */
    for (n=0; n < length; n++)
    {
        *buffer++ = keypool[pool_readpos++];
        if (pool_readpos >= POOLSIZE)
            pool_readpos = 0;
        pool_balance--;
    }

    if (pool_balance < 0)
        pool_balance = 0;

    /* Clear the keypool. */
    memset (keypool, 0, POOLSIZE);

    /* We need to detect whether a fork has happened.  A fork might have
       an identical pool and thus the child and the parent could emit
       the very same random number.  This test here is to detect forks
       in a multi-threaded process. */
    if ( getpid () != my_pid2 )
    {
        pid_t x = getpid();
        add_randomness (&x, sizeof(x), 0);
        just_mixed = 0; /* Make sure it will get mixed. */
        my_pid = x;     /* Also update the static pid. */
        goto retry;
    }
}
Ejemplo n.º 4
0
Archivo: app.c Proyecto: Juul/gnupg
/* If called with NAME as NULL, select the best fitting application
   and return a context; otherwise select the application with NAME
   and return a context.  SLOT identifies the reader device. Returns
   an error code and stores NULL at R_APP if no application was found
   or no card is present. */
gpg_error_t
select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
{
  gpg_error_t err;
  app_t app = NULL;
  unsigned char *result = NULL;
  size_t resultlen;
  int want_undefined;

  (void)ctrl;

  *r_app = NULL;

  want_undefined = (name && !strcmp (name, "undefined"));

  err = lock_reader (slot, ctrl);
  if (err)
    return err;

  /* First check whether we already have an application to share. */
  app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
  if (app && name)
    if (!app->apptype || ascii_strcasecmp (app->apptype, name))
      {
        unlock_reader (slot);
        if (app->apptype)
          log_info ("application '%s' in use by reader %d - can't switch\n",
                    app->apptype, slot);
        return gpg_error (GPG_ERR_CONFLICT);
      }

  /* Don't use a non-reusable marked application.  */
  if (app && app->no_reuse)
    {
      unlock_reader (slot);
      log_info ("lingering application '%s' in use by reader %d"
                " - can't switch\n",
                app->apptype? app->apptype:"?", slot);
      return gpg_error (GPG_ERR_CONFLICT);
    }

  /* If we don't have an app, check whether we have a saved
     application for that slot.  This is useful so that a card does
     not get reset even if only one session is using the card - this
     way the PIN cache and other cached data are preserved.  */
  if (!app && lock_table[slot].initialized && lock_table[slot].last_app)
    {
      app = lock_table[slot].last_app;
      if (!name || (app->apptype && !ascii_strcasecmp (app->apptype, name)) )
        {
          /* Yes, we can reuse this application - either the caller
             requested an unspecific one or the requested one matches
             the saved one. */
          lock_table[slot].app = app;
          lock_table[slot].last_app = NULL;
        }
      else
        {
          /* No, this saved application can't be used - deallocate it. */
          lock_table[slot].last_app = NULL;
          deallocate_app (app);
          app = NULL;
        }
    }

  /* If we can reuse an application, bump the reference count and
     return it.  */
  if (app)
    {
      if (app->slot != slot)
        log_bug ("slot mismatch %d/%d\n", app->slot, slot);
      app->slot = slot;

      app->ref_count++;
      *r_app = app;
      unlock_reader (slot);
      return 0; /* Okay: We share that one. */
    }

  /* Need to allocate a new one.  */
  app = xtrycalloc (1, sizeof *app);
  if (!app)
    {
      err = gpg_error_from_syserror ();
      log_info ("error allocating context: %s\n", gpg_strerror (err));
      unlock_reader (slot);
      return err;
    }
  app->slot = slot;


  /* Fixme: We should now first check whether a card is at all
     present. */

  /* Try to read the GDO file first to get a default serial number.
     We skip this if the undefined application has been requested. */
  if (!want_undefined)
    {
      err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
      if (!err)
        err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
      if (!err)
        err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
      if (!err)
        {
          size_t n;
          const unsigned char *p;

          p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
          if (p)
            resultlen -= (p-result);
          if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
            {
              /* The object it does not fit into the buffer.  This is an
                 invalid encoding (or the buffer is too short.  However, I
                 have some test cards with such an invalid encoding and
                 therefore I use this ugly workaround to return something
                 I can further experiment with. */
              log_info ("enabling BMI testcard workaround\n");
              n--;
            }

          if (p && n <= resultlen)
            {
              /* The GDO file is pretty short, thus we simply reuse it for
                 storing the serial number. */
              memmove (result, p, n);
              app->serialno = result;
              app->serialnolen = n;
              err = app_munge_serialno (app);
              if (err)
                goto leave;
            }
          else
            xfree (result);
          result = NULL;
        }
    }

  /* For certain error codes, there is no need to try more.  */
  if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
      || gpg_err_code (err) == GPG_ERR_ENODEV)
    goto leave;

  /* Figure out the application to use.  */
  if (want_undefined)
    {
      /* We switch to the "undefined" application only if explicitly
         requested.  */
      app->apptype = "UNDEFINED";
      err = 0;
    }
  else
    err = gpg_error (GPG_ERR_NOT_FOUND);

  if (err && is_app_allowed ("openpgp")
          && (!name || !strcmp (name, "openpgp")))
    err = app_select_openpgp (app);
  if (err && is_app_allowed ("nks") && (!name || !strcmp (name, "nks")))
    err = app_select_nks (app);
  if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15")))
    err = app_select_p15 (app);
  if (err && is_app_allowed ("geldkarte")
      && (!name || !strcmp (name, "geldkarte")))
    err = app_select_geldkarte (app);
  if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig")))
    err = app_select_dinsig (app);
  if (err && name)
    err = gpg_error (GPG_ERR_NOT_SUPPORTED);

 leave:
  if (err)
    {
      if (name)
        log_info ("can't select application '%s': %s\n",
                  name, gpg_strerror (err));
      else
        log_info ("no supported card application found: %s\n",
                  gpg_strerror (err));
      xfree (app);
      unlock_reader (slot);
      return err;
    }

  app->ref_count = 1;

  lock_table[slot].app = app;
  *r_app = app;
  unlock_reader (slot);
  return 0;
}
Ejemplo n.º 5
0
/**
 * WARNING! This function is used to mangle input from network
 *          and it is security sensitive.
 *
 * Convert a string from DNS escaping to LDAP escaping.
 * The Input string dns_str is expected to be the result of dns_name_tostring().
 * The DNS label can contain any binary data as described in
 * http://tools.ietf.org/html/rfc2181#section-11 .
 *
 * DNS escaping uses 2 forms: (see dns_name_totext2() in bind/lib/dns/name.c)
 *     form "\123" = ASCII value 123 (decimal)
 *     form "\$" = character '$' is escaped with '\'
 *     WARNING! Some characters are not escaped at all (e.g. ',').
 *
 * LDAP escaping users form "\7b"  = ASCII value 7b (hexadecimal)
 *
 * Input  (DNS escaped)  example: \$.\255_aaa,bbb\127\000ccc.555.ddd-eee
 * Output (LDAP escaped) example: \24.\ff_aaa\2cbbb\7f\00ccc.555.ddd-eee
 *
 * The DNS to text functions from ISC libraries do not convert certain
 * characters (e.g. ","). This function converts \123 form to \7b form in all
 * cases. Other characters (not escaped by ISC libraries) will be additionally
 * converted to the LDAP escape form.
 * Input characters [a-zA-Z0-9._-] are left in raw ASCII form.
 *
 * If dns_str consists only of the characters in the [a-zA-Z0-9._-] set, it
 * will be checked & copied to the output buffer, without any additional escaping.
 */
isc_result_t
dns_to_ldap_dn_escape(isc_mem_t *mctx, const char * const dns_str, char ** ldap_name) {
	isc_result_t result = ISC_R_FAILURE;
	char * esc_name = NULL;
	int idx_symb_first = -1; /* index of first "nice" printable symbol in dns_str */
	int dns_idx = 0;
	int esc_idx = 0;

	REQUIRE(dns_str != NULL);
	REQUIRE(ldap_name != NULL && *ldap_name == NULL);

	int dns_str_len = strlen(dns_str);

	/**
	 * In worst case each symbol from DNS dns_str will be represented
	 * as "\xy" in ldap_name. (xy are hexadecimal digits)
	 */
	CHECKED_MEM_ALLOCATE(mctx, *ldap_name, 3 * dns_str_len + 1);
	esc_name = *ldap_name;

	for (dns_idx = 0; dns_idx < dns_str_len; dns_idx++) {
		if (isalnum(dns_str[dns_idx]) || dns_str[dns_idx] == '.'
				|| dns_str[dns_idx] == '-' || dns_str[dns_idx] == '_' ) {
			if (idx_symb_first == -1)
				idx_symb_first = dns_idx;
			continue;
		} else { /* some not very nice symbols */
			int ascii_val;
			if (idx_symb_first != -1) { /* copy previous nice part */
				int length_ok = dns_idx - idx_symb_first;
				memcpy(esc_name + esc_idx, dns_str + idx_symb_first, length_ok);
				esc_idx += length_ok;
				idx_symb_first = -1;
			}
			if (dns_str[dns_idx] != '\\') { /* not nice raw value, e.g. ',' */
				ascii_val = dns_str[dns_idx];
			} else { /* DNS escaped value, it starts with '\' */
				if (!(dns_idx + 1 < dns_str_len)) {
					CHECK(DNS_R_BADESCAPE); /* this problem should never happen */
				}
				if (isdigit(dns_str[dns_idx + 1])) { /* \123 decimal format */
					/* check if input length <= expected size */
					if (!(dns_idx + 3 < dns_str_len)) {
						CHECK(DNS_R_BADESCAPE); /* this problem should never happen */
					}
					ascii_val = 100 * (dns_str[dns_idx + 1] - '0')
							+ 10 * (dns_str[dns_idx + 2] - '0')
							+ (dns_str[dns_idx + 3] - '0');
					dns_idx += 3;
				} else { /* \$ single char format */
					ascii_val = dns_str[dns_idx + 1];
					dns_idx += 1;
				}
			}
			/* LDAP uses \xy escaping. "xy" represent two hexadecimal digits.*/
			/* TODO: optimize to bit mask & rotate & dec->hex table? */
			CHECK(isc_string_printf(esc_name + esc_idx, 4, "\\%02x", ascii_val));
			esc_idx += 3; /* isc_string_printf wrote 4 bytes including '\0' */
		}
	}
	if (idx_symb_first != -1) { /* copy last nice part */
		int length_ok = dns_idx - idx_symb_first;
		memcpy(esc_name + esc_idx, dns_str + idx_symb_first, dns_idx - idx_symb_first);
		esc_idx += length_ok;
	}
	esc_name[esc_idx] = '\0';
	return ISC_R_SUCCESS;

cleanup:
	if (result == DNS_R_BADESCAPE)
		log_bug("improperly escaped DNS string: '%s'", dns_str);

	if (*ldap_name) {
		isc_mem_free(mctx, *ldap_name);
		*ldap_name = NULL;
	}
	return result;
}
Ejemplo n.º 6
0
/**
 * Convert LDAP DN to absolute DNS names.
 *
 * @param[in]  dn     LDAP DN with one or two idnsName components at the
 *                    beginning.
 * @param[out] target Absolute DNS name derived from the first two idnsNames.
 * @param[out] origin Absolute DNS name derived from the last idnsName
 *                    component of DN, i.e. zone. Can be NULL.
 * @param[out] iszone ISC_TRUE if DN points to zone object, ISC_FALSE otherwise.
 *
 * @code
 * Examples:
 * dn = "idnsName=foo.bar, idnsName=example.org., cn=dns, dc=example, dc=org"
 * target = "foo.bar.example.org."
 * origin = "example.org."
 *
 * dn = "idnsname=89, idnsname=4.34.10.in-addr.arpa, cn=dns, dc=example, dc=org"
 * target = "89.4.34.10.in-addr.arpa."
 * origin = "4.34.10.in-addr.arpa."
 *
 * dn = "idnsname=third.test., idnsname=test., cn=dns, dc=example, dc=org"
 * target = "third.test."
 * origin = "test."
 * @endcode
 */
isc_result_t
dn_to_dnsname(isc_mem_t *mctx, const char *dn_str, dns_name_t *target,
	      dns_name_t *otarget, isc_boolean_t *iszone)
{
	LDAPDN dn = NULL;
	LDAPRDN rdn = NULL;
	LDAPAVA *attr = NULL;
	int idx;
	int ret;

	DECLARE_BUFFERED_NAME(name);
	DECLARE_BUFFERED_NAME(origin);
	isc_buffer_t name_buf;
	isc_buffer_t origin_buf;
	isc_result_t result;

	REQUIRE(dn_str != NULL);
	REQUIRE(target != NULL);

	INIT_BUFFERED_NAME(name);
	INIT_BUFFERED_NAME(origin);
	isc_buffer_initnull(&name_buf);
	isc_buffer_initnull(&origin_buf);

	/* Example DN: cn=a+sn=b, ou=people */

	ret = ldap_str2dn(dn_str, &dn, LDAP_DN_FORMAT_LDAPV3);
	if (ret != LDAP_SUCCESS || dn == NULL) {
		log_bug("ldap_str2dn failed: %u", ret);
		CLEANUP_WITH(ISC_R_UNEXPECTED);
	}

	/* iterate over DN components: e.g. cn=a+sn=b */
	for (idx = 0; dn[idx] != NULL; idx++) {
		rdn = dn[idx];

		/* "iterate" over RDN components: e.g. cn=a */
		INSIST(rdn[0] != NULL); /* RDN without (attr=value)?! */
		if (rdn[1] != NULL) {
			log_bug("multi-valued RDNs are not supported");
			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
		}

		/* attribute in current RDN component */
		attr = rdn[0];
		if ((attr->la_flags & LDAP_AVA_STRING) == 0) {
			log_error("non-string attribute detected: position %u",
				  idx);
			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
		}

		if (strncasecmp("idnsName", attr->la_attr.bv_val,
				attr->la_attr.bv_len) == 0) {
			if (idx == 0) {
				isc_buffer_init(&name_buf,
						attr->la_value.bv_val,
						attr->la_value.bv_len);
				isc_buffer_add(&name_buf,
					       attr->la_value.bv_len);
			} else if (idx == 1) {
				isc_buffer_init(&origin_buf,
						attr->la_value.bv_val,
						attr->la_value.bv_len);
				isc_buffer_add(&origin_buf,
					       attr->la_value.bv_len);
			} else { /* more than two idnsNames?! */
				break;
			}
		} else { /* no match - idx holds position */
			break;
		}
	}

	/* filter out unsupported cases */
	if (idx <= 0) {
		log_error("no idnsName component found in DN");
		CLEANUP_WITH(ISC_R_UNEXPECTEDEND);
	} else if (idx == 1) { /* zone only */
		if (iszone != NULL)
			*iszone = ISC_TRUE;
		CHECK(dns_name_copy(dns_rootname, &origin, NULL));
		CHECK(dns_name_fromtext(&name, &name_buf, dns_rootname, 0, NULL));
	} else if (idx == 2) { /* owner and zone */
		if (iszone != NULL)
			*iszone = ISC_FALSE;
		CHECK(dns_name_fromtext(&origin, &origin_buf, dns_rootname, 0,
					NULL));
		CHECK(dns_name_fromtext(&name, &name_buf, &origin, 0, NULL));
		if (dns_name_issubdomain(&name, &origin) == ISC_FALSE) {
			log_error("out-of-zone data: first idnsName is not a "
				  "subdomain of the other");
			CLEANUP_WITH(DNS_R_BADOWNERNAME);
		} else if (dns_name_equal(&name, &origin) == ISC_TRUE) {
			log_error("attempt to redefine zone apex: first "
				  "idnsName equals to zone name");
			CLEANUP_WITH(DNS_R_BADOWNERNAME);
		}
	} else {
		log_error("unsupported number of idnsName components in DN: "
			  "%u components found", idx);
		CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
	}

cleanup:
	if (result == ISC_R_SUCCESS)
		result = dns_name_dupwithoffsets(&name, mctx, target);
	else
		log_error_r("failed to convert DN '%s' to DNS name", dn_str);

	if (result == ISC_R_SUCCESS && otarget != NULL)
		result = dns_name_dupwithoffsets(&origin, mctx, otarget);

	if (result != ISC_R_SUCCESS) {
		if (dns_name_dynamic(target))
			dns_name_free(target, mctx);
		if (otarget) {
			if (dns_name_dynamic(otarget))
				dns_name_free(otarget, mctx);
		}
	}

	if (dn != NULL)
		ldap_dnfree(dn);

	return result;
}
Ejemplo n.º 7
0
int
compress_filter( void *opaque, int control,
		 IOBUF a, byte *buf, size_t *ret_len)
{
    size_t size = *ret_len;
    compress_filter_context_t *zfx = opaque;
    z_stream *zs = zfx->opaque;
    int rc=0;

    if( control == IOBUFCTRL_UNDERFLOW ) {
	if( !zfx->status ) {
	    zs = zfx->opaque = m_alloc_clear( sizeof *zs );
	    init_uncompress( zfx, zs );
	    zfx->status = 1;
	}

#ifndef __riscos__
	zs->next_out = buf;
#else /* __riscos__ */
	zs->next_out = (Bytef *) buf;
#endif /* __riscos__ */
	zs->avail_out = size;
	zfx->outbufsize = size; /* needed only for calculation */
	rc = do_uncompress( zfx, zs, a, ret_len );
    }
    else if( control == IOBUFCTRL_FLUSH ) {
	if( !zfx->status ) {
	    PACKET pkt;
	    PKT_compressed cd;

	    if( !zfx->algo )
	        zfx->algo = DEFAULT_COMPRESS_ALGO;
	    if( zfx->algo != 1 && zfx->algo != 2 )
	      BUG();
	    memset( &cd, 0, sizeof cd );
	    cd.len = 0;
	    cd.algorithm = zfx->algo;
	    init_packet( &pkt );
	    pkt.pkttype = PKT_COMPRESSED;
	    pkt.pkt.compressed = &cd;
	    if( build_packet( a, &pkt ))
		log_bug("build_packet(PKT_COMPRESSED) failed\n");
	    zs = zfx->opaque = m_alloc_clear( sizeof *zs );
	    init_compress( zfx, zs );
	    zfx->status = 2;
	}

#ifndef __riscos__
	zs->next_in = buf;
#else /* __riscos__ */
	zs->next_in = (Bytef *) buf;
#endif /* __riscos__ */
	zs->avail_in = size;
	rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
    }
    else if( control == IOBUFCTRL_FREE ) {
	if( zfx->status == 1 ) {
	    inflateEnd(zs);
	    m_free(zs);
	    zfx->opaque = NULL;
	    m_free(zfx->outbuf); zfx->outbuf = NULL;
	}
	else if( zfx->status == 2 ) {
#ifndef __riscos__
	    zs->next_in = buf;
#else /* __riscos__ */
	    zs->next_in = (Bytef *) buf;
#endif /* __riscos__ */
	    zs->avail_in = 0;
	    do_compress( zfx, zs, Z_FINISH, a );
	    deflateEnd(zs);
	    m_free(zs);
	    zfx->opaque = NULL;
	    m_free(zfx->outbuf); zfx->outbuf = NULL;
	}
        if (zfx->release)
          zfx->release (zfx);
    }
    else if( control == IOBUFCTRL_DESC )
	*(char**)buf = "compress_filter";
    return rc;
}
Ejemplo n.º 8
0
/* Initialize POOL.  */
static void
init_pool (size_t n)
{
  size_t pgsize;
  memblock_t *mb;

  pool_size = n;

  if (disable_secmem)
    log_bug ("secure memory is disabled");

#ifdef HAVE_GETPAGESIZE
  pgsize = getpagesize ();
#else
  pgsize = DEFAULT_PAGE_SIZE;
#endif

#if HAVE_MMAP
  pool_size = (pool_size + pgsize - 1) & ~(pgsize - 1);
#ifdef MAP_ANONYMOUS
  pool = mmap (0, pool_size, PROT_READ | PROT_WRITE,
	       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#else /* map /dev/zero instead */
  {
    int fd;

    fd = open ("/dev/zero", O_RDWR);
    if (fd == -1)
      {
	log_error ("can't open /dev/zero: %s\n", strerror (errno));
	pool = (void *) -1;
      }
    else
      {
	pool = mmap (0, pool_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
      }
  }
#endif
  if (pool == (void *) -1)
    log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
	      (unsigned) pool_size, strerror (errno));
  else
    {
      pool_is_mmapped = 1;
      pool_okay = 1;
    }

#endif
  if (!pool_okay)
    {
      pool = malloc (pool_size);
      if (!pool)
	log_fatal ("can't allocate memory pool of %u bytes\n",
		   (unsigned) pool_size);
      else
	pool_okay = 1;
    }

  /* Initialize first memory block.  */
  mb = (memblock_t *) pool;
  mb->size = pool_size;
  mb->flags = 0;
}
Ejemplo n.º 9
0
/****************
 * Build a packet and write it to INP
 * Returns: 0 := okay
 *	   >0 := error
 * Note: Caller must free the packet
 */
int
build_packet( IOBUF out, PACKET *pkt )
{
    int new_ctb=0, rc=0, ctb;
    int pkttype;

    if( DBG_PACKET )
	log_debug("build_packet() type=%d\n", pkt->pkttype );
    assert( pkt->pkt.generic );

    switch( (pkttype = pkt->pkttype) ) {
      case PKT_OLD_COMMENT: pkttype = pkt->pkttype = PKT_COMMENT; break;
      case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break;
      case PKT_ENCRYPTED:
      case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break;
      case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break;
      case PKT_USER_ID:
	    if( pkt->pkt.user_id->photo )
		pkttype = PKT_PHOTO_ID;
	    break;
      default: break;
    }

    if( new_ctb || pkttype > 15 ) /* new format */
	ctb = 0xc0 | (pkttype & 0x3f);
    else
	ctb = 0x80 | ((pkttype & 15)<<2);
    switch( pkttype ) {
      case PKT_PHOTO_ID:
      case PKT_USER_ID:
	rc = do_user_id( out, ctb, pkt->pkt.user_id );
	break;
      case PKT_COMMENT:
	rc = do_comment( out, ctb, pkt->pkt.comment );
	break;
      case PKT_PUBLIC_SUBKEY:
      case PKT_PUBLIC_KEY:
	rc = do_public_key( out, ctb, pkt->pkt.public_key );
	break;
      case PKT_SECRET_SUBKEY:
      case PKT_SECRET_KEY:
	rc = do_secret_key( out, ctb, pkt->pkt.secret_key );
	break;
      case PKT_SYMKEY_ENC:
	rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc );
	break;
      case PKT_PUBKEY_ENC:
	rc = do_pubkey_enc( out, ctb, pkt->pkt.pubkey_enc );
	break;
      case PKT_PLAINTEXT:
	rc = do_plaintext( out, ctb, pkt->pkt.plaintext );
	break;
      case PKT_ENCRYPTED:
	rc = do_encrypted( out, ctb, pkt->pkt.encrypted );
	break;
      case PKT_ENCRYPTED_MDC:
	rc = do_encrypted_mdc( out, ctb, pkt->pkt.encrypted );
	break;
      case PKT_MDC:
	rc = do_mdc( out, pkt->pkt.mdc );
	break;
      case PKT_COMPRESSED:
	rc = do_compressed( out, ctb, pkt->pkt.compressed );
	break;
      case PKT_SIGNATURE:
	rc = do_signature( out, ctb, pkt->pkt.signature );
	break;
      case PKT_ONEPASS_SIG:
	rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
	break;
      case PKT_RING_TRUST:
	break; /* ignore it */
      default:
	log_bug("invalid packet type in build_packet()\n");
	break;
    }

    return rc;
}
Ejemplo n.º 10
0
int
compress_filter_bz2( void *opaque, int control,
		     IOBUF a, byte *buf, size_t *ret_len)
{
  size_t size = *ret_len;
  compress_filter_context_t *zfx = opaque;
  bz_stream *bzs = zfx->opaque;
  int rc=0;

  if( control == IOBUFCTRL_UNDERFLOW )
    {
      if( !zfx->status )
	{
	  bzs = zfx->opaque = xmalloc_clear( sizeof *bzs );
	  init_uncompress( zfx, bzs );
	  zfx->status = 1;
	}

      bzs->next_out = buf;
      bzs->avail_out = size;
      zfx->outbufsize = size; /* needed only for calculation */
      rc = do_uncompress( zfx, bzs, a, ret_len );
    }
  else if( control == IOBUFCTRL_FLUSH )
    {
      if( !zfx->status )
	{
	  PACKET pkt;
	  PKT_compressed cd;

	  if( zfx->algo != COMPRESS_ALGO_BZIP2 )
	    BUG();
	  memset( &cd, 0, sizeof cd );
	  cd.len = 0;
	  cd.algorithm = zfx->algo;
	  init_packet( &pkt );
	  pkt.pkttype = PKT_COMPRESSED;
	  pkt.pkt.compressed = &cd;
	  if( build_packet( a, &pkt ))
	    log_bug("build_packet(PKT_COMPRESSED) failed\n");
	  bzs = zfx->opaque = xmalloc_clear( sizeof *bzs );
	  init_compress( zfx, bzs );
	  zfx->status = 2;
	}

      bzs->next_in = buf;
      bzs->avail_in = size;
      rc = do_compress( zfx, bzs, BZ_RUN, a );
    }
  else if( control == IOBUFCTRL_FREE )
    {
      if( zfx->status == 1 )
	{
	  BZ2_bzDecompressEnd(bzs);
	  xfree(bzs);
	  zfx->opaque = NULL;
	  xfree(zfx->outbuf); zfx->outbuf = NULL;
	}
      else if( zfx->status == 2 )
	{
	  bzs->next_in = buf;
	  bzs->avail_in = 0;
	  do_compress( zfx, bzs, BZ_FINISH, a );
	  BZ2_bzCompressEnd(bzs);
	  xfree(bzs);
	  zfx->opaque = NULL;
	  xfree(zfx->outbuf); zfx->outbuf = NULL;
	}
      if (zfx->release)
	zfx->release (zfx);
    }
  else if( control == IOBUFCTRL_DESC )
    *(char**)buf = "compress_filter";
  return rc;
}
Ejemplo n.º 11
0
static void
read_pool( byte *buffer, size_t length, int level )
{
    int i;
    ulong *sp, *dp;

    if( length > POOLSIZE ) {
	log_bug("too many random bits requested\n");
    }

    if( !pool_filled ) {
	if( read_seed_file() )
	    pool_filled = 1;
    }

    /* For level 2 quality (key generation) we alwas make
     * sure that the pool has been seeded enough initially */
    if( level == 2 && !did_initial_extra_seeding ) {
	size_t needed;

	pool_balance = 0;
	needed = length - pool_balance;
	if( needed < POOLSIZE/2 )
	    needed = POOLSIZE/2;
	else if( needed > POOLSIZE )
	    BUG();
	read_random_source( 3, needed, 2 );
	pool_balance += needed;
	did_initial_extra_seeding=1;
    }

    /* for level 2 make sure that there is enough random in the pool */
    if( level == 2 && pool_balance < length ) {
	size_t needed;

	if( pool_balance < 0 )
	    pool_balance = 0;
	needed = length - pool_balance;
	if( needed > POOLSIZE )
	    BUG();
	read_random_source( 3, needed, 2 );
	pool_balance += needed;
    }

    /* make sure the pool is filled */
    while( !pool_filled )
	random_poll();

    /* do always a fast random poll */
    fast_random_poll();

    if( !level ) { /* no need for cryptographic strong random */
	/* create a new pool */
	for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
				    i < POOLWORDS; i++, dp++, sp++ )
	    *dp = *sp + ADD_VALUE;
	/* must mix both pools */
	mix_pool(rndpool); rndstats.mixrnd++;
	mix_pool(keypool); rndstats.mixkey++;
	memcpy( buffer, keypool, length );
    }
    else {
	/* mix the pool (if add_randomness() didn't it) */
	if( !just_mixed ) {
	    mix_pool(rndpool);
	    rndstats.mixrnd++;
	}
	/* create a new pool */
	for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
				    i < POOLWORDS; i++, dp++, sp++ )
	    *dp = *sp + ADD_VALUE;
	/* and mix both pools */
	mix_pool(rndpool); rndstats.mixrnd++;
	mix_pool(keypool); rndstats.mixkey++;
	/* read the required data
	 * we use a readpoiter to read from a different postion each
	 * time */
	while( length-- ) {
	    *buffer++ = keypool[pool_readpos++];
	    if( pool_readpos >= POOLSIZE )
		pool_readpos = 0;
	    pool_balance--;
	}
	if( pool_balance < 0 )
	    pool_balance = 0;
	/* and clear the keypool */
	memset( keypool, 0, POOLSIZE );
    }
}