Drizzled Public API Documentation

auth_http.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2009 Sun Microsystems, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include <config.h>
21 
22 #include <curl/curl.h>
23 
24 #include <string>
25 #include <cassert>
26 #include <boost/program_options.hpp>
27 
28 #include <drizzled/item.h>
30 #include <drizzled/identifier.h>
31 #include <drizzled/plugin/authentication.h>
32 #include <drizzled/gettext.h>
33 namespace po= boost::program_options;
34 using namespace drizzled;
35 using namespace std;
36 
37 namespace auth_http {
38 bool updateAuthURL(Session *, set_var *);
39 
40 static size_t curl_cb_read(void *ptr, size_t size, size_t nmemb, void *stream)
41 {
42  (void) ptr;
43  (void) stream;
44  return (size * nmemb);
45 }
46 
47 
49 {
50  CURLcode rv;
51  CURL *curl_handle;
52  std::string sysvar_auth_url;
53 public:
54  Auth_http(std::string name_arg, const std::string &url_arg) :
56  sysvar_auth_url(url_arg)
57  {
58  // we are trusting that plugin initializers are called singlethreaded at startup
59  // if something else also calls curl_global_init() in a threadrace while we are here,
60  // we will crash the server.
61  curl_handle= curl_easy_init();
62 
63  // turn off curl stuff that might mess us up
64  rv= curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0);
65  rv= curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
66  rv= curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
67 
68  // do a HEAD instead of a default GET
69  rv= curl_easy_setopt(curl_handle, CURLOPT_NOBODY, 1);
70 
71  // set the read callback. this shouldnt get called, because we are doing a HEAD
72  rv= curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, curl_cb_read);
73  }
74 
75  std::string& getAuthURL()
76  {
77  return sysvar_auth_url;
78  }
79 
80  bool setAuthURL(std::string& new_auth_url)
81  {
82  if (new_auth_url.empty())
83  {
84  errmsg_printf(error::ERROR, _("auth url cannot be an empty string"));
85  return false; // error
86  }
87  sysvar_auth_url= new_auth_url;
88  return true;
89  }
90 
91  ~Auth_http()
92  {
93  curl_easy_cleanup(curl_handle);
94  curl_global_cleanup();
95  }
96 
97  virtual bool authenticate(const identifier::User &sctx, const string &password)
98  {
99  long http_response_code;
100 
101  assert(sctx.username().c_str());
102 
103  // set the parameters: url, username, password
104  rv= curl_easy_setopt(curl_handle, CURLOPT_URL, sysvar_auth_url.c_str());
105 #if defined(HAVE_CURLOPT_USERNAME)
106 
107  rv= curl_easy_setopt(curl_handle, CURLOPT_USERNAME,
108  sctx.username().c_str());
109  rv= curl_easy_setopt(curl_handle, CURLOPT_PASSWORD, password.c_str());
110 
111 #else
112 
113  string userpwd(sctx.username());
114  userpwd.append(":");
115  userpwd.append(password);
116  rv= curl_easy_setopt(curl_handle, CURLOPT_USERPWD, userpwd.c_str());
117 
118 #endif /* defined(HAVE_CURLOPT_USERNAME) */
119 
120  // do it
121  rv= curl_easy_perform(curl_handle);
122 
123  // what did we get? goes into http_response_code
124  rv= curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_response_code);
125 
126  // so here is an interesting question.
127  // return true if the response_code is 2XX, or return false if its 4XX
128  // for now, return false for 401, true otherwise
129  // this means that if the url breaks, then anyone can log in
130  // this might be the wrong thing
131 
132  if (http_response_code == 401)
133  return false;
134  return true;
135  }
136 };
137 
138 Auth_http* auth= NULL;
139 
145 bool updateAuthURL(Session *, set_var* var)
146 {
147  if (not var->value->str_value.empty())
148  {
149  std::string new_auth_url(var->value->str_value.data());
150  if (auth->setAuthURL(new_auth_url))
151  return false; //success
152  else
153  return true; // error
154  }
155  errmsg_printf(error::ERROR, _("auth_http url cannot be NULL"));
156  return true; // error
157 }
158 
159 
160 static int initialize(drizzled::module::Context &context)
161 {
162  const module::option_map &vm= context.getOptions();
163 
164  /*
165  * Per libcurl manual, in multi-threaded applications, curl_global_init() should
166  * be called *before* curl_easy_init()...which is called in Auto_http's
167  * constructor.
168  */
169  if (curl_global_init(CURL_GLOBAL_NOTHING) != 0)
170  return 1;
171 
172  const string auth_url(vm["url"].as<string>());
173  if (auth_url.size() == 0)
174  {
175  errmsg_printf(error::ERROR,
176  _("auth_http plugin loaded but required option url not "
177  "specified. Against which URL are you intending on "
178  "authenticating?\n"));
179  return 1;
180  }
181 
182  auth= new Auth_http("auth_http", auth_url);
183  context.add(auth);
184  context.registerVariable(new sys_var_std_string("url", auth->getAuthURL(), NULL, &updateAuthURL));
185 
186  return 0;
187 }
188 
189 static void init_options(drizzled::module::option_context &context)
190 {
191  context("url", po::value<string>()->default_value(""),
192  N_("URL for HTTP Auth check"));
193 }
194 
195 } /* namespace auth_http */
196 
197 DRIZZLE_DECLARE_PLUGIN
198 {
199  DRIZZLE_VERSION_ID,
200  "auth-http",
201  "0.1",
202  "Mark Atwood",
203  N_("Authenication against a web server using HTTP"),
204  PLUGIN_LICENSE_GPL,
205  auth_http::initialize,
206  NULL,
207  auth_http::init_options
208 }
209 DRIZZLE_DECLARE_PLUGIN_END;
A set of Session members describing the current authenticated user.
Definition: user.h:34
TODO: Rename this file - func.h is stupid.
An Proxy Wrapper around boost::program_options::variables_map.
String str_value
Definition: item.h:107