1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """HTTP module.
22
23 """
24
25 import logging
26 import mimetools
27 import OpenSSL
28 import select
29 import socket
30 import errno
31
32 from cStringIO import StringIO
33
34 from ganeti import constants
35 from ganeti import serializer
36 from ganeti import utils
37
38
39 HTTP_GANETI_VERSION = "Ganeti %s" % constants.RELEASE_VERSION
40
41 HTTP_OK = 200
42 HTTP_NO_CONTENT = 204
43 HTTP_NOT_MODIFIED = 304
44
45 HTTP_0_9 = "HTTP/0.9"
46 HTTP_1_0 = "HTTP/1.0"
47 HTTP_1_1 = "HTTP/1.1"
48
49 HTTP_GET = "GET"
50 HTTP_HEAD = "HEAD"
51 HTTP_POST = "POST"
52 HTTP_PUT = "PUT"
53 HTTP_DELETE = "DELETE"
54
55 HTTP_ETAG = "ETag"
56 HTTP_HOST = "Host"
57 HTTP_SERVER = "Server"
58 HTTP_DATE = "Date"
59 HTTP_USER_AGENT = "User-Agent"
60 HTTP_CONTENT_TYPE = "Content-Type"
61 HTTP_CONTENT_LENGTH = "Content-Length"
62 HTTP_CONNECTION = "Connection"
63 HTTP_KEEP_ALIVE = "Keep-Alive"
64 HTTP_WWW_AUTHENTICATE = "WWW-Authenticate"
65 HTTP_AUTHORIZATION = "Authorization"
66 HTTP_AUTHENTICATION_INFO = "Authentication-Info"
67 HTTP_ALLOW = "Allow"
68
69 _SSL_UNEXPECTED_EOF = "Unexpected EOF"
70
71
72 (SOCKOP_SEND,
73 SOCKOP_RECV,
74 SOCKOP_SHUTDOWN,
75 SOCKOP_HANDSHAKE) = range(4)
76
77
78 SOCK_BUF_SIZE = 32768
79
80
82 """Internal exception for HTTP errors.
83
84 This should only be used for internal error reporting.
85
86 """
87
88
90 """Internal exception for a closed connection.
91
92 This should only be used for internal error reporting. Only use
93 it if there's no other way to report this condition.
94
95 """
96
97
99 """Internal exception for errors during SSL handshake.
100
101 This should only be used for internal error reporting.
102
103 """
104
105
107 """Internal exception for socket timeouts.
108
109 This should only be used for internal error reporting.
110
111 """
112
113
122
123
125 """400 Bad Request
126
127 RFC2616, 10.4.1: The request could not be understood by the server
128 due to malformed syntax. The client SHOULD NOT repeat the request
129 without modifications.
130
131 """
132 code = 400
133
134
136 """401 Unauthorized
137
138 RFC2616, section 10.4.2: The request requires user
139 authentication. The response MUST include a WWW-Authenticate header
140 field (section 14.47) containing a challenge applicable to the
141 requested resource.
142
143 """
144 code = 401
145
146
148 """403 Forbidden
149
150 RFC2616, 10.4.4: The server understood the request, but is refusing
151 to fulfill it. Authorization will not help and the request SHOULD
152 NOT be repeated.
153
154 """
155 code = 403
156
157
159 """404 Not Found
160
161 RFC2616, 10.4.5: The server has not found anything matching the
162 Request-URI. No indication is given of whether the condition is
163 temporary or permanent.
164
165 """
166 code = 404
167
168
170 """405 Method Not Allowed
171
172 RFC2616, 10.4.6: The method specified in the Request-Line is not
173 allowed for the resource identified by the Request-URI. The response
174 MUST include an Allow header containing a list of valid methods for
175 the requested resource.
176
177 """
178 code = 405
179
180
182 """408 Request Timeout
183
184 RFC2616, 10.4.9: The client did not produce a request within the
185 time that the server was prepared to wait. The client MAY repeat the
186 request without modifications at any later time.
187
188 """
189 code = 408
190
191
193 """409 Conflict
194
195 RFC2616, 10.4.10: The request could not be completed due to a
196 conflict with the current state of the resource. This code is only
197 allowed in situations where it is expected that the user might be
198 able to resolve the conflict and resubmit the request.
199
200 """
201 code = 409
202
203
205 """410 Gone
206
207 RFC2616, 10.4.11: The requested resource is no longer available at
208 the server and no forwarding address is known. This condition is
209 expected to be considered permanent.
210
211 """
212 code = 410
213
214
216 """411 Length Required
217
218 RFC2616, 10.4.12: The server refuses to accept the request without a
219 defined Content-Length. The client MAY repeat the request if it adds
220 a valid Content-Length header field containing the length of the
221 message-body in the request message.
222
223 """
224 code = 411
225
226
228 """412 Precondition Failed
229
230 RFC2616, 10.4.13: The precondition given in one or more of the
231 request-header fields evaluated to false when it was tested on the
232 server.
233
234 """
235 code = 412
236
237
239 """500 Internal Server Error
240
241 RFC2616, 10.5.1: The server encountered an unexpected condition
242 which prevented it from fulfilling the request.
243
244 """
245 code = 500
246
247
249 """501 Not Implemented
250
251 RFC2616, 10.5.2: The server does not support the functionality
252 required to fulfill the request.
253
254 """
255 code = 501
256
257
259 """502 Bad Gateway
260
261 RFC2616, 10.5.3: The server, while acting as a gateway or proxy,
262 received an invalid response from the upstream server it accessed in
263 attempting to fulfill the request.
264
265 """
266 code = 502
267
268
270 """503 Service Unavailable
271
272 RFC2616, 10.5.4: The server is currently unable to handle the
273 request due to a temporary overloading or maintenance of the server.
274
275 """
276 code = 503
277
278
280 """504 Gateway Timeout
281
282 RFC2616, 10.5.5: The server, while acting as a gateway or proxy, did
283 not receive a timely response from the upstream server specified by
284 the URI (e.g. HTTP, FTP, LDAP) or some other auxiliary server
285 (e.g. DNS) it needed to access in attempting to complete the
286 request.
287
288 """
289 code = 504
290
291
293 """505 HTTP Version Not Supported
294
295 RFC2616, 10.5.6: The server does not support, or refuses to support,
296 the HTTP protocol version that was used in the request message.
297
298 """
299 code = 505
300
301
310
311
313 """Waits for a condition to occur on the socket.
314
315 @type sock: socket
316 @param sock: Wait for events on this socket
317 @type event: int
318 @param event: ORed condition (see select module)
319 @type timeout: float or None
320 @param timeout: Timeout in seconds
321 @rtype: int or None
322 @return: None for timeout, otherwise occured conditions
323
324 """
325 check = (event | select.POLLPRI |
326 select.POLLNVAL | select.POLLHUP | select.POLLERR)
327
328 if timeout is not None:
329
330 timeout *= 1000
331
332 poller = select.poll()
333 poller.register(sock, event)
334 try:
335 while True:
336
337
338
339 io_events = poller.poll(timeout)
340 if not io_events:
341
342 return None
343 for (evfd, evcond) in io_events:
344 if evcond & check:
345 return evcond
346 finally:
347 poller.unregister(sock)
348
349
351 """Wrapper around socket functions.
352
353 This function abstracts error handling for socket operations, especially
354 for the complicated interaction with OpenSSL.
355
356 @type sock: socket
357 @param sock: Socket for the operation
358 @type op: int
359 @param op: Operation to execute (SOCKOP_* constants)
360 @type arg1: any
361 @param arg1: Parameter for function (if needed)
362 @type timeout: None or float
363 @param timeout: Timeout in seconds or None
364 @return: Return value of socket function
365
366 """
367
368 if op in (SOCKOP_SEND, SOCKOP_HANDSHAKE):
369 event_poll = select.POLLOUT
370
371 elif op == SOCKOP_RECV:
372 event_poll = select.POLLIN
373
374 elif op == SOCKOP_SHUTDOWN:
375 event_poll = None
376
377
378
379 assert timeout
380
381 else:
382 raise AssertionError("Invalid socket operation")
383
384
385 if (op == SOCKOP_HANDSHAKE and
386 not isinstance(sock, OpenSSL.SSL.ConnectionType)):
387 return
388
389
390 event_override = 0
391
392 while True:
393
394 if event_override or op in (SOCKOP_SEND, SOCKOP_RECV, SOCKOP_HANDSHAKE):
395 if event_override:
396 wait_for_event = event_override
397 else:
398 wait_for_event = event_poll
399
400 event = WaitForSocketCondition(sock, wait_for_event, timeout)
401 if event is None:
402 raise HttpSocketTimeout()
403
404 if (op == SOCKOP_RECV and
405 event & (select.POLLNVAL | select.POLLHUP | select.POLLERR)):
406 return ""
407
408 if not event & wait_for_event:
409 continue
410
411
412 event_override = 0
413
414 try:
415 try:
416 if op == SOCKOP_SEND:
417 return sock.send(arg1)
418
419 elif op == SOCKOP_RECV:
420 return sock.recv(arg1)
421
422 elif op == SOCKOP_SHUTDOWN:
423 if isinstance(sock, OpenSSL.SSL.ConnectionType):
424
425 return sock.shutdown()
426 else:
427 return sock.shutdown(arg1)
428
429 elif op == SOCKOP_HANDSHAKE:
430 return sock.do_handshake()
431
432 except OpenSSL.SSL.WantWriteError:
433
434 event_override = select.POLLOUT
435 continue
436
437 except OpenSSL.SSL.WantReadError:
438
439 event_override = select.POLLIN | select.POLLPRI
440 continue
441
442 except OpenSSL.SSL.WantX509LookupError:
443 continue
444
445 except OpenSSL.SSL.ZeroReturnError, err:
446
447
448
449
450
451 if op == SOCKOP_SEND:
452
453 raise HttpConnectionClosed(err.args)
454 elif op == SOCKOP_RECV:
455 return ""
456
457
458 raise socket.error(err.args)
459
460 except OpenSSL.SSL.SysCallError, err:
461 if op == SOCKOP_SEND:
462
463 if err.args and err.args[0] == -1 and arg1 == "":
464
465
466 return 0
467
468 if err.args == (-1, _SSL_UNEXPECTED_EOF):
469 if op == SOCKOP_RECV:
470 return ""
471 elif op == SOCKOP_HANDSHAKE:
472
473
474 raise HttpSessionHandshakeUnexpectedEOF(err.args)
475
476 raise socket.error(err.args)
477
478 except OpenSSL.SSL.Error, err:
479 raise socket.error(err.args)
480
481 except socket.error, err:
482 if err.args and err.args[0] == errno.EAGAIN:
483
484 continue
485
486 raise
487
488
490 """Closes the connection.
491
492 @type sock: socket
493 @param sock: Socket to be shut down
494 @type close_timeout: float
495 @param close_timeout: How long to wait for the peer to close
496 the connection
497 @type write_timeout: float
498 @param write_timeout: Write timeout for shutdown
499 @type msgreader: http.HttpMessageReader
500 @param msgreader: Request message reader, used to determine whether
501 peer should close connection
502 @type force: bool
503 @param force: Whether to forcibly close the connection without
504 waiting for peer
505
506 """
507
508 if msgreader and msgreader.peer_will_close and not force:
509
510 try:
511
512 if not SocketOperation(sock, SOCKOP_RECV, 1, close_timeout):
513 return
514 except (socket.error, HttpError, HttpSocketTimeout):
515
516 pass
517
518
519 try:
520
521 SocketOperation(sock, SOCKOP_SHUTDOWN, socket.SHUT_RDWR,
522 write_timeout)
523 except HttpSocketTimeout:
524 raise HttpError("Timeout while shutting down connection")
525 except socket.error, err:
526
527 if not (err.args and err.args[0] == errno.ENOTCONN):
528 raise HttpError("Error while shutting down connection: %s" % err)
529
530
532 """Shakes peer's hands.
533
534 @type sock: socket
535 @param sock: Socket to be shut down
536 @type write_timeout: float
537 @param write_timeout: Write timeout for handshake
538
539 """
540 try:
541 return SocketOperation(sock, SOCKOP_HANDSHAKE, None, write_timeout)
542 except HttpSocketTimeout:
543 raise HttpError("Timeout during SSL handshake")
544 except socket.error, err:
545 raise HttpError("Error in SSL handshake: %s" % err)
546
547
549 """Data class for SSL key and certificate.
550
551 """
552 - def __init__(self, ssl_key_path, ssl_cert_path):
553 """Initializes this class.
554
555 @type ssl_key_path: string
556 @param ssl_key_path: Path to file containing SSL key in PEM format
557 @type ssl_cert_path: string
558 @param ssl_cert_path: Path to file containing SSL certificate
559 in PEM format
560
561 """
562 self.ssl_key_pem = utils.ReadFile(ssl_key_path)
563 self.ssl_cert_pem = utils.ReadFile(ssl_cert_path)
564
566 return OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM,
567 self.ssl_key_pem)
568
570 return OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
571 self.ssl_cert_pem)
572
573
575 """Base class for HTTP server and client.
576
577 """
579 self.using_ssl = None
580 self._ssl_params = None
581 self._ssl_key = None
582 self._ssl_cert = None
583
585 """Creates a TCP socket and initializes SSL if needed.
586
587 @type ssl_params: HttpSslParams
588 @param ssl_params: SSL key and certificate
589 @type ssl_verify_peer: bool
590 @param ssl_verify_peer: Whether to require client certificate
591 and compare it with our certificate
592
593 """
594 self._ssl_params = ssl_params
595
596 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
597
598
599 self.using_ssl = ssl_params is not None
600
601 if not self.using_ssl:
602 return sock
603
604 self._ssl_key = ssl_params.GetKey()
605 self._ssl_cert = ssl_params.GetCertificate()
606
607 ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
608 ctx.set_options(OpenSSL.SSL.OP_NO_SSLv2)
609
610 ctx.use_privatekey(self._ssl_key)
611 ctx.use_certificate(self._ssl_cert)
612 ctx.check_privatekey()
613
614 if ssl_verify_peer:
615 ctx.set_verify(OpenSSL.SSL.VERIFY_PEER |
616 OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
617 self._SSLVerifyCallback)
618
619 return OpenSSL.SSL.Connection(ctx, sock)
620
622 """Verify the certificate provided by the peer
623
624 We only compare fingerprints. The client must use the same certificate as
625 we do on our side.
626
627 """
628 assert self._ssl_params, "SSL not initialized"
629
630 return (self._ssl_cert.digest("sha1") == cert.digest("sha1") and
631 self._ssl_cert.digest("md5") == cert.digest("md5"))
632
633
635 """Data structure for HTTP message.
636
637 """
639 self.start_line = None
640 self.headers = None
641 self.body = None
642 self.decoded_body = None
643
644
646 """Data structure for HTTP request start line.
647
648 """
649 - def __init__(self, method, path, version):
650 self.method = method
651 self.path = path
652 self.version = version
653
655 return "%s %s %s" % (self.method, self.path, self.version)
656
657
659 """Data structure for HTTP response start line.
660
661 """
662 - def __init__(self, version, code, reason):
663 self.version = version
664 self.code = code
665 self.reason = reason
666
668 return "%s %s %s" % (self.version, self.code, self.reason)
669
670
672 """Writes an HTTP message to a socket.
673
674 """
675 - def __init__(self, sock, msg, write_timeout):
676 """Initializes this class and writes an HTTP message to a socket.
677
678 @type sock: socket
679 @param sock: Socket to be written to
680 @type msg: http.HttpMessage
681 @param msg: HTTP message to be written
682 @type write_timeout: float
683 @param write_timeout: Write timeout for socket
684
685 """
686 self._msg = msg
687
688 self._PrepareMessage()
689
690 buf = self._FormatMessage()
691
692 pos = 0
693 end = len(buf)
694 while pos < end:
695
696 data = buf[pos:(pos + SOCK_BUF_SIZE)]
697
698 sent = SocketOperation(sock, SOCKOP_SEND, data, write_timeout)
699
700
701 pos += sent
702
703 assert pos == end, "Message wasn't sent completely"
704
706 """Prepares the HTTP message by setting mandatory headers.
707
708 """
709
710
711
712 if self._msg.body:
713 self._msg.headers[HTTP_CONTENT_LENGTH] = len(self._msg.body)
714
740
741 - def HasMessageBody(self):
742 """Checks whether the HTTP message contains a body.
743
744 Can be overridden by subclasses.
745
746 """
747 return bool(self._msg.body)
748
749
751 """Reads HTTP message from socket.
752
753 """
754
755 START_LINE_LENGTH_MAX = None
756 HEADER_LENGTH_MAX = None
757
758
759 PS_START_LINE = "start-line"
760 PS_HEADERS = "headers"
761 PS_BODY = "entity-body"
762 PS_COMPLETE = "complete"
763
764 - def __init__(self, sock, msg, read_timeout):
765 """Reads an HTTP message from a socket.
766
767 @type sock: socket
768 @param sock: Socket to be read from
769 @type msg: http.HttpMessage
770 @param msg: Object for the read message
771 @type read_timeout: float
772 @param read_timeout: Read timeout for socket
773
774 """
775 self.sock = sock
776 self.msg = msg
777
778 self.start_line_buffer = None
779 self.header_buffer = StringIO()
780 self.body_buffer = StringIO()
781 self.parser_status = self.PS_START_LINE
782 self.content_length = None
783 self.peer_will_close = None
784
785 buf = ""
786 eof = False
787 while self.parser_status != self.PS_COMPLETE:
788
789
790 data = SocketOperation(sock, SOCKOP_RECV, SOCK_BUF_SIZE, read_timeout)
791
792 if data:
793 buf += data
794 else:
795 eof = True
796
797
798 buf = self._ContinueParsing(buf, eof)
799
800
801
802 if (eof and
803 self.parser_status in (self.PS_START_LINE,
804 self.PS_HEADERS)):
805 raise HttpError("Connection closed prematurely")
806
807
808 buf = self._ContinueParsing(buf, True)
809
810 assert self.parser_status == self.PS_COMPLETE
811 assert not buf, "Parser didn't read full response"
812
813 msg.body = self.body_buffer.getvalue()
814
815
816 if msg.body:
817 msg.decoded_body = HttpJsonConverter().Decode(msg.body)
818 else:
819 msg.decoded_body = None
820
821 if msg.decoded_body:
822 logging.debug("Message body: %s", msg.decoded_body)
823
825 """Main function for HTTP message state machine.
826
827 @type buf: string
828 @param buf: Receive buffer
829 @type eof: bool
830 @param eof: Whether we've reached EOF on the socket
831 @rtype: string
832 @return: Updated receive buffer
833
834 """
835
836 if self.parser_status == self.PS_START_LINE:
837
838 while True:
839 idx = buf.find("\r\n")
840
841
842
843
844
845
846 if idx == 0:
847
848 buf = buf[:2]
849 continue
850
851 if idx > 0:
852 self.start_line_buffer = buf[:idx]
853
854 self._CheckStartLineLength(len(self.start_line_buffer))
855
856
857 buf = buf[idx + 2:]
858
859 self.msg.start_line = self.ParseStartLine(self.start_line_buffer)
860
861 self.parser_status = self.PS_HEADERS
862 else:
863
864
865 self._CheckStartLineLength(len(buf))
866
867 break
868
869
870 if self.parser_status == self.PS_HEADERS:
871
872 idx = buf.find("\r\n\r\n")
873 if idx >= 0:
874 self.header_buffer.write(buf[:idx + 2])
875
876 self._CheckHeaderLength(self.header_buffer.tell())
877
878
879 buf = buf[idx + 4:]
880
881 self._ParseHeaders()
882
883 self.parser_status = self.PS_BODY
884 else:
885
886
887 self._CheckHeaderLength(len(buf))
888
889 if self.parser_status == self.PS_BODY:
890
891 self.body_buffer.write(buf)
892 buf = ""
893
894
895
896
897
898
899
900
901
902
903 if (eof or
904 self.content_length is None or
905 (self.content_length is not None and
906 self.body_buffer.tell() >= self.content_length)):
907 self.parser_status = self.PS_COMPLETE
908
909 return buf
910
922
933
935 """Parses the start line of a message.
936
937 Must be overridden by subclass.
938
939 @type start_line: string
940 @param start_line: Start line string
941
942 """
943 raise NotImplementedError()
944
946 """Evaluate whether peer will close the connection.
947
948 @rtype: bool
949 @return: Whether peer will close the connection
950
951 """
952
953
954
955
956
957
958
959
960
961
962 hdr_connection = self.msg.headers.get(HTTP_CONNECTION, None)
963 if hdr_connection:
964 hdr_connection = hdr_connection.lower()
965
966
967 if self.msg.start_line.version == HTTP_1_1:
968 return (hdr_connection and "close" in hdr_connection)
969
970
971
972
973
974 if self.msg.headers.get(HTTP_KEEP_ALIVE):
975 return False
976
977
978
979 if hdr_connection and "keep-alive" in hdr_connection:
980 return False
981
982 return True
983
985 """Parses the headers.
986
987 This function also adjusts internal variables based on header values.
988
989 RFC2616, section 4.3: The presence of a message-body in a request is
990 signaled by the inclusion of a Content-Length or Transfer-Encoding header
991 field in the request's message-headers.
992
993 """
994
995 self.header_buffer.seek(0, 0)
996 self.msg.headers = mimetools.Message(self.header_buffer, 0)
997
998 self.peer_will_close = self._WillPeerCloseConnection()
999
1000
1001 hdr_content_length = self.msg.headers.get(HTTP_CONTENT_LENGTH, None)
1002 if hdr_content_length:
1003 try:
1004 self.content_length = int(hdr_content_length)
1005 except (TypeError, ValueError):
1006 self.content_length = None
1007 if self.content_length is not None and self.content_length < 0:
1008 self.content_length = None
1009
1010
1011
1012 if self.content_length is None:
1013 self.peer_will_close = True
1014