Пример #1
0
void X509Certificate_OpenSSL::write
	(utility::outputStream& os, const Format format) const
{
	BIO* membio = 0;
	int dataSize = 0;
	unsigned char* out = 0;

	if (format == FORMAT_DER)
	{	
		if ((dataSize = i2d_X509(m_data->cert, &out)) < 0)
			goto err;

		os.write(reinterpret_cast <utility::stream::value_type*>(out), dataSize);
		os.flush();
		OPENSSL_free(out);
	}
	else if (format == FORMAT_PEM)
	{
		membio = BIO_new(BIO_s_mem());
		BIO_set_close(membio, BIO_CLOSE);

		if (!PEM_write_bio_X509(membio, m_data->cert))
			goto pem_err;

		dataSize = BIO_get_mem_data(membio, &out);
		os.write(reinterpret_cast <utility::stream::value_type*>(out), dataSize);
		os.flush();
		BIO_vfree(membio);
	}
	else
	{
		throw vmime::exceptions::unsupported_certificate_type("Unknown cert type");
	}

	return; // #### Early Return ####

pem_err:
	{
		if (membio)
			BIO_vfree(membio);
	}

err:
	{
		char errstr[256];
		long ec = ERR_get_error();
		ERR_error_string(ec, errstr);
		throw vmime::exceptions::certificate_exception(
			"OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr));
	}
}
Пример #2
0
static int verify_certificate_chain(X509_STORE_CTX * x509_ctx, void * ignored) {
    qeo_platform_custom_certificate_validator custom_cert_validator_cb = qeo_platform_get_custom_certificate_validator();
    qeo_der_certificate certificate_chain[10];
    BIO* bios[10];
    int rc = 0;

    /** We need access to unchecked chain of certificates
     * No obvious API is found to get a hold of it. The API's available to get certificates
     * expect to do the verification first and only then you can get the chain.
     * As we want to do the validation ourselves, we just pull them out the struct to get
     * the untrusted chain.
     */
    STACK_OF(X509) *sk = x509_ctx->untrusted;

    if (sk) {
        //Lets check the stack.
        qeo_util_retcode_t retcode = QEO_UTIL_EFAIL;
        int certs = sk_X509_num(sk);
        int i;

        if (certs > 10) { //to many certificates;
            //there is also a limit of 10 in openssl for the maximum certificate chain length. We should not hit this; Still better safe then sorry.
            return 0;
        }
        memset(bios, 0, sizeof(BIO*) * 10);
        for (i = 0; i < certs ; i++) {
            int result;
            X509* cert = sk_X509_value(sk, i);
            //create a memory BIO
            BIO *mem = BIO_new(BIO_s_mem());
            if (NULL == mem) {
                goto out; //failed to create BIO
            }
            bios[i] = mem;
            //write to bio int i2d_X509_bio(BIO *bp, X509 *x);
            result = i2d_X509_bio(mem, cert);

            if (result < 0) {
                qeo_log_e("Failed to write certificate data to mem bio %d\n", result);
                goto out;
            }
            // add to array
            certificate_chain[i].size = BIO_get_mem_data(mem, &certificate_chain[i].cert_data);
        }
        //call the callback
        retcode = custom_cert_validator_cb(certificate_chain, certs);
        if (retcode == QEO_UTIL_OK) {
            rc = 1;
        } else {
            qeo_log_e("Custom certificate verification callback returned %d - Treating this as a verification error\n", retcode);
        }
out:
        //free memory
        for (i = 0; i < certs ; i++) {
            if (bios[i])
               BIO_vfree(bios[i]); //we take the void version; not much we can do if the free fails
        }
    }
    return rc;
}
Пример #3
0
audited_err_t audited_init(const char* audit_server_pub_pem)
{
  audited_err_t rv=0;
  BIO *mem=NULL;
  did_init=false;

  if(audit_pub_key) {
    RSA_free(audit_pub_key);
    audit_pub_key=NULL;
  }

  mem = BIO_new_mem_buf((char*)audit_server_pub_pem, -1);
  CHECK(mem, AUDITED_ECRYPTO, "BIO_new_mem_buf");

  audit_pub_key =
    PEM_read_bio_RSA_PUBKEY(mem, NULL, NULL, NULL);
  CHECK(audit_pub_key, AUDITED_EBADKEY,
        "PEM_read_bio_RSA_PUBKEY(%s)", audit_server_pub_pem);
  /* ERR_print_errors_fp(stderr); */

  did_init=true;

 out:
  if(mem) {
    BIO_vfree(mem);
    mem=NULL;
  }
  return rv;
}
Пример #4
0
/* returned pointer is mallocd */
audited_err_t audited_get_audit_server_pub_pem(char **audit_pub_key_pem)
{
  BIO *bio=NULL;
  audited_err_t rv=0;
  int cryptorv;
  size_t len;

  bio = BIO_new(BIO_s_mem());
  CHECK(bio, AUDITED_ECRYPTO, "BIO_new");
  
  cryptorv = PEM_write_bio_RSA_PUBKEY(bio, audit_pub_key);
  CHECK(cryptorv, AUDITED_ECRYPTO, "PEM_write_bio_RSA_PUBKEY");

  /* copy to a plain old mallocd buffer, so that caller can free it */
  clone_mem_bio(bio, (void**)audit_pub_key_pem, &len);
  CHECK(*audit_pub_key_pem, AUDITED_ECRYPTO, "clone_mem_bio");
  (*audit_pub_key_pem)[len] = '\0';

 out:
  if(bio) {
    BIO_vfree(bio);
    bio=NULL;
  }
  if(rv) {
    *audit_pub_key_pem=NULL;
  }
  return rv;
}
Пример #5
0
// static
ref <X509Certificate> X509Certificate::import
	(const byte_t* data, const unsigned int length)
{
	ref <X509Certificate_OpenSSL> cert = vmime::create <X509Certificate_OpenSSL>();

	BIO* membio = BIO_new_mem_buf(const_cast <byte_t*>(data), length);

	if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0))
	{
		BIO_vfree(membio);
		return NULL;
	}

	BIO_vfree(membio);

	return cert;
}
Пример #6
0
void
dpl_profile_free(dpl_ctx_t *ctx)
{
  dpl_conn_pool_destroy(ctx);

  dpl_close_event_log(ctx);

  if (NULL != ctx->pricing)
    dpl_pricing_free(ctx);

  if (1 == ctx->use_https)
    {
      SSL_CTX_free(ctx->ssl_ctx);
      BIO_vfree(ctx->ssl_bio_err);
    }

  /*
   * profile
   */
  if (NULL != ctx->addrlist)
    dpl_addrlist_free(ctx->addrlist);
  if (NULL != ctx->base_path)
    free(ctx->base_path);
  if (NULL != ctx->access_key)
    free(ctx->access_key);
  if (NULL != ctx->secret_key)
    free(ctx->secret_key);
  if (NULL != ctx->ssl_cert_file)
    free(ctx->ssl_cert_file);
  if (NULL != ctx->ssl_key_file)
    free(ctx->ssl_key_file);
  if (NULL != ctx->ssl_password)
    free(ctx->ssl_password);
  if (NULL != ctx->ssl_ca_list)
    free(ctx->ssl_ca_list);
  if (NULL != ctx->pricing)
    free(ctx->pricing);
  if (NULL != ctx->encrypt_key)
    free(ctx->encrypt_key);
  if (NULL != ctx->pricing_dir)
    free(ctx->pricing_dir);

  /**/

  if (NULL != ctx->droplet_dir)
    free(ctx->droplet_dir);
  if (NULL != ctx->profile_name)
    free(ctx->profile_name);

  if (NULL != ctx->cwds)
    dpl_dict_free(ctx->cwds);
  if (NULL != ctx->cur_bucket)
    free(ctx->cur_bucket);

}
Пример #7
0
CryptStream::~CryptStream () {
	sync();
	//
	if (_crypt_bio) {
		if (_mode == WRITE)
			BIO_flush(_crypt_bio);
		BIO_pop(_crypt_bio);
		BIO_vfree(_crypt_bio);
	}
	if (_base64_bio) {
		if (_mode == WRITE)
			BIO_flush(_base64_bio);
		BIO_pop(_base64_bio);
		BIO_vfree(_base64_bio);
	}
	if (_mode == WRITE)
		BIO_flush(_file_bio);
	BIO_pop(_file_bio);
	BIO_vfree(_file_bio);
}
Пример #8
0
	bool HttpAuth::InitPassword(const std::string & strLicense, const char * pFile)
	{
		bool res = false;
		if (pFile)
		{
			BIO * pBio = BIO_new_file(pFile, "r");
			res = InitPassword(strLicense, pBio);
			BIO_vfree(pBio);
		}

		return res;
	}
