Beispiel #1
0
static void
initialize(void)
{
    /* The data buffer is allocated somewhat larger, so that
     * we can use this extra space (which is allocated in secure memory)
     * as a temporary hash buffer */
    rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
			   : m_alloc_clear(POOLSIZE+BLOCKLEN);
    keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
			   : m_alloc_clear(POOLSIZE+BLOCKLEN);
    is_initialized = 1;
}
Beispiel #2
0
/****************
 * Get the session key from a pubkey enc paket and return
 * it in DEK, which should have been allocated in secure memory.
 */
int
get_session_key( PKT_pubkey_enc *k, DEK *dek )
{
    PKT_secret_key *sk = NULL;
    int rc;

    rc = check_pubkey_algo( k->pubkey_algo );
    if( rc )
	goto leave;

    if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) {
	sk = m_alloc_clear( sizeof *sk );
	sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/
	if( !(rc = get_seckey( sk, k->keyid )) )
	    rc = get_it( k, dek, sk, k->keyid );
    }
    else { /* anonymous receiver: Try all available secret keys */
	void *enum_context = NULL;
	u32 keyid[2];

	for(;;) {
	    if( sk )
		free_secret_key( sk );
	    sk = m_alloc_clear( sizeof *sk );
	    rc=enum_secret_keys( &enum_context, sk, 1);
	    if( rc ) {
		rc = G10ERR_NO_SECKEY;
		break;
	    }
	    if( sk->pubkey_algo != k->pubkey_algo )
		continue;
	    keyid_from_sk( sk, keyid );
	    log_info(_("anonymous receiver; trying secret key %08lX ...\n"),
				     (ulong)keyid[1] );
	    rc = check_secret_key( sk, 1 ); /* ask only once */
	    if( !rc )
		rc = get_it( k, dek, sk, keyid );
	    if( !rc ) {
		log_info(_("okay, we are the anonymous recipient.\n") );
		break;
	    }
	}
	enum_secret_keys( &enum_context, NULL, 0 ); /* free context */
    }

  leave:
    if( sk )
	free_secret_key( sk );
    return rc;
}
Beispiel #3
0
void
mpihelp_mul_karatsuba_case( mpi_ptr_t prodp,
			    mpi_ptr_t up, mpi_size_t usize,
			    mpi_ptr_t vp, mpi_size_t vsize,
			    struct karatsuba_ctx *ctx )
{
    mpi_limb_t cy;

    if( !ctx->tspace || ctx->tspace_size < vsize ) {
	if( ctx->tspace )
	    mpi_free_limb_space( ctx->tspace );
	ctx->tspace = mpi_alloc_limb_space( 2 * vsize,
				       m_is_secure( up ) || m_is_secure( vp ) );
	ctx->tspace_size = vsize;
    }

    MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace );

    prodp += vsize;
    up += vsize;
    usize -= vsize;
    if( usize >= vsize ) {
	if( !ctx->tp || ctx->tp_size < vsize ) {
	    if( ctx->tp )
		mpi_free_limb_space( ctx->tp );
	    ctx->tp = mpi_alloc_limb_space( 2 * vsize, m_is_secure( up )
						      || m_is_secure( vp ) );
	    ctx->tp_size = vsize;
	}

	do {
	    MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace );
	    cy = mpihelp_add_n( prodp, prodp, ctx->tp, vsize );
	    mpihelp_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy );
	    prodp += vsize;
	    up += vsize;
	    usize -= vsize;
	} while( usize >= vsize );
    }

    if( usize ) {
	if( usize < KARATSUBA_THRESHOLD ) {
	    mpihelp_mul( ctx->tspace, vp, vsize, up, usize );
	}
	else {
	    if( !ctx->next ) {
		ctx->next = m_alloc_clear( sizeof *ctx );
	    }
	    mpihelp_mul_karatsuba_case( ctx->tspace,
					vp, vsize,
					up, usize,
					ctx->next );
	}

	cy = mpihelp_add_n( prodp, prodp, ctx->tspace, vsize);
	mpihelp_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy );
    }
}
Beispiel #4
0
KBNODE
make_comment_node( const char *s )
{
    PACKET *pkt;
    size_t n = strlen(s);

    pkt = m_alloc_clear( sizeof *pkt );
    pkt->pkttype = PKT_COMMENT;
    pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 );
    pkt->pkt.comment->len = n;
    strcpy(pkt->pkt.comment->data, s);
    return new_kbnode( pkt );
}
Beispiel #5
0
char *
parser_create_req (char *buff)
{
  char address[16] = { 0 };
  char *ret = NULL;

  struct in_addr tmpaddr;

  strncpy (address, buff, 15);
  if (inet_aton (address, &tmpaddr))
    {
      ret = m_alloc_clear (5 + strlen (address) + 2);
      strcat (ret, "Req: ");
      strcat (ret, address);
      strcat (ret, "\n");
    }
  return ret;
}
Beispiel #6
0
/****************
 * Handle a compressed packet
 */
