Exemplo n.º 1
0
// This is a function that checks out a file from the server
// - RETURNS 0 in case of success, 1 otherwise
int checkout_file(SSL* ssl, BIO *sslbio, char *buffer) {

   FILE* file;            // pointer to the file to be received
   int ret;
   int length;

    // Sending the client name
   // BIO_write(sslbio, CLIENT_NAME, strlen(CLIENT_NAME));

    // Receive number of options
    memset(buffer,0,4096);
    length = BIO_read(sslbio, buffer, BUF_SIZE);
    if(length <= 0)
    {
        strcpy(buffer, "No message");
        length = strlen(buffer);
    }
    buffer[length] = '\0';
    printf("\nSelect file number to check out file.\n");
    printf("You have %s option(s):\n", buffer); 
    int opns = atoi(buffer);
    
    if ( opns < 1 ) {
        //No files to choose from.
        printf("You have ZERO files stored at server...\n");
	printf("Unable to check-out file: Choose a different option.\n");
	exit(1);
    }

    // If files are present, receive file options
    printf("\nFILE UID | FILE NAME | FILE OWNER\n");
    int i;
    for (i = 0; i < opns; i++) {
        memset(buffer,0,4096);
        length = BIO_read(sslbio, buffer, BUF_SIZE);
        if(length <= 0)
        {
            strcpy(buffer, "No message");
            length = strlen(buffer);
        }
        buffer[length] = '\0';
        printf("%s\n", buffer); 
    }

    // Receive deliminated list of option numbers
    memset(buffer,0,4096);
    length = BIO_read(sslbio, buffer, BUF_SIZE);
    if(length <= 0)
    {
        strcpy(buffer, "No message");
        length = strlen(buffer);
    }
    buffer[length] = '\0';

    // Tokenize options
    int options[opns];
    int numtokens = str_to_ints(buffer, options);
    
    // Select Option, i.e., file UID choice
    int filechoice =  getintchoice("Select FILE UID to checkout", options, opns);
    length = floor(log10(abs(filechoice))) + 1;
    char sfile[length];
    sprintf(sfile, "%d", filechoice);

    // Send File UID to Server
    BIO_write(sslbio, sfile, length);

    // Get file name from Server
    memset(buffer,0,4096);
    length = BIO_read(sslbio, buffer, BUF_SIZE);
    if(length <= 0)
    {
        strcpy(buffer, "No message");
        length = strlen(buffer);
    }
    buffer[length] = '\0';
    printf("Saving file '%s' to local disk.\n", buffer);

    // Open file
    file = fopen(buffer, "w+");
    if(file == NULL) {
      fprintf(stderr, "File not found: '%s'\n", buffer);
      return 1;
    }

    // Get file data from Server
    memset(buffer,0,4096);
    length = BIO_read(sslbio, buffer, BUF_SIZE);
    if(length <= 0)
    {
        strcpy(buffer, "No message");
        length = strlen(buffer);
    }
    buffer[length] = '\0';
    printf("Plain text received:\n%s\n",buffer);

    // Writing to file
    fwrite(buffer, length, 1, file);
    // Close file.
    fclose(file);
    printf("File Saved.\n");

    // Send confirmation to server
    char message[] = "File Saved.";
    BIO_write(sslbio, message, strlen(message));

    // Receive confirmation from server
    memset(buffer,0,4096);
    length = BIO_read(sslbio, buffer, BUF_SIZE);
    if(length <= 0)
    {
        strcpy(buffer, "No message");
        length = strlen(buffer);
    }
    buffer[length] = '\0';
    printf("File Successfully Checked Out: %s\n",buffer);

    return 0;
}
Exemplo n.º 2
0
/* int */
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
	{
	int i,j;
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
	X509_ALGOR *xa;
	ASN1_OCTET_STRING *data_body=NULL;
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
	EVP_CIPHER_CTX *evp_ctx=NULL;
	X509_ALGOR *enc_alg=NULL;
	STACK_OF(X509_ALGOR) *md_sk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	PKCS7_RECIP_INFO *ri=NULL;

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
		md_sk=p7->d.sign->md_algs;
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		enc_alg=p7->d.enveloped->enc_data->algorithm;
		data_body=p7->d.enveloped->enc_data->enc_data;
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	/* We will be checking the signature */
	if (md_sk != NULL)
		{
		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
			{
			xa=sk_X509_ALGOR_value(md_sk,i);
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
				goto err;
				}

			j=OBJ_obj2nid(xa->algorithm);
			evp_md=EVP_get_digestbynid(j);
			if (evp_md == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
				goto err;
				}

			BIO_set_md(btmp,evp_md);
			if (out == NULL)
				out=btmp;
			else
				BIO_push(out,btmp);
			btmp=NULL;
			}
		}

	if (evp_cipher != NULL)
		{
#if 0
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		unsigned char *p;
		int keylen,ivlen;
		int max;
		X509_OBJECT ret;
#endif
		unsigned char *ek = NULL;
		int eklen;

		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
			goto err;
			}

		/* It was encrypted, we need to decrypt the secret key
		 * with the private key */

		/* Find the recipientInfo which matches the passed certificate
		 * (if any)
		 */

		if (pcert)
			{
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
				{
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
				if (!pkcs7_cmp_ri(ri, pcert))
					break;
				ri=NULL;
				}
			if (ri == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				      PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
				goto err;
				}
			}

		/* If we haven't got a certificate try each ri in turn */

		if (pcert == NULL)
			{
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
				{
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
				if (pkcs7_decrypt_rinfo(&ek, &eklen,
							ri, pkey) > 0)
					break;
				ERR_clear_error();
				ri = NULL;
				}
			if (ri == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				      PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
				goto err;
				}
			}
		else
			{
			if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) <= 0)
				goto err;
			}

		evp_ctx=NULL;
		BIO_get_cipher_ctx(etmp,&evp_ctx);
		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
			goto err;
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
			goto err;

		if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) {
			/* Some S/MIME clients don't use the same key
			 * and effective key length. The key length is
			 * determined by the size of the decrypted RSA key.
			 */
			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen))
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
					PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
				goto err;
				}
		} 
		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,ek,NULL,0) <= 0)
			goto err;

		if (ek)
			{
			OPENSSL_cleanse(ek,eklen);
			OPENSSL_free(ek);
			}

		if (out == NULL)
			out=etmp;
		else
			BIO_push(out,etmp);
		etmp=NULL;
		}

#if 1
	if (PKCS7_is_detached(p7) || (in_bio != NULL))
		{
		bio=in_bio;
		}
	else 
		{
#if 0
		bio=BIO_new(BIO_s_mem());
		/* We need to set this so that when we have read all
		 * the data, the encrypt BIO, if present, will read
		 * EOF and encode the last few bytes */
		BIO_set_mem_eof_return(bio,0);

		if (data_body->length > 0)
			BIO_write(bio,(char *)data_body->data,data_body->length);
#else
		if (data_body->length > 0)
		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
		else {
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
		}
		if (bio == NULL)
			goto err;
#endif
		}
	BIO_push(out,bio);
	bio=NULL;
#endif
	if (0)
		{
err:
		if (out != NULL) BIO_free_all(out);
		if (btmp != NULL) BIO_free_all(btmp);
		if (etmp != NULL) BIO_free_all(etmp);
		if (bio != NULL) BIO_free_all(bio);
		out=NULL;
		}
	return(out);
	}
Exemplo n.º 3
0
int
s_client_main(int argc, char **argv)
{
	unsigned int off = 0, clr = 0;
	SSL *con = NULL;
	int s, k, state = 0, af = AF_UNSPEC;
	char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL;
	int cbuf_len, cbuf_off;
	int sbuf_len, sbuf_off;
	char *port = PORT_STR;
	int full_log = 1;
	char *host = SSL_HOST_NAME;
	char *xmpphost = NULL;
	char *proxy = NULL, *connect = NULL;
	char *cert_file = NULL, *key_file = NULL;
	int cert_format = FORMAT_PEM, key_format = FORMAT_PEM;
	char *passarg = NULL, *pass = NULL;
	X509 *cert = NULL;
	EVP_PKEY *key = NULL;
	char *CApath = NULL, *CAfile = NULL, *cipher = NULL;
	int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE, bugs = 0;
	int crlf = 0;
	int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
	SSL_CTX *ctx = NULL;
	int ret = 1, in_init = 1, i, nbio_test = 0;
	int starttls_proto = PROTO_OFF;
	int prexit = 0;
	X509_VERIFY_PARAM *vpm = NULL;
	int badarg = 0;
	const SSL_METHOD *meth = NULL;
	int socket_type = SOCK_STREAM;
	BIO *sbio;
	int mbuf_len = 0;
	struct timeval timeout;
	const char *errstr = NULL;
	char *servername = NULL;
	tlsextctx tlsextcbp =
	{NULL, 0};
	const char *next_proto_neg_in = NULL;
	const char *alpn_in = NULL;
	char *sess_in = NULL;
	char *sess_out = NULL;
	struct sockaddr peer;
	int peerlen = sizeof(peer);
	int enable_timeouts = 0;
	long socket_mtu = 0;

	meth = SSLv23_client_method();

	c_Pause = 0;
	c_quiet = 0;
	c_ign_eof = 0;
	c_debug = 0;
	c_msg = 0;
	c_showcerts = 0;

	if (((cbuf = malloc(BUFSIZZ)) == NULL) ||
	    ((sbuf = malloc(BUFSIZZ)) == NULL) ||
	    ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) {	/* NUL byte */
		BIO_printf(bio_err, "out of memory\n");
		goto end;
	}
	verify_depth = 0;
	c_nbio = 0;

	argc--;
	argv++;
	while (argc >= 1) {
		if (strcmp(*argv, "-host") == 0) {
			if (--argc < 1)
				goto bad;
			host = *(++argv);
		} else if (strcmp(*argv, "-port") == 0) {
			if (--argc < 1)
				goto bad;
			port = *(++argv);
			if (port == NULL || *port == '\0')
				goto bad;
		} else if (strcmp(*argv, "-connect") == 0) {
			if (--argc < 1)
				goto bad;
			connect = *(++argv);
		} else if (strcmp(*argv, "-proxy") == 0) {
			if (--argc < 1)
				goto bad;
			proxy = *(++argv);
		} else if (strcmp(*argv,"-xmpphost") == 0) {
			if (--argc < 1)
				goto bad;
			xmpphost= *(++argv);
		} else if (strcmp(*argv, "-verify") == 0) {
			verify = SSL_VERIFY_PEER;
			if (--argc < 1)
				goto bad;
			verify_depth = strtonum(*(++argv), 0, INT_MAX, &errstr);
			if (errstr)
				goto bad;
			BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
		} else if (strcmp(*argv, "-cert") == 0) {
			if (--argc < 1)
				goto bad;
			cert_file = *(++argv);
		} else if (strcmp(*argv, "-sess_out") == 0) {
			if (--argc < 1)
				goto bad;
			sess_out = *(++argv);
		} else if (strcmp(*argv, "-sess_in") == 0) {
			if (--argc < 1)
				goto bad;
			sess_in = *(++argv);
		} else if (strcmp(*argv, "-certform") == 0) {
			if (--argc < 1)
				goto bad;
			cert_format = str2fmt(*(++argv));
		} else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) {
			if (badarg)
				goto bad;
			continue;
		} else if (strcmp(*argv, "-verify_return_error") == 0)
			verify_return_error = 1;
		else if (strcmp(*argv, "-prexit") == 0)
			prexit = 1;
		else if (strcmp(*argv, "-crlf") == 0)
			crlf = 1;
		else if (strcmp(*argv, "-quiet") == 0) {
			c_quiet = 1;
			c_ign_eof = 1;
		} else if (strcmp(*argv, "-ign_eof") == 0)
			c_ign_eof = 1;
		else if (strcmp(*argv, "-no_ign_eof") == 0)
			c_ign_eof = 0;
		else if (strcmp(*argv, "-pause") == 0)
			c_Pause = 1;
		else if (strcmp(*argv, "-debug") == 0)
			c_debug = 1;
		else if (strcmp(*argv, "-tlsextdebug") == 0)
			c_tlsextdebug = 1;
		else if (strcmp(*argv, "-status") == 0)
			c_status_req = 1;
		else if (strcmp(*argv, "-msg") == 0)
			c_msg = 1;
		else if (strcmp(*argv, "-showcerts") == 0)
			c_showcerts = 1;
		else if (strcmp(*argv, "-nbio_test") == 0)
			nbio_test = 1;
		else if (strcmp(*argv, "-state") == 0)
			state = 1;
		else if (strcmp(*argv, "-tls1_2") == 0)
			meth = TLSv1_2_client_method();
		else if (strcmp(*argv, "-tls1_1") == 0)
			meth = TLSv1_1_client_method();
		else if (strcmp(*argv, "-tls1") == 0)
			meth = TLSv1_client_method();
#ifndef OPENSSL_NO_DTLS1
		else if (strcmp(*argv, "-dtls1") == 0) {
			meth = DTLSv1_client_method();
			socket_type = SOCK_DGRAM;
		} else if (strcmp(*argv, "-timeout") == 0)
			enable_timeouts = 1;
		else if (strcmp(*argv, "-mtu") == 0) {
			if (--argc < 1)
				goto bad;
			socket_mtu = strtonum(*(++argv), 0, LONG_MAX, &errstr);
			if (errstr)
				goto bad;
		}
#endif
		else if (strcmp(*argv, "-bugs") == 0)
			bugs = 1;
		else if (strcmp(*argv, "-keyform") == 0) {
			if (--argc < 1)
				goto bad;
			key_format = str2fmt(*(++argv));
		} else if (strcmp(*argv, "-pass") == 0) {
			if (--argc < 1)
				goto bad;
			passarg = *(++argv);
		} else if (strcmp(*argv, "-key") == 0) {
			if (--argc < 1)
				goto bad;
			key_file = *(++argv);
		} else if (strcmp(*argv, "-reconnect") == 0) {
			reconnect = 5;
		} else if (strcmp(*argv, "-CApath") == 0) {
			if (--argc < 1)
				goto bad;
			CApath = *(++argv);
		} else if (strcmp(*argv, "-CAfile") == 0) {
			if (--argc < 1)
				goto bad;
			CAfile = *(++argv);
		} else if (strcmp(*argv, "-no_tls1_2") == 0)
			off |= SSL_OP_NO_TLSv1_2;
		else if (strcmp(*argv, "-no_tls1_1") == 0)
			off |= SSL_OP_NO_TLSv1_1;
		else if (strcmp(*argv, "-no_tls1") == 0)
			off |= SSL_OP_NO_TLSv1;
		else if (strcmp(*argv, "-no_ssl3") == 0)
			off |= SSL_OP_NO_SSLv3;
		else if (strcmp(*argv, "-no_ssl2") == 0)
			off |= SSL_OP_NO_SSLv2;
		else if (strcmp(*argv, "-no_comp") == 0) {
			off |= SSL_OP_NO_COMPRESSION;
		}
		else if (strcmp(*argv, "-no_ticket") == 0) {
			off |= SSL_OP_NO_TICKET;
		}
		else if (strcmp(*argv, "-nextprotoneg") == 0) {
			if (--argc < 1)
				goto bad;
			next_proto_neg_in = *(++argv);
		}
		else if (strcmp(*argv, "-alpn") == 0) {
			if (--argc < 1)
				goto bad;
			alpn_in = *(++argv);
		} else if (strcmp(*argv, "-serverpref") == 0)
			off |= SSL_OP_CIPHER_SERVER_PREFERENCE;
		else if (strcmp(*argv, "-legacy_renegotiation") == 0)
			; /* no-op */
		else if (strcmp(*argv, "-legacy_server_connect") == 0) {
			off |= SSL_OP_LEGACY_SERVER_CONNECT;
		} else if (strcmp(*argv, "-no_legacy_server_connect") == 0) {
			clr |= SSL_OP_LEGACY_SERVER_CONNECT;
		} else if (strcmp(*argv, "-cipher") == 0) {
			if (--argc < 1)
				goto bad;
			cipher = *(++argv);
		}
		else if (strcmp(*argv, "-nbio") == 0) {
			c_nbio = 1;
		}
		else if (strcmp(*argv, "-starttls") == 0) {
			if (--argc < 1)
				goto bad;
			++argv;
			if (strcmp(*argv, "smtp") == 0)
				starttls_proto = PROTO_SMTP;
			else if (strcmp(*argv, "lmtp") == 0)
				starttls_proto = PROTO_LMTP;
			else if (strcmp(*argv, "pop3") == 0)
				starttls_proto = PROTO_POP3;
			else if (strcmp(*argv, "imap") == 0)
				starttls_proto = PROTO_IMAP;
			else if (strcmp(*argv, "ftp") == 0)
				starttls_proto = PROTO_FTP;
			else if (strcmp(*argv, "xmpp") == 0)
				starttls_proto = PROTO_XMPP;
			else
				goto bad;
		}
		else if (strcmp(*argv, "-4") == 0) {
			af = AF_INET;
		} else if (strcmp(*argv, "-6") == 0) {
			af = AF_INET6;
		}
		else if (strcmp(*argv, "-servername") == 0) {
			if (--argc < 1)
				goto bad;
			servername = *(++argv);
			/* meth=TLSv1_client_method(); */
		}
#ifndef OPENSSL_NO_SRTP
		else if (strcmp(*argv, "-use_srtp") == 0) {
			if (--argc < 1)
				goto bad;
			srtp_profiles = *(++argv);
		}
#endif
		else if (strcmp(*argv, "-keymatexport") == 0) {
			if (--argc < 1)
				goto bad;
			keymatexportlabel = *(++argv);
		} else if (strcmp(*argv, "-keymatexportlen") == 0) {
			if (--argc < 1)
				goto bad;
			keymatexportlen = strtonum(*(++argv), 1, INT_MAX, &errstr);
			if (errstr)
				goto bad;
		} else {
			BIO_printf(bio_err, "unknown option %s\n", *argv);
			badop = 1;
			break;
		}
		argc--;
		argv++;
	}
	if (proxy != NULL) {
		if (!extract_host_port(proxy, &host, NULL, &port))
			goto bad;
		if (connect == NULL)
			connect = SSL_HOST_NAME;
	} else if (connect != NULL) {
		if (!extract_host_port(connect, &host, NULL, &port))
			goto bad;
	}
	if (badop) {
bad:
		if (errstr)
			BIO_printf(bio_err, "invalid argument %s: %s\n",
			    *argv, errstr);
		else
			sc_usage();
		goto end;
	}

	next_proto.status = -1;
	if (next_proto_neg_in) {
		next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in);
		if (next_proto.data == NULL) {
			BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n");
			goto end;
		}
	} else
		next_proto.data = NULL;

	if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) {
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
	}
	if (key_file == NULL)
		key_file = cert_file;


	if (key_file) {

		key = load_key(bio_err, key_file, key_format, 0, pass,
		    "client certificate private key file");
		if (!key) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (cert_file) {
		cert = load_cert(bio_err, cert_file, cert_format,
		    NULL, "client certificate file");

		if (!cert) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (bio_c_out == NULL) {
		if (c_quiet && !c_debug && !c_msg) {
			bio_c_out = BIO_new(BIO_s_null());
		} else {
			if (bio_c_out == NULL)
				bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE);
		}
	}

	ctx = SSL_CTX_new(meth);
	if (ctx == NULL) {
		ERR_print_errors(bio_err);
		goto end;
	}
	if (vpm)
		SSL_CTX_set1_param(ctx, vpm);

#ifndef OPENSSL_NO_SRTP
	if (srtp_profiles != NULL)
		SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles);
