Permalink
Browse files

Sync embedded yahttp copy

API: Replace HTTP Basic auth with static key in custom header

Given that the key is sent in a custom header, this should prevent
any possible CSRF attacks.

Fixes #1769.

Conflicts:
	pdns/docs/httpapi/README.md
	pdns/docs/httpapi/api_spec.md
	pdns/docs/pdns.xml
	regression-tests.api/runtests.py

Updated:
	pdns/webserver.cc to work with older recursor include files.
	pdns/dist-recursor to reflect changes in paths.
	Includes all yahttp updates from master.
	Disables auth API tests.
  • Loading branch information...
1 parent 6fdd40d commit 752756c18cacc654560c837fda9b94ae4befa690 @zeha zeha committed Jun 9, 2014
View
@@ -52,7 +52,6 @@ script:
- sleep 3
- ./clean.sh
- cd ../regression-tests.api
- - ./runtests authoritative
- ./runtests recursor
- cd ../regression-tests
- touch tests/verify-dnssec-zone/allow-missing
View
@@ -1,4 +1,4 @@
-SUBDIRS=modules codedocs @programdescend@
+SUBDIRS=pdns/ext/yahttp modules codedocs @programdescend@
DIST_SUBDIRS=modules codedocs pdns pdns/ext/rapidjson
EXTRA_DIST=README HACKING INSTALL NOTICE debian-pdns/* pdns.spec \
codedocs/doxygen.conf contrib/powerdns.solaris.init.d \
View
@@ -33,6 +33,8 @@ AC_PROG_LIBTOOL
LT_INIT
])
+MC_TM_GMTOFF
+
AM_CONDITIONAL([RELEASE_BUILD], [test "$PACKAGE_VERSION" != "git"])
# Define full_libdir to be the fully expanded (${exec_prefix}, etc.)
@@ -320,6 +322,8 @@ AC_CONFIG_FILES([
pdns/Makefile
codedocs/Makefile
pdns/pdns
+ pdns/ext/yahttp/Makefile
+ pdns/ext/yahttp/yahttp/Makefile
modules/bindbackend/Makefile
modules/db2backend/Makefile
modules/geobackend/Makefile
View
@@ -0,0 +1,13 @@
+dnl Check for the tm_gmtoff field in struct tm
+dnl (Borrowed from the Gaim project)
+
+AC_DEFUN([MC_TM_GMTOFF],
+[AC_REQUIRE([AC_STRUCT_TM])dnl
+AC_CACHE_CHECK([for tm_gmtoff in struct tm], ac_cv_struct_tm_gmtoff,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <$ac_cv_struct_tm>], [struct tm tm; tm.tm_gmtoff;],
+ ac_cv_struct_tm_gmtoff=yes, ac_cv_struct_tm_gmtoff=no)])
+if test "$ac_cv_struct_tm_gmtoff" = yes; then
+ AC_DEFINE(HAVE_TM_GMTOFF, 1, [tm_gmtoff is available.])
+fi
+])
@@ -23,7 +23,7 @@ rec_channel.o rec_channel_rec.o selectmplexer.o sillyrecords.o \
dns_random.o ext/polarssl-1.3.2/library/aes.o ext/polarssl-1.3.2/library/padlock.o dnslabeltext.o \
lua-pdns.o lua-recursor.o randomhelper.o recpacketcache.o dns.o \
reczones.o base32.o nsecrecords.o json.o ws-recursor.o ws-api.o \
-version.o responsestats.o webserver.o ext/yahttp/yahttp/reqresp.o \
+version.o responsestats.o webserver.o ext/yahttp/yahttp/reqresp.o ext/yahttp/yahttp/router.o \
rec-carbon.o
REC_CONTROL_OBJECTS=rec_channel.o rec_control.o arguments.o misc.o \
@@ -65,6 +65,7 @@ void declareArguments()
::arg().set("retrieval-threads", "Number of AXFR-retrieval threads for slave operation")="2";
::arg().setSwitch("experimental-json-interface", "If the webserver should serve JSON data")="no";
::arg().setSwitch("experimental-api-readonly", "If the JSON API should disallow data modification")="no";
+ ::arg().set("experimental-api-key", "REST API Static authentication key (required for API use)")="";
::arg().setSwitch("experimental-dname-processing", "If we should support DNAME records")="no";
::arg().setCmd("help","Provide a helpful message");
View
@@ -54,6 +54,7 @@ cp config-recursor.h $DIRNAME/config.h
cat >>$DIRNAME/config.h <<EOF
#define VERSION "$VERSION"
#define DIST_HOST "$DIST_HOST"
+#define HAVE_BOOST 1
EOF
mkdir -p $DIRNAME/ext/rapidjson/include/rapidjson/internal
cp -a ext/rapidjson/include/rapidjson/*.h $DIRNAME/ext/rapidjson/include/rapidjson/
@@ -63,6 +64,7 @@ cp -a ext/polarssl-1.3.2/include/polarssl/config.h ext/polarssl-1.3.2/include/po
mkdir -p $DIRNAME/ext/polarssl-1.3.2/library
cp -a ext/polarssl-1.3.2/library/aes.c ext/polarssl-1.3.2/library/padlock.c $DIRNAME/ext/polarssl-1.3.2/library
cp -a ext/yahttp/ $DIRNAME/ext/yahttp
+echo '#include "../../../config.h"' > $DIRNAME/ext/yahttp/yahttp/yahttp-config.h
mkdir $DIRNAME/rrd
cp tools/rrd/{create,update,makegraphs,index.html} $DIRNAME/rrd
cp dnslabeltext.rl $DIRNAME
@@ -1,2 +1,4 @@
yahttp/libyahttp.a
*.o
+Makefile
+Makefile.in
Oops, something went wrong.
@@ -1,22 +0,0 @@
-.SILENT:
-
-all:
- $(MAKE) -C yahttp all
-
-install:
-
-uninstall:
-
-distclean: clean
-
-clean:
- $(MAKE) -C yahttp clean
-
-check:
-
-distdir:
- mkdir -p $(distdir)
- cp LICENSE Makefile $(distdir)
- mkdir $(distdir)/yahttp
- cp yahttp/Makefile yahttp/*.cpp yahttp/*.hpp $(distdir)/yahttp
-
@@ -0,0 +1,3 @@
+SUBDIRS=yahttp
+
+EXTRA_DIST=LICENSE README.md
@@ -0,0 +1,62 @@
+Yet Another HTTP Library
+========================
+
+YaHTTP aims to be a pure http request/response parser that has no IO ties. It is intended to be used on small-footprint applications and other utilities that want to use HTTP over something else than network IO.
+
+[![Build Status](https://travis-ci.org/cmouse/yahttp.svg?branch=master)](https://travis-ci.org/cmouse/yahttp)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/2161/badge.svg)](https://scan.coverity.com/projects/2161)
+
+WARNINGS
+--------
+If you are upgrading from version before May 02, 2014 - *PLEASE BE SURE TO CHECK THAT EVERYTHING WORKS AS EXPECTED*. There has been complete overhaul of the library and many things have changed.
+
+Integration guide
+-----------------
+
+Here are some instructions on how to integrate YaHTTP into your project.
+
+With automake and libtool
+-------------------------
+
+If you don't need router or any of the C++11 features, you can just create empty yahttp-config.h, or symlink it to your project's config.h for the yahttp.hpp to include. Then just put this stuff into it's own folder and create Makefile.am with following contents (you can change the compilation flags):
+
+```
+noinst_LTLIBRARIES=libyahttp.la
+libyahttp_la_CXXFLAGS=$(RELRO_CFLAGS) $(PIE_CFLAGS) -D__STRICT_ANSI__
+libyahttp_la_SOURCES=cookie.hpp exception.hpp reqresp.cpp reqresp.hpp router.cpp router.hpp url.hpp utility.hpp yahttp.hpp
+```
+
+You can define RELRO and PIE to match your project.
+
+To compile your project use -Lpath/to/yahttp -lyahttp
+
+If you need router, additionally check for boost or C++11 and replace yahttp-config.h to config.h in yahttp.hpp or add relevant options to your compiler CXXFLAGS. See below for the flags.
+
+Without automake
+----------------
+
+Create simple Makefile with contents for C++11:
+
+```
+OBJECTS=reqresp.o router.o
+CXX=gcc
+CXXFLAGS=-W -Wall -DHAVE_CXX11 -std=c++11
+```
+
+Or create simple Makefile with contents for boost:
+
+```
+OBJECTS=reqresp.o router.o
+CXX=gcc
+CXXFLAGS=-W -Wall -DHAVE_BOOST
+```
+
+Or if you don't need either one, just:
+
+```
+OBJECTS=reqresp.o
+CXX=gcc
+CXXFLAGS=-W -Wall
+```
+
+YaHTTP include files can be placed where the rest of your includes are. Then just add your own code there and it should work just fine.
@@ -1,14 +0,0 @@
-
-all: libyahttp.a
-
-
-clean:
- -rm -f *.o *.a
-
-
-reqresp.o: *.cpp *.hpp
-
-
-libyahttp.a: reqresp.o
- echo AR $@
- $(AR) rcs $@ $<
@@ -0,0 +1,3 @@
+noinst_LTLIBRARIES=libyahttp.la
+
+libyahttp_la_SOURCES=cookie.hpp exception.hpp reqresp.cpp reqresp.hpp router.cpp router.hpp url.hpp utility.hpp yahttp-config.h yahttp.hpp
@@ -0,0 +1,135 @@
+namespace YaHTTP {
+ /*! Implements a single cookie */
+ class Cookie {
+ public:
+ Cookie() {
+ secure = false;
+ httponly = false;
+ name = value = "";
+ }; //!< Set the cookie to empty value
+
+ Cookie(const Cookie &rhs) {
+ domain = rhs.domain;
+ path = rhs.path;
+ secure = rhs.secure;
+ httponly = rhs.httponly;
+ name = rhs.name;
+ value = rhs.value;
+ }; //<! Copy cookie values
+
+ DateTime expires; /*!< Expiration date */
+ std::string domain; /*!< Domain where cookie is valid */
+ std::string path; /*!< Path where the cookie is valid */
+ bool httponly; /*!< Whether the cookie is for server use only */
+ bool secure; /*!< Whether the cookie is for HTTPS only */
+
+ std::string name; /*!< Cookie name */
+ std::string value; /*!< Cookie value */
+
+ std::string str() const {
+ std::ostringstream oss;
+ oss << YaHTTP::Utility::encodeURL(name) << "=" << YaHTTP::Utility::encodeURL(value);
+ if (expires.isSet)
+ oss << "; expires=" << expires.cookie_str();
+ if (domain.size()>0)
+ oss << "; domain=" << domain;
+ if (path.size()>0)
+ oss << "; path=" << path;
+ if (secure)
+ oss << "; secure";
+ if (httponly)
+ oss << "; httpOnly";
+ return oss.str();
+ }; //!< Stringify the cookie
+ };
+
+ /*! Implements a Cookie jar for storing multiple cookies */
+ class CookieJar {
+ public:
+ std::map<std::string, Cookie> cookies; //<! cookie container
+
+ CookieJar() {}; //<! constructs empty cookie jar
+ CookieJar(const CookieJar & rhs) {
+ this->cookies = rhs.cookies;
+ } //<! copy cookies from another cookie jar
+
+ void keyValuePair(const std::string &keyvalue, std::string &key, std::string &value) {
+ size_t pos;
+ pos = keyvalue.find("=");
+ if (pos == std::string::npos) throw "Not a Key-Value pair (cookie)";
+ key = std::string(keyvalue.begin(), keyvalue.begin()+pos);
+ value = std::string(keyvalue.begin()+pos+1, keyvalue.end());
+ } //<! key value pair parser
+
+ void parseCookieHeader(const std::string &cookiestr) {
+ std::list<Cookie> cookies;
+ int cstate = 0; //cookiestate
+ size_t pos,npos;
+ pos = 0;
+ cstate = 0;
+ while(pos < cookiestr.size()) {
+ if (cookiestr.compare(pos, 7, "expires") ==0 ||
+ cookiestr.compare(pos, 6, "domain") ==0 ||
+ cookiestr.compare(pos, 4, "path") ==0) {
+ cstate = 1;
+ // get the date
+ std::string key, value, s;
+ npos = cookiestr.find("; ", pos);
+ if (npos == std::string::npos) {
+ // last value
+ s = std::string(cookiestr.begin() + pos + 1, cookiestr.end());
+ pos = cookiestr.size();
+ } else {
+ s = std::string(cookiestr.begin() + pos + 1, cookiestr.begin() + npos - 1);
+ pos = npos+2;
+ }
+ keyValuePair(s, key, value);
+ if (s == "expires") {
+ DateTime dt;
+ dt.parseCookie(value);
+ for(std::list<Cookie>::iterator i = cookies.begin(); i != cookies.end(); i++)
+ i->expires = dt;
+ } else if (s == "domain") {
+ for(std::list<Cookie>::iterator i = cookies.begin(); i != cookies.end(); i++)
+ i->domain = value;
+ } else if (s == "path") {
+ for(std::list<Cookie>::iterator i = cookies.begin(); i != cookies.end(); i++)
+ i->path = value;
+ }
+ } else if (cookiestr.compare(pos, 8, "httpOnly")==0) {
+ cstate = 1;
+ for(std::list<Cookie>::iterator i = cookies.begin(); i != cookies.end(); i++)
+ i->httponly = true;
+ } else if (cookiestr.compare(pos, 6, "secure") ==0) {
+ cstate = 1;
+ for(std::list<Cookie>::iterator i = cookies.begin(); i != cookies.end(); i++)
+ i->secure = true;
+ } else if (cstate == 0) { // expect cookie
+ Cookie c;
+ std::string s;
+ npos = cookiestr.find("; ", pos);
+ if (npos == std::string::npos) {
+ // last value
+ s = std::string(cookiestr.begin() + pos, cookiestr.end());
+ pos = cookiestr.size();
+ } else {
+ s = std::string(cookiestr.begin() + pos, cookiestr.begin() + npos);
+ pos = npos+2;
+ }
+ keyValuePair(s, c.name, c.value);
+ c.name = YaHTTP::Utility::decodeURL(c.name);
+ c.value = YaHTTP::Utility::decodeURL(c.value);
+ cookies.push_back(c);
+ } else if (cstate == 1) {
+ // ignore crap
+ break;
+ }
+ }
+
+ // store cookies
+ for(std::list<Cookie>::iterator i = cookies.begin(); i != cookies.end(); i++) {
+ this->cookies[i->name] = *i;
+ }
+ }; //<! Parse multiple cookies from header
+ };
+};
@@ -4,17 +4,24 @@
#include <exception>
namespace YaHTTP {
- class ParseError: public std::exception {
+ /*! Generic error class */
+ class Error: public std::exception {
public:
- ParseError() {};
- ParseError(const std::string& reason): reason(reason) {};
- virtual ~ParseError() throw() {};
+ Error() {};
+ Error(const std::string& reason): reason(reason) {};
+ virtual ~Error() throw() {};
virtual const char* what() const throw()
{
return reason.c_str();
}
- const std::string reason;
+ const std::string reason; //<! Cause of the error
+ };
+ /*! Parse error class */
+ class ParseError: public YaHTTP::Error {
+ public:
+ ParseError() {};
+ ParseError(const std::string& reason): Error(reason) {};
};
};
Oops, something went wrong.

0 comments on commit 752756c

Please sign in to comment.