int
handle_compressed( void *procctx, PKT_compressed *cd,
		   int (*callback)(IOBUF, void *), void *passthru )
{
    compress_filter_context_t *cfx;
    int rc;

    if( cd->algorithm < 1 || cd->algorithm > 2	)
	return G10ERR_COMPR_ALGO;
    cfx = m_alloc_clear (sizeof *cfx);
    cfx->algo = cd->algorithm;
    cfx->release = release_context;
    iobuf_push_filter( cd->buf, compress_filter, cfx );
    if( callback )
	rc = callback(cd->buf, passthru );
    else
	rc = proc_packets(procctx, cd->buf);
    cd->buf = NULL;
    return rc;
}
Beispiel #7
0
KBNODE
make_mpi_comment_node( const char *s, MPI a )
{
    PACKET *pkt;
    byte *buf, *p, *pp;
    unsigned n1, nb1;
    size_t n = strlen(s);

    nb1 = mpi_get_nbits( a );
    p = buf = mpi_get_buffer( a, &n1, NULL );
    pkt = m_alloc_clear( sizeof *pkt );
    pkt->pkttype = PKT_COMMENT;
    pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n + 2 + n1 );
    pkt->pkt.comment->len = n+1+2+n1;
    pp = pkt->pkt.comment->data;
    memcpy(pp, s, n+1);
    pp[n+1] = nb1 >> 8;
    pp[n+2] = nb1 ;
    memcpy(pp+n+3, p, n1 );
    m_free(buf);
    return new_kbnode( pkt );
}
Beispiel #8
0
int
parse_body (char *buffer, int length, struct body_msg *body)
{
  char *tmp = buffer;
  char *end = buffer + length;
  int offset;
  int off;
  char *bodyline;
  char *address;
  uint16_t port = 0;
  size_t keylen;
  struct reg_body *tmp_body = NULL;
  struct id_body *tmp_body1 = NULL;
  struct add_body *tmp_body2 = NULL;
  struct key_body *tmp_body3 = NULL;




/* strip the beginning space */
  for (tmp; ((*tmp == '\n') || (*tmp == '\r'))
       && ((tmp - buffer) < length); tmp++);
  offset = tmp - buffer;
  do
    {
      switch (*tmp)
        {
        case 'U':
        case 'u':
          {
            if (!tmp_body)
              tmp_body = create_reg_body ();
            body->type = BODYREG;
            if (off = check ("USER", 4, tmp, end))
              {
                if (LOG_PARSER)
                  log_info ("Body USER found in %u\n", tmp - buffer);
                offset += off;

                /* find the end of this header */
                offset += find_end (tmp + off, end);

                /* find the user address */
                tmp = tmp + off;
                for (tmp; (*tmp == ' ') && ((tmp) < end); tmp++);

                /* copy it to structure */
                tmp_body->user =
                  (char *) strndup (tmp, buffer + offset - tmp - 1);
                tmp_body->user_len = buffer + offset - tmp - 1;

                if (LOG_PARSER)
                  log_info ("The user is : %s\n", tmp_body->user);
                tmp = buffer + offset;
                break;
              }
          }

        case 'A':
        case 'a':
          {
            if (off = check ("ADDRESS", 7, tmp, end))
              {
                if (!tmp_body)
                  tmp_body = create_reg_body ();
                body->type = BODYREG;
                if (LOG_PARSER)
                  log_info ("Body ADDRESS found in %u\n", tmp - buffer);
                offset += off;

                /* find the end of this header */
                offset += find_end (tmp + off, end);

                /* find the IP address */
                tmp = tmp + off;
                for (tmp; (*tmp == ' ') && ((tmp) < end); tmp++);


                /* copy it to structure */
                tmp_body->ip =
                  (char *) strndup (tmp, buffer + offset - tmp - 1);
                tmp_body->ip_len = buffer + offset - tmp - 1;

                if (LOG_PARSER)
                  log_info ("The IP address is : %s\n", tmp_body->ip);
                tmp = buffer + offset;
                break;
              }
            else if (off = check ("ADDER", 5, tmp, end))
              {
                char *data;
                MPI val = mpi_alloc (0);

                if (!tmp_body2)
                  tmp_body2 = create_add_body ();
                body->type = BODYADD;

                if (LOG_PARSER)
                  log_info ("Body Adder found in %u\n", tmp - buffer);

                offset += off;
                /* find the end of this line */
                offset += find_end (tmp + off, end);

                /* find the adder */
                tmp = tmp + off;
                for (tmp; (*tmp == ' ') && ((tmp) < end); tmp++);
                data = m_alloc_clear (buffer + offset - tmp);
                strncpy (data, tmp, buffer + offset - tmp - 1);

                if (mpi_fromstr (val, data))
                  {
                    mpi_free (val);
                    m_free (data);
                    tmp = buffer + offset;
                    break;
                  }
                tmp_body2->adder[tmp_body2->num] = val;
                (tmp_body2->num)++;
                m_free (data);
                tmp = buffer + offset;
                break;
              }
          }

        case 'P':
        case 'p':
          {
            if (off = check ("PORT", 4, tmp, end))
              {
                if (!tmp_body)
                  tmp_body = create_reg_body ();
                body->type = BODYREG;
                if (LOG_PARSER)
                  log_info ("Body PORT found in %u\n", tmp - buffer);
                offset += off;

                /* find the end of this header */
                offset += find_end (tmp + off, end);

                /* find the user address */
                tmp = tmp + off;
                for (tmp; (*tmp == ' ') && ((tmp) < end); tmp++);
                for (tmp; tmp < (buffer + offset - 1); tmp++)
                  {
                    if ((*tmp - 48) <= 9 && (*tmp - 48) >= 0)
                      port = port * 10 + (*tmp - 48);
                    else
                      {
                        log_error ("Error while changing port to number\n");
                        return 1;
                      }
                  }

                /* copy it to structure */
                tmp_body->port = port;

                if (LOG_PARSER)
                  log_info ("The PORT is : %u\n", port);
                tmp = buffer + offset;
                break;
              }
          }

        case '-':
          {
            if (!tmp_body)
              tmp_body = create_reg_body ();
            body->type = BODYREG;
            if (keylen = check_public_key (tmp, end))
              {
                tmp_body->public_key = (char *) strndup (tmp, keylen);
                tmp_body->pk_len = keylen;

                if (LOG_PARSER)
                  log_info ("We found begin pgp length : %u\n"
                            "%s\n", keylen, strndup (tmp, keylen));
                tmp += (keylen + 1);
              }
          }
          break;

        case 'I':
        case 'i':
          {
            uint32_t address;
            char c;
            if (!tmp_body1)
              tmp_body1 = create_id_body ();
            body->type = BODYID;
            if (off = check ("ID_LIST", 7, tmp, end))
              {
                if (LOG_PARSER)
                  log_info ("Body id list found in %u\n", tmp - buffer);
                offset += off;
                /* find the end of this header */
                offset += find_end (tmp + off, end);

                /* find the id */
                tmp = tmp + off;
                for (tmp; (*tmp == ' ') && ((tmp) < end); tmp++);
                if (sscanf (tmp, "%x%c", &address, &c) == 2)
                  {
                    tmp_body1->id[tmp_body1->num] = address;
                    (tmp_body1->num)++;
                  }
                tmp = buffer + offset;
                break;
              }
          }

        case 'K':
        case 'k':
          {
            int length;
            if (!tmp_body3)
              tmp_body3 = create_key_body ();
            body->type = BODYKEY;
            if (off = check ("KEY", 3, tmp, end))
              {
                if (LOG_PARSER)
                  log_info ("Body key found in %u\n", tmp - buffer);
                offset += off;
                /* find the end of this header */
                offset += find_end (tmp + off, end);

                /* find the key */
                tmp = tmp + off;
                for (tmp; (*tmp == ' ') && ((tmp) < end); tmp++);
                length = buffer + offset - tmp;
                tmp_body3->radmsg = m_alloc (length);
                strncpy (tmp_body3->radmsg, tmp, length - 1);
                tmp_body3->radmsg[length] = '\0';
                tmp_body3->length = length - 1;
                tmp = buffer + offset;
                break;
              }
          }
        default:
          {

            log_error
              ("Other body type is found %c. Dont know what to do in %u\n",
               *tmp, tmp - buffer);
            return 1;
          }
        }
    }
  while (*tmp != '\n' && *tmp != '\r' && tmp < end);

  if (body->type == BODYREG)
    {
      /* check if any field is empty, we need a full one */
      if (!tmp_body->user || !tmp_body->ip || (tmp_body->port == 0)
          || !tmp_body->public_key)
        {

          if (tmp_body->user)
            m_free (tmp_body->user);
          if (tmp_body->ip)
            m_free (tmp_body->ip);
          if (tmp_body->public_key)
            m_free (tmp_body->public_key);
          m_free (tmp_body);
          return 1;
        }
      else
        {

          body->msg.regbody = tmp_body;
          tmp_body = NULL;
          return 0;
        }
    }
  else if (body->type == BODYID)
    {
      body->msg.idbody = tmp_body1;
      tmp_body1 = NULL;
      return 0;
    }
  else if (body->type == BODYADD)
    {
      body->msg.addbody = tmp_body2;
      tmp_body2 = NULL;
      return 0;
    }
  else if (body->type == BODYKEY)
    {
      body->msg.keybody = tmp_body3;
      tmp_body2 = NULL;
      return 0;
    }
  return 1;
}
Beispiel #9
0
int
signature_check2( PKT_signature *sig, MD_HANDLE digest,
		  u32 *r_expiredate, int *r_expired )
{
    PKT_public_key *pk = m_alloc_clear( sizeof *pk );
    int rc=0;

    *r_expiredate = 0;

    /* Sanity check that the md has a context for the hash that the
       sig is expecting.  This can happen if a onepass sig header does
       not match the actual sig, and also if the clearsign "Hash:"
       header is missing or does not match the actual sig. */

    if(!md_algo_present(digest,sig->digest_algo)) {
        log_info(_("WARNING: signature digest conflict in message\n"));
	rc=G10ERR_BAD_SIGN;
    }
    else if( get_pubkey( pk, sig->keyid ) )
	rc = G10ERR_NO_PUBKEY;
    else if(!pk->is_valid && !pk->is_primary)
        rc=G10ERR_BAD_PUBKEY; /* you cannot have a good sig from an
				 invalid subkey */
    else {
	*r_expiredate = pk->expiredate;
	rc = do_check( pk, sig, digest, r_expired );
    }

    free_public_key( pk );

    if( !rc && sig->sig_class < 2 && is_status_enabled() ) {
	/* This signature id works best with DLP algorithms because
	 * they use a random parameter for every signature.  Instead of
	 * this sig-id we could have also used the hash of the document
	 * and the timestamp, but the drawback of this is, that it is
	 * not possible to sign more than one identical document within
	 * one second.	Some remote batch processing applications might
	 * like this feature here */
	MD_HANDLE md;
	u32 a = sig->timestamp;
	int i, nsig = pubkey_get_nsig( sig->pubkey_algo );
	byte *p, *buffer;

	md = md_open( DIGEST_ALGO_RMD160, 0);
	md_putc( digest, sig->pubkey_algo );
	md_putc( digest, sig->digest_algo );
	md_putc( digest, (a >> 24) & 0xff );
	md_putc( digest, (a >> 16) & 0xff );
	md_putc( digest, (a >>	8) & 0xff );
	md_putc( digest,  a	   & 0xff );
	for(i=0; i < nsig; i++ ) {
	    unsigned n = mpi_get_nbits( sig->data[i]);

	    md_putc( md, n>>8);
	    md_putc( md, n );
	    p = mpi_get_buffer( sig->data[i], &n, NULL );
	    md_write( md, p, n );
	    m_free(p);
	}
	md_final( md );
	p = make_radix64_string( md_read( md, 0 ), 20 );
	buffer = m_alloc( strlen(p) + 60 );
	sprintf( buffer, "%s %s %lu",
		 p, strtimestamp( sig->timestamp ), (ulong)sig->timestamp );
	write_status_text( STATUS_SIG_ID, buffer );
	m_free(buffer);
	m_free(p);
	md_close(md);
    }
Beispiel #10
0
void
mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m)
{
    int k;	/* number of elements */
    int t;	/* bit size of largest exponent */
    int i, j, idx;
    MPI *G;	/* table with precomputed values of size 2^k */
    MPI tmp;
  #ifdef USE_BARRETT
    MPI barrett_y, barrett_r1, barrett_r2;
    int barrett_k;
  #endif

    for(k=0; basearray[k]; k++ )
	;
    passert(k);
    for(t=0, i=0; (tmp=exparray[i]); i++ ) {
	/*log_mpidump("exp: ", tmp );*/
	j = mpi_get_nbits(tmp);
	if( j > t )
	    t = j;
    }
    /*log_mpidump("mod: ", m );*/
    passert(i==k);
    passert(t);
    passert( k < 10 );

#ifdef PLUTO
    m_alloc_ptrs_clear(G, 1<<k);
#else
    G = m_alloc_clear( (1<<k) * sizeof *G );
#endif

  #ifdef USE_BARRETT
    barrett_y = init_barrett( m, &barrett_k, &barrett_r1, &barrett_r2 );
  #endif
    /* and calculate */
    tmp =  mpi_alloc( mpi_get_nlimbs(m)+1 );
    mpi_set_ui( res, 1 );
    for(i = 1; i <= t; i++ ) {
	barrett_mulm(tmp, res, res, m, barrett_y, barrett_k,
				       barrett_r1, barrett_r2 );
	idx = build_index( exparray, k, i, t );
	passert( idx >= 0 && idx < (1<<k) );
	if( !G[idx] ) {
	    if( !idx )
		 G[0] = mpi_alloc_set_ui( 1 );
	    else {
		for(j=0; j < k; j++ ) {
		    if( (idx & (1<<j) ) ) {
			if( !G[idx] )
			    G[idx] = mpi_copy( basearray[j] );
			else
			    barrett_mulm( G[idx], G[idx], basearray[j],
					       m, barrett_y, barrett_k, barrett_r1, barrett_r2	);
		    }
		}
		if( !G[idx] )
		    G[idx] = mpi_alloc(0);
	    }
	}
	barrett_mulm(res, tmp, G[idx], m, barrett_y, barrett_k, barrett_r1, barrett_r2	);
    }

    /* cleanup */
    mpi_free(tmp);
  #ifdef USE_BARRETT
    mpi_free(barrett_y);
    mpi_free(barrett_r1);
    mpi_free(barrett_r2);
  #endif
    for(i=0; i < (1<<k); i++ )
	mpi_free(G[i]);
    m_free(G);
}
Beispiel #11
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;
}
Beispiel #12
0
/****************
 * Create a lockfile with the given name and return an object of
 * type DOTLOCK which may be used later to actually do the lock.
 * A cleanup routine gets installed to cleanup left over locks
 * or other files used together with the lockmechanism.
 * Althoug the function is called dotlock, this does not necessarily
 * mean that real lockfiles are used - the function may decide to
 * use fcntl locking.  Calling the function with NULL only install
 * the atexit handler and maybe used to assure that the cleanup
 * is called after all other atexit handlers.
 *
 * Notes: This function creates a lock file in the same directory
 *	  as file_to_lock with the name "file_to_lock.lock"
 *	  A temporary file ".#lk.<hostname>.pid[.threadid] is used.
 *	  This function does nothing for Windoze.
 */