#endif
	if (bugs)
		SSL_CTX_set_options(ctx, SSL_OP_ALL | off);
	else
		SSL_CTX_set_options(ctx, off);

	if (clr)
		SSL_CTX_clear_options(ctx, clr);
	/*
	 * DTLS: partial reads end up discarding unread UDP bytes :-( Setting
	 * read ahead solves this problem.
	 */
	if (socket_type == SOCK_DGRAM)
		SSL_CTX_set_read_ahead(ctx, 1);

	if (next_proto.data)
		SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
	if (alpn_in) {
		unsigned short alpn_len;
		unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in);

		if (alpn == NULL) {
			BIO_printf(bio_err, "Error parsing -alpn argument\n");
			goto end;
		}
		SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len);
		free(alpn);
	}

	if (state)
		SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
	if (cipher != NULL)
		if (!SSL_CTX_set_cipher_list(ctx, cipher)) {
			BIO_printf(bio_err, "error setting cipher list\n");
			ERR_print_errors(bio_err);
			goto end;
		}

	SSL_CTX_set_verify(ctx, verify, verify_callback);
	if (!set_cert_key_stuff(ctx, cert, key))
		goto end;

	if ((!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) ||
	    (!SSL_CTX_set_default_verify_paths(ctx))) {
		/*
		 * BIO_printf(bio_err,"error setting default verify
		 * locations\n");
		 */
		ERR_print_errors(bio_err);
		/* goto end; */
	}
	if (servername != NULL) {
		tlsextcbp.biodebug = bio_err;
		SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
		SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
	}

	con = SSL_new(ctx);
	if (sess_in) {
		SSL_SESSION *sess;
		BIO *stmp = BIO_new_file(sess_in, "r");
		if (!stmp) {
			BIO_printf(bio_err, "Can't open session file %s\n",
			    sess_in);
			ERR_print_errors(bio_err);
			goto end;
		}
		sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
		BIO_free(stmp);
		if (!sess) {
			BIO_printf(bio_err, "Can't open session file %s\n",
			    sess_in);
			ERR_print_errors(bio_err);
			goto end;
		}
		SSL_set_session(con, sess);
		SSL_SESSION_free(sess);
	}
	if (servername != NULL) {
		if (!SSL_set_tlsext_host_name(con, servername)) {
			BIO_printf(bio_err, "Unable to set TLS servername extension.\n");
			ERR_print_errors(bio_err);
			goto end;
		}
	}
/*	SSL_set_cipher_list(con,"RC4-MD5"); */

re_start:

	if (init_client(&s, host, port, socket_type, af) == 0) {
		BIO_printf(bio_err, "connect:errno=%d\n", errno);
		goto end;
	}
	BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);

	if (c_nbio) {
		if (!c_quiet)
			BIO_printf(bio_c_out, "turning on non blocking io\n");
		if (!BIO_socket_nbio(s, 1)) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (c_Pause & 0x01)
		SSL_set_debug(con, 1);

	if (SSL_version(con) == DTLS1_VERSION) {

		sbio = BIO_new_dgram(s, BIO_NOCLOSE);
		if (getsockname(s, &peer, (void *) &peerlen) < 0) {
			BIO_printf(bio_err, "getsockname:errno=%d\n",
			    errno);
			shutdown(s, SHUT_RD);
			close(s);
			goto end;
		}
		(void) BIO_ctrl_set_connected(sbio, 1, &peer);

		if (enable_timeouts) {
			timeout.tv_sec = 0;
			timeout.tv_usec = DGRAM_RCV_TIMEOUT;
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);

			timeout.tv_sec = 0;
			timeout.tv_usec = DGRAM_SND_TIMEOUT;
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
		}
		if (socket_mtu > 28) {
			SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
			SSL_set_mtu(con, socket_mtu - 28);
		} else
			/* want to do MTU discovery */
			BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
	} else
		sbio = BIO_new_socket(s, BIO_NOCLOSE);

	if (nbio_test) {
		BIO *test;

		test = BIO_new(BIO_f_nbio_test());
		sbio = BIO_push(test, sbio);
	}
	if (c_debug) {
		SSL_set_debug(con, 1);
		BIO_set_callback(sbio, bio_dump_callback);
		BIO_set_callback_arg(sbio, (char *) bio_c_out);
	}
	if (c_msg) {
		SSL_set_msg_callback(con, msg_cb);
		SSL_set_msg_callback_arg(con, bio_c_out);
	}
	if (c_tlsextdebug) {
		SSL_set_tlsext_debug_callback(con, tlsext_cb);
		SSL_set_tlsext_debug_arg(con, bio_c_out);
	}
	if (c_status_req) {
		SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
		SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
		SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
	}

	SSL_set_bio(con, sbio, sbio);
	SSL_set_connect_state(con);

	/* ok, lets connect */
	read_tty = 1;
	write_tty = 0;
	tty_on = 0;
	read_ssl = 1;
	write_ssl = 1;

	cbuf_len = 0;
	cbuf_off = 0;
	sbuf_len = 0;
	sbuf_off = 0;

	/* This is an ugly hack that does a lot of assumptions */
	/*
	 * We do have to handle multi-line responses which may come in a
	 * single packet or not. We therefore have to use BIO_gets() which
	 * does need a buffering BIO. So during the initial chitchat we do
	 * push a buffering BIO into the chain that is removed again later on
	 * to not disturb the rest of the s_client operation.
	 */
	if (starttls_proto == PROTO_SMTP || starttls_proto == PROTO_LMTP) {
		int foundit = 0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from SMTP */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		/* STARTTLS command requires EHLO... */
		BIO_printf(fbio, "%cHLO openssl.client.net\r\n",
			   starttls_proto == PROTO_SMTP ? 'E' : 'L');
		(void) BIO_flush(fbio);
		/* wait for multi-line response to end EHLO SMTP response */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
			if (strstr(mbuf, "STARTTLS"))
				foundit = 1;
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
			    "didn't found starttls in server response,"
			    " try anyway...\n");
		BIO_printf(sbio, "STARTTLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_POP3) {
		mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
		if (mbuf_len == -1) {
			BIO_printf(bio_err, "BIO_read failed\n");
			goto end;
		}
		BIO_printf(sbio, "STLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_IMAP) {
		int foundit = 0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		BIO_gets(fbio, mbuf, BUFSIZZ);
		/* STARTTLS command requires CAPABILITY... */
		BIO_printf(fbio, ". CAPABILITY\r\n");
		(void) BIO_flush(fbio);
		/* wait for multi-line CAPABILITY response */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
			if (strstr(mbuf, "STARTTLS"))
				foundit = 1;
		}
		while (mbuf_len > 3 && mbuf[0] != '.');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
			    "didn't found STARTTLS in server response,"
			    " try anyway...\n");
		BIO_printf(sbio, ". STARTTLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_FTP) {
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from FTP */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		BIO_printf(sbio, "AUTH TLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_XMPP) {
		int seen = 0;
		BIO_printf(sbio, "<stream:stream "
		    "xmlns:stream='http://etherx.jabber.org/streams' "
		    "xmlns='jabber:client' to='%s' version='1.0'>", xmpphost ? xmpphost : host);
		seen = BIO_read(sbio, mbuf, BUFSIZZ);

		if (seen <= 0)
			goto shut;

		mbuf[seen] = 0;
		while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'") &&
		       !strstr(mbuf, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"")) {
			seen = BIO_read(sbio, mbuf, BUFSIZZ);

			if (seen <= 0)
				goto shut;

			mbuf[seen] = 0;
		}
		BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
		seen = BIO_read(sbio, sbuf, BUFSIZZ);
		sbuf[seen] = 0;
		if (!strstr(sbuf, "<proceed"))
			goto shut;
		mbuf[0] = 0;
	} else if (proxy != NULL) {
		BIO_printf(sbio, "CONNECT %s HTTP/1.0\r\n\r\n", connect);
		mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
		if (mbuf_len == -1) {
			BIO_printf(bio_err, "BIO_read failed\n");
			goto end;
		}
	}
	for (;;) {
		struct pollfd pfd[3];	/* stdin, stdout, socket */
		int ptimeout = -1;

		if ((SSL_version(con) == DTLS1_VERSION) &&
		    DTLSv1_get_timeout(con, &timeout))
			ptimeout = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;

		if (SSL_in_init(con) && !SSL_total_renegotiations(con)) {
			in_init = 1;
			tty_on = 0;
		} else {
			tty_on = 1;
			if (in_init) {
				in_init = 0;
				if (sess_out) {
					BIO *stmp = BIO_new_file(sess_out, "w");
					if (stmp) {
						PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
						BIO_free(stmp);
					} else
						BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
				}
				print_stuff(bio_c_out, con, full_log);
				if (full_log > 0)
					full_log--;

				if (starttls_proto) {
					BIO_write(bio_err, mbuf, mbuf_len);
					/* We don't need to know any more */
					starttls_proto = PROTO_OFF;
				}
				if (reconnect) {
					reconnect--;
					BIO_printf(bio_c_out, "drop connection and then reconnect\n");
					SSL_shutdown(con);
					SSL_set_connect_state(con);
					shutdown(SSL_get_fd(con), SHUT_RD);
					close(SSL_get_fd(con));
					goto re_start;
				}
			}
		}

		ssl_pending = read_ssl && SSL_pending(con);

		pfd[0].fd = -1;
		pfd[1].fd = -1;
		if (!ssl_pending) {
			if (tty_on) {
				if (read_tty) {
					pfd[0].fd = fileno(stdin);
					pfd[0].events = POLLIN;
				}
				if (write_tty) {
					pfd[1].fd = fileno(stdout);
					pfd[1].events = POLLOUT;
				}
			}

			pfd[2].fd = SSL_get_fd(con);
			pfd[2].events = 0;
			if (read_ssl)
				pfd[2].events |= POLLIN;
			if (write_ssl)
				pfd[2].events |= POLLOUT;

/*			printf("mode tty(%d %d%d) ssl(%d%d)\n",
				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/

			i = poll(pfd, 3, ptimeout);
			if (i < 0) {
				BIO_printf(bio_err, "bad select %d\n",
				    errno);
				goto shut;
				/* goto end; */
			}
		}
		if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) {
			BIO_printf(bio_err, "TIMEOUT occured\n");
		}
		if (!ssl_pending && (pfd[2].revents & (POLLOUT|POLLERR|POLLNVAL))) {
			if (pfd[2].revents & (POLLERR|POLLNVAL)) {
				BIO_printf(bio_err, "poll error");
				goto shut;
			}
			k = SSL_write(con, &(cbuf[cbuf_off]),
			    (unsigned int) cbuf_len);
			switch (SSL_get_error(con, k)) {
			case SSL_ERROR_NONE:
				cbuf_off += k;
				cbuf_len -= k;
				if (k <= 0)
					goto end;
				/* we have done a  write(con,NULL,0); */
				if (cbuf_len <= 0) {
					read_tty = 1;
					write_ssl = 0;
				} else {	/* if (cbuf_len > 0) */
					read_tty = 0;
					write_ssl = 1;
				}
				break;
			case SSL_ERROR_WANT_WRITE:
				BIO_printf(bio_c_out, "write W BLOCK\n");
				write_ssl = 1;
				read_tty = 0;
				break;
			case SSL_ERROR_WANT_READ:
				BIO_printf(bio_c_out, "write R BLOCK\n");
				write_tty = 0;
				read_ssl = 1;
				write_ssl = 0;
				break;
			case SSL_ERROR_WANT_X509_LOOKUP:
				BIO_printf(bio_c_out, "write X BLOCK\n");
				break;
			case SSL_ERROR_ZERO_RETURN:
				if (cbuf_len != 0) {
					BIO_printf(bio_c_out, "shutdown\n");
					ret = 0;
					goto shut;
				} else {
					read_tty = 1;
					write_ssl = 0;
					break;
				}

			case SSL_ERROR_SYSCALL:
				if ((k != 0) || (cbuf_len != 0)) {
					BIO_printf(bio_err, "write:errno=%d\n",
					    errno);
					goto shut;
				} else {
					read_tty = 1;
					write_ssl = 0;
				}
				break;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
			}
		} else if (!ssl_pending &&
		    (pfd[1].revents & (POLLOUT|POLLERR|POLLNVAL))) {
			if (pfd[1].revents & (POLLERR|POLLNVAL)) {
				BIO_printf(bio_err, "poll error");
				goto shut;
			}
			i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len);

			if (i <= 0) {
				BIO_printf(bio_c_out, "DONE\n");
				ret = 0;
				goto shut;
				/* goto end; */
			}
			sbuf_len -= i;
			sbuf_off += i;
			if (sbuf_len <= 0) {
				read_ssl = 1;
				write_tty = 0;
			}
		} else if (ssl_pending || (pfd[2].revents & (POLLIN|POLLHUP))) {
#ifdef RENEG
			{
				static int iiii;
				if (++iiii == 52) {
					SSL_renegotiate(con);
					iiii = 0;
				}
			}
#endif
			k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ );

			switch (SSL_get_error(con, k)) {
			case SSL_ERROR_NONE:
				if (k <= 0)
					goto end;
				sbuf_off = 0;
				sbuf_len = k;

				read_ssl = 0;
				write_tty = 1;
				break;
			case SSL_ERROR_WANT_WRITE:
				BIO_printf(bio_c_out, "read W BLOCK\n");
				write_ssl = 1;
				read_tty = 0;
				break;
			case SSL_ERROR_WANT_READ:
				BIO_printf(bio_c_out, "read R BLOCK\n");
				write_tty = 0;
				read_ssl = 1;
				if ((read_tty == 0) && (write_ssl == 0))
					write_ssl = 1;
				break;
			case SSL_ERROR_WANT_X509_LOOKUP:
				BIO_printf(bio_c_out, "read X BLOCK\n");
				break;
			case SSL_ERROR_SYSCALL:
				ret = errno;
				BIO_printf(bio_err, "read:errno=%d\n", ret);
				goto shut;
			case SSL_ERROR_ZERO_RETURN:
				BIO_printf(bio_c_out, "closed\n");
				ret = 0;
				goto shut;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
				/* break; */
			}
		} else if (pfd[0].revents) {
			if (pfd[0].revents & (POLLERR|POLLNVAL)) {
				BIO_printf(bio_err, "poll error");
				goto shut;
			}
			if (crlf) {
				int j, lf_num;

				i = read(fileno(stdin), cbuf, BUFSIZZ / 2);
				lf_num = 0;
				/* both loops are skipped when i <= 0 */
				for (j = 0; j < i; j++)
					if (cbuf[j] == '\n')
						lf_num++;
				for (j = i - 1; j >= 0; j--) {
					cbuf[j + lf_num] = cbuf[j];
					if (cbuf[j] == '\n') {
						lf_num--;
						i++;
						cbuf[j + lf_num] = '\r';
					}
				}
				assert(lf_num == 0);
			} else
				i = read(fileno(stdin), cbuf, BUFSIZZ);

			if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) {
				BIO_printf(bio_err, "DONE\n");
				ret = 0;
				goto shut;
			}
			if ((!c_ign_eof) && (cbuf[0] == 'R')) {
				BIO_printf(bio_err, "RENEGOTIATING\n");
				SSL_renegotiate(con);
				cbuf_len = 0;
			} else {
				cbuf_len = i;
				cbuf_off = 0;
			}

			write_ssl = 1;
			read_tty = 0;
		}
	}

	ret = 0;
shut:
	if (in_init)
		print_stuff(bio_c_out, con, full_log);
	SSL_shutdown(con);
	shutdown(SSL_get_fd(con), SHUT_RD);
	close(SSL_get_fd(con));