Пример #9
0
	bool HttpAuth::InitPassword(const std::string & strLicense, void * pPublicKey)
	{
		bool res = false;
		if (pPublicKey)
		{
			BIO * pBio = BIO_new_mem_buf(pPublicKey, (INT32)(strlen((const char *)pPublicKey)));
			res = InitPassword(strLicense , pBio);
			BIO_vfree(pBio);
		}

		return res;
	}
Пример #10
0
int
amqp_ssl_socket_set_key_buffer(amqp_socket_t *base,
                               const char *cert,
                               const void *key,
                               size_t n)
{
  int status = AMQP_STATUS_OK;
  BIO *buf = NULL;
  RSA *rsa = NULL;
  struct amqp_ssl_socket_t *self;
  if (base->klass != &amqp_ssl_socket_class) {
    amqp_abort("<%p> is not of type amqp_ssl_socket_t", base);
  }
  if (n > INT_MAX) {
    return AMQP_STATUS_INVALID_PARAMETER;
  }
  self = (struct amqp_ssl_socket_t *)base;
  status = SSL_CTX_use_certificate_chain_file(self->ctx, cert);
  if (1 != status) {
    return AMQP_STATUS_SSL_ERROR;
  }
  buf = BIO_new_mem_buf((void *)key, (int)n);
  if (!buf) {
    goto error;
  }
  rsa = PEM_read_bio_RSAPrivateKey(buf, NULL, password_cb, NULL);
  if (!rsa) {
    goto error;
  }
  status = SSL_CTX_use_RSAPrivateKey(self->ctx, rsa);
  if (1 != status) {
    goto error;
  }
exit:
  BIO_vfree(buf);
  RSA_free(rsa);
  return status;
error:
  status = AMQP_STATUS_SSL_ERROR;
  goto exit;
}
Пример #11
0
/* Clear datagram connection */
void v_conn_dgram_clear(struct VDgramConn *dgram_conn)
{
	/* Debug print */
	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "Free connection ");
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "%d ", dgram_conn->host_id);
		v_print_addr_port(VRS_PRINT_DEBUG_MSG, &dgram_conn->peer_address);
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");
	}

#ifdef WITH_OPENSSL
	if(dgram_conn->io_ctx.bio != NULL) {
		BIO_vfree(dgram_conn->io_ctx.bio);
		dgram_conn->io_ctx.bio = NULL;
	}