DOTLOCK
create_dotlock( const char *file_to_lock )
{
    static int initialized;
    DOTLOCK h;
    int  fd = -1;
    char pidstr[16];
  #if !defined (HAVE_DOSISH_SYSTEM)
    struct utsname utsbuf;
  #endif
    const char *nodename;
    const char *dirpart;
    int dirpartlen;

    if( !initialized ) {
	atexit( remove_lockfiles );
	initialized = 1;
    }
    if( !file_to_lock )
	return NULL;

    h = m_alloc_clear( sizeof *h );
    if( never_lock ) {
	h->disable = 1;
      #ifdef _REENTRANT
	/* fixme: aquire mutex on all_lockfiles */
      #endif
	h->next = all_lockfiles;
	all_lockfiles = h;
	return h;
    }


#if !defined (HAVE_DOSISH_SYSTEM)
    sprintf( pidstr, "%10d\n", (int)getpid() );
    /* fixme: add the hostname to the second line (FQDN or IP addr?) */

    /* create a temporary file */
    if( uname( &utsbuf ) )
	nodename = "unknown";
    else
	nodename = utsbuf.nodename;

#ifdef __riscos__
    {
        char *iter = (char *) nodename;
        for (; iter[0]; iter++)
            if (iter[0] == '.')
                iter[0] = '/';
    }
#endif /* __riscos__ */

    if( !(dirpart = strrchr( file_to_lock, DIRSEP_C )) ) {
	dirpart = EXTSEP_S;
	dirpartlen = 1;
    }
    else {
	dirpartlen = dirpart - file_to_lock;
	dirpart = file_to_lock;
    }

  #ifdef _REENTRANT
    /* fixme: aquire mutex on all_lockfiles */
  #endif
    h->next = all_lockfiles;
    all_lockfiles = h;

    h->tname = m_alloc( dirpartlen + 6+30+ strlen(nodename) + 11 );
#ifndef __riscos__
    sprintf( h->tname, "%.*s/.#lk%p.%s.%d",
	     dirpartlen, dirpart, h, nodename, (int)getpid() );
#else /* __riscos__ */
    sprintf( h->tname, "%.*s.lk%p/%s/%d",
	     dirpartlen, dirpart, h, nodename, (int)getpid() );
#endif /* __riscos__ */

    do {
	errno = 0;
	fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL,
			  S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
    } while( fd == -1 && errno == EINTR );
    if( fd == -1 ) {
	all_lockfiles = h->next;
	log_error( "failed to create temporary file `%s': %s\n",
					    h->tname, strerror(errno));
	m_free(h->tname);
	m_free(h);
	return NULL;
    }
    if( write(fd, pidstr, 11 ) != 11 ) {
	all_lockfiles = h->next;
      #ifdef _REENTRANT
	/* release mutex */
      #endif
	log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) );
	close(fd);
	unlink(h->tname);
	m_free(h->tname);
	m_free(h);
	return NULL;
    }
    if( close(fd) ) {
	all_lockfiles = h->next;
      #ifdef _REENTRANT
	/* release mutex */
      #endif
	log_error( "error closing `%s': %s\n", h->tname, strerror(errno));
	unlink(h->tname);
	m_free(h->tname);
	m_free(h);
	return NULL;
    }

  #ifdef _REENTRANT
    /* release mutex */
  #endif