end:
	if (con != NULL) {
		if (prexit != 0)
			print_stuff(bio_c_out, con, 1);
		SSL_free(con);
	}
	free(next_proto.data);
	if (ctx != NULL)
		SSL_CTX_free(ctx);
	if (cert)
		X509_free(cert);
	if (key)
		EVP_PKEY_free(key);
	free(pass);
	if (vpm)
		X509_VERIFY_PARAM_free(vpm);
	if (cbuf != NULL) {
		explicit_bzero(cbuf, BUFSIZZ);
		free(cbuf);
	}
	if (sbuf != NULL) {
		explicit_bzero(sbuf, BUFSIZZ);
		free(sbuf);
	}
	if (mbuf != NULL) {
		explicit_bzero(mbuf, BUFSIZZ);
		free(mbuf);
	}
	if (bio_c_out != NULL) {
		BIO_free(bio_c_out);
		bio_c_out = NULL;
	}

	return (ret);
}
Exemplo n.º 4
0
int RSA_print(BIO *bp, RSA *x, int off)
	{
	char str[128];
	const char *s;
	unsigned char *m=NULL;
	int ret=0;
	size_t buf_len=0, i;

	if (x->n)
		buf_len = (size_t)BN_num_bytes(x->n);
	if (x->e)
		if (buf_len < (i = (size_t)BN_num_bytes(x->e)))
			buf_len = i;
	if (x->d)
		if (buf_len < (i = (size_t)BN_num_bytes(x->d)))
			buf_len = i;
	if (x->p)
		if (buf_len < (i = (size_t)BN_num_bytes(x->p)))
			buf_len = i;
	if (x->q)
		if (buf_len < (i = (size_t)BN_num_bytes(x->q)))
			buf_len = i;
	if (x->dmp1)
		if (buf_len < (i = (size_t)BN_num_bytes(x->dmp1)))
			buf_len = i;
	if (x->dmq1)
		if (buf_len < (i = (size_t)BN_num_bytes(x->dmq1)))
			buf_len = i;
	if (x->iqmp)
		if (buf_len < (i = (size_t)BN_num_bytes(x->iqmp)))
			buf_len = i;

	m=(unsigned char *)OPENSSL_malloc(buf_len+10);
	if (m == NULL)
		{
		RSAerr(RSA_F_RSA_PRINT,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	if (off)
		{
		if (off > 128) off=128;
		memset(str,' ',off);
		}
	if (x->d != NULL)
		{
		if (off && (BIO_write(bp,str,off) <= 0)) goto err;
		if (BIO_printf(bp,"Private-Key: (%d bit)\n",BN_num_bits(x->n))
			<= 0) goto err;
		}

	if (x->d == NULL)
		sprintf(str,"Modulus (%d bit):",BN_num_bits(x->n));
	else
		strcpy(str,"modulus:");
	if (!print(bp,str,x->n,m,off)) goto err;
	s=(x->d == NULL)?"Exponent:":"publicExponent:";
	if (!print(bp,s,x->e,m,off)) goto err;
	if (!print(bp,"privateExponent:",x->d,m,off)) goto err;
	if (!print(bp,"prime1:",x->p,m,off)) goto err;
	if (!print(bp,"prime2:",x->q,m,off)) goto err;
	if (!print(bp,"exponent1:",x->dmp1,m,off)) goto err;
	if (!print(bp,"exponent2:",x->dmq1,m,off)) goto err;
	if (!print(bp,"coefficient:",x->iqmp,m,off)) goto err;
	ret=1;
err:
	if (m != NULL) OPENSSL_free(m);
	return(ret);
	}
Exemplo n.º 5
0
int process_files(char **parameters, int param_count){
	int i, success = 0;
	size_t siglen;
	long int filesize=0, bytes_written=0;
	unsigned char *signature, *file_mem;
	char *boincname, *filename;
	EVP_MD_CTX *mdctx = NULL;
	FILE *current_file;
	BIO *b64, *bio_out;
	printf("Boinc filename     Filename           Status\n");
	printf("--------------------------------------------------------\n");
	for(i = 0; i<param_count; i+=2){
		boincname = parameters[i];
		filename = parameters[i+1];
		printf("%-18.18s %-18.18s ", boincname, filename);
		if(!(mdctx = EVP_MD_CTX_create())) goto err;

		if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, private_key)) goto err;

		/* Open file and get size */
		current_file = fopen(filename, "rb");
		if(current_file == NULL)
			{print_error("file_signing", "unable to open file", filename); goto err;}
		fseek(current_file, 0L, SEEK_END);
		filesize = ftell(current_file);
		file_mem = (unsigned char *)OPENSSL_malloc(filesize);
		if(file_mem == NULL)
			{print_error("file_signing", "unable to reserve memory for file", filename); goto err;}
		fseek(current_file, 0L, SEEK_SET);	//rewind to beginning of file

		/* read file to memory */
		bytes_written = fread(file_mem, 1, filesize, current_file);

		if(bytes_written != filesize){
			if(ferror(current_file))
				{print_error("file_signing", "Error reading file", filename); goto err;}
			else if(feof(current_file))
				{printf("File: %s wrote %li of filesize %li", filename, bytes_written, filesize); goto err;}
			else
				{print_error("file_signing", "something strange happened", filename); goto err;}
		}

		if(1 != EVP_DigestSignUpdate(mdctx, file_mem, filesize)) goto err;

		if(1 != EVP_DigestSignFinal(mdctx, NULL, &siglen)) goto err; // Get signature size

		if(!(signature = OPENSSL_malloc(sizeof(unsigned char) * siglen))) goto err;

		if(1 != EVP_DigestSignFinal(mdctx, signature, &siglen)) goto err;
		fwrite(boincname, sizeof(char), strlen(boincname), outputfile);
		fputc(' ', outputfile);
		b64 = BIO_new(BIO_f_base64());
		bio_out = BIO_new_fp(outputfile, BIO_NOCLOSE);
		BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
		BIO_push(b64, bio_out);
		BIO_write(b64, signature, sizeof(unsigned char) * siglen);
		BIO_flush(b64);
		BIO_free_all(b64);
		fputc('\n', outputfile);

		success = 1;

		printf("%-18.18s\n", "Success!");

		err:
		if(mdctx) EVP_MD_CTX_destroy(mdctx);
		if(current_file) fclose(current_file);
		if(file_mem) OPENSSL_free(file_mem);
		if(signature) OPENSSL_free(signature);
		if(!success)
			printf("%-18.18s\n", "Failed!");
	}
}
Exemplo n.º 6
0
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
          EVP_PKEY *key, unsigned char *sigin, int siglen,
          const char *sig_name, const char *md_name,
          const char *file, BIO *bmd)
{
    size_t len;
    int i;

    for (;;) {
        i = BIO_read(bp, (char *)buf, BUFSIZE);
        if (i < 0) {
            BIO_printf(bio_err, "Read Error in %s\n", file);
            ERR_print_errors(bio_err);
            return 1;
        }
        if (i == 0)
            break;
    }
    if (sigin) {
        EVP_MD_CTX *ctx;
        BIO_get_md_ctx(bp, &ctx);
        i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
        if (i > 0)
            BIO_printf(out, "Verified OK\n");
        else if (i == 0) {
            BIO_printf(out, "Verification Failure\n");
            return 1;
        } else {
            BIO_printf(bio_err, "Error Verifying Data\n");
            ERR_print_errors(bio_err);
            return 1;
        }
        return 0;
    }
    if (key) {
        EVP_MD_CTX *ctx;
        BIO_get_md_ctx(bp, &ctx);
        len = BUFSIZE;
        if (!EVP_DigestSignFinal(ctx, buf, &len)) {
            BIO_printf(bio_err, "Error Signing Data\n");
            ERR_print_errors(bio_err);
            return 1;
        }
    } else {
        len = BIO_gets(bp, (char *)buf, BUFSIZE);
        if ((int)len < 0) {
            ERR_print_errors(bio_err);
            return 1;
        }
    }

    if (binout)
        BIO_write(out, buf, len);
    else if (sep == 2) {
        for (i = 0; i < (int)len; i++)
            BIO_printf(out, "%02x", buf[i]);
        BIO_printf(out, " *%s\n", file);
    } else {
        if (sig_name) {
            BIO_puts(out, sig_name);
            if (md_name)
                BIO_printf(out, "-%s", md_name);
            BIO_printf(out, "(%s)= ", file);
        } else if (md_name)
            BIO_printf(out, "%s(%s)= ", md_name, file);
        else
            BIO_printf(out, "(%s)= ", file);
        for (i = 0; i < (int)len; i++) {
            if (sep && (i != 0))
                BIO_printf(out, ":");
            BIO_printf(out, "%02x", buf[i]);
        }
        BIO_printf(out, "\n");
    }
    return 0;
}
Exemplo n.º 7
0
static int b64_write(BIO *b, const char *in, int inl)
{
    int ret = 0;
    int n;
    int i;
    BIO_B64_CTX *ctx;

    ctx = (BIO_B64_CTX *)b->ptr;
    BIO_clear_retry_flags(b);

    if (ctx->encode != B64_ENCODE) {
        ctx->encode = B64_ENCODE;
        ctx->buf_len = 0;
        ctx->buf_off = 0;
        ctx->tmp_len = 0;
        EVP_EncodeInit(ctx->base64);
    }

    OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf));
    OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
    OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    n = ctx->buf_len - ctx->buf_off;
    while (n > 0) {
        i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
        if (i <= 0) {
            BIO_copy_next_retry(b);
            return (i);
        }
        OPENSSL_assert(i <= n);
        ctx->buf_off += i;
        OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
        n -= i;
    }
    /* at this point all pending data has been written */
    ctx->buf_off = 0;
    ctx->buf_len = 0;

    if ((in == NULL) || (inl <= 0))
        return (0);

    while (inl > 0) {
        n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl;

        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
            if (ctx->tmp_len > 0) {
                OPENSSL_assert(ctx->tmp_len <= 3);
                n = 3 - ctx->tmp_len;
                /*
                 * There's a theoretical possibility for this
                 */
                if (n > inl)
                    n = inl;
                memcpy(&(ctx->tmp[ctx->tmp_len]), in, n);
                ctx->tmp_len += n;
                ret += n;
                if (ctx->tmp_len < 3)
                    break;
                ctx->buf_len =
                    EVP_EncodeBlock((unsigned char *)ctx->buf,
                                    (unsigned char *)ctx->tmp, ctx->tmp_len);
                OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
                OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
                /*
                 * Since we're now done using the temporary buffer, the
                 * length should be 0'd
                 */
                ctx->tmp_len = 0;
            } else {
                if (n < 3) {
                    memcpy(ctx->tmp, in, n);
                    ctx->tmp_len = n;
                    ret += n;
                    break;
                }
                n -= n % 3;
                ctx->buf_len =
                    EVP_EncodeBlock((unsigned char *)ctx->buf,
                                    (const unsigned char *)in, n);
                OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
                OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
                ret += n;
            }
        } else {
            EVP_EncodeUpdate(ctx->base64,
                             (unsigned char *)ctx->buf, &ctx->buf_len,
                             (unsigned char *)in, n);
            OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
            OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
            ret += n;
        }
        inl -= n;
        in += n;

        ctx->buf_off = 0;
        n = ctx->buf_len;
        while (n > 0) {
            i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
            if (i <= 0) {
                BIO_copy_next_retry(b);
                return ((ret == 0) ? i : ret);
            }
            OPENSSL_assert(i <= n);
            n -= i;
            ctx->buf_off += i;
            OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
            OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
        }
        ctx->buf_len = 0;
        ctx->buf_off = 0;
    }
    return (ret);
}
Exemplo n.º 8
0
static int buffer_write(BIO *b, const char *in, int inl)
{
    int i, num = 0;
    BIO_F_BUFFER_CTX *ctx;

    if ((in == NULL) || (inl <= 0))
        return (0);
    ctx = (BIO_F_BUFFER_CTX *)b->ptr;
    if ((ctx == NULL) || (b->next_bio == NULL))
        return (0);

    BIO_clear_retry_flags(b);
 start:
    i = ctx->obuf_size - (ctx->obuf_len + ctx->obuf_off);
    /* add to buffer and return */
    if (i >= inl) {
        memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, inl);
        ctx->obuf_len += inl;
        return (num + inl);
    }
    /* else */
    /* stuff already in buffer, so add to it first, then flush */
    if (ctx->obuf_len != 0) {
        if (i > 0) {            /* lets fill it up if we can */
            memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, i);
            in += i;
            inl -= i;
            num += i;
            ctx->obuf_len += i;
        }
        /* we now have a full buffer needing flushing */
        for (;;) {
            i = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
                          ctx->obuf_len);
            if (i <= 0) {
                BIO_copy_next_retry(b);

                if (i < 0)
                    return ((num > 0) ? num : i);
                if (i == 0)
                    return (num);
            }
            ctx->obuf_off += i;
            ctx->obuf_len -= i;
            if (ctx->obuf_len == 0)
                break;
        }
    }
    /*
     * we only get here if the buffer has been flushed and we still have
     * stuff to write
     */
    ctx->obuf_off = 0;

    /* we now have inl bytes to write */
    while (inl >= ctx->obuf_size) {
        i = BIO_write(b->next_bio, in, inl);
        if (i <= 0) {
            BIO_copy_next_retry(b);
            if (i < 0)
                return ((num > 0) ? num : i);
            if (i == 0)
                return (num);
        }
        num += i;
        in += i;
        inl -= i;
        if (inl == 0)
            return (num);
    }

    /*
     * copy the rest into the buffer since we have only a small amount left
     */
    goto start;
}
Exemplo n.º 9
0
static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
{
    BIO *dbio;
    BIO_F_BUFFER_CTX *ctx;
    long ret = 1;
    char *p1, *p2;
    int r, i, *ip;
    int ibs, obs;

    ctx = (BIO_F_BUFFER_CTX *)b->ptr;

    switch (cmd) {
    case BIO_CTRL_RESET:
        ctx->ibuf_off = 0;
        ctx->ibuf_len = 0;
        ctx->obuf_off = 0;
        ctx->obuf_len = 0;
        if (b->next_bio == NULL)
            return (0);
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;
    case BIO_CTRL_INFO:
        ret = (long)ctx->obuf_len;
        break;
    case BIO_C_GET_BUFF_NUM_LINES:
        ret = 0;
        p1 = ctx->ibuf;
        for (i = 0; i < ctx->ibuf_len; i++) {
            if (p1[ctx->ibuf_off + i] == '\n')
                ret++;
        }
        break;
    case BIO_CTRL_WPENDING:
        ret = (long)ctx->obuf_len;
        if (ret == 0) {
            if (b->next_bio == NULL)
                return (0);
            ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        }
        break;
    case BIO_CTRL_PENDING:
        ret = (long)ctx->ibuf_len;
        if (ret == 0) {
            if (b->next_bio == NULL)
                return (0);
            ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        }
        break;
    case BIO_C_SET_BUFF_READ_DATA:
        if (num > ctx->ibuf_size) {
            p1 = OPENSSL_malloc((int)num);
            if (p1 == NULL)
                goto malloc_error;
            OPENSSL_free(ctx->ibuf);
            ctx->ibuf = p1;
        }
        ctx->ibuf_off = 0;
        ctx->ibuf_len = (int)num;
        memcpy(ctx->ibuf, ptr, (int)num);
        ret = 1;
        break;
    case BIO_C_SET_BUFF_SIZE:
        if (ptr != NULL) {
            ip = (int *)ptr;
            if (*ip == 0) {
                ibs = (int)num;
                obs = ctx->obuf_size;
            } else {            /* if (*ip == 1) */

                ibs = ctx->ibuf_size;
                obs = (int)num;
            }
        } else {
            ibs = (int)num;
            obs = (int)num;
        }
        p1 = ctx->ibuf;
        p2 = ctx->obuf;
        if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) {
            p1 = OPENSSL_malloc((int)num);
            if (p1 == NULL)
                goto malloc_error;
        }
        if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) {
            p2 = OPENSSL_malloc((int)num);
            if (p2 == NULL) {
                if (p1 != ctx->ibuf)
                    OPENSSL_free(p1);
                goto malloc_error;
            }
        }
        if (ctx->ibuf != p1) {
            OPENSSL_free(ctx->ibuf);
            ctx->ibuf = p1;
            ctx->ibuf_off = 0;
            ctx->ibuf_len = 0;
            ctx->ibuf_size = ibs;
        }
        if (ctx->obuf != p2) {
            OPENSSL_free(ctx->obuf);
            ctx->obuf = p2;
            ctx->obuf_off = 0;
            ctx->obuf_len = 0;
            ctx->obuf_size = obs;
        }
        break;
    case BIO_C_DO_STATE_MACHINE:
        if (b->next_bio == NULL)
            return (0);
        BIO_clear_retry_flags(b);
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        BIO_copy_next_retry(b);
        break;

    case BIO_CTRL_FLUSH:
        if (b->next_bio == NULL)
            return (0);
        if (ctx->obuf_len <= 0) {
            ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
            break;
        }

        for (;;) {
            BIO_clear_retry_flags(b);
            if (ctx->obuf_len > 0) {
                r = BIO_write(b->next_bio,
                              &(ctx->obuf[ctx->obuf_off]), ctx->obuf_len);
                BIO_copy_next_retry(b);
                if (r <= 0)
                    return ((long)r);
                ctx->obuf_off += r;
                ctx->obuf_len -= r;
            } else {
                ctx->obuf_len = 0;
                ctx->obuf_off = 0;
                ret = 1;
                break;
            }
        }
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;
    case BIO_CTRL_DUP:
        dbio = (BIO *)ptr;
        if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) ||
            !BIO_set_write_buffer_size(dbio, ctx->obuf_size))
            ret = 0;
        break;
    default:
        if (b->next_bio == NULL)
            return (0);
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;
    }
    return (ret);
 malloc_error:
    BIOerr(BIO_F_BUFFER_CTRL, ERR_R_MALLOC_FAILURE);
    return (0);
}
Exemplo n.º 10
0
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
	  EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title,
	  const char *file)
	{
	int len;
	int i;

	for (;;)
		{
		i=BIO_read(bp,(char *)buf,BUFSIZE);
		if(i < 0)
			{
			BIO_printf(bio_err, "Read Error in %s\n",file);
			ERR_print_errors(bio_err);
			return 1;
			}
		if (i == 0) break;
		}
	if(sigin)
		{
		EVP_MD_CTX *ctx;
		BIO_get_md_ctx(bp, &ctx);
		i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key); 
		if(i > 0)
			BIO_printf(out, "Verified OK\n");
		else if(i == 0)
			{
			BIO_printf(out, "Verification Failure\n");
			return 1;
			}
		else
			{
			BIO_printf(bio_err, "Error Verifying Data\n");
			ERR_print_errors(bio_err);
			return 1;
			}
		return 0;
		}
	if(key)
		{
		EVP_MD_CTX *ctx;
		BIO_get_md_ctx(bp, &ctx);
		if(!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key)) 
			{
			BIO_printf(bio_err, "Error Signing Data\n");
			ERR_print_errors(bio_err);
			return 1;
			}
		}
	else
		len=BIO_gets(bp,(char *)buf,BUFSIZE);

	if(binout) BIO_write(out, buf, len);
	else 
		{
		BIO_write(out,title,strlen(title));
		for (i=0; i<len; i++)
			{
			if (sep && (i != 0))
				BIO_printf(out, ":");
			BIO_printf(out, "%02x",buf[i]);
			}
		BIO_printf(out, "\n");
		}
	return 0;
	}
Exemplo n.º 11
0
  int HUServer::hu_aap_recv_process (int tmo) {                                          //
                                                                        // Terminate unless started or starting (we need to process when starting)
    if (iaap_state != hu_STATE_STARTED && iaap_state != hu_STATE_STARTIN) {
      loge ("CHECK: iaap_state: %d (%s)", iaap_state, state_get (iaap_state));
      return (-1);
    }

    int ret = 0;
    errno = 0;
    int min_size_hdr = 4;
    int have_len = 0;                                                   // Length remaining to process for all sub-packets plus 4/8 byte headers


    temp_assembly_buffer.clear();

    bool has_last = false;
    bool has_first = false;
    int chan = -1;
    while (!has_last)
    {                                              // While length remaining to process,... Process Rx packet:
      have_len = hu_aap_tra_recv (enc_buf, min_size_hdr, tmo);
      if (have_len == 0 && !has_first)
      {
        return 0;
      }

      if (have_len < min_size_hdr) {                                      // If we don't have a full 6 byte header at least...
        loge ("Recv have_len: %d", have_len);
        return (-1);
      }

      if (ena_log_verbo) {
        logd ("Recv while (have_len > 0): %d", have_len);
        hex_dump ("LR: ", 16, enc_buf, have_len);
      }
      int cur_chan = (int) enc_buf [0];                                         // Channel
      if (cur_chan != chan && chan >= 0)
      {
          loge ("Interleaved channels");
          return (-1);
      }
      chan = cur_chan;
      int flags = enc_buf [1];                                              // Flags
      int frame_len = be16toh(*((uint16_t*)&enc_buf[2]));

      logd("Frame flags %i len %i", flags, frame_len);

      if (frame_len > MAX_FRAME_PAYLOAD_SIZE)
      {
          loge ("Too big");
          return (-1);
      }

      int header_size = 4;
      bool has_total_size_header = false;
      if ((flags & HU_FRAME_FIRST_FRAME) & !(flags & HU_FRAME_LAST_FRAME))
      {
        //if first but not last, next 4 is total size
        has_total_size_header = true;
        header_size += 4;
      }

      int remaining_bytes_in_frame = (frame_len + header_size) - have_len;
      while(remaining_bytes_in_frame > 0)
      {
        logd("Getting more %i", remaining_bytes_in_frame);
        int got_bytes = hu_aap_tra_recv (&enc_buf[have_len], remaining_bytes_in_frame, tmo);     // Get Rx packet from Transport
        if (got_bytes < 0) {                                      // If we don't have a full 6 byte header at least...
          loge ("Recv got_bytes: %d", got_bytes);
          return (-1);
        }
        have_len += got_bytes;
        remaining_bytes_in_frame -= got_bytes;
      }

      if (!has_first && !(flags & HU_FRAME_FIRST_FRAME))
      {
          loge ("No HU_FRAME_FIRST_FRAME");
          return (-1);
      }
      has_first = true;
      has_last = (flags & HU_FRAME_LAST_FRAME) != 0;

      if (has_total_size_header)
      {
        uint32_t total_size = be32toh(*((uint32_t*)&enc_buf[4]));
        logd("First only, total len %u", total_size);
        temp_assembly_buffer.reserve(total_size);
      }
      else
      {
        temp_assembly_buffer.reserve(frame_len);
      }


      if (flags & HU_FRAME_ENCRYPTED)
      {
          size_t cur_vec = temp_assembly_buffer.size();
          temp_assembly_buffer.resize(cur_vec + frame_len); //just incase

          int bytes_written = BIO_write (hu_ssl_rm_bio, &enc_buf[header_size], frame_len);           // Write encrypted to SSL input BIO
          if (bytes_written <= 0) {
            loge ("BIO_write() bytes_written: %d", bytes_written);
            return (-1);
          }
          if (bytes_written != frame_len)
            loge ("BIO_write() len: %d  bytes_written: %d  chan: %d %s", frame_len, bytes_written, chan, chan_get (chan));
          else if (ena_log_verbo)
            logd ("BIO_write() len: %d  bytes_written: %d  chan: %d %s", frame_len, bytes_written, chan, chan_get (chan));

          int bytes_read = SSL_read (hu_ssl_ssl, &temp_assembly_buffer[cur_vec], frame_len);   // Read decrypted to decrypted rx buf
          if (bytes_read <= 0 || bytes_read > frame_len) {
            loge ("SSL_read() bytes_read: %d  errno: %d", bytes_read, errno);
            hu_ssl_ret_log (bytes_read);
            return (-1);                                                      // Fatal so return error and de-initialize; Should we be able to recover, if Transport data got corrupted ??
          }
          if (ena_log_verbo)
            logd ("SSL_read() bytes_read: %d", bytes_read);

          temp_assembly_buffer.resize(cur_vec + bytes_read);
      }
      else
      {
          temp_assembly_buffer.insert(temp_assembly_buffer.end(), &enc_buf[header_size], &enc_buf[frame_len+header_size]);
      }
    }

    const int buf_len = temp_assembly_buffer.size();
    if (buf_len >= 2)
    {
      uint16_t msg_type = be16toh(*reinterpret_cast<uint16_t*>(temp_assembly_buffer.data()));

      ret = iaap_msg_process (chan, msg_type, &temp_assembly_buffer[2], buf_len - 2);          // Decrypt & Process 1 received encrypted message
      if (ret < 0 && iaap_state != hu_STATE_STOPPED) {                                                    // If error...
        loge ("Error iaap_msg_process() ret: %d  ", ret);
        return (ret);
      }
    }

    return (ret);                                                       // Return value from the last iaap_recv_dec_process() call; should be 0
  }
