/*
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Siemens AG 2018-2020
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h"
#include <stdio.h>
#include <stdlib.h>
#include "crypto/ctype.h"
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/httperr.h>
#include <openssl/cmperr.h>
#include <openssl/buffer.h>
#include <openssl/http.h>
#include "internal/sockets.h"
#include "internal/cryptlib.h" /* for ossl_assert() */
#include "http_local.h"
#define HTTP_PREFIX "HTTP/"
#define HTTP_VERSION_PATT "1." /* allow 1.x */
#define HTTP_VERSION_STR_LEN 3
#define HTTP_LINE1_MINLEN ((int)strlen(HTTP_PREFIX HTTP_VERSION_PATT "x 200\n"))
#define HTTP_VERSION_MAX_REDIRECTIONS 50
#define HTTP_STATUS_CODE_OK 200
#define HTTP_STATUS_CODE_MOVED_PERMANENTLY 301
#define HTTP_STATUS_CODE_FOUND 302
/* Stateful HTTP request code, supporting blocking and non-blocking I/O */
/* Opaque HTTP request status structure */
struct ossl_http_req_ctx_st {
int state; /* Current I/O state */
unsigned char *readbuf; /* Buffer for reading response by line */
int readbuflen; /* Buffer length, equals maxline */
BIO *wbio; /* BIO to send request to */
BIO *rbio; /* BIO to read response from */
BIO *mem; /* Memory BIO response is built into */
int method_POST; /* HTTP method is "POST" (else "GET") */
const char *expected_ct; /* expected Content-Type, or NULL */
int expect_asn1; /* response must be ASN.1-encoded */
long len_to_send; /* number of bytes in request still to send */
unsigned long resp_len; /* length of response */
unsigned long max_resp_len; /* Maximum length of response */
time_t max_time; /* Maximum end time of the transfer, or 0 */
char *redirection_url; /* Location given with HTTP status 301/302 */
};
/* HTTP states */
#define OHS_NOREAD 0x1000 /* If set no reading should be performed */
#define OHS_ERROR (0 | OHS_NOREAD) /* Error condition */
#define OHS_FIRSTLINE 1 /* First line being read */
#define OHS_REDIRECT 0xa /* Looking for redirection location */
#define OHS_HEADERS 2 /* MIME headers being read */
#define OHS_ASN1_HEADER 3 /* HTTP initial header (tag+length) being read */
#define OHS_CONTENT 4 /* HTTP content octets being read */
#define OHS_WRITE_INIT (5 | OHS_NOREAD) /* 1st call: ready to start send */
#define OHS_WRITE (6 | OHS_NOREAD) /* Request being sent */
#define OHS_FLUSH (7 | OHS_NOREAD) /* Request being flushed */
#define OHS_DONE (8 | OHS_NOREAD) /* Completed */
#define OHS_HTTP_HEADER (9 | OHS_NOREAD) /* Headers set, w/o final \r\n */
OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio,
int maxline, unsigned long max_resp_len,
int timeout, const char *expected_ct,
int expect_asn1)
{
OSSL_HTTP_REQ_CTX *rctx;
if (wbio == NULL || rbio == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((rctx = OPENSSL_zalloc(sizeof(*rctx))) == NULL)
return NULL;