#endif

	close(dgram_conn->io_ctx.sockfd);

	v_conn_dgram_init(dgram_conn);
}
Пример #12
0
static int def_load_bio(CONF *conf, BIO *in, long *line)
{
/* The macro BUFSIZE conflicts with a system macro in VxWorks */
#define CONFBUFSIZE     512
    int bufnum = 0, i, ii;
    BUF_MEM *buff = NULL;
    char *s, *p, *end;
    int again;
    long eline = 0;
    char btmp[DECIMAL_SIZE(eline) + 1];
    CONF_VALUE *v = NULL, *tv;
    CONF_VALUE *sv = NULL;
    char *section = NULL, *buf;
    char *start, *psection, *pname;
    void *h = (void *)(conf->data);
    STACK_OF(BIO) *biosk = NULL;
#ifndef OPENSSL_NO_POSIX_IO
    char *dirpath = NULL;
    OPENSSL_DIR_CTX *dirctx = NULL;
#endif

    if ((buff = BUF_MEM_new()) == NULL) {
        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
        goto err;
    }

    section = OPENSSL_strdup("default");
    if (section == NULL) {
        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (_CONF_new_data(conf) == 0) {
        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    sv = _CONF_new_section(conf, section);
    if (sv == NULL) {
        CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
        goto err;
    }

    bufnum = 0;
    again = 0;
    for (;;) {
        if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
            CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
            goto err;
        }
        p = &(buff->data[bufnum]);
        *p = '\0';
 read_retry:
        BIO_gets(in, p, CONFBUFSIZE - 1);
        p[CONFBUFSIZE - 1] = '\0';
        ii = i = strlen(p);
        if (i == 0 && !again) {
            /* the currently processed BIO is at EOF */
            BIO *parent;

#ifndef OPENSSL_NO_POSIX_IO
            /* continue processing with the next file from directory */
            if (dirctx != NULL) {
                BIO *next;

                if ((next = get_next_file(dirpath, &dirctx)) != NULL) {
                    BIO_vfree(in);
                    in = next;
                    goto read_retry;
                } else {
                    OPENSSL_free(dirpath);
                    dirpath = NULL;
                }
            }
#endif
            /* no more files in directory, continue with processing parent */
            if ((parent = sk_BIO_pop(biosk)) == NULL) {
                /* everything processed get out of the loop */
                break;
            } else {
                BIO_vfree(in);
                in = parent;
                goto read_retry;
            }
        }
        again = 0;
        while (i > 0) {
            if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
                break;
            else
                i--;
        }
        /*
         * we removed some trailing stuff so there is a new line on the end.
         */
        if (ii && i == ii)
            again = 1;          /* long line */
        else {
            p[i] = '\0';
            eline++;            /* another input line */
        }

        /* we now have a line with trailing \r\n removed */

        /* i is the number of bytes */
        bufnum += i;

        v = NULL;
        /* check for line continuation */
        if (bufnum >= 1) {
            /*
             * If we have bytes and the last char '\\' and second last char
             * is not '\\'
             */
            p = &(buff->data[bufnum - 1]);
            if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
                bufnum--;
                again = 1;
            }
        }
        if (again)
            continue;
        bufnum = 0;
        buf = buff->data;

        clear_comments(conf, buf);
        s = eat_ws(conf, buf);
        if (IS_EOF(conf, *s))
            continue;           /* blank line */
        if (*s == '[') {
            char *ss;

            s++;
            start = eat_ws(conf, s);
            ss = start;
 again:
            end = eat_alpha_numeric(conf, ss);
            p = eat_ws(conf, end);
            if (*p != ']') {
                if (*p != '\0' && ss != p) {
                    ss = p;
                    goto again;
                }
                CONFerr(CONF_F_DEF_LOAD_BIO,
                        CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
                goto err;
            }
            *end = '\0';
            if (!str_copy(conf, NULL, &section, start))
                goto err;
            if ((sv = _CONF_get_section(conf, section)) == NULL)
                sv = _CONF_new_section(conf, section);
            if (sv == NULL) {
                CONFerr(CONF_F_DEF_LOAD_BIO,
                        CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
                goto err;
            }
            continue;
        } else {
            pname = s;
            end = eat_alpha_numeric(conf, s);
            if ((end[0] == ':') && (end[1] == ':')) {
                *end = '\0';
                end += 2;
                psection = pname;
                pname = end;
                end = eat_alpha_numeric(conf, end);
            } else {
                psection = section;
            }
            p = eat_ws(conf, end);
            if (strncmp(pname, ".include", 8) == 0
                && (p != pname + 8 || *p == '=')) {
                char *include = NULL;
                BIO *next;

                if (*p == '=') {
                    p++;
                    p = eat_ws(conf, p);
                }
                trim_ws(conf, p);
                if (!str_copy(conf, psection, &include, p))
                    goto err;
                /* get the BIO of the included file */
#ifndef OPENSSL_NO_POSIX_IO
                next = process_include(include, &dirctx, &dirpath);
                if (include != dirpath) {
                    /* dirpath will contain include in case of a directory */
                    OPENSSL_free(include);
                }
#else
                next = BIO_new_file(include, "r");
                OPENSSL_free(include);
#endif
                if (next != NULL) {
                    /* push the currently processing BIO onto stack */
                    if (biosk == NULL) {
                        if ((biosk = sk_BIO_new_null()) == NULL) {
                            CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                            goto err;
                        }
                    }
                    if (!sk_BIO_push(biosk, in)) {
                        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                        goto err;
                    }
                    /* continue with reading from the included BIO */
                    in = next;
                }
                continue;
            } else if (*p != '=') {
                CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN);
                goto err;
            }
            *end = '\0';
            p++;
            start = eat_ws(conf, p);
            trim_ws(conf, start);

            if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) {
                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            v->name = OPENSSL_strdup(pname);
            v->value = NULL;
            if (v->name == NULL) {
                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            if (!str_copy(conf, psection, &(v->value), start))
                goto err;

            if (strcmp(psection, section) != 0) {
                if ((tv = _CONF_get_section(conf, psection))
                    == NULL)
                    tv = _CONF_new_section(conf, psection);
                if (tv == NULL) {
                    CONFerr(CONF_F_DEF_LOAD_BIO,
                            CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
                    goto err;
                }
            } else
                tv = sv;
            if (_CONF_add_string(conf, tv, v) == 0) {
                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            v = NULL;
        }
    }
    BUF_MEM_free(buff);
    OPENSSL_free(section);
    /*
     * No need to pop, since we only get here if the stack is empty.
     * If this causes a BIO leak, THE ISSUE IS SOMEWHERE ELSE!
     */
    sk_BIO_free(biosk);
    return 1;
 err:
    BUF_MEM_free(buff);
    OPENSSL_free(section);
    /*
     * Since |in| is the first element of the stack and should NOT be freed
     * here, we cannot use sk_BIO_pop_free().  Instead, we pop and free one
     * BIO at a time, making sure that the last one popped isn't.
     */
    while (sk_BIO_num(biosk) > 0) {
        BIO *popped = sk_BIO_pop(biosk);
        BIO_vfree(in);
        in = popped;
    }
    sk_BIO_free(biosk);
#ifndef OPENSSL_NO_POSIX_IO
    OPENSSL_free(dirpath);
    if (dirctx != NULL)
        OPENSSL_DIR_end(&dirctx);
#endif
    if (line != NULL)
        *line = eline;
    BIO_snprintf(btmp, sizeof(btmp), "%ld", eline);
    ERR_add_error_data(2, "line ", btmp);
    if (h != conf->data) {
        CONF_free(conf->data);
        conf->data = NULL;
    }
    if (v != NULL) {
        OPENSSL_free(v->name);
        OPENSSL_free(v->value);
        OPENSSL_free(v);
    }
    return 0;
}
Пример #13
0
int cert_verify_file(
    CERT_SIGS* signatures, const char* origFile, const char* trustLocation
) {
    MD5_CTX md5CTX;
    int rbytes;
    unsigned char md5_md[MD5_DIGEST_LENGTH],  rbuf[2048];
    char buf[256];
    char fbuf[MAXPATHLEN];
    int verified = false;
    int file_counter = 0;
    DATA_BLOCK sig_db;
    BIO *bio;
    X509 *cert;
    X509_NAME *subj;

    if (signatures->signatures.size() == 0) {
        printf("No signatures available for file ('%s').\n", origFile);
        fflush(stdout);
        return false;
    }
    SSL_library_init();
    if (!is_file(origFile)) return false;
    FILE* of = boinc_fopen(origFile, "r");
    if (!of) return false;
    MD5_Init(&md5CTX);
    while (0 != (rbytes = (int)fread(rbuf, 1, sizeof(rbuf), of))) {
	    MD5_Update(&md5CTX, rbuf, rbytes);
    }
    MD5_Final(md5_md, &md5CTX);
    fclose(of);
    for(unsigned int i=0;i < signatures->signatures.size(); i++) {
        sig_db.data = (unsigned char*)calloc(128, sizeof(char));
        if (sig_db.data == NULL) {
            printf("Cannot allocate 128 bytes for signature buffer\n");
            return false;
        }
        sig_db.len=128;
        sscan_hex_data(signatures->signatures.at(i).signature, sig_db);
        file_counter = 0;
        while (1) {
            snprintf(fbuf, MAXPATHLEN, "%s/%s.%d", trustLocation, signatures->signatures.at(i).hash,
                file_counter);
#ifndef _USING_FCGI_
            FILE *f = fopen(fbuf, "r");
#else
            FCGI_FILE *f = FCGI::fopen(fbuf, "r");
#endif 
            if (f==NULL)
                break;
            fclose(f);
            bio = BIO_new(BIO_s_file());
            BIO_read_filename(bio, fbuf);
            if (NULL == (cert = PEM_read_bio_X509(bio, NULL, 0, NULL))) {
        	    BIO_vfree(bio);
                printf("Cannot read certificate ('%s')\n", fbuf);
                file_counter++;
        	    continue;
            }
            fflush(stdout);
            subj = X509_get_subject_name(cert);
            X509_NAME_oneline(subj, buf, 256);
            // ???
            //X509_NAME_free(subj);
            X509_free(cert);
    	    BIO_vfree(bio);
            if (strcmp(buf, signatures->signatures.at(i).subject)) {
                printf("Subject does not match ('%s' <-> '%s')\n", buf, signatures->signatures.at(i).subject);
                file_counter++;
                continue;
            } 
            verified = check_validity_of_cert(fbuf, md5_md, sig_db.data, 128, trustLocation);
            if (verified) 
                break;
            file_counter++;
        }
        free(sig_db.data);
        if (!verified)
            return false;
    }
    return verified;
}
Пример #14
0
int check_validity_of_cert(
    const char *cFile, const unsigned char *md5_md, unsigned char *sfileMsg,
    const int sfsize, const char* caPath
) {
    int retval = 0;
    X509 *cert;
    X509_STORE *store;
    X509_LOOKUP *lookup;
    X509_STORE_CTX *ctx = 0;
    EVP_PKEY *pubKey;
    BIO *bio;

    bio = BIO_new(BIO_s_file());
    BIO_read_filename(bio, cFile);
    if (NULL == (cert = PEM_read_bio_X509(bio, NULL, 0, NULL))) {
	    BIO_vfree(bio);
	    return 0;
    }
    // verify certificate
    store = X509_STORE_new();
    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
    X509_LOOKUP_add_dir(lookup, (char *)caPath, X509_FILETYPE_PEM);
    if ((ctx = X509_STORE_CTX_new()) != 0) {
        if (X509_STORE_CTX_init(ctx, store, cert, 0) == 1)
            retval = X509_verify_cert(ctx);
        X509_STORE_CTX_free(ctx);
    }
    X509_STORE_free(store);
    
    if (retval != 1) {
        fprintf(stderr,"ERROR: Cannot verify certificate ('%s')\n", cFile);
        return 0;
    }        
    pubKey = X509_get_pubkey(cert);
    if (!pubKey) {
        X509_free(cert);
        BIO_vfree(bio);
        return 0;
    }
    if (pubKey->type == EVP_PKEY_RSA) {
        BN_CTX *c = BN_CTX_new();
        if (!c) {
	        X509_free(cert);
	        EVP_PKEY_free(pubKey);
	        BIO_vfree(bio);
	        return 0;
	    }
	    if (!RSA_blinding_on(pubKey->pkey.rsa, c)) {
	        X509_free(cert);
	        EVP_PKEY_free(pubKey);
	        BIO_vfree(bio);
	        BN_CTX_free(c);
	        return 0;
	    }
	    retval = RSA_verify(NID_md5, md5_md, MD5_DIGEST_LENGTH, sfileMsg, sfsize, pubKey->pkey.rsa);
	    RSA_blinding_off(pubKey->pkey.rsa);
	    BN_CTX_free(c);
    }
    if (pubKey->type == EVP_PKEY_DSA) {
        fprintf(stderr, "ERROR: DSA keys are not supported.\n");
        return 0;
    }
    EVP_PKEY_free(pubKey);
    X509_free(cert);
    BIO_vfree(bio);
    return retval;
}
Пример #15
0
/** Add a DSA key to the tspc key file
 *
 * @param dsa        the DSA param pointer filled with our key info
 * @param host       the hostname of the corresponding broker
 * @param filename   the keyfile to use
 *
 * @return  0 if error
 *          1 if ok
 *
 */
int
add_dsakey_to_keyfile(DSA *dsa, char *host, char *filename, tBoolean autoaccept)
{

  FILE *fp = NULL;
  Buffer buf;
  char *str = NULL;
  int ret = 0;

  switch (is_dsakey_in_keyfile(dsa, host, filename)) {

  case 0:
    Display(LOG_LEVEL_3, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_ERR_IN_KEY_VERIF);
    Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED);
    break;
  case 1: /* not in, we add and continue */
#if defined(WIN32) && !defined(WINCE)
// When running as a service we can't ask user
// permission. Compromise and accept the key auto
//
    if (!IsService && !autoaccept)
    {
#else
    if (!autoaccept)
    {
#endif
      if (!ask(GOGO_STR_UNKNOWN_HOST_ADD_KEY, host))
      {
        Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED_USER);
        break;
      }
    }
    else
  Display(LOG_LEVEL_1, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_SERVER_KEY_AUTO_ADDED);

    Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_ACCEPTED_ADDED);

    buffer_init(&buf);
    if (buf.buf == NULL)
      break;
    buffer_put_cstring(&buf, "ssh-dss");
    buffer_put_bignum(&buf, dsa->p);
    buffer_put_bignum(&buf, dsa->q);
    buffer_put_bignum(&buf, dsa->g);
    buffer_put_bignum(&buf, dsa->pub_key);

    if ( (str = pal_malloc(2 * buffer_len(&buf))) == NULL)
      break;

    if ( (base64encode(str, buffer_ptr(&buf), (int) buffer_len(&buf))) < 1)
      break;

    fp = fopen(filename, "a");
    if (fp) {
      fprintf(fp, "%s ssh-dss %s\n", host, str);
      fclose(fp);
      ret = 1;
    }
    buffer_free(&buf);
    pal_free(str);
    break;
  case 2: /* in and matching correctly, hurray */
    Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_MATCHING_KEY_FOUND_USED);
    ret = 1;
    break;
  case 3: /* in and NOT matching correctly */
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_STORED_LOCAL_KEY_NO_MATCH, filename, host);
  Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED);
    ret = 0;
    break;
  }

  return ret;
}


