1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
93
  
94
  
95
  
96
  
97
  
98
  
99
  
100
  
101
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
116
  
117
  
118
  
119
  
120
  
121
  
122
  
123
  
124
  
#pike __REAL_VERSION__ 
 
#if constant(SSL.Cipher.CipherAlgorithm) 
 
import "."; 
 
MySSLPort port; 
int portno; 
string|int(0..0) interface; 
function(Request:void) callback; 
 
//! 
object|function|program request_program=Request; 
 
//! The simplest SSL server possible. Binds a port and calls 
//! a callback with @[request_program] objects. 
 
//! Create a HTTPS (HTTP over SSL) server. 
//! 
//! @param _callback 
//!   The function run when a request is received. 
//!   takes one argument of type @[Request]. 
//! @param _portno 
//!   The port number to bind to, defaults to 443. 
//! @param _interface 
//!   The interface address to bind to. 
//! @param key 
//!   An optional SSL secret key, provided in binary format, such 
//!   as that created by @[Standards.PKCS.RSA.private_key()]. 
//! @param certificate 
//!   An optional SSL certificate or chain of certificates with the host  
//!   certificate first, provided in binary format. 
void create(function(Request:void) _callback, 
            void|int _portno, 
            void|string _interface, void|string key, void|string|array certificate) 
{ 
   portno=_portno; 
   if (!portno) portno=443; // default HTTPS port 
 
   callback=_callback; 
   interface=_interface; 
 
   port=MySSLPort(); 
   port->set_default_keycert(); 
   if(key) 
     port->set_key(key); 
   if(certificate) 
     port->set_certificate(certificate); 
 
   if (!port->bind(portno,new_connection,[string]interface)) 
      error("HTTP.Server.SSLPort: failed to bind port %s%d: %s\n", 
            interface?interface+":":"", 
            portno,strerror(port->errno())); 
} 
 
//! Closes the HTTP port. 
void close() 
{ 
   destruct(port); 
   port=0; 
} 
 
void destroy() { close(); } 
 
//! The port accept callback 
protected void new_connection() 
{ 
   SSL.sslfile fd=port->accept(); 
   Request r=request_program(); 
   r->attach_fd(fd,this,callback); 
} 
 
//! 
class MySSLPort 
{ 
 
  inherit SSL.sslport; 
 
  //! 
  void set_default_keycert() 
  { 
    private_key = Crypto.RSA(); 
    private_key->generate_key( 4096 ); 
 
    mapping a = ([ 
      "organizationName" : "Pike TLS server", 
      "commonName" : "*", 
    ]); 
 
    certificates = ({ 
      Standards.X509.make_selfsigned_certificate(private_key, 3600*24*365, a) 
    }); 
  } 
 
  //! 
  void set_key(string skey) 
  { 
    private_key = Standards.PKCS.RSA.parse_private_key(skey); 
  } 
 
  //! 
  void set_certificate(string|array(string) certificate) 
  { 
    if(arrayp(certificate)) 
      certificates = [array(string)]certificate; 
    else 
      certificates = ({ [string]certificate }); 
  } 
 
  void create() 
  { 
    sslport::create(); 
    random = Crypto.Random.random_string; 
  } 
 
} 
 
string _sprintf(int t) { 
  return t=='O' && sprintf("%O(%O:%d)", this_program, interface, portno); 
} 
 
#endif