示例#1
0
int get_config_handler(worker_st *ws, unsigned http_ver)
{
int ret;
struct stat st;

	oclog(ws, LOG_HTTP_DEBUG, "requested config: %s", ws->req.url); 
	if (ws->config->xml_config_file == NULL) {
		oclog(ws, LOG_INFO, "requested config but no config file is set");
		cstp_printf(ws, "HTTP/1.%u 404 Not found\r\n", http_ver);
		return -1;
	}
	
	ret = stat( ws->config->xml_config_file, &st);
	if (ret == -1) {
		oclog(ws, LOG_INFO, "cannot load config file '%s'", ws->config->xml_config_file);
		cstp_printf(ws, "HTTP/1.%u 404 Not found\r\n", http_ver);
		return -1;
	}

	cstp_cork(ws);
	ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver);
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Connection: Keep-Alive\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Content-Type: text/xml\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_printf(ws, "Content-Length: %u\r\n", (unsigned)st.st_size);
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_uncork(ws);
	if (ret < 0)
		return -1;

	ret = cstp_send_file(ws, ws->config->xml_config_file);
	if (ret < 0) {
		oclog(ws, LOG_ERR, "error sending file '%s': %s", ws->config->xml_config_file, gnutls_strerror(ret));
		return -1;
	}

	return 0;
}
示例#2
0
static
int basic_auth_handler(worker_st * ws, unsigned http_ver, const char *msg)
{
	int ret;

	oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: 401 Unauthorized");
	cstp_cork(ws);
	ret = cstp_printf(ws, "HTTP/1.%u 401 Unauthorized\r\n", http_ver);
	if (ret < 0)
		return -1;

	if (ws->perm_config->auth_methods > 1) {
		ret = cstp_puts(ws, "X-HTTP-Auth-Support: fallback\r\n");
		if (ret < 0)
			return -1;
	}

	if (msg == NULL) {
		oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: WWW-Authenticate: Negotiate");
		ret = cstp_puts(ws, "WWW-Authenticate: Negotiate\r\n");
	} else {
		oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: WWW-Authenticate: Negotiate %s", msg);
		ret = cstp_printf(ws, "WWW-Authenticate: Negotiate %s\r\n", msg);
	}
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Content-Length: 0\r\n");
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}

	ret = cstp_puts(ws, "\r\n");
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}

	ret = cstp_uncork(ws);
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}

	ret = 0;

 cleanup:
	return ret;
}
示例#3
0
int get_string_handler(worker_st *ws, unsigned http_ver)
{
int ret;
const char *data;
int len;

	oclog(ws, LOG_HTTP_DEBUG, "requested fixed string: %s", ws->req.url); 
	if (!strcmp(ws->req.url, "/1/binaries/update.txt")) {
		data = VPN_VERSION;
		len = sizeof(VPN_VERSION)-1;
	} else {
		data = XML_START;
		len = sizeof(XML_START)-1;
	}

	cstp_cork(ws);
	ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver);
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Connection: Keep-Alive\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Content-Type: text/xml\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_printf(ws, "Content-Length: %d\r\n\r\n", len);
	if (ret < 0)
		return -1;
		
	ret = cstp_send(ws, data, len);
	if (ret < 0)
		return -1;

	ret = cstp_uncork(ws);
	if (ret < 0)
		return -1;
	
	return 0;
}
示例#4
0
int get_dl_handler(worker_st *ws, unsigned http_ver)
{
int ret;
const char *data;
int len;

	oclog(ws, LOG_HTTP_DEBUG, "requested downloader: %s", ws->req.url); 

	data = SH_SCRIPT;
	len = sizeof(SH_SCRIPT)-1;

	cstp_cork(ws);
	ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver);
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Connection: Keep-Alive\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Content-Type: application/x-shellscript\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_printf(ws, "Content-Length: %d\r\n\r\n", len);
	if (ret < 0)
		return -1;
		
	ret = cstp_send(ws, data, len);
	if (ret < 0)
		return -1;

	ret = cstp_uncork(ws);
	if (ret < 0)
		return -1;
	
	return 0;
}
示例#5
0
int get_empty_handler(worker_st *ws, unsigned http_ver)
{
int ret;

	cstp_cork(ws);
	ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver);
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Connection: Keep-Alive\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Content-Type: text/html\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_printf(ws, "Content-Length: %u\r\n", (unsigned int)sizeof(empty_msg)-1);
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "\r\n");
	if (ret < 0)
		return -1;

	ret = cstp_send(ws, empty_msg, sizeof(empty_msg)-1);
	if (ret < 0)
		return -1;
	
	ret = cstp_uncork(ws);
	if (ret < 0)
		return -1;
	
	return 0;
}
示例#6
0
int post_kkdcp_handler(worker_st *ws, unsigned http_ver)
{
	int ret, e, fd = -1;
	struct http_req_st *req = &ws->req;
	unsigned i, length;
	kkdcp_st *kkdcp = NULL;
	uint8_t *buf;
	uint32_t mlength;
	char realm[128] = "";
	const char *reason = "Unknown";
	kkdcp_realm_st *kr;

	oclog(ws, LOG_INFO, "Processing KKDCP request");

	for (i=0;i<ws->config->kkdcp_size;i++) {
		if (ws->config->kkdcp[i].url && strcmp(ws->config->kkdcp[i].url, req->url) == 0) {
			kkdcp = &ws->config->kkdcp[i];
			break;
		}
	}

	if (kkdcp == NULL) {
		oclog(ws, LOG_HTTP_DEBUG, "could not figure kkdcp handler for %s", req->url);
		return -1;
	}

	if (req->body_length == 0) {
		oclog(ws, LOG_HTTP_DEBUG, "empty body length for kkdcp handler %s", req->url);
		return -1;
	}

	ws_add_score_to_ip(ws, ws->config->ban_points_kkdcp, 0);
	oclog(ws, LOG_HTTP_DEBUG, "HTTP processing kkdcp framed request: %u bytes", (unsigned)req->body_length);

	length = BUF_SIZE;
	buf = talloc_size(ws, length);
	if (buf == NULL) {
		oclog(ws, LOG_ERR, "kkdcp: memory error");
		reason = "memory error";
		return -1;
	}

	ret = der_decode((uint8_t*)req->body, req->body_length, buf, &length, realm, sizeof(realm), &e);
	if (ret < 0) {
		oclog(ws, LOG_ERR, "kkdcp: DER decoding error: %s", asn1_strerror(e));
		reason = "DER decoding error";
		goto fail;
	}

	kr = &kkdcp->realms[0];
	if (realm[0] != 0 && kkdcp->realms_size > 1) {
		oclog(ws, LOG_DEBUG, "kkdcp: client asked for '%s'", realm);

		for (i=0;i<kkdcp->realms_size;i++) {
			if (strcmp(kkdcp->realms[i].realm, realm) == 0) {
				kr = &kkdcp->realms[i];
				break;
			}
		}
	}

	fd = socket(kr->ai_family, kr->ai_socktype, kr->ai_protocol);
	if (fd == -1) {
		e = errno;
		oclog(ws, LOG_ERR, "kkdcp: socket error: %s", strerror(e));
		reason = "socket error";
		goto fail;
	}

	ret = connect(fd, (struct sockaddr*)&kr->addr, kr->addr_len);
	if (ret == -1) {
		e = errno;
		oclog(ws, LOG_ERR, "kkdcp: connect error: %s", strerror(e));
		reason = "connect error";
		goto fail;
	}

	oclog(ws, LOG_HTTP_DEBUG, "HTTP sending kkdcp request: %u bytes", (unsigned)length);
	ret = send(fd, buf, length, 0);
	if (ret != length) {
		if (ret == -1) {
			e = errno;
			oclog(ws, LOG_ERR, "kkdcp: send error: %s", strerror(e));
		} else {
			oclog(ws, LOG_ERR, "kkdcp: send error: only %d were sent", ret);
		}
		reason = "send error";
		goto fail;
	}

	if (kr->ai_socktype == SOCK_DGRAM) {
		ret = recv(fd, buf, BUF_SIZE, 0);
		if (ret == -1) {
			e = errno;
			oclog(ws, LOG_ERR, "kkdcp: recv error: %s", strerror(e));
			reason = "recv error";
			goto fail;
		}

		length = ret;
	} else {
		ret = recv(fd, buf, 4, 0);
		if (ret < 4) {
			e = errno;
			oclog(ws, LOG_ERR, "kkdcp: recv error: %s", strerror(e));
			reason = "Recv error";
			ret = -1;
			goto fail;
		}

		memcpy(&mlength, buf, 4);
		mlength = ntohl(mlength);
		if (mlength >= BUF_SIZE-4) {
			oclog(ws, LOG_ERR, "kkdcp: too long message (%d bytes)", (int)mlength);
			reason = "recv error";
			ret = -1;
			goto fail;
		}

		ret = force_read_timeout(fd, buf+4, mlength, 5);
		if (ret == -1) {
			e = errno;
			oclog(ws, LOG_ERR, "kkdcp: recv error: %s", strerror(e));
			reason = "recv error";
			goto fail;
		}
		length = ret + 4;
	}

	oclog(ws, LOG_HTTP_DEBUG, "HTTP processing kkdcp reply: %u bytes", (unsigned)length);

	cstp_cork(ws);
	ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver);
	if (ret < 0) {
		goto fail;
	}

	ret =
	    cstp_puts(ws, "Content-Type: application/kerberos\r\n");
	if (ret < 0) {
		goto fail;
	}

	ret = der_encode_inplace(buf, &length, BUF_SIZE, &e);
	if (ret < 0) {
		oclog(ws, LOG_ERR, "kkdcp: DER encoding error: %s", asn1_strerror(e));
		reason = "DER encoding error";
		goto fail;
	}

	oclog(ws, LOG_HTTP_DEBUG, "HTTP sending kkdcp framed reply: %u bytes", (unsigned)length);
	ret =
	    cstp_printf(ws, "Content-Length: %u\r\n",
		       (unsigned int)length);
	if (ret < 0) {
		goto fail;
	}

	ret = cstp_puts(ws, "Connection: Keep-Alive\r\n");
	if (ret < 0) {
		goto fail;
	}

	ret = cstp_puts(ws, "\r\n");
	if (ret < 0) {
		goto fail;
	}

	ret = cstp_send(ws, buf, length);
	if (ret < 0) {
		goto fail;
	}

	ret = cstp_uncork(ws);
	if (ret < 0) {
		goto fail;
	}

	ret = 0;
	goto cleanup;
 fail:
	cstp_printf(ws,
		   "HTTP/1.%u 502 Bad Gateway\r\nX-Reason: %s\r\n\r\n",
		   http_ver, reason);
	ret = -1;

 cleanup:
 	talloc_free(buf);
 	if (fd != -1)
	 	close(fd);
 	return ret;
}
示例#7
0
int post_common_handler(worker_st * ws, unsigned http_ver, const char *imsg)
{
	int ret, size;
	char str_cookie[BASE64_LENGTH(ws->cookie_size)+1];
	size_t str_cookie_size = sizeof(str_cookie);
	char msg[MAX_BANNER_SIZE + 32];
	const char *success_msg_head;
	const char *success_msg_foot;
	unsigned success_msg_head_size;
	unsigned success_msg_foot_size;

	if (ws->req.user_agent_type == AGENT_OPENCONNECT_V3) {
		success_msg_head = ocv3_success_msg_head;
		success_msg_foot = ocv3_success_msg_foot;
		success_msg_head_size = sizeof(ocv3_success_msg_head)-1;
		success_msg_foot_size = sizeof(ocv3_success_msg_foot)-1;
	} else {
		success_msg_head = oc_success_msg_head;
		success_msg_foot = oc_success_msg_foot;
		success_msg_head_size = sizeof(oc_success_msg_head)-1;
		success_msg_foot_size = sizeof(oc_success_msg_foot)-1;
	}

	base64_encode((char *)ws->cookie, ws->cookie_size,
		      (char *)str_cookie, str_cookie_size);

	/* reply */
	oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: 200 OK");

	cstp_cork(ws);
	ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver);
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "Connection: Keep-Alive\r\n");
	if (ret < 0)
		return -1;

	if (ws->selected_auth->type & AUTH_TYPE_GSSAPI && imsg != NULL && imsg[0] != 0) {
		ret = cstp_printf(ws, "WWW-Authenticate: Negotiate %s\r\n", imsg);
		if (ret < 0)
			return -1;
	}

	ret = cstp_puts(ws, "Content-Type: text/xml\r\n");
	if (ret < 0)
		return -1;

	if (ws->config->banner) {
		size =
		    snprintf(msg, sizeof(msg), "<banner>%s</banner>",
			     ws->config->banner);
		if (size <= 0)
			return -1;
		/* snprintf() returns not a very useful value, so we need to recalculate */
		size = strlen(msg);
	} else {
		msg[0] = 0;
		size = 0;
	}

	size += success_msg_head_size + success_msg_foot_size;

	ret = cstp_printf(ws, "Content-Length: %u\r\n", (unsigned)size);
	if (ret < 0)
		return -1;

	ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n");
	if (ret < 0)
		return -1;

	ret =
	    cstp_printf(ws,
		       "Set-Cookie: webvpn=%s; Secure\r\n",
		       str_cookie);
	if (ret < 0)
		return -1;