/**
 * Authenticate to the Migration Broker using PASSDSS-3DES-1
 *
 * Buf_H will contain the data used to validate the server
 * signature. The data is a concatenation of the following parameters,
 * in that order:
 * azname,authname,DH_public_key,pklength,"ssh-dss",p,q,g,z,Y,ssecmask,sbuflen,dh_K
 *
 * @param socket
 * @param user
 * @param passwd
 * @param host
 * @param nt
 *
 * @return
 *
 * @todo DH public key validation  (RFC2631, 2.1.5)
 * @todo Local storage for server public keys
 *
 */
gogoc_status AuthPASSDSS_3DES_1(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list)
{
  DH   *dh = NULL;        /**< client DH key used to exchange key with server */
  DSA  *dsa = NULL; /**< Remote server DSA key public information */
  DSA_SIG *sig = NULL;    /**< DSA signature */
  char authenticate[] = "AUTHENTICATE PASSDSS-3DES-1\r\n";
  char *BufferIn  = NULL;
  char *BufferOut = NULL;
  char *BufferPtr = NULL;
  Buffer BufH;    /**< Buffer to hold data used for signature. */
  Buffer BufSpace;  /**< Space to hold data before/after base64 conversion */
  Buffer *Buf_H = &BufH;
  Buffer *Buf_Space = &BufSpace;
  BIO  *bio_rw = NULL;    /**< Memory buffer bio */
  BIO  *b64= NULL;    /**< Base64 bio */
  BIO  *cipher = NULL;    /**< Symmetric crypto bio */
  BIGNUM *server_pubkey = NULL; /**< received server public DH key */
  BIGNUM *dh_K = NULL;          /**< DH computed shared secret */
  u_char hash[20];  /**< SHA1 hash */
  u_char enc_key[24]; /**< encryption key (3des) */
  u_char enc_iv[8]; /**< initialization vector (3des) */
  u_char int_key[20]; /**< cs integrity key */
  u_char tmphash[40]; /**< temporary hash storage */
  u_char hmac[EVP_MAX_MD_SIZE]; /**< HMAC for integrity of sent data (step L) */
  int  pklength = 0;  /**< length of SSH-style DSA server public key */
  int ssecmask = 0; /**< SASL security layers offered */
  int sbuflen = 0;  /**< maximum server security layer block size */
  char *s = NULL;
  u_char num[3];    /**< Array to manupulate 3 octet number (sbuflen)  */
  /* Temporary variables */
  int  buflen, readlen, keysize, siglength;
  gogoc_status status = STATUS_SUCCESS_INIT;
  sint32_t tsp_status;

/* From draft-newman-sasl-passdss-01.  "This group was taken from the
 * ISAKMP/Oakley specification, and was originally generated by
 * Richard Schroeppel at the University of Arizona.  Properties of
 * this prime are described in [Orm96]"
 */

        /* RFC2409, DH group 2 (second Oakley group) */
  static char *dh_group2=
      "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
      "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
      "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
      "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
      "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
      "FFFFFFFF" "FFFFFFFF";
  static unsigned char dh_g[]={
    0x02,
  };


  /* Initialize Diffie Hellman variables */
  if ((dh = DH_new()) == NULL || (server_pubkey = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Convert dh_group2 and dh_g to BIGNUM type */
  BN_hex2bn(&dh->p, dh_group2);
  dh->g = BN_bin2bn(dh_g,sizeof(dh_g),NULL);
  if ((dh->p == NULL) || (dh->g == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_INITIALIZATION_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  if ((dh_K = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /* Reserve storage for DSA key */
  if ((dsa = DSA_new()) == NULL || (dsa->p = BN_new()) == NULL ||
      (dsa->q = BN_new()) == NULL ||  (dsa->g = BN_new()) == NULL ||
      (dsa->pub_key = BN_new()) == NULL || (dsa->priv_key = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /* Allocate memory for DSA signature */
  if ((sig = DSA_SIG_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Initialize data buffers */
  BufferIn  = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE);
  BufferOut = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE);

  if ((BufferIn == NULL) || (BufferOut == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  buffer_init(Buf_Space);
  buffer_init(Buf_H);
  if (Buf_Space->buf == NULL || Buf_H->buf == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Create a read/write memory BIO. Memory is segment is
   * created and resized as needed. When BIO is destroyed, the
   * memory is freed. */
  bio_rw = BIO_new(BIO_s_mem());
  /* Create a base64 BIO filter */
  b64 = BIO_new(BIO_f_base64());
  if ((bio_rw == NULL) || (b64 == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /*
    Compute the Diffie-Hellman public value "X" as follows.  If
    X has a value of 0, repeat.

         x
    X = g  mod n

    where g = dh_g = 2
          n = dh_group2
    x = DH secret key
    X = DH public key
  */
  if (DH_generate_key(dh) == 0)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_GEN_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }

  /* Validate DH public key (RFC2631, 2.1.5) */

  /* Send  message with SASL mechanism identifier */
  if ( nt->netsend(socket, authenticate, sizeof(authenticate)) == -1 )
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_W_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }

  /* First PASSDSS  message from client to server:
     string azname       ; the user name to login as, may be empty if
                           same as authentication name
     string authname     ; the authentication name
     mpint  X            ; Diffie-Hellman parameter X
  */
  /* azname is empty. Just insert a string length zero */
  buffer_put_int(Buf_Space, 0);
  /* authname */
  buffer_put_cstring(Buf_Space, conf->userid);
  /* DH public key */
  buffer_put_bignum(Buf_Space, dh->pub_key);

  /* At this point, save the buffer into Buf_H. Used later for
   * signature verification. */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), buffer_len(Buf_Space));

  /* Push base64 filter */
  BIO_push(b64, bio_rw);
  /* no newline */
  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  /* Write Buffer content into bio_rw. Buffer will be base64
   * encoded. */
  BIO_write(b64, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space));
  BIO_flush(b64);
  /* Get pointer to the result */
  buflen = BIO_get_mem_data(bio_rw, &BufferPtr);

  // Send data to server, save response in BufferIn.
  if((readlen = nt->netsendrecv(socket,
               BufferPtr, buflen,
               BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }
  /* remove base64 filter */
  BIO_pop(bio_rw);
  buffer_clear(Buf_Space);
  buflen = 0;

  /* Decode response (base64) and extract server response
   *
   * The response format is as follows:

       uint32   pklength   ; length of SSH-style DSA server public key
           (number of bytes up to y, inclusively)
         string "ssh-dss"  ; constant string "ssh-dss" (lower case)
         mpint  p          ; DSA public key parameters
         mpint  q
         mpint  g
         mpint  z            (y in draft)
       mpint    Y          ; Diffie-Hellman parameter Y
       OCTET    ssecmask   ; SASL security layers offered
       3 OCTET  sbuflen    ; maximum server security layer block size
       uint32   siglength  ; length of SSH-style dss signature
           (number of bytes up to s inclusively)
         string "ssh-dss"  ; constant string "ssh-dss" (lower case)
         mpint  r          ; DSA signature parameters
         mpint  s

   */

  buflen = base64decode(BufferOut, BufferIn);

  buffer_append(Buf_Space, BufferOut, buflen);
  /* Get pklength */
  pklength = buffer_get_int(Buf_Space);
  /* Assuming that
   * p, g, and y are 512 bits,
   * q is 160 bits,
   * "ssh-dss" is 7 bytes
   * pklength should be at least 240 bytes.
   */
  if (pklength < 240)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }

  /* Make a copy of (pklength|"ssh-dss"|p|q|g|z) in Buf_H */
  /* Add pklength */
  buffer_put_int(Buf_H, pklength);
  /* Add "ssh-dss"|p|q|g|z */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), pklength);

  /* Get "ssh-dss" string */
  s = buffer_get_string(Buf_Space, (unsigned int*)&buflen);
  pal_free(s); s = NULL;
  /* Get p */
  buffer_get_bignum(Buf_Space, dsa->p);
  /* Get q */
  buffer_get_bignum(Buf_Space, dsa->q);
  /* Get g */
  buffer_get_bignum(Buf_Space, dsa->g);
  /* Get z (pub_key) */
  buffer_get_bignum(Buf_Space, dsa->pub_key);
  /* Get DH public key */
  buffer_get_bignum(Buf_Space, server_pubkey);
  /* Copy in Buf_H for signature verification later */
  buffer_put_bignum(Buf_H, server_pubkey);

  /* Buffer now points at ssecmask (1 octet), followed by
   * sbuflen (3 octets). Make a copy of these 4 octets in Buf_H
   * now, then extract these values. */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), 4);

  /* Get ssecmask */
  ssecmask = buffer_get_octet(Buf_Space);
  /* Get sbuflen
   * Big endian binary unsigned integer */
  buffer_get(Buf_Space, (char *)num, 3);
  sbuflen =  (((u_long)(u_char)(num)[0] << 16) |
        ((u_long)(u_char)(num)[1] << 8) |
        ((u_long)(u_char)(num)[2]));

  /* DSS signature */
  /* Get siglength */
  siglength = buffer_get_int(Buf_Space);
  /* r and s are 20 bytes each, encoded as mpint (2*24)
   * "ssh-dss" is 7 bytes + int32 siglength should be >= 59
   * octets (mpint may have leading zero byte)
   */
  if (siglength < 59)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  /* Get "ssh-dss" string */
  s = buffer_get_string(Buf_Space, (unsigned int*)&buflen);
  pal_free(s); s = NULL;
  /* Get DSA signature r and s*/
  if ((sig->r= BN_new()) == NULL || (sig->s = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Get r */
  buffer_get_bignum(Buf_Space, sig->r);
  /* Get s */
  buffer_get_bignum(Buf_Space, sig->s);

  /* Validate server DH public key  (RFC2631, 2.1.5) */

  {
    if( !add_dsakey_to_keyfile(dsa, conf->server, TSPC_DSA_KEYFILE, conf->no_questions) )
    {
      Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_KEY_VERIF_ERROR);
      status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
      goto error;
    }
  }

  /* Verify that DSA public key belongs to server */

  /* Compute DH shared secret */
  if ((s = calloc(1, DH_size(dh))) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  if( (keysize = DH_compute_key((unsigned char*)s, server_pubkey, dh)) < 0 )
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_SHARED_COMPUTE_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  BN_bin2bn((const unsigned char*)s, keysize, dh_K);
  memset(s, 0, keysize);
  pal_free(s);
  s = NULL;
  Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
    GOGO_STR_DH_SHARED_KEY, BN_bn2hex(dh_K));

  /* Append dh_K in to complete the buffer. Use Buffer to hold
   * result to keep Bf_H intact, since to will be used (without
   * dh_K) to compute HMAC for packet integrity. */
  buffer_clear(Buf_Space);
  buffer_append(Buf_Space, buffer_ptr(Buf_H), buffer_len(Buf_H));
  buffer_put_bignum(Buf_Space, dh_K);

  /* Compute SHA1 hash of Buffer */
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), hash);

  /* Debug information available at level 4 */
 {
   BIGNUM *h;
   h = BN_bin2bn(hash, 20, NULL);
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_SIGNED_HASH, BN_bn2hex(h));
   BN_free(h);
 }
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_DSA_SIGN_R, BN_bn2hex(sig->r));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_DSA_SIGN_S, BN_bn2hex(sig->s));

  // Verify that the DSS signature is a signature of hash.
  switch( DSA_do_verify(hash, sizeof(hash), sig, dsa) )
  {
  case 0:
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_BAD_SIG_FROM_SERVER);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
    break; /* NOTREACHED */

  case 1:  /* correct signature */
    break;

  default: /* -1 on error */
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SIG_VERIF_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
    break; /* NOTREACHED */
  }

  /* Step I: Compute 3DES key and iv */
  /*
    cs-encryption-iv    = SHA1( K || "A" || H )
    sc-encryption-iv    = SHA1( K || "B" || H )
    cs-encryption-key-1 = SHA1( K || "C" || H )
    cs-encryption-key-2 = SHA1( K || cs-encryption-key-1 )
    cs-encryption-key   = cs-encryption-key-1 || cs-encryption-key-2
    sc-encryption-key-1 = SHA1( K || "D" || H )
    sc-encryption-key-2 = SHA1( K || sc-encryption-key-1 )
    sc-encryption-key   = sc-encryption-key-1 || sc-encryption-key-2
    cs-integrity-key    = SHA1( K || "E" || H )
    sc-integrity-key    = SHA1( K || "F" || H )

    K is dh_k in mpint format (string)
    H is hash
  */

  /* Since we won't support SASL security layers, we need to
   * compute the following only:
   * cs-encryption-iv
   * cs-encryption-key
   * cs-integrity-key
   */
  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'A');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash);
  /* Use first 8 octets as iv */
  memcpy(enc_iv, tmphash, 8);

  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'E');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), int_key);

  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'C');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash);
  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_append(Buf_Space, tmphash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash+20);
  /* Use first 24 octets as key */
  memcpy(enc_key, tmphash, 24);
 {
   BIGNUM *enc, *i, *iv;
   enc = BN_bin2bn(enc_key, 24, NULL);
   iv = BN_bin2bn(enc_iv, 8, NULL);
   i = BN_bin2bn(int_key, 20, NULL);

   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_ENC_KEY, BN_bn2hex(enc));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_IV, BN_bn2hex(iv));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_INTEG_KEY, BN_bn2hex(i));
   BN_free(enc);
   BN_free(i);
   BN_free(iv);
 }
  /*
    (J) Create a buffer beginning with a bit mask for the
    selected security layer (it MUST be one offered from server)
    followed by three octets representing the maximum
    cipher-text buffer size (at least 32) the client can accept
    in network byte order.  This is followed by a string
    containing the passphrase.
  */
  buffer_clear(Buf_Space);
  buffer_put_octet(Buf_Space, ssecmask);
  buffer_put_octet(Buf_Space, 0);
  buffer_put_octet(Buf_Space, 0);
  buffer_put_octet(Buf_Space, 0); /**< @bug must be at least 32 */
  buffer_put_cstring(Buf_Space, conf->passwd);

  /*
    (K) Create a buffer containing items (1) through (7)
    immediately followed by the first four octets of (J).
  */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), 4);

  /*
    (L) Compute HMAC-SHA-1 with (K) as the data and the
    cs-integrity- key from step (I) as the key.  This produces a
    20 octet result.
  */
  HMAC(EVP_sha1(), int_key, sizeof(int_key),
       buffer_ptr(Buf_H), buffer_len(Buf_H), hmac, (unsigned int*)&keysize);
  /*
    (M) Create a buffer containing (J) followed by (L) followed
    by an arbitrary number of zero octets as necessary to reach
    the block size of DES and conceal the passphrase length from
    an eavesdropper.
  */
  buffer_append(Buf_Space, hmac, keysize);

  /*
    (N) Apply the triple-DES algorithm to (M) with the first 8
    octets of cs-encryption-iv from step (I) as the
    initialization vector and the first 24 octets of
    cs-encryption-key as the key.
  */
  /*
    Padding is automatically done. From OpenSSL EVP_EncryptInit(3):
    EVP_CIPHER_CTX_set_padding() enables or disables padding. By default
    encryption operations are padded using standard block padding and the
    padding is checked and removed when decrypting.
  */

  /*
    Create BIO filter to encrypt using 3des + convert to
    base64. Result is written in memory BIO.
  */
  /* Erase BIO and buffer memory */
  BIO_reset(bio_rw);
  memset(BufferOut, 0, TSP_AUTH_PASSDSS_BUFFERSIZE);
  memset(BufferIn, 0, TSP_AUTH_PASSDSS_BUFFERSIZE);
  buflen = 0;

  /* Create cipher BIO */
  cipher = BIO_new(BIO_f_cipher());
  BIO_set_cipher(cipher, EVP_des_ede3_cbc(), enc_key, enc_iv, 1);
  /* Assemble filters as cipher->b64->bio_rw */
  BIO_push(cipher, b64);
  BIO_push(b64, bio_rw);

  /* Write Buffer content into bio_rw */
  BIO_write(cipher, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space));
  BIO_flush(cipher);
  /* Get pointer to the result. */
  buflen = BIO_get_mem_data(bio_rw, &BufferPtr);

  /* wipe encryption material */
  memset(enc_key, 0, sizeof(enc_key));
  memset(enc_iv, 0, sizeof(enc_iv));

  /* Send data to server, save response in BufferIn */
  if( (readlen = nt->netsendrecv(socket, BufferPtr, buflen,
       BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }
  tsp_status = tspGetStatusCode(BufferIn);

  // Check if the reply status indicated a broker redirection.
  if( tspIsRedirectStatus(tsp_status) )
  {
    if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK )
    {
      status = make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION);
    }
    else
    {
      // Redirect error.
      status = make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION);
    }
    goto error;
  }

  // Check if authentication was successful.
  switch( tsp_status )
  {
  case TSP_PROTOCOL_SUCCESS:
    break;

  case TSP_PROTOCOL_AUTH_FAILED:
    Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_AUTH_FAILED_USER, conf->userid);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;

  default:
    Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status));
    status = make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR);
    goto error;
  }

  status = STATUS_SUCCESS_INIT;

 error:

  /* Free storage for DSA key */
  if (dsa != NULL) DSA_free(dsa); /* Also frees BIGNUMs inside struct */
  /* DSA signature */
  if (sig != NULL) DSA_SIG_free(sig);
  /* Free Diffie Hellman variables */
  if (dh != NULL) DH_free(dh); /* Also frees BIGNUMs inside struct */
  if (server_pubkey != NULL) BN_free(server_pubkey);
  if (dh_K != NULL) BN_free(dh_K);
  /* Buffers */
  if (Buf_Space->buf != NULL) buffer_free(Buf_Space);
  if (Buf_H->buf != NULL)  buffer_free(Buf_H);
  /* malloc'ed space*/
  if (BufferIn != NULL) pal_free(BufferIn);
  if (BufferOut != NULL) pal_free(BufferOut);
  /* BIOs */
  if (cipher != NULL) BIO_vfree(cipher);
  if (b64 != NULL) BIO_vfree(b64);
  if (bio_rw != NULL) BIO_vfree(bio_rw);
  /* strings buffers */
  if (s != NULL) pal_free(s);

  return status;
}
Пример #16
0
/* handle a file descriptor event */
int httpd_handle_event(fd_set *rset, fd_set *wset, fd_sets_t *fds)
{
   
    struct REQUEST      *req, *prev, *tmp;
    int                 length;
    int opt = 0;
   
    now = time(NULL);

    /* new connection ? */
    if ((rset != NULL) && FD_ISSET(slisten, rset)) {
        req = malloc(sizeof(struct REQUEST));
        if (NULL == req) {
            /* oom: let the request sit in the listen queue */
#ifdef DEBUG
            fprintf(stderr,"oom\n");
#endif
        } else {
            memset(req,0,sizeof(struct REQUEST));
            if ((req->fd = accept(slisten,NULL,&opt)) == -1) {
                if (EAGAIN != errno) {
                    log_error_func(1, LOG_WARNING,"accept",NULL);
                }
                free(req);
            } else {
                fcntl(req->fd,F_SETFL,O_NONBLOCK);
                req->bfd = -1;
                req->state = STATE_READ_HEADER;
                req->ping = now;
                req->lifespan = -1;
                req->next = conns;
                conns = req;
                curr_conn++;
#ifdef DEBUG
                fprintf(stderr,"%03d/%d: new request (%d)\n",req->fd,req->state,curr_conn);
#endif
#ifdef USE_SSL
                if (with_ssl) {
                    open_ssl_session(req);
                }
#endif
                length = sizeof(req->peer);
                if (getpeername(req->fd,(struct sockaddr*)&(req->peer),&length) == -1) {
                    log_error_func(1, LOG_WARNING,"getpeername",NULL);
                    req->state = STATE_CLOSE;
                }
                getnameinfo((struct sockaddr*)&req->peer,length,
                            req->peerhost,64,req->peerserv,8,
                            NI_NUMERICHOST | NI_NUMERICSERV);
#ifdef DEBUG
                fprintf(stderr,"%03d/%d: connect from (%s)\n",
                        req->fd,req->state,req->peerhost);
#endif

                /* host auth callback */
                if (access_check_func != NULL) {
                    if (access_check_func(req->peerhost, NULL) < 0) {
                        /* read request */
                        read_header(req,0);
                        req->ping = now;
                        /* reply with access denied and close connection */
                        mkerror(req,403,0);
                        write_request(req);	     
                        req->state = STATE_CLOSE;
                    }
                }
	 
                FD_SET(req->fd, &fds->rset); 
                if (req->fd > fds->max) {
                    fds->max = req->fd;
                }
            }
        }
    }
    
    /* check active connections */
    for (req = conns, prev = NULL; req != NULL;) {

        /* I/O */
        if ((rset != NULL) && FD_ISSET(req->fd, rset)) {
            if (req->state == STATE_KEEPALIVE) {
                req->state = STATE_READ_HEADER;
            }

            if (req->state == STATE_READ_HEADER) {
                while (read_header(req,0) > 0);
            }
          
            if (req->state == STATE_READ_BODY) {
                while (read_body(req, 0) >0);
            }
            
            req->ping = now;
        }
      
        if ((wset != NULL) && FD_ISSET(req->fd, wset)) {
            write_request(req);
            req->ping = now;
        }

        /* check timeouts */
        if (req->state == STATE_KEEPALIVE) {
            if (now > req->ping + keepalive_time ||
                curr_conn > max_conn * 9 / 10) {
#ifdef DEBUG
                fprintf(stderr,"%03d/%d: keepalive timeout\n",req->fd,req->state);
#endif
                req->state = STATE_CLOSE;
            }
        } else {
            if (now > req->ping + timeout) {
                if ((req->state == STATE_READ_HEADER) ||
                    (req->state == STATE_READ_BODY)) {
                    mkerror(req,408,0);
                } else {
                    log_error_func(0,LOG_INFO,"network timeout",req->peerhost);
                    req->state = STATE_CLOSE;
                }
            }
        }

        /* parsing */
      parsing:
      
        if (req->state == STATE_PARSE_HEADER) {
            parse_request(req, server_host);
        }

        /* body parsing */
        if (req->state == STATE_PARSE_BODY) {
            parse_request_body(req);
        }

        if (req->state == STATE_WRITE_HEADER) {
            /* switch to writing */
            FD_CLR(req->fd, &fds->rset);
            FD_SET(req->fd, &fds->wset);
            
            write_request(req);
        }
        

        /* handle finished requests */
        if (req->state == STATE_FINISHED && !req->keep_alive) {
            req->state = STATE_CLOSE;
        }
        if (req->state == STATE_FINISHED) {
            /* access log hook */
            if (log_request_func != NULL) {
                log_request_func(req, now);
            }

            /* switch to reading */
            FD_CLR(req->fd, &fds->wset);
            FD_SET(req->fd, &fds->rset);
            
            /* cleanup */
            req->auth[0]       = 0;
            req->if_modified   = 0;
            req->if_unmodified = 0;
            req->if_range      = 0;
            req->range_hdr     = NULL;
            req->ranges        = 0;
            if (req->r_start) { 
                free(req->r_start); 
                req->r_start = NULL; 
            }
            if (req->r_end) { 
                free(req->r_end);   
                req->r_end   = NULL; 
            }
            if (req->r_head) { 
                free(req->r_head);  
                req->r_head  = NULL; 
            }
            if (req->r_hlen) { 
                free(req->r_hlen);  
                req->r_hlen  = NULL; 
            }
            list_free(&req->header);
	
            if (req->bfd != -1) {
                close(req->bfd);
                req->bfd  = -1;
            }
	
            /* free memory of response body */
            if ((req->status<400) && (req->body != NULL)) {
                free(req->body);
                req->body = NULL;
            }
            req->written   = 0;
            req->head_only = 0;
            req->rh        = 0;
            req->rb        = 0;
            req->hostname[0] = 0;
            req->path[0]     = 0;
            req->query[0]    = 0;
            req->lifespan = -1;

            if (req->hdata == (req->lreq + req->lbreq)) {
                /* ok, wait for the next one ... */
#ifdef DEBUG
                fprintf(stderr,"%03d/%d: keepalive wait\n",req->fd,req->state);
#endif
                req->state = STATE_KEEPALIVE;
                req->hdata = 0;
                req->lreq  = 0;
                req->lbreq = 0;

#ifdef TCP_CORK
                if (req->tcp_cork == 1) {
                    req->tcp_cork = 0;
#ifdef DEBUG
                    fprintf(stderr,"%03d/%d: tcp_cork=%d\n",req->fd,req->state,req->tcp_cork);
#endif
                    setsockopt(req->fd,SOL_TCP,TCP_CORK,&req->tcp_cork,sizeof(int));
                }
#endif
            } else {
                /* there is a pipelined request in the queue ... */
#ifdef DEBUG
                fprintf(stderr,"%03d/%d: keepalive pipeline\n",req->fd,req->state);
#endif
                req->state = STATE_READ_HEADER;
                memmove(req->hreq,req->hreq + req->lreq + req->lbreq,
                        req->hdata - (req->lreq + req->lbreq));
                req->hdata -= req->lreq + req->lbreq;
                req->lreq  =  0;
                read_header(req,1);
                goto parsing;
            }
        }
      
        /* connections to close */
        if (req->state == STATE_CLOSE) {
            /* access log hook */
            /*if (log_request_func != NULL) {
                log_request_func(req, now);
                }*/

            FD_CLR(req->fd, &fds->rset);
            FD_CLR(req->fd, &fds->wset);
            /* leave max as is */

            /* cleanup */
            close(req->fd);
#ifdef USE_SSL
            if (with_ssl) {
                SSL_free(req->ssl_s);
            }
#endif
            if (req->bfd != -1) {
                close(req->bfd);
#ifdef USE_SSL
                if (with_ssl) {
                    BIO_vfree(req->bio_in);
                }
#endif
            }
	
            curr_conn--;
#ifdef DEBUG
            fprintf(stderr,"%03d/%d: done (%d)\n",req->fd,req->state,curr_conn);
#endif
            /* unlink from list */
            tmp = req;
            if (prev == NULL) {
                conns = req->next;
                req = conns;
            } else {
                prev->next = req->next;
                req = req->next;
            }
            /* free memory  */
            if (tmp->r_start) {
                free(tmp->r_start);
            }
            if (tmp->r_end) {  
                free(tmp->r_end);
            }
            if (tmp->r_head) { 
                free(tmp->r_head);
            }
            if (tmp->r_hlen) { 
                free(tmp->r_hlen);
            }
            list_free(&tmp->header);
            free(tmp);
        } else {
            prev = req;
            req = req->next;
        }
    }

    return 0;
}
Пример #17
0
int dill_tls_attach_client_mem(int s, struct dill_tls_storage *mem,
      int64_t deadline) {
    int err;
    if(dill_slow(!mem)) {err = EINVAL; goto error1;}
    /* Check whether underlying socket is a bytestream. */
    void *q = dill_hquery(s, dill_bsock_type);
    if(dill_slow(!q && errno == ENOTSUP)) {err = EPROTO; goto error1;}
    if(dill_slow(!q)) {err = errno; goto error1;}
    /* Create OpenSSL connection context. */
    dill_tls_init();
    const SSL_METHOD *method = SSLv23_method();
    if(dill_slow(!method)) {err = EFAULT; goto error1;}
    SSL_CTX *ctx = SSL_CTX_new(method);
    if(dill_slow(!ctx)) {err = EFAULT; goto error1;}
    /* Create OpenSSL connection object. */
    SSL *ssl = SSL_new(ctx);
    if(dill_slow(!ssl)) {err = EFAULT; goto error2;}
	  SSL_set_connect_state(ssl);
    /* Create a BIO and attach it to the connection. */
    BIO *bio = dill_tls_new_cbio(mem);
    if(dill_slow(!bio)) {err = errno; goto error3;}
	  SSL_set_bio(ssl, bio, bio);
    /* Take ownership of the underlying socket. */
    s = dill_hown(s);
    if(dill_slow(s < 0)) {err = errno; goto error1;}
    /* Create the object. */
    struct dill_tls_sock *self = (struct dill_tls_sock*)mem;
    self->hvfs.query = dill_tls_hquery;
    self->hvfs.close = dill_tls_hclose;
    self->bvfs.bsendl = dill_tls_bsendl;
    self->bvfs.brecvl = dill_tls_brecvl;
    self->ctx = ctx;
    self->ssl = ssl;
    self->u = s;
    self->deadline = -1;
    self->indone = 0;
    self->outdone = 0;
    self->inerr = 0;
    self->outerr = 0;
    self->mem = 1;
    /* Initial handshaking. */
    while(1) {
        ERR_clear_error();
        int rc = SSL_connect(ssl);
        if(dill_tls_followup(self, rc)) break;
        if(dill_slow(errno != 0)) {err = errno; goto error4;}
    }
    /* Create the handle. */
    int h = dill_hmake(&self->hvfs);
    if(dill_slow(h < 0)) {int err = errno; goto error4;}
    return h;
error4:
    BIO_vfree(bio);
error3:
    SSL_free(ssl);
error2:
    SSL_CTX_free(ctx);
error1:
    if(s >= 0) dill_hclose(s);
    errno = err;
    return -1;
}
Пример #18
0
int
main( int argc, char * argv [] )
{
    enum
    {
        ARG_IN_DATA_FILE_IX          = 1,
        ARG_OUT_SIG_FILE_IX          = 2,
        ARG_KEY_FILE_IX              = 3,
        ARG_KEY_PASS_IX              = 4,
        ARG_KEY_CERT_FILE_IX         = 5,
        ARG_FIRST_EXTRA_CERT_FILE_IX = 6
    };

    int exit_code = 0;

    /* -------------------------------------------------------------- */
    /* initialization */

    exit_code = 1;

    SSL_load_error_strings();
    SSL_library_init();

    /* -------------------------------------------------------------- */
    /* command-line processing */

    exit_code = 2;

    if ( argc < 6 )
    {
        fprintf( stderr, "usage: %s IN_DATA_FILE OUT_SIG_FILE"
                 " KEY_FILE KEY_PASS KEY_CERT EXTRA_CERTS...\n", argv[0] );
        return 1;
    }

    BIO * in_data_file = BIO_new_file( argv[ ARG_IN_DATA_FILE_IX ], "rb" );
    if ( ! in_data_file )
    {
        perror( argv[ ARG_IN_DATA_FILE_IX ] );
        goto end;
    }

    BIO * out_sig_file = BIO_new_file( argv[ ARG_OUT_SIG_FILE_IX ], "wb" );
    if ( ! out_sig_file )
    {
        perror( argv[ ARG_OUT_SIG_FILE_IX ] );
        goto free_in_data_file;
    }

    BIO * key_file = BIO_new_file( argv[ ARG_KEY_FILE_IX ], "rb" );
    if ( ! key_file )
    {
        perror( argv[ ARG_KEY_FILE_IX ] );
        goto free_out_sig_file;
    }

    char * pw = argv[ ARG_KEY_PASS_IX ];
    /* fprintf( stderr, "pw='%s'\n", pw ); */

    BIO * key_cert_file = BIO_new_file( argv[ ARG_KEY_CERT_FILE_IX ], "rb" );
    if ( ! key_cert_file )
    {
        perror( argv[ ARG_KEY_CERT_FILE_IX ] );
        goto free_key_file;
    }

    BIO * * extra_cert_files = NULL;
    int num_extra_cert_files = argc - ARG_FIRST_EXTRA_CERT_FILE_IX;
    if ( num_extra_cert_files > 0 )
    {
        extra_cert_files = calloc( num_extra_cert_files, sizeof( BIO * ) );
        if ( ! extra_cert_files )
        {
            perror( "extra_cert_files" );
            goto free_key_cert_file;
        }

        for ( int i = 0; i < num_extra_cert_files; ++i )
        {
            extra_cert_files[i] =
              BIO_new_file( argv[ ARG_FIRST_EXTRA_CERT_FILE_IX + i ], "rb" );
            if ( ! extra_cert_files[i] )
            {
                perror( argv[ ARG_FIRST_EXTRA_CERT_FILE_IX + i ] );
                goto free_key_cert_file;
            }
        }
    }

    /* -------------------------------------------------------------- */
    /* processing */

    exit_code = 3;

#define FAIL( msg, dest )                      \
    do {                                       \
        fprintf( stderr, "error: " msg "\n" ); \
        goto dest;                             \
    } while ( 0 )

    EVP_PKEY * key = PEM_read_bio_PrivateKey( key_file, NULL, NULL, pw );
    if ( ! key )
        FAIL( "reading private key", free_extra_cert_files );

    X509 * key_cert = PEM_read_bio_X509( key_cert_file, NULL, NULL, NULL );
    if ( ! key_cert )
        FAIL( "reading signing cert", free_key );

    STACK_OF(X509) * extra_certs = NULL;
    if ( num_extra_cert_files > 0 )
    {
        int success = 1;

        extra_certs = sk_X509_new_null();
        if ( ! extra_certs )
            FAIL( "allocating stack for extra certs", free_key_cert );

        for ( int i = 0; i < num_extra_cert_files; ++i )
        {
            X509 * tmp = PEM_read_bio_X509( extra_cert_files[i],
                                            NULL, NULL, NULL );
            if ( ! tmp )
            {
                fprintf( stderr, "error reading '%s'\n",
                         argv[ ARG_FIRST_EXTRA_CERT_FILE_IX + i ] );
                success = 0;
                break;
            }

            if ( ! sk_X509_push( extra_certs, tmp ) )
            {
                fprintf( stderr, "error pushing '%s'\n",
                         argv[ ARG_FIRST_EXTRA_CERT_FILE_IX + i ] );
                success = 0;
                X509_free( tmp );
                break;
            }
        }

        if ( ! success )
            FAIL( "could not read extra certs", free_extra_certs );
    }

    CMS_ContentInfo * ci = CMS_sign( key_cert, key, extra_certs, in_data_file,
                                     CMS_DETACHED | CMS_BINARY );

    /* if ( 1 != PEM_write_bio_CMS( out_sig_file, ci ) )
           FAIL( "could not write signature in PEM", free_ci ); */

    if ( 1 != i2d_CMS_bio( out_sig_file, ci ) )
           FAIL( "could not write signature in DER", free_ci );

    /* -------------------------------------------------------------- */
    /* success */

    exit_code = 0;

    /* -------------------------------------------------------------- */
    /* cleanup */

free_ci:
    CMS_ContentInfo_free( ci );

free_extra_certs:
    sk_X509_pop_free( extra_certs, &X509_free );

free_key_cert:
    X509_free( key_cert );

free_key:
    EVP_PKEY_free( key );

free_extra_cert_files:
    for ( int i = 0; i < num_extra_cert_files; ++i )
        BIO_vfree( extra_cert_files[ i ] );
    free( extra_cert_files );

free_key_cert_file:
    BIO_vfree( key_cert_file );

free_key_file:
    BIO_vfree( key_file );

free_out_sig_file:
    BIO_vfree( out_sig_file );

free_in_data_file:
    BIO_vfree( in_data_file );

    ERR_print_errors_fp( stderr );

    ERR_remove_state( /* pid= */ 0 );
    ENGINE_cleanup();
    CONF_modules_unload( /* all= */ 1 );
    EVP_cleanup();
    ERR_free_strings();
    CRYPTO_cleanup_all_ex_data();

end:
    return exit_code;
}