Exemplo n.º 12
0
int pkeyutl_main(int argc, char **argv)
{
    BIO *in = NULL, *out = NULL;
    ENGINE *e = NULL;
    EVP_PKEY_CTX *ctx = NULL;
    EVP_PKEY *pkey = NULL;
    char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL;
    char hexdump = 0, asn1parse = 0, rev = 0, *prog;
    unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
    OPTION_CHOICE o;
    int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM;
    int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
    int engine_impl = 0;
    int ret = 1, rv = -1;
    size_t buf_outlen;
    const char *inkey = NULL;
    const char *peerkey = NULL;
    const char *kdfalg = NULL;
    int kdflen = 0;
    STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
    STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
    int rawin = 0;
    const EVP_MD *md = NULL;

    prog = opt_init(argc, argv, pkeyutl_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(pkeyutl_options);
            ret = 0;
            goto end;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_SIGFILE:
            sigfile = opt_arg();
            break;
        case OPT_ENGINE_IMPL:
            engine_impl = 1;
            break;
        case OPT_INKEY:
            inkey = opt_arg();
            break;
        case OPT_PEERKEY:
            peerkey = opt_arg();
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_PEERFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform))
                goto opthelp;
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform))
                goto opthelp;
            break;
        case OPT_R_CASES:
            if (!opt_rand(o))
                goto end;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_PUBIN:
            key_type = KEY_PUBKEY;
            break;
        case OPT_CERTIN:
            key_type = KEY_CERT;
            break;
        case OPT_ASN1PARSE:
            asn1parse = 1;
            break;
        case OPT_HEXDUMP:
            hexdump = 1;
            break;
        case OPT_SIGN:
            pkey_op = EVP_PKEY_OP_SIGN;
            break;
        case OPT_VERIFY:
            pkey_op = EVP_PKEY_OP_VERIFY;
            break;
        case OPT_VERIFYRECOVER:
            pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
            break;
        case OPT_ENCRYPT:
            pkey_op = EVP_PKEY_OP_ENCRYPT;
            break;
        case OPT_DECRYPT:
            pkey_op = EVP_PKEY_OP_DECRYPT;
            break;
        case OPT_DERIVE:
            pkey_op = EVP_PKEY_OP_DERIVE;
            break;
        case OPT_KDF:
            pkey_op = EVP_PKEY_OP_DERIVE;
            key_type = KEY_NONE;
            kdfalg = opt_arg();
            break;
        case OPT_KDFLEN:
            kdflen = atoi(opt_arg());
            break;
        case OPT_REV:
            rev = 1;
            break;
        case OPT_PKEYOPT:
            if ((pkeyopts == NULL &&
                 (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) ||
                sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) {
                BIO_puts(bio_err, "out of memory\n");
                goto end;
            }
            break;
        case OPT_PKEYOPT_PASSIN:
            if ((pkeyopts_passin == NULL &&
                 (pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) ||
                sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) {
                BIO_puts(bio_err, "out of memory\n");
                goto end;
            }
            break;
        case OPT_RAWIN:
            rawin = 1;
            break;
        case OPT_DIGEST:
            if (!opt_md(opt_arg(), &md))
                goto end;
            break;
        }
    }
    argc = opt_num_rest();
    if (argc != 0)
        goto opthelp;

    if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
        BIO_printf(bio_err,
                   "%s: -rawin can only be used with -sign or -verify\n",
                   prog);
        goto opthelp;
    }

    if (md != NULL && !rawin) {
        BIO_printf(bio_err,
                   "%s: -digest can only be used with -rawin\n",
                   prog);
        goto opthelp;
    }

    if (rawin && rev) {
        BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n",
                   prog);
        goto opthelp;
    }

    if (kdfalg != NULL) {
        if (kdflen == 0) {
            BIO_printf(bio_err,
                       "%s: no KDF length given (-kdflen parameter).\n", prog);
            goto opthelp;
        }
    } else if (inkey == NULL) {
        BIO_printf(bio_err,
                   "%s: no private key given (-inkey parameter).\n", prog);
        goto opthelp;
    } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) {
        BIO_printf(bio_err,
                   "%s: no peer key given (-peerkey parameter).\n", prog);
        goto opthelp;
    }
    ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
                   passinarg, pkey_op, e, engine_impl, &pkey);
    if (ctx == NULL) {
        BIO_printf(bio_err, "%s: Error initializing context\n", prog);
        ERR_print_errors(bio_err);
        goto end;
    }
    if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) {
        BIO_printf(bio_err, "%s: Error setting up peer key\n", prog);
        ERR_print_errors(bio_err);
        goto end;
    }
    if (pkeyopts != NULL) {
        int num = sk_OPENSSL_STRING_num(pkeyopts);
        int i;

        for (i = 0; i < num; ++i) {
            const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i);

            if (pkey_ctrl_string(ctx, opt) <= 0) {
                BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
                           prog, opt);
                ERR_print_errors(bio_err);
                goto end;
            }
        }
    }
    if (pkeyopts_passin != NULL) {
        int num = sk_OPENSSL_STRING_num(pkeyopts_passin);
        int i;

        for (i = 0; i < num; i++) {
            char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i);
            char *passin = strchr(opt, ':');
            char *passwd;

            if (passin == NULL) {
                /* Get password interactively */
                char passwd_buf[4096];
                BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt);
                EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1,
                                   passwd_buf, 0);
                passwd = OPENSSL_strdup(passwd_buf);
                if (passwd == NULL) {
                    BIO_puts(bio_err, "out of memory\n");
                    goto end;
                }
            } else {
                /* Get password as a passin argument: First split option name
                 * and passphrase argument into two strings */
                *passin = 0;
                passin++;
                if (app_passwd(passin, NULL, &passwd, NULL) == 0) {
                    BIO_printf(bio_err, "failed to get '%s'\n", opt);
                    goto end;
                }
            }

            if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) {
                BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
                           prog, opt);
                goto end;
            }
            OPENSSL_free(passwd);
        }
    }

    if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) {
        BIO_printf(bio_err,
                   "%s: Signature file specified for non verify\n", prog);
        goto end;
    }

    if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) {
        BIO_printf(bio_err,
                   "%s: No signature file specified for verify\n", prog);
        goto end;
    }

    if (pkey_op != EVP_PKEY_OP_DERIVE) {
        in = bio_open_default(infile, 'r', FORMAT_BINARY);
        if (in == NULL)
            goto end;
    }
    out = bio_open_default(outfile, 'w', FORMAT_BINARY);
    if (out == NULL)
        goto end;

    if (sigfile != NULL) {
        BIO *sigbio = BIO_new_file(sigfile, "rb");

        if (sigbio == NULL) {
            BIO_printf(bio_err, "Can't open signature file %s\n", sigfile);
            goto end;
        }
        siglen = bio_to_mem(&sig, keysize * 10, sigbio);
        BIO_free(sigbio);
        if (siglen < 0) {
            BIO_printf(bio_err, "Error reading signature data\n");
            goto end;
        }
    }

    /* Raw input data is handled elsewhere */
    if (in != NULL && !rawin) {
        /* Read the input data */
        buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
        if (buf_inlen < 0) {
            BIO_printf(bio_err, "Error reading input Data\n");
            goto end;
        }
        if (rev) {
            size_t i;
            unsigned char ctmp;
            size_t l = (size_t)buf_inlen;
            for (i = 0; i < l / 2; i++) {
                ctmp = buf_in[i];
                buf_in[i] = buf_in[l - 1 - i];
                buf_in[l - 1 - i] = ctmp;
            }
        }
    }

    /* Sanity check the input if the input is not raw */
    if (!rawin
            && buf_inlen > EVP_MAX_MD_SIZE
            && (pkey_op == EVP_PKEY_OP_SIGN
                || pkey_op == EVP_PKEY_OP_VERIFY
                || pkey_op == EVP_PKEY_OP_VERIFYRECOVER)) {
        BIO_printf(bio_err,
                   "Error: The input data looks too long to be a hash\n");
        goto end;
    }

    if (pkey_op == EVP_PKEY_OP_VERIFY) {
        if (rawin) {
            rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, sig, siglen,
                              NULL, 0);
        } else {
            rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
                                 buf_in, (size_t)buf_inlen);
        }
        if (rv == 1) {
            BIO_puts(out, "Signature Verified Successfully\n");
            ret = 0;
        } else {
            BIO_puts(out, "Signature Verification Failure\n");
        }
        goto end;
    }
    if (kdflen != 0) {
        buf_outlen = kdflen;
        rv = 1;
    } else {
        if (rawin) {
            /* rawin allocates the buffer in do_raw_keyop() */
            rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, NULL, 0,
                              &buf_out, (size_t *)&buf_outlen);
        } else {
            rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
                          buf_in, (size_t)buf_inlen);
            if (rv > 0 && buf_outlen != 0) {
                buf_out = app_malloc(buf_outlen, "buffer output");
                rv = do_keyop(ctx, pkey_op,
                              buf_out, (size_t *)&buf_outlen,
                              buf_in, (size_t)buf_inlen);
            }
        }
    }
    if (rv <= 0) {
        if (pkey_op != EVP_PKEY_OP_DERIVE) {
            BIO_puts(bio_err, "Public Key operation error\n");
        } else {
            BIO_puts(bio_err, "Key derivation failed\n");
        }
        ERR_print_errors(bio_err);
        goto end;
    }
    ret = 0;

    if (asn1parse) {
        if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
            ERR_print_errors(bio_err);
    } else if (hexdump) {
        BIO_dump(out, (char *)buf_out, buf_outlen);
    } else {
        BIO_write(out, buf_out, buf_outlen);
    }

 end:
    EVP_PKEY_CTX_free(ctx);
    release_engine(e);
    BIO_free(in);
    BIO_free_all(out);
    OPENSSL_free(buf_in);
    OPENSSL_free(buf_out);
    OPENSSL_free(sig);
    sk_OPENSSL_STRING_free(pkeyopts);
    sk_OPENSSL_STRING_free(pkeyopts_passin);
    return ret;
}
Exemplo n.º 13
0
/** Returns status of ticket by filling 'buf' with a NetID if the ticket
 *  is valid and buf is large enough and returning 1.  If not, 0 is
 *  returned.
 */
int cas_validate(
    char *ticket, char *service, char *outbuf, int outbuflen, pam_cas_config_t *config)
{
  int b, ret, total;
  SSL_CTX *ctx = NULL;
  BIO * bio = NULL;
  SSL *ssl = NULL;
  char buf[4096];
  char *full_request = NULL, *str;
  char netid[CAS_LEN_NETID];
  char parsebuf[128];

  debug = config->debug;

  if (config->ssl)
  {
    DEBUG_LOG("We use SSL as configured\n", "");
    /* Set up the SSL library */
    ERR_load_BIO_strings();
    SSL_load_error_strings();
    OpenSSL_add_all_algorithms();
#if defined(OpenSSL_add_ssl_algorithms)
    OpenSSL_add_ssl_algorithms();
#endif

    /* Set up the SSL context */
    ctx = SSL_CTX_new(SSLv23_client_method());
    if ( ! ctx ) 
    {
      DEBUG_LOG("Cannot create SSL context", "");
      END(CAS_SSL_ERROR_INIT);
    }

    /* Load the trust store */
    if(! SSL_CTX_load_verify_locations(ctx, config->trusted_ca, NULL))
    {
      DEBUG_LOG("Error loading certificate store : %s\n", ERR_reason_error_string(ERR_get_error()));
      END(CAS_SSL_ERROR_CERT_LOAD);
    }

    /* Setup the connection */
    bio = BIO_new_ssl_connect(ctx);

    /* Set the SSL_MODE_AUTO_RETRY flag :
       if the server suddenly wants a new handshake, OpenSSL handles it in the background */
    BIO_get_ssl(bio, & ssl);
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    /* Create and setup the connection */
    DEBUG_LOG("We connect to host %s\n", config->host);
    BIO_set_conn_hostname(bio, config->host);
    BIO_set_conn_port(bio, config->port);
    if(BIO_do_connect(bio) <= 0)
    {
      DEBUG_LOG("Error attempting to connect : %s\n", ERR_reason_error_string(ERR_get_error()));
      END(CAS_SSL_ERROR_CONN);
    }

    /* Check the certificate */
    if (SSL_get_verify_result(ssl) != X509_V_OK)
    {
      DEBUG_LOG("Certificate verification error: %ld\n", SSL_get_verify_result(ssl));
      END(CAS_SSL_ERROR_CERT_VALID);
    }
  }
  else  /* no ssl */
  {    
    bio = BIO_new_connect(config->host);
    BIO_set_conn_port(bio, config->port);
    if(BIO_do_connect(bio) <= 0)
    {
      DEBUG_LOG("Error attempting to connect : %s\n", config->host);
      END(CAS_ERROR_CONN);
    }
  }

  /* build request */
  full_request = malloc(strlen(CAS_METHOD) + strlen(" ")
    + strlen(config->uriValidate) + strlen("?ticket=") + strlen(ticket) + 
    + strlen("&service=") + strlen(service) + strlen(" ") 
    + strlen(GENERIC_HEADERS) + strlen ("\r\n")
#ifdef HEADER_HOST_NAME
    + strlen(HEADER_HOST_NAME) + strlen (": ") + strlen (config->host)
#endif
    + strlen("\r\n\r\n") + 1);
  if (full_request == NULL)
  {
      DEBUG_LOG("Error memory allocation%s\n", "");
      END(CAS_ERROR_MEMORY_ALLOC);
  }
#ifdef HEADER_HOST_NAME
  sprintf(full_request, "%s %s?ticket=%s&service=%s %s\r\n%s: %s\r\n\r\n",
	  CAS_METHOD, config->uriValidate, ticket, service, GENERIC_HEADERS,
          HEADER_HOST_NAME,config->host);
#else
  sprintf(full_request, "%s %s?ticket=%s&service=%s %s\r\n\r\n",
	  CAS_METHOD, config->uriValidate, ticket, service, GENERIC_HEADERS);
#endif

  /* send request */
  DEBUG_LOG("---- request :\n%s\n", full_request);
  if (BIO_write(bio, full_request, strlen(full_request)) != strlen(full_request))
  {
    DEBUG_LOG("Unable to correctly send request to %s\n", config->host);
    END(CAS_ERROR_HTTP);
  }

  /* Read the response */
  total = 0;
  b = 0;
  do 
  {
    b = BIO_read(bio, buf + total, (sizeof(buf) - 1) - total);
    total += b;
  } while (b > 0);
  buf[total] = '\0';

  if (b != 0 || total >= sizeof(buf) - 1)
  {
    DEBUG_LOG("Unexpected read error or response too large from %s\n", config->host);
    DEBUG_LOG("b = %d\n", b);
    DEBUG_LOG("total = %d\n", total);
    DEBUG_LOG("buf = %s\n", buf);
    END(CAS_ERROR_HTTP);		// unexpected read error or response too large
  }

  DEBUG_LOG("---- response :\n%s\n", buf);
  str = (char *)strstr(buf, "\r\n\r\n");  // find the end of the header

  if (!str)
  {
    DEBUG_LOG("no header in response%s\n", "");
    END(CAS_ERROR_HTTP);			  // no header
  }

  /*
   * 'str' now points to the beginning of the body, which should be an
   * XML document
   */

  // make sure that the authentication succeeded
  
  if (!element_body(
    str, "cas:authenticationSuccess", 1, parsebuf, sizeof(parsebuf))) {
    END(CAS_BAD_TICKET);
  }

  // retrieve the NetID
  if (!element_body(str, "cas:user", 1, netid, sizeof(netid))) {
    DEBUG_LOG("unable to determine username%s\n", "");
    END(CAS_PROTOCOL_FAILURE);
  }


  // check the first proxy (if present)
  if ((config->proxies) && (config->proxies[0]))
    if (element_body(str, "cas:proxies", 1, parsebuf, sizeof(parsebuf)))
      if (element_body(str, "cas:proxy", 1, parsebuf, sizeof(parsebuf)))
        if (!arrayContains(config->proxies, parsebuf)) {
          DEBUG_LOG("bad proxy: %s\n", parsebuf);
          END(CAS_BAD_PROXY);
        }

  /*
   * without enough space, fail entirely, since a partial NetID could
   * be dangerous
   */
  if (outbuflen < strlen(netid) + 1) 
  {
    syslog(LOG_ERR, "output buffer too short");
    DEBUG_LOG("output buffer too short%s\n", "");
    END(CAS_PROTOCOL_FAILURE);
  }

  strcpy(outbuf, netid);
  SUCCEED;

   /* cleanup and return */

end:
  if (ctx)
    SSL_CTX_free(ctx);
  if (bio)
    BIO_free_all(bio);
  if (full_request)
    free(full_request);
  return ret;
}
Exemplo n.º 14
0
int main(int argc, char **argv)  
{
    BIO *sslbio;
    SSL_CTX *ctx;  
    SSL *ssl;  
    //SSL_METHOD *meth;  
    unsigned long totl;  
    int i, p;
    char hostname[BUF_SIZE + 1];
    char server[16];
    char choice;
    int ret;    

  
    if (argc != 2) {  
        printf("Usage: %s ClientName\n", argv[0]);  
        printf("eg: '%s client1'\n", argv[0]);  
        return -1;  
    }

    if (strlen(argv[1]) >= NAME_SIZE) {
        fprintf(stderr, "%s is too long! \nPick a shorter client name.\n",argv[1]);
    } else {
        strcpy(CLIENT_NAME, argv[1]);    
    }
    printf("client name: %s\n", CLIENT_NAME);

    /* Formatting required certificates for client ...
       certificates are matched to client with file names */
    int length = strlen(CLIENT_NAME) + 10;
    char CLIENT_CERT_FILE2[length];
    strcpy(CLIENT_CERT_FILE2, "cert/");
    strcat(CLIENT_CERT_FILE2, CLIENT_NAME);
    strcat(CLIENT_CERT_FILE2, ".pem");
    printf("This client CERT file is required: %s\n", CLIENT_CERT_FILE2);
    // Checking for required certificate
    if( access( CLIENT_CERT_FILE2, F_OK ) != -1 ) {
    // file exists
	printf("CERT file verified present\n");
    } else {
    // file doesn't exist
	printf("CERT NOT FOUND....\n"
		"Perhaps this client does not have valid\n"
		"certificates present at this location\n"
		">>> ./%s\n",CLIENT_CERT_FILE2);
	exit(4);
    }
    char CLIENT_KEY_FILE2[length];
    strcpy(CLIENT_KEY_FILE2, "cert/");
    strcat(CLIENT_KEY_FILE2, CLIENT_NAME);
    strcat(CLIENT_KEY_FILE2, ".key");
    printf("This client KEY file is required: %s\n", CLIENT_KEY_FILE2);
    // Checking for required certificate
    if( access( CLIENT_KEY_FILE2, F_OK ) != -1 ) {
    // file exists
	printf("KEY file verified present\n\n");
    } else {
    // file doesn't exist
	printf("KEY NOT FOUND....\n"
		"Perhaps this client does not have valid"
		"certificates present at this location\n"
		">>> ./%s\n",CLIENT_KEY_FILE2);
	exit(4);
    }

    /* Give initial menu to user; get hostname for connection */
    choice = getchoice("Please select an action", imenu);
    printf("You have chosen: %c\n", choice);
    if (choice == 'q')
    {
	printf("Ending Program... Goodbye.\n");
    } 
    else // choice == 'a' 
    {
	printf("Initializing connection...\n");
    
	// NOTE: 45 is the max length of a IPv4 address
        getInput(server, "Enter server hostname to connect \n (e.g., '127.0.0.1')", 15);
    	SSL_library_init();  
    	ERR_load_BIO_strings();
    	ERR_load_SSL_strings();  
    	SSL_load_error_strings();
    	OpenSSL_add_all_algorithms();
	ctx = SSL_CTX_new(SSLv3_client_method()); 
//    	ctx = SSL_CTX_new(SSLv3_method());
    	  
    	//ctx = SSL_CTX_new(meth);  
    	assert(ctx != NULL);  
          
    	/* Verify the server */  
    	SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);  
    	/* Load CA Certificate */  
    	if (!SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, NULL)) {  
            printf("Load CA file failed.\r\n");  
            //goto free_ctx;
            BIO_free_all(sslbio);
            SSL_CTX_free(ctx);
            return 0;
        }  
  

    	/* Load Client Certificate with Public Key */  
    	if (SSL_CTX_use_certificate_file(ctx, CLIENT_CERT_FILE2, SSL_FILETYPE_PEM) <= 0) {  
            ERR_print_errors_fp(stdout);  
            printf("ssl_ctx_use_certificate_file failed.\r\n");  
            //goto free_ctx;
            BIO_free_all(sslbio);
            SSL_CTX_free(ctx);
            return 0;  
        }  
  
      
    	/* Load Private Key */  
    	if (SSL_CTX_use_PrivateKey_file(ctx, CLIENT_KEY_FILE2, SSL_FILETYPE_PEM) <= 0) {  
            ERR_print_errors_fp(stdout);  
            printf("ssl_ctx_use_privatekey_file failed.\r\n");  
            //goto free_ctx;
            BIO_free_all(sslbio);
            SSL_CTX_free(ctx);
            return 0;
        }  
  
      
    	/* Check the validity of Private Key */  
    	if (!SSL_CTX_check_private_key(ctx)) {  
            ERR_print_errors_fp(stdout);  
            printf("ssl_ctx_check_private_key failed.\r\n");  
            //goto free_ctx;
            BIO_free_all(sslbio);
            SSL_CTX_free(ctx);
            return 0;  
    	}

    	/* Create the connection */
    	sslbio = BIO_new_ssl_connect(ctx);
    	/* Get SSL from sslbio */
    	BIO_get_ssl(sslbio, &ssl);
    	/* Set the SSL mode into SSL_MODE_AUTO_RETRY */
    	SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
 
    	//////////////////////////////////////////////////
    	// NOTE: Port# hardcoded here; change if necessary
    	////////////////////////////////////////////////// 
    	BIO_set_conn_port(sslbio, "7777");
    	BIO_set_conn_hostname(sslbio, server);
	
	/* Request Connection */
	if(BIO_do_connect(sslbio) <= 0)
    	{
            fprintf(stderr, "Error attempting to connect\n");
            ERR_print_errors_fp(stderr);
            BIO_free_all(sslbio);
            SSL_CTX_free(ctx);
            return 0;
    	}
    	else
    	{
            printf("Connection to server successful!\n");
    	}

    	/* Verify Server Certificate Validity */
    	if(SSL_get_verify_result(ssl) != X509_V_OK)
    	{
            printf("Certificate Verification Error: %ld\n", SSL_get_verify_result(ssl));
            BIO_free_all(sslbio);
            SSL_CTX_free(ctx);
            return 0;
    	}
    	else
    	{
    	    printf("verify server cert successful\n");
    	}

    	//Send hostname to server
    	printf("Sending client name to server.\n");
    	BIO_write(sslbio, CLIENT_NAME, strlen(CLIENT_NAME));
  
    	do
    	{
    	    choice = getchoice("Please select an action", menu);
    	    printf("You have chosen: %c\n", choice);
	
	    if (choice == 'a')
	    {
        	printf("Check-in function will be executed\n");
                choiceProcess (sslbio, buffer, choice);
                ret = checkin_file(ssl, sslbio, buffer);
            }
            else if (choice == 'b')
            {
                printf("Check-out function will be executed\n");
                choiceProcess (sslbio, buffer, choice);
		ret = checkout_file(ssl, sslbio, buffer);
            }
            else if (choice == 'c')
            {
                printf("Delegate function will be executed\n");
                choiceProcess (sslbio, buffer, choice);
            }
            else if (choice == 'd')
            {
                printf("Safe-delete function will be executed\n");
                choiceProcess (sslbio, buffer, choice);
            }
            else
            {
                printf("Terminate function will be executed\n");
            }

        } while (choice != 'q');

        /* Terminate the connection by sending message */
        clientTerminate (sslbio, buffer);

        /* Close the connection and free the context */
        BIO_ssl_shutdown(sslbio);
        BIO_free_all(sslbio);
    	SSL_CTX_free(ctx);
    }

    return 0;  
} 
Exemplo n.º 15
0
static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *buffer, size_t max_len)
{
  pni_ssl_t *ssl = transport->ssl;
  if (!ssl) return PN_EOS;
  if (ssl->ssl == NULL && init_ssl_socket(transport, ssl)) return PN_EOS;

  ssize_t written = 0;
  bool work_pending;

  do {
    work_pending = false;
    // first, get any pending application output, if possible

    if (!ssl->app_output_closed && ssl->out_count < ssl->out_size) {
      ssize_t app_bytes = transport->io_layers[layer+1]->process_output(transport, layer+1, &ssl->outbuf[ssl->out_count], ssl->out_size - ssl->out_count);
      if (app_bytes > 0) {
        ssl->out_count += app_bytes;
        work_pending = true;
        ssl_log(transport, "Gathered %d bytes from app to send to peer", app_bytes );
      } else {
        if (app_bytes < 0) {
          ssl_log(transport, "Application layer closed its output, error=%d (%d bytes pending send)",
               (int) app_bytes, (int) ssl->out_count);
          ssl->app_output_closed = app_bytes;
        }
      }
    }

    // now push any pending app data into the socket

    if (!ssl->ssl_closed) {
      char *data = ssl->outbuf;
      if (ssl->out_count > 0) {
        int wrote = BIO_write( ssl->bio_ssl, data, ssl->out_count );
        if (wrote > 0) {
          data += wrote;
          ssl->out_count -= wrote;
          work_pending = true;
          ssl_log( transport, "Wrote %d bytes from app to socket", wrote );
        } else {
          if (!BIO_should_retry(ssl->bio_ssl)) {
            int reason = SSL_get_error( ssl->ssl, wrote );
            switch (reason) {
            case SSL_ERROR_ZERO_RETURN:
              // SSL closed cleanly
              ssl_log(transport, "SSL connection has closed");
              start_ssl_shutdown(transport); // KAG: not sure - this may not be necessary
              ssl->out_count = 0;      // can no longer write to socket, so erase app output data
              ssl->ssl_closed = true;
              break;
            default:
              // unexpected error
              return (ssize_t)ssl_failed(transport);
            }
          } else {
            if (BIO_should_read( ssl->bio_ssl )) {
              ssl->read_blocked = true;
              ssl_log(transport, "Detected read-blocked");
            }
            if (BIO_should_write( ssl->bio_ssl )) {
              ssl->write_blocked = true;
              ssl_log(transport, "Detected write-blocked");
            }
          }
        }
      }

      if (ssl->out_count == 0) {
        if (ssl->app_input_closed && ssl->app_output_closed) {
          // application is done sending/receiving data, and all buffered output data has
          // been written to the SSL socket
          start_ssl_shutdown(transport);
        }
      } else if (data != ssl->outbuf) {
        memmove( ssl->outbuf, data, ssl->out_count );
      }
    }

    // read from the network bio as much as possible, filling the buffer
    if (max_len) {
      int available = BIO_read( ssl->bio_net_io, buffer, max_len );
      if (available > 0) {
        max_len -= available;
        buffer += available;
        written += available;
        ssl->write_blocked = false;
        work_pending = work_pending || max_len > 0;
        ssl_log(transport, "Read %d bytes from BIO Layer", available );
      }
    }

  } while (work_pending);

  //_log(ssl, "written=%d ssl_closed=%d in_count=%d app_input_closed=%d app_output_closed=%d bio_pend=%d",
  //     written, ssl->ssl_closed, ssl->in_count, ssl->app_input_closed, ssl->app_output_closed, BIO_pending(ssl->bio_net_io) );

  // PROTON-82: close the output side as soon as we've sent the SSL close_notify.
  // We're not requiring the response, as some implementations never reply.
  // ----
  // Once no more data is available "below" the SSL socket, tell the transport we are
  // done.
  //if (written == 0 && ssl->ssl_closed && BIO_pending(ssl->bio_net_io) == 0) {
  //  written = ssl->app_output_closed ? ssl->app_output_closed : PN_EOS;
  //}
  if (written == 0 && (SSL_get_shutdown(ssl->ssl) & SSL_SENT_SHUTDOWN) && BIO_pending(ssl->bio_net_io) == 0) {
    written = ssl->app_output_closed ? ssl->app_output_closed : PN_EOS;
    if (transport->io_layers[layer]==&ssl_input_closed_layer) {
      transport->io_layers[layer] = &ssl_closed_layer;
    } else {
      transport->io_layers[layer] = &ssl_output_closed_layer;
    }
  }
  ssl_log(transport, "process_output_ssl() returning %d", (int) written);
  return written;
}
Exemplo n.º 16
0
int rand_main(int argc, char **argv)
{
    BIO *out = NULL;
    char *inrand = NULL, *outfile = NULL, *prog;
    OPTION_CHOICE o;
    int format = FORMAT_BINARY, i, num = -1, r, ret = 1;

    prog = opt_init(argc, argv, rand_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(rand_options);
            ret = 0;
            goto end;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENGINE:
            (void)setup_engine(opt_arg(), 0);
            break;
        case OPT_RAND:
            inrand = opt_arg();
            break;
        case OPT_BASE64:
            format = FORMAT_BASE64;
            break;
        case OPT_HEX:
            format = FORMAT_TEXT;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (argc != 1)
        goto opthelp;
    if (sscanf(argv[0], "%d", &num) != 1 || num < 0)
        goto opthelp;

    app_RAND_load_file(NULL, (inrand != NULL));
    if (inrand != NULL)
        BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                   app_RAND_load_files(inrand));

    out = bio_open_default(outfile, 'w', format);
    if (out == NULL)
        goto end;

    if (format == FORMAT_BASE64) {
        BIO *b64 = BIO_new(BIO_f_base64());
        if (b64 == NULL)
            goto end;
        out = BIO_push(b64, out);
    }

    while (num > 0) {
        unsigned char buf[4096];
        int chunk;

        chunk = num;
        if (chunk > (int)sizeof(buf))
            chunk = sizeof buf;
        r = RAND_bytes(buf, chunk);
        if (r <= 0)
            goto end;
        if (format != FORMAT_TEXT) /* hex */
            BIO_write(out, buf, chunk);
        else {
            for (i = 0; i < chunk; i++)
                BIO_printf(out, "%02x", buf[i]);
        }
        num -= chunk;
    }
    if (format == FORMAT_TEXT)
        BIO_puts(out, "\n");
    (void)BIO_flush(out);

    app_RAND_write_file(NULL);
    ret = 0;

 end:
    BIO_free_all(out);
    return (ret);
}
Exemplo n.º 17
0
// take data from the network, and pass it into SSL.  Attempt to read decrypted data from
// SSL socket and pass it to the application.
static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t available)
{
  pni_ssl_t *ssl = transport->ssl;
  if (ssl->ssl == NULL && init_ssl_socket(transport, ssl)) return PN_EOS;

  ssl_log( transport, "process_input_ssl( data size=%d )",available );

  ssize_t consumed = 0;
  bool work_pending;
  bool shutdown_input = (available == 0);  // caller is closed

  do {
    work_pending = false;

    // Write to network bio as much as possible, consuming bytes/available

    if (available > 0) {
      int written = BIO_write( ssl->bio_net_io, input_data, available );
      if (written > 0) {
        input_data += written;
        available -= written;
        consumed += written;
        ssl->read_blocked = false;
        work_pending = (available > 0);
        ssl_log( transport, "Wrote %d bytes to BIO Layer, %d left over", written, available );
      }
    } else if (shutdown_input) {
      // lower layer (caller) has closed.  Close the WRITE side of the BIO.  This will cause
      // an EOF to be passed to SSL once all pending inbound data has been consumed.
      ssl_log( transport, "Lower layer closed - shutting down BIO write side");
      (void)BIO_shutdown_wr( ssl->bio_net_io );
      shutdown_input = false;
    }

    // Read all available data from the SSL socket

    if (!ssl->ssl_closed && ssl->in_count < ssl->in_size) {
      int read = BIO_read( ssl->bio_ssl, &ssl->inbuf[ssl->in_count], ssl->in_size - ssl->in_count );
      if (read > 0) {
        ssl_log( transport, "Read %d bytes from SSL socket for app", read );
        ssl_log_clear_data(transport, &ssl->inbuf[ssl->in_count], read );
        ssl->in_count += read;
        work_pending = true;
      } else {
        if (!BIO_should_retry(ssl->bio_ssl)) {
          int reason = SSL_get_error( ssl->ssl, read );
          switch (reason) {
          case SSL_ERROR_ZERO_RETURN:
            // SSL closed cleanly
            ssl_log(transport, "SSL connection has closed");
            start_ssl_shutdown(transport);  // KAG: not sure - this may not be necessary
            ssl->ssl_closed = true;
            break;
          default:
            // unexpected error
            return (ssize_t)ssl_failed(transport);
          }
        } else {
          if (BIO_should_write( ssl->bio_ssl )) {
            ssl->write_blocked = true;
            ssl_log(transport, "Detected write-blocked");
          }
          if (BIO_should_read( ssl->bio_ssl )) {
            ssl->read_blocked = true;
            ssl_log(transport, "Detected read-blocked");
          }
        }
      }
    }

    // write incoming data to app layer

    if (!ssl->app_input_closed) {
      if (ssl->in_count > 0 || ssl->ssl_closed) {  /* if ssl_closed, send 0 count */
        ssize_t consumed = transport->io_layers[layer+1]->process_input(transport, layer+1, ssl->inbuf, ssl->in_count);
        if (consumed > 0) {
          ssl->in_count -= consumed;
          if (ssl->in_count)
            memmove( ssl->inbuf, ssl->inbuf + consumed, ssl->in_count );
          work_pending = true;
          ssl_log( transport, "Application consumed %d bytes from peer", (int) consumed );
        } else if (consumed < 0) {
          ssl_log(transport, "Application layer closed its input, error=%d (discarding %d bytes)",
               (int) consumed, (int)ssl->in_count);
          ssl->in_count = 0;    // discard any pending input
          ssl->app_input_closed = consumed;
          if (ssl->app_output_closed && ssl->out_count == 0) {
            // both sides of app closed, and no more app output pending:
            start_ssl_shutdown(transport);
          }
        } else {
          // app did not consume any bytes, must be waiting for a full frame
          if (ssl->in_count == ssl->in_size) {
            // but the buffer is full, not enough room for a full frame.
            // can we grow the buffer?
            uint32_t max_frame = pn_transport_get_max_frame(transport);
            if (!max_frame) max_frame = ssl->in_size * 2;  // no limit
            if (ssl->in_size < max_frame) {
              // no max frame limit - grow it.
              size_t newsize = pn_min(max_frame, ssl->in_size * 2);
              char *newbuf = (char *)realloc( ssl->inbuf, newsize );
              if (newbuf) {
                ssl->in_size = newsize;
                ssl->inbuf = newbuf;
                work_pending = true;  // can we get more input?
              }
            } else {
              // can't gather any more input, but app needs more?
              // This is a bug - since SSL can buffer up to max-frame,
              // the application _must_ have enough data to process.  If
              // this is an oversized frame, the app _must_ handle it
              // by returning an error code to SSL.
              pn_transport_log(transport, "Error: application unable to consume input.");
            }
          }
        }
      }
    }

  } while (work_pending);

  //_log(ssl, "ssl_closed=%d in_count=%d app_input_closed=%d app_output_closed=%d",
  //     ssl->ssl_closed, ssl->in_count, ssl->app_input_closed, ssl->app_output_closed );

  // PROTON-82: Instead, close the input side as soon as we've completed enough of the SSL
  // shutdown handshake to send the close_notify.  We're not requiring the response, as
  // some implementations never reply.
  // ---
  // tell transport our input side is closed if the SSL socket cannot be read from any
  // longer, AND any pending input has been written up to the application (or the
  // application is closed)
  //if (ssl->ssl_closed && ssl->app_input_closed) {
  //  consumed = ssl->app_input_closed;
  //}
  if (ssl->app_input_closed && (SSL_get_shutdown(ssl->ssl) & SSL_SENT_SHUTDOWN) ) {
    consumed = ssl->app_input_closed;
    if (transport->io_layers[layer]==&ssl_output_closed_layer) {
      transport->io_layers[layer] = &ssl_closed_layer;
    } else {
      transport->io_layers[layer] = &ssl_input_closed_layer;
    }
  }
  ssl_log(transport, "process_input_ssl() returning %d", (int) consumed);
  return consumed;
}
Exemplo n.º 18
0
UNSIGNED32 get_timestamp_response(const char* urlStr, char* hash, UNSIGNED32 hash_size, UNSIGNED32 httpTimeOut, TS_RESP** tsResponse)
{
	UNSIGNED32 result = TINTERNALERROR;
	BIO* responseBio = NULL;
	Url* url = NULL;
	TS_REQ* tsRequest = NULL;
	BIO* requestBio = NULL;
	int requestHeaderLength;
	int requestLength;
	int requestContentLength;
	char requestHeader[2048 + 256];
	char* request = NULL;
	void* contentBuffer = NULL;
	void* resultBuffer = NULL;
	int resultLength;
	TS_MSG_IMPRINT* msgImprint = NULL;
	ASN1_OCTET_STRING* hashedMessage = NULL;
	int hashedMessageLength;
	int httpResult;
	char *urlBuffer = NULL;
	int redirection = 0;

	/* Check if TS url is specified */
	if (!urlStr)
	{
		goto end;
	}

	/* Get Request for timestamp */
	tsRequest = get_timestamp_request(hash, hash_size, create_nonce(NONCE_LENGTH));
	msgImprint = TS_REQ_get_msg_imprint(tsRequest);
	hashedMessage = TS_MSG_IMPRINT_get_msg(msgImprint);
	hashedMessageLength = ASN1_STRING_length((ASN1_STRING*)hashedMessage);
	if ((int)hash_size != hashedMessageLength)
	{
		goto end;
	}

	requestBio = BIO_new(BIO_s_mem());
	if (requestBio == NULL)
	{
		goto end;
	}

	if (!i2d_TS_REQ_bio(requestBio, tsRequest))
	{
		goto end;
	}

	contentBuffer = memory_alloc(BIO_number_written(requestBio));
	if (contentBuffer == NULL)
	{
		goto end;
	}

    requestContentLength = BIO_read(requestBio, contentBuffer, BIO_number_written(requestBio));

    /* Allocate memory buffer for timestamp server url */
    urlBuffer = memory_alloc(strlen(urlStr) + 1);
    if (!urlBuffer)
    {
    	goto end;
    }
    /* Copy TS url to allocated buffer */
    strcpy(urlBuffer, urlStr);

http_redirect:

	/* Parse and check URL */
	url = parse_url(urlBuffer);
	if (url == NULL)
	{
		goto end;
	}
	if (strcmp(url->Scheme, "http") != 0)
	{
		goto end;
	}

    requestHeaderLength = sprintf(requestHeader, "POST %s HTTP/1.0\r\nHOST: %s\r\nPragma: no-cache\r\nContent-Type: application/timestamp-query\r\nAccept: application/timestamp-reply\r\nContent-Length: %d\r\n\r\n",
    		urlBuffer, url->Host, requestContentLength);

	requestLength = requestHeaderLength + requestContentLength;

	request = (char*)memory_alloc(requestLength);
	if (request == NULL)
	{
		goto end;
	}

	memcpy(request, requestHeader, requestHeaderLength);
	memcpy(request + requestHeaderLength, contentBuffer, requestContentLength);

	httpResult = http_read(url->Host, request, requestLength, url->Port, httpTimeOut, 1, &resultBuffer, &resultLength);
	if (httpResult == HTTP_REDIRECTION && (resultBuffer) && !redirection)
	{
		free_url(url);
		url = NULL;
		memory_free(request);
		request = NULL;
		/* Allocated buffer for redirected url */
	    urlBuffer = memory_realloc(urlBuffer, resultLength);
	    if (!urlBuffer)
	    {
	    	goto end;
	    }
	    memcpy(urlBuffer, resultBuffer, resultLength);
	    memory_free(resultBuffer);
	    redirection++;
		goto http_redirect;
	} else
	if ((httpResult == HTTP_NOERROR) && (resultBuffer))
	{
		responseBio = BIO_new(BIO_s_mem());
		if (responseBio == NULL)
		{
			goto end;
		}
		BIO_write(responseBio, resultBuffer, resultLength);

		*tsResponse = d2i_TS_RESP_bio(responseBio, NULL);
		if (*tsResponse == NULL)
		{
			goto end;
		}

		result = TNOERR;
	}
	else
	{
		switch (httpResult)
		{
			case HTTP_NOLIVEINTERNET_ERROR:
				result = TNONET;
				break;
			case HTTP_TIMEOUT_ERROR:
				result = TTIMEOUT;
				break;
			case HTTP_RESPONSESTATUS_ERROR:
				result = TSERVERERROR;
				break;
			default:
				result = TINTERNALERROR;
				break;
		}
	}

end:
	free_url(url);
	if (tsRequest != NULL)
	{
		TS_REQ_free(tsRequest);
	}
	if (requestBio != NULL)
	{
		BIO_free_all(requestBio);
	}
	if (responseBio != NULL)
	{
		BIO_free_all(responseBio);
	}
	if (request != NULL)
	{
		memory_free(request);
	}
	if (contentBuffer != NULL)
	{
		memory_free(contentBuffer);
	}
	if (resultBuffer != NULL)
	{
		memory_free(resultBuffer);
	}
	if (urlBuffer != NULL)
	{
		memory_free(urlBuffer);
	}

	return result;
}
Exemplo n.º 19
0
int
enc_main(int argc, char **argv)
{
	static const char magic[] = "Salted__";
	char mbuf[sizeof magic - 1];
	char *strbuf = NULL, *pass = NULL;
	unsigned char *buff = NULL;
	int bsize = BSIZE;
	int ret = 1, inl;
	unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
	unsigned char salt[PKCS5_SALT_LEN];
#ifdef ZLIB
	BIO *bzl = NULL;
#endif
	EVP_CIPHER_CTX *ctx = NULL;
	const EVP_MD *dgst = NULL;
	BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL;
	BIO *rbio = NULL, *wbio = NULL;
#define PROG_NAME_SIZE  39
	char pname[PROG_NAME_SIZE + 1];
	int i;

	if (single_execution) {
		if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
			perror("pledge");
			exit(1);
		}
	}

	memset(&enc_config, 0, sizeof(enc_config));
	enc_config.enc = 1;

	/* first check the program name */
	program_name(argv[0], pname, sizeof(pname));

	if (strcmp(pname, "base64") == 0)
		enc_config.base64 = 1;

