}
/* Do the CURL stuff! */
+ if(fuzz.header_list != NULL) {
+ curl_easy_setopt(fuzz.easy, CURLOPT_HTTPHEADER, fuzz.header_list);
+ }
+
+ if(fuzz.mail_recipients_list != NULL) {
+ curl_easy_setopt(fuzz.easy, CURLOPT_MAIL_RCPT, fuzz.mail_recipients_list);
+ }
+
curl_easy_perform(fuzz.easy);
EXIT_LABEL:
CURLOPT_SOCKOPTFUNCTION,
fuzz_sockopt_callback));
- /* Can enable verbose mode */
- /* FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 1L)); */
+ /* Set the standard read function callback. */
+ FTRY(curl_easy_setopt(fuzz->easy,
+ CURLOPT_READFUNCTION,
+ fuzz_read_callback));
+ FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_READDATA, fuzz));
+
+ /* Can enable verbose mode by changing 0L to 1L */
+ FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 0L));
/* Set up the state parser */
fuzz->state.data = data;
fuzz_free((void **)&fuzz->username);
fuzz_free((void **)&fuzz->password);
fuzz_free((void **)&fuzz->postfields);
+ fuzz_free((void **)&fuzz->cookie);
+ fuzz_free((void **)&fuzz->range);
+ fuzz_free((void **)&fuzz->customrequest);
+ fuzz_free((void **)&fuzz->mail_from);
+
+ if(fuzz->header_list != NULL) {
+ curl_slist_free_all(fuzz->header_list);
+ fuzz->header_list = NULL;
+ }
+
+ if(fuzz->mail_recipients_list != NULL) {
+ curl_slist_free_all(fuzz->mail_recipients_list);
+ fuzz->mail_recipients_list = NULL;
+ }
if(fuzz->easy != NULL) {
curl_easy_cleanup(fuzz->easy);
return CURL_SOCKOPT_ALREADY_CONNECTED;
}
+/**
+ * Callback function for doing data uploads.
+ */
+static size_t fuzz_read_callback(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *ptr)
+{
+ FUZZ_DATA *fuzz = (FUZZ_DATA *)ptr;
+ curl_off_t nread;
+
+ /* If no upload data has been specified, then return an error code. */
+ if(fuzz->upload1_data_len == 0) {
+ /* No data to upload */
+ return CURL_READFUNC_ABORT;
+ }
+
+ /* Send the upload data. */
+ memcpy(buffer,
+ fuzz->upload1_data,
+ fuzz->upload1_data_len);
+
+ return fuzz->upload1_data_len;
+}
+
/**
* TLV access function - gets the first TLV from a data stream.
*/
int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv)
{
int rc;
+ char *tmp;
switch(tlv->type) {
- case TLV_TYPE_URL:
- FCHECK(fuzz->url == NULL);
- fuzz->url = fuzz_tlv_to_string(tlv);
- FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_URL, fuzz->url));
- break;
-
case TLV_TYPE_RESPONSE1:
/* The pointers in the TLV will always be valid as long as the fuzz data
is in scope, which is the entirety of this file. */
fuzz->rsp1_data_len = tlv->length;
break;
- case TLV_TYPE_USERNAME:
- FCHECK(fuzz->username == NULL);
- fuzz->username = fuzz_tlv_to_string(tlv);
- FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_USERNAME, fuzz->username));
+ case TLV_TYPE_UPLOAD1:
+ /* The pointers in the TLV will always be valid as long as the fuzz data
+ is in scope, which is the entirety of this file. */
+ fuzz->upload1_data = tlv->value;
+ fuzz->upload1_data_len = tlv->length;
+
+ curl_easy_setopt(fuzz->easy, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(fuzz->easy,
+ CURLOPT_INFILESIZE_LARGE,
+ (curl_off_t)fuzz->upload1_data_len);
break;
- case TLV_TYPE_PASSWORD:
- FCHECK(fuzz->password == NULL);
- fuzz->password = fuzz_tlv_to_string(tlv);
- FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_PASSWORD, fuzz->password));
+ case TLV_TYPE_HEADER:
+ tmp = fuzz_tlv_to_string(tlv);
+ fuzz->header_list = curl_slist_append(fuzz->header_list, tmp);
+ fuzz_free((void **)&tmp);
break;
- case TLV_TYPE_POSTFIELDS:
- FCHECK(fuzz->postfields == NULL);
- fuzz->postfields = fuzz_tlv_to_string(tlv);
- FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_POSTFIELDS, fuzz->postfields));
+ case TLV_TYPE_MAIL_RECIPIENT:
+ tmp = fuzz_tlv_to_string(tlv);
+ fuzz->mail_recipients_list =
+ curl_slist_append(fuzz->mail_recipients_list, tmp);
+ fuzz_free((void **)&tmp);
break;
+ /* Define a set of singleton TLVs - they can only have their value set once
+ and all follow the same pattern. */
+ FSINGLETONTLV(TLV_TYPE_URL, url, CURLOPT_URL);
+ FSINGLETONTLV(TLV_TYPE_USERNAME, username, CURLOPT_USERNAME);
+ FSINGLETONTLV(TLV_TYPE_PASSWORD, password, CURLOPT_PASSWORD);
+ FSINGLETONTLV(TLV_TYPE_POSTFIELDS, postfields, CURLOPT_POSTFIELDS);
+ FSINGLETONTLV(TLV_TYPE_COOKIE, cookie, CURLOPT_COOKIE);
+ FSINGLETONTLV(TLV_TYPE_RANGE, range, CURLOPT_RANGE);
+ FSINGLETONTLV(TLV_TYPE_CUSTOMREQUEST, customrequest, CURLOPT_CUSTOMREQUEST);
+ FSINGLETONTLV(TLV_TYPE_MAIL_FROM, mail_from, CURLOPT_MAIL_FROM);
+
default:
/* The fuzzer generates lots of unknown TLVs, so don't do anything if
the TLV isn't known. */
#define TLV_TYPE_USERNAME 3
#define TLV_TYPE_PASSWORD 4
#define TLV_TYPE_POSTFIELDS 5
+#define TLV_TYPE_HEADER 6
+#define TLV_TYPE_COOKIE 7
+#define TLV_TYPE_UPLOAD1 8
+#define TLV_TYPE_RANGE 9
+#define TLV_TYPE_CUSTOMREQUEST 10
+#define TLV_TYPE_MAIL_RECIPIENT 11
+#define TLV_TYPE_MAIL_FROM 12
/**
* TLV function return codes.
/* Parser state */
FUZZ_PARSE_STATE state;
- /* Current URL. */
- char *url;
-
/* Response data and length */
const uint8_t *rsp1_data;
size_t rsp1_data_len;
- /* Username and password */
+ /* Upload data and length; */
+ const uint8_t *upload1_data;
+ size_t upload1_data_len;
+
+ /* Singleton string fields. */
+ char *url;
char *username;
char *password;
-
- /* Postfields */
char *postfields;
+ char *cookie;
+ char *range;
+ char *customrequest;
+ char *mail_from;
+
+ /* List of headers */
+ struct curl_slist *header_list;
+
+ /* List of mail recipients */
+ struct curl_slist *mail_recipients_list;
} FUZZ_DATA;
static int fuzz_sockopt_callback(void *ptr,
curl_socket_t curlfd,
curlsocktype purpose);
+static size_t fuzz_read_callback(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *ptr);
int fuzz_get_first_tlv(FUZZ_DATA *fuzz, TLV *tlv);
int fuzz_get_next_tlv(FUZZ_DATA *fuzz, TLV *tlv);
int fuzz_get_tlv_comn(FUZZ_DATA *fuzz, TLV *tlv);
goto EXIT_LABEL; \
} \
}
+
+#define FSINGLETONTLV(TLVNAME, FIELDNAME, OPTNAME) \
+ case TLVNAME: \
+ FCHECK(fuzz->FIELDNAME == NULL); \
+ fuzz->FIELDNAME = fuzz_tlv_to_string(tlv); \
+ FTRY(curl_easy_setopt(fuzz->easy, OPTNAME, fuzz->FIELDNAME)); \
+ break
\ No newline at end of file
enc.maybe_write_string(enc.TYPE_USERNAME, options.username)
enc.maybe_write_string(enc.TYPE_PASSWORD, options.password)
enc.maybe_write_string(enc.TYPE_POSTFIELDS, options.postfields)
+ enc.maybe_write_string(enc.TYPE_COOKIE, options.cookie)
+ enc.maybe_write_string(enc.TYPE_RANGE, options.range)
+ enc.maybe_write_string(enc.TYPE_CUSTOMREQUEST, options.customrequest)
+ enc.maybe_write_string(enc.TYPE_MAIL_FROM, options.mailfrom)
+
+ # Write the first upload to the file.
+ if options.upload1:
+ enc.write_bytes(enc.TYPE_UPLOAD1, options.upload1.encode("utf-8"))
+ elif options.upload1file:
+ with open(options.upload1file, "rb") as g:
+ enc.write_bytes(enc.TYPE_UPLOAD1, g.read())
+
+ # Write an array of headers to the file.
+ if options.header:
+ for header in options.header:
+ enc.write_string(enc.TYPE_HEADER, header)
+
+ # Write an array of headers to the file.
+ if options.mailrecipient:
+ for mailrecipient in options.mailrecipient:
+ enc.write_string(enc.TYPE_MAIL_RECIPIENT, mailrecipient)
return ScriptRC.SUCCESS
TYPE_USERNAME = 3
TYPE_PASSWORD = 4
TYPE_POSTFIELDS = 5
+ TYPE_HEADER = 6
+ TYPE_COOKIE = 7
+ TYPE_UPLOAD1 = 8
+ TYPE_RANGE = 9
+ TYPE_CUSTOMREQUEST = 10
+ TYPE_MAIL_RECIPIENT = 11
+ TYPE_MAIL_FROM = 12
def __init__(self, output):
self.output = output
self.write_tlv(tlv_type, len(bytedata), bytedata)
def maybe_write_string(self, tlv_type, wstring):
- if wstring:
+ if wstring is not None:
self.write_string(tlv_type, wstring)
def write_tlv(self, tlv_type, tlv_length, tlv_data=None):
parser.add_argument("--username")
parser.add_argument("--password")
parser.add_argument("--postfields")
+ parser.add_argument("--header", action="append")
+ parser.add_argument("--cookie")
+ parser.add_argument("--range")
+ parser.add_argument("--customrequest")
+ parser.add_argument("--mailfrom")
+ parser.add_argument("--mailrecipient", action="append")
rsp1 = parser.add_mutually_exclusive_group(required=True)
rsp1.add_argument("--rsp1")
rsp1.add_argument("--rsp1file")
rsp1.add_argument("--rsp1test", type=int)
+ upload1 = parser.add_mutually_exclusive_group()
+ upload1.add_argument("--upload1")
+ upload1.add_argument("--upload1file")
+
return parser.parse_args()