Exemplo n.º 1
0
bool master_service::thread_on_read(acl::socket_stream* conn)
{
	if (conf_ == NULL)
		return do_run(*conn, NULL);

	acl::polarssl_io* ssl = setup_ssl(*conn, *conf_);
	if (ssl == NULL)
		return false;

	if (ssl->handshake() == false)
	{
		logger_error("ssl handshake failed");
		return false;
	}

	if (ssl->handshake_ok() == false)
	{
		logger("handshake trying again...");
		return true;
	}

	logger("handshake_ok");

	return do_run(*conn, ssl);
}
Exemplo n.º 2
0
/** go ahead and read config, contact server and perform command and display */
static int
go(const char* cfgfile, char* svr, int argc, char* argv[])
{
	struct config_file* cfg;
	int fd, ret;
	SSL_CTX* ctx;
	SSL* ssl;

	/* read config */
	if(!(cfg = config_create()))
		fatal_exit("out of memory");
	if(!config_read(cfg, cfgfile, NULL))
		fatal_exit("could not read config file");
	if(!cfg->remote_control_enable)
		log_warn("control-enable is 'no' in the config file.");
	ctx = setup_ctx(cfg);
	
	/* contact server */
	fd = contact_server(svr, cfg, argc>0&&strcmp(argv[0],"status")==0);
	ssl = setup_ssl(ctx, fd);
	
	/* send command */
	ret = go_cmd(ssl, argc, argv);

	SSL_free(ssl);
#ifndef USE_WINSOCK
	close(fd);
#else
	closesocket(fd);
#endif
	SSL_CTX_free(ctx);
	config_delete(cfg);
	return ret;
}
Exemplo n.º 3
0
/** provide ssl service */
static void
do_service(char* addr, int port, char* key, char* cert)
{
	SSL_CTX* sslctx = setup_ctx(key, cert);
	int fd = setup_fd(addr, port);
	int go = 1;
	if(fd == -1) print_exit("could not setup sockets");
	if(verb) {printf("petal start\n"); fflush(stdout);}
	while(go) {
		struct sockaddr_storage from;
		socklen_t flen = (socklen_t)sizeof(from);
		int s = accept(fd, (struct sockaddr*)&from, &flen);
		if(verb) fflush(stdout);
		if(s != -1) {
			SSL* ssl = setup_ssl(s, sslctx);
			if(verb) fflush(stdout);
			if(ssl) {
				service_ssl(ssl, &from, flen);
				if(verb) fflush(stdout);
				SSL_shutdown(ssl);
				SSL_free(ssl);
			}
			fd_close(s);
		} else if (verb >=2) log_errno("accept");
		if(verb) fflush(stdout);
	}
	/* if we get a kill signal, the process dies and the OS reaps us */
	if(verb) printf("petal end\n");
	fd_close(fd);
	SSL_CTX_free(sslctx);
}
Exemplo n.º 4
0
/** go ahead and read config, contact server and perform command and display */
static int
go(const char* cfgfile, char* svr, int argc, char* argv[])
{
	struct nsd_options* opt;
	int fd, ret;
	SSL_CTX* ctx;
	SSL* ssl;

	/* read config */
	if(!(opt = nsd_options_create(region_create(xalloc, free)))) {
		fprintf(stderr, "out of memory\n");
		exit(1);
	}
	tsig_init(opt->region);
	if(!parse_options_file(opt, cfgfile, NULL, NULL)) {
		fprintf(stderr, "could not read config file\n");
		exit(1);
	}
	if(!opt->control_enable)
		fprintf(stderr, "warning: control-enable is 'no' in the config file.\n");
	ctx = setup_ctx(opt);

	/* contact server */
	fd = contact_server(svr, opt, argc>0&&strcmp(argv[0],"status")==0);
	ssl = setup_ssl(ctx, fd);

	/* send command */
	ret = go_cmd(ssl, fd, argc, argv);

	if(ssl) SSL_free(ssl);
	close(fd);
	if(ctx) SSL_CTX_free(ctx);
	region_destroy(opt->region);
	return ret;
}
Exemplo n.º 5
0
bool master_service::thread_on_read(acl::socket_stream* conn)
{
    http_servlet* servlet = (http_servlet*) conn->get_ctx();
    if (servlet == NULL)
        logger_fatal("servlet null!");

    if (conf_ == NULL)
        return servlet->doRun("127.0.0.1:11211", conn);

    acl::polarssl_io* ssl = setup_ssl(*conn, *conf_);
    if (ssl == NULL)
        return false;

    if (ssl->handshake() == false)
    {
        logger_error("ssl handshake failed");
        return false;
    }

    if (ssl->handshake_ok() == false)
    {
        logger("handshake trying ...");
        return true;
    }

    return servlet->doRun("127.0.0.1:11211", conn);
}
Exemplo n.º 6
0
bool master_service::thread_on_read(acl::socket_stream* conn)
{
	http_servlet* servlet = (http_servlet*) conn->get_ctx();
	if (servlet == NULL)
		logger_fatal("servlet null!");

	if (conf_ == NULL)
		return servlet->doRun("127.0.0.1:11211", conn);

	acl::polarssl_io* ssl = setup_ssl(*conn, *conf_);
	if (ssl == NULL)
		return false;

	return servlet->doRun("127.0.0.1:11211", conn);
}
Exemplo n.º 7
0
	/**
	 * 基类虚函数, 当异步连接成功后调用此函数
	 * @return {bool} 返回给调用者 true 表示继续,否则表示需要关闭异步流
	 */
	bool open_callback()
	{
		// 连接成功,设置IO读写回调函数
		client_->add_read_callback(this);
		client_->add_write_callback(this);
		ctx_->nopen_total++;

		acl::assert_(id_ > 0);
		if (ctx_->nopen_total < ctx_->nopen_limit)
		{
			// 开始进行下一个连接过程
			if (connect_server(ssl_conf_, ctx_, id_ + 1) == false)
				std::cout << "connect error!" << std::endl;
		}

		// 设置 SSL 方式
		if (ssl_conf_)
			return setup_ssl(*ssl_conf_);

		// 开始与服务端的读写过程
		else
			return begin_run();
	}
Exemplo n.º 8
0
void do_tcp_tests(int timeout, int concurrency)
{
	int		selres;
	fd_set		readfds, writefds;
	struct timespec	timestamp;
	int 		absmaxconcurrency;

	int		activesockets = 0; /* Number of allocated sockets */
	int		pending = 0;	   /* Total number of tests */
	tcptest_t	*nextinqueue;      /* Points to the next item to start testing */
	tcptest_t	*firstactive;      /* Points to the first item currently being tested */
					   /* Thus, active connections are between firstactive..nextinqueue */
	tcptest_t	*item;
	int		sockok;
	int		maxfd;
	int		res;
	socklen_t	connressize;
	char		msgbuf[4096];

	struct rlimit lim;

	/* If timeout or concurrency are 0, set them to reasonable defaults */
	if (timeout == 0) timeout = 10;	/* seconds */

	/* 
	 * Decide how many tests to run in parallel.
	 * If no --concurrency set by user, default to (FD_SETSIZE / 4) - typically 256.
	 * But never go above the ressource limit that is set, or above FD_SETSIZE.
	 * And we save 10 fd's for stdio, libs etc.
	 */
	absmaxconcurrency = (FD_SETSIZE - 10);
	getrlimit(RLIMIT_NOFILE, &lim); 
	if ((lim.rlim_cur > 10) && ((lim.rlim_cur - 10) < absmaxconcurrency)) absmaxconcurrency = (lim.rlim_cur - 10);

	if (concurrency == 0) concurrency = (FD_SETSIZE / 4);
	if (concurrency > absmaxconcurrency) concurrency = absmaxconcurrency;

	dbgprintf("Concurrency evaluation: rlim_cur=%lu, FD_SETSIZE=%d, absmax=%d, initial=%d\n", 
		  lim.rlim_cur, FD_SETSIZE, absmaxconcurrency, concurrency);

	if (shuffletests) {
		struct timeval tv;
		struct timezone tz;
		gettimeofday(&tv, &tz);
		srandom(tv.tv_usec);
	}

	/* How many tests to do ? */
	for (item = thead; (item); item = item->next) {
		if (shuffletests) item->randomizer = random();
		pending++; 
	}
	if (shuffletests) thead = msort(thead, tcptest_compare, tcptest_getnext, tcptest_setnext);

	firstactive = nextinqueue = thead;
	dbgprintf("About to do %d TCP tests running %d in parallel, abs.max %d\n", 
		  pending, concurrency, absmaxconcurrency);

	while (pending > 0) {
		int slowrunning, cclimit;
		time_t slowtimestamp = gettimer() - SLOWLIMSECS;

		/*
		 * First, see if we need to allocate new sockets and initiate connections.
		 */

		/*
		 * We start by counting the number of tests where the latest activity
		 * happened more than SLOWLIMSECS seconds ago. These are ignored when counting
		 * how many more tests we can start concurrenly. But never exceed the absolute 
		 * max. number of concurrently open sockets possible.
		 */
		for (item=firstactive, slowrunning = 0; (item != nextinqueue); item=item->next) {
			if ((item->fd > -1) && (item->lastactive < slowtimestamp)) slowrunning++;
		}
		cclimit = concurrency + slowrunning; 
		if (cclimit > absmaxconcurrency) cclimit = absmaxconcurrency;

		sockok = 1;
		while (sockok && nextinqueue && (activesockets < cclimit)) {
			/*
			 * We need to allocate a new socket that has O_NONBLOCK set.
			 */
			nextinqueue->fd = socket(PF_INET, SOCK_STREAM, 0);
			sockok = (nextinqueue->fd != -1);
			if (sockok) {
				/* Set the source address */
				if (nextinqueue->srcaddr) {
					struct sockaddr_in src;
					int isip;

					memset(&src, 0, sizeof(src));
					src.sin_family = PF_INET;
					src.sin_port = 0;
					isip = (inet_aton(nextinqueue->srcaddr, (struct in_addr *) &src.sin_addr.s_addr) != 0);

					if (!isip) {
						char *envaddr = getenv(nextinqueue->srcaddr);
						isip = (envaddr && (inet_aton(envaddr, (struct in_addr *) &src.sin_addr.s_addr) != 0));
					}

					if (isip) {
						res = bind(nextinqueue->fd, (struct sockaddr *)&src, sizeof(src));
						if (res != 0) errprintf("WARNING: Could not bind to source IP %s for test %s: %s\n",
								nextinqueue->srcaddr, nextinqueue->tspec, strerror(errno));
					}
					else {
						errprintf("WARNING: Invalid source IP %s for test %s, using default\n",
								nextinqueue->srcaddr, nextinqueue->tspec);
					}
				}

				res = fcntl(nextinqueue->fd, F_SETFL, O_NONBLOCK);

				if (res == 0) {
					/*
					 * Initiate the connection attempt ... 
					 */
					getntimer(&nextinqueue->timestart);
					nextinqueue->lastactive = nextinqueue->timestart.tv_sec;
					nextinqueue->cutoff = nextinqueue->timestart.tv_sec + timeout + 1;
					res = connect(nextinqueue->fd, (struct sockaddr *)&nextinqueue->addr, sizeof(nextinqueue->addr));

					/*
					 * Did it work ?
					 */
					if ((res == 0) || ((res == -1) && (errno == EINPROGRESS))) {
						/* This is OK - EINPROGRES and res=0 pick up status in select() */
						activesockets++;
						tcp_stats_connects++;
					}
					else if (res == -1) {
						/* connect() failed. Flag the item as "not open" */
						nextinqueue->connres = errno;
						nextinqueue->open = 0;
						nextinqueue->errcode = CONTEST_ENOCONN;
						close(nextinqueue->fd);
						nextinqueue->fd = -1;
						pending--;

						switch (nextinqueue->connres) {
						   /* These may happen if connection is refused immediately */
						   case ECONNREFUSED : break;
						   case EHOSTUNREACH : break;
						   case ENETUNREACH  : break;
						   case EHOSTDOWN    : break;

						   /* Not likely ... */
						   case ETIMEDOUT    : break;

						   /* These should not happen. */
						   case EBADF        : errprintf("connect returned EBADF!\n"); break;
						   case ENOTSOCK     : errprintf("connect returned ENOTSOCK!\n"); break;
						   case EADDRNOTAVAIL: errprintf("connect returned EADDRNOTAVAIL!\n"); break;
						   case EAFNOSUPPORT : errprintf("connect returned EAFNOSUPPORT!\n"); break;
						   case EISCONN      : errprintf("connect returned EISCONN!\n"); break;
						   case EADDRINUSE   : errprintf("connect returned EADDRINUSE!\n"); break;
						   case EFAULT       : errprintf("connect returned EFAULT!\n"); break;
						   case EALREADY     : errprintf("connect returned EALREADY!\n"); break;
						   default           : errprintf("connect returned %d, errno=%d\n", res, errno);
						}
					}
					else {
						/* Should NEVER happen. connect returns 0 or -1 */
						errprintf("Strange result from connect: %d, errno=%d\n", res, errno);
					}
				}
				else {
					/* Could net set to non-blocking mode! Hmmm ... */
					sockok = 0;
					errprintf("Cannot set O_NONBLOCK\n");
				}

				nextinqueue=nextinqueue->next;
			}
			else {
				int newconcurrency = ((activesockets > 5) ? (activesockets-1) : 5);

				/* Could not get a socket */
				switch (errno) {
				   case EPROTONOSUPPORT: errprintf("Cannot get socket - EPROTONOSUPPORT\n"); break;
				   case EAFNOSUPPORT   : errprintf("Cannot get socket - EAFNOSUPPORT\n"); break;
				   case EMFILE         : errprintf("Cannot get socket - EMFILE\n"); break;
				   case ENFILE         : errprintf("Cannot get socket - ENFILE\n"); break;
				   case EACCES         : errprintf("Cannot get socket - EACCESS\n"); break;
				   case ENOBUFS        : errprintf("Cannot get socket - ENOBUFS\n"); break;
				   case ENOMEM         : errprintf("Cannot get socket - ENOMEM\n"); break;
				   case EINVAL         : errprintf("Cannot get socket - EINVAL\n"); break;
				   default             : errprintf("Cannot get socket - errno=%d\n", errno); break;
				}

				if (newconcurrency != concurrency) {
					errprintf("Reducing --concurrency setting from %d to %d\n", 
							concurrency, newconcurrency);
					concurrency = newconcurrency;
				}
			}
		}

		/* Ready to go - we have a bunch of connections being established */
		dbgprintf("%d tests pending - %d active tests, %d slow tests\n", 
			  pending, activesockets, slowrunning);

restartselect:
		/*
		 * Setup the FDSET's
		 */
		FD_ZERO(&readfds); FD_ZERO(&writefds); maxfd = -1;
		for (item=firstactive; (item != nextinqueue); item=item->next) {
			if (item->fd > -1) {
				/*
				 * WRITE events are used to signal that a
				 * connection is ready, or it has been refused.
				 * READ events are only interesting for sockets
				 * that have already been found to be open, and
				 * thus have the "readpending" flag set.
				 *
				 * So: On any given socket, we want either a 
				 * write-event or a read-event - never both.
				 */
				if (item->readpending)
					FD_SET(item->fd, &readfds);
				else 
					FD_SET(item->fd, &writefds);

				if (item->fd > maxfd) maxfd = item->fd;
			}
		}

		if (maxfd == -1) {
			/* No active connections */
			if (activesockets == 0) {
				/* This can happen, if we get an immediate CONNREFUSED on all connections. */
				continue;
			}
			else {
				errprintf("contest logic error: No FD's, active=%d, pending=%d\n",
					  activesockets, pending);
				continue;
			}
		}
				
		/*
		 * Wait for something to happen: connect, timeout, banner arrives ...
		 */
		if (maxfd < 0) {
			errprintf("select - no active fd's found, but pending is %d\n", pending);
			selres = 0;
		}
		else {
			struct timeval tmo = { 1, 0 };
			dbgprintf("Doing select with maxfd=%d\n", maxfd);
			selres = select((maxfd+1), &readfds, &writefds, NULL, &tmo);
			dbgprintf("select returned %d\n", selres);
		}

		if (selres == -1) {
			int selerr = errno;

			/*
			 * select() failed - this is BAD!
			 */
			switch (selerr) {
			   case EINTR : errprintf("select failed - EINTR\n"); goto restartselect;
			   case EBADF : errprintf("select failed - EBADF\n"); break;
			   case EINVAL: errprintf("select failed - EINVAL\n"); break;
			   case ENOMEM: errprintf("select failed - ENOMEM\n"); break;
			   default    : errprintf("Unknown select() error %d\n", selerr); break;
			}

			/* Leave this mess ... */
			errprintf("Aborting TCP tests with %d tests pending\n", pending);
			return;
		}

		/* selres == 0 (timeout) isn't special - just go through the list of active tests */

		/* Fetch the timestamp so we can tell how long the connect took */
		getntimer(&timestamp);

		/* Now find out which connections had something happen to them */
		for (item=firstactive; (item != nextinqueue); item=item->next) {
			if (item->fd > -1) {		/* Only active sockets have this */
				if (timestamp.tv_sec > item->cutoff) {
					/* 
					 * Request timed out.
					 */
					if (item->readpending) {
						/* Final read timeout - just shut this socket */
						socket_shutdown(item);
						item->errcode = CONTEST_ETIMEOUT;
					}
					else {
						/* Connection timeout */
						item->open = 0;
						item->errcode = CONTEST_ETIMEOUT;
					}
					get_totaltime(item, &timestamp);
					close(item->fd);
					item->fd = -1;
					activesockets--;
					pending--;
					if (item == firstactive) firstactive = item->next;
				}
				else {
					if (FD_ISSET(item->fd, &writefds)) {
						int do_talk = 1;
						unsigned char *outbuf = NULL;
						unsigned int outlen = 0;

						item->lastactive = timestamp.tv_sec;

						if (!item->open) {
							/*
							 * First time here.
							 *
							 * Active response on this socket - either OK, or 
							 * connection refused.
							 * We determine what happened by getting the SO_ERROR status.
							 * (cf. select_tut(2) manpage).
							 */
							connressize = sizeof(item->connres);
							res = getsockopt(item->fd, SOL_SOCKET, SO_ERROR, &item->connres, &connressize);
							item->open = (item->connres == 0);
							if (!item->open) item->errcode = CONTEST_ENOCONN;
							do_talk = item->open;
							get_connectiontime(item, &timestamp);
						}

						if (item->open && (item->svcinfo->flags & TCP_SSL)) {
							/* 
							 * Setup the SSL connection, if not done already.
							 *
							 * NB: This can be triggered many times, as setup_ssl()
							 * may need more data from the remote and return with
							 * item->sslrunning == SSLSETUP_PENDING
							 */
							if (item->sslrunning == SSLSETUP_PENDING) {
								setup_ssl(item);
								if (item->sslrunning == 1) {
									/*
									 * Update connectiontime to include
									 * time for SSL handshake.
									 */
									get_connectiontime(item, &timestamp);
								}
							}
							do_talk = (item->sslrunning == 1);
						}

						/*
						 * Connection succeeded - port is open, if SSL then the
						 * SSL handshake is complete. 
						 *
						 * If we have anything to send then send it.
						 * If we want the banner, set the "readpending" flag to initiate
						 * select() for read()'s.
						 * NB: We want the banner EITHER if the GET_BANNER flag is set,
						 *     OR if we need it to match the expect string in the servicedef.
						 */

						item->readpending = (do_talk && !item->silenttest && 
							( (item->svcinfo->flags & TCP_GET_BANNER) || item->svcinfo->exptext ));
						if (do_talk) {
							if (item->telnetnegotiate && item->telnetbuflen) {
								/*
								 * Return the telnet negotiate data response
								 */
								outbuf = item->telnetbuf;
								outlen = item->telnetbuflen;
							}
							else if (item->sendtxt && !item->silenttest) {
								outbuf = item->sendtxt;
								outlen = (item->sendlen ? item->sendlen : strlen(outbuf));
							}

							if (outbuf && outlen) {
								/*
								 * It may be that we cannot write all of the
								 * data we want to. Tough ... 
								 */
								res = socket_write(item, outbuf, outlen);
								tcp_stats_written += res;
								if (res == -1) {
									/* Write failed - this socket is done. */
									dbgprintf("write failed\n");
									item->readpending = 0;
									item->errcode = CONTEST_EIO;
								}
								else if (item->svcinfo->flags & TCP_HTTP) {
									/*
									 * HTTP tests require us to send the full buffer.
									 * So adjust sendtxt/sendlen accordingly.
									 * If no more to send, switch to read-mode.
									 */
									item->sendtxt += res;
									item->sendlen -= res;
									item->readpending = (item->sendlen == 0);
								}
							}
						}

						/* If closed and/or no bannergrabbing, shut down socket */
						if (item->sslrunning != SSLSETUP_PENDING) {
							if (!item->open || !item->readpending) {
								if (item->open) {
									socket_shutdown(item);
								}
								close(item->fd);
								get_totaltime(item, &timestamp);
								if (item->finalcallback) item->finalcallback(item->priv);
								item->fd = -1;
								activesockets--;
								pending--;
								if (item == firstactive) firstactive = item->next;
							}
						}
					}
					else if (FD_ISSET(item->fd, &readfds)) {
						/*
						 * Data ready to read on this socket. Grab the
						 * banner - we only do one read (need the socket
						 * for other tests), so if the banner takes more
						 * than one cycle to arrive, too bad!
						 */
						int wantmoredata = 0;
						int datadone = 0;

						item->lastactive = timestamp.tv_sec;

						/*
						 * We may be in the process of setting up an SSL connection
						 */
						if (item->sslrunning == SSLSETUP_PENDING) setup_ssl(item);
						if (item->sslrunning == SSLSETUP_PENDING) break;  /* Loop again waiting for more data */

						/*
						 * Connection is ready - plain or SSL. Read data.
						 */
						res = socket_read(item, msgbuf, sizeof(msgbuf)-1);
						tcp_stats_read += res;
						dbgprintf("read %d bytes from socket\n", res);

						if ((res > 0) && item->datacallback) {
							datadone = item->datacallback(msgbuf, res, item->priv);
						}

						if ((res > 0) && item->telnetnegotiate) {
							/*
							 * telnet data has telnet options first.
							 * We must negotiate the session before we
							 * get the banner.
							 */
							item->telnetbuf = item->banner;
							item->telnetbuflen = res;

							/*
							 * Safety measure: Dont loop forever doing
							 * telnet options.
							 * This puts a maximum on how many times
							 * we go here.
							 */
							item->telnetnegotiate--;
							if (!item->telnetnegotiate) {
								dbgprintf("Max. telnet negotiation (%d) reached for host %s\n", 
									MAX_TELNET_CYCLES,
									inet_ntoa(item->addr.sin_addr));
							}

							if (do_telnet_options(item)) {
								/* Still havent seen the session banner */
								item->banner = NULL;
								item->bannerbytes = 0;
								item->readpending = 0;
								wantmoredata = 1;
							}
							else {
								/* No more options - we have the banner */
								item->telnetnegotiate = 0;
							}
						}

						if ((item->svcinfo->flags & TCP_HTTP) && 
						    ((res > 0) || item->sslagain)     &&
						    (!datadone) ) {
							/*
							 * HTTP : Grab the entire response.
							 */
							wantmoredata = 1;
						}

						if (!wantmoredata) {
							if (item->open) {
								socket_shutdown(item);
							}
							item->readpending = 0;
							close(item->fd);
							get_totaltime(item, &timestamp);
							if (item->finalcallback) item->finalcallback(item->priv);
							item->fd = -1;
							activesockets--;
							pending--;
							if (item == firstactive) firstactive = item->next;
						}
					}
				}
			}
		}  /* end for loop */
	} /* end while (pending) */

	dbgprintf("TCP tests completed normally\n");
}
Exemplo n.º 9
0
/* FIXME: Leaky as a bucket */
void open_connection(const char *url)
{
    char *proxy_host = get_option(opt_proxy), *pnt;
    ne_server_capabilities caps;
    int ret, use_ssl = 0;
    ne_session *sess;

    if (session.connected) {
	close_connection();
    } else {
        ne_uri_free(&session.uri);
        if (session.lastwp) {
            ne_free(session.lastwp);
            session.lastwp = NULL;
        }
    }

    /* Single argument: see whether we have a path or scheme */
    if (strchr(url, '/') == NULL) {
	/* No path, no scheme -> just a hostname */
	pnt = strchr(url, ':');
	if (pnt != NULL) {
	    *pnt++ = '\0';
	    session.uri.port = atoi(pnt);
	} else {
	    session.uri.port = 80;
	}
	session.uri.host = ne_strdup(url);
	session.uri.scheme = ne_strdup("http");
    } else {
	/* Parse the URL */
	if (ne_uri_parse(url, &session.uri) || session.uri.host == NULL) {
	    printf(_("Could not parse URL `%s'\n"), url);
	    return;
	}

	if (session.uri.scheme == NULL)
	    session.uri.scheme = ne_strdup("http");

	if (!session.uri.port)
	    session.uri.port = ne_uri_defaultport(session.uri.scheme);

	if (strcasecmp(session.uri.scheme, "https") == 0) {
	    if (!ne_has_support(NE_FEATURE_SSL)) {
		printf(_("SSL is not enabled.\n"));
		return;
	    }
	    use_ssl = 1;
	}
    }

    session.sess = ne_session_create(session.uri.scheme, session.uri.host,
                                     session.uri.port);
    sess = session.sess;
    
    if (use_ssl && setup_ssl()) {
	return;
    }

    ne_lockstore_register(session.locks, sess);
    ne_redirect_register(sess);
    ne_set_notifier(sess, notifier, NULL);

    if (session.uri.path == NULL) {
	session.uri.path = ne_strdup("/");
    } else {
	if (!ne_path_has_trailing_slash(session.uri.path)) {
	    pnt = ne_concat(session.uri.path, "/", NULL);
	    free(session.uri.path);
	    session.uri.path = pnt;
	}
    }

    /* Get the proxy details */
    if (proxy_host != NULL) {
	if (get_option(opt_proxy_port) != NULL) {
	    proxy_port = atoi(get_option(opt_proxy_port));
	} else {
	    proxy_port = 8080;
	}
	proxy_hostname = proxy_host;
    }

#ifdef ENABLE_NETRC
    {
	netrc_entry *found;
	found = search_netrc(netrc_list, session.uri.host);
	if (found != NULL) {
	    if (found->account && found->password) {
		server_username = found->account;
		server_password = found->password;
	    }
	}
    }
#endif /* ENABLE_NETRC */
#ifdef NE_SESSFLAG_EXPECT100
	ne_set_session_flag(session.sess, NE_SESSFLAG_EXPECT100, get_bool_option(opt_expect100));
#endif /* NE_SESSFLAG_EXPECT100 */
    session.connected = 0;

    ne_set_useragent(session.sess, "cadaver/" PACKAGE_VERSION);
    ne_set_server_auth(session.sess, supply_creds_server, NULL);
    ne_set_proxy_auth(session.sess, supply_creds_proxy, NULL);
    
    if (proxy_host) {
	ne_session_proxy(session.sess, proxy_hostname, proxy_port);
    }

    ret = ne_options(session.sess, session.uri.path, &caps);
    
    switch (ret) {
    case NE_OK:
	session.connected = true;
	if (set_path(session.uri.path)) {
	    close_connection();
	}
	break;
    case NE_CONNECT:
	if (proxy_host) {
	    printf(_("Could not connect to `%s' on port %d:\n%s\n"),
		   proxy_hostname, proxy_port, ne_get_error(session.sess));
	} else {
	    printf(_("Could not connect to `%s' on port %d:\n%s\n"),
		   session.uri.host, session.uri.port, ne_get_error(session.sess));
	}
	break;
    case NE_LOOKUP:
	puts(ne_get_error(session.sess));
	break;
    default:
	printf(_("Could not open collection:\n%s\n"),
	       ne_get_error(session.sess));
	break;
    }

}