86903b2003-01-23Martin Nilsson // This is a ChiliMoon protocol module.
50c4c42001-08-23Martin Nilsson // Copyright © 2001, Roxen IS.
f9531d2004-04-04Martin Nilsson // $Id: prot_https.pike,v 2.10 2004/04/04 14:24:53 mani Exp $
c39ebd2000-12-28Martin Stjernholm  // --- Debug defines --- #ifdef SSL3_DEBUG # define SSL3_WERR(X) werror("SSL3: "+X+"\n") #else # define SSL3_WERR(X) #endif
0d0e952000-11-13Per Hedbor inherit SSLProtocol; constant supports_ipless = 0; constant name = "https";
a9fa0d2001-07-21Martin Stjernholm constant prot_name = "https";
3250252002-06-14Martin Nilsson constant requesthandlerfile = "plugins/protocols/http.pike";
0d0e952000-11-13Per Hedbor constant default_port = 443; class fallback_redirect_request { string in = ""; string out; string default_prefix; int port; Stdio.File f; void die() { SSL3_WERR(sprintf("fallback_redirect_request::die()"));
e317812004-04-03Martin Nilsson  f->set_blocking();
0d0e952000-11-13Per Hedbor  f->close(); }
e317812004-04-03Martin Nilsson  void write_callback()
0d0e952000-11-13Per Hedbor  { SSL3_WERR(sprintf("fallback_redirect_request::write_callback()"));
e317812004-04-03Martin Nilsson  int written = f->write(out);
0d0e952000-11-13Per Hedbor  if (written <= 0) die();
e317812004-04-03Martin Nilsson  else { out = out[written..]; if (!strlen(out)) die(); }
0d0e952000-11-13Per Hedbor  }
e317812004-04-03Martin Nilsson  void read_callback(mixed ignored, string s)
0d0e952000-11-13Per Hedbor  {
e317812004-04-03Martin Nilsson  SSL3_WERR(sprintf("fallback_redirect_request::read_callback(X, %O)\n", s));
0d0e952000-11-13Per Hedbor  in += s; string name; string prefix;
6bae6e2002-10-22Martin Nilsson  if (has_value(in, "\r\n\r\n"))
0d0e952000-11-13Per Hedbor  { // werror("request = '%s'\n", in); array(string) lines = in / "\r\n"; array(string) req = replace(lines[0], "\t", " ") / " "; if (sizeof(req) < 2) { out = "HTTP/1.0 400 Bad Request\r\n\r\n"; } else { if (sizeof(req) == 2) { name = req[1]; } else { name = req[1..sizeof(req)-2] * " "; foreach(map(lines[1..], `/, ":"), array header) { if ( (sizeof(header) >= 2) && (lower_case(header[0]) == "host") ) prefix = "https://" + header[1] - " "; } } if (prefix) { if (prefix[-1] == '/') prefix = prefix[..strlen(prefix)-2]; prefix = prefix + ":" + port; } else { /* default_prefix (aka MyWorldLocation) already contains the * portnumber. */ if (!(prefix = default_prefix)) { /* This case is most unlikely to occur, * but better safe than sorry... */ string ip = (f->query_address(1)/" ")[0]; prefix = "https://" + ip + ":" + port; } else if (prefix[..4] == "http:") { /* Broken MyWorldLocation -- fix. */ prefix = "https:" + prefix[5..]; } } out = sprintf("HTTP/1.0 301 Redirect to secure server\r\n" "Location: %s%s\r\n\r\n", prefix, name); } f->set_read_callback(0); f->set_write_callback(write_callback); } }
e317812004-04-03Martin Nilsson  void create(Stdio.File socket, string s, string l, int p)
0d0e952000-11-13Per Hedbor  {
e317812004-04-03Martin Nilsson  SSL3_WERR(sprintf("fallback_redirect_request(X, %O, %O, %O)", s, l||"CONFIG PORT", p));
0d0e952000-11-13Per Hedbor  f = socket; default_prefix = l; port = p; f->set_nonblocking(read_callback, 0, die); read_callback(f, s); }
e317812004-04-03Martin Nilsson  string _sprintf(int t) { return t=='O' && sprintf("fallback_redirect_request(%O)", f); }
0d0e952000-11-13Per Hedbor } class http_fallback {
e317812004-04-03Martin Nilsson  SSL.sslfile my_fd;
0d0e952000-11-13Per Hedbor  void ssl_alert_callback(object alert, object|int n, string data) {
e317812004-04-03Martin Nilsson  SSL3_WERR(sprintf("http_fallback(X, %O, %O)", n, data));
0d0e952000-11-13Per Hedbor  // trace(1);
e317812004-04-03Martin Nilsson  if ( (my_fd->query_connection()->current_write_state->seq_num == 0)
6bae6e2002-10-22Martin Nilsson  && has_value(lower_case(data), "http"))
0d0e952000-11-13Per Hedbor  {
e317812004-04-03Martin Nilsson  Stdio.File raw_fd = my_fd->shutdown();
0d0e952000-11-13Per Hedbor  /* Redirect to a https-url */ fallback_redirect_request(raw_fd, data, my_fd->config && my_fd->config->query("MyWorldLocation"), port); } }
e317812004-04-03Martin Nilsson  void ssl_accept_callback(mixed ignored)
0d0e952000-11-13Per Hedbor  { SSL3_WERR(sprintf("ssl_accept_callback(X)"));
e317812004-04-03Martin Nilsson  my_fd->set_alert_callback(0); /* Forget about http_fallback */ my_fd->set_accept_callback(0);
0d0e952000-11-13Per Hedbor  my_fd = 0; /* Not needed any more */ }
e317812004-04-03Martin Nilsson  void create(SSL.sslfile fd)
0d0e952000-11-13Per Hedbor  { my_fd = fd; fd->set_alert_callback(ssl_alert_callback); fd->set_accept_callback(ssl_accept_callback); }
e317812004-04-03Martin Nilsson  string _sprintf(int t) { return t=='O' && sprintf("http_fallback(%O)", my_fd); }
0d0e952000-11-13Per Hedbor }
e317812004-04-03Martin Nilsson SSL.sslfile accept()
0d0e952000-11-13Per Hedbor {
e317812004-04-03Martin Nilsson  SSL.sslfile q = ::accept();
0d0e952000-11-13Per Hedbor  if (q) { http_fallback(q); } return q; } int set_cookie, set_cookie_only_once; void fix_cvars( Variable.Variable a ) { set_cookie = query( "set_cookie" ); set_cookie_only_once = query( "set_cookie_only_once" ); } void create( mixed ... args ) {
f9531d2004-04-04Martin Nilsson  core.set_up_http_variables( this );
0d0e952000-11-13Per Hedbor  if( variables[ "set_cookie" ] ) variables[ "set_cookie" ]->set_changed_callback( fix_cvars ); if( variables[ "set_cookie_only_once" ] ) variables[ "set_cookie_only_once" ]->set_changed_callback( fix_cvars ); fix_cvars(0); ::create( @args ); }