#ifdef ZLIB
	if (strcmp(pname, "zlib") == 0)
		enc_config.do_zlib = 1;
#endif

	enc_config.cipher = EVP_get_cipherbyname(pname);

#ifdef ZLIB
	if (!enc_config.do_zlib && !enc_config.base64 &&
	    enc_config.cipher == NULL && strcmp(pname, "enc") != 0)
#else
	if (!enc_config.base64 && enc_config.cipher == NULL &&
	    strcmp(pname, "enc") != 0)
#endif
	{
		BIO_printf(bio_err, "%s is an unknown cipher\n", pname);
		goto end;
	}

	if (options_parse(argc, argv, enc_options, NULL, NULL) != 0) {
		enc_usage();
		goto end;
	}

	if (enc_config.keyfile != NULL) {
		static char buf[128];
		FILE *infile;

		infile = fopen(enc_config.keyfile, "r");
		if (infile == NULL) {
			BIO_printf(bio_err, "unable to read key from '%s'\n",
			    enc_config.keyfile);
			goto end;
		}
		buf[0] = '\0';
		if (!fgets(buf, sizeof buf, infile)) {
			BIO_printf(bio_err, "unable to read key from '%s'\n",
			    enc_config.keyfile);
			fclose(infile);
			goto end;
		}
		fclose(infile);
		i = strlen(buf);
		if ((i > 0) && ((buf[i - 1] == '\n') || (buf[i - 1] == '\r')))
			buf[--i] = '\0';
		if ((i > 0) && ((buf[i - 1] == '\n') || (buf[i - 1] == '\r')))
			buf[--i] = '\0';
		if (i < 1) {
			BIO_printf(bio_err, "zero length password\n");
			goto end;
		}
		enc_config.keystr = buf;
	}

	if (enc_config.md != NULL &&
	    (dgst = EVP_get_digestbyname(enc_config.md)) == NULL) {
		BIO_printf(bio_err,
		    "%s is an unsupported message digest type\n",
		    enc_config.md);
		goto end;
	}
	if (dgst == NULL) {
		dgst = EVP_md5();	/* XXX */
	}

	if (enc_config.bufsize != NULL) {
		char *p = enc_config.bufsize;
		unsigned long n;

		/* XXX - provide an OPTION_ARG_DISKUNIT. */
		for (n = 0; *p != '\0'; p++) {
			i = *p;
			if ((i <= '9') && (i >= '0'))
				n = n * 10 + i - '0';
			else if (i == 'k') {
				n *= 1024;
				p++;
				break;
			}
		}
		if (*p != '\0') {
			BIO_printf(bio_err, "invalid 'bufsize' specified.\n");
			goto end;
		}
		/* It must be large enough for a base64 encoded line. */
		if (enc_config.base64 && n < 80)
			n = 80;

		bsize = (int)n;
		if (enc_config.verbose)
			BIO_printf(bio_err, "bufsize=%d\n", bsize);
	}
	strbuf = malloc(SIZE);
	buff = malloc(EVP_ENCODE_LENGTH(bsize));
	if ((buff == NULL) || (strbuf == NULL)) {
		BIO_printf(bio_err, "malloc failure %ld\n", (long) EVP_ENCODE_LENGTH(bsize));
		goto end;
	}
	in = BIO_new(BIO_s_file());
	out = BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL)) {
		ERR_print_errors(bio_err);
		goto end;
	}
	if (enc_config.debug) {
		BIO_set_callback(in, BIO_debug_callback);
		BIO_set_callback(out, BIO_debug_callback);
		BIO_set_callback_arg(in, (char *) bio_err);
		BIO_set_callback_arg(out, (char *) bio_err);
	}
	if (enc_config.inf == NULL) {
		if (enc_config.bufsize != NULL)
			setvbuf(stdin, (char *) NULL, _IONBF, 0);
		BIO_set_fp(in, stdin, BIO_NOCLOSE);
	} else {
		if (BIO_read_filename(in, enc_config.inf) <= 0) {
			perror(enc_config.inf);
			goto end;
		}
	}

	if (!enc_config.keystr && enc_config.passarg) {
		if (!app_passwd(bio_err, enc_config.passarg, NULL,
		    &pass, NULL)) {
			BIO_printf(bio_err, "Error getting password\n");
			goto end;
		}
		enc_config.keystr = pass;
	}
	if (enc_config.keystr == NULL && enc_config.cipher != NULL &&
	    enc_config.hkey == NULL) {
		for (;;) {
			char buf[200];
			int retval;

			retval = snprintf(buf, sizeof buf,
			    "enter %s %s password:"******"encryption" : "decryption");
			if ((size_t)retval >= sizeof buf) {
				BIO_printf(bio_err,
				    "Password prompt too long\n");
				goto end;
			}
			strbuf[0] = '\0';
			i = EVP_read_pw_string((char *)strbuf, SIZE, buf,
			    enc_config.enc);
			if (i == 0) {
				if (strbuf[0] == '\0') {
					ret = 1;
					goto end;
				}
				enc_config.keystr = strbuf;
				break;
			}
			if (i < 0) {
				BIO_printf(bio_err, "bad password read\n");
				goto end;
			}
		}
	}
	if (enc_config.outf == NULL) {
		BIO_set_fp(out, stdout, BIO_NOCLOSE);
		if (enc_config.bufsize != NULL)
			setvbuf(stdout, (char *)NULL, _IONBF, 0);
	} else {
		if (BIO_write_filename(out, enc_config.outf) <= 0) {
			perror(enc_config.outf);
			goto end;
		}
	}

	rbio = in;
	wbio = out;

#ifdef ZLIB
	if (do_zlib) {
		if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
			goto end;
		if (enc)
			wbio = BIO_push(bzl, wbio);
		else
			rbio = BIO_push(bzl, rbio);
	}
#endif

	if (enc_config.base64) {
		if ((b64 = BIO_new(BIO_f_base64())) == NULL)
			goto end;
		if (enc_config.debug) {
			BIO_set_callback(b64, BIO_debug_callback);
			BIO_set_callback_arg(b64, (char *) bio_err);
		}
		if (enc_config.olb64)
			BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
		if (enc_config.enc)
			wbio = BIO_push(b64, wbio);
		else
			rbio = BIO_push(b64, rbio);
	}
	if (enc_config.cipher != NULL) {
		/*
		 * Note that keystr is NULL if a key was passed on the command
		 * line, so we get no salt in that case. Is this a bug?
		 */
		if (enc_config.keystr != NULL) {
			/*
			 * Salt handling: if encrypting generate a salt and
			 * write to output BIO. If decrypting read salt from
			 * input BIO.
			 */
			unsigned char *sptr;
			if (enc_config.nosalt)
				sptr = NULL;
			else {
				if (enc_config.enc) {
					if (enc_config.hsalt) {
						if (!set_hex(enc_config.hsalt, salt, sizeof salt)) {
							BIO_printf(bio_err,
							    "invalid hex salt value\n");
							goto end;
						}
					} else
						arc4random_buf(salt,
						    sizeof(salt));
					/*
					 * If -P option then don't bother
					 * writing
					 */
					if ((enc_config.printkey != 2)
					    && (BIO_write(wbio, magic,
						    sizeof magic - 1) != sizeof magic - 1
						|| BIO_write(wbio,
						    (char *) salt,
						    sizeof salt) != sizeof salt)) {
						BIO_printf(bio_err, "error writing output file\n");
						goto end;
					}
				} else if (BIO_read(rbio, mbuf, sizeof mbuf) != sizeof mbuf
					    || BIO_read(rbio,
						(unsigned char *) salt,
					sizeof salt) != sizeof salt) {
					BIO_printf(bio_err, "error reading input file\n");
					goto end;
				} else if (memcmp(mbuf, magic, sizeof magic - 1)) {
					BIO_printf(bio_err, "bad magic number\n");
					goto end;
				}
				sptr = salt;
			}

			EVP_BytesToKey(enc_config.cipher, dgst, sptr,
			    (unsigned char *)enc_config.keystr,
			    strlen(enc_config.keystr), 1, key, iv);
			/*
			 * zero the complete buffer or the string passed from
			 * the command line bug picked up by Larry J. Hughes
			 * Jr. <*****@*****.**>
			 */
			if (enc_config.keystr == strbuf)
				explicit_bzero(enc_config.keystr, SIZE);
			else
				explicit_bzero(enc_config.keystr,
				    strlen(enc_config.keystr));
		}
		if (enc_config.hiv != NULL &&
		    !set_hex(enc_config.hiv, iv, sizeof iv)) {
			BIO_printf(bio_err, "invalid hex iv value\n");
			goto end;
		}
		if (enc_config.hiv == NULL && enc_config.keystr == NULL &&
		    EVP_CIPHER_iv_length(enc_config.cipher) != 0) {
			/*
			 * No IV was explicitly set and no IV was generated
			 * during EVP_BytesToKey. Hence the IV is undefined,
			 * making correct decryption impossible.
			 */
			BIO_printf(bio_err, "iv undefined\n");
			goto end;
		}
		if (enc_config.hkey != NULL &&
		    !set_hex(enc_config.hkey, key, sizeof key)) {
			BIO_printf(bio_err, "invalid hex key value\n");
			goto end;
		}
		if ((benc = BIO_new(BIO_f_cipher())) == NULL)
			goto end;

		/*
		 * Since we may be changing parameters work on the encryption
		 * context rather than calling BIO_set_cipher().
		 */

		BIO_get_cipher_ctx(benc, &ctx);

		if (!EVP_CipherInit_ex(ctx, enc_config.cipher, NULL, NULL,
		    NULL, enc_config.enc)) {
			BIO_printf(bio_err, "Error setting cipher %s\n",
			    EVP_CIPHER_name(enc_config.cipher));
			ERR_print_errors(bio_err);
			goto end;
		}
		if (enc_config.nopad)
			EVP_CIPHER_CTX_set_padding(ctx, 0);

		if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv,
		    enc_config.enc)) {
			BIO_printf(bio_err, "Error setting cipher %s\n",
			    EVP_CIPHER_name(enc_config.cipher));
			ERR_print_errors(bio_err);
			goto end;
		}
		if (enc_config.debug) {
			BIO_set_callback(benc, BIO_debug_callback);
			BIO_set_callback_arg(benc, (char *) bio_err);
		}
		if (enc_config.printkey) {
			if (!enc_config.nosalt) {
				printf("salt=");
				for (i = 0; i < (int) sizeof(salt); i++)
					printf("%02X", salt[i]);
				printf("\n");
			}
			if (enc_config.cipher->key_len > 0) {
				printf("key=");
				for (i = 0; i < enc_config.cipher->key_len; i++)
					printf("%02X", key[i]);
				printf("\n");
			}
			if (enc_config.cipher->iv_len > 0) {
				printf("iv =");
				for (i = 0; i < enc_config.cipher->iv_len; i++)
					printf("%02X", iv[i]);
				printf("\n");
			}
			if (enc_config.printkey == 2) {
				ret = 0;
				goto end;
			}
		}
	}
	/* Only encrypt/decrypt as we write the file */
	if (benc != NULL)
		wbio = BIO_push(benc, wbio);

	for (;;) {
		inl = BIO_read(rbio, (char *) buff, bsize);
		if (inl <= 0)
			break;
		if (BIO_write(wbio, (char *) buff, inl) != inl) {
			BIO_printf(bio_err, "error writing output file\n");
			goto end;
		}
	}
	if (!BIO_flush(wbio)) {
		BIO_printf(bio_err, "bad decrypt\n");
		goto end;
	}
	ret = 0;
	if (enc_config.verbose) {
		BIO_printf(bio_err, "bytes read   :%8ld\n", BIO_number_read(in));
		BIO_printf(bio_err, "bytes written:%8ld\n", BIO_number_written(out));
	}
 end:
	ERR_print_errors(bio_err);
	free(strbuf);
	free(buff);
	BIO_free(in);
	BIO_free_all(out);
	BIO_free(benc);
	BIO_free(b64);
#ifdef ZLIB
	BIO_free(bzl);