#ifdef ANYCONNECT_CLIENT_COMPAT
	ret =
	    cstp_puts(ws,
		     "Set-Cookie: webvpnc=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; Secure\r\n");
	if (ret < 0)
		return -1;

	if (ws->config->xml_config_file) {
		ret =
		    cstp_printf(ws,
			       "Set-Cookie: webvpnc=bu:/&p:t&iu:1/&sh:%s&lu:/+CSCOT+/translation-table?textdomain%%3DAnyConnect%%26type%%3Dmanifest&fu:profiles%%2F%s&fh:%s; path=/; Secure\r\n",
			       ws->config->cert_hash,
			       ws->config->xml_config_file,
			       ws->config->xml_config_hash);
	} else {
		ret =
		    cstp_printf(ws,
			       "Set-Cookie: webvpnc=bu:/&p:t&iu:1/&sh:%s; path=/; Secure\r\n",
			       ws->config->cert_hash);
	}

	if (ret < 0)
		return -1;
#endif

	ret =
	    cstp_printf(ws,
		       "\r\n%s%s%s", success_msg_head, msg, success_msg_foot);
	if (ret < 0)
		return -1;

	ret = cstp_uncork(ws);
	if (ret < 0)
		return -1;

	return 0;
}
示例#8
0
int get_auth_handler2(worker_st * ws, unsigned http_ver, const char *pmsg)
{
	int ret;
	char context[BASE64_LENGTH(SID_SIZE) + 1];
	unsigned int i, j;
	str_st str;
	const char *login_msg_start;
	const char *login_msg_end;

	if (ws->req.user_agent_type == AGENT_OPENCONNECT_V3) {
		login_msg_start = OCV3_LOGIN_MSG_START;
		login_msg_end = ocv3_login_msg_end;
	} else {
		login_msg_start = OC_LOGIN_MSG_START;
		login_msg_end = oc_login_msg_end;
	}

	if (ws->selected_auth->type & AUTH_TYPE_GSSAPI && ws->auth_state < S_AUTH_COOKIE) {
		if (ws->req.authorization == NULL || ws->req.authorization_size == 0)
			return basic_auth_handler(ws, http_ver, NULL);
		else
			return post_auth_handler(ws, http_ver);
	}

	str_init(&str, ws);

	oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: 200 OK");
	cstp_cork(ws);
	ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver);
	if (ret < 0)
		return -1;


	if (ws->sid_set != 0) {
		base64_encode((char *)ws->sid, sizeof(ws->sid), (char *)context,
			      sizeof(context));

		ret =
		    cstp_printf(ws,
			       "Set-Cookie: webvpncontext=%s; Max-Age=%u; Secure\r\n",
			       context, (unsigned)ws->config->cookie_timeout);
		if (ret < 0)
			return -1;

		oclog(ws, LOG_DEBUG, "sent sid: %s", context);
	} else {
		ret =
		    cstp_puts(ws,
			     "Set-Cookie: webvpncontext=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; Secure\r\n");
		if (ret < 0)
			return -1;
	}

	ret = cstp_puts(ws, "Content-Type: text/xml\r\n");
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}

	if (ws->auth_state == S_AUTH_REQ) {
		/* only ask password */
		if (pmsg == NULL)
			pmsg = "Please enter your password";

		ret = str_append_printf(&str, login_msg_start, pmsg);
		if (ret < 0) {
			ret = -1;
			goto cleanup;
		}

		ret = str_append_str(&str, login_msg_password);
		if (ret < 0) {
			ret = -1;
			goto cleanup;
		}

		ret = str_append_str(&str, login_msg_end);
		if (ret < 0) {
			ret = -1;
			goto cleanup;
		}

	} else {
		if (pmsg == NULL)
			pmsg = "Please enter your username";

		/* ask for username and groups */
		ret = str_append_printf(&str, login_msg_start, pmsg);
		if (ret < 0) {
			ret = -1;
			goto cleanup;
		}

		if (ws->selected_auth->type & AUTH_TYPE_USERNAME_PASS) {
			ret = str_append_str(&str, login_msg_user);
			if (ret < 0) {
				ret = -1;
				goto cleanup;
			}
		}

		if (ws->selected_auth->type & AUTH_TYPE_CERTIFICATE && ws->cert_auth_ok != 0) {
			ret = get_cert_info(ws);
			if (ret < 0) {
				ret = -1;
				oclog(ws, LOG_WARNING, "cannot obtain certificate information");
				goto cleanup;
			}
		}

		/* send groups */
		if (ws->config->group_list_size > 0 || ws->cert_groups_size > 0) {
			ret = str_append_str(&str, "<select name=\"group_list\" label=\"GROUP:\">\n");
			if (ret < 0) {
				ret = -1;
				goto cleanup;
			}

			/* Several anyconnect clients (and openconnect) submit the group name
			 * separately in that form. In that case they expect that we re-order
			 * the list and we place the group they selected first. WTF! No respect
			 * to server time.
			 */
			if (ws->groupname[0] != 0) {
				ret = append_group_str(ws, &str, ws->groupname);
				if (ret < 0) {
					ret = -1;
					goto cleanup;
				}
			}

			if (ws->config->default_select_group) {
				ret = str_append_printf(&str, "<option>%s</option>\n", ws->config->default_select_group);
				if (ret < 0) {
					ret = -1;
					goto cleanup;
				}
			}

			/* append any groups available in the certificate */
			if (ws->selected_auth->type & AUTH_TYPE_CERTIFICATE && ws->cert_auth_ok != 0) {
				unsigned dup;

				for (i=0;i<ws->cert_groups_size;i++) {
					dup = 0;
					for (j=0;j<ws->config->group_list_size;j++) {
						if (strcmp(ws->cert_groups[i], ws->config->group_list[j]) == 0) {
							dup = 1;
							break;
						}
					}

					if (dup == 0 && ws->groupname[0] != 0 && strcmp(ws->groupname, ws->cert_groups[i]) == 0)
						dup = 1;

					if (dup != 0)
						continue;

					ret = str_append_printf(&str, "<option>%s</option>\n", ws->cert_groups[i]);
					if (ret < 0) {
						ret = -1;
						goto cleanup;
					}
				}
			}


			for (i=0;i<ws->config->group_list_size;i++) {
				if (ws->groupname[0] != 0 && strcmp(ws->groupname, ws->config->group_list[i]) == 0)
					continue;

				ret = append_group_idx(ws, &str, i);
				if (ret < 0) {
					ret = -1;
					goto cleanup;
				}
			}
			ret = str_append_str(&str, "</select>\n");
			if (ret < 0) {
				ret = -1;
				goto cleanup;
			}
		}

		ret = str_append_str(&str, login_msg_end);
		if (ret < 0) {
			ret = -1;
			goto cleanup;
		}

	}

	ret =
	    cstp_printf(ws, "Content-Length: %u\r\n",
		       (unsigned int)str.length);
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}

	ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n");
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}

	ret = cstp_puts(ws, "\r\n");
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}

	ret = cstp_send(ws, str.data, str.length);
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}


	ret = cstp_uncork(ws);
	if (ret < 0) {
		ret = -1;
		goto cleanup;
	}

	ret = 0;

 cleanup:
 	str_clear(&str);
	return ret;
}