Guard against emitting 'end' twice on http responses
[platform/upstream/nodejs.git] / src / node_crypto.h
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #ifndef SRC_NODE_CRYPTO_H_
23 #define SRC_NODE_CRYPTO_H_
24
25 #include "node.h"
26
27 #include "node_object_wrap.h"
28 #include "v8.h"
29
30 #include <openssl/ssl.h>
31 #include <openssl/err.h>
32 #include <openssl/evp.h>
33 #include <openssl/pem.h>
34 #include <openssl/x509.h>
35 #include <openssl/x509v3.h>
36 #include <openssl/hmac.h>
37 #include <openssl/rand.h>
38
39 #ifdef OPENSSL_NPN_NEGOTIATED
40 #include "node_buffer.h"
41 #endif
42
43 #define EVP_F_EVP_DECRYPTFINAL 101
44
45
46 namespace node {
47 namespace crypto {
48
49 static X509_STORE* root_cert_store;
50
51 class SecureContext : ObjectWrap {
52  public:
53   static void Initialize(v8::Handle<v8::Object> target);
54
55   SSL_CTX *ctx_;
56   // TODO: ca_store_ should probably be removed, it's not used anywhere.
57   X509_STORE *ca_store_;
58
59  protected:
60   static v8::Handle<v8::Value> New(const v8::Arguments& args);
61   static v8::Handle<v8::Value> Init(const v8::Arguments& args);
62   static v8::Handle<v8::Value> SetKey(const v8::Arguments& args);
63   static v8::Handle<v8::Value> SetCert(const v8::Arguments& args);
64   static v8::Handle<v8::Value> AddCACert(const v8::Arguments& args);
65   static v8::Handle<v8::Value> AddCRL(const v8::Arguments& args);
66   static v8::Handle<v8::Value> AddRootCerts(const v8::Arguments& args);
67   static v8::Handle<v8::Value> SetCiphers(const v8::Arguments& args);
68   static v8::Handle<v8::Value> SetOptions(const v8::Arguments& args);
69   static v8::Handle<v8::Value> SetSessionIdContext(const v8::Arguments& args);
70   static v8::Handle<v8::Value> Close(const v8::Arguments& args);
71
72   SecureContext() : ObjectWrap() {
73     ctx_ = NULL;
74     ca_store_ = NULL;
75   }
76
77   void FreeCTXMem() {
78     if (ctx_) {
79       if (ctx_->cert_store == root_cert_store) {
80         // SSL_CTX_free() will attempt to free the cert_store as well.
81         // Since we want our root_cert_store to stay around forever
82         // we just clear the field. Hopefully OpenSSL will not modify this
83         // struct in future versions.
84         ctx_->cert_store = NULL;
85       }
86       SSL_CTX_free(ctx_);
87       ctx_ = NULL;
88       ca_store_ = NULL;
89     } else {
90       assert(ca_store_ == NULL);
91     }
92   }
93
94   ~SecureContext() {
95     FreeCTXMem();
96   }
97
98  private:
99 };
100
101 class Connection : ObjectWrap {
102  public:
103   static void Initialize(v8::Handle<v8::Object> target);
104
105 #ifdef OPENSSL_NPN_NEGOTIATED
106   v8::Persistent<v8::Object> npnProtos_;
107   v8::Persistent<v8::Value> selectedNPNProto_;
108 #endif
109
110 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
111   v8::Persistent<v8::Function> sniCallback_;
112   v8::Persistent<v8::Value> sniContext_;
113   v8::Persistent<v8::String> servername_;
114 #endif
115
116  protected:
117   static v8::Handle<v8::Value> New(const v8::Arguments& args);
118   static v8::Handle<v8::Value> EncIn(const v8::Arguments& args);
119   static v8::Handle<v8::Value> ClearOut(const v8::Arguments& args);
120   static v8::Handle<v8::Value> ClearPending(const v8::Arguments& args);
121   static v8::Handle<v8::Value> EncPending(const v8::Arguments& args);
122   static v8::Handle<v8::Value> EncOut(const v8::Arguments& args);
123   static v8::Handle<v8::Value> ClearIn(const v8::Arguments& args);
124   static v8::Handle<v8::Value> GetPeerCertificate(const v8::Arguments& args);
125   static v8::Handle<v8::Value> GetSession(const v8::Arguments& args);
126   static v8::Handle<v8::Value> SetSession(const v8::Arguments& args);
127   static v8::Handle<v8::Value> IsSessionReused(const v8::Arguments& args);
128   static v8::Handle<v8::Value> IsInitFinished(const v8::Arguments& args);
129   static v8::Handle<v8::Value> VerifyError(const v8::Arguments& args);
130   static v8::Handle<v8::Value> GetCurrentCipher(const v8::Arguments& args);
131   static v8::Handle<v8::Value> Shutdown(const v8::Arguments& args);
132   static v8::Handle<v8::Value> ReceivedShutdown(const v8::Arguments& args);
133   static v8::Handle<v8::Value> Start(const v8::Arguments& args);
134   static v8::Handle<v8::Value> Close(const v8::Arguments& args);
135
136 #ifdef OPENSSL_NPN_NEGOTIATED
137   // NPN
138   static v8::Handle<v8::Value> GetNegotiatedProto(const v8::Arguments& args);
139   static v8::Handle<v8::Value> SetNPNProtocols(const v8::Arguments& args);
140   static int AdvertiseNextProtoCallback_(SSL *s,
141                                          const unsigned char **data,
142                                          unsigned int *len,
143                                          void *arg);
144   static int SelectNextProtoCallback_(SSL *s,
145                                       unsigned char **out, unsigned char *outlen,
146                                       const unsigned char* in,
147                                       unsigned int inlen, void *arg);
148 #endif
149
150 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
151   // SNI
152   static v8::Handle<v8::Value> GetServername(const v8::Arguments& args);
153   static v8::Handle<v8::Value> SetSNICallback(const v8::Arguments& args);
154   static int SelectSNIContextCallback_(SSL *s, int *ad, void* arg);
155 #endif
156
157   int HandleBIOError(BIO *bio, const char* func, int rv);
158   int HandleSSLError(const char* func, int rv);
159
160   void ClearError();
161   void SetShutdownFlags();
162
163   static Connection* Unwrap(const v8::Arguments& args) {
164     Connection* ss = ObjectWrap::Unwrap<Connection>(args.Holder());
165     ss->ClearError();
166     return ss;
167   }
168
169   Connection() : ObjectWrap() {
170     bio_read_ = bio_write_ = NULL;
171     ssl_ = NULL;
172   }
173
174   ~Connection() {
175     if (ssl_ != NULL) {
176       SSL_free(ssl_);
177       ssl_ = NULL;
178     }
179
180 #ifdef OPENSSL_NPN_NEGOTIATED
181     if (!npnProtos_.IsEmpty()) npnProtos_.Dispose();
182     if (!selectedNPNProto_.IsEmpty()) selectedNPNProto_.Dispose();
183 #endif
184
185 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
186    if (!sniCallback_.IsEmpty()) sniCallback_.Dispose();
187    if (!sniContext_.IsEmpty()) sniContext_.Dispose();
188    if (!servername_.IsEmpty()) servername_.Dispose();
189 #endif
190   }
191
192  private:
193   static void SSLInfoCallback(const SSL *ssl, int where, int ret);
194
195   BIO *bio_read_;
196   BIO *bio_write_;
197   SSL *ssl_;
198
199   bool is_server_; /* coverity[member_decl] */
200 };
201
202 void InitCrypto(v8::Handle<v8::Object> target);
203
204 }  // namespace crypto
205 }  // namespace node
206
207 #endif  // SRC_NODE_CRYPTO_H_