#endif
	free(pass);

	return (ret);
}
/**
  Handle Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero,
  TLS session has errors and the response packet needs to be Alert message based on error type.

  @param[in]       Tls            Pointer to the TLS object for state checking.
  @param[in]       BufferIn       Pointer to the most recently received TLS Alert packet.
  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
                                  Alert packet.
  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
                                  the buffer size provided by the caller. On output, it
                                  is the buffer size in fact needed to contain the
                                  packet.

  @retval EFI_SUCCESS             The required TLS packet is built successfully.
  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
                                  Tls is NULL.
                                  BufferIn is NULL but BufferInSize is NOT 0.
                                  BufferInSize is 0 but BufferIn is NOT NULL.
                                  BufferOutSize is NULL.
                                  BufferOut is NULL if *BufferOutSize is not zero.
  @retval EFI_ABORTED             An error occurred.
  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.

**/
EFI_STATUS
EFIAPI
TlsHandleAlert (
  IN     VOID                     *Tls,
  IN     UINT8                    *BufferIn, OPTIONAL
  IN     UINTN                    BufferInSize, OPTIONAL
     OUT UINT8                    *BufferOut, OPTIONAL
  IN OUT UINTN                    *BufferOutSize
  )
{
  TLS_CONNECTION  *TlsConn;
  UINTN           PendingBufferSize;
  UINT8           *TempBuffer;
  INTN            Ret;

  TlsConn           = (TLS_CONNECTION *) Tls;
  PendingBufferSize = 0;
  TempBuffer        = NULL;
  Ret               = 0;

  if (TlsConn == NULL || \
    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \
    BufferOutSize == NULL || \
    (BufferIn == NULL && BufferInSize != 0) || \
    (BufferIn != NULL && BufferInSize == 0) || \
    (BufferOut == NULL && *BufferOutSize != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
  if (PendingBufferSize == 0 && BufferIn != NULL && BufferInSize != 0) {
    Ret = BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
    if (Ret != (INTN) BufferInSize) {
      return EFI_ABORTED;
    }

    TempBuffer = (UINT8 *) OPENSSL_malloc (MAX_BUFFER_SIZE);

    //
    // ssl3_send_alert() will be called in ssl3_read_bytes() function.
    // TempBuffer is invalid since it's a Alert message, so just ignore it.
    //
    SSL_read (TlsConn->Ssl, TempBuffer, MAX_BUFFER_SIZE);

    OPENSSL_free (TempBuffer);

    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
  }

  if (PendingBufferSize > *BufferOutSize) {
    *BufferOutSize = PendingBufferSize;
    return EFI_BUFFER_TOO_SMALL;
  }

  if (PendingBufferSize > 0) {
    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);
  } else {
    *BufferOutSize = 0;
  }

  return EFI_SUCCESS;
}
Exemplo n.º 21
0
static int asn1_bio_write(BIO *b, const char *in, int inl)
{
    BIO_ASN1_BUF_CTX *ctx;
    int wrmax, wrlen, ret;
    unsigned char *p;
    if (!in || (inl < 0) || (b->next_bio == NULL))
        return 0;
    ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
    if (ctx == NULL)
        return 0;

    wrlen = 0;
    ret = -1;

    for (;;) {
        switch (ctx->state) {

            /* Setup prefix data, call it */
        case ASN1_STATE_START:
            if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
                                   ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
                return 0;
            break;

            /* Copy any pre data first */
        case ASN1_STATE_PRE_COPY:

            ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
                                    ASN1_STATE_HEADER);

            if (ret <= 0)
                goto done;

            break;

        case ASN1_STATE_HEADER:
            ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
            OPENSSL_assert(ctx->buflen <= ctx->bufsize);
            p = ctx->buf;
            ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
            ctx->copylen = inl;
            ctx->state = ASN1_STATE_HEADER_COPY;

            break;

        case ASN1_STATE_HEADER_COPY:
            ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
            if (ret <= 0)
                goto done;

            ctx->buflen -= ret;
            if (ctx->buflen)
                ctx->bufpos += ret;
            else {
                ctx->bufpos = 0;
                ctx->state = ASN1_STATE_DATA_COPY;
            }

            break;

        case ASN1_STATE_DATA_COPY:

            if (inl > ctx->copylen)
                wrmax = ctx->copylen;
            else
                wrmax = inl;
            ret = BIO_write(b->next_bio, in, wrmax);
            if (ret <= 0)
                break;
            wrlen += ret;
            ctx->copylen -= ret;
            in += ret;
            inl -= ret;

            if (ctx->copylen == 0)
                ctx->state = ASN1_STATE_HEADER;

            if (inl == 0)
                goto done;

            break;

        default:
            BIO_clear_retry_flags(b);
            return 0;

        }

    }

 done:
    BIO_clear_retry_flags(b);
    BIO_copy_next_retry(b);

    return (wrlen > 0) ? wrlen : ret;

}
/**
  Perform a TLS/SSL handshake.

  This function will perform a TLS/SSL handshake.

  @param[in]       Tls            Pointer to the TLS object for handshake operation.
  @param[in]       BufferIn       Pointer to the most recently received TLS Handshake packet.
  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
                                  Handshake packet.
  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
                                  the buffer size provided by the caller. On output, it
                                  is the buffer size in fact needed to contain the
                                  packet.

  @retval EFI_SUCCESS             The required TLS packet is built successfully.
  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
                                  Tls is NULL.
                                  BufferIn is NULL but BufferInSize is NOT 0.
                                  BufferInSize is 0 but BufferIn is NOT NULL.
                                  BufferOutSize is NULL.
                                  BufferOut is NULL if *BufferOutSize is not zero.
  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
  @retval EFI_ABORTED             Something wrong during handshake.

**/
EFI_STATUS
EFIAPI
TlsDoHandshake (
  IN     VOID                     *Tls,
  IN     UINT8                    *BufferIn, OPTIONAL
  IN     UINTN                    BufferInSize, OPTIONAL
     OUT UINT8                    *BufferOut, OPTIONAL
  IN OUT UINTN                    *BufferOutSize
  )
{
  TLS_CONNECTION  *TlsConn;
  UINTN           PendingBufferSize;
  INTN            Ret;
  UINTN           ErrorCode;

  TlsConn           = (TLS_CONNECTION *) Tls;
  PendingBufferSize = 0;
  Ret               = 1;

  if (TlsConn == NULL || \
    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \
    BufferOutSize == NULL || \
    (BufferIn == NULL && BufferInSize != 0) || \
    (BufferIn != NULL && BufferInSize == 0) || \
    (BufferOut == NULL && *BufferOutSize != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  if(BufferIn == NULL && BufferInSize == 0) {
    //
    // If RequestBuffer is NULL and RequestSize is 0, and TLS session
    // status is EfiTlsSessionNotStarted, the TLS session will be initiated
    // and the response packet needs to be ClientHello.
    //
    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
    if (PendingBufferSize == 0) {
      SSL_set_connect_state (TlsConn->Ssl);
      Ret = SSL_do_handshake (TlsConn->Ssl);
      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
    }
  } else {
    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
    if (PendingBufferSize == 0) {
      BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
      Ret = SSL_do_handshake (TlsConn->Ssl);
      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
    }
  }

  if (Ret < 1) {
    Ret = SSL_get_error (TlsConn->Ssl, (int) Ret);
    if (Ret == SSL_ERROR_SSL ||
        Ret == SSL_ERROR_SYSCALL ||
        Ret == SSL_ERROR_ZERO_RETURN) {
      DEBUG ((
        DEBUG_ERROR,
        "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n",
        __FUNCTION__,
        SSL_get_state (TlsConn->Ssl),
        Ret == SSL_ERROR_SSL ? "SSL" : Ret == SSL_ERROR_SYSCALL ? "SYSCALL" : "ZERO_RETURN"
        ));
      DEBUG_CODE_BEGIN ();
        while (TRUE) {
          ErrorCode = ERR_get_error ();
          if (ErrorCode == 0) {
            break;
          }
          DEBUG ((
            DEBUG_ERROR,
            "%a ERROR 0x%x=L%x:F%x:R%x\n",
            __FUNCTION__,
            ErrorCode,
            ERR_GET_LIB (ErrorCode),
            ERR_GET_FUNC (ErrorCode),
            ERR_GET_REASON (ErrorCode)
            ));
        }
      DEBUG_CODE_END ();
      return EFI_ABORTED;
    }
  }

  if (PendingBufferSize > *BufferOutSize) {
    *BufferOutSize = PendingBufferSize;
    return EFI_BUFFER_TOO_SMALL;
  }

  if (PendingBufferSize > 0) {
    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);
  } else {
    *BufferOutSize = 0;
  }

  return EFI_SUCCESS;
}
Exemplo n.º 23
0
int TS_TST_INFO_print_bio(BIO *bio, TS_TST_INFO *a)
	{
	int v;
	ASN1_OBJECT *policy_id;
	const ASN1_INTEGER *serial;
	const ASN1_GENERALIZEDTIME *gtime;
	TS_ACCURACY *accuracy;
	const ASN1_INTEGER *nonce;
	GENERAL_NAME *tsa_name;

	if (a == NULL) return 0;

	/* Print version. */
	v = TS_TST_INFO_get_version(a);
	BIO_printf(bio, "Version: %d\n", v);

	/* Print policy id. */
	BIO_printf(bio, "Policy OID: ");
	policy_id = TS_TST_INFO_get_policy_id(a);
	TS_OBJ_print_bio(bio, policy_id);

	/* Print message imprint. */
	TS_MSG_IMPRINT_print_bio(bio, TS_TST_INFO_get_msg_imprint(a));

	/* Print serial number. */
	BIO_printf(bio, "Serial number: ");
	serial = TS_TST_INFO_get_serial(a);
	if (serial == NULL)
		BIO_printf(bio, "unspecified");
	else
		TS_ASN1_INTEGER_print_bio(bio, serial);
	BIO_write(bio, "\n", 1);

	/* Print time stamp. */
	BIO_printf(bio, "Time stamp: ");
	gtime = TS_TST_INFO_get_time(a);
	ASN1_GENERALIZEDTIME_print(bio, gtime);
	BIO_write(bio, "\n", 1);

	/* Print accuracy. */
	BIO_printf(bio, "Accuracy: ");
	accuracy = TS_TST_INFO_get_accuracy(a);
	if (accuracy == NULL)
		BIO_printf(bio, "unspecified");
	else
		TS_ACCURACY_print_bio(bio, accuracy);
	BIO_write(bio, "\n", 1);

	/* Print ordering. */
	BIO_printf(bio, "Ordering: %s\n", 
		   TS_TST_INFO_get_ordering(a) ? "yes" : "no");

	/* Print nonce. */
	BIO_printf(bio, "Nonce: ");
	nonce = TS_TST_INFO_get_nonce(a);
	if (nonce == NULL)
		BIO_printf(bio, "unspecified");
	else
		TS_ASN1_INTEGER_print_bio(bio, nonce);
	BIO_write(bio, "\n", 1);

	/* Print TSA name. */
	BIO_printf(bio, "TSA: ");
	tsa_name = TS_TST_INFO_get_tsa(a);
	if (tsa_name == NULL)
		BIO_printf(bio, "unspecified");
	else
		{
		STACK_OF(CONF_VALUE) *nval;
		if ((nval = i2v_GENERAL_NAME(NULL, tsa_name, NULL)))
			X509V3_EXT_val_prn(bio, nval, 0, 0);
		sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
		}
	BIO_write(bio, "\n", 1);

	/* Print extensions. */
	TS_ext_print_bio(bio, TS_TST_INFO_get_exts(a));

	return 1;
	}
Exemplo n.º 24
0
SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context,
        PSecBufferDesc pInput, PSecBufferDesc pOutput)
{
	int status;
	int ssl_error;
	PSecBuffer pBuffer;

	if (!context->connected)
	{
		if (pInput)
		{
			if (pInput->cBuffers < 1)
				return SEC_E_INVALID_TOKEN;

			pBuffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);

			if (!pBuffer)
				return SEC_E_INVALID_TOKEN;

			status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer);
		}

		status = SSL_connect(context->ssl);

		if (status < 0)
		{
			ssl_error = SSL_get_error(context->ssl, status);
			WLog_ERR(TAG, "SSL_connect error: %s", openssl_get_ssl_error_string(ssl_error));
		}

		if (status == 1)
			context->connected = TRUE;

		status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);

		if (pOutput->cBuffers < 1)
			return SEC_E_INVALID_TOKEN;

		pBuffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);

		if (!pBuffer)
			return SEC_E_INVALID_TOKEN;

		if (status > 0)
		{
			if (pBuffer->cbBuffer < (unsigned long) status)
				return SEC_E_INSUFFICIENT_MEMORY;

			CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
			pBuffer->cbBuffer = status;
			return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
		}
		else
		{
			pBuffer->cbBuffer = 0;
			return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
		}
	}

	return SEC_E_OK;
}
Exemplo n.º 25
0
int main(int argc, char **argv) {
  SSL_load_error_strings();
  ERR_load_BIO_strings();
  SSL_library_init();

  /*BIO *SSLout = BIO_new_connect(BROKER_CONN);
  if (!SSLout) {
    fprintf(stderr, "Error creating BIO\n");
    exit(EXIT_FAILURE);
  }
  if (BIO_do_connect(SSLout) <= 0) {
    fprintf(stderr,"Error connecting BIO\n");
    exit(EXIT_FAILURE);
  }
  char buf[BUFSIZ];
  */

  printf("HERE\n");

  SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
  if (!SSL_CTX_load_verify_locations(ctx,BROKER_CERT,NULL)) {
    fprintf(stderr,"Failed to load broker cert\n");
    exit(EXIT_FAILURE);
  }
  printf("HERE\n");
  SSL *ssl = SSL_new(ctx);
  SSL_set_mode(ssl,SSL_MODE_AUTO_RETRY);
  BIO *sslconn = BIO_new_ssl_connect(ctx);
  BIO_get_ssl(sslconn, &ssl);
 
  printf("HERE\n"); 

  // Do connection
  BIO_set_conn_hostname(sslconn,BROKER_CONN);
  BIO_set_conn_port(sslconn,BROKER_PORT);
  if (BIO_do_connect(sslconn) < 0) {
    fprintf(stderr,"Failed to make ssl connection\n");
    fprintf(stderr,"Error description: %s\n", ERR_reason_error_string(ERR_get_error()));
    exit(EXIT_FAILURE);
  }

  int err; 
  if((err = SSL_connect(ssl)) < 1)
  {
      fprintf(stderr, "Failed to initiate handshake:%s\n", ERR_reason_error_string(ERR_get_error()));
  }
  printf("HERE\n"); 
 
  char buf[BUFSIZ];  

  strcpy(buf,"OHAITHAR!\n");

  if( BIO_write(sslconn,buf,strlen(buf)) <= 0 ) {
    if(! BIO_should_retry(sslconn)) {
      
    }
  }
  
  
  /*if we want to reuse, start fresh
  BIO_reset(sslconn);
  */
  BIO_free_all(sslconn);
  
  return 0;
}
Exemplo n.º 26
0
void QFrankSSL::K_DatenKoennenGelesenWerden()
{
	int BytesDa=bytesAvailable();
#ifndef QT_NO_DEBUG
	qDebug(qPrintable(trUtf8("QFrankSSL: Es können %1 Bytes gelesen werden.","debug").arg(BytesDa)));
#endif
	if(K_Verbindungsstatus==QFrankSSL::GETRENNT)
	{
#ifndef QT_NO_DEBUG
		qDebug(qPrintable(QString("\tAber es besteht keine Verbindung zum SSL Server:(")));
#endif
		return;
	}
	if(BytesDa==0)
	{
#ifndef QT_NO_DEBUG
		qDebug("\tEs sollen 0 Byte gelesen werde. Sinnlos.");
#endif
		return;
	}
	 
	BIO_write(K_Empfangspuffer,read(BytesDa).data(),BytesDa);
	//müssen wir senden??
	if(K_MussWasGesendetWerden())
		K_DatenSenden();
	QString ServerAntwort;
	switch(K_Verbindungsstatus)
	{
		case QFrankSSL::VERBUNDEN:
									K_EmpfangenenDaten.resize(BytesDa);
									K_SSL_Fehlercode=SSL_read(K_SSLStruktur,K_EmpfangenenDaten.data(),BytesDa);
									if(K_SSL_Fehlercode>0)
									{
#ifndef QT_NO_DEBUG
										qDebug("QFrankSSL: Daten empfangen");
#endif
										if(K_SSL_Fehlercode<BytesDa)
											K_EmpfangenenDaten.resize(K_SSL_Fehlercode);
										emit DatenBereitZumAbhohlen(K_EmpfangenenDaten);
#ifndef QT_NO_DEBUG
										qDebug(qPrintable(QString("QFrankSSL: Daten:\r\n%1").arg(K_FeldNachHex(K_EmpfangenenDaten))));
#endif
									}
									if(K_SSL_Fehlercode<0)
									{
										K_SSL_Fehlercode=SSL_get_error(K_SSLStruktur,K_SSL_Fehlercode);
#ifndef QT_NO_DEBUG
										qDebug(qPrintable(QString("\tSSL_Error ergab:%1").arg(K_SSL_Fehlercode)));
#endif									
									}
									
									//ServerAntwort=SSL_state_string_long(K_SSLStruktur);
									//qDebug(ServerAntwort.toAscii().constData());

									break;
		case QFrankSSL::VERBINDEN:
									/*	Wenn die Verbindung mit dem SSL Server steht, Handschlag durchführen
										Es sollte das Wort server hello drin vorkommen.

									*/
									ServerAntwort=SSL_state_string_long(K_SSLStruktur);
									if(ServerAntwort.contains("server hello"))
									{
#ifndef QT_NO_DEBUG
										qDebug(qPrintable(trUtf8("QFrankSSL Daten empfangen: Bereit für den Handschake.\r\nAntwort vom Server: %1","debug")
																.arg(ServerAntwort)));
#endif
										K_SSL_Handshake();
									}
									else
									{
#ifndef QT_NO_DEBUG
										qDebug(qPrintable(trUtf8("QFrankSSL Daten empfangen: Nicht bereit für den Handschake.\r\nAntwort vom Server: %1","debug")
																.arg(ServerAntwort)));
#endif
									}
									break;
		case QFrankSSL::HANDSCHLAG:
										/*	schauen wir mal ob der Handschlag geklappt hat.
											es sollte der Text read finished oder read server verfify stehen drin stehen.
										*/
									ServerAntwort=SSL_state_string_long(K_SSLStruktur);
									if(ServerAntwort.contains("read finished") || ServerAntwort.contains("read server verfify"))
									{
#ifndef QT_NO_DEBUG
										qDebug(qPrintable(QString("QFrankSSL Daten empfangen: Handshake ok.\r\nAntwort vom Server: %1").arg(ServerAntwort)));
										K_ServerZertifikatUntersuchen();
#endif
										K_Verbindungsstatus=QFrankSSL::VERBUNDEN;
										emit TunnelBereit();
									}
									else
									{
#ifndef QT_NO_DEBUG
										qDebug(qPrintable(QString("QFrankSSL Daten empfangen: Handshake gescheitert.\r\nAntwort vom Server: %1")
																  .arg(ServerAntwort)));
#endif
									}
									break;
	}
	
}
Exemplo n.º 27
0
static void
print_stuff(BIO * bio, SSL * s, int full)
{
	X509 *peer = NULL;
	char *p;
	static const char *space = "                ";
	char buf[BUFSIZ];
	STACK_OF(X509) * sk;
	STACK_OF(X509_NAME) * sk2;
	const SSL_CIPHER *c;
	X509_NAME *xn;
	int j, i;
	unsigned char *exportedkeymat;

	if (full) {
		int got_a_chain = 0;

		sk = SSL_get_peer_cert_chain(s);
		if (sk != NULL) {
			got_a_chain = 1;	/* we don't have it for SSL2
						 * (yet) */

			BIO_printf(bio, "---\nCertificate chain\n");
			for (i = 0; i < sk_X509_num(sk); i++) {
				X509_NAME_oneline(X509_get_subject_name(
					sk_X509_value(sk, i)), buf, sizeof buf);
				BIO_printf(bio, "%2d s:%s\n", i, buf);
				X509_NAME_oneline(X509_get_issuer_name(
					sk_X509_value(sk, i)), buf, sizeof buf);
				BIO_printf(bio, "   i:%s\n", buf);
				if (c_showcerts)
					PEM_write_bio_X509(bio, sk_X509_value(sk, i));
			}
		}
		BIO_printf(bio, "---\n");
		peer = SSL_get_peer_certificate(s);
		if (peer != NULL) {
			BIO_printf(bio, "Server certificate\n");
			if (!(c_showcerts && got_a_chain))	/* Redundant if we
								 * showed the whole
								 * chain */
				PEM_write_bio_X509(bio, peer);
			X509_NAME_oneline(X509_get_subject_name(peer),
			    buf, sizeof buf);
			BIO_printf(bio, "subject=%s\n", buf);
			X509_NAME_oneline(X509_get_issuer_name(peer),
			    buf, sizeof buf);
			BIO_printf(bio, "issuer=%s\n", buf);
		} else
			BIO_printf(bio, "no peer certificate available\n");

		sk2 = SSL_get_client_CA_list(s);
		if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) {
			BIO_printf(bio, "---\nAcceptable client certificate CA names\n");
			for (i = 0; i < sk_X509_NAME_num(sk2); i++) {
				xn = sk_X509_NAME_value(sk2, i);
				X509_NAME_oneline(xn, buf, sizeof(buf));
				BIO_write(bio, buf, strlen(buf));
				BIO_write(bio, "\n", 1);
			}
		} else {
			BIO_printf(bio, "---\nNo client certificate CA names sent\n");
		}
		p = SSL_get_shared_ciphers(s, buf, sizeof buf);
		if (p != NULL) {
			/*
			 * This works only for SSL 2.  In later protocol
			 * versions, the client does not know what other
			 * ciphers (in addition to the one to be used in the
			 * current connection) the server supports.
			 */

			BIO_printf(bio, "---\nCiphers common between both SSL endpoints:\n");
			j = i = 0;
			while (*p) {
				if (*p == ':') {
					BIO_write(bio, space, 15 - j % 25);
					i++;
					j = 0;
					BIO_write(bio, ((i % 3) ? " " : "\n"), 1);
				} else {
					BIO_write(bio, p, 1);
					j++;
				}
				p++;
			}
			BIO_write(bio, "\n", 1);
		}
		BIO_printf(bio, "---\nSSL handshake has read %ld bytes and written %ld bytes\n",
		    BIO_number_read(SSL_get_rbio(s)),
		    BIO_number_written(SSL_get_wbio(s)));
	}
	BIO_printf(bio, (SSL_cache_hit(s) ? "---\nReused, " : "---\nNew, "));
	c = SSL_get_current_cipher(s);
	BIO_printf(bio, "%s, Cipher is %s\n",
	    SSL_CIPHER_get_version(c),
	    SSL_CIPHER_get_name(c));
	if (peer != NULL) {
		EVP_PKEY *pktmp;
		pktmp = X509_get_pubkey(peer);
		BIO_printf(bio, "Server public key is %d bit\n",
		    EVP_PKEY_bits(pktmp));
		EVP_PKEY_free(pktmp);
	}
	BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
	    SSL_get_secure_renegotiation_support(s) ? "" : " NOT");

	/* Compression is not supported and will always be none. */
	BIO_printf(bio, "Compression: NONE\n");
	BIO_printf(bio, "Expansion: NONE\n");

#ifdef SSL_DEBUG
	{
		/* Print out local port of connection: useful for debugging */
		int sock;
		struct sockaddr_in ladd;
		socklen_t ladd_size = sizeof(ladd);
		sock = SSL_get_fd(s);
		getsockname(sock, (struct sockaddr *) & ladd, &ladd_size);
		BIO_printf(bio_c_out, "LOCAL PORT is %u\n", ntohs(ladd.sin_port));
	}
#endif

	if (next_proto.status != -1) {
		const unsigned char *proto;
		unsigned int proto_len;
		SSL_get0_next_proto_negotiated(s, &proto, &proto_len);
		BIO_printf(bio, "Next protocol: (%d) ", next_proto.status);
		BIO_write(bio, proto, proto_len);
		BIO_write(bio, "\n", 1);
	}
	{
		const unsigned char *proto;
		unsigned int proto_len;
		SSL_get0_alpn_selected(s, &proto, &proto_len);
		if (proto_len > 0) {
			BIO_printf(bio, "ALPN protocol: ");
			BIO_write(bio, proto, proto_len);
			BIO_write(bio, "\n", 1);
		} else
			BIO_printf(bio, "No ALPN negotiated\n");
	}

#ifndef OPENSSL_NO_SRTP
	{
		SRTP_PROTECTION_PROFILE *srtp_profile = SSL_get_selected_srtp_profile(s);

		if (srtp_profile)
			BIO_printf(bio, "SRTP Extension negotiated, profile=%s\n",
			    srtp_profile->name);
	}