#endif
    h->lockname = m_alloc( strlen(file_to_lock) + 6 );
    strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
    return h;
}
Beispiel #13
0
/****************
 * We do not need to use the strongest RNG because we gain no extra
 * security from it - The prime number is public and we could also
 * offer the factors for those who are willing to check that it is
 * indeed a strong prime.
 *
 * mode 0: Standard
 *	1: Make sure that at least one factor is of size qbits.
 */
MPI
generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
		    MPI g, MPI **ret_factors )
{
    int n;  /* number of factors */
    int m;  /* number of primes in pool */
    unsigned fbits; /* length of prime factors */
    MPI *factors; /* current factors */
    MPI *pool;	/* pool of primes */
    MPI q;	/* first prime factor (variable)*/
    MPI prime;	/* prime test value */
    MPI q_factor; /* used for mode 1 */
    byte *perms = NULL;
    int i, j;
    int count1, count2;
    unsigned nprime;
    unsigned req_qbits = qbits; /* the requested q bits size */
    MPI val_2  = mpi_alloc_set_ui( 2 );

    /* find number of needed prime factors */
    for(n=1; (pbits - qbits - 1) / n  >= qbits; n++ )
	;
    n--;
    if( !n || (mode==1 && n < 2) )
	log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits );
    if( mode == 1 ) {
	n--;
	fbits = (pbits - 2*req_qbits -1) / n;
	qbits =  pbits - req_qbits - n*fbits;
    }
    else {
	fbits = (pbits - req_qbits -1) / n;
	qbits = pbits - n*fbits;
    }
    if( DBG_CIPHER )
	log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n",
		    pbits, req_qbits, qbits, fbits, n  );
    prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) /  BITS_PER_MPI_LIMB );
    q = gen_prime( qbits, 0, 0 );
    q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL;

    /* allocate an array to hold the factors + 2 for later usage */
    factors = m_alloc_clear( (n+2) * sizeof *factors );

    /* make a pool of 3n+5 primes (this is an arbitrary value) */
    m = n*3+5;
    if( mode == 1 )
	m += 5; /* need some more for DSA */
    if( m < 25 )
	m = 25;
    pool = m_alloc_clear( m * sizeof *pool );

    /* permutate over the pool of primes */
    count1=count2=0;
    do {
      next_try:
	if( !perms ) {
	    /* allocate new primes */
	    for(i=0; i < m; i++ ) {
		mpi_free(pool[i]);
		pool[i] = NULL;
	    }
	    /* init m_out_of_n() */
	    perms = m_alloc_clear( m );
	    for(i=0; i < n; i++ ) {
		perms[i] = 1;
		pool[i] = gen_prime( fbits, 0, 0 );
		factors[i] = pool[i];
	    }
	}
	else {
	    m_out_of_n( perms, n, m );
	    for(i=j=0; i < m && j < n ; i++ )
		if( perms[i] ) {
		    if( !pool[i] )
			pool[i] = gen_prime( fbits, 0, 0 );
		    factors[j++] = pool[i];
		}
	    if( i == n ) {
		m_free(perms); perms = NULL;
		progress('!');
		goto next_try;	/* allocate new primes */
	    }
	}

	mpi_set( prime, q );
	mpi_mul_ui( prime, prime, 2 );
	if( mode == 1 )
	    mpi_mul( prime, prime, q_factor );
	for(i=0; i < n; i++ )
	    mpi_mul( prime, prime, factors[i] );
	mpi_add_ui( prime, prime, 1 );
	nprime = mpi_get_nbits(prime);
	if( nprime < pbits ) {
	    if( ++count1 > 20 ) {
		count1 = 0;
		qbits++;
		progress('>');
                mpi_free (q);
		q = gen_prime( qbits, 0, 0 );
		goto next_try;
	    }
	}
	else
	    count1 = 0;
	if( nprime > pbits ) {
	    if( ++count2 > 20 ) {
		count2 = 0;
		qbits--;
		progress('<');
                mpi_free (q);
		q = gen_prime( qbits, 0, 0 );
		goto next_try;
	    }
	}
	else
	    count2 = 0;
    } while( !(nprime == pbits && check_prime( prime, val_2 )) );

    if( DBG_CIPHER ) {
	progress('\n');
	log_mpidump( "prime    : ", prime );
	log_mpidump( "factor  q: ", q );
	if( mode == 1 )
	    log_mpidump( "factor q0: ", q_factor );
	for(i=0; i < n; i++ )
	    log_mpidump( "factor pi: ", factors[i] );
	log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) );
	if( mode == 1 )
	    fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) );
	for(i=0; i < n; i++ )
	    fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) );
	progress('\n');
    }

    if( ret_factors ) { /* caller wants the factors */
	*ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
        i = 0;
	if( mode == 1 ) {
	    (*ret_factors)[i++] = mpi_copy( q_factor );
	    for(; i <= n; i++ )
		(*ret_factors)[i] = mpi_copy( factors[i] );
	}
	else {
	    for(; i < n; i++ )
		(*ret_factors)[i] = mpi_copy( factors[i] );
	}
    }

    if( g ) { /* create a generator (start with 3)*/
	MPI tmp   = mpi_alloc( mpi_get_nlimbs(prime) );
	MPI b	  = mpi_alloc( mpi_get_nlimbs(prime) );
	MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) );

	if( mode == 1 )
	    BUG(); /* not yet implemented */
	factors[n] = q;
	factors[n+1] = mpi_alloc_set_ui(2);
	mpi_sub_ui( pmin1, prime, 1 );
	mpi_set_ui(g,2);
	do {
	    mpi_add_ui(g, g, 1);
	    if( DBG_CIPHER ) {
		log_debug("checking g: ");
		mpi_print( stderr, g, 1 );
	    }
	    else
		progress('^');
	    for(i=0; i < n+2; i++ ) {
		/*fputc('~', stderr);*/
		mpi_fdiv_q(tmp, pmin1, factors[i] );
		/* (no mpi_pow(), but it is okay to use this with mod prime) */
		mpi_powm(b, g, tmp, prime );
		if( !mpi_cmp_ui(b, 1) )
		    break;
	    }
	    if( DBG_CIPHER )
		progress('\n');
	} while( i < n+2 );
	mpi_free(factors[n+1]);
	mpi_free(tmp);
	mpi_free(b);
	mpi_free(pmin1);
    }
    if( !DBG_CIPHER )
	progress('\n');

    m_free( factors );	/* (factors are shallow copies) */
    for(i=0; i < m; i++ )
	mpi_free( pool[i] );
    m_free( pool );
    m_free(perms);
    mpi_free(val_2);
    mpi_free(q);
    return prime;
}
Beispiel #14
0
static int
get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
{
    int rc;
    MPI plain_dek  = NULL;
    byte *frame = NULL;
    unsigned n, nframe;
    u16 csum, csum2;

    rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, k->data, sk->skey );
    if( rc )
	goto leave;
    frame = mpi_get_buffer( plain_dek, &nframe, NULL );
    mpi_free( plain_dek ); plain_dek = NULL;

    /* Now get the DEK (data encryption key) from the frame
     *
     * Old versions encode the DEK in in this format (msb is left):
     *
     *	   0  1  DEK(16 bytes)	CSUM(2 bytes)  0  RND(n bytes) 2
     *
     * Later versions encode the DEK like this:
     *
     *	   0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
     *
     * (mpi_get_buffer already removed the leading zero).
     *
     * RND are non-zero randow bytes.
     * A   is the cipher algorithm
     * DEK is the encryption key (session key) with length k
     * CSUM
     */
    if( DBG_CIPHER )
	log_hexdump("DEK frame:", frame, nframe );
    n=0;
    if( n + 7 > nframe )
	{ rc = G10ERR_WRONG_SECKEY; goto leave; }
    if( frame[n] == 1 && frame[nframe-1] == 2 ) {
	log_info(_("old encoding of the DEK is not supported\n"));
	rc = G10ERR_CIPHER_ALGO;
	goto leave;
    }
    if( frame[n] != 2 )  /* somethink is wrong */
	{ rc = G10ERR_WRONG_SECKEY; goto leave; }
    for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
	;
    n++; /* and the zero byte */
    if( n + 4 > nframe )
	{ rc = G10ERR_WRONG_SECKEY; goto leave; }

    dek->keylen = nframe - (n+1) - 2;
    dek->algo = frame[n++];
    if( dek->algo ==  CIPHER_ALGO_IDEA )
	write_status(STATUS_RSA_OR_IDEA);
    rc = check_cipher_algo( dek->algo );
    if( rc ) {
	if( !opt.quiet && rc == G10ERR_CIPHER_ALGO ) {
	    log_info(_("cipher algorithm %d is unknown or disabled\n"),
							    dek->algo);
	}
	dek->algo = 0;
	goto leave;
    }
    if( (dek->keylen*8) != cipher_get_keylen( dek->algo ) ) {
	rc = G10ERR_WRONG_SECKEY;
	goto leave;
    }

    /* copy the key to DEK and compare the checksum */
    csum  = frame[nframe-2] << 8;
    csum |= frame[nframe-1];
    memcpy( dek->key, frame+n, dek->keylen );
    for( csum2=0, n=0; n < dek->keylen; n++ )
	csum2 += dek->key[n];
    if( csum != csum2 ) {
	rc = G10ERR_WRONG_SECKEY;
	goto leave;
    }
    if( DBG_CIPHER )
	log_hexdump("DEK is:", dek->key, dek->keylen );
    /* check that the algo is in the preferences and whether it has expired */
    {
	PKT_public_key *pk = m_alloc_clear( sizeof *pk );
	if( (rc = get_pubkey( pk, keyid )) )
	    log_error("public key problem: %s\n", g10_errstr(rc) );
	else if( !pk->local_id && query_trust_record(pk) )
	    log_error("can't check algorithm against preferences\n");
	else if( dek->algo != CIPHER_ALGO_3DES
	    && !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) {
	    /* Don't print a note while we are not on verbose mode,
	     * the cipher is blowfish and the preferences have twofish
	     * listed */
	    if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
		|| !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM,
						    CIPHER_ALGO_TWOFISH ) )
		log_info(_(
		    "NOTE: cipher algorithm %d not found in preferences\n"),
								 dek->algo );
	}


	if( !rc && pk->expiredate && pk->expiredate <= make_timestamp() ) {
	    log_info(_("NOTE: secret key %08lX expired at %s\n"),
			   (ulong)keyid[1], asctimestamp( pk->expiredate) );
	}

	/* FIXME: check wheter the key has been revoked and display
	 * the revocation reason.  Actually the user should know this himself,
	 * but the sender might not know already and therefor the user
	 * should get a notice that an revoked key has been used to decode
	 * the message.  The user can than watch out for snakes send by
	 * one of those Eves outside his paradise :-)
	 */
	free_public_key( pk );
	rc = 0;
    }


  leave:
    mpi_free(plain_dek);
    m_free(frame);
    return rc;
}
Beispiel #15
0
int exec_write(struct exec_info **info,const char *program,
	       const char *args_in,const char *name,int writeonly,int binary)
{
  int ret=G10ERR_GENERAL;

  if(opt.exec_disable && !opt.no_perm_warn)
    {
      log_info(_("external program calls are disabled due to unsafe "
		 "options file permissions\n"));

      return ret;
    }

#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
  /* There should be no way to get to this spot while still carrying
     setuid privs.  Just in case, bomb out if we are. */
  if(getuid()!=geteuid())
    BUG();
#endif

  if(program==NULL && args_in==NULL)
    BUG();

  *info=m_alloc_clear(sizeof(struct exec_info));

  if(name)
    (*info)->name=m_strdup(name);
  (*info)->binary=binary;
  (*info)->writeonly=writeonly;

  /* Expand the args, if any */
  if(args_in && expand_args(*info,args_in))
    goto fail;

#ifdef EXEC_TEMPFILE_ONLY
  if(!(*info)->use_temp_files)
    {
      log_error(_("this platform requires temp files when calling external "
		  "programs\n"));
      goto fail;
    }

#else /* !EXEC_TEMPFILE_ONLY */

  /* If there are no args, or there are args, but no temp files, we
     can use fork/exec/pipe */
  if(args_in==NULL || (*info)->use_temp_files==0)
    {
      int to[2],from[2];

      if(pipe(to)==-1)
	goto fail;

      if(pipe(from)==-1)
	{
	  close(to[0]);
	  close(to[1]);
	  goto fail;
	}

      if(((*info)->child=fork())==-1)
	{
	  close(to[0]);
	  close(to[1]);
	  close(from[0]);
	  close(from[1]);
	  goto fail;
	}

      if((*info)->child==0)
	{
	  char *shell=getenv("SHELL");

	  if(shell==NULL)
	    shell="/bin/sh";

	  /* I'm the child */

	  /* If the program isn't going to respond back, they get to
             keep their stdout/stderr */
	  if(!(*info)->writeonly)
	    {
	      /* implied close of STDERR */
	      if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1)
		_exit(1);

	      /* implied close of STDOUT */
	      close(from[0]);
	      if(dup2(from[1],STDOUT_FILENO)==-1)
		_exit(1);
	    }

	  /* implied close of STDIN */
	  close(to[1]);
	  if(dup2(to[0],STDIN_FILENO)==-1)
	    _exit(1);

	  if(args_in==NULL)
	    {
	      if(DBG_EXTPROG)
		log_debug("execlp: %s\n",program);

	      execlp(program,program,NULL);
	    }
	  else
	    {
	      if(DBG_EXTPROG)
		log_debug("execlp: %s -c %s\n",shell,(*info)->command);

	      execlp(shell,shell,"-c",(*info)->command,NULL);
	    }

	  /* If we get this far the exec failed.  Clean up and return. */

	  log_error(_("unable to execute %s \"%s\": %s\n"),
		    args_in==NULL?"program":"shell",
		    args_in==NULL?program:shell,
		    strerror(errno));

	  /* This mimics the POSIX sh behavior - 127 means "not found"
             from the shell. */
	  if(errno==ENOENT)
	    _exit(127);

	  _exit(1);
	}

      /* I'm the parent */

      close(to[0]);

      (*info)->tochild=fdopen(to[1],binary?"wb":"w");
      if((*info)->tochild==NULL)
	{
	  close(to[1]);
	  ret=G10ERR_WRITE_FILE;
	  goto fail;
	}

      close(from[1]);

      (*info)->fromchild=iobuf_fdopen(from[0],"r");
      if((*info)->fromchild==NULL)
	{
	  close(from[0]);
	  ret=G10ERR_READ_FILE;
	  goto fail;
	}

      /* fd iobufs are cached?! */
      iobuf_ioctl((*info)->fromchild,3,1,NULL);

      return 0;
    }
#endif /* !EXEC_TEMPFILE_ONLY */

  if(DBG_EXTPROG)
    log_debug("using temp file `%s'\n",(*info)->tempfile_in);

  /* It's not fork/exec/pipe, so create a temp file */
  (*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w");
  if((*info)->tochild==NULL)
    {
      log_error(_("can't create `%s': %s\n"),
		(*info)->tempfile_in,strerror(errno));
      ret=G10ERR_WRITE_FILE;
      goto fail;
    }

  ret=0;

 fail:
  return ret;
}