⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tunala.c

📁 开源的ssl算法openssl,版本0.9.8H
💻 C
📖 第 1 页 / 共 3 页
字号:
	meth = (server_mode ? SSLv23_server_method() : SSLv23_client_method());	if(meth == NULL)		goto err;	if(engine_id) {		ENGINE_load_builtin_engines();		if((e = ENGINE_by_id(engine_id)) == NULL) {			fprintf(stderr, "Error obtaining '%s' engine, openssl "					"errors follow\n", engine_id);			goto err;		}		if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {			fprintf(stderr, "Error assigning '%s' engine, openssl "					"errors follow\n", engine_id);			goto err;		}		ENGINE_free(e);	}	if((ctx = SSL_CTX_new(meth)) == NULL)		goto err;	/* cacert */	if(CAfile) {		if(!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx),					CAfile, NULL)) {			fprintf(stderr, "Error loading CA cert(s) in '%s'\n",					CAfile);			goto err;		}		fprintf(stderr, "Info, operating with CA cert(s) in '%s'\n",				CAfile);	} else		fprintf(stderr, "Info, operating without a CA cert(-list)\n");	if(!SSL_CTX_set_default_verify_paths(ctx)) {		fprintf(stderr, "Error setting default verify paths\n");		goto err;	}	/* cert and key */	if((cert || key) && !ctx_set_cert(ctx, cert, key))		goto err;	/* dcert and dkey */	if((dcert || dkey) && !ctx_set_cert(ctx, dcert, dkey))		goto err;	/* temporary RSA key generation */	if(tmp_rsa)		SSL_CTX_set_tmp_rsa_callback(ctx, cb_generate_tmp_rsa);	/* cipher_list */	if(cipher_list) {		if(!SSL_CTX_set_cipher_list(ctx, cipher_list)) {			fprintf(stderr, "Error setting cipher list '%s'\n",					cipher_list);			goto err;		}		fprintf(stderr, "Info, set cipher list '%s'\n", cipher_list);	} else		fprintf(stderr, "Info, operating with default cipher list\n");	/* dh_file & dh_special */	if((dh_file || dh_special) && !ctx_set_dh(ctx, dh_file, dh_special))		goto err;	/* ctx_options */	SSL_CTX_set_options(ctx, ctx_options);	/* out_state (output of SSL handshake states to screen). */	if(out_state)		cb_ssl_info_set_output(stderr);	/* out_verify */	if(out_verify > 0) {		cb_ssl_verify_set_output(stderr);		cb_ssl_verify_set_level(out_verify);	}	/* verify_depth */	cb_ssl_verify_set_depth(verify_depth);	/* Success! (includes setting verify_mode) */	SSL_CTX_set_info_callback(ctx, cb_ssl_info);	SSL_CTX_set_verify(ctx, verify_mode, cb_ssl_verify);	ret = ctx;err:	if(!ret) {		ERR_print_errors_fp(stderr);		if(ctx)			SSL_CTX_free(ctx);	}	return ret;}/*****************//* Selector bits *//*****************/static void selector_sets_init(select_sets_t *s){	s->max = 0;	FD_ZERO(&s->reads);	FD_ZERO(&s->sends);	FD_ZERO(&s->excepts);}static void selector_init(tunala_selector_t *selector){	selector_sets_init(&selector->last_selected);	selector_sets_init(&selector->next_select);}#define SEL_EXCEPTS 0x00#define SEL_READS   0x01#define SEL_SENDS   0x02static void selector_add_raw_fd(tunala_selector_t *s, int fd, int flags){	FD_SET(fd, &s->next_select.excepts);	if(flags & SEL_READS)		FD_SET(fd, &s->next_select.reads);	if(flags & SEL_SENDS)		FD_SET(fd, &s->next_select.sends);	/* Adjust "max" */	if(s->next_select.max < (fd + 1))		s->next_select.max = fd + 1;}static void selector_add_listener(tunala_selector_t *selector, int fd){	selector_add_raw_fd(selector, fd, SEL_READS);}static void selector_add_tunala(tunala_selector_t *s, tunala_item_t *t){	/* Set clean read if sm.clean_in is not full */	if(t->clean_read != -1) {		selector_add_raw_fd(s, t->clean_read,			(buffer_full(state_machine_get_buffer(&t->sm,				SM_CLEAN_IN)) ? SEL_EXCEPTS : SEL_READS));	}	/* Set clean send if sm.clean_out is not empty */	if(t->clean_send != -1) {		selector_add_raw_fd(s, t->clean_send,			(buffer_empty(state_machine_get_buffer(&t->sm,				SM_CLEAN_OUT)) ? SEL_EXCEPTS : SEL_SENDS));	}	/* Set dirty read if sm.dirty_in is not full */	if(t->dirty_read != -1) {		selector_add_raw_fd(s, t->dirty_read,			(buffer_full(state_machine_get_buffer(&t->sm,				SM_DIRTY_IN)) ? SEL_EXCEPTS : SEL_READS));	}	/* Set dirty send if sm.dirty_out is not empty */	if(t->dirty_send != -1) {		selector_add_raw_fd(s, t->dirty_send,			(buffer_empty(state_machine_get_buffer(&t->sm,				SM_DIRTY_OUT)) ? SEL_EXCEPTS : SEL_SENDS));	}}static int selector_select(tunala_selector_t *selector){	memcpy(&selector->last_selected, &selector->next_select,			sizeof(select_sets_t));	selector_sets_init(&selector->next_select);	return select(selector->last_selected.max,			&selector->last_selected.reads,			&selector->last_selected.sends,			&selector->last_selected.excepts, NULL);}/* This returns -1 for error, 0 for no new connections, or 1 for success, in * which case *newfd is populated. */static int selector_get_listener(tunala_selector_t *selector, int fd, int *newfd){	if(FD_ISSET(fd, &selector->last_selected.excepts))		return -1;	if(!FD_ISSET(fd, &selector->last_selected.reads))		return 0;	if((*newfd = ip_accept_connection(fd)) == -1)		return -1;	return 1;}/************************//* "Tunala" world stuff *//************************/static int tunala_world_make_room(tunala_world_t *world){	unsigned int newsize;	tunala_item_t *newarray;	if(world->tunnels_used < world->tunnels_size)		return 1;	newsize = (world->tunnels_size == 0 ? 16 :			((world->tunnels_size * 3) / 2));	if((newarray = malloc(newsize * sizeof(tunala_item_t))) == NULL)		return 0;	memset(newarray, 0, newsize * sizeof(tunala_item_t));	if(world->tunnels_used > 0)		memcpy(newarray, world->tunnels,			world->tunnels_used * sizeof(tunala_item_t));	if(world->tunnels_size > 0)		free(world->tunnels);	/* migrate */	world->tunnels = newarray;	world->tunnels_size = newsize;	return 1;}static int tunala_world_new_item(tunala_world_t *world, int fd,		const char *ip, unsigned short port, int flipped){	tunala_item_t *item;	int newfd;	SSL *new_ssl = NULL;	if(!tunala_world_make_room(world))		return 0;	if((new_ssl = SSL_new(world->ssl_ctx)) == NULL) {		fprintf(stderr, "Error creating new SSL\n");		ERR_print_errors_fp(stderr);		return 0;	}	item = world->tunnels + (world->tunnels_used++);	state_machine_init(&item->sm);	item->clean_read = item->clean_send =		item->dirty_read = item->dirty_send = -1;	if((newfd = ip_create_connection_split(ip, port)) == -1)		goto err;	/* Which way round? If we're a server, "fd" is the dirty side and the	 * connection we open is the clean one. For a client, it's the other way	 * around. Unless, of course, we're "flipped" in which case everything	 * gets reversed. :-) */	if((world->server_mode && !flipped) ||			(!world->server_mode && flipped)) {		item->dirty_read = item->dirty_send = fd;		item->clean_read = item->clean_send = newfd;	} else {		item->clean_read = item->clean_send = fd;		item->dirty_read = item->dirty_send = newfd;	}	/* We use the SSL's "app_data" to indicate a call-back induced "kill" */	SSL_set_app_data(new_ssl, NULL);	if(!state_machine_set_SSL(&item->sm, new_ssl, world->server_mode))		goto err;	return 1;err:	tunala_world_del_item(world, world->tunnels_used - 1);	return 0;}static void tunala_world_del_item(tunala_world_t *world, unsigned int idx){	tunala_item_t *item = world->tunnels + idx;	if(item->clean_read != -1)		close(item->clean_read);	if(item->clean_send != item->clean_read)		close(item->clean_send);	item->clean_read = item->clean_send = -1;	if(item->dirty_read != -1)		close(item->dirty_read);	if(item->dirty_send != item->dirty_read)		close(item->dirty_send);	item->dirty_read = item->dirty_send = -1;	state_machine_close(&item->sm);	/* OK, now we fix the item array */	if(idx + 1 < world->tunnels_used)		/* We need to scroll entries to the left */		memmove(world->tunnels + idx,				world->tunnels + (idx + 1),				(world->tunnels_used - (idx + 1)) *					sizeof(tunala_item_t));	world->tunnels_used--;}static int tunala_item_io(tunala_selector_t *selector, tunala_item_t *item){	int c_r, c_s, d_r, d_s; /* Four boolean flags */	/* Take ourselves out of the gene-pool if there was an except */	if((item->clean_read != -1) && FD_ISSET(item->clean_read,				&selector->last_selected.excepts))		return 0;	if((item->clean_send != -1) && FD_ISSET(item->clean_send,				&selector->last_selected.excepts))		return 0;	if((item->dirty_read != -1) && FD_ISSET(item->dirty_read,				&selector->last_selected.excepts))		return 0;	if((item->dirty_send != -1) && FD_ISSET(item->dirty_send,				&selector->last_selected.excepts))		return 0;	/* Grab our 4 IO flags */	c_r = c_s = d_r = d_s = 0;	if(item->clean_read != -1)		c_r = FD_ISSET(item->clean_read, &selector->last_selected.reads);	if(item->clean_send != -1)		c_s = FD_ISSET(item->clean_send, &selector->last_selected.sends);	if(item->dirty_read != -1)		d_r = FD_ISSET(item->dirty_read, &selector->last_selected.reads);	if(item->dirty_send != -1)		d_s = FD_ISSET(item->dirty_send, &selector->last_selected.sends);	/* If no IO has happened for us, skip needless data looping */	if(!c_r && !c_s && !d_r && !d_s)		return 1;	if(c_r)		c_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,				SM_CLEAN_IN), item->clean_read) <= 0);	if(c_s)		c_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,				SM_CLEAN_OUT), item->clean_send) <= 0);	if(d_r)		d_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,				SM_DIRTY_IN), item->dirty_read) <= 0);	if(d_s)		d_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,				SM_DIRTY_OUT), item->dirty_send) <= 0);	/* If any of the flags is non-zero, that means they need closing */	if(c_r) {		close(item->clean_read);		if(item->clean_send == item->clean_read)			item->clean_send = -1;		item->clean_read = -1;	}	if(c_s && (item->clean_send != -1)) {		close(item->clean_send);		if(item->clean_send == item->clean_read)			item->clean_read = -1;		item->clean_send = -1;	}	if(d_r) {		close(item->dirty_read);		if(item->dirty_send == item->dirty_read)			item->dirty_send = -1;		item->dirty_read = -1;	}	if(d_s && (item->dirty_send != -1)) {		close(item->dirty_send);		if(item->dirty_send == item->dirty_read)			item->dirty_read = -1;		item->dirty_send = -1;	}	/* This function name is attributed to the term donated by David	 * Schwartz on openssl-dev, message-ID:	 * <NCBBLIEPOCNJOAEKBEAKEEDGLIAA.davids@webmaster.com>. :-) */	if(!state_machine_churn(&item->sm))		/* If the SSL closes, it will also zero-out the _in buffers		 * and will in future process just outgoing data. As and		 * when the outgoing data has gone, it will return zero		 * here to tell us to bail out. */		return 0;	/* Otherwise, we return zero if both sides are dead. */	if(((item->clean_read == -1) || (item->clean_send == -1)) &&			((item->dirty_read == -1) || (item->dirty_send == -1)))		return 0;	/* If only one side closed, notify the SSL of this so it can take	 * appropriate action. */	if((item->clean_read == -1) || (item->clean_send == -1)) {		if(!state_machine_close_clean(&item->sm))			return 0;	}	if((item->dirty_read == -1) || (item->dirty_send == -1)) {		if(!state_machine_close_dirty(&item->sm))			return 0;	}	return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -