Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
mongoose
Commits
b589e0cd
Commit
b589e0cd
authored
Jan 25, 2013
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed mg_upload() and some SSL related issues
parent
2b87f909
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
79 additions
and
126 deletions
+79
-126
mongoose.c
mongoose.c
+79
-126
No files found.
mongoose.c
View file @
b589e0cd
...
...
@@ -139,6 +139,7 @@ typedef long off_t;
#define flockfile(x) EnterCriticalSection(&global_log_file_lock)
#define funlockfile(x) LeaveCriticalSection(&global_log_file_lock)
#define sleep(x) Sleep((x) * 1000)
#define va_copy(x, y) x = y
#if !defined(fileno)
#define fileno(x) _fileno(x)
...
...
@@ -296,45 +297,15 @@ typedef int socklen_t;
static
const
char
*
http_500_error
=
"Internal Server Error"
;
// Snatched from OpenSSL includes. I put the prototypes here to be independent
// from the OpenSSL source installation. Having this, mongoose + SSL can be
// built on any system with binary SSL libraries installed.
#if defined(NO_SSL_DL)
#include <openssl/ssl.h>
#else
// SSL loaded dynamically from DLL.
// I put the prototypes here to be independent from OpenSSL source installation.
typedef
struct
ssl_st
SSL
;
typedef
struct
ssl_method_st
SSL_METHOD
;
typedef
struct
ssl_ctx_st
SSL_CTX
;
#define SSL_ERROR_WANT_READ 2
#define SSL_ERROR_WANT_WRITE 3
#define SSL_FILETYPE_PEM 1
#define CRYPTO_LOCK 1
#if defined(NO_SSL_DL)
extern
void
SSL_free
(
SSL
*
);
extern
int
SSL_accept
(
SSL
*
);
extern
int
SSL_connect
(
SSL
*
);
extern
int
SSL_read
(
SSL
*
,
void
*
,
int
);
extern
int
SSL_write
(
SSL
*
,
const
void
*
,
int
);
extern
int
SSL_get_error
(
const
SSL
*
,
int
);
extern
int
SSL_set_fd
(
SSL
*
,
int
);
extern
int
SSL_pending
(
SSL
*
);
extern
SSL
*
SSL_new
(
SSL_CTX
*
);
extern
SSL_CTX
*
SSL_CTX_new
(
SSL_METHOD
*
);
extern
SSL_METHOD
*
SSLv23_server_method
(
void
);
extern
SSL_METHOD
*
SSLv23_client_method
(
void
);
extern
int
SSL_library_init
(
void
);
extern
void
SSL_load_error_strings
(
void
);
extern
int
SSL_CTX_use_PrivateKey_file
(
SSL_CTX
*
,
const
char
*
,
int
);
extern
int
SSL_CTX_use_certificate_file
(
SSL_CTX
*
,
const
char
*
,
int
);
extern
int
SSL_CTX_use_certificate_chain_file
(
SSL_CTX
*
,
const
char
*
);
extern
void
SSL_CTX_set_default_passwd_cb
(
SSL_CTX
*
,
mg_callback_t
);
extern
void
SSL_CTX_free
(
SSL_CTX
*
);
extern
unsigned
long
ERR_get_error
(
void
);
extern
char
*
ERR_error_string
(
unsigned
long
,
char
*
);
extern
int
CRYPTO_num_locks
(
void
);
extern
void
CRYPTO_set_locking_callback
(
void
(
*
)(
int
,
int
,
const
char
*
,
int
));
extern
void
CRYPTO_set_id_callback
(
unsigned
long
(
*
)(
void
));
#else
// Dynamically loaded SSL functionality
struct
ssl_func
{
const
char
*
name
;
// SSL function name
void
(
*
ptr
)(
void
);
// Function pointer
...
...
@@ -363,6 +334,7 @@ struct ssl_func {
(
*
(
int
(
*
)(
SSL_CTX
*
,
const
char
*
))
ssl_sw
[
16
].
ptr
)
#define SSLv23_client_method (* (SSL_METHOD * (*)(void)) ssl_sw[17].ptr)
#define SSL_pending (* (int (*)(SSL *)) ssl_sw[18].ptr)
#define SSL_CTX_set_verify (* (void (*)(SSL_CTX *, int, int)) ssl_sw[19].ptr)
#define CRYPTO_num_locks (* (int (*)(void)) crypto_sw[0].ptr)
#define CRYPTO_set_locking_callback \
...
...
@@ -396,6 +368,7 @@ static struct ssl_func ssl_sw[] = {
{
"SSL_CTX_use_certificate_chain_file"
,
NULL
},
{
"SSLv23_client_method"
,
NULL
},
{
"SSL_pending"
,
NULL
},
{
"SSL_CTX_set_verify"
,
NULL
},
{
NULL
,
NULL
}
};
...
...
@@ -494,7 +467,6 @@ static const char *config_options[] = {
struct
mg_context
{
volatile
int
stop_flag
;
// Should we stop event loop
SSL_CTX
*
ssl_ctx
;
// SSL context
SSL_CTX
*
client_ssl_ctx
;
// Client SSL context
char
*
config
[
NUM_OPTIONS
];
// Mongoose configuration parameters
mg_callback_t
user_callback
;
// User-defined callback function
void
*
user_data
;
// User-defined data
...
...
@@ -517,6 +489,7 @@ struct mg_connection {
struct
mg_request_info
request_info
;
struct
mg_context
*
ctx
;
SSL
*
ssl
;
// SSL descriptor
SSL_CTX
*
client_ssl_ctx
;
// SSL context for client connections
struct
socket
client
;
// Connected client
time_t
birth_time
;
// Time when request was received
int64_t
num_bytes_sent
;
// Total bytes sent to client
...
...
@@ -1414,7 +1387,7 @@ static pid_t spawn_process(struct mg_connection *conn, const char *prog,
pid_t
pid
;
const
char
*
interp
;
envblk
=
NULL
;
// Unused
(
void
)
envblk
;
if
((
pid
=
fork
())
==
-
1
)
{
// Parent
...
...
@@ -1492,7 +1465,7 @@ static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf,
n
=
send
(
sock
,
buf
+
sent
,
(
size_t
)
k
,
MSG_NOSIGNAL
);
}
if
(
n
<
0
)
if
(
n
<
=
0
)
break
;
sent
+=
n
;
...
...
@@ -1627,34 +1600,42 @@ int mg_write(struct mg_connection *conn, const void *buf, size_t len) {
return
(
int
)
total
;
}
// Print message to buffer. If buffer is large enough to hold the message,
// return buffer. If buffer is to small, allocate large enough buffer on heap,
// and return allocated buffer.
static
int
alloc_vprintf
(
char
**
buf
,
size_t
size
,
const
char
*
fmt
,
va_list
ap
)
{
va_list
ap_copy
;
int
len
;
// Windows is not standard-compliant, and vsnprintf() returns -1 if
// buffer is too small. Also, older versions of msvcrt.dll do not have
// _vscprintf(). However, if size is 0, vsnprintf() behaves correctly.
// Therefore, we make two passes: on first pass, get required message length.
// On second pass, actually print the message.
va_copy
(
ap_copy
,
ap
);
len
=
vsnprintf
(
NULL
,
0
,
fmt
,
ap_copy
);
if
(
len
>
(
int
)
size
&&
(
size
=
len
+
1
)
>
0
&&
(
*
buf
=
(
char
*
)
malloc
(
size
))
==
NULL
)
{
len
=
-
1
;
// Allocation failed, mark failure
}
else
{
va_copy
(
ap_copy
,
ap
);
vsnprintf
(
*
buf
,
size
,
fmt
,
ap_copy
);
}
return
len
;
}
int
mg_vprintf
(
struct
mg_connection
*
conn
,
const
char
*
fmt
,
va_list
ap
)
{
char
mem
[
MG_BUF_LEN
],
*
buf
=
mem
;
int
len
;
// Print in a local buffer first, hoping that it is large enough to
// hold the whole message
len
=
vsnprintf
(
mem
,
sizeof
(
mem
),
fmt
,
ap
);
if
(
len
==
0
)
{
// Do nothing. mg_printf(conn, "%s", "") was called.
}
else
if
(
len
<
0
)
{
// vsnprintf() error, give up
len
=
-
1
;
cry
(
conn
,
"%s(%s, ...): vsnprintf() error"
,
__func__
,
fmt
);
}
else
if
(
len
>
(
int
)
sizeof
(
mem
)
&&
(
buf
=
(
char
*
)
malloc
(
len
+
1
))
!=
NULL
)
{
// Local buffer is not large enough, allocate big buffer on heap
vsnprintf
(
buf
,
len
+
1
,
fmt
,
ap
);
if
((
len
=
alloc_vprintf
(
&
buf
,
sizeof
(
mem
),
fmt
,
ap
))
>
0
)
{
len
=
mg_write
(
conn
,
buf
,
(
size_t
)
len
);
}
if
(
buf
!=
mem
&&
buf
!=
NULL
)
{
free
(
buf
);
}
else
if
(
len
>
(
int
)
sizeof
(
mem
))
{
// Failed to allocate large enough buffer, give up
cry
(
conn
,
"%s(%s, ...): Can't allocate %d bytes, not printing anything"
,
__func__
,
fmt
,
len
);
len
=
-
1
;
}
else
{
// Copy to the local buffer succeeded
len
=
mg_write
(
conn
,
buf
,
(
size_t
)
len
);
}
return
len
;
...
...
@@ -3826,7 +3807,7 @@ static void send_websocket_handshake(struct mg_connection *conn) {
}
static
void
read_websocket
(
struct
mg_connection
*
conn
)
{
unsigned
char
*
mask
,
*
buf
=
(
unsigned
char
*
)
conn
->
buf
+
conn
->
request_len
;
unsigned
char
*
buf
=
(
unsigned
char
*
)
conn
->
buf
+
conn
->
request_len
;
int
n
,
len
,
mask_len
,
body_len
,
discard_len
;
for
(;;)
{
...
...
@@ -3835,15 +3816,12 @@ static void read_websocket(struct mg_connection *conn) {
mask_len
=
buf
[
1
]
&
128
?
4
:
0
;
if
(
len
<
126
)
{
conn
->
content_len
=
2
+
mask_len
+
len
;
mask
=
buf
+
2
;
}
else
if
(
len
==
126
&&
body_len
>=
4
)
{
conn
->
content_len
=
4
+
mask_len
+
((((
int
)
buf
[
2
])
<<
8
)
+
buf
[
3
]);
mask
=
buf
+
4
;
}
else
if
(
body_len
>=
10
)
{
conn
->
content_len
=
10
+
mask_len
+
(((
uint64_t
)
htonl
(
*
(
uint32_t
*
)
&
buf
[
2
]))
<<
32
)
|
(((
uint64_t
)
htonl
(
*
(
uint32_t
*
)
&
buf
[
2
]))
<<
32
)
+
htonl
(
*
(
uint32_t
*
)
&
buf
[
6
]);
mask
=
buf
+
10
;
}
}
...
...
@@ -4100,7 +4078,7 @@ static void handle_lsp_request(struct mg_connection *conn, const char *path,
int
mg_upload
(
struct
mg_connection
*
conn
,
const
char
*
destination_dir
)
{
const
char
*
content_type_header
,
*
boundary_start
;
char
buf
[
8192
],
path
[
PATH_MAX
],
fname
[
1024
],
boundary
[
100
],
*
s
;
char
buf
[
MG_BUF_LEN
],
path
[
PATH_MAX
],
fname
[
1024
],
boundary
[
100
],
*
s
;
FILE
*
fp
;
int
bl
,
n
,
i
,
j
,
headers_len
,
boundary_len
,
len
=
0
,
num_uploaded_files
=
0
;
...
...
@@ -4196,7 +4174,7 @@ int mg_upload(struct mg_connection *conn, const char *destination_dir) {
}
if
(
len
>
bl
)
{
fwrite
(
buf
,
1
,
len
-
bl
,
fp
);
memmove
(
buf
,
&
buf
[
len
-
bl
],
len
-
bl
);
memmove
(
buf
,
&
buf
[
len
-
bl
],
bl
);
len
=
bl
;
}
}
while
((
n
=
mg_read
(
conn
,
buf
+
len
,
sizeof
(
buf
)
-
len
))
>
0
);
...
...
@@ -4213,7 +4191,7 @@ static int is_put_or_delete_request(const struct mg_connection *conn) {
static
int
get_first_ssl_listener_index
(
const
struct
mg_context
*
ctx
)
{
int
i
,
index
=
-
1
;
for
(
i
=
0
;
i
<
ctx
->
num_listening_sockets
;
i
++
)
{
for
(
i
=
0
;
i
ndex
==
-
1
&&
i
<
ctx
->
num_listening_sockets
;
i
++
)
{
index
=
ctx
->
listening_sockets
[
i
].
is_ssl
?
i
:
-
1
;
}
return
index
;
...
...
@@ -4531,10 +4509,10 @@ static const char *ssl_error(void) {
static
void
ssl_locking_callback
(
int
mode
,
int
mutex_num
,
const
char
*
file
,
int
line
)
{
line
=
0
;
// Unused
file
=
NULL
;
// Unused
(
void
)
line
;
(
void
)
file
;
if
(
mode
&
CRYPTO_LOCK
)
{
if
(
mode
&
1
)
{
// 1 is CRYPTO_LOCK
(
void
)
pthread_mutex_lock
(
&
ssl_mutexes
[
mutex_num
]);
}
else
{
(
void
)
pthread_mutex_unlock
(
&
ssl_mutexes
[
mutex_num
]);
...
...
@@ -4580,7 +4558,6 @@ static int load_dll(struct mg_context *ctx, const char *dll_name,
// Dynamically load SSL library. Set up ctx->ssl_ctx pointer.
static
int
set_ssl_option
(
struct
mg_context
*
ctx
)
{
struct
mg_connection
*
conn
;
int
i
,
size
;
const
char
*
pem
;
...
...
@@ -4596,14 +4573,10 @@ static int set_ssl_option(struct mg_context *ctx) {
}
#endif // NO_SSL_DL
// Initialize SSL
crap
// Initialize SSL
library
SSL_library_init
();
SSL_load_error_strings
();
if
((
ctx
->
client_ssl_ctx
=
SSL_CTX_new
(
SSLv23_client_method
()))
==
NULL
)
{
cry
(
fc
(
ctx
),
"SSL_CTX_new (client) error: %s"
,
ssl_error
());
}
if
((
ctx
->
ssl_ctx
=
SSL_CTX_new
(
SSLv23_server_method
()))
==
NULL
)
{
cry
(
fc
(
ctx
),
"SSL_CTX_new (server) error: %s"
,
ssl_error
());
return
0
;
...
...
@@ -4611,11 +4584,10 @@ static int set_ssl_option(struct mg_context *ctx) {
// If user callback returned non-NULL, that means that user callback has
// set up certificate itself. In this case, skip sertificate setting.
conn
=
fc
(
ctx
);
conn
->
request_info
.
ev_data
=
ctx
->
ssl_ctx
;
if
(
call_user
(
conn
,
MG_INIT_SSL
)
==
NULL
&&
(
SSL_CTX_use_certificate_file
(
ctx
->
ssl_ctx
,
pem
,
SSL_FILETYPE_PEM
)
==
0
||
SSL_CTX_use_PrivateKey_file
(
ctx
->
ssl_ctx
,
pem
,
SSL_FILETYPE_PEM
)
==
0
))
{
fc
(
ctx
)
->
request_info
.
ev_data
=
ctx
->
ssl_ctx
;
if
(
call_user
(
fc
(
ctx
),
MG_INIT_SSL
)
==
NULL
&&
(
SSL_CTX_use_certificate_file
(
ctx
->
ssl_ctx
,
pem
,
1
)
==
0
||
SSL_CTX_use_PrivateKey_file
(
ctx
->
ssl_ctx
,
pem
,
1
)
==
0
))
{
cry
(
fc
(
ctx
),
"%s: cannot open %s: %s"
,
__func__
,
pem
,
ssl_error
());
return
0
;
}
...
...
@@ -4682,17 +4654,17 @@ static void close_socket_gracefully(struct mg_connection *conn) {
int
n
;
#endif
struct
linger
linger
;
int
sock
=
conn
->
client
.
sock
;
// Set linger option to avoid socket hanging out after close. This prevent
// ephemeral port exhaust problem under high QPS.
linger
.
l_onoff
=
1
;
linger
.
l_linger
=
1
;
setsockopt
(
sock
,
SOL_SOCKET
,
SO_LINGER
,
(
char
*
)
&
linger
,
sizeof
(
linger
));
setsockopt
(
conn
->
client
.
sock
,
SOL_SOCKET
,
SO_LINGER
,
(
char
*
)
&
linger
,
sizeof
(
linger
));
// Send FIN to the client
(
void
)
shutdown
(
sock
,
SHUT_WR
);
set_non_blocking_mode
(
sock
);
shutdown
(
conn
->
client
.
sock
,
SHUT_WR
);
set_non_blocking_mode
(
conn
->
client
.
sock
);
#if defined(_WIN32)
// Read and discard pending incoming data. If we do not do that and close the
...
...
@@ -4706,23 +4678,24 @@ static void close_socket_gracefully(struct mg_connection *conn) {
#endif
// Now we know that our FIN is ACK-ed, safe to close
(
void
)
closesocket
(
sock
);
closesocket
(
conn
->
client
.
sock
);
}
static
void
close_connection
(
struct
mg_connection
*
conn
)
{
conn
->
must_close
=
1
;
if
(
conn
->
ssl
)
{
SSL_free
(
conn
->
ssl
);
conn
->
ssl
=
NULL
;
}
if
(
conn
->
client
.
sock
!=
INVALID_SOCKET
)
{
close_socket_gracefully
(
conn
);
}
// Must be done AFTER socket is closed
if
(
conn
->
ssl
!=
NULL
)
{
SSL_free
(
conn
->
ssl
);
}
}
void
mg_close_connection
(
struct
mg_connection
*
conn
)
{
if
(
conn
->
client_ssl_ctx
!=
NULL
)
{
SSL_CTX_free
((
SSL_CTX
*
)
conn
->
client_ssl_ctx
);
}
close_connection
(
conn
);
free
(
conn
);
}
...
...
@@ -4733,17 +4706,12 @@ struct mg_connection *mg_connect(const char *host, int port, int use_ssl,
struct
mg_connection
*
conn
=
NULL
;
struct
sockaddr_in
sin
;
struct
hostent
*
he
;
SSL_CTX
*
ssl
=
NULL
;
int
sock
;
if
(
host
==
NULL
)
{
snprintf
(
ebuf
,
ebuf_len
,
"%s"
,
"NULL host"
);
}
else
if
(
use_ssl
&&
SSLv23_client_method
==
NULL
)
{
snprintf
(
ebuf
,
ebuf_len
,
"%s"
,
"SSL is not initialized"
);
#ifndef NO_SSL
}
else
if
(
use_ssl
&&
(
ssl
=
SSL_CTX_new
(
SSLv23_client_method
()))
==
NULL
)
{
snprintf
(
ebuf
,
ebuf_len
,
"SSL_CTX_new: %s"
,
ssl_error
());
#endif // NO_SSL
}
else
if
((
he
=
gethostbyname
(
host
))
==
NULL
)
{
snprintf
(
ebuf
,
ebuf_len
,
"gethostbyname(%s): %s"
,
host
,
strerror
(
ERRNO
));
}
else
if
((
sock
=
socket
(
PF_INET
,
SOCK_STREAM
,
0
))
==
INVALID_SOCKET
)
{
...
...
@@ -4760,6 +4728,14 @@ struct mg_connection *mg_connect(const char *host, int port, int use_ssl,
calloc
(
1
,
sizeof
(
*
conn
)
+
MAX_REQUEST_SIZE
))
==
NULL
)
{
snprintf
(
ebuf
,
ebuf_len
,
"calloc(): %s"
,
strerror
(
ERRNO
));
closesocket
(
sock
);
#ifndef NO_SSL
}
else
if
(
use_ssl
&&
(
conn
->
client_ssl_ctx
=
SSL_CTX_new
(
SSLv23_client_method
()))
==
NULL
)
{
snprintf
(
ebuf
,
ebuf_len
,
"SSL_CTX_new error"
);
closesocket
(
sock
);
free
(
conn
);
conn
=
NULL
;
#endif // NO_SSL
}
else
{
conn
->
buf_size
=
MAX_REQUEST_SIZE
;
conn
->
buf
=
(
char
*
)
(
conn
+
1
);
...
...
@@ -4768,13 +4744,13 @@ struct mg_connection *mg_connect(const char *host, int port, int use_ssl,
conn
->
client
.
rsa
.
sin
=
sin
;
conn
->
client
.
is_ssl
=
use_ssl
;
if
(
use_ssl
)
{
sslize
(
conn
,
ssl
,
SSL_connect
);
// SSL_CTX_set_verify call is needed to switch off server certificate
// checking, which is off by default in OpenSSL and on in yaSSL.
SSL_CTX_set_verify
(
conn
->
client_ssl_ctx
,
0
,
0
);
sslize
(
conn
,
conn
->
client_ssl_ctx
,
SSL_connect
);
}
}
}
if
(
ssl
!=
NULL
)
{
SSL_CTX_free
(
ssl
);
}
return
conn
;
}
...
...
@@ -4827,28 +4803,8 @@ struct mg_connection *mg_download(const char *host, int port, int use_ssl,
if
((
conn
=
mg_connect
(
host
,
port
,
use_ssl
,
ebuf
,
ebuf_len
))
==
NULL
)
{
}
else
if
(
mg_vprintf
(
conn
,
fmt
,
ap
)
<=
0
)
{
snprintf
(
ebuf
,
ebuf_len
,
"%s"
,
"Error sending request"
);
}
else
if
(
!
getreq
(
conn
,
ebuf
,
ebuf_len
))
{
}
else
{
#if 0
// Write chunk of data that may be in the user's buffer
data_length -= req_length;
if (data_length > 0 &&
fwrite(buf + req_length, 1, data_length, fp) != (size_t) data_length) {
cry(fc(ctx), "%s: fwrite(%s): %s", __func__, path, strerror(ERRNO));
fclose(fp);
fp = NULL;
}
// Read the rest of the response and write it to the file. Do not use
// mg_read() cause we didn't set conn->content_len properly.
while (fp && (data_length = pull(0, conn, buf2, sizeof(buf2))) > 0) {
if (fwrite(buf2, 1, data_length, fp) != (size_t) data_length) {
cry(fc(ctx), "%s: fwrite(%s): %s", __func__, path, strerror(ERRNO));
fclose(fp);
fp = NULL;
break;
}
}
#endif
getreq
(
conn
,
ebuf
,
ebuf_len
);
}
if
(
ebuf
[
0
]
!=
'\0'
&&
conn
!=
NULL
)
{
mg_close_connection
(
conn
);
...
...
@@ -5116,9 +5072,6 @@ static void free_context(struct mg_context *ctx) {
if
(
ctx
->
ssl_ctx
!=
NULL
)
{
SSL_CTX_free
(
ctx
->
ssl_ctx
);
}
if
(
ctx
->
client_ssl_ctx
!=
NULL
)
{
SSL_CTX_free
(
ctx
->
client_ssl_ctx
);
}
#ifndef NO_SSL
if
(
ssl_mutexes
!=
NULL
)
{
free
(
ssl_mutexes
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment