Exemple #1
0
/*
 * Send back a simple error page
 */
void
http_response_send_error(struct http_response *resp,
	int code, const char *fmt, ...)
{
	struct http_request *const req = resp->msg->conn->req;
	const char *ua;
	FILE *fp;
	int i;

	/* Check headers already sent */
	if (resp->msg->hdrs_sent)
		return;

	/* Set response line info */
	http_response_set_header(resp, 0, HDR_REPLY_STATUS, "%d", code);
	http_response_set_header(resp, 0, HDR_REPLY_REASON,
	      "%s", http_response_status_msg(code));

	/* Set additional headers */
	http_response_set_header(resp, 0, HTTP_HEADER_CONTENT_TYPE,
		"text/html; charset=iso-8859-1");

	/* Close connection for real errors */
	if (code >= 400) {
		http_response_set_header(resp,
		    0, _http_message_connection_header(resp->msg), "close");
	}

	/* Send error page body */
	if ((fp = http_response_get_output(resp, 1)) == NULL)
		return;
	fprintf(fp, "<HTML>\n<HEAD>\n<TITLE>%d %s</TITLE></HEAD>\n",
	    code, http_response_status_msg(code));
	fprintf(fp, "<BODY BGCOLOR=\"#FFFFFF\">\n<H3>%d %s</H3>\n",
	    code, http_response_status_msg(code));
	if (fmt != NULL) {
		va_list args;

		fprintf(fp, "<B>");
		va_start(args, fmt);
		vfprintf(fp, fmt, args);
		va_end(args);
		fprintf(fp, "</B>\n");
	}
#if 0
	fprintf(fp, "<P></P>\n<HR>\n");
	fprintf(fp, "<FONT SIZE=\"-1\"><EM>%s</EM></FONT>\n",
	    serv->server_name);
#endif

	/* Add fillter for IE */
	if ((ua = http_request_get_header(req, HTTP_HEADER_USER_AGENT)) != NULL
	    && strstr(ua, "IE") != NULL) {
		for (i = 0; i < 20; i++) {
			fprintf(fp, "<!-- FILLER TO MAKE INTERNET EXPLORER SHOW"
			    " THIS PAGE INSTEAD OF ITS OWN PAGE -->\n");
		}
	}
	fprintf(fp, "</BODY>\n</HTML>\n");
}
Exemple #2
0
static int	
WebServletRun(struct http_servlet *servlet,
                         struct http_request *req, struct http_response *resp)
{
    FILE *f;
    const char *path;
    const char *query;
    int priv = 0;
    
    if (Enabled(&gWeb.options, WEB_AUTH)) {
	const char *username;
	const char *password;
	ConsoleUser		u;
	struct console_user	iu;

	/* Get username and password */
	if ((username = http_request_get_username(req)) == NULL)
    	    username = "";
	if ((password = http_request_get_password(req)) == NULL)
    	    password = "";

	strlcpy(iu.username, username, sizeof(iu.username));
	RWLOCK_RDLOCK(gUsersLock);
	u = ghash_get(gUsers, &iu);
	RWLOCK_UNLOCK(gUsersLock);

	if ((u == NULL) || strcmp(u->password, password)) {
		http_response_send_basic_auth(resp, "Access Restricted");
		return (1);
	}
	priv = u->priv;
    }

    if (!(f = http_response_get_output(resp, 1))) {
	return 0;
    }
    if (!(path = http_request_get_path(req)))
	return 0;
    if (!(query = http_request_get_query_string(req)))
	return 0;

    if (!strcmp(path,"/mpd.css")) {
	http_response_set_header(resp, 0, "Content-Type", "text/css");
	WebShowCSS(f);
    } else if (!strcmp(path,"/bincmd")) {
	http_response_set_header(resp, 0, "Content-Type", "text/plain");
	http_response_set_header(resp, 1, "Pragma", "no-cache");
	http_response_set_header(resp, 1, "Cache-Control", "no-cache, must-revalidate");
	
	pthread_cleanup_push(WebServletRunCleanup, NULL);
	GIANT_MUTEX_LOCK();
	WebRunBinCmd(f, query, priv);
	GIANT_MUTEX_UNLOCK();
	pthread_cleanup_pop(0);
    } else if (!strcmp(path,"/") || !strcmp(path,"/cmd")) {
	http_response_set_header(resp, 0, "Content-Type", "text/html");
	http_response_set_header(resp, 1, "Pragma", "no-cache");
	http_response_set_header(resp, 1, "Cache-Control", "no-cache, must-revalidate");
	
	pthread_cleanup_push(WebServletRunCleanup, NULL);
	GIANT_MUTEX_LOCK();
	fprintf(f, "<!DOCTYPE HTML "
	    "PUBLIC \"-//W3C//DTD HTML 4.01//EN\" "
	    "\"http://www.w3.org/TR/html4/strict.dtd\">\n");
	fprintf(f, "<HTML>\n");
	fprintf(f, "<HEAD><TITLE>Multi-link PPP Daemon for FreeBSD (mpd)</TITLE>\n");
	fprintf(f, "<LINK rel='stylesheet' href='/mpd.css' type='text/css'>\n");
	fprintf(f, "</HEAD>\n<BODY>\n");
	fprintf(f, "<H1>Multi-link PPP Daemon for FreeBSD</H1>\n");
    
	if (!strcmp(path,"/"))
	    WebShowSummary(f, priv);
	else if (!strcmp(path,"/cmd"))
	    WebRunCmd(f, query, priv);
	    
	GIANT_MUTEX_UNLOCK();
	pthread_cleanup_pop(0);
	
	fprintf(f, "</BODY>\n</HTML>\n");
    } else {
	http_response_send_error(resp, 404, NULL);
    }
    return 1;
}
/*
 * Run template servlet
 */
static int
http_servlet_tmpl_run(struct http_servlet *servlet,
	struct http_request *req, struct http_response *resp)
{
	struct tmpl_private *const priv = servlet->arg;
	struct http_servlet_tmpl_info *const info = &priv->info;
	struct http_servlet_tmpl_tinfo *const tinfo = &priv->info.tinfo;
	struct tmpl_instance *this = NULL;
	FILE *output = NULL;
	const char *hval;
	struct stat sb;
	int num_errors;
	int r;

	/* Construct per-instance state */
	if ((this = MALLOC(MEM_TYPE, sizeof(*this))) == NULL) {
		(*info->logger)(LOG_ERR, "%s: %s: %s",
		    __FUNCTION__, "malloc", strerror(errno));
		return (-1);
	}
	memset(this, 0, sizeof(*this));
	this->priv = priv;

	/* Grab lock to avoid race with http_servlet_tmpl_destroy() */
	r = pthread_rwlock_rdlock(&priv->lock);
	assert(r == 0);

	/* Push cleanup hook in case thread gets canceled */
	pthread_cleanup_push(http_servlet_tmpl_run_cleanup, this);

	/* Get servlet output stream (buffered) */
	if ((output = http_response_get_output(resp, 1)) == NULL) {
		(*info->logger)(LOG_ERR, "can't get template output: %s",
		    strerror(errno));
		goto fail_errno;
	}

	/* Set MIME type */
	if (info->mime_type == NULL) {
		http_response_set_header(resp, 0,
		    HTTP_HEADER_CONTENT_TYPE, "text/html; charset=iso-8859-1");
	} else {
		http_response_set_header(resp, 0,
		    HTTP_HEADER_CONTENT_TYPE, "%s", info->mime_type);
		if (info->mime_encoding != NULL) {
			http_response_set_header(resp,
			0, HTTP_HEADER_CONTENT_ENCODING,
			    "%s", info->mime_encoding);
		}
	}

	/* Assume servlet output is not cachable */
	http_response_set_header(resp, 1, HTTP_HEADER_PRAGMA, "no-cache");
	http_response_set_header(resp, 0,
	    HTTP_HEADER_CACHE_CONTROL, "no-cache");

	/* Get modification timestamp of the template file */
	if (stat(info->path, &sb) == -1) {
		(*info->logger)(LOG_ERR, "%s: %s: %s",
		    __FUNCTION__, info->path, strerror(errno));
		memset(&sb.st_mtime, 0, sizeof(sb.st_mtime));
	}

	/* Invalidate cached template if template file has changed */
	if (priv->tmpl != NULL
	    && memcmp(&sb.st_mtime, &priv->mtime, sizeof(priv->mtime)) != 0) {
		(*info->logger)(LOG_INFO,
		    "template \"%s\" was updated", info->path);
		tmpl_destroy(&priv->tmpl);
	}

	/* Do we need to (re)parse the template? */
	if (priv->tmpl == NULL) {

		/* Parse template file */
		if ((priv->tmpl = tmpl_create_mmap(info->path,
		    &num_errors, tinfo->mtype)) == NULL) {
			(*info->logger)(LOG_ERR,
			    "can't create template from \"%s\": %s",
			    info->path, strerror(errno));
			goto fail_errno;
		}

		/* Check for an error from tmpl_create() */
		if (priv->tmpl == NULL) {
			(*info->logger)(LOG_ERR,
			    "can't create \"%s\" template: %s", info->path,
			    strerror(errno));
			goto fail_errno;
		}

		/* Warn if there were any parse errors */
		if (num_errors != 0) {
			(*info->logger)(LOG_WARNING,
			    "%d parse error%s in template \"%s\"",
			    num_errors, num_errors == 1 ? "" : "s",
			    info->path);
		}

		/* Update last modified time */
		memcpy(&priv->mtime, &sb.st_mtime, sizeof(priv->mtime));
	}

	/* Read URL-encoded form data if this is a normal POST */
	if (strcmp(http_request_get_method(req), HTTP_METHOD_POST) == 0
	    && (hval = http_request_get_header(req,
	      HTTP_HEADER_CONTENT_TYPE)) != NULL
	    && strcasecmp(hval, HTTP_CTYPE_FORM_URLENCODED) == 0) {
		if (http_request_read_url_encoded_values(req) == -1) {
			(*info->logger)(LOG_ERR,
			    "error reading %s data for \"%s\" template: %s",
			    HTTP_METHOD_POST, info->path, strerror(errno));
			goto fail_errno;
		}
	}

	/* Fill in handler function cookie */
	this->targ.arg = info->tinfo.arg;
	this->targ.req = req;
	this->targ.resp = resp;

	/* Create tmpl execution context */
	if ((this->ctx = tmpl_ctx_create(&this->targ,
	    tinfo->mtype, tinfo->handler, tinfo->errfmtr)) == NULL) {
		(*info->logger)(LOG_ERR, "%s: %s: %s",
		    __FUNCTION__, "tmpl_ctx_create", strerror(errno));
		goto fail_errno;
	}

	/* Execute template */
	if (tmpl_execute(priv->tmpl, this->ctx, output, tinfo->flags) == -1) {
		(*info->logger)(LOG_ERR, "can't execute \"%s\" template: %s",
		    info->path, strerror(errno));
		goto fail_errno;
	}

	/* OK */
	goto done;

fail_errno:
	/* Fail with appropriate error response */
	http_response_send_errno_error(resp);

done:
	/* Done */
	if (output != NULL)
		fclose(output);
	pthread_cleanup_pop(1);
	return (1);
}