#endif

	SSL_SESSION_print(bio, SSL_get_session(s));
	if (keymatexportlabel != NULL) {
		BIO_printf(bio, "Keying material exporter:\n");
		BIO_printf(bio, "    Label: '%s'\n", keymatexportlabel);
		BIO_printf(bio, "    Length: %i bytes\n", keymatexportlen);
		exportedkeymat = malloc(keymatexportlen);
		if (exportedkeymat != NULL) {
			if (!SSL_export_keying_material(s, exportedkeymat,
				keymatexportlen,
				keymatexportlabel,
				strlen(keymatexportlabel),
				NULL, 0, 0)) {
				BIO_printf(bio, "    Error\n");
			} else {
				BIO_printf(bio, "    Keying material: ");
				for (i = 0; i < keymatexportlen; i++)
					BIO_printf(bio, "%02X",
					    exportedkeymat[i]);
				BIO_printf(bio, "\n");
			}
			free(exportedkeymat);
		}
	}
	BIO_printf(bio, "---\n");
	if (peer != NULL)
		X509_free(peer);
	/* flush, or debugging output gets mixed with http response */
	(void) BIO_flush(bio);
}
Exemplo n.º 28
0
int DTLSv1_listen(SSL *s, BIO_ADDR *client)
{
    int next, n, ret = 0, clearpkt = 0;
    unsigned char cookie[DTLS1_COOKIE_LENGTH];
    unsigned char seq[SEQ_NUM_SIZE];
    const unsigned char *data;
    unsigned char *buf;
    size_t fragoff, fraglen, msglen;
    unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen;
    BIO *rbio, *wbio;
    BUF_MEM *bufm;
    BIO_ADDR *tmpclient = NULL;
    PACKET pkt, msgpkt, msgpayload, session, cookiepkt;

    if (s->handshake_func == NULL) {
        /* Not properly initialized yet */
        SSL_set_accept_state(s);
    }

    /* Ensure there is no state left over from a previous invocation */
    if (!SSL_clear(s))
        return -1;

    ERR_clear_error();

    rbio = SSL_get_rbio(s);
    wbio = SSL_get_wbio(s);

    if (!rbio || !wbio) {
        SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET);
        return -1;
    }

    /*
     * We only peek at incoming ClientHello's until we're sure we are going to
     * to respond with a HelloVerifyRequest. If its a ClientHello with a valid
     * cookie then we leave it in the BIO for accept to handle.
     */
    BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL);

    /*
     * Note: This check deliberately excludes DTLS1_BAD_VER because that version
     * requires the MAC to be calculated *including* the first ClientHello
     * (without the cookie). Since DTLSv1_listen is stateless that cannot be
     * supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via
     * SSL_accept)
     */
    if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
        SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION);
        return -1;
    }

    if (s->init_buf == NULL) {
        if ((bufm = BUF_MEM_new()) == NULL) {
            SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
            return -1;
        }

        if (!BUF_MEM_grow(bufm, SSL3_RT_MAX_PLAIN_LENGTH)) {
            BUF_MEM_free(bufm);
            SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
            return -1;
        }
        s->init_buf = bufm;
    }
    buf = (unsigned char *)s->init_buf->data;

    do {
        /* Get a packet */

        clear_sys_error();
        /*
         * Technically a ClientHello could be SSL3_RT_MAX_PLAIN_LENGTH
         * + DTLS1_RT_HEADER_LENGTH bytes long. Normally init_buf does not store
         * the record header as well, but we do here. We've set up init_buf to
         * be the standard size for simplicity. In practice we shouldn't ever
         * receive a ClientHello as long as this. If we do it will get dropped
         * in the record length check below.
         */
        n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);

        if (n <= 0) {
            if (BIO_should_retry(rbio)) {
                /* Non-blocking IO */
                goto end;
            }
            return -1;
        }

        /* If we hit any problems we need to clear this packet from the BIO */
        clearpkt = 1;

        if (!PACKET_buf_init(&pkt, buf, n)) {
            SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
            return -1;
        }

        /*
         * Parse the received record. If there are any problems with it we just
         * dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is
         * resilient in the face of invalid records (e.g., invalid formatting,
         * length, MAC, etc.).  In general, invalid records SHOULD be silently
         * discarded, thus preserving the association; however, an error MAY be
         * logged for diagnostic purposes."
         */

        /* this packet contained a partial record, dump it */
        if (n < DTLS1_RT_HEADER_LENGTH) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL);
            goto end;
        }

        if (s->msg_callback)
            s->msg_callback(0, 0, SSL3_RT_HEADER, buf,
                            DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);

        /* Get the record header */
        if (!PACKET_get_1(&pkt, &rectype)
            || !PACKET_get_1(&pkt, &versmajor)) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }

        if (rectype != SSL3_RT_HANDSHAKE) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
            goto end;
        }

        /*
         * Check record version number. We only check that the major version is
         * the same.
         */
        if (versmajor != DTLS1_VERSION_MAJOR) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
            goto end;
        }

        if (!PACKET_forward(&pkt, 1)
            /* Save the sequence number: 64 bits, with top 2 bytes = epoch */
            || !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE)
            || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }
        /*
         * We allow data remaining at the end of the packet because there could
         * be a second record (but we ignore it)
         */

        /* This is an initial ClientHello so the epoch has to be 0 */
        if (seq[0] != 0 || seq[1] != 0) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
            goto end;
        }

        /* Get a pointer to the raw message for the later callback */
        data = PACKET_data(&msgpkt);

        /* Finished processing the record header, now process the message */
        if (!PACKET_get_1(&msgpkt, &msgtype)
            || !PACKET_get_net_3_len(&msgpkt, &msglen)
            || !PACKET_get_net_2(&msgpkt, &msgseq)
            || !PACKET_get_net_3_len(&msgpkt, &fragoff)
            || !PACKET_get_net_3_len(&msgpkt, &fraglen)
            || !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen)
            || PACKET_remaining(&msgpkt) != 0) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }

        if (msgtype != SSL3_MT_CLIENT_HELLO) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
            goto end;
        }

        /* Message sequence number can only be 0 or 1 */
        if (msgseq > 2) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER);
            goto end;
        }

        /*
         * We don't support fragment reassembly for ClientHellos whilst
         * listening because that would require server side state (which is
         * against the whole point of the ClientHello/HelloVerifyRequest
         * mechanism). Instead we only look at the first ClientHello fragment
         * and require that the cookie must be contained within it.
         */
        if (fragoff != 0 || fraglen > msglen) {
            /* Non initial ClientHello fragment (or bad fragment) */
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
            goto end;
        }

        if (s->msg_callback)
            s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data,
                            fraglen + DTLS1_HM_HEADER_LENGTH, s,
                            s->msg_callback_arg);

        if (!PACKET_get_net_2(&msgpayload, &clientvers)) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }

        /*
         * Verify client version is supported
         */
        if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) &&
            s->method->version != DTLS_ANY_VERSION) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
            goto end;
        }

        if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE)
            || !PACKET_get_length_prefixed_1(&msgpayload, &session)
            || !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) {
            /*
             * Could be malformed or the cookie does not fit within the initial
             * ClientHello fragment. Either way we can't handle it.
             */
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }

        /*
         * Check if we have a cookie or not. If not we need to send a
         * HelloVerifyRequest.
         */
        if (PACKET_remaining(&cookiepkt) == 0) {
            next = LISTEN_SEND_VERIFY_REQUEST;
        } else {
            /*
             * We have a cookie, so lets check it.
             */
            if (s->ctx->app_verify_cookie_cb == NULL) {
                SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
                /* This is fatal */
                return -1;
            }
            if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookiepkt),
                    (unsigned int)PACKET_remaining(&cookiepkt)) == 0) {
                /*
                 * We treat invalid cookies in the same was as no cookie as
                 * per RFC6347
                 */
                next = LISTEN_SEND_VERIFY_REQUEST;
            } else {
                /* Cookie verification succeeded */
                next = LISTEN_SUCCESS;
            }
        }

        if (next == LISTEN_SEND_VERIFY_REQUEST) {
            WPACKET wpkt;
            unsigned int version;
            size_t wreclen;

            /*
             * There was no cookie in the ClientHello so we need to send a
             * HelloVerifyRequest. If this fails we do not worry about trying
             * to resend, we just drop it.
             */

            /*
             * Dump the read packet, we don't need it any more. Ignore return
             * value
             */
            BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
            BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
            BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL);

            /* Generate the cookie */
            if (s->ctx->app_gen_cookie_cb == NULL ||
                s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 ||
                cookielen > 255) {
                SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
                /* This is fatal */
                return -1;
            }

            /*
             * Special case: for hello verify request, client version 1.0 and we
             * haven't decided which version to use yet send back using version
             * 1.0 header: otherwise some clients will ignore it.
             */
            version = (s->method->version == DTLS_ANY_VERSION) ? DTLS1_VERSION
                                                               : s->version;

            /* Construct the record and message headers */
            if (!WPACKET_init(&wpkt, s->init_buf)
                    || !WPACKET_put_bytes_u8(&wpkt, SSL3_RT_HANDSHAKE)
                    || !WPACKET_put_bytes_u16(&wpkt, version)
                       /*
                        * Record sequence number is always the same as in the
                        * received ClientHello
                        */
                    || !WPACKET_memcpy(&wpkt, seq, SEQ_NUM_SIZE)
                       /* End of record, start sub packet for message */
                    || !WPACKET_start_sub_packet_u16(&wpkt)
                       /* Message type */
                    || !WPACKET_put_bytes_u8(&wpkt,
                                             DTLS1_MT_HELLO_VERIFY_REQUEST)
                       /*
                        * Message length - doesn't follow normal TLS convention:
                        * the length isn't the last thing in the message header.
                        * We'll need to fill this in later when we know the
                        * length. Set it to zero for now
                        */
                    || !WPACKET_put_bytes_u24(&wpkt, 0)
                       /*
                        * Message sequence number is always 0 for a
                        * HelloVerifyRequest
                        */
                    || !WPACKET_put_bytes_u16(&wpkt, 0)
                       /*
                        * We never fragment a HelloVerifyRequest, so fragment
                        * offset is 0
                        */
                    || !WPACKET_put_bytes_u24(&wpkt, 0)
                       /*
                        * Fragment length is the same as message length, but
                        * this *is* the last thing in the message header so we
                        * can just start a sub-packet. No need to come back
                        * later for this one.
                        */
                    || !WPACKET_start_sub_packet_u24(&wpkt)
                       /* Create the actual HelloVerifyRequest body */
                    || !dtls_raw_hello_verify_request(&wpkt, cookie, cookielen)
                       /* Close message body */
                    || !WPACKET_close(&wpkt)
                       /* Close record body */
                    || !WPACKET_close(&wpkt)
                    || !WPACKET_get_total_written(&wpkt, &wreclen)
                    || !WPACKET_finish(&wpkt)) {
                SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
                WPACKET_cleanup(&wpkt);
                /* This is fatal */
                return -1;
            }

            /*
             * Fix up the message len in the message header. Its the same as the
             * fragment len which has been filled in by WPACKET, so just copy
             * that. Destination for the message len is after the record header
             * plus one byte for the message content type. The source is the
             * last 3 bytes of the message header
             */
            memcpy(&buf[DTLS1_RT_HEADER_LENGTH + 1],
                   &buf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3],
                   3);

            if (s->msg_callback)
                s->msg_callback(1, 0, SSL3_RT_HEADER, buf,
                                DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);

            if ((tmpclient = BIO_ADDR_new()) == NULL) {
                SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
                goto end;
            }

            /*
             * This is unnecessary if rbio and wbio are one and the same - but
             * maybe they're not. We ignore errors here - some BIOs do not
             * support this.
             */
            if (BIO_dgram_get_peer(rbio, tmpclient) > 0) {
                (void)BIO_dgram_set_peer(wbio, tmpclient);
            }
            BIO_ADDR_free(tmpclient);
            tmpclient = NULL;

            /* TODO(size_t): convert this call */
            if (BIO_write(wbio, buf, wreclen) < (int)wreclen) {
                if (BIO_should_retry(wbio)) {
                    /*
                     * Non-blocking IO...but we're stateless, so we're just
                     * going to drop this packet.
                     */
                    goto end;
                }
                return -1;
            }

            if (BIO_flush(wbio) <= 0) {
                if (BIO_should_retry(wbio)) {
                    /*
                     * Non-blocking IO...but we're stateless, so we're just
                     * going to drop this packet.
                     */
                    goto end;
                }
                return -1;
            }
        }
    } while (next != LISTEN_SUCCESS);

    /*
     * Set expected sequence numbers to continue the handshake.
     */
    s->d1->handshake_read_seq = 1;
    s->d1->handshake_write_seq = 1;
    s->d1->next_handshake_write_seq = 1;
    DTLS_RECORD_LAYER_set_write_sequence(&s->rlayer, seq);

    /*
     * We are doing cookie exchange, so make sure we set that option in the
     * SSL object
     */
    SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);

    /*
     * Tell the state machine that we've done the initial hello verify
     * exchange
     */
    ossl_statem_set_hello_verify_done(s);

    /*
     * Some BIOs may not support this. If we fail we clear the client address
     */
    if (BIO_dgram_get_peer(rbio, client) <= 0)
        BIO_ADDR_clear(client);

    ret = 1;
    clearpkt = 0;
 end:
    BIO_ADDR_free(tmpclient);
    BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
    if (clearpkt) {
        /* Dump this packet. Ignore return value */
        BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
    }
    return ret;
}
Exemplo n.º 29
0
int transport_write(rdpTransport* transport, wStream* s)
{
	size_t length;
	int status = -1;
	int writtenlength = 0;

	if (!s)
		return -1;

	if (!transport)
		goto fail;

	if (!transport->frontBio)
	{
		transport->layer = TRANSPORT_LAYER_CLOSED;
		goto fail;
	}

	EnterCriticalSection(&(transport->WriteLock));
	length = Stream_GetPosition(s);
	writtenlength = length;
	Stream_SetPosition(s, 0);

	if (length > 0)
	{
		WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length,
		            WLOG_PACKET_OUTBOUND);
	}

	while (length > 0)
	{
		status = BIO_write(transport->frontBio, Stream_Pointer(s), length);

		if (status <= 0)
		{
			/* the buffered BIO that is at the end of the chain always says OK for writing,
			 * so a retry means that for any reason we need to read. The most probable
			 * is a SSL or TSG BIO in the chain.
			 */
			if (!BIO_should_retry(transport->frontBio))
			{
				WLog_ERR_BIO(transport, "BIO_should_retry", transport->frontBio);
				goto out_cleanup;
			}

			/* non-blocking can live with blocked IOs */
			if (!transport->blocking)
			{
				WLog_ERR_BIO(transport, "BIO_write", transport->frontBio);
				goto out_cleanup;
			}

			if (BIO_wait_write(transport->frontBio, 100) < 0)
			{
				WLog_ERR_BIO(transport, "BIO_wait_write", transport->frontBio);
				status = -1;
				goto out_cleanup;
			}

			continue;
		}

		if (transport->blocking || transport->settings->WaitForOutputBufferFlush)
		{
			while (BIO_write_blocked(transport->frontBio))
			{
				if (BIO_wait_write(transport->frontBio, 100) < 0)
				{
					WLog_Print(transport->log, WLOG_ERROR, "error when selecting for write");
					status = -1;
					goto out_cleanup;
				}

				if (BIO_flush(transport->frontBio) < 1)
				{
					WLog_Print(transport->log, WLOG_ERROR, "error when flushing outputBuffer");
					status = -1;
					goto out_cleanup;
				}
			}
		}

		length -= status;
		Stream_Seek(s, status);
	}

	transport->written += writtenlength;
out_cleanup:

	if (status < 0)
	{
		/* A write error indicates that the peer has dropped the connection */
		transport->layer = TRANSPORT_LAYER_CLOSED;
	}

	LeaveCriticalSection(&(transport->WriteLock));
fail:
	Stream_Release(s);
	return status;
}
Exemplo n.º 30
0
// This is a function that checks in a file to the server
int checkin_file(SSL* ssl, BIO *sslbio, char *buffer) {
    char choice;
    int ret,length;    
    char filename[BUF_SIZE];

    choice = getchoice("Please select an action", cimenu);
    printf("You have chosen: %c\n", choice);
  	
    if (choice == 'a')
    {
	printf("Check-in By filename (NO File UID)\n");
	choiceProcess (sslbio, buffer, choice);

	getInput(filename, "Enter the filename \n (e.g., 'testfile.txt')", 32);

   	/* Sending the file name */
   	BIO_write(sslbio, filename, strlen(filename));

	// Receive server status 
        memset(buffer,0,4096);
    	length = BIO_read(sslbio, buffer, BUF_SIZE);
    	if(length <= 0)
    	{
    	    strcpy(buffer, "No message");
    	    length = strlen(buffer);
    	}
    	buffer[length] = '\0';
	printf("BUffer: %s",buffer);
	if (buffer[0] == '0') {
	    printf("Server confirms file is not already stored; storing file now.\n");	
	} else {
	    printf("Similiar file found in database...\n");
	    choice = getchoice("Overwrite your old file?", ynmenu);
	    if ( choice == 'y' ) {
		char answer[] = "yes";
		BIO_write(sslbio,answer,strlen(answer));
	     } else { 
	        char answer[] = "no";
		BIO_write(sslbio, answer, strlen(answer));
	     }
	}


	// Send the file to the server
	ret = send_file(filename, sslbio);

        // Get Server confirmation
    	memset(buffer,0,4096);
    	length = BIO_read(sslbio, buffer, BUF_SIZE);
    	if(length <= 0)
    	{
    	    strcpy(buffer, "No message");
    	    length = strlen(buffer);
    	}
    	buffer[length] = '\0';
        printf("Server confirmation: %s\n",buffer);

	char SecurityFlag[16];
	choice = getchoice("Select 'SecurityFlag' for this file",smenu);
	if (choice == 'a') {
	    strcpy(SecurityFlag, "CONFIDENTIALITY");
	} else if (choice == 'b') {
	    strcpy(SecurityFlag, "INTEGRITY");
	} else {
	    strcpy(SecurityFlag, "NONE");
	}

	printf("SecurityFlag confirmed as '%s'\n",SecurityFlag);
	BIO_write(sslbio, SecurityFlag, strlen(SecurityFlag));



    }
    else if (choice == 'b')
    {
    	printf("Check-in By File UID\n");
        choiceProcess (sslbio, buffer, choice);
	
	// Receive the number of File UID options 
        memset(buffer,0,4096);
    	length = BIO_read(sslbio, buffer, BUF_SIZE);
    	if(length <= 0)
    	{
    	    strcpy(buffer, "No message");
    	    length = strlen(buffer);
    	}
    	buffer[length] = '\0';
    	printf("You have access to %s file(s) on the server that are\n", buffer);
	printf("available for you to check in by File UID.\n"); 
    	int opns = atoi(buffer);
    
    	if ( opns < 1 ) {
    	    //No files to choose from.
    	    printf("You have access to ZERO files stored at server...\n");
	    printf("Unable to check-in by File UID: Choose a different option.\n");
	    printf("Recommend check-in by filename instead to receive new UID from server.\n");
	    exit(1);
	}

	// Receive deliminated list of option numbers
	memset(buffer,0,4096);
    	length = BIO_read(sslbio, buffer, BUF_SIZE);
    	if(length <= 0)
    	{
            strcpy(buffer, "No message");
            length = strlen(buffer);
    	}
    	buffer[length] = '\0';

    	// Tokenize options
    	int options[opns];
    	int numtokens = str_to_ints(buffer, options);
    
    	// Select Option, i.e., file UID choice
    	int filechoice =  getintchoice("Enter File UID you wish to check-in", options, opns);
    	length = floor(log10(abs(filechoice))) + 1;
    	char sfile[length];
    	sprintf(sfile, "%d", filechoice);

    	// Send File UID to Server
    	BIO_write(sslbio, sfile, length);

	// Receive File Name from Server
	memset(buffer,0,4096);
    	length = BIO_read(sslbio, buffer, BUF_SIZE);
    	if(length <= 0)
    	{
    	    strcpy(buffer, "No message");
    	    length = strlen(buffer);
    	}
    	buffer[length] = '\0';

	printf("Preparing to check-in File UID '%d', Filename '%s'\n",filechoice,buffer);
	printf("Has your filename changed since last upload? (Is it different than listed here?)\n");
	choice = getchoice("Please select an action", ynmenu);

	char filename[BUF_SIZE];

	if (choice == 'y') 
	{
	    getInput(filename, "Enter the new filename \n (e.g., 'testfile.txt')", 32);
	}
	else //File name hasn't changed 
	{
	    strcpy(filename,buffer);
	}

	char SecurityFlag[16];
	choice = getchoice("Select 'SecurityFlag' for this file",smenu);
	if (choice == 'a') {
	    strcpy(SecurityFlag, "CONFIDENTIALITY");
	} else if (choice == 'b') {
	    strcpy(SecurityFlag, "INTEGRITY");
	} else {
	    strcpy(SecurityFlag, "NONE");
	}

	printf("SecurityFlag confirmed as '%s'\n",SecurityFlag);
	BIO_write(sslbio, SecurityFlag, strlen(SecurityFlag));
	
	// Send the file to the server
	ret = send_file(filename, sslbio);

        // Get Server confirmation
    	memset(buffer,0,4096);
    	length = BIO_read(sslbio, buffer, BUF_SIZE);
    	if(length <= 0)
    	{
    	    strcpy(buffer, "No message");
    	    length = strlen(buffer);
    	}
    	buffer[length] = '\0';
        printf("Server confirmation: %s\n",buffer);

    }
    else
    {
    	printf("Terminate function will be executed\n